mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-21 12:00:18 +00:00
...
This commit is contained in:
parent
f397917ff5
commit
515321a0af
@ -204,8 +204,10 @@ inline void init_builtins(VM* _vm) {
|
||||
_vm->bind_method<1>("object", "__eq__", CPP_LAMBDA(VAR(args[0] == args[1])));
|
||||
_vm->bind_method<1>("object", "__ne__", CPP_LAMBDA(VAR(args[0] != args[1])));
|
||||
|
||||
_vm->bind_static_method<1>("type", "__new__", CPP_LAMBDA(vm->_t(args[0])));
|
||||
_vm->bind_static_method<-1>("range", "__new__", [](VM* vm, ArgsView args) {
|
||||
_vm->bind_constructor<2>("type", CPP_LAMBDA(vm->_t(args[1])));
|
||||
|
||||
_vm->bind_constructor<-1>("range", [](VM* vm, ArgsView args) {
|
||||
args._begin += 1; // skip cls
|
||||
Range r;
|
||||
switch (args.size()) {
|
||||
case 1: r.stop = CAST(i64, args[0]); break;
|
||||
@ -258,12 +260,12 @@ inline void init_builtins(VM* _vm) {
|
||||
_vm->bind_method<1>("float", "__pow__", py_number_pow);
|
||||
|
||||
/************ PyInt ************/
|
||||
_vm->bind_static_method<1>("int", "__new__", [](VM* vm, ArgsView args) {
|
||||
if (is_type(args[0], vm->tp_float)) return VAR((i64)CAST(f64, args[0]));
|
||||
if (is_type(args[0], vm->tp_int)) return args[0];
|
||||
if (is_type(args[0], vm->tp_bool)) return VAR(_CAST(bool, args[0]) ? 1 : 0);
|
||||
if (is_type(args[0], vm->tp_str)) {
|
||||
const Str& s = CAST(Str&, args[0]);
|
||||
_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];
|
||||
if (is_type(args[1], vm->tp_bool)) return VAR(_CAST(bool, args[1]) ? 1 : 0);
|
||||
if (is_type(args[1], vm->tp_str)) {
|
||||
const Str& s = CAST(Str&, args[1]);
|
||||
try{
|
||||
size_t parsed = 0;
|
||||
i64 val = Number::stoi(s.str(), &parsed, 10);
|
||||
@ -304,12 +306,12 @@ inline void init_builtins(VM* _vm) {
|
||||
#undef INT_BITWISE_OP
|
||||
|
||||
/************ PyFloat ************/
|
||||
_vm->bind_static_method<1>("float", "__new__", [](VM* vm, ArgsView args) {
|
||||
if (is_type(args[0], vm->tp_int)) return VAR((f64)CAST(i64, args[0]));
|
||||
if (is_type(args[0], vm->tp_float)) return args[0];
|
||||
if (is_type(args[0], vm->tp_bool)) return VAR(_CAST(bool, args[0]) ? 1.0 : 0.0);
|
||||
if (is_type(args[0], vm->tp_str)) {
|
||||
const Str& s = CAST(Str&, args[0]);
|
||||
_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];
|
||||
if (is_type(args[1], vm->tp_bool)) return VAR(_CAST(bool, args[1]) ? 1.0 : 0.0);
|
||||
if (is_type(args[1], vm->tp_str)) {
|
||||
const Str& s = CAST(Str&, args[1]);
|
||||
if(s == "inf") return VAR(INFINITY);
|
||||
if(s == "-inf") return VAR(-INFINITY);
|
||||
try{
|
||||
@ -340,7 +342,7 @@ inline void init_builtins(VM* _vm) {
|
||||
});
|
||||
|
||||
/************ PyString ************/
|
||||
_vm->bind_static_method<1>("str", "__new__", CPP_LAMBDA(vm->asStr(args[0])));
|
||||
_vm->bind_constructor<2>("str", CPP_LAMBDA(vm->asStr(args[1])));
|
||||
|
||||
_vm->bind_method<1>("str", "__add__", [](VM* vm, ArgsView args) {
|
||||
const Str& lhs = _CAST(Str&, args[0]);
|
||||
@ -453,16 +455,21 @@ inline void init_builtins(VM* _vm) {
|
||||
_vm->bind_method<1>("str", "join", [](VM* vm, ArgsView args) {
|
||||
const Str& self = _CAST(Str&, args[0]);
|
||||
FastStrStream ss;
|
||||
PyObject* obj = vm->asList(args[1]);
|
||||
const List& list = CAST(List&, obj);
|
||||
for (int i = 0; i < list.size(); ++i) {
|
||||
if (i > 0) ss << self;
|
||||
ss << CAST(Str&, list[i]);
|
||||
PyObject* it = vm->asIter(args[1]);
|
||||
PyObject* obj = vm->PyIterNext(it);
|
||||
while(obj != vm->StopIteration){
|
||||
if(!ss.empty()) ss << self;
|
||||
ss << CAST(Str&, obj);
|
||||
obj = vm->PyIterNext(it);
|
||||
}
|
||||
return VAR(ss.str());
|
||||
});
|
||||
|
||||
/************ PyList ************/
|
||||
_vm->bind_constructor<2>("list", [](VM* vm, ArgsView args) {
|
||||
return vm->asList(args[1]);
|
||||
});
|
||||
|
||||
_vm->bind_method<1>("list", "append", [](VM* vm, ArgsView args) {
|
||||
List& self = _CAST(List&, args[0]);
|
||||
self.push_back(args[1]);
|
||||
@ -471,9 +478,12 @@ inline void init_builtins(VM* _vm) {
|
||||
|
||||
_vm->bind_method<1>("list", "extend", [](VM* vm, ArgsView args) {
|
||||
List& self = _CAST(List&, args[0]);
|
||||
PyObject* obj = vm->asList(args[1]);
|
||||
const List& list = CAST(List&, obj);
|
||||
self.extend(list);
|
||||
PyObject* it = vm->asIter(args[1]);
|
||||
PyObject* obj = vm->PyIterNext(it);
|
||||
while(obj != vm->StopIteration){
|
||||
self.push_back(obj);
|
||||
obj = vm->PyIterNext(it);
|
||||
}
|
||||
return vm->None;
|
||||
});
|
||||
|
||||
@ -560,8 +570,8 @@ inline void init_builtins(VM* _vm) {
|
||||
});
|
||||
|
||||
/************ PyTuple ************/
|
||||
_vm->bind_static_method<1>("tuple", "__new__", [](VM* vm, ArgsView args) {
|
||||
List list = CAST(List, vm->asList(args[0]));
|
||||
_vm->bind_constructor<2>("tuple", [](VM* vm, ArgsView args) {
|
||||
List list = CAST(List, vm->asList(args[1]));
|
||||
return VAR(Tuple(std::move(list)));
|
||||
});
|
||||
|
||||
@ -592,7 +602,7 @@ inline void init_builtins(VM* _vm) {
|
||||
});
|
||||
|
||||
/************ bool ************/
|
||||
_vm->bind_static_method<1>("bool", "__new__", CPP_LAMBDA(VAR(vm->asBool(args[0]))));
|
||||
_vm->bind_constructor<2>("bool", CPP_LAMBDA(VAR(vm->asBool(args[1]))));
|
||||
|
||||
_vm->bind_method<0>("bool", "__repr__", [](VM* vm, ArgsView args) {
|
||||
bool val = _CAST(bool, args[0]);
|
||||
@ -613,8 +623,8 @@ inline void init_builtins(VM* _vm) {
|
||||
_vm->bind_method<0>("ellipsis", "__repr__", CPP_LAMBDA(VAR("Ellipsis")));
|
||||
|
||||
/************ bytes ************/
|
||||
_vm->bind_static_method<1>("bytes", "__new__", [](VM* vm, ArgsView args){
|
||||
List& list = CAST(List&, args[0]);
|
||||
_vm->bind_constructor<2>("bytes", [](VM* vm, ArgsView args){
|
||||
List& list = CAST(List&, args[1]);
|
||||
std::vector<char> buffer(list.size());
|
||||
for(int i=0; i<list.size(); i++){
|
||||
i64 b = CAST(i64, list[i]);
|
||||
@ -668,8 +678,8 @@ inline void init_builtins(VM* _vm) {
|
||||
});
|
||||
|
||||
/************ slice ************/
|
||||
_vm->bind_static_method<3>("slice", "__new__", [](VM* vm, ArgsView args) {
|
||||
return VAR(Slice(args[0], args[1], args[2]));
|
||||
_vm->bind_constructor<4>("slice", [](VM* vm, ArgsView args) {
|
||||
return VAR(Slice(args[1], args[2], args[3]));
|
||||
});
|
||||
|
||||
_vm->bind_method<0>("slice", "__repr__", [](VM* vm, ArgsView args) {
|
||||
@ -919,7 +929,7 @@ struct Random{
|
||||
}
|
||||
|
||||
static void _register(VM* vm, PyObject* mod, PyObject* type){
|
||||
vm->bind_static_method<0>(type, "__new__", CPP_LAMBDA(VAR_T(Random)));
|
||||
vm->bind_default_constructor<Random>(type);
|
||||
|
||||
vm->bind_method<1>(type, "seed", [](VM* vm, ArgsView args) {
|
||||
Random& self = _CAST(Random&, args[0]);
|
||||
|
@ -359,6 +359,8 @@ struct FastStrStream{
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool empty() const { return parts.empty(); }
|
||||
|
||||
Str str() const{
|
||||
int len = 0;
|
||||
bool is_ascii = true;
|
||||
|
69
src/vm.h
69
src/vm.h
@ -64,6 +64,7 @@ struct PyTypeInfo{
|
||||
PyObject* obj;
|
||||
Type base;
|
||||
Str name;
|
||||
bool subclass_enabled;
|
||||
};
|
||||
|
||||
struct FrameId{
|
||||
@ -142,18 +143,12 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PyObject* asList(PyObject* it){
|
||||
if(is_non_tagged_type(it, tp_list)) return it;
|
||||
return call(_t(tp_list), it);
|
||||
}
|
||||
|
||||
PyObject* find_name_in_mro(PyObject* cls, StrName name){
|
||||
PyObject* val;
|
||||
do{
|
||||
val = cls->attr().try_get(name);
|
||||
if(val != nullptr) return val;
|
||||
Type cls_t = OBJ_GET(Type, cls);
|
||||
Type base = _all_types[cls_t].base;
|
||||
Type base = _all_types[OBJ_GET(Type, cls)].base;
|
||||
if(base.index == -1) break;
|
||||
cls = _all_types[base].obj;
|
||||
}while(true);
|
||||
@ -242,12 +237,17 @@ public:
|
||||
return call(p, _0, _1);
|
||||
}
|
||||
|
||||
PyObject* new_type_object(PyObject* mod, StrName name, Type base){
|
||||
PyObject* new_type_object(PyObject* mod, StrName name, Type base, bool subclass_enabled=true){
|
||||
PyObject* obj = heap._new<Type>(tp_type, _all_types.size());
|
||||
const PyTypeInfo& base_info = _all_types[base];
|
||||
if(!base_info.subclass_enabled){
|
||||
TypeError(fmt("type ", base_info.name.escape(), " is not `subclass_enabled`"));
|
||||
}
|
||||
PyTypeInfo info{
|
||||
obj,
|
||||
base,
|
||||
(mod!=nullptr && mod!=builtins) ? Str(OBJ_NAME(mod)+"."+name.sv()): name.sv()
|
||||
(mod!=nullptr && mod!=builtins) ? Str(OBJ_NAME(mod)+"."+name.sv()): name.sv(),
|
||||
subclass_enabled,
|
||||
};
|
||||
if(mod != nullptr) mod->attr().set(name, obj);
|
||||
_all_types.push_back(info);
|
||||
@ -255,7 +255,7 @@ public:
|
||||
}
|
||||
|
||||
Type _new_type_object(StrName name, Type base=0) {
|
||||
PyObject* obj = new_type_object(nullptr, name, base);
|
||||
PyObject* obj = new_type_object(nullptr, name, base, false);
|
||||
return OBJ_GET(Type, obj);
|
||||
}
|
||||
|
||||
@ -278,9 +278,18 @@ public:
|
||||
bind_method<ARGC>(_find_type(type), name, fn);
|
||||
}
|
||||
|
||||
template<int ARGC, typename... Args>
|
||||
void bind_static_method(Args&&... args) {
|
||||
bind_func<ARGC>(std::forward<Args>(args)...);
|
||||
template<int ARGC, typename __T>
|
||||
void bind_constructor(__T&& type, NativeFuncC fn) {
|
||||
static_assert(ARGC==-1 || ARGC>=1);
|
||||
bind_func<ARGC>(std::forward<__T>(type), "__new__", fn);
|
||||
}
|
||||
|
||||
template<typename T, typename __T>
|
||||
void bind_default_constructor(__T&& type) {
|
||||
bind_constructor<1>(std::forward<__T>(type), [](VM* vm, ArgsView args){
|
||||
Type t = OBJ_GET(Type, args[0]);
|
||||
return vm->heap.gcnew<T>(t, T());
|
||||
});
|
||||
}
|
||||
|
||||
template<int ARGC>
|
||||
@ -382,7 +391,8 @@ public:
|
||||
f64 num_to_float(PyObject* obj);
|
||||
bool asBool(PyObject* obj);
|
||||
i64 hash(PyObject* obj);
|
||||
PyObject* asRepr(PyObject* obj);
|
||||
PyObject* asRepr(PyObject*);
|
||||
PyObject* asList(PyObject*);
|
||||
PyObject* new_module(StrName name);
|
||||
Str disassemble(CodeObject_ co);
|
||||
void init_builtin_types();
|
||||
@ -568,6 +578,17 @@ inline bool VM::asBool(PyObject* obj){
|
||||
return true;
|
||||
}
|
||||
|
||||
inline PyObject* VM::asList(PyObject* it){
|
||||
it = asIter(it);
|
||||
List list;
|
||||
PyObject* obj = PyIterNext(it);
|
||||
while(obj != StopIteration){
|
||||
list.push_back(obj);
|
||||
obj = PyIterNext(it);
|
||||
}
|
||||
return VAR(std::move(list));
|
||||
}
|
||||
|
||||
inline void VM::parse_int_slice(const Slice& s, int length, int& start, int& stop, int& step){
|
||||
auto clip = [](int value, int min, int max){
|
||||
if(value < min) return min;
|
||||
@ -838,8 +859,8 @@ inline void VM::_log_s_data(const char* title) {
|
||||
}
|
||||
|
||||
inline void VM::init_builtin_types(){
|
||||
_all_types.push_back({heap._new<Type>(Type(1), Type(0)), -1, "object"});
|
||||
_all_types.push_back({heap._new<Type>(Type(1), Type(1)), 0, "type"});
|
||||
_all_types.push_back({heap._new<Type>(Type(1), Type(0)), -1, "object", true});
|
||||
_all_types.push_back({heap._new<Type>(Type(1), Type(1)), 0, "type", false});
|
||||
tp_object = 0; tp_type = 1;
|
||||
|
||||
tp_int = _new_type_object("int");
|
||||
@ -947,19 +968,25 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){
|
||||
if(method_call) FATAL_ERROR();
|
||||
// [type, NULL, args..., kwargs...]
|
||||
|
||||
// TODO: derived __new__ ?
|
||||
PyObject* new_f = callable->attr().try_get(__new__);
|
||||
// __new__
|
||||
const static StrName m_new("__new__");
|
||||
PyObject* new_f = find_name_in_mro(callable, m_new);
|
||||
PyObject* obj;
|
||||
if(new_f != nullptr){
|
||||
PUSH(new_f);
|
||||
PUSH(PY_NULL);
|
||||
PUSH(callable); // cls
|
||||
for(PyObject* obj: args) PUSH(obj);
|
||||
for(PyObject* obj: kwargs) PUSH(obj);
|
||||
obj = vectorcall(ARGC, KWARGC);
|
||||
if(!isinstance(obj, OBJ_GET(Type, callable))) return obj;
|
||||
// if obj is not an instance of callable, the behavior is undefined
|
||||
obj = vectorcall(ARGC+1, KWARGC);
|
||||
}else{
|
||||
obj = heap.gcnew<DummyInstance>(OBJ_GET(Type, callable), {});
|
||||
// fast path for object.__new__
|
||||
Type t = OBJ_GET(Type, callable);
|
||||
obj= vm->heap.gcnew<DummyInstance>(t, {});
|
||||
}
|
||||
|
||||
// __init__
|
||||
PyObject* self;
|
||||
callable = get_unbound_method(obj, __init__, &self, false);
|
||||
if (self != PY_NULL) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user