mirror of
				https://github.com/pocketpy/pocketpy
				synced 2025-10-31 00:40:16 +00:00 
			
		
		
		
	Compare commits
	
		
			No commits in common. "841cc25a4eaf77ec64885a24bd24e8baacccb1dc" and "8c41065258e2340e7e8f2fe15d9165f56ea90241" have entirely different histories.
		
	
	
		
			841cc25a4e
			...
			8c41065258
		
	
		
| @ -50,9 +50,10 @@ typedef struct pk_VM { | |||||||
|     void (*_stdout)(const char*, ...); |     void (*_stdout)(const char*, ...); | ||||||
|     void (*_stderr)(const char*, ...); |     void (*_stderr)(const char*, ...); | ||||||
| 
 | 
 | ||||||
|     py_TValue last_retval; |     // singleton objects
 | ||||||
|     bool has_error; |     py_TValue True, False, None, NotImplemented, Ellipsis; | ||||||
| 
 | 
 | ||||||
|  |     py_TValue last_retval; | ||||||
|     py_TValue reg[8];  // users' registers
 |     py_TValue reg[8];  // users' registers
 | ||||||
| 
 | 
 | ||||||
|     py_TValue __curr_class; |     py_TValue __curr_class; | ||||||
|  | |||||||
| @ -40,10 +40,10 @@ void py_initialize(); | |||||||
| void py_finalize(); | void py_finalize(); | ||||||
| 
 | 
 | ||||||
| /// Run a simple source string. Do not change the stack.
 | /// Run a simple source string. Do not change the stack.
 | ||||||
| bool py_exec(const char* source); | bool py_exec(const char*); | ||||||
| /// Eval a simple expression.
 | /// Eval a simple expression.
 | ||||||
| /// The result will be set to `py_retval()`.
 | /// The result will be set to `py_retval()`.
 | ||||||
| bool py_eval(const char* source); | bool py_eval(const char*); | ||||||
| 
 | 
 | ||||||
| /************* Values Creation *************/ | /************* Values Creation *************/ | ||||||
| void py_newint(py_Ref, py_i64); | void py_newint(py_Ref, py_i64); | ||||||
|  | |||||||
| @ -27,7 +27,6 @@ static void pk_SourceData__ctor(struct pk_SourceData* self, | |||||||
|     } |     } | ||||||
|     self->source = c11_sbuf__submit(&ss); |     self->source = c11_sbuf__submit(&ss); | ||||||
|     self->is_precompiled = (strncmp(source, "pkpy:", 5) == 0); |     self->is_precompiled = (strncmp(source, "pkpy:", 5) == 0); | ||||||
|     self->is_dynamic = is_dynamic; |  | ||||||
|     c11_vector__push(const char*, &self->line_starts, self->source->data); |     c11_vector__push(const char*, &self->line_starts, self->source->data); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -10,10 +10,12 @@ | |||||||
| #include <ctype.h> | #include <ctype.h> | ||||||
| #include <math.h> | #include <math.h> | ||||||
| 
 | 
 | ||||||
|  | const static int C11_STRING_HEADER_SIZE = sizeof(c11_string); | ||||||
|  | 
 | ||||||
| void c11_sbuf__ctor(c11_sbuf* self) { | void c11_sbuf__ctor(c11_sbuf* self) { | ||||||
|     c11_vector__ctor(&self->data, sizeof(char)); |     c11_vector__ctor(&self->data, sizeof(char)); | ||||||
|     c11_vector__reserve(&self->data, sizeof(c11_string) + 100); |     c11_vector__reserve(&self->data, 100 + C11_STRING_HEADER_SIZE); | ||||||
|     self->data.count = sizeof(c11_string); |     self->data.count = C11_STRING_HEADER_SIZE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void c11_sbuf__dtor(c11_sbuf* self) { c11_vector__dtor(&self->data); } | void c11_sbuf__dtor(c11_sbuf* self) { c11_vector__dtor(&self->data); } | ||||||
| @ -23,16 +25,14 @@ void c11_sbuf__write_char(c11_sbuf* self, char c) { c11_vector__push(char, &self | |||||||
| void c11_sbuf__write_int(c11_sbuf* self, int i) { | void c11_sbuf__write_int(c11_sbuf* self, int i) { | ||||||
|     // len('-2147483648') == 11
 |     // len('-2147483648') == 11
 | ||||||
|     c11_vector__reserve(&self->data, self->data.count + 11 + 1); |     c11_vector__reserve(&self->data, self->data.count + 11 + 1); | ||||||
|     char* p = self->data.data + self->data.count; |     int n = snprintf(self->data.data, 11 + 1, "%d", i); | ||||||
|     int n = snprintf(p, 11 + 1, "%d", i); |  | ||||||
|     self->data.count += n; |     self->data.count += n; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void c11_sbuf__write_i64(c11_sbuf* self, int64_t val) { | void c11_sbuf__write_i64(c11_sbuf* self, int64_t val) { | ||||||
|     // len('-9223372036854775808') == 20
 |     // len('-9223372036854775808') == 20
 | ||||||
|     c11_vector__reserve(&self->data, self->data.count + 20 + 1); |     c11_vector__reserve(&self->data, self->data.count + 20 + 1); | ||||||
|     char* p = self->data.data + self->data.count; |     int n = snprintf(self->data.data, 20 + 1, "%lld", (long long)val); | ||||||
|     int n = snprintf(p, 20 + 1, "%lld", (long long)val); |  | ||||||
|     self->data.count += n; |     self->data.count += n; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -136,8 +136,8 @@ void c11_sbuf__write_ptr(c11_sbuf* self, void* p) { | |||||||
| c11_string* c11_sbuf__submit(c11_sbuf* self) { | c11_string* c11_sbuf__submit(c11_sbuf* self) { | ||||||
|     c11_vector__push(char, &self->data, '\0'); |     c11_vector__push(char, &self->data, '\0'); | ||||||
|     c11_array arr = c11_vector__submit(&self->data); |     c11_array arr = c11_vector__submit(&self->data); | ||||||
|     c11_string* retval = arr.data; |     c11_string* retval = (c11_string*)arr.data; | ||||||
|     retval->size = arr.count - sizeof(c11_string) - 1; |     retval->size = arr.count - C11_STRING_HEADER_SIZE - 1; | ||||||
|     return retval; |     return retval; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -20,6 +20,11 @@ void py_Name__initialize() { | |||||||
| #define MAGIC_METHOD(x) assert(x == py_name(#x)); | #define MAGIC_METHOD(x) assert(x == py_name(#x)); | ||||||
| #include "pocketpy/xmacros/magics.h" | #include "pocketpy/xmacros/magics.h" | ||||||
| #undef MAGIC_METHOD | #undef MAGIC_METHOD | ||||||
|  | 
 | ||||||
|  |     // print all names
 | ||||||
|  |     for(int i = 0; i < _interned.count; i++) { | ||||||
|  |         printf("%d: %s\n", i + 1, c11__getitem(char*, &_r_interned, i)); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void py_Name__finalize() { | void py_Name__finalize() { | ||||||
|  | |||||||
| @ -64,7 +64,7 @@ typedef struct Ctx { | |||||||
|     int curr_iblock; |     int curr_iblock; | ||||||
|     bool is_compiling_class; |     bool is_compiling_class; | ||||||
|     c11_vector /*T=Expr* */ s_expr; |     c11_vector /*T=Expr* */ s_expr; | ||||||
|     c11_smallmap_n2i global_names; |     c11_vector /*T=py_Name*/ global_names; | ||||||
|     c11_smallmap_s2n co_consts_string_dedup_map; |     c11_smallmap_s2n co_consts_string_dedup_map; | ||||||
| } Ctx; | } Ctx; | ||||||
| 
 | 
 | ||||||
| @ -1209,7 +1209,7 @@ void Ctx__ctor(Ctx* self, CodeObject* co, FuncDecl* func, int level) { | |||||||
|     self->curr_iblock = 0; |     self->curr_iblock = 0; | ||||||
|     self->is_compiling_class = false; |     self->is_compiling_class = false; | ||||||
|     c11_vector__ctor(&self->s_expr, sizeof(Expr*)); |     c11_vector__ctor(&self->s_expr, sizeof(Expr*)); | ||||||
|     c11_smallmap_n2i__ctor(&self->global_names); |     c11_vector__ctor(&self->global_names, sizeof(py_Name)); | ||||||
|     c11_smallmap_s2n__ctor(&self->co_consts_string_dedup_map); |     c11_smallmap_s2n__ctor(&self->co_consts_string_dedup_map); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -1220,7 +1220,7 @@ void Ctx__dtor(Ctx* self) { | |||||||
|     } |     } | ||||||
|     c11_vector__clear(&self->s_expr); |     c11_vector__clear(&self->s_expr); | ||||||
|     c11_vector__dtor(&self->s_expr); |     c11_vector__dtor(&self->s_expr); | ||||||
|     c11_smallmap_n2i__dtor(&self->global_names); |     c11_vector__dtor(&self->global_names); | ||||||
|     c11_smallmap_s2n__dtor(&self->co_consts_string_dedup_map); |     c11_smallmap_s2n__dtor(&self->co_consts_string_dedup_map); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -1455,7 +1455,7 @@ static void Compiler__dtor(Compiler* self) { | |||||||
|                            pk_TokenSymbols[expected],                                              \ |                            pk_TokenSymbols[expected],                                              \ | ||||||
|                            pk_TokenSymbols[curr()->type]); |                            pk_TokenSymbols[curr()->type]); | ||||||
| #define consume_end_stmt()                                                                         \ | #define consume_end_stmt()                                                                         \ | ||||||
|     if(!match_end_stmt(self)) return SyntaxError("expected statement end") |     if(!match_end_stmt()) return SyntaxError("expected statement end") | ||||||
| #define check_newlines_repl()                                                                      \ | #define check_newlines_repl()                                                                      \ | ||||||
|     do {                                                                                           \ |     do {                                                                                           \ | ||||||
|         bool __nml;                                                                                \ |         bool __nml;                                                                                \ | ||||||
| @ -1471,7 +1471,7 @@ static NameScope name_scope(Compiler* self) { | |||||||
|     return s; |     return s; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #define SyntaxError(...) NULL | static Error* SyntaxError(const char* fmt, ...) { return NULL; } | ||||||
| 
 | 
 | ||||||
| static Error* NeedMoreLines() { return NULL; } | static Error* NeedMoreLines() { return NULL; } | ||||||
| 
 | 
 | ||||||
| @ -1798,7 +1798,10 @@ static Error* exprName(Compiler* self) { | |||||||
|     py_Name name = py_name2(Token__sv(prev())); |     py_Name name = py_name2(Token__sv(prev())); | ||||||
|     NameScope scope = name_scope(self); |     NameScope scope = name_scope(self); | ||||||
|     // promote this name to global scope if needed
 |     // promote this name to global scope if needed
 | ||||||
|     if(c11_smallmap_n2i__contains(&ctx()->global_names, name)) { scope = NAME_GLOBAL; } |     c11_vector* global_names = &ctx()->global_names; | ||||||
|  |     c11__foreach(py_Name, global_names, it) { | ||||||
|  |         if(*it == name) scope = NAME_GLOBAL; | ||||||
|  |     } | ||||||
|     NameExpr* e = NameExpr__new(prev()->line, name, scope); |     NameExpr* e = NameExpr__new(prev()->line, name, scope); | ||||||
|     Ctx__s_push(ctx(), (Expr*)e); |     Ctx__s_push(ctx(), (Expr*)e); | ||||||
|     return NULL; |     return NULL; | ||||||
| @ -2002,258 +2005,6 @@ static Error* exprSubscr(Compiler* self) { | |||||||
|     return NULL; |     return NULL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ////////////////
 |  | ||||||
| static Error* consume_type_hints(Compiler* self) { |  | ||||||
|     Error* err; |  | ||||||
|     check(EXPR(self)); |  | ||||||
|     Ctx__s_pop(ctx()); |  | ||||||
|     return NULL; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| Error* try_compile_assignment(Compiler* self, bool* is_assign) { |  | ||||||
|     Error* err; |  | ||||||
|     switch(curr()->type) { |  | ||||||
|         case TK_IADD: |  | ||||||
|         case TK_ISUB: |  | ||||||
|         case TK_IMUL: |  | ||||||
|         case TK_IDIV: |  | ||||||
|         case TK_IFLOORDIV: |  | ||||||
|         case TK_IMOD: |  | ||||||
|         case TK_ILSHIFT: |  | ||||||
|         case TK_IRSHIFT: |  | ||||||
|         case TK_IAND: |  | ||||||
|         case TK_IOR: |  | ||||||
|         case TK_IXOR: { |  | ||||||
|             if(Ctx__s_top(ctx())->vt->is_starred) return SyntaxError(); |  | ||||||
|             if(ctx()->is_compiling_class) { |  | ||||||
|                 return SyntaxError("can't use inplace operator in class definition"); |  | ||||||
|             } |  | ||||||
|             advance(); |  | ||||||
|             // a[x] += 1;   a and x should be evaluated only once
 |  | ||||||
|             // a.x += 1;    a should be evaluated only once
 |  | ||||||
|             // -1 to remove =; inplace=true
 |  | ||||||
|             int line = prev()->line; |  | ||||||
|             TokenIndex op = (TokenIndex)(prev()->type - 1); |  | ||||||
|             // [lhs]
 |  | ||||||
|             check(EXPR_TUPLE(self));  // [lhs, rhs]
 |  | ||||||
|             if(Ctx__s_top(ctx())->vt->is_starred) return SyntaxError(); |  | ||||||
|             BinaryExpr* e = BinaryExpr__new(line, op, true); |  | ||||||
|             e->rhs = Ctx__s_popx(ctx());  // [lhs]
 |  | ||||||
|             e->lhs = Ctx__s_popx(ctx());  // []
 |  | ||||||
|             vtemit_((Expr*)e, ctx()); |  | ||||||
|             bool ok = vtemit_istore(e->lhs, ctx()); |  | ||||||
|             vtdelete((Expr*)e); |  | ||||||
|             if(!ok) return SyntaxError(); |  | ||||||
|             *is_assign = true; |  | ||||||
|             return NULL; |  | ||||||
|         } |  | ||||||
|         case TK_ASSIGN: { |  | ||||||
|             int n = 0; |  | ||||||
|             while(match(TK_ASSIGN)) { |  | ||||||
|                 check(EXPR_TUPLE(self)); |  | ||||||
|                 n += 1; |  | ||||||
|             } |  | ||||||
|             // stack size is n+1
 |  | ||||||
|             Ctx__s_emit_top(ctx()); |  | ||||||
|             for(int j = 1; j < n; j++) |  | ||||||
|                 Ctx__emit_(ctx(), OP_DUP_TOP, BC_NOARG, BC_KEEPLINE); |  | ||||||
|             for(int j = 0; j < n; j++) { |  | ||||||
|                 if(Ctx__s_top(ctx())->vt->is_starred) return SyntaxError(); |  | ||||||
|                 Expr* e = Ctx__s_top(ctx()); |  | ||||||
|                 bool ok = vtemit_store(e, ctx()); |  | ||||||
|                 Ctx__s_pop(ctx()); |  | ||||||
|                 if(!ok) return SyntaxError(); |  | ||||||
|             } |  | ||||||
|             *is_assign = true; |  | ||||||
|             return NULL; |  | ||||||
|         } |  | ||||||
|         default: *is_assign = false; |  | ||||||
|     } |  | ||||||
|     return NULL; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static Error* compile_stmt(Compiler* self) { |  | ||||||
|     Error* err; |  | ||||||
|     if(match(TK_CLASS)) { |  | ||||||
|         // check(compile_class());
 |  | ||||||
|         assert(false); |  | ||||||
|         return NULL; |  | ||||||
|     } |  | ||||||
|     advance(); |  | ||||||
|     int kw_line = prev()->line;  // backup line number
 |  | ||||||
|     int curr_loop_block = Ctx__get_loop(ctx()); |  | ||||||
|     switch(prev()->type) { |  | ||||||
|         case TK_BREAK: |  | ||||||
|             if(curr_loop_block < 0) return SyntaxError("'break' outside loop"); |  | ||||||
|             Ctx__emit_(ctx(), OP_LOOP_BREAK, curr_loop_block, kw_line); |  | ||||||
|             consume_end_stmt(); |  | ||||||
|             break; |  | ||||||
|         case TK_CONTINUE: |  | ||||||
|             if(curr_loop_block < 0) return SyntaxError("'continue' not properly in loop"); |  | ||||||
|             Ctx__emit_(ctx(), OP_LOOP_CONTINUE, curr_loop_block, kw_line); |  | ||||||
|             consume_end_stmt(); |  | ||||||
|             break; |  | ||||||
|         case TK_YIELD: |  | ||||||
|             if(self->contexts.count <= 1) return SyntaxError("'yield' outside function"); |  | ||||||
|             check(EXPR_TUPLE(self)); |  | ||||||
|             Ctx__s_emit_top(ctx()); |  | ||||||
|             Ctx__emit_(ctx(), OP_YIELD_VALUE, BC_NOARG, kw_line); |  | ||||||
|             consume_end_stmt(); |  | ||||||
|             break; |  | ||||||
|         case TK_YIELD_FROM: |  | ||||||
|             if(self->contexts.count <= 1) return SyntaxError("'yield from' outside function"); |  | ||||||
|             check(EXPR_TUPLE(self)); |  | ||||||
|             Ctx__s_emit_top(ctx()); |  | ||||||
|             Ctx__emit_(ctx(), OP_GET_ITER_NEW, BC_NOARG, kw_line); |  | ||||||
|             Ctx__enter_block(ctx(), CodeBlockType_FOR_LOOP); |  | ||||||
|             Ctx__emit_(ctx(), OP_FOR_ITER_YIELD_VALUE, BC_NOARG, kw_line); |  | ||||||
|             Ctx__emit_(ctx(), OP_LOOP_CONTINUE, Ctx__get_loop(ctx()), kw_line); |  | ||||||
|             Ctx__exit_block(ctx()); |  | ||||||
|             consume_end_stmt(); |  | ||||||
|             break; |  | ||||||
|         case TK_RETURN: |  | ||||||
|             if(self->contexts.count <= 1) return SyntaxError("'return' outside function"); |  | ||||||
|             if(match_end_stmt(self)) { |  | ||||||
|                 Ctx__emit_(ctx(), OP_RETURN_VALUE, 1, kw_line); |  | ||||||
|             } else { |  | ||||||
|                 check(EXPR_TUPLE(self)); |  | ||||||
|                 Ctx__s_emit_top(ctx()); |  | ||||||
|                 consume_end_stmt(); |  | ||||||
|                 Ctx__emit_(ctx(), OP_RETURN_VALUE, BC_NOARG, kw_line); |  | ||||||
|             } |  | ||||||
|             break; |  | ||||||
|         /*************************************************/ |  | ||||||
|         // case TK_IF: check(compile_if_stmt()); break;
 |  | ||||||
|         // case TK_WHILE: check(compile_while_loop()); break;
 |  | ||||||
|         // case TK_FOR: check(compile_for_loop()); break;
 |  | ||||||
|         // case TK_IMPORT: check(compile_normal_import()); break;
 |  | ||||||
|         // case TK_FROM: check(compile_from_import()); break;
 |  | ||||||
|         // case TK_DEF: check(compile_function()); break;
 |  | ||||||
|         // case TK_DECORATOR: check(compile_decorated()); break;
 |  | ||||||
|         // case TK_TRY: check(compile_try_except()); break;
 |  | ||||||
|         case TK_PASS: consume_end_stmt(); break; |  | ||||||
|         /*************************************************/ |  | ||||||
|         case TK_ASSERT: { |  | ||||||
|             check(EXPR(self));  // condition
 |  | ||||||
|             Ctx__s_emit_top(ctx()); |  | ||||||
|             int index = Ctx__emit_(ctx(), OP_POP_JUMP_IF_TRUE, BC_NOARG, kw_line); |  | ||||||
|             int has_msg = 0; |  | ||||||
|             if(match(TK_COMMA)) { |  | ||||||
|                 check(EXPR(self));  // message
 |  | ||||||
|                 Ctx__s_emit_top(ctx()); |  | ||||||
|                 has_msg = 1; |  | ||||||
|             } |  | ||||||
|             Ctx__emit_(ctx(), OP_RAISE_ASSERT, has_msg, kw_line); |  | ||||||
|             Ctx__patch_jump(ctx(), index); |  | ||||||
|             consume_end_stmt(); |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|         case TK_GLOBAL: |  | ||||||
|             do { |  | ||||||
|                 consume(TK_ID); |  | ||||||
|                 py_Name name = py_name2(Token__sv(prev())); |  | ||||||
|                 c11_smallmap_n2i__set(&ctx()->global_names, name, 0); |  | ||||||
|             } while(match(TK_COMMA)); |  | ||||||
|             consume_end_stmt(); |  | ||||||
|             break; |  | ||||||
|         case TK_RAISE: { |  | ||||||
|             check(EXPR(self)); |  | ||||||
|             Ctx__s_emit_top(ctx()); |  | ||||||
|             Ctx__emit_(ctx(), OP_RAISE, BC_NOARG, kw_line); |  | ||||||
|             consume_end_stmt(); |  | ||||||
|         } break; |  | ||||||
|         case TK_DEL: { |  | ||||||
|             check(EXPR_TUPLE(self)); |  | ||||||
|             Expr* e = Ctx__s_top(ctx()); |  | ||||||
|             if(!vtemit_del(e, ctx())) return SyntaxError(); |  | ||||||
|             Ctx__s_pop(ctx()); |  | ||||||
|             consume_end_stmt(); |  | ||||||
|         } break; |  | ||||||
|         // case TK_WITH: {
 |  | ||||||
|         //     check(EXPR(self));  // [ <expr> ]
 |  | ||||||
|         //     Ctx__s_emit_top(ctx());
 |  | ||||||
|         //     Ctx__enter_block(ctx(), CodeBlockType_CONTEXT_MANAGER);
 |  | ||||||
|         //     Expr* as_name = nullptr;
 |  | ||||||
|         //     if(match(TK_AS)) {
 |  | ||||||
|         //         consume(TK_ID);
 |  | ||||||
|         //         as_name = make_expr<NameExpr>(prev().str(), name_scope());
 |  | ||||||
|         //     }
 |  | ||||||
|         //     Ctx__emit_(ctx(), OP_WITH_ENTER, BC_NOARG, prev().line);
 |  | ||||||
|         //     // [ <expr> <expr>.__enter__() ]
 |  | ||||||
|         //     if(as_name) {
 |  | ||||||
|         //         bool ok = as_name->emit_store(ctx());
 |  | ||||||
|         //         delete_expr(as_name);
 |  | ||||||
|         //         if(!ok) return SyntaxError();
 |  | ||||||
|         //     } else {
 |  | ||||||
|         //         Ctx__emit_(ctx(), OP_POP_TOP, BC_NOARG, BC_KEEPLINE);
 |  | ||||||
|         //     }
 |  | ||||||
|         //     check(compile_block_body());
 |  | ||||||
|         //     Ctx__emit_(ctx(), OP_WITH_EXIT, BC_NOARG, prev().line);
 |  | ||||||
|         //     Ctx__exit_block(ctx());
 |  | ||||||
|         // } break;
 |  | ||||||
|         /*************************************************/ |  | ||||||
|         case TK_EQ: { |  | ||||||
|             consume(TK_ID); |  | ||||||
|             if(mode() != EXEC_MODE) return SyntaxError("'label' is only available in EXEC_MODE"); |  | ||||||
|             c11_sv name = Token__sv(prev()); |  | ||||||
|             bool ok = Ctx__add_label(ctx(), py_name2(name)); |  | ||||||
|             if(!ok) return SyntaxError("label %q already exists", name); |  | ||||||
|             consume(TK_EQ); |  | ||||||
|             consume_end_stmt(); |  | ||||||
|         } break; |  | ||||||
|         case TK_ARROW: |  | ||||||
|             consume(TK_ID); |  | ||||||
|             if(mode() != EXEC_MODE) return SyntaxError("'goto' is only available in EXEC_MODE"); |  | ||||||
|             py_Name name = py_name2(Token__sv(prev())); |  | ||||||
|             Ctx__emit_(ctx(), OP_GOTO, name, prev()->line); |  | ||||||
|             consume_end_stmt(); |  | ||||||
|             break; |  | ||||||
|         /*************************************************/ |  | ||||||
|         // handle dangling expression or assignment
 |  | ||||||
|         default: { |  | ||||||
|             // do revert since we have pre-called advance() at the beginning
 |  | ||||||
|             --self->i; |  | ||||||
| 
 |  | ||||||
|             check(EXPR_TUPLE(self)); |  | ||||||
| 
 |  | ||||||
|             bool is_typed_name = false;  // e.g. x: int
 |  | ||||||
|             // eat variable's type hint if it is a single name
 |  | ||||||
|             if(Ctx__s_top(ctx())->vt->is_name) { |  | ||||||
|                 if(match(TK_COLON)) { |  | ||||||
|                     check(consume_type_hints(self)); |  | ||||||
|                     is_typed_name = true; |  | ||||||
| 
 |  | ||||||
|                     if(ctx()->is_compiling_class) { |  | ||||||
|                         NameExpr* ne = (NameExpr*)Ctx__s_top(ctx()); |  | ||||||
|                         Ctx__emit_(ctx(), OP_ADD_CLASS_ANNOTATION, ne->name, BC_KEEPLINE); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             bool is_assign = false; |  | ||||||
|             check(try_compile_assignment(self, &is_assign)); |  | ||||||
|             if(!is_assign) { |  | ||||||
|                 if(Ctx__s_size(ctx()) > 0 && Ctx__s_top(ctx())->vt->is_starred) { |  | ||||||
|                     return SyntaxError(); |  | ||||||
|                 } |  | ||||||
|                 if(!is_typed_name) { |  | ||||||
|                     Ctx__s_emit_top(ctx()); |  | ||||||
|                     if((mode() == CELL_MODE || mode() == REPL_MODE) && |  | ||||||
|                        name_scope(self) == NAME_GLOBAL) { |  | ||||||
|                         Ctx__emit_(ctx(), OP_PRINT_EXPR, BC_NOARG, BC_KEEPLINE); |  | ||||||
|                     } else { |  | ||||||
|                         Ctx__emit_(ctx(), OP_POP_TOP, BC_NOARG, BC_KEEPLINE); |  | ||||||
|                     } |  | ||||||
|                 } else { |  | ||||||
|                     Ctx__s_pop(ctx()); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             consume_end_stmt(); |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     return NULL; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /////////////////////////////////////////////////////////////////
 | /////////////////////////////////////////////////////////////////
 | ||||||
| 
 | 
 | ||||||
| Error* Compiler__compile(Compiler* self, CodeObject* out) { | Error* Compiler__compile(Compiler* self, CodeObject* out) { | ||||||
| @ -2275,22 +2026,25 @@ Error* Compiler__compile(Compiler* self, CodeObject* out) { | |||||||
|         Ctx__emit_(ctx(), OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE); |         Ctx__emit_(ctx(), OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE); | ||||||
|         check(pop_context(self)); |         check(pop_context(self)); | ||||||
|         return NULL; |         return NULL; | ||||||
|     } else if(mode() == JSON_MODE) { |  | ||||||
|         check(EXPR(self)); |  | ||||||
|         Expr* e = Ctx__s_popx(ctx()); |  | ||||||
|         if(!e->vt->is_json_object) { return SyntaxError("expect a JSON object, literal or array"); } |  | ||||||
|         consume(TK_EOF); |  | ||||||
|         vtemit_(e, ctx()); |  | ||||||
|         Ctx__emit_(ctx(), OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE); |  | ||||||
|         check(pop_context(self)); |  | ||||||
|         return NULL; |  | ||||||
|     } |     } | ||||||
|  |     // } else if(mode() == JSON_MODE) {
 | ||||||
|  |     //     check(EXPR(self));
 | ||||||
|  |     //     Expr* e = Ctx__s_popx(ctx());
 | ||||||
|  |     //     if(!e->is_json_object()){
 | ||||||
|  |     //         return SyntaxError("expect a JSON object, literal or array");
 | ||||||
|  |     //     }
 | ||||||
|  |     //     consume(TK_EOF);
 | ||||||
|  |     //     e->emit_(ctx());
 | ||||||
|  |     //     ctx()->emit_(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
 | ||||||
|  |     //     check(pop_context());
 | ||||||
|  |     //     return NULL;
 | ||||||
|  |     // }
 | ||||||
| 
 | 
 | ||||||
|     while(!match(TK_EOF)) { |     // while(!match(TK_EOF)) {
 | ||||||
|         check(compile_stmt(self)); |     //     check(compile_stmt());
 | ||||||
|         match_newlines(); |     //     match_newlines();
 | ||||||
|     } |     // }
 | ||||||
|     check(pop_context(self)); |     // check(pop_context());
 | ||||||
|     return NULL; |     return NULL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -2315,8 +2069,6 @@ Error* pk_compile(pk_SourceData_ src, CodeObject* out) { | |||||||
|     if(err) { |     if(err) { | ||||||
|         // if error occurs, dispose the code object
 |         // if error occurs, dispose the code object
 | ||||||
|         CodeObject__dtor(out); |         CodeObject__dtor(out); | ||||||
|     } else { |  | ||||||
|         assert(out->codes.count); |  | ||||||
|     } |     } | ||||||
|     Compiler__dtor(&compiler); |     Compiler__dtor(&compiler); | ||||||
|     return err; |     return err; | ||||||
|  | |||||||
| @ -13,6 +13,7 @@ int NameError(py_Name name) { return -1; } | |||||||
| 
 | 
 | ||||||
| static bool stack_binaryop(pk_VM* self, py_Name op, py_Name rop); | static bool stack_binaryop(pk_VM* self, py_Name op, py_Name rop); | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| #define DISPATCH()                                                                                 \ | #define DISPATCH()                                                                                 \ | ||||||
|     do {                                                                                           \ |     do {                                                                                           \ | ||||||
|         frame->ip++;                                                                               \ |         frame->ip++;                                                                               \ | ||||||
| @ -122,13 +123,13 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) { | |||||||
|                 DISPATCH(); |                 DISPATCH(); | ||||||
|             /*****************************************/ |             /*****************************************/ | ||||||
|             case OP_LOAD_CONST: PUSH(c11__at(py_TValue, &frame->co->consts, byte.arg)); DISPATCH(); |             case OP_LOAD_CONST: PUSH(c11__at(py_TValue, &frame->co->consts, byte.arg)); DISPATCH(); | ||||||
|             case OP_LOAD_NONE: py_newnone(SP()++); DISPATCH(); |             case OP_LOAD_NONE: PUSH(&self->None); DISPATCH(); | ||||||
|             case OP_LOAD_TRUE: py_newbool(SP()++, true); DISPATCH(); |             case OP_LOAD_TRUE: PUSH(&self->True); DISPATCH(); | ||||||
|             case OP_LOAD_FALSE: py_newbool(SP()++, false); DISPATCH(); |             case OP_LOAD_FALSE: PUSH(&self->False); DISPATCH(); | ||||||
|             /*****************************************/ |             /*****************************************/ | ||||||
|             case OP_LOAD_SMALL_INT: py_newint(SP()++, (int64_t)(int16_t)byte.arg); DISPATCH(); |             case OP_LOAD_SMALL_INT: py_newint(SP()++, (int64_t)(int16_t)byte.arg); DISPATCH(); | ||||||
|             /*****************************************/ |             /*****************************************/ | ||||||
|             case OP_LOAD_ELLIPSIS: py_newellipsis(SP()++); DISPATCH(); |             case OP_LOAD_ELLIPSIS: PUSH(&self->Ellipsis); DISPATCH(); | ||||||
|             case OP_LOAD_FUNCTION: { |             case OP_LOAD_FUNCTION: { | ||||||
|                 // FuncDecl_ decl = c11__getitem(FuncDecl_, &frame->co->func_decls, byte.arg);
 |                 // FuncDecl_ decl = c11__getitem(FuncDecl_, &frame->co->func_decls, byte.arg);
 | ||||||
|                 // py_TValue obj;
 |                 // py_TValue obj;
 | ||||||
| @ -511,7 +512,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) { | |||||||
|                 bool res = py_isidentical(SECOND(), TOP()); |                 bool res = py_isidentical(SECOND(), TOP()); | ||||||
|                 POP(); |                 POP(); | ||||||
|                 if(byte.arg) res = !res; |                 if(byte.arg) res = !res; | ||||||
|                 py_newbool(TOP(), res); |                 *TOP() = res ? self->True : self->False; | ||||||
|                 DISPATCH(); |                 DISPATCH(); | ||||||
|             } |             } | ||||||
|             case OP_CONTAINS_OP: { |             case OP_CONTAINS_OP: { | ||||||
| @ -576,7 +577,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) { | |||||||
|                 if(res < 0) goto __ERROR; |                 if(res < 0) goto __ERROR; | ||||||
|                 if(!res) {               // [b, False]
 |                 if(!res) {               // [b, False]
 | ||||||
|                     STACK_SHRINK(2);     // []
 |                     STACK_SHRINK(2);     // []
 | ||||||
|                     py_newbool(SP()++, false);  // [False]
 |                     PUSH(&self->False);  // [False]
 | ||||||
|                     DISPATCH_JUMP((int16_t)byte.arg); |                     DISPATCH_JUMP((int16_t)byte.arg); | ||||||
|                 } else { |                 } else { | ||||||
|                     POP();  // [b]
 |                     POP();  // [b]
 | ||||||
| @ -605,11 +606,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) { | |||||||
|                 // }
 |                 // }
 | ||||||
|                 /*****************************************/ |                 /*****************************************/ | ||||||
|             case OP_RETURN_VALUE: { |             case OP_RETURN_VALUE: { | ||||||
|                 if(byte.arg == BC_NOARG) { |                 self->last_retval = byte.arg == BC_NOARG ? POPX() : self->None; | ||||||
|                     self->last_retval = POPX(); |  | ||||||
|                 } else { |  | ||||||
|                     py_newnone(&self->last_retval); |  | ||||||
|                 } |  | ||||||
|                 pk_VM__pop_frame(self); |                 pk_VM__pop_frame(self); | ||||||
|                 if(frame == base_frame) {  // [ frameBase<- ]
 |                 if(frame == base_frame) {  // [ frameBase<- ]
 | ||||||
|                     return RES_RETURN; |                     return RES_RETURN; | ||||||
| @ -620,31 +617,6 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) { | |||||||
|                 } |                 } | ||||||
|                 DISPATCH(); |                 DISPATCH(); | ||||||
|             } |             } | ||||||
| 
 |  | ||||||
|                 /////////
 |  | ||||||
|             case OP_UNARY_NEGATIVE: { |  | ||||||
|                 if(!py_callmagic(__neg__, 1, TOP())) goto __ERROR; |  | ||||||
|                 *TOP() = self->last_retval; |  | ||||||
|                 DISPATCH(); |  | ||||||
|             } |  | ||||||
|             case OP_UNARY_NOT: { |  | ||||||
|                 int res = py_bool(TOP()); |  | ||||||
|                 if(res < 0) goto __ERROR; |  | ||||||
|                 py_newbool(TOP(), !res); |  | ||||||
|                 DISPATCH(); |  | ||||||
|             } |  | ||||||
|                 // case OP_UNARY_STAR: TOP() = VAR(StarWrapper(byte.arg, TOP())); DISPATCH();
 |  | ||||||
|                 // case OP_UNARY_INVERT: {
 |  | ||||||
|                 //     PyVar _0;
 |  | ||||||
|                 //     auto _ti = _tp_info(TOP());
 |  | ||||||
|                 //     if(_ti->m__invert__)
 |  | ||||||
|                 //         _0 = _ti->m__invert__(this, TOP());
 |  | ||||||
|                 //     else
 |  | ||||||
|                 //         _0 = call_method(TOP(), __invert__);
 |  | ||||||
|                 //     TOP() = _0;
 |  | ||||||
|                 //     DISPATCH();
 |  | ||||||
|                 // }
 |  | ||||||
| 
 |  | ||||||
|             default: PK_UNREACHABLE(); |             default: PK_UNREACHABLE(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -653,7 +625,6 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) { | |||||||
|     __ERROR: |     __ERROR: | ||||||
|         // 1. Exception can be handled inside the current frame
 |         // 1. Exception can be handled inside the current frame
 | ||||||
|         // 2. Exception need to be propagated to the upper frame
 |         // 2. Exception need to be propagated to the upper frame
 | ||||||
|         printf("byte.op: %d, line: %d\n", byte.op, Frame__lineno(frame)); |  | ||||||
|         assert(false); |         assert(false); | ||||||
|         return RES_ERROR; |         return RES_ERROR; | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -68,7 +68,6 @@ void pk_VM__ctor(pk_VM* self) { | |||||||
|     self->_stderr = pk_default_stderr; |     self->_stderr = pk_default_stderr; | ||||||
| 
 | 
 | ||||||
|     self->last_retval = PY_NULL; |     self->last_retval = PY_NULL; | ||||||
|     self->has_error = false; |  | ||||||
| 
 | 
 | ||||||
|     self->__curr_class = PY_NULL; |     self->__curr_class = PY_NULL; | ||||||
|     self->__cached_object_new = PY_NULL; |     self->__cached_object_new = PY_NULL; | ||||||
| @ -149,10 +148,7 @@ void pk_VM__ctor(pk_VM* self) { | |||||||
|         pk_TypeInfo* ti = c11__at(pk_TypeInfo, &self->types, t); |         pk_TypeInfo* ti = c11__at(pk_TypeInfo, &self->types, t); | ||||||
|         py_setdict(&self->builtins, ti->name, py_tpobject(t)); |         py_setdict(&self->builtins, ti->name, py_tpobject(t)); | ||||||
|     } |     } | ||||||
| 
 |     py_setdict(&self->builtins, py_name("NotImplemented"), &self->NotImplemented); | ||||||
|     py_TValue tmp; |  | ||||||
|     py_newnotimplemented(&tmp); |  | ||||||
|     py_setdict(&self->builtins, py_name("NotImplemented"), &tmp); |  | ||||||
| 
 | 
 | ||||||
|     /* Do Buildin Bindings*/ |     /* Do Buildin Bindings*/ | ||||||
|     pk_VM__init_builtins(self); |     pk_VM__init_builtins(self); | ||||||
|  | |||||||
| @ -1,16 +0,0 @@ | |||||||
| #include "pocketpy/pocketpy.h" |  | ||||||
| #include "pocketpy/interpreter/vm.h" |  | ||||||
| 
 |  | ||||||
| void py_printexc(){ |  | ||||||
|     pk_VM* vm = pk_current_vm; |  | ||||||
|     if(vm->has_error){ |  | ||||||
|         assert(vm->last_retval.type == tp_exception); |  | ||||||
|     }else{ |  | ||||||
|         vm->_stdout("NoneType: None\n"); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| void py_formatexc(char *out){ |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
							
								
								
									
										141
									
								
								src/public/vm.c
									
									
									
									
									
								
							
							
						
						
									
										141
									
								
								src/public/vm.c
									
									
									
									
									
								
							| @ -2,7 +2,6 @@ | |||||||
| #include "pocketpy/pocketpy.h" | #include "pocketpy/pocketpy.h" | ||||||
| 
 | 
 | ||||||
| #include "pocketpy/common/utils.h" | #include "pocketpy/common/utils.h" | ||||||
| #include "pocketpy/common/sstream.h" |  | ||||||
| #include "pocketpy/objects/object.h" | #include "pocketpy/objects/object.h" | ||||||
| #include "pocketpy/interpreter/vm.h" | #include "pocketpy/interpreter/vm.h" | ||||||
| #include "pocketpy/compiler/compiler.h" | #include "pocketpy/compiler/compiler.h" | ||||||
| @ -24,145 +23,17 @@ void py_finalize() { | |||||||
|     pk_MemoryPools__finalize(); |     pk_MemoryPools__finalize(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void disassemble(CodeObject* co) { | bool py_exec(const char* source) { PK_UNREACHABLE(); } | ||||||
|     const static char* OP_NAMES[] = { |  | ||||||
| #define OPCODE(name) #name, |  | ||||||
| #include "pocketpy/xmacros/opcodes.h" |  | ||||||
| #undef OPCODE |  | ||||||
|     }; |  | ||||||
| 
 | 
 | ||||||
|     c11_vector /*T=int*/ jumpTargets; | bool py_eval(const char* source) { | ||||||
|     c11_vector__ctor(&jumpTargets, sizeof(int)); |  | ||||||
|     for(int i = 0; i < co->codes.count; i++) { |  | ||||||
|         Bytecode* bc = c11__at(Bytecode, &co->codes, i); |  | ||||||
|         if(Bytecode__is_forward_jump(bc)) { |  | ||||||
|             int target = (int16_t)bc->arg + i; |  | ||||||
|             c11_vector__push(int, &jumpTargets, target); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     c11_sbuf ss; |  | ||||||
|     c11_sbuf__ctor(&ss); |  | ||||||
| 
 |  | ||||||
|     int prev_line = -1; |  | ||||||
|     for(int i = 0; i < co->codes.count; i++) { |  | ||||||
|         Bytecode byte = c11__getitem(Bytecode, &co->codes, i); |  | ||||||
|         BytecodeEx ex = c11__getitem(BytecodeEx, &co->codes_ex, i); |  | ||||||
| 
 |  | ||||||
|         char line[8] = ""; |  | ||||||
|         if(ex.lineno == prev_line) { |  | ||||||
|             // do nothing
 |  | ||||||
|         } else { |  | ||||||
|             snprintf(line, sizeof(line), "%d", ex.lineno); |  | ||||||
|             if(prev_line != -1) c11_sbuf__write_char(&ss, '\n'); |  | ||||||
|             prev_line = ex.lineno; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         char pointer[4] = ""; |  | ||||||
|         c11__foreach(int, &jumpTargets, it) { |  | ||||||
|             if(*it == i) { |  | ||||||
|                 snprintf(pointer, sizeof(pointer), "->"); |  | ||||||
|                 break; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         char buf[32]; |  | ||||||
|         snprintf(buf, sizeof(buf), "%-8s%-3s%-3d", line, pointer, i); |  | ||||||
|         c11_sbuf__write_cstr(&ss, buf); |  | ||||||
| 
 |  | ||||||
|         snprintf(buf, sizeof(buf), " %-24s", OP_NAMES[byte.op]); |  | ||||||
|         c11_sbuf__write_cstr(&ss, buf); |  | ||||||
|         c11_sbuf__write_char(&ss, ex.is_virtual ? '*' : ' '); |  | ||||||
| 
 |  | ||||||
|         // _opcode_argstr(this, i, byte, co);
 |  | ||||||
|         do { |  | ||||||
|             if(Bytecode__is_forward_jump(&byte)) { |  | ||||||
|                 c11_sbuf__write_int(&ss, (int16_t)byte.arg); |  | ||||||
|                 c11_sbuf__write_cstr(&ss, " (to "); |  | ||||||
|                 c11_sbuf__write_int(&ss, (int16_t)byte.arg + i); |  | ||||||
|                 c11_sbuf__write_char(&ss, ')'); |  | ||||||
|                 break; |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             c11_sbuf__write_int(&ss, byte.arg); |  | ||||||
|             switch(byte.op) { |  | ||||||
|                 case OP_LOAD_CONST: |  | ||||||
|                 case OP_FORMAT_STRING: |  | ||||||
|                 case OP_IMPORT_PATH: { |  | ||||||
|                     py_Ref tmp = c11__at(py_TValue, &co->consts, byte.arg); |  | ||||||
|                     c11_sbuf__write_cstr(&ss, " ("); |  | ||||||
|                     // here we need to use py_repr, however this function is not ready yet
 |  | ||||||
|                     c11_sbuf__write_cstr(&ss, "<class '"); |  | ||||||
|                     c11_sbuf__write_cstr(&ss, py_tpname(tmp->type)); |  | ||||||
|                     c11_sbuf__write_cstr(&ss, "'>)"); |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|                 case OP_LOAD_NAME: |  | ||||||
|                 case OP_LOAD_GLOBAL: |  | ||||||
|                 case OP_LOAD_NONLOCAL: |  | ||||||
|                 case OP_STORE_GLOBAL: |  | ||||||
|                 case OP_LOAD_ATTR: |  | ||||||
|                 case OP_LOAD_METHOD: |  | ||||||
|                 case OP_STORE_ATTR: |  | ||||||
|                 case OP_DELETE_ATTR: |  | ||||||
|                 case OP_BEGIN_CLASS: |  | ||||||
|                 case OP_GOTO: |  | ||||||
|                 case OP_DELETE_GLOBAL: |  | ||||||
|                 case OP_STORE_CLASS_ATTR: |  | ||||||
|                 case OP_FOR_ITER_STORE_GLOBAL: { |  | ||||||
|                     c11_sbuf__write_cstr(&ss, " ("); |  | ||||||
|                     c11_sbuf__write_cstr(&ss, py_name2str(byte.arg)); |  | ||||||
|                     c11_sbuf__write_char(&ss, ')'); |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|                 case OP_LOAD_FAST: |  | ||||||
|                 case OP_STORE_FAST: |  | ||||||
|                 case OP_DELETE_FAST: |  | ||||||
|                 case OP_FOR_ITER_STORE_FAST: { |  | ||||||
|                     py_Name name = c11__getitem(py_Name, &co->varnames, byte.arg); |  | ||||||
|                     c11_sbuf__write_cstr(&ss, " ("); |  | ||||||
|                     c11_sbuf__write_cstr(&ss, py_name2str(name)); |  | ||||||
|                     c11_sbuf__write_char(&ss, ')'); |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|                 case OP_LOAD_FUNCTION: { |  | ||||||
|                     const FuncDecl* decl = c11__getitem(FuncDecl*, &co->func_decls, byte.arg); |  | ||||||
|                     c11_sbuf__write_cstr(&ss, " ("); |  | ||||||
|                     c11_sbuf__write_cstr(&ss, decl->code.name->data); |  | ||||||
|                     c11_sbuf__write_char(&ss, ')'); |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|                 case OP_BINARY_OP: { |  | ||||||
|                     py_Name name = byte.arg & 0xFF; |  | ||||||
|                     c11_sbuf__write_cstr(&ss, " ("); |  | ||||||
|                     c11_sbuf__write_cstr(&ss, py_name2str(name)); |  | ||||||
|                     c11_sbuf__write_char(&ss, ')'); |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } while(0); |  | ||||||
| 
 |  | ||||||
|         if(i != co->codes.count - 1) c11_sbuf__write_char(&ss, '\n'); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     c11_string* output = c11_sbuf__submit(&ss); |  | ||||||
|     pk_current_vm->_stdout("%s\n", output->data); |  | ||||||
|     c11_string__delete(output); |  | ||||||
|     c11_vector__dtor(&jumpTargets); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool |  | ||||||
|     pk_VM__exec(pk_VM* vm, const char* source, const char* filename, enum CompileMode mode) { |  | ||||||
|     CodeObject co; |     CodeObject co; | ||||||
|     pk_SourceData_ src = pk_SourceData__rcnew(source, filename, mode, false); |     pk_SourceData_ src = pk_SourceData__rcnew(source, "main.py", EVAL_MODE, false); | ||||||
|     Error* err = pk_compile(src, &co); |     Error* err = pk_compile(src, &co); | ||||||
|     if(err) { |     if(err) { | ||||||
|         PK_DECREF(src); |         PK_DECREF(src); | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
| 
 |     pk_VM* vm = pk_current_vm; | ||||||
|     disassemble(&co); |  | ||||||
| 
 |  | ||||||
|     Frame* frame = Frame__new(&co, &vm->main, NULL, vm->stack.sp, vm->stack.sp, &co); |     Frame* frame = Frame__new(&co, &vm->main, NULL, vm->stack.sp, vm->stack.sp, &co); | ||||||
|     pk_VM__push_frame(vm, frame); |     pk_VM__push_frame(vm, frame); | ||||||
|     pk_FrameResult res = pk_VM__run_top_frame(vm); |     pk_FrameResult res = pk_VM__run_top_frame(vm); | ||||||
| @ -173,10 +44,6 @@ static bool | |||||||
|     PK_UNREACHABLE(); |     PK_UNREACHABLE(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool py_exec(const char* source) { return pk_VM__exec(pk_current_vm, source, "<exec>", EXEC_MODE); } |  | ||||||
| 
 |  | ||||||
| bool py_eval(const char* source) { return pk_VM__exec(pk_current_vm, source, "<eval>", EVAL_MODE); } |  | ||||||
| 
 |  | ||||||
| bool py_call(py_Ref f, int argc, py_Ref argv) { return -1; } | bool py_call(py_Ref f, 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_callmethod(py_Ref self, py_Name name, int argc, py_Ref argv) { return -1; } | ||||||
|  | |||||||
							
								
								
									
										23
									
								
								src2/main.c
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								src2/main.c
									
									
									
									
									
								
							| @ -25,7 +25,6 @@ int main(int argc, char** argv) { | |||||||
|     SetConsoleOutputCP(CP_UTF8); |     SetConsoleOutputCP(CP_UTF8); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #if 0 |  | ||||||
|     py_initialize(); |     py_initialize(); | ||||||
|     const char* source = "1 < 2"; |     const char* source = "1 < 2"; | ||||||
| 
 | 
 | ||||||
| @ -48,18 +47,20 @@ int main(int argc, char** argv) { | |||||||
| 
 | 
 | ||||||
|     py_finalize(); |     py_finalize(); | ||||||
|     return 0; |     return 0; | ||||||
| #endif |  | ||||||
| 
 | 
 | ||||||
|     if(argc != 2) goto __HELP; |     //     if(argc != 2) goto __HELP;
 | ||||||
|     char* source = read_file(argv[1]); |     //     char* source = read_file(argv[1]);
 | ||||||
|     py_initialize(); |     //     py_initialize();
 | ||||||
| 
 | 
 | ||||||
|     if(!py_exec(source)) py_printexc(); |     //     if(py_exec(source)){
 | ||||||
|  |     //         py_Error* err = py_getlasterror();
 | ||||||
|  |     //         py_Error__print(err);
 | ||||||
|  |     //     }
 | ||||||
| 
 | 
 | ||||||
|     py_finalize(); |     //     py_finalize();
 | ||||||
|     free(source); |     //     free(source);
 | ||||||
| 
 | 
 | ||||||
| __HELP: |     // __HELP:
 | ||||||
|     printf("Usage: pocketpy [filename]\n"); |     //     printf("Usage: pocketpy [filename]\n");
 | ||||||
|     return 0; |     //     return 0;
 | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user