mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
some fix
This commit is contained in:
parent
9943516d79
commit
eae0aa6c8b
@ -194,3 +194,13 @@ Enabling the profiler has a performance overhead. Only enable it when you need i
|
|||||||
|
|
||||||
+ `vm->is_non_tagged_type` was removed. Use `vm->is_type` instead.
|
+ `vm->is_non_tagged_type` was removed. Use `vm->is_type` instead.
|
||||||
+ `vm->check_non_tagged_type` was removed. Use `vm->check_type` instead.
|
+ `vm->check_non_tagged_type` was removed. Use `vm->check_type` instead.
|
||||||
|
|
||||||
|
## Python Stringify functions
|
||||||
|
|
||||||
|
The following functions now return `Str` object instead of `PyObject*`:
|
||||||
|
|
||||||
|
+ `vm->py_str`
|
||||||
|
+ `vm->py_repr`
|
||||||
|
+ `vm->py_json`
|
||||||
|
|
||||||
|
Also, `vm->bind__str__` and `vm->bind__repr__` were changed to return `Str` object.
|
||||||
|
@ -237,21 +237,21 @@ Convert a python object to string
|
|||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
PyObject* obj = py_var(vm, 123);
|
PyObject* obj = py_var(vm, 123);
|
||||||
obj = vm->py_str(obj); // 123
|
Str s = vm->py_str(obj); // 123
|
||||||
```
|
```
|
||||||
|
|
||||||
Get the string representation of a python object
|
Get the string representation of a python object
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
PyObject* obj = py_var(vm, "123");
|
PyObject* obj = py_var(vm, "123");
|
||||||
obj = vm->py_repr(obj); // "'123'"
|
Str s = vm->py_repr(obj); // "'123'"
|
||||||
```
|
```
|
||||||
|
|
||||||
Get the JSON representation of a python object
|
Get the JSON representation of a python object
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
PyObject* obj = py_var(vm, 123);
|
PyObject* obj = py_var(vm, 123);
|
||||||
obj = vm->py_json(obj); // "123"
|
Str s = vm->py_json(obj); // "123"
|
||||||
```
|
```
|
||||||
|
|
||||||
Get the hash value of a python object
|
Get the hash value of a python object
|
||||||
|
@ -14,17 +14,18 @@ auto _lock = vm->heap.gc_scope_lock();
|
|||||||
|
|
||||||
The scope lock is required if you create a PyObject and then try to run python-level bytecodes.
|
The scope lock is required if you create a PyObject and then try to run python-level bytecodes.
|
||||||
|
|
||||||
For example, you create a temporary object on the stack and then call `vm->py_str`.
|
For example, you create a temporary object on the stack and then call `vm->py_next`.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
void some_func(VM* vm){
|
void some_func(VM* vm){
|
||||||
PyObject* obj = VAR(List(5));
|
PyObject* obj = VAR(List(5));
|
||||||
// unsafe
|
// unsafe
|
||||||
PyObject obj_string = vm->py_str(obj);
|
PyObject iter = vm->py_iter(obj);
|
||||||
|
PyObject next = vm->py_next(iter);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Because users can have an overload of `__str__`, this call is unsafe.
|
Because users can have an overload of `__next__`, this call is unsafe.
|
||||||
When the vm is running python-level bytecodes, gc may start and delete your temporary object.
|
When the vm is running python-level bytecodes, gc may start and delete your temporary object.
|
||||||
|
|
||||||
The scope lock prevents this from happening.
|
The scope lock prevents this from happening.
|
||||||
@ -34,6 +35,7 @@ void some_func(VM* vm){
|
|||||||
PyObject* obj = VAR(List(5));
|
PyObject* obj = VAR(List(5));
|
||||||
// safe
|
// safe
|
||||||
auto _lock = vm->heap.gc_scope_lock();
|
auto _lock = vm->heap.gc_scope_lock();
|
||||||
PyObject obj_string = vm->py_str(obj);
|
PyObject iter = vm->py_iter(obj);
|
||||||
|
PyObject next = vm->py_next(iter);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -50,10 +50,9 @@ struct PyTypeInfo{
|
|||||||
|
|
||||||
std::vector<StrName> annotated_fields = {};
|
std::vector<StrName> annotated_fields = {};
|
||||||
|
|
||||||
// cached special methods
|
|
||||||
// unary operators
|
// unary operators
|
||||||
PyObject* (*m__repr__)(VM* vm, PyObject*) = nullptr;
|
Str (*m__repr__)(VM* vm, PyObject*) = nullptr;
|
||||||
PyObject* (*m__str__)(VM* vm, PyObject*) = nullptr;
|
Str (*m__str__)(VM* vm, PyObject*) = nullptr;
|
||||||
i64 (*m__hash__)(VM* vm, PyObject*) = nullptr;
|
i64 (*m__hash__)(VM* vm, PyObject*) = nullptr;
|
||||||
i64 (*m__len__)(VM* vm, PyObject*) = nullptr;
|
i64 (*m__len__)(VM* vm, PyObject*) = nullptr;
|
||||||
PyObject* (*m__iter__)(VM* vm, PyObject*) = nullptr;
|
PyObject* (*m__iter__)(VM* vm, PyObject*) = nullptr;
|
||||||
@ -183,9 +182,10 @@ public:
|
|||||||
VM(bool enable_os=true);
|
VM(bool enable_os=true);
|
||||||
|
|
||||||
#if PK_REGION("Python Equivalents")
|
#if PK_REGION("Python Equivalents")
|
||||||
PyObject* py_str(PyObject* obj); // x -> str(x)
|
Str py_str(PyObject* obj); // x -> str(x)
|
||||||
PyObject* py_repr(PyObject* obj); // x -> repr(x)
|
Str py_repr(PyObject* obj); // x -> repr(x)
|
||||||
PyObject* py_json(PyObject* obj); // x -> json.dumps(x)
|
Str py_json(PyObject* obj); // x -> json.dumps(x)
|
||||||
|
|
||||||
PyObject* py_iter(PyObject* obj); // x -> iter(x)
|
PyObject* py_iter(PyObject* obj); // x -> iter(x)
|
||||||
PyObject* py_next(PyObject*); // x -> next(x)
|
PyObject* py_next(PyObject*); // x -> next(x)
|
||||||
PyObject* _py_next(const PyTypeInfo*, PyObject*); // x -> next(x) with type info cache
|
PyObject* _py_next(const PyTypeInfo*, PyObject*); // x -> next(x) with type info cache
|
||||||
@ -269,9 +269,10 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PK_REGION("Magic Bindings")
|
#if PK_REGION("Magic Bindings")
|
||||||
void bind__repr__(Type type, PyObject* (*f)(VM*, PyObject*));
|
void bind__repr__(Type type, Str (*f)(VM*, PyObject*));
|
||||||
void bind__str__(Type type, PyObject* (*f)(VM*, PyObject*));
|
void bind__str__(Type type, Str (*f)(VM*, PyObject*));
|
||||||
void bind__iter__(Type type, PyObject* (*f)(VM*, PyObject*));
|
void bind__iter__(Type type, PyObject* (*f)(VM*, PyObject*));
|
||||||
|
|
||||||
void bind__next__(Type type, unsigned (*f)(VM*, PyObject*));
|
void bind__next__(Type type, unsigned (*f)(VM*, PyObject*));
|
||||||
[[deprecated]] void bind__next__(Type type, PyObject* (*f)(VM*, PyObject*));
|
[[deprecated]] void bind__next__(Type type, PyObject* (*f)(VM*, PyObject*));
|
||||||
void bind__neg__(Type type, PyObject* (*f)(VM*, PyObject*));
|
void bind__neg__(Type type, PyObject* (*f)(VM*, PyObject*));
|
||||||
|
@ -181,9 +181,9 @@ struct Array2d{
|
|||||||
return (i64)self.numel;
|
return (i64)self.numel;
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0){
|
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* _0) -> Str{
|
||||||
Array2d& self = PK_OBJ_GET(Array2d, _0);
|
Array2d& self = PK_OBJ_GET(Array2d, _0);
|
||||||
return VAR(_S("array2d(", self.n_cols, ", ", self.n_rows, ')'));
|
return _S("array2d(", self.n_cols, ", ", self.n_rows, ')');
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind(type, "map(self, f)", [](VM* vm, ArgsView args){
|
vm->bind(type, "map(self, f)", [](VM* vm, ArgsView args){
|
||||||
|
@ -134,7 +134,7 @@ __NEXT_STEP:;
|
|||||||
THIRD() = _0;
|
THIRD() = _0;
|
||||||
} DISPATCH()
|
} DISPATCH()
|
||||||
case OP_PRINT_EXPR:{
|
case OP_PRINT_EXPR:{
|
||||||
if(TOP() != None) stdout_write(CAST(Str&, py_repr(TOP())) + "\n");
|
if(TOP() != None) stdout_write(py_repr(TOP()) + "\n");
|
||||||
POP();
|
POP();
|
||||||
} DISPATCH()
|
} DISPATCH()
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
@ -383,7 +383,7 @@ __NEXT_STEP:;
|
|||||||
case OP_BUILD_STRING: {
|
case OP_BUILD_STRING: {
|
||||||
SStream ss;
|
SStream ss;
|
||||||
ArgsView view = STACK_VIEW(byte.arg);
|
ArgsView view = STACK_VIEW(byte.arg);
|
||||||
for(PyObject* obj : view) ss << CAST(Str&, py_str(obj));
|
for(PyObject* obj : view) ss << py_str(obj);
|
||||||
STACK_SHRINK(byte.arg);
|
STACK_SHRINK(byte.arg);
|
||||||
PUSH(VAR(ss.str()));
|
PUSH(VAR(ss.str()));
|
||||||
} DISPATCH()
|
} DISPATCH()
|
||||||
@ -657,7 +657,7 @@ __NEXT_STEP:;
|
|||||||
PUSH(_0);
|
PUSH(_0);
|
||||||
} DISPATCH()
|
} DISPATCH()
|
||||||
case OP_REPR:
|
case OP_REPR:
|
||||||
TOP() = py_repr(TOP());
|
TOP() = VAR(py_repr(TOP()));
|
||||||
DISPATCH()
|
DISPATCH()
|
||||||
case OP_CALL:{
|
case OP_CALL:{
|
||||||
if(heap._should_auto_collect()) heap._auto_collect();
|
if(heap._should_auto_collect()) heap._auto_collect();
|
||||||
@ -933,8 +933,9 @@ __NEXT_STEP:;
|
|||||||
} DISPATCH()
|
} DISPATCH()
|
||||||
case OP_RAISE_ASSERT:
|
case OP_RAISE_ASSERT:
|
||||||
if(byte.arg){
|
if(byte.arg){
|
||||||
PyObject* _0 = py_str(POPX());
|
Str msg = py_str(TOP());
|
||||||
AssertionError(CAST(Str, _0));
|
POP();
|
||||||
|
AssertionError(msg);
|
||||||
}else{
|
}else{
|
||||||
AssertionError();
|
AssertionError();
|
||||||
}
|
}
|
||||||
|
10
src/cffi.cpp
10
src/cffi.cpp
@ -14,9 +14,9 @@ namespace pkpy{
|
|||||||
return reinterpret_cast<i64>(self.ptr);
|
return reinterpret_cast<i64>(self.ptr);
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
|
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj) -> Str{
|
||||||
VoidP& self = PK_OBJ_GET(VoidP, obj);
|
VoidP& self = PK_OBJ_GET(VoidP, obj);
|
||||||
return VAR(_S("<void* at ", self.hex(), ">"));
|
return _S("<void* at ", self.hex(), ">");
|
||||||
});
|
});
|
||||||
|
|
||||||
#define BIND_CMP(name, op) \
|
#define BIND_CMP(name, op) \
|
||||||
@ -76,7 +76,7 @@ namespace pkpy{
|
|||||||
Struct& self = _CAST(Struct&, obj);
|
Struct& self = _CAST(Struct&, obj);
|
||||||
SStream ss;
|
SStream ss;
|
||||||
ss << "<struct object of " << self.size << " bytes>";
|
ss << "<struct object of " << self.size << " bytes>";
|
||||||
return VAR(ss.str());
|
return ss.str();
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind_func(type, "addr", 1, [](VM* vm, ArgsView args){
|
vm->bind_func(type, "addr", 1, [](VM* vm, ArgsView args){
|
||||||
@ -234,9 +234,9 @@ void add_module_c(VM* vm){
|
|||||||
T* target = (T*)voidp.ptr; \
|
T* target = (T*)voidp.ptr; \
|
||||||
return vm->heap.gcnew<VoidP>(lhs->type, target - offset); \
|
return vm->heap.gcnew<VoidP>(lhs->type, target - offset); \
|
||||||
}); \
|
}); \
|
||||||
vm->bind__repr__(type_t, [](VM* vm, PyObject* obj){ \
|
vm->bind__repr__(type_t, [](VM* vm, PyObject* obj) -> Str{ \
|
||||||
VoidP& self = _CAST(VoidP&, obj); \
|
VoidP& self = _CAST(VoidP&, obj); \
|
||||||
return VAR(_S("<", CNAME, "* at ", self.hex(), ">")); \
|
return _S("<", CNAME, "* at ", self.hex(), ">"); \
|
||||||
}); \
|
}); \
|
||||||
|
|
||||||
BIND_PRIMITIVE(char, "char")
|
BIND_PRIMITIVE(char, "char")
|
||||||
|
@ -105,21 +105,21 @@ namespace pkpy
|
|||||||
return vm->new_user_object<PyDequeIter>(_0, self.dequeItems.begin(), self.dequeItems.end());
|
return vm->new_user_object<PyDequeIter>(_0, self.dequeItems.begin(), self.dequeItems.end());
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM *vm, PyObject* _0)
|
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM *vm, PyObject* _0) -> Str
|
||||||
{
|
{
|
||||||
if(vm->_repr_recursion_set.count(_0)) return VAR("[...]");
|
if(vm->_repr_recursion_set.count(_0)) return "[...]";
|
||||||
const PyDeque &self = _CAST(PyDeque&, _0);
|
const PyDeque &self = _CAST(PyDeque&, _0);
|
||||||
SStream ss;
|
SStream ss;
|
||||||
ss << "deque([";
|
ss << "deque([";
|
||||||
vm->_repr_recursion_set.insert(_0);
|
vm->_repr_recursion_set.insert(_0);
|
||||||
for (auto it = self.dequeItems.begin(); it != self.dequeItems.end(); ++it)
|
for (auto it = self.dequeItems.begin(); it != self.dequeItems.end(); ++it)
|
||||||
{
|
{
|
||||||
ss << CAST(Str&, vm->py_repr(*it));
|
ss << vm->py_repr(*it);
|
||||||
if (it != self.dequeItems.end() - 1) ss << ", ";
|
if (it != self.dequeItems.end() - 1) ss << ", ";
|
||||||
}
|
}
|
||||||
vm->_repr_recursion_set.erase(_0);
|
vm->_repr_recursion_set.erase(_0);
|
||||||
self.bounded ? ss << "], maxlen=" << self.maxlen << ")" : ss << "])";
|
self.bounded ? ss << "], maxlen=" << self.maxlen << ")" : ss << "])";
|
||||||
return VAR(ss.str());
|
return ss.str();
|
||||||
});
|
});
|
||||||
|
|
||||||
// enables comparison between two deques, == and != are supported
|
// enables comparison between two deques, == and != are supported
|
||||||
@ -253,7 +253,7 @@ namespace pkpy
|
|||||||
int start = CAST_DEFAULT(int, args[2], 0);
|
int start = CAST_DEFAULT(int, args[2], 0);
|
||||||
int stop = CAST_DEFAULT(int, args[3], self.dequeItems.size());
|
int stop = CAST_DEFAULT(int, args[3], self.dequeItems.size());
|
||||||
int index = self.findIndex(vm, obj, start, stop);
|
int index = self.findIndex(vm, obj, start, stop);
|
||||||
if (index < 0) vm->ValueError(_CAST(Str &, vm->py_repr(obj)) + " is not in deque");
|
if (index < 0) vm->ValueError(vm->py_repr(obj) + " is not in deque");
|
||||||
return VAR(index);
|
return VAR(index);
|
||||||
});
|
});
|
||||||
// NEW: returns the index of the given object in the deque
|
// NEW: returns the index of the given object in the deque
|
||||||
@ -290,7 +290,7 @@ namespace pkpy
|
|||||||
PyObject *obj = args[1];
|
PyObject *obj = args[1];
|
||||||
PyObject *removed = self.popObj(false, false, obj, vm);
|
PyObject *removed = self.popObj(false, false, obj, vm);
|
||||||
if (removed == nullptr)
|
if (removed == nullptr)
|
||||||
vm->ValueError(_CAST(Str &, vm->py_repr(obj)) + " is not in list");
|
vm->ValueError(vm->py_repr(obj) + " is not in list");
|
||||||
return vm->None;
|
return vm->None;
|
||||||
});
|
});
|
||||||
// NEW: reverses the deque
|
// NEW: reverses the deque
|
||||||
|
@ -45,8 +45,7 @@ static void patch__init__(VM* vm, Type cls){
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void patch__repr__(VM* vm, Type cls){
|
static void patch__repr__(VM* vm, Type cls){
|
||||||
vm->bind__repr__(cls, [](VM* vm, PyObject* _0){
|
vm->bind__repr__(cls, [](VM* vm, PyObject* _0) -> Str{
|
||||||
auto _lock = vm->heap.gc_scope_lock();
|
|
||||||
const PyTypeInfo* cls_info = &vm->_all_types[vm->_tp(_0)];
|
const PyTypeInfo* cls_info = &vm->_all_types[vm->_tp(_0)];
|
||||||
const auto& fields = cls_info->annotated_fields;
|
const auto& fields = cls_info->annotated_fields;
|
||||||
const NameDict& obj_d = _0->attr();
|
const NameDict& obj_d = _0->attr();
|
||||||
@ -56,10 +55,10 @@ static void patch__repr__(VM* vm, Type cls){
|
|||||||
for(StrName field: fields){
|
for(StrName field: fields){
|
||||||
if(first) first = false;
|
if(first) first = false;
|
||||||
else ss << ", ";
|
else ss << ", ";
|
||||||
ss << field << "=" << CAST(Str&, vm->py_repr(obj_d[field]));
|
ss << field << "=" << vm->py_repr(obj_d[field]);
|
||||||
}
|
}
|
||||||
ss << ")";
|
ss << ")";
|
||||||
return VAR(ss.str());
|
return ss.str();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,12 +149,12 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
|||||||
return VAR(val);
|
return VAR(val);
|
||||||
}, {}, BindType::STATICMETHOD);
|
}, {}, BindType::STATICMETHOD);
|
||||||
|
|
||||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
|
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj) -> Str{
|
||||||
Vec2 self = _CAST(Vec2&, obj);
|
Vec2 self = _CAST(Vec2&, obj);
|
||||||
SStream ss;
|
SStream ss;
|
||||||
ss.setprecision(3);
|
ss.setprecision(3);
|
||||||
ss << "vec2(" << self.x << ", " << self.y << ")";
|
ss << "vec2(" << self.x << ", " << self.y << ")";
|
||||||
return VAR(ss.str());
|
return ss.str();
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind_func(type, "rotate", 2, [](VM* vm, ArgsView args){
|
vm->bind_func(type, "rotate", 2, [](VM* vm, ArgsView args){
|
||||||
@ -200,12 +200,12 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
|||||||
return vm->heap.gcnew<Vec3>(PK_OBJ_GET(Type, args[0]), x, y, z);
|
return vm->heap.gcnew<Vec3>(PK_OBJ_GET(Type, args[0]), x, y, z);
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
|
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj) -> Str{
|
||||||
Vec3 self = _CAST(Vec3&, obj);
|
Vec3 self = _CAST(Vec3&, obj);
|
||||||
SStream ss;
|
SStream ss;
|
||||||
ss.setprecision(3);
|
ss.setprecision(3);
|
||||||
ss << "vec3(" << self.x << ", " << self.y << ", " << self.z << ")";
|
ss << "vec3(" << self.x << ", " << self.y << ", " << self.z << ")";
|
||||||
return VAR(ss.str());
|
return ss.str();
|
||||||
});
|
});
|
||||||
|
|
||||||
PY_FIELD(Vec3, "x", x)
|
PY_FIELD(Vec3, "x", x)
|
||||||
@ -239,12 +239,12 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
|||||||
return vm->heap.gcnew<Vec4>(PK_OBJ_GET(Type, args[0]), x, y, z, w);
|
return vm->heap.gcnew<Vec4>(PK_OBJ_GET(Type, args[0]), x, y, z, w);
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
|
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj) -> Str{
|
||||||
Vec4 self = _CAST(Vec4&, obj);
|
Vec4 self = _CAST(Vec4&, obj);
|
||||||
SStream ss;
|
SStream ss;
|
||||||
ss.setprecision(3);
|
ss.setprecision(3);
|
||||||
ss << "vec4(" << self.x << ", " << self.y << ", " << self.z << ", " << self.w << ")";
|
ss << "vec4(" << self.x << ", " << self.y << ", " << self.z << ", " << self.w << ")";
|
||||||
return VAR(ss.str());
|
return ss.str();
|
||||||
});
|
});
|
||||||
|
|
||||||
PY_FIELD(Vec4, "x", x)
|
PY_FIELD(Vec4, "x", x)
|
||||||
@ -298,14 +298,14 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
|||||||
return vm->None;
|
return vm->None;
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj){
|
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj) -> Str{
|
||||||
const Mat3x3& self = _CAST(Mat3x3&, obj);
|
const Mat3x3& self = _CAST(Mat3x3&, obj);
|
||||||
SStream ss;
|
SStream ss;
|
||||||
ss.setprecision(3);
|
ss.setprecision(3);
|
||||||
ss << "mat3x3([" << self._11 << ", " << self._12 << ", " << self._13 << ",\n";
|
ss << "mat3x3([" << self._11 << ", " << self._12 << ", " << self._13 << ",\n";
|
||||||
ss << " " << self._21 << ", " << self._22 << ", " << self._23 << ",\n";
|
ss << " " << self._21 << ", " << self._22 << ", " << self._23 << ",\n";
|
||||||
ss << " " << self._31 << ", " << self._32 << ", " << self._33 << "])";
|
ss << " " << self._31 << ", " << self._32 << ", " << self._33 << "])";
|
||||||
return VAR(ss.str());
|
return ss.str();
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind__getitem__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj, PyObject* index){
|
vm->bind__getitem__(PK_OBJ_GET(Type, type), [](VM* vm, PyObject* obj, PyObject* index){
|
||||||
|
@ -103,7 +103,7 @@ void add_module_json(VM* vm){
|
|||||||
});
|
});
|
||||||
|
|
||||||
vm->bind_func(mod, "dumps", 1, [](VM* vm, ArgsView args) {
|
vm->bind_func(mod, "dumps", 1, [](VM* vm, ArgsView args) {
|
||||||
return vm->py_json(args[0]);
|
return VAR(vm->py_json(args[0]));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
107
src/pocketpy.cpp
107
src/pocketpy.cpp
@ -245,7 +245,7 @@ void __init_builtins(VM* _vm) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind_func(_vm->builtins, "repr", 1, [](VM* vm, ArgsView args){
|
_vm->bind_func(_vm->builtins, "repr", 1, [](VM* vm, ArgsView args){
|
||||||
return vm->py_repr(args[0]);
|
return VAR(vm->py_repr(args[0]));
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind_func(_vm->builtins, "len", 1, [](VM* vm, ArgsView args){
|
_vm->bind_func(_vm->builtins, "len", 1, [](VM* vm, ArgsView args){
|
||||||
@ -343,13 +343,13 @@ void __init_builtins(VM* _vm) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// tp_object
|
// tp_object
|
||||||
_vm->bind__repr__(VM::tp_object, [](VM* vm, PyObject* obj) {
|
_vm->bind__repr__(VM::tp_object, [](VM* vm, PyObject* obj) -> Str{
|
||||||
if(is_tagged(obj)) PK_FATAL_ERROR();
|
if(is_tagged(obj)) PK_FATAL_ERROR();
|
||||||
SStream ss;
|
SStream ss;
|
||||||
ss << "<" << _type_name(vm, vm->_tp(obj)) << " object at ";
|
ss << "<" << _type_name(vm, vm->_tp(obj)) << " object at ";
|
||||||
ss.write_hex(obj);
|
ss.write_hex(obj);
|
||||||
ss << ">";
|
ss << ">";
|
||||||
return VAR(ss.str());
|
return ss.str();
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind__eq__(VM::tp_object, [](VM* vm, PyObject* _0, PyObject* _1) {
|
_vm->bind__eq__(VM::tp_object, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||||
@ -382,8 +382,8 @@ void __init_builtins(VM* _vm) {
|
|||||||
_vm->bind__iter__(VM::tp_range, [](VM* vm, PyObject* obj) { return vm->new_user_object<RangeIter>(PK_OBJ_GET(Range, obj)); });
|
_vm->bind__iter__(VM::tp_range, [](VM* vm, PyObject* obj) { return vm->new_user_object<RangeIter>(PK_OBJ_GET(Range, obj)); });
|
||||||
|
|
||||||
// tp_nonetype
|
// tp_nonetype
|
||||||
_vm->bind__repr__(_vm->_tp(_vm->None), [](VM* vm, PyObject* _0) {
|
_vm->bind__repr__(_vm->_tp(_vm->None), [](VM* vm, PyObject* _0) -> Str {
|
||||||
return VAR("None");
|
return "None";
|
||||||
});
|
});
|
||||||
|
|
||||||
// tp_float / tp_float
|
// tp_float / tp_float
|
||||||
@ -475,7 +475,9 @@ void __init_builtins(VM* _vm) {
|
|||||||
return VAR(bits);
|
return VAR(bits);
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind__repr__(VM::tp_int, [](VM* vm, PyObject* obj) { return VAR(std::to_string(_CAST(i64, obj))); });
|
_vm->bind__repr__(VM::tp_int, [](VM* vm, PyObject* obj) -> Str{
|
||||||
|
return std::to_string(_CAST(i64, obj));
|
||||||
|
});
|
||||||
_vm->bind__neg__(VM::tp_int, [](VM* vm, PyObject* obj) { return VAR(-_CAST(i64, obj)); });
|
_vm->bind__neg__(VM::tp_int, [](VM* vm, PyObject* obj) { return VAR(-_CAST(i64, obj)); });
|
||||||
_vm->bind__hash__(VM::tp_int, [](VM* vm, PyObject* obj) { return _CAST(i64, obj); });
|
_vm->bind__hash__(VM::tp_int, [](VM* vm, PyObject* obj) { return _CAST(i64, obj); });
|
||||||
_vm->bind__invert__(VM::tp_int, [](VM* vm, PyObject* obj) { return VAR(~_CAST(i64, obj)); });
|
_vm->bind__invert__(VM::tp_int, [](VM* vm, PyObject* obj) { return VAR(~_CAST(i64, obj)); });
|
||||||
@ -532,18 +534,18 @@ void __init_builtins(VM* _vm) {
|
|||||||
|
|
||||||
_vm->bind__neg__(VM::tp_float, [](VM* vm, PyObject* _0) { return VAR(-_CAST(f64, _0)); });
|
_vm->bind__neg__(VM::tp_float, [](VM* vm, PyObject* _0) { return VAR(-_CAST(f64, _0)); });
|
||||||
|
|
||||||
_vm->bind__repr__(VM::tp_float, [](VM* vm, PyObject* _0) {
|
_vm->bind__repr__(VM::tp_float, [](VM* vm, PyObject* _0) -> Str {
|
||||||
f64 val = _CAST(f64, _0);
|
f64 val = _CAST(f64, _0);
|
||||||
SStream ss;
|
SStream ss;
|
||||||
ss << val;
|
ss << val;
|
||||||
return VAR(ss.str());
|
return ss.str();
|
||||||
});
|
});
|
||||||
|
|
||||||
// tp_str
|
// tp_str
|
||||||
_vm->bind_func(VM::tp_str, __new__, -1, [](VM* vm, ArgsView args) {
|
_vm->bind_func(VM::tp_str, __new__, -1, [](VM* vm, ArgsView args) {
|
||||||
if(args.size() == 1) return VAR(Str());
|
if(args.size() == 1) return VAR(Str());
|
||||||
if(args.size() > 2) vm->TypeError("str() takes at most 1 argument");
|
if(args.size() > 2) vm->TypeError("str() takes at most 1 argument");
|
||||||
return vm->py_str(args[1]);
|
return VAR(vm->py_str(args[1]));
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind__hash__(VM::tp_str, [](VM* vm, PyObject* _0) {
|
_vm->bind__hash__(VM::tp_str, [](VM* vm, PyObject* _0) {
|
||||||
@ -574,11 +576,12 @@ void __init_builtins(VM* _vm) {
|
|||||||
const Str& self = _CAST(Str&, _0);
|
const Str& self = _CAST(Str&, _0);
|
||||||
return VAR(self.index(CAST(Str&, _1)) != -1);
|
return VAR(self.index(CAST(Str&, _1)) != -1);
|
||||||
});
|
});
|
||||||
_vm->bind__str__(VM::tp_str, [](VM* vm, PyObject* _0) { return _0; });
|
|
||||||
|
_vm->bind_func(VM::tp_str, __str__, 1, [](VM* vm, ArgsView args) { return args[0]; });
|
||||||
_vm->bind__iter__(VM::tp_str, [](VM* vm, PyObject* _0) { return vm->new_user_object<StringIter>(_0); });
|
_vm->bind__iter__(VM::tp_str, [](VM* vm, PyObject* _0) { return vm->new_user_object<StringIter>(_0); });
|
||||||
_vm->bind__repr__(VM::tp_str, [](VM* vm, PyObject* _0) {
|
_vm->bind__repr__(VM::tp_str, [](VM* vm, PyObject* _0) -> Str {
|
||||||
const Str& self = _CAST(Str&, _0);
|
const Str& self = _CAST(Str&, _0);
|
||||||
return VAR(self.escape());
|
return self.escape();
|
||||||
});
|
});
|
||||||
|
|
||||||
#define BIND_CMP_STR(name, op) \
|
#define BIND_CMP_STR(name, op) \
|
||||||
@ -799,36 +802,36 @@ void __init_builtins(VM* _vm) {
|
|||||||
return vm->None;
|
return vm->None;
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind__repr__(VM::tp_list, [](VM* vm, PyObject* _0){
|
_vm->bind__repr__(VM::tp_list, [](VM* vm, PyObject* _0) -> Str{
|
||||||
if(vm->_repr_recursion_set.count(_0)) return VAR("[...]");
|
if(vm->_repr_recursion_set.count(_0)) return "[...]";
|
||||||
List& iterable = _CAST(List&, _0);
|
List& iterable = _CAST(List&, _0);
|
||||||
SStream ss;
|
SStream ss;
|
||||||
ss << '[';
|
ss << '[';
|
||||||
vm->_repr_recursion_set.insert(_0);
|
vm->_repr_recursion_set.insert(_0);
|
||||||
for(int i=0; i<iterable.size(); i++){
|
for(int i=0; i<iterable.size(); i++){
|
||||||
ss << CAST(Str&, vm->py_repr(iterable[i]));
|
ss << vm->py_repr(iterable[i]);
|
||||||
if(i != iterable.size()-1) ss << ", ";
|
if(i != iterable.size()-1) ss << ", ";
|
||||||
}
|
}
|
||||||
vm->_repr_recursion_set.erase(_0);
|
vm->_repr_recursion_set.erase(_0);
|
||||||
ss << ']';
|
ss << ']';
|
||||||
return VAR(ss.str());
|
return ss.str();
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind__repr__(VM::tp_tuple, [](VM* vm, PyObject* _0){
|
_vm->bind__repr__(VM::tp_tuple, [](VM* vm, PyObject* _0) -> Str{
|
||||||
Tuple& iterable = _CAST(Tuple&, _0);
|
Tuple& iterable = _CAST(Tuple&, _0);
|
||||||
SStream ss;
|
SStream ss;
|
||||||
ss << '(';
|
ss << '(';
|
||||||
if(iterable.size() == 1){
|
if(iterable.size() == 1){
|
||||||
ss << CAST(Str&, vm->py_repr(iterable[0]));
|
ss << vm->py_repr(iterable[0]);
|
||||||
ss << ',';
|
ss << ',';
|
||||||
}else{
|
}else{
|
||||||
for(int i=0; i<iterable.size(); i++){
|
for(int i=0; i<iterable.size(); i++){
|
||||||
ss << CAST(Str&, vm->py_repr(iterable[i]));
|
ss << vm->py_repr(iterable[i]);
|
||||||
if(i != iterable.size()-1) ss << ", ";
|
if(i != iterable.size()-1) ss << ", ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ss << ')';
|
ss << ')';
|
||||||
return VAR(ss.str());
|
return ss.str();
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind_func(VM::tp_list, __new__, -1, [](VM* vm, ArgsView args) {
|
_vm->bind_func(VM::tp_list, __new__, -1, [](VM* vm, ArgsView args) {
|
||||||
@ -869,7 +872,7 @@ void __init_builtins(VM* _vm) {
|
|||||||
for(int i=start; i<self.size(); i++){
|
for(int i=start; i<self.size(); i++){
|
||||||
if(vm->py_eq(self[i], obj)) return VAR(i);
|
if(vm->py_eq(self[i], obj)) return VAR(i);
|
||||||
}
|
}
|
||||||
vm->ValueError(_CAST(Str&, vm->py_repr(obj)) + " is not in list");
|
vm->ValueError(vm->py_repr(obj) + " is not in list");
|
||||||
return vm->None;
|
return vm->None;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -882,7 +885,7 @@ void __init_builtins(VM* _vm) {
|
|||||||
return vm->None;
|
return vm->None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vm->ValueError(_CAST(Str&, vm->py_repr(obj)) + " is not in list");
|
vm->ValueError(vm->py_repr(obj) + " is not in list");
|
||||||
return vm->None;
|
return vm->None;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1075,9 +1078,9 @@ void __init_builtins(VM* _vm) {
|
|||||||
_vm->bind__hash__(VM::tp_bool, [](VM* vm, PyObject* _0) {
|
_vm->bind__hash__(VM::tp_bool, [](VM* vm, PyObject* _0) {
|
||||||
return (i64)_CAST(bool, _0);
|
return (i64)_CAST(bool, _0);
|
||||||
});
|
});
|
||||||
_vm->bind__repr__(VM::tp_bool, [](VM* vm, PyObject* _0) {
|
_vm->bind__repr__(VM::tp_bool, [](VM* vm, PyObject* _0) -> Str{
|
||||||
bool val = _CAST(bool, _0);
|
bool val = _CAST(bool, _0);
|
||||||
return VAR(val ? "True" : "False");
|
return val ? "True" : "False";
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind__and__(VM::tp_bool, [](VM* vm, PyObject* _0, PyObject* _1) {
|
_vm->bind__and__(VM::tp_bool, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||||
@ -1096,11 +1099,11 @@ void __init_builtins(VM* _vm) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// tp_ellipsis / tp_NotImplementedType
|
// tp_ellipsis / tp_NotImplementedType
|
||||||
_vm->bind__repr__(_vm->_tp(_vm->Ellipsis), [](VM* vm, PyObject* _0) {
|
_vm->bind__repr__(_vm->_tp(_vm->Ellipsis), [](VM* vm, PyObject* _0) -> Str{
|
||||||
return VAR("...");
|
return "...";
|
||||||
});
|
});
|
||||||
_vm->bind__repr__(_vm->_tp(_vm->NotImplemented), [](VM* vm, PyObject* _0) {
|
_vm->bind__repr__(_vm->_tp(_vm->NotImplemented), [](VM* vm, PyObject* _0) -> Str{
|
||||||
return VAR("NotImplemented");
|
return "NotImplemented";
|
||||||
});
|
});
|
||||||
|
|
||||||
// tp_bytes
|
// tp_bytes
|
||||||
@ -1148,7 +1151,7 @@ void __init_builtins(VM* _vm) {
|
|||||||
return (i64)std::hash<std::string_view>()(view);
|
return (i64)std::hash<std::string_view>()(view);
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind__repr__(VM::tp_bytes, [](VM* vm, PyObject* _0) {
|
_vm->bind__repr__(VM::tp_bytes, [](VM* vm, PyObject* _0) -> Str {
|
||||||
const Bytes& self = _CAST(Bytes&, _0);
|
const Bytes& self = _CAST(Bytes&, _0);
|
||||||
SStream ss;
|
SStream ss;
|
||||||
ss << "b'";
|
ss << "b'";
|
||||||
@ -1157,7 +1160,7 @@ void __init_builtins(VM* _vm) {
|
|||||||
ss.write_hex((unsigned char)self[i]);
|
ss.write_hex((unsigned char)self[i]);
|
||||||
}
|
}
|
||||||
ss << "'";
|
ss << "'";
|
||||||
return VAR(ss.str());
|
return ss.str();
|
||||||
});
|
});
|
||||||
_vm->bind__len__(VM::tp_bytes, [](VM* vm, PyObject* _0) {
|
_vm->bind__len__(VM::tp_bytes, [](VM* vm, PyObject* _0) {
|
||||||
return (i64)_CAST(Bytes&, _0).size();
|
return (i64)_CAST(Bytes&, _0).size();
|
||||||
@ -1189,14 +1192,14 @@ void __init_builtins(VM* _vm) {
|
|||||||
return vm->True;
|
return vm->True;
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind__repr__(VM::tp_slice, [](VM* vm, PyObject* _0) {
|
_vm->bind__repr__(VM::tp_slice, [](VM* vm, PyObject* _0) -> Str {
|
||||||
const Slice& self = _CAST(Slice&, _0);
|
const Slice& self = _CAST(Slice&, _0);
|
||||||
SStream ss;
|
SStream ss;
|
||||||
ss << "slice(";
|
ss << "slice(";
|
||||||
ss << CAST(Str, vm->py_repr(self.start)) << ", ";
|
ss << vm->py_repr(self.start) << ", ";
|
||||||
ss << CAST(Str, vm->py_repr(self.stop)) << ", ";
|
ss << vm->py_repr(self.stop) << ", ";
|
||||||
ss << CAST(Str, vm->py_repr(self.step)) << ")";
|
ss << vm->py_repr(self.step) << ")";
|
||||||
return VAR(ss.str());
|
return ss.str();
|
||||||
});
|
});
|
||||||
|
|
||||||
// tp_mappingproxy
|
// tp_mappingproxy
|
||||||
@ -1251,8 +1254,8 @@ void __init_builtins(VM* _vm) {
|
|||||||
return ret;
|
return ret;
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind__repr__(VM::tp_mappingproxy, [](VM* vm, PyObject* _0) {
|
_vm->bind__repr__(VM::tp_mappingproxy, [](VM* vm, PyObject* _0) -> Str{
|
||||||
if(vm->_repr_recursion_set.count(_0)) return VAR("{...}");
|
if(vm->_repr_recursion_set.count(_0)) return "{...}";
|
||||||
MappingProxy& self = _CAST(MappingProxy&, _0);
|
MappingProxy& self = _CAST(MappingProxy&, _0);
|
||||||
SStream ss;
|
SStream ss;
|
||||||
ss << "mappingproxy({";
|
ss << "mappingproxy({";
|
||||||
@ -1262,11 +1265,11 @@ void __init_builtins(VM* _vm) {
|
|||||||
if(!first) ss << ", ";
|
if(!first) ss << ", ";
|
||||||
first = false;
|
first = false;
|
||||||
ss << k.escape() << ": ";
|
ss << k.escape() << ": ";
|
||||||
ss << CAST(Str, vm->py_repr(v));
|
ss << vm->py_repr(v);
|
||||||
}
|
}
|
||||||
vm->_repr_recursion_set.erase(_0);
|
vm->_repr_recursion_set.erase(_0);
|
||||||
ss << "})";
|
ss << "})";
|
||||||
return VAR(ss.str());
|
return ss.str();
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind__contains__(VM::tp_mappingproxy, [](VM* vm, PyObject* _0, PyObject* _1) {
|
_vm->bind__contains__(VM::tp_mappingproxy, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||||
@ -1412,8 +1415,8 @@ void __init_builtins(VM* _vm) {
|
|||||||
return vm->None;
|
return vm->None;
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind__repr__(VM::tp_dict, [](VM* vm, PyObject* _0) {
|
_vm->bind__repr__(VM::tp_dict, [](VM* vm, PyObject* _0) -> Str{
|
||||||
if(vm->_repr_recursion_set.count(_0)) return VAR("{...}");
|
if(vm->_repr_recursion_set.count(_0)) return "{...}";
|
||||||
Dict& self = _CAST(Dict&, _0);
|
Dict& self = _CAST(Dict&, _0);
|
||||||
SStream ss;
|
SStream ss;
|
||||||
ss << "{";
|
ss << "{";
|
||||||
@ -1422,11 +1425,11 @@ void __init_builtins(VM* _vm) {
|
|||||||
self.apply([&](PyObject* k, PyObject* v){
|
self.apply([&](PyObject* k, PyObject* v){
|
||||||
if(!first) ss << ", ";
|
if(!first) ss << ", ";
|
||||||
first = false;
|
first = false;
|
||||||
ss << CAST(Str&, vm->py_repr(k)) << ": " << CAST(Str&, vm->py_repr(v));
|
ss << vm->py_repr(k) << ": " << vm->py_repr(v);
|
||||||
});
|
});
|
||||||
vm->_repr_recursion_set.erase(_0);
|
vm->_repr_recursion_set.erase(_0);
|
||||||
ss << "}";
|
ss << "}";
|
||||||
return VAR(ss.str());
|
return ss.str();
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind__eq__(VM::tp_dict, [](VM* vm, PyObject* _0, PyObject* _1) {
|
_vm->bind__eq__(VM::tp_dict, [](VM* vm, PyObject* _0, PyObject* _1) {
|
||||||
@ -1444,9 +1447,9 @@ void __init_builtins(VM* _vm) {
|
|||||||
return vm->True;
|
return vm->True;
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind__repr__(VM::tp_module, [](VM* vm, PyObject* _0) {
|
_vm->bind__repr__(VM::tp_module, [](VM* vm, PyObject* _0) -> Str {
|
||||||
const Str& path = CAST(Str&, _0->attr(__path__));
|
const Str& path = CAST(Str&, _0->attr(__path__));
|
||||||
return VAR(_S("<module ", path.escape(), ">"));
|
return _S("<module ", path.escape(), ">");
|
||||||
});
|
});
|
||||||
|
|
||||||
// tp_property
|
// tp_property
|
||||||
@ -1493,14 +1496,14 @@ void __init_builtins(VM* _vm) {
|
|||||||
return vm->None;
|
return vm->None;
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind__repr__(VM::tp_exception, [](VM* vm, PyObject* _0) {
|
_vm->bind__repr__(VM::tp_exception, [](VM* vm, PyObject* _0) -> Str {
|
||||||
Exception& self = _CAST(Exception&, _0);
|
Exception& self = _CAST(Exception&, _0);
|
||||||
return VAR(_S(_type_name(vm, _0->type), '(', self.msg.escape(), ')'));
|
return _S(_type_name(vm, _0->type), '(', self.msg.escape(), ')');
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind__str__(VM::tp_exception, [](VM* vm, PyObject* _0) {
|
_vm->bind__str__(VM::tp_exception, [](VM* vm, PyObject* _0) -> Str{
|
||||||
Exception& self = _CAST(Exception&, _0);
|
Exception& self = _CAST(Exception&, _0);
|
||||||
return VAR(self.msg);
|
return self.msg;
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->register_user_class<RangeIter>(_vm->builtins, "_range_iter");
|
_vm->register_user_class<RangeIter>(_vm->builtins, "_range_iter");
|
||||||
@ -1533,11 +1536,11 @@ void VM::__post_init_builtin_types(){
|
|||||||
return self; // for generics
|
return self; // for generics
|
||||||
});
|
});
|
||||||
|
|
||||||
bind__repr__(tp_type, [](VM* vm, PyObject* self){
|
bind__repr__(tp_type, [](VM* vm, PyObject* self) -> Str{
|
||||||
SStream ss;
|
SStream ss;
|
||||||
const PyTypeInfo& info = vm->_all_types[PK_OBJ_GET(Type, self)];
|
const PyTypeInfo& info = vm->_all_types[PK_OBJ_GET(Type, self)];
|
||||||
ss << "<class '" << info.name << "'>";
|
ss << "<class '" << info.name << "'>";
|
||||||
return VAR(ss.str());
|
return ss.str();
|
||||||
});
|
});
|
||||||
|
|
||||||
bind_property(_t(tp_object), "__class__", PK_LAMBDA(vm->_t(args[0])));
|
bind_property(_t(tp_object), "__class__", PK_LAMBDA(vm->_t(args[0])));
|
||||||
@ -1589,7 +1592,7 @@ void VM::__post_init_builtin_types(){
|
|||||||
const Str& _2 = CAST(Str&, args[2]);
|
const Str& _2 = CAST(Str&, args[2]);
|
||||||
SStream ss;
|
SStream ss;
|
||||||
for(int i=0; i<_0.size(); i++){
|
for(int i=0; i<_0.size(); i++){
|
||||||
ss << CAST(Str&, vm->py_str(_0[i]));
|
ss << vm->py_str(_0[i]);
|
||||||
if(i != _0.size()-1) ss << _1;
|
if(i != _0.size()-1) ss << _1;
|
||||||
}
|
}
|
||||||
ss << _2;
|
ss << _2;
|
||||||
|
@ -473,7 +473,7 @@ bool pkpy_py_repr(pkpy_vm* vm_handle) {
|
|||||||
PK_ASSERT_N_EXTRA_ELEMENTS(1)
|
PK_ASSERT_N_EXTRA_ELEMENTS(1)
|
||||||
PyObject* item = vm->s_data.top();
|
PyObject* item = vm->s_data.top();
|
||||||
PK_PROTECTED(
|
PK_PROTECTED(
|
||||||
item = vm->py_repr(item);
|
item = VAR(vm->py_repr(item));
|
||||||
)
|
)
|
||||||
vm->s_data.top() = item;
|
vm->s_data.top() = item;
|
||||||
return true;
|
return true;
|
||||||
@ -485,7 +485,7 @@ bool pkpy_py_str(pkpy_vm* vm_handle) {
|
|||||||
PK_ASSERT_N_EXTRA_ELEMENTS(1)
|
PK_ASSERT_N_EXTRA_ELEMENTS(1)
|
||||||
PyObject* item = vm->s_data.top();
|
PyObject* item = vm->s_data.top();
|
||||||
PK_PROTECTED(
|
PK_PROTECTED(
|
||||||
item = vm->py_str(item);
|
item = VAR(vm->py_str(item));
|
||||||
)
|
)
|
||||||
vm->s_data.top() = item;
|
vm->s_data.top() = item;
|
||||||
return true;
|
return true;
|
||||||
|
53
src/vm.cpp
53
src/vm.cpp
@ -83,24 +83,34 @@ namespace pkpy{
|
|||||||
__init_builtin_types();
|
__init_builtin_types();
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* VM::py_str(PyObject* obj){
|
Str VM::py_str(PyObject* obj){
|
||||||
const PyTypeInfo* ti = _tp_info(obj);
|
const PyTypeInfo* ti = _tp_info(obj);
|
||||||
if(ti->m__str__) return ti->m__str__(this, obj);
|
if(ti->m__str__) return ti->m__str__(this, obj);
|
||||||
PyObject* self;
|
PyObject* self;
|
||||||
PyObject* f = get_unbound_method(obj, __str__, &self, false);
|
PyObject* f = get_unbound_method(obj, __str__, &self, false);
|
||||||
if(self != PY_NULL) return call_method(self, f);
|
if(self != PY_NULL){
|
||||||
|
PyObject* retval = call_method(self, f);
|
||||||
|
if(!is_type(retval, tp_str)){
|
||||||
|
throw std::runtime_error("object.__str__ must return str");
|
||||||
|
}
|
||||||
|
return PK_OBJ_GET(Str, retval);
|
||||||
|
}
|
||||||
return py_repr(obj);
|
return py_repr(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* VM::py_repr(PyObject* obj){
|
Str VM::py_repr(PyObject* obj){
|
||||||
const PyTypeInfo* ti = _tp_info(obj);
|
const PyTypeInfo* ti = _tp_info(obj);
|
||||||
if(ti->m__repr__) return ti->m__repr__(this, obj);
|
if(ti->m__repr__) return ti->m__repr__(this, obj);
|
||||||
return call_method(obj, __repr__);
|
PyObject* retval = call_method(obj, __repr__);
|
||||||
|
if(!is_type(retval, tp_str)){
|
||||||
|
throw std::runtime_error("object.__repr__ must return str");
|
||||||
|
}
|
||||||
|
return PK_OBJ_GET(Str, retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* VM::py_json(PyObject* obj){
|
Str VM::py_json(PyObject* obj){
|
||||||
auto j = JsonSerializer(this, obj);
|
auto j = JsonSerializer(this, obj);
|
||||||
return VAR(j.serialize());
|
return j.serialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject* VM::py_iter(PyObject* obj){
|
PyObject* VM::py_iter(PyObject* obj){
|
||||||
@ -495,7 +505,7 @@ i64 VM::py_hash(PyObject* obj){
|
|||||||
}
|
}
|
||||||
|
|
||||||
PyObject* VM::__format_object(PyObject* obj, Str spec){
|
PyObject* VM::__format_object(PyObject* obj, Str spec){
|
||||||
if(spec.empty()) return py_str(obj);
|
if(spec.empty()) return VAR(py_str(obj));
|
||||||
char type;
|
char type;
|
||||||
switch(spec.end()[-1]){
|
switch(spec.end()[-1]){
|
||||||
case 'f': case 'd': case 's':
|
case 'f': case 'd': case 's':
|
||||||
@ -560,7 +570,7 @@ PyObject* VM::__format_object(PyObject* obj, Str spec){
|
|||||||
}else if(type == 's'){
|
}else if(type == 's'){
|
||||||
ret = CAST(Str&, obj);
|
ret = CAST(Str&, obj);
|
||||||
}else{
|
}else{
|
||||||
ret = CAST(Str&, py_str(obj));
|
ret = py_str(obj);
|
||||||
}
|
}
|
||||||
if(width != -1 && width > ret.length()){
|
if(width != -1 && width > ret.length()){
|
||||||
int pad = width - ret.length();
|
int pad = width - ret.length();
|
||||||
@ -602,7 +612,7 @@ static std::string _opcode_argstr(VM* vm, Bytecode byte, const CodeObject* co){
|
|||||||
switch(byte.op){
|
switch(byte.op){
|
||||||
case OP_LOAD_CONST: case OP_FORMAT_STRING: case OP_IMPORT_PATH:
|
case OP_LOAD_CONST: case OP_FORMAT_STRING: case OP_IMPORT_PATH:
|
||||||
if(vm != nullptr){
|
if(vm != nullptr){
|
||||||
argStr += _S(" (", CAST(Str, vm->py_repr(co->consts[byte.arg])), ")").sv();
|
argStr += _S(" (", vm->py_repr(co->consts[byte.arg]), ")").sv();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OP_LOAD_NAME: case OP_LOAD_GLOBAL: case OP_LOAD_NONLOCAL: case OP_STORE_GLOBAL:
|
case OP_LOAD_NAME: case OP_LOAD_GLOBAL: case OP_LOAD_NONLOCAL: case OP_STORE_GLOBAL:
|
||||||
@ -1398,14 +1408,27 @@ void VM::bind__next__(Type type, PyObject* (*f)(VM*, PyObject*)){
|
|||||||
return lambda_get_userdata<PyObject*(*)(VM*, PyObject*)>(args.begin())(vm, args[0]); \
|
return lambda_get_userdata<PyObject*(*)(VM*, PyObject*)>(args.begin())(vm, args[0]); \
|
||||||
}, f); \
|
}, f); \
|
||||||
}
|
}
|
||||||
|
|
||||||
BIND_UNARY_SPECIAL(__repr__)
|
|
||||||
BIND_UNARY_SPECIAL(__str__)
|
|
||||||
BIND_UNARY_SPECIAL(__iter__)
|
BIND_UNARY_SPECIAL(__iter__)
|
||||||
BIND_UNARY_SPECIAL(__neg__)
|
BIND_UNARY_SPECIAL(__neg__)
|
||||||
BIND_UNARY_SPECIAL(__invert__)
|
BIND_UNARY_SPECIAL(__invert__)
|
||||||
#undef BIND_UNARY_SPECIAL
|
#undef BIND_UNARY_SPECIAL
|
||||||
|
|
||||||
|
void VM::bind__str__(Type type, Str (*f)(VM*, PyObject*)){
|
||||||
|
_all_types[type].m__str__ = f;
|
||||||
|
bind_func(type, __str__, 1, [](VM* vm, ArgsView args){
|
||||||
|
Str s = lambda_get_userdata<decltype(f)>(args.begin())(vm, args[0]);
|
||||||
|
return VAR(s);
|
||||||
|
}, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VM::bind__repr__(Type type, Str (*f)(VM*, PyObject*)){
|
||||||
|
_all_types[type].m__repr__ = f;
|
||||||
|
bind_func(type, __repr__, 1, [](VM* vm, ArgsView args){
|
||||||
|
Str s = lambda_get_userdata<decltype(f)>(args.begin())(vm, args[0]);
|
||||||
|
return VAR(s);
|
||||||
|
}, f);
|
||||||
|
}
|
||||||
|
|
||||||
void VM::bind__hash__(Type type, i64 (*f)(VM*, PyObject*)){
|
void VM::bind__hash__(Type type, i64 (*f)(VM*, PyObject*)){
|
||||||
_all_types[type].m__hash__ = f;
|
_all_types[type].m__hash__ = f;
|
||||||
bind_func(type, __hash__, 1, [](VM* vm, ArgsView args){
|
bind_func(type, __hash__, 1, [](VM* vm, ArgsView args){
|
||||||
@ -1460,7 +1483,6 @@ void Dict::_probe_0(PyObject *key, bool &ok, int &i) const{
|
|||||||
ok = false;
|
ok = false;
|
||||||
i64 hash = vm->py_hash(key);
|
i64 hash = vm->py_hash(key);
|
||||||
i = hash & _mask;
|
i = hash & _mask;
|
||||||
// std::cout << CAST(Str, vm->py_repr(key)) << " " << hash << " " << i << std::endl;
|
|
||||||
for(int j=0; j<_capacity; j++) {
|
for(int j=0; j<_capacity; j++) {
|
||||||
if(_items[i].first != nullptr){
|
if(_items[i].first != nullptr){
|
||||||
if(vm->py_eq(_items[i].first, key)) { ok = true; break; }
|
if(vm->py_eq(_items[i].first, key)) { ok = true; break; }
|
||||||
@ -1469,7 +1491,6 @@ void Dict::_probe_0(PyObject *key, bool &ok, int &i) const{
|
|||||||
}
|
}
|
||||||
// https://github.com/python/cpython/blob/3.8/Objects/dictobject.c#L166
|
// https://github.com/python/cpython/blob/3.8/Objects/dictobject.c#L166
|
||||||
i = ((5*i) + 1) & _mask;
|
i = ((5*i) + 1) & _mask;
|
||||||
// std::cout << CAST(Str, vm->py_repr(key)) << " next: " << i << std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1600,7 +1621,7 @@ void VM::__breakpoint(){
|
|||||||
for(PyObject* obj: frame_0->_locals){
|
for(PyObject* obj: frame_0->_locals){
|
||||||
if(obj == PY_NULL) continue;
|
if(obj == PY_NULL) continue;
|
||||||
StrName name = frame_0->co->varnames[i++];
|
StrName name = frame_0->co->varnames[i++];
|
||||||
stdout_write(_S(name.sv(), " = ", CAST(Str&, vm->py_repr(obj)), '\n'));
|
stdout_write(_S(name.sv(), " = ", vm->py_repr(obj), '\n'));
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1644,7 +1665,7 @@ void VM::__breakpoint(){
|
|||||||
if(cmd == "p" || cmd == "print"){
|
if(cmd == "p" || cmd == "print"){
|
||||||
CodeObject_ code = compile(arg, "<stdin>", EVAL_MODE, true);
|
CodeObject_ code = compile(arg, "<stdin>", EVAL_MODE, true);
|
||||||
PyObject* retval = vm->_exec(code.get(), frame_0->_module, frame_0->_callable, frame_0->_locals);
|
PyObject* retval = vm->_exec(code.get(), frame_0->_module, frame_0->_callable, frame_0->_locals);
|
||||||
stdout_write(CAST(Str&, vm->py_repr(retval)));
|
stdout_write(vm->py_repr(retval));
|
||||||
stdout_write("\n");
|
stdout_write("\n");
|
||||||
}else if(cmd == "!"){
|
}else if(cmd == "!"){
|
||||||
CodeObject_ code = compile(arg, "<stdin>", EXEC_MODE, true);
|
CodeObject_ code = compile(arg, "<stdin>", EXEC_MODE, true);
|
||||||
|
@ -166,7 +166,7 @@ assert repr(a) == "{1: 2, 3: 4, 'a': {...}}"
|
|||||||
# test gc
|
# test gc
|
||||||
import gc
|
import gc
|
||||||
gc.collect()
|
gc.collect()
|
||||||
x = gc.collect()
|
|
||||||
for k, v in a.items():
|
for k, v in a.items():
|
||||||
pass
|
pass
|
||||||
assert x+1 == gc.collect()
|
assert gc.collect() == 1
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user