From d54cd8413822671de933d5f472e99d4bf591bfc0 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 2 Apr 2023 14:46:59 +0800 Subject: [PATCH] up --- amalgamate.py | 2 +- src/ceval.h | 8 +- src/codeobject.h | 7 +- src/compiler.h | 197 +++++++++++++++++++---------------------------- src/expr.h | 44 ++++++++++- src/opcodes.h | 9 +-- src/ref.h | 179 ------------------------------------------ 7 files changed, 131 insertions(+), 315 deletions(-) delete mode 100644 src/ref.h diff --git a/amalgamate.py b/amalgamate.py index 8327b940..b5cd8fd5 100644 --- a/amalgamate.py +++ b/amalgamate.py @@ -8,7 +8,7 @@ with open("src/opcodes.h", "rt", encoding='utf-8') as f: pipeline = [ ["common.h", "memory.h", "str.h", "tuplelist.h", "namedict.h", "error.h", "lexer.h"], ["obj.h", "codeobject.h", "frame.h"], - ["gc.h", "vm.h", "ref.h", "ceval.h", "compiler.h", "repl.h"], + ["gc.h", "vm.h", "ceval.h", "expr.h", "compiler.h", "repl.h"], ["iter.h", "cffi.h", "io.h", "_generated.h", "pocketpy.h"] ] diff --git a/src/ceval.h b/src/ceval.h index 9a45f1b3..cb873dc2 100644 --- a/src/ceval.h +++ b/src/ceval.h @@ -2,7 +2,6 @@ #include "common.h" #include "vm.h" -#include "ref.h" namespace pkpy{ @@ -135,10 +134,11 @@ inline PyObject* VM::run_frame(Frame* frame){ PyObject* cls = frame->top(); cls->attr().set(name.first, std::move(obj)); } continue; - case OP_RETURN_VALUE: return frame->pop_value(this); + case OP_RETURN_VALUE: return frame->popx(); case OP_PRINT_EXPR: { - PyObject* expr = frame->top_value(this); + PyObject* expr = frame->top(); // use top() here to avoid accidental gc if(expr != None) *_stdout << CAST(Str, asRepr(expr)) << '\n'; + frame->pop(); } continue; case OP_POP_TOP: frame->_pop(); continue; case OP_BINARY_OP: { @@ -239,7 +239,7 @@ inline PyObject* VM::run_frame(Frame* frame){ PyObject* obj = frame->pop_value(this); call(frame->top_1(), "add", Args{obj}); } continue; - case OP_DUP_TOP_VALUE: frame->push(frame->top_value(this)); continue; + case OP_DUP_TOP: frame->push(frame->top()); continue; case OP_UNARY_STAR: { if(byte.arg > 0){ // rvalue frame->top() = VAR(StarWrapper(frame->top_value(this), true)); diff --git a/src/codeobject.h b/src/codeobject.h index b238bc7a..e851fb31 100644 --- a/src/codeobject.h +++ b/src/codeobject.h @@ -5,12 +5,7 @@ namespace pkpy{ -enum NameScope { - NAME_LOCAL = 0, - NAME_GLOBAL, - NAME_ATTR, - NAME_SPECIAL, -}; +enum NameScope { NAME_LOCAL, NAME_GLOBAL }; enum Opcode { #define OPCODE(name) OP_##name, diff --git a/src/compiler.h b/src/compiler.h index a4647e49..6348e264 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -24,10 +24,18 @@ class Compiler { std::unique_ptr lexer; stack contexts; std::map rules; - bool used = false; VM* vm; + bool used; + // for parsing token stream + int i = 0; + std::vector tokens; + + const Token& prev() { return tokens.at(i-1); } + const Token& curr() { return tokens.at(i); } + const Token& next() { return tokens.at(i+1); } + const Token& peek(int offset) { return tokens.at(i+offset); } + void advance() { i++; } - CodeObject* co() const{ return contexts.top().co.get(); } CodeEmitContext* ctx() { return &contexts.top(); } CompileMode mode() const{ return lexer->src->mode; } NameScope name_scope() const { return contexts.size()>1 ? NAME_LOCAL : NAME_GLOBAL; } @@ -41,6 +49,7 @@ class Compiler { void pop_context(){ if(!ctx()->s_expr.empty()) UNREACHABLE(); + // if last instruction is not return, add a default return None if(ctx()->co->codes.back().op != OP_RETURN_VALUE){ ctx()->emit(OP_LOAD_NONE, BC_NOARG, BC_KEEPLINE); ctx()->emit(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE); @@ -52,6 +61,7 @@ class Compiler { public: Compiler(VM* vm, const char* source, Str filename, CompileMode mode){ this->vm = vm; + this->used = false; this->lexer = std::make_unique( make_sp(source, filename, mode) ); @@ -60,25 +70,32 @@ public: #define METHOD(name) &Compiler::name #define NO_INFIX nullptr, PREC_NONE for(TokenIndex i=0; i")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION }; - rules[TK("<")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION }; - rules[TK("==")] = { nullptr, METHOD(exprBinaryOp), PREC_EQUALITY }; - rules[TK("!=")] = { nullptr, METHOD(exprBinaryOp), PREC_EQUALITY }; - rules[TK(">=")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION }; - rules[TK("<=")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION }; - rules[TK("in")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST }; - rules[TK("is")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST }; + rules[TK(".")] = { nullptr, METHOD(exprAttrib), PREC_ATTRIB }; + rules[TK("(")] = { METHOD(exprGroup), METHOD(exprCall), PREC_CALL }; + rules[TK("[")] = { METHOD(exprList), METHOD(exprSubscr), PREC_SUBSCRIPT }; + rules[TK("{")] = { METHOD(exprMap), NO_INFIX }; + rules[TK("%")] = { nullptr, METHOD(exprBinaryOp), PREC_FACTOR }; + rules[TK("+")] = { nullptr, METHOD(exprBinaryOp), PREC_TERM }; + rules[TK("-")] = { METHOD(exprUnaryOp), METHOD(exprBinaryOp), PREC_TERM }; + rules[TK("*")] = { METHOD(exprUnaryOp), METHOD(exprBinaryOp), PREC_FACTOR }; + rules[TK("/")] = { nullptr, METHOD(exprBinaryOp), PREC_FACTOR }; + rules[TK("//")] = { nullptr, METHOD(exprBinaryOp), PREC_FACTOR }; + rules[TK("**")] = { nullptr, METHOD(exprBinaryOp), PREC_EXPONENT }; + rules[TK(">")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION }; + rules[TK("<")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION }; + rules[TK("==")] = { nullptr, METHOD(exprBinaryOp), PREC_EQUALITY }; + rules[TK("!=")] = { nullptr, METHOD(exprBinaryOp), PREC_EQUALITY }; + rules[TK(">=")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION }; + rules[TK("<=")] = { nullptr, METHOD(exprBinaryOp), PREC_COMPARISION }; + rules[TK("in")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST }; + rules[TK("is")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST }; + rules[TK("<<")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_SHIFT }; + rules[TK(">>")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_SHIFT }; + rules[TK("&")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_AND }; + rules[TK("|")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_OR }; + rules[TK("^")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_XOR }; + rules[TK("?")] = { nullptr, METHOD(exprTernary), PREC_TERNARY }; + rules[TK(",")] = { nullptr, METHOD(exprTuple), PREC_TUPLE }; rules[TK("not in")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST }; rules[TK("is not")] = { nullptr, METHOD(exprBinaryOp), PREC_TEST }; rules[TK("and") ] = { nullptr, METHOD(exprAnd), PREC_LOGICAL_AND }; @@ -93,13 +110,6 @@ public: rules[TK("@num")] = { METHOD(exprLiteral), NO_INFIX }; rules[TK("@str")] = { METHOD(exprLiteral), NO_INFIX }; rules[TK("@fstr")] = { METHOD(exprFString), NO_INFIX }; - rules[TK("?")] = { nullptr, METHOD(exprTernary), PREC_TERNARY }; - rules[TK(",")] = { nullptr, METHOD(exprTuple), PREC_TUPLE }; - rules[TK("<<")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_SHIFT }; - rules[TK(">>")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_SHIFT }; - rules[TK("&")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_AND }; - rules[TK("|")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_OR }; - rules[TK("^")] = { nullptr, METHOD(exprBinaryOp), PREC_BITWISE_XOR }; #undef METHOD #undef NO_INFIX @@ -118,15 +128,6 @@ public: } private: - int i = 0; - std::vector tokens; - - const Token& prev() { return tokens.at(i-1); } - const Token& curr() { return tokens.at(i); } - const Token& next() { return tokens.at(i+1); } - const Token& peek(int offset) { return tokens.at(i+offset); } - void advance() { i++; } - bool match(TokenIndex expected) { if (curr().type != expected) return false; advance(); @@ -164,12 +165,14 @@ private: if (!match_end_stmt()) SyntaxError("expected statement end"); } - void EXPR(ExprAction action=EXPR_PUSH_STACK) { - parse_expression(PREC_TUPLE + 1, action); + /*************************************************/ + + void EXPR(bool push_stack=true) { + parse_expression(PREC_TUPLE+1, push_stack); } - void EXPR_TUPLE(ExprAction action=EXPR_PUSH_STACK) { - parse_expression(PREC_TUPLE, action); + void EXPR_TUPLE(bool push_stack=true) { + parse_expression(PREC_TUPLE, push_stack); } template @@ -179,8 +182,6 @@ private: return expr; } - /********************************************/ - // PASS void exprLiteral(){ ctx()->s_expr.push(make_expr(prev().value)); @@ -201,63 +202,12 @@ private: consume(TK(":")); } e->func.code = push_context(lexer->src, ""); - // https://github.com/blueloveTH/pocketpy/issues/37 - EXPR(true); + EXPR(true); // https://github.com/blueloveTH/pocketpy/issues/37 ctx()->emit(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE); pop_context(); ctx()->s_expr.push(std::move(e)); } - void exprAssign(){ - // if(co()->codes.empty()) UNREACHABLE(); - // bool is_load_name_ref = co()->codes.back().op == OP_LOAD_NAME_REF; - // int _name_arg = co()->codes.back().arg; - // // if the last op is OP_LOAD_NAME_REF, remove it - // // because we will emit OP_STORE_NAME or OP_STORE_CLASS_ATTR - // if(is_load_name_ref) co()->codes.pop_back(); - - // co()->_rvalue += 1; - // TokenIndex op = prev().type; - // if(op == TK("=")) { // a = (expr) - // EXPR_TUPLE(); - // if(is_load_name_ref){ - // auto op = ctx()->is_compiling_class ? OP_STORE_CLASS_ATTR : OP_STORE_NAME; - // emit(op, _name_arg); - // }else{ - // if(ctx()->is_compiling_class) SyntaxError(); - // emit(OP_STORE_REF); - // } - // }else{ // a += (expr) -> a = a + (expr) - // if(ctx()->is_compiling_class) SyntaxError(); - // if(is_load_name_ref){ - // emit(OP_LOAD_NAME, _name_arg); - // }else{ - // emit(OP_DUP_TOP_VALUE); - // } - // EXPR(); - // switch (op) { - // case TK("+="): emit(OP_BINARY_OP, 0); break; - // case TK("-="): emit(OP_BINARY_OP, 1); break; - // case TK("*="): emit(OP_BINARY_OP, 2); break; - // case TK("/="): emit(OP_BINARY_OP, 3); break; - // case TK("//="): emit(OP_BINARY_OP, 4); break; - // case TK("%="): emit(OP_BINARY_OP, 5); break; - // case TK("<<="): emit(OP_BITWISE_OP, 0); break; - // case TK(">>="): emit(OP_BITWISE_OP, 1); break; - // case TK("&="): emit(OP_BITWISE_OP, 2); break; - // case TK("|="): emit(OP_BITWISE_OP, 3); break; - // case TK("^="): emit(OP_BITWISE_OP, 4); break; - // default: UNREACHABLE(); - // } - // if(is_load_name_ref){ - // emit(OP_STORE_NAME, _name_arg); - // }else{ - // emit(OP_STORE_REF); - // } - // } - // co()->_rvalue -= 1; - } - // PASS void exprTuple(){ auto e = make_expr(); @@ -540,17 +490,17 @@ private: return; } do { - ctx()->emit(OP_DUP_TOP_VALUE, BC_NOARG, BC_KEEPLINE); + ctx()->emit(OP_DUP_TOP, BC_NOARG, BC_KEEPLINE); consume(TK("@id")); Str name = prev().str(); - int index = ctx()->add_name(name, NAME_ATTR); - ctx()->emit(OP_BUILD_ATTR, index, prev().line); + int index = ctx()->add_name(name); + ctx()->emit(OP_LOAD_ATTR, index, prev().line); if (match(TK("as"))) { consume(TK("@id")); name = prev().str(); } - index = ctx()->add_name(name, name_scope()); - ctx()->emit(OP_STORE_NAME, index, prev().line); + index = ctx()->add_name(name); + ctx()->emit(OP_STORE_GLOBAL, index, prev().line); } while (match(TK(","))); ctx()->emit(OP_POP_TOP, BC_NOARG, BC_KEEPLINE); consume_end_stmt(); @@ -650,7 +600,20 @@ private: } bool try_compile_assignment(){ - + // switch (op) { + // case TK("+="): emit(OP_BINARY_OP, 0); break; + // case TK("-="): emit(OP_BINARY_OP, 1); break; + // case TK("*="): emit(OP_BINARY_OP, 2); break; + // case TK("/="): emit(OP_BINARY_OP, 3); break; + // case TK("//="): emit(OP_BINARY_OP, 4); break; + // case TK("%="): emit(OP_BINARY_OP, 5); break; + // case TK("<<="): emit(OP_BITWISE_OP, 0); break; + // case TK(">>="): emit(OP_BITWISE_OP, 1); break; + // case TK("&="): emit(OP_BITWISE_OP, 2); break; + // case TK("|="): emit(OP_BITWISE_OP, 3); break; + // case TK("^="): emit(OP_BITWISE_OP, 4); break; + // default: UNREACHABLE(); + // } } void compile_stmt() { @@ -728,16 +691,18 @@ private: consume_end_stmt(); } break; case TK("with"): { - EXPR(true); - consume(TK("as")); - consume(TK("@id")); - int index = ctx()->add_name(prev().str(), name_scope()); - emit(OP_STORE_NAME, index); - emit(OP_LOAD_NAME_REF, index); - emit(OP_WITH_ENTER); - compile_block_body(); - emit(OP_LOAD_NAME_REF, index); - emit(OP_WITH_EXIT); + // TODO: reimpl this + UNREACHABLE(); + // EXPR(true); + // consume(TK("as")); + // consume(TK("@id")); + // int index = ctx()->add_name(prev().str(), name_scope()); + // emit(OP_STORE_NAME, index); + // emit(OP_LOAD_NAME_REF, index); + // emit(OP_WITH_ENTER); + // compile_block_body(); + // emit(OP_LOAD_NAME_REF, index); + // emit(OP_WITH_EXIT); } break; /*************************************************/ // TODO: refactor goto/label use special $ syntax @@ -749,21 +714,21 @@ private: consume_end_stmt(); break; case TK("goto"): - if(mode() != EXEC_MODE) SyntaxError("'goto' is only available in EXEC_MODE"); + if(mode()!=EXEC_MODE) SyntaxError("'goto' is only available in EXEC_MODE"); consume(TK(".")); consume(TK("@id")); emit(OP_GOTO, co()->add_name(prev().str(), NAME_SPECIAL)); consume_end_stmt(); break; /*************************************************/ - // dangling expression or assignment + // handle dangling expression or assignment default: { EXPR_TUPLE(true); - bool assigment = try_compile_assignment(); - if(!assigment){ + if(!try_compile_assignment()){ if(mode()==REPL_MODE && name_scope()==NAME_GLOBAL){ emit(OP_PRINT_EXPR, BC_NOARG, BC_KEEPLINE); + }else{ + emit(OP_POP_TOP, BC_NOARG, BC_KEEPLINE); } - emit(OP_POP_TOP, BC_NOARG, BC_KEEPLINE); } consume_end_stmt(); } diff --git a/src/expr.h b/src/expr.h index f66e82c0..8f35faba 100644 --- a/src/expr.h +++ b/src/expr.h @@ -594,4 +594,46 @@ struct TernaryExpr: Expr{ }; -} // namespace pkpy \ No newline at end of file +} // namespace pkpy + + +// struct TupleRef : BaseRef { +// Tuple objs; +// TupleRef(Tuple&& objs) : objs(std::move(objs)) {} + +// PyObject* get(VM* vm, Frame* frame) const{ +// Tuple args(objs.size()); +// for (int i = 0; i < objs.size(); i++) { +// args[i] = vm->PyRef_AS_C(objs[i])->get(vm, frame); +// } +// return VAR(std::move(args)); +// } + +// void set(VM* vm, Frame* frame, PyObject* val) const{ +// val = vm->asIter(val); +// BaseIter* iter = vm->PyIter_AS_C(val); +// for(int i=0; itp_star_wrapper)){ +// auto& star = _CAST(StarWrapper&, objs[i]); +// if(star.rvalue) vm->ValueError("can't use starred expression here"); +// if(i != objs.size()-1) vm->ValueError("* can only be used at the end"); +// auto ref = vm->PyRef_AS_C(star.obj); +// List list; +// while((x = iter->next()) != nullptr) list.push_back(x); +// ref->set(vm, frame, VAR(std::move(list))); +// return; +// }else{ +// x = iter->next(); +// if(x == nullptr) vm->ValueError("not enough values to unpack"); +// vm->PyRef_AS_C(objs[i])->set(vm, frame, x); +// } +// } +// PyObject* x = iter->next(); +// if(x != nullptr) vm->ValueError("too many values to unpack"); +// } + +// void del(VM* vm, Frame* frame) const{ +// for(int i=0; iPyRef_AS_C(objs[i])->del(vm, frame); +// } +// }; \ No newline at end of file diff --git a/src/opcodes.h b/src/opcodes.h index 97a45a22..0a2f2636 100644 --- a/src/opcodes.h +++ b/src/opcodes.h @@ -2,7 +2,7 @@ OPCODE(NO_OP) OPCODE(POP_TOP) -OPCODE(DUP_TOP_VALUE) +OPCODE(DUP_TOP) OPCODE(CALL) OPCODE(CALL_UNPACK) OPCODE(CALL_KWARGS) @@ -57,20 +57,13 @@ OPCODE(LOAD_FALSE) OPCODE(LOAD_EVAL_FN) OPCODE(LOAD_FUNCTION) OPCODE(LOAD_ELLIPSIS) -OPCODE(LOAD_NAME) -OPCODE(LOAD_NAME_REF) OPCODE(ASSERT) OPCODE(EXCEPTION_MATCH) OPCODE(RAISE) OPCODE(RE_RAISE) -OPCODE(BUILD_INDEX) -OPCODE(BUILD_ATTR) -OPCODE(BUILD_ATTR_REF) -OPCODE(STORE_NAME) OPCODE(STORE_FUNCTION) -OPCODE(STORE_REF) OPCODE(TRY_BLOCK_ENTER) OPCODE(TRY_BLOCK_EXIT) diff --git a/src/ref.h b/src/ref.h deleted file mode 100644 index ca33ad18..00000000 --- a/src/ref.h +++ /dev/null @@ -1,179 +0,0 @@ -#pragma once - -#include "obj.h" -#include "vm.h" - -namespace pkpy { - -struct BaseRef { - virtual PyObject* get(VM*, Frame*) const = 0; - virtual void set(VM*, Frame*, PyObject*) const = 0; - virtual void del(VM*, Frame*) const = 0; - virtual ~BaseRef() = default; -}; - -struct NameRef : BaseRef { - const std::pair pair; - StrName name() const { return pair.first; } - NameScope scope() const { return pair.second; } - NameRef(const std::pair& pair) : pair(pair) {} - - PyObject* get(VM* vm, Frame* frame) const{ - PyObject* val; - val = frame->f_locals().try_get(name()); - if(val != nullptr) return val; - val = frame->f_closure_try_get(name()); - if(val != nullptr) return val; - val = frame->f_globals().try_get(name()); - if(val != nullptr) return val; - val = vm->builtins->attr().try_get(name()); - if(val != nullptr) return val; - vm->NameError(name()); - return nullptr; - } - - void set(VM* vm, Frame* frame, PyObject* val) const{ - switch(scope()) { - case NAME_LOCAL: frame->f_locals().set(name(), val); break; - case NAME_GLOBAL: - if(frame->f_locals().try_set(name(), val)) return; - frame->f_globals().set(name(), val); - break; - default: UNREACHABLE(); - } - } - - void del(VM* vm, Frame* frame) const{ - switch(scope()) { - case NAME_LOCAL: { - if(frame->f_locals().contains(name())){ - frame->f_locals().erase(name()); - }else{ - vm->NameError(name()); - } - } break; - case NAME_GLOBAL: - { - if(frame->f_locals().contains(name())){ - frame->f_locals().erase(name()); - }else{ - if(frame->f_globals().contains(name())){ - frame->f_globals().erase(name()); - }else{ - vm->NameError(name()); - } - } - } break; - default: UNREACHABLE(); - } - } -}; - - -struct AttrRef : BaseRef { - mutable PyObject* obj; - NameRef attr; - AttrRef(PyObject* obj, NameRef attr) : obj(obj), attr(attr) {} - - PyObject* get(VM* vm, Frame* frame) const{ - return vm->getattr(obj, attr.name()); - } - - void set(VM* vm, Frame* frame, PyObject* val) const{ - vm->setattr(obj, attr.name(), std::move(val)); - } - -}; - -struct IndexRef : BaseRef { - mutable PyObject* obj; - PyObject* index; - IndexRef(PyObject* obj, PyObject* index) : obj(obj), index(index) {} - - PyObject* get(VM* vm, Frame* frame) const{ - return vm->fast_call(__getitem__, Args{obj, index}); - } - - void set(VM* vm, Frame* frame, PyObject* val) const{ - vm->fast_call(__setitem__, Args{obj, index, val}); - } - - void del(VM* vm, Frame* frame) const{ - vm->fast_call(__delitem__, Args{obj, index}); - } -}; - -struct TupleRef : BaseRef { - Tuple objs; - TupleRef(Tuple&& objs) : objs(std::move(objs)) {} - - PyObject* get(VM* vm, Frame* frame) const{ - Tuple args(objs.size()); - for (int i = 0; i < objs.size(); i++) { - args[i] = vm->PyRef_AS_C(objs[i])->get(vm, frame); - } - return VAR(std::move(args)); - } - - void set(VM* vm, Frame* frame, PyObject* val) const{ - val = vm->asIter(val); - BaseIter* iter = vm->PyIter_AS_C(val); - for(int i=0; itp_star_wrapper)){ - auto& star = _CAST(StarWrapper&, objs[i]); - if(star.rvalue) vm->ValueError("can't use starred expression here"); - if(i != objs.size()-1) vm->ValueError("* can only be used at the end"); - auto ref = vm->PyRef_AS_C(star.obj); - List list; - while((x = iter->next()) != nullptr) list.push_back(x); - ref->set(vm, frame, VAR(std::move(list))); - return; - }else{ - x = iter->next(); - if(x == nullptr) vm->ValueError("not enough values to unpack"); - vm->PyRef_AS_C(objs[i])->set(vm, frame, x); - } - } - PyObject* x = iter->next(); - if(x != nullptr) vm->ValueError("too many values to unpack"); - } - - void del(VM* vm, Frame* frame) const{ - for(int i=0; iPyRef_AS_C(objs[i])->del(vm, frame); - } -}; - - -template -PyObject* VM::PyRef(P&& value) { - static_assert(std::is_base_of_v>); - return heap.gcnew

(tp_ref, std::forward

(value)); -} - -inline const BaseRef* VM::PyRef_AS_C(PyObject* obj) -{ - if(!is_type(obj, tp_ref)) TypeError("expected an l-value"); - return static_cast(obj->value()); -} - -/***** Frame's Impl *****/ -inline void Frame::try_deref(VM* vm, PyObject*& v){ - if(is_type(v, vm->tp_ref)) v = vm->PyRef_AS_C(v)->get(vm, this); -} - -/***** GC's Impl *****/ -template<> inline void _mark(AttrRef& t){ - OBJ_MARK(t.obj); -} - -template<> inline void _mark(IndexRef& t){ - OBJ_MARK(t.obj); - OBJ_MARK(t.index); -} - -template<> inline void _mark(TupleRef& t){ - _mark(t.objs); -} - -} // namespace pkpy \ No newline at end of file