mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-21 20:10:17 +00:00
up
This commit is contained in:
parent
449fb9a2f8
commit
d54cd84138
@ -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"]
|
||||
]
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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,
|
||||
|
197
src/compiler.h
197
src/compiler.h
@ -24,10 +24,18 @@ class Compiler {
|
||||
std::unique_ptr<Lexer> lexer;
|
||||
stack<CodeEmitContext> contexts;
|
||||
std::map<TokenIndex, PrattRule> rules;
|
||||
bool used = false;
|
||||
VM* vm;
|
||||
bool used;
|
||||
// for parsing token stream
|
||||
int i = 0;
|
||||
std::vector<Token> 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<Lexer>(
|
||||
make_sp<SourceData>(source, filename, mode)
|
||||
);
|
||||
@ -60,25 +70,32 @@ public:
|
||||
#define METHOD(name) &Compiler::name
|
||||
#define NO_INFIX nullptr, PREC_NONE
|
||||
for(TokenIndex i=0; i<kTokenCount; i++) rules[i] = { nullptr, NO_INFIX };
|
||||
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(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<Token> 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 <typename T, typename... Args>
|
||||
@ -179,8 +182,6 @@ private:
|
||||
return expr;
|
||||
}
|
||||
|
||||
/********************************************/
|
||||
|
||||
// PASS
|
||||
void exprLiteral(){
|
||||
ctx()->s_expr.push(make_expr<LiteralExpr>(prev().value));
|
||||
@ -201,63 +202,12 @@ private:
|
||||
consume(TK(":"));
|
||||
}
|
||||
e->func.code = push_context(lexer->src, "<lambda>");
|
||||
// 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<TupleExpr>();
|
||||
@ -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();
|
||||
}
|
||||
|
44
src/expr.h
44
src/expr.h
@ -594,4 +594,46 @@ struct TernaryExpr: Expr{
|
||||
};
|
||||
|
||||
|
||||
} // namespace pkpy
|
||||
} // 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; i<objs.size(); i++){
|
||||
// PyObject* x;
|
||||
// if(is_type(objs[i], vm->tp_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; i<objs.size(); i++) vm->PyRef_AS_C(objs[i])->del(vm, frame);
|
||||
// }
|
||||
// };
|
@ -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)
|
||||
|
179
src/ref.h
179
src/ref.h
@ -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<StrName, NameScope> pair;
|
||||
StrName name() const { return pair.first; }
|
||||
NameScope scope() const { return pair.second; }
|
||||
NameRef(const std::pair<StrName, NameScope>& 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; i<objs.size(); i++){
|
||||
PyObject* x;
|
||||
if(is_type(objs[i], vm->tp_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; i<objs.size(); i++) vm->PyRef_AS_C(objs[i])->del(vm, frame);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename P>
|
||||
PyObject* VM::PyRef(P&& value) {
|
||||
static_assert(std::is_base_of_v<BaseRef, std::decay_t<P>>);
|
||||
return heap.gcnew<P>(tp_ref, std::forward<P>(value));
|
||||
}
|
||||
|
||||
inline const BaseRef* VM::PyRef_AS_C(PyObject* obj)
|
||||
{
|
||||
if(!is_type(obj, tp_ref)) TypeError("expected an l-value");
|
||||
return static_cast<const BaseRef*>(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>(AttrRef& t){
|
||||
OBJ_MARK(t.obj);
|
||||
}
|
||||
|
||||
template<> inline void _mark<IndexRef>(IndexRef& t){
|
||||
OBJ_MARK(t.obj);
|
||||
OBJ_MARK(t.index);
|
||||
}
|
||||
|
||||
template<> inline void _mark<TupleRef>(TupleRef& t){
|
||||
_mark<Tuple>(t.objs);
|
||||
}
|
||||
|
||||
} // namespace pkpy
|
Loading…
x
Reference in New Issue
Block a user