This commit is contained in:
blueloveTH 2023-04-02 15:50:33 +08:00
parent d54cd84138
commit 8364adef70
8 changed files with 95 additions and 95 deletions

View File

@ -26,23 +26,15 @@ inline PyObject* VM::run_frame(Frame* frame){
f._closure = frame->_locals;
} continue;
case OP_ROT_TWO: ::std::swap(frame->top(), frame->top_1()); continue;
case OP_BUILD_TUPLE: {
Args items = frame->pop_n_values_reversed(this, byte.arg);
frame->push(VAR(std::move(items)));
} continue;
/*****************************************/
case OP_LOAD_NAME: {
// TODO: use name resolution linked list to optimize this
StrName name = frame->co->names[byte.arg];
PyObject* val;
val = frame->f_locals().try_get(name);
if(val != nullptr) { frame->push(val); continue; }
val = frame->f_closure_try_get(name);
if(val != nullptr) { frame->push(val); continue; }
val = frame->f_globals().try_get(name);
if(val != nullptr) { frame->push(val); continue; }
val = vm->builtins->attr().try_get(name);
if(val != nullptr) { frame->push(val); continue; }
int i = 0; // names[0] is ensured to be non-null
do{
val = frame->names[i++]->try_get(name);
if(val != nullptr){ frame->push(val); break; }
}while(frame->names[i] != nullptr);
vm->NameError(name);
} continue;
case OP_LOAD_ATTR: {
@ -51,9 +43,10 @@ inline PyObject* VM::run_frame(Frame* frame){
frame->top() = getattr(a, name);
} continue;
case OP_LOAD_SUBSCR: {
PyObject* b = frame->popx();
PyObject* a = frame->top();
frame->top() = fast_call(__getitem__, Args{a, b});
Args args(2);
args[1] = frame->popx(); // b
args[0] = frame->top(); // a
frame->top() = fast_call(__getitem__, std::move(args));
} continue;
case OP_STORE_LOCAL: {
StrName name = frame->co->names[byte.arg];
@ -105,34 +98,58 @@ inline PyObject* VM::run_frame(Frame* frame){
fast_call(__delitem__, Args{a, b});
} continue;
/*****************************************/
case OP_BUILD_TUPLE_REF: {
Args items = frame->pop_n_reversed(byte.arg);
frame->push(PyRef(TupleRef(std::move(items))));
case OP_BUILD_LIST:
frame->push(VAR(frame->popx_n_reversed(byte.arg).to_list()));
continue;
case OP_BUILD_DICT: {
PyObject* t = VAR(frame->popx_n_reversed(byte.arg));
PyObject* obj = call(builtins->attr(m_dict), Args{t});
frame->push(obj);
} continue;
case OP_BUILD_SET: {
PyObject* t = VAR(frame->popx_n_reversed(byte.arg));
PyObject* obj = call(builtins->attr(m_set), Args{t});
frame->push(obj);
} continue;
case OP_BUILD_SLICE: {
PyObject* step = frame->popx();
PyObject* stop = frame->popx();
PyObject* start = frame->popx();
Slice s;
if(start != None) { s.start = CAST(int, start);}
if(stop != None) { s.stop = CAST(int, stop);}
if(step != None) { s.step = CAST(int, step);}
frame->push(VAR(s));
} continue;
case OP_BUILD_TUPLE: {
Tuple items = frame->popx_n_reversed(byte.arg);
frame->push(VAR(std::move(items)));
} continue;
case OP_BUILD_STRING: {
Args items = frame->pop_n_values_reversed(this, byte.arg);
Args items = frame->popx_n_reversed(byte.arg);
StrStream ss;
for(int i=0; i<items.size(); i++) ss << CAST(Str, asStr(items[i]));
frame->push(VAR(ss.str()));
} continue;
/*****************************************/
case OP_LOAD_EVAL_FN: frame->push(builtins->attr(m_eval)); continue;
case OP_BEGIN_CLASS: {
auto& name = frame->co->names[byte.arg];
PyObject* clsBase = frame->pop_value(this);
StrName name = frame->co->names[byte.arg];
PyObject* clsBase = frame->popx();
if(clsBase == None) clsBase = _t(tp_object);
check_type(clsBase, tp_type);
PyObject* cls = new_type_object(frame->_module, name.first, OBJ_GET(Type, clsBase));
PyObject* cls = new_type_object(frame->_module, name, OBJ_GET(Type, clsBase));
frame->push(cls);
} continue;
case OP_END_CLASS: {
PyObject* cls = frame->pop();
PyObject* cls = frame->popx();
cls->attr()._try_perfect_rehash();
}; continue;
case OP_STORE_CLASS_ATTR: {
auto& name = frame->co->names[byte.arg];
PyObject* obj = frame->pop_value(this);
StrName name = frame->co->names[byte.arg];
PyObject* obj = frame->popx();
PyObject* cls = frame->top();
cls->attr().set(name.first, std::move(obj));
cls->attr().set(name, obj);
} continue;
case OP_RETURN_VALUE: return frame->popx();
case OP_PRINT_EXPR: {
@ -204,27 +221,7 @@ inline PyObject* VM::run_frame(Frame* frame){
_error(type, msg);
} continue;
case OP_RE_RAISE: _raise(); continue;
case OP_BUILD_LIST:
frame->push(VAR(frame->pop_n_values_reversed(this, byte.arg).to_list()));
continue;
case OP_BUILD_MAP: {
List list(byte.arg);
for(int i=0; i<byte.arg; i++){
PyObject* value = frame->pop_value(this);
PyObject* key = frame->pop_value(this);
list[i] = VAR(Tuple({key, value}));
}
PyObject* d_arg = VAR(std::move(list));
PyObject* obj = call(builtins->attr("dict"), Args{d_arg});
frame->push(obj);
} continue;
case OP_BUILD_SET: {
PyObject* list = VAR(
frame->pop_n_values_reversed(this, byte.arg).to_list()
);
PyObject* obj = call(builtins->attr("set"), Args{list});
frame->push(obj);
} continue;
case OP_LIST_APPEND: {
PyObject* obj = frame->pop_value(this);
List& list = CAST(List&, frame->top_1());
@ -310,14 +307,7 @@ inline PyObject* VM::run_frame(Frame* frame){
if(asBool(expr)==True) frame->jump_abs(byte.arg);
else frame->pop_value(this);
} continue;
case OP_BUILD_SLICE: {
PyObject* stop = frame->pop_value(this);
PyObject* start = frame->pop_value(this);
Slice s;
if(start != None) { s.start = CAST(int, start);}
if(stop != None) { s.stop = CAST(int, stop);}
frame->push(VAR(s));
} continue;
case OP_IMPORT_NAME: {
StrName name = frame->co->names[byte.arg].first;
PyObject* ext_mod = _modules.try_get(name);

View File

@ -142,6 +142,10 @@ private:
}
}
bool match_newlines_repl(){
return match_newlines(mode()==REPL_MODE);
}
bool match_newlines(bool repl_throw=false) {
bool consumed = false;
if (curr().type == TK("@eol")) {
@ -281,9 +285,9 @@ private:
// PASS
void exprGroup(){
match_newlines(mode()==REPL_MODE);
match_newlines_repl();
EXPR_TUPLE(); // () is just for change precedence
match_newlines(mode()==REPL_MODE);
match_newlines_repl();
consume(TK(")"));
}
@ -298,13 +302,13 @@ private:
consume(TK("in"));
EXPR();
ce->iter = ctx()->s_expr.popx();
match_newlines(mode()==REPL_MODE);
match_newlines_repl();
if(match(TK("if"))){
EXPR();
ce->cond = ctx()->s_expr.popx();
}
ctx()->s_expr.push(std::move(ce));
match_newlines(mode()==REPL_MODE);
match_newlines_repl();
}
// PASS
@ -312,17 +316,17 @@ private:
int line = prev().line;
std::vector<Expr_> items;
do {
match_newlines(mode()==REPL_MODE);
match_newlines_repl();
if (curr().type == TK("]")) break;
EXPR();
items.push_back(ctx()->s_expr.popx());
match_newlines(mode()==REPL_MODE);
match_newlines_repl();
if(items.size()==1 && match(TK("for"))){
_consume_comp<ListCompExpr>(std::move(items[0]));
consume(TK("]"));
return;
}
match_newlines(mode()==REPL_MODE);
match_newlines_repl();
} while (match(TK(",")));
consume(TK("]"));
auto e = make_expr<ListExpr>(std::move(items));
@ -335,7 +339,7 @@ private:
bool parsing_dict = false; // {...} may be dict or set
std::vector<Expr_> items;
do {
match_newlines(mode()==REPL_MODE);
match_newlines_repl();
if (curr().type == TK("}")) break;
EXPR();
if(curr().type == TK(":")) parsing_dict = true;
@ -349,14 +353,14 @@ private:
}else{
items.push_back(ctx()->s_expr.popx());
}
match_newlines(mode()==REPL_MODE);
match_newlines_repl();
if(items.size()==1 && match(TK("for"))){
if(parsing_dict) _consume_comp<DictCompExpr>(std::move(items[0]));
else _consume_comp<SetCompExpr>(std::move(items[0]));
consume(TK("}"));
return;
}
match_newlines(mode()==REPL_MODE);
match_newlines_repl();
} while (match(TK(",")));
consume(TK("}"));
if(items.size()==0 || parsing_dict){
@ -373,7 +377,7 @@ private:
auto e = make_expr<CallExpr>();
e->callable = ctx()->s_expr.popx();
do {
match_newlines(mode()==REPL_MODE);
match_newlines_repl();
if (curr().type==TK(")")) break;
if(curr().type==TK("@id") && next().type==TK("=")) {
consume(TK("@id"));
@ -386,7 +390,7 @@ private:
EXPR();
e->args.push_back(ctx()->s_expr.popx());
}
match_newlines(mode()==REPL_MODE);
match_newlines_repl();
} while (match(TK(",")));
consume(TK(")"));
if(e->args.size() > 32767) SyntaxError("too many positional arguments");
@ -709,7 +713,7 @@ private:
case TK("label"):
if(mode()!=EXEC_MODE) SyntaxError("'label' is only available in EXEC_MODE");
consume(TK(".")); consume(TK("@id"));
bool ok = co()->add_label(prev().str());
bool ok = ctx()->add_label(prev().str());
if(!ok) SyntaxError("label " + prev().str().escape(true) + " already exists");
consume_end_stmt();
break;

View File

@ -14,24 +14,23 @@ struct Frame {
const CodeObject* co;
PyObject* _module;
NameDict_ _locals;
NameDict_ _closure;
const uint64_t id;
std::vector<std::pair<int, std::vector<PyObject*>>> s_try_block;
const NameDict* names[5]; // name resolution array, zero terminated
NameDict& f_locals() noexcept { return _locals != nullptr ? *_locals : _module->attr(); }
NameDict& f_locals() noexcept { return *_locals; }
NameDict& f_globals() noexcept { return _module->attr(); }
PyObject* f_closure_try_get(StrName name) noexcept {
if(_closure == nullptr) return nullptr;
return _closure->try_get(name);
Frame(const CodeObject_& co, PyObject* _module, NameDict_ _locals=nullptr, NameDict_ _closure=nullptr)
: co(co.get()), _module(_module), _locals(_locals), id(kFrameGlobalId++) {
memset(names, 0, sizeof(names));
int i = 0;
if(_locals != nullptr) names[i++] = _locals.get();
if(_closure != nullptr) names[i++] = _closure.get();
names[i++] = &_module->attr();
// names[i++] = builtins
}
Frame(const CodeObject_& co,
PyObject* _module,
const NameDict_& _locals=nullptr,
const NameDict_& _closure=nullptr)
: co(co.get()), _module(_module), _locals(_locals), _closure(_closure), id(kFrameGlobalId++) { }
const Bytecode& next_bytecode() {
_ip = _next_ip++;
return co->codes[_ip];
@ -127,7 +126,7 @@ struct Frame {
}
}
Args pop_n_reversed(int n){
Args popx_n_reversed(int n){
Args v(n);
for(int i=n-1; i>=0; i--) v[i] = popx();
return v;
@ -135,9 +134,13 @@ struct Frame {
void _mark() const {
for(PyObject* obj : _data) OBJ_MARK(obj);
if(_locals != nullptr) _locals->_mark();
if(_closure != nullptr) _closure->_mark();
OBJ_MARK(_module);
int i = 0; // names[0] is ensured to be non-null
do{
names[i++]->_mark();
}while(names[i] != nullptr);
for(auto& p : s_try_block){
for(PyObject* obj : p.second) OBJ_MARK(obj);
}

View File

@ -114,7 +114,7 @@ struct ManagedHeap{
void mark(VM* vm);
};
inline void NameDict::_mark(){
inline void NameDict::_mark() const{
for(uint16_t i=0; i<_capacity; i++){
if(_items[i].first.empty()) continue;
OBJ_MARK(_items[i].second);

View File

@ -125,7 +125,7 @@ while(!_items[i].first.empty()) { \
_rehash(false); // do not resize
}
PyObject* try_get(StrName key){
PyObject* try_get(StrName key) const{
bool ok; uint16_t i;
HASH_PROBE(key, ok, i);
if(!ok) return nullptr;
@ -180,7 +180,7 @@ while(!_items[i].first.empty()) { \
return v;
}
void _mark();
void _mark() const;
#undef HASH_PROBE
#undef _hash
};

View File

@ -65,9 +65,11 @@ struct StarWrapper {
using Super = std::pair<PyObject*, Type>;
// TODO: re-examine the design of Slice
struct Slice {
int start = 0;
int stop = 0x7fffffff;
int stop = 0x7fffffff;
int step = 1;
void normalize(int len){
if(start < 0) start += len;

View File

@ -20,14 +20,6 @@ OPCODE(UNARY_NEGATIVE)
OPCODE(UNARY_NOT)
OPCODE(UNARY_STAR)
OPCODE(BUILD_LIST)
OPCODE(BUILD_MAP)
OPCODE(BUILD_SET)
OPCODE(BUILD_SLICE)
OPCODE(BUILD_TUPLE)
OPCODE(BUILD_TUPLE_REF)
OPCODE(BUILD_STRING)
OPCODE(LIST_APPEND)
OPCODE(MAP_ADD)
OPCODE(SET_ADD)
@ -96,5 +88,12 @@ OPCODE(DELETE_GLOBAL)
OPCODE(DELETE_ATTR)
OPCODE(DELETE_SUBSCR)
/**************************/
OPCODE(BUILD_LIST)
OPCODE(BUILD_DICT)
OPCODE(BUILD_SET)
OPCODE(BUILD_SLICE)
OPCODE(BUILD_TUPLE)
OPCODE(BUILD_STRING)
/**************************/
#endif

View File

@ -209,6 +209,8 @@ const StrName __call__ = StrName::get("__call__");
const StrName m_eval = StrName::get("eval");
const StrName m_self = StrName::get("self");
const StrName m_dict = StrName::get("dict");
const StrName m_set = StrName::get("set");
const StrName __enter__ = StrName::get("__enter__");
const StrName __exit__ = StrName::get("__exit__");