mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-23 13:00:17 +00:00
Compare commits
13 Commits
6a7da5a1d5
...
8264f125d6
Author | SHA1 | Date | |
---|---|---|---|
|
8264f125d6 | ||
|
b6993532fa | ||
|
1c1e898950 | ||
|
6805b418b5 | ||
|
3a2e8ab6c5 | ||
|
c4f761d7c2 | ||
|
e94cfaf42e | ||
|
749435e516 | ||
|
f756bd813d | ||
|
bf5fe3d898 | ||
|
f9a1bd1d49 | ||
|
0bd25e7224 | ||
|
ceb49d832b |
@ -1,3 +1,5 @@
|
||||
set -e
|
||||
|
||||
# if no $1 default arm64-v8a
|
||||
if [ -z $1 ]; then
|
||||
$1=arm64-v8a
|
||||
|
@ -1,3 +1,5 @@
|
||||
set -e
|
||||
|
||||
rm -rf build
|
||||
mkdir build
|
||||
cd build
|
||||
|
@ -1,10 +1,10 @@
|
||||
set -e
|
||||
|
||||
python prebuild.py
|
||||
|
||||
rm -rf web/lib
|
||||
mkdir web/lib
|
||||
|
||||
SRC_C=$(find src/ -name "*.c")
|
||||
SRC_CPP=$(find src/ -name "*.cpp")
|
||||
SRC="$SRC_C $SRC_CPP"
|
||||
SRC=$(find src/ -name "*.c")
|
||||
|
||||
em++ $SRC -Iinclude/ -fexceptions -frtti -s -Os -sEXPORTED_FUNCTIONS=_pkpy_new_repl,_pkpy_repl_input,_pkpy_new_vm -sEXPORTED_RUNTIME_METHODS=ccall -o web/lib/pocketpy.js
|
||||
emcc $SRC -Iinclude/ -s -Os -sEXPORTED_FUNCTIONS=_py_initialize,_py_finalize,_py_exec,_py_replinput -sEXPORTED_RUNTIME_METHODS=ccall -o web/lib/pocketpy.js
|
||||
|
@ -1,20 +1,14 @@
|
||||
#pragma once
|
||||
// generated by prebuild.py
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
const char* load_kPythonLib(const char* name);
|
||||
|
||||
extern const char kPythonLibs__enum[];
|
||||
extern const char kPythonLibs__long[];
|
||||
extern const char kPythonLibs__set[];
|
||||
extern const char kPythonLibs_bisect[];
|
||||
extern const char kPythonLibs_builtins[];
|
||||
extern const char kPythonLibs_cmath[];
|
||||
extern const char kPythonLibs_collections[];
|
||||
extern const char kPythonLibs_colorsys[];
|
||||
extern const char kPythonLibs_datetime[];
|
||||
extern const char kPythonLibs_functools[];
|
||||
extern const char kPythonLibs_heapq[];
|
||||
@ -23,7 +17,3 @@ extern const char kPythonLibs_operator[];
|
||||
extern const char kPythonLibs_pickle[];
|
||||
extern const char kPythonLibs_this[];
|
||||
extern const char kPythonLibs_typing[];
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
@ -2,10 +2,6 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define c11__less(a, b) ((a) < (b))
|
||||
|
||||
#define c11__lower_bound(T, ptr, count, key, less, out_index) \
|
||||
@ -42,8 +38,3 @@ bool c11__stable_sort(void* ptr,
|
||||
int elem_size,
|
||||
int (*f_lt)(const void* a, const void* b, void* extra),
|
||||
void* extra);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
#endif
|
@ -1,9 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define kPoolExprBlockSize 128
|
||||
#define kPoolFrameBlockSize 80
|
||||
#define kPoolObjectBlockSize 80
|
||||
@ -24,8 +20,3 @@ void PoolObject_dealloc(void* p);
|
||||
void PoolObject_shrink_to_fit();
|
||||
|
||||
void Pools_debug_info(char* buffer, int size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -4,10 +4,6 @@
|
||||
#include "pocketpy/common/str.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SMALLMAP_T__HEADER
|
||||
#define K uint16_t
|
||||
#define V int
|
||||
@ -24,7 +20,3 @@ extern "C" {
|
||||
#define equal(a, b) (c11_sv__cmp((a), (b)) == 0)
|
||||
#include "pocketpy/xmacros/smallmap.h"
|
||||
#undef SMALLMAP_T__HEADER
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -6,10 +6,6 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct c11_sbuf {
|
||||
c11_vector data;
|
||||
} c11_sbuf;
|
||||
@ -34,7 +30,3 @@ void c11_sbuf__py_submit(c11_sbuf* self, py_Ref out);
|
||||
|
||||
void pk_vsprintf(c11_sbuf* ss, const char* fmt, va_list args);
|
||||
void pk_sprintf(c11_sbuf* ss, const char* fmt, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -4,10 +4,6 @@
|
||||
#include "pocketpy/common/utils.h"
|
||||
#include "pocketpy/pocketpy.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* string */
|
||||
typedef struct c11_string{
|
||||
// int size | char[] | '\0'
|
||||
@ -21,6 +17,8 @@ typedef struct c11_bytes{
|
||||
unsigned char data[]; // flexible array member
|
||||
} c11_bytes;
|
||||
|
||||
bool c11_bytes__eq(c11_bytes* self, c11_bytes* other);
|
||||
|
||||
int c11_sv__cmp(c11_sv self, c11_sv other);
|
||||
int c11_sv__cmp2(c11_sv self, const char* other);
|
||||
|
||||
@ -72,7 +70,3 @@ typedef enum IntParsingResult{
|
||||
} IntParsingResult;
|
||||
|
||||
IntParsingResult c11__parse_uint(c11_sv text, int64_t* out, int base);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -3,13 +3,5 @@
|
||||
#include <stdint.h>
|
||||
#include "pocketpy/common/str.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void py_Name__initialize();
|
||||
void py_Name__finalize();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -3,10 +3,6 @@
|
||||
#include "stdio.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PK_REGION(name) 1
|
||||
|
||||
#define PK_SLICE_LOOP(i, start, stop, step) \
|
||||
@ -52,7 +48,3 @@ typedef struct RefCounted {
|
||||
free(obj); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -7,10 +7,6 @@
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct c11_array {
|
||||
void* data;
|
||||
int count;
|
||||
@ -92,7 +88,3 @@ c11_array c11_vector__submit(c11_vector* self);
|
||||
// NOTE: here we do an extra NULL check for it to avoid UB
|
||||
#define c11__foreach(T, self, it) \
|
||||
for(T* it = (self)->data; it && it != (T*)(self)->data + (self)->count; it++)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -5,12 +5,4 @@
|
||||
#include "pocketpy/objects/sourcedata.h"
|
||||
#include "pocketpy/objects/codeobject.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
Error* pk_compile(SourceData_ src, CodeObject* out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -6,10 +6,6 @@
|
||||
#include "pocketpy/objects/error.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const char* TokenSymbols[];
|
||||
|
||||
typedef enum TokenIndex{
|
||||
@ -95,7 +91,3 @@ Error* Lexer__process_and_dump(SourceData_ src, c11_string** out_string);
|
||||
void TokenArray__dtor(TokenArray* self);
|
||||
|
||||
#define Token__sv(self) (c11_sv){(self)->start, (self)->length}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -6,10 +6,7 @@
|
||||
#include "pocketpy/objects/object.h"
|
||||
#include "pocketpy/common/config.h"
|
||||
#include "pocketpy/common/strname.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "pocketpy/pocketpy.h"
|
||||
|
||||
py_TValue* FastLocals__try_get_by_name(py_TValue* locals, const CodeObject* co, py_Name name);
|
||||
NameDict* FastLocals__to_namedict(py_TValue* locals, const CodeObject* co);
|
||||
@ -38,7 +35,7 @@ typedef struct Frame {
|
||||
struct Frame* f_back;
|
||||
const Bytecode* ip;
|
||||
const CodeObject* co;
|
||||
py_TValue module; // weak ref
|
||||
py_GlobalRef module;
|
||||
py_StackRef function; // a function object or NULL (global scope)
|
||||
py_StackRef p0; // unwinding base
|
||||
py_StackRef locals; // locals base
|
||||
@ -46,7 +43,7 @@ typedef struct Frame {
|
||||
} Frame;
|
||||
|
||||
Frame* Frame__new(const CodeObject* co,
|
||||
py_TValue* module,
|
||||
py_GlobalRef module,
|
||||
py_StackRef function,
|
||||
py_StackRef p0,
|
||||
py_StackRef locals);
|
||||
@ -66,7 +63,3 @@ int Frame__exit_block(Frame* self, ValueStack*, int);
|
||||
void Frame__gc_mark(Frame* self);
|
||||
UnwindTarget* Frame__find_unwind_target(Frame* self, int iblock);
|
||||
void Frame__set_unwind_target(Frame* self, py_TValue* sp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1,10 +1,6 @@
|
||||
#include "pocketpy/objects/object.h"
|
||||
#include "pocketpy/common/config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct ManagedHeap{
|
||||
c11_vector no_gc;
|
||||
c11_vector gen;
|
||||
@ -28,7 +24,3 @@ PyObject* ManagedHeap__gcnew(ManagedHeap* self, py_Type type, int slots, int uds
|
||||
|
||||
// external implementation
|
||||
void ManagedHeap__mark(ManagedHeap* self);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
10
include/pocketpy/interpreter/generator.h
Normal file
10
include/pocketpy/interpreter/generator.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "pocketpy/interpreter/frame.h"
|
||||
|
||||
typedef struct Generator{
|
||||
Frame* frame;
|
||||
int state;
|
||||
} Generator;
|
||||
|
||||
void pk_newgenerator(py_Ref out, Frame* frame, int slots);
|
@ -1,14 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void pk__add_module_pkpy();
|
||||
void pk__add_module_os();
|
||||
void pk__add_module_math();
|
||||
void pk__add_module_dis();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -6,10 +6,6 @@
|
||||
#include "pocketpy/interpreter/frame.h"
|
||||
#include "pocketpy/interpreter/modules.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct py_TypeInfo {
|
||||
py_Name name;
|
||||
py_Type base;
|
||||
@ -69,6 +65,9 @@ bool pk__normalize_index(int* index, int length);
|
||||
void pk_list__mark(void* ud, void (*marker)(py_TValue*));
|
||||
void pk_dict__mark(void* ud, void (*marker)(py_TValue*));
|
||||
|
||||
bool pk_wrapper__self(int argc, py_Ref argv);
|
||||
bool pk_wrapper__NotImplementedError(int argc, py_Ref argv);
|
||||
|
||||
typedef enum FrameResult {
|
||||
RES_RETURN,
|
||||
RES_CALL,
|
||||
@ -126,9 +125,6 @@ py_Type pk_super__register();
|
||||
py_Type pk_property__register();
|
||||
py_Type pk_staticmethod__register();
|
||||
py_Type pk_classmethod__register();
|
||||
py_Type pk_generator__register();
|
||||
|
||||
py_TValue pk_builtins__register();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -9,10 +9,6 @@
|
||||
#include "pocketpy/common/utils.h"
|
||||
#include "pocketpy/pocketpy.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct PyObject PyObject;
|
||||
typedef struct VM VM;
|
||||
extern VM* pk_current_vm;
|
||||
@ -35,7 +31,3 @@ typedef struct py_TValue {
|
||||
// 16 bytes to make py_arg() macro work
|
||||
static_assert(sizeof(py_CFunction) <= 8, "sizeof(py_CFunction) > 8");
|
||||
static_assert(sizeof(py_TValue) == 16, "sizeof(py_TValue) != 16");
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -10,10 +10,6 @@
|
||||
#include "pocketpy/objects/namedict.h"
|
||||
#include "pocketpy/pocketpy.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BC_NOARG 0
|
||||
#define BC_KEEPLINE -1
|
||||
|
||||
@ -144,8 +140,4 @@ typedef struct Function {
|
||||
} Function;
|
||||
|
||||
void Function__ctor(Function* self, FuncDecl_ decl, py_TValue* module);
|
||||
void Function__dtor(Function* self);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
void Function__dtor(Function* self);
|
@ -7,10 +7,6 @@
|
||||
#include "pocketpy/objects/object.h"
|
||||
#include "pocketpy/pocketpy.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct{
|
||||
SourceData_ src;
|
||||
int lineno;
|
||||
@ -20,7 +16,3 @@ typedef struct{
|
||||
void py_BaseException__set_lineno(py_Ref, int lineno, const CodeObject* code);
|
||||
int py_BaseException__get_lineno(py_Ref, const CodeObject* code);
|
||||
void py_BaseException__stpush(py_Ref, SourceData_ src, int lineno, const char* func_name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -5,10 +5,6 @@
|
||||
#include "pocketpy/objects/base.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SMALLMAP_T__HEADER
|
||||
#define K uint16_t
|
||||
#define V py_TValue
|
||||
@ -16,6 +12,3 @@ extern "C" {
|
||||
#include "pocketpy/xmacros/smallmap.h"
|
||||
#undef SMALLMAP_T__HEADER
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -3,10 +3,6 @@
|
||||
#include "pocketpy/objects/namedict.h"
|
||||
#include "pocketpy/objects/base.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct PyObject {
|
||||
py_Type type; // we have a duplicated type here for convenience
|
||||
bool gc_is_large;
|
||||
@ -29,7 +25,3 @@ void* PyObject__userdata(PyObject* self);
|
||||
|
||||
PyObject* PyObject__new(py_Type type, int slots, int size);
|
||||
void PyObject__delete(PyObject* self);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -6,10 +6,6 @@
|
||||
#include "pocketpy/common/sstream.h"
|
||||
#include "pocketpy/common/vector.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct SourceData {
|
||||
RefCounted rc;
|
||||
enum py_CompileMode mode;
|
||||
@ -38,7 +34,3 @@ void SourceData__snapshot(const struct SourceData* self,
|
||||
int lineno,
|
||||
const char* cursor,
|
||||
const char* name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -385,7 +385,7 @@ void py_clearexc(py_StackRef p0);
|
||||
#define ValueError(...) py_exception(tp_ValueError, __VA_ARGS__)
|
||||
#define IndexError(...) py_exception(tp_IndexError, __VA_ARGS__)
|
||||
#define ImportError(...) py_exception(tp_ImportError, __VA_ARGS__)
|
||||
#define NotImplementedError() py_exception(tp_NotImplementedError, "")
|
||||
#define ZeroDivisionError(...) py_exception(tp_ZeroDivisionError, __VA_ARGS__)
|
||||
#define AttributeError(self, n) \
|
||||
py_exception(tp_AttributeError, "'%t' object has no attribute '%n'", (self)->type, (n))
|
||||
#define UnboundLocalError(n) \
|
||||
@ -451,7 +451,6 @@ int py_list_len(py_Ref self);
|
||||
void py_list_append(py_Ref self, py_Ref val);
|
||||
void py_list_clear(py_Ref self);
|
||||
void py_list_insert(py_Ref self, int i, py_Ref val);
|
||||
void py_list_reverse(py_Ref self);
|
||||
|
||||
py_TmpRef py_dict_getitem(py_Ref self, py_Ref key) PY_RAISE;
|
||||
void py_dict_setitem(py_Ref self, py_Ref key, py_Ref val) PY_RAISE;
|
||||
@ -517,9 +516,10 @@ enum py_PredefinedTypes {
|
||||
tp_NoneType,
|
||||
tp_NotImplementedType,
|
||||
tp_ellipsis,
|
||||
tp_SyntaxError,
|
||||
tp_StopIteration,
|
||||
tp_generator,
|
||||
/* builtin exceptions */
|
||||
tp_StopIteration,
|
||||
tp_SyntaxError,
|
||||
tp_StackOverflowError,
|
||||
tp_IOError,
|
||||
tp_OSError,
|
||||
|
@ -27,21 +27,12 @@ with open("include/pocketpy/common/_generated.h", "wt", encoding='utf-8', newlin
|
||||
data = '''#pragma once
|
||||
// generated by prebuild.py
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
const char* load_kPythonLib(const char* name);
|
||||
|
||||
'''
|
||||
for key in sorted(sources.keys()):
|
||||
value = sources[key]
|
||||
data += f'extern const char kPythonLibs_{key}[];\n'
|
||||
data += '''
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
'''
|
||||
f.write(data)
|
||||
|
||||
with open("src/common/_generated.c", "wt", encoding='utf-8', newline='\n') as f:
|
||||
|
@ -1,80 +0,0 @@
|
||||
class set:
|
||||
def __init__(self, iterable=None):
|
||||
iterable = iterable or []
|
||||
self._a = {}
|
||||
self.update(iterable)
|
||||
|
||||
def add(self, elem):
|
||||
self._a[elem] = None
|
||||
|
||||
def discard(self, elem):
|
||||
self._a.pop(elem, None)
|
||||
|
||||
def remove(self, elem):
|
||||
del self._a[elem]
|
||||
|
||||
def clear(self):
|
||||
self._a.clear()
|
||||
|
||||
def update(self, other):
|
||||
for elem in other:
|
||||
self.add(elem)
|
||||
|
||||
def __len__(self):
|
||||
return len(self._a)
|
||||
|
||||
def copy(self):
|
||||
return set(self._a.keys())
|
||||
|
||||
def __and__(self, other):
|
||||
return {elem for elem in self if elem in other}
|
||||
|
||||
def __sub__(self, other):
|
||||
return {elem for elem in self if elem not in other}
|
||||
|
||||
def __or__(self, other):
|
||||
ret = self.copy()
|
||||
ret.update(other)
|
||||
return ret
|
||||
|
||||
def __xor__(self, other):
|
||||
_0 = self - other
|
||||
_1 = other - self
|
||||
return _0 | _1
|
||||
|
||||
def union(self, other):
|
||||
return self | other
|
||||
|
||||
def intersection(self, other):
|
||||
return self & other
|
||||
|
||||
def difference(self, other):
|
||||
return self - other
|
||||
|
||||
def symmetric_difference(self, other):
|
||||
return self ^ other
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, set):
|
||||
return NotImplemented
|
||||
return len(self ^ other) == 0
|
||||
|
||||
def isdisjoint(self, other):
|
||||
return len(self & other) == 0
|
||||
|
||||
def issubset(self, other):
|
||||
return len(self - other) == 0
|
||||
|
||||
def issuperset(self, other):
|
||||
return len(other - self) == 0
|
||||
|
||||
def __contains__(self, elem):
|
||||
return elem in self._a
|
||||
|
||||
def __repr__(self):
|
||||
if len(self) == 0:
|
||||
return 'set()'
|
||||
return '{'+ ', '.join([repr(i) for i in self._a.keys()]) + '}'
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self._a.keys())
|
@ -1,4 +1,4 @@
|
||||
from pkpy import next as __builtins_next
|
||||
from pkpy import next as __pkpy_next
|
||||
|
||||
def all(iterable):
|
||||
for i in iterable:
|
||||
@ -37,8 +37,8 @@ def zip(a, b):
|
||||
a = iter(a)
|
||||
b = iter(b)
|
||||
while True:
|
||||
ai = __builtins_next(a)
|
||||
bi = __builtins_next(b)
|
||||
ai = __pkpy_next(a)
|
||||
bi = __pkpy_next(b)
|
||||
if ai is StopIteration or bi is StopIteration:
|
||||
break
|
||||
yield ai, bi
|
||||
@ -182,36 +182,83 @@ def long(*args, **kwargs):
|
||||
import _long
|
||||
return _long.long(*args, **kwargs)
|
||||
|
||||
class set:
|
||||
def __init__(self, iterable=None):
|
||||
iterable = iterable or []
|
||||
self._a = {}
|
||||
self.update(iterable)
|
||||
|
||||
# builtin exceptions
|
||||
class StackOverflowError(Exception): pass
|
||||
class IOError(Exception): pass
|
||||
class NotImplementedError(Exception): pass
|
||||
class TypeError(Exception): pass
|
||||
class IndexError(Exception): pass
|
||||
class ValueError(Exception): pass
|
||||
class RuntimeError(Exception): pass
|
||||
class ZeroDivisionError(Exception): pass
|
||||
class NameError(Exception): pass
|
||||
class UnboundLocalError(Exception): pass
|
||||
class AttributeError(Exception): pass
|
||||
class ImportError(Exception): pass
|
||||
class AssertionError(Exception): pass
|
||||
def add(self, elem):
|
||||
self._a[elem] = None
|
||||
|
||||
def discard(self, elem):
|
||||
self._a.pop(elem, None)
|
||||
|
||||
class KeyError(Exception):
|
||||
def __init__(self, key=...):
|
||||
self.key = key
|
||||
if key is ...:
|
||||
super().__init__()
|
||||
else:
|
||||
super().__init__(repr(key))
|
||||
def remove(self, elem):
|
||||
del self._a[elem]
|
||||
|
||||
def clear(self):
|
||||
self._a.clear()
|
||||
|
||||
def __str__(self):
|
||||
if self.key is ...:
|
||||
return ''
|
||||
return str(self.key)
|
||||
def update(self, other):
|
||||
for elem in other:
|
||||
self.add(elem)
|
||||
|
||||
def __len__(self):
|
||||
return len(self._a)
|
||||
|
||||
def copy(self):
|
||||
return set(self._a.keys())
|
||||
|
||||
def __and__(self, other):
|
||||
return {elem for elem in self if elem in other}
|
||||
|
||||
def __sub__(self, other):
|
||||
return {elem for elem in self if elem not in other}
|
||||
|
||||
def __or__(self, other):
|
||||
ret = self.copy()
|
||||
ret.update(other)
|
||||
return ret
|
||||
|
||||
def __xor__(self, other):
|
||||
_0 = self - other
|
||||
_1 = other - self
|
||||
return _0 | _1
|
||||
|
||||
def union(self, other):
|
||||
return self | other
|
||||
|
||||
def intersection(self, other):
|
||||
return self & other
|
||||
|
||||
def difference(self, other):
|
||||
return self - other
|
||||
|
||||
def symmetric_difference(self, other):
|
||||
return self ^ other
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, set):
|
||||
return NotImplemented
|
||||
return len(self ^ other) == 0
|
||||
|
||||
def isdisjoint(self, other):
|
||||
return len(self & other) == 0
|
||||
|
||||
def issubset(self, other):
|
||||
return len(self - other) == 0
|
||||
|
||||
def issuperset(self, other):
|
||||
return len(other - self) == 0
|
||||
|
||||
def __contains__(self, elem):
|
||||
return elem in self._a
|
||||
|
||||
def __repr__(self):
|
||||
if self.key is ...:
|
||||
return 'KeyError()'
|
||||
return f'KeyError({self.key!r})'
|
||||
if len(self) == 0:
|
||||
return 'set()'
|
||||
return '{'+ ', '.join([repr(i) for i in self._a.keys()]) + '}'
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self._a.keys())
|
@ -1,171 +0,0 @@
|
||||
"""Conversion functions between RGB and other color systems.
|
||||
|
||||
This modules provides two functions for each color system ABC:
|
||||
|
||||
rgb_to_abc(r, g, b) --> a, b, c
|
||||
abc_to_rgb(a, b, c) --> r, g, b
|
||||
|
||||
All inputs and outputs are triples of floats in the range [0.0...1.0]
|
||||
(with the exception of I and Q, which covers a slightly larger range).
|
||||
Inputs outside the valid range may cause exceptions or invalid outputs.
|
||||
|
||||
Supported color systems:
|
||||
RGB: Red, Green, Blue components
|
||||
YIQ: Luminance, Chrominance (used by composite video signals)
|
||||
HLS: Hue, Luminance, Saturation
|
||||
HSV: Hue, Saturation, Value
|
||||
"""
|
||||
|
||||
# References:
|
||||
# http://en.wikipedia.org/wiki/YIQ
|
||||
# http://en.wikipedia.org/wiki/HLS_color_space
|
||||
# http://en.wikipedia.org/wiki/HSV_color_space
|
||||
|
||||
__all__ = ["rgb_to_yiq","yiq_to_rgb","rgb_to_hls","hls_to_rgb",
|
||||
"rgb_to_hsv","hsv_to_rgb"]
|
||||
|
||||
# Some floating point constants
|
||||
|
||||
ONE_THIRD = 1.0/3.0
|
||||
ONE_SIXTH = 1.0/6.0
|
||||
TWO_THIRD = 2.0/3.0
|
||||
|
||||
# YIQ: used by composite video signals (linear combinations of RGB)
|
||||
# Y: perceived grey level (0.0 == black, 1.0 == white)
|
||||
# I, Q: color components
|
||||
#
|
||||
# There are a great many versions of the constants used in these formulae.
|
||||
# The ones in this library uses constants from the FCC version of NTSC.
|
||||
|
||||
def rgb_to_yiq(r, g, b):
|
||||
y = 0.30*r + 0.59*g + 0.11*b
|
||||
i = 0.74*(r-y) - 0.27*(b-y)
|
||||
q = 0.48*(r-y) + 0.41*(b-y)
|
||||
return (y, i, q)
|
||||
|
||||
def yiq_to_rgb(y, i, q):
|
||||
# r = y + (0.27*q + 0.41*i) / (0.74*0.41 + 0.27*0.48)
|
||||
# b = y + (0.74*q - 0.48*i) / (0.74*0.41 + 0.27*0.48)
|
||||
# g = y - (0.30*(r-y) + 0.11*(b-y)) / 0.59
|
||||
|
||||
r = y + 0.9468822170900693*i + 0.6235565819861433*q
|
||||
g = y - 0.27478764629897834*i - 0.6356910791873801*q
|
||||
b = y - 1.1085450346420322*i + 1.7090069284064666*q
|
||||
|
||||
if r < 0.0:
|
||||
r = 0.0
|
||||
if g < 0.0:
|
||||
g = 0.0
|
||||
if b < 0.0:
|
||||
b = 0.0
|
||||
if r > 1.0:
|
||||
r = 1.0
|
||||
if g > 1.0:
|
||||
g = 1.0
|
||||
if b > 1.0:
|
||||
b = 1.0
|
||||
return (r, g, b)
|
||||
|
||||
|
||||
# HLS: Hue, Luminance, Saturation
|
||||
# H: position in the spectrum
|
||||
# L: color lightness
|
||||
# S: color saturation
|
||||
|
||||
def rgb_to_hls(r, g, b):
|
||||
maxc = max(r, g, b)
|
||||
minc = min(r, g, b)
|
||||
sumc = (maxc+minc)
|
||||
rangec = (maxc-minc)
|
||||
l = sumc/2.0
|
||||
if minc == maxc:
|
||||
return 0.0, l, 0.0
|
||||
if l <= 0.5:
|
||||
s = rangec / sumc
|
||||
else:
|
||||
s = rangec / (2.0-maxc-minc) # Not always 2.0-sumc: gh-106498.
|
||||
rc = (maxc-r) / rangec
|
||||
gc = (maxc-g) / rangec
|
||||
bc = (maxc-b) / rangec
|
||||
if r == maxc:
|
||||
h = bc-gc
|
||||
elif g == maxc:
|
||||
h = 2.0+rc-bc
|
||||
else:
|
||||
h = 4.0+gc-rc
|
||||
# h = (h/6.0) % 1.0
|
||||
h = h / 6.0
|
||||
h = h - int(h)
|
||||
return h, l, s
|
||||
|
||||
def hls_to_rgb(h, l, s):
|
||||
if s == 0.0:
|
||||
return l, l, l
|
||||
if l <= 0.5:
|
||||
m2 = l * (1.0+s)
|
||||
else:
|
||||
m2 = l+s-(l*s)
|
||||
m1 = 2.0*l - m2
|
||||
return (_v(m1, m2, h+ONE_THIRD), _v(m1, m2, h), _v(m1, m2, h-ONE_THIRD))
|
||||
|
||||
def _v(m1, m2, hue):
|
||||
# hue = hue % 1.0
|
||||
hue = hue - int(hue)
|
||||
if hue < ONE_SIXTH:
|
||||
return m1 + (m2-m1)*hue*6.0
|
||||
if hue < 0.5:
|
||||
return m2
|
||||
if hue < TWO_THIRD:
|
||||
return m1 + (m2-m1)*(TWO_THIRD-hue)*6.0
|
||||
return m1
|
||||
|
||||
|
||||
# HSV: Hue, Saturation, Value
|
||||
# H: position in the spectrum
|
||||
# S: color saturation ("purity")
|
||||
# V: color brightness
|
||||
|
||||
def rgb_to_hsv(r, g, b):
|
||||
maxc = max(r, g, b)
|
||||
minc = min(r, g, b)
|
||||
rangec = (maxc-minc)
|
||||
v = maxc
|
||||
if minc == maxc:
|
||||
return 0.0, 0.0, v
|
||||
s = rangec / maxc
|
||||
rc = (maxc-r) / rangec
|
||||
gc = (maxc-g) / rangec
|
||||
bc = (maxc-b) / rangec
|
||||
if r == maxc:
|
||||
h = bc-gc
|
||||
elif g == maxc:
|
||||
h = 2.0+rc-bc
|
||||
else:
|
||||
h = 4.0+gc-rc
|
||||
# h = (h/6.0) % 1.0
|
||||
h = h / 6.0
|
||||
h = h - int(h)
|
||||
return h, s, v
|
||||
|
||||
def hsv_to_rgb(h, s, v):
|
||||
if s == 0.0:
|
||||
return v, v, v
|
||||
i = int(h*6.0) # XXX assume int() truncates!
|
||||
f = (h*6.0) - i
|
||||
p = v*(1.0 - s)
|
||||
q = v*(1.0 - s*f)
|
||||
t = v*(1.0 - s*(1.0-f))
|
||||
i = i%6
|
||||
if i == 0:
|
||||
return v, t, p
|
||||
if i == 1:
|
||||
return q, v, p
|
||||
if i == 2:
|
||||
return p, v, t
|
||||
if i == 3:
|
||||
return p, q, v
|
||||
if i == 4:
|
||||
return t, p, v
|
||||
if i == 5:
|
||||
return v, p, q
|
||||
# Cannot get here
|
@ -1,17 +0,0 @@
|
||||
cd c_bindings
|
||||
rm -rf build
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
cmake --build . --config Release
|
||||
|
||||
./test_c_bindings > binding_test_scratch
|
||||
|
||||
echo "checking results (they should be identical)"
|
||||
diff -q -s binding_test_scratch ../test_answers.txt
|
||||
|
||||
if [ $? -eq 1 ]
|
||||
then
|
||||
echo "ERROR: c binding test failed"
|
||||
exit 1
|
||||
fi
|
@ -1,10 +1,10 @@
|
||||
set -e
|
||||
|
||||
python prebuild.py
|
||||
|
||||
SRC_C=$(find src/ -name "*.c")
|
||||
SRC_CPP=$(find src/ -name "*.cpp")
|
||||
SRC="$SRC_C $SRC_CPP"
|
||||
SRC=$(find src/ -name "*.c")
|
||||
|
||||
g++ -pg -Og -std=c++17 -frtti -Wfatal-errors -o main $SRC src2/main.cpp -Iinclude
|
||||
gcc -pg -Og -std=c11 -Wfatal-errors -o main $SRC src2/main.c -Iinclude
|
||||
./main benchmarks/fib.py
|
||||
gprof main gmon.out > gprof.txt
|
||||
rm gmon.out
|
||||
|
@ -1,10 +1,10 @@
|
||||
set -e
|
||||
|
||||
python prebuild.py
|
||||
|
||||
SRC_C=$(find src/ -name "*.c")
|
||||
SRC_CPP=$(find src/ -name "*.cpp")
|
||||
SRC="$SRC_C $SRC_CPP"
|
||||
SRC=$(find src/ -name "*.c")
|
||||
|
||||
clang++ -std=c++17 --coverage -O1 -stdlib=libc++ -frtti -Wfatal-errors -o main src2/main.cpp $SRC -Iinclude -DPK_ENABLE_OS=1 -DPK_DEBUG_PRECOMPILED_EXEC=1 -DPK_ENABLE_PROFILER=1
|
||||
clang -std=c11 --coverage -O1 -Wfatal-errors -o main src2/main.c $SRC -Iinclude -DPK_ENABLE_OS=1 -DPK_DEBUG_PRECOMPILED_EXEC=1 -DPK_ENABLE_PROFILER=1
|
||||
|
||||
python scripts/run_tests.py
|
||||
|
||||
|
@ -1,43 +0,0 @@
|
||||
import re
|
||||
|
||||
filepath = 'include/pocketpy/vm.h'
|
||||
|
||||
with open(filepath, 'r', encoding='utf-8') as f:
|
||||
lines = f.readlines()
|
||||
|
||||
REGION_PATTERN = re.compile(r'#if PK_REGION\("(.+)"\)')
|
||||
|
||||
current_region = None
|
||||
output = []
|
||||
|
||||
def parse_line(line: str):
|
||||
output.append(line)
|
||||
|
||||
for line in lines:
|
||||
if current_region:
|
||||
if line.startswith('#endif'):
|
||||
current_region = None
|
||||
output.append('```\n\n')
|
||||
else:
|
||||
parse_line(line.strip(' '))
|
||||
else:
|
||||
m = REGION_PATTERN.match(line)
|
||||
if m:
|
||||
current_region = m.group(1)
|
||||
output.append(f'### {current_region}\n')
|
||||
output.append('```cpp\n')
|
||||
|
||||
with open('docs/references.md', 'w', encoding='utf-8') as f:
|
||||
f.write('''---
|
||||
label: References
|
||||
icon: code
|
||||
order: 2
|
||||
---
|
||||
|
||||
This page contains all useful methods of `VM` class.
|
||||
|
||||
''')
|
||||
content = ''.join(output)
|
||||
# replace {...} to ; (multi-line match)
|
||||
content = re.sub(r'\{[^}]+?\}', r';', content, flags=re.DOTALL)
|
||||
f.write(content)
|
@ -10,7 +10,7 @@ def get_all_files(root: str):
|
||||
continue
|
||||
if file.startswith('_'):
|
||||
continue
|
||||
if not file.endswith('.cpp') and not file.endswith('.h') and not file.endswith('.hpp'):
|
||||
if not file.endswith('.c') and not file.endswith('.h') and not file.endswith('.hpp'):
|
||||
continue
|
||||
yield fullpath
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
@ -232,6 +232,10 @@ int c11__byte_index_to_unicode(const char* data, int n) {
|
||||
}
|
||||
|
||||
//////////////
|
||||
bool c11_bytes__eq(c11_bytes* self, c11_bytes* other) {
|
||||
if(self->size != other->size) return false;
|
||||
return memcmp(self->data, other->data, self->size) == 0;
|
||||
}
|
||||
|
||||
int c11_sv__cmp(c11_sv self, c11_sv other) {
|
||||
int res = strncmp(self.data, other.data, c11__min(self.size, other.size));
|
||||
|
@ -134,7 +134,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
case OP_LOAD_FUNCTION: {
|
||||
FuncDecl_ decl = c11__getitem(FuncDecl_, &frame->co->func_decls, byte.arg);
|
||||
Function* ud = py_newobject(SP(), tp_function, 0, sizeof(Function));
|
||||
Function__ctor(ud, decl, &frame->module);
|
||||
Function__ctor(ud, decl, frame->module);
|
||||
if(decl->nested) {
|
||||
ud->closure = FastLocals__to_namedict(frame->locals, frame->co);
|
||||
py_Name name = py_name(decl->code.name->data);
|
||||
@ -173,7 +173,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
PUSH(tmp);
|
||||
DISPATCH();
|
||||
}
|
||||
tmp = py_getdict(&frame->module, name);
|
||||
tmp = py_getdict(frame->module, name);
|
||||
if(tmp != NULL) {
|
||||
PUSH(tmp);
|
||||
DISPATCH();
|
||||
@ -193,7 +193,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
PUSH(tmp);
|
||||
DISPATCH();
|
||||
}
|
||||
tmp = py_getdict(&frame->module, name);
|
||||
tmp = py_getdict(frame->module, name);
|
||||
if(tmp != NULL) {
|
||||
PUSH(tmp);
|
||||
DISPATCH();
|
||||
@ -208,7 +208,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
}
|
||||
case OP_LOAD_GLOBAL: {
|
||||
py_Name name = byte.arg;
|
||||
py_Ref tmp = py_getdict(&frame->module, name);
|
||||
py_Ref tmp = py_getdict(frame->module, name);
|
||||
if(tmp != NULL) {
|
||||
PUSH(tmp);
|
||||
DISPATCH();
|
||||
@ -237,7 +237,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
DISPATCH();
|
||||
}
|
||||
// load global if attribute not found
|
||||
tmp = py_getdict(&frame->module, name);
|
||||
tmp = py_getdict(frame->module, name);
|
||||
if(tmp) {
|
||||
PUSH(tmp);
|
||||
DISPATCH();
|
||||
@ -300,13 +300,13 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
// }
|
||||
}
|
||||
} else {
|
||||
py_setdict(&frame->module, name, TOP());
|
||||
py_setdict(frame->module, name, TOP());
|
||||
}
|
||||
POP();
|
||||
DISPATCH();
|
||||
}
|
||||
case OP_STORE_GLOBAL: {
|
||||
py_setdict(&frame->module, byte.arg, TOP());
|
||||
py_setdict(frame->module, byte.arg, TOP());
|
||||
POP();
|
||||
DISPATCH();
|
||||
}
|
||||
@ -361,7 +361,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
// }
|
||||
}
|
||||
} else {
|
||||
bool ok = py_deldict(&frame->module, name);
|
||||
bool ok = py_deldict(frame->module, name);
|
||||
if(!ok) {
|
||||
NameError(name);
|
||||
goto __ERROR;
|
||||
@ -371,7 +371,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
}
|
||||
case OP_DELETE_GLOBAL: {
|
||||
py_Name name = byte.arg;
|
||||
bool ok = py_deldict(&frame->module, name);
|
||||
bool ok = py_deldict(frame->module, name);
|
||||
if(!ok) {
|
||||
NameError(name);
|
||||
goto __ERROR;
|
||||
@ -701,7 +701,9 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
DISPATCH();
|
||||
}
|
||||
case OP_YIELD_VALUE: {
|
||||
assert(false);
|
||||
py_assign(py_retval(), TOP());
|
||||
POP();
|
||||
return RES_YIELD;
|
||||
}
|
||||
/////////
|
||||
case OP_LIST_APPEND: {
|
||||
@ -800,7 +802,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
ImportError("cannot import name '%n'", name);
|
||||
goto __ERROR;
|
||||
} else {
|
||||
py_setdict(&frame->module, name, value);
|
||||
py_setdict(frame->module, name, value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -809,7 +811,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
if(!kv->key) continue;
|
||||
c11_sv name = py_name2sv(kv->key);
|
||||
if(name.size == 0 || name.data[0] == '_') continue;
|
||||
py_setdict(&frame->module, kv->key, &kv->value);
|
||||
py_setdict(frame->module, kv->key, &kv->value);
|
||||
}
|
||||
}
|
||||
POP();
|
||||
@ -855,7 +857,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
}
|
||||
POP();
|
||||
py_Type type =
|
||||
pk_newtype(py_name2str(name), base, &frame->module, NULL, true, false);
|
||||
pk_newtype(py_name2str(name), base, frame->module, NULL, true, false);
|
||||
PUSH(py_tpobject(type));
|
||||
self->__curr_class = TOP();
|
||||
DISPATCH();
|
||||
@ -864,7 +866,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
// [cls or decorated]
|
||||
py_Name name = byte.arg;
|
||||
// set into f_globals
|
||||
py_setdict(&frame->module, name, TOP());
|
||||
py_setdict(frame->module, name, TOP());
|
||||
|
||||
if(py_istype(TOP(), tp_type)) {
|
||||
// call on_end_subclass
|
||||
@ -948,7 +950,7 @@ FrameResult VM__run_top_frame(VM* self) {
|
||||
py_TValue* tmp = c11__at(py_TValue, &frame->co->consts, byte.arg);
|
||||
const char* string = py_tostr(tmp);
|
||||
// TODO: optimize this
|
||||
if(!py_exec(string, "<eval>", EVAL_MODE, &frame->module)) goto __ERROR;
|
||||
if(!py_exec(string, "<eval>", EVAL_MODE, frame->module)) goto __ERROR;
|
||||
PUSH(py_retval());
|
||||
DISPATCH();
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "pocketpy/interpreter/frame.h"
|
||||
#include "pocketpy/objects/codeobject.h"
|
||||
#include "pocketpy/objects/object.h"
|
||||
#include "pocketpy/pocketpy.h"
|
||||
|
||||
void ValueStack__ctor(ValueStack* self) {
|
||||
self->sp = self->begin;
|
||||
@ -35,7 +36,7 @@ UnwindTarget* UnwindTarget__new(UnwindTarget* next, int iblock, int offset) {
|
||||
void UnwindTarget__delete(UnwindTarget* self) { free(self); }
|
||||
|
||||
Frame* Frame__new(const CodeObject* co,
|
||||
py_TValue* module,
|
||||
py_GlobalRef module,
|
||||
py_StackRef function,
|
||||
py_StackRef p0,
|
||||
py_StackRef locals) {
|
||||
@ -44,7 +45,7 @@ Frame* Frame__new(const CodeObject* co,
|
||||
self->f_back = NULL;
|
||||
self->ip = (Bytecode*)co->codes.data - 1;
|
||||
self->co = co;
|
||||
self->module = *module;
|
||||
self->module = module;
|
||||
self->function = function;
|
||||
self->p0 = p0;
|
||||
self->locals = locals;
|
||||
|
22
src/interpreter/generator.c
Normal file
22
src/interpreter/generator.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include "pocketpy/interpreter/generator.h"
|
||||
#include "pocketpy/interpreter/frame.h"
|
||||
#include "pocketpy/interpreter/vm.h"
|
||||
#include "pocketpy/pocketpy.h"
|
||||
|
||||
void pk_newgenerator(py_Ref out, Frame* frame, int slots) {
|
||||
Generator* ud = py_newobject(out, tp_generator, slots, sizeof(Generator));
|
||||
ud->frame = frame;
|
||||
ud->state = 0;
|
||||
}
|
||||
|
||||
static bool generator__next__(int argc, py_Ref argv){
|
||||
return true;
|
||||
}
|
||||
|
||||
py_Type pk_generator__register() {
|
||||
py_Type type = pk_newtype("generator", tp_object, NULL, NULL, false, true);
|
||||
|
||||
py_bindmagic(type, __iter__, pk_wrapper__self);
|
||||
py_bindmagic(type, __next__, generator__next__);
|
||||
return type;
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
#include "pocketpy/common/memorypool.h"
|
||||
#include "pocketpy/common/sstream.h"
|
||||
#include "pocketpy/common/utils.h"
|
||||
#include "pocketpy/interpreter/generator.h"
|
||||
#include "pocketpy/objects/base.h"
|
||||
#include "pocketpy/common/_generated.h"
|
||||
#include "pocketpy/pocketpy.h"
|
||||
@ -126,9 +127,7 @@ void VM__ctor(VM* self) {
|
||||
validate(tp_NotImplementedType,
|
||||
pk_newtype("NotImplementedType", tp_object, NULL, NULL, false, true));
|
||||
validate(tp_ellipsis, pk_newtype("ellipsis", tp_object, NULL, NULL, false, true));
|
||||
|
||||
validate(tp_SyntaxError, pk_newtype("SyntaxError", tp_Exception, NULL, NULL, false, true));
|
||||
validate(tp_StopIteration, pk_newtype("StopIteration", tp_Exception, NULL, NULL, false, true));
|
||||
validate(tp_generator, pk_generator__register());
|
||||
|
||||
self->builtins = pk_builtins__register();
|
||||
|
||||
@ -140,6 +139,8 @@ void VM__ctor(VM* self) {
|
||||
validate(tp_##name, type); \
|
||||
} while(0)
|
||||
|
||||
INJECT_BUILTIN_EXC(StopIteration);
|
||||
INJECT_BUILTIN_EXC(SyntaxError);
|
||||
INJECT_BUILTIN_EXC(StackOverflowError);
|
||||
INJECT_BUILTIN_EXC(IOError);
|
||||
INJECT_BUILTIN_EXC(OSError);
|
||||
@ -160,11 +161,26 @@ void VM__ctor(VM* self) {
|
||||
#undef validate
|
||||
|
||||
/* Setup Public Builtin Types */
|
||||
py_Type public_types[] = {tp_object, tp_type, tp_int, tp_float,
|
||||
tp_bool, tp_str, tp_list, tp_tuple,
|
||||
tp_slice, tp_range, tp_bytes, tp_dict,
|
||||
tp_property, tp_staticmethod, tp_classmethod, tp_super,
|
||||
tp_BaseException, tp_Exception, tp_StopIteration, tp_SyntaxError};
|
||||
py_Type public_types[] = {
|
||||
tp_object,
|
||||
tp_type,
|
||||
tp_int,
|
||||
tp_float,
|
||||
tp_bool,
|
||||
tp_str,
|
||||
tp_list,
|
||||
tp_tuple,
|
||||
tp_slice,
|
||||
tp_range,
|
||||
tp_bytes,
|
||||
tp_dict,
|
||||
tp_property,
|
||||
tp_staticmethod,
|
||||
tp_classmethod,
|
||||
tp_super,
|
||||
tp_BaseException,
|
||||
tp_Exception,
|
||||
};
|
||||
|
||||
for(int i = 0; i < c11__count_array(public_types); i++) {
|
||||
py_TypeInfo* ti = c11__at(py_TypeInfo, &self->types, public_types[i]);
|
||||
@ -181,11 +197,13 @@ void VM__ctor(VM* self) {
|
||||
|
||||
// add python builtins
|
||||
do {
|
||||
bool ok = py_exec(kPythonLibs__set, "<builtins>", EXEC_MODE, &self->builtins);
|
||||
if(!ok) {
|
||||
py_printexc();
|
||||
c11__abort("failed to load python builtins!");
|
||||
}
|
||||
bool ok;
|
||||
ok = py_exec(kPythonLibs_builtins, "<builtins>", EXEC_MODE, &self->builtins);
|
||||
if(!ok) goto __ABORT;
|
||||
break;
|
||||
__ABORT:
|
||||
py_printexc();
|
||||
c11__abort("failed to load python builtins!");
|
||||
} while(0);
|
||||
|
||||
self->main = *py_newmodule("__main__");
|
||||
@ -435,9 +453,14 @@ FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall
|
||||
// submit the call
|
||||
VM__push_frame(self, Frame__new(co, &fn->module, p0, p0, argv));
|
||||
return opcall ? RES_CALL : VM__run_top_frame(self);
|
||||
case FuncType_GENERATOR:
|
||||
assert(false);
|
||||
break;
|
||||
case FuncType_GENERATOR: {
|
||||
bool ok = prepare_py_call(self->__vectorcall_buffer, argv, p1, kwargc, fn->decl);
|
||||
if(!ok) return RES_ERROR;
|
||||
Frame* frame = Frame__new(co, &fn->module, p0, p0, argv);
|
||||
pk_newgenerator(py_retval(), frame, 0);
|
||||
self->stack.sp = p0;
|
||||
return RES_RETURN;
|
||||
}
|
||||
// prepare_py_call(__vectorcall_buffer, args, kwargs, fn.decl);
|
||||
// s_data.reset(p0);
|
||||
// callstack.emplace(nullptr, co, fn._module, callable.get(), nullptr);
|
||||
@ -558,7 +581,7 @@ void ManagedHeap__mark(ManagedHeap* self) {
|
||||
}
|
||||
// mark frame
|
||||
for(Frame* frame = vm->top_frame; frame; frame = frame->f_back) {
|
||||
mark_value(&frame->module);
|
||||
mark_value(frame->module);
|
||||
}
|
||||
// mark vm's registers
|
||||
mark_value(&vm->last_retval);
|
||||
@ -624,4 +647,14 @@ void pk_print_stack(VM* self, Frame* frame, Bytecode byte) {
|
||||
byte.arg,
|
||||
stack_str->data);
|
||||
c11_string__delete(stack_str);
|
||||
}
|
||||
|
||||
bool pk_wrapper__self(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_assign(py_retval(), argv);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pk_wrapper__NotImplementedError(int argc, py_Ref argv){
|
||||
return py_exception(tp_NotImplementedError, "");
|
||||
}
|
@ -68,7 +68,7 @@ int py_import(const char* path_cstr) {
|
||||
c11_sv top_filename = c11_string__sv(vm->top_frame->co->src->filename);
|
||||
int is_init = c11_sv__endswith(top_filename, (c11_sv){"__init__.py", 11});
|
||||
|
||||
py_Ref package = py_getdict(&vm->top_frame->module, __path__);
|
||||
py_Ref package = py_getdict(vm->top_frame->module, __path__);
|
||||
c11_sv package_sv = py_tosv(package);
|
||||
if(package_sv.size == 0) {
|
||||
return ImportError("attempted relative import with no known parent package");
|
||||
@ -170,14 +170,6 @@ static bool builtins_len(int argc, py_Ref argv) {
|
||||
return py_len(argv);
|
||||
}
|
||||
|
||||
static bool builtins_reversed(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
// convert _0 to list object
|
||||
if(!py_tpcall(tp_list, 1, argv)) return false;
|
||||
py_list_reverse(py_retval());
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool builtins_hex(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
PY_CHECK_ARG_TYPE(0, tp_int);
|
||||
@ -221,23 +213,6 @@ static bool builtins_next(int argc, py_Ref argv) {
|
||||
return py_exception(tp_StopIteration, "");
|
||||
}
|
||||
|
||||
static bool builtins_sorted(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(3);
|
||||
// convert _0 to list object
|
||||
if(!py_tpcall(tp_list, 1, py_arg(0))) return false;
|
||||
py_push(py_retval()); // duptop
|
||||
py_push(py_retval()); // [| <list>]
|
||||
bool ok = py_pushmethod(py_name("sort")); // [| list.sort, <list>]
|
||||
if(!ok) return false;
|
||||
py_push(py_arg(1)); // [| list.sort, <list>, key]
|
||||
py_push(py_arg(2)); // [| list.sort, <list>, key, reverse]
|
||||
ok = py_vectorcall(2, 0); // [| ]
|
||||
if(!ok) return false;
|
||||
py_assign(py_retval(), py_peek(-1));
|
||||
py_pop();
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool builtins_hash(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_i64 val;
|
||||
@ -251,41 +226,9 @@ static bool builtins_abs(int argc, py_Ref argv) {
|
||||
return pk_callmagic(__abs__, 1, argv);
|
||||
}
|
||||
|
||||
static bool builtins_sum(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
|
||||
if(!py_iter(py_arg(0))) return false;
|
||||
py_push(py_retval()); // iter
|
||||
|
||||
py_i64 total_i64 = 0;
|
||||
py_f64 total_f64 = 0.0;
|
||||
bool is_float = false;
|
||||
while(true) {
|
||||
int res = py_next(py_peek(-1));
|
||||
if(res == -1) {
|
||||
py_pop();
|
||||
return false;
|
||||
}
|
||||
if(res == 0) break;
|
||||
|
||||
py_Ref item = py_retval();
|
||||
switch(item->type) {
|
||||
case tp_int: total_i64 += item->_i64; break;
|
||||
case tp_float:
|
||||
is_float = true;
|
||||
total_f64 += item->_f64;
|
||||
break;
|
||||
default: return TypeError("sum() expects an iterable of numbers");
|
||||
}
|
||||
}
|
||||
|
||||
if(is_float) {
|
||||
py_newfloat(py_retval(), total_f64 + total_i64);
|
||||
} else {
|
||||
py_newint(py_retval(), total_i64);
|
||||
}
|
||||
py_pop();
|
||||
return true;
|
||||
static bool builtins_divmod(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
return pk_callmagic(__divmod__, 2, argv);
|
||||
}
|
||||
|
||||
static bool builtins_print(int argc, py_Ref argv) {
|
||||
@ -309,23 +252,18 @@ static bool builtins_print(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool NoneType__repr__(int argc, py_Ref argv) {
|
||||
py_newstr(py_retval(), "None");
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool builtins_exec(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
PY_CHECK_ARG_TYPE(0, tp_str);
|
||||
Frame* frame = pk_current_vm->top_frame;
|
||||
return py_exec(py_tostr(argv), "<exec>", EXEC_MODE, &frame->module);
|
||||
return py_exec(py_tostr(argv), "<exec>", EXEC_MODE, frame->module);
|
||||
}
|
||||
|
||||
static bool builtins_eval(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
PY_CHECK_ARG_TYPE(0, tp_str);
|
||||
Frame* frame = pk_current_vm->top_frame;
|
||||
return py_exec(py_tostr(argv), "<eval>", EVAL_MODE, &frame->module);
|
||||
return py_exec(py_tostr(argv), "<eval>", EVAL_MODE, frame->module);
|
||||
}
|
||||
|
||||
static bool builtins_isinstance(int argc, py_Ref argv) {
|
||||
@ -409,24 +347,57 @@ static bool builtins_delattr(int argc, py_Ref argv) {
|
||||
return py_delattr(py_arg(0), name);
|
||||
}
|
||||
|
||||
static bool builtins_chr(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
PY_CHECK_ARG_TYPE(0, tp_int);
|
||||
py_i64 val = py_toint(py_arg(0));
|
||||
if(val < 0 || val > 128) { return ValueError("chr() arg not in range(128)"); }
|
||||
py_newstrn(py_retval(), (const char*)&val, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool builtins_ord(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
PY_CHECK_ARG_TYPE(0, tp_str);
|
||||
c11_sv sv = py_tosv(py_arg(0));
|
||||
if(sv.size != 1) {
|
||||
return TypeError("ord() expected a character, but string of length %d found", sv.size);
|
||||
}
|
||||
py_newint(py_retval(), sv.data[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool NoneType__repr__(int argc, py_Ref argv) {
|
||||
py_newstr(py_retval(), "None");
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ellipsis__repr__(int argc, py_Ref argv) {
|
||||
py_newstr(py_retval(), "Ellipsis");
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool NotImplementedType__repr__(int argc, py_Ref argv) {
|
||||
py_newstr(py_retval(), "NotImplemented");
|
||||
return true;
|
||||
}
|
||||
|
||||
py_TValue pk_builtins__register() {
|
||||
py_Ref builtins = py_newmodule("builtins");
|
||||
py_bindfunc(builtins, "repr", builtins_repr);
|
||||
py_bindfunc(builtins, "exit", builtins_exit);
|
||||
py_bindfunc(builtins, "len", builtins_len);
|
||||
py_bindfunc(builtins, "reversed", builtins_reversed);
|
||||
py_bindfunc(builtins, "hex", builtins_hex);
|
||||
py_bindfunc(builtins, "iter", builtins_iter);
|
||||
py_bindfunc(builtins, "next", builtins_next);
|
||||
py_bindfunc(builtins, "hash", builtins_hash);
|
||||
py_bindfunc(builtins, "abs", builtins_abs);
|
||||
py_bindfunc(builtins, "sum", builtins_sum);
|
||||
py_bindfunc(builtins, "divmod", builtins_divmod);
|
||||
|
||||
py_bindfunc(builtins, "exec", builtins_exec);
|
||||
py_bindfunc(builtins, "eval", builtins_eval);
|
||||
|
||||
py_bind(builtins, "print(*args, sep=' ', end='\\n')", builtins_print);
|
||||
py_bind(builtins, "sorted(iterable, key=None, reverse=False)", builtins_sorted);
|
||||
|
||||
py_bindfunc(builtins, "isinstance", builtins_isinstance);
|
||||
py_bindfunc(builtins, "issubclass", builtins_issubclass);
|
||||
@ -436,8 +407,13 @@ py_TValue pk_builtins__register() {
|
||||
py_bindfunc(builtins, "hasattr", builtins_hasattr);
|
||||
py_bindfunc(builtins, "delattr", builtins_delattr);
|
||||
|
||||
// None __repr__
|
||||
py_bindfunc(builtins, "chr", builtins_chr);
|
||||
py_bindfunc(builtins, "ord", builtins_ord);
|
||||
|
||||
// some patches
|
||||
py_bindmagic(tp_NoneType, __repr__, NoneType__repr__);
|
||||
py_bindmagic(tp_ellipsis, __repr__, ellipsis__repr__);
|
||||
py_bindmagic(tp_NotImplementedType, __repr__, NotImplementedType__repr__);
|
||||
return *builtins;
|
||||
}
|
||||
|
||||
|
@ -457,12 +457,6 @@ py_Type pk_dict__register() {
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
static bool dict_items__iter__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
*py_retval() = *argv;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool dict_items__next__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
DictIterator* iter = py_touserdata(py_arg(0));
|
||||
@ -478,7 +472,7 @@ static bool dict_items__next__(int argc, py_Ref argv) {
|
||||
|
||||
py_Type pk_dict_items__register() {
|
||||
py_Type type = pk_newtype("dict_items", tp_object, NULL, NULL, false, true);
|
||||
py_bindmagic(type, __iter__, dict_items__iter__);
|
||||
py_bindmagic(type, __iter__, pk_wrapper__self);
|
||||
py_bindmagic(type, __next__, dict_items__next__);
|
||||
return type;
|
||||
}
|
||||
|
@ -59,11 +59,6 @@ void py_list_insert(py_Ref self, int i, py_Ref val) {
|
||||
c11_vector__insert(py_TValue, userdata, i, *val);
|
||||
}
|
||||
|
||||
void py_list_reverse(py_Ref self) {
|
||||
List* userdata = py_touserdata(self);
|
||||
c11__reverse(py_TValue, userdata);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
static bool list__len__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
|
@ -36,10 +36,6 @@ py_Type pk_classmethod__register(){
|
||||
}
|
||||
|
||||
/* boundmethod */
|
||||
static bool boundmethod__new__(int argc, py_Ref argv) {
|
||||
return NotImplementedError();
|
||||
}
|
||||
|
||||
static bool boundmethod__self__getter(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_assign(py_retval(), py_getslot(argv, 0));
|
||||
@ -55,7 +51,6 @@ static bool boundmethod__func__getter(int argc, py_Ref argv) {
|
||||
py_Type pk_boundmethod__register(){
|
||||
py_Type type = pk_newtype("boundmethod", tp_object, NULL, NULL, false, true);
|
||||
|
||||
py_bindmagic(type, __new__, boundmethod__new__);
|
||||
py_bindproperty(type, "__self__", boundmethod__self__getter, NULL);
|
||||
py_bindproperty(type, "__func__", boundmethod__func__getter, NULL);
|
||||
return type;
|
||||
|
@ -83,8 +83,6 @@ static bool float__truediv__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#define ZeroDivisionError(msg) false
|
||||
|
||||
static bool number__pow__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
if(py_isint(&argv[0]) && py_isint(&argv[1])) {
|
||||
@ -124,7 +122,7 @@ static bool int__floordiv__(int argc, py_Ref argv) {
|
||||
py_i64 lhs = py_toint(&argv[0]);
|
||||
if(py_isint(&argv[1])) {
|
||||
py_i64 rhs = py_toint(&argv[1]);
|
||||
if(rhs == 0) return -1;
|
||||
if(rhs == 0) return ZeroDivisionError("integer division or modulo by zero");
|
||||
py_newint(py_retval(), lhs / rhs);
|
||||
} else {
|
||||
py_newnotimplemented(py_retval());
|
||||
@ -145,6 +143,19 @@ static bool int__mod__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool int__divmod__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
PY_CHECK_ARG_TYPE(1, tp_int);
|
||||
py_i64 lhs = py_toint(&argv[0]);
|
||||
py_i64 rhs = py_toint(&argv[1]);
|
||||
if(rhs == 0) return ZeroDivisionError("integer division or modulo by zero");
|
||||
py_newtuple(py_retval(), 2);
|
||||
ldiv_t res = ldiv(lhs, rhs);
|
||||
py_newint(py_getslot(py_retval(), 0), res.quot);
|
||||
py_newint(py_getslot(py_retval(), 1), res.rem);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool int__invert__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
py_i64 val = py_toint(&argv[0]);
|
||||
@ -459,9 +470,10 @@ void pk_number__register() {
|
||||
py_bindmagic(tp_int, __pow__, number__pow__);
|
||||
py_bindmagic(tp_float, __pow__, number__pow__);
|
||||
|
||||
// __floordiv__ & __mod__
|
||||
// __floordiv__ & __mod__ & __divmod__
|
||||
py_bindmagic(tp_int, __floordiv__, int__floordiv__);
|
||||
py_bindmagic(tp_int, __mod__, int__mod__);
|
||||
py_bindmagic(tp_int, __divmod__, int__divmod__);
|
||||
|
||||
// int.__invert__ & int.<BITWISE OP>
|
||||
py_bindmagic(tp_int, __invert__, int__invert__);
|
||||
|
@ -68,12 +68,6 @@ static bool range_iterator__new__(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool range_iterator__iter__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
*py_retval() = *py_arg(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool range_iterator__next__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
RangeIterator* ud = py_touserdata(py_arg(0));
|
||||
@ -91,7 +85,7 @@ py_Type pk_range_iterator__register() {
|
||||
py_Type type = pk_newtype("range_iterator", tp_object, NULL, NULL, false, true);
|
||||
|
||||
py_bindmagic(type, __new__, range_iterator__new__);
|
||||
py_bindmagic(type, __iter__, range_iterator__iter__);
|
||||
py_bindmagic(type, __iter__, pk_wrapper__self);
|
||||
py_bindmagic(type, __next__, range_iterator__next__);
|
||||
return type;
|
||||
}
|
@ -190,7 +190,7 @@ static bool str__getitem__(int argc, py_Ref argv) {
|
||||
}
|
||||
|
||||
#define DEF_STR_CMP_OP(op, __f, __cond) \
|
||||
static bool str##op(int argc, py_Ref argv) { \
|
||||
static bool str##op(int argc, py_Ref argv) { \
|
||||
PY_CHECK_ARGC(2); \
|
||||
c11_string* self = py_touserdata(&argv[0]); \
|
||||
if(py_arg(1)->type != tp_str) { \
|
||||
@ -355,17 +355,11 @@ static bool str__strip_impl(bool left, bool right, int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool str_strip(int argc, py_Ref argv) {
|
||||
return str__strip_impl(true, true, argc, argv);
|
||||
}
|
||||
static bool str_strip(int argc, py_Ref argv) { return str__strip_impl(true, true, argc, argv); }
|
||||
|
||||
static bool str_lstrip(int argc, py_Ref argv) {
|
||||
return str__strip_impl(true, false, argc, argv);
|
||||
}
|
||||
static bool str_lstrip(int argc, py_Ref argv) { return str__strip_impl(true, false, argc, argv); }
|
||||
|
||||
static bool str_rstrip(int argc, py_Ref argv) {
|
||||
return str__strip_impl(false, true, argc, argv);
|
||||
}
|
||||
static bool str_rstrip(int argc, py_Ref argv) { return str__strip_impl(false, true, argc, argv); }
|
||||
|
||||
static bool str_zfill(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
@ -423,13 +417,9 @@ static bool str__widthjust_impl(bool left, int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool str_ljust(int argc, py_Ref argv) {
|
||||
return str__widthjust_impl(true, argc, argv);
|
||||
}
|
||||
static bool str_ljust(int argc, py_Ref argv) { return str__widthjust_impl(true, argc, argv); }
|
||||
|
||||
static bool str_rjust(int argc, py_Ref argv) {
|
||||
return str__widthjust_impl(false, argc, argv);
|
||||
}
|
||||
static bool str_rjust(int argc, py_Ref argv) { return str__widthjust_impl(false, argc, argv); }
|
||||
|
||||
static bool str_find(int argc, py_Ref argv) {
|
||||
if(argc > 3) return TypeError("find() takes at most 3 arguments");
|
||||
@ -453,6 +443,15 @@ static bool str_index(int argc, py_Ref argv) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool str_encode(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
int size;
|
||||
const char* data = py_tostrn(argv, &size);
|
||||
unsigned char* p = py_newbytes(py_retval(), size);
|
||||
memcpy(p, data, size);
|
||||
return true;
|
||||
}
|
||||
|
||||
py_Type pk_str__register() {
|
||||
py_Type type = pk_newtype("str", tp_object, NULL, NULL, false, true);
|
||||
// no need to dtor because the memory is controlled by the object
|
||||
@ -492,15 +491,10 @@ py_Type pk_str__register() {
|
||||
py_bindmethod(tp_str, "rjust", str_rjust);
|
||||
py_bindmethod(tp_str, "find", str_find);
|
||||
py_bindmethod(tp_str, "index", str_index);
|
||||
py_bindmethod(tp_str, "encode", str_encode);
|
||||
return type;
|
||||
}
|
||||
|
||||
static bool str_iterator__iter__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
*py_retval() = argv[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool str_iterator__next__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
int* ud = py_touserdata(&argv[0]);
|
||||
@ -517,14 +511,127 @@ static bool str_iterator__next__(int argc, py_Ref argv) {
|
||||
py_Type pk_str_iterator__register() {
|
||||
py_Type type = pk_newtype("str_iterator", tp_object, NULL, NULL, false, true);
|
||||
|
||||
py_bindmagic(type, __iter__, str_iterator__iter__);
|
||||
py_bindmagic(type, __iter__, pk_wrapper__self);
|
||||
py_bindmagic(type, __next__, str_iterator__next__);
|
||||
return type;
|
||||
}
|
||||
|
||||
static bool bytes__new__(int argc, py_Ref argv){
|
||||
if(argc == 1){
|
||||
py_newbytes(py_retval(), 0);
|
||||
return true;
|
||||
}
|
||||
if(argc > 2) return TypeError("bytes() takes at most 1 argument");
|
||||
int length;
|
||||
py_TValue* p = pk_arrayview(&argv[1], &length);
|
||||
if(!p) return TypeError("bytes() argument must be a list or tuple");
|
||||
unsigned char* data = py_newbytes(py_retval(), length);
|
||||
for(int i = 0; i < length; i++){
|
||||
if(!py_checktype(&p[i], tp_int)) return false;
|
||||
py_i64 v = py_toint(&p[i]);
|
||||
if(v < 0 || v > 255) return ValueError("bytes must be in range(0, 256)");
|
||||
data[i] = v;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool bytes__repr__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
c11_bytes* self = py_touserdata(&argv[0]);
|
||||
c11_sbuf buf;
|
||||
c11_sbuf__ctor(&buf);
|
||||
c11_sbuf__write_char(&buf, 'b');
|
||||
c11_sbuf__write_quoted(&buf, (c11_sv){(const char*)self->data, self->size}, '\'');
|
||||
c11_sbuf__py_submit(&buf, py_retval());
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool bytes__getitem__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
int size;
|
||||
unsigned char* data = py_tobytes(&argv[0], &size);
|
||||
py_Ref _1 = py_arg(1);
|
||||
if(_1->type == tp_int) {
|
||||
int index = py_toint(_1);
|
||||
if(!pk__normalize_index(&index, size)) return false;
|
||||
py_newint(py_retval(), data[index]);
|
||||
return true;
|
||||
} else if(_1->type == tp_slice) {
|
||||
int start, stop, step;
|
||||
bool ok = pk__parse_int_slice(_1, size, &start, &stop, &step);
|
||||
if(!ok) return false;
|
||||
c11_vector res;
|
||||
c11_vector__ctor(&res, sizeof(unsigned char));
|
||||
for(int i = start; step > 0 ? i < stop : i > stop; i += step) {
|
||||
c11_vector__push(unsigned char, &res, data[i]);
|
||||
}
|
||||
unsigned char* p = py_newbytes(py_retval(), res.count);
|
||||
memcpy(p, res.data, res.count);
|
||||
c11_vector__dtor(&res);
|
||||
return true;
|
||||
} else {
|
||||
return TypeError("bytes indices must be integers");
|
||||
}
|
||||
}
|
||||
|
||||
static bool bytes__eq__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
c11_bytes* self = py_touserdata(&argv[0]);
|
||||
if(!py_istype(&argv[1], tp_bytes)) {
|
||||
py_newnotimplemented(py_retval());
|
||||
} else {
|
||||
c11_bytes* other = py_touserdata(&argv[1]);
|
||||
py_newbool(py_retval(), c11_bytes__eq(self, other));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool bytes__ne__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
c11_bytes* self = py_touserdata(&argv[0]);
|
||||
if(!py_istype(&argv[1], tp_bytes)) {
|
||||
py_newnotimplemented(py_retval());
|
||||
} else {
|
||||
c11_bytes* other = py_touserdata(&argv[1]);
|
||||
py_newbool(py_retval(), !c11_bytes__eq(self, other));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool bytes__add__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
c11_bytes* self = py_touserdata(&argv[0]);
|
||||
if(py_arg(1)->type != tp_bytes) {
|
||||
py_newnotimplemented(py_retval());
|
||||
} else {
|
||||
c11_bytes* other = py_touserdata(&argv[1]);
|
||||
unsigned char* p = py_newbytes(py_retval(), self->size + other->size);
|
||||
memcpy(p, self->data, self->size);
|
||||
memcpy(p + self->size, other->data, other->size);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool bytes_decode(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
int size;
|
||||
unsigned char* data = py_tobytes(&argv[0], &size);
|
||||
py_newstrn(py_retval(), (const char*)data, size);
|
||||
return true;
|
||||
}
|
||||
|
||||
py_Type pk_bytes__register() {
|
||||
py_Type type = pk_newtype("bytes", tp_object, NULL, NULL, false, true);
|
||||
// no need to dtor because the memory is controlled by the object
|
||||
|
||||
py_bindmagic(tp_bytes, __new__, bytes__new__);
|
||||
py_bindmagic(tp_bytes, __repr__, bytes__repr__);
|
||||
py_bindmagic(tp_bytes, __getitem__, bytes__getitem__);
|
||||
py_bindmagic(tp_bytes, __eq__, bytes__eq__);
|
||||
py_bindmagic(tp_bytes, __ne__, bytes__ne__);
|
||||
py_bindmagic(tp_bytes, __add__, bytes__add__);
|
||||
|
||||
py_bindmethod(tp_bytes, "decode", bytes_decode);
|
||||
return type;
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,8 @@ assert b'\xff\xee' == b'\xff\xee'
|
||||
a = '测试123'
|
||||
assert a == a.encode().decode()
|
||||
|
||||
|
||||
assert chr(0) == '\x00'
|
||||
assert ord('\x00') == 0
|
||||
|
||||
# test slice
|
||||
s = b"football"
|
||||
@ -33,4 +34,8 @@ assert a[::-1] == b"!dlroW ,olleH"
|
||||
assert a[::2] == b"Hlo ol!"
|
||||
assert a[2:5:2] == b"lo"
|
||||
assert a[5:2:-1] == b",ol"
|
||||
assert a[5:2:-2] == b",l"
|
||||
assert a[5:2:-2] == b",l"
|
||||
|
||||
assert bytes() == b''
|
||||
assert bytes((65,)) == b'A'
|
||||
assert bytes([0, 1, 2, 3]) == b'\x00\x01\x02\x03'
|
@ -1,21 +0,0 @@
|
||||
a = '测试 123'
|
||||
a = a.encode()
|
||||
|
||||
import base64
|
||||
|
||||
b = base64.b64encode(a)
|
||||
c = base64.b64decode(b)
|
||||
|
||||
assert a == c
|
||||
|
||||
|
||||
data = [66, 110, 145, 18, 176, 13, 255, 202, 173, 109, 178, 194, 171, 198, 143, 24, 113, 46, 70, 94, 71, 140, 159, 191, 134, 230, 190, 224, 223, 94, 217, 20, 241, 138, 104, 120, 249, 91, 134, 48, 108, 49, 0, 249, 235, 225, 228, 190, 63, 204, 216, 102, 153, 51, 79, 221, 234, 252, 231, 156, 74, 23, 131, 161, 172, 157, 26, 15, 88, 28, 21, 170, 86, 177, 177, 249, 111, 230, 35, 180, 61, 140, 33, 14, 74, 238, 253, 19, 177, 76, 249, 21, 35, 105, 24, 136, 187, 121, 71, 202, 239, 235, 71, 126, 60, 37, 83, 186, 102, 114, 95, 212, 81, 48, 102, 167, 208, 66, 250, 132, 199, 137, 141, 231, 126, 219, 125, 1, 86, 87, 132, 161, 55, 166, 192, 27, 95, 27, 237, 225, 32, 240, 234, 160, 247, 143, 241, 232, 195, 117, 83, 133, 69, 178, 239, 123, 144, 172, 34, 43, 56, 136, 184, 68, 65, 70, 61, 164, 109, 134, 142, 153, 125, 154, 62, 117, 166, 86, 234, 39, 73, 207, 67, 91, 88, 220, 43, 148, 201, 185, 128, 93, 151, 210, 167, 82, 87, 246, 171, 125, 210, 46, 60, 156, 4, 173, 219, 149, 24, 226, 63, 176, 92, 103, 126, 201, 254, 6, 186, 233, 165, 169, 237, 141, 252, 0, 195, 212, 222, 186, 103, 15, 137, 41, 251, 16, 163, 22, 177, 232, 205, 58, 50, 205, 89, 249, 38, 45, 98, 42, 155, 33, 225, 232, 16, 157, 91, 246, 207, 164, 150, 214, 76, 151, 179, 203, 67, 194, 213, 83, 2, 106, 109, 254, 15, 110, 168, 19, 114, 185, 174, 20, 106, 141, 116, 222, 205, 135, 222, 110, 90, 27, 61, 6, 118, 50, 155, 6, 224, 213, 109, 98, 252, 84, 166, 77, 124, 187, 187, 113, 173, 45, 17, 232, 208, 126, 248, 239, 18, 33, 205, 117, 44, 32, 223, 1, 221, 210, 41, 67, 28, 218, 218, 161, 209, 11, 93, 250, 96, 2, 43, 157, 217, 134, 183, 24, 105, 177, 74, 214, 18, 114, 191, 64, 195, 94, 194, 19, 115, 211, 103, 49, 218, 87, 8, 199, 50, 225, 174, 222, 75, 23, 159, 76, 56, 208, 224, 172, 48, 197, 126, 159, 191, 80, 216, 148, 30, 114, 231, 142, 100, 159, 67, 77, 190, 64, 182, 21, 108, 4, 232, 73, 145, 247, 196, 220, 197, 234, 55, 241, 212, 115, 115, 142, 172, 248, 132, 117, 115, 107, 176, 230, 130, 189, 160, 150, 63, 79, 253, 240, 113, 61, 222, 46, 102, 118, 100, 208, 170, 0, 60, 154, 102, 168, 241, 159, 146, 71, 55, 244, 123, 82, 49, 64, 231, 190, 49, 51, 16, 111, 153, 209, 208, 116, 19, 68, 139, 208, 105, 248, 80, 12, 237, 29, 63, 80, 127, 1, 118, 22, 39, 83, 25, 220, 75, 31, 152, 16, 94, 254, 141, 55, 6, 89, 45, 247, 229, 209, 239, 223, 226, 124, 50, 51, 219, 110, 100, 251, 122, 53, 166, 63, 43, 116, 190, 114, 169, 72, 18, 190, 55, 4, 249, 3, 200, 99, 0, 37, 94, 50, 58, 37, 56, 154, 18, 154, 127, 123, 187, 123, 110, 131, 14, 185, 76, 193, 11, 227, 36, 184, 88, 3, 222, 126, 32, 143, 125, 180, 104, 142, 84, 22, 53, 2, 38, 188, 187, 51, 163, 189, 25, 215, 94, 190, 196, 213, 155, 23, 84, 206, 237, 125, 76, 185, 12, 111, 201, 249, 101, 50, 217, 32, 3, 37, 49, 177, 4, 10, 123, 29, 126, 106, 108, 246, 89, 42, 182, 135, 11, 152, 122, 12, 23, 159, 212, 53, 44, 244, 48, 251, 130, 109, 191, 76, 148, 226, 83, 55, 225, 100, 196, 166, 171, 108, 91, 67, 226, 207, 143, 73, 81, 95, 69, 92, 141, 150, 108, 168, 235, 1, 33, 160, 158, 62, 149, 0, 200, 228, 176, 38, 112, 18, 253, 239, 107, 214, 17, 22, 112, 255, 117, 155, 248, 59, 113, 100, 145, 101, 245, 113, 230, 167, 58, 232, 195, 51, 76, 26, 7, 94, 201, 198, 96, 93, 8, 231, 60, 139, 37, 191, 37, 101, 155, 83, 246, 181, 109, 149, 241, 96, 168, 126, 232, 54, 230, 197, 179, 214, 148, 79, 13, 27, 195, 164, 146, 183, 129, 82, 82, 177, 2, 255, 8, 85, 214, 83, 244, 237, 143, 104, 107, 28, 215, 178, 46, 71, 175, 186, 77, 191, 93, 13, 204, 154, 234, 193, 231, 49, 27, 7, 66, 53, 170, 63, 3, 172, 177, 176, 255, 249, 116, 172, 165, 78, 64, 218, 147, 214, 206, 68, 42, 186, 119, 75, 28, 141, 187, 117, 21, 89, 69, 96, 79, 211, 1, 141]
|
||||
data = bytes(data)
|
||||
encoded = base64.b64encode(data)
|
||||
|
||||
res = 'Qm6RErAN/8qtbbLCq8aPGHEuRl5HjJ+/hua+4N9e2RTximh4+VuGMGwxAPnr4eS+P8zYZpkzT93q/OecSheDoaydGg9YHBWqVrGx+W/mI7Q9jCEOSu79E7FM+RUjaRiIu3lHyu/rR348JVO6ZnJf1FEwZqfQQvqEx4mN537bfQFWV4ShN6bAG18b7eEg8Oqg94/x6MN1U4VFsu97kKwiKziIuERBRj2kbYaOmX2aPnWmVuonSc9DW1jcK5TJuYBdl9KnUlf2q33SLjycBK3blRjiP7BcZ37J/ga66aWp7Y38AMPU3rpnD4kp+xCjFrHozToyzVn5Ji1iKpsh4egQnVv2z6SW1kyXs8tDwtVTAmpt/g9uqBNyua4Uao103s2H3m5aGz0GdjKbBuDVbWL8VKZNfLu7ca0tEejQfvjvEiHNdSwg3wHd0ilDHNraodELXfpgAiud2Ya3GGmxStYScr9Aw17CE3PTZzHaVwjHMuGu3ksXn0w40OCsMMV+n79Q2JQecueOZJ9DTb5AthVsBOhJkffE3MXqN/HUc3OOrPiEdXNrsOaCvaCWP0/98HE93i5mdmTQqgA8mmao8Z+SRzf0e1IxQOe+MTMQb5nR0HQTRIvQafhQDO0dP1B/AXYWJ1MZ3EsfmBBe/o03Blkt9+XR79/ifDIz225k+3o1pj8rdL5yqUgSvjcE+QPIYwAlXjI6JTiaEpp/e7t7boMOuUzBC+MkuFgD3n4gj320aI5UFjUCJry7M6O9GddevsTVmxdUzu19TLkMb8n5ZTLZIAMlMbEECnsdfmps9lkqtocLmHoMF5/UNSz0MPuCbb9MlOJTN+FkxKarbFtD4s+PSVFfRVyNlmyo6wEhoJ4+lQDI5LAmcBL972vWERZw/3Wb+DtxZJFl9XHmpzrowzNMGgdeycZgXQjnPIslvyVlm1P2tW2V8WCofug25sWz1pRPDRvDpJK3gVJSsQL/CFXWU/Ttj2hrHNeyLkevuk2/XQ3MmurB5zEbB0I1qj8DrLGw//l0rKVOQNqT1s5EKrp3SxyNu3UVWUVgT9MBjQ=='
|
||||
assert encoded.decode() == res
|
||||
|
||||
decoded = base64.b64decode(encoded)
|
||||
assert decoded == data
|
||||
|
@ -1,50 +0,0 @@
|
||||
import csv
|
||||
def test(data: str, expected):
|
||||
ret = list(csv.reader(data.splitlines()))
|
||||
assert ret==expected, f"Expected {expected}, got {ret}"
|
||||
|
||||
test("""a,b,c
|
||||
1,2,3
|
||||
""", [['a', 'b', 'c'], ['1', '2', '3']])
|
||||
|
||||
test("""a,b,c
|
||||
1,2,"3"
|
||||
""", [['a', 'b', 'c'], ['1', '2', '3']])
|
||||
|
||||
test("""a,b,c
|
||||
1,2,"3,,"
|
||||
""", [['a', 'b', 'c'], ['1', '2', '3,,']])
|
||||
|
||||
test("""a,b,c
|
||||
1,2,'3'
|
||||
""", [['a', 'b', 'c'], ['1', '2', '\'3\'']])
|
||||
|
||||
test('''a,b,c
|
||||
1,2,"123"""
|
||||
''', [['a', 'b', 'c'], ['1', '2', '123"']])
|
||||
|
||||
test("""a,b,c,
|
||||
1,2,3,
|
||||
""", [['a', 'b', 'c', ''], ['1', '2', '3', '']])
|
||||
|
||||
test("""a,b ,c,
|
||||
1,"22""33",3
|
||||
""", [['a', 'b ', 'c', ''], ['1', '22"33', '3']])
|
||||
|
||||
# newline
|
||||
test('''a,b,c
|
||||
1,2,"3,
|
||||
4"
|
||||
5,"a,""
|
||||
b",7
|
||||
''', [['a', 'b', 'c'], ['1', '2', '3,\n 4'], ['5', 'a,"\nb', '7']])
|
||||
|
||||
ret = csv.DictReader("""a,b,c
|
||||
1,2,3
|
||||
"4",5,6
|
||||
""".splitlines())
|
||||
|
||||
assert list(ret)==[
|
||||
{'a': '1', 'b': '2', 'c': '3'},
|
||||
{'a': '4', 'b': '5', 'c': '6'},
|
||||
]
|
Loading…
x
Reference in New Issue
Block a user