From 5be33005546d72b0663e5690e2a37fee24f70a77 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sat, 29 Jun 2024 21:14:11 +0800 Subject: [PATCH] fix initial demo --- build_g.sh | 4 ++-- include/pocketpy/interpreter/frame.h | 15 -------------- include/pocketpy/interpreter/vm.h | 4 +++- include/pocketpy/pocketpy.h | 7 ++++--- src/common/strname.c | 4 ++++ src/compiler/compiler.c | 25 ++++++++++++------------ src/compiler/lexer.c | 2 +- src/interpreter/ceval.c | 29 ++++++++++++++++++++++++++++ src/interpreter/frame.c | 10 +++++++++- src/interpreter/vm.c | 10 ++++++++-- src/public/py_ops.c | 12 ++++++++++++ src/public/py_tuple.c | 25 ++++++++++++++++++++++++ src/public/stack_ops.c | 7 +++++++ src/public/values.c | 8 -------- src/public/vm.c | 7 +++++-- src2/main.c | 10 +++++----- 16 files changed, 127 insertions(+), 52 deletions(-) create mode 100644 src/public/py_tuple.c diff --git a/build_g.sh b/build_g.sh index 64e2035d..72f29054 100644 --- a/build_g.sh +++ b/build_g.sh @@ -5,8 +5,8 @@ python prebuild.py SRC=$(find src/ -name "*.c") FLAGS="-std=c11 -lm -Iinclude -O0 -Wfatal-errors -g -DDEBUG -DPK_ENABLE_OS=1" -# SANITIZE_FLAGS="-fsanitize=address,leak,undefined" -SANITIZE_FLAGS="" +SANITIZE_FLAGS="-fsanitize=address,leak,undefined" +# SANITIZE_FLAGS="" echo "Compiling C files..." clang $FLAGS $SANITIZE_FLAGS $SRC src2/main.c -o main diff --git a/include/pocketpy/interpreter/frame.h b/include/pocketpy/interpreter/frame.h index e6310d9c..4c1aef70 100644 --- a/include/pocketpy/interpreter/frame.h +++ b/include/pocketpy/interpreter/frame.h @@ -89,18 +89,3 @@ void Frame__set_unwind_target(Frame* self, py_TValue* sp); #ifdef __cplusplus } #endif - - -// some patch here -#ifdef __cplusplus -#include "pocketpy/objects/codeobject.hpp" - -extern "C"{ - inline py_TValue* Frame__f_closure_try_get(Frame* self, StrName name){ - if(self->function == NULL) return NULL; - pkpy::Function* fn = PyObject__as(pkpy::Function, self->function); - if(fn->_closure == nullptr) return nullptr; - return pk_NameDict__try_get(fn->_closure, name); - } -} -#endif \ No newline at end of file diff --git a/include/pocketpy/interpreter/vm.h b/include/pocketpy/interpreter/vm.h index b7056193..c553713a 100644 --- a/include/pocketpy/interpreter/vm.h +++ b/include/pocketpy/interpreter/vm.h @@ -58,8 +58,10 @@ typedef struct pk_VM { // singleton objects py_TValue True, False, None, NotImplemented, Ellipsis; - // last error + py_Error* last_error; + py_TValue last_retval; + py_TValue reg[8]; // users' registers PyObject* __curr_class; PyObject* __cached_object_new; diff --git a/include/pocketpy/pocketpy.h b/include/pocketpy/pocketpy.h index 03eaef54..b7e2f739 100644 --- a/include/pocketpy/pocketpy.h +++ b/include/pocketpy/pocketpy.h @@ -31,7 +31,7 @@ void py_finalize(); /// Run a simple source string. Do not change the stack. int py_exec(const char*); /// Eval a simple expression. The result is pushed to the stack. -int py_eval(const char*); +int py_eval(const char*, py_Ref out); /************* Values Creation *************/ void py_newint(py_Ref, int64_t); @@ -101,6 +101,9 @@ bool py_istype(const py_Ref, py_Type); // bool py_issubclass(py_Type derived, py_Type base); /************* References *************/ +py_Ref py_getreg(int i); +void py_setreg(int i, const py_Ref val); + py_Ref py_getdict(const py_Ref self, py_Name name); void py_setdict(py_Ref self, py_Name name, const py_Ref val); @@ -171,14 +174,12 @@ int py_callmethod(py_Ref self, py_Name name, ...); py_Ref py_tuple__getitem(const py_Ref self, int i); void py_tuple__setitem(py_Ref self, int i, const py_Ref val); int py_tuple__len(const py_Ref self); -bool py_tuple__contains(const py_Ref self, const py_Ref val); // unchecked functions, if self is not a list, the behavior is undefined py_Ref py_list__getitem(const py_Ref self, int i); void py_list__setitem(py_Ref self, int i, const py_Ref val); void py_list__delitem(py_Ref self, int i); int py_list__len(const py_Ref self); -bool py_list__contains(const py_Ref self, const py_Ref val); void py_list__append(py_Ref self, const py_Ref val); void py_list__extend(py_Ref self, const py_Ref begin, const py_Ref end); void py_list__clear(py_Ref self); diff --git a/src/common/strname.c b/src/common/strname.c index c1d2de2f..008c07c0 100644 --- a/src/common/strname.c +++ b/src/common/strname.c @@ -79,6 +79,10 @@ void pk_StrName__initialize(){ void pk_StrName__finalize(){ if(!_initialized) return; + // free all char* + for(int i=0; i<_r_interned.count; i++){ + free(c11__getitem(char*, &_r_interned, i)); + } c11_smallmap_s2n__dtor(&_interned); c11_vector__dtor(&_r_interned); } diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index 3328efba..9458850d 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -468,7 +468,7 @@ static SequenceExpr* SequenceExpr__new(int line, const ExprVt* vt, int count, Op self->vt = vt; self->line = line; self->opcode = opcode; - c11_array__ctor(&self->items, count, sizeof(Expr*)); + c11_array__ctor(&self->items, sizeof(Expr*), count); return self; } @@ -1395,7 +1395,7 @@ void Ctx__emit_store_name(Ctx* self, NameScope scope, StrName name, int line) { // emit top -> pop -> delete void Ctx__s_emit_top(Ctx* self) { Expr* top = c11_vector__back(Expr*, &self->s_expr); - top->vt->emit_(top, self); + vtemit_(top, self); c11_vector__pop(&self->s_expr); vtdelete(top); } @@ -1670,7 +1670,8 @@ static Error* pop_context(Compiler* self) { /* Expression Callbacks */ static Error* exprLiteral(Compiler* self) { - Ctx__s_push(ctx(), (Expr*)LiteralExpr__new(prev()->line, &prev()->value)); + LiteralExpr* e = LiteralExpr__new(prev()->line, &prev()->value); + Ctx__s_push(ctx(), (Expr*)e); return NULL; } @@ -2064,15 +2065,15 @@ Error* pk_compile(pk_SourceData_ src, CodeObject* out) { Error* err = pk_Lexer__process(src, &tokens); if(err) return err; - // Token* data = (Token*)tokens.data; - // printf("%s\n", py_Str__data(&src->filename)); - // for(int i = 0; i < tokens.count; i++) { - // Token* t = data + i; - // py_Str tmp; - // py_Str__ctor2(&tmp, t->start, t->length); - // printf("[%d] %s: %s\n", t->line, pk_TokenSymbols[t->type], py_Str__data(&tmp)); - // py_Str__dtor(&tmp); - // } + Token* data = (Token*)tokens.data; + printf("%s\n", py_Str__data(&src->filename)); + for(int i = 0; i < tokens.count; i++) { + Token* t = data + i; + py_Str tmp; + py_Str__ctor2(&tmp, t->start, t->length); + printf("[%d] %s: %s\n", t->line, pk_TokenSymbols[t->type], py_Str__data(&tmp)); + py_Str__dtor(&tmp); + } Compiler compiler; Compiler__ctor(&compiler, src, tokens); diff --git a/src/compiler/lexer.c b/src/compiler/lexer.c index 7f463bed..0fa80106 100644 --- a/src/compiler/lexer.c +++ b/src/compiler/lexer.c @@ -376,7 +376,7 @@ static Error* eat_number(pk_Lexer* self){ return NULL; } // try integer - TokenValue value = {.index = TokenValue_EMPTY}; + TokenValue value = {.index = TokenValue_I64}; switch(parse_uint(text, &value._i64, -1)) { case IntParsing_SUCCESS: add_token_with_value(self, TK_NUM, value); diff --git a/src/interpreter/ceval.c b/src/interpreter/ceval.c index b30bfc16..87945b35 100644 --- a/src/interpreter/ceval.c +++ b/src/interpreter/ceval.c @@ -203,7 +203,36 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) { if(err) goto __ERROR; DISPATCH(); } + /*******************/ + // ... + + /*******************/ + case OP_BUILD_TUPLE: { + py_TValue tmp; + py_newtuple(&tmp, byte.arg); + py_TValue* begin = SP() - byte.arg; + for(int i = 0; i < byte.arg; i++) { + py_tuple__setitem(&tmp, i, begin + i); + } + SP() = begin; + PUSH(tmp); + DISPATCH(); + } + /**************************** */ + case OP_RETURN_VALUE: { + py_TValue tmp = byte.arg == BC_NOARG ? POPX() : self->None; + pk_VM__pop_frame(self); + if(frame == base_frame) { // [ frameBase<- ] + self->last_retval = tmp; + return RES_RETURN; + } else { + frame = self->top_frame; + PUSH(tmp); + goto __NEXT_FRAME; + } + DISPATCH(); + } default: PK_UNREACHABLE(); } diff --git a/src/interpreter/frame.c b/src/interpreter/frame.c index 1e178e5e..f5310ef2 100644 --- a/src/interpreter/frame.c +++ b/src/interpreter/frame.c @@ -46,7 +46,7 @@ Frame* Frame__new(const CodeObject* co, const py_TValue* module, const py_TValue self->ip = (Bytecode*)co->codes.data - 1; self->co = co; self->module = module->_obj; - self->function = function->_obj; + self->function = function ? function->_obj : NULL; self->p0 = p0; self->locals = locals; self->locals_co = locals_co; @@ -131,3 +131,11 @@ void Frame__set_unwind_target(Frame* self, py_TValue* sp) { self->uw_list = UnwindTarget__new(prev, iblock, sp - self->locals); } } + +py_TValue* Frame__f_closure_try_get(Frame* self, StrName name){ + // if(self->function == NULL) return NULL; + // pkpy::Function* fn = PyObject__as(pkpy::Function, self->function); + // if(fn->_closure == nullptr) return nullptr; + // return pk_NameDict__try_get(fn->_closure, name); + return NULL; +} \ No newline at end of file diff --git a/src/interpreter/vm.c b/src/interpreter/vm.c index 0ba0fa32..439ece22 100644 --- a/src/interpreter/vm.c +++ b/src/interpreter/vm.c @@ -56,6 +56,7 @@ void pk_VM__ctor(pk_VM* self){ self->_stderr = pk_default_stderr; self->last_error = NULL; + self->last_retval = PY_NULL; self->__curr_class = NULL; self->__cached_object_new = NULL; @@ -153,7 +154,9 @@ void pk_VM__ctor(pk_VM* self){ } void pk_VM__dtor(pk_VM* self){ - PK_DECREF(self->__dynamic_func_decl); + if(self->__dynamic_func_decl){ + PK_DECREF(self->__dynamic_func_decl); + } // destroy all objects pk_ManagedHeap__dtor(&self->heap); // clear frames @@ -171,6 +174,9 @@ void pk_VM__push_frame(pk_VM* self, Frame* frame){ void pk_VM__pop_frame(pk_VM* self){ assert(self->top_frame); Frame* frame = self->top_frame; + // reset stack pointer + self->stack.sp = frame->p0; + // pop frame and delete self->top_frame = frame->f_back; Frame__delete(frame); } @@ -187,7 +193,7 @@ py_Type pk_VM__new_type(pk_VM* self, const char* name, py_Type base, const py_TV /****************************************/ void PyObject__delete(PyObject *self){ - pk_TypeInfo* ti = c11__getitem(pk_TypeInfo*, &pk_current_vm->types, self->type); + pk_TypeInfo* ti = c11__at(pk_TypeInfo, &pk_current_vm->types, self->type); if(ti->dtor) ti->dtor(PyObject__value(self)); if(self->slots == -1) pk_NameDict__dtor(PyObject__dict(self)); if(self->gc_is_large){ diff --git a/src/public/py_ops.c b/src/public/py_ops.c index 41baa2e4..bb7c33dc 100644 --- a/src/public/py_ops.c +++ b/src/public/py_ops.c @@ -13,4 +13,16 @@ int py_repr(const py_Ref val) { const pk_TypeInfo* ti = c11__at(pk_TypeInfo, &pk_current_vm->types, val->type); if(ti->m__repr__) return ti->m__repr__(1, val); return py_callmethod(val, __repr__); +} + +int py_getattr(const py_Ref self, py_Name name, py_Ref out){ + return -1; +} + +int py_setattr(py_Ref self, py_Name name, const py_Ref val){ + return -1; +} + +int py_callmethod(py_Ref self, py_Name name, ...){ + return -1; } \ No newline at end of file diff --git a/src/public/py_tuple.c b/src/public/py_tuple.c new file mode 100644 index 00000000..cc6e8c22 --- /dev/null +++ b/src/public/py_tuple.c @@ -0,0 +1,25 @@ +#include "pocketpy/pocketpy.h" + +#include "pocketpy/common/utils.h" +#include "pocketpy/objects/object.h" +#include "pocketpy/interpreter/vm.h" + +void py_newtuple(py_Ref out, int n) { + pk_VM* vm = pk_current_vm; + PyObject* obj = pk_ManagedHeap__gcnew(&vm->heap, tp_tuple, n, 0); + out->type = tp_tuple; + out->is_ptr = true; + out->_obj = obj; +} + +py_Ref py_tuple__getitem(const py_Ref self, int i){ + return py_getslot(self, i); +} + +void py_tuple__setitem(py_Ref self, int i, const py_Ref val){ + py_setslot(self, i, val); +} + +int py_tuple__len(const py_Ref self){ + return self->_obj->slots; +} diff --git a/src/public/stack_ops.c b/src/public/stack_ops.c index 3bd24793..90a4bc03 100644 --- a/src/public/stack_ops.c +++ b/src/public/stack_ops.c @@ -4,6 +4,13 @@ #include "pocketpy/objects/object.h" #include "pocketpy/interpreter/vm.h" +py_Ref py_getreg(int i){ + return pk_current_vm->reg + i; +} + +void py_setreg(int i, const py_Ref val){ + pk_current_vm->reg[i] = *val; +} py_Ref py_getdict(const py_Ref self, py_Name name){ assert(self && self->is_ptr); diff --git a/src/public/values.c b/src/public/values.c index bf769541..a946b4f8 100644 --- a/src/public/values.c +++ b/src/public/values.c @@ -46,14 +46,6 @@ void py_newnone(py_Ref out) { void py_newnull(py_Ref out) { out->type = 0; } -void py_newtuple(py_Ref out, int n) { - pk_VM* vm = pk_current_vm; - PyObject* obj = pk_ManagedHeap__gcnew(&vm->heap, tp_tuple, n, 0); - out->type = tp_tuple; - out->is_ptr = true; - out->_obj = obj; -} - void py_newfunction(py_Ref out, py_CFunction f, const char* sig) { py_newfunction2(out, f, sig, BindType_FUNCTION, NULL, NULL); } diff --git a/src/public/vm.c b/src/public/vm.c index cc4b8a36..2fb9e14b 100644 --- a/src/public/vm.c +++ b/src/public/vm.c @@ -25,7 +25,7 @@ void py_finalize() { int py_exec(const char* source) { PK_UNREACHABLE(); } -int py_eval(const char* source) { +int py_eval(const char* source, py_Ref out) { CodeObject co; pk_SourceData_ src = pk_SourceData__rcnew(source, "main.py", EVAL_MODE, false); Error* err = pk_compile(src, &co); @@ -40,6 +40,9 @@ int py_eval(const char* source) { CodeObject__dtor(&co); PK_DECREF(src); if(res == RES_ERROR) return vm->last_error->type; - if(res == RES_RETURN) return 0; + if(res == RES_RETURN){ + *out = vm->last_retval; + return 0; + } PK_UNREACHABLE(); } \ No newline at end of file diff --git a/src2/main.c b/src2/main.c index ad4867ec..61328869 100644 --- a/src2/main.c +++ b/src2/main.c @@ -25,19 +25,19 @@ int main(int argc, char** argv) { #endif py_initialize(); - const char* source = "[1, 'a']"; + const char* source = "1, 'a'"; - if(py_eval(source)){ + py_Ref r0 = py_getreg(0); + if(py_eval(source, r0)){ py_Error* err = py_getlasterror(); py_Error__print(err); }else{ // handle the result - py_Ref _0 = py_list__getitem(py_gettop(), 0); - py_Ref _1 = py_list__getitem(py_gettop(), 1); + py_Ref _0 = py_tuple__getitem(r0, 0); + py_Ref _1 = py_tuple__getitem(r0, 1); int _L0 = py_toint(_0); const char* _L1 = py_tostr(_1); printf("%d, %s\n", _L0, _L1); - py_pop(); } py_finalize();