blueloveTH před 1 rokem
rodič
revize
182177482f
4 změnil soubory, kde provedl 27 přidání a 23 odebrání
  1. 1 1
      amalgamate.py
  2. 19 11
      include/pocketpy/any.h
  3. 2 11
      include/pocketpy/codeobject.h
  4. 5 0
      src/any.cpp

+ 1 - 1
amalgamate.py

@@ -6,7 +6,7 @@ with open("include/pocketpy/opcodes.h", "rt", encoding='utf-8') as f:
 	OPCODES_TEXT = '\n' + f.read() + '\n'
 
 pipeline = [
-	["config.h", "export.h", "_generated.h", "common.h", "memory.h", "any.h", "vector.h", "str.h", "tuplelist.h", "namedict.h", "error.h"],
+	["config.h", "export.h", "_generated.h", "common.h", "memory.h", "vector.h", "str.h", "tuplelist.h", "namedict.h", "error.h", "any.h"],
 	["obj.h", "dict.h", "codeobject.h", "frame.h", "profiler.h"],
 	["gc.h", "vm.h", "ceval.h", "lexer.h", "expr.h", "compiler.h", "repl.h"],
 	["cffi.h", "bindings.h", "iter.h", "base64.h", "csv.h", "collections.h", "array2d.h", "dataclasses.h", "random.h", "linalg.h", "easing.h", "io.h", "modules.h"],

+ 19 - 11
include/pocketpy/any.h

@@ -1,6 +1,7 @@
 #pragma once
 
 #include "common.h"
+#include "str.h"
 
 namespace pkpy {
 
@@ -52,18 +53,25 @@ struct any{
     any& operator=(const any& other) = delete;
 
     ~any() { if(data) _vt->deleter(data); }
-};
 
-template<typename T>
-bool any_cast(const any& a, T** out){
-    static_assert(std::is_same_v<T, std::decay_t<T>>);
-    if(a.type_id() != typeid(T)) return false;
-    if constexpr (is_sso_v<T>){
-        *out = (T*)(&a.data);
-    }else{
-        *out = static_cast<T*>(a.data);
+    template<typename T>
+    T& _cast() const noexcept{
+        static_assert(std::is_same_v<T, std::decay_t<T>>);
+        if constexpr (is_sso_v<T>){
+            return *((T*)(&data));
+        }else{
+            return *(static_cast<T*>(data));
+        }
     }
-    return true;
-}
+
+    template<typename T>
+    T& cast() const{
+        static_assert(std::is_same_v<T, std::decay_t<T>>);
+        if(type_id() != typeid(T)) __bad_any_cast(typeid(T), type_id());
+        return _cast<T>();
+    }
+
+    static void __bad_any_cast(const std::type_index expected, const std::type_index actual);
+};
 
 } // namespace pkpy

+ 2 - 11
include/pocketpy/codeobject.h

@@ -186,17 +186,8 @@ struct Py_<NativeFunc> final: PyObject {
 template<typename T>
 T& lambda_get_userdata(PyObject** p){
     static_assert(std::is_same_v<T, std::decay_t<T>>);
-    any* ud;
-    if(p[-1] != PY_NULL) ud = &PK_OBJ_GET(NativeFunc, p[-1])._userdata;
-    else ud = &PK_OBJ_GET(NativeFunc, p[-2])._userdata;
-    T* out;
-    if(!any_cast(*ud, &out)){
-        const char* expected = typeid(T).name();
-        const char* actual = ud->type_id().name();
-        Str error = _S("lambda_get_userdata: any_cast failed: expected ", expected, ", got ", actual);
-        throw std::runtime_error(error.c_str());
-    }
-    return *out;
+    int offset = p[-1] != PY_NULL ? -1 : -2;
+    return PK_OBJ_GET(NativeFunc, p[offset])._userdata.cast<T>();
 }
 
 } // namespace pkpy

+ 5 - 0
src/any.cpp

@@ -2,6 +2,11 @@
 
 namespace pkpy{
 
+void any::__bad_any_cast(const std::type_index expected, const std::type_index actual){
+    Str error = _S("bad_any_cast: expected ", expected.name(), ", got ", actual.name());
+    throw std::runtime_error(error.c_str());
+}
+
 any::any(any&& other) noexcept: data(other.data), _vt(other._vt){
     other.data = nullptr;
     other._vt = nullptr;