This commit is contained in:
BLUELOVETH 2023-02-11 22:07:56 +00:00
parent 794d0785a0
commit 3c098e638f
5 changed files with 85 additions and 55 deletions

View File

@ -138,16 +138,16 @@ struct Frame {
return co->src->snapshot(line);
}
Str stack_info(){
StrStream ss;
ss << "[";
for(int i=0; i<_data.size(); i++){
ss << OBJ_TP_NAME(_data[i]);
if(i != _data.size()-1) ss << ", ";
}
ss << "]";
return ss.str();
}
// Str stack_info(){
// StrStream ss;
// ss << "[";
// for(int i=0; i<_data.size(); i++){
// ss << OBJ_TP_NAME(_data[i]);
// if(i != _data.size()-1) ss << ", ";
// }
// ss << "]";
// return ss.str();
// }
inline bool has_next_bytecode() const {
return _next_ip < co->codes.size();

View File

@ -32,7 +32,7 @@
#define UNREACHABLE() throw std::runtime_error( __FILE__ + std::string(":") + std::to_string(__LINE__) + " UNREACHABLE()!");
#endif
#define PK_VERSION "0.8.5"
#define PK_VERSION "0.8.6"
typedef int64_t i64;
typedef double f64;
@ -40,6 +40,18 @@ typedef double f64;
struct Dummy { char _; };
#define DUMMY_VAL Dummy()
struct Type {
int index;
Type(): index(-1) {}
Type(int index): index(index) {}
inline bool operator==(Type other) const noexcept {
return this->index == other.index;
}
inline bool operator!=(Type other) const noexcept {
return this->index != other.index;
}
};
template<typename T>
void* tid() {
static volatile int8_t _x;

View File

@ -75,17 +75,17 @@ public:
};
struct PyObject {
PyVar type;
Type type;
pkpy::NameDict* _attr;
//void* _tid;
inline bool is_attr_valid() const noexcept { return _attr != nullptr; }
inline pkpy::NameDict& attr() noexcept { return *_attr; }
inline PyVar& attr(const Str& name) noexcept { return (*_attr)[name]; }
inline bool is_type(const PyVar& type) const noexcept{ return this->type == type; }
inline bool is_type(Type type) const noexcept{ return this->type == type; }
virtual void* value() = 0;
PyObject(const PyVar& type) : type(type) {}
PyObject(Type type) : type(type) {}
virtual ~PyObject() { delete _attr; }
};
@ -93,8 +93,8 @@ template <typename T>
struct Py_ : PyObject {
T _value;
Py_(const PyVar& type, T val) : PyObject(type), _value(val) {
if constexpr (std::is_same_v<T, Dummy>
Py_(Type type, T val) : PyObject(type), _value(val) {
if constexpr (std::is_same_v<T, Dummy> || std::is_same_v<T, Type>
|| std::is_same_v<T, pkpy::Function_> || std::is_same_v<T, pkpy::NativeFunc>) {
_attr = new pkpy::NameDict();
}else{
@ -106,9 +106,8 @@ struct Py_ : PyObject {
#define OBJ_GET(T, obj) (((Py_<T>*)((obj).get()))->_value)
#define OBJ_NAME(obj) OBJ_GET(Str, (obj)->attr(__name__))
#define OBJ_TP_NAME(obj) OBJ_GET(Str, (obj)->type->attr(__name__))
#define PY_CLASS(mod, name) \
inline static PyVar _type(VM* vm) { return vm->_modules[#mod]->attr(#name); } \
inline static Type _type(VM* vm) { return OBJ_GET(Type, vm->_modules[#mod]->attr(#name)); } \
inline static const char* _mod() { return #mod; } \
inline static const char* _name() { return #name; }

View File

@ -123,7 +123,7 @@ void init_builtins(VM* _vm) {
_vm->bind_builtin_func<1>("dir", [](VM* vm, const pkpy::Args& args) {
std::vector<Str> names;
for (auto& [k, _] : args[0]->attr()) names.push_back(k);
for (auto& [k, _] : args[0]->type->attr()) {
for (auto& [k, _] : vm->_t(args[0])->attr()) {
if (k.find("__") == 0) continue;
if (std::find(names.begin(), names.end(), k) == names.end()) names.push_back(k);
}
@ -136,17 +136,17 @@ void init_builtins(VM* _vm) {
});
_vm->bind_method<0>("object", "__repr__", [](VM* vm, const pkpy::Args& args) {
PyVar _self = args[0];
std::stringstream ss;
ss << std::hex << (uintptr_t)_self.get();
Str s = "<" + OBJ_TP_NAME(_self) + " object at 0x" + ss.str() + ">";
PyVar self = args[0];
StrStream ss;
ss << std::hex << (uintptr_t)self.get();
Str s = "<" + OBJ_NAME(vm->_t(self)) + " object at 0x" + ss.str() + ">";
return vm->PyStr(s);
});
_vm->bind_method<1>("object", "__eq__", CPP_LAMBDA(vm->PyBool(args[0] == args[1])));
_vm->bind_method<1>("object", "__ne__", CPP_LAMBDA(vm->PyBool(args[0] != args[1])));
_vm->bind_static_method<1>("type", "__new__", CPP_LAMBDA(args[0]->type));
_vm->bind_static_method<1>("type", "__new__", CPP_LAMBDA(vm->_t(args[0])));
_vm->bind_static_method<-1>("range", "__new__", [](VM* vm, const pkpy::Args& args) {
pkpy::Range r;

View File

@ -110,7 +110,7 @@ class VM {
{
const Str& clsName = frame->co->names[byte.arg].first;
PyVar clsBase = frame->pop_value(this);
if(clsBase == None) clsBase = tp_object;
if(clsBase == None) clsBase = _t(tp_object);
check_type(clsBase, tp_type);
PyVar cls = new_type_object(frame->_module, clsName, clsBase);
while(true){
@ -254,7 +254,7 @@ class VM {
PyIter_AS_C(tmp)->var = var;
frame->push(std::move(tmp));
}else{
TypeError(OBJ_TP_NAME(obj).escape(true) + " object is not iterable");
TypeError(OBJ_NAME(_t(obj)).escape(true) + " object is not iterable");
}
} break;
case OP_FOR_ITER:
@ -398,7 +398,7 @@ public:
}
PyVar fast_call(const Str& name, pkpy::Args&& args){
PyObject* cls = args[0]->type.get();
PyObject* cls = _t(args[0]).get();
while(cls != None.get()) {
PyVar* val = cls->attr().try_get(name);
if(val != nullptr) return call(*val, std::move(args));
@ -510,7 +510,7 @@ public:
}
return _exec(fn->code, _module, _locals);
}
TypeError("'" + OBJ_TP_NAME(*callable) + "' object is not callable");
TypeError("'" + OBJ_NAME(_t(*callable)) + "' object is not callable");
return None;
}
@ -584,28 +584,37 @@ public:
}
}
std::vector<PyVar> _all_types;
PyVar new_type_object(PyVar mod, Str name, PyVar base){
if(!base->is_type(tp_type)) UNREACHABLE();
PyVar obj = pkpy::make_shared<PyObject, Py_<Dummy>>(tp_type, DUMMY_VAL);
PyVar obj = pkpy::make_shared<PyObject, Py_<Type>>(tp_type, _all_types.size());
setattr(obj, __base__, base);
Str fullName = name;
if(mod != builtins) fullName = OBJ_NAME(mod) + "." + name;
setattr(obj, __name__, PyStr(fullName));
setattr(mod, name, obj);
_all_types.push_back(obj);
return obj;
}
PyVar _new_type_object(Str name, PyVar base=nullptr) {
if(base == nullptr) base = tp_object;
PyVar obj = pkpy::make_shared<PyObject, Py_<Dummy>>(tp_type, DUMMY_VAL);
setattr(obj, __base__, base);
Type _new_type_object(Str name, Type base=0) {
PyVar obj = pkpy::make_shared<PyObject, Py_<Type>>(tp_type, _all_types.size());
setattr(obj, __base__, _t(base));
_types[name] = obj;
return obj;
_all_types.push_back(obj);
return OBJ_GET(Type, obj);
}
template<typename T>
inline PyVar new_object(PyVar type, T _value) {
if(!type->is_type(tp_type)) UNREACHABLE();
return pkpy::make_shared<PyObject, Py_<T>>(
OBJ_GET(Type, type), _value);
}
template<typename T>
inline PyVar new_object(Type type, T _value) {
return pkpy::make_shared<PyObject, Py_<T>>(type, _value);
}
@ -633,7 +642,7 @@ public:
if(!(*root)->is_type(tp_super)) break;
depth++;
}
cls = (*root)->type.get();
cls = _t(*root).get();
for(int i=0; i<depth; i++) cls = cls->attr(__base__).get();
it = (*root)->attr().find(name);
@ -643,7 +652,7 @@ public:
it = obj->attr().find(name);
if(it != obj->attr().end()) return it->second;
}
cls = obj->type.get();
cls = _t(obj).get();
}
while(cls != None.get()) {
@ -707,7 +716,7 @@ public:
}else if(obj->is_type(tp_float)){
return PyFloat_AS_C(obj);
}
TypeError("expected 'int' or 'float', got " + OBJ_TP_NAME(obj).escape(true));
TypeError("expected 'int' or 'float', got " + OBJ_NAME(_t(obj)).escape(true));
return 0;
}
@ -793,11 +802,11 @@ public:
}
// for quick access
PyVar tp_object, tp_type, tp_int, tp_float, tp_bool, tp_str;
PyVar tp_list, tp_tuple;
PyVar tp_function, tp_native_function, tp_native_iterator, tp_bound_method;
PyVar tp_slice, tp_range, tp_module, tp_ref;
PyVar tp_super, tp_exception;
Type tp_object, tp_type, tp_int, tp_float, tp_bool, tp_str;
Type tp_list, tp_tuple;
Type tp_function, tp_native_function, tp_native_iterator, tp_bound_method;
Type tp_slice, tp_range, tp_module, tp_ref;
Type tp_super, tp_exception;
template<typename P>
inline PyVarRef PyRef(P&& value) {
@ -841,10 +850,14 @@ public:
inline const PyVar& PyBool(bool value){return value ? True : False;}
void init_builtin_types(){
tp_object = pkpy::make_shared<PyObject, Py_<Dummy>>(nullptr, DUMMY_VAL);
tp_type = pkpy::make_shared<PyObject, Py_<Dummy>>(nullptr, DUMMY_VAL);
_types["object"] = tp_object;
_types["type"] = tp_type;
PyVar _tp_object = pkpy::make_shared<PyObject, Py_<Type>>(1, 0);
PyVar _tp_type = pkpy::make_shared<PyObject, Py_<Type>>(1, 1);
_all_types.push_back(_tp_object);
_all_types.push_back(_tp_type);
tp_object = 0; tp_type = 1;
_types["object"] = _tp_object;
_types["type"] = _tp_type;
tp_bool = _new_type_object("bool");
tp_int = _new_type_object("int");
@ -872,10 +885,8 @@ public:
this->_main = new_module("__main__");
this->_py_op_call = new_object(_new_type_object("_internal"), DUMMY_VAL);
setattr(tp_type, __base__, tp_object);
tp_type->type = tp_type;
setattr(tp_object, __base__, None);
tp_object->type = tp_type;
setattr(_t(tp_type), __base__, _t(tp_object));
setattr(_t(tp_object), __base__, None);
for (auto& [name, type] : _types) {
setattr(type, __name__, PyStr(name));
@ -905,7 +916,7 @@ public:
}
return x;
}
TypeError("unhashable type: " + OBJ_TP_NAME(obj).escape(true));
TypeError("unhashable type: " + OBJ_NAME(_t(obj)).escape(true));
return 0;
}
@ -939,17 +950,25 @@ public:
void NameError(const Str& name){ _error("NameError", "name " + name.escape(true) + " is not defined"); }
void AttributeError(PyVar obj, const Str& name){
_error("AttributeError", "type " + OBJ_TP_NAME(obj).escape(true) + " has no attribute " + name.escape(true));
_error("AttributeError", "type " + OBJ_NAME(_t(obj)).escape(true) + " has no attribute " + name.escape(true));
}
inline void check_type(const PyVar& obj, const PyVar& type){
inline void check_type(const PyVar& obj, Type type){
if(obj->is_type(type)) return;
TypeError("expected " + OBJ_NAME(type).escape(true) + ", but got " + OBJ_TP_NAME(obj).escape(true));
TypeError("expected " + OBJ_NAME(_t(type)).escape(true) + ", but got " + OBJ_NAME(_t(obj)).escape(true));
}
inline PyVar& _t(Type t){
return _all_types[t.index];
}
inline PyVar& _t(const PyVar& obj){
return _all_types[OBJ_GET(Type, _t(obj->type)).index];
}
template<typename T>
PyVar register_class(PyVar mod){
PyVar type = new_type_object(mod, T::_name(), tp_object);
PyVar type = new_type_object(mod, T::_name(), _t(tp_object));
if(OBJ_NAME(mod) != T::_mod()) UNREACHABLE();
T::_register(this, mod, type);
return type;