From aab4ff7647921e475a67c225be82ee4f3c2860f9 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Mon, 27 Feb 2023 17:07:56 +0800 Subject: [PATCH] move all to `pkpy` namespace --- src/ceval.h | 44 ++++--- src/cffi.h | 48 +++---- src/codeobject.h | 11 +- src/common.h | 12 +- src/compiler.h | 22 ++-- src/error.h | 6 +- src/frame.h | 18 +-- src/iter.h | 10 +- src/main.cpp | 4 +- src/memory.h | 150 +++++++++++----------- src/namedict.h | 317 ++++++++++++++++++++++++----------------------- src/obj.h | 48 ++++--- src/parser.h | 10 +- src/pocketpy.h | 250 ++++++++++++++++++------------------- src/ref.h | 11 +- src/repl.h | 6 +- src/str.h | 6 +- src/tuplelist.h | 6 +- src/vm.h | 155 +++++++++++++++-------- 19 files changed, 626 insertions(+), 508 deletions(-) diff --git a/src/ceval.h b/src/ceval.h index 50e0d6cb..1b1a3e49 100644 --- a/src/ceval.h +++ b/src/ceval.h @@ -2,6 +2,8 @@ #include "vm.h" +namespace pkpy{ + PyVar VM::run_frame(Frame* frame){ while(frame->has_next_bytecode()){ const Bytecode& byte = frame->next_bytecode(); @@ -15,12 +17,12 @@ PyVar VM::run_frame(Frame* frame){ case OP_LOAD_CONST: frame->push(frame->co->consts[byte.arg]); continue; case OP_LOAD_FUNCTION: { const PyVar obj = frame->co->consts[byte.arg]; - pkpy::Function f = PyFunction_AS_C(obj); // copy + Function f = PyFunction_AS_C(obj); // copy f._module = frame->_module; frame->push(PyFunction(f)); } continue; case OP_SETUP_CLOSURE: { - pkpy::Function& f = PyFunction_AS_C(frame->top()); // reference + Function& f = PyFunction_AS_C(frame->top()); // reference f._closure = frame->_locals; } continue; case OP_LOAD_NAME_REF: { @@ -66,15 +68,15 @@ PyVar VM::run_frame(Frame* frame){ frame->_pop(); continue; case OP_BUILD_TUPLE: { - pkpy::Args items = frame->pop_n_values_reversed(this, byte.arg); + Args items = frame->pop_n_values_reversed(this, byte.arg); frame->push(PyTuple(std::move(items))); } continue; case OP_BUILD_TUPLE_REF: { - pkpy::Args items = frame->pop_n_reversed(byte.arg); + Args items = frame->pop_n_reversed(byte.arg); frame->push(PyRef(TupleRef(std::move(items)))); } continue; case OP_BUILD_STRING: { - pkpy::Args items = frame->pop_n_values_reversed(this, byte.arg); + Args items = frame->pop_n_values_reversed(this, byte.arg); StrStream ss; for(int i=0; ipush(PyStr(ss.str())); @@ -82,7 +84,7 @@ PyVar VM::run_frame(Frame* frame){ case OP_LOAD_EVAL_FN: frame->push(builtins->attr(m_eval)); continue; case OP_LIST_APPEND: { PyVar obj = frame->pop_value(this); - pkpy::List& list = PyList_AS_C(frame->top_1()); + List& list = PyList_AS_C(frame->top_1()); list.push_back(std::move(obj)); } continue; case OP_BEGIN_CLASS: { @@ -110,19 +112,19 @@ PyVar VM::run_frame(Frame* frame){ } continue; case OP_POP_TOP: frame->_pop(); continue; case OP_BINARY_OP: { - pkpy::Args args(2); + Args args(2); args[1] = frame->pop_value(this); args[0] = frame->top_value(this); frame->top() = fast_call(BINARY_SPECIAL_METHODS[byte.arg], std::move(args)); } continue; case OP_BITWISE_OP: { - pkpy::Args args(2); + Args args(2); args[1] = frame->pop_value(this); args[0] = frame->top_value(this); frame->top() = fast_call(BITWISE_SPECIAL_METHODS[byte.arg], std::move(args)); } continue; case OP_INPLACE_BINARY_OP: { - pkpy::Args args(2); + Args args(2); args[1] = frame->pop(); args[0] = frame->top_value(this); PyVar ret = fast_call(BINARY_SPECIAL_METHODS[byte.arg], std::move(args)); @@ -130,7 +132,7 @@ PyVar VM::run_frame(Frame* frame){ frame->_pop(); } continue; case OP_INPLACE_BITWISE_OP: { - pkpy::Args args(2); + Args args(2); args[1] = frame->pop_value(this); args[0] = frame->top_value(this); PyVar ret = fast_call(BITWISE_SPECIAL_METHODS[byte.arg], std::move(args)); @@ -138,7 +140,7 @@ PyVar VM::run_frame(Frame* frame){ frame->_pop(); } continue; case OP_COMPARE_OP: { - pkpy::Args args(2); + Args args(2); args[1] = frame->pop_value(this); args[0] = frame->top_value(this); frame->top() = fast_call(CMP_SPECIAL_METHODS[byte.arg], std::move(args)); @@ -151,7 +153,7 @@ PyVar VM::run_frame(Frame* frame){ } continue; case OP_CONTAINS_OP: { PyVar rhs = frame->pop_value(this); - bool ret_c = PyBool_AS_C(call(rhs, __contains__, pkpy::one_arg(frame->pop_value(this)))); + bool ret_c = PyBool_AS_C(call(rhs, __contains__, one_arg(frame->pop_value(this)))); if(byte.arg == 1) ret_c = !ret_c; frame->push(PyBool(ret_c)); } continue; @@ -192,10 +194,10 @@ PyVar VM::run_frame(Frame* frame){ frame->push(PyList(frame->pop_n_values_reversed(this, byte.arg).move_to_list())); continue; case OP_BUILD_MAP: { - pkpy::Args items = frame->pop_n_values_reversed(this, byte.arg*2); + Args items = frame->pop_n_values_reversed(this, byte.arg*2); PyVar obj = call(builtins->attr("dict")); for(int i=0; ipush(obj); } continue; @@ -203,7 +205,7 @@ PyVar VM::run_frame(Frame* frame){ PyVar list = PyList( frame->pop_n_values_reversed(this, byte.arg).move_to_list() ); - PyVar obj = call(builtins->attr("set"), pkpy::one_arg(list)); + PyVar obj = call(builtins->attr("set"), one_arg(list)); frame->push(obj); } continue; case OP_DUP_TOP_VALUE: frame->push(frame->top_value(this)); continue; @@ -218,8 +220,8 @@ PyVar VM::run_frame(Frame* frame){ case OP_CALL_KWARGS_UNPACK: case OP_CALL_KWARGS: { int ARGC = byte.arg & 0xFFFF; int KWARGC = (byte.arg >> 16) & 0xFFFF; - pkpy::Args kwargs = frame->pop_n_values_reversed(this, KWARGC*2); - pkpy::Args args = frame->pop_n_values_reversed(this, ARGC); + Args kwargs = frame->pop_n_values_reversed(this, KWARGC*2); + Args args = frame->pop_n_values_reversed(this, ARGC); if(byte.op == OP_CALL_KWARGS_UNPACK) unpack_args(args); PyVar callable = frame->pop_value(this); PyVar ret = call(callable, std::move(args), kwargs, true); @@ -227,10 +229,10 @@ PyVar VM::run_frame(Frame* frame){ frame->push(std::move(ret)); } continue; case OP_CALL_UNPACK: case OP_CALL: { - pkpy::Args args = frame->pop_n_values_reversed(this, byte.arg); + Args args = frame->pop_n_values_reversed(this, byte.arg); if(byte.op == OP_CALL_UNPACK) unpack_args(args); PyVar callable = frame->pop_value(this); - PyVar ret = call(callable, std::move(args), pkpy::no_arg(), true); + PyVar ret = call(callable, std::move(args), no_arg(), true); if(ret == _py_op_call) return ret; frame->push(std::move(ret)); } continue; @@ -280,7 +282,7 @@ PyVar VM::run_frame(Frame* frame){ case OP_BUILD_SLICE: { PyVar stop = frame->pop_value(this); PyVar start = frame->pop_value(this); - pkpy::Slice s; + Slice s; if(start != None) { s.start = (int)PyInt_AS_C(start);} if(stop != None) { s.stop = (int)PyInt_AS_C(stop);} frame->push(PySlice(s)); @@ -332,3 +334,5 @@ PyVar VM::run_frame(Frame* frame){ #endif return None; } + +} // namespace pkpy \ No newline at end of file diff --git a/src/cffi.h b/src/cffi.h index ba2be953..a7d344ca 100644 --- a/src/cffi.h +++ b/src/cffi.h @@ -2,6 +2,8 @@ #include "vm.h" +namespace pkpy { + struct CType{ PY_CLASS(c, type_) @@ -13,7 +15,7 @@ struct CType{ static void _register(VM* vm, PyVar mod, PyVar type){ vm->bind_static_method<-1>(type, "__new__", CPP_NOT_IMPLEMENTED()); - vm->bind_method<0>(type, "__repr__", [](VM* vm, pkpy::Args& args) { + vm->bind_method<0>(type, "__repr__", [](VM* vm, Args& args) { CType& self = vm->py_cast(args[0]); StrStream ss; ss << ""; @@ -67,61 +69,61 @@ struct Pointer{ static void _register(VM* vm, PyVar mod, PyVar type){ vm->bind_static_method<-1>(type, "__new__", CPP_NOT_IMPLEMENTED()); - vm->bind_method<0>(type, "__repr__", [](VM* vm, pkpy::Args& args) { + vm->bind_method<0>(type, "__repr__", [](VM* vm, Args& args) { Pointer& self = vm->py_cast(args[0]); StrStream ss; ss << "<" << self.ctype.name << "* at " << (i64)self.ptr << ">"; return vm->PyStr(ss.str()); }); - vm->bind_method<1>(type, "__add__", [](VM* vm, pkpy::Args& args) { + vm->bind_method<1>(type, "__add__", [](VM* vm, Args& args) { Pointer& self = vm->py_cast(args[0]); return vm->new_object(self + vm->PyInt_AS_C(args[1])); }); - vm->bind_method<1>(type, "__sub__", [](VM* vm, pkpy::Args& args) { + vm->bind_method<1>(type, "__sub__", [](VM* vm, Args& args) { Pointer& self = vm->py_cast(args[0]); return vm->new_object(self - vm->PyInt_AS_C(args[1])); }); - vm->bind_method<1>(type, "__eq__", [](VM* vm, pkpy::Args& args) { + vm->bind_method<1>(type, "__eq__", [](VM* vm, Args& args) { Pointer& self = vm->py_cast(args[0]); Pointer& other = vm->py_cast(args[1]); return vm->PyBool(self.ptr == other.ptr); }); - vm->bind_method<1>(type, "__ne__", [](VM* vm, pkpy::Args& args) { + vm->bind_method<1>(type, "__ne__", [](VM* vm, Args& args) { Pointer& self = vm->py_cast(args[0]); Pointer& other = vm->py_cast(args[1]); return vm->PyBool(self.ptr != other.ptr); }); // https://docs.python.org/zh-cn/3/library/ctypes.html - vm->bind_method<1>(type, "__getitem__", [](VM* vm, pkpy::Args& args) { + vm->bind_method<1>(type, "__getitem__", [](VM* vm, Args& args) { Pointer& self = vm->py_cast(args[0]); i64 index = vm->PyInt_AS_C(args[1]); return (self+index).get(vm); }); - vm->bind_method<2>(type, "__setitem__", [](VM* vm, pkpy::Args& args) { + vm->bind_method<2>(type, "__setitem__", [](VM* vm, Args& args) { Pointer& self = vm->py_cast(args[0]); i64 index = vm->PyInt_AS_C(args[1]); (self+index).set(vm, args[2]); return vm->None; }); - vm->bind_method<1>(type, "cast", [](VM* vm, pkpy::Args& args) { + vm->bind_method<1>(type, "cast", [](VM* vm, Args& args) { Pointer& self = vm->py_cast(args[0]); CType& ctype = vm->py_cast(args[1]); return vm->new_object(self.ptr, ctype); }); - vm->bind_method<0>(type, "get", [](VM* vm, pkpy::Args& args) { + vm->bind_method<0>(type, "get", [](VM* vm, Args& args) { Pointer& self = vm->py_cast(args[0]); return self.get(vm); }); - vm->bind_method<1>(type, "set", [](VM* vm, pkpy::Args& args) { + vm->bind_method<1>(type, "set", [](VM* vm, Args& args) { Pointer& self = vm->py_cast(args[0]); self.set(vm, args[1]); return vm->None; @@ -235,11 +237,11 @@ struct Struct { } static void _register(VM* vm, PyVar mod, PyVar type){ - vm->bind_static_method<-1>(type, "__new__", [](VM* vm, pkpy::Args& args) { + vm->bind_static_method<-1>(type, "__new__", [](VM* vm, Args& args) { return vm->new_object(); }); - vm->bind_method<0>(type, "__repr__", [](VM* vm, pkpy::Args& args) { + vm->bind_method<0>(type, "__repr__", [](VM* vm, Args& args) { Struct& self = vm->py_cast(args[0]); StrStream ss; ss << self.info->name << "(" << ")"; @@ -259,23 +261,23 @@ void add_module_c(VM* vm){ } vm->setattr(mod, "nullptr", vm->new_object(nullptr, C_TYPE_T("void_"))); - vm->bind_func<1>(mod, "malloc", [](VM* vm, pkpy::Args& args) { + vm->bind_func<1>(mod, "malloc", [](VM* vm, Args& args) { i64 size = vm->PyInt_AS_C(args[0]); return vm->new_object(malloc(size), C_TYPE_T("void_")); }); - vm->bind_func<1>(mod, "free", [](VM* vm, pkpy::Args& args) { + vm->bind_func<1>(mod, "free", [](VM* vm, Args& args) { Pointer& self = vm->py_cast(args[0]); free(self.ptr); return vm->None; }); - vm->bind_func<1>(mod, "sizeof", [](VM* vm, pkpy::Args& args) { + vm->bind_func<1>(mod, "sizeof", [](VM* vm, Args& args) { CType& ctype = vm->py_cast(args[0]); return vm->PyInt(ctype.size); }); - vm->bind_func<3>(mod, "memcpy", [](VM* vm, pkpy::Args& args) { + vm->bind_func<3>(mod, "memcpy", [](VM* vm, Args& args) { Pointer& dst = vm->py_cast(args[0]); Pointer& src = vm->py_cast(args[1]); i64 size = vm->PyInt_AS_C(args[2]); @@ -283,7 +285,7 @@ void add_module_c(VM* vm){ return vm->None; }); - vm->bind_func<3>(mod, "memset", [](VM* vm, pkpy::Args& args) { + vm->bind_func<3>(mod, "memset", [](VM* vm, Args& args) { Pointer& dst = vm->py_cast(args[0]); i64 val = vm->PyInt_AS_C(args[1]); i64 size = vm->PyInt_AS_C(args[2]); @@ -291,7 +293,7 @@ void add_module_c(VM* vm){ return vm->None; }); - vm->bind_func<1>(mod, "strdup", [ptr_t](VM* vm, pkpy::Args& args) { + vm->bind_func<1>(mod, "strdup", [ptr_t](VM* vm, Args& args) { if(is_type(args[0], vm->tp_str)){ const Str& s = vm->PyStr_AS_C(args[0]); return vm->new_object(strdup(s.c_str()), C_TYPE_T("char_")); @@ -304,14 +306,16 @@ void add_module_c(VM* vm){ } }); - vm->bind_func<2>(mod, "strcmp", [](VM* vm, pkpy::Args& args) { + vm->bind_func<2>(mod, "strcmp", [](VM* vm, Args& args) { Pointer& p1 = vm->py_cast(args[0]); Pointer& p2 = vm->py_cast(args[1]); return vm->PyInt(strcmp(p1.cast(), p2.cast())); }); - vm->bind_func<1>(mod, "strlen", [](VM* vm, pkpy::Args& args) { + vm->bind_func<1>(mod, "strlen", [](VM* vm, Args& args) { Pointer& p = vm->py_cast(args[0]); return vm->PyInt(strlen(p.cast())); }); -} \ No newline at end of file +} + +} // namespace pkpy \ No newline at end of file diff --git a/src/codeobject.h b/src/codeobject.h index 6ed6837a..3a000ed5 100644 --- a/src/codeobject.h +++ b/src/codeobject.h @@ -4,6 +4,8 @@ #include "ref.h" #include "error.h" +namespace pkpy{ + enum Opcode { #define OPCODE(name) OP_##name, #include "opcodes.h" @@ -49,17 +51,17 @@ struct CodeBlock { }; struct CodeObject { - pkpy::shared_ptr src; + shared_ptr src; Str name; bool is_generator = false; - CodeObject(pkpy::shared_ptr src, Str name) { + CodeObject(shared_ptr src, Str name) { this->src = src; this->name = name; } std::vector codes; - pkpy::List consts; + List consts; std::vector> names; std::map global_names; std::vector blocks = { CodeBlock{NO_BLOCK, -1} }; @@ -111,3 +113,6 @@ struct CodeObject { } /************************************************/ }; + + +} // namespace pkpy \ No newline at end of file diff --git a/src/common.h b/src/common.h index feebc043..e0fd8afe 100644 --- a/src/common.h +++ b/src/common.h @@ -26,8 +26,6 @@ #include #include #include -// #include -// namespace fs = std::filesystem; #define PK_VERSION "0.9.1" @@ -43,6 +41,8 @@ typedef double f64; #define S_TO_FLOAT std::stod #endif +namespace pkpy{ + struct Dummy { }; struct DummyInstance { }; struct DummyModule { }; @@ -62,8 +62,8 @@ struct Type { //#define THREAD_LOCAL thread_local #define THREAD_LOCAL -#define CPP_LAMBDA(x) ([](VM* vm, pkpy::Args& args) { return x; }) -#define CPP_NOT_IMPLEMENTED() ([](VM* vm, pkpy::Args& args) { vm->NotImplementedError(); return vm->None; }) +#define CPP_LAMBDA(x) ([](VM* vm, Args& args) { return x; }) +#define CPP_NOT_IMPLEMENTED() ([](VM* vm, Args& args) { vm->NotImplementedError(); return vm->None; }) #ifdef POCKETPY_H #define UNREACHABLE() throw std::runtime_error( "L" + std::to_string(__LINE__) + " UNREACHABLE()!"); @@ -78,4 +78,6 @@ const float kInstAttrLoadFactor = 0.67; const float kTypeAttrLoadFactor = 0.5; // do extra check for debug -#define PK_EXTRA_CHECK \ No newline at end of file +#define PK_EXTRA_CHECK + +} // namespace pkpy \ No newline at end of file diff --git a/src/compiler.h b/src/compiler.h index 050ec334..ab34c132 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -4,6 +4,8 @@ #include "error.h" #include "ceval.h" +namespace pkpy{ + class Compiler; typedef void (Compiler::*GrammarFn)(); typedef void (Compiler::*CompilerAction)(); @@ -32,7 +34,7 @@ public: Compiler(VM* vm, const char* source, Str filename, CompileMode mode){ this->vm = vm; this->parser = std::make_unique( - pkpy::make_shared(source, filename, mode) + make_sp(source, filename, mode) ); // http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/ @@ -385,13 +387,13 @@ private: } void exprLambda() { - pkpy::Function func; + Function func; func.name = ""; if(!match(TK(":"))){ _compile_f_args(func, false); consume(TK(":")); } - func.code = pkpy::make_shared(parser->src, func.name.str()); + func.code = make_sp(parser->src, func.name.str()); this->codes.push(func.code); co()->_rvalue += 1; EXPR_TUPLE(); co()->_rvalue -= 1; emit(OP_RETURN_VALUE); @@ -1009,7 +1011,7 @@ __LISTCOMP: emit(OP_END_CLASS); } - void _compile_f_args(pkpy::Function& func, bool enable_type_hints){ + void _compile_f_args(Function& func, bool enable_type_hints){ int state = 0; // 0 for args, 1 for *args, 2 for k=v, 3 for **kwargs do { if(state == 3) SyntaxError("**kwargs should be the last argument"); @@ -1051,7 +1053,7 @@ __LISTCOMP: void compile_function(){ bool has_decorator = !co()->codes.empty() && co()->codes.back().op == OP_SETUP_DECORATOR; - pkpy::Function func; + Function func; StrName obj_name; consume(TK("@id")); func.name = parser->prev.str(); @@ -1066,7 +1068,7 @@ __LISTCOMP: consume(TK(")")); } if(match(TK("->"))) consume(TK("@id")); // eat type hints - func.code = pkpy::make_shared(parser->src, func.name.str()); + func.code = make_sp(parser->src, func.name.str()); this->codes.push(func.code); compile_block_body(); func.code->optimize(vm); @@ -1116,7 +1118,7 @@ __LISTCOMP: cursor = parser->curr_char; } if(parser->peekchar() == '\n') lineno--; - auto e = pkpy::Exception("SyntaxError", msg); + auto e = Exception("SyntaxError", msg); e.st_push(parser->src->snapshot(lineno, cursor)); throw e; } @@ -1130,7 +1132,7 @@ public: if(used) UNREACHABLE(); used = true; - CodeObject_ code = pkpy::make_shared(parser->src, Str("")); + CodeObject_ code = make_sp(parser->src, Str("")); codes.push(code); lex_token(); lex_token(); @@ -1162,4 +1164,6 @@ public: code->optimize(vm); return code; } -}; \ No newline at end of file +}; + +} // namespace pkpy \ No newline at end of file diff --git a/src/error.h b/src/error.h index 333ccb42..945e929c 100644 --- a/src/error.h +++ b/src/error.h @@ -3,6 +3,8 @@ #include "namedict.h" #include "tuplelist.h" +namespace pkpy{ + struct NeedMoreLines { NeedMoreLines(bool is_compiling_class) : is_compiling_class(is_compiling_class) {} bool is_compiling_class; @@ -67,7 +69,6 @@ struct SourceData { ~SourceData() { free((void*)source); } }; -namespace pkpy{ class Exception { StrName type; Str msg; @@ -92,4 +93,5 @@ public: return ss.str(); } }; -} + +} // namespace pkpy \ No newline at end of file diff --git a/src/frame.h b/src/frame.h index 3aa2a9c5..088de356 100644 --- a/src/frame.h +++ b/src/frame.h @@ -2,6 +2,8 @@ #include "codeobject.h" +namespace pkpy{ + static THREAD_LOCAL uint64_t kFrameGlobalId = 0; struct Frame { @@ -16,8 +18,8 @@ struct Frame { const uint64_t id; std::vector>> s_try_block; - inline pkpy::NameDict& f_locals() noexcept { return _locals != nullptr ? *_locals : _module->attr(); } - inline pkpy::NameDict& f_globals() noexcept { return _module->attr(); } + inline NameDict& f_locals() noexcept { return _locals != nullptr ? *_locals : _module->attr(); } + inline NameDict& f_globals() noexcept { return _module->attr(); } inline PyVar* f_closure_try_get(StrName name) noexcept { if(_closure == nullptr) return nullptr; @@ -143,8 +145,8 @@ struct Frame { } } - pkpy::Args pop_n_values_reversed(VM* vm, int n){ - pkpy::Args v(n); + Args pop_n_values_reversed(VM* vm, int n){ + Args v(n); for(int i=n-1; i>=0; i--){ v[i] = pop(); try_deref(vm, v[i]); @@ -152,9 +154,11 @@ struct Frame { return v; } - pkpy::Args pop_n_reversed(int n){ - pkpy::Args v(n); + Args pop_n_reversed(int n){ + Args v(n); for(int i=n-1; i>=0; i--) v[i] = pop(); return v; } -}; \ No newline at end of file +}; + +}; // namespace pkpy \ No newline at end of file diff --git a/src/iter.h b/src/iter.h index 311e5497..bca3c65d 100644 --- a/src/iter.h +++ b/src/iter.h @@ -2,12 +2,14 @@ #include "ceval.h" +namespace pkpy{ + class RangeIter : public BaseIter { i64 current; - pkpy::Range r; + Range r; public: RangeIter(VM* vm, PyVar _ref) : BaseIter(vm, _ref) { - this->r = OBJ_GET(pkpy::Range, _ref); + this->r = OBJ_GET(Range, _ref); this->current = r.start; } @@ -61,4 +63,6 @@ PyVar Generator::next(){ state = 2; return nullptr; } -} \ No newline at end of file +} + +} // namespace pkpy \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 1074dcc7..b85f1c92 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,11 +1,13 @@ #include #include "pocketpy.h" +using namespace pkpy; + #ifndef __EMSCRIPTEN__ int main(int argc, char** argv){ VM* vm = pkpy_new_vm(true); - vm->bind_builtin_func<0>("input", [](VM* vm, pkpy::Args& args){ + vm->bind_builtin_func<0>("input", [](VM* vm, Args& args){ static std::string line; std::getline(std::cin, line); return vm->PyStr(line); diff --git a/src/memory.h b/src/memory.h index 9f71d78f..2f3ff1bc 100644 --- a/src/memory.h +++ b/src/memory.h @@ -2,97 +2,98 @@ #include "common.h" +namespace pkpy{ + struct PyObject; -namespace pkpy{ - template - struct SpAllocator { - template - inline static int* alloc(){ - return (int*)malloc(sizeof(int) + sizeof(U)); - } +template +struct SpAllocator { + template + inline static int* alloc(){ + return (int*)malloc(sizeof(int) + sizeof(U)); + } - inline static void dealloc(int* counter){ - ((T*)(counter + 1))->~T(); - free(counter); - } + inline static void dealloc(int* counter){ + ((T*)(counter + 1))->~T(); + free(counter); + } +}; + +template +struct shared_ptr { + union { + int* counter; + i64 bits; }; - template - struct shared_ptr { - union { - int* counter; - i64 bits; - }; - #define _t() (T*)(counter + 1) #define _inc_counter() if(!is_tagged() && counter) ++(*counter) #define _dec_counter() if(!is_tagged() && counter && --(*counter) == 0) SpAllocator::dealloc(counter) - public: - shared_ptr() : counter(nullptr) {} - shared_ptr(int* counter) : counter(counter) {} - shared_ptr(const shared_ptr& other) : counter(other.counter) { - _inc_counter(); - } - shared_ptr(shared_ptr&& other) noexcept : counter(other.counter) { - other.counter = nullptr; - } - ~shared_ptr() { _dec_counter(); } +public: + shared_ptr() : counter(nullptr) {} + shared_ptr(int* counter) : counter(counter) {} + shared_ptr(const shared_ptr& other) : counter(other.counter) { + _inc_counter(); + } + shared_ptr(shared_ptr&& other) noexcept : counter(other.counter) { + other.counter = nullptr; + } + ~shared_ptr() { _dec_counter(); } - bool operator==(const shared_ptr& other) const { return counter == other.counter; } - bool operator!=(const shared_ptr& other) const { return counter != other.counter; } - bool operator<(const shared_ptr& other) const { return counter < other.counter; } - bool operator>(const shared_ptr& other) const { return counter > other.counter; } - bool operator<=(const shared_ptr& other) const { return counter <= other.counter; } - bool operator>=(const shared_ptr& other) const { return counter >= other.counter; } - bool operator==(std::nullptr_t) const { return counter == nullptr; } - bool operator!=(std::nullptr_t) const { return counter != nullptr; } + bool operator==(const shared_ptr& other) const { return counter == other.counter; } + bool operator!=(const shared_ptr& other) const { return counter != other.counter; } + bool operator<(const shared_ptr& other) const { return counter < other.counter; } + bool operator>(const shared_ptr& other) const { return counter > other.counter; } + bool operator<=(const shared_ptr& other) const { return counter <= other.counter; } + bool operator>=(const shared_ptr& other) const { return counter >= other.counter; } + bool operator==(std::nullptr_t) const { return counter == nullptr; } + bool operator!=(std::nullptr_t) const { return counter != nullptr; } - shared_ptr& operator=(const shared_ptr& other) { - _dec_counter(); - counter = other.counter; - _inc_counter(); - return *this; - } + shared_ptr& operator=(const shared_ptr& other) { + _dec_counter(); + counter = other.counter; + _inc_counter(); + return *this; + } - shared_ptr& operator=(shared_ptr&& other) noexcept { - _dec_counter(); - counter = other.counter; - other.counter = nullptr; - return *this; - } + shared_ptr& operator=(shared_ptr&& other) noexcept { + _dec_counter(); + counter = other.counter; + other.counter = nullptr; + return *this; + } - T& operator*() const { return *_t(); } - T* operator->() const { return _t(); } - T* get() const { return _t(); } + T& operator*() const { return *_t(); } + T* operator->() const { return _t(); } + T* get() const { return _t(); } - int use_count() const { - if(is_tagged()) return 1; - return counter ? *counter : 0; - } + int use_count() const { + if(is_tagged()) return 1; + return counter ? *counter : 0; + } - void reset(){ - _dec_counter(); - counter = nullptr; - } + void reset(){ + _dec_counter(); + counter = nullptr; + } - inline constexpr bool is_tagged() const { - if constexpr(!std::is_same_v) return false; - return (bits & 0b11) != 0b00; - } - inline bool is_tag_00() const { return (bits & 0b11) == 0b00; } - inline bool is_tag_01() const { return (bits & 0b11) == 0b01; } - inline bool is_tag_10() const { return (bits & 0b11) == 0b10; } - inline bool is_tag_11() const { return (bits & 0b11) == 0b11; } - }; + inline constexpr bool is_tagged() const { + if constexpr(!std::is_same_v) return false; + return (bits & 0b11) != 0b00; + } + inline bool is_tag_00() const { return (bits & 0b11) == 0b00; } + inline bool is_tag_01() const { return (bits & 0b11) == 0b01; } + inline bool is_tag_10() const { return (bits & 0b11) == 0b10; } + inline bool is_tag_11() const { return (bits & 0b11) == 0b11; } +}; #undef _t #undef _inc_counter #undef _dec_counter template - shared_ptr make_shared(Args&&... args) { + shared_ptr make_sp(Args&&... args) { static_assert(std::is_base_of_v, "U must be derived from T"); static_assert(std::has_virtual_destructor_v, "T must have virtual destructor"); static_assert(!std::is_same_v || (!std::is_same_v && !std::is_same_v)); @@ -102,16 +103,15 @@ namespace pkpy{ } template - shared_ptr make_shared(Args&&... args) { + shared_ptr make_sp(Args&&... args) { int* p = SpAllocator::template alloc(); *p = 1; new(p+1) T(std::forward(args)...); return shared_ptr(p); } -}; static_assert(sizeof(i64) == sizeof(int*)); static_assert(sizeof(f64) == sizeof(int*)); -static_assert(sizeof(pkpy::shared_ptr) == sizeof(int*)); +static_assert(sizeof(shared_ptr) == sizeof(int*)); static_assert(std::numeric_limits::is_iec559); static_assert(std::numeric_limits::is_iec559); @@ -147,6 +147,8 @@ struct SmallArrayPool { }; -typedef pkpy::shared_ptr PyVar; +typedef shared_ptr PyVar; typedef PyVar PyVarOrNull; -typedef PyVar PyVarRef; \ No newline at end of file +typedef PyVar PyVarRef; + +}; // namespace pkpy diff --git a/src/namedict.h b/src/namedict.h index 641e0182..8b8a3516 100644 --- a/src/namedict.h +++ b/src/namedict.h @@ -4,6 +4,8 @@ #include "memory.h" #include "str.h" +namespace pkpy{ + const int kNameDictNodeSize = sizeof(StrName) + sizeof(PyVar); template @@ -38,199 +40,198 @@ struct DictArrayPool { } }; -namespace pkpy{ - const std::vector kHashSeeds = {9629, 43049, 13267, 59509, 39251, 1249, 35803, 54469, 27689, 9719, 34897, 18973, 30661, 19913, 27919, 32143, 3467, 28019, 1051, 39419, 1361, 28547, 48197, 2609, 24317, 22861, 41467, 17623, 52837, 59053, 33589, 32117}; - static DictArrayPool<32> _dict_pool; +const std::vector kHashSeeds = {9629, 43049, 13267, 59509, 39251, 1249, 35803, 54469, 27689, 9719, 34897, 18973, 30661, 19913, 27919, 32143, 3467, 28019, 1051, 39419, 1361, 28547, 48197, 2609, 24317, 22861, 41467, 17623, 52837, 59053, 33589, 32117}; +static DictArrayPool<32> _dict_pool; - uint16_t find_next_capacity(uint16_t n){ - uint16_t x = 2; - while(x < n) x <<= 1; - return x; - } +uint16_t find_next_capacity(uint16_t n){ + uint16_t x = 2; + while(x < n) x <<= 1; + return x; +} #define _hash(key, mask, hash_seed) ( ( (key).index * (hash_seed) >> 8 ) & (mask) ) - uint16_t find_perfect_hash_seed(uint16_t capacity, const std::vector& keys){ - if(keys.empty()) return kHashSeeds[0]; - std::set indices; - std::pair best_score = {kHashSeeds[0], 0.0f}; - for(int i=0; i best_score.second) best_score = {kHashSeeds[i], score}; +uint16_t find_perfect_hash_seed(uint16_t capacity, const std::vector& keys){ + if(keys.empty()) return kHashSeeds[0]; + std::set indices; + std::pair best_score = {kHashSeeds[0], 0.0f}; + for(int i=0; i best_score.second) best_score = {kHashSeeds[i], score}; + } + return best_score.first; +} + +struct NameDict { + uint16_t _capacity; + uint16_t _size; + float _load_factor; + uint16_t _hash_seed; + uint16_t _mask; + StrName* _keys; + + inline PyVar& value(uint16_t i){ + return reinterpret_cast(_keys + _capacity)[i]; } - struct NameDict { - uint16_t _capacity; - uint16_t _size; - float _load_factor; - uint16_t _hash_seed; - uint16_t _mask; - StrName* _keys; + inline const PyVar& value(uint16_t i) const { + return reinterpret_cast(_keys + _capacity)[i]; + } - inline PyVar& value(uint16_t i){ - return reinterpret_cast(_keys + _capacity)[i]; + NameDict(uint16_t capacity=2, float load_factor=0.67, uint16_t hash_seed=kHashSeeds[0]): + _capacity(capacity), _size(0), _load_factor(load_factor), + _hash_seed(hash_seed), _mask(capacity-1) { + _keys = _dict_pool.alloc(capacity); } - inline const PyVar& value(uint16_t i) const { - return reinterpret_cast(_keys + _capacity)[i]; + NameDict(const NameDict& other) { + memcpy(this, &other, sizeof(NameDict)); + _keys = _dict_pool.alloc(_capacity); + for(int i=0; i<_capacity; i++){ + _keys[i] = other._keys[i]; + value(i) = other.value(i); } + } - NameDict(uint16_t capacity=2, float load_factor=0.67, uint16_t hash_seed=kHashSeeds[0]): - _capacity(capacity), _size(0), _load_factor(load_factor), - _hash_seed(hash_seed), _mask(capacity-1) { - _keys = _dict_pool.alloc(capacity); - } - - NameDict(const NameDict& other) { - memcpy(this, &other, sizeof(NameDict)); - _keys = _dict_pool.alloc(_capacity); - for(int i=0; i<_capacity; i++){ - _keys[i] = other._keys[i]; - value(i) = other.value(i); - } + NameDict& operator=(const NameDict& other) { + _dict_pool.dealloc(_keys, _capacity); + memcpy(this, &other, sizeof(NameDict)); + _keys = _dict_pool.alloc(_capacity); + for(int i=0; i<_capacity; i++){ + _keys[i] = other._keys[i]; + value(i) = other.value(i); } + return *this; + } + + ~NameDict(){ _dict_pool.dealloc(_keys, _capacity); } - NameDict& operator=(const NameDict& other) { - _dict_pool.dealloc(_keys, _capacity); - memcpy(this, &other, sizeof(NameDict)); - _keys = _dict_pool.alloc(_capacity); - for(int i=0; i<_capacity; i++){ - _keys[i] = other._keys[i]; - value(i) = other.value(i); - } - return *this; - } - - ~NameDict(){ _dict_pool.dealloc(_keys, _capacity); } - - NameDict(NameDict&&) = delete; - NameDict& operator=(NameDict&&) = delete; - uint16_t size() const { return _size; } + NameDict(NameDict&&) = delete; + NameDict& operator=(NameDict&&) = delete; + uint16_t size() const { return _size; } #define HASH_PROBE(key, ok, i) \ - ok = false; \ - i = _hash(key, _mask, _hash_seed); \ - while(!_keys[i].empty()) { \ - if(_keys[i] == (key)) { ok = true; break; } \ - i = (i + 1) & _mask; \ +ok = false; \ +i = _hash(key, _mask, _hash_seed); \ +while(!_keys[i].empty()) { \ + if(_keys[i] == (key)) { ok = true; break; } \ + i = (i + 1) & _mask; \ +} + + const PyVar& operator[](StrName key) const { + bool ok; uint16_t i; + HASH_PROBE(key, ok, i); + if(!ok) throw std::out_of_range("NameDict key not found: " + key.str()); + return value(i); } - const PyVar& operator[](StrName key) const { - bool ok; uint16_t i; - HASH_PROBE(key, ok, i); - if(!ok) throw std::out_of_range("NameDict key not found: " + key.str()); - return value(i); - } + PyVar& get(StrName key){ + bool ok; uint16_t i; + HASH_PROBE(key, ok, i); + if(!ok) throw std::out_of_range("NameDict key not found: " + key.str()); + return value(i); + } - PyVar& get(StrName key){ - bool ok; uint16_t i; - HASH_PROBE(key, ok, i); - if(!ok) throw std::out_of_range("NameDict key not found: " + key.str()); - return value(i); - } - - template - void set(StrName key, T&& val){ - bool ok; uint16_t i; - HASH_PROBE(key, ok, i); - if(!ok) { - _size++; - if(_size > _capacity*_load_factor){ - _rehash(true); - HASH_PROBE(key, ok, i); - } - _keys[i] = key; + template + void set(StrName key, T&& val){ + bool ok; uint16_t i; + HASH_PROBE(key, ok, i); + if(!ok) { + _size++; + if(_size > _capacity*_load_factor){ + _rehash(true); + HASH_PROBE(key, ok, i); } - value(i) = std::forward(val); + _keys[i] = key; } + value(i) = std::forward(val); + } - void _rehash(bool resize){ - StrName* old_keys = _keys; - PyVar* old_values = &value(0); - uint16_t old_capacity = _capacity; - if(resize){ - _capacity = find_next_capacity(_capacity * 2); - _mask = _capacity - 1; - } - _keys = _dict_pool.alloc(_capacity); - for(uint16_t i=0; i> items() const { - std::vector> v; - for(uint16_t i=0; i<_capacity; i++){ - if(_keys[i].empty()) continue; - v.push_back(std::make_pair(_keys[i], value(i))); - } - return v; + std::vector> items() const { + std::vector> v; + for(uint16_t i=0; i<_capacity; i++){ + if(_keys[i].empty()) continue; + v.push_back(std::make_pair(_keys[i], value(i))); } + return v; + } - std::vector keys() const { - std::vector v; - for(uint16_t i=0; i<_capacity; i++){ - if(_keys[i].empty()) continue; - v.push_back(_keys[i]); - } - return v; + std::vector keys() const { + std::vector v; + for(uint16_t i=0; i<_capacity; i++){ + if(_keys[i].empty()) continue; + v.push_back(_keys[i]); } + return v; + } #undef HASH_PROBE #undef _hash - }; +}; } // namespace pkpy \ No newline at end of file diff --git a/src/obj.h b/src/obj.h index 735b5238..5fa72ccc 100644 --- a/src/obj.h +++ b/src/obj.h @@ -3,23 +3,24 @@ #include "namedict.h" #include "tuplelist.h" +namespace pkpy { + struct CodeObject; struct Frame; struct BaseRef; class VM; -typedef std::function NativeFuncRaw; -typedef pkpy::shared_ptr CodeObject_; -typedef pkpy::shared_ptr NameDict_; +typedef std::function NativeFuncRaw; +typedef shared_ptr CodeObject_; +typedef shared_ptr NameDict_; -namespace pkpy{ struct NativeFunc { NativeFuncRaw f; int argc; // DONOT include self bool method; NativeFunc(NativeFuncRaw f, int argc, bool method) : f(f), argc(argc), method(method) {} - inline PyVar operator()(VM* vm, pkpy::Args& args) const; + inline PyVar operator()(VM* vm, Args& args) const; }; struct Function { @@ -27,7 +28,7 @@ struct Function { CodeObject_ code; std::vector args; StrName starred_arg; // empty if no *arg - pkpy::NameDict kwargs; // empty if no k=v + NameDict kwargs; // empty if no k=v std::vector kwargs_order; // runtime settings @@ -71,7 +72,6 @@ struct Slice { if(stop < start) stop = start; } }; -} class BaseIter { protected: @@ -86,10 +86,10 @@ public: struct PyObject { Type type; - pkpy::NameDict* _attr; + NameDict* _attr; inline bool is_attr_valid() const noexcept { return _attr != nullptr; } - inline pkpy::NameDict& attr() noexcept { return *_attr; } + inline NameDict& attr() noexcept { return *_attr; } inline const PyVar& attr(StrName name) const noexcept { return _attr->get(name); } virtual void* value() = 0; @@ -106,11 +106,11 @@ struct Py_ : PyObject { inline void _init() noexcept { if constexpr (std::is_same_v || std::is_same_v) { - _attr = new pkpy::NameDict(16, kTypeAttrLoadFactor); + _attr = new NameDict(16, kTypeAttrLoadFactor); }else if constexpr(std::is_same_v){ - _attr = new pkpy::NameDict(4, kInstAttrLoadFactor); - }else if constexpr(std::is_same_v || std::is_same_v){ - _attr = new pkpy::NameDict(4, kInstAttrLoadFactor); + _attr = new NameDict(4, kInstAttrLoadFactor); + }else if constexpr(std::is_same_v || std::is_same_v){ + _attr = new NameDict(4, kInstAttrLoadFactor); }else{ _attr = nullptr; } @@ -162,4 +162,24 @@ union __8B { f64 _float; __8B(i64 val) : _int(val) {} __8B(f64 val) : _float(val) {} -}; \ No newline at end of file +}; + +// Create a new object with the native type `T` and return a PyVar +template +PyVar object(VM* vm, T&) { UNREACHABLE(); } +template +PyVar object(VM* vm, T&&) { UNREACHABLE(); } +template +PyVar object(VM* vm, T) { UNREACHABLE(); } + +// Cast a PyVar to a native type `T` by reference +template +T& cast(VM* vm, const PyVar& var) { UNREACHABLE(); } +template +T cast(VM* vm, const PyVar& var) { UNREACHABLE(); } +template +T& _cast(VM* vm, const PyVar& var) { UNREACHABLE(); } +template +T _cast(VM* vm, const PyVar& var) { UNREACHABLE(); } + +} // namespace pkpy \ No newline at end of file diff --git a/src/parser.h b/src/parser.h index b7e2f20b..7f98fc8d 100644 --- a/src/parser.h +++ b/src/parser.h @@ -2,6 +2,8 @@ #include "obj.h" +namespace pkpy{ + typedef uint8_t TokenIndex; constexpr const char* kTokens[] = { @@ -90,7 +92,7 @@ enum Precedence { // The context of the parsing phase for the compiler. struct Parser { - pkpy::shared_ptr src; + shared_ptr src; const char* token_start; const char* curr_char; @@ -285,11 +287,13 @@ struct Parser { else set_next_token(one); } - Parser(pkpy::shared_ptr src) { + Parser(shared_ptr src) { this->src = src; this->token_start = src->source; this->curr_char = src->source; this->nexts.push(Token{TK("@sof"), token_start, 0, current_line}); this->indents.push(0); } -}; \ No newline at end of file +}; + +} // namespace pkpy \ No newline at end of file diff --git a/src/pocketpy.h b/src/pocketpy.h index 3aa73dfc..d9431056 100644 --- a/src/pocketpy.h +++ b/src/pocketpy.h @@ -4,12 +4,15 @@ #include "compiler.h" #include "repl.h" #include "iter.h" +#include "cffi.h" + +namespace pkpy { CodeObject_ VM::compile(Str source, Str filename, CompileMode mode) { Compiler compiler(this, source.c_str(), filename, mode); try{ return compiler.compile(); - }catch(pkpy::Exception& e){ + }catch(Exception& e){ // std::cout << e.summary() << std::endl; _error(e); return nullptr; @@ -17,7 +20,7 @@ CodeObject_ VM::compile(Str source, Str filename, CompileMode mode) { } #define BIND_NUM_ARITH_OPT(name, op) \ - _vm->_bind_methods<1>({"int","float"}, #name, [](VM* vm, pkpy::Args& args){ \ + _vm->_bind_methods<1>({"int","float"}, #name, [](VM* vm, Args& args){ \ if(is_both_int(args[0], args[1])){ \ return vm->PyInt(vm->_PyInt_AS_C(args[0]) op vm->_PyInt_AS_C(args[1])); \ }else{ \ @@ -26,7 +29,7 @@ CodeObject_ VM::compile(Str source, Str filename, CompileMode mode) { }); #define BIND_NUM_LOGICAL_OPT(name, op, is_eq) \ - _vm->_bind_methods<1>({"int","float"}, #name, [](VM* vm, pkpy::Args& args){ \ + _vm->_bind_methods<1>({"int","float"}, #name, [](VM* vm, Args& args){ \ if(!is_both_int_or_float(args[0], args[1])){ \ if constexpr(is_eq) return vm->PyBool(args[0] op args[1]); \ vm->TypeError("unsupported operand type(s) for " #op ); \ @@ -52,40 +55,40 @@ void init_builtins(VM* _vm) { #undef BIND_NUM_ARITH_OPT #undef BIND_NUM_LOGICAL_OPT - _vm->bind_builtin_func<1>("__sys_stdout_write", [](VM* vm, pkpy::Args& args) { + _vm->bind_builtin_func<1>("__sys_stdout_write", [](VM* vm, Args& args) { (*vm->_stdout) << vm->PyStr_AS_C(args[0]); return vm->None; }); - // _vm->bind_builtin_func<1>("test", [](VM* vm, pkpy::Args& args) { + // _vm->bind_builtin_func<1>("test", [](VM* vm, Args& args) { // args[0]->attr().print_stats(); // return vm->None; // }); - _vm->bind_builtin_func<0>("super", [](VM* vm, pkpy::Args& args) { + _vm->bind_builtin_func<0>("super", [](VM* vm, Args& args) { const PyVar* self = vm->top_frame()->f_locals().try_get(m_self); if(self == nullptr) vm->TypeError("super() can only be called in a class"); return vm->new_object(vm->tp_super, *self); }); - _vm->bind_builtin_func<1>("id", [](VM* vm, pkpy::Args& args) { + _vm->bind_builtin_func<1>("id", [](VM* vm, Args& args) { const PyVar& obj = args[0]; if(obj.is_tagged()) return vm->PyInt((i64)0); return vm->PyInt(obj.bits); }); - _vm->bind_builtin_func<1>("eval", [](VM* vm, pkpy::Args& args) { + _vm->bind_builtin_func<1>("eval", [](VM* vm, Args& args) { CodeObject_ code = vm->compile(vm->PyStr_AS_C(args[0]), "", EVAL_MODE); return vm->_exec(code, vm->top_frame()->_module, vm->top_frame()->_locals); }); - _vm->bind_builtin_func<1>("exec", [](VM* vm, pkpy::Args& args) { + _vm->bind_builtin_func<1>("exec", [](VM* vm, Args& args) { CodeObject_ code = vm->compile(vm->PyStr_AS_C(args[0]), "", EXEC_MODE); vm->_exec(code, vm->top_frame()->_module, vm->top_frame()->_locals); return vm->None; }); - _vm->bind_builtin_func<-1>("exit", [](VM* vm, pkpy::Args& args) { + _vm->bind_builtin_func<-1>("exit", [](VM* vm, Args& args) { if(args.size() == 0) std::exit(0); else if(args.size() == 1) std::exit((int)vm->PyInt_AS_C(args[0])); else vm->TypeError("exit() takes at most 1 argument"); @@ -93,61 +96,61 @@ void init_builtins(VM* _vm) { }); _vm->bind_builtin_func<1>("repr", CPP_LAMBDA(vm->asRepr(args[0]))); - _vm->bind_builtin_func<1>("len", CPP_LAMBDA(vm->call(args[0], __len__, pkpy::no_arg()))); + _vm->bind_builtin_func<1>("len", CPP_LAMBDA(vm->call(args[0], __len__, no_arg()))); - _vm->bind_builtin_func<1>("hash", [](VM* vm, pkpy::Args& args){ + _vm->bind_builtin_func<1>("hash", [](VM* vm, Args& args){ i64 value = vm->hash(args[0]); if(((value << 2) >> 2) != value) value >>= 2; return vm->PyInt(value); }); - _vm->bind_builtin_func<1>("chr", [](VM* vm, pkpy::Args& args) { + _vm->bind_builtin_func<1>("chr", [](VM* vm, Args& args) { i64 i = vm->PyInt_AS_C(args[0]); if (i < 0 || i > 128) vm->ValueError("chr() arg not in range(128)"); return vm->PyStr(std::string(1, (char)i)); }); - _vm->bind_builtin_func<1>("ord", [](VM* vm, pkpy::Args& args) { + _vm->bind_builtin_func<1>("ord", [](VM* vm, Args& args) { Str s = vm->PyStr_AS_C(args[0]); if (s.size() != 1) vm->TypeError("ord() expected an ASCII character"); return vm->PyInt((i64)(s.c_str()[0])); }); - _vm->bind_builtin_func<2>("hasattr", [](VM* vm, pkpy::Args& args) { + _vm->bind_builtin_func<2>("hasattr", [](VM* vm, Args& args) { return vm->PyBool(vm->getattr(args[0], vm->PyStr_AS_C(args[1]), false) != nullptr); }); - _vm->bind_builtin_func<3>("setattr", [](VM* vm, pkpy::Args& args) { + _vm->bind_builtin_func<3>("setattr", [](VM* vm, Args& args) { vm->setattr(args[0], vm->PyStr_AS_C(args[1]), args[2]); return vm->None; }); - _vm->bind_builtin_func<2>("getattr", [](VM* vm, pkpy::Args& args) { + _vm->bind_builtin_func<2>("getattr", [](VM* vm, Args& args) { Str name = vm->PyStr_AS_C(args[1]); return vm->getattr(args[0], name); }); - _vm->bind_builtin_func<1>("hex", [](VM* vm, pkpy::Args& args) { + _vm->bind_builtin_func<1>("hex", [](VM* vm, Args& args) { std::stringstream ss; ss << std::hex << vm->PyInt_AS_C(args[0]); return vm->PyStr("0x" + ss.str()); }); - _vm->bind_builtin_func<1>("dir", [](VM* vm, pkpy::Args& args) { + _vm->bind_builtin_func<1>("dir", [](VM* vm, Args& args) { std::set names; if(args[0]->is_attr_valid()){ std::vector keys = args[0]->attr().keys(); names.insert(keys.begin(), keys.end()); } - const pkpy::NameDict& t_attr = vm->_t(args[0])->attr(); + const NameDict& t_attr = vm->_t(args[0])->attr(); std::vector keys = t_attr.keys(); names.insert(keys.begin(), keys.end()); - pkpy::List ret; + List ret; for (StrName name : names) ret.push_back(vm->PyStr(name.str())); return vm->PyList(std::move(ret)); }); - _vm->bind_method<0>("object", "__repr__", [](VM* vm, pkpy::Args& args) { + _vm->bind_method<0>("object", "__repr__", [](VM* vm, Args& args) { PyVar self = args[0]; std::uintptr_t addr = self.is_tagged() ? 0 : (uintptr_t)self.get(); StrStream ss; @@ -161,8 +164,8 @@ void init_builtins(VM* _vm) { _vm->bind_static_method<1>("type", "__new__", CPP_LAMBDA(vm->_t(args[0]))); - _vm->bind_static_method<-1>("range", "__new__", [](VM* vm, pkpy::Args& args) { - pkpy::Range r; + _vm->bind_static_method<-1>("range", "__new__", [](VM* vm, Args& args) { + Range r; switch (args.size()) { case 1: r.stop = vm->PyInt_AS_C(args[0]); break; case 2: r.start = vm->PyInt_AS_C(args[0]); r.stop = vm->PyInt_AS_C(args[1]); break; @@ -179,13 +182,13 @@ void init_builtins(VM* _vm) { _vm->bind_method<0>("NoneType", "__repr__", CPP_LAMBDA(vm->PyStr("None"))); _vm->bind_method<0>("NoneType", "__json__", CPP_LAMBDA(vm->PyStr("null"))); - _vm->_bind_methods<1>({"int", "float"}, "__truediv__", [](VM* vm, pkpy::Args& args) { + _vm->_bind_methods<1>({"int", "float"}, "__truediv__", [](VM* vm, Args& args) { f64 rhs = vm->num_to_float(args[1]); if (rhs == 0) vm->ZeroDivisionError(); return vm->PyFloat(vm->num_to_float(args[0]) / rhs); }); - _vm->_bind_methods<1>({"int", "float"}, "__pow__", [](VM* vm, pkpy::Args& args) { + _vm->_bind_methods<1>({"int", "float"}, "__pow__", [](VM* vm, Args& args) { if(is_both_int(args[0], args[1])){ i64 lhs = vm->_PyInt_AS_C(args[0]); i64 rhs = vm->_PyInt_AS_C(args[1]); @@ -205,7 +208,7 @@ void init_builtins(VM* _vm) { }); /************ PyInt ************/ - _vm->bind_static_method<1>("int", "__new__", [](VM* vm, pkpy::Args& args) { + _vm->bind_static_method<1>("int", "__new__", [](VM* vm, Args& args) { if (is_type(args[0], vm->tp_int)) return args[0]; if (is_type(args[0], vm->tp_float)) return vm->PyInt((i64)vm->PyFloat_AS_C(args[0])); if (is_type(args[0], vm->tp_bool)) return vm->PyInt(vm->_PyBool_AS_C(args[0]) ? 1 : 0); @@ -224,13 +227,13 @@ void init_builtins(VM* _vm) { return vm->None; }); - _vm->bind_method<1>("int", "__floordiv__", [](VM* vm, pkpy::Args& args) { + _vm->bind_method<1>("int", "__floordiv__", [](VM* vm, Args& args) { i64 rhs = vm->PyInt_AS_C(args[1]); if(rhs == 0) vm->ZeroDivisionError(); return vm->PyInt(vm->PyInt_AS_C(args[0]) / rhs); }); - _vm->bind_method<1>("int", "__mod__", [](VM* vm, pkpy::Args& args) { + _vm->bind_method<1>("int", "__mod__", [](VM* vm, Args& args) { i64 rhs = vm->PyInt_AS_C(args[1]); if(rhs == 0) vm->ZeroDivisionError(); return vm->PyInt(vm->PyInt_AS_C(args[0]) % rhs); @@ -251,10 +254,10 @@ void init_builtins(VM* _vm) { #undef INT_BITWISE_OP /************ PyFloat ************/ - _vm->bind_static_method<1>("float", "__new__", [](VM* vm, pkpy::Args& args) { + _vm->bind_static_method<1>("float", "__new__", [](VM* vm, Args& args) { if (is_type(args[0], vm->tp_int)) return vm->PyFloat((f64)vm->PyInt_AS_C(args[0])); if (is_type(args[0], vm->tp_float)) return args[0]; - if (is_type(args[0], vm->tp_bool)) return vm->PyFloat(vm->PyBool_AS_C(args[0]) ? 1.0 : 0.0); + if (is_type(args[0], vm->tp_bool)) return vm->PyFloat(vm->_PyBool_AS_C(args[0]) ? 1.0 : 0.0); if (is_type(args[0], vm->tp_str)) { const Str& s = vm->PyStr_AS_C(args[0]); if(s == "inf") return vm->PyFloat(INFINITY); @@ -270,7 +273,7 @@ void init_builtins(VM* _vm) { return vm->None; }); - _vm->bind_method<0>("float", "__repr__", [](VM* vm, pkpy::Args& args) { + _vm->bind_method<0>("float", "__repr__", [](VM* vm, Args& args) { f64 val = vm->PyFloat_AS_C(args[0]); if(std::isinf(val) || std::isnan(val)) return vm->PyStr(std::to_string(val)); StrStream ss; @@ -280,7 +283,7 @@ void init_builtins(VM* _vm) { return vm->PyStr(s); }); - _vm->bind_method<0>("float", "__json__", [](VM* vm, pkpy::Args& args) { + _vm->bind_method<0>("float", "__json__", [](VM* vm, Args& args) { f64 val = vm->PyFloat_AS_C(args[0]); if(std::isinf(val) || std::isnan(val)) vm->ValueError("cannot jsonify 'nan' or 'inf'"); return vm->PyStr(std::to_string(val)); @@ -289,18 +292,18 @@ void init_builtins(VM* _vm) { /************ PyString ************/ _vm->bind_static_method<1>("str", "__new__", CPP_LAMBDA(vm->asStr(args[0]))); - _vm->bind_method<1>("str", "__add__", [](VM* vm, pkpy::Args& args) { + _vm->bind_method<1>("str", "__add__", [](VM* vm, Args& args) { const Str& lhs = vm->PyStr_AS_C(args[0]); const Str& rhs = vm->PyStr_AS_C(args[1]); return vm->PyStr(lhs + rhs); }); - _vm->bind_method<0>("str", "__len__", [](VM* vm, pkpy::Args& args) { + _vm->bind_method<0>("str", "__len__", [](VM* vm, Args& args) { const Str& self = vm->PyStr_AS_C(args[0]); return vm->PyInt(self.u8_length()); }); - _vm->bind_method<1>("str", "__contains__", [](VM* vm, pkpy::Args& args) { + _vm->bind_method<1>("str", "__contains__", [](VM* vm, Args& args) { const Str& self = vm->PyStr_AS_C(args[0]); const Str& other = vm->PyStr_AS_C(args[1]); return vm->PyBool(self.find(other) != Str::npos); @@ -309,33 +312,33 @@ void init_builtins(VM* _vm) { _vm->bind_method<0>("str", "__str__", CPP_LAMBDA(args[0])); _vm->bind_method<0>("str", "__iter__", CPP_LAMBDA(vm->PyIter(StringIter(vm, args[0])))); - _vm->bind_method<0>("str", "__repr__", [](VM* vm, pkpy::Args& args) { + _vm->bind_method<0>("str", "__repr__", [](VM* vm, Args& args) { const Str& _self = vm->PyStr_AS_C(args[0]); return vm->PyStr(_self.escape(true)); }); - _vm->bind_method<0>("str", "__json__", [](VM* vm, pkpy::Args& args) { + _vm->bind_method<0>("str", "__json__", [](VM* vm, Args& args) { const Str& _self = vm->PyStr_AS_C(args[0]); return vm->PyStr(_self.escape(false)); }); - _vm->bind_method<1>("str", "__eq__", [](VM* vm, pkpy::Args& args) { + _vm->bind_method<1>("str", "__eq__", [](VM* vm, Args& args) { if(is_type(args[0], vm->tp_str) && is_type(args[1], vm->tp_str)) return vm->PyBool(vm->PyStr_AS_C(args[0]) == vm->PyStr_AS_C(args[1])); return vm->PyBool(args[0] == args[1]); }); - _vm->bind_method<1>("str", "__ne__", [](VM* vm, pkpy::Args& args) { + _vm->bind_method<1>("str", "__ne__", [](VM* vm, Args& args) { if(is_type(args[0], vm->tp_str) && is_type(args[1], vm->tp_str)) return vm->PyBool(vm->PyStr_AS_C(args[0]) != vm->PyStr_AS_C(args[1])); return vm->PyBool(args[0] != args[1]); }); - _vm->bind_method<1>("str", "__getitem__", [](VM* vm, pkpy::Args& args) { + _vm->bind_method<1>("str", "__getitem__", [](VM* vm, Args& args) { const Str& self (vm->PyStr_AS_C(args[0])); if(is_type(args[1], vm->tp_slice)){ - pkpy::Slice s = vm->PySlice_AS_C(args[1]); + Slice s = vm->PySlice_AS_C(args[1]); s.normalize(self.u8_length()); return vm->PyStr(self.u8_substr(s.start, s.stop)); } @@ -345,19 +348,19 @@ void init_builtins(VM* _vm) { return vm->PyStr(self.u8_getitem(index)); }); - _vm->bind_method<1>("str", "__gt__", [](VM* vm, pkpy::Args& args) { + _vm->bind_method<1>("str", "__gt__", [](VM* vm, Args& args) { const Str& self (vm->PyStr_AS_C(args[0])); const Str& obj (vm->PyStr_AS_C(args[1])); return vm->PyBool(self > obj); }); - _vm->bind_method<1>("str", "__lt__", [](VM* vm, pkpy::Args& args) { + _vm->bind_method<1>("str", "__lt__", [](VM* vm, Args& args) { const Str& self (vm->PyStr_AS_C(args[0])); const Str& obj (vm->PyStr_AS_C(args[1])); return vm->PyBool(self < obj); }); - _vm->bind_method<2>("str", "replace", [](VM* vm, pkpy::Args& args) { + _vm->bind_method<2>("str", "replace", [](VM* vm, Args& args) { const Str& _self = vm->PyStr_AS_C(args[0]); const Str& _old = vm->PyStr_AS_C(args[1]); const Str& _new = vm->PyStr_AS_C(args[2]); @@ -371,23 +374,23 @@ void init_builtins(VM* _vm) { return vm->PyStr(_copy); }); - _vm->bind_method<1>("str", "startswith", [](VM* vm, pkpy::Args& args) { + _vm->bind_method<1>("str", "startswith", [](VM* vm, Args& args) { const Str& _self = vm->PyStr_AS_C(args[0]); const Str& _prefix = vm->PyStr_AS_C(args[1]); return vm->PyBool(_self.find(_prefix) == 0); }); - _vm->bind_method<1>("str", "endswith", [](VM* vm, pkpy::Args& args) { + _vm->bind_method<1>("str", "endswith", [](VM* vm, Args& args) { const Str& _self = vm->PyStr_AS_C(args[0]); const Str& _suffix = vm->PyStr_AS_C(args[1]); return vm->PyBool(_self.rfind(_suffix) == _self.length() - _suffix.length()); }); - _vm->bind_method<1>("str", "join", [](VM* vm, pkpy::Args& args) { + _vm->bind_method<1>("str", "join", [](VM* vm, Args& args) { const Str& self = vm->PyStr_AS_C(args[0]); StrStream ss; PyVar obj = vm->asList(args[1]); - const pkpy::List& list = vm->PyList_AS_C(obj); + const List& list = vm->PyList_AS_C(obj); for (int i = 0; i < list.size(); ++i) { if (i > 0) ss << self; ss << vm->PyStr_AS_C(list[i]); @@ -396,29 +399,29 @@ void init_builtins(VM* _vm) { }); /************ PyList ************/ - _vm->bind_method<1>("list", "append", [](VM* vm, pkpy::Args& args) { - pkpy::List& self = vm->PyList_AS_C(args[0]); + _vm->bind_method<1>("list", "append", [](VM* vm, Args& args) { + List& self = vm->PyList_AS_C(args[0]); self.push_back(args[1]); return vm->None; }); - _vm->bind_method<0>("list", "reverse", [](VM* vm, pkpy::Args& args) { - pkpy::List& self = vm->PyList_AS_C(args[0]); + _vm->bind_method<0>("list", "reverse", [](VM* vm, Args& args) { + List& self = vm->PyList_AS_C(args[0]); std::reverse(self.begin(), self.end()); return vm->None; }); - _vm->bind_method<1>("list", "__mul__", [](VM* vm, pkpy::Args& args) { - const pkpy::List& self = vm->PyList_AS_C(args[0]); + _vm->bind_method<1>("list", "__mul__", [](VM* vm, Args& args) { + const List& self = vm->PyList_AS_C(args[0]); int n = (int)vm->PyInt_AS_C(args[1]); - pkpy::List result; + List result; result.reserve(self.size() * n); for(int i = 0; i < n; i++) result.insert(result.end(), self.begin(), self.end()); return vm->PyList(std::move(result)); }); - _vm->bind_method<2>("list", "insert", [](VM* vm, pkpy::Args& args) { - pkpy::List& _self = vm->PyList_AS_C(args[0]); + _vm->bind_method<2>("list", "insert", [](VM* vm, Args& args) { + List& _self = vm->PyList_AS_C(args[0]); int index = (int)vm->PyInt_AS_C(args[1]); if(index < 0) index += _self.size(); if(index < 0) index = 0; @@ -427,37 +430,37 @@ void init_builtins(VM* _vm) { return vm->None; }); - _vm->bind_method<0>("list", "clear", [](VM* vm, pkpy::Args& args) { + _vm->bind_method<0>("list", "clear", [](VM* vm, Args& args) { vm->PyList_AS_C(args[0]).clear(); return vm->None; }); _vm->bind_method<0>("list", "copy", CPP_LAMBDA(vm->PyList(vm->PyList_AS_C(args[0])))); - _vm->bind_method<1>("list", "__add__", [](VM* vm, pkpy::Args& args) { - const pkpy::List& self = vm->PyList_AS_C(args[0]); - const pkpy::List& obj = vm->PyList_AS_C(args[1]); - pkpy::List new_list = self; + _vm->bind_method<1>("list", "__add__", [](VM* vm, Args& args) { + const List& self = vm->PyList_AS_C(args[0]); + const List& obj = vm->PyList_AS_C(args[1]); + List new_list = self; new_list.insert(new_list.end(), obj.begin(), obj.end()); return vm->PyList(new_list); }); - _vm->bind_method<0>("list", "__len__", [](VM* vm, pkpy::Args& args) { - const pkpy::List& self = vm->PyList_AS_C(args[0]); + _vm->bind_method<0>("list", "__len__", [](VM* vm, Args& args) { + const List& self = vm->PyList_AS_C(args[0]); return vm->PyInt(self.size()); }); - _vm->bind_method<0>("list", "__iter__", [](VM* vm, pkpy::Args& args) { - return vm->PyIter(ArrayIter(vm, args[0])); + _vm->bind_method<0>("list", "__iter__", [](VM* vm, Args& args) { + return vm->PyIter(ArrayIter(vm, args[0])); }); - _vm->bind_method<1>("list", "__getitem__", [](VM* vm, pkpy::Args& args) { - const pkpy::List& self = vm->PyList_AS_C(args[0]); + _vm->bind_method<1>("list", "__getitem__", [](VM* vm, Args& args) { + const List& self = vm->PyList_AS_C(args[0]); if(is_type(args[1], vm->tp_slice)){ - pkpy::Slice s = vm->PySlice_AS_C(args[1]); + Slice s = vm->PySlice_AS_C(args[1]); s.normalize(self.size()); - pkpy::List new_list; + List new_list; for(size_t i = s.start; i < s.stop; i++) new_list.push_back(self[i]); return vm->PyList(std::move(new_list)); } @@ -467,16 +470,16 @@ void init_builtins(VM* _vm) { return self[index]; }); - _vm->bind_method<2>("list", "__setitem__", [](VM* vm, pkpy::Args& args) { - pkpy::List& self = vm->PyList_AS_C(args[0]); + _vm->bind_method<2>("list", "__setitem__", [](VM* vm, Args& args) { + List& self = vm->PyList_AS_C(args[0]); int index = (int)vm->PyInt_AS_C(args[1]); index = vm->normalized_index(index, self.size()); self[index] = args[2]; return vm->None; }); - _vm->bind_method<1>("list", "__delitem__", [](VM* vm, pkpy::Args& args) { - pkpy::List& self = vm->PyList_AS_C(args[0]); + _vm->bind_method<1>("list", "__delitem__", [](VM* vm, Args& args) { + List& self = vm->PyList_AS_C(args[0]); int index = (int)vm->PyInt_AS_C(args[1]); index = vm->normalized_index(index, self.size()); self.erase(self.begin() + index); @@ -484,22 +487,22 @@ void init_builtins(VM* _vm) { }); /************ PyTuple ************/ - _vm->bind_static_method<1>("tuple", "__new__", [](VM* vm, pkpy::Args& args) { - pkpy::List list = vm->PyList_AS_C(vm->asList(args[0])); + _vm->bind_static_method<1>("tuple", "__new__", [](VM* vm, Args& args) { + List list = vm->PyList_AS_C(vm->asList(args[0])); return vm->PyTuple(std::move(list)); }); - _vm->bind_method<0>("tuple", "__iter__", [](VM* vm, pkpy::Args& args) { - return vm->PyIter(ArrayIter(vm, args[0])); + _vm->bind_method<0>("tuple", "__iter__", [](VM* vm, Args& args) { + return vm->PyIter(ArrayIter(vm, args[0])); }); - _vm->bind_method<1>("tuple", "__getitem__", [](VM* vm, pkpy::Args& args) { - const pkpy::Tuple& self = vm->PyTuple_AS_C(args[0]); + _vm->bind_method<1>("tuple", "__getitem__", [](VM* vm, Args& args) { + const Tuple& self = vm->PyTuple_AS_C(args[0]); if(is_type(args[1], vm->tp_slice)){ - pkpy::Slice s = vm->PySlice_AS_C(args[1]); + Slice s = vm->PySlice_AS_C(args[1]); s.normalize(self.size()); - pkpy::List new_list; + List new_list; for(size_t i = s.start; i < s.stop; i++) new_list.push_back(self[i]); return vm->PyTuple(std::move(new_list)); } @@ -509,25 +512,25 @@ void init_builtins(VM* _vm) { return self[index]; }); - _vm->bind_method<0>("tuple", "__len__", [](VM* vm, pkpy::Args& args) { - const pkpy::Tuple& self = vm->PyTuple_AS_C(args[0]); + _vm->bind_method<0>("tuple", "__len__", [](VM* vm, Args& args) { + const Tuple& self = vm->PyTuple_AS_C(args[0]); return vm->PyInt(self.size()); }); /************ PyBool ************/ _vm->bind_static_method<1>("bool", "__new__", CPP_LAMBDA(vm->asBool(args[0]))); - _vm->bind_method<0>("bool", "__repr__", [](VM* vm, pkpy::Args& args) { + _vm->bind_method<0>("bool", "__repr__", [](VM* vm, Args& args) { bool val = vm->PyBool_AS_C(args[0]); return vm->PyStr(val ? "True" : "False"); }); - _vm->bind_method<0>("bool", "__json__", [](VM* vm, pkpy::Args& args) { + _vm->bind_method<0>("bool", "__json__", [](VM* vm, Args& args) { bool val = vm->PyBool_AS_C(args[0]); return vm->PyStr(val ? "true" : "false"); }); - _vm->bind_method<1>("bool", "__xor__", [](VM* vm, pkpy::Args& args) { + _vm->bind_method<1>("bool", "__xor__", [](VM* vm, Args& args) { bool self = vm->PyBool_AS_C(args[0]); bool other = vm->PyBool_AS_C(args[1]); return vm->PyBool(self ^ other); @@ -552,7 +555,7 @@ void init_builtins(VM* _vm) { void add_module_time(VM* vm){ PyVar mod = vm->new_module("time"); - vm->bind_func<0>(mod, "time", [](VM* vm, pkpy::Args& args) { + vm->bind_func<0>(mod, "time", [](VM* vm, Args& args) { auto now = std::chrono::high_resolution_clock::now(); return vm->PyFloat(std::chrono::duration_cast(now.time_since_epoch()).count() / 1000000.0); }); @@ -565,7 +568,7 @@ void add_module_sys(VM* vm){ vm->bind_func<1>(mod, "getrefcount", CPP_LAMBDA(vm->PyInt(args[0].use_count()))); vm->bind_func<0>(mod, "getrecursionlimit", CPP_LAMBDA(vm->PyInt(vm->recursionlimit))); - vm->bind_func<1>(mod, "setrecursionlimit", [](VM* vm, pkpy::Args& args) { + vm->bind_func<1>(mod, "setrecursionlimit", [](VM* vm, Args& args) { vm->recursionlimit = (int)vm->PyInt_AS_C(args[0]); return vm->None; }); @@ -573,7 +576,7 @@ void add_module_sys(VM* vm){ void add_module_json(VM* vm){ PyVar mod = vm->new_module("json"); - vm->bind_func<1>(mod, "loads", [](VM* vm, pkpy::Args& args) { + vm->bind_func<1>(mod, "loads", [](VM* vm, Args& args) { const Str& expr = vm->PyStr_AS_C(args[0]); CodeObject_ code = vm->compile(expr, "", JSON_MODE); return vm->_exec(code, vm->top_frame()->_module, vm->top_frame()->_locals); @@ -603,7 +606,7 @@ void add_module_math(VM* vm){ void add_module_dis(VM* vm){ PyVar mod = vm->new_module("dis"); - vm->bind_func<1>(mod, "dis", [](VM* vm, pkpy::Args& args) { + vm->bind_func<1>(mod, "dis", [](VM* vm, Args& args) { PyVar f = args[0]; if(is_type(f, vm->tp_bound_method)) f = vm->PyBoundMethod_AS_C(args[0]).method; CodeObject_ code = vm->PyFunction_AS_C(f).code; @@ -632,32 +635,32 @@ struct FileIO { } static void _register(VM* vm, PyVar mod, PyVar type){ - vm->bind_static_method<2>(type, "__new__", [](VM* vm, pkpy::Args& args){ + vm->bind_static_method<2>(type, "__new__", [](VM* vm, Args& args){ return vm->new_object( vm, vm->PyStr_AS_C(args[0]), vm->PyStr_AS_C(args[1]) ); }); - vm->bind_method<0>(type, "read", [](VM* vm, pkpy::Args& args){ + vm->bind_method<0>(type, "read", [](VM* vm, Args& args){ FileIO& io = vm->py_cast(args[0]); std::string buffer; io._fs >> buffer; return vm->PyStr(buffer); }); - vm->bind_method<1>(type, "write", [](VM* vm, pkpy::Args& args){ + vm->bind_method<1>(type, "write", [](VM* vm, Args& args){ FileIO& io = vm->py_cast(args[0]); io._fs << vm->PyStr_AS_C(args[1]); return vm->None; }); - vm->bind_method<0>(type, "close", [](VM* vm, pkpy::Args& args){ + vm->bind_method<0>(type, "close", [](VM* vm, Args& args){ FileIO& io = vm->py_cast(args[0]); io._fs.close(); return vm->None; }); - vm->bind_method<0>(type, "__exit__", [](VM* vm, pkpy::Args& args){ + vm->bind_method<0>(type, "__exit__", [](VM* vm, Args& args){ FileIO& io = vm->py_cast(args[0]); io._fs.close(); return vm->None; @@ -669,7 +672,7 @@ struct FileIO { void add_module_io(VM* vm){ PyVar mod = vm->new_module("io"); PyVar type = vm->register_class(mod); - vm->bind_builtin_func<2>("open", [type](VM* vm, const pkpy::Args& args){ + vm->bind_builtin_func<2>("open", [type](VM* vm, const Args& args){ return vm->call(type, args); }); } @@ -689,12 +692,12 @@ struct ReMatch { vm->bind_method<0>(type, "start", CPP_LAMBDA(vm->PyInt(vm->py_cast(args[0]).start))); vm->bind_method<0>(type, "end", CPP_LAMBDA(vm->PyInt(vm->py_cast(args[0]).end))); - vm->bind_method<0>(type, "span", [](VM* vm, pkpy::Args& args) { + vm->bind_method<0>(type, "span", [](VM* vm, Args& args) { auto& self = vm->py_cast(args[0]); return vm->PyTuple({ vm->PyInt(self.start), vm->PyInt(self.end) }); }); - vm->bind_method<1>(type, "group", [](VM* vm, pkpy::Args& args) { + vm->bind_method<1>(type, "group", [](VM* vm, Args& args) { auto& self = vm->py_cast(args[0]); int index = (int)vm->PyInt_AS_C(args[1]); index = vm->normalized_index(index, self.m.size()); @@ -719,19 +722,19 @@ void add_module_re(VM* vm){ PyVar mod = vm->new_module("re"); vm->register_class(mod); - vm->bind_func<2>(mod, "match", [](VM* vm, pkpy::Args& args) { + vm->bind_func<2>(mod, "match", [](VM* vm, Args& args) { const Str& pattern = vm->PyStr_AS_C(args[0]); const Str& string = vm->PyStr_AS_C(args[1]); return _regex_search(pattern, string, true, vm); }); - vm->bind_func<2>(mod, "search", [](VM* vm, pkpy::Args& args) { + vm->bind_func<2>(mod, "search", [](VM* vm, Args& args) { const Str& pattern = vm->PyStr_AS_C(args[0]); const Str& string = vm->PyStr_AS_C(args[1]); return _regex_search(pattern, string, false, vm); }); - vm->bind_func<3>(mod, "sub", [](VM* vm, pkpy::Args& args) { + vm->bind_func<3>(mod, "sub", [](VM* vm, Args& args) { const Str& pattern = vm->PyStr_AS_C(args[0]); const Str& repl = vm->PyStr_AS_C(args[1]); const Str& string = vm->PyStr_AS_C(args[2]); @@ -739,13 +742,13 @@ void add_module_re(VM* vm){ return vm->PyStr(std::regex_replace(string, re, repl)); }); - vm->bind_func<2>(mod, "split", [](VM* vm, pkpy::Args& args) { + vm->bind_func<2>(mod, "split", [](VM* vm, Args& args) { const Str& pattern = vm->PyStr_AS_C(args[0]); const Str& string = vm->PyStr_AS_C(args[1]); std::regex re(pattern); std::sregex_token_iterator it(string.begin(), string.end(), re, -1); std::sregex_token_iterator end; - pkpy::List vec; + List vec; for(; it != end; ++it){ vec.push_back(vm->PyStr(it->str())); } @@ -756,20 +759,20 @@ void add_module_re(VM* vm){ void add_module_random(VM* vm){ PyVar mod = vm->new_module("random"); std::srand(std::time(0)); - vm->bind_func<1>(mod, "seed", [](VM* vm, pkpy::Args& args) { + vm->bind_func<1>(mod, "seed", [](VM* vm, Args& args) { std::srand((unsigned int)vm->PyInt_AS_C(args[0])); return vm->None; }); vm->bind_func<0>(mod, "random", CPP_LAMBDA(vm->PyFloat(std::rand() / (f64)RAND_MAX))); - vm->bind_func<2>(mod, "randint", [](VM* vm, pkpy::Args& args) { + vm->bind_func<2>(mod, "randint", [](VM* vm, Args& args) { i64 a = vm->PyInt_AS_C(args[0]); i64 b = vm->PyInt_AS_C(args[1]); if(a > b) std::swap(a, b); return vm->PyInt(a + std::rand() % (b - a + 1)); }); - vm->bind_func<2>(mod, "uniform", [](VM* vm, pkpy::Args& args) { + vm->bind_func<2>(mod, "uniform", [](VM* vm, Args& args) { f64 a = vm->PyFloat_AS_C(args[0]); f64 b = vm->PyFloat_AS_C(args[1]); if(a > b) std::swap(a, b); @@ -786,8 +789,6 @@ void add_module_functools(VM* vm){ vm->_exec(code, mod); } -#include "cffi.h" - void VM::post_init(){ init_builtins(this); add_module_sys(this); @@ -806,17 +807,15 @@ void VM::post_init(){ this->_exec(code, this->builtins); } - -class _PkExported{ +class PkExportedBase{ public: - virtual ~_PkExported() = default; + virtual ~PkExportedBase() = default; virtual void* get() = 0; }; -static std::vector<_PkExported*> _pk_lookup_table; - +static std::vector _pk_lookup_table; template -class PkExported : public _PkExported{ +class PkExported : public PkExportedBase{ T* _ptr; public: template @@ -832,7 +831,6 @@ public: #define PKPY_ALLOCATE(T, ...) *(new PkExported(__VA_ARGS__)) - extern "C" { __EXPORT /// Delete a pointer allocated by `pkpy_xxx_xxx`. @@ -947,12 +945,12 @@ extern "C" { __EXPORT /// Setup the callback functions. - void pkpy_setup_callbacks(f_int_t f_int, f_float_t f_float, f_bool_t f_bool, f_str_t f_str, f_None_t f_None){ - ::f_int = f_int; - ::f_float = f_float; - ::f_bool = f_bool; - ::f_str = f_str; - ::f_None = f_None; + void pkpy_setup_callbacks(f_int_t _f_int, f_float_t _f_float, f_bool_t _f_bool, f_str_t _f_str, f_None_t _f_None){ + f_int = _f_int; + f_float = _f_float; + f_bool = _f_bool; + f_str = _f_str; + f_None = _f_None; } __EXPORT @@ -964,7 +962,7 @@ extern "C" { for(int i=0; name[i]; i++) if(name[i] == ' ') return nullptr; std::string f_header = std::string(mod) + '.' + name + '#' + std::to_string(kGlobalBindId++); PyVar obj = vm->_modules.contains(mod) ? vm->_modules[mod] : vm->new_module(mod); - vm->bind_func<-1>(obj, name, [ret_code, f_header](VM* vm, const pkpy::Args& args){ + vm->bind_func<-1>(obj, name, [ret_code, f_header](VM* vm, const Args& args){ StrStream ss; ss << f_header; for(int i=0; i _lazy_modules; // lazy loaded modules PyVar None, True, False, Ellipsis; @@ -100,10 +102,10 @@ public: PyVar asList(const PyVar& iterable){ if(is_type(iterable, tp_list)) return iterable; - return call(_t(tp_list), pkpy::one_arg(iterable)); + return call(_t(tp_list), one_arg(iterable)); } - PyVar fast_call(StrName name, pkpy::Args&& args){ + PyVar fast_call(StrName name, Args&& args){ PyObject* cls = _t(args[0]).get(); while(cls != None.get()) { PyVar* val = cls->attr().try_get(name); @@ -115,26 +117,26 @@ public: } inline PyVar call(const PyVar& _callable){ - return call(_callable, pkpy::no_arg(), pkpy::no_arg(), false); + return call(_callable, no_arg(), no_arg(), false); } template - inline std::enable_if_t, PyVar> + inline std::enable_if_t, PyVar> call(const PyVar& _callable, ArgT&& args){ - return call(_callable, std::forward(args), pkpy::no_arg(), false); + return call(_callable, std::forward(args), no_arg(), false); } template - inline std::enable_if_t, PyVar> + inline std::enable_if_t, PyVar> call(const PyVar& obj, const StrName name, ArgT&& args){ - return call(getattr(obj, name), std::forward(args), pkpy::no_arg(), false); + return call(getattr(obj, name), std::forward(args), no_arg(), false); } inline PyVar call(const PyVar& obj, StrName name){ - return call(getattr(obj, name), pkpy::no_arg(), pkpy::no_arg(), false); + return call(getattr(obj, name), no_arg(), no_arg(), false); } - PyVar call(const PyVar& _callable, pkpy::Args args, const pkpy::Args& kwargs, bool opCall){ + PyVar call(const PyVar& _callable, Args args, const Args& kwargs, bool opCall){ if(is_type(_callable, tp_type)){ PyVar* new_f = _callable->attr().try_get(__new__); PyVar obj; @@ -156,12 +158,12 @@ public: } if(is_type(*callable, tp_native_function)){ - const auto& f = OBJ_GET(pkpy::NativeFunc, *callable); + const auto& f = OBJ_GET(NativeFunc, *callable); if(kwargs.size() != 0) TypeError("native_function does not accept keyword arguments"); return f(this, args); } else if(is_type(*callable, tp_function)){ - const pkpy::Function& fn = PyFunction_AS_C(*callable); - NameDict_ locals = pkpy::make_shared( + const Function& fn = PyFunction_AS_C(*callable); + NameDict_ locals = make_sp( fn.code->perfect_locals_capacity, kLocalsLoadFactor, fn.code->perfect_hash_seed @@ -179,7 +181,7 @@ public: locals->update(fn.kwargs); if(!fn.starred_arg.empty()){ - pkpy::List vargs; // handle *args + List vargs; // handle *args while(i < args.size()) vargs.push_back(std::move(args[i++])); locals->set(fn.starred_arg, PyTuple(std::move(vargs))); }else{ @@ -217,7 +219,7 @@ public: try { CodeObject_ code = compile(source, filename, mode); return _exec(code, _module); - }catch (const pkpy::Exception& e){ + }catch (const Exception& e){ *_stderr << e.summary() << '\n'; }catch (const std::exception& e) { *_stderr << "An std::exception occurred! It could be a bug.\n"; @@ -269,7 +271,7 @@ public: continue; }catch(UnhandledException& e){ PyVar obj = frame->pop(); - pkpy::Exception& _e = PyException_AS_C(obj); + Exception& _e = PyException_AS_C(obj); _e.st_push(frame->snapshot()); callstack.pop(); if(callstack.empty()) throw _e; @@ -285,7 +287,7 @@ public: PyVar new_type_object(PyVar mod, StrName name, PyVar base){ if(!is_type(base, tp_type)) UNREACHABLE(); - PyVar obj = pkpy::make_shared>(tp_type, _all_types.size()); + PyVar obj = make_sp>(tp_type, _all_types.size()); setattr(obj, __base__, base); Str fullName = name.str(); if(mod != builtins) fullName = OBJ_NAME(mod) + "." + name.str(); @@ -296,7 +298,7 @@ public: } Type _new_type_object(StrName name, Type base=0) { - PyVar obj = pkpy::make_shared>(tp_type, _all_types.size()); + PyVar obj = make_sp>(tp_type, _all_types.size()); setattr(obj, __base__, _t(base)); _types.set(name, obj); _all_types.push_back(obj); @@ -306,21 +308,21 @@ public: template inline PyVar new_object(const PyVar& type, const T& _value) { if(!is_type(type, tp_type)) UNREACHABLE(); - return pkpy::make_shared>(OBJ_GET(Type, type), _value); + return make_sp>(OBJ_GET(Type, type), _value); } template inline PyVar new_object(const PyVar& type, T&& _value) { if(!is_type(type, tp_type)) UNREACHABLE(); - return pkpy::make_shared>(OBJ_GET(Type, type), std::move(_value)); + return make_sp>(OBJ_GET(Type, type), std::move(_value)); } template inline PyVar new_object(Type type, const T& _value) { - return pkpy::make_shared>(type, _value); + return make_sp>(type, _value); } template inline PyVar new_object(Type type, T&& _value) { - return pkpy::make_shared>(type, std::move(_value)); + return make_sp>(type, std::move(_value)); } template @@ -365,7 +367,7 @@ public: if(val != nullptr){ PyVarOrNull descriptor = getattr(*val, __get__, false); if(descriptor != nullptr){ - return call(descriptor, pkpy::one_arg(obj)); + return call(descriptor, one_arg(obj)); } if(is_type(*val, tp_function) || is_type(*val, tp_native_function)){ return PyBoundMethod({obj, *val}); @@ -391,12 +393,12 @@ public: template void bind_method(PyVar obj, Str funcName, NativeFuncRaw fn) { check_type(obj, tp_type); - setattr(obj, funcName, PyNativeFunc(pkpy::NativeFunc(fn, ARGC, true))); + setattr(obj, funcName, PyNativeFunc(NativeFunc(fn, ARGC, true))); } template void bind_func(PyVar obj, Str funcName, NativeFuncRaw fn) { - setattr(obj, funcName, PyNativeFunc(pkpy::NativeFunc(fn, ARGC, false))); + setattr(obj, funcName, PyNativeFunc(NativeFunc(fn, ARGC, false))); } template @@ -504,7 +506,7 @@ public: StrStream names; names << "co_names: "; - pkpy::List list; + List list; for(int i=0; inames.size(); i++){ list.push_back(PyStr(co->names[i].first.str())); } @@ -602,15 +604,15 @@ public: return __8B(bits)._float; } - DEF_NATIVE(List, pkpy::List, tp_list) - DEF_NATIVE(Tuple, pkpy::Tuple, tp_tuple) - DEF_NATIVE(Function, pkpy::Function, tp_function) - DEF_NATIVE(NativeFunc, pkpy::NativeFunc, tp_native_function) - DEF_NATIVE(BoundMethod, pkpy::BoundMethod, tp_bound_method) - DEF_NATIVE(Range, pkpy::Range, tp_range) - DEF_NATIVE(Slice, pkpy::Slice, tp_slice) - DEF_NATIVE(Exception, pkpy::Exception, tp_exception) - DEF_NATIVE(StarWrapper, pkpy::StarWrapper, tp_star_wrapper) + DEF_NATIVE(List, List, tp_list) + DEF_NATIVE(Tuple, Tuple, tp_tuple) + DEF_NATIVE(Function, Function, tp_function) + DEF_NATIVE(NativeFunc, NativeFunc, tp_native_function) + DEF_NATIVE(BoundMethod, BoundMethod, tp_bound_method) + DEF_NATIVE(Range, Range, tp_range) + DEF_NATIVE(Slice, Slice, tp_slice) + DEF_NATIVE(Exception, Exception, tp_exception) + DEF_NATIVE(StarWrapper, StarWrapper, tp_star_wrapper) // there is only one True/False, so no need to copy them! inline bool PyBool_AS_C(const PyVar& obj){ @@ -621,8 +623,8 @@ public: inline const PyVar& PyBool(bool value){return value ? True : False;} void init_builtin_types(){ - PyVar _tp_object = pkpy::make_shared>(1, 0); - PyVar _tp_type = pkpy::make_shared>(1, 1); + PyVar _tp_object = make_sp>(1, 0); + PyVar _tp_type = make_sp>(1, 1); _all_types.push_back(_tp_object); _all_types.push_back(_tp_type); tp_object = 0; tp_type = 1; @@ -684,7 +686,7 @@ public: if (is_int(obj)) return PyInt_AS_C(obj); if (is_type(obj, tp_tuple)) { i64 x = 1000003; - const pkpy::Tuple& items = PyTuple_AS_C(obj); + const Tuple& items = PyTuple_AS_C(obj); for (int i=0; i> 2)); // recommended by Github Copilot @@ -702,12 +704,11 @@ public: } /***** Error Reporter *****/ -private: void _error(StrName name, const Str& msg){ - _error(pkpy::Exception(name, msg)); + _error(Exception(name, msg)); } - void _error(pkpy::Exception e){ + void _error(Exception e){ if(callstack.empty()){ e.is_re = false; throw e; @@ -767,14 +768,14 @@ public: return OBJ_GET(T, obj); } - void unpack_args(pkpy::Args& args){ - pkpy::List unpacked; + void unpack_args(Args& args){ + List unpacked; for(int i=0; ifast_call(__getitem__, pkpy::two_args(obj, index)); + return vm->fast_call(__getitem__, two_args(obj, index)); } void IndexRef::set(VM* vm, Frame* frame, PyVar val) const{ - pkpy::Args args(3); + Args args(3); args[0] = obj; args[1] = index; args[2] = std::move(val); vm->fast_call(__setitem__, std::move(args)); } void IndexRef::del(VM* vm, Frame* frame) const{ - vm->fast_call(__delitem__, pkpy::two_args(obj, index)); + vm->fast_call(__delitem__, two_args(obj, index)); } PyVar TupleRef::get(VM* vm, Frame* frame) const{ - pkpy::Tuple args(objs.size()); + Tuple args(objs.size()); for (int i = 0; i < objs.size(); i++) { args[i] = vm->PyRef_AS_C(objs[i])->get(vm, frame); } @@ -890,7 +891,7 @@ void TupleRef::set(VM* vm, Frame* frame, PyVar val) const{ if(star.rvalue) vm->ValueError("can't use starred expression here"); if(i != objs.size()-1) vm->ValueError("* can only be used at the end"); auto ref = vm->PyRef_AS_C(star.obj); - pkpy::List list; + List list; while((x = iter->next()) != nullptr) list.push_back(x); ref->set(vm, frame, vm->PyList(std::move(list))); return; @@ -913,7 +914,7 @@ inline void Frame::try_deref(VM* vm, PyVar& v){ if(is_type(v, vm->tp_ref)) v = vm->PyRef_AS_C(v)->get(vm, this); } -PyVar pkpy::NativeFunc::operator()(VM* vm, pkpy::Args& args) const{ +PyVar NativeFunc::operator()(VM* vm, Args& args) const{ int args_size = args.size() - (int)method; // remove self if(argc != -1 && args_size != argc) { vm->TypeError("expected " + std::to_string(argc) + " arguments, but got " + std::to_string(args_size)); @@ -925,8 +926,8 @@ void CodeObject::optimize(VM* vm){ std::vector keys; for(auto& p: names) if(p.second == NAME_LOCAL) keys.push_back(p.first); uint32_t base_n = (uint32_t)(keys.size() / kLocalsLoadFactor + 0.5); - perfect_locals_capacity = pkpy::find_next_capacity(base_n); - perfect_hash_seed = pkpy::find_perfect_hash_seed(perfect_locals_capacity, keys); + perfect_locals_capacity = find_next_capacity(base_n); + perfect_hash_seed = find_perfect_hash_seed(perfect_locals_capacity, keys); for(int i=1; i PyVar object(VM* vm, i64 val){ + if(((val << 2) >> 2) != val){ + vm->_error("OverflowError", std::to_string(val) + " is out of range"); + } + val = (val << 2) | 0b01; + return PyVar(reinterpret_cast(val)); + } + template<> i64 cast(VM* vm, const PyVar& obj){ + vm->check_type(obj, vm->tp_int); + return obj.bits >> 2; + } + template<> i64 _cast(VM* vm, const PyVar& obj){ + return obj.bits >> 2; + } + + template<> PyVar object(VM* vm, f64 val){ + i64 bits = __8B(val)._int; + bits = (bits >> 2) << 2; + bits |= 0b10; + return PyVar(reinterpret_cast(bits)); + } + template<> f64 cast(VM* vm, const PyVar& obj){ + vm->check_type(obj, vm->tp_float); + i64 bits = obj.bits; + bits = (bits >> 2) << 2; + return __8B(bits)._float; + } + template<> f64 _cast(VM* vm, const PyVar& obj){ + i64 bits = obj.bits; + bits = (bits >> 2) << 2; + return __8B(bits)._float; + } + + template<> PyVar object(VM* vm, bool val){ + return val ? vm->True : vm->False; + } + template<> bool cast(VM* vm, const PyVar& obj){ + vm->check_type(obj, vm->tp_bool); + return obj == vm->True; + } + template<> bool _cast(VM* vm, const PyVar& obj){ + return obj == vm->True; + } + +} // namespace pkpy \ No newline at end of file