From 3c972c9f4607690abc0bae5b042803bc3c845df6 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Mon, 27 Feb 2023 19:22:03 +0800 Subject: [PATCH] up --- src/cffi.h | 26 ++++++++++---------- src/iter.h | 2 +- src/pocketpy.h | 48 ++++++++++++++++++------------------- src/vm.h | 64 +++++++++++++++++++++++++++++++++----------------- 4 files changed, 80 insertions(+), 60 deletions(-) diff --git a/src/cffi.h b/src/cffi.h index a7d344ca..746498be 100644 --- a/src/cffi.h +++ b/src/cffi.h @@ -141,20 +141,20 @@ struct Pointer{ PyVar get(VM* vm){ switch(ctype.index){ - case C_TYPE("char_"): return vm->PyInt(ref()); - case C_TYPE("int_"): return vm->PyInt(ref()); + case C_TYPE("char_"): return py_object(vm, ref()); + case C_TYPE("int_"): return py_object(vm, ref()); case C_TYPE("float_"): return vm->PyFloat(ref()); case C_TYPE("double_"): return vm->PyFloat(ref()); case C_TYPE("bool_"): return vm->PyBool(ref()); case C_TYPE("void_"): vm->ValueError("cannot get void*"); break; - case C_TYPE("int8_"): return vm->PyInt(ref()); - case C_TYPE("int16_"): return vm->PyInt(ref()); - case C_TYPE("int32_"): return vm->PyInt(ref()); - case C_TYPE("int64_"): return vm->PyInt(ref()); - case C_TYPE("uint8_"): return vm->PyInt(ref()); - case C_TYPE("uint16_"): return vm->PyInt(ref()); - case C_TYPE("uint32_"): return vm->PyInt(ref()); - case C_TYPE("uint64_"): return vm->PyInt(ref()); + case C_TYPE("int8_"): return py_object(vm, ref()); + case C_TYPE("int16_"): return py_object(vm, ref()); + case C_TYPE("int32_"): return py_object(vm, ref()); + case C_TYPE("int64_"): return py_object(vm, ref()); + case C_TYPE("uint8_"): return py_object(vm, ref()); + case C_TYPE("uint16_"): return py_object(vm, ref()); + case C_TYPE("uint32_"): return py_object(vm, ref()); + case C_TYPE("uint64_"): return py_object(vm, ref()); case C_TYPE("void_p_"): return vm->new_object(ref(), C_TYPE_T("void_")); // use macro here to do extension default: UNREACHABLE(); @@ -274,7 +274,7 @@ void add_module_c(VM* vm){ vm->bind_func<1>(mod, "sizeof", [](VM* vm, Args& args) { CType& ctype = vm->py_cast(args[0]); - return vm->PyInt(ctype.size); + return py_object(vm, ctype.size); }); vm->bind_func<3>(mod, "memcpy", [](VM* vm, Args& args) { @@ -309,12 +309,12 @@ void add_module_c(VM* vm){ 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())); + return py_object(vm, strcmp(p1.cast(), p2.cast())); }); vm->bind_func<1>(mod, "strlen", [](VM* vm, Args& args) { Pointer& p = vm->py_cast(args[0]); - return vm->PyInt(strlen(p.cast())); + return py_object(vm, strlen(p.cast())); }); } diff --git a/src/iter.h b/src/iter.h index bca3c65d..21580ff8 100644 --- a/src/iter.h +++ b/src/iter.h @@ -20,7 +20,7 @@ public: PyVar next(){ if(!_has_next()) return nullptr; current += r.step; - return vm->PyInt(current-r.step); + return py_object(vm, current-r.step); } }; diff --git a/src/pocketpy.h b/src/pocketpy.h index 3fd0d34d..54e328b2 100644 --- a/src/pocketpy.h +++ b/src/pocketpy.h @@ -22,7 +22,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, 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])); \ + return py_object(vm, vm->_PyInt_AS_C(args[0]) op vm->_PyInt_AS_C(args[1])); \ }else{ \ return vm->PyFloat(vm->num_to_float(args[0]) op vm->num_to_float(args[1])); \ } \ @@ -73,8 +73,8 @@ void init_builtins(VM* _vm) { _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); + if(obj.is_tagged()) return py_object(vm, (i64)0); + return py_object(vm, obj.bits); }); _vm->bind_builtin_func<1>("eval", [](VM* vm, Args& args) { @@ -101,7 +101,7 @@ void init_builtins(VM* _vm) { _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); + return py_object(vm, value); }); _vm->bind_builtin_func<1>("chr", [](VM* vm, Args& args) { @@ -113,7 +113,7 @@ void init_builtins(VM* _vm) { _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])); + return py_object(vm, (i64)(s.c_str()[0])); }); _vm->bind_builtin_func<2>("hasattr", [](VM* vm, Args& args) { @@ -201,7 +201,7 @@ void init_builtins(VM* _vm) { rhs >>= 1; } if(flag) return vm->PyFloat((f64)(1.0 / ret)); - return vm->PyInt(ret); + return py_object(vm, ret); }else{ return vm->PyFloat((f64)std::pow(vm->num_to_float(args[0]), vm->num_to_float(args[1]))); } @@ -210,15 +210,15 @@ void init_builtins(VM* _vm) { /************ PyInt ************/ _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); + if (is_type(args[0], vm->tp_float)) return py_object(vm, (i64)vm->PyFloat_AS_C(args[0])); + if (is_type(args[0], vm->tp_bool)) return py_object(vm, vm->_PyBool_AS_C(args[0]) ? 1 : 0); if (is_type(args[0], vm->tp_str)) { const Str& s = vm->PyStr_AS_C(args[0]); try{ size_t parsed = 0; i64 val = S_TO_INT(s, &parsed, 10); if(parsed != s.size()) throw std::invalid_argument(""); - return vm->PyInt(val); + return py_object(vm, val); }catch(std::invalid_argument&){ vm->ValueError("invalid literal for int(): " + s.escape(true)); } @@ -230,20 +230,20 @@ void init_builtins(VM* _vm) { _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); + return py_object(vm, vm->PyInt_AS_C(args[0]) / rhs); }); _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); + return py_object(vm, vm->PyInt_AS_C(args[0]) % rhs); }); _vm->bind_method<0>("int", "__repr__", CPP_LAMBDA(vm->PyStr(std::to_string(vm->PyInt_AS_C(args[0]))))); _vm->bind_method<0>("int", "__json__", CPP_LAMBDA(vm->PyStr(std::to_string(vm->PyInt_AS_C(args[0]))))); #define INT_BITWISE_OP(name,op) \ - _vm->bind_method<1>("int", #name, CPP_LAMBDA(vm->PyInt(vm->PyInt_AS_C(args[0]) op vm->PyInt_AS_C(args[1])))); + _vm->bind_method<1>("int", #name, CPP_LAMBDA(py_object(vm, vm->PyInt_AS_C(args[0]) op vm->PyInt_AS_C(args[1])))); INT_BITWISE_OP(__lshift__, <<) INT_BITWISE_OP(__rshift__, >>) @@ -300,7 +300,7 @@ void init_builtins(VM* _vm) { _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()); + return py_object(vm, self.u8_length()); }); _vm->bind_method<1>("str", "__contains__", [](VM* vm, Args& args) { @@ -447,7 +447,7 @@ void init_builtins(VM* _vm) { _vm->bind_method<0>("list", "__len__", [](VM* vm, Args& args) { const List& self = vm->PyList_AS_C(args[0]); - return vm->PyInt(self.size()); + return py_object(vm, self.size()); }); _vm->bind_method<0>("list", "__iter__", [](VM* vm, Args& args) { @@ -514,7 +514,7 @@ void init_builtins(VM* _vm) { _vm->bind_method<0>("tuple", "__len__", [](VM* vm, Args& args) { const Tuple& self = vm->PyTuple_AS_C(args[0]); - return vm->PyInt(self.size()); + return py_object(vm, self.size()); }); /************ PyBool ************/ @@ -565,8 +565,8 @@ void add_module_sys(VM* vm){ PyVar mod = vm->new_module("sys"); vm->setattr(mod, "version", vm->PyStr(PK_VERSION)); - 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, "getrefcount", CPP_LAMBDA(py_object(vm, args[0].use_count()))); + vm->bind_func<0>(mod, "getrecursionlimit", CPP_LAMBDA(py_object(vm, vm->recursionlimit))); vm->bind_func<1>(mod, "setrecursionlimit", [](VM* vm, Args& args) { vm->recursionlimit = (int)vm->PyInt_AS_C(args[0]); @@ -599,8 +599,8 @@ void add_module_math(VM* vm){ vm->bind_func<1>(mod, "isnan", CPP_LAMBDA(vm->PyBool(std::isnan(vm->num_to_float(args[0]))))); vm->bind_func<1>(mod, "isinf", CPP_LAMBDA(vm->PyBool(std::isinf(vm->num_to_float(args[0]))))); vm->bind_func<1>(mod, "fabs", CPP_LAMBDA(vm->PyFloat(std::fabs(vm->num_to_float(args[0]))))); - vm->bind_func<1>(mod, "floor", CPP_LAMBDA(vm->PyInt((i64)std::floor(vm->num_to_float(args[0]))))); - vm->bind_func<1>(mod, "ceil", CPP_LAMBDA(vm->PyInt((i64)std::ceil(vm->num_to_float(args[0]))))); + vm->bind_func<1>(mod, "floor", CPP_LAMBDA(py_object(vm, (i64)std::floor(vm->num_to_float(args[0]))))); + vm->bind_func<1>(mod, "ceil", CPP_LAMBDA(py_object(vm, (i64)std::ceil(vm->num_to_float(args[0]))))); vm->bind_func<1>(mod, "sqrt", CPP_LAMBDA(vm->PyFloat(std::sqrt(vm->num_to_float(args[0]))))); } @@ -688,12 +688,12 @@ struct ReMatch { static void _register(VM* vm, PyVar mod, PyVar type){ vm->bind_method<-1>(type, "__init__", CPP_NOT_IMPLEMENTED()); - 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, "start", CPP_LAMBDA(py_object(vm, vm->py_cast(args[0]).start))); + vm->bind_method<0>(type, "end", CPP_LAMBDA(py_object(vm, vm->py_cast(args[0]).end))); 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) }); + return vm->PyTuple({ py_object(vm, self.start), py_object(vm, self.end) }); }); vm->bind_method<1>(type, "group", [](VM* vm, Args& args) { @@ -768,7 +768,7 @@ void add_module_random(VM* vm){ 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)); + return py_object(vm, a + std::rand() % (b - a + 1)); }); vm->bind_func<2>(mod, "uniform", [](VM* vm, Args& args) { @@ -975,7 +975,7 @@ extern "C" { } char* packet = strdup(ss.str().c_str()); switch(ret_code){ - case 'i': return vm->PyInt(f_int(packet)); + case 'i': return py_object(vm, f_int(packet)); case 'f': return vm->PyFloat(f_float(packet)); case 'b': return vm->PyBool(f_bool(packet)); case 's': { diff --git a/src/vm.h b/src/vm.h index dc539139..6b91b1e1 100644 --- a/src/vm.h +++ b/src/vm.h @@ -4,7 +4,7 @@ #include "error.h" namespace pkpy{ - + #define DEF_NATIVE(type, ctype, ptype) \ inline ctype& Py##type##_AS_C(const PyVar& obj) { \ check_type(obj, ptype); \ @@ -13,6 +13,17 @@ namespace pkpy{ inline PyVar Py##type(const ctype& value) { return new_object(ptype, value);} \ inline PyVar Py##type(ctype&& value) { return new_object(ptype, std::move(value));} +#define DEF_NATIVE_2(ctype, ptype) \ + template<> ctype& py_cast(VM* vm, const PyVar& obj) { \ + vm->check_type(obj, vm->ptype); \ + return OBJ_GET(ctype, obj); \ + } \ + template<> ctype& _py_cast(VM* vm, const PyVar& obj) { \ + return OBJ_GET(ctype, obj); \ + } \ + PyVar py_object(VM* vm, const ctype& value) { return vm->new_object(vm->ptype, value);} \ + PyVar py_object(VM* vm, ctype&& value) { return vm->new_object(vm->ptype, std::move(value));} + class Generator: public BaseIter { std::unique_ptr frame; int state; // 0,1,2 @@ -307,12 +318,16 @@ public: template inline PyVar new_object(const PyVar& type, const T& _value) { +#ifdef PK_EXTRA_CHECK if(!is_type(type, tp_type)) UNREACHABLE(); +#endif return make_sp>(OBJ_GET(Type, type), _value); } template inline PyVar new_object(const PyVar& type, T&& _value) { +#ifdef PK_EXTRA_CHECK if(!is_type(type, tp_type)) UNREACHABLE(); +#endif return make_sp>(OBJ_GET(Type, type), std::move(_value)); } @@ -436,16 +451,6 @@ public: return 0; } - PyVar num_negated(const PyVar& obj){ - if (is_int(obj)){ - return PyInt(-PyInt_AS_C(obj)); - }else if(is_float(obj)){ - return PyFloat(-PyFloat_AS_C(obj)); - } - TypeError("expected 'int' or 'float', got " + OBJ_NAME(_t(obj)).escape(true)); - return nullptr; - } - int normalized_index(int index, int size){ if(index < 0) index += size; if(index < 0 || index >= size){ @@ -567,14 +572,6 @@ public: return new_object(tp_str, value); } - inline PyVar PyInt(i64 value) { - if(((value << 2) >> 2) != value){ - _error("OverflowError", std::to_string(value) + " is out of range"); - } - value = (value << 2) | 0b01; - return PyVar(reinterpret_cast(value)); - } - inline i64 PyInt_AS_C(const PyVar& obj){ check_type(obj, tp_int); return obj.bits >> 2; @@ -679,8 +676,6 @@ public: for(auto [k, v]: _modules.items()) v->attr()._try_perfect_rehash(); } - void post_init(); - i64 hash(const PyVar& obj){ if (is_type(obj, tp_str)) return PyStr_AS_C(obj).hash(); if (is_int(obj)) return PyInt_AS_C(obj); @@ -792,6 +787,8 @@ public: } CodeObject_ compile(Str source, Str filename, CompileMode mode); + void post_init(); + PyVar num_negated(const PyVar& obj); }; /***** Pointers' Impl *****/ @@ -958,7 +955,9 @@ void CodeObject::optimize(VM* vm){ template std::enable_if_t, PyVar> py_object(VM* vm, T _val){ i64 val = static_cast(_val); - if(((val << 2) >> 2) != val) vm->_error("OverflowError", std::to_string(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)); } @@ -999,4 +998,25 @@ template<> bool _py_cast(VM* vm, const PyVar& obj){ return obj == vm->True; } +DEF_NATIVE_2(List, tp_list) +DEF_NATIVE_2(Tuple, tp_tuple) +DEF_NATIVE_2(Function, tp_function) +DEF_NATIVE_2(NativeFunc, tp_native_function) +DEF_NATIVE_2(BoundMethod, tp_bound_method) +DEF_NATIVE_2(Range, tp_range) +DEF_NATIVE_2(Slice, tp_slice) +DEF_NATIVE_2(Exception, tp_exception) +DEF_NATIVE_2(StarWrapper, tp_star_wrapper) + + +PyVar VM::num_negated(const PyVar& obj){ + if (is_int(obj)){ + return py_object(this, -PyInt_AS_C(obj)); + }else if(is_float(obj)){ + return py_object(this, -PyFloat_AS_C(obj)); + } + TypeError("expected 'int' or 'float', got " + OBJ_NAME(_t(obj)).escape(true)); + return nullptr; +} + } // namespace pkpy \ No newline at end of file