add pointer system

This commit is contained in:
blueloveTH 2022-11-07 15:04:41 +08:00
parent 532f915860
commit c623646501
8 changed files with 192 additions and 210 deletions

View File

@ -3,7 +3,7 @@ with open("src/opcodes.h", "rt", encoding='utf-8') as f:
pipeline = [ pipeline = [
["str.h", "builtins.h"], ["str.h", "builtins.h"],
["obj.h", "iter.h", "parser.h", "codeobject.h"], ["obj.h", "iter.h", "parser.h", "pointer.h", "codeobject.h"],
["error.h", "vm.h", "compiler.h"], ["error.h", "vm.h", "compiler.h"],
["pocketpy.h"] ["pocketpy.h"]
] ]

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "obj.h" #include "obj.h"
#include "pointer.h"
enum Opcode { enum Opcode {
#define OPCODE(name) OP_##name, #define OPCODE(name) OP_##name,
@ -31,28 +32,22 @@ public:
_Str co_name; _Str co_name;
PyVarList co_consts; PyVarList co_consts;
std::vector<_Str> co_names; std::vector<NamePointer> co_name_ptrs;
int addNamePtr(const _Str& name, NameScope scope){
auto p = NamePointer(name, scope);
for(int i=0; i<co_name_ptrs.size(); i++){
if(co_name_ptrs[i] == p) return i;
}
co_name_ptrs.push_back(p);
return co_name_ptrs.size() - 1;
}
int addConst(PyVar v){ int addConst(PyVar v){
co_consts.push_back(v); co_consts.push_back(v);
return co_consts.size() - 1; return co_consts.size() - 1;
} }
int addName(const _Str& name){
auto iter = std::find(co_names.begin(), co_names.end(), name);
if(iter == co_names.end()){
co_names.push_back(name);
return co_names.size() - 1;
}
return iter - co_names.begin();
}
int getNameIndex(const _Str& name){
auto iter = std::find(co_names.begin(), co_names.end(), name);
if(iter == co_names.end()) return -1;
return iter - co_names.begin();
}
_Str toString(){ _Str toString(){
_StrStream ss; _StrStream ss;
int prev_line = -1; int prev_line = -1;
@ -78,9 +73,9 @@ public:
_StrStream names; _StrStream names;
names << "co_names: "; names << "co_names: ";
for(int i=0; i<co_names.size(); i++){ for(int i=0; i<co_name_ptrs.size(); i++){
names << co_names[i]; names << co_name_ptrs[i].name;
if(i != co_names.size() - 1) names << ", "; if(i != co_name_ptrs.size() - 1) names << ", ";
} }
ss << '\n' << consts.str() << '\n' << names.str() << '\n'; ss << '\n' << consts.str() << '\n' << names.str() << '\n';
for(int i=0; i<co_consts.size(); i++){ for(int i=0; i<co_consts.size(); i++){

View File

@ -105,6 +105,12 @@ public:
rules[TK("@id")] = { METHOD(exprName), NO_INFIX }; rules[TK("@id")] = { METHOD(exprName), NO_INFIX };
rules[TK("@num")] = { METHOD(exprLiteral), NO_INFIX }; rules[TK("@num")] = { METHOD(exprLiteral), NO_INFIX };
rules[TK("@str")] = { METHOD(exprLiteral), NO_INFIX }; rules[TK("@str")] = { METHOD(exprLiteral), NO_INFIX };
rules[TK("=")] = { nullptr, METHOD(exprAssign), PREC_ASSIGNMENT };
rules[TK("+=")] = { nullptr, METHOD(exprAssign), PREC_ASSIGNMENT };
rules[TK("-=")] = { nullptr, METHOD(exprAssign), PREC_ASSIGNMENT };
rules[TK("*=")] = { nullptr, METHOD(exprAssign), PREC_ASSIGNMENT };
rules[TK("/=")] = { nullptr, METHOD(exprAssign), PREC_ASSIGNMENT };
rules[TK("//=")] = { nullptr, METHOD(exprAssign), PREC_ASSIGNMENT };
#undef METHOD #undef METHOD
#undef NO_INFIX #undef NO_INFIX
} }
@ -282,18 +288,6 @@ public:
throw SyntaxError(path, parser->current, "expected statement end"); throw SyntaxError(path, parser->current, "expected statement end");
} }
bool matchAssignment() {
if (match(TK("="))) return true;
if (match(TK("+="))) return true;
if (match(TK("-="))) return true;
if (match(TK("*="))) return true;
if (match(TK("/="))) return true;
if (match(TK("//="))) return true;
return false;
}
#define OP_STORE_AUTO (codes.size()==1) ? OP_STORE_NAME : OP_STORE_FAST
void exprLiteral() { void exprLiteral() {
PyVar value = parser->previous.value; PyVar value = parser->previous.value;
int index = getCode()->addConst(value); int index = getCode()->addConst(value);
@ -304,55 +298,41 @@ public:
} }
void exprName() { void exprAssign(){
Token tkname = parser->previous; _TokenType op = parser->previous.type;
_Str name(tkname.start, tkname.length); if(op == TK("=")) { // a = (expr)
int index = getCode()->addName(name); parsePrecedence((Precedence)(rules[op].precedence + 1));
emitCode(OP_STORE_PTR);
if (l_value && matchAssignment()) { }else{ // a += (expr) -> a = a + (expr)
_TokenType assignment = parser->previous.type; // TODO: optimization is needed for inplace operators
matchNewLines(); emitCode(OP_DUP_TOP);
if (assignment == TK("=")) { // name = (expr); parsePrecedence((Precedence)(rules[op].precedence + 1));
compileExpressionTuple(); switch (op) {
} else { // name += / -= / *= ... = (expr); case TK("+="): emitCode(OP_BINARY_OP, 0); break;
emitCode(OP_LOAD_NAME, index); case TK("-="): emitCode(OP_BINARY_OP, 1); break;
compileExpression(); case TK("*="): emitCode(OP_BINARY_OP, 2); break;
emitAssignOp(assignment); case TK("/="): emitCode(OP_BINARY_OP, 3); break;
case TK("//="): emitCode(OP_BINARY_OP, 4); break;
default: UNREACHABLE();
} }
emitCode(OP_STORE_AUTO, index); emitCode(OP_STORE_PTR);
} else { // Just the name and no assignment followed by.
emitCode(OP_LOAD_NAME, index);
}
}
void emitAssignOp(_TokenType assignment){
switch (assignment) {
case TK("+="): emitCode(OP_BINARY_OP, 0); break;
case TK("-="): emitCode(OP_BINARY_OP, 1); break;
case TK("*="): emitCode(OP_BINARY_OP, 2); break;
case TK("/="): emitCode(OP_BINARY_OP, 3); break;
case TK("//="): emitCode(OP_BINARY_OP, 4); break;
default: UNREACHABLE();
} }
} }
void exprOr() { void exprOr() {
int patch = emitCode(OP_JUMP_IF_TRUE_OR_POP); int patch = emitCode(OP_JUMP_IF_TRUE_OR_POP);
matchNewLines();
parsePrecedence(PREC_LOGICAL_OR); parsePrecedence(PREC_LOGICAL_OR);
patchJump(patch); patchJump(patch);
} }
void exprAnd() { void exprAnd() {
int patch = emitCode(OP_JUMP_IF_FALSE_OR_POP); int patch = emitCode(OP_JUMP_IF_FALSE_OR_POP);
matchNewLines();
parsePrecedence(PREC_LOGICAL_AND); parsePrecedence(PREC_LOGICAL_AND);
patchJump(patch); patchJump(patch);
} }
void exprBinaryOp() { void exprBinaryOp() {
_TokenType op = parser->previous.type; _TokenType op = parser->previous.type;
matchNewLines();
parsePrecedence((Precedence)(rules[op].precedence + 1)); parsePrecedence((Precedence)(rules[op].precedence + 1));
switch (op) { switch (op) {
@ -422,38 +402,25 @@ public:
emitCode(OP_CALL, ARGC); emitCode(OP_CALL, ARGC);
} }
void exprName() {
Token tkname = parser->previous;
int index = getCode()->addNamePtr(
tkname.str(),
codes.size()>1 ? NAME_LOCAL : NAME_GLOBAL
);
emitCode(OP_LOAD_NAME_PTR, index);
}
void exprAttrib() { void exprAttrib() {
consume(TK("@id")); consume(TK("@id"));
const _Str& name = parser->previous.str(); const _Str& name = parser->previous.str();
int index = getCode()->addName(name); int index = getCode()->addNamePtr(name, NAME_ATTR);
emitCode(OP_BUILD_ATTR_PTR, index);
if (match(TK("("))) {
emitCode(OP_LOAD_ATTR, index);
exprCall();
return;
}
if (l_value && matchAssignment()) {
_TokenType assignment = parser->previous.type;
matchNewLines();
if (assignment == TK("=")) {
compileExpressionTuple();
} else { // name += / -= / *= ... = (expr);
emitCode(OP_DUP_TOP);
emitCode(OP_LOAD_ATTR, index);
compileExpression();
emitAssignOp(assignment);
}
emitCode(OP_STORE_ATTR, index);
} else {
emitCode(OP_LOAD_ATTR, index);
}
} }
// [:], [:b] // [:], [:b]
// [a], [a:], [a:b] // [a], [a:], [a:b]
void exprSubscript() { void exprSubscript() {
bool slice = false;
if(match(TK(":"))){ if(match(TK(":"))){
emitCode(OP_LOAD_NONE); emitCode(OP_LOAD_NONE);
if(match(TK("]"))){ if(match(TK("]"))){
@ -463,7 +430,6 @@ public:
consume(TK("]")); consume(TK("]"));
} }
emitCode(OP_BUILD_SLICE); emitCode(OP_BUILD_SLICE);
slice = true;
}else{ }else{
compileExpression(); compileExpression();
if(match(TK(":"))){ if(match(TK(":"))){
@ -474,26 +440,12 @@ public:
consume(TK("]")); consume(TK("]"));
} }
emitCode(OP_BUILD_SLICE); emitCode(OP_BUILD_SLICE);
slice = true;
}else{ }else{
consume(TK("]")); consume(TK("]"));
} }
} }
if (l_value && matchAssignment()) { emitCode(OP_BUILD_INDEX_PTR);
if(slice) throw SyntaxError(path, parser->previous, "can't assign to slice");
_TokenType assignment = parser->previous.type;
matchNewLines();
if (assignment == TK("=")) {
compileExpressionTuple();
} else {
UNREACHABLE();
}
emitCode(OP_STORE_SUBSCR);
} else {
emitCode(OP_BINARY_SUBSCR);
}
} }
void exprValue() { void exprValue() {
@ -569,7 +521,7 @@ public:
Token compileImportPath() { Token compileImportPath() {
consume(TK("@id")); consume(TK("@id"));
Token tkmodule = parser->previous; Token tkmodule = parser->previous;
int index = getCode()->addName(tkmodule.str()); int index = getCode()->addNamePtr(tkmodule.str(), NAME_GLOBAL);
emitCode(OP_IMPORT_NAME, index); emitCode(OP_IMPORT_NAME, index);
return tkmodule; return tkmodule;
} }
@ -582,8 +534,8 @@ public:
consume(TK("@id")); consume(TK("@id"));
tkmodule = parser->previous; tkmodule = parser->previous;
} }
int index = getCode()->addName(tkmodule.str()); int index = getCode()->addNamePtr(tkmodule.str(), NAME_GLOBAL);
emitCode(OP_STORE_NAME, index); emitCode(OP_STORE_NAME_PTR, index);
} while (match(TK(",")) && (matchNewLines(), true)); } while (match(TK(",")) && (matchNewLines(), true));
consumeEndStatement(); consumeEndStatement();
} }
@ -650,14 +602,16 @@ public:
void compileForStatement() { void compileForStatement() {
consume(TK("@id")); consume(TK("@id"));
const _Str& iterName = parser->previous.str(); int iterIndex = getCode()->addNamePtr(
int iterIndex = getCode()->addName(iterName); parser->previous.str(),
codes.size()>1 ? NAME_LOCAL : NAME_GLOBAL
);
consume(TK("in")); consume(TK("in"));
compileExpressionTuple(); compileExpressionTuple();
emitCode(OP_GET_ITER); emitCode(OP_GET_ITER);
Loop& loop = enterLoop(true); Loop& loop = enterLoop(true);
int patch = emitCode(OP_FOR_ITER); int patch = emitCode(OP_FOR_ITER);
emitCode(OP_STORE_AUTO, iterIndex); emitCode(OP_STORE_NAME_PTR, iterIndex);
compileBlockBody(); compileBlockBody();
emitCode(OP_JUMP_ABSOLUTE, loop.start); keepOpcodeLine(); emitCode(OP_JUMP_ABSOLUTE, loop.start); keepOpcodeLine();
patchJump(patch); patchJump(patch);
@ -704,15 +658,8 @@ public:
emitCode(OP_RAISE_ERROR); emitCode(OP_RAISE_ERROR);
consumeEndStatement(); consumeEndStatement();
} else if(match(TK("del"))){ } else if(match(TK("del"))){
// TODO: The del implementation is problematic in some cases.
compileExpression(); compileExpression();
ByteCode& lastCode = getCode()->co_code.back(); emitCode(OP_DELETE_PTR);
if(lastCode.op == OP_BINARY_SUBSCR){
lastCode.op = OP_DELETE_SUBSCR;
lastCode.arg = -1;
}else{
throw SyntaxError(path, parser->previous, "you should use 'del a[b]' syntax");
}
consumeEndStatement(); consumeEndStatement();
} else if(match(TK("pass"))){ } else if(match(TK("pass"))){
consumeEndStatement(); consumeEndStatement();
@ -722,7 +669,7 @@ public:
// If last op is not an assignment, pop the result. // If last op is not an assignment, pop the result.
uint8_t lastOp = getCode()->co_code.back().op; uint8_t lastOp = getCode()->co_code.back().op;
if( lastOp != OP_STORE_NAME && lastOp != OP_STORE_FAST && lastOp != OP_STORE_SUBSCR && lastOp != OP_STORE_ATTR){ if( lastOp != OP_STORE_NAME_PTR && lastOp != OP_STORE_PTR){
if(repl_mode && parser->indents.top() == 0){ if(repl_mode && parser->indents.top() == 0){
emitCode(OP_PRINT_EXPR); emitCode(OP_PRINT_EXPR);
} }
@ -733,11 +680,11 @@ public:
void compileClass(){ void compileClass(){
consume(TK("@id")); consume(TK("@id"));
int clsNameIdx = getCode()->addName(parser->previous.str()); int clsNameIdx = getCode()->addNamePtr(parser->previous.str(), NAME_GLOBAL);
int superClsNameIdx = -1; int superClsNameIdx = -1;
if(match(TK("("))){ if(match(TK("("))){
consume(TK("@id")); consume(TK("@id"));
superClsNameIdx = getCode()->addName(parser->previous.str()); superClsNameIdx = getCode()->addNamePtr(parser->previous.str(), NAME_GLOBAL);
consume(TK(")")); consume(TK(")"));
} }
emitCode(OP_LOAD_NONE); emitCode(OP_LOAD_NONE);
@ -746,7 +693,7 @@ public:
isCompilingClass = false; isCompilingClass = false;
if(superClsNameIdx == -1) emitCode(OP_LOAD_NONE); if(superClsNameIdx == -1) emitCode(OP_LOAD_NONE);
else emitCode(OP_LOAD_NAME, superClsNameIdx); else emitCode(OP_LOAD_NAME_PTR, superClsNameIdx);
emitCode(OP_BUILD_CLASS, clsNameIdx); emitCode(OP_BUILD_CLASS, clsNameIdx);
} }

View File

@ -12,12 +12,14 @@
class PyObject; class PyObject;
class CodeObject; class CodeObject;
class BasePointer;
class VM; class VM;
typedef std::shared_ptr<PyObject> PyVar; typedef std::shared_ptr<PyObject> PyVar;
typedef PyVar PyVarOrNull; typedef PyVar PyVarOrNull;
typedef std::vector<PyVar> PyVarList; typedef std::vector<PyVar> PyVarList;
typedef std::unordered_map<_Str, PyVar> StlDict; typedef std::unordered_map<_Str, PyVar> StlDict;
typedef std::shared_ptr<const BasePointer> _Pointer;
typedef PyVar (*_CppFunc)(VM*, PyVarList); typedef PyVar (*_CppFunc)(VM*, PyVarList);
typedef std::shared_ptr<CodeObject> _Code; typedef std::shared_ptr<CodeObject> _Code;
@ -60,7 +62,7 @@ public:
_Iterator(PyVar _ref) : _ref(_ref) {} _Iterator(PyVar _ref) : _ref(_ref) {}
}; };
typedef std::variant<int,float,bool,_Str,PyVarList,_CppFunc,_Func,std::shared_ptr<_Iterator>,BoundedMethod,_Range,_Slice> _Value; typedef std::variant<int,float,bool,_Str,PyVarList,_CppFunc,_Func,std::shared_ptr<_Iterator>,BoundedMethod,_Range,_Slice,_Pointer> _Value;
#define UNREACHABLE() throw std::runtime_error("Unreachable code") #define UNREACHABLE() throw std::runtime_error("Unreachable code")

View File

@ -1,12 +1,7 @@
#ifdef OPCODE #ifdef OPCODE
OPCODE(LOAD_CONST) OPCODE(LOAD_CONST)
OPCODE(LOAD_NAME)
OPCODE(IMPORT_NAME) OPCODE(IMPORT_NAME)
OPCODE(STORE_FAST)
OPCODE(STORE_NAME)
OPCODE(PRINT_EXPR) OPCODE(PRINT_EXPR)
OPCODE(POP_TOP) OPCODE(POP_TOP)
OPCODE(CALL) OPCODE(CALL)
@ -28,13 +23,6 @@ OPCODE(BUILD_MAP)
OPCODE(BUILD_SLICE) OPCODE(BUILD_SLICE)
OPCODE(UNPACK_SEQUENCE) OPCODE(UNPACK_SEQUENCE)
OPCODE(BINARY_SUBSCR)
OPCODE(STORE_SUBSCR)
OPCODE(DELETE_SUBSCR)
OPCODE(LOAD_ATTR)
OPCODE(STORE_ATTR)
OPCODE(GET_ITER) OPCODE(GET_ITER)
OPCODE(FOR_ITER) OPCODE(FOR_ITER)
@ -54,4 +42,11 @@ OPCODE(RAISE_ERROR)
OPCODE(STORE_FUNCTION) OPCODE(STORE_FUNCTION)
OPCODE(BUILD_CLASS) OPCODE(BUILD_CLASS)
OPCODE(LOAD_NAME_PTR) // no arg
OPCODE(BUILD_ATTR_PTR) // arg for the name_ptr, [ptr, name_ptr] -> (*ptr).name_ptr
OPCODE(BUILD_INDEX_PTR) // no arg, [ptr, expr] -> (*ptr)[expr]
OPCODE(STORE_NAME_PTR) // arg for the name_ptr, [expr], directly store to the name_ptr without pushing it to the stack
OPCODE(STORE_PTR) // no arg, [ptr, expr] -> *ptr = expr
OPCODE(DELETE_PTR) // no arg, [ptr] -> [] -> delete ptr
#endif #endif

View File

@ -66,6 +66,7 @@ struct Token{
enum Precedence { enum Precedence {
PREC_NONE, PREC_NONE,
PREC_LOWEST, PREC_LOWEST,
PREC_ASSIGNMENT, // =
PREC_LOGICAL_OR, // or PREC_LOGICAL_OR, // or
PREC_LOGICAL_AND, // and PREC_LOGICAL_AND, // and
PREC_EQUALITY, // == != PREC_EQUALITY, // == !=

47
src/pointer.h Normal file
View File

@ -0,0 +1,47 @@
#pragma once
#include "obj.h"
class Frame;
struct BasePointer {
virtual PyVar get(VM*, Frame*) const = 0;
virtual void set(VM*, Frame*, PyVar) const = 0;
};
enum NameScope {
NAME_LOCAL = 0,
NAME_GLOBAL = 1,
NAME_ATTR = 2,
};
struct NamePointer : BasePointer {
const _Str name;
const NameScope scope;
NamePointer(const _Str& name, NameScope scope) : name(name), scope(scope) {}
PyVar get(VM* vm, Frame* frame) const;
void set(VM* vm, Frame* frame, PyVar val) const;
bool operator==(const NamePointer& other) const {
return name == other.name && scope == other.scope;
}
};
struct AttrPointer : BasePointer {
const _Pointer root;
const NamePointer* attr;
AttrPointer(const _Pointer& root, const NamePointer* attr) : root(root), attr(attr) {}
PyVar get(VM* vm, Frame* frame) const;
void set(VM* vm, Frame* frame, PyVar val) const;
};
struct IndexPointer : BasePointer {
const _Pointer root;
const PyVar index;
IndexPointer(_Pointer root, PyVar index) : root(root), index(index) {}
PyVar get(VM* vm, Frame* frame) const;
void set(VM* vm, Frame* frame, PyVar val) const;
};

147
src/vm.h
View File

@ -136,46 +136,33 @@ public:
switch (byte.op) switch (byte.op)
{ {
case OP_LOAD_CONST: case OP_LOAD_CONST: frame->pushValue(frame->code->co_consts[byte.arg]); break;
frame->pushValue(frame->code->co_consts[byte.arg]); case OP_LOAD_NAME_PTR: {
break; const NamePointer* p = &frame->code->co_name_ptrs[byte.arg];
case OP_LOAD_NAME: frame->pushValue(PyPointer(_Pointer(p)));
{ } break;
const _Str& name = frame->code->co_names[byte.arg]; case OP_STORE_NAME_PTR: {
auto it = frame->f_locals.find(name); const NamePointer& p = frame->code->co_name_ptrs[byte.arg];
if(it != frame->f_locals.end()){ p.set(this, frame.get(), frame->popValue());
frame->pushValue(it->second); } break;
break; case OP_BUILD_ATTR_PTR: {
} const NamePointer* p = &frame->code->co_name_ptrs[byte.arg];
_Pointer root = PyPointer_AS_C(frame->popValue());
it = frame->f_globals->find(name); frame->pushValue(PyPointer(
if(it != frame->f_globals->end()){ std::make_shared<AttrPointer>(root, p)
frame->pushValue(it->second); ));
break; } break;
} case OP_BUILD_INDEX_PTR: {
PyVar index = frame->popValue();
it = builtins->attribs.find(name); _Pointer root = PyPointer_AS_C(frame->popValue());
if(it != builtins->attribs.end()){ frame->pushValue(PyPointer(
frame->pushValue(it->second); std::make_shared<IndexPointer>(root, index)
break; ));
} } break;
case OP_STORE_PTR: {
nameError(name); _Pointer p = PyPointer_AS_C(frame->popValue());
} break; p->set(this, frame.get(), frame->popValue());
case OP_STORE_FAST: } break;
{
const _Str& name = frame->code->co_names[byte.arg];
frame->f_locals[name] = frame->popValue();
} break;
case OP_STORE_NAME:
{
const _Str& name = frame->code->co_names[byte.arg];
if(frame->f_locals.find(name) != frame->f_locals.end()){
frame->f_locals[name] = frame->popValue();
}else{
frame->f_globals->operator[](name) = frame->popValue();
}
} break;
case OP_STORE_FUNCTION: case OP_STORE_FUNCTION:
{ {
PyVar obj = frame->popValue(); PyVar obj = frame->popValue();
@ -184,7 +171,7 @@ public:
} break; } break;
case OP_BUILD_CLASS: case OP_BUILD_CLASS:
{ {
_Str clsName = frame->code->co_names[byte.arg]; const _Str& clsName = frame->code->co_name_ptrs[byte.arg].name;
PyVar clsBase = frame->popValue(); PyVar clsBase = frame->popValue();
if(clsBase == None) clsBase = _tp_object; if(clsBase == None) clsBase = _tp_object;
__checkType(clsBase, _tp_type); __checkType(clsBase, _tp_type);
@ -248,19 +235,6 @@ public:
PyVar obj_bool = asBool(obj); PyVar obj_bool = asBool(obj);
frame->pushValue(PyBool(!PyBool_AS_C(obj_bool))); frame->pushValue(PyBool(!PyBool_AS_C(obj_bool)));
} break; } break;
case OP_LOAD_ATTR:
{
PyVar obj = frame->popValue();
const _Str& name = frame->code->co_names[byte.arg];
frame->pushValue(getAttr(obj, name));
} break;
case OP_STORE_ATTR:
{
PyVar value = frame->popValue();
PyVar obj = frame->popValue();
const _Str& name = frame->code->co_names[byte.arg];
setAttr(obj, name, value);
} break;
case OP_POP_JUMP_IF_FALSE: case OP_POP_JUMP_IF_FALSE:
if(!PyBool_AS_C(asBool(frame->popValue()))) frame->jumpTo(byte.arg); if(!PyBool_AS_C(asBool(frame->popValue()))) frame->jumpTo(byte.arg);
break; break;
@ -294,19 +268,6 @@ public:
PyVarList items = frame->popNReversed(byte.arg); PyVarList items = frame->popNReversed(byte.arg);
frame->pushValue(PyTuple(items)); frame->pushValue(PyTuple(items));
} break; } break;
case OP_BINARY_SUBSCR:
{
PyVar key = frame->popValue();
PyVar obj = frame->popValue();
frame->pushValue(call(obj, __getitem__, {key}));
} break;
case OP_STORE_SUBSCR:
{
PyVar value = frame->popValue();
PyVar key = frame->popValue();
PyVar obj = frame->popValue();
call(obj, __setitem__, {key, value});
} break;
case OP_DUP_TOP: frame->pushValue(frame->topValue()); break; case OP_DUP_TOP: frame->pushValue(frame->topValue()); break;
case OP_CALL: case OP_CALL:
{ {
@ -363,7 +324,7 @@ public:
} break; } break;
case OP_IMPORT_NAME: case OP_IMPORT_NAME:
{ {
const _Str& name = frame->code->co_names[byte.arg]; const _Str& name = frame->code->co_name_ptrs[byte.arg].name;
auto it = _modules.find(name); auto it = _modules.find(name);
if(it == _modules.end()){ if(it == _modules.end()){
_error("ImportError", "module '" + name + "' not found"); _error("ImportError", "module '" + name + "' not found");
@ -371,12 +332,6 @@ public:
frame->pushValue(it->second); frame->pushValue(it->second);
} }
} break; } break;
case OP_DELETE_SUBSCR:
{
PyVar index = frame->popValue();
PyVar obj = frame->popValue();
call(obj, "__delitem__", {index});
} break;
default: default:
_error("SystemError", _Str("opcode ") + OP_NAMES[byte.op] + " is not implemented"); _error("SystemError", _Str("opcode ") + OP_NAMES[byte.op] + " is not implemented");
break; break;
@ -525,7 +480,7 @@ public:
PyVar _tp_object, _tp_type, _tp_int, _tp_float, _tp_bool, _tp_str; PyVar _tp_object, _tp_type, _tp_int, _tp_float, _tp_bool, _tp_str;
PyVar _tp_list, _tp_tuple; PyVar _tp_list, _tp_tuple;
PyVar _tp_function, _tp_native_function, _tp_native_iterator, _tp_bounded_method; PyVar _tp_function, _tp_native_function, _tp_native_iterator, _tp_bounded_method;
PyVar _tp_slice, _tp_range, _tp_module; PyVar _tp_slice, _tp_range, _tp_module, _tp_pointer;
DEF_NATIVE(Int, int, _tp_int) DEF_NATIVE(Int, int, _tp_int)
DEF_NATIVE(Float, float, _tp_float) DEF_NATIVE(Float, float, _tp_float)
@ -538,6 +493,7 @@ public:
DEF_NATIVE(BoundedMethod, BoundedMethod, _tp_bounded_method) DEF_NATIVE(BoundedMethod, BoundedMethod, _tp_bounded_method)
DEF_NATIVE(Range, _Range, _tp_range) DEF_NATIVE(Range, _Range, _tp_range)
DEF_NATIVE(Slice, _Slice, _tp_slice) DEF_NATIVE(Slice, _Slice, _tp_slice)
DEF_NATIVE(Pointer, _Pointer, _tp_pointer)
inline bool PyBool_AS_C(PyVar obj){return obj == True;} inline bool PyBool_AS_C(PyVar obj){return obj == True;}
inline PyVar PyBool(bool value){return value ? True : False;} inline PyVar PyBool(bool value){return value ? True : False;}
@ -558,6 +514,7 @@ public:
_tp_slice = newClassType("slice"); _tp_slice = newClassType("slice");
_tp_range = newClassType("range"); _tp_range = newClassType("range");
_tp_module = newClassType("module"); _tp_module = newClassType("module");
_tp_pointer = newClassType("_pointer");
newClassType("NoneType"); newClassType("NoneType");
@ -605,4 +562,42 @@ public:
exec(code, {}, _m); exec(code, {}, _m);
_modules[name] = _m; _modules[name] = _m;
} }
}; };
/**************** Pointers' Impl ****************/
PyVar NamePointer::get(VM* vm, Frame* frame) const{
switch(scope) {
case NAME_LOCAL: frame->f_locals[name] = frame->popValue(); break;
case NAME_GLOBAL: frame->f_globals->operator[](name) = frame->popValue(); break;
}
UNREACHABLE();
}
void NamePointer::set(VM* vm, Frame* frame, PyVar val) const{
switch(scope) {
case NAME_LOCAL: frame->f_locals[name] = val; break;
case NAME_GLOBAL: frame->f_globals->operator[](name) = val; break;
}
UNREACHABLE();
}
PyVar AttrPointer::get(VM* vm, Frame* frame) const{
PyVar obj = root->get(vm, frame);
return vm->getAttr(obj, attr->name);
}
void AttrPointer::set(VM* vm, Frame* frame, PyVar val) const{
PyVar obj = root->get(vm, frame);
vm->setAttr(obj, attr->name, val);
}
PyVar IndexPointer::get(VM* vm, Frame* frame) const{
PyVar obj = root->get(vm, frame);
return vm->call(obj, __getitem__, {index});
}
void IndexPointer::set(VM* vm, Frame* frame, PyVar val) const{
PyVar obj = root->get(vm, frame);
vm->call(obj, __setitem__, {index, val});
}