From 4cb624159882797cbb9ea449517b35d64e77ffa4 Mon Sep 17 00:00:00 2001 From: BLUELOVETH Date: Fri, 7 Jul 2023 18:27:38 +0800 Subject: [PATCH] `CAST(f64, x)` accept `i64` now --- include/pocketpy/obj.h | 2 +- include/pocketpy/vm.h | 38 +++++++++++++++++++++----------------- src/linalg.cpp | 8 ++++---- src/vm.cpp | 13 ++++--------- 4 files changed, 30 insertions(+), 31 deletions(-) diff --git a/include/pocketpy/obj.h b/include/pocketpy/obj.h index 00dc362f..e4aa3e92 100644 --- a/include/pocketpy/obj.h +++ b/include/pocketpy/obj.h @@ -223,7 +223,7 @@ __T _py_cast(VM* vm, PyObject* obj) { #define CAST(T, x) py_cast(vm, x) #define _CAST(T, x) _py_cast(vm, x) -#define CAST_F(x) vm->num_to_float(x) +#define CAST_F(x) py_cast(vm, x) #define CAST_DEFAULT(T, x, default_value) (x != vm->None) ? py_cast(vm, x) : (default_value) /*****************************************************************/ diff --git a/include/pocketpy/vm.h b/include/pocketpy/vm.h index a7e0e229..5f727a95 100644 --- a/include/pocketpy/vm.h +++ b/include/pocketpy/vm.h @@ -382,10 +382,7 @@ public: check_type(obj, tp_int); // if failed, redirect to check_type to raise TypeError } - void check_float(PyObject* obj){ - if(is_float(obj)) return; - check_type(obj, tp_float); // if failed, redirect to check_type to raise TypeError - } + void check_int_or_float(PyObject* obj); PyObject* _t(Type t){ return _all_types[t.index].obj; @@ -433,7 +430,6 @@ public: PyObject* vectorcall(int ARGC, int KWARGC=0, bool op_call=false); CodeObject_ compile(Str source, Str filename, CompileMode mode, bool unknown_global_scope=false); PyObject* py_negate(PyObject* obj); - f64 num_to_float(PyObject* obj); bool py_bool(PyObject* obj); i64 py_hash(PyObject* obj); PyObject* py_list(PyObject*); @@ -498,24 +494,32 @@ PY_CAST_INT(unsigned long) PY_CAST_INT(unsigned long long) template<> inline float py_cast(VM* vm, PyObject* obj){ - vm->check_float(obj); - i64 bits = PK_BITS(obj) & Number::c1; - return BitsCvt(bits)._float; + if(is_float(obj)){ + i64 bits = PK_BITS(obj) & Number::c1; + return BitsCvt(bits)._float; + } + if(is_int(obj)){ + return (float)_py_cast(vm, obj); + } + vm->check_int_or_float(obj); // error! + return 0; } template<> inline float _py_cast(VM* vm, PyObject* obj){ - PK_UNUSED(vm); - i64 bits = PK_BITS(obj) & Number::c1; - return BitsCvt(bits)._float; + return py_cast(vm, obj); } template<> inline double py_cast(VM* vm, PyObject* obj){ - vm->check_float(obj); - i64 bits = PK_BITS(obj) & Number::c1; - return BitsCvt(bits)._float; + if(is_float(obj)){ + i64 bits = PK_BITS(obj) & Number::c1; + return BitsCvt(bits)._float; + } + if(is_int(obj)){ + return (float)_py_cast(vm, obj); + } + vm->check_int_or_float(obj); // error! + return 0; } template<> inline double _py_cast(VM* vm, PyObject* obj){ - PK_UNUSED(vm); - i64 bits = PK_BITS(obj) & Number::c1; - return BitsCvt(bits)._float; + return py_cast(vm, obj); } diff --git a/src/linalg.cpp b/src/linalg.cpp index fd38caf7..cadc4d05 100644 --- a/src/linalg.cpp +++ b/src/linalg.cpp @@ -18,7 +18,7 @@ namespace pkpy{ #define BIND_VEC_FLOAT_OP(D, name, op) \ vm->bind_method<1>(type, #name, [](VM* vm, ArgsView args){ \ PyVec##D& self = _CAST(PyVec##D&, args[0]); \ - f64 other = vm->num_to_float(args[1]); \ + f64 other = CAST(f64, args[1]); \ return VAR(self op other); \ }); @@ -41,7 +41,7 @@ namespace pkpy{ return VAR(self.name); \ }, [](VM* vm, ArgsView args){ \ PyVec##D& self = _CAST(PyVec##D&, args[0]); \ - self.name = vm->num_to_float(args[1]); \ + self.name = CAST(f64, args[1]); \ return vm->None; \ })); @@ -72,7 +72,7 @@ namespace pkpy{ vm->bind_method<1>(type, "rotate", [](VM* vm, ArgsView args){ Vec2 self = _CAST(PyVec2&, args[0]); - float radian = vm->num_to_float(args[1]); + float radian = CAST(f64, args[1]); float cr = cosf(radian); float sr = sinf(radian); Mat3x3 rotate(cr, -sr, 0.0f, @@ -289,7 +289,7 @@ namespace pkpy{ return VAR(self.field); \ }, [](VM* vm, ArgsView args){ \ PyMat3x3& self = _CAST(PyMat3x3&, args[0]); \ - self.field = vm->num_to_float(args[1]); \ + self.field = CAST(f64, args[1]); \ return vm->None; \ })); diff --git a/src/vm.cpp b/src/vm.cpp index 2613f1ca..b97a2ffb 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -278,17 +278,12 @@ PyObject* VM::py_negate(PyObject* obj){ return call_method(obj, __neg__); } -f64 VM::num_to_float(PyObject* obj){ - if(is_float(obj)){ - return _CAST(f64, obj); - } else if (is_int(obj)){ - return (f64)_CAST(i64, obj); +void VM::check_int_or_float(PyObject *obj){ + if(!is_tagged(obj)){ + TypeError("expected 'int' or 'float', got " + OBJ_NAME(_t(obj)).escape()); } - TypeError("expected 'int' or 'float', got " + OBJ_NAME(_t(obj)).escape()); - return 0; } - bool VM::py_bool(PyObject* obj){ if(is_non_tagged_type(obj, tp_bool)) return obj == True; if(obj == None) return false; @@ -416,7 +411,7 @@ PyObject* VM::format(Str spec, PyObject* obj){ if(type != 'f' && dot >= 0) ValueError("precision not allowed in the format specifier"); Str ret; if(type == 'f'){ - f64 val = num_to_float(obj); + f64 val = CAST(f64, obj); if(precision < 0) precision = 6; std::stringstream ss; ss << std::fixed << std::setprecision(precision) << val;