Compare commits

...

3 Commits

Author SHA1 Message Date
blueloveTH
841cc25a4e some fix 2024-07-03 01:24:29 +08:00
blueloveTH
e365124af3 some up 2024-07-03 00:48:45 +08:00
blueloveTH
1696bb6d66 some up 2024-07-02 23:34:50 +08:00
11 changed files with 497 additions and 73 deletions

View File

@ -50,10 +50,9 @@ typedef struct pk_VM {
void (*_stdout)(const char*, ...);
void (*_stderr)(const char*, ...);
// singleton objects
py_TValue True, False, None, NotImplemented, Ellipsis;
py_TValue last_retval;
bool has_error;
py_TValue reg[8]; // users' registers
py_TValue __curr_class;

View File

@ -40,10 +40,10 @@ void py_initialize();
void py_finalize();
/// Run a simple source string. Do not change the stack.
bool py_exec(const char*);
bool py_exec(const char* source);
/// Eval a simple expression.
/// The result will be set to `py_retval()`.
bool py_eval(const char*);
bool py_eval(const char* source);
/************* Values Creation *************/
void py_newint(py_Ref, py_i64);

View File

@ -27,6 +27,7 @@ static void pk_SourceData__ctor(struct pk_SourceData* self,
}
self->source = c11_sbuf__submit(&ss);
self->is_precompiled = (strncmp(source, "pkpy:", 5) == 0);
self->is_dynamic = is_dynamic;
c11_vector__push(const char*, &self->line_starts, self->source->data);
}

View File

@ -10,12 +10,10 @@
#include <ctype.h>
#include <math.h>
const static int C11_STRING_HEADER_SIZE = sizeof(c11_string);
void c11_sbuf__ctor(c11_sbuf* self) {
c11_vector__ctor(&self->data, sizeof(char));
c11_vector__reserve(&self->data, 100 + C11_STRING_HEADER_SIZE);
self->data.count = C11_STRING_HEADER_SIZE;
c11_vector__reserve(&self->data, sizeof(c11_string) + 100);
self->data.count = sizeof(c11_string);
}
void c11_sbuf__dtor(c11_sbuf* self) { c11_vector__dtor(&self->data); }
@ -25,14 +23,16 @@ 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) {
// len('-2147483648') == 11
c11_vector__reserve(&self->data, self->data.count + 11 + 1);
int n = snprintf(self->data.data, 11 + 1, "%d", i);
char* p = self->data.data + self->data.count;
int n = snprintf(p, 11 + 1, "%d", i);
self->data.count += n;
}
void c11_sbuf__write_i64(c11_sbuf* self, int64_t val) {
// len('-9223372036854775808') == 20
c11_vector__reserve(&self->data, self->data.count + 20 + 1);
int n = snprintf(self->data.data, 20 + 1, "%lld", (long long)val);
char* p = self->data.data + self->data.count;
int n = snprintf(p, 20 + 1, "%lld", (long long)val);
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_vector__push(char, &self->data, '\0');
c11_array arr = c11_vector__submit(&self->data);
c11_string* retval = (c11_string*)arr.data;
retval->size = arr.count - C11_STRING_HEADER_SIZE - 1;
c11_string* retval = arr.data;
retval->size = arr.count - sizeof(c11_string) - 1;
return retval;
}

View File

@ -20,11 +20,6 @@ void py_Name__initialize() {
#define MAGIC_METHOD(x) assert(x == py_name(#x));
#include "pocketpy/xmacros/magics.h"
#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() {

View File

@ -64,7 +64,7 @@ typedef struct Ctx {
int curr_iblock;
bool is_compiling_class;
c11_vector /*T=Expr* */ s_expr;
c11_vector /*T=py_Name*/ global_names;
c11_smallmap_n2i global_names;
c11_smallmap_s2n co_consts_string_dedup_map;
} Ctx;
@ -671,7 +671,7 @@ static void FStringExpr__emit_(Expr* self_, Ctx* ctx) {
int conon = c11_sv__index(expr, ':');
if(conon >= 0) {
c11_sv spec = {expr.data + (conon + 1),
expr.size - (conon + 1)}; // expr[conon+1:]
expr.size - (conon + 1)}; // expr[conon+1:]
// filter some invalid spec
bool ok = true;
for(int k = 0; k < spec.size; k++) {
@ -1209,7 +1209,7 @@ void Ctx__ctor(Ctx* self, CodeObject* co, FuncDecl* func, int level) {
self->curr_iblock = 0;
self->is_compiling_class = false;
c11_vector__ctor(&self->s_expr, sizeof(Expr*));
c11_vector__ctor(&self->global_names, sizeof(py_Name));
c11_smallmap_n2i__ctor(&self->global_names);
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__dtor(&self->s_expr);
c11_vector__dtor(&self->global_names);
c11_smallmap_n2i__dtor(&self->global_names);
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[curr()->type]);
#define consume_end_stmt() \
if(!match_end_stmt()) return SyntaxError("expected statement end")
if(!match_end_stmt(self)) return SyntaxError("expected statement end")
#define check_newlines_repl() \
do { \
bool __nml; \
@ -1471,7 +1471,7 @@ static NameScope name_scope(Compiler* self) {
return s;
}
static Error* SyntaxError(const char* fmt, ...) { return NULL; }
#define SyntaxError(...) NULL
static Error* NeedMoreLines() { return NULL; }
@ -1798,10 +1798,7 @@ static Error* exprName(Compiler* self) {
py_Name name = py_name2(Token__sv(prev()));
NameScope scope = name_scope(self);
// promote this name to global scope if needed
c11_vector* global_names = &ctx()->global_names;
c11__foreach(py_Name, global_names, it) {
if(*it == name) scope = NAME_GLOBAL;
}
if(c11_smallmap_n2i__contains(&ctx()->global_names, name)) { scope = NAME_GLOBAL; }
NameExpr* e = NameExpr__new(prev()->line, name, scope);
Ctx__s_push(ctx(), (Expr*)e);
return NULL;
@ -2005,6 +2002,258 @@ static Error* exprSubscr(Compiler* self) {
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) {
@ -2026,25 +2275,22 @@ Error* Compiler__compile(Compiler* self, CodeObject* out) {
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->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)) {
// check(compile_stmt());
// match_newlines();
// }
// check(pop_context());
while(!match(TK_EOF)) {
check(compile_stmt(self));
match_newlines();
}
check(pop_context(self));
return NULL;
}
@ -2069,6 +2315,8 @@ Error* pk_compile(pk_SourceData_ src, CodeObject* out) {
if(err) {
// if error occurs, dispose the code object
CodeObject__dtor(out);
} else {
assert(out->codes.count);
}
Compiler__dtor(&compiler);
return err;

View File

@ -13,7 +13,6 @@ int NameError(py_Name name) { return -1; }
static bool stack_binaryop(pk_VM* self, py_Name op, py_Name rop);
#define DISPATCH() \
do { \
frame->ip++; \
@ -123,13 +122,13 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
DISPATCH();
/*****************************************/
case OP_LOAD_CONST: PUSH(c11__at(py_TValue, &frame->co->consts, byte.arg)); DISPATCH();
case OP_LOAD_NONE: PUSH(&self->None); DISPATCH();
case OP_LOAD_TRUE: PUSH(&self->True); DISPATCH();
case OP_LOAD_FALSE: PUSH(&self->False); DISPATCH();
case OP_LOAD_NONE: py_newnone(SP()++); DISPATCH();
case OP_LOAD_TRUE: py_newbool(SP()++, true); DISPATCH();
case OP_LOAD_FALSE: py_newbool(SP()++, false); DISPATCH();
/*****************************************/
case OP_LOAD_SMALL_INT: py_newint(SP()++, (int64_t)(int16_t)byte.arg); DISPATCH();
/*****************************************/
case OP_LOAD_ELLIPSIS: PUSH(&self->Ellipsis); DISPATCH();
case OP_LOAD_ELLIPSIS: py_newellipsis(SP()++); DISPATCH();
case OP_LOAD_FUNCTION: {
// FuncDecl_ decl = c11__getitem(FuncDecl_, &frame->co->func_decls, byte.arg);
// py_TValue obj;
@ -512,7 +511,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
bool res = py_isidentical(SECOND(), TOP());
POP();
if(byte.arg) res = !res;
*TOP() = res ? self->True : self->False;
py_newbool(TOP(), res);
DISPATCH();
}
case OP_CONTAINS_OP: {
@ -575,9 +574,9 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
case OP_SHORTCUT_IF_FALSE_OR_POP: {
int res = py_bool(TOP());
if(res < 0) goto __ERROR;
if(!res) { // [b, False]
STACK_SHRINK(2); // []
PUSH(&self->False); // [False]
if(!res) { // [b, False]
STACK_SHRINK(2); // []
py_newbool(SP()++, false); // [False]
DISPATCH_JUMP((int16_t)byte.arg);
} else {
POP(); // [b]
@ -606,7 +605,11 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
// }
/*****************************************/
case OP_RETURN_VALUE: {
self->last_retval = byte.arg == BC_NOARG ? POPX() : self->None;
if(byte.arg == BC_NOARG) {
self->last_retval = POPX();
} else {
py_newnone(&self->last_retval);
}
pk_VM__pop_frame(self);
if(frame == base_frame) { // [ frameBase<- ]
return RES_RETURN;
@ -617,6 +620,31 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
}
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();
}
@ -625,6 +653,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
__ERROR:
// 1. Exception can be handled inside the current 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);
return RES_ERROR;
}

View File

@ -68,7 +68,8 @@ void pk_VM__ctor(pk_VM* self) {
self->_stderr = pk_default_stderr;
self->last_retval = PY_NULL;
self->has_error = false;
self->__curr_class = PY_NULL;
self->__cached_object_new = PY_NULL;
self->__dynamic_func_decl = NULL;
@ -148,7 +149,10 @@ void pk_VM__ctor(pk_VM* self) {
pk_TypeInfo* ti = c11__at(pk_TypeInfo, &self->types, 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*/
pk_VM__init_builtins(self);

View File

@ -0,0 +1,16 @@
#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){
}

View File

@ -2,6 +2,7 @@
#include "pocketpy/pocketpy.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/common/sstream.h"
#include "pocketpy/objects/object.h"
#include "pocketpy/interpreter/vm.h"
#include "pocketpy/compiler/compiler.h"
@ -23,17 +24,145 @@ void py_finalize() {
pk_MemoryPools__finalize();
}
bool py_exec(const char* source) { PK_UNREACHABLE(); }
static void disassemble(CodeObject* co) {
const static char* OP_NAMES[] = {
#define OPCODE(name) #name,
#include "pocketpy/xmacros/opcodes.h"
#undef OPCODE
};
bool py_eval(const char* source) {
c11_vector /*T=int*/ jumpTargets;
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;
pk_SourceData_ src = pk_SourceData__rcnew(source, "main.py", EVAL_MODE, false);
pk_SourceData_ src = pk_SourceData__rcnew(source, filename, mode, false);
Error* err = pk_compile(src, &co);
if(err) {
PK_DECREF(src);
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);
pk_VM__push_frame(vm, frame);
pk_FrameResult res = pk_VM__run_top_frame(vm);
@ -44,6 +173,10 @@ bool py_eval(const char* source) {
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_callmethod(py_Ref self, py_Name name, int argc, py_Ref argv) { return -1; }

View File

@ -25,6 +25,7 @@ int main(int argc, char** argv) {
SetConsoleOutputCP(CP_UTF8);
#endif
#if 0
py_initialize();
const char* source = "1 < 2";
@ -47,20 +48,18 @@ int main(int argc, char** argv) {
py_finalize();
return 0;
#endif
// if(argc != 2) goto __HELP;
// char* source = read_file(argv[1]);
// py_initialize();
if(argc != 2) goto __HELP;
char* source = read_file(argv[1]);
py_initialize();
// if(py_exec(source)){
// py_Error* err = py_getlasterror();
// py_Error__print(err);
// }
if(!py_exec(source)) py_printexc();
// py_finalize();
// free(source);
py_finalize();
free(source);
// __HELP:
// printf("Usage: pocketpy [filename]\n");
// return 0;
__HELP:
printf("Usage: pocketpy [filename]\n");
return 0;
}