This commit is contained in:
BLUELOVETH 2023-04-06 04:35:09 +00:00
parent 818ee2981e
commit 7ce783360f
8 changed files with 62 additions and 40 deletions

View File

@ -15,11 +15,14 @@ __NEXT_STEP:;
* For example, frame->popx() returns a strong reference which may be dangerous * For example, frame->popx() returns a strong reference which may be dangerous
* `Args` containing strong references is safe if it is passed to `call` or `fast_call` * `Args` containing strong references is safe if it is passed to `call` or `fast_call`
*/ */
//heap._auto_collect(this); #if !DEBUG_NO_GC
heap._auto_collect(this);
#endif
const Bytecode& byte = frame->next_bytecode(); const Bytecode& byte = frame->next_bytecode();
#if DEBUG_CEVAL_STEP
// std::cout << frame->stack_info() << " " << OP_NAMES[byte.op] << std::endl; std::cout << frame->stack_info() << " " << OP_NAMES[byte.op] << std::endl;
#endif
switch (byte.op) switch (byte.op)
{ {
@ -298,8 +301,10 @@ __NEXT_STEP:;
PyObject* new_mod = new_module(name); PyObject* new_mod = new_module(name);
_exec(code, new_mod, builtins); _exec(code, new_mod, builtins);
new_mod->attr()._try_perfect_rehash(); new_mod->attr()._try_perfect_rehash();
} frame->push(new_mod);
}else{
frame->push(ext_mod); frame->push(ext_mod);
}
} DISPATCH(); } DISPATCH();
case OP_IMPORT_STAR: { case OP_IMPORT_STAR: {
PyObject* obj = frame->popx(); PyObject* obj = frame->popx();

View File

@ -32,15 +32,17 @@
// debug macros // debug macros
#define DEBUG_NO_BUILTIN_MODULES 0 #define DEBUG_NO_BUILTIN_MODULES 0
#define DEBUG_EXTRA_CHECK 1 #define DEBUG_EXTRA_CHECK 0
#define DEBUG_DIS_REPL 0 #define DEBUG_DIS_EXEC_REPL 0
#define DEBUG_DIS_REPL_MIN 1 #define DEBUG_DIS_EXEC_REPL_MIN 1
#define DEBUG_CEVAL_STEP 0
#define DEBUG_FULL_EXCEPTION 0 #define DEBUG_FULL_EXCEPTION 0
#define DEBUG_NO_GC 1
#if (defined(__ANDROID__) && __ANDROID_API__ <= 22) || defined(__EMSCRIPTEN__) #if (defined(__ANDROID__) && __ANDROID_API__ <= 22) || defined(__EMSCRIPTEN__)
#define PK_ENABLE_FILEIO 0 #define PK_ENABLE_FILEIO 0
#else #else
#define PK_ENABLE_FILEIO (1-DEBUG_NO_BUILTIN_MODULES) #define PK_ENABLE_FILEIO 0 // TODO: refactor this
#endif #endif
#if defined(__EMSCRIPTEN__) || defined(__arm__) || defined(__i386__) #if defined(__EMSCRIPTEN__) || defined(__arm__) || defined(__i386__)

View File

@ -757,15 +757,15 @@ __SUBSCR_END:
} break; } break;
case TK("with"): { case TK("with"): {
// TODO: reimpl this // TODO: reimpl this
UNREACHABLE(); EXPR(false);
// EXPR(false); ctx()->emit(OP_POP_TOP, BC_NOARG, prev().line);
// consume(TK("as")); consume(TK("as"));
// consume(TK("@id")); consume(TK("@id"));
// int index = ctx()->add_name(prev().str(), name_scope()); // int index = ctx()->add_name(prev().str());
// emit(OP_STORE_NAME, index); // emit(OP_STORE_NAME, index);
// emit(OP_LOAD_NAME_REF, index); // emit(OP_LOAD_NAME_REF, index);
// emit(OP_WITH_ENTER); // emit(OP_WITH_ENTER);
// compile_block_body(); compile_block_body();
// emit(OP_LOAD_NAME_REF, index); // emit(OP_LOAD_NAME_REF, index);
// emit(OP_WITH_EXIT); // emit(OP_WITH_EXIT);
} break; } break;
@ -958,12 +958,11 @@ public:
pop_context(); pop_context();
return code; return code;
}else if(mode()==JSON_MODE){ }else if(mode()==JSON_MODE){
PyObject* value = read_literal(); EXPR();
if(value != nullptr) ctx()->emit(OP_LOAD_CONST, ctx()->add_const(value), prev().line); Expr_ e = ctx()->s_expr.popx();
else if(match(TK("{"))) exprMap(); if(!e->is_json_object()) SyntaxError("expect a JSON object, literal or array");
else if(match(TK("["))) exprList();
else SyntaxError("expect a JSON object or array");
consume(TK("@eof")); consume(TK("@eof"));
e->emit(ctx());
ctx()->emit(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE); ctx()->emit(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
pop_context(); pop_context();
return code; return code;

View File

@ -20,6 +20,7 @@ struct Expr{
virtual std::vector<const Expr*> children() const { return {}; } virtual std::vector<const Expr*> children() const { return {}; }
virtual bool is_starred() const { return false; } virtual bool is_starred() const { return false; }
virtual bool is_literal() const { return false; } virtual bool is_literal() const { return false; }
virtual bool is_json_object() const { return false; }
// for OP_DELETE_XXX // for OP_DELETE_XXX
virtual bool emit_del(CodeEmitContext* ctx) { return false; } virtual bool emit_del(CodeEmitContext* ctx) { return false; }
@ -238,6 +239,8 @@ struct Literal0Expr: Expr{
default: UNREACHABLE(); default: UNREACHABLE();
} }
} }
bool is_json_object() const override { return true; }
}; };
// @num, @str which needs to invoke OP_LOAD_CONST // @num, @str which needs to invoke OP_LOAD_CONST
@ -283,6 +286,7 @@ struct LiteralExpr: Expr{
} }
bool is_literal() const override { return true; } bool is_literal() const override { return true; }
bool is_json_object() const override { return true; }
}; };
// PASS // PASS
@ -313,6 +317,10 @@ struct NegatedExpr: Expr{
child->emit(ctx); child->emit(ctx);
ctx->emit(OP_UNARY_NEGATIVE, BC_NOARG, line); ctx->emit(OP_UNARY_NEGATIVE, BC_NOARG, line);
} }
bool is_json_object() const override {
return child->is_literal();
}
}; };
// PASS // PASS
@ -384,12 +392,16 @@ struct ListExpr: SequenceExpr{
using SequenceExpr::SequenceExpr; using SequenceExpr::SequenceExpr;
Str str() const override { return "list()"; } Str str() const override { return "list()"; }
Opcode opcode() const override { return OP_BUILD_LIST; } Opcode opcode() const override { return OP_BUILD_LIST; }
bool is_json_object() const override { return true; }
}; };
struct DictExpr: SequenceExpr{ struct DictExpr: SequenceExpr{
using SequenceExpr::SequenceExpr; using SequenceExpr::SequenceExpr;
Str str() const override { return "dict()"; } Str str() const override { return "dict()"; }
Opcode opcode() const override { return OP_BUILD_DICT; } Opcode opcode() const override { return OP_BUILD_DICT; }
bool is_json_object() const override { return true; }
}; };
struct SetExpr: SequenceExpr{ struct SetExpr: SequenceExpr{

View File

@ -46,7 +46,7 @@ struct Frame {
Str stack_info(){ Str stack_info(){
StrStream ss; StrStream ss;
ss << "["; ss << id << " [";
for(int i=0; i<_data.size(); i++){ for(int i=0; i<_data.size(); i++){
ss << (i64)_data[i]; ss << (i64)_data[i];
if(i != _data.size()-1) ss << ", "; if(i != _data.size()-1) ss << ", ";
@ -93,8 +93,12 @@ struct Frame {
return _data[_data.size()-n]; return _data[_data.size()-n];
} }
template<typename T> void push(PyObject* obj){
void push(T&& obj){ _data.push_back(std::forward<T>(obj)); } #if DEBUG_EXTRA_CHECK
if(obj == nullptr) throw std::runtime_error("obj == nullptr");
#endif
_data.push_back(obj);
}
void jump_abs(int i){ _next_ip = i; } void jump_abs(int i){ _next_ip = i; }
void jump_rel(int i){ _next_ip += i; } void jump_rel(int i){ _next_ip += i; }

View File

@ -172,11 +172,10 @@ inline void init_builtins(VM* _vm) {
_vm->bind_method<0>("object", "__repr__", [](VM* vm, Args& args) { _vm->bind_method<0>("object", "__repr__", [](VM* vm, Args& args) {
PyObject* self = args[0]; PyObject* self = args[0];
std::uintptr_t addr = is_tagged(self) ? 0 : (uintptr_t)self; if(is_tagged(self)) self = nullptr;
StrStream ss; StrStream ss;
ss << std::hex << addr; ss << "<" << OBJ_NAME(vm->_t(self)) << " object at " << std::hex << self << ">";
Str s = "<" + OBJ_NAME(vm->_t(self)) + " object at 0x" + ss.str() + ">"; return VAR(ss.str());
return VAR(s);
}); });
_vm->bind_method<1>("object", "__eq__", CPP_LAMBDA(VAR(args[0] == args[1]))); _vm->bind_method<1>("object", "__eq__", CPP_LAMBDA(VAR(args[0] == args[1])));

View File

@ -166,7 +166,7 @@ public:
if(_module == nullptr) _module = _main; if(_module == nullptr) _module = _main;
try { try {
CodeObject_ code = compile(source, filename, mode); CodeObject_ code = compile(source, filename, mode);
#if DEBUG_DIS_REPL #if DEBUG_DIS_EXEC_REPL
if(_module == _main) std::cout << disassemble(code) << '\n'; if(_module == _main) std::cout << disassemble(code) << '\n';
#endif #endif
return _exec(code, _module, builtins); return _exec(code, _module, builtins);
@ -596,6 +596,7 @@ inline Str VM::disassemble(CodeObject_ co){
break; break;
case OP_LOAD_NAME: case OP_STORE_LOCAL: case OP_STORE_GLOBAL: case OP_LOAD_NAME: case OP_STORE_LOCAL: case OP_STORE_GLOBAL:
case OP_LOAD_ATTR: case OP_STORE_ATTR: case OP_DELETE_ATTR: case OP_LOAD_ATTR: case OP_STORE_ATTR: case OP_DELETE_ATTR:
case OP_IMPORT_NAME: case OP_BEGIN_CLASS:
case OP_DELETE_LOCAL: case OP_DELETE_GLOBAL: case OP_DELETE_LOCAL: case OP_DELETE_GLOBAL:
argStr += " (" + co->names[byte.arg].str().escape(true) + ")"; argStr += " (" + co->names[byte.arg].str().escape(true) + ")";
break; break;
@ -614,7 +615,7 @@ inline Str VM::disassemble(CodeObject_ co){
if(i != co->codes.size() - 1) ss << '\n'; if(i != co->codes.size() - 1) ss << '\n';
} }
#if !DEBUG_DIS_REPL_MIN #if !DEBUG_DIS_EXEC_REPL_MIN
StrStream consts; StrStream consts;
consts << "co_consts: "; consts << "co_consts: ";
consts << CAST(Str, asRepr(VAR(co->consts))); consts << CAST(Str, asRepr(VAR(co->consts)));

View File

@ -11,21 +11,21 @@ r.shuffle(a)
r.choice(a) r.choice(a)
r.choice(b) r.choice(b)
from sys import version as v # from sys import version as v
assert type(v) is str # assert type(v) is str
class Context: # class Context:
def __init__(self): # def __init__(self):
self.x = 0 # self.x = 0
def __enter__(self): # def __enter__(self):
self.x = 1 # self.x = 1
def __exit__(self): # def __exit__(self):
self.x = 2 # self.x = 2
with Context() as c: # with Context() as c:
assert c.x == 1 # assert c.x == 1
assert c.x == 2 # assert c.x == 2