diff --git a/src/base64.h b/src/base64.h index e7e577d1..da2cde84 100644 --- a/src/base64.h +++ b/src/base64.h @@ -74,7 +74,7 @@ static const unsigned char base64de[] = { 49, 50, 51, 255, 255, 255, 255, 255 }; -unsigned int +inline static unsigned int base64_encode(const unsigned char *in, unsigned int inlen, char *out) { int s; @@ -123,7 +123,7 @@ base64_encode(const unsigned char *in, unsigned int inlen, char *out) return j; } -unsigned int +inline static unsigned int base64_decode(const char *in, unsigned int inlen, unsigned char *out) { unsigned int i; @@ -168,7 +168,7 @@ base64_decode(const char *in, unsigned int inlen, unsigned char *out) return j; } -void add_module_base64(VM* vm){ +inline void add_module_base64(VM* vm){ PyObject* mod = vm->new_module("base64"); // b64encode diff --git a/src/ceval.h b/src/ceval.h index bd91df6d..506252d8 100644 --- a/src/ceval.h +++ b/src/ceval.h @@ -21,7 +21,6 @@ inline PyObject* VM::_run_top_frame(){ #endif try{ if(need_raise){ need_raise = false; _raise(); } - // if(s_data.is_overflow()) StackOverflowError(); /**********************************************************************/ /* NOTE: * Be aware of accidental gc! @@ -145,8 +144,8 @@ __NEXT_STEP:; PUSH(_0); DISPATCH(); TARGET(LOAD_SUBSCR) - _1 = POPX(); - _0 = TOP(); + _1 = POPX(); // b + _0 = TOP(); // a TOP() = call_method(_0, __getitem__, _1); DISPATCH(); TARGET(STORE_FAST) @@ -203,7 +202,7 @@ __NEXT_STEP:; TARGET(DELETE_ATTR) _0 = POPX(); _name = StrName(byte.arg); - if(!_0->is_attr_valid()) TypeError("cannot delete attribute"); + if(is_tagged(_0) || !_0->is_attr_valid()) TypeError("cannot delete attribute"); if(!_0->attr().contains(_name)) AttributeError(_0, _name); _0->attr().erase(_name); DISPATCH(); @@ -218,18 +217,18 @@ __NEXT_STEP:; STACK_SHRINK(byte.arg); PUSH(_0); DISPATCH(); - TARGET(BUILD_DICT) { - PyObject* t = VAR(STACK_VIEW(byte.arg).to_tuple()); - PyObject* obj = call(builtins->attr(m_dict), t); + TARGET(BUILD_DICT) + _0 = VAR(STACK_VIEW(byte.arg).to_tuple()); + _0 = call(builtins->attr(m_dict), _0); STACK_SHRINK(byte.arg); - PUSH(obj); - } DISPATCH(); - TARGET(BUILD_SET) { - PyObject* t = VAR(STACK_VIEW(byte.arg).to_tuple()); - PyObject* obj = call(builtins->attr(m_set), t); + PUSH(_0); + DISPATCH(); + TARGET(BUILD_SET) + _0 = VAR(STACK_VIEW(byte.arg).to_tuple()); + _0 = call(builtins->attr(m_set), _0); STACK_SHRINK(byte.arg); - PUSH(obj); - } DISPATCH(); + PUSH(_0); + DISPATCH(); TARGET(BUILD_SLICE) _2 = POPX(); // step _1 = POPX(); // stop @@ -243,16 +242,25 @@ __NEXT_STEP:; DISPATCH(); TARGET(BUILD_STRING) { std::stringstream ss; - auto view = STACK_VIEW(byte.arg); + ArgsView view = STACK_VIEW(byte.arg); for(PyObject* obj : view) ss << CAST(Str&, asStr(obj)); STACK_SHRINK(byte.arg); PUSH(VAR(ss.str())); } DISPATCH(); /*****************************************/ - TARGET(BINARY_OP) - _1 = POPX(); // b - _0 = TOP(); // a - TOP() = call_method(_0, BINARY_SPECIAL_METHODS[byte.arg], _1); + TARGET(BINARY_TRUEDIV) + _1 = POPX(); + _0 = TOP(); + if(is_float(_0)){ + TOP() = VAR(_CAST(f64, _0) / num_to_float(_1)); + }else{ + TOP() = call_method(_0, __truediv__, _1); + } + DISPATCH(); + TARGET(BINARY_POW) + _1 = POPX(); + _0 = TOP(); + TOP() = call_method(_0, __pow__, _1); DISPATCH(); #define INT_BINARY_OP(op, func) \ @@ -358,9 +366,9 @@ __NEXT_STEP:; frame->jump_abs_break(co_blocks[byte.block].end); DISPATCH(); TARGET(GOTO) { - StrName name(byte.arg); - int index = co->labels.try_get(name); - if(index < 0) _error("KeyError", fmt("label ", name.escape(), " not found")); + _name = StrName(byte.arg); + int index = co->labels.try_get(_name); + if(index < 0) _error("KeyError", fmt("label ", _name.escape(), " not found")); frame->jump_abs_break(index); } DISPATCH(); /*****************************************/ @@ -445,55 +453,55 @@ __NEXT_STEP:; PUSH(ext_mod); } } DISPATCH(); - TARGET(IMPORT_STAR) { - PyObject* obj = POPX(); - for(auto& [name, value]: obj->attr().items()){ + TARGET(IMPORT_STAR) + _0 = POPX(); + for(auto& [name, value]: _0->attr().items()){ std::string_view s = name.sv(); if(s.empty() || s[0] == '_') continue; frame->f_globals().set(name, value); } - }; DISPATCH(); + DISPATCH(); /*****************************************/ TARGET(UNPACK_SEQUENCE) TARGET(UNPACK_EX) { auto _lock = heap.gc_scope_lock(); // lock the gc via RAII!! - PyObject* iter = asIter(POPX()); + _0 = asIter(POPX()); for(int i=0; i_module, name, OBJ_GET(Type, super_cls)); - PUSH(cls); - } DISPATCH(); + TARGET(BEGIN_CLASS) + _name = StrName(byte.arg); + _0 = POPX(); // super + if(_0 == None) _0 = _t(tp_object); + check_non_tagged_type(_0, tp_type); + _1 = new_type_object(frame->_module, _name, OBJ_GET(Type, _0)); + PUSH(_1); + DISPATCH(); TARGET(END_CLASS) _0 = POPX(); _0->attr()._try_perfect_rehash(); @@ -513,15 +521,15 @@ __NEXT_STEP:; DISPATCH(); /*****************************************/ TARGET(ASSERT) { - PyObject* obj = TOP(); + _0 = TOP(); Str msg; - if(is_type(obj, tp_tuple)){ - auto& t = CAST(Tuple&, obj); + if(is_type(_0, tp_tuple)){ + auto& t = CAST(Tuple&, _0); if(t.size() != 2) ValueError("assert tuple must have 2 elements"); - obj = t[0]; + _0 = t[0]; msg = CAST(Str&, asStr(t[1])); } - bool ok = asBool(obj); + bool ok = asBool(_0); POP(); if(!ok) _error("AssertionError", msg); } DISPATCH(); @@ -531,8 +539,8 @@ __NEXT_STEP:; PUSH(VAR(e.match_type(_name))); } DISPATCH(); TARGET(RAISE) { - PyObject* obj = POPX(); - Str msg = obj == None ? "" : CAST(Str, asStr(obj)); + _0 = POPX(); + Str msg = _0 == None ? "" : CAST(Str, asStr(_0)); _error(StrName(byte.arg), msg); } DISPATCH(); TARGET(RE_RAISE) _raise(); DISPATCH(); diff --git a/src/expr.h b/src/expr.h index 25849da6..326c722b 100644 --- a/src/expr.h +++ b/src/expr.h @@ -681,10 +681,10 @@ struct BinaryExpr: Expr{ case TK("+"): ctx->emit(OP_BINARY_ADD, BC_NOARG, line); break; case TK("-"): ctx->emit(OP_BINARY_SUB, BC_NOARG, line); break; case TK("*"): ctx->emit(OP_BINARY_MUL, BC_NOARG, line); break; - case TK("/"): ctx->emit(OP_BINARY_OP, 3, line); break; + case TK("/"): ctx->emit(OP_BINARY_TRUEDIV, BC_NOARG, line); break; case TK("//"): ctx->emit(OP_BINARY_FLOORDIV, BC_NOARG, line); break; case TK("%"): ctx->emit(OP_BINARY_MOD, BC_NOARG, line); break; - case TK("**"): ctx->emit(OP_BINARY_OP, 6, line); break; + case TK("**"): ctx->emit(OP_BINARY_POW, BC_NOARG, line); break; case TK("<"): ctx->emit(OP_COMPARE_LT, BC_NOARG, line); break; case TK("<="): ctx->emit(OP_COMPARE_LE, BC_NOARG, line); break; diff --git a/src/opcodes.h b/src/opcodes.h index 477fac86..7575edc6 100644 --- a/src/opcodes.h +++ b/src/opcodes.h @@ -44,7 +44,9 @@ OPCODE(BUILD_SLICE) OPCODE(BUILD_TUPLE) OPCODE(BUILD_STRING) /**************************/ -OPCODE(BINARY_OP) +OPCODE(BINARY_TRUEDIV) +OPCODE(BINARY_POW) + OPCODE(BINARY_ADD) OPCODE(BINARY_SUB) OPCODE(BINARY_MUL) diff --git a/src/str.h b/src/str.h index 50996b1f..0df22cbb 100644 --- a/src/str.h +++ b/src/str.h @@ -423,6 +423,9 @@ const StrName BINARY_SPECIAL_METHODS[] = { StrName::get("__mod__"), StrName::get("__pow__") }; +const StrName __truediv__ = StrName::get("__truediv__"); +const StrName __pow__ = StrName::get("__pow__"); + const StrName __lt__ = StrName::get("__lt__"); const StrName __le__ = StrName::get("__le__"); const StrName __eq__ = StrName::get("__eq__"); diff --git a/src/vm.h b/src/vm.h index 0f5e0de3..be22af65 100644 --- a/src/vm.h +++ b/src/vm.h @@ -99,8 +99,6 @@ public: PrintFunc _stdout; PrintFunc _stderr; - bool _initialized; - // for quick access Type tp_object, tp_type, tp_int, tp_float, tp_bool, tp_str; Type tp_list, tp_tuple; @@ -115,9 +113,8 @@ public: _stdout = [](VM* vm, const Str& s) { std::cout << s; }; _stderr = [](VM* vm, const Str& s) { std::cerr << s; }; callstack.reserve(8); - _initialized = false; + _main = nullptr; init_builtin_types(); - _initialized = true; } FrameId top_frame() { @@ -752,9 +749,6 @@ inline std::string _opcode_argstr(VM* vm, Bytecode byte, const CodeObject* co){ case OP_LOAD_FAST: case OP_STORE_FAST: case OP_DELETE_FAST: argStr += fmt(" (", co->varnames[byte.arg].sv(), ")"); break; - case OP_BINARY_OP: - argStr += fmt(" (", BINARY_SPECIAL_METHODS[byte.arg], ")"); - break; case OP_LOAD_FUNCTION: argStr += fmt(" (", co->func_decls[byte.arg]->code->name, ")"); break; @@ -809,7 +803,7 @@ inline Str VM::disassemble(CodeObject_ co){ } inline void VM::_log_s_data(const char* title) { - if(!_initialized) return; + if(_main == nullptr) return; if(callstack.empty()) return; std::stringstream ss; if(title) ss << title << " | "; @@ -890,7 +884,6 @@ inline void VM::init_builtin_types(){ this->StopIteration = heap._new(_new_type_object("StopIterationType"), {}); this->builtins = new_module("builtins"); - this->_main = new_module("__main__"); // setup public types builtins->attr().set("type", _t(tp_type)); @@ -911,6 +904,7 @@ inline void VM::init_builtin_types(){ _all_types[i].obj->attr()._try_perfect_rehash(); } for(auto [k, v]: _modules.items()) v->attr()._try_perfect_rehash(); + this->_main = new_module("__main__"); } inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){ @@ -931,7 +925,6 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){ PyObject* callable = p1[-(ARGC + 2)]; bool method_call = p1[-(ARGC + 1)] != PY_NULL; - // handle boundmethod, do a patch if(is_non_tagged_type(callable, tp_bound_method)){ if(method_call) FATAL_ERROR();