This commit is contained in:
blueloveTH 2023-05-09 14:23:28 +08:00
parent f397917ff5
commit 515321a0af
3 changed files with 91 additions and 52 deletions

View File

@ -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]);

View File

@ -359,6 +359,8 @@ struct FastStrStream{
return *this;
}
bool empty() const { return parts.empty(); }
Str str() const{
int len = 0;
bool is_ascii = true;

View File

@ -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) {