This commit is contained in:
blueloveTH 2023-01-11 18:07:38 +08:00
parent 944f98be6f
commit 3a0c495e78
4 changed files with 200 additions and 214 deletions

View File

@ -1029,7 +1029,7 @@ __LISTCOMP:
if(match(TK("-"))){ if(match(TK("-"))){
consume(TK("@num")); consume(TK("@num"));
PyVar val = parser->prev.value; PyVar val = parser->prev.value;
return vm->numNegated(val); return vm->num_negated(val);
} }
if(match(TK("@num"))) return parser->prev.value; if(match(TK("@num"))) return parser->prev.value;
if(match(TK("@str"))) return parser->prev.value; if(match(TK("@str"))) return parser->prev.value;

View File

@ -1,11 +1,10 @@
#ifdef OPCODE #ifdef OPCODE
OPCODE(NO_OP) OPCODE(NO_OP)
OPCODE(DELETED_OP)
OPCODE(IMPORT_NAME) OPCODE(IMPORT_NAME)
OPCODE(PRINT_EXPR) OPCODE(PRINT_EXPR)
OPCODE(POP_TOP) OPCODE(POP_TOP)
OPCODE(DUP_TOP)
OPCODE(CALL) OPCODE(CALL)
OPCODE(RETURN_VALUE) OPCODE(RETURN_VALUE)
@ -18,8 +17,6 @@ OPCODE(CONTAINS_OP)
OPCODE(UNARY_NEGATIVE) OPCODE(UNARY_NEGATIVE)
OPCODE(UNARY_NOT) OPCODE(UNARY_NOT)
OPCODE(DUP_TOP)
OPCODE(BUILD_LIST) OPCODE(BUILD_LIST)
OPCODE(BUILD_MAP) OPCODE(BUILD_MAP)
OPCODE(BUILD_SET) OPCODE(BUILD_SET)
@ -30,6 +27,11 @@ OPCODE(LIST_APPEND)
OPCODE(GET_ITER) OPCODE(GET_ITER)
OPCODE(FOR_ITER) OPCODE(FOR_ITER)
OPCODE(WITH_ENTER)
OPCODE(WITH_EXIT)
OPCODE(LOOP_BREAK)
OPCODE(LOOP_CONTINUE)
OPCODE(POP_JUMP_IF_FALSE) OPCODE(POP_JUMP_IF_FALSE)
OPCODE(JUMP_ABSOLUTE) OPCODE(JUMP_ABSOLUTE)
OPCODE(SAFE_JUMP_ABSOLUTE) OPCODE(SAFE_JUMP_ABSOLUTE)
@ -44,30 +46,22 @@ OPCODE(LOAD_EVAL_FN)
OPCODE(LOAD_LAMBDA) OPCODE(LOAD_LAMBDA)
OPCODE(LOAD_ELLIPSIS) OPCODE(LOAD_ELLIPSIS)
OPCODE(LOAD_NAME) OPCODE(LOAD_NAME)
OPCODE(LOAD_NAME_REF) // no arg OPCODE(LOAD_NAME_REF)
OPCODE(ASSERT) OPCODE(ASSERT)
OPCODE(RAISE_ERROR) OPCODE(RAISE_ERROR)
OPCODE(STORE_FUNCTION) OPCODE(STORE_FUNCTION)
OPCODE(BUILD_CLASS) OPCODE(BUILD_CLASS)
OPCODE(BUILD_ATTR_REF) // arg for the name_ptr, [ptr, name_ptr] -> (*ptr).name_ptr OPCODE(BUILD_ATTR_REF)
OPCODE(BUILD_INDEX_REF) // no arg, [ptr, expr] -> (*ptr)[expr] OPCODE(BUILD_INDEX_REF)
OPCODE(STORE_NAME_REF) // arg for the name_ptr, [expr], directly store to the name_ptr without pushing it to the stack OPCODE(STORE_NAME_REF)
OPCODE(STORE_REF) // no arg, [ptr, expr] -> *ptr = expr OPCODE(STORE_REF)
OPCODE(DELETE_REF) // no arg, [ptr] -> [] -> delete ptr OPCODE(DELETE_REF)
OPCODE(BUILD_SMART_TUPLE) // if all elements are pointers, build a compound pointer, otherwise build a tuple OPCODE(BUILD_SMART_TUPLE)
OPCODE(BUILD_STRING) // arg is the expr count, build a string from the top of the stack OPCODE(BUILD_STRING)
OPCODE(GOTO) OPCODE(GOTO)
OPCODE(WITH_ENTER)
OPCODE(WITH_EXIT)
OPCODE(RAISE_VARARGS)
OPCODE(LOOP_BREAK)
OPCODE(LOOP_CONTINUE)
#endif #endif

View File

@ -17,22 +17,22 @@ _Code VM::compile(_Str source, _Str filename, CompileMode mode) {
#define BIND_NUM_ARITH_OPT(name, op) \ #define BIND_NUM_ARITH_OPT(name, op) \
_vm->bindMethodMulti({"int","float"}, #name, [](VM* vm, const pkpy::ArgList& args){ \ _vm->bindMethodMulti({"int","float"}, #name, [](VM* vm, const pkpy::ArgList& args){ \
if(!vm->isIntOrFloat(args[0], args[1])) \ if(!vm->is_int_or_float(args[0], args[1])) \
vm->typeError("unsupported operand type(s) for " #op ); \ vm->typeError("unsupported operand type(s) for " #op ); \
if(args._index(0)->isType(vm->_tp_int) && args._index(1)->isType(vm->_tp_int)){ \ if(args._index(0)->isType(vm->_tp_int) && args._index(1)->isType(vm->_tp_int)){ \
return vm->PyInt(vm->PyInt_AS_C(args._index(0)) op vm->PyInt_AS_C(args._index(1))); \ return vm->PyInt(vm->PyInt_AS_C(args._index(0)) op vm->PyInt_AS_C(args._index(1))); \
}else{ \ }else{ \
return vm->PyFloat(vm->numToFloat(args._index(0)) op vm->numToFloat(args._index(1))); \ return vm->PyFloat(vm->num_to_float(args._index(0)) op vm->num_to_float(args._index(1))); \
} \ } \
}); });
#define BIND_NUM_LOGICAL_OPT(name, op, is_eq) \ #define BIND_NUM_LOGICAL_OPT(name, op, is_eq) \
_vm->bindMethodMulti({"int","float"}, #name, [](VM* vm, const pkpy::ArgList& args){ \ _vm->bindMethodMulti({"int","float"}, #name, [](VM* vm, const pkpy::ArgList& args){ \
if(!vm->isIntOrFloat(args[0], args[1])){ \ if(!vm->is_int_or_float(args[0], args[1])){ \
if constexpr(is_eq) return vm->PyBool(args[0] == args[1]); \ if constexpr(is_eq) return vm->PyBool(args[0] == args[1]); \
vm->typeError("unsupported operand type(s) for " #op ); \ vm->typeError("unsupported operand type(s) for " #op ); \
} \ } \
return vm->PyBool(vm->numToFloat(args._index(0)) op vm->numToFloat(args._index(1))); \ return vm->PyBool(vm->num_to_float(args._index(0)) op vm->num_to_float(args._index(1))); \
}); });
@ -51,62 +51,62 @@ void __initializeBuiltinFunctions(VM* _vm) {
#undef BIND_NUM_LOGICAL_OPT #undef BIND_NUM_LOGICAL_OPT
_vm->bindBuiltinFunc("__sys_stdout_write", [](VM* vm, const pkpy::ArgList& args) { _vm->bindBuiltinFunc("__sys_stdout_write", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1); vm->check_args_size(args, 1);
(*vm->_stdout) << vm->PyStr_AS_C(args[0]); (*vm->_stdout) << vm->PyStr_AS_C(args[0]);
return vm->None; return vm->None;
}); });
_vm->bindBuiltinFunc("super", [](VM* vm, const pkpy::ArgList& args) { _vm->bindBuiltinFunc("super", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 0); vm->check_args_size(args, 0);
auto it = vm->topFrame()->f_locals.find(m_self); auto it = vm->top_frame()->f_locals.find(m_self);
if(it == vm->topFrame()->f_locals.end()) vm->typeError("super() can only be called in a class method"); if(it == vm->top_frame()->f_locals.end()) vm->typeError("super() can only be called in a class method");
return vm->newObject(vm->_tp_super, it->second); return vm->new_object(vm->_tp_super, it->second);
}); });
_vm->bindBuiltinFunc("eval", [](VM* vm, const pkpy::ArgList& args) { _vm->bindBuiltinFunc("eval", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1); vm->check_args_size(args, 1);
const _Str& expr = vm->PyStr_AS_C(args[0]); const _Str& expr = vm->PyStr_AS_C(args[0]);
_Code code = vm->compile(expr, "<eval>", EVAL_MODE); _Code code = vm->compile(expr, "<eval>", EVAL_MODE);
return vm->_exec(code, vm->topFrame()->_module, vm->topFrame()->f_locals_copy()); return vm->_exec(code, vm->top_frame()->_module, vm->top_frame()->f_locals_copy());
}); });
_vm->bindBuiltinFunc("isinstance", [](VM* vm, const pkpy::ArgList& args) { _vm->bindBuiltinFunc("isinstance", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 2); vm->check_args_size(args, 2);
return vm->PyBool(vm->isInstance(args[0], args[1])); return vm->PyBool(vm->isinstance(args[0], args[1]));
}); });
_vm->bindBuiltinFunc("repr", [](VM* vm, const pkpy::ArgList& args) { _vm->bindBuiltinFunc("repr", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1); vm->check_args_size(args, 1);
return vm->asRepr(args[0]); return vm->asRepr(args[0]);
}); });
_vm->bindBuiltinFunc("hash", [](VM* vm, const pkpy::ArgList& args) { _vm->bindBuiltinFunc("hash", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1); vm->check_args_size(args, 1);
return vm->PyInt(vm->hash(args[0])); return vm->PyInt(vm->hash(args[0]));
}); });
_vm->bindBuiltinFunc("len", [](VM* vm, const pkpy::ArgList& args) { _vm->bindBuiltinFunc("len", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1); vm->check_args_size(args, 1);
return vm->call(args[0], __len__, pkpy::noArg()); return vm->call(args[0], __len__, pkpy::noArg());
}); });
_vm->bindBuiltinFunc("chr", [](VM* vm, const pkpy::ArgList& args) { _vm->bindBuiltinFunc("chr", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1); vm->check_args_size(args, 1);
_Int i = vm->PyInt_AS_C(args[0]); _Int i = vm->PyInt_AS_C(args[0]);
if (i < 0 || i > 128) vm->valueError("chr() arg not in range(128)"); if (i < 0 || i > 128) vm->valueError("chr() arg not in range(128)");
return vm->PyStr(std::string(1, (char)i)); return vm->PyStr(std::string(1, (char)i));
}); });
_vm->bindBuiltinFunc("ord", [](VM* vm, const pkpy::ArgList& args) { _vm->bindBuiltinFunc("ord", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1); vm->check_args_size(args, 1);
_Str s = vm->PyStr_AS_C(args[0]); _Str s = vm->PyStr_AS_C(args[0]);
if (s.size() != 1) vm->typeError("ord() expected an ASCII character"); if (s.size() != 1) vm->typeError("ord() expected an ASCII character");
return vm->PyInt((_Int)s[0]); return vm->PyInt((_Int)s[0]);
}); });
_vm->bindBuiltinFunc("globals", [](VM* vm, const pkpy::ArgList& args) { _vm->bindBuiltinFunc("globals", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 0); vm->check_args_size(args, 0);
const auto& d = vm->topFrame()->f_globals(); const auto& d = vm->top_frame()->f_globals();
PyVar obj = vm->call(vm->builtins->attribs["dict"]); PyVar obj = vm->call(vm->builtins->attribs["dict"]);
for (const auto& [k, v] : d) { for (const auto& [k, v] : d) {
vm->call(obj, __setitem__, pkpy::twoArgs(vm->PyStr(k), v)); vm->call(obj, __setitem__, pkpy::twoArgs(vm->PyStr(k), v));
@ -115,8 +115,8 @@ void __initializeBuiltinFunctions(VM* _vm) {
}); });
_vm->bindBuiltinFunc("locals", [](VM* vm, const pkpy::ArgList& args) { _vm->bindBuiltinFunc("locals", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 0); vm->check_args_size(args, 0);
const auto& d = vm->topFrame()->f_locals; const auto& d = vm->top_frame()->f_locals;
PyVar obj = vm->call(vm->builtins->attribs["dict"]); PyVar obj = vm->call(vm->builtins->attribs["dict"]);
for (const auto& [k, v] : d) { for (const auto& [k, v] : d) {
vm->call(obj, __setitem__, pkpy::twoArgs(vm->PyStr(k), v)); vm->call(obj, __setitem__, pkpy::twoArgs(vm->PyStr(k), v));
@ -125,14 +125,14 @@ void __initializeBuiltinFunctions(VM* _vm) {
}); });
_vm->bindBuiltinFunc("hex", [](VM* vm, const pkpy::ArgList& args) { _vm->bindBuiltinFunc("hex", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1); vm->check_args_size(args, 1);
std::stringstream ss; std::stringstream ss;
ss << std::hex << vm->PyInt_AS_C(args[0]); ss << std::hex << vm->PyInt_AS_C(args[0]);
return vm->PyStr("0x" + ss.str()); return vm->PyStr("0x" + ss.str());
}); });
_vm->bindBuiltinFunc("dir", [](VM* vm, const pkpy::ArgList& args) { _vm->bindBuiltinFunc("dir", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1); vm->check_args_size(args, 1);
std::vector<_Str> names; std::vector<_Str> names;
for (auto& [k, _] : args[0]->attribs) names.push_back(k); for (auto& [k, _] : args[0]->attribs) names.push_back(k);
for (auto& [k, _] : args[0]->_type->attribs) { for (auto& [k, _] : args[0]->_type->attribs) {
@ -156,12 +156,12 @@ void __initializeBuiltinFunctions(VM* _vm) {
}); });
_vm->bindMethod("type", "__new__", [](VM* vm, const pkpy::ArgList& args) { _vm->bindMethod("type", "__new__", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1); vm->check_args_size(args, 1);
return args[0]->_type; return args[0]->_type;
}); });
_vm->bindMethod("type", "__eq__", [](VM* vm, const pkpy::ArgList& args) { _vm->bindMethod("type", "__eq__", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 2, true); vm->check_args_size(args, 2, true);
return vm->PyBool(args[0] == args[1]); return vm->PyBool(args[0] == args[1]);
}); });
@ -177,7 +177,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
}); });
_vm->bindMethod("range", "__iter__", [](VM* vm, const pkpy::ArgList& args) { _vm->bindMethod("range", "__iter__", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkType(args[0], vm->_tp_range); vm->check_type(args[0], vm->_tp_range);
return vm->PyIter( return vm->PyIter(
pkpy::make_shared<BaseIterator, RangeIterator>(vm, args[0]) pkpy::make_shared<BaseIterator, RangeIterator>(vm, args[0])
); );
@ -196,27 +196,27 @@ void __initializeBuiltinFunctions(VM* _vm) {
}); });
_vm->bindMethodMulti({"int", "float"}, "__truediv__", [](VM* vm, const pkpy::ArgList& args) { _vm->bindMethodMulti({"int", "float"}, "__truediv__", [](VM* vm, const pkpy::ArgList& args) {
if(!vm->isIntOrFloat(args[0], args[1])) if(!vm->is_int_or_float(args[0], args[1]))
vm->typeError("unsupported operand type(s) for " "/" ); vm->typeError("unsupported operand type(s) for " "/" );
_Float rhs = vm->numToFloat(args[1]); _Float rhs = vm->num_to_float(args[1]);
if (rhs == 0) vm->zeroDivisionError(); if (rhs == 0) vm->zeroDivisionError();
return vm->PyFloat(vm->numToFloat(args[0]) / rhs); return vm->PyFloat(vm->num_to_float(args[0]) / rhs);
}); });
_vm->bindMethodMulti({"int", "float"}, "__pow__", [](VM* vm, const pkpy::ArgList& args) { _vm->bindMethodMulti({"int", "float"}, "__pow__", [](VM* vm, const pkpy::ArgList& args) {
if(!vm->isIntOrFloat(args[0], args[1])) if(!vm->is_int_or_float(args[0], args[1]))
vm->typeError("unsupported operand type(s) for " "**" ); vm->typeError("unsupported operand type(s) for " "**" );
if(args[0]->isType(vm->_tp_int) && args[1]->isType(vm->_tp_int)){ if(args[0]->isType(vm->_tp_int) && args[1]->isType(vm->_tp_int)){
return vm->PyInt((_Int)round(pow(vm->PyInt_AS_C(args[0]), vm->PyInt_AS_C(args[1])))); return vm->PyInt((_Int)round(pow(vm->PyInt_AS_C(args[0]), vm->PyInt_AS_C(args[1]))));
}else{ }else{
return vm->PyFloat((_Float)pow(vm->numToFloat(args[0]), vm->numToFloat(args[1]))); return vm->PyFloat((_Float)pow(vm->num_to_float(args[0]), vm->num_to_float(args[1])));
} }
}); });
/************ PyInt ************/ /************ PyInt ************/
_vm->bindMethod("int", "__new__", [](VM* vm, const pkpy::ArgList& args) { _vm->bindMethod("int", "__new__", [](VM* vm, const pkpy::ArgList& args) {
if(args.size() == 0) return vm->PyInt(0); if(args.size() == 0) return vm->PyInt(0);
vm->__checkArgSize(args, 1); vm->check_args_size(args, 1);
if (args[0]->isType(vm->_tp_int)) return args[0]; if (args[0]->isType(vm->_tp_int)) return args[0];
if (args[0]->isType(vm->_tp_float)) return vm->PyInt((_Int)vm->PyFloat_AS_C(args[0])); if (args[0]->isType(vm->_tp_float)) return vm->PyInt((_Int)vm->PyFloat_AS_C(args[0]));
if (args[0]->isType(vm->_tp_bool)) return vm->PyInt(vm->PyBool_AS_C(args[0]) ? 1 : 0); if (args[0]->isType(vm->_tp_bool)) return vm->PyInt(vm->PyBool_AS_C(args[0]) ? 1 : 0);
@ -277,7 +277,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
/************ PyFloat ************/ /************ PyFloat ************/
_vm->bindMethod("float", "__new__", [](VM* vm, const pkpy::ArgList& args) { _vm->bindMethod("float", "__new__", [](VM* vm, const pkpy::ArgList& args) {
if(args.size() == 0) return vm->PyFloat(0.0); if(args.size() == 0) return vm->PyFloat(0.0);
vm->__checkArgSize(args, 1); vm->check_args_size(args, 1);
if (args[0]->isType(vm->_tp_int)) return vm->PyFloat((_Float)vm->PyInt_AS_C(args[0])); if (args[0]->isType(vm->_tp_int)) return vm->PyFloat((_Float)vm->PyInt_AS_C(args[0]));
if (args[0]->isType(vm->_tp_float)) return args[0]; if (args[0]->isType(vm->_tp_float)) return args[0];
if (args[0]->isType(vm->_tp_bool)) return vm->PyFloat(vm->PyBool_AS_C(args[0]) ? 1.0 : 0.0); if (args[0]->isType(vm->_tp_bool)) return vm->PyFloat(vm->PyBool_AS_C(args[0]) ? 1.0 : 0.0);
@ -316,7 +316,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
/************ PyString ************/ /************ PyString ************/
_vm->bindMethod("str", "__new__", [](VM* vm, const pkpy::ArgList& args) { _vm->bindMethod("str", "__new__", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1); vm->check_args_size(args, 1);
return vm->asStr(args[0]); return vm->asStr(args[0]);
}); });
@ -392,7 +392,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
}); });
_vm->bindMethod("str", "upper", [](VM* vm, const pkpy::ArgList& args) { _vm->bindMethod("str", "upper", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1, true); vm->check_args_size(args, 1, true);
const _Str& _self (vm->PyStr_AS_C(args[0])); const _Str& _self (vm->PyStr_AS_C(args[0]));
_StrStream ss; _StrStream ss;
for(auto c : _self) ss << (char)toupper(c); for(auto c : _self) ss << (char)toupper(c);
@ -400,7 +400,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
}); });
_vm->bindMethod("str", "lower", [](VM* vm, const pkpy::ArgList& args) { _vm->bindMethod("str", "lower", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1, true); vm->check_args_size(args, 1, true);
const _Str& _self (vm->PyStr_AS_C(args[0])); const _Str& _self (vm->PyStr_AS_C(args[0]));
_StrStream ss; _StrStream ss;
for(auto c : _self) ss << (char)tolower(c); for(auto c : _self) ss << (char)tolower(c);
@ -408,7 +408,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
}); });
_vm->bindMethod("str", "replace", [](VM* vm, const pkpy::ArgList& args) { _vm->bindMethod("str", "replace", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 3, true); vm->check_args_size(args, 3, true);
const _Str& _self = vm->PyStr_AS_C(args[0]); const _Str& _self = vm->PyStr_AS_C(args[0]);
const _Str& _old = vm->PyStr_AS_C(args[1]); const _Str& _old = vm->PyStr_AS_C(args[1]);
const _Str& _new = vm->PyStr_AS_C(args[2]); const _Str& _new = vm->PyStr_AS_C(args[2]);
@ -423,21 +423,21 @@ void __initializeBuiltinFunctions(VM* _vm) {
}); });
_vm->bindMethod("str", "startswith", [](VM* vm, const pkpy::ArgList& args) { _vm->bindMethod("str", "startswith", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 2, true); vm->check_args_size(args, 2, true);
const _Str& _self = vm->PyStr_AS_C(args[0]); const _Str& _self = vm->PyStr_AS_C(args[0]);
const _Str& _prefix = vm->PyStr_AS_C(args[1]); const _Str& _prefix = vm->PyStr_AS_C(args[1]);
return vm->PyBool(_self.find(_prefix) == 0); return vm->PyBool(_self.find(_prefix) == 0);
}); });
_vm->bindMethod("str", "endswith", [](VM* vm, const pkpy::ArgList& args) { _vm->bindMethod("str", "endswith", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 2, true); vm->check_args_size(args, 2, true);
const _Str& _self = vm->PyStr_AS_C(args[0]); const _Str& _self = vm->PyStr_AS_C(args[0]);
const _Str& _suffix = vm->PyStr_AS_C(args[1]); const _Str& _suffix = vm->PyStr_AS_C(args[1]);
return vm->PyBool(_self.rfind(_suffix) == _self.length() - _suffix.length()); return vm->PyBool(_self.rfind(_suffix) == _self.length() - _suffix.length());
}); });
_vm->bindMethod("str", "join", [](VM* vm, const pkpy::ArgList& args) { _vm->bindMethod("str", "join", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 2, true); vm->check_args_size(args, 2, true);
const _Str& _self = vm->PyStr_AS_C(args[0]); const _Str& _self = vm->PyStr_AS_C(args[0]);
PyVarList* _list; PyVarList* _list;
if(args[1]->isType(vm->_tp_list)){ if(args[1]->isType(vm->_tp_list)){
@ -457,21 +457,21 @@ void __initializeBuiltinFunctions(VM* _vm) {
/************ PyList ************/ /************ PyList ************/
_vm->bindMethod("list", "__iter__", [](VM* vm, const pkpy::ArgList& args) { _vm->bindMethod("list", "__iter__", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkType(args[0], vm->_tp_list); vm->check_type(args[0], vm->_tp_list);
return vm->PyIter( return vm->PyIter(
pkpy::make_shared<BaseIterator, VectorIterator>(vm, args[0]) pkpy::make_shared<BaseIterator, VectorIterator>(vm, args[0])
); );
}); });
_vm->bindMethod("list", "append", [](VM* vm, const pkpy::ArgList& args) { _vm->bindMethod("list", "append", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 2, true); vm->check_args_size(args, 2, true);
PyVarList& _self = vm->PyList_AS_C(args[0]); PyVarList& _self = vm->PyList_AS_C(args[0]);
_self.push_back(args[1]); _self.push_back(args[1]);
return vm->None; return vm->None;
}); });
_vm->bindMethod("list", "insert", [](VM* vm, const pkpy::ArgList& args) { _vm->bindMethod("list", "insert", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 3, true); vm->check_args_size(args, 3, true);
PyVarList& _self = vm->PyList_AS_C(args[0]); PyVarList& _self = vm->PyList_AS_C(args[0]);
int _index = (int)vm->PyInt_AS_C(args[1]); int _index = (int)vm->PyInt_AS_C(args[1]);
if(_index < 0) _index += _self.size(); if(_index < 0) _index += _self.size();
@ -482,13 +482,13 @@ void __initializeBuiltinFunctions(VM* _vm) {
}); });
_vm->bindMethod("list", "clear", [](VM* vm, const pkpy::ArgList& args) { _vm->bindMethod("list", "clear", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1, true); vm->check_args_size(args, 1, true);
vm->PyList_AS_C(args[0]).clear(); vm->PyList_AS_C(args[0]).clear();
return vm->None; return vm->None;
}); });
_vm->bindMethod("list", "copy", [](VM* vm, const pkpy::ArgList& args) { _vm->bindMethod("list", "copy", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1, true); vm->check_args_size(args, 1, true);
return vm->PyList(vm->PyList_AS_C(args[0])); return vm->PyList(vm->PyList_AS_C(args[0]));
}); });
@ -540,13 +540,13 @@ void __initializeBuiltinFunctions(VM* _vm) {
/************ PyTuple ************/ /************ PyTuple ************/
_vm->bindMethod("tuple", "__new__", [](VM* vm, const pkpy::ArgList& args) { _vm->bindMethod("tuple", "__new__", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1); vm->check_args_size(args, 1);
PyVarList _list = vm->PyList_AS_C(vm->call(vm->builtins->attribs["list"], args)); PyVarList _list = vm->PyList_AS_C(vm->call(vm->builtins->attribs["list"], args));
return vm->PyTuple(_list); return vm->PyTuple(_list);
}); });
_vm->bindMethod("tuple", "__iter__", [](VM* vm, const pkpy::ArgList& args) { _vm->bindMethod("tuple", "__iter__", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkType(args[0], vm->_tp_tuple); vm->check_type(args[0], vm->_tp_tuple);
return vm->PyIter( return vm->PyIter(
pkpy::make_shared<BaseIterator, VectorIterator>(vm, args[0]) pkpy::make_shared<BaseIterator, VectorIterator>(vm, args[0])
); );
@ -566,7 +566,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
/************ PyBool ************/ /************ PyBool ************/
_vm->bindMethod("bool", "__new__", [](VM* vm, const pkpy::ArgList& args) { _vm->bindMethod("bool", "__new__", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1); vm->check_args_size(args, 1);
return vm->asBool(args[0]); return vm->asBool(args[0]);
}); });
@ -604,7 +604,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
}); });
_vm->bindMethod("_bounded_method", "__call__", [](VM* vm, const pkpy::ArgList& args) { _vm->bindMethod("_bounded_method", "__call__", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkType(args[0], vm->_tp_bounded_method); vm->check_type(args[0], vm->_tp_bounded_method);
const _BoundedMethod& _self = vm->PyBoundedMethod_AS_C(args[0]); const _BoundedMethod& _self = vm->PyBoundedMethod_AS_C(args[0]);
pkpy::ArgList newArgs(args.size()); pkpy::ArgList newArgs(args.size());
newArgs[0] = _self.obj; newArgs[0] = _self.obj;
@ -635,11 +635,11 @@ void __addModuleTime(VM* vm){
}); });
vm->bindFunc(mod, "sleep", [](VM* vm, const pkpy::ArgList& args) { vm->bindFunc(mod, "sleep", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1); vm->check_args_size(args, 1);
if(!vm->isIntOrFloat(args[0])){ if(!vm->is_int_or_float(args[0])){
vm->typeError("time.sleep() argument must be int or float"); vm->typeError("time.sleep() argument must be int or float");
} }
double sec = vm->numToFloat(args[0]); double sec = vm->num_to_float(args[0]);
vm->sleepForSecs(sec); vm->sleepForSecs(sec);
return vm->None; return vm->None;
}); });
@ -648,89 +648,89 @@ void __addModuleTime(VM* vm){
void __addModuleSys(VM* vm){ void __addModuleSys(VM* vm){
PyVar mod = vm->newModule("sys"); PyVar mod = vm->newModule("sys");
vm->bindFunc(mod, "getrefcount", [](VM* vm, const pkpy::ArgList& args) { vm->bindFunc(mod, "getrefcount", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1); vm->check_args_size(args, 1);
return vm->PyInt(args[0].use_count()); return vm->PyInt(args[0].use_count());
}); });
vm->bindFunc(mod, "getrecursionlimit", [](VM* vm, const pkpy::ArgList& args) { vm->bindFunc(mod, "getrecursionlimit", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 0); vm->check_args_size(args, 0);
return vm->PyInt(vm->maxRecursionDepth); return vm->PyInt(vm->maxRecursionDepth);
}); });
vm->bindFunc(mod, "setrecursionlimit", [](VM* vm, const pkpy::ArgList& args) { vm->bindFunc(mod, "setrecursionlimit", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1); vm->check_args_size(args, 1);
vm->maxRecursionDepth = (int)vm->PyInt_AS_C(args[0]); vm->maxRecursionDepth = (int)vm->PyInt_AS_C(args[0]);
return vm->None; return vm->None;
}); });
vm->setAttr(mod, "version", vm->PyStr(PK_VERSION)); vm->setattr(mod, "version", vm->PyStr(PK_VERSION));
} }
void __addModuleJson(VM* vm){ void __addModuleJson(VM* vm){
PyVar mod = vm->newModule("json"); PyVar mod = vm->newModule("json");
vm->bindFunc(mod, "loads", [](VM* vm, const pkpy::ArgList& args) { vm->bindFunc(mod, "loads", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1); vm->check_args_size(args, 1);
const _Str& expr = vm->PyStr_AS_C(args[0]); const _Str& expr = vm->PyStr_AS_C(args[0]);
_Code code = vm->compile(expr, "<json>", JSON_MODE); _Code code = vm->compile(expr, "<json>", JSON_MODE);
return vm->_exec(code, vm->topFrame()->_module, vm->topFrame()->f_locals_copy()); return vm->_exec(code, vm->top_frame()->_module, vm->top_frame()->f_locals_copy());
}); });
vm->bindFunc(mod, "dumps", [](VM* vm, const pkpy::ArgList& args) { vm->bindFunc(mod, "dumps", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1); vm->check_args_size(args, 1);
return vm->asJson(args[0]); return vm->asJson(args[0]);
}); });
} }
void __addModuleMath(VM* vm){ void __addModuleMath(VM* vm){
PyVar mod = vm->newModule("math"); PyVar mod = vm->newModule("math");
vm->setAttr(mod, "pi", vm->PyFloat(3.1415926535897932384)); vm->setattr(mod, "pi", vm->PyFloat(3.1415926535897932384));
vm->setAttr(mod, "e" , vm->PyFloat(2.7182818284590452354)); vm->setattr(mod, "e" , vm->PyFloat(2.7182818284590452354));
vm->bindFunc(mod, "log", [](VM* vm, const pkpy::ArgList& args) { vm->bindFunc(mod, "log", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1); vm->check_args_size(args, 1);
return vm->PyFloat(log(vm->numToFloat(args[0]))); return vm->PyFloat(log(vm->num_to_float(args[0])));
}); });
vm->bindFunc(mod, "log10", [](VM* vm, const pkpy::ArgList& args) { vm->bindFunc(mod, "log10", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1); vm->check_args_size(args, 1);
return vm->PyFloat(log10(vm->numToFloat(args[0]))); return vm->PyFloat(log10(vm->num_to_float(args[0])));
}); });
vm->bindFunc(mod, "log2", [](VM* vm, const pkpy::ArgList& args) { vm->bindFunc(mod, "log2", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1); vm->check_args_size(args, 1);
return vm->PyFloat(log2(vm->numToFloat(args[0]))); return vm->PyFloat(log2(vm->num_to_float(args[0])));
}); });
vm->bindFunc(mod, "sin", [](VM* vm, const pkpy::ArgList& args) { vm->bindFunc(mod, "sin", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1); vm->check_args_size(args, 1);
return vm->PyFloat(sin(vm->numToFloat(args[0]))); return vm->PyFloat(sin(vm->num_to_float(args[0])));
}); });
vm->bindFunc(mod, "cos", [](VM* vm, const pkpy::ArgList& args) { vm->bindFunc(mod, "cos", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1); vm->check_args_size(args, 1);
return vm->PyFloat(cos(vm->numToFloat(args[0]))); return vm->PyFloat(cos(vm->num_to_float(args[0])));
}); });
vm->bindFunc(mod, "tan", [](VM* vm, const pkpy::ArgList& args) { vm->bindFunc(mod, "tan", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1); vm->check_args_size(args, 1);
return vm->PyFloat(tan(vm->numToFloat(args[0]))); return vm->PyFloat(tan(vm->num_to_float(args[0])));
}); });
vm->bindFunc(mod, "isclose", [](VM* vm, const pkpy::ArgList& args) { vm->bindFunc(mod, "isclose", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 2); vm->check_args_size(args, 2);
_Float a = vm->numToFloat(args[0]); _Float a = vm->num_to_float(args[0]);
_Float b = vm->numToFloat(args[1]); _Float b = vm->num_to_float(args[1]);
return vm->PyBool(fabs(a - b) < 1e-9); return vm->PyBool(fabs(a - b) < 1e-9);
}); });
vm->bindFunc(mod, "isnan", [](VM* vm, const pkpy::ArgList& args) { vm->bindFunc(mod, "isnan", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1); vm->check_args_size(args, 1);
return vm->PyBool(std::isnan(vm->numToFloat(args[0]))); return vm->PyBool(std::isnan(vm->num_to_float(args[0])));
}); });
vm->bindFunc(mod, "isinf", [](VM* vm, const pkpy::ArgList& args) { vm->bindFunc(mod, "isinf", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1); vm->check_args_size(args, 1);
return vm->PyBool(std::isinf(vm->numToFloat(args[0]))); return vm->PyBool(std::isinf(vm->num_to_float(args[0])));
}); });
} }
@ -741,18 +741,18 @@ PyVar __regex_search(const _Str& pattern, const _Str& string, bool fromStart, VM
if(fromStart && m.position() != 0){ if(fromStart && m.position() != 0){
return vm->None; return vm->None;
} }
PyVar ret = vm->newObject(vm->_userTypes["re.Match"], (_Int)1); PyVar ret = vm->new_object(vm->_userTypes["re.Match"], (_Int)1);
vm->setAttr(ret, "_start", vm->PyInt( vm->setattr(ret, "_start", vm->PyInt(
string.__to_u8_index(m.position()) string.__to_u8_index(m.position())
)); ));
vm->setAttr(ret, "_end", vm->PyInt( vm->setattr(ret, "_end", vm->PyInt(
string.__to_u8_index(m.position() + m.length()) string.__to_u8_index(m.position() + m.length())
)); ));
PyVarList groups(m.size()); PyVarList groups(m.size());
for(size_t i = 0; i < m.size(); ++i){ for(size_t i = 0; i < m.size(); ++i){
groups[i] = vm->PyStr(m[i].str()); groups[i] = vm->PyStr(m[i].str());
} }
vm->setAttr(ret, "_groups", vm->PyTuple(groups)); vm->setattr(ret, "_groups", vm->PyTuple(groups));
return ret; return ret;
} }
return vm->None; return vm->None;
@ -760,51 +760,51 @@ PyVar __regex_search(const _Str& pattern, const _Str& string, bool fromStart, VM
void __addModuleRe(VM* vm){ void __addModuleRe(VM* vm){
PyVar mod = vm->newModule("re"); PyVar mod = vm->newModule("re");
PyVar _tp_match = vm->newUserClassType(mod, "Match", vm->_tp_object); PyVar _tp_match = vm->new_user_type_object(mod, "Match", vm->_tp_object);
vm->bindMethod("re.Match", "start", [](VM* vm, const pkpy::ArgList& args) { vm->bindMethod("re.Match", "start", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1, true); vm->check_args_size(args, 1, true);
PyVar self = args[0]; PyVar self = args[0];
return vm->getAttr(self, "_start"); return vm->getattr(self, "_start");
}); });
vm->bindMethod("re.Match", "end", [](VM* vm, const pkpy::ArgList& args) { vm->bindMethod("re.Match", "end", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1, true); vm->check_args_size(args, 1, true);
PyVar self = args[0]; PyVar self = args[0];
return vm->getAttr(self, "_end"); return vm->getattr(self, "_end");
}); });
vm->bindMethod("re.Match", "span", [](VM* vm, const pkpy::ArgList& args) { vm->bindMethod("re.Match", "span", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 1, true); vm->check_args_size(args, 1, true);
PyVar self = args[0]; PyVar self = args[0];
PyVarList vec = { vm->getAttr(self, "_start"), vm->getAttr(self, "_end") }; PyVarList vec = { vm->getattr(self, "_start"), vm->getattr(self, "_end") };
return vm->PyTuple(vec); return vm->PyTuple(vec);
}); });
vm->bindMethod("re.Match", "group", [](VM* vm, const pkpy::ArgList& args) { vm->bindMethod("re.Match", "group", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 2, true); vm->check_args_size(args, 2, true);
int index = (int)vm->PyInt_AS_C(args[1]); int index = (int)vm->PyInt_AS_C(args[1]);
const auto& vec = vm->PyTuple_AS_C(vm->getAttr(args[0], "_groups")); const auto& vec = vm->PyTuple_AS_C(vm->getattr(args[0], "_groups"));
vm->normalizedIndex(index, vec.size()); vm->normalizedIndex(index, vec.size());
return vec[index]; return vec[index];
}); });
vm->bindFunc(mod, "match", [](VM* vm, const pkpy::ArgList& args) { vm->bindFunc(mod, "match", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 2); vm->check_args_size(args, 2);
const _Str& pattern = vm->PyStr_AS_C(args[0]); const _Str& pattern = vm->PyStr_AS_C(args[0]);
const _Str& string = vm->PyStr_AS_C(args[1]); const _Str& string = vm->PyStr_AS_C(args[1]);
return __regex_search(pattern, string, true, vm); return __regex_search(pattern, string, true, vm);
}); });
vm->bindFunc(mod, "search", [](VM* vm, const pkpy::ArgList& args) { vm->bindFunc(mod, "search", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 2); vm->check_args_size(args, 2);
const _Str& pattern = vm->PyStr_AS_C(args[0]); const _Str& pattern = vm->PyStr_AS_C(args[0]);
const _Str& string = vm->PyStr_AS_C(args[1]); const _Str& string = vm->PyStr_AS_C(args[1]);
return __regex_search(pattern, string, false, vm); return __regex_search(pattern, string, false, vm);
}); });
vm->bindFunc(mod, "sub", [](VM* vm, const pkpy::ArgList& args) { vm->bindFunc(mod, "sub", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 3); vm->check_args_size(args, 3);
const _Str& pattern = vm->PyStr_AS_C(args[0]); const _Str& pattern = vm->PyStr_AS_C(args[0]);
const _Str& repl = vm->PyStr_AS_C(args[1]); const _Str& repl = vm->PyStr_AS_C(args[1]);
const _Str& string = vm->PyStr_AS_C(args[2]); const _Str& string = vm->PyStr_AS_C(args[2]);
@ -813,7 +813,7 @@ void __addModuleRe(VM* vm){
}); });
vm->bindFunc(mod, "split", [](VM* vm, const pkpy::ArgList& args) { vm->bindFunc(mod, "split", [](VM* vm, const pkpy::ArgList& args) {
vm->__checkArgSize(args, 2); vm->check_args_size(args, 2);
const _Str& pattern = vm->PyStr_AS_C(args[0]); const _Str& pattern = vm->PyStr_AS_C(args[0]);
const _Str& string = vm->PyStr_AS_C(args[1]); const _Str& string = vm->PyStr_AS_C(args[1]);
std::regex re(pattern); std::regex re(pattern);

182
src/vm.h
View File

@ -6,13 +6,13 @@
#define __DEF_PY_AS_C(type, ctype, ptype) \ #define __DEF_PY_AS_C(type, ctype, ptype) \
inline ctype& Py##type##_AS_C(const PyVar& obj) { \ inline ctype& Py##type##_AS_C(const PyVar& obj) { \
__checkType(obj, ptype); \ check_type(obj, ptype); \
return UNION_GET(ctype, obj); \ return UNION_GET(ctype, obj); \
} }
#define __DEF_PY(type, ctype, ptype) \ #define __DEF_PY(type, ctype, ptype) \
inline PyVar Py##type(ctype value) { \ inline PyVar Py##type(ctype value) { \
return newObject(ptype, value); \ return new_object(ptype, value); \
} }
#define DEF_NATIVE(type, ctype, ptype) \ #define DEF_NATIVE(type, ctype, ptype) \
@ -50,7 +50,7 @@ protected:
case OP_LOAD_CONST: frame->push(frame->code->co_consts[byte.arg]); break; case OP_LOAD_CONST: frame->push(frame->code->co_consts[byte.arg]); break;
case OP_LOAD_LAMBDA: { case OP_LOAD_LAMBDA: {
PyVar obj = frame->code->co_consts[byte.arg]; PyVar obj = frame->code->co_consts[byte.arg];
setAttr(obj, __module__, frame->_module); setattr(obj, __module__, frame->_module);
frame->push(obj); frame->push(obj);
} break; } break;
case OP_LOAD_NAME_REF: { case OP_LOAD_NAME_REF: {
@ -112,13 +112,13 @@ protected:
pkpy::ArgList args(2); pkpy::ArgList args(2);
args[1] = frame->pop_value(this); // obj args[1] = frame->pop_value(this); // obj
args[0] = frame->top_value_offset(this, -2); // list args[0] = frame->top_value_offset(this, -2); // list
fastCall(m_append, std::move(args)); fast_call(m_append, std::move(args));
} break; } break;
case OP_STORE_FUNCTION: case OP_STORE_FUNCTION:
{ {
PyVar obj = frame->pop_value(this); PyVar obj = frame->pop_value(this);
const _Func& fn = PyFunction_AS_C(obj); const _Func& fn = PyFunction_AS_C(obj);
setAttr(obj, __module__, frame->_module); setattr(obj, __module__, frame->_module);
frame->f_globals()[fn->name] = obj; frame->f_globals()[fn->name] = obj;
} break; } break;
case OP_BUILD_CLASS: case OP_BUILD_CLASS:
@ -126,14 +126,14 @@ protected:
const _Str& clsName = frame->code->co_names[byte.arg].first; const _Str& clsName = frame->code->co_names[byte.arg].first;
PyVar clsBase = frame->pop_value(this); PyVar clsBase = frame->pop_value(this);
if(clsBase == None) clsBase = _tp_object; if(clsBase == None) clsBase = _tp_object;
__checkType(clsBase, _tp_type); check_type(clsBase, _tp_type);
PyVar cls = newUserClassType(frame->_module, clsName, clsBase); PyVar cls = new_user_type_object(frame->_module, clsName, clsBase);
while(true){ while(true){
PyVar fn = frame->pop_value(this); PyVar fn = frame->pop_value(this);
if(fn == None) break; if(fn == None) break;
const _Func& f = PyFunction_AS_C(fn); const _Func& f = PyFunction_AS_C(fn);
setAttr(fn, __module__, frame->_module); setattr(fn, __module__, frame->_module);
setAttr(cls, f->name, fn); setattr(cls, f->name, fn);
} }
} break; } break;
case OP_RETURN_VALUE: return frame->pop_value(this); case OP_RETURN_VALUE: return frame->pop_value(this);
@ -146,19 +146,15 @@ protected:
case OP_POP_TOP: frame->pop_value(this); break; case OP_POP_TOP: frame->pop_value(this); break;
case OP_BINARY_OP: case OP_BINARY_OP:
{ {
frame->push( pkpy::ArgList args(2);
fastCall(BINARY_SPECIAL_METHODS[byte.arg], args._index(1) = frame->pop_value(this);
frame->pop_n_values_reversed(this, 2)) args._index(0) = frame->top_value(this);
); frame->top() = fast_call(BINARY_SPECIAL_METHODS[byte.arg], std::move(args));
// pkpy::ArgList args(2);
// args._index(1) = frame->pop_value(this);
// args._index(0) = frame->top_value(this);
// frame->top() = fastCall(BINARY_SPECIAL_METHODS[byte.arg], std::move(args));
} break; } break;
case OP_BITWISE_OP: case OP_BITWISE_OP:
{ {
frame->push( frame->push(
fastCall(BITWISE_SPECIAL_METHODS[byte.arg], fast_call(BITWISE_SPECIAL_METHODS[byte.arg],
frame->pop_n_values_reversed(this, 2)) frame->pop_n_values_reversed(this, 2))
); );
} break; } break;
@ -166,7 +162,7 @@ protected:
{ {
// for __ne__ we use the negation of __eq__ // for __ne__ we use the negation of __eq__
int op = byte.arg == 3 ? 2 : byte.arg; int op = byte.arg == 3 ? 2 : byte.arg;
PyVar res = fastCall(CMP_SPECIAL_METHODS[op], frame->pop_n_values_reversed(this, 2)); PyVar res = fast_call(CMP_SPECIAL_METHODS[op], frame->pop_n_values_reversed(this, 2));
if(op != byte.arg) res = PyBool(!PyBool_AS_C(res)); if(op != byte.arg) res = PyBool(!PyBool_AS_C(res));
frame->push(std::move(res)); frame->push(std::move(res));
} break; } break;
@ -186,7 +182,7 @@ protected:
case OP_UNARY_NEGATIVE: case OP_UNARY_NEGATIVE:
{ {
PyVar obj = frame->pop_value(this); PyVar obj = frame->pop_value(this);
frame->push(numNegated(obj)); frame->push(num_negated(obj));
} break; } break;
case OP_UNARY_NOT: case OP_UNARY_NOT:
{ {
@ -204,7 +200,7 @@ protected:
case OP_ASSERT: case OP_ASSERT:
{ {
PyVar expr = frame->pop_value(this); PyVar expr = frame->pop_value(this);
_assert(PyBool_AS_C(expr), "assertion failed"); if(asBool(expr) != True) _error("AssertionError", "");
} break; } break;
case OP_RAISE_ERROR: case OP_RAISE_ERROR:
{ {
@ -262,11 +258,11 @@ protected:
case OP_GET_ITER: case OP_GET_ITER:
{ {
PyVar obj = frame->pop_value(this); PyVar obj = frame->pop_value(this);
PyVarOrNull iter_fn = getAttr(obj, __iter__, false); PyVarOrNull iter_fn = getattr(obj, __iter__, false);
if(iter_fn != nullptr){ if(iter_fn != nullptr){
PyVar tmp = call(iter_fn); PyVar tmp = call(iter_fn);
PyVarRef var = frame->pop(); PyVarRef var = frame->pop();
__checkType(var, _tp_ref); check_type(var, _tp_ref);
PyIter_AS_C(tmp)->var = var; PyIter_AS_C(tmp)->var = var;
frame->push(std::move(tmp)); frame->push(std::move(tmp));
}else{ }else{
@ -311,8 +307,8 @@ protected:
PyVar stop = frame->pop_value(this); PyVar stop = frame->pop_value(this);
PyVar start = frame->pop_value(this); PyVar start = frame->pop_value(this);
_Slice s; _Slice s;
if(start != None) {__checkType(start, _tp_int); s.start = (int)PyInt_AS_C(start);} if(start != None) {check_type(start, _tp_int); s.start = (int)PyInt_AS_C(start);}
if(stop != None) {__checkType(stop, _tp_int); s.stop = (int)PyInt_AS_C(stop);} if(stop != None) {check_type(stop, _tp_int); s.stop = (int)PyInt_AS_C(stop);}
frame->push(PySlice(s)); frame->push(PySlice(s));
} break; } break;
case OP_IMPORT_NAME: case OP_IMPORT_NAME:
@ -381,7 +377,7 @@ public:
initializeBuiltinClasses(); initializeBuiltinClasses();
_small_integers.reserve(300); _small_integers.reserve(300);
for(_Int i=-5; i<=256; i++) _small_integers.push_back(newObject(_tp_int, i)); for(_Int i=-5; i<=256; i++) _small_integers.push_back(new_object(_tp_int, i));
} }
void keyboardInterrupt(){ void keyboardInterrupt(){
@ -401,12 +397,12 @@ public:
} }
PyVar asStr(const PyVar& obj){ PyVar asStr(const PyVar& obj){
PyVarOrNull str_fn = getAttr(obj, __str__, false); PyVarOrNull str_fn = getattr(obj, __str__, false);
if(str_fn != nullptr) return call(str_fn); if(str_fn != nullptr) return call(str_fn);
return asRepr(obj); return asRepr(obj);
} }
inline Frame* topFrame() const { inline Frame* top_frame() const {
if(callstack.size() == 0) UNREACHABLE(); if(callstack.size() == 0) UNREACHABLE();
return callstack.back().get(); return callstack.back().get();
} }
@ -425,7 +421,7 @@ public:
if(obj->_type == _tp_bool) return obj; if(obj->_type == _tp_bool) return obj;
if(obj->_type == _tp_int) return PyBool(PyInt_AS_C(obj) != 0); if(obj->_type == _tp_int) return PyBool(PyInt_AS_C(obj) != 0);
if(obj->_type == _tp_float) return PyBool(PyFloat_AS_C(obj) != 0.0); if(obj->_type == _tp_float) return PyBool(PyFloat_AS_C(obj) != 0.0);
PyVarOrNull len_fn = getAttr(obj, __len__, false); PyVarOrNull len_fn = getattr(obj, __len__, false);
if(len_fn != nullptr){ if(len_fn != nullptr){
PyVar ret = call(len_fn); PyVar ret = call(len_fn);
return PyBool(PyInt_AS_C(ret) > 0); return PyBool(PyInt_AS_C(ret) > 0);
@ -433,7 +429,7 @@ public:
return True; return True;
} }
PyVar fastCall(const _Str& name, pkpy::ArgList&& args){ PyVar fast_call(const _Str& name, pkpy::ArgList&& args){
PyObject* cls = args[0]->_type.get(); PyObject* cls = args[0]->_type.get();
while(cls != None.get()) { while(cls != None.get()) {
PyVar* val = cls->attribs.try_get(name); PyVar* val = cls->attribs.try_get(name);
@ -457,11 +453,11 @@ public:
template<typename ArgT> template<typename ArgT>
inline std::enable_if_t<std::is_same_v<std::remove_const_t<std::remove_reference_t<ArgT>>, pkpy::ArgList>, PyVar> inline std::enable_if_t<std::is_same_v<std::remove_const_t<std::remove_reference_t<ArgT>>, pkpy::ArgList>, PyVar>
call(const PyVar& obj, const _Str& func, ArgT&& args){ call(const PyVar& obj, const _Str& func, ArgT&& args){
return call(getAttr(obj, func), std::forward<ArgT>(args), pkpy::noArg(), false); return call(getattr(obj, func), std::forward<ArgT>(args), pkpy::noArg(), false);
} }
inline PyVar call(const PyVar& obj, const _Str& func){ inline PyVar call(const PyVar& obj, const _Str& func){
return call(getAttr(obj, func), pkpy::noArg(), pkpy::noArg(), false); return call(getattr(obj, func), pkpy::noArg(), pkpy::noArg(), false);
} }
PyVar call(const PyVar& _callable, pkpy::ArgList args, const pkpy::ArgList& kwargs, bool opCall){ PyVar call(const PyVar& _callable, pkpy::ArgList args, const pkpy::ArgList& kwargs, bool opCall){
@ -471,8 +467,8 @@ public:
if(it != _callable->attribs.end()){ if(it != _callable->attribs.end()){
obj = call(it->second, args, kwargs, false); obj = call(it->second, args, kwargs, false);
}else{ }else{
obj = newObject(_callable, (_Int)-1); obj = new_object(_callable, (_Int)-1);
PyVarOrNull init_fn = getAttr(obj, __init__, false); PyVarOrNull init_fn = getattr(obj, __init__, false);
if (init_fn != nullptr) call(init_fn, args, kwargs, false); if (init_fn != nullptr) call(init_fn, args, kwargs, false);
} }
return obj; return obj;
@ -541,7 +537,7 @@ public:
} }
PyVar* it_m = (*callable)->attribs.try_get(__module__); PyVar* it_m = (*callable)->attribs.try_get(__module__);
PyVar _module = it_m != nullptr ? *it_m : topFrame()->_module; PyVar _module = it_m != nullptr ? *it_m : top_frame()->_module;
if(opCall){ if(opCall){
__pushNewFrame(fn->code, _module, std::move(locals)); __pushNewFrame(fn->code, _module, std::move(locals));
return __py2py_call_signal; return __py2py_call_signal;
@ -608,33 +604,33 @@ public:
return ret; return ret;
} }
PyVar newUserClassType(PyVar mod, _Str name, PyVar base){ PyVar new_user_type_object(PyVar mod, _Str name, PyVar base){
PyVar obj = pkpy::make_shared<PyObject, Py_<_Int>>((_Int)1, _tp_type); PyVar obj = pkpy::make_shared<PyObject, Py_<_Int>>((_Int)1, _tp_type);
setAttr(obj, __base__, base); setattr(obj, __base__, base);
_Str fullName = UNION_NAME(mod) + "." +name; _Str fullName = UNION_NAME(mod) + "." +name;
setAttr(obj, __name__, PyStr(fullName)); setattr(obj, __name__, PyStr(fullName));
_userTypes[fullName] = obj; _userTypes[fullName] = obj;
setAttr(mod, name, obj); setattr(mod, name, obj);
return obj; return obj;
} }
PyVar newClassType(_Str name, PyVar base=nullptr) { PyVar new_type_object(_Str name, PyVar base=nullptr) {
if(base == nullptr) base = _tp_object; if(base == nullptr) base = _tp_object;
PyVar obj = pkpy::make_shared<PyObject, Py_<_Int>>((_Int)0, _tp_type); PyVar obj = pkpy::make_shared<PyObject, Py_<_Int>>((_Int)0, _tp_type);
setAttr(obj, __base__, base); setattr(obj, __base__, base);
_types[name] = obj; _types[name] = obj;
return obj; return obj;
} }
template<typename T> template<typename T>
inline PyVar newObject(PyVar type, T _value) { inline PyVar new_object(PyVar type, T _value) {
if(!type->isType(_tp_type)) UNREACHABLE(); if(!type->isType(_tp_type)) UNREACHABLE();
return pkpy::make_shared<PyObject, Py_<T>>(_value, type); return pkpy::make_shared<PyObject, Py_<T>>(_value, type);
} }
PyVar newModule(_Str name) { PyVar newModule(_Str name) {
PyVar obj = newObject(_tp_module, (_Int)-2); PyVar obj = new_object(_tp_module, (_Int)-2);
setAttr(obj, __name__, PyStr(name)); setattr(obj, __name__, PyStr(name));
_modules[name] = obj; _modules[name] = obj;
return obj; return obj;
} }
@ -643,7 +639,7 @@ public:
_lazy_modules[name] = source; _lazy_modules[name] = source;
} }
PyVarOrNull getAttr(const PyVar& obj, const _Str& name, bool throw_err=true) { PyVarOrNull getattr(const PyVar& obj, const _Str& name, bool throw_err=true) {
PyVarDict::iterator it; PyVarDict::iterator it;
PyObject* cls; PyObject* cls;
@ -683,14 +679,14 @@ public:
} }
template<typename T> template<typename T>
void setAttr(PyObject* obj, const _Str& name, T&& value) { void setattr(PyObject* obj, const _Str& name, T&& value) {
while(obj->isType(_tp_super)) obj = ((Py_<PyVar>*)obj)->_valueT.get(); while(obj->isType(_tp_super)) obj = ((Py_<PyVar>*)obj)->_valueT.get();
obj->attribs[name] = value; obj->attribs[name] = value;
} }
template<typename T> template<typename T>
inline void setAttr(PyVar& obj, const _Str& name, T&& value) { inline void setattr(PyVar& obj, const _Str& name, T&& value) {
setAttr(obj.get(), name, value); setattr(obj.get(), name, value);
} }
void bindMethod(_Str typeName, _Str funcName, _CppFunc fn) { void bindMethod(_Str typeName, _Str funcName, _CppFunc fn) {
@ -698,7 +694,7 @@ public:
if(type == nullptr) type = _userTypes.try_get(typeName); if(type == nullptr) type = _userTypes.try_get(typeName);
if(type == nullptr) UNREACHABLE(); if(type == nullptr) UNREACHABLE();
PyVar func = PyNativeFunction(fn); PyVar func = PyNativeFunction(fn);
setAttr(*type, funcName, func); setattr(*type, funcName, func);
} }
void bindMethodMulti(std::vector<_Str> typeNames, _Str funcName, _CppFunc fn) { void bindMethodMulti(std::vector<_Str> typeNames, _Str funcName, _CppFunc fn) {
@ -712,13 +708,13 @@ public:
} }
void bindFunc(PyVar module, _Str funcName, _CppFunc fn) { void bindFunc(PyVar module, _Str funcName, _CppFunc fn) {
__checkType(module, _tp_module); check_type(module, _tp_module);
PyVar func = PyNativeFunction(fn); PyVar func = PyNativeFunction(fn);
setAttr(module, funcName, func); setattr(module, funcName, func);
} }
bool isInstance(PyVar obj, PyVar type){ bool isinstance(PyVar obj, PyVar type){
__checkType(type, _tp_type); check_type(type, _tp_type);
PyObject* t = obj->_type.get(); PyObject* t = obj->_type.get();
while (t != None.get()){ while (t != None.get()){
if (t == type.get()) return true; if (t == type.get()) return true;
@ -727,15 +723,15 @@ public:
return false; return false;
} }
inline bool isIntOrFloat(const PyVar& obj){ inline bool is_int_or_float(const PyVar& obj) const{
return obj->isType(_tp_int) || obj->isType(_tp_float); return obj->isType(_tp_int) || obj->isType(_tp_float);
} }
inline bool isIntOrFloat(const PyVar& obj1, const PyVar& obj2){ inline bool is_int_or_float(const PyVar& obj1, const PyVar& obj2) const{
return isIntOrFloat(obj1) && isIntOrFloat(obj2); return is_int_or_float(obj1) && is_int_or_float(obj2);
} }
inline _Float numToFloat(const PyVar& obj){ inline _Float num_to_float(const PyVar& obj){
if (obj->isType(_tp_int)){ if (obj->isType(_tp_int)){
return (_Float)PyInt_AS_C(obj); return (_Float)PyInt_AS_C(obj);
}else if(obj->isType(_tp_float)){ }else if(obj->isType(_tp_float)){
@ -744,7 +740,7 @@ public:
UNREACHABLE(); UNREACHABLE();
} }
PyVar numNegated(const PyVar& obj){ PyVar num_negated(const PyVar& obj){
if (obj->isType(_tp_int)){ if (obj->isType(_tp_int)){
return PyInt(-PyInt_AS_C(obj)); return PyInt(-PyInt_AS_C(obj));
}else if(obj->isType(_tp_float)){ }else if(obj->isType(_tp_float)){
@ -835,7 +831,7 @@ public:
template<typename P> template<typename P>
inline PyVarRef PyRef(P&& value) { inline PyVarRef PyRef(P&& value) {
static_assert(std::is_base_of<BaseRef, P>::value, "P should derive from BaseRef"); static_assert(std::is_base_of<BaseRef, P>::value, "P should derive from BaseRef");
return newObject(_tp_ref, std::forward<P>(value)); return new_object(_tp_ref, std::forward<P>(value));
} }
inline const BaseRef* PyRef_AS_C(const PyVar& obj) inline const BaseRef* PyRef_AS_C(const PyVar& obj)
@ -847,7 +843,7 @@ public:
__DEF_PY_AS_C(Int, _Int, _tp_int) __DEF_PY_AS_C(Int, _Int, _tp_int)
inline PyVar PyInt(_Int value) { inline PyVar PyInt(_Int value) {
if(value >= -5 && value <= 256) return _small_integers[value + 5]; if(value >= -5 && value <= 256) return _small_integers[value + 5];
return newObject(_tp_int, value); return new_object(_tp_int, value);
} }
DEF_NATIVE(Float, _Float, _tp_float) DEF_NATIVE(Float, _Float, _tp_float)
@ -872,47 +868,47 @@ public:
_types["object"] = _tp_object; _types["object"] = _tp_object;
_types["type"] = _tp_type; _types["type"] = _tp_type;
_tp_bool = newClassType("bool"); _tp_bool = new_type_object("bool");
_tp_int = newClassType("int"); _tp_int = new_type_object("int");
_tp_float = newClassType("float"); _tp_float = new_type_object("float");
_tp_str = newClassType("str"); _tp_str = new_type_object("str");
_tp_list = newClassType("list"); _tp_list = new_type_object("list");
_tp_tuple = newClassType("tuple"); _tp_tuple = new_type_object("tuple");
_tp_slice = newClassType("slice"); _tp_slice = new_type_object("slice");
_tp_range = newClassType("range"); _tp_range = new_type_object("range");
_tp_module = newClassType("module"); _tp_module = new_type_object("module");
_tp_ref = newClassType("_ref"); _tp_ref = new_type_object("_ref");
newClassType("NoneType"); new_type_object("NoneType");
newClassType("ellipsis"); new_type_object("ellipsis");
_tp_function = newClassType("function"); _tp_function = new_type_object("function");
_tp_native_function = newClassType("_native_function"); _tp_native_function = new_type_object("_native_function");
_tp_native_iterator = newClassType("_native_iterator"); _tp_native_iterator = new_type_object("_native_iterator");
_tp_bounded_method = newClassType("_bounded_method"); _tp_bounded_method = new_type_object("_bounded_method");
_tp_super = newClassType("super"); _tp_super = new_type_object("super");
this->None = newObject(_types["NoneType"], (_Int)0); this->None = new_object(_types["NoneType"], (_Int)0);
this->Ellipsis = newObject(_types["ellipsis"], (_Int)0); this->Ellipsis = new_object(_types["ellipsis"], (_Int)0);
this->True = newObject(_tp_bool, true); this->True = new_object(_tp_bool, true);
this->False = newObject(_tp_bool, false); this->False = new_object(_tp_bool, false);
this->builtins = newModule("builtins"); this->builtins = newModule("builtins");
this->_main = newModule("__main__"); this->_main = newModule("__main__");
setAttr(_tp_type, __base__, _tp_object); setattr(_tp_type, __base__, _tp_object);
_tp_type->_type = _tp_type; _tp_type->_type = _tp_type;
setAttr(_tp_object, __base__, None); setattr(_tp_object, __base__, None);
_tp_object->_type = _tp_type; _tp_object->_type = _tp_type;
for (auto& [name, type] : _types) { for (auto& [name, type] : _types) {
setAttr(type, __name__, PyStr(name)); setattr(type, __name__, PyStr(name));
} }
this->__py2py_call_signal = newObject(_tp_object, (_Int)7); this->__py2py_call_signal = new_object(_tp_object, (_Int)7);
std::vector<_Str> publicTypes = {"type", "object", "bool", "int", "float", "str", "list", "tuple", "range"}; std::vector<_Str> publicTypes = {"type", "object", "bool", "int", "float", "str", "list", "tuple", "range"};
for (auto& name : publicTypes) { for (auto& name : publicTypes) {
setAttr(builtins, name, _types[name]); setattr(builtins, name, _types[name]);
} }
} }
@ -985,22 +981,18 @@ public:
_error("AttributeError", "type '" + UNION_TP_NAME(obj) + "' has no attribute '" + name + "'"); _error("AttributeError", "type '" + UNION_TP_NAME(obj) + "' has no attribute '" + name + "'");
} }
inline void __checkType(const PyVar& obj, const PyVar& type){ inline void check_type(const PyVar& obj, const PyVar& type){
#ifndef PKPY_NO_TYPE_CHECK #ifndef PKPY_NO_TYPE_CHECK
if(!obj->isType(type)) typeError("expected '" + UNION_NAME(type) + "', but got '" + UNION_TP_NAME(obj) + "'"); if(!obj->isType(type)) typeError("expected '" + UNION_NAME(type) + "', but got '" + UNION_TP_NAME(obj) + "'");
#endif #endif
} }
inline void __checkArgSize(const pkpy::ArgList& args, int size, bool method=false){ inline void check_args_size(const pkpy::ArgList& args, int size, bool method=false){
if(args.size() == size) return; if(args.size() == size) return;
if(method) typeError(args.size()>size ? "too many arguments" : "too few arguments"); if(method) typeError(args.size()>size ? "too many arguments" : "too few arguments");
else typeError("expected " + std::to_string(size) + " arguments, but got " + std::to_string(args.size())); else typeError("expected " + std::to_string(size) + " arguments, but got " + std::to_string(args.size()));
} }
void _assert(bool val, const _Str& msg){
if (!val) _error("AssertionError", msg);
}
virtual ~VM() { virtual ~VM() {
if(!use_stdio){ if(!use_stdio){
delete _stdout; delete _stdout;
@ -1065,11 +1057,11 @@ void NameRef::del(VM* vm, Frame* frame) const{
} }
PyVar AttrRef::get(VM* vm, Frame* frame) const{ PyVar AttrRef::get(VM* vm, Frame* frame) const{
return vm->getAttr(obj, attr.pair->first); return vm->getattr(obj, attr.pair->first);
} }
void AttrRef::set(VM* vm, Frame* frame, PyVar val) const{ void AttrRef::set(VM* vm, Frame* frame, PyVar val) const{
vm->setAttr(obj, attr.pair->first, val); vm->setattr(obj, attr.pair->first, val);
} }
void AttrRef::del(VM* vm, Frame* frame) const{ void AttrRef::del(VM* vm, Frame* frame) const{
@ -1158,7 +1150,7 @@ class ThreadedVM : public VM {
public: public:
ThreadedVM(bool use_stdio) : VM(use_stdio) { ThreadedVM(bool use_stdio) : VM(use_stdio) {
bindBuiltinFunc("__string_channel_call", [](VM* vm, const pkpy::ArgList& args){ bindBuiltinFunc("__string_channel_call", [](VM* vm, const pkpy::ArgList& args){
vm->__checkArgSize(args, 1); vm->check_args_size(args, 1);
_Str data = vm->PyStr_AS_C(args[0]); _Str data = vm->PyStr_AS_C(args[0]);
ThreadedVM* tvm = (ThreadedVM*)vm; ThreadedVM* tvm = (ThreadedVM*)vm;