This commit is contained in:
blueloveTH 2024-08-10 16:04:50 +08:00
parent 0806b1aee1
commit b51bf33572
15 changed files with 206 additions and 134 deletions

View File

@ -47,8 +47,7 @@ Frame* Frame__new(const CodeObject* co,
py_GlobalRef module, py_GlobalRef module,
py_StackRef p0, py_StackRef p0,
py_StackRef locals, py_StackRef locals,
bool has_function, bool has_function);
bool is_dynamic);
void Frame__delete(Frame* self); void Frame__delete(Frame* self);
int Frame__ip(const Frame* self); int Frame__ip(const Frame* self);

View File

@ -97,6 +97,8 @@ bool pk_arraycontains(py_Ref self, py_Ref val);
bool pk_loadmethod(py_StackRef self, py_Name name); bool pk_loadmethod(py_StackRef self, py_Name name);
bool pk_callmagic(py_Name name, int argc, py_Ref argv); bool pk_callmagic(py_Name name, int argc, py_Ref argv);
bool pk_exec(CodeObject* co, py_Ref module);
/// 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.
@ -129,6 +131,7 @@ py_Type pk_classmethod__register();
py_Type pk_generator__register(); py_Type pk_generator__register();
py_Type pk_namedict__register(); py_Type pk_namedict__register();
py_Type pk_locals__register(); py_Type pk_locals__register();
py_Type pk_code__register();
py_TValue pk_builtins__register(); py_TValue pk_builtins__register();

View File

@ -45,7 +45,7 @@ typedef py_TValue* py_TmpRef;
/// @return true if the function is successful. /// @return true if the function is successful.
typedef bool (*py_CFunction)(int argc, py_StackRef argv) PY_RAISE; typedef bool (*py_CFunction)(int argc, py_StackRef argv) PY_RAISE;
enum py_CompileMode { EXEC_MODE, EVAL_MODE, REPL_MODE, CELL_MODE }; enum py_CompileMode { EXEC_MODE, EVAL_MODE, SINGLE_MODE };
extern py_GlobalRef py_True; extern py_GlobalRef py_True;
extern py_GlobalRef py_False; extern py_GlobalRef py_False;
@ -75,14 +75,16 @@ bool py_exec(const char* source,
enum py_CompileMode mode, enum py_CompileMode mode,
py_Ref module) PY_RAISE; py_Ref module) PY_RAISE;
/// Run a source string in dynamic mode. bool py_compile(const char* source,
/// Assume `globals()` and `locals()` are pushed to the stack.
/// After the execution, the result will be set to `py_retval()`.
/// The stack size will be reduced by 2.
bool py_execdyn(const char* source,
const char* filename, const char* filename,
enum py_CompileMode mode, enum py_CompileMode mode,
py_Ref module) PY_RAISE; bool is_dynamic) PY_RAISE;
/// Python equivalent to `globals()`.
void py_newglobals(py_Ref);
/// Python equivalent to `locals()`.
/// NOTE: Return a temporary object, which expires on the associated function return.
void py_newlocals(py_Ref);
/************* Values Creation *************/ /************* Values Creation *************/
@ -343,6 +345,8 @@ py_StackRef py_peek(int i);
void py_push(py_Ref src); void py_push(py_Ref src);
/// Push a `nil` object to the stack. /// Push a `nil` object to the stack.
void py_pushnil(); void py_pushnil();
/// Push a `None` object to the stack.
void py_pushnone();
/// Pop an object from the stack. /// Pop an object from the stack.
void py_pop(); void py_pop();
/// Shrink the stack by n. /// Shrink the stack by n.
@ -531,6 +535,7 @@ enum py_PredefinedTypes {
tp_bytes, tp_bytes,
tp_namedict, tp_namedict,
tp_locals, tp_locals,
tp_code,
tp_dict, tp_dict,
tp_dict_items, // 1 slot tp_dict_items, // 1 slot
tp_property, // 2 slots (getter + setter) tp_property, // 2 slots (getter + setter)

View File

@ -629,17 +629,7 @@ static bool is_fmt_valid_char(char c) {
} }
} }
static bool is_identifier(c11_sv s) { static void _load_expr(Ctx* ctx, c11_sv expr, int line) {
if(s.size == 0) return false;
if(!isalpha(s.data[0]) && s.data[0] != '_') return false;
for(int i = 0; i < s.size; i++) {
char c = s.data[i];
if(!isalnum(c) && c != '_') return false;
}
return true;
}
static void _load_simple_expr(Ctx* ctx, c11_sv expr, int line) {
bool repr = false; bool repr = false;
const char* expr_end = expr.data + expr.size; const char* expr_end = expr.data + expr.size;
if(expr.size >= 2 && expr_end[-2] == '!') { if(expr.size >= 2 && expr_end[-2] == '!') {
@ -655,30 +645,18 @@ static void _load_simple_expr(Ctx* ctx, c11_sv expr, int line) {
default: break; // nothing happens default: break; // nothing happens
} }
} }
// name or name.name
bool is_fastpath = false;
if(is_identifier(expr)) {
Ctx__emit_(ctx, OP_LOAD_NAME, py_namev(expr), line);
is_fastpath = true;
} else {
int dot = c11_sv__index(expr, '.');
if(dot > 0) {
c11_sv a = {expr.data, dot}; // expr[:dot]
c11_sv b = {expr.data + (dot + 1), expr.size - (dot + 1)}; // expr[dot+1:]
if(is_identifier(a) && is_identifier(b)) {
Ctx__emit_(ctx, OP_LOAD_NAME, py_namev(a), line);
Ctx__emit_(ctx, OP_LOAD_ATTR, py_namev(b), line);
is_fastpath = true;
}
}
}
if(!is_fastpath) { c11_string* source = c11_string__new2(expr.data, expr.size);
int index = Ctx__add_const_string(ctx, expr); bool ok = py_compile(source->data, "<f-string>", EVAL_MODE, false);
if(!ok){
py_printexc();
c11__abort("f-string: invalid expression");
}
int index = Ctx__add_const(ctx, py_retval());
c11_string__delete(source);
Ctx__emit_(ctx, OP_FSTRING_EVAL, index, line); Ctx__emit_(ctx, OP_FSTRING_EVAL, index, line);
}
if(repr) { Ctx__emit_(ctx, OP_REPR, BC_NOARG, line); } if(repr) Ctx__emit_(ctx, OP_REPR, BC_NOARG, line);
} }
static void FStringExpr__emit_(Expr* self_, Ctx* ctx) { static void FStringExpr__emit_(Expr* self_, Ctx* ctx) {
@ -710,18 +688,17 @@ static void FStringExpr__emit_(Expr* self_, Ctx* ctx) {
} }
if(ok) { if(ok) {
expr.size = conon; // expr[:conon] expr.size = conon; // expr[:conon]
_load_simple_expr(ctx, expr, self->line); _load_expr(ctx, expr, self->line);
// ctx->emit_(OP_FORMAT_STRING, ctx->add_const_string(spec.sv()), line);
Ctx__emit_(ctx, Ctx__emit_(ctx,
OP_FORMAT_STRING, OP_FORMAT_STRING,
Ctx__add_const_string(ctx, spec), Ctx__add_const_string(ctx, spec),
self->line); self->line);
} else { } else {
// ':' is not a spec indicator // ':' is not a spec indicator
_load_simple_expr(ctx, expr, self->line); _load_expr(ctx, expr, self->line);
} }
} else { } else {
_load_simple_expr(ctx, expr, self->line); _load_expr(ctx, expr, self->line);
} }
flag = false; flag = false;
count++; count++;
@ -2743,8 +2720,7 @@ static Error* compile_stmt(Compiler* self) {
} }
if(!is_typed_name) { if(!is_typed_name) {
Ctx__s_emit_top(ctx()); Ctx__s_emit_top(ctx());
if((mode() == CELL_MODE || mode() == REPL_MODE) && if((mode() == SINGLE_MODE) && name_scope(self) == NAME_GLOBAL) {
name_scope(self) == NAME_GLOBAL) {
Ctx__emit_(ctx(), OP_PRINT_EXPR, BC_NOARG, BC_KEEPLINE); Ctx__emit_(ctx(), OP_PRINT_EXPR, BC_NOARG, BC_KEEPLINE);
} else { } else {
Ctx__emit_(ctx(), OP_POP_TOP, BC_NOARG, BC_KEEPLINE); Ctx__emit_(ctx(), OP_POP_TOP, BC_NOARG, BC_KEEPLINE);

View File

@ -186,6 +186,7 @@ FrameResult VM__run_top_frame(VM* self) {
} else { } else {
py_newstr(SP()++, py_name2str(name)); py_newstr(SP()++, py_name2str(name));
// locals // locals
if(!py_isnone(&frame->p0[1])) {
if(py_getitem(&frame->p0[1], TOP())) { if(py_getitem(&frame->p0[1], TOP())) {
py_assign(TOP(), py_retval()); py_assign(TOP(), py_retval());
DISPATCH(); DISPATCH();
@ -196,11 +197,6 @@ FrameResult VM__run_top_frame(VM* self) {
goto __ERROR; goto __ERROR;
} }
} }
// closure
tmp = Frame__f_closure_try_get(frame, name);
if(tmp != NULL) {
py_assign(TOP(), tmp);
DISPATCH();
} }
// globals // globals
if(py_getitem(&frame->p0[0], TOP())) { if(py_getitem(&frame->p0[0], TOP())) {
@ -1032,9 +1028,8 @@ FrameResult VM__run_top_frame(VM* self) {
////////////////// //////////////////
case OP_FSTRING_EVAL: { case OP_FSTRING_EVAL: {
py_TValue* tmp = c11__at(py_TValue, &frame->co->consts, byte.arg); py_TValue* tmp = c11__at(py_TValue, &frame->co->consts, byte.arg);
const char* string = py_tostr(tmp); assert(py_istype(tmp, tp_code));
// TODO: optimize this if(!pk_exec(py_touserdata(tmp), frame->module)) goto __ERROR;
if(!py_exec(string, "<f-string>", EVAL_MODE, frame->module)) goto __ERROR;
PUSH(py_retval()); PUSH(py_retval());
DISPATCH(); DISPATCH();
} }

View File

@ -41,8 +41,7 @@ Frame* Frame__new(const CodeObject* co,
py_GlobalRef module, py_GlobalRef module,
py_StackRef p0, py_StackRef p0,
py_StackRef locals, py_StackRef locals,
bool has_function, bool has_function) {
bool is_dynamic) {
static_assert(sizeof(Frame) <= kPoolFrameBlockSize, "!(sizeof(Frame) <= kPoolFrameBlockSize)"); static_assert(sizeof(Frame) <= kPoolFrameBlockSize, "!(sizeof(Frame) <= kPoolFrameBlockSize)");
Frame* self = PoolFrame_alloc(); Frame* self = PoolFrame_alloc();
self->f_back = NULL; self->f_back = NULL;
@ -52,7 +51,7 @@ Frame* Frame__new(const CodeObject* co,
self->p0 = p0; self->p0 = p0;
self->locals = locals; self->locals = locals;
self->has_function = has_function; self->has_function = has_function;
self->is_dynamic = is_dynamic; self->is_dynamic = co->src->is_dynamic;
self->uw_list = NULL; self->uw_list = NULL;
return self; return self;
} }

View File

@ -115,6 +115,7 @@ void VM__ctor(VM* self) {
validate(tp_bytes, pk_bytes__register()); validate(tp_bytes, pk_bytes__register());
validate(tp_namedict, pk_namedict__register()); validate(tp_namedict, pk_namedict__register());
validate(tp_locals, pk_locals__register()); validate(tp_locals, pk_locals__register());
validate(tp_code, pk_code__register());
validate(tp_dict, pk_dict__register()); validate(tp_dict, pk_dict__register());
validate(tp_dict_items, pk_dict_items__register()); validate(tp_dict_items, pk_dict_items__register());
@ -435,7 +436,7 @@ FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall
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) {
VM__push_frame(self, Frame__new(co, &fn->module, p0, argv, true, false)); VM__push_frame(self, Frame__new(co, &fn->module, p0, argv, true));
return opcall ? RES_CALL : VM__run_top_frame(self); return opcall ? RES_CALL : VM__run_top_frame(self);
} else { } else {
bool ok = py_callcfunc(fn->cfunc, co->nlocals, argv); bool ok = py_callcfunc(fn->cfunc, co->nlocals, argv);
@ -459,12 +460,12 @@ FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall
// 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
VM__push_frame(self, Frame__new(co, &fn->module, p0, argv, true, false)); VM__push_frame(self, Frame__new(co, &fn->module, p0, argv, true));
return opcall ? RES_CALL : VM__run_top_frame(self); return opcall ? RES_CALL : VM__run_top_frame(self);
case FuncType_GENERATOR: { case FuncType_GENERATOR: {
bool ok = prepare_py_call(self->__vectorcall_buffer, argv, p1, kwargc, fn->decl); bool ok = prepare_py_call(self->__vectorcall_buffer, argv, p1, kwargc, fn->decl);
if(!ok) return RES_ERROR; if(!ok) return RES_ERROR;
Frame* frame = Frame__new(co, &fn->module, p0, argv, false, false); Frame* frame = Frame__new(co, &fn->module, p0, argv, false);
pk_newgenerator(py_retval(), frame, self->__vectorcall_buffer, co->nlocals); pk_newgenerator(py_retval(), frame, self->__vectorcall_buffer, co->nlocals);
self->stack.sp = p0; self->stack.sp = p0;
return RES_RETURN; return RES_RETURN;

View File

@ -113,9 +113,17 @@ static void disassemble(CodeObject* co) {
static bool dis_dis(int argc, py_Ref argv) { static bool dis_dis(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_function);
CodeObject* code = NULL;
if(py_istype(argv, tp_function)){
Function* ud = py_touserdata(argv); Function* ud = py_touserdata(argv);
disassemble(&ud->decl->code); code = &ud->decl->code;
}else if(py_istype(argv, tp_code)){
code = py_touserdata(argv);
}else{
return TypeError("dis() expected a code object");
}
disassemble(code);
py_newnone(py_retval()); py_newnone(py_retval());
return true; return true;
} }

View File

@ -19,7 +19,7 @@ bool py_castfloat(py_Ref self, double* out) {
switch(self->type) { switch(self->type) {
case tp_int: *out = (double)self->_i64; return true; case tp_int: *out = (double)self->_i64; return true;
case tp_float: *out = self->_f64; return true; case tp_float: *out = self->_f64; return true;
default: return TypeError("expected int or float, got %t", self->type); default: return TypeError("expected 'int' or 'float', got '%t'", self->type);
} }
} }
@ -43,7 +43,7 @@ bool py_istype(py_Ref self, py_Type type) { return self->type == type; }
bool py_checktype(py_Ref self, py_Type type) { bool py_checktype(py_Ref self, py_Type type) {
if(self->type == type) return true; if(self->type == type) return true;
return TypeError("expected %t, got %t", type, self->type); return TypeError("expected '%t', got '%t'", type, self->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); }

View File

@ -8,15 +8,22 @@
#include "pocketpy/interpreter/vm.h" #include "pocketpy/interpreter/vm.h"
#include "pocketpy/compiler/compiler.h" #include "pocketpy/compiler/compiler.h"
static bool _py_exec(const char* source, static void code__gc_mark(void* ud) { CodeObject__gc_mark(ud); }
py_Type pk_code__register() {
py_Type type = pk_newtype("code", tp_object, NULL, (py_Dtor)CodeObject__dtor, false, true);
pk__tp_set_marker(type, code__gc_mark);
return type;
}
bool _py_compile(CodeObject* out,
const char* source,
const char* filename, const char* filename,
enum py_CompileMode mode, enum py_CompileMode mode,
py_Ref module,
bool is_dynamic) { bool is_dynamic) {
VM* vm = pk_current_vm; VM* vm = pk_current_vm;
CodeObject co;
SourceData_ src = SourceData__rcnew(source, filename, mode, is_dynamic); SourceData_ src = SourceData__rcnew(source, filename, mode, is_dynamic);
Error* err = pk_compile(src, &co); Error* err = pk_compile(src, out);
if(err) { if(err) {
py_exception(tp_SyntaxError, err->msg); py_exception(tp_SyntaxError, err->msg);
py_BaseException__stpush(&vm->curr_exception, err->src, err->lineno, NULL); py_BaseException__stpush(&vm->curr_exception, err->src, err->lineno, NULL);
@ -26,29 +33,44 @@ static bool _py_exec(const char* source,
free(err); free(err);
return false; return false;
} }
PK_DECREF(src);
if(!module) module = &vm->main; return true;
py_StackRef sp = vm->stack.sp;
if(is_dynamic) {
// [globals, locals]
sp -= 2;
} }
Frame* frame = Frame__new(&co, module, sp, sp, false, is_dynamic); bool py_compile(const char* source,
const char* filename,
enum py_CompileMode mode,
bool is_dynamic) {
CodeObject co;
bool ok = _py_compile(&co, source, filename, mode, is_dynamic);
if(ok) {
// compile success
CodeObject* ud = py_newobject(py_retval(), tp_code, 0, sizeof(CodeObject));
*ud = co;
}
return ok;
}
bool pk_exec(CodeObject* co, py_Ref module) {
VM* vm = pk_current_vm;
if(!module) module = &vm->main;
assert(module->type == tp_module);
py_StackRef sp = vm->stack.sp;
if(co->src->is_dynamic) sp -= 3; // [globals, locals, code]
Frame* frame = Frame__new(co, module, sp, sp, false);
VM__push_frame(vm, frame); VM__push_frame(vm, frame);
FrameResult res = VM__run_top_frame(vm); FrameResult res = VM__run_top_frame(vm);
CodeObject__dtor(&co);
PK_DECREF(src);
if(res == RES_ERROR) return false; if(res == RES_ERROR) return false;
if(res == RES_RETURN) return true; if(res == RES_RETURN) return true;
c11__unreachedable(); c11__unreachedable();
} }
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) {
return _py_exec(source, filename, mode, module, false); CodeObject co;
} if(!_py_compile(&co, source, filename, mode, false)) return false;
bool ok = pk_exec(&co, module);
bool py_execdyn(const char* source, const char* filename, enum py_CompileMode mode, py_Ref module) { CodeObject__dtor(&co);
return _py_exec(source, filename, mode, module, true); return ok;
} }

View File

@ -388,64 +388,118 @@ static bool builtins_ord(int argc, py_Ref argv) {
static bool builtins_globals(int argc, py_Ref argv) { static bool builtins_globals(int argc, py_Ref argv) {
PY_CHECK_ARGC(0); PY_CHECK_ARGC(0);
Frame* frame = pk_current_vm->top_frame; py_newglobals(py_retval());
if(frame->is_dynamic) {
py_assign(py_retval(), &frame->p0[0]);
return true;
}
pk_mappingproxy__namedict(py_retval(), frame->module);
return true; return true;
} }
static bool builtins_locals(int argc, py_Ref argv) { static bool builtins_locals(int argc, py_Ref argv) {
PY_CHECK_ARGC(0); PY_CHECK_ARGC(0);
Frame* frame = pk_current_vm->top_frame; py_newlocals(py_retval());
if(frame->is_dynamic) {
py_assign(py_retval(), &frame->p0[1]);
return true;
}
if(!frame->has_function) return builtins_globals(argc, argv);
pk_mappingproxy__locals(py_retval(), frame);
return true; return true;
} }
static bool _builtins_execdyn(const char* title, int argc, py_Ref argv, enum py_CompileMode mode) { void py_newglobals(py_Ref out) {
PY_CHECK_ARG_TYPE(0, tp_str);
Frame* frame = pk_current_vm->top_frame; Frame* frame = pk_current_vm->top_frame;
if(frame->is_dynamic) {
py_assign(out, &frame->p0[0]);
} else {
pk_mappingproxy__namedict(out, frame->module);
}
}
void py_newlocals(py_Ref out) {
Frame* frame = pk_current_vm->top_frame;
if(frame->is_dynamic) {
py_assign(out, &frame->p0[1]);
return;
}
if(frame->has_function) {
pk_mappingproxy__locals(out, frame);
} else {
py_newglobals(out);
}
}
static bool _builtins_execdyn(const char* title, int argc, py_Ref argv, enum py_CompileMode mode) {
switch(argc) { switch(argc) {
case 1: { case 1: {
// system globals + system locals py_newglobals(py_pushtmp());
if(!builtins_globals(0, NULL)) return false; py_newlocals(py_pushtmp());
py_push(py_retval());
if(!builtins_locals(0, NULL)) return false;
py_push(py_retval());
break; break;
} }
case 2: { case 2: {
// user globals + user globals if(py_isnone(py_arg(1))) {
py_push(py_arg(1)); py_newglobals(py_pushtmp());
} else {
py_push(py_arg(1)); py_push(py_arg(1));
}
py_pushnone();
break; break;
} }
case 3: { case 3: {
// user globals + user locals if(py_isnone(py_arg(1))) {
py_newglobals(py_pushtmp());
} else {
py_push(py_arg(1)); py_push(py_arg(1));
}
py_push(py_arg(2)); py_push(py_arg(2));
break; break;
} }
default: return TypeError("%s() takes at most 3 arguments", title); default: return TypeError("%s() takes at most 3 arguments", title);
} }
return py_execdyn(py_tostr(argv), "<string>", mode, frame->module);
py_Ref code;
if(py_isstr(argv)) {
bool ok = py_compile(py_tostr(argv), "<string>", mode, true);
if(!ok) return false;
code = py_retval();
} else if(py_istype(argv, tp_code)) {
code = argv;
} else {
return TypeError("%s() expected 'str' or 'code', got '%t'", title, argv->type);
}
py_push(code); // keep it alive
// [globals, locals, code]
CodeObject* co = py_touserdata(code);
if(!co->src->is_dynamic) py_shrink(3);
Frame* frame = pk_current_vm->top_frame;
return pk_exec(co, frame ? frame->module : NULL);
} }
static bool builtins_exec(int argc, py_Ref argv) { static bool builtins_exec(int argc, py_Ref argv) {
return _builtins_execdyn("exec", argc, argv, EXEC_MODE); bool ok = _builtins_execdyn("exec", argc, argv, EXEC_MODE);
py_newnone(py_retval());
return ok;
} }
static bool builtins_eval(int argc, py_Ref argv) { static bool builtins_eval(int argc, py_Ref argv) {
return _builtins_execdyn("eval", argc, argv, EVAL_MODE); return _builtins_execdyn("eval", argc, argv, EVAL_MODE);
} }
static bool builtins_compile(int argc, py_Ref argv) {
PY_CHECK_ARGC(3);
for(int i = 0; i < 3; i++) {
if(!py_checktype(py_arg(i), tp_str)) return false;
}
const char* source = py_tostr(py_arg(0));
const char* filename = py_tostr(py_arg(1));
const char* mode = py_tostr(py_arg(2));
enum py_CompileMode compile_mode;
if(strcmp(mode, "exec") == 0) {
compile_mode = EXEC_MODE;
} else if(strcmp(mode, "eval") == 0) {
compile_mode = EVAL_MODE;
} else if(strcmp(mode, "single") == 0) {
compile_mode = SINGLE_MODE;
} else {
return ValueError("compile() mode must be 'exec', 'eval', or 'single'");
}
return py_compile(source, filename, compile_mode, true);
}
static bool NoneType__repr__(int argc, py_Ref argv) { static bool NoneType__repr__(int argc, py_Ref argv) {
py_newstr(py_retval(), "None"); py_newstr(py_retval(), "None");
return true; return true;
@ -491,6 +545,7 @@ py_TValue pk_builtins__register() {
py_bindfunc(builtins, "locals", builtins_locals); py_bindfunc(builtins, "locals", builtins_locals);
py_bindfunc(builtins, "exec", builtins_exec); py_bindfunc(builtins, "exec", builtins_exec);
py_bindfunc(builtins, "eval", builtins_eval); py_bindfunc(builtins, "eval", builtins_eval);
py_bindfunc(builtins, "compile", builtins_compile);
// some patches // some patches
py_bindmagic(tp_NoneType, __repr__, NoneType__repr__); py_bindmagic(tp_NoneType, __repr__, NoneType__repr__);
@ -502,9 +557,7 @@ py_TValue pk_builtins__register() {
static bool function__closure__getter(int argc, py_Ref argv) { static bool function__closure__getter(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
Function* ud = py_touserdata(argv); Function* ud = py_touserdata(argv);
if(!ud->closure) { if(!ud->closure) { py_newnone(py_retval()); }
py_newnone(py_retval());
}
py_Ref r0 = py_pushtmp(); py_Ref r0 = py_pushtmp();
py_Ref retval = py_pushtmp(); py_Ref retval = py_pushtmp();
py_newdict(retval); py_newdict(retval);

View File

@ -7,9 +7,9 @@
void pk_mappingproxy__namedict(py_Ref out, py_Ref object){ void pk_mappingproxy__namedict(py_Ref out, py_Ref object){
py_newobject(py_retval(), tp_namedict, 1, 0); py_newobject(out, tp_namedict, 1, 0);
assert(object->is_ptr && object->_obj->slots == -1); assert(object->is_ptr && object->_obj->slots == -1);
py_setslot(py_retval(), 0, object); py_setslot(out, 0, object);
} }
static bool namedict__getitem__(int argc, py_Ref argv){ static bool namedict__getitem__(int argc, py_Ref argv){
@ -63,7 +63,7 @@ py_Type pk_namedict__register() {
void pk_mappingproxy__locals(py_Ref out, Frame* frame){ void pk_mappingproxy__locals(py_Ref out, Frame* frame){
assert(frame->has_function && !frame->is_dynamic); assert(frame->has_function && !frame->is_dynamic);
Frame** ud = py_newobject(py_retval(), tp_locals, 0, sizeof(Frame*)); Frame** ud = py_newobject(out, tp_locals, 0, sizeof(Frame*));
*ud = frame; *ud = frame;
} }

View File

@ -92,6 +92,11 @@ void py_pushnil() {
py_newnil(vm->stack.sp++); py_newnil(vm->stack.sp++);
} }
void py_pushnone() {
VM* vm = pk_current_vm;
py_newnone(vm->stack.sp++);
}
py_Ref py_pushtmp() { py_Ref py_pushtmp() {
VM* vm = pk_current_vm; VM* vm = pk_current_vm;
py_newnil(vm->stack.sp++); py_newnil(vm->stack.sp++);

View File

@ -49,7 +49,11 @@ int main(int argc, char** argv) {
int size = py_replinput(buf, sizeof(buf)); int size = py_replinput(buf, sizeof(buf));
assert(size < sizeof(buf)); assert(size < sizeof(buf));
if(size >= 0) { if(size >= 0) {
if(!py_exec(buf, "<stdin>", REPL_MODE, NULL)) py_printexc(); py_StackRef p0 = py_peek(0);
if(!py_exec(buf, "<stdin>", SINGLE_MODE, NULL)) {
py_printexc();
py_clearexc(p0);
}
} }
} }
} else { } else {

View File

@ -43,6 +43,8 @@ assert (res==1), res
# test locals and globals # test locals and globals
assert eval('a', {'a': 2}) == 2
globals = {'a': 1} globals = {'a': 1}
locals = {'a': 1} locals = {'a': 1}