mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-21 12:00:18 +00:00
...
This commit is contained in:
parent
cd9a9f7119
commit
56763e05f9
@ -11,8 +11,8 @@ extern "C" {
|
|||||||
#define kPoolObjectArenaSize (256*1024)
|
#define kPoolObjectArenaSize (256*1024)
|
||||||
#define kPoolObjectMaxBlocks (kPoolObjectArenaSize / kPoolObjectBlockSize)
|
#define kPoolObjectMaxBlocks (kPoolObjectArenaSize / kPoolObjectBlockSize)
|
||||||
|
|
||||||
void pk_MemoryPools__initialize();
|
void MemoryPools__initialize();
|
||||||
void pk_MemoryPools__finalize();
|
void MemoryPools__finalize();
|
||||||
|
|
||||||
void* PoolExpr_alloc();
|
void* PoolExpr_alloc();
|
||||||
void PoolExpr_dealloc(void*);
|
void PoolExpr_dealloc(void*);
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Error* pk_compile(pk_SourceData_ src, CodeObject* out);
|
Error* pk_compile(SourceData_ src, CodeObject* out);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern const char* pk_TokenSymbols[];
|
extern const char* TokenSymbols[];
|
||||||
|
|
||||||
typedef enum TokenIndex{
|
typedef enum TokenIndex{
|
||||||
TK_EOF, TK_EOL, TK_SOF,
|
TK_EOF, TK_EOL, TK_SOF,
|
||||||
@ -88,11 +88,11 @@ enum Precedence {
|
|||||||
PREC_HIGHEST,
|
PREC_HIGHEST,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef c11_array pk_TokenArray;
|
typedef c11_array TokenArray;
|
||||||
|
|
||||||
Error* pk_Lexer__process(pk_SourceData_ src, pk_TokenArray* out_tokens);
|
Error* Lexer__process(SourceData_ src, TokenArray* out_tokens);
|
||||||
Error* pk_Lexer__process_and_dump(pk_SourceData_ src, c11_string** out_string);
|
Error* Lexer__process_and_dump(SourceData_ src, c11_string** out_string);
|
||||||
void pk_TokenArray__dtor(pk_TokenArray* self);
|
void TokenArray__dtor(TokenArray* self);
|
||||||
|
|
||||||
#define Token__sv(self) (c11_sv){(self)->start, (self)->length}
|
#define Token__sv(self) (c11_sv){(self)->start, (self)->length}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
py_TValue* FastLocals__try_get_by_name(py_TValue* locals, const CodeObject* co, py_Name name);
|
py_TValue* FastLocals__try_get_by_name(py_TValue* locals, const CodeObject* co, py_Name name);
|
||||||
pk_NameDict* FastLocals__to_namedict(py_TValue* locals, const CodeObject* co);
|
NameDict* FastLocals__to_namedict(py_TValue* locals, const CodeObject* co);
|
||||||
|
|
||||||
typedef struct ValueStack {
|
typedef struct ValueStack {
|
||||||
// We allocate extra PK_VM_STACK_SIZE/128 places to keep `_sp` valid when `is_overflow() ==
|
// We allocate extra PK_VM_STACK_SIZE/128 places to keep `_sp` valid when `is_overflow() ==
|
||||||
|
@ -5,29 +5,29 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct pk_ManagedHeap{
|
typedef struct ManagedHeap{
|
||||||
c11_vector no_gc;
|
c11_vector no_gc;
|
||||||
c11_vector gen;
|
c11_vector gen;
|
||||||
|
|
||||||
int gc_threshold;
|
int gc_threshold;
|
||||||
int gc_counter;
|
int gc_counter;
|
||||||
pk_VM* vm;
|
VM* vm;
|
||||||
|
|
||||||
void (*gc_on_delete)(pk_VM*, PyObject*);
|
void (*gc_on_delete)(VM*, PyObject*);
|
||||||
} pk_ManagedHeap;
|
} ManagedHeap;
|
||||||
|
|
||||||
void pk_ManagedHeap__ctor(pk_ManagedHeap* self, pk_VM* vm);
|
void ManagedHeap__ctor(ManagedHeap* self, VM* vm);
|
||||||
void pk_ManagedHeap__dtor(pk_ManagedHeap* self);
|
void ManagedHeap__dtor(ManagedHeap* self);
|
||||||
|
|
||||||
void pk_ManagedHeap__collect_if_needed(pk_ManagedHeap* self);
|
void ManagedHeap__collect_if_needed(ManagedHeap* self);
|
||||||
int pk_ManagedHeap__collect(pk_ManagedHeap* self);
|
int ManagedHeap__collect(ManagedHeap* self);
|
||||||
int pk_ManagedHeap__sweep(pk_ManagedHeap* self);
|
int ManagedHeap__sweep(ManagedHeap* self);
|
||||||
|
|
||||||
PyObject* pk_ManagedHeap__new(pk_ManagedHeap* self, py_Type type, int slots, int udsize);
|
PyObject* ManagedHeap__new(ManagedHeap* self, py_Type type, int slots, int udsize);
|
||||||
PyObject* pk_ManagedHeap__gcnew(pk_ManagedHeap* self, py_Type type, int slots, int udsize);
|
PyObject* ManagedHeap__gcnew(ManagedHeap* self, py_Type type, int slots, int udsize);
|
||||||
|
|
||||||
// external implementation
|
// external implementation
|
||||||
void pk_ManagedHeap__mark(pk_ManagedHeap* self);
|
void ManagedHeap__mark(ManagedHeap* self);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct pk_TypeInfo {
|
typedef struct py_TypeInfo {
|
||||||
py_Name name;
|
py_Name name;
|
||||||
py_Type base;
|
py_Type base;
|
||||||
|
|
||||||
@ -24,17 +24,17 @@ typedef struct pk_TypeInfo {
|
|||||||
|
|
||||||
c11_vector /*T=py_Name*/ annotated_fields;
|
c11_vector /*T=py_Name*/ annotated_fields;
|
||||||
|
|
||||||
void (*on_end_subclass)(struct pk_TypeInfo*); // backdoor for enum module
|
void (*on_end_subclass)(struct py_TypeInfo*); // backdoor for enum module
|
||||||
|
|
||||||
/* Magic Slots */
|
/* Magic Slots */
|
||||||
py_TValue magic[64];
|
py_TValue magic[64];
|
||||||
} pk_TypeInfo;
|
} py_TypeInfo;
|
||||||
|
|
||||||
typedef struct pk_VM {
|
typedef struct VM {
|
||||||
Frame* top_frame;
|
Frame* top_frame;
|
||||||
|
|
||||||
pk_NameDict modules;
|
NameDict modules;
|
||||||
c11_vector /*T=pk_TypeInfo*/ types;
|
c11_vector /*T=py_TypeInfo*/ types;
|
||||||
|
|
||||||
py_TValue builtins; // builtins module
|
py_TValue builtins; // builtins module
|
||||||
py_TValue main; // __main__ module
|
py_TValue main; // __main__ module
|
||||||
@ -53,15 +53,15 @@ typedef struct pk_VM {
|
|||||||
FuncDecl_ __dynamic_func_decl;
|
FuncDecl_ __dynamic_func_decl;
|
||||||
py_TValue __vectorcall_buffer[PK_MAX_CO_VARNAMES];
|
py_TValue __vectorcall_buffer[PK_MAX_CO_VARNAMES];
|
||||||
|
|
||||||
pk_ManagedHeap heap;
|
ManagedHeap heap;
|
||||||
ValueStack stack; // put `stack` at the end for better cache locality
|
ValueStack stack; // put `stack` at the end for better cache locality
|
||||||
} pk_VM;
|
} VM;
|
||||||
|
|
||||||
void pk_VM__ctor(pk_VM* self);
|
void VM__ctor(VM* self);
|
||||||
void pk_VM__dtor(pk_VM* self);
|
void VM__dtor(VM* self);
|
||||||
|
|
||||||
void pk_VM__push_frame(pk_VM* self, Frame* frame);
|
void VM__push_frame(VM* self, Frame* frame);
|
||||||
void pk_VM__pop_frame(pk_VM* self);
|
void VM__pop_frame(VM* self);
|
||||||
|
|
||||||
bool pk__parse_int_slice(py_Ref slice, int length, int* start, int* stop, int* step);
|
bool pk__parse_int_slice(py_Ref slice, int length, int* start, int* stop, int* step);
|
||||||
bool pk__normalize_index(int* index, int length);
|
bool pk__normalize_index(int* index, int length);
|
||||||
@ -69,14 +69,14 @@ bool pk__normalize_index(int* index, int length);
|
|||||||
void pk_list__mark(void* ud, void (*marker)(py_TValue*));
|
void pk_list__mark(void* ud, void (*marker)(py_TValue*));
|
||||||
void pk_dict__mark(void* ud, void (*marker)(py_TValue*));
|
void pk_dict__mark(void* ud, void (*marker)(py_TValue*));
|
||||||
|
|
||||||
typedef enum pk_FrameResult {
|
typedef enum FrameResult {
|
||||||
RES_RETURN,
|
RES_RETURN,
|
||||||
RES_CALL,
|
RES_CALL,
|
||||||
RES_YIELD,
|
RES_YIELD,
|
||||||
RES_ERROR,
|
RES_ERROR,
|
||||||
} pk_FrameResult;
|
} FrameResult;
|
||||||
|
|
||||||
pk_FrameResult pk_VM__run_top_frame(pk_VM* self);
|
FrameResult VM__run_top_frame(VM* self);
|
||||||
|
|
||||||
py_Type pk_newtype(const char* name,
|
py_Type pk_newtype(const char* name,
|
||||||
py_Type base,
|
py_Type base,
|
||||||
@ -85,7 +85,7 @@ py_Type pk_newtype(const char* name,
|
|||||||
bool is_python,
|
bool is_python,
|
||||||
bool is_sealed);
|
bool is_sealed);
|
||||||
|
|
||||||
pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bool opcall);
|
FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall);
|
||||||
|
|
||||||
const char* pk_opname(Opcode op);
|
const char* pk_opname(Opcode op);
|
||||||
|
|
||||||
@ -100,9 +100,9 @@ bool pk_callmagic(py_Name name, int argc, py_Ref argv);
|
|||||||
/// Assumes [a, b] are on the stack, performs a binary op.
|
/// Assumes [a, b] are on the stack, performs a binary op.
|
||||||
/// The result is stored in `self->last_retval`.
|
/// The result is stored in `self->last_retval`.
|
||||||
/// The stack remains unchanged.
|
/// The stack remains unchanged.
|
||||||
bool pk_stack_binaryop(pk_VM* self, py_Name op, py_Name rop);
|
bool pk_stack_binaryop(VM* self, py_Name op, py_Name rop);
|
||||||
|
|
||||||
void pk_print_stack(pk_VM* self, Frame* frame, Bytecode byte);
|
void pk_print_stack(VM* self, Frame* frame, Bytecode byte);
|
||||||
|
|
||||||
// type registration
|
// type registration
|
||||||
void pk_object__register();
|
void pk_object__register();
|
||||||
|
@ -14,8 +14,8 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct PyObject PyObject;
|
typedef struct PyObject PyObject;
|
||||||
typedef struct pk_VM pk_VM;
|
typedef struct VM VM;
|
||||||
extern pk_VM* pk_current_vm;
|
extern VM* pk_current_vm;
|
||||||
|
|
||||||
typedef struct py_TValue {
|
typedef struct py_TValue {
|
||||||
py_Type type;
|
py_Type type;
|
||||||
|
@ -68,7 +68,7 @@ typedef struct BytecodeEx {
|
|||||||
} BytecodeEx;
|
} BytecodeEx;
|
||||||
|
|
||||||
typedef struct CodeObject {
|
typedef struct CodeObject {
|
||||||
pk_SourceData_ src;
|
SourceData_ src;
|
||||||
c11_string* name;
|
c11_string* name;
|
||||||
|
|
||||||
c11_vector /*T=Bytecode*/ codes;
|
c11_vector /*T=Bytecode*/ codes;
|
||||||
@ -88,7 +88,7 @@ typedef struct CodeObject {
|
|||||||
int end_line;
|
int end_line;
|
||||||
} CodeObject;
|
} CodeObject;
|
||||||
|
|
||||||
void CodeObject__ctor(CodeObject* self, pk_SourceData_ src, c11_sv name);
|
void CodeObject__ctor(CodeObject* self, SourceData_ src, c11_sv name);
|
||||||
void CodeObject__dtor(CodeObject* self);
|
void CodeObject__dtor(CodeObject* self);
|
||||||
int CodeObject__add_varname(CodeObject* self, py_Name name);
|
int CodeObject__add_varname(CodeObject* self, py_Name name);
|
||||||
void CodeObject__gc_mark(const CodeObject* self);
|
void CodeObject__gc_mark(const CodeObject* self);
|
||||||
@ -118,7 +118,7 @@ typedef struct FuncDecl {
|
|||||||
|
|
||||||
typedef FuncDecl* FuncDecl_;
|
typedef FuncDecl* FuncDecl_;
|
||||||
|
|
||||||
FuncDecl_ FuncDecl__rcnew(pk_SourceData_ src, c11_sv name);
|
FuncDecl_ FuncDecl__rcnew(SourceData_ src, c11_sv name);
|
||||||
bool FuncDecl__is_duplicated_arg(const FuncDecl* self, py_Name name);
|
bool FuncDecl__is_duplicated_arg(const FuncDecl* self, py_Name name);
|
||||||
void FuncDecl__add_arg(FuncDecl* self, py_Name name);
|
void FuncDecl__add_arg(FuncDecl* self, py_Name name);
|
||||||
void FuncDecl__add_kwarg(FuncDecl* self, py_Name name, const py_TValue* value);
|
void FuncDecl__add_kwarg(FuncDecl* self, py_Name name, const py_TValue* value);
|
||||||
@ -139,7 +139,7 @@ typedef struct Function {
|
|||||||
FuncDecl_ decl;
|
FuncDecl_ decl;
|
||||||
py_TValue module; // weak ref
|
py_TValue module; // weak ref
|
||||||
PyObject* clazz; // weak ref
|
PyObject* clazz; // weak ref
|
||||||
pk_NameDict* closure; // strong ref
|
NameDict* closure; // strong ref
|
||||||
py_CFunction cfunc; // wrapped C function
|
py_CFunction cfunc; // wrapped C function
|
||||||
} Function;
|
} Function;
|
||||||
|
|
||||||
|
@ -12,14 +12,14 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct{
|
typedef struct{
|
||||||
pk_SourceData_ src;
|
SourceData_ src;
|
||||||
int lineno;
|
int lineno;
|
||||||
char msg[100];
|
char msg[100];
|
||||||
} Error;
|
} Error;
|
||||||
|
|
||||||
void py_BaseException__set_lineno(py_Ref, int lineno, const CodeObject* code);
|
void py_BaseException__set_lineno(py_Ref, int lineno, const CodeObject* code);
|
||||||
int py_BaseException__get_lineno(py_Ref, const CodeObject* code);
|
int py_BaseException__get_lineno(py_Ref, const CodeObject* code);
|
||||||
void py_BaseException__stpush(py_Ref, pk_SourceData_ src, int lineno, const char* func_name);
|
void py_BaseException__stpush(py_Ref, SourceData_ src, int lineno, const char* func_name);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ extern "C" {
|
|||||||
#define SMALLMAP_T__HEADER
|
#define SMALLMAP_T__HEADER
|
||||||
#define K uint16_t
|
#define K uint16_t
|
||||||
#define V py_TValue
|
#define V py_TValue
|
||||||
#define NAME pk_NameDict
|
#define NAME NameDict
|
||||||
#include "pocketpy/xmacros/smallmap.h"
|
#include "pocketpy/xmacros/smallmap.h"
|
||||||
#undef SMALLMAP_T__HEADER
|
#undef SMALLMAP_T__HEADER
|
||||||
|
|
||||||
|
@ -22,10 +22,10 @@ typedef struct PyObject {
|
|||||||
// | HEADER | <dict> | <userdata>
|
// | HEADER | <dict> | <userdata>
|
||||||
|
|
||||||
py_TValue* PyObject__slots(PyObject* self);
|
py_TValue* PyObject__slots(PyObject* self);
|
||||||
pk_NameDict* PyObject__dict(PyObject* self);
|
NameDict* PyObject__dict(PyObject* self);
|
||||||
void* PyObject__userdata(PyObject* self);
|
void* PyObject__userdata(PyObject* self);
|
||||||
|
|
||||||
#define PK_OBJ_SLOTS_SIZE(slots) ((slots) >= 0 ? sizeof(py_TValue) * (slots) : sizeof(pk_NameDict))
|
#define PK_OBJ_SLOTS_SIZE(slots) ((slots) >= 0 ? sizeof(py_TValue) * (slots) : sizeof(NameDict))
|
||||||
|
|
||||||
PyObject* PyObject__new(py_Type type, int slots, int size);
|
PyObject* PyObject__new(py_Type type, int slots, int size);
|
||||||
void PyObject__delete(PyObject* self);
|
void PyObject__delete(PyObject* self);
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct pk_SourceData {
|
struct SourceData {
|
||||||
RefCounted rc;
|
RefCounted rc;
|
||||||
enum py_CompileMode mode;
|
enum py_CompileMode mode;
|
||||||
bool is_precompiled;
|
bool is_precompiled;
|
||||||
@ -23,17 +23,17 @@ struct pk_SourceData {
|
|||||||
c11_vector /*T=c11_string* */ _precompiled_tokens;
|
c11_vector /*T=c11_string* */ _precompiled_tokens;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct pk_SourceData* pk_SourceData_;
|
typedef struct SourceData* SourceData_;
|
||||||
|
|
||||||
pk_SourceData_ pk_SourceData__rcnew(const char* source,
|
SourceData_ SourceData__rcnew(const char* source,
|
||||||
const char* filename,
|
const char* filename,
|
||||||
enum py_CompileMode mode,
|
enum py_CompileMode mode,
|
||||||
bool is_dynamic);
|
bool is_dynamic);
|
||||||
bool pk_SourceData__get_line(const struct pk_SourceData* self,
|
bool SourceData__get_line(const struct SourceData* self,
|
||||||
int lineno,
|
int lineno,
|
||||||
const char** st,
|
const char** st,
|
||||||
const char** ed);
|
const char** ed);
|
||||||
void pk_SourceData__snapshot(const struct pk_SourceData* self,
|
void SourceData__snapshot(const struct SourceData* self,
|
||||||
c11_sbuf* ss,
|
c11_sbuf* ss,
|
||||||
int lineno,
|
int lineno,
|
||||||
const char* cursor,
|
const char* cursor,
|
||||||
|
@ -242,13 +242,13 @@ static FixedMemoryPool PoolExpr;
|
|||||||
static FixedMemoryPool PoolFrame;
|
static FixedMemoryPool PoolFrame;
|
||||||
static MemoryPool PoolObject;
|
static MemoryPool PoolObject;
|
||||||
|
|
||||||
void pk_MemoryPools__initialize(){
|
void MemoryPools__initialize(){
|
||||||
FixedMemoryPool__ctor(&PoolExpr, kPoolExprBlockSize, 64);
|
FixedMemoryPool__ctor(&PoolExpr, kPoolExprBlockSize, 64);
|
||||||
FixedMemoryPool__ctor(&PoolFrame, kPoolFrameBlockSize, 128);
|
FixedMemoryPool__ctor(&PoolFrame, kPoolFrameBlockSize, 128);
|
||||||
MemoryPool__ctor(&PoolObject);
|
MemoryPool__ctor(&PoolObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pk_MemoryPools__finalize(){
|
void MemoryPools__finalize(){
|
||||||
FixedMemoryPool__dtor(&PoolExpr);
|
FixedMemoryPool__dtor(&PoolExpr);
|
||||||
FixedMemoryPool__dtor(&PoolFrame);
|
FixedMemoryPool__dtor(&PoolFrame);
|
||||||
MemoryPool__dtor(&PoolObject);
|
MemoryPool__dtor(&PoolObject);
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
static void pk_SourceData__ctor(struct pk_SourceData* self,
|
static void SourceData__ctor(struct SourceData* self,
|
||||||
const char* source,
|
const char* source,
|
||||||
const char* filename,
|
const char* filename,
|
||||||
enum py_CompileMode mode,
|
enum py_CompileMode mode,
|
||||||
@ -31,7 +31,7 @@ static void pk_SourceData__ctor(struct pk_SourceData* self,
|
|||||||
c11_vector__push(const char*, &self->line_starts, self->source->data);
|
c11_vector__push(const char*, &self->line_starts, self->source->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pk_SourceData__dtor(struct pk_SourceData* self) {
|
static void SourceData__dtor(struct SourceData* self) {
|
||||||
c11_string__delete(self->filename);
|
c11_string__delete(self->filename);
|
||||||
c11_string__delete(self->source);
|
c11_string__delete(self->source);
|
||||||
|
|
||||||
@ -43,18 +43,18 @@ static void pk_SourceData__dtor(struct pk_SourceData* self) {
|
|||||||
c11_vector__dtor(&self->_precompiled_tokens);
|
c11_vector__dtor(&self->_precompiled_tokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
pk_SourceData_ pk_SourceData__rcnew(const char* source,
|
SourceData_ SourceData__rcnew(const char* source,
|
||||||
const char* filename,
|
const char* filename,
|
||||||
enum py_CompileMode mode,
|
enum py_CompileMode mode,
|
||||||
bool is_dynamic) {
|
bool is_dynamic) {
|
||||||
pk_SourceData_ self = malloc(sizeof(struct pk_SourceData));
|
SourceData_ self = malloc(sizeof(struct SourceData));
|
||||||
pk_SourceData__ctor(self, source, filename, mode, is_dynamic);
|
SourceData__ctor(self, source, filename, mode, is_dynamic);
|
||||||
self->rc.count = 1;
|
self->rc.count = 1;
|
||||||
self->rc.dtor = (void (*)(void*))pk_SourceData__dtor;
|
self->rc.dtor = (void (*)(void*))SourceData__dtor;
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pk_SourceData__get_line(const struct pk_SourceData* self,
|
bool SourceData__get_line(const struct SourceData* self,
|
||||||
int lineno,
|
int lineno,
|
||||||
const char** st,
|
const char** st,
|
||||||
const char** ed) {
|
const char** ed) {
|
||||||
@ -71,7 +71,7 @@ bool pk_SourceData__get_line(const struct pk_SourceData* self,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pk_SourceData__snapshot(const struct pk_SourceData* self,
|
void SourceData__snapshot(const struct SourceData* self,
|
||||||
c11_sbuf* ss,
|
c11_sbuf* ss,
|
||||||
int lineno,
|
int lineno,
|
||||||
const char* cursor,
|
const char* cursor,
|
||||||
@ -86,7 +86,7 @@ void pk_SourceData__snapshot(const struct pk_SourceData* self,
|
|||||||
if(!self->is_precompiled) {
|
if(!self->is_precompiled) {
|
||||||
c11_sbuf__write_char(ss, '\n');
|
c11_sbuf__write_char(ss, '\n');
|
||||||
const char *st = NULL, *ed;
|
const char *st = NULL, *ed;
|
||||||
if(pk_SourceData__get_line(self, lineno, &st, &ed)) {
|
if(SourceData__get_line(self, lineno, &st, &ed)) {
|
||||||
while(st < ed && isblank(*st))
|
while(st < ed && isblank(*st))
|
||||||
++st;
|
++st;
|
||||||
if(st < ed) {
|
if(st < ed) {
|
||||||
|
@ -1435,13 +1435,13 @@ typedef struct PrattRule {
|
|||||||
const static PrattRule rules[TK__COUNT__];
|
const static PrattRule rules[TK__COUNT__];
|
||||||
|
|
||||||
typedef struct Compiler {
|
typedef struct Compiler {
|
||||||
pk_SourceData_ src; // weakref
|
SourceData_ src; // weakref
|
||||||
pk_TokenArray tokens;
|
TokenArray tokens;
|
||||||
int i;
|
int i;
|
||||||
c11_vector /*T=CodeEmitContext*/ contexts;
|
c11_vector /*T=CodeEmitContext*/ contexts;
|
||||||
} Compiler;
|
} Compiler;
|
||||||
|
|
||||||
static void Compiler__ctor(Compiler* self, pk_SourceData_ src, pk_TokenArray tokens) {
|
static void Compiler__ctor(Compiler* self, SourceData_ src, TokenArray tokens) {
|
||||||
self->src = src;
|
self->src = src;
|
||||||
self->tokens = tokens;
|
self->tokens = tokens;
|
||||||
self->i = 0;
|
self->i = 0;
|
||||||
@ -1449,7 +1449,7 @@ static void Compiler__ctor(Compiler* self, pk_SourceData_ src, pk_TokenArray tok
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void Compiler__dtor(Compiler* self) {
|
static void Compiler__dtor(Compiler* self) {
|
||||||
pk_TokenArray__dtor(&self->tokens);
|
TokenArray__dtor(&self->tokens);
|
||||||
c11__foreach(Ctx, &self->contexts, ctx) Ctx__dtor(ctx);
|
c11__foreach(Ctx, &self->contexts, ctx) Ctx__dtor(ctx);
|
||||||
c11_vector__dtor(&self->contexts);
|
c11_vector__dtor(&self->contexts);
|
||||||
}
|
}
|
||||||
@ -1470,8 +1470,8 @@ static void Compiler__dtor(Compiler* self) {
|
|||||||
if(!match(expected)) \
|
if(!match(expected)) \
|
||||||
return SyntaxError(self, \
|
return SyntaxError(self, \
|
||||||
"expected '%s', got '%s'", \
|
"expected '%s', got '%s'", \
|
||||||
pk_TokenSymbols[expected], \
|
TokenSymbols[expected], \
|
||||||
pk_TokenSymbols[curr()->type]);
|
TokenSymbols[curr()->type]);
|
||||||
#define consume_end_stmt() \
|
#define consume_end_stmt() \
|
||||||
if(!match_end_stmt(self)) return SyntaxError(self, "expected statement end")
|
if(!match_end_stmt(self)) return SyntaxError(self, "expected statement end")
|
||||||
|
|
||||||
@ -1531,7 +1531,7 @@ static bool match_end_stmt(Compiler* self) {
|
|||||||
static Error* parse_expression(Compiler* self, int precedence, bool allow_slice) {
|
static Error* parse_expression(Compiler* self, int precedence, bool allow_slice) {
|
||||||
PrattCallback prefix = rules[curr()->type].prefix;
|
PrattCallback prefix = rules[curr()->type].prefix;
|
||||||
if(!prefix || (curr()->type == TK_COLON && !allow_slice)) {
|
if(!prefix || (curr()->type == TK_COLON && !allow_slice)) {
|
||||||
return SyntaxError(self, "expected an expression, got %s", pk_TokenSymbols[curr()->type]);
|
return SyntaxError(self, "expected an expression, got %s", TokenSymbols[curr()->type]);
|
||||||
}
|
}
|
||||||
advance();
|
advance();
|
||||||
Error* err;
|
Error* err;
|
||||||
@ -2782,9 +2782,9 @@ Error* Compiler__compile(Compiler* self, CodeObject* out) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error* pk_compile(pk_SourceData_ src, CodeObject* out) {
|
Error* pk_compile(SourceData_ src, CodeObject* out) {
|
||||||
pk_TokenArray tokens;
|
TokenArray tokens;
|
||||||
Error* err = pk_Lexer__process(src, &tokens);
|
Error* err = Lexer__process(src, &tokens);
|
||||||
if(err) return err;
|
if(err) return err;
|
||||||
|
|
||||||
// Token* data = (Token*)tokens.data;
|
// Token* data = (Token*)tokens.data;
|
||||||
@ -2792,7 +2792,7 @@ Error* pk_compile(pk_SourceData_ src, CodeObject* out) {
|
|||||||
// for(int i = 0; i < tokens.count; i++) {
|
// for(int i = 0; i < tokens.count; i++) {
|
||||||
// Token* t = data + i;
|
// Token* t = data + i;
|
||||||
// c11_string* tmp = c11_string__new2(t->start, t->length);
|
// c11_string* tmp = c11_string__new2(t->start, t->length);
|
||||||
// printf("[%d] %s: %s\n", t->line, pk_TokenSymbols[t->type], tmp->data);
|
// printf("[%d] %s: %s\n", t->line, TokenSymbols[t->type], tmp->data);
|
||||||
// c11_string__delete(tmp);
|
// c11_string__delete(tmp);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
@ -10,8 +10,8 @@
|
|||||||
|
|
||||||
#define is_raw_string_used(t) ((t) == TK_ID || (t) == TK_LONG)
|
#define is_raw_string_used(t) ((t) == TK_ID || (t) == TK_LONG)
|
||||||
|
|
||||||
typedef struct pk_Lexer{
|
typedef struct Lexer{
|
||||||
pk_SourceData_ src;
|
SourceData_ src;
|
||||||
const char* token_start;
|
const char* token_start;
|
||||||
const char* curr_char;
|
const char* curr_char;
|
||||||
int current_line;
|
int current_line;
|
||||||
@ -19,7 +19,7 @@ typedef struct pk_Lexer{
|
|||||||
|
|
||||||
c11_vector/*T=Token*/ nexts;
|
c11_vector/*T=Token*/ nexts;
|
||||||
c11_vector/*T=int*/ indents;
|
c11_vector/*T=int*/ indents;
|
||||||
} pk_Lexer;
|
} Lexer;
|
||||||
|
|
||||||
typedef struct TokenDeserializer {
|
typedef struct TokenDeserializer {
|
||||||
const char* curr;
|
const char* curr;
|
||||||
@ -37,7 +37,7 @@ double TokenDeserializer__read_float(TokenDeserializer* self, char c);
|
|||||||
|
|
||||||
const static TokenValue EmptyTokenValue;
|
const static TokenValue EmptyTokenValue;
|
||||||
|
|
||||||
static void pk_Lexer__ctor(pk_Lexer* self, pk_SourceData_ src){
|
static void Lexer__ctor(Lexer* self, SourceData_ src){
|
||||||
PK_INCREF(src);
|
PK_INCREF(src);
|
||||||
self->src = src;
|
self->src = src;
|
||||||
self->curr_char = self->token_start = src->source->data;
|
self->curr_char = self->token_start = src->source->data;
|
||||||
@ -47,20 +47,20 @@ static void pk_Lexer__ctor(pk_Lexer* self, pk_SourceData_ src){
|
|||||||
c11_vector__ctor(&self->indents, sizeof(int));
|
c11_vector__ctor(&self->indents, sizeof(int));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pk_Lexer__dtor(pk_Lexer* self){
|
static void Lexer__dtor(Lexer* self){
|
||||||
PK_DECREF(self->src);
|
PK_DECREF(self->src);
|
||||||
c11_vector__dtor(&self->nexts);
|
c11_vector__dtor(&self->nexts);
|
||||||
c11_vector__dtor(&self->indents);
|
c11_vector__dtor(&self->indents);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char eatchar(pk_Lexer* self){
|
static char eatchar(Lexer* self){
|
||||||
char c = *self->curr_char;
|
char c = *self->curr_char;
|
||||||
assert(c != '\n'); // eatchar() cannot consume a newline
|
assert(c != '\n'); // eatchar() cannot consume a newline
|
||||||
self->curr_char++;
|
self->curr_char++;
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char eatchar_include_newline(pk_Lexer* self){
|
static char eatchar_include_newline(Lexer* self){
|
||||||
char c = *self->curr_char;
|
char c = *self->curr_char;
|
||||||
self->curr_char++;
|
self->curr_char++;
|
||||||
if(c == '\n') {
|
if(c == '\n') {
|
||||||
@ -70,7 +70,7 @@ static char eatchar_include_newline(pk_Lexer* self){
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int eat_spaces(pk_Lexer* self){
|
static int eat_spaces(Lexer* self){
|
||||||
int count = 0;
|
int count = 0;
|
||||||
while(true) {
|
while(true) {
|
||||||
switch(*self->curr_char) {
|
switch(*self->curr_char) {
|
||||||
@ -82,13 +82,13 @@ static int eat_spaces(pk_Lexer* self){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool matchchar(pk_Lexer* self, char c){
|
static bool matchchar(Lexer* self, char c){
|
||||||
if(*self->curr_char != c) return false;
|
if(*self->curr_char != c) return false;
|
||||||
eatchar_include_newline(self);
|
eatchar_include_newline(self);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool match_n_chars(pk_Lexer* self, int n, char c0){
|
static bool match_n_chars(Lexer* self, int n, char c0){
|
||||||
const char* c = self->curr_char;
|
const char* c = self->curr_char;
|
||||||
for(int i = 0; i < n; i++) {
|
for(int i = 0; i < n; i++) {
|
||||||
if(*c == '\0') return false;
|
if(*c == '\0') return false;
|
||||||
@ -100,14 +100,14 @@ static bool match_n_chars(pk_Lexer* self, int n, char c0){
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void skip_line_comment(pk_Lexer* self){
|
static void skip_line_comment(Lexer* self){
|
||||||
while(*self->curr_char) {
|
while(*self->curr_char) {
|
||||||
if(*self->curr_char == '\n') return;
|
if(*self->curr_char == '\n') return;
|
||||||
eatchar(self);
|
eatchar(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_token_with_value(pk_Lexer* self, TokenIndex type, TokenValue value){
|
static void add_token_with_value(Lexer* self, TokenIndex type, TokenValue value){
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case TK_LBRACE:
|
case TK_LBRACE:
|
||||||
case TK_LBRACKET:
|
case TK_LBRACKET:
|
||||||
@ -142,18 +142,18 @@ static void add_token_with_value(pk_Lexer* self, TokenIndex type, TokenValue val
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_token(pk_Lexer* self, TokenIndex type){
|
static void add_token(Lexer* self, TokenIndex type){
|
||||||
add_token_with_value(self, type, EmptyTokenValue);
|
add_token_with_value(self, type, EmptyTokenValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_token_2(pk_Lexer* self, char c, TokenIndex one, TokenIndex two){
|
static void add_token_2(Lexer* self, char c, TokenIndex one, TokenIndex two){
|
||||||
if(matchchar(self, c))
|
if(matchchar(self, c))
|
||||||
add_token(self, two);
|
add_token(self, two);
|
||||||
else
|
else
|
||||||
add_token(self, one);
|
add_token(self, one);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool eat_indentation(pk_Lexer* self){
|
static bool eat_indentation(Lexer* self){
|
||||||
if(self->brackets_level > 0) return true;
|
if(self->brackets_level > 0) return true;
|
||||||
int spaces = eat_spaces(self);
|
int spaces = eat_spaces(self);
|
||||||
if(*self->curr_char == '#') skip_line_comment(self);
|
if(*self->curr_char == '#') skip_line_comment(self);
|
||||||
@ -192,7 +192,7 @@ static bool is_possible_number_char(char c){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/******************************/
|
/******************************/
|
||||||
static Error* SyntaxError(pk_Lexer* self, const char* fmt, ...){
|
static Error* SyntaxError(Lexer* self, const char* fmt, ...){
|
||||||
Error* err = malloc(sizeof(Error));
|
Error* err = malloc(sizeof(Error));
|
||||||
err->src = self->src;
|
err->src = self->src;
|
||||||
PK_INCREF(self->src);
|
PK_INCREF(self->src);
|
||||||
@ -207,7 +207,7 @@ static Error* SyntaxError(pk_Lexer* self, const char* fmt, ...){
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Error* eat_name(pk_Lexer* self){
|
static Error* eat_name(Lexer* self){
|
||||||
self->curr_char--;
|
self->curr_char--;
|
||||||
while(true) {
|
while(true) {
|
||||||
unsigned char c = *self->curr_char;
|
unsigned char c = *self->curr_char;
|
||||||
@ -247,7 +247,7 @@ static Error* eat_name(pk_Lexer* self){
|
|||||||
if(length == 0) return SyntaxError(self, "@id contains invalid char");
|
if(length == 0) return SyntaxError(self, "@id contains invalid char");
|
||||||
c11_sv name = {self->token_start, length};
|
c11_sv name = {self->token_start, length};
|
||||||
|
|
||||||
const char** KW_BEGIN = pk_TokenSymbols + TK_FALSE;
|
const char** KW_BEGIN = TokenSymbols + TK_FALSE;
|
||||||
int KW_COUNT = TK__COUNT__ - TK_FALSE;
|
int KW_COUNT = TK__COUNT__ - TK_FALSE;
|
||||||
#define less(a, b) (c11_sv__cmp2(b, a) > 0)
|
#define less(a, b) (c11_sv__cmp2(b, a) > 0)
|
||||||
int out;
|
int out;
|
||||||
@ -262,7 +262,7 @@ static Error* eat_name(pk_Lexer* self){
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Error* eat_string_until(pk_Lexer* self, char quote, bool raw, c11_string** out) {
|
static Error* eat_string_until(Lexer* self, char quote, bool raw, c11_string** out) {
|
||||||
// previous char is quote
|
// previous char is quote
|
||||||
bool quote3 = match_n_chars(self, 2, quote);
|
bool quote3 = match_n_chars(self, 2, quote);
|
||||||
c11_sbuf buff;
|
c11_sbuf buff;
|
||||||
@ -321,7 +321,7 @@ enum StringType {
|
|||||||
NORMAL_BYTES
|
NORMAL_BYTES
|
||||||
};
|
};
|
||||||
|
|
||||||
static Error* eat_string(pk_Lexer* self, char quote, enum StringType type){
|
static Error* eat_string(Lexer* self, char quote, enum StringType type){
|
||||||
c11_string* s;
|
c11_string* s;
|
||||||
Error* err = eat_string_until(self, quote, type == RAW_STRING, &s);
|
Error* err = eat_string_until(self, quote, type == RAW_STRING, &s);
|
||||||
if(err) return err;
|
if(err) return err;
|
||||||
@ -336,7 +336,7 @@ static Error* eat_string(pk_Lexer* self, char quote, enum StringType type){
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Error* eat_number(pk_Lexer* self){
|
static Error* eat_number(Lexer* self){
|
||||||
const char* i = self->token_start;
|
const char* i = self->token_start;
|
||||||
while(is_possible_number_char(*i)) i++;
|
while(is_possible_number_char(*i)) i++;
|
||||||
|
|
||||||
@ -389,7 +389,7 @@ static Error* eat_number(pk_Lexer* self){
|
|||||||
return SyntaxError(self, "invalid number literal");
|
return SyntaxError(self, "invalid number literal");
|
||||||
}
|
}
|
||||||
|
|
||||||
static Error* lex_one_token(pk_Lexer* self, bool* eof){
|
static Error* lex_one_token(Lexer* self, bool* eof){
|
||||||
*eof = false;
|
*eof = false;
|
||||||
while(*self->curr_char) {
|
while(*self->curr_char) {
|
||||||
self->token_start = self->curr_char;
|
self->token_start = self->curr_char;
|
||||||
@ -532,7 +532,7 @@ static Error* lex_one_token(pk_Lexer* self, bool* eof){
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Error* from_precompiled(pk_Lexer* self) {
|
static Error* from_precompiled(Lexer* self) {
|
||||||
TokenDeserializer deserializer;
|
TokenDeserializer deserializer;
|
||||||
TokenDeserializer__ctor(&deserializer, self->src->source->data);
|
TokenDeserializer__ctor(&deserializer, self->src->source->data);
|
||||||
|
|
||||||
@ -603,14 +603,14 @@ static Error* from_precompiled(pk_Lexer* self) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error* pk_Lexer__process(pk_SourceData_ src, pk_TokenArray* out_tokens){
|
Error* Lexer__process(SourceData_ src, TokenArray* out_tokens){
|
||||||
pk_Lexer lexer;
|
Lexer lexer;
|
||||||
pk_Lexer__ctor(&lexer, src);
|
Lexer__ctor(&lexer, src);
|
||||||
|
|
||||||
if(src->is_precompiled) {
|
if(src->is_precompiled) {
|
||||||
Error* err = from_precompiled(&lexer);
|
Error* err = from_precompiled(&lexer);
|
||||||
// TODO: set out tokens
|
// TODO: set out tokens
|
||||||
pk_Lexer__dtor(&lexer);
|
Lexer__dtor(&lexer);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
// push initial tokens
|
// push initial tokens
|
||||||
@ -622,21 +622,21 @@ Error* pk_Lexer__process(pk_SourceData_ src, pk_TokenArray* out_tokens){
|
|||||||
while(!eof) {
|
while(!eof) {
|
||||||
void* err = lex_one_token(&lexer, &eof);
|
void* err = lex_one_token(&lexer, &eof);
|
||||||
if(err){
|
if(err){
|
||||||
pk_Lexer__dtor(&lexer);
|
Lexer__dtor(&lexer);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// set out_tokens
|
// set out_tokens
|
||||||
*out_tokens = c11_vector__submit(&lexer.nexts);
|
*out_tokens = c11_vector__submit(&lexer.nexts);
|
||||||
|
|
||||||
pk_Lexer__dtor(&lexer);
|
Lexer__dtor(&lexer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error* pk_Lexer__process_and_dump(pk_SourceData_ src, c11_string** out) {
|
Error* Lexer__process_and_dump(SourceData_ src, c11_string** out) {
|
||||||
assert(!src->is_precompiled);
|
assert(!src->is_precompiled);
|
||||||
pk_TokenArray nexts; // output tokens
|
TokenArray nexts; // output tokens
|
||||||
Error* err = pk_Lexer__process(src, &nexts);
|
Error* err = Lexer__process(src, &nexts);
|
||||||
if(err) return err;
|
if(err) return err;
|
||||||
|
|
||||||
c11_sbuf ss;
|
c11_sbuf ss;
|
||||||
@ -729,7 +729,7 @@ Error* pk_Lexer__process_and_dump(pk_SourceData_ src, c11_string** out) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pk_TokenArray__dtor(pk_TokenArray *self){
|
void TokenArray__dtor(TokenArray *self){
|
||||||
Token* data = self->data;
|
Token* data = self->data;
|
||||||
for(int i=0; i<self->count; i++){
|
for(int i=0; i<self->count; i++){
|
||||||
if(data[i].value.index == TokenValue_STR){
|
if(data[i].value.index == TokenValue_STR){
|
||||||
@ -739,7 +739,7 @@ void pk_TokenArray__dtor(pk_TokenArray *self){
|
|||||||
c11_array__dtor(self);
|
c11_array__dtor(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* pk_TokenSymbols[] = {
|
const char* TokenSymbols[] = {
|
||||||
"@eof", "@eol", "@sof",
|
"@eof", "@eol", "@sof",
|
||||||
"@id", "@num", "@str", "@fstr", "@long", "@bytes", "@imag",
|
"@id", "@num", "@str", "@fstr", "@long", "@bytes", "@imag",
|
||||||
"@indent", "@dedent",
|
"@indent", "@dedent",
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#include "pocketpy/objects/error.h"
|
#include "pocketpy/objects/error.h"
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
static bool stack_unpack_sequence(pk_VM* self, uint16_t arg);
|
static bool stack_unpack_sequence(VM* self, uint16_t arg);
|
||||||
static bool format_object(py_Ref obj, c11_sv spec);
|
static bool format_object(py_Ref obj, c11_sv spec);
|
||||||
|
|
||||||
#define DISPATCH() \
|
#define DISPATCH() \
|
||||||
@ -54,7 +54,7 @@ static bool format_object(py_Ref obj, c11_sv spec);
|
|||||||
|
|
||||||
#define vectorcall_opcall(argc, kwargc) \
|
#define vectorcall_opcall(argc, kwargc) \
|
||||||
do { \
|
do { \
|
||||||
pk_FrameResult res = pk_VM__vectorcall(self, (argc), (kwargc), true); \
|
FrameResult res = VM__vectorcall(self, (argc), (kwargc), true); \
|
||||||
switch(res) { \
|
switch(res) { \
|
||||||
case RES_RETURN: PUSH(&self->last_retval); break; \
|
case RES_RETURN: PUSH(&self->last_retval); break; \
|
||||||
case RES_CALL: frame = self->top_frame; goto __NEXT_FRAME; \
|
case RES_CALL: frame = self->top_frame; goto __NEXT_FRAME; \
|
||||||
@ -75,7 +75,7 @@ static bool unpack_dict_to_buffer(py_Ref key, py_Ref val, void* ctx) {
|
|||||||
return TypeError("keywords must be strings, not '%t'", key->type);
|
return TypeError("keywords must be strings, not '%t'", key->type);
|
||||||
}
|
}
|
||||||
|
|
||||||
pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
FrameResult VM__run_top_frame(VM* self) {
|
||||||
Frame* frame = self->top_frame;
|
Frame* frame = self->top_frame;
|
||||||
const Frame* base_frame = frame;
|
const Frame* base_frame = frame;
|
||||||
|
|
||||||
@ -139,7 +139,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
|||||||
ud->closure = FastLocals__to_namedict(frame->locals, frame->locals_co);
|
ud->closure = FastLocals__to_namedict(frame->locals, frame->locals_co);
|
||||||
py_Name name = py_namev(c11_string__sv(decl->code.name));
|
py_Name name = py_namev(c11_string__sv(decl->code.name));
|
||||||
// capture itself to allow recursion
|
// capture itself to allow recursion
|
||||||
pk_NameDict__set(ud->closure, name, *SP());
|
NameDict__set(ud->closure, name, *SP());
|
||||||
}
|
}
|
||||||
SP()++;
|
SP()++;
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
@ -619,7 +619,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
|||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
case OP_CALL: {
|
case OP_CALL: {
|
||||||
pk_ManagedHeap__collect_if_needed(&self->heap);
|
ManagedHeap__collect_if_needed(&self->heap);
|
||||||
vectorcall_opcall(byte.arg & 0xFF, byte.arg >> 8);
|
vectorcall_opcall(byte.arg & 0xFF, byte.arg >> 8);
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
@ -684,7 +684,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
|||||||
} else {
|
} else {
|
||||||
py_newnone(&self->last_retval);
|
py_newnone(&self->last_retval);
|
||||||
}
|
}
|
||||||
pk_VM__pop_frame(self);
|
VM__pop_frame(self);
|
||||||
if(frame == base_frame) { // [ frameBase<- ]
|
if(frame == base_frame) { // [ frameBase<- ]
|
||||||
return RES_RETURN;
|
return RES_RETURN;
|
||||||
} else {
|
} else {
|
||||||
@ -770,8 +770,8 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
|||||||
}
|
}
|
||||||
case OP_POP_IMPORT_STAR: {
|
case OP_POP_IMPORT_STAR: {
|
||||||
// [module]
|
// [module]
|
||||||
pk_NameDict* dict = PyObject__dict(TOP()->_obj);
|
NameDict* dict = PyObject__dict(TOP()->_obj);
|
||||||
py_Ref all = pk_NameDict__try_get(dict, __all__);
|
py_Ref all = NameDict__try_get(dict, __all__);
|
||||||
if(all) {
|
if(all) {
|
||||||
int length;
|
int length;
|
||||||
py_TValue* p = pk_arrayview(all, &length);
|
py_TValue* p = pk_arrayview(all, &length);
|
||||||
@ -781,7 +781,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
|||||||
}
|
}
|
||||||
for(int i = 0; i < length; i++) {
|
for(int i = 0; i < length; i++) {
|
||||||
py_Name name = py_namev(py_tosv(p + i));
|
py_Name name = py_namev(py_tosv(p + i));
|
||||||
py_Ref value = pk_NameDict__try_get(dict, name);
|
py_Ref value = NameDict__try_get(dict, name);
|
||||||
if(value == NULL) {
|
if(value == NULL) {
|
||||||
ImportError("cannot import name '%n'", name);
|
ImportError("cannot import name '%n'", name);
|
||||||
goto __ERROR;
|
goto __ERROR;
|
||||||
@ -791,7 +791,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for(int i = 0; i < dict->count; i++) {
|
for(int i = 0; i < dict->count; i++) {
|
||||||
pk_NameDict_KV* kv = c11__at(pk_NameDict_KV, dict, i);
|
NameDict_KV* kv = c11__at(NameDict_KV, dict, i);
|
||||||
if(!kv->key) continue;
|
if(!kv->key) continue;
|
||||||
c11_sv name = py_name2sv(kv->key);
|
c11_sv name = py_name2sv(kv->key);
|
||||||
if(name.size == 0 || name.data[0] == '_') continue;
|
if(name.size == 0 || name.data[0] == '_') continue;
|
||||||
@ -854,10 +854,10 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
|||||||
|
|
||||||
if(py_istype(TOP(), tp_type)) {
|
if(py_istype(TOP(), tp_type)) {
|
||||||
// call on_end_subclass
|
// call on_end_subclass
|
||||||
pk_TypeInfo* ti = c11__at(pk_TypeInfo, &self->types, py_totype(TOP()));
|
py_TypeInfo* ti = c11__at(py_TypeInfo, &self->types, py_totype(TOP()));
|
||||||
if(ti->base != tp_object) {
|
if(ti->base != tp_object) {
|
||||||
// PyTypeInfo* base_ti = &_all_types[ti->base];
|
// PyTypeInfo* base_ti = &_all_types[ti->base];
|
||||||
pk_TypeInfo* base_ti = c11__at(pk_TypeInfo, &self->types, ti->base);
|
py_TypeInfo* base_ti = c11__at(py_TypeInfo, &self->types, ti->base);
|
||||||
if(base_ti->on_end_subclass) base_ti->on_end_subclass(ti);
|
if(base_ti->on_end_subclass) base_ti->on_end_subclass(ti);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -877,7 +877,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
|||||||
}
|
}
|
||||||
case OP_ADD_CLASS_ANNOTATION: {
|
case OP_ADD_CLASS_ANNOTATION: {
|
||||||
py_Type type = py_totype(self->__curr_class);
|
py_Type type = py_totype(self->__curr_class);
|
||||||
pk_TypeInfo* ti = c11__at(pk_TypeInfo, &self->types, type);
|
py_TypeInfo* ti = c11__at(py_TypeInfo, &self->types, type);
|
||||||
c11_vector__push(py_Name, &ti->annotated_fields, byte.arg);
|
c11_vector__push(py_Name, &ti->annotated_fields, byte.arg);
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
@ -970,7 +970,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
|||||||
} else {
|
} else {
|
||||||
// 2. Exception need to be propagated to the upper frame
|
// 2. Exception need to be propagated to the upper frame
|
||||||
bool is_base_frame_to_be_popped = frame == base_frame;
|
bool is_base_frame_to_be_popped = frame == base_frame;
|
||||||
pk_VM__pop_frame(self);
|
VM__pop_frame(self);
|
||||||
if(self->top_frame == NULL || is_base_frame_to_be_popped) {
|
if(self->top_frame == NULL || is_base_frame_to_be_popped) {
|
||||||
// propagate to the top level
|
// propagate to the top level
|
||||||
return RES_ERROR;
|
return RES_ERROR;
|
||||||
@ -983,7 +983,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
|||||||
return RES_RETURN;
|
return RES_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pk_stack_binaryop(pk_VM* self, py_Name op, py_Name rop) {
|
bool pk_stack_binaryop(VM* self, py_Name op, py_Name rop) {
|
||||||
// [a, b]
|
// [a, b]
|
||||||
py_Ref magic = py_tpfindmagic(SECOND()->type, op);
|
py_Ref magic = py_tpfindmagic(SECOND()->type, op);
|
||||||
if(magic) {
|
if(magic) {
|
||||||
@ -1014,7 +1014,7 @@ bool pk_stack_binaryop(pk_VM* self, py_Name op, py_Name rop) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool py_binaryop(py_Ref lhs, py_Ref rhs, py_Name op, py_Name rop) {
|
bool py_binaryop(py_Ref lhs, py_Ref rhs, py_Name op, py_Name rop) {
|
||||||
pk_VM* self = pk_current_vm;
|
VM* self = pk_current_vm;
|
||||||
PUSH(lhs);
|
PUSH(lhs);
|
||||||
PUSH(rhs);
|
PUSH(rhs);
|
||||||
bool ok = pk_stack_binaryop(self, op, rop);
|
bool ok = pk_stack_binaryop(self, op, rop);
|
||||||
@ -1022,7 +1022,7 @@ bool py_binaryop(py_Ref lhs, py_Ref rhs, py_Name op, py_Name rop) {
|
|||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool stack_unpack_sequence(pk_VM* self, uint16_t arg) {
|
static bool stack_unpack_sequence(VM* self, uint16_t arg) {
|
||||||
int length;
|
int length;
|
||||||
py_TValue* p = pk_arrayview(TOP(), &length);
|
py_TValue* p = pk_arrayview(TOP(), &length);
|
||||||
if(!p) return TypeError("expected list or tuple to unpack, got '%t'", TOP()->type);
|
if(!p) return TypeError("expected list or tuple to unpack, got '%t'", TOP()->type);
|
||||||
|
@ -14,11 +14,11 @@ py_TValue* FastLocals__try_get_by_name(py_TValue* locals, const CodeObject* co,
|
|||||||
return &locals[index];
|
return &locals[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
pk_NameDict* FastLocals__to_namedict(py_TValue* locals, const CodeObject* co) {
|
NameDict* FastLocals__to_namedict(py_TValue* locals, const CodeObject* co) {
|
||||||
pk_NameDict* dict = pk_NameDict__new();
|
NameDict* dict = NameDict__new();
|
||||||
c11__foreach(c11_smallmap_n2i_KV, &co->varnames_inv, entry) {
|
c11__foreach(c11_smallmap_n2i_KV, &co->varnames_inv, entry) {
|
||||||
py_TValue value = locals[entry->value];
|
py_TValue value = locals[entry->value];
|
||||||
if(!py_isnil(&value)) { pk_NameDict__set(dict, entry->key, value); }
|
if(!py_isnil(&value)) { NameDict__set(dict, entry->key, value); }
|
||||||
}
|
}
|
||||||
return dict;
|
return dict;
|
||||||
}
|
}
|
||||||
@ -134,6 +134,6 @@ py_TValue* Frame__f_closure_try_get(Frame* self, py_Name name) {
|
|||||||
// if(self->function == NULL) return NULL;
|
// if(self->function == NULL) return NULL;
|
||||||
// pkpy::Function* fn = PyObject__as(pkpy::Function, self->function);
|
// pkpy::Function* fn = PyObject__as(pkpy::Function, self->function);
|
||||||
// if(fn->_closure == nullptr) return nullptr;
|
// if(fn->_closure == nullptr) return nullptr;
|
||||||
// return pk_NameDict__try_get(fn->_closure, name);
|
// return NameDict__try_get(fn->_closure, name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
@ -2,7 +2,7 @@
|
|||||||
#include "pocketpy/common/memorypool.h"
|
#include "pocketpy/common/memorypool.h"
|
||||||
#include "pocketpy/objects/base.h"
|
#include "pocketpy/objects/base.h"
|
||||||
|
|
||||||
void pk_ManagedHeap__ctor(pk_ManagedHeap *self, pk_VM *vm){
|
void ManagedHeap__ctor(ManagedHeap *self, VM *vm){
|
||||||
c11_vector__ctor(&self->no_gc, sizeof(PyObject*));
|
c11_vector__ctor(&self->no_gc, sizeof(PyObject*));
|
||||||
c11_vector__ctor(&self->gen, sizeof(PyObject*));
|
c11_vector__ctor(&self->gen, sizeof(PyObject*));
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ void pk_ManagedHeap__ctor(pk_ManagedHeap *self, pk_VM *vm){
|
|||||||
self->gc_on_delete = NULL;
|
self->gc_on_delete = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pk_ManagedHeap__dtor(pk_ManagedHeap *self){
|
void ManagedHeap__dtor(ManagedHeap *self){
|
||||||
for(int i = 0; i < self->gen.count; i++){
|
for(int i = 0; i < self->gen.count; i++){
|
||||||
PyObject* obj = c11__getitem(PyObject*, &self->gen, i);
|
PyObject* obj = c11__getitem(PyObject*, &self->gen, i);
|
||||||
PyObject__delete(obj);
|
PyObject__delete(obj);
|
||||||
@ -26,23 +26,23 @@ void pk_ManagedHeap__dtor(pk_ManagedHeap *self){
|
|||||||
c11_vector__dtor(&self->gen);
|
c11_vector__dtor(&self->gen);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pk_ManagedHeap__collect_if_needed(pk_ManagedHeap *self){
|
void ManagedHeap__collect_if_needed(ManagedHeap *self){
|
||||||
if(self->gc_counter < self->gc_threshold) return;
|
if(self->gc_counter < self->gc_threshold) return;
|
||||||
self->gc_counter = 0;
|
self->gc_counter = 0;
|
||||||
pk_ManagedHeap__collect(self);
|
ManagedHeap__collect(self);
|
||||||
self->gc_threshold = self->gen.count * 2;
|
self->gc_threshold = self->gen.count * 2;
|
||||||
if(self->gc_threshold < PK_GC_MIN_THRESHOLD){
|
if(self->gc_threshold < PK_GC_MIN_THRESHOLD){
|
||||||
self->gc_threshold = PK_GC_MIN_THRESHOLD;
|
self->gc_threshold = PK_GC_MIN_THRESHOLD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int pk_ManagedHeap__collect(pk_ManagedHeap *self){
|
int ManagedHeap__collect(ManagedHeap *self){
|
||||||
pk_ManagedHeap__mark(self);
|
ManagedHeap__mark(self);
|
||||||
int freed = pk_ManagedHeap__sweep(self);
|
int freed = ManagedHeap__sweep(self);
|
||||||
return freed;
|
return freed;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pk_ManagedHeap__sweep(pk_ManagedHeap *self){
|
int ManagedHeap__sweep(ManagedHeap *self){
|
||||||
c11_vector alive;
|
c11_vector alive;
|
||||||
c11_vector__ctor(&alive, sizeof(PyObject*));
|
c11_vector__ctor(&alive, sizeof(PyObject*));
|
||||||
c11_vector__reserve(&alive, self->gen.count / 2);
|
c11_vector__reserve(&alive, self->gen.count / 2);
|
||||||
@ -77,13 +77,13 @@ int pk_ManagedHeap__sweep(pk_ManagedHeap *self){
|
|||||||
return freed;
|
return freed;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* pk_ManagedHeap__new(pk_ManagedHeap *self, py_Type type, int slots, int udsize){
|
PyObject* ManagedHeap__new(ManagedHeap *self, py_Type type, int slots, int udsize){
|
||||||
PyObject* obj = PyObject__new(type, slots, udsize);
|
PyObject* obj = PyObject__new(type, slots, udsize);
|
||||||
c11_vector__push(PyObject*, &self->no_gc, obj);
|
c11_vector__push(PyObject*, &self->no_gc, obj);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* pk_ManagedHeap__gcnew(pk_ManagedHeap *self, py_Type type, int slots, int udsize){
|
PyObject* ManagedHeap__gcnew(ManagedHeap *self, py_Type type, int slots, int udsize){
|
||||||
PyObject* obj = PyObject__new(type, slots, udsize);
|
PyObject* obj = PyObject__new(type, slots, udsize);
|
||||||
c11_vector__push(PyObject*, &self->gen, obj);
|
c11_vector__push(PyObject*, &self->gen, obj);
|
||||||
self->gc_counter++;
|
self->gc_counter++;
|
||||||
@ -111,7 +111,7 @@ PyObject* PyObject__new(py_Type type, int slots, int size){
|
|||||||
if(slots >= 0){
|
if(slots >= 0){
|
||||||
memset(p, 0, slots*sizeof(py_TValue));
|
memset(p, 0, slots*sizeof(py_TValue));
|
||||||
}else{
|
}else{
|
||||||
pk_NameDict__ctor(p);
|
NameDict__ctor(p);
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
@ -25,19 +25,19 @@ static char* pk_default_import_file(const char* path) {
|
|||||||
|
|
||||||
static void pk_default_print(const char* data) { printf("%s", data); }
|
static void pk_default_print(const char* data) { printf("%s", data); }
|
||||||
|
|
||||||
static void pk_TypeInfo__ctor(pk_TypeInfo* self,
|
static void py_TypeInfo__ctor(py_TypeInfo* self,
|
||||||
py_Name name,
|
py_Name name,
|
||||||
py_Type index,
|
py_Type index,
|
||||||
py_Type base,
|
py_Type base,
|
||||||
py_TValue module) {
|
py_TValue module) {
|
||||||
memset(self, 0, sizeof(pk_TypeInfo));
|
memset(self, 0, sizeof(py_TypeInfo));
|
||||||
|
|
||||||
self->name = name;
|
self->name = name;
|
||||||
self->base = base;
|
self->base = base;
|
||||||
|
|
||||||
// create type object with __dict__
|
// create type object with __dict__
|
||||||
pk_ManagedHeap* heap = &pk_current_vm->heap;
|
ManagedHeap* heap = &pk_current_vm->heap;
|
||||||
PyObject* typeobj = pk_ManagedHeap__new(heap, tp_type, -1, sizeof(py_Type));
|
PyObject* typeobj = ManagedHeap__new(heap, tp_type, -1, sizeof(py_Type));
|
||||||
*(py_Type*)PyObject__userdata(typeobj) = index;
|
*(py_Type*)PyObject__userdata(typeobj) = index;
|
||||||
self->self = (py_TValue){
|
self->self = (py_TValue){
|
||||||
.type = typeobj->type,
|
.type = typeobj->type,
|
||||||
@ -49,13 +49,13 @@ static void pk_TypeInfo__ctor(pk_TypeInfo* self,
|
|||||||
c11_vector__ctor(&self->annotated_fields, sizeof(py_Name));
|
c11_vector__ctor(&self->annotated_fields, sizeof(py_Name));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pk_TypeInfo__dtor(pk_TypeInfo* self) { c11_vector__dtor(&self->annotated_fields); }
|
static void py_TypeInfo__dtor(py_TypeInfo* self) { c11_vector__dtor(&self->annotated_fields); }
|
||||||
|
|
||||||
void pk_VM__ctor(pk_VM* self) {
|
void VM__ctor(VM* self) {
|
||||||
self->top_frame = NULL;
|
self->top_frame = NULL;
|
||||||
|
|
||||||
pk_NameDict__ctor(&self->modules);
|
NameDict__ctor(&self->modules);
|
||||||
c11_vector__ctor(&self->types, sizeof(pk_TypeInfo));
|
c11_vector__ctor(&self->types, sizeof(py_TypeInfo));
|
||||||
|
|
||||||
self->builtins = *py_NIL;
|
self->builtins = *py_NIL;
|
||||||
self->main = *py_NIL;
|
self->main = *py_NIL;
|
||||||
@ -71,13 +71,13 @@ void pk_VM__ctor(pk_VM* self) {
|
|||||||
self->__curr_class = NULL;
|
self->__curr_class = NULL;
|
||||||
self->__dynamic_func_decl = NULL;
|
self->__dynamic_func_decl = NULL;
|
||||||
|
|
||||||
pk_ManagedHeap__ctor(&self->heap, self);
|
ManagedHeap__ctor(&self->heap, self);
|
||||||
ValueStack__ctor(&self->stack);
|
ValueStack__ctor(&self->stack);
|
||||||
|
|
||||||
/* Init Builtin Types */
|
/* Init Builtin Types */
|
||||||
// 0: unused
|
// 0: unused
|
||||||
void* placeholder = c11_vector__emplace(&self->types);
|
void* placeholder = c11_vector__emplace(&self->types);
|
||||||
memset(placeholder, 0, sizeof(pk_TypeInfo));
|
memset(placeholder, 0, sizeof(py_TypeInfo));
|
||||||
|
|
||||||
#define validate(t, expr) \
|
#define validate(t, expr) \
|
||||||
if(t != (expr)) abort()
|
if(t != (expr)) abort()
|
||||||
@ -154,7 +154,7 @@ void pk_VM__ctor(pk_VM* self) {
|
|||||||
|
|
||||||
for(int i = 0; i < c11__count_array(public_types); i++) {
|
for(int i = 0; i < c11__count_array(public_types); i++) {
|
||||||
py_Type t = public_types[i];
|
py_Type t = public_types[i];
|
||||||
pk_TypeInfo* ti = c11__at(pk_TypeInfo, &self->types, t);
|
py_TypeInfo* ti = c11__at(py_TypeInfo, &self->types, t);
|
||||||
py_setdict(&self->builtins, ti->name, py_tpobject(t));
|
py_setdict(&self->builtins, ti->name, py_tpobject(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,24 +196,24 @@ void pk_VM__ctor(pk_VM* self) {
|
|||||||
self->main = *py_newmodule("__main__");
|
self->main = *py_newmodule("__main__");
|
||||||
}
|
}
|
||||||
|
|
||||||
void pk_VM__dtor(pk_VM* self) {
|
void VM__dtor(VM* self) {
|
||||||
if(self->__dynamic_func_decl) { PK_DECREF(self->__dynamic_func_decl); }
|
if(self->__dynamic_func_decl) { PK_DECREF(self->__dynamic_func_decl); }
|
||||||
// destroy all objects
|
// destroy all objects
|
||||||
pk_ManagedHeap__dtor(&self->heap);
|
ManagedHeap__dtor(&self->heap);
|
||||||
// clear frames
|
// clear frames
|
||||||
// ...
|
// ...
|
||||||
pk_NameDict__dtor(&self->modules);
|
NameDict__dtor(&self->modules);
|
||||||
c11__foreach(pk_TypeInfo, &self->types, ti) pk_TypeInfo__dtor(ti);
|
c11__foreach(py_TypeInfo, &self->types, ti) py_TypeInfo__dtor(ti);
|
||||||
c11_vector__dtor(&self->types);
|
c11_vector__dtor(&self->types);
|
||||||
ValueStack__clear(&self->stack);
|
ValueStack__clear(&self->stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pk_VM__push_frame(pk_VM* self, Frame* frame) {
|
void VM__push_frame(VM* self, Frame* frame) {
|
||||||
frame->f_back = self->top_frame;
|
frame->f_back = self->top_frame;
|
||||||
self->top_frame = frame;
|
self->top_frame = frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pk_VM__pop_frame(pk_VM* self) {
|
void VM__pop_frame(VM* self) {
|
||||||
assert(self->top_frame);
|
assert(self->top_frame);
|
||||||
Frame* frame = self->top_frame;
|
Frame* frame = self->top_frame;
|
||||||
// reset stack pointer
|
// reset stack pointer
|
||||||
@ -293,9 +293,9 @@ py_Type pk_newtype(const char* name,
|
|||||||
bool is_sealed) {
|
bool is_sealed) {
|
||||||
c11_vector* types = &pk_current_vm->types;
|
c11_vector* types = &pk_current_vm->types;
|
||||||
py_Type index = types->count;
|
py_Type index = types->count;
|
||||||
pk_TypeInfo* ti = c11_vector__emplace(types);
|
py_TypeInfo* ti = c11_vector__emplace(types);
|
||||||
pk_TypeInfo__ctor(ti, py_name(name), index, base, module ? *module : *py_NIL);
|
py_TypeInfo__ctor(ti, py_name(name), index, base, module ? *module : *py_NIL);
|
||||||
if(!dtor && base) { dtor = c11__at(pk_TypeInfo, types, base)->dtor; }
|
if(!dtor && base) { dtor = c11__at(py_TypeInfo, types, base)->dtor; }
|
||||||
ti->dtor = dtor;
|
ti->dtor = dtor;
|
||||||
ti->is_python = is_python;
|
ti->is_python = is_python;
|
||||||
ti->is_sealed = is_sealed;
|
ti->is_sealed = is_sealed;
|
||||||
@ -373,7 +373,7 @@ static bool
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bool opcall) {
|
FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall) {
|
||||||
pk_print_stack(self, self->top_frame, (Bytecode){0});
|
pk_print_stack(self, self->top_frame, (Bytecode){0});
|
||||||
|
|
||||||
py_Ref p1 = self->stack.sp - kwargc * 2;
|
py_Ref p1 = self->stack.sp - kwargc * 2;
|
||||||
@ -416,8 +416,8 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bo
|
|||||||
memcpy(argv, self->__vectorcall_buffer, co->nlocals * sizeof(py_TValue));
|
memcpy(argv, self->__vectorcall_buffer, co->nlocals * sizeof(py_TValue));
|
||||||
// submit the call
|
// submit the call
|
||||||
if(!fn->cfunc) {
|
if(!fn->cfunc) {
|
||||||
pk_VM__push_frame(self, Frame__new(co, &fn->module, p0, p0, argv, co));
|
VM__push_frame(self, Frame__new(co, &fn->module, p0, p0, argv, co));
|
||||||
return opcall ? RES_CALL : pk_VM__run_top_frame(self);
|
return opcall ? RES_CALL : VM__run_top_frame(self);
|
||||||
} else {
|
} else {
|
||||||
bool ok = fn->cfunc(co->nlocals, argv);
|
bool ok = fn->cfunc(co->nlocals, argv);
|
||||||
self->stack.sp = p0;
|
self->stack.sp = p0;
|
||||||
@ -440,8 +440,8 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bo
|
|||||||
// initialize local variables to py_NIL
|
// initialize local variables to py_NIL
|
||||||
memset(p1, 0, (char*)self->stack.sp - (char*)p1);
|
memset(p1, 0, (char*)self->stack.sp - (char*)p1);
|
||||||
// submit the call
|
// submit the call
|
||||||
pk_VM__push_frame(self, Frame__new(co, &fn->module, p0, p0, argv, co));
|
VM__push_frame(self, Frame__new(co, &fn->module, p0, p0, argv, co));
|
||||||
return opcall ? RES_CALL : pk_VM__run_top_frame(self);
|
return opcall ? RES_CALL : VM__run_top_frame(self);
|
||||||
case FuncType_GENERATOR:
|
case FuncType_GENERATOR:
|
||||||
assert(false);
|
assert(false);
|
||||||
break;
|
break;
|
||||||
@ -476,7 +476,7 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bo
|
|||||||
memcpy(self->stack.sp, argv, span * sizeof(py_TValue));
|
memcpy(self->stack.sp, argv, span * sizeof(py_TValue));
|
||||||
self->stack.sp += span;
|
self->stack.sp += span;
|
||||||
// [new_f, cls, args..., kwargs...]
|
// [new_f, cls, args..., kwargs...]
|
||||||
if(pk_VM__vectorcall(self, argc, kwargc, false) == RES_ERROR) return RES_ERROR;
|
if(VM__vectorcall(self, argc, kwargc, false) == RES_ERROR) return RES_ERROR;
|
||||||
// by recursively using vectorcall, args and kwargs are consumed
|
// by recursively using vectorcall, args and kwargs are consumed
|
||||||
|
|
||||||
// try __init__
|
// try __init__
|
||||||
@ -489,7 +489,7 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bo
|
|||||||
*p0 = *init_f; // __init__
|
*p0 = *init_f; // __init__
|
||||||
p0[1] = self->last_retval; // self
|
p0[1] = self->last_retval; // self
|
||||||
// [__init__, self, args..., kwargs...]
|
// [__init__, self, args..., kwargs...]
|
||||||
if(pk_VM__vectorcall(self, argc, kwargc, false) == RES_ERROR) return RES_ERROR;
|
if(VM__vectorcall(self, argc, kwargc, false) == RES_ERROR) return RES_ERROR;
|
||||||
*py_retval() = p0[1]; // restore the new instance
|
*py_retval() = p0[1]; // restore the new instance
|
||||||
}
|
}
|
||||||
// reset the stack
|
// reset the stack
|
||||||
@ -500,7 +500,7 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bo
|
|||||||
// handle `__call__` overload
|
// handle `__call__` overload
|
||||||
if(pk_pushmethod(p0, __call__)) {
|
if(pk_pushmethod(p0, __call__)) {
|
||||||
// [__call__, self, args..., kwargs...]
|
// [__call__, self, args..., kwargs...]
|
||||||
return pk_VM__vectorcall(self, argc, kwargc, opcall);
|
return VM__vectorcall(self, argc, kwargc, opcall);
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeError("'%t' object is not callable", p0->type);
|
TypeError("'%t' object is not callable", p0->type);
|
||||||
@ -509,9 +509,9 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bo
|
|||||||
|
|
||||||
/****************************************/
|
/****************************************/
|
||||||
void PyObject__delete(PyObject* self) {
|
void PyObject__delete(PyObject* self) {
|
||||||
pk_TypeInfo* ti = c11__at(pk_TypeInfo, &pk_current_vm->types, self->type);
|
py_TypeInfo* ti = c11__at(py_TypeInfo, &pk_current_vm->types, self->type);
|
||||||
if(ti->dtor) ti->dtor(PyObject__userdata(self));
|
if(ti->dtor) ti->dtor(PyObject__userdata(self));
|
||||||
if(self->slots == -1) pk_NameDict__dtor(PyObject__dict(self));
|
if(self->slots == -1) NameDict__dtor(PyObject__dict(self));
|
||||||
if(self->gc_is_large) {
|
if(self->gc_is_large) {
|
||||||
free(self);
|
free(self);
|
||||||
} else {
|
} else {
|
||||||
@ -537,9 +537,9 @@ static void mark_object(PyObject* obj) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(obj->slots == -1) {
|
if(obj->slots == -1) {
|
||||||
pk_NameDict* dict = PyObject__dict(obj);
|
NameDict* dict = PyObject__dict(obj);
|
||||||
for(int j = 0; j < dict->count; j++) {
|
for(int j = 0; j < dict->count; j++) {
|
||||||
pk_NameDict_KV* kv = c11__at(pk_NameDict_KV, dict, j);
|
NameDict_KV* kv = c11__at(NameDict_KV, dict, j);
|
||||||
mark_value(&kv->value);
|
mark_value(&kv->value);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -552,8 +552,8 @@ static void mark_object(PyObject* obj) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pk_ManagedHeap__mark(pk_ManagedHeap* self) {
|
void ManagedHeap__mark(ManagedHeap* self) {
|
||||||
pk_VM* vm = self->vm;
|
VM* vm = self->vm;
|
||||||
// mark heap objects
|
// mark heap objects
|
||||||
for(int i = 0; i < self->no_gc.count; i++) {
|
for(int i = 0; i < self->no_gc.count; i++) {
|
||||||
PyObject* obj = c11__getitem(PyObject*, &self->no_gc, i);
|
PyObject* obj = c11__getitem(PyObject*, &self->no_gc, i);
|
||||||
@ -576,7 +576,7 @@ void pk_ManagedHeap__mark(pk_ManagedHeap* self) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pk_print_stack(pk_VM* self, Frame* frame, Bytecode byte) {
|
void pk_print_stack(VM* self, Frame* frame, Bytecode byte) {
|
||||||
return;
|
return;
|
||||||
if(frame == NULL) return;
|
if(frame == NULL) return;
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ static void FuncDecl__dtor(FuncDecl* self) {
|
|||||||
c11_smallmap_n2i__dtor(&self->kw_to_index);
|
c11_smallmap_n2i__dtor(&self->kw_to_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
FuncDecl_ FuncDecl__rcnew(pk_SourceData_ src, c11_sv name) {
|
FuncDecl_ FuncDecl__rcnew(SourceData_ src, c11_sv name) {
|
||||||
FuncDecl* self = malloc(sizeof(FuncDecl));
|
FuncDecl* self = malloc(sizeof(FuncDecl));
|
||||||
self->rc.count = 1;
|
self->rc.count = 1;
|
||||||
self->rc.dtor = (void (*)(void*))FuncDecl__dtor;
|
self->rc.dtor = (void (*)(void*))FuncDecl__dtor;
|
||||||
@ -94,7 +94,7 @@ FuncDecl_ FuncDecl__build(c11_sv name,
|
|||||||
py_Ref kwdefaults, // a tuple contains default values
|
py_Ref kwdefaults, // a tuple contains default values
|
||||||
c11_sv starred_kwarg,
|
c11_sv starred_kwarg,
|
||||||
const char* docstring) {
|
const char* docstring) {
|
||||||
pk_SourceData_ source = pk_SourceData__rcnew("pass", "<bind>", EXEC_MODE, false);
|
SourceData_ source = SourceData__rcnew("pass", "<bind>", EXEC_MODE, false);
|
||||||
FuncDecl_ decl = FuncDecl__rcnew(source, name);
|
FuncDecl_ decl = FuncDecl__rcnew(source, name);
|
||||||
for(int i = 0; i < argc; i++) {
|
for(int i = 0; i < argc; i++) {
|
||||||
FuncDecl__add_arg(decl, py_namev(args[i]));
|
FuncDecl__add_arg(decl, py_namev(args[i]));
|
||||||
@ -111,7 +111,7 @@ FuncDecl_ FuncDecl__build(c11_sv name,
|
|||||||
return decl;
|
return decl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeObject__ctor(CodeObject* self, pk_SourceData_ src, c11_sv name) {
|
void CodeObject__ctor(CodeObject* self, SourceData_ src, c11_sv name) {
|
||||||
self->src = src;
|
self->src = src;
|
||||||
PK_INCREF(src);
|
PK_INCREF(src);
|
||||||
self->name = c11_string__new2(name.data, name.size);
|
self->name = c11_string__new2(name.data, name.size);
|
||||||
@ -179,5 +179,5 @@ int CodeObject__add_varname(CodeObject* self, py_Name name) {
|
|||||||
|
|
||||||
void Function__dtor(Function* self) {
|
void Function__dtor(Function* self) {
|
||||||
PK_DECREF(self->decl);
|
PK_DECREF(self->decl);
|
||||||
if(self->closure) pk_NameDict__delete(self->closure);
|
if(self->closure) NameDict__delete(self->closure);
|
||||||
}
|
}
|
@ -3,6 +3,6 @@
|
|||||||
#define SMALLMAP_T__SOURCE
|
#define SMALLMAP_T__SOURCE
|
||||||
#define K uint16_t
|
#define K uint16_t
|
||||||
#define V py_TValue
|
#define V py_TValue
|
||||||
#define NAME pk_NameDict
|
#define NAME NameDict
|
||||||
#include "pocketpy/xmacros/smallmap.h"
|
#include "pocketpy/xmacros/smallmap.h"
|
||||||
#undef SMALLMAP_T__SOURCE
|
#undef SMALLMAP_T__SOURCE
|
||||||
|
@ -4,9 +4,9 @@
|
|||||||
|
|
||||||
void* PyObject__userdata(PyObject* self) { return self->flex + PK_OBJ_SLOTS_SIZE(self->slots); }
|
void* PyObject__userdata(PyObject* self) { return self->flex + PK_OBJ_SLOTS_SIZE(self->slots); }
|
||||||
|
|
||||||
pk_NameDict* PyObject__dict(PyObject* self) {
|
NameDict* PyObject__dict(PyObject* self) {
|
||||||
assert(self->slots == -1);
|
assert(self->slots == -1);
|
||||||
return (pk_NameDict*)(self->flex);
|
return (NameDict*)(self->flex);
|
||||||
}
|
}
|
||||||
|
|
||||||
py_TValue* PyObject__slots(PyObject* self) {
|
py_TValue* PyObject__slots(PyObject* self) {
|
||||||
|
@ -49,7 +49,7 @@ bool py_checktype(py_Ref self, py_Type type) {
|
|||||||
bool py_isinstance(py_Ref obj, py_Type type) { return py_issubclass(obj->type, type); }
|
bool py_isinstance(py_Ref obj, py_Type type) { return py_issubclass(obj->type, type); }
|
||||||
|
|
||||||
bool py_issubclass(py_Type derived, py_Type base) {
|
bool py_issubclass(py_Type derived, py_Type base) {
|
||||||
pk_TypeInfo* types = pk_current_vm->types.data;
|
py_TypeInfo* types = pk_current_vm->types.data;
|
||||||
do {
|
do {
|
||||||
if(derived == base) return true;
|
if(derived == base) return true;
|
||||||
derived = types[derived].base;
|
derived = types[derived].base;
|
||||||
|
@ -9,18 +9,18 @@
|
|||||||
#include "pocketpy/compiler/compiler.h"
|
#include "pocketpy/compiler/compiler.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
pk_VM* pk_current_vm;
|
VM* pk_current_vm;
|
||||||
|
|
||||||
py_GlobalRef py_True;
|
py_GlobalRef py_True;
|
||||||
py_GlobalRef py_False;
|
py_GlobalRef py_False;
|
||||||
py_GlobalRef py_None;
|
py_GlobalRef py_None;
|
||||||
py_GlobalRef py_NIL;
|
py_GlobalRef py_NIL;
|
||||||
|
|
||||||
static pk_VM pk_default_vm;
|
static VM pk_default_vm;
|
||||||
static pk_VM* pk_all_vm[16];
|
static VM* pk_all_vm[16];
|
||||||
|
|
||||||
void py_initialize() {
|
void py_initialize() {
|
||||||
pk_MemoryPools__initialize();
|
MemoryPools__initialize();
|
||||||
py_Name__initialize();
|
py_Name__initialize();
|
||||||
|
|
||||||
pk_current_vm = pk_all_vm[0] = &pk_default_vm;
|
pk_current_vm = pk_all_vm[0] = &pk_default_vm;
|
||||||
@ -35,28 +35,28 @@ void py_initialize() {
|
|||||||
py_False = &_False;
|
py_False = &_False;
|
||||||
py_None = &_None;
|
py_None = &_None;
|
||||||
py_NIL = &_NIL;
|
py_NIL = &_NIL;
|
||||||
pk_VM__ctor(&pk_default_vm);
|
VM__ctor(&pk_default_vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void py_finalize() {
|
void py_finalize() {
|
||||||
for(int i = 1; i < 16; i++) {
|
for(int i = 1; i < 16; i++) {
|
||||||
pk_VM* vm = pk_all_vm[i];
|
VM* vm = pk_all_vm[i];
|
||||||
if(vm) {
|
if(vm) {
|
||||||
pk_VM__dtor(vm);
|
VM__dtor(vm);
|
||||||
free(vm);
|
free(vm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pk_VM__dtor(&pk_default_vm);
|
VM__dtor(&pk_default_vm);
|
||||||
pk_current_vm = NULL;
|
pk_current_vm = NULL;
|
||||||
py_Name__finalize();
|
py_Name__finalize();
|
||||||
pk_MemoryPools__finalize();
|
MemoryPools__finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void py_switchvm(int index) {
|
void py_switchvm(int index) {
|
||||||
if(index < 0 || index >= 16) c11__abort("invalid vm index");
|
if(index < 0 || index >= 16) c11__abort("invalid vm index");
|
||||||
if(!pk_all_vm[index]) {
|
if(!pk_all_vm[index]) {
|
||||||
pk_all_vm[index] = malloc(sizeof(pk_VM));
|
pk_all_vm[index] = malloc(sizeof(VM));
|
||||||
pk_VM__ctor(pk_all_vm[index]);
|
VM__ctor(pk_all_vm[index]);
|
||||||
}
|
}
|
||||||
pk_current_vm = pk_all_vm[index];
|
pk_current_vm = pk_all_vm[index];
|
||||||
}
|
}
|
||||||
@ -184,9 +184,9 @@ static void disassemble(CodeObject* co) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool py_exec(const char* source, const char* filename, enum py_CompileMode mode, py_Ref module) {
|
bool py_exec(const char* source, const char* filename, enum py_CompileMode mode, py_Ref module) {
|
||||||
pk_VM* vm = pk_current_vm;
|
VM* vm = pk_current_vm;
|
||||||
CodeObject co;
|
CodeObject co;
|
||||||
pk_SourceData_ src = pk_SourceData__rcnew(source, filename, mode, false);
|
SourceData_ src = SourceData__rcnew(source, filename, mode, false);
|
||||||
Error* err = pk_compile(src, &co);
|
Error* err = pk_compile(src, &co);
|
||||||
if(err) {
|
if(err) {
|
||||||
py_exception("SyntaxError", err->msg);
|
py_exception("SyntaxError", err->msg);
|
||||||
@ -201,8 +201,8 @@ bool py_exec(const char* source, const char* filename, enum py_CompileMode mode,
|
|||||||
if(!module) module = &vm->main;
|
if(!module) module = &vm->main;
|
||||||
|
|
||||||
Frame* frame = Frame__new(&co, module, NULL, vm->stack.sp, vm->stack.sp, &co);
|
Frame* frame = Frame__new(&co, module, NULL, vm->stack.sp, vm->stack.sp, &co);
|
||||||
pk_VM__push_frame(vm, frame);
|
VM__push_frame(vm, frame);
|
||||||
pk_FrameResult res = pk_VM__run_top_frame(vm);
|
FrameResult res = VM__run_top_frame(vm);
|
||||||
CodeObject__dtor(&co);
|
CodeObject__dtor(&co);
|
||||||
PK_DECREF(src);
|
PK_DECREF(src);
|
||||||
if(res == RES_ERROR) return false;
|
if(res == RES_ERROR) return false;
|
||||||
@ -225,8 +225,8 @@ bool py_call(py_Ref f, int argc, py_Ref argv) {
|
|||||||
bool py_callmethod(py_Ref self, py_Name name, int argc, py_Ref argv) { return -1; }
|
bool py_callmethod(py_Ref self, py_Name name, int argc, py_Ref argv) { return -1; }
|
||||||
|
|
||||||
bool py_vectorcall(uint16_t argc, uint16_t kwargc) {
|
bool py_vectorcall(uint16_t argc, uint16_t kwargc) {
|
||||||
pk_VM* vm = pk_current_vm;
|
VM* vm = pk_current_vm;
|
||||||
return pk_VM__vectorcall(vm, argc, kwargc, false) != RES_ERROR;
|
return VM__vectorcall(vm, argc, kwargc, false) != RES_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
py_Ref py_retval() { return &pk_current_vm->last_retval; }
|
py_Ref py_retval() { return &pk_current_vm->last_retval; }
|
||||||
@ -262,7 +262,7 @@ bool pk_pushmethod(py_StackRef self, py_Name name) {
|
|||||||
break;
|
break;
|
||||||
case tp_classmethod:
|
case tp_classmethod:
|
||||||
self[0] = *py_getslot(cls_var, 0);
|
self[0] = *py_getslot(cls_var, 0);
|
||||||
self[1] = c11__getitem(pk_TypeInfo, &pk_current_vm->types, type).self;
|
self[1] = c11__getitem(py_TypeInfo, &pk_current_vm->types, type).self;
|
||||||
break;
|
break;
|
||||||
default: c11__unreachedable();
|
default: c11__unreachedable();
|
||||||
}
|
}
|
||||||
@ -274,7 +274,7 @@ bool pk_pushmethod(py_StackRef self, py_Name name) {
|
|||||||
|
|
||||||
py_Ref py_tpfindmagic(py_Type t, py_Name name) {
|
py_Ref py_tpfindmagic(py_Type t, py_Name name) {
|
||||||
assert(py_ismagicname(name));
|
assert(py_ismagicname(name));
|
||||||
pk_TypeInfo* types = (pk_TypeInfo*)pk_current_vm->types.data;
|
py_TypeInfo* types = (py_TypeInfo*)pk_current_vm->types.data;
|
||||||
do {
|
do {
|
||||||
py_Ref f = &types[t].magic[name];
|
py_Ref f = &types[t].magic[name];
|
||||||
if(!py_isnil(f)) return f;
|
if(!py_isnil(f)) return f;
|
||||||
@ -284,7 +284,7 @@ py_Ref py_tpfindmagic(py_Type t, py_Name name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
py_Ref py_tpfindname(py_Type t, py_Name name) {
|
py_Ref py_tpfindname(py_Type t, py_Name name) {
|
||||||
pk_TypeInfo* types = (pk_TypeInfo*)pk_current_vm->types.data;
|
py_TypeInfo* types = (py_TypeInfo*)pk_current_vm->types.data;
|
||||||
do {
|
do {
|
||||||
py_Ref res = py_getdict(&types[t].self, name);
|
py_Ref res = py_getdict(&types[t].self, name);
|
||||||
if(res) return res;
|
if(res) return res;
|
||||||
@ -295,20 +295,20 @@ py_Ref py_tpfindname(py_Type t, py_Name name) {
|
|||||||
|
|
||||||
py_Ref py_tpmagic(py_Type type, py_Name name) {
|
py_Ref py_tpmagic(py_Type type, py_Name name) {
|
||||||
assert(py_ismagicname(name));
|
assert(py_ismagicname(name));
|
||||||
pk_VM* vm = pk_current_vm;
|
VM* vm = pk_current_vm;
|
||||||
return &c11__at(pk_TypeInfo, &vm->types, type)->magic[name];
|
return &c11__at(py_TypeInfo, &vm->types, type)->magic[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
py_Ref py_tpobject(py_Type type) {
|
py_Ref py_tpobject(py_Type type) {
|
||||||
assert(type);
|
assert(type);
|
||||||
pk_VM* vm = pk_current_vm;
|
VM* vm = pk_current_vm;
|
||||||
return &c11__at(pk_TypeInfo, &vm->types, type)->self;
|
return &c11__at(py_TypeInfo, &vm->types, type)->self;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* py_tpname(py_Type type) {
|
const char* py_tpname(py_Type type) {
|
||||||
if(!type) return "nil";
|
if(!type) return "nil";
|
||||||
pk_VM* vm = pk_current_vm;
|
VM* vm = pk_current_vm;
|
||||||
py_Name name = c11__at(pk_TypeInfo, &vm->types, type)->name;
|
py_Name name = c11__at(py_TypeInfo, &vm->types, type)->name;
|
||||||
return py_name2str(name);
|
return py_name2str(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,7 +325,7 @@ bool pk_callmagic(py_Name name, int argc, py_Ref argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool StopIteration() {
|
bool StopIteration() {
|
||||||
pk_VM* vm = pk_current_vm;
|
VM* vm = pk_current_vm;
|
||||||
assert(!vm->is_stopiteration); // flag is already set
|
assert(!vm->is_stopiteration); // flag is already set
|
||||||
vm->is_stopiteration = true;
|
vm->is_stopiteration = true;
|
||||||
return false;
|
return false;
|
||||||
|
@ -7,13 +7,13 @@
|
|||||||
#include "pocketpy/common/_generated.h"
|
#include "pocketpy/common/_generated.h"
|
||||||
|
|
||||||
py_Ref py_getmodule(const char* path) {
|
py_Ref py_getmodule(const char* path) {
|
||||||
pk_VM* vm = pk_current_vm;
|
VM* vm = pk_current_vm;
|
||||||
return pk_NameDict__try_get(&vm->modules, py_name(path));
|
return NameDict__try_get(&vm->modules, py_name(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
py_Ref py_newmodule(const char* path) {
|
py_Ref py_newmodule(const char* path) {
|
||||||
pk_ManagedHeap* heap = &pk_current_vm->heap;
|
ManagedHeap* heap = &pk_current_vm->heap;
|
||||||
PyObject* obj = pk_ManagedHeap__new(heap, tp_module, -1, 0);
|
PyObject* obj = ManagedHeap__new(heap, tp_module, -1, 0);
|
||||||
|
|
||||||
py_Ref r0 = py_pushtmp();
|
py_Ref r0 = py_pushtmp();
|
||||||
py_Ref r1 = py_pushtmp();
|
py_Ref r1 = py_pushtmp();
|
||||||
@ -44,9 +44,9 @@ py_Ref py_newmodule(const char* path) {
|
|||||||
// we do not allow override in order to avoid memory leak
|
// we do not allow override in order to avoid memory leak
|
||||||
// it is because Module objects are not garbage collected
|
// it is because Module objects are not garbage collected
|
||||||
py_Name path_name = py_name(path);
|
py_Name path_name = py_name(path);
|
||||||
bool exists = pk_NameDict__contains(&pk_current_vm->modules, path_name);
|
bool exists = NameDict__contains(&pk_current_vm->modules, path_name);
|
||||||
if(exists) c11__abort("module '%s' already exists", path);
|
if(exists) c11__abort("module '%s' already exists", path);
|
||||||
pk_NameDict__set(&pk_current_vm->modules, path_name, *r0);
|
NameDict__set(&pk_current_vm->modules, path_name, *r0);
|
||||||
|
|
||||||
py_shrink(2);
|
py_shrink(2);
|
||||||
return py_getmodule(path);
|
return py_getmodule(path);
|
||||||
@ -55,7 +55,7 @@ py_Ref py_newmodule(const char* path) {
|
|||||||
int py_import(const char* path_cstr) {
|
int py_import(const char* path_cstr) {
|
||||||
// printf("importing %s\n", path_cstr);
|
// printf("importing %s\n", path_cstr);
|
||||||
|
|
||||||
pk_VM* vm = pk_current_vm;
|
VM* vm = pk_current_vm;
|
||||||
c11_sv path = {path_cstr, strlen(path_cstr)};
|
c11_sv path = {path_cstr, strlen(path_cstr)};
|
||||||
if(path.size == 0) return ValueError("empty module name");
|
if(path.size == 0) return ValueError("empty module name");
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#include "pocketpy/common/sstream.h"
|
#include "pocketpy/common/sstream.h"
|
||||||
|
|
||||||
typedef struct BaseExceptionFrame {
|
typedef struct BaseExceptionFrame {
|
||||||
pk_SourceData_ src;
|
SourceData_ src;
|
||||||
int lineno;
|
int lineno;
|
||||||
c11_string* name;
|
c11_string* name;
|
||||||
} BaseExceptionFrame;
|
} BaseExceptionFrame;
|
||||||
@ -31,7 +31,7 @@ int py_BaseException__get_lineno(py_Ref self, const CodeObject* code) {
|
|||||||
return ud->lineno_backup;
|
return ud->lineno_backup;
|
||||||
}
|
}
|
||||||
|
|
||||||
void py_BaseException__stpush(py_Ref self, pk_SourceData_ src, int lineno, const char* func_name) {
|
void py_BaseException__stpush(py_Ref self, SourceData_ src, int lineno, const char* func_name) {
|
||||||
BaseException* ud = py_touserdata(self);
|
BaseException* ud = py_touserdata(self);
|
||||||
if(ud->stacktrace.count >= 7) return;
|
if(ud->stacktrace.count >= 7) return;
|
||||||
BaseExceptionFrame* frame = c11_vector__emplace(&ud->stacktrace);
|
BaseExceptionFrame* frame = c11_vector__emplace(&ud->stacktrace);
|
||||||
@ -111,12 +111,12 @@ py_Type pk_Exception__register() {
|
|||||||
|
|
||||||
//////////////////////////////////////////////////
|
//////////////////////////////////////////////////
|
||||||
bool py_checkexc() {
|
bool py_checkexc() {
|
||||||
pk_VM* vm = pk_current_vm;
|
VM* vm = pk_current_vm;
|
||||||
return !py_isnil(&vm->curr_exception);
|
return !py_isnil(&vm->curr_exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
void py_clearexc(py_StackRef p0) {
|
void py_clearexc(py_StackRef p0) {
|
||||||
pk_VM* vm = pk_current_vm;
|
VM* vm = pk_current_vm;
|
||||||
vm->last_retval = *py_NIL;
|
vm->last_retval = *py_NIL;
|
||||||
vm->curr_exception = *py_NIL;
|
vm->curr_exception = *py_NIL;
|
||||||
vm->is_stopiteration = false;
|
vm->is_stopiteration = false;
|
||||||
@ -133,7 +133,7 @@ void py_printexc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
char* py_formatexc() {
|
char* py_formatexc() {
|
||||||
pk_VM* vm = pk_current_vm;
|
VM* vm = pk_current_vm;
|
||||||
if(py_isnil(&vm->curr_exception)) return NULL;
|
if(py_isnil(&vm->curr_exception)) return NULL;
|
||||||
c11_sbuf ss;
|
c11_sbuf ss;
|
||||||
c11_sbuf__ctor(&ss);
|
c11_sbuf__ctor(&ss);
|
||||||
@ -144,7 +144,7 @@ char* py_formatexc() {
|
|||||||
|
|
||||||
for(int i = ud->stacktrace.count - 1; i >= 0; i--) {
|
for(int i = ud->stacktrace.count - 1; i >= 0; i--) {
|
||||||
BaseExceptionFrame* frame = c11__at(BaseExceptionFrame, &ud->stacktrace, i);
|
BaseExceptionFrame* frame = c11__at(BaseExceptionFrame, &ud->stacktrace, i);
|
||||||
pk_SourceData__snapshot(frame->src,
|
SourceData__snapshot(frame->src,
|
||||||
&ss,
|
&ss,
|
||||||
frame->lineno,
|
frame->lineno,
|
||||||
NULL,
|
NULL,
|
||||||
@ -191,7 +191,7 @@ bool py_exception(const char* name, const char* fmt, ...) {
|
|||||||
|
|
||||||
bool py_raise(py_Ref exc) {
|
bool py_raise(py_Ref exc) {
|
||||||
assert(py_isinstance(exc, tp_BaseException));
|
assert(py_isinstance(exc, tp_BaseException));
|
||||||
pk_VM* vm = pk_current_vm;
|
VM* vm = pk_current_vm;
|
||||||
vm->curr_exception = *exc;
|
vm->curr_exception = *exc;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -354,7 +354,7 @@ static bool list__insert(int argc, py_Ref argv) {
|
|||||||
|
|
||||||
static int lt_with_key(py_TValue* a, py_TValue* b, py_TValue* key) {
|
static int lt_with_key(py_TValue* a, py_TValue* b, py_TValue* key) {
|
||||||
if(!key) return py_less(a, b);
|
if(!key) return py_less(a, b);
|
||||||
pk_VM* vm = pk_current_vm;
|
VM* vm = pk_current_vm;
|
||||||
// project a
|
// project a
|
||||||
py_push(key);
|
py_push(key);
|
||||||
py_pushnil();
|
py_pushnil();
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
static bool object__new__(int argc, py_Ref argv) {
|
static bool object__new__(int argc, py_Ref argv) {
|
||||||
if(argc == 0) return TypeError("object.__new__(): not enough arguments");
|
if(argc == 0) return TypeError("object.__new__(): not enough arguments");
|
||||||
py_Type cls = py_totype(py_arg(0));
|
py_Type cls = py_totype(py_arg(0));
|
||||||
pk_TypeInfo* ti = c11__at(pk_TypeInfo, &pk_current_vm->types, cls);
|
py_TypeInfo* ti = c11__at(py_TypeInfo, &pk_current_vm->types, cls);
|
||||||
if(!ti->is_python) {
|
if(!ti->is_python) {
|
||||||
return TypeError("object.__new__(%t) is not safe, use %t.__new__()", cls, cls);
|
return TypeError("object.__new__(%t) is not safe, use %t.__new__()", cls, cls);
|
||||||
}
|
}
|
||||||
@ -63,7 +63,7 @@ static bool type__new__(int argc, py_Ref argv) {
|
|||||||
static bool type__base__getter(int argc, py_Ref argv) {
|
static bool type__base__getter(int argc, py_Ref argv) {
|
||||||
PY_CHECK_ARGC(1);
|
PY_CHECK_ARGC(1);
|
||||||
py_Type type = py_totype(argv);
|
py_Type type = py_totype(argv);
|
||||||
pk_TypeInfo* ti = c11__at(pk_TypeInfo, &pk_current_vm->types, type);
|
py_TypeInfo* ti = c11__at(py_TypeInfo, &pk_current_vm->types, type);
|
||||||
py_assign(py_retval(), py_tpobject(ti->base));
|
py_assign(py_retval(), py_tpobject(ti->base));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ int py_bool(py_Ref val) {
|
|||||||
|
|
||||||
bool py_hash(py_Ref val, int64_t* out) {
|
bool py_hash(py_Ref val, int64_t* out) {
|
||||||
py_Type t = val->type;
|
py_Type t = val->type;
|
||||||
pk_TypeInfo* types = (pk_TypeInfo*)pk_current_vm->types.data;
|
py_TypeInfo* types = (py_TypeInfo*)pk_current_vm->types.data;
|
||||||
do {
|
do {
|
||||||
py_Ref _hash = &types[t].magic[__hash__];
|
py_Ref _hash = &types[t].magic[__hash__];
|
||||||
if(py_isnone(_hash)) break;
|
if(py_isnone(_hash)) break;
|
||||||
@ -68,7 +68,7 @@ bool py_iter(py_Ref val) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int py_next(py_Ref val) {
|
int py_next(py_Ref val) {
|
||||||
pk_VM* vm = pk_current_vm;
|
VM* vm = pk_current_vm;
|
||||||
vm->is_stopiteration = false;
|
vm->is_stopiteration = false;
|
||||||
py_Ref tmp = py_tpfindmagic(val->type, __next__);
|
py_Ref tmp = py_tpfindmagic(val->type, __next__);
|
||||||
if(!tmp) return TypeError("'%t' object is not an iterator", val->type);
|
if(!tmp) return TypeError("'%t' object is not an iterator", val->type);
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
#include "pocketpy/interpreter/vm.h"
|
#include "pocketpy/interpreter/vm.h"
|
||||||
|
|
||||||
void py_newslice(py_Ref out) {
|
void py_newslice(py_Ref out) {
|
||||||
pk_VM* vm = pk_current_vm;
|
VM* vm = pk_current_vm;
|
||||||
PyObject* obj = pk_ManagedHeap__gcnew(&vm->heap, tp_slice, 3, 0);
|
PyObject* obj = ManagedHeap__gcnew(&vm->heap, tp_slice, 3, 0);
|
||||||
out->type = tp_slice;
|
out->type = tp_slice;
|
||||||
out->is_ptr = true;
|
out->is_ptr = true;
|
||||||
out->_obj = obj;
|
out->_obj = obj;
|
||||||
|
@ -9,9 +9,9 @@
|
|||||||
void py_newstr(py_Ref out, const char* data) { py_newstrn(out, data, strlen(data)); }
|
void py_newstr(py_Ref out, const char* data) { py_newstrn(out, data, strlen(data)); }
|
||||||
|
|
||||||
void py_newstrn(py_Ref out, const char* data, int size) {
|
void py_newstrn(py_Ref out, const char* data, int size) {
|
||||||
pk_ManagedHeap* heap = &pk_current_vm->heap;
|
ManagedHeap* heap = &pk_current_vm->heap;
|
||||||
int total_size = sizeof(c11_string) + size + 1;
|
int total_size = sizeof(c11_string) + size + 1;
|
||||||
PyObject* obj = pk_ManagedHeap__gcnew(heap, tp_str, 0, total_size);
|
PyObject* obj = ManagedHeap__gcnew(heap, tp_str, 0, total_size);
|
||||||
c11_string* ud = PyObject__userdata(obj);
|
c11_string* ud = PyObject__userdata(obj);
|
||||||
c11_string__ctor2(ud, data, size);
|
c11_string__ctor2(ud, data, size);
|
||||||
out->type = tp_str;
|
out->type = tp_str;
|
||||||
@ -20,9 +20,9 @@ void py_newstrn(py_Ref out, const char* data, int size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsigned char* py_newbytes(py_Ref out, int size) {
|
unsigned char* py_newbytes(py_Ref out, int size) {
|
||||||
pk_ManagedHeap* heap = &pk_current_vm->heap;
|
ManagedHeap* heap = &pk_current_vm->heap;
|
||||||
// 4 bytes size + data
|
// 4 bytes size + data
|
||||||
PyObject* obj = pk_ManagedHeap__gcnew(heap, tp_bytes, 0, sizeof(c11_bytes) + size);
|
PyObject* obj = ManagedHeap__gcnew(heap, tp_bytes, 0, sizeof(c11_bytes) + size);
|
||||||
c11_bytes* ud = PyObject__userdata(obj);
|
c11_bytes* ud = PyObject__userdata(obj);
|
||||||
ud->size = size;
|
ud->size = size;
|
||||||
out->type = tp_bytes;
|
out->type = tp_bytes;
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
#include "pocketpy/interpreter/vm.h"
|
#include "pocketpy/interpreter/vm.h"
|
||||||
|
|
||||||
void py_newtuple(py_Ref out, int n) {
|
void py_newtuple(py_Ref out, int n) {
|
||||||
pk_VM* vm = pk_current_vm;
|
VM* vm = pk_current_vm;
|
||||||
PyObject* obj = pk_ManagedHeap__gcnew(&vm->heap, tp_tuple, n, 0);
|
PyObject* obj = ManagedHeap__gcnew(&vm->heap, tp_tuple, n, 0);
|
||||||
out->type = tp_tuple;
|
out->type = tp_tuple;
|
||||||
out->is_ptr = true;
|
out->is_ptr = true;
|
||||||
out->_obj = obj;
|
out->_obj = obj;
|
||||||
|
@ -11,7 +11,7 @@ void py_setreg(int i, py_Ref val) { pk_current_vm->reg[i] = *val; }
|
|||||||
py_Ref py_getdict(py_Ref self, py_Name name) {
|
py_Ref py_getdict(py_Ref self, py_Name name) {
|
||||||
assert(self && self->is_ptr);
|
assert(self && self->is_ptr);
|
||||||
if(!py_ismagicname(name) || self->type != tp_type) {
|
if(!py_ismagicname(name) || self->type != tp_type) {
|
||||||
return pk_NameDict__try_get(PyObject__dict(self->_obj), name);
|
return NameDict__try_get(PyObject__dict(self->_obj), name);
|
||||||
} else {
|
} else {
|
||||||
py_Type* ud = py_touserdata(self);
|
py_Type* ud = py_touserdata(self);
|
||||||
py_Ref slot = py_tpmagic(*ud, name);
|
py_Ref slot = py_tpmagic(*ud, name);
|
||||||
@ -22,7 +22,7 @@ py_Ref py_getdict(py_Ref self, py_Name name) {
|
|||||||
void py_setdict(py_Ref self, py_Name name, py_Ref val) {
|
void py_setdict(py_Ref self, py_Name name, py_Ref val) {
|
||||||
assert(self && self->is_ptr);
|
assert(self && self->is_ptr);
|
||||||
if(!py_ismagicname(name) || self->type != tp_type) {
|
if(!py_ismagicname(name) || self->type != tp_type) {
|
||||||
pk_NameDict__set(PyObject__dict(self->_obj), name, *val);
|
NameDict__set(PyObject__dict(self->_obj), name, *val);
|
||||||
} else {
|
} else {
|
||||||
py_Type* ud = py_touserdata(self);
|
py_Type* ud = py_touserdata(self);
|
||||||
*py_tpmagic(*ud, name) = *val;
|
*py_tpmagic(*ud, name) = *val;
|
||||||
@ -37,7 +37,7 @@ py_TmpRef py_emplacedict(py_Ref self, py_Name name){
|
|||||||
bool py_deldict(py_Ref self, py_Name name) {
|
bool py_deldict(py_Ref self, py_Name name) {
|
||||||
assert(self && self->is_ptr);
|
assert(self && self->is_ptr);
|
||||||
if(!py_ismagicname(name) || self->type != tp_type) {
|
if(!py_ismagicname(name) || self->type != tp_type) {
|
||||||
return pk_NameDict__del(PyObject__dict(self->_obj), name);
|
return NameDict__del(PyObject__dict(self->_obj), name);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
py_Type* ud = py_touserdata(self);
|
py_Type* ud = py_touserdata(self);
|
||||||
@ -67,27 +67,27 @@ py_Ref py_peek(int i) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void py_pop() {
|
void py_pop() {
|
||||||
pk_VM* vm = pk_current_vm;
|
VM* vm = pk_current_vm;
|
||||||
vm->stack.sp--;
|
vm->stack.sp--;
|
||||||
}
|
}
|
||||||
|
|
||||||
void py_shrink(int n) {
|
void py_shrink(int n) {
|
||||||
pk_VM* vm = pk_current_vm;
|
VM* vm = pk_current_vm;
|
||||||
vm->stack.sp -= n;
|
vm->stack.sp -= n;
|
||||||
}
|
}
|
||||||
|
|
||||||
void py_push(py_Ref src) {
|
void py_push(py_Ref src) {
|
||||||
pk_VM* vm = pk_current_vm;
|
VM* vm = pk_current_vm;
|
||||||
*vm->stack.sp++ = *src;
|
*vm->stack.sp++ = *src;
|
||||||
}
|
}
|
||||||
|
|
||||||
void py_pushnil() {
|
void py_pushnil() {
|
||||||
pk_VM* vm = pk_current_vm;
|
VM* vm = pk_current_vm;
|
||||||
py_newnil(vm->stack.sp++);
|
py_newnil(vm->stack.sp++);
|
||||||
}
|
}
|
||||||
|
|
||||||
py_Ref py_pushtmp() {
|
py_Ref py_pushtmp() {
|
||||||
pk_VM* vm = pk_current_vm;
|
VM* vm = pk_current_vm;
|
||||||
py_newnil(vm->stack.sp++);
|
py_newnil(vm->stack.sp++);
|
||||||
return py_peek(-1);
|
return py_peek(-1);
|
||||||
}
|
}
|
@ -84,7 +84,7 @@ py_Name
|
|||||||
snprintf(buffer, sizeof(buffer), "def %s: pass", sig);
|
snprintf(buffer, sizeof(buffer), "def %s: pass", sig);
|
||||||
// fn(a, b, *c, d=1) -> None
|
// fn(a, b, *c, d=1) -> None
|
||||||
CodeObject code;
|
CodeObject code;
|
||||||
pk_SourceData_ source = pk_SourceData__rcnew(buffer, "<bind>", EXEC_MODE, false);
|
SourceData_ source = SourceData__rcnew(buffer, "<bind>", EXEC_MODE, false);
|
||||||
Error* err = pk_compile(source, &code);
|
Error* err = pk_compile(source, &code);
|
||||||
if(err || code.func_decls.count != 1) {
|
if(err || code.func_decls.count != 1) {
|
||||||
c11__abort("py_newfunction(): invalid signature '%s'", sig);
|
c11__abort("py_newfunction(): invalid signature '%s'", sig);
|
||||||
@ -102,8 +102,8 @@ py_Name
|
|||||||
}
|
}
|
||||||
|
|
||||||
void* py_newobject(py_Ref out, py_Type type, int slots, int udsize) {
|
void* py_newobject(py_Ref out, py_Type type, int slots, int udsize) {
|
||||||
pk_ManagedHeap* heap = &pk_current_vm->heap;
|
ManagedHeap* heap = &pk_current_vm->heap;
|
||||||
PyObject* obj = pk_ManagedHeap__gcnew(heap, type, slots, udsize);
|
PyObject* obj = ManagedHeap__gcnew(heap, type, slots, udsize);
|
||||||
out->type = type;
|
out->type = type;
|
||||||
out->is_ptr = true;
|
out->is_ptr = true;
|
||||||
out->_obj = obj;
|
out->_obj = obj;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user