mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-25 14:00:18 +00:00
...
This commit is contained in:
parent
8c85881d14
commit
ca0aa5e1ab
119
python/_dict.py
119
python/_dict.py
@ -1,119 +0,0 @@
|
||||
class dict:
|
||||
def __init__(self, mapping=None):
|
||||
self._capacity = 16
|
||||
self._a = [None] * self._capacity
|
||||
self._len = 0
|
||||
|
||||
if mapping is not None:
|
||||
for k,v in mapping:
|
||||
self[k] = v
|
||||
|
||||
def __len__(self):
|
||||
return self._len
|
||||
|
||||
def __probe(self, key):
|
||||
i = hash(key) % self._capacity
|
||||
while self._a[i] is not None:
|
||||
if self._a[i][0] == key:
|
||||
return True, i
|
||||
i = (i + 1) % self._capacity
|
||||
return False, i
|
||||
|
||||
def __getitem__(self, key):
|
||||
ok, i = self.__probe(key)
|
||||
if not ok:
|
||||
raise KeyError(repr(key))
|
||||
return self._a[i][1]
|
||||
|
||||
def __contains__(self, key):
|
||||
ok, i = self.__probe(key)
|
||||
return ok
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
ok, i = self.__probe(key)
|
||||
if ok:
|
||||
self._a[i][1] = value
|
||||
else:
|
||||
self._a[i] = [key, value]
|
||||
self._len += 1
|
||||
if self._len > self._capacity * 0.67:
|
||||
self._capacity *= 2
|
||||
self.__rehash()
|
||||
|
||||
def __delitem__(self, key):
|
||||
ok, i = self.__probe(key)
|
||||
if not ok:
|
||||
raise KeyError(repr(key))
|
||||
self._a[i] = None
|
||||
self._len -= 1
|
||||
|
||||
def __rehash(self):
|
||||
old_a = self._a
|
||||
self._a = [None] * self._capacity
|
||||
self._len = 0
|
||||
for kv in old_a:
|
||||
if kv is not None:
|
||||
self[kv[0]] = kv[1]
|
||||
|
||||
def get(self, key, default=None):
|
||||
ok, i = self.__probe(key)
|
||||
if ok:
|
||||
return self._a[i][1]
|
||||
return default
|
||||
|
||||
def keys(self):
|
||||
for kv in self._a:
|
||||
if kv is not None:
|
||||
yield kv[0]
|
||||
|
||||
def values(self):
|
||||
for kv in self._a:
|
||||
if kv is not None:
|
||||
yield kv[1]
|
||||
|
||||
def items(self):
|
||||
for kv in self._a:
|
||||
if kv is not None:
|
||||
yield kv[0], kv[1]
|
||||
|
||||
def clear(self):
|
||||
self._a = [None] * self._capacity
|
||||
self._len = 0
|
||||
|
||||
def update(self, other):
|
||||
for k, v in other.items():
|
||||
self[k] = v
|
||||
|
||||
def copy(self):
|
||||
d = dict()
|
||||
for kv in self._a:
|
||||
if kv is not None:
|
||||
d[kv[0]] = kv[1]
|
||||
return d
|
||||
|
||||
def __repr__(self):
|
||||
a = [repr(k)+': '+repr(v) for k,v in self.items()]
|
||||
return '{'+ ', '.join(a) + '}'
|
||||
|
||||
def __json__(self):
|
||||
a = []
|
||||
for k,v in self.items():
|
||||
if type(k) is not str:
|
||||
raise TypeError('json keys must be strings, got ' + repr(k) )
|
||||
a.append(k.__json__()+': '+v.__json__())
|
||||
return '{'+ ', '.join(a) + '}'
|
||||
|
||||
def __eq__(self, __o: object) -> bool:
|
||||
if type(__o) is not dict:
|
||||
return False
|
||||
if len(self) != len(__o):
|
||||
return False
|
||||
for k in self.keys():
|
||||
if k not in __o:
|
||||
return False
|
||||
if self[k] != __o[k]:
|
||||
return False
|
||||
return True
|
||||
|
||||
def __ne__(self, __o: object) -> bool:
|
||||
return not self.__eq__(__o)
|
||||
13
src/ceval.h
13
src/ceval.h
@ -368,6 +368,7 @@ __NEXT_STEP:;
|
||||
DISPATCH();
|
||||
|
||||
#undef BINARY_OP_SPECIAL
|
||||
#undef PREDICT_INT_OP
|
||||
|
||||
TARGET(IS_OP)
|
||||
_1 = POPX(); // rhs
|
||||
@ -398,14 +399,14 @@ __NEXT_STEP:;
|
||||
frame->jump_abs(byte.arg);
|
||||
DISPATCH();
|
||||
TARGET(POP_JUMP_IF_FALSE)
|
||||
if(!asBool(POPX())) frame->jump_abs(byte.arg);
|
||||
if(!py_bool(POPX())) frame->jump_abs(byte.arg);
|
||||
DISPATCH();
|
||||
TARGET(JUMP_IF_TRUE_OR_POP)
|
||||
if(asBool(TOP()) == true) frame->jump_abs(byte.arg);
|
||||
if(py_bool(TOP()) == true) frame->jump_abs(byte.arg);
|
||||
else POP();
|
||||
DISPATCH();
|
||||
TARGET(JUMP_IF_FALSE_OR_POP)
|
||||
if(asBool(TOP()) == false) frame->jump_abs(byte.arg);
|
||||
if(py_bool(TOP()) == false) frame->jump_abs(byte.arg);
|
||||
else POP();
|
||||
DISPATCH();
|
||||
TARGET(LOOP_CONTINUE)
|
||||
@ -461,10 +462,10 @@ __NEXT_STEP:;
|
||||
DISPATCH();
|
||||
/*****************************************/
|
||||
TARGET(UNARY_NEGATIVE)
|
||||
TOP() = num_negated(TOP());
|
||||
TOP() = py_negate(TOP());
|
||||
DISPATCH();
|
||||
TARGET(UNARY_NOT)
|
||||
TOP() = VAR(!asBool(TOP()));
|
||||
TOP() = VAR(!py_bool(TOP()));
|
||||
DISPATCH();
|
||||
/*****************************************/
|
||||
TARGET(GET_ITER)
|
||||
@ -578,7 +579,7 @@ __NEXT_STEP:;
|
||||
_0 = t[0];
|
||||
msg = CAST(Str&, py_str(t[1]));
|
||||
}
|
||||
bool ok = asBool(_0);
|
||||
bool ok = py_bool(_0);
|
||||
POP();
|
||||
if(!ok) _error("AssertionError", msg);
|
||||
} DISPATCH();
|
||||
|
||||
@ -980,7 +980,7 @@ __SUBSCR_END:
|
||||
case TK("-"): {
|
||||
consume(TK("@num"));
|
||||
PyObject* val = to_object(prev().value);
|
||||
return vm->num_negated(val);
|
||||
return vm->py_negate(val);
|
||||
}
|
||||
case TK("@num"): return to_object(prev().value);
|
||||
case TK("@str"): return to_object(prev().value);
|
||||
|
||||
28
src/dict.h
28
src/dict.h
@ -70,6 +70,34 @@ struct Dict{
|
||||
return _items[i].second;
|
||||
}
|
||||
|
||||
bool contains(PyObject* key) const{
|
||||
bool ok; int i;
|
||||
_probe(key, ok, i);
|
||||
return ok;
|
||||
}
|
||||
|
||||
void erase(PyObject* key){
|
||||
bool ok; int i;
|
||||
_probe(key, ok, i);
|
||||
if(!ok) return;
|
||||
_items[i].first = nullptr;
|
||||
_size--;
|
||||
}
|
||||
|
||||
std::vector<Item> items() const {
|
||||
std::vector<Item> v;
|
||||
for(uint16_t i=0; i<_capacity; i++){
|
||||
if(_items[i].first == nullptr) continue;
|
||||
v.push_back(_items[i]);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
void clear(){
|
||||
memset(_items, 0, _capacity * sizeof(Item));
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
~Dict(){ pool128.dealloc(_items); }
|
||||
};
|
||||
|
||||
|
||||
190
src/pocketpy.h
190
src/pocketpy.h
@ -2,6 +2,7 @@
|
||||
|
||||
#include "ceval.h"
|
||||
#include "compiler.h"
|
||||
#include "dict.h"
|
||||
#include "obj.h"
|
||||
#include "repl.h"
|
||||
#include "iter.h"
|
||||
@ -139,7 +140,7 @@ inline void init_builtins(VM* _vm) {
|
||||
});
|
||||
|
||||
_vm->bind_builtin_func<1>("hash", [](VM* vm, ArgsView args){
|
||||
i64 value = vm->hash(args[0]);
|
||||
i64 value = vm->py_hash(args[0]);
|
||||
if(((value << 2) >> 2) != value) value >>= 2;
|
||||
return VAR(value);
|
||||
});
|
||||
@ -262,7 +263,7 @@ inline void init_builtins(VM* _vm) {
|
||||
_vm->bind__pow__(_vm->tp_int, py_number_pow);
|
||||
_vm->bind__pow__(_vm->tp_float, py_number_pow);
|
||||
|
||||
/************ PyInt ************/
|
||||
/************ int ************/
|
||||
_vm->bind_constructor<2>("int", [](VM* vm, ArgsView args) {
|
||||
if (is_type(args[1], vm->tp_float)) return VAR((i64)CAST(f64, args[1]));
|
||||
if (is_type(args[1], vm->tp_int)) return args[1];
|
||||
@ -295,6 +296,8 @@ inline void init_builtins(VM* _vm) {
|
||||
_vm->bind__repr__(_vm->tp_int, [](VM* vm, PyObject* obj) { return VAR(std::to_string(_CAST(i64, obj))); });
|
||||
_vm->bind__json__(_vm->tp_int, [](VM* vm, PyObject* obj) { return VAR(std::to_string(_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); });
|
||||
|
||||
#define INT_BITWISE_OP(name, op) \
|
||||
@ -310,7 +313,7 @@ inline void init_builtins(VM* _vm) {
|
||||
|
||||
#undef INT_BITWISE_OP
|
||||
|
||||
/************ PyFloat ************/
|
||||
/************ float ************/
|
||||
_vm->bind_constructor<2>("float", [](VM* vm, ArgsView args) {
|
||||
if (is_type(args[1], vm->tp_int)) return VAR((f64)CAST(i64, args[1]));
|
||||
if (is_type(args[1], vm->tp_float)) return args[1];
|
||||
@ -335,6 +338,8 @@ inline void init_builtins(VM* _vm) {
|
||||
return (i64)std::hash<f64>()(val);
|
||||
});
|
||||
|
||||
_vm->bind__neg__(_vm->tp_float, [](VM* vm, PyObject* obj) { return VAR(-_CAST(f64, obj)); });
|
||||
|
||||
_vm->bind__repr__(_vm->tp_float, [](VM* vm, PyObject* obj) {
|
||||
f64 val = _CAST(f64, obj);
|
||||
if(std::isinf(val) || std::isnan(val)) return VAR(std::to_string(val));
|
||||
@ -350,7 +355,7 @@ inline void init_builtins(VM* _vm) {
|
||||
return VAR(std::to_string(val));
|
||||
});
|
||||
|
||||
/************ PyString ************/
|
||||
/************ str ************/
|
||||
_vm->bind_constructor<2>("str", CPP_LAMBDA(vm->py_str(args[1])));
|
||||
|
||||
_vm->bind__hash__(_vm->tp_str, [](VM* vm, PyObject* obj) {
|
||||
@ -475,9 +480,9 @@ inline void init_builtins(VM* _vm) {
|
||||
return VAR(Str(p));
|
||||
});
|
||||
|
||||
/************ PyList ************/
|
||||
/************ list ************/
|
||||
_vm->bind_constructor<2>("list", [](VM* vm, ArgsView args) {
|
||||
return vm->asList(args[1]);
|
||||
return vm->py_list(args[1]);
|
||||
});
|
||||
|
||||
_vm->bind_method<1>("list", "append", [](VM* vm, ArgsView args) {
|
||||
@ -563,9 +568,9 @@ inline void init_builtins(VM* _vm) {
|
||||
self.erase(i);
|
||||
});
|
||||
|
||||
/************ PyTuple ************/
|
||||
/************ tuple ************/
|
||||
_vm->bind_constructor<2>("tuple", [](VM* vm, ArgsView args) {
|
||||
List list = CAST(List, vm->asList(args[1]));
|
||||
List list = CAST(List, vm->py_list(args[1]));
|
||||
return VAR(Tuple(std::move(list)));
|
||||
});
|
||||
|
||||
@ -573,7 +578,7 @@ inline void init_builtins(VM* _vm) {
|
||||
i64 x = 1000003;
|
||||
const Tuple& items = CAST(Tuple&, obj);
|
||||
for (int i=0; i<items.size(); i++) {
|
||||
i64 y = vm->hash(items[i]);
|
||||
i64 y = vm->py_hash(items[i]);
|
||||
// recommended by Github Copilot
|
||||
x = x ^ (y + 0x9e3779b9 + (x << 6) + (x >> 2));
|
||||
}
|
||||
@ -590,7 +595,7 @@ inline void init_builtins(VM* _vm) {
|
||||
});
|
||||
|
||||
/************ bool ************/
|
||||
_vm->bind_constructor<2>("bool", CPP_LAMBDA(VAR(vm->asBool(args[1]))));
|
||||
_vm->bind_constructor<2>("bool", CPP_LAMBDA(VAR(vm->py_bool(args[1]))));
|
||||
_vm->bind__hash__(_vm->tp_bool, [](VM* vm, PyObject* obj) {
|
||||
return (i64)_CAST(bool, obj);
|
||||
});
|
||||
@ -758,6 +763,165 @@ inline void init_builtins(VM* _vm) {
|
||||
MappingProxy& self = _CAST(MappingProxy&, obj);
|
||||
return self.attr().contains(CAST(Str&, key));
|
||||
});
|
||||
|
||||
/************ dict ************/
|
||||
_vm->bind_constructor<-1>("dict", [](VM* vm, ArgsView args){
|
||||
return VAR(Dict(vm));
|
||||
});
|
||||
|
||||
_vm->bind_method<-1>("dict", "__init__", [](VM* vm, ArgsView args){
|
||||
if(args.size() == 1+0) return vm->None;
|
||||
if(args.size() == 1+1){
|
||||
auto _lock = vm->heap.gc_scope_lock();
|
||||
Dict& self = _CAST(Dict&, args[0]);
|
||||
List& list = CAST(List&, vm->py_list(args[1]));
|
||||
for(PyObject* item : list){
|
||||
Tuple& t = CAST(Tuple&, item);
|
||||
if(t.size() != 2){
|
||||
vm->ValueError("dict() takes an iterable of tuples (key, value)");
|
||||
return vm->None;
|
||||
}
|
||||
self.set(t[0], t[1]);
|
||||
}
|
||||
}
|
||||
vm->TypeError("dict() takes at most 1 argument");
|
||||
return vm->None;
|
||||
});
|
||||
|
||||
_vm->bind__len__(_vm->tp_dict, [](VM* vm, PyObject* obj) {
|
||||
return (i64)_CAST(Dict&, obj).size();
|
||||
});
|
||||
|
||||
_vm->bind__getitem__(_vm->tp_dict, [](VM* vm, PyObject* obj, PyObject* index) {
|
||||
Dict& self = _CAST(Dict&, obj);
|
||||
PyObject* ret = self.try_get(index);
|
||||
if(ret == nullptr) vm->KeyError(index);
|
||||
return ret;
|
||||
});
|
||||
|
||||
_vm->bind__setitem__(_vm->tp_dict, [](VM* vm, PyObject* obj, PyObject* key, PyObject* value) {
|
||||
Dict& self = _CAST(Dict&, obj);
|
||||
self.set(key, value);
|
||||
});
|
||||
|
||||
_vm->bind__delitem__(_vm->tp_dict, [](VM* vm, PyObject* obj, PyObject* key) {
|
||||
Dict& self = _CAST(Dict&, obj);
|
||||
if(!self.contains(key)) vm->KeyError(key);
|
||||
self.erase(key);
|
||||
});
|
||||
|
||||
_vm->bind__contains__(_vm->tp_dict, [](VM* vm, PyObject* obj, PyObject* key) {
|
||||
Dict& self = _CAST(Dict&, obj);
|
||||
return self.contains(key);
|
||||
});
|
||||
|
||||
_vm->bind_method<-1>("dict", "get", [](VM* vm, ArgsView args) {
|
||||
Dict& self = _CAST(Dict&, args[0]);
|
||||
if(args.size() == 1+1){
|
||||
PyObject* ret = self.try_get(args[1]);
|
||||
if(ret != nullptr) return ret;
|
||||
return vm->None;
|
||||
}else if(args.size() == 1+2){
|
||||
PyObject* ret = self.try_get(args[1]);
|
||||
if(ret != nullptr) return ret;
|
||||
return args[2];
|
||||
}
|
||||
vm->TypeError("get() takes at most 2 arguments");
|
||||
return vm->None;
|
||||
});
|
||||
|
||||
_vm->bind_method<0>("dict", "keys", [](VM* vm, ArgsView args) {
|
||||
Dict& self = _CAST(Dict&, args[0]);
|
||||
List keys;
|
||||
for(auto& item : self.items()) keys.push_back(item.first);
|
||||
return VAR(std::move(keys));
|
||||
});
|
||||
|
||||
_vm->bind_method<0>("dict", "values", [](VM* vm, ArgsView args) {
|
||||
Dict& self = _CAST(Dict&, args[0]);
|
||||
List values;
|
||||
for(auto& item : self.items()) values.push_back(item.second);
|
||||
return VAR(std::move(values));
|
||||
});
|
||||
|
||||
_vm->bind_method<0>("dict", "items", [](VM* vm, ArgsView args) {
|
||||
Dict& self = _CAST(Dict&, args[0]);
|
||||
List items;
|
||||
for(auto& item : self.items()){
|
||||
PyObject* t = VAR(Tuple({item.first, item.second}));
|
||||
items.push_back(std::move(t));
|
||||
}
|
||||
return VAR(std::move(items));
|
||||
});
|
||||
|
||||
_vm->bind_method<-1>("dict", "update", [](VM* vm, ArgsView args) {
|
||||
Dict& self = _CAST(Dict&, args[0]);
|
||||
Dict& other = CAST(Dict&, args[1]);
|
||||
for(auto& item : other.items()) self.set(item.first, item.second);
|
||||
return vm->None;
|
||||
});
|
||||
|
||||
_vm->bind_method<0>("dict", "copy", [](VM* vm, ArgsView args) {
|
||||
Dict& self = _CAST(Dict&, args[0]);
|
||||
Dict copy(vm);
|
||||
for(auto& item : self.items()) copy.set(item.first, item.second);
|
||||
return VAR(std::move(copy));
|
||||
});
|
||||
|
||||
_vm->bind_method<0>("dict", "clear", [](VM* vm, ArgsView args) {
|
||||
Dict& self = _CAST(Dict&, args[0]);
|
||||
self.clear();
|
||||
return vm->None;
|
||||
});
|
||||
|
||||
_vm->bind__repr__(_vm->tp_dict, [](VM* vm, PyObject* obj) {
|
||||
Dict& self = _CAST(Dict&, obj);
|
||||
std::stringstream ss;
|
||||
ss << "{";
|
||||
bool first = true;
|
||||
for(auto& item : self.items()){
|
||||
if(!first) ss << ", ";
|
||||
first = false;
|
||||
Str key = CAST(Str&, vm->py_repr(item.first));
|
||||
Str value = CAST(Str&, vm->py_repr(item.second));
|
||||
ss << key << ": " << value;
|
||||
}
|
||||
ss << "}";
|
||||
return VAR(ss.str());
|
||||
});
|
||||
|
||||
_vm->bind__json__(_vm->tp_dict, [](VM* vm, PyObject* obj) {
|
||||
Dict& self = _CAST(Dict&, obj);
|
||||
std::stringstream ss;
|
||||
ss << "{";
|
||||
bool first = true;
|
||||
for(auto& item : self.items()){
|
||||
if(!first) ss << ", ";
|
||||
first = false;
|
||||
Str key = CAST(Str&, item.first);
|
||||
Str value = CAST(Str&, vm->py_json(item.second));
|
||||
ss << key << ": " << value;
|
||||
}
|
||||
ss << "}";
|
||||
return VAR(ss.str());
|
||||
});
|
||||
|
||||
_vm->bind__eq__(_vm->tp_dict, [](VM* vm, PyObject* a, PyObject* b) {
|
||||
Dict& self = _CAST(Dict&, a);
|
||||
if(!is_non_tagged_type(b, vm->tp_dict)) return false;
|
||||
Dict& other = _CAST(Dict&, b);
|
||||
if(self.size() != other.size()) return false;
|
||||
for(auto& item : self.items()){
|
||||
PyObject* value = other.try_get(item.first);
|
||||
if(value == nullptr) return false;
|
||||
if(!vm->py_equals(item.second, value)) return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
_vm->bind__ne__(_vm->tp_dict, [](VM* vm, PyObject* a, PyObject* b) {
|
||||
return !vm->py_equals(a, b);
|
||||
});
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
@ -819,9 +983,7 @@ inline void add_module_json(VM* vm){
|
||||
});
|
||||
|
||||
vm->bind_func<1>(mod, "dumps", [](VM* vm, ArgsView args) {
|
||||
const PyTypeInfo* ti = vm->_inst_type_info(args[0]);
|
||||
if(ti->m__json__) return ti->m__json__(vm, args[0]);
|
||||
return vm->call_method(args[0], __json__);
|
||||
return vm->py_json(args[0]);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1049,8 +1211,6 @@ inline void VM::post_init(){
|
||||
|
||||
CodeObject_ code = compile(kPythonLibs["builtins"], "<builtins>", EXEC_MODE);
|
||||
this->_exec(code, this->builtins);
|
||||
code = compile(kPythonLibs["_dict"], "<dict>", EXEC_MODE);
|
||||
this->_exec(code, this->builtins);
|
||||
code = compile(kPythonLibs["_set"], "<set>", EXEC_MODE);
|
||||
this->_exec(code, this->builtins);
|
||||
|
||||
|
||||
61
src/vm.h
61
src/vm.h
@ -9,7 +9,7 @@
|
||||
#include "obj.h"
|
||||
#include "str.h"
|
||||
#include "tuplelist.h"
|
||||
// #include "dict.h"
|
||||
#include "dict.h"
|
||||
|
||||
namespace pkpy{
|
||||
|
||||
@ -147,6 +147,7 @@ public:
|
||||
Type tp_function, tp_native_func, tp_iterator, tp_bound_method;
|
||||
Type tp_slice, tp_range, tp_module;
|
||||
Type tp_super, tp_exception, tp_bytes, tp_mappingproxy;
|
||||
Type tp_dict;
|
||||
|
||||
const bool enable_os;
|
||||
|
||||
@ -181,6 +182,12 @@ public:
|
||||
return call_method(obj, __repr__);
|
||||
}
|
||||
|
||||
PyObject* py_json(PyObject* obj){
|
||||
const PyTypeInfo* ti = _inst_type_info(obj);
|
||||
if(ti->m__json__) return ti->m__json__(this, obj);
|
||||
return call_method(obj, __json__);
|
||||
}
|
||||
|
||||
PyObject* py_iter(PyObject* obj){
|
||||
if(is_type(obj, tp_iterator)) return obj;
|
||||
const PyTypeInfo* ti = _inst_type_info(obj);
|
||||
@ -521,7 +528,7 @@ public:
|
||||
void IndexError(const Str& msg){ _error("IndexError", msg); }
|
||||
void ValueError(const Str& msg){ _error("ValueError", msg); }
|
||||
void NameError(StrName name){ _error("NameError", fmt("name ", name.escape() + " is not defined")); }
|
||||
void KeyError(const Str& msg){ _error("KeyError", msg); }
|
||||
void KeyError(PyObject* obj){ _error("KeyError", OBJ_GET(Str, py_repr(obj))); }
|
||||
|
||||
void AttributeError(PyObject* obj, StrName name){
|
||||
// OBJ_NAME calls getattr, which may lead to a infinite recursion
|
||||
@ -567,15 +574,16 @@ public:
|
||||
_modules.clear();
|
||||
_lazy_modules.clear();
|
||||
}
|
||||
|
||||
#if DEBUG_CEVAL_STEP
|
||||
void _log_s_data(const char* title = nullptr);
|
||||
#endif
|
||||
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* num_negated(PyObject* obj);
|
||||
PyObject* py_negate(PyObject* obj);
|
||||
f64 num_to_float(PyObject* obj);
|
||||
bool asBool(PyObject* obj);
|
||||
i64 hash(PyObject* obj);
|
||||
PyObject* asList(PyObject*);
|
||||
bool py_bool(PyObject* obj);
|
||||
i64 py_hash(PyObject* obj);
|
||||
PyObject* py_list(PyObject*);
|
||||
PyObject* new_module(StrName name);
|
||||
Str disassemble(CodeObject_ co);
|
||||
void init_builtin_types();
|
||||
@ -622,6 +630,7 @@ DEF_NATIVE_2(Slice, tp_slice)
|
||||
DEF_NATIVE_2(Exception, tp_exception)
|
||||
DEF_NATIVE_2(Bytes, tp_bytes)
|
||||
DEF_NATIVE_2(MappingProxy, tp_mappingproxy)
|
||||
DEF_NATIVE_2(Dict, tp_dict)
|
||||
|
||||
#define PY_CAST_INT(T) \
|
||||
template<> inline T py_cast<T>(VM* vm, PyObject* obj){ \
|
||||
@ -733,14 +742,10 @@ inline PyObject* py_var(VM* vm, PyObject* val){
|
||||
return val;
|
||||
}
|
||||
|
||||
inline PyObject* VM::num_negated(PyObject* obj){
|
||||
if (is_int(obj)){
|
||||
return VAR(-CAST(i64, obj));
|
||||
}else if(is_float(obj)){
|
||||
return VAR(-CAST(f64, obj));
|
||||
}
|
||||
TypeError("expected 'int' or 'float', got " + OBJ_NAME(_t(obj)).escape());
|
||||
return nullptr;
|
||||
inline PyObject* VM::py_negate(PyObject* obj){
|
||||
const PyTypeInfo* ti = _inst_type_info(obj);
|
||||
if(ti->m__neg__) return ti->m__neg__(this, obj);
|
||||
return call_method(obj, __neg__);
|
||||
}
|
||||
|
||||
inline f64 VM::num_to_float(PyObject* obj){
|
||||
@ -753,7 +758,7 @@ inline f64 VM::num_to_float(PyObject* obj){
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline bool VM::asBool(PyObject* obj){
|
||||
inline bool VM::py_bool(PyObject* obj){
|
||||
if(is_non_tagged_type(obj, tp_bool)) return obj == True;
|
||||
if(obj == None) return false;
|
||||
if(is_int(obj)) return _CAST(i64, obj) != 0;
|
||||
@ -767,7 +772,7 @@ inline bool VM::asBool(PyObject* obj){
|
||||
return true;
|
||||
}
|
||||
|
||||
inline PyObject* VM::asList(PyObject* it){
|
||||
inline PyObject* VM::py_list(PyObject* it){
|
||||
auto _lock = heap.gc_scope_lock();
|
||||
it = py_iter(it);
|
||||
List list;
|
||||
@ -821,7 +826,7 @@ inline void VM::parse_int_slice(const Slice& s, int length, int& start, int& sto
|
||||
}
|
||||
}
|
||||
|
||||
inline i64 VM::hash(PyObject* obj){
|
||||
inline i64 VM::py_hash(PyObject* obj){
|
||||
const PyTypeInfo* ti = _inst_type_info(obj);
|
||||
if(ti->m__hash__) return ti->m__hash__(this, obj);
|
||||
PyObject* ret = call_method(obj, __hash__);
|
||||
@ -974,6 +979,7 @@ inline Str VM::disassemble(CodeObject_ co){
|
||||
return Str(ss.str());
|
||||
}
|
||||
|
||||
#if DEBUG_CEVAL_STEP
|
||||
inline void VM::_log_s_data(const char* title) {
|
||||
if(_main == nullptr) return;
|
||||
if(callstack.empty()) return;
|
||||
@ -1023,6 +1029,7 @@ inline void VM::_log_s_data(const char* title) {
|
||||
Bytecode byte = frame->co->codes[frame->_ip];
|
||||
std::cout << output << " " << OP_NAMES[byte.op] << " " << _opcode_argstr(nullptr, byte, frame->co) << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline void VM::init_builtin_types(){
|
||||
_all_types.push_back({heap._new<Type>(Type(1), Type(0)), -1, "object", true});
|
||||
@ -1048,6 +1055,7 @@ inline void VM::init_builtin_types(){
|
||||
tp_exception = _new_type_object("Exception");
|
||||
tp_bytes = _new_type_object("bytes");
|
||||
tp_mappingproxy = _new_type_object("mappingproxy");
|
||||
tp_dict = _new_type_object("dict");
|
||||
|
||||
this->None = heap._new<Dummy>(_new_type_object("NoneType"), {});
|
||||
this->Ellipsis = heap._new<Dummy>(_new_type_object("ellipsis"), {});
|
||||
@ -1068,6 +1076,7 @@ inline void VM::init_builtin_types(){
|
||||
builtins->attr().set("tuple", _t(tp_tuple));
|
||||
builtins->attr().set("range", _t(tp_range));
|
||||
builtins->attr().set("bytes", _t(tp_bytes));
|
||||
builtins->attr().set("dict", _t(tp_dict));
|
||||
builtins->attr().set("StopIteration", StopIteration);
|
||||
builtins->attr().set("slice", _t(tp_slice));
|
||||
|
||||
@ -1444,13 +1453,13 @@ inline void VM::bind__len__(Type type, i64 (*f)(VM*, PyObject*)){
|
||||
}
|
||||
|
||||
|
||||
// inline void Dict::_probe(PyObject *key, bool &ok, int &i) const{
|
||||
// ok = false;
|
||||
// i = vm->hash(key) & _mask;
|
||||
// while(_items[i].first != nullptr) {
|
||||
// if(vm->py_equals(_items[i].first, key)) { ok = true; break; }
|
||||
// i = (i + 1) & _mask;
|
||||
// }
|
||||
// }
|
||||
inline void Dict::_probe(PyObject *key, bool &ok, int &i) const{
|
||||
ok = false;
|
||||
i = vm->py_hash(key) & _mask;
|
||||
while(_items[i].first != nullptr) {
|
||||
if(vm->py_equals(_items[i].first, key)) { ok = true; break; }
|
||||
i = (i + 1) & _mask;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace pkpy
|
||||
Loading…
x
Reference in New Issue
Block a user