mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-21 12:00:18 +00:00
add pointer system
This commit is contained in:
parent
532f915860
commit
c623646501
@ -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"]
|
||||||
]
|
]
|
||||||
|
@ -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++){
|
||||||
|
139
src/compiler.h
139
src/compiler.h
@ -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,29 +298,16 @@ 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);
|
|
||||||
emitCode(OP_LOAD_NAME, index);
|
|
||||||
compileExpression();
|
|
||||||
emitAssignOp(assignment);
|
|
||||||
}
|
|
||||||
emitCode(OP_STORE_AUTO, index);
|
|
||||||
} 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, 0); break;
|
||||||
case TK("-="): emitCode(OP_BINARY_OP, 1); break;
|
case TK("-="): emitCode(OP_BINARY_OP, 1); break;
|
||||||
case TK("*="): emitCode(OP_BINARY_OP, 2); break;
|
case TK("*="): emitCode(OP_BINARY_OP, 2); break;
|
||||||
@ -334,25 +315,24 @@ public:
|
|||||||
case TK("//="): emitCode(OP_BINARY_OP, 4); break;
|
case TK("//="): emitCode(OP_BINARY_OP, 4); break;
|
||||||
default: UNREACHABLE();
|
default: UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
emitCode(OP_STORE_PTR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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")
|
||||||
|
|
||||||
|
@ -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
|
@ -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
47
src/pointer.h
Normal 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;
|
||||||
|
};
|
139
src/vm.h
139
src/vm.h
@ -136,45 +136,32 @@ 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)));
|
||||||
{
|
|
||||||
const _Str& name = frame->code->co_names[byte.arg];
|
|
||||||
auto it = frame->f_locals.find(name);
|
|
||||||
if(it != frame->f_locals.end()){
|
|
||||||
frame->pushValue(it->second);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
it = frame->f_globals->find(name);
|
|
||||||
if(it != frame->f_globals->end()){
|
|
||||||
frame->pushValue(it->second);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
it = builtins->attribs.find(name);
|
|
||||||
if(it != builtins->attribs.end()){
|
|
||||||
frame->pushValue(it->second);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
nameError(name);
|
|
||||||
} break;
|
} break;
|
||||||
case OP_STORE_FAST:
|
case OP_STORE_NAME_PTR: {
|
||||||
{
|
const NamePointer& p = frame->code->co_name_ptrs[byte.arg];
|
||||||
const _Str& name = frame->code->co_names[byte.arg];
|
p.set(this, frame.get(), frame->popValue());
|
||||||
frame->f_locals[name] = frame->popValue();
|
|
||||||
} break;
|
} break;
|
||||||
case OP_STORE_NAME:
|
case OP_BUILD_ATTR_PTR: {
|
||||||
{
|
const NamePointer* p = &frame->code->co_name_ptrs[byte.arg];
|
||||||
const _Str& name = frame->code->co_names[byte.arg];
|
_Pointer root = PyPointer_AS_C(frame->popValue());
|
||||||
if(frame->f_locals.find(name) != frame->f_locals.end()){
|
frame->pushValue(PyPointer(
|
||||||
frame->f_locals[name] = frame->popValue();
|
std::make_shared<AttrPointer>(root, p)
|
||||||
}else{
|
));
|
||||||
frame->f_globals->operator[](name) = frame->popValue();
|
} break;
|
||||||
}
|
case OP_BUILD_INDEX_PTR: {
|
||||||
|
PyVar index = frame->popValue();
|
||||||
|
_Pointer root = PyPointer_AS_C(frame->popValue());
|
||||||
|
frame->pushValue(PyPointer(
|
||||||
|
std::make_shared<IndexPointer>(root, index)
|
||||||
|
));
|
||||||
|
} break;
|
||||||
|
case OP_STORE_PTR: {
|
||||||
|
_Pointer p = PyPointer_AS_C(frame->popValue());
|
||||||
|
p->set(this, frame.get(), frame->popValue());
|
||||||
} break;
|
} break;
|
||||||
case OP_STORE_FUNCTION:
|
case OP_STORE_FUNCTION:
|
||||||
{
|
{
|
||||||
@ -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");
|
||||||
|
|
||||||
@ -606,3 +563,41 @@ public:
|
|||||||
_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});
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user