mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-21 03:50:16 +00:00
up
This commit is contained in:
parent
d54cd84138
commit
8364adef70
102
src/ceval.h
102
src/ceval.h
@ -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);
|
||||
|
@ -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;
|
||||
|
31
src/frame.h
31
src/frame.h
@ -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);
|
||||
}
|
||||
|
2
src/gc.h
2
src/gc.h
@ -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);
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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
|
@ -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__");
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user