mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
add 0xFFF support and fix a bug of int()
This commit is contained in:
parent
353fedfbbe
commit
bfcec88871
@ -55,7 +55,7 @@ os.system("g++ -o pocketpy amalgamated/main.cpp --std=c++17 -pthread")
|
|||||||
os.system("rm pocketpy")
|
os.system("rm pocketpy")
|
||||||
|
|
||||||
os.system("cp amalgamated/pocketpy.h plugins/flutter/src/pocketpy.h")
|
os.system("cp amalgamated/pocketpy.h plugins/flutter/src/pocketpy.h")
|
||||||
os.system("cp amalgamated/pocketpy.h plugins/unity/Assets/PocketPy/Plugins/iOS/pocketpy.h")
|
os.system("cp amalgamated/pocketpy.h plugins/unity/com.bl.pocketpy/Plugins/iOS/pocketpy.h")
|
||||||
|
|
||||||
if os.path.exists("plugins/godot/godot-cpp/pocketpy"):
|
if os.path.exists("plugins/godot/godot-cpp/pocketpy"):
|
||||||
os.system("cp amalgamated/pocketpy.h plugins/godot/godot-cpp/pocketpy/src/pocketpy.h")
|
os.system("cp amalgamated/pocketpy.h plugins/godot/godot-cpp/pocketpy/src/pocketpy.h")
|
@ -15,7 +15,6 @@
|
|||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <variant>
|
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
@ -38,7 +37,10 @@
|
|||||||
#define UNREACHABLE() throw std::runtime_error( __FILE__ + std::string(":") + std::to_string(__LINE__) + " UNREACHABLE()!");
|
#define UNREACHABLE() throw std::runtime_error( __FILE__ + std::string(":") + std::to_string(__LINE__) + " UNREACHABLE()!");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PK_VERSION "0.4.7"
|
#define PK_VERSION "0.4.8"
|
||||||
|
|
||||||
|
//#define PKPY_NO_TYPE_CHECK
|
||||||
|
//#define PKPY_NO_INDEX_CHECK
|
||||||
|
|
||||||
|
|
||||||
namespace pkpy{
|
namespace pkpy{
|
||||||
@ -2275,15 +2277,18 @@ private:
|
|||||||
struct PyObject;
|
struct PyObject;
|
||||||
typedef pkpy::shared_ptr<PyObject> PyVar;
|
typedef pkpy::shared_ptr<PyObject> PyVar;
|
||||||
typedef PyVar PyVarOrNull;
|
typedef PyVar PyVarOrNull;
|
||||||
|
typedef PyVar VarRef;
|
||||||
|
|
||||||
class PyVarList: public std::vector<PyVar> {
|
class PyVarList: public std::vector<PyVar> {
|
||||||
PyVar& at(size_t) = delete;
|
PyVar& at(size_t) = delete;
|
||||||
|
|
||||||
inline void __checkIndex(size_t i) const {
|
inline void __checkIndex(size_t i) const {
|
||||||
|
#ifndef PKPY_NO_INDEX_CHECK
|
||||||
if (i >= size()){
|
if (i >= size()){
|
||||||
auto msg = "std::vector index out of range, " + std::to_string(i) + " not in [0, " + std::to_string(size()) + ")";
|
auto msg = "std::vector index out of range, " + std::to_string(i) + " not in [0, " + std::to_string(size()) + ")";
|
||||||
throw std::out_of_range(msg);
|
throw std::out_of_range(msg);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
PyVar& operator[](size_t i) {
|
PyVar& operator[](size_t i) {
|
||||||
@ -2305,6 +2310,8 @@ class PyVarDict: public emhash8::HashMap<_Str, PyVar> {
|
|||||||
PyVar& at(const _Str&) = delete;
|
PyVar& at(const _Str&) = delete;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
#ifndef PKPY_NO_INDEX_CHECK
|
||||||
PyVar& operator[](const _Str& key) {
|
PyVar& operator[](const _Str& key) {
|
||||||
return emhash8::HashMap<_Str, PyVar>::operator[](key);
|
return emhash8::HashMap<_Str, PyVar>::operator[](key);
|
||||||
}
|
}
|
||||||
@ -2317,8 +2324,9 @@ public:
|
|||||||
}
|
}
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
using emhash8::HashMap<_Str, PyVar>::HashMap;
|
PyVarDict() : emhash8::HashMap<_Str, PyVar>(5) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -2331,10 +2339,12 @@ namespace pkpy {
|
|||||||
uint8_t _size = 0;
|
uint8_t _size = 0;
|
||||||
|
|
||||||
inline void __checkIndex(uint8_t i) const {
|
inline void __checkIndex(uint8_t i) const {
|
||||||
|
#ifndef PKPY_NO_INDEX_CHECK
|
||||||
if (i >= _size){
|
if (i >= _size){
|
||||||
auto msg = "pkpy:ArgList index out of range, " + std::to_string(i) + " not in [0, " + std::to_string(size()) + ")";
|
auto msg = "pkpy:ArgList index out of range, " + std::to_string(i) + " not in [0, " + std::to_string(size()) + ")";
|
||||||
throw std::out_of_range(msg);
|
throw std::out_of_range(msg);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void __tryAlloc(uint8_t n){
|
void __tryAlloc(uint8_t n){
|
||||||
@ -2932,7 +2942,6 @@ struct BasePointer;
|
|||||||
class VM;
|
class VM;
|
||||||
class Frame;
|
class Frame;
|
||||||
|
|
||||||
typedef pkpy::shared_ptr<const BasePointer> _Pointer;
|
|
||||||
typedef PyVar (*_CppFunc)(VM*, const pkpy::ArgList&);
|
typedef PyVar (*_CppFunc)(VM*, const pkpy::ArgList&);
|
||||||
typedef pkpy::shared_ptr<CodeObject> _Code;
|
typedef pkpy::shared_ptr<CodeObject> _Code;
|
||||||
|
|
||||||
@ -2975,60 +2984,54 @@ struct _Slice {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class _Iterator {
|
class BaseIterator {
|
||||||
protected:
|
protected:
|
||||||
VM* vm;
|
VM* vm;
|
||||||
PyVar _ref; // keep a reference to the object so it will not be deleted while iterating
|
PyVar _ref; // keep a reference to the object so it will not be deleted while iterating
|
||||||
public:
|
public:
|
||||||
virtual PyVar next() = 0;
|
virtual PyVar next() = 0;
|
||||||
virtual bool hasNext() = 0;
|
virtual bool hasNext() = 0;
|
||||||
_Pointer var;
|
VarRef var;
|
||||||
_Iterator(VM* vm, PyVar _ref) : vm(vm), _ref(_ref) {}
|
BaseIterator(VM* vm, PyVar _ref) : vm(vm), _ref(_ref) {}
|
||||||
virtual ~_Iterator() = default;
|
virtual ~BaseIterator() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef pkpy::shared_ptr<Function> _Func;
|
typedef pkpy::shared_ptr<Function> _Func;
|
||||||
typedef std::variant<PyVar,_Int,_Float,bool,_Str,PyVarList,_CppFunc,_Func,pkpy::shared_ptr<_Iterator>,_BoundedMethod,_Range,_Slice,_Pointer> _Value;
|
typedef pkpy::shared_ptr<BaseIterator> _Iterator;
|
||||||
|
|
||||||
const int VALUE_SIZE = sizeof(_Value);
|
|
||||||
|
|
||||||
|
|
||||||
struct PyObject {
|
struct PyObject {
|
||||||
PyVarDict attribs;
|
|
||||||
_Value _native;
|
|
||||||
PyVar _type;
|
PyVar _type;
|
||||||
|
PyVarDict attribs;
|
||||||
|
|
||||||
inline bool isType(const PyVar& type){
|
inline bool isType(const PyVar& type){ return this->_type == type; }
|
||||||
return this->_type == type;
|
inline virtual void* value() = 0;
|
||||||
}
|
|
||||||
|
|
||||||
inline void setType(const PyVar& type){
|
|
||||||
this->_type = type;
|
|
||||||
// this->attribs[__class__] = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
// currently __name__ is only used for 'type'
|
// currently __name__ is only used for 'type'
|
||||||
_Str getName(){
|
PyVar _typeName(){ return _type->attribs[__name__]; }
|
||||||
_Value val = attribs[__name__]->_native;
|
|
||||||
return std::get<_Str>(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
_Str getTypeName(){
|
PyObject(PyVar type) : _type(type) {}
|
||||||
return _type->getName();
|
virtual ~PyObject() = default;
|
||||||
}
|
|
||||||
|
|
||||||
PyObject(const _Value& val): _native(val) {}
|
|
||||||
PyObject(_Value&& val): _native(std::move(val)) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct Py_ : PyObject {
|
||||||
|
T _valueT;
|
||||||
|
|
||||||
class RangeIterator : public _Iterator {
|
Py_(T val, const PyVar& type) : PyObject(type), _valueT(val) {}
|
||||||
|
virtual void* value() override { return &_valueT; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#define UNION_GET(T, obj) (((Py_<T>*)((obj).get()))->_valueT)
|
||||||
|
#define UNION_TP_NAME(obj) UNION_GET(_Str, (obj)->_typeName())
|
||||||
|
|
||||||
|
|
||||||
|
class RangeIterator : public BaseIterator {
|
||||||
private:
|
private:
|
||||||
_Int current;
|
_Int current;
|
||||||
_Range r;
|
_Range r;
|
||||||
public:
|
public:
|
||||||
RangeIterator(VM* vm, PyVar _ref) : _Iterator(vm, _ref) {
|
RangeIterator(VM* vm, PyVar _ref) : BaseIterator(vm, _ref) {
|
||||||
this->r = std::get<_Range>(_ref->_native);
|
this->r = UNION_GET(_Range, _ref);
|
||||||
this->current = r.start;
|
this->current = r.start;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3043,13 +3046,13 @@ public:
|
|||||||
PyVar next() override;
|
PyVar next() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class VectorIterator : public _Iterator {
|
class VectorIterator : public BaseIterator {
|
||||||
private:
|
private:
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
const PyVarList* vec;
|
const PyVarList* vec;
|
||||||
public:
|
public:
|
||||||
VectorIterator(VM* vm, PyVar _ref) : _Iterator(vm, _ref) {
|
VectorIterator(VM* vm, PyVar _ref) : BaseIterator(vm, _ref) {
|
||||||
vec = &std::get<PyVarList>(_ref->_native);
|
vec = &UNION_GET(PyVarList, _ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasNext(){
|
bool hasNext(){
|
||||||
@ -3061,13 +3064,13 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class StringIterator : public _Iterator {
|
class StringIterator : public BaseIterator {
|
||||||
private:
|
private:
|
||||||
int index = 0;
|
int index = 0;
|
||||||
_Str str;
|
_Str str;
|
||||||
public:
|
public:
|
||||||
StringIterator(VM* vm, PyVar _ref) : _Iterator(vm, _ref) {
|
StringIterator(VM* vm, PyVar _ref) : BaseIterator(vm, _ref) {
|
||||||
str = std::get<_Str>(_ref->_native);
|
str = UNION_GET(_Str, _ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasNext(){
|
bool hasNext(){
|
||||||
@ -3407,13 +3410,8 @@ enum NameScope {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct NamePointer : BasePointer {
|
struct NamePointer : BasePointer {
|
||||||
const _Str name;
|
const std::pair<_Str, NameScope>* pair;
|
||||||
const NameScope scope;
|
NamePointer(const std::pair<_Str, NameScope>* pair) : pair(pair) {}
|
||||||
NamePointer(const _Str& name, NameScope scope) : name(name), scope(scope) {}
|
|
||||||
|
|
||||||
bool operator==(const NamePointer& other) const {
|
|
||||||
return name == other.name && scope == other.scope;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyVar get(VM* vm, Frame* frame) const;
|
PyVar get(VM* vm, Frame* frame) const;
|
||||||
void set(VM* vm, Frame* frame, PyVar val) const;
|
void set(VM* vm, Frame* frame, PyVar val) const;
|
||||||
@ -3422,8 +3420,8 @@ struct NamePointer : BasePointer {
|
|||||||
|
|
||||||
struct AttrPointer : BasePointer {
|
struct AttrPointer : BasePointer {
|
||||||
mutable PyVar obj;
|
mutable PyVar obj;
|
||||||
const NamePointer* attr;
|
const NamePointer attr;
|
||||||
AttrPointer(PyVar obj, const NamePointer* attr) : obj(obj), attr(attr) {}
|
AttrPointer(PyVar obj, const NamePointer attr) : obj(obj), attr(attr) {}
|
||||||
|
|
||||||
PyVar get(VM* vm, Frame* frame) const;
|
PyVar get(VM* vm, Frame* frame) const;
|
||||||
void set(VM* vm, Frame* frame, PyVar val) const;
|
void set(VM* vm, Frame* frame, PyVar val) const;
|
||||||
@ -3432,7 +3430,7 @@ struct AttrPointer : BasePointer {
|
|||||||
|
|
||||||
struct IndexPointer : BasePointer {
|
struct IndexPointer : BasePointer {
|
||||||
mutable PyVar obj;
|
mutable PyVar obj;
|
||||||
const PyVar index;
|
PyVar index;
|
||||||
IndexPointer(PyVar obj, PyVar index) : obj(obj), index(index) {}
|
IndexPointer(PyVar obj, PyVar index) : obj(obj), index(index) {}
|
||||||
|
|
||||||
PyVar get(VM* vm, Frame* frame) const;
|
PyVar get(VM* vm, Frame* frame) const;
|
||||||
@ -3441,9 +3439,9 @@ struct IndexPointer : BasePointer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct CompoundPointer : BasePointer {
|
struct CompoundPointer : BasePointer {
|
||||||
const std::vector<_Pointer> pointers;
|
PyVarList varRefs;
|
||||||
CompoundPointer(const std::vector<_Pointer>& pointers) : pointers(pointers) {}
|
CompoundPointer(const PyVarList& varRefs) : varRefs(varRefs) {}
|
||||||
CompoundPointer(std::vector<_Pointer>&& pointers) : pointers(pointers) {}
|
CompoundPointer(PyVarList&& varRefs) : varRefs(std::move(varRefs)) {}
|
||||||
|
|
||||||
PyVar get(VM* vm, Frame* frame) const;
|
PyVar get(VM* vm, Frame* frame) const;
|
||||||
void set(VM* vm, Frame* frame, PyVar val) const;
|
void set(VM* vm, Frame* frame, PyVar val) const;
|
||||||
@ -3451,9 +3449,9 @@ struct CompoundPointer : BasePointer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct UserPointer : BasePointer {
|
struct UserPointer : BasePointer {
|
||||||
const _Pointer p;
|
VarRef p;
|
||||||
uint64_t f_id;
|
uint64_t f_id;
|
||||||
UserPointer(_Pointer p, uint64_t f_id) : p(p), f_id(f_id) {}
|
UserPointer(VarRef p, uint64_t f_id) : p(p), f_id(f_id) {}
|
||||||
|
|
||||||
PyVar get(VM* vm, Frame* frame) const;
|
PyVar get(VM* vm, Frame* frame) const;
|
||||||
void set(VM* vm, Frame* frame, PyVar val) const;
|
void set(VM* vm, Frame* frame, PyVar val) const;
|
||||||
@ -3636,7 +3634,7 @@ struct CodeObject {
|
|||||||
|
|
||||||
std::vector<ByteCode> co_code;
|
std::vector<ByteCode> co_code;
|
||||||
PyVarList co_consts;
|
PyVarList co_consts;
|
||||||
std::vector<NamePointer> co_names;
|
std::vector<std::pair<_Str, NameScope>> co_names;
|
||||||
std::vector<_Str> co_global_names;
|
std::vector<_Str> co_global_names;
|
||||||
|
|
||||||
// for goto use
|
// for goto use
|
||||||
@ -3657,7 +3655,7 @@ struct CodeObject {
|
|||||||
if(scope == NAME_LOCAL && std::find(co_global_names.begin(), co_global_names.end(), name) != co_global_names.end()){
|
if(scope == NAME_LOCAL && std::find(co_global_names.begin(), co_global_names.end(), name) != co_global_names.end()){
|
||||||
scope = NAME_GLOBAL;
|
scope = NAME_GLOBAL;
|
||||||
}
|
}
|
||||||
auto p = NamePointer(name, scope);
|
auto p = std::make_pair(name, scope);
|
||||||
for(int i=0; i<co_names.size(); i++){
|
for(int i=0; i<co_names.size(); i++){
|
||||||
if(co_names[i] == p) return i;
|
if(co_names[i] == p) return i;
|
||||||
}
|
}
|
||||||
@ -3697,21 +3695,21 @@ struct CodeObject {
|
|||||||
_StrStream consts;
|
_StrStream consts;
|
||||||
consts << "co_consts: ";
|
consts << "co_consts: ";
|
||||||
for(int i=0; i<co_consts.size(); i++){
|
for(int i=0; i<co_consts.size(); i++){
|
||||||
consts << co_consts[i]->getTypeName();
|
consts << UNION_TP_NAME(co_consts[i]);
|
||||||
if(i != co_consts.size() - 1) consts << ", ";
|
if(i != co_consts.size() - 1) consts << ", ";
|
||||||
}
|
}
|
||||||
|
|
||||||
_StrStream names;
|
_StrStream names;
|
||||||
names << "co_names: ";
|
names << "co_names: ";
|
||||||
for(int i=0; i<co_names.size(); i++){
|
for(int i=0; i<co_names.size(); i++){
|
||||||
names << co_names[i].name;
|
names << co_names[i].first;
|
||||||
if(i != co_names.size() - 1) names << ", ";
|
if(i != co_names.size() - 1) names << ", ";
|
||||||
}
|
}
|
||||||
ss << '\n' << consts.str() << '\n' << names.str() << '\n';
|
ss << '\n' << consts.str() << '\n' << names.str() << '\n';
|
||||||
for(int i=0; i<co_consts.size(); i++){
|
// for(int i=0; i<co_consts.size(); i++){
|
||||||
auto fn = std::get_if<_Func>(&co_consts[i]->_native);
|
// auto fn = std::get_if<_Func>(&co_consts[i]->_native);
|
||||||
if(fn) ss << '\n' << (*fn)->code->name << ":\n" << (*fn)->code->toString();
|
// if(fn) ss << '\n' << (*fn)->code->name << ":\n" << (*fn)->code->toString();
|
||||||
}
|
// }
|
||||||
return _Str(ss.str());
|
return _Str(ss.str());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -3838,7 +3836,7 @@ public:
|
|||||||
#define __DEF_PY_AS_C(type, ctype, ptype) \
|
#define __DEF_PY_AS_C(type, ctype, ptype) \
|
||||||
inline ctype& Py##type##_AS_C(const PyVar& obj) { \
|
inline ctype& Py##type##_AS_C(const PyVar& obj) { \
|
||||||
__checkType(obj, ptype); \
|
__checkType(obj, ptype); \
|
||||||
return std::get<ctype>(obj->_native); \
|
return UNION_GET(ctype, obj); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define __DEF_PY(type, ctype, ptype) \
|
#define __DEF_PY(type, ctype, ptype) \
|
||||||
@ -3850,7 +3848,6 @@ public:
|
|||||||
__DEF_PY(type, ctype, ptype) \
|
__DEF_PY(type, ctype, ptype) \
|
||||||
__DEF_PY_AS_C(type, ctype, ptype)
|
__DEF_PY_AS_C(type, ctype, ptype)
|
||||||
|
|
||||||
typedef void(*PrintFn)(const VM*, const char*);
|
|
||||||
|
|
||||||
class VM {
|
class VM {
|
||||||
std::atomic<bool> _stopFlag = false;
|
std::atomic<bool> _stopFlag = false;
|
||||||
@ -3886,45 +3883,40 @@ protected:
|
|||||||
frame->push(obj);
|
frame->push(obj);
|
||||||
} break;
|
} break;
|
||||||
case OP_LOAD_NAME_PTR: {
|
case OP_LOAD_NAME_PTR: {
|
||||||
frame->push(PyPointer(
|
frame->push(PyPointer(NamePointer(
|
||||||
pkpy::make_shared<const BasePointer, NamePointer>(frame->code->co_names[byte.arg])
|
&(frame->code->co_names[byte.arg])
|
||||||
));
|
)));
|
||||||
} break;
|
} break;
|
||||||
case OP_STORE_NAME_PTR: {
|
case OP_STORE_NAME_PTR: {
|
||||||
const auto& p = frame->code->co_names[byte.arg];
|
const auto& p = frame->code->co_names[byte.arg];
|
||||||
p.set(this, frame, frame->popValue(this));
|
NamePointer(&p).set(this, frame, frame->popValue(this));
|
||||||
} break;
|
} break;
|
||||||
case OP_BUILD_ATTR_PTR: {
|
case OP_BUILD_ATTR_PTR: {
|
||||||
const auto& attr = frame->code->co_names[byte.arg];
|
const auto& attr = frame->code->co_names[byte.arg];
|
||||||
PyVar obj = frame->popValue(this);
|
PyVar obj = frame->popValue(this);
|
||||||
frame->push(PyPointer(
|
frame->push(PyPointer(AttrPointer(obj, NamePointer(&attr))));
|
||||||
pkpy::make_shared<const BasePointer, AttrPointer>(obj, &attr)
|
|
||||||
));
|
|
||||||
} break;
|
} break;
|
||||||
case OP_BUILD_ATTR_PTR_PTR: {
|
case OP_BUILD_ATTR_PTR_PTR: {
|
||||||
const auto& attr = frame->code->co_names[byte.arg];
|
const auto& attr = frame->code->co_names[byte.arg];
|
||||||
PyVar obj = frame->popValue(this);
|
PyVar obj = frame->popValue(this);
|
||||||
__checkType(obj, _tp_user_pointer);
|
__checkType(obj, _tp_user_pointer);
|
||||||
const _Pointer& p = std::get<_Pointer>(obj->_native);
|
const VarRef& var = UNION_GET(VarRef, obj);
|
||||||
frame->push(PyPointer(
|
auto p = PyPointer_AS_C(var);
|
||||||
pkpy::make_shared<const BasePointer, AttrPointer>(p->get(this, frame), &attr)
|
frame->push(PyPointer(AttrPointer(p->get(this, frame), &attr)));
|
||||||
));
|
|
||||||
} break;
|
} break;
|
||||||
case OP_BUILD_INDEX_PTR: {
|
case OP_BUILD_INDEX_PTR: {
|
||||||
PyVar index = frame->popValue(this);
|
PyVar index = frame->popValue(this);
|
||||||
PyVar obj = frame->popValue(this);
|
PyVar obj = frame->popValue(this);
|
||||||
frame->push(PyPointer(
|
frame->push(PyPointer(IndexPointer(obj, index)));
|
||||||
pkpy::make_shared<const BasePointer, IndexPointer>(obj, index)
|
|
||||||
));
|
|
||||||
} break;
|
} break;
|
||||||
case OP_STORE_PTR: {
|
case OP_STORE_PTR: {
|
||||||
PyVar obj = frame->popValue(this);
|
PyVar obj = frame->popValue(this);
|
||||||
const _Pointer p = PyPointer_AS_C(frame->__pop());
|
VarRef r = frame->__pop();
|
||||||
p->set(this, frame, std::move(obj));
|
PyPointer_AS_C(r)->set(this, frame, std::move(obj));
|
||||||
} break;
|
} break;
|
||||||
case OP_DELETE_PTR: {
|
case OP_DELETE_PTR: {
|
||||||
const _Pointer p = PyPointer_AS_C(frame->__pop());
|
VarRef r = frame->__pop();
|
||||||
p->del(this, frame);
|
PyPointer_AS_C(r)->del(this, frame);
|
||||||
} break;
|
} break;
|
||||||
case OP_BUILD_SMART_TUPLE:
|
case OP_BUILD_SMART_TUPLE:
|
||||||
{
|
{
|
||||||
@ -3942,12 +3934,7 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(done) break;
|
if(done) break;
|
||||||
std::vector<_Pointer> pointers(items.size());
|
frame->push(PyPointer(CompoundPointer(items.toList())));
|
||||||
for(int i=0; i<items.size(); i++)
|
|
||||||
pointers[i] = PyPointer_AS_C(items[i]);
|
|
||||||
frame->push(PyPointer(
|
|
||||||
pkpy::make_shared<const BasePointer, CompoundPointer>(std::move(pointers))
|
|
||||||
));
|
|
||||||
} break;
|
} break;
|
||||||
case OP_BUILD_STRING:
|
case OP_BUILD_STRING:
|
||||||
{
|
{
|
||||||
@ -3974,7 +3961,7 @@ protected:
|
|||||||
} break;
|
} break;
|
||||||
case OP_BUILD_CLASS:
|
case OP_BUILD_CLASS:
|
||||||
{
|
{
|
||||||
const _Str& clsName = frame->code->co_names[byte.arg].name;
|
const _Str& clsName = frame->code->co_names[byte.arg].first;
|
||||||
PyVar clsBase = frame->popValue(this);
|
PyVar clsBase = frame->popValue(this);
|
||||||
if(clsBase == None) clsBase = _tp_object;
|
if(clsBase == None) clsBase = _tp_object;
|
||||||
__checkType(clsBase, _tp_type);
|
__checkType(clsBase, _tp_type);
|
||||||
@ -4043,10 +4030,11 @@ protected:
|
|||||||
case OP_UNARY_REF:
|
case OP_UNARY_REF:
|
||||||
{
|
{
|
||||||
// _pointer to pointer
|
// _pointer to pointer
|
||||||
const _Pointer p = PyPointer_AS_C(frame->__pop());
|
VarRef obj = frame->__pop();
|
||||||
|
__checkType(obj, _tp_pointer);
|
||||||
frame->push(newObject(
|
frame->push(newObject(
|
||||||
_tp_user_pointer,
|
_tp_user_pointer,
|
||||||
pkpy::make_shared<const BasePointer, UserPointer>(p, frame->id)
|
PyPointer(UserPointer(obj, frame->id))
|
||||||
));
|
));
|
||||||
} break;
|
} break;
|
||||||
case OP_UNARY_DEREF:
|
case OP_UNARY_DEREF:
|
||||||
@ -4054,7 +4042,7 @@ protected:
|
|||||||
// pointer to _pointer
|
// pointer to _pointer
|
||||||
PyVar obj = frame->popValue(this);
|
PyVar obj = frame->popValue(this);
|
||||||
__checkType(obj, _tp_user_pointer);
|
__checkType(obj, _tp_user_pointer);
|
||||||
frame->push(PyPointer(std::get<_Pointer>(obj->_native)));
|
frame->push(UNION_GET(VarRef, obj));
|
||||||
} break;
|
} break;
|
||||||
case OP_POP_JUMP_IF_FALSE:
|
case OP_POP_JUMP_IF_FALSE:
|
||||||
if(!PyBool_AS_C(asBool(frame->popValue(this)))) frame->jump(byte.arg);
|
if(!PyBool_AS_C(asBool(frame->popValue(this)))) frame->jump(byte.arg);
|
||||||
@ -4114,10 +4102,12 @@ protected:
|
|||||||
PyVarOrNull iter_fn = getAttr(obj, __iter__, false);
|
PyVarOrNull iter_fn = getAttr(obj, __iter__, false);
|
||||||
if(iter_fn != nullptr){
|
if(iter_fn != nullptr){
|
||||||
PyVar tmp = call(iter_fn, {obj});
|
PyVar tmp = call(iter_fn, {obj});
|
||||||
PyIter_AS_C(tmp)->var = std::move(PyPointer_AS_C(frame->__pop()));
|
VarRef var = frame->__pop();
|
||||||
|
__checkType(var, _tp_pointer);
|
||||||
|
PyIter_AS_C(tmp)->var = var;
|
||||||
frame->push(std::move(tmp));
|
frame->push(std::move(tmp));
|
||||||
}else{
|
}else{
|
||||||
typeError("'" + obj->getTypeName() + "' object is not iterable");
|
typeError("'" + UNION_TP_NAME(obj) + "' object is not iterable");
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case OP_FOR_ITER:
|
case OP_FOR_ITER:
|
||||||
@ -4126,7 +4116,7 @@ protected:
|
|||||||
// __top() must be PyIter, so no need to __deref()
|
// __top() must be PyIter, so no need to __deref()
|
||||||
auto& it = PyIter_AS_C(frame->__top());
|
auto& it = PyIter_AS_C(frame->__top());
|
||||||
if(it->hasNext()){
|
if(it->hasNext()){
|
||||||
it->var->set(this, frame, it->next());
|
PyPointer_AS_C(it->var)->set(this, frame, it->next());
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
frame->safeJump(byte.arg);
|
frame->safeJump(byte.arg);
|
||||||
@ -4155,7 +4145,7 @@ protected:
|
|||||||
} break;
|
} break;
|
||||||
case OP_IMPORT_NAME:
|
case OP_IMPORT_NAME:
|
||||||
{
|
{
|
||||||
const _Str& name = frame->code->co_names[byte.arg].name;
|
const _Str& name = frame->code->co_names[byte.arg].first;
|
||||||
auto it = _modules.find(name);
|
auto it = _modules.find(name);
|
||||||
if(it == _modules.end()){
|
if(it == _modules.end()){
|
||||||
auto it2 = _lazyModules.find(name);
|
auto it2 = _lazyModules.find(name);
|
||||||
@ -4262,7 +4252,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
PyVar asRepr(const PyVar& obj){
|
PyVar asRepr(const PyVar& obj){
|
||||||
if(obj->isType(_tp_type)) return PyStr("<class '" + obj->getName() + "'>");
|
if(obj->isType(_tp_type)) return PyStr("<class '" + UNION_GET(_Str, obj->attribs[__name__]) + "'>");
|
||||||
return call(obj, __repr__, {});
|
return call(obj, __repr__, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4323,7 +4313,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if((*callable)->isType(_tp_native_function)){
|
if((*callable)->isType(_tp_native_function)){
|
||||||
const auto& f = std::get<_CppFunc>((*callable)->_native);
|
const auto& f = UNION_GET(_CppFunc, *callable);
|
||||||
return f(this, args);
|
return f(this, args);
|
||||||
} else if((*callable)->isType(_tp_function)){
|
} else if((*callable)->isType(_tp_function)){
|
||||||
const _Func& fn = PyFunction_AS_C((*callable));
|
const _Func& fn = PyFunction_AS_C((*callable));
|
||||||
@ -4361,7 +4351,7 @@ public:
|
|||||||
}
|
}
|
||||||
return _exec(fn->code, _module, locals);
|
return _exec(fn->code, _module, locals);
|
||||||
}
|
}
|
||||||
typeError("'" + (*callable)->getTypeName() + "' object is not callable");
|
typeError("'" + UNION_TP_NAME(*callable) + "' object is not callable");
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4378,15 +4368,13 @@ public:
|
|||||||
if(_module == nullptr) _module = _main;
|
if(_module == nullptr) _module = _main;
|
||||||
try {
|
try {
|
||||||
return _exec(code, _module, {});
|
return _exec(code, _module, {});
|
||||||
} catch (const std::exception& e) {
|
}catch (const _Error& e){
|
||||||
if(dynamic_cast<const _Error*>(&e)){
|
*_stderr << e.what() << '\n';
|
||||||
*_stderr << e.what() << '\n';
|
}catch (const std::exception& e) {
|
||||||
}else{
|
auto re = RuntimeError("UnexpectedError", e.what(), _cleanErrorAndGetSnapshots());
|
||||||
auto re = RuntimeError("UnexpectedError", e.what(), _cleanErrorAndGetSnapshots());
|
*_stderr << re.what() << '\n';
|
||||||
*_stderr << re.what() << '\n';
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void execAsync(const _Code& code) {
|
virtual void execAsync(const _Code& code) {
|
||||||
@ -4437,18 +4425,16 @@ public:
|
|||||||
|
|
||||||
PyVar newClassType(_Str name, PyVar base=nullptr) {
|
PyVar newClassType(_Str name, PyVar base=nullptr) {
|
||||||
if(base == nullptr) base = _tp_object;
|
if(base == nullptr) base = _tp_object;
|
||||||
PyVar obj = pkpy::make_shared<PyObject>((_Int)0);
|
PyVar obj = pkpy::make_shared<PyObject, Py_<_Int>>((_Int)0, _tp_type);
|
||||||
obj->setType(_tp_type);
|
|
||||||
setAttr(obj, __base__, base);
|
setAttr(obj, __base__, base);
|
||||||
_types[name] = obj;
|
_types[name] = obj;
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyVar newObject(PyVar type, const _Value& _native) {
|
template<typename T>
|
||||||
|
inline PyVar newObject(PyVar type, T _value) {
|
||||||
__checkType(type, _tp_type);
|
__checkType(type, _tp_type);
|
||||||
PyVar obj = pkpy::make_shared<PyObject>(_native);
|
return pkpy::make_shared<PyObject, Py_<T>>(_value, type);
|
||||||
obj->setType(type);
|
|
||||||
return obj;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PyVar newModule(_Str name) {
|
PyVar newModule(_Str name) {
|
||||||
@ -4470,7 +4456,7 @@ public:
|
|||||||
const PyVar* root = &obj;
|
const PyVar* root = &obj;
|
||||||
int depth = 1;
|
int depth = 1;
|
||||||
while(true){
|
while(true){
|
||||||
root = &std::get<PyVar>((*root)->_native);
|
root = &UNION_GET(PyVar, *root);
|
||||||
if(!(*root)->isType(_tp_super)) break;
|
if(!(*root)->isType(_tp_super)) break;
|
||||||
depth++;
|
depth++;
|
||||||
}
|
}
|
||||||
@ -4505,7 +4491,7 @@ public:
|
|||||||
if(obj->isType(_tp_super)){
|
if(obj->isType(_tp_super)){
|
||||||
const PyVar* root = &obj;
|
const PyVar* root = &obj;
|
||||||
while(true){
|
while(true){
|
||||||
root = &std::get<PyVar>((*root)->_native);
|
root = &UNION_GET(PyVar, *root);
|
||||||
if(!(*root)->isType(_tp_super)) break;
|
if(!(*root)->isType(_tp_super)) break;
|
||||||
}
|
}
|
||||||
(*root)->attribs[name] = value;
|
(*root)->attribs[name] = value;
|
||||||
@ -4518,7 +4504,7 @@ public:
|
|||||||
if(obj->isType(_tp_super)){
|
if(obj->isType(_tp_super)){
|
||||||
const PyVar* root = &obj;
|
const PyVar* root = &obj;
|
||||||
while(true){
|
while(true){
|
||||||
root = &std::get<PyVar>((*root)->_native);
|
root = &UNION_GET(PyVar, *root);
|
||||||
if(!(*root)->isType(_tp_super)) break;
|
if(!(*root)->isType(_tp_super)) break;
|
||||||
}
|
}
|
||||||
(*root)->attribs[name] = std::move(value);
|
(*root)->attribs[name] = std::move(value);
|
||||||
@ -4603,11 +4589,16 @@ public:
|
|||||||
PyVar _tp_slice, _tp_range, _tp_module, _tp_pointer;
|
PyVar _tp_slice, _tp_range, _tp_module, _tp_pointer;
|
||||||
PyVar _tp_user_pointer, _tp_super;
|
PyVar _tp_user_pointer, _tp_super;
|
||||||
|
|
||||||
__DEF_PY(Pointer, _Pointer, _tp_pointer)
|
template<typename P>
|
||||||
inline _Pointer& PyPointer_AS_C(const PyVar& obj)
|
inline VarRef PyPointer(P value) {
|
||||||
|
static_assert(std::is_base_of<BasePointer, P>::value, "P should derive from BasePointer");
|
||||||
|
return newObject(_tp_pointer, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const BasePointer* PyPointer_AS_C(const PyVar& obj)
|
||||||
{
|
{
|
||||||
if(!obj->isType(_tp_pointer)) typeError("expected an l-value");
|
if(!obj->isType(_tp_pointer)) typeError("expected an l-value");
|
||||||
return std::get<_Pointer>(obj->_native);
|
return (const BasePointer*)(obj->value());
|
||||||
}
|
}
|
||||||
|
|
||||||
__DEF_PY_AS_C(Int, _Int, _tp_int)
|
__DEF_PY_AS_C(Int, _Int, _tp_int)
|
||||||
@ -4622,7 +4613,7 @@ public:
|
|||||||
DEF_NATIVE(Tuple, PyVarList, _tp_tuple)
|
DEF_NATIVE(Tuple, PyVarList, _tp_tuple)
|
||||||
DEF_NATIVE(Function, _Func, _tp_function)
|
DEF_NATIVE(Function, _Func, _tp_function)
|
||||||
DEF_NATIVE(NativeFunction, _CppFunc, _tp_native_function)
|
DEF_NATIVE(NativeFunction, _CppFunc, _tp_native_function)
|
||||||
DEF_NATIVE(Iter, pkpy::shared_ptr<_Iterator>, _tp_native_iterator)
|
DEF_NATIVE(Iter, _Iterator, _tp_native_iterator)
|
||||||
DEF_NATIVE(BoundedMethod, _BoundedMethod, _tp_bounded_method)
|
DEF_NATIVE(BoundedMethod, _BoundedMethod, _tp_bounded_method)
|
||||||
DEF_NATIVE(Range, _Range, _tp_range)
|
DEF_NATIVE(Range, _Range, _tp_range)
|
||||||
DEF_NATIVE(Slice, _Slice, _tp_slice)
|
DEF_NATIVE(Slice, _Slice, _tp_slice)
|
||||||
@ -4632,8 +4623,8 @@ public:
|
|||||||
inline const PyVar& PyBool(bool value){return value ? True : False;}
|
inline const PyVar& PyBool(bool value){return value ? True : False;}
|
||||||
|
|
||||||
void initializeBuiltinClasses(){
|
void initializeBuiltinClasses(){
|
||||||
_tp_object = pkpy::make_shared<PyObject>((_Int)0);
|
_tp_object = pkpy::make_shared<PyObject, Py_<_Int>>((_Int)0, nullptr);
|
||||||
_tp_type = pkpy::make_shared<PyObject>((_Int)0);
|
_tp_type = pkpy::make_shared<PyObject, Py_<_Int>>((_Int)0, nullptr);
|
||||||
|
|
||||||
_types["object"] = _tp_object;
|
_types["object"] = _tp_object;
|
||||||
_types["type"] = _tp_type;
|
_types["type"] = _tp_type;
|
||||||
@ -4667,9 +4658,9 @@ public:
|
|||||||
this->_main = newModule("__main__"_c);
|
this->_main = newModule("__main__"_c);
|
||||||
|
|
||||||
setAttr(_tp_type, __base__, _tp_object);
|
setAttr(_tp_type, __base__, _tp_object);
|
||||||
_tp_type->setType(_tp_type);
|
_tp_type->_type = _tp_type;
|
||||||
setAttr(_tp_object, __base__, None);
|
setAttr(_tp_object, __base__, None);
|
||||||
_tp_object->setType(_tp_type);
|
_tp_object->_type = _tp_type;
|
||||||
|
|
||||||
for (auto& [name, type] : _types) {
|
for (auto& [name, type] : _types) {
|
||||||
setAttr(type, __name__, PyStr(name));
|
setAttr(type, __name__, PyStr(name));
|
||||||
@ -4702,7 +4693,7 @@ public:
|
|||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
typeError("unhashable type: " + obj->getTypeName());
|
typeError("unhashable type: " + UNION_TP_NAME(obj));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4753,11 +4744,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void attributeError(PyVar obj, const _Str& name){
|
void attributeError(PyVar obj, const _Str& name){
|
||||||
_error("AttributeError", "type '" + obj->getTypeName() + "' has no attribute '" + name + "'");
|
_error("AttributeError", "type '" + UNION_TP_NAME(obj) + "' has no attribute '" + name + "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void __checkType(const PyVar& obj, const PyVar& type){
|
inline void __checkType(const PyVar& obj, const PyVar& type){
|
||||||
if(!obj->isType(type)) typeError("expected '" + type->getName() + "', but got '" + obj->getTypeName() + "'");
|
#ifndef PKPY_NO_TYPE_CHECK
|
||||||
|
if(!obj->isType(type)) typeError("expected '" + UNION_TP_NAME(type) + "', but got '" + UNION_TP_NAME(obj) + "'");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void __checkArgSize(const pkpy::ArgList& args, int size, bool method=false){
|
inline void __checkArgSize(const pkpy::ArgList& args, int size, bool method=false){
|
||||||
@ -4781,25 +4774,25 @@ public:
|
|||||||
/***** Pointers' Impl *****/
|
/***** Pointers' Impl *****/
|
||||||
|
|
||||||
PyVar NamePointer::get(VM* vm, Frame* frame) const{
|
PyVar NamePointer::get(VM* vm, Frame* frame) const{
|
||||||
auto it = frame->f_locals.find(name);
|
auto it = frame->f_locals.find(pair->first);
|
||||||
if(it != frame->f_locals.end()) return it->second;
|
if(it != frame->f_locals.end()) return it->second;
|
||||||
it = frame->f_globals().find(name);
|
it = frame->f_globals().find(pair->first);
|
||||||
if(it != frame->f_globals().end()) return it->second;
|
if(it != frame->f_globals().end()) return it->second;
|
||||||
it = vm->builtins->attribs.find(name);
|
it = vm->builtins->attribs.find(pair->first);
|
||||||
if(it != vm->builtins->attribs.end()) return it->second;
|
if(it != vm->builtins->attribs.end()) return it->second;
|
||||||
vm->nameError(name);
|
vm->nameError(pair->first);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NamePointer::set(VM* vm, Frame* frame, PyVar val) const{
|
void NamePointer::set(VM* vm, Frame* frame, PyVar val) const{
|
||||||
switch(scope) {
|
switch(pair->second) {
|
||||||
case NAME_LOCAL: frame->f_locals[name] = std::move(val); break;
|
case NAME_LOCAL: frame->f_locals[pair->first] = std::move(val); break;
|
||||||
case NAME_GLOBAL:
|
case NAME_GLOBAL:
|
||||||
{
|
{
|
||||||
if(frame->f_locals.count(name) > 0){
|
if(frame->f_locals.count(pair->first) > 0){
|
||||||
frame->f_locals[name] = std::move(val);
|
frame->f_locals[pair->first] = std::move(val);
|
||||||
}else{
|
}else{
|
||||||
frame->f_globals()[name] = std::move(val);
|
frame->f_globals()[pair->first] = std::move(val);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
default: UNREACHABLE();
|
default: UNREACHABLE();
|
||||||
@ -4807,23 +4800,23 @@ void NamePointer::set(VM* vm, Frame* frame, PyVar val) const{
|
|||||||
}
|
}
|
||||||
|
|
||||||
void NamePointer::del(VM* vm, Frame* frame) const{
|
void NamePointer::del(VM* vm, Frame* frame) const{
|
||||||
switch(scope) {
|
switch(pair->second) {
|
||||||
case NAME_LOCAL: {
|
case NAME_LOCAL: {
|
||||||
if(frame->f_locals.count(name) > 0){
|
if(frame->f_locals.count(pair->first) > 0){
|
||||||
frame->f_locals.erase(name);
|
frame->f_locals.erase(pair->first);
|
||||||
}else{
|
}else{
|
||||||
vm->nameError(name);
|
vm->nameError(pair->first);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case NAME_GLOBAL:
|
case NAME_GLOBAL:
|
||||||
{
|
{
|
||||||
if(frame->f_locals.count(name) > 0){
|
if(frame->f_locals.count(pair->first) > 0){
|
||||||
frame->f_locals.erase(name);
|
frame->f_locals.erase(pair->first);
|
||||||
}else{
|
}else{
|
||||||
if(frame->f_globals().count(name) > 0){
|
if(frame->f_globals().count(pair->first) > 0){
|
||||||
frame->f_globals().erase(name);
|
frame->f_globals().erase(pair->first);
|
||||||
}else{
|
}else{
|
||||||
vm->nameError(name);
|
vm->nameError(pair->first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@ -4832,11 +4825,11 @@ void NamePointer::del(VM* vm, Frame* frame) const{
|
|||||||
}
|
}
|
||||||
|
|
||||||
PyVar AttrPointer::get(VM* vm, Frame* frame) const{
|
PyVar AttrPointer::get(VM* vm, Frame* frame) const{
|
||||||
return vm->getAttr(obj, attr->name);
|
return vm->getAttr(obj, attr.pair->first);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttrPointer::set(VM* vm, Frame* frame, PyVar val) const{
|
void AttrPointer::set(VM* vm, Frame* frame, PyVar val) const{
|
||||||
vm->setAttr(obj, attr->name, val);
|
vm->setAttr(obj, attr.pair->first, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttrPointer::del(VM* vm, Frame* frame) const{
|
void AttrPointer::del(VM* vm, Frame* frame) const{
|
||||||
@ -4856,9 +4849,9 @@ void IndexPointer::del(VM* vm, Frame* frame) const{
|
|||||||
}
|
}
|
||||||
|
|
||||||
PyVar CompoundPointer::get(VM* vm, Frame* frame) const{
|
PyVar CompoundPointer::get(VM* vm, Frame* frame) const{
|
||||||
PyVarList args(pointers.size());
|
PyVarList args(varRefs.size());
|
||||||
for (int i = 0; i < pointers.size(); i++) {
|
for (int i = 0; i < varRefs.size(); i++) {
|
||||||
args[i] = pointers[i]->get(vm, frame);
|
args[i] = vm->PyPointer_AS_C(varRefs[i])->get(vm, frame);
|
||||||
}
|
}
|
||||||
return vm->PyTuple(args);
|
return vm->PyTuple(args);
|
||||||
}
|
}
|
||||||
@ -4867,28 +4860,28 @@ void CompoundPointer::set(VM* vm, Frame* frame, PyVar val) const{
|
|||||||
if(!val->isType(vm->_tp_tuple) && !val->isType(vm->_tp_list)){
|
if(!val->isType(vm->_tp_tuple) && !val->isType(vm->_tp_list)){
|
||||||
vm->typeError("only tuple or list can be unpacked");
|
vm->typeError("only tuple or list can be unpacked");
|
||||||
}
|
}
|
||||||
const PyVarList& args = std::get<PyVarList>(val->_native);
|
const PyVarList& args = UNION_GET(PyVarList, val);
|
||||||
if(args.size() > pointers.size()) vm->valueError("too many values to unpack");
|
if(args.size() > varRefs.size()) vm->valueError("too many values to unpack");
|
||||||
if(args.size() < pointers.size()) vm->valueError("not enough values to unpack");
|
if(args.size() < varRefs.size()) vm->valueError("not enough values to unpack");
|
||||||
for (int i = 0; i < pointers.size(); i++) {
|
for (int i = 0; i < varRefs.size(); i++) {
|
||||||
pointers[i]->set(vm, frame, args[i]);
|
vm->PyPointer_AS_C(varRefs[i])->set(vm, frame, args[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompoundPointer::del(VM* vm, Frame* frame) const{
|
void CompoundPointer::del(VM* vm, Frame* frame) const{
|
||||||
for (auto& ptr : pointers) ptr->del(vm, frame);
|
for (auto& r : varRefs) vm->PyPointer_AS_C(r)->del(vm, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyVar UserPointer::get(VM* vm, Frame* frame) const{
|
PyVar UserPointer::get(VM* vm, Frame* frame) const{
|
||||||
frame = vm->__findFrame(f_id);
|
frame = vm->__findFrame(f_id);
|
||||||
if(frame == nullptr) vm->nullPointerError();
|
if(frame == nullptr) vm->nullPointerError();
|
||||||
return p->get(vm, frame);
|
return vm->PyPointer_AS_C(p)->get(vm, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserPointer::set(VM* vm, Frame* frame, PyVar val) const{
|
void UserPointer::set(VM* vm, Frame* frame, PyVar val) const{
|
||||||
frame = vm->__findFrame(f_id);
|
frame = vm->__findFrame(f_id);
|
||||||
if(frame == nullptr) vm->nullPointerError();
|
if(frame == nullptr) vm->nullPointerError();
|
||||||
p->set(vm, frame, val);
|
vm->PyPointer_AS_C(p)->set(vm, frame, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserPointer::del(VM* vm, Frame* frame) const{
|
void UserPointer::del(VM* vm, Frame* frame) const{
|
||||||
@ -5144,7 +5137,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void eatNumber() {
|
void eatNumber() {
|
||||||
static const std::regex pattern("^(0x)?[0-9a-f]+(\\.[0-9]+)?");
|
static const std::regex pattern("^(0x)?[0-9a-fA-F]+(\\.[0-9]+)?");
|
||||||
std::smatch m;
|
std::smatch m;
|
||||||
|
|
||||||
const char* i = parser->token_start;
|
const char* i = parser->token_start;
|
||||||
@ -6029,15 +6022,13 @@ _Code compile(VM* vm, const char* source, _Str filename, CompileMode mode=EXEC_M
|
|||||||
if(!noThrow) return compiler.__fillCode();
|
if(!noThrow) return compiler.__fillCode();
|
||||||
try{
|
try{
|
||||||
return compiler.__fillCode();
|
return compiler.__fillCode();
|
||||||
|
}catch(_Error& e){
|
||||||
|
(*vm->_stderr) << e.what() << '\n';
|
||||||
}catch(std::exception& e){
|
}catch(std::exception& e){
|
||||||
if(dynamic_cast<const _Error*>(&e)){
|
auto ce = CompileError("UnexpectedError", e.what(), compiler.getLineSnapshot());
|
||||||
(*vm->_stderr) << e.what() << '\n';
|
(*vm->_stderr) << ce.what() << '\n';
|
||||||
}else{
|
|
||||||
auto ce = CompileError("UnexpectedError", e.what(), compiler.getLineSnapshot());
|
|
||||||
(*vm->_stderr) << ce.what() << '\n';
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -6228,7 +6219,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
|||||||
|
|
||||||
_vm->bindMethod("object", "__repr__", [](VM* vm, const pkpy::ArgList& args) {
|
_vm->bindMethod("object", "__repr__", [](VM* vm, const pkpy::ArgList& args) {
|
||||||
PyVar _self = args[0];
|
PyVar _self = args[0];
|
||||||
_Str s = "<" + _self->getTypeName() + " object at " + std::to_string((uintptr_t)_self.get()) + ">";
|
_Str s = "<" + UNION_TP_NAME(_self) + " object at " + std::to_string((uintptr_t)_self.get()) + ">";
|
||||||
return vm->PyStr(s);
|
return vm->PyStr(s);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -6251,7 +6242,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
|||||||
_vm->bindMethod("range", "__iter__", [](VM* vm, const pkpy::ArgList& args) {
|
_vm->bindMethod("range", "__iter__", [](VM* vm, const pkpy::ArgList& args) {
|
||||||
vm->__checkType(args[0], vm->_tp_range);
|
vm->__checkType(args[0], vm->_tp_range);
|
||||||
return vm->PyIter(
|
return vm->PyIter(
|
||||||
pkpy::make_shared<_Iterator, RangeIterator>(vm, args[0])
|
pkpy::make_shared<BaseIterator, RangeIterator>(vm, args[0])
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -6295,7 +6286,9 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
|||||||
if (args[0]->isType(vm->_tp_str)) {
|
if (args[0]->isType(vm->_tp_str)) {
|
||||||
const _Str& s = vm->PyStr_AS_C(args[0]);
|
const _Str& s = vm->PyStr_AS_C(args[0]);
|
||||||
try{
|
try{
|
||||||
_Int val = std::stoll(s.str());
|
size_t parsed = 0;
|
||||||
|
_Int val = std::stoll(s.str(), &parsed, 10);
|
||||||
|
if(parsed != s.str().size()) throw std::invalid_argument("");
|
||||||
return vm->PyInt(val);
|
return vm->PyInt(val);
|
||||||
}catch(std::invalid_argument&){
|
}catch(std::invalid_argument&){
|
||||||
vm->valueError("invalid literal for int(): '" + s + "'");
|
vm->valueError("invalid literal for int(): '" + s + "'");
|
||||||
@ -6417,7 +6410,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
|||||||
|
|
||||||
_vm->bindMethod("str", "__iter__", [](VM* vm, const pkpy::ArgList& args) {
|
_vm->bindMethod("str", "__iter__", [](VM* vm, const pkpy::ArgList& args) {
|
||||||
return vm->PyIter(
|
return vm->PyIter(
|
||||||
pkpy::make_shared<_Iterator, StringIterator>(vm, args[0])
|
pkpy::make_shared<BaseIterator, StringIterator>(vm, args[0])
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -6531,7 +6524,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
|||||||
_vm->bindMethod("list", "__iter__", [](VM* vm, const pkpy::ArgList& args) {
|
_vm->bindMethod("list", "__iter__", [](VM* vm, const pkpy::ArgList& args) {
|
||||||
vm->__checkType(args[0], vm->_tp_list);
|
vm->__checkType(args[0], vm->_tp_list);
|
||||||
return vm->PyIter(
|
return vm->PyIter(
|
||||||
pkpy::make_shared<_Iterator, VectorIterator>(vm, args[0])
|
pkpy::make_shared<BaseIterator, VectorIterator>(vm, args[0])
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -6629,7 +6622,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
|||||||
_vm->bindMethod("tuple", "__iter__", [](VM* vm, const pkpy::ArgList& args) {
|
_vm->bindMethod("tuple", "__iter__", [](VM* vm, const pkpy::ArgList& args) {
|
||||||
vm->__checkType(args[0], vm->_tp_tuple);
|
vm->__checkType(args[0], vm->_tp_tuple);
|
||||||
return vm->PyIter(
|
return vm->PyIter(
|
||||||
pkpy::make_shared<_Iterator, VectorIterator>(vm, args[0])
|
pkpy::make_shared<BaseIterator, VectorIterator>(vm, args[0])
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -6952,8 +6945,8 @@ extern "C" {
|
|||||||
/// Return a json representing the result.
|
/// Return a json representing the result.
|
||||||
char* pkpy_vm_read_output(VM* vm){
|
char* pkpy_vm_read_output(VM* vm){
|
||||||
if(vm->use_stdio) return nullptr;
|
if(vm->use_stdio) return nullptr;
|
||||||
_StrStream* s_out = dynamic_cast<_StrStream*>(vm->_stdout);
|
_StrStream* s_out = (_StrStream*)(vm->_stdout);
|
||||||
_StrStream* s_err = dynamic_cast<_StrStream*>(vm->_stderr);
|
_StrStream* s_err = (_StrStream*)(vm->_stderr);
|
||||||
_Str _stdout = s_out->str();
|
_Str _stdout = s_out->str();
|
||||||
_Str _stderr = s_err->str();
|
_Str _stderr = s_err->str();
|
||||||
_StrStream ss;
|
_StrStream ss;
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 1ef383ad9eac13df66857620ccb1f0d32724b148
|
Subproject commit 711b948542a1fa76abb1d5786ab5dbd28e5c1b88
|
@ -15,7 +15,6 @@
|
|||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <variant>
|
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
@ -38,7 +37,10 @@
|
|||||||
#define UNREACHABLE() throw std::runtime_error( __FILE__ + std::string(":") + std::to_string(__LINE__) + " UNREACHABLE()!");
|
#define UNREACHABLE() throw std::runtime_error( __FILE__ + std::string(":") + std::to_string(__LINE__) + " UNREACHABLE()!");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PK_VERSION "0.4.7"
|
#define PK_VERSION "0.4.8"
|
||||||
|
|
||||||
|
//#define PKPY_NO_TYPE_CHECK
|
||||||
|
//#define PKPY_NO_INDEX_CHECK
|
||||||
|
|
||||||
|
|
||||||
namespace pkpy{
|
namespace pkpy{
|
||||||
@ -2275,15 +2277,18 @@ private:
|
|||||||
struct PyObject;
|
struct PyObject;
|
||||||
typedef pkpy::shared_ptr<PyObject> PyVar;
|
typedef pkpy::shared_ptr<PyObject> PyVar;
|
||||||
typedef PyVar PyVarOrNull;
|
typedef PyVar PyVarOrNull;
|
||||||
|
typedef PyVar VarRef;
|
||||||
|
|
||||||
class PyVarList: public std::vector<PyVar> {
|
class PyVarList: public std::vector<PyVar> {
|
||||||
PyVar& at(size_t) = delete;
|
PyVar& at(size_t) = delete;
|
||||||
|
|
||||||
inline void __checkIndex(size_t i) const {
|
inline void __checkIndex(size_t i) const {
|
||||||
|
#ifndef PKPY_NO_INDEX_CHECK
|
||||||
if (i >= size()){
|
if (i >= size()){
|
||||||
auto msg = "std::vector index out of range, " + std::to_string(i) + " not in [0, " + std::to_string(size()) + ")";
|
auto msg = "std::vector index out of range, " + std::to_string(i) + " not in [0, " + std::to_string(size()) + ")";
|
||||||
throw std::out_of_range(msg);
|
throw std::out_of_range(msg);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
PyVar& operator[](size_t i) {
|
PyVar& operator[](size_t i) {
|
||||||
@ -2305,6 +2310,8 @@ class PyVarDict: public emhash8::HashMap<_Str, PyVar> {
|
|||||||
PyVar& at(const _Str&) = delete;
|
PyVar& at(const _Str&) = delete;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
#ifndef PKPY_NO_INDEX_CHECK
|
||||||
PyVar& operator[](const _Str& key) {
|
PyVar& operator[](const _Str& key) {
|
||||||
return emhash8::HashMap<_Str, PyVar>::operator[](key);
|
return emhash8::HashMap<_Str, PyVar>::operator[](key);
|
||||||
}
|
}
|
||||||
@ -2317,8 +2324,9 @@ public:
|
|||||||
}
|
}
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
using emhash8::HashMap<_Str, PyVar>::HashMap;
|
PyVarDict() : emhash8::HashMap<_Str, PyVar>(5) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -2331,10 +2339,12 @@ namespace pkpy {
|
|||||||
uint8_t _size = 0;
|
uint8_t _size = 0;
|
||||||
|
|
||||||
inline void __checkIndex(uint8_t i) const {
|
inline void __checkIndex(uint8_t i) const {
|
||||||
|
#ifndef PKPY_NO_INDEX_CHECK
|
||||||
if (i >= _size){
|
if (i >= _size){
|
||||||
auto msg = "pkpy:ArgList index out of range, " + std::to_string(i) + " not in [0, " + std::to_string(size()) + ")";
|
auto msg = "pkpy:ArgList index out of range, " + std::to_string(i) + " not in [0, " + std::to_string(size()) + ")";
|
||||||
throw std::out_of_range(msg);
|
throw std::out_of_range(msg);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void __tryAlloc(uint8_t n){
|
void __tryAlloc(uint8_t n){
|
||||||
@ -2932,7 +2942,6 @@ struct BasePointer;
|
|||||||
class VM;
|
class VM;
|
||||||
class Frame;
|
class Frame;
|
||||||
|
|
||||||
typedef pkpy::shared_ptr<const BasePointer> _Pointer;
|
|
||||||
typedef PyVar (*_CppFunc)(VM*, const pkpy::ArgList&);
|
typedef PyVar (*_CppFunc)(VM*, const pkpy::ArgList&);
|
||||||
typedef pkpy::shared_ptr<CodeObject> _Code;
|
typedef pkpy::shared_ptr<CodeObject> _Code;
|
||||||
|
|
||||||
@ -2975,60 +2984,54 @@ struct _Slice {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class _Iterator {
|
class BaseIterator {
|
||||||
protected:
|
protected:
|
||||||
VM* vm;
|
VM* vm;
|
||||||
PyVar _ref; // keep a reference to the object so it will not be deleted while iterating
|
PyVar _ref; // keep a reference to the object so it will not be deleted while iterating
|
||||||
public:
|
public:
|
||||||
virtual PyVar next() = 0;
|
virtual PyVar next() = 0;
|
||||||
virtual bool hasNext() = 0;
|
virtual bool hasNext() = 0;
|
||||||
_Pointer var;
|
VarRef var;
|
||||||
_Iterator(VM* vm, PyVar _ref) : vm(vm), _ref(_ref) {}
|
BaseIterator(VM* vm, PyVar _ref) : vm(vm), _ref(_ref) {}
|
||||||
virtual ~_Iterator() = default;
|
virtual ~BaseIterator() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef pkpy::shared_ptr<Function> _Func;
|
typedef pkpy::shared_ptr<Function> _Func;
|
||||||
typedef std::variant<PyVar,_Int,_Float,bool,_Str,PyVarList,_CppFunc,_Func,pkpy::shared_ptr<_Iterator>,_BoundedMethod,_Range,_Slice,_Pointer> _Value;
|
typedef pkpy::shared_ptr<BaseIterator> _Iterator;
|
||||||
|
|
||||||
const int VALUE_SIZE = sizeof(_Value);
|
|
||||||
|
|
||||||
|
|
||||||
struct PyObject {
|
struct PyObject {
|
||||||
PyVarDict attribs;
|
|
||||||
_Value _native;
|
|
||||||
PyVar _type;
|
PyVar _type;
|
||||||
|
PyVarDict attribs;
|
||||||
|
|
||||||
inline bool isType(const PyVar& type){
|
inline bool isType(const PyVar& type){ return this->_type == type; }
|
||||||
return this->_type == type;
|
inline virtual void* value() = 0;
|
||||||
}
|
|
||||||
|
|
||||||
inline void setType(const PyVar& type){
|
|
||||||
this->_type = type;
|
|
||||||
// this->attribs[__class__] = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
// currently __name__ is only used for 'type'
|
// currently __name__ is only used for 'type'
|
||||||
_Str getName(){
|
PyVar _typeName(){ return _type->attribs[__name__]; }
|
||||||
_Value val = attribs[__name__]->_native;
|
|
||||||
return std::get<_Str>(val);
|
|
||||||
}
|
|
||||||
|
|
||||||
_Str getTypeName(){
|
PyObject(PyVar type) : _type(type) {}
|
||||||
return _type->getName();
|
virtual ~PyObject() = default;
|
||||||
}
|
|
||||||
|
|
||||||
PyObject(const _Value& val): _native(val) {}
|
|
||||||
PyObject(_Value&& val): _native(std::move(val)) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct Py_ : PyObject {
|
||||||
|
T _valueT;
|
||||||
|
|
||||||
class RangeIterator : public _Iterator {
|
Py_(T val, const PyVar& type) : PyObject(type), _valueT(val) {}
|
||||||
|
virtual void* value() override { return &_valueT; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#define UNION_GET(T, obj) (((Py_<T>*)((obj).get()))->_valueT)
|
||||||
|
#define UNION_TP_NAME(obj) UNION_GET(_Str, (obj)->_typeName())
|
||||||
|
|
||||||
|
|
||||||
|
class RangeIterator : public BaseIterator {
|
||||||
private:
|
private:
|
||||||
_Int current;
|
_Int current;
|
||||||
_Range r;
|
_Range r;
|
||||||
public:
|
public:
|
||||||
RangeIterator(VM* vm, PyVar _ref) : _Iterator(vm, _ref) {
|
RangeIterator(VM* vm, PyVar _ref) : BaseIterator(vm, _ref) {
|
||||||
this->r = std::get<_Range>(_ref->_native);
|
this->r = UNION_GET(_Range, _ref);
|
||||||
this->current = r.start;
|
this->current = r.start;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3043,13 +3046,13 @@ public:
|
|||||||
PyVar next() override;
|
PyVar next() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class VectorIterator : public _Iterator {
|
class VectorIterator : public BaseIterator {
|
||||||
private:
|
private:
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
const PyVarList* vec;
|
const PyVarList* vec;
|
||||||
public:
|
public:
|
||||||
VectorIterator(VM* vm, PyVar _ref) : _Iterator(vm, _ref) {
|
VectorIterator(VM* vm, PyVar _ref) : BaseIterator(vm, _ref) {
|
||||||
vec = &std::get<PyVarList>(_ref->_native);
|
vec = &UNION_GET(PyVarList, _ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasNext(){
|
bool hasNext(){
|
||||||
@ -3061,13 +3064,13 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class StringIterator : public _Iterator {
|
class StringIterator : public BaseIterator {
|
||||||
private:
|
private:
|
||||||
int index = 0;
|
int index = 0;
|
||||||
_Str str;
|
_Str str;
|
||||||
public:
|
public:
|
||||||
StringIterator(VM* vm, PyVar _ref) : _Iterator(vm, _ref) {
|
StringIterator(VM* vm, PyVar _ref) : BaseIterator(vm, _ref) {
|
||||||
str = std::get<_Str>(_ref->_native);
|
str = UNION_GET(_Str, _ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasNext(){
|
bool hasNext(){
|
||||||
@ -3407,13 +3410,8 @@ enum NameScope {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct NamePointer : BasePointer {
|
struct NamePointer : BasePointer {
|
||||||
const _Str name;
|
const std::pair<_Str, NameScope>* pair;
|
||||||
const NameScope scope;
|
NamePointer(const std::pair<_Str, NameScope>* pair) : pair(pair) {}
|
||||||
NamePointer(const _Str& name, NameScope scope) : name(name), scope(scope) {}
|
|
||||||
|
|
||||||
bool operator==(const NamePointer& other) const {
|
|
||||||
return name == other.name && scope == other.scope;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyVar get(VM* vm, Frame* frame) const;
|
PyVar get(VM* vm, Frame* frame) const;
|
||||||
void set(VM* vm, Frame* frame, PyVar val) const;
|
void set(VM* vm, Frame* frame, PyVar val) const;
|
||||||
@ -3422,8 +3420,8 @@ struct NamePointer : BasePointer {
|
|||||||
|
|
||||||
struct AttrPointer : BasePointer {
|
struct AttrPointer : BasePointer {
|
||||||
mutable PyVar obj;
|
mutable PyVar obj;
|
||||||
const NamePointer* attr;
|
const NamePointer attr;
|
||||||
AttrPointer(PyVar obj, const NamePointer* attr) : obj(obj), attr(attr) {}
|
AttrPointer(PyVar obj, const NamePointer attr) : obj(obj), attr(attr) {}
|
||||||
|
|
||||||
PyVar get(VM* vm, Frame* frame) const;
|
PyVar get(VM* vm, Frame* frame) const;
|
||||||
void set(VM* vm, Frame* frame, PyVar val) const;
|
void set(VM* vm, Frame* frame, PyVar val) const;
|
||||||
@ -3432,7 +3430,7 @@ struct AttrPointer : BasePointer {
|
|||||||
|
|
||||||
struct IndexPointer : BasePointer {
|
struct IndexPointer : BasePointer {
|
||||||
mutable PyVar obj;
|
mutable PyVar obj;
|
||||||
const PyVar index;
|
PyVar index;
|
||||||
IndexPointer(PyVar obj, PyVar index) : obj(obj), index(index) {}
|
IndexPointer(PyVar obj, PyVar index) : obj(obj), index(index) {}
|
||||||
|
|
||||||
PyVar get(VM* vm, Frame* frame) const;
|
PyVar get(VM* vm, Frame* frame) const;
|
||||||
@ -3441,9 +3439,9 @@ struct IndexPointer : BasePointer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct CompoundPointer : BasePointer {
|
struct CompoundPointer : BasePointer {
|
||||||
const std::vector<_Pointer> pointers;
|
PyVarList varRefs;
|
||||||
CompoundPointer(const std::vector<_Pointer>& pointers) : pointers(pointers) {}
|
CompoundPointer(const PyVarList& varRefs) : varRefs(varRefs) {}
|
||||||
CompoundPointer(std::vector<_Pointer>&& pointers) : pointers(pointers) {}
|
CompoundPointer(PyVarList&& varRefs) : varRefs(std::move(varRefs)) {}
|
||||||
|
|
||||||
PyVar get(VM* vm, Frame* frame) const;
|
PyVar get(VM* vm, Frame* frame) const;
|
||||||
void set(VM* vm, Frame* frame, PyVar val) const;
|
void set(VM* vm, Frame* frame, PyVar val) const;
|
||||||
@ -3451,9 +3449,9 @@ struct CompoundPointer : BasePointer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct UserPointer : BasePointer {
|
struct UserPointer : BasePointer {
|
||||||
const _Pointer p;
|
VarRef p;
|
||||||
uint64_t f_id;
|
uint64_t f_id;
|
||||||
UserPointer(_Pointer p, uint64_t f_id) : p(p), f_id(f_id) {}
|
UserPointer(VarRef p, uint64_t f_id) : p(p), f_id(f_id) {}
|
||||||
|
|
||||||
PyVar get(VM* vm, Frame* frame) const;
|
PyVar get(VM* vm, Frame* frame) const;
|
||||||
void set(VM* vm, Frame* frame, PyVar val) const;
|
void set(VM* vm, Frame* frame, PyVar val) const;
|
||||||
@ -3636,7 +3634,7 @@ struct CodeObject {
|
|||||||
|
|
||||||
std::vector<ByteCode> co_code;
|
std::vector<ByteCode> co_code;
|
||||||
PyVarList co_consts;
|
PyVarList co_consts;
|
||||||
std::vector<NamePointer> co_names;
|
std::vector<std::pair<_Str, NameScope>> co_names;
|
||||||
std::vector<_Str> co_global_names;
|
std::vector<_Str> co_global_names;
|
||||||
|
|
||||||
// for goto use
|
// for goto use
|
||||||
@ -3657,7 +3655,7 @@ struct CodeObject {
|
|||||||
if(scope == NAME_LOCAL && std::find(co_global_names.begin(), co_global_names.end(), name) != co_global_names.end()){
|
if(scope == NAME_LOCAL && std::find(co_global_names.begin(), co_global_names.end(), name) != co_global_names.end()){
|
||||||
scope = NAME_GLOBAL;
|
scope = NAME_GLOBAL;
|
||||||
}
|
}
|
||||||
auto p = NamePointer(name, scope);
|
auto p = std::make_pair(name, scope);
|
||||||
for(int i=0; i<co_names.size(); i++){
|
for(int i=0; i<co_names.size(); i++){
|
||||||
if(co_names[i] == p) return i;
|
if(co_names[i] == p) return i;
|
||||||
}
|
}
|
||||||
@ -3697,21 +3695,21 @@ struct CodeObject {
|
|||||||
_StrStream consts;
|
_StrStream consts;
|
||||||
consts << "co_consts: ";
|
consts << "co_consts: ";
|
||||||
for(int i=0; i<co_consts.size(); i++){
|
for(int i=0; i<co_consts.size(); i++){
|
||||||
consts << co_consts[i]->getTypeName();
|
consts << UNION_TP_NAME(co_consts[i]);
|
||||||
if(i != co_consts.size() - 1) consts << ", ";
|
if(i != co_consts.size() - 1) consts << ", ";
|
||||||
}
|
}
|
||||||
|
|
||||||
_StrStream names;
|
_StrStream names;
|
||||||
names << "co_names: ";
|
names << "co_names: ";
|
||||||
for(int i=0; i<co_names.size(); i++){
|
for(int i=0; i<co_names.size(); i++){
|
||||||
names << co_names[i].name;
|
names << co_names[i].first;
|
||||||
if(i != co_names.size() - 1) names << ", ";
|
if(i != co_names.size() - 1) names << ", ";
|
||||||
}
|
}
|
||||||
ss << '\n' << consts.str() << '\n' << names.str() << '\n';
|
ss << '\n' << consts.str() << '\n' << names.str() << '\n';
|
||||||
for(int i=0; i<co_consts.size(); i++){
|
// for(int i=0; i<co_consts.size(); i++){
|
||||||
auto fn = std::get_if<_Func>(&co_consts[i]->_native);
|
// auto fn = std::get_if<_Func>(&co_consts[i]->_native);
|
||||||
if(fn) ss << '\n' << (*fn)->code->name << ":\n" << (*fn)->code->toString();
|
// if(fn) ss << '\n' << (*fn)->code->name << ":\n" << (*fn)->code->toString();
|
||||||
}
|
// }
|
||||||
return _Str(ss.str());
|
return _Str(ss.str());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -3838,7 +3836,7 @@ public:
|
|||||||
#define __DEF_PY_AS_C(type, ctype, ptype) \
|
#define __DEF_PY_AS_C(type, ctype, ptype) \
|
||||||
inline ctype& Py##type##_AS_C(const PyVar& obj) { \
|
inline ctype& Py##type##_AS_C(const PyVar& obj) { \
|
||||||
__checkType(obj, ptype); \
|
__checkType(obj, ptype); \
|
||||||
return std::get<ctype>(obj->_native); \
|
return UNION_GET(ctype, obj); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define __DEF_PY(type, ctype, ptype) \
|
#define __DEF_PY(type, ctype, ptype) \
|
||||||
@ -3850,7 +3848,6 @@ public:
|
|||||||
__DEF_PY(type, ctype, ptype) \
|
__DEF_PY(type, ctype, ptype) \
|
||||||
__DEF_PY_AS_C(type, ctype, ptype)
|
__DEF_PY_AS_C(type, ctype, ptype)
|
||||||
|
|
||||||
typedef void(*PrintFn)(const VM*, const char*);
|
|
||||||
|
|
||||||
class VM {
|
class VM {
|
||||||
std::atomic<bool> _stopFlag = false;
|
std::atomic<bool> _stopFlag = false;
|
||||||
@ -3886,45 +3883,40 @@ protected:
|
|||||||
frame->push(obj);
|
frame->push(obj);
|
||||||
} break;
|
} break;
|
||||||
case OP_LOAD_NAME_PTR: {
|
case OP_LOAD_NAME_PTR: {
|
||||||
frame->push(PyPointer(
|
frame->push(PyPointer(NamePointer(
|
||||||
pkpy::make_shared<const BasePointer, NamePointer>(frame->code->co_names[byte.arg])
|
&(frame->code->co_names[byte.arg])
|
||||||
));
|
)));
|
||||||
} break;
|
} break;
|
||||||
case OP_STORE_NAME_PTR: {
|
case OP_STORE_NAME_PTR: {
|
||||||
const auto& p = frame->code->co_names[byte.arg];
|
const auto& p = frame->code->co_names[byte.arg];
|
||||||
p.set(this, frame, frame->popValue(this));
|
NamePointer(&p).set(this, frame, frame->popValue(this));
|
||||||
} break;
|
} break;
|
||||||
case OP_BUILD_ATTR_PTR: {
|
case OP_BUILD_ATTR_PTR: {
|
||||||
const auto& attr = frame->code->co_names[byte.arg];
|
const auto& attr = frame->code->co_names[byte.arg];
|
||||||
PyVar obj = frame->popValue(this);
|
PyVar obj = frame->popValue(this);
|
||||||
frame->push(PyPointer(
|
frame->push(PyPointer(AttrPointer(obj, NamePointer(&attr))));
|
||||||
pkpy::make_shared<const BasePointer, AttrPointer>(obj, &attr)
|
|
||||||
));
|
|
||||||
} break;
|
} break;
|
||||||
case OP_BUILD_ATTR_PTR_PTR: {
|
case OP_BUILD_ATTR_PTR_PTR: {
|
||||||
const auto& attr = frame->code->co_names[byte.arg];
|
const auto& attr = frame->code->co_names[byte.arg];
|
||||||
PyVar obj = frame->popValue(this);
|
PyVar obj = frame->popValue(this);
|
||||||
__checkType(obj, _tp_user_pointer);
|
__checkType(obj, _tp_user_pointer);
|
||||||
const _Pointer& p = std::get<_Pointer>(obj->_native);
|
const VarRef& var = UNION_GET(VarRef, obj);
|
||||||
frame->push(PyPointer(
|
auto p = PyPointer_AS_C(var);
|
||||||
pkpy::make_shared<const BasePointer, AttrPointer>(p->get(this, frame), &attr)
|
frame->push(PyPointer(AttrPointer(p->get(this, frame), &attr)));
|
||||||
));
|
|
||||||
} break;
|
} break;
|
||||||
case OP_BUILD_INDEX_PTR: {
|
case OP_BUILD_INDEX_PTR: {
|
||||||
PyVar index = frame->popValue(this);
|
PyVar index = frame->popValue(this);
|
||||||
PyVar obj = frame->popValue(this);
|
PyVar obj = frame->popValue(this);
|
||||||
frame->push(PyPointer(
|
frame->push(PyPointer(IndexPointer(obj, index)));
|
||||||
pkpy::make_shared<const BasePointer, IndexPointer>(obj, index)
|
|
||||||
));
|
|
||||||
} break;
|
} break;
|
||||||
case OP_STORE_PTR: {
|
case OP_STORE_PTR: {
|
||||||
PyVar obj = frame->popValue(this);
|
PyVar obj = frame->popValue(this);
|
||||||
const _Pointer p = PyPointer_AS_C(frame->__pop());
|
VarRef r = frame->__pop();
|
||||||
p->set(this, frame, std::move(obj));
|
PyPointer_AS_C(r)->set(this, frame, std::move(obj));
|
||||||
} break;
|
} break;
|
||||||
case OP_DELETE_PTR: {
|
case OP_DELETE_PTR: {
|
||||||
const _Pointer p = PyPointer_AS_C(frame->__pop());
|
VarRef r = frame->__pop();
|
||||||
p->del(this, frame);
|
PyPointer_AS_C(r)->del(this, frame);
|
||||||
} break;
|
} break;
|
||||||
case OP_BUILD_SMART_TUPLE:
|
case OP_BUILD_SMART_TUPLE:
|
||||||
{
|
{
|
||||||
@ -3942,12 +3934,7 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(done) break;
|
if(done) break;
|
||||||
std::vector<_Pointer> pointers(items.size());
|
frame->push(PyPointer(CompoundPointer(items.toList())));
|
||||||
for(int i=0; i<items.size(); i++)
|
|
||||||
pointers[i] = PyPointer_AS_C(items[i]);
|
|
||||||
frame->push(PyPointer(
|
|
||||||
pkpy::make_shared<const BasePointer, CompoundPointer>(std::move(pointers))
|
|
||||||
));
|
|
||||||
} break;
|
} break;
|
||||||
case OP_BUILD_STRING:
|
case OP_BUILD_STRING:
|
||||||
{
|
{
|
||||||
@ -3974,7 +3961,7 @@ protected:
|
|||||||
} break;
|
} break;
|
||||||
case OP_BUILD_CLASS:
|
case OP_BUILD_CLASS:
|
||||||
{
|
{
|
||||||
const _Str& clsName = frame->code->co_names[byte.arg].name;
|
const _Str& clsName = frame->code->co_names[byte.arg].first;
|
||||||
PyVar clsBase = frame->popValue(this);
|
PyVar clsBase = frame->popValue(this);
|
||||||
if(clsBase == None) clsBase = _tp_object;
|
if(clsBase == None) clsBase = _tp_object;
|
||||||
__checkType(clsBase, _tp_type);
|
__checkType(clsBase, _tp_type);
|
||||||
@ -4043,10 +4030,11 @@ protected:
|
|||||||
case OP_UNARY_REF:
|
case OP_UNARY_REF:
|
||||||
{
|
{
|
||||||
// _pointer to pointer
|
// _pointer to pointer
|
||||||
const _Pointer p = PyPointer_AS_C(frame->__pop());
|
VarRef obj = frame->__pop();
|
||||||
|
__checkType(obj, _tp_pointer);
|
||||||
frame->push(newObject(
|
frame->push(newObject(
|
||||||
_tp_user_pointer,
|
_tp_user_pointer,
|
||||||
pkpy::make_shared<const BasePointer, UserPointer>(p, frame->id)
|
PyPointer(UserPointer(obj, frame->id))
|
||||||
));
|
));
|
||||||
} break;
|
} break;
|
||||||
case OP_UNARY_DEREF:
|
case OP_UNARY_DEREF:
|
||||||
@ -4054,7 +4042,7 @@ protected:
|
|||||||
// pointer to _pointer
|
// pointer to _pointer
|
||||||
PyVar obj = frame->popValue(this);
|
PyVar obj = frame->popValue(this);
|
||||||
__checkType(obj, _tp_user_pointer);
|
__checkType(obj, _tp_user_pointer);
|
||||||
frame->push(PyPointer(std::get<_Pointer>(obj->_native)));
|
frame->push(UNION_GET(VarRef, obj));
|
||||||
} break;
|
} break;
|
||||||
case OP_POP_JUMP_IF_FALSE:
|
case OP_POP_JUMP_IF_FALSE:
|
||||||
if(!PyBool_AS_C(asBool(frame->popValue(this)))) frame->jump(byte.arg);
|
if(!PyBool_AS_C(asBool(frame->popValue(this)))) frame->jump(byte.arg);
|
||||||
@ -4114,10 +4102,12 @@ protected:
|
|||||||
PyVarOrNull iter_fn = getAttr(obj, __iter__, false);
|
PyVarOrNull iter_fn = getAttr(obj, __iter__, false);
|
||||||
if(iter_fn != nullptr){
|
if(iter_fn != nullptr){
|
||||||
PyVar tmp = call(iter_fn, {obj});
|
PyVar tmp = call(iter_fn, {obj});
|
||||||
PyIter_AS_C(tmp)->var = std::move(PyPointer_AS_C(frame->__pop()));
|
VarRef var = frame->__pop();
|
||||||
|
__checkType(var, _tp_pointer);
|
||||||
|
PyIter_AS_C(tmp)->var = var;
|
||||||
frame->push(std::move(tmp));
|
frame->push(std::move(tmp));
|
||||||
}else{
|
}else{
|
||||||
typeError("'" + obj->getTypeName() + "' object is not iterable");
|
typeError("'" + UNION_TP_NAME(obj) + "' object is not iterable");
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case OP_FOR_ITER:
|
case OP_FOR_ITER:
|
||||||
@ -4126,7 +4116,7 @@ protected:
|
|||||||
// __top() must be PyIter, so no need to __deref()
|
// __top() must be PyIter, so no need to __deref()
|
||||||
auto& it = PyIter_AS_C(frame->__top());
|
auto& it = PyIter_AS_C(frame->__top());
|
||||||
if(it->hasNext()){
|
if(it->hasNext()){
|
||||||
it->var->set(this, frame, it->next());
|
PyPointer_AS_C(it->var)->set(this, frame, it->next());
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
frame->safeJump(byte.arg);
|
frame->safeJump(byte.arg);
|
||||||
@ -4155,7 +4145,7 @@ protected:
|
|||||||
} break;
|
} break;
|
||||||
case OP_IMPORT_NAME:
|
case OP_IMPORT_NAME:
|
||||||
{
|
{
|
||||||
const _Str& name = frame->code->co_names[byte.arg].name;
|
const _Str& name = frame->code->co_names[byte.arg].first;
|
||||||
auto it = _modules.find(name);
|
auto it = _modules.find(name);
|
||||||
if(it == _modules.end()){
|
if(it == _modules.end()){
|
||||||
auto it2 = _lazyModules.find(name);
|
auto it2 = _lazyModules.find(name);
|
||||||
@ -4262,7 +4252,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
PyVar asRepr(const PyVar& obj){
|
PyVar asRepr(const PyVar& obj){
|
||||||
if(obj->isType(_tp_type)) return PyStr("<class '" + obj->getName() + "'>");
|
if(obj->isType(_tp_type)) return PyStr("<class '" + UNION_GET(_Str, obj->attribs[__name__]) + "'>");
|
||||||
return call(obj, __repr__, {});
|
return call(obj, __repr__, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4323,7 +4313,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if((*callable)->isType(_tp_native_function)){
|
if((*callable)->isType(_tp_native_function)){
|
||||||
const auto& f = std::get<_CppFunc>((*callable)->_native);
|
const auto& f = UNION_GET(_CppFunc, *callable);
|
||||||
return f(this, args);
|
return f(this, args);
|
||||||
} else if((*callable)->isType(_tp_function)){
|
} else if((*callable)->isType(_tp_function)){
|
||||||
const _Func& fn = PyFunction_AS_C((*callable));
|
const _Func& fn = PyFunction_AS_C((*callable));
|
||||||
@ -4361,7 +4351,7 @@ public:
|
|||||||
}
|
}
|
||||||
return _exec(fn->code, _module, locals);
|
return _exec(fn->code, _module, locals);
|
||||||
}
|
}
|
||||||
typeError("'" + (*callable)->getTypeName() + "' object is not callable");
|
typeError("'" + UNION_TP_NAME(*callable) + "' object is not callable");
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4378,15 +4368,13 @@ public:
|
|||||||
if(_module == nullptr) _module = _main;
|
if(_module == nullptr) _module = _main;
|
||||||
try {
|
try {
|
||||||
return _exec(code, _module, {});
|
return _exec(code, _module, {});
|
||||||
} catch (const std::exception& e) {
|
}catch (const _Error& e){
|
||||||
if(dynamic_cast<const _Error*>(&e)){
|
*_stderr << e.what() << '\n';
|
||||||
*_stderr << e.what() << '\n';
|
}catch (const std::exception& e) {
|
||||||
}else{
|
auto re = RuntimeError("UnexpectedError", e.what(), _cleanErrorAndGetSnapshots());
|
||||||
auto re = RuntimeError("UnexpectedError", e.what(), _cleanErrorAndGetSnapshots());
|
*_stderr << re.what() << '\n';
|
||||||
*_stderr << re.what() << '\n';
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void execAsync(const _Code& code) {
|
virtual void execAsync(const _Code& code) {
|
||||||
@ -4437,18 +4425,16 @@ public:
|
|||||||
|
|
||||||
PyVar newClassType(_Str name, PyVar base=nullptr) {
|
PyVar newClassType(_Str name, PyVar base=nullptr) {
|
||||||
if(base == nullptr) base = _tp_object;
|
if(base == nullptr) base = _tp_object;
|
||||||
PyVar obj = pkpy::make_shared<PyObject>((_Int)0);
|
PyVar obj = pkpy::make_shared<PyObject, Py_<_Int>>((_Int)0, _tp_type);
|
||||||
obj->setType(_tp_type);
|
|
||||||
setAttr(obj, __base__, base);
|
setAttr(obj, __base__, base);
|
||||||
_types[name] = obj;
|
_types[name] = obj;
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyVar newObject(PyVar type, const _Value& _native) {
|
template<typename T>
|
||||||
|
inline PyVar newObject(PyVar type, T _value) {
|
||||||
__checkType(type, _tp_type);
|
__checkType(type, _tp_type);
|
||||||
PyVar obj = pkpy::make_shared<PyObject>(_native);
|
return pkpy::make_shared<PyObject, Py_<T>>(_value, type);
|
||||||
obj->setType(type);
|
|
||||||
return obj;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PyVar newModule(_Str name) {
|
PyVar newModule(_Str name) {
|
||||||
@ -4470,7 +4456,7 @@ public:
|
|||||||
const PyVar* root = &obj;
|
const PyVar* root = &obj;
|
||||||
int depth = 1;
|
int depth = 1;
|
||||||
while(true){
|
while(true){
|
||||||
root = &std::get<PyVar>((*root)->_native);
|
root = &UNION_GET(PyVar, *root);
|
||||||
if(!(*root)->isType(_tp_super)) break;
|
if(!(*root)->isType(_tp_super)) break;
|
||||||
depth++;
|
depth++;
|
||||||
}
|
}
|
||||||
@ -4505,7 +4491,7 @@ public:
|
|||||||
if(obj->isType(_tp_super)){
|
if(obj->isType(_tp_super)){
|
||||||
const PyVar* root = &obj;
|
const PyVar* root = &obj;
|
||||||
while(true){
|
while(true){
|
||||||
root = &std::get<PyVar>((*root)->_native);
|
root = &UNION_GET(PyVar, *root);
|
||||||
if(!(*root)->isType(_tp_super)) break;
|
if(!(*root)->isType(_tp_super)) break;
|
||||||
}
|
}
|
||||||
(*root)->attribs[name] = value;
|
(*root)->attribs[name] = value;
|
||||||
@ -4518,7 +4504,7 @@ public:
|
|||||||
if(obj->isType(_tp_super)){
|
if(obj->isType(_tp_super)){
|
||||||
const PyVar* root = &obj;
|
const PyVar* root = &obj;
|
||||||
while(true){
|
while(true){
|
||||||
root = &std::get<PyVar>((*root)->_native);
|
root = &UNION_GET(PyVar, *root);
|
||||||
if(!(*root)->isType(_tp_super)) break;
|
if(!(*root)->isType(_tp_super)) break;
|
||||||
}
|
}
|
||||||
(*root)->attribs[name] = std::move(value);
|
(*root)->attribs[name] = std::move(value);
|
||||||
@ -4603,11 +4589,16 @@ public:
|
|||||||
PyVar _tp_slice, _tp_range, _tp_module, _tp_pointer;
|
PyVar _tp_slice, _tp_range, _tp_module, _tp_pointer;
|
||||||
PyVar _tp_user_pointer, _tp_super;
|
PyVar _tp_user_pointer, _tp_super;
|
||||||
|
|
||||||
__DEF_PY(Pointer, _Pointer, _tp_pointer)
|
template<typename P>
|
||||||
inline _Pointer& PyPointer_AS_C(const PyVar& obj)
|
inline VarRef PyPointer(P value) {
|
||||||
|
static_assert(std::is_base_of<BasePointer, P>::value, "P should derive from BasePointer");
|
||||||
|
return newObject(_tp_pointer, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const BasePointer* PyPointer_AS_C(const PyVar& obj)
|
||||||
{
|
{
|
||||||
if(!obj->isType(_tp_pointer)) typeError("expected an l-value");
|
if(!obj->isType(_tp_pointer)) typeError("expected an l-value");
|
||||||
return std::get<_Pointer>(obj->_native);
|
return (const BasePointer*)(obj->value());
|
||||||
}
|
}
|
||||||
|
|
||||||
__DEF_PY_AS_C(Int, _Int, _tp_int)
|
__DEF_PY_AS_C(Int, _Int, _tp_int)
|
||||||
@ -4622,7 +4613,7 @@ public:
|
|||||||
DEF_NATIVE(Tuple, PyVarList, _tp_tuple)
|
DEF_NATIVE(Tuple, PyVarList, _tp_tuple)
|
||||||
DEF_NATIVE(Function, _Func, _tp_function)
|
DEF_NATIVE(Function, _Func, _tp_function)
|
||||||
DEF_NATIVE(NativeFunction, _CppFunc, _tp_native_function)
|
DEF_NATIVE(NativeFunction, _CppFunc, _tp_native_function)
|
||||||
DEF_NATIVE(Iter, pkpy::shared_ptr<_Iterator>, _tp_native_iterator)
|
DEF_NATIVE(Iter, _Iterator, _tp_native_iterator)
|
||||||
DEF_NATIVE(BoundedMethod, _BoundedMethod, _tp_bounded_method)
|
DEF_NATIVE(BoundedMethod, _BoundedMethod, _tp_bounded_method)
|
||||||
DEF_NATIVE(Range, _Range, _tp_range)
|
DEF_NATIVE(Range, _Range, _tp_range)
|
||||||
DEF_NATIVE(Slice, _Slice, _tp_slice)
|
DEF_NATIVE(Slice, _Slice, _tp_slice)
|
||||||
@ -4632,8 +4623,8 @@ public:
|
|||||||
inline const PyVar& PyBool(bool value){return value ? True : False;}
|
inline const PyVar& PyBool(bool value){return value ? True : False;}
|
||||||
|
|
||||||
void initializeBuiltinClasses(){
|
void initializeBuiltinClasses(){
|
||||||
_tp_object = pkpy::make_shared<PyObject>((_Int)0);
|
_tp_object = pkpy::make_shared<PyObject, Py_<_Int>>((_Int)0, nullptr);
|
||||||
_tp_type = pkpy::make_shared<PyObject>((_Int)0);
|
_tp_type = pkpy::make_shared<PyObject, Py_<_Int>>((_Int)0, nullptr);
|
||||||
|
|
||||||
_types["object"] = _tp_object;
|
_types["object"] = _tp_object;
|
||||||
_types["type"] = _tp_type;
|
_types["type"] = _tp_type;
|
||||||
@ -4667,9 +4658,9 @@ public:
|
|||||||
this->_main = newModule("__main__"_c);
|
this->_main = newModule("__main__"_c);
|
||||||
|
|
||||||
setAttr(_tp_type, __base__, _tp_object);
|
setAttr(_tp_type, __base__, _tp_object);
|
||||||
_tp_type->setType(_tp_type);
|
_tp_type->_type = _tp_type;
|
||||||
setAttr(_tp_object, __base__, None);
|
setAttr(_tp_object, __base__, None);
|
||||||
_tp_object->setType(_tp_type);
|
_tp_object->_type = _tp_type;
|
||||||
|
|
||||||
for (auto& [name, type] : _types) {
|
for (auto& [name, type] : _types) {
|
||||||
setAttr(type, __name__, PyStr(name));
|
setAttr(type, __name__, PyStr(name));
|
||||||
@ -4702,7 +4693,7 @@ public:
|
|||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
typeError("unhashable type: " + obj->getTypeName());
|
typeError("unhashable type: " + UNION_TP_NAME(obj));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4753,11 +4744,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void attributeError(PyVar obj, const _Str& name){
|
void attributeError(PyVar obj, const _Str& name){
|
||||||
_error("AttributeError", "type '" + obj->getTypeName() + "' has no attribute '" + name + "'");
|
_error("AttributeError", "type '" + UNION_TP_NAME(obj) + "' has no attribute '" + name + "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void __checkType(const PyVar& obj, const PyVar& type){
|
inline void __checkType(const PyVar& obj, const PyVar& type){
|
||||||
if(!obj->isType(type)) typeError("expected '" + type->getName() + "', but got '" + obj->getTypeName() + "'");
|
#ifndef PKPY_NO_TYPE_CHECK
|
||||||
|
if(!obj->isType(type)) typeError("expected '" + UNION_TP_NAME(type) + "', but got '" + UNION_TP_NAME(obj) + "'");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void __checkArgSize(const pkpy::ArgList& args, int size, bool method=false){
|
inline void __checkArgSize(const pkpy::ArgList& args, int size, bool method=false){
|
||||||
@ -4781,25 +4774,25 @@ public:
|
|||||||
/***** Pointers' Impl *****/
|
/***** Pointers' Impl *****/
|
||||||
|
|
||||||
PyVar NamePointer::get(VM* vm, Frame* frame) const{
|
PyVar NamePointer::get(VM* vm, Frame* frame) const{
|
||||||
auto it = frame->f_locals.find(name);
|
auto it = frame->f_locals.find(pair->first);
|
||||||
if(it != frame->f_locals.end()) return it->second;
|
if(it != frame->f_locals.end()) return it->second;
|
||||||
it = frame->f_globals().find(name);
|
it = frame->f_globals().find(pair->first);
|
||||||
if(it != frame->f_globals().end()) return it->second;
|
if(it != frame->f_globals().end()) return it->second;
|
||||||
it = vm->builtins->attribs.find(name);
|
it = vm->builtins->attribs.find(pair->first);
|
||||||
if(it != vm->builtins->attribs.end()) return it->second;
|
if(it != vm->builtins->attribs.end()) return it->second;
|
||||||
vm->nameError(name);
|
vm->nameError(pair->first);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NamePointer::set(VM* vm, Frame* frame, PyVar val) const{
|
void NamePointer::set(VM* vm, Frame* frame, PyVar val) const{
|
||||||
switch(scope) {
|
switch(pair->second) {
|
||||||
case NAME_LOCAL: frame->f_locals[name] = std::move(val); break;
|
case NAME_LOCAL: frame->f_locals[pair->first] = std::move(val); break;
|
||||||
case NAME_GLOBAL:
|
case NAME_GLOBAL:
|
||||||
{
|
{
|
||||||
if(frame->f_locals.count(name) > 0){
|
if(frame->f_locals.count(pair->first) > 0){
|
||||||
frame->f_locals[name] = std::move(val);
|
frame->f_locals[pair->first] = std::move(val);
|
||||||
}else{
|
}else{
|
||||||
frame->f_globals()[name] = std::move(val);
|
frame->f_globals()[pair->first] = std::move(val);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
default: UNREACHABLE();
|
default: UNREACHABLE();
|
||||||
@ -4807,23 +4800,23 @@ void NamePointer::set(VM* vm, Frame* frame, PyVar val) const{
|
|||||||
}
|
}
|
||||||
|
|
||||||
void NamePointer::del(VM* vm, Frame* frame) const{
|
void NamePointer::del(VM* vm, Frame* frame) const{
|
||||||
switch(scope) {
|
switch(pair->second) {
|
||||||
case NAME_LOCAL: {
|
case NAME_LOCAL: {
|
||||||
if(frame->f_locals.count(name) > 0){
|
if(frame->f_locals.count(pair->first) > 0){
|
||||||
frame->f_locals.erase(name);
|
frame->f_locals.erase(pair->first);
|
||||||
}else{
|
}else{
|
||||||
vm->nameError(name);
|
vm->nameError(pair->first);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case NAME_GLOBAL:
|
case NAME_GLOBAL:
|
||||||
{
|
{
|
||||||
if(frame->f_locals.count(name) > 0){
|
if(frame->f_locals.count(pair->first) > 0){
|
||||||
frame->f_locals.erase(name);
|
frame->f_locals.erase(pair->first);
|
||||||
}else{
|
}else{
|
||||||
if(frame->f_globals().count(name) > 0){
|
if(frame->f_globals().count(pair->first) > 0){
|
||||||
frame->f_globals().erase(name);
|
frame->f_globals().erase(pair->first);
|
||||||
}else{
|
}else{
|
||||||
vm->nameError(name);
|
vm->nameError(pair->first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@ -4832,11 +4825,11 @@ void NamePointer::del(VM* vm, Frame* frame) const{
|
|||||||
}
|
}
|
||||||
|
|
||||||
PyVar AttrPointer::get(VM* vm, Frame* frame) const{
|
PyVar AttrPointer::get(VM* vm, Frame* frame) const{
|
||||||
return vm->getAttr(obj, attr->name);
|
return vm->getAttr(obj, attr.pair->first);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttrPointer::set(VM* vm, Frame* frame, PyVar val) const{
|
void AttrPointer::set(VM* vm, Frame* frame, PyVar val) const{
|
||||||
vm->setAttr(obj, attr->name, val);
|
vm->setAttr(obj, attr.pair->first, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttrPointer::del(VM* vm, Frame* frame) const{
|
void AttrPointer::del(VM* vm, Frame* frame) const{
|
||||||
@ -4856,9 +4849,9 @@ void IndexPointer::del(VM* vm, Frame* frame) const{
|
|||||||
}
|
}
|
||||||
|
|
||||||
PyVar CompoundPointer::get(VM* vm, Frame* frame) const{
|
PyVar CompoundPointer::get(VM* vm, Frame* frame) const{
|
||||||
PyVarList args(pointers.size());
|
PyVarList args(varRefs.size());
|
||||||
for (int i = 0; i < pointers.size(); i++) {
|
for (int i = 0; i < varRefs.size(); i++) {
|
||||||
args[i] = pointers[i]->get(vm, frame);
|
args[i] = vm->PyPointer_AS_C(varRefs[i])->get(vm, frame);
|
||||||
}
|
}
|
||||||
return vm->PyTuple(args);
|
return vm->PyTuple(args);
|
||||||
}
|
}
|
||||||
@ -4867,28 +4860,28 @@ void CompoundPointer::set(VM* vm, Frame* frame, PyVar val) const{
|
|||||||
if(!val->isType(vm->_tp_tuple) && !val->isType(vm->_tp_list)){
|
if(!val->isType(vm->_tp_tuple) && !val->isType(vm->_tp_list)){
|
||||||
vm->typeError("only tuple or list can be unpacked");
|
vm->typeError("only tuple or list can be unpacked");
|
||||||
}
|
}
|
||||||
const PyVarList& args = std::get<PyVarList>(val->_native);
|
const PyVarList& args = UNION_GET(PyVarList, val);
|
||||||
if(args.size() > pointers.size()) vm->valueError("too many values to unpack");
|
if(args.size() > varRefs.size()) vm->valueError("too many values to unpack");
|
||||||
if(args.size() < pointers.size()) vm->valueError("not enough values to unpack");
|
if(args.size() < varRefs.size()) vm->valueError("not enough values to unpack");
|
||||||
for (int i = 0; i < pointers.size(); i++) {
|
for (int i = 0; i < varRefs.size(); i++) {
|
||||||
pointers[i]->set(vm, frame, args[i]);
|
vm->PyPointer_AS_C(varRefs[i])->set(vm, frame, args[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompoundPointer::del(VM* vm, Frame* frame) const{
|
void CompoundPointer::del(VM* vm, Frame* frame) const{
|
||||||
for (auto& ptr : pointers) ptr->del(vm, frame);
|
for (auto& r : varRefs) vm->PyPointer_AS_C(r)->del(vm, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyVar UserPointer::get(VM* vm, Frame* frame) const{
|
PyVar UserPointer::get(VM* vm, Frame* frame) const{
|
||||||
frame = vm->__findFrame(f_id);
|
frame = vm->__findFrame(f_id);
|
||||||
if(frame == nullptr) vm->nullPointerError();
|
if(frame == nullptr) vm->nullPointerError();
|
||||||
return p->get(vm, frame);
|
return vm->PyPointer_AS_C(p)->get(vm, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserPointer::set(VM* vm, Frame* frame, PyVar val) const{
|
void UserPointer::set(VM* vm, Frame* frame, PyVar val) const{
|
||||||
frame = vm->__findFrame(f_id);
|
frame = vm->__findFrame(f_id);
|
||||||
if(frame == nullptr) vm->nullPointerError();
|
if(frame == nullptr) vm->nullPointerError();
|
||||||
p->set(vm, frame, val);
|
vm->PyPointer_AS_C(p)->set(vm, frame, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserPointer::del(VM* vm, Frame* frame) const{
|
void UserPointer::del(VM* vm, Frame* frame) const{
|
||||||
@ -5144,7 +5137,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void eatNumber() {
|
void eatNumber() {
|
||||||
static const std::regex pattern("^(0x)?[0-9a-f]+(\\.[0-9]+)?");
|
static const std::regex pattern("^(0x)?[0-9a-fA-F]+(\\.[0-9]+)?");
|
||||||
std::smatch m;
|
std::smatch m;
|
||||||
|
|
||||||
const char* i = parser->token_start;
|
const char* i = parser->token_start;
|
||||||
@ -6029,15 +6022,13 @@ _Code compile(VM* vm, const char* source, _Str filename, CompileMode mode=EXEC_M
|
|||||||
if(!noThrow) return compiler.__fillCode();
|
if(!noThrow) return compiler.__fillCode();
|
||||||
try{
|
try{
|
||||||
return compiler.__fillCode();
|
return compiler.__fillCode();
|
||||||
|
}catch(_Error& e){
|
||||||
|
(*vm->_stderr) << e.what() << '\n';
|
||||||
}catch(std::exception& e){
|
}catch(std::exception& e){
|
||||||
if(dynamic_cast<const _Error*>(&e)){
|
auto ce = CompileError("UnexpectedError", e.what(), compiler.getLineSnapshot());
|
||||||
(*vm->_stderr) << e.what() << '\n';
|
(*vm->_stderr) << ce.what() << '\n';
|
||||||
}else{
|
|
||||||
auto ce = CompileError("UnexpectedError", e.what(), compiler.getLineSnapshot());
|
|
||||||
(*vm->_stderr) << ce.what() << '\n';
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -6228,7 +6219,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
|||||||
|
|
||||||
_vm->bindMethod("object", "__repr__", [](VM* vm, const pkpy::ArgList& args) {
|
_vm->bindMethod("object", "__repr__", [](VM* vm, const pkpy::ArgList& args) {
|
||||||
PyVar _self = args[0];
|
PyVar _self = args[0];
|
||||||
_Str s = "<" + _self->getTypeName() + " object at " + std::to_string((uintptr_t)_self.get()) + ">";
|
_Str s = "<" + UNION_TP_NAME(_self) + " object at " + std::to_string((uintptr_t)_self.get()) + ">";
|
||||||
return vm->PyStr(s);
|
return vm->PyStr(s);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -6251,7 +6242,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
|||||||
_vm->bindMethod("range", "__iter__", [](VM* vm, const pkpy::ArgList& args) {
|
_vm->bindMethod("range", "__iter__", [](VM* vm, const pkpy::ArgList& args) {
|
||||||
vm->__checkType(args[0], vm->_tp_range);
|
vm->__checkType(args[0], vm->_tp_range);
|
||||||
return vm->PyIter(
|
return vm->PyIter(
|
||||||
pkpy::make_shared<_Iterator, RangeIterator>(vm, args[0])
|
pkpy::make_shared<BaseIterator, RangeIterator>(vm, args[0])
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -6295,7 +6286,9 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
|||||||
if (args[0]->isType(vm->_tp_str)) {
|
if (args[0]->isType(vm->_tp_str)) {
|
||||||
const _Str& s = vm->PyStr_AS_C(args[0]);
|
const _Str& s = vm->PyStr_AS_C(args[0]);
|
||||||
try{
|
try{
|
||||||
_Int val = std::stoll(s.str());
|
size_t parsed = 0;
|
||||||
|
_Int val = std::stoll(s.str(), &parsed, 10);
|
||||||
|
if(parsed != s.str().size()) throw std::invalid_argument("");
|
||||||
return vm->PyInt(val);
|
return vm->PyInt(val);
|
||||||
}catch(std::invalid_argument&){
|
}catch(std::invalid_argument&){
|
||||||
vm->valueError("invalid literal for int(): '" + s + "'");
|
vm->valueError("invalid literal for int(): '" + s + "'");
|
||||||
@ -6417,7 +6410,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
|||||||
|
|
||||||
_vm->bindMethod("str", "__iter__", [](VM* vm, const pkpy::ArgList& args) {
|
_vm->bindMethod("str", "__iter__", [](VM* vm, const pkpy::ArgList& args) {
|
||||||
return vm->PyIter(
|
return vm->PyIter(
|
||||||
pkpy::make_shared<_Iterator, StringIterator>(vm, args[0])
|
pkpy::make_shared<BaseIterator, StringIterator>(vm, args[0])
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -6531,7 +6524,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
|||||||
_vm->bindMethod("list", "__iter__", [](VM* vm, const pkpy::ArgList& args) {
|
_vm->bindMethod("list", "__iter__", [](VM* vm, const pkpy::ArgList& args) {
|
||||||
vm->__checkType(args[0], vm->_tp_list);
|
vm->__checkType(args[0], vm->_tp_list);
|
||||||
return vm->PyIter(
|
return vm->PyIter(
|
||||||
pkpy::make_shared<_Iterator, VectorIterator>(vm, args[0])
|
pkpy::make_shared<BaseIterator, VectorIterator>(vm, args[0])
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -6629,7 +6622,7 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
|||||||
_vm->bindMethod("tuple", "__iter__", [](VM* vm, const pkpy::ArgList& args) {
|
_vm->bindMethod("tuple", "__iter__", [](VM* vm, const pkpy::ArgList& args) {
|
||||||
vm->__checkType(args[0], vm->_tp_tuple);
|
vm->__checkType(args[0], vm->_tp_tuple);
|
||||||
return vm->PyIter(
|
return vm->PyIter(
|
||||||
pkpy::make_shared<_Iterator, VectorIterator>(vm, args[0])
|
pkpy::make_shared<BaseIterator, VectorIterator>(vm, args[0])
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -6952,8 +6945,8 @@ extern "C" {
|
|||||||
/// Return a json representing the result.
|
/// Return a json representing the result.
|
||||||
char* pkpy_vm_read_output(VM* vm){
|
char* pkpy_vm_read_output(VM* vm){
|
||||||
if(vm->use_stdio) return nullptr;
|
if(vm->use_stdio) return nullptr;
|
||||||
_StrStream* s_out = dynamic_cast<_StrStream*>(vm->_stdout);
|
_StrStream* s_out = (_StrStream*)(vm->_stdout);
|
||||||
_StrStream* s_err = dynamic_cast<_StrStream*>(vm->_stderr);
|
_StrStream* s_err = (_StrStream*)(vm->_stderr);
|
||||||
_Str _stdout = s_out->str();
|
_Str _stdout = s_out->str();
|
||||||
_Str _stderr = s_err->str();
|
_Str _stderr = s_err->str();
|
||||||
_StrStream ss;
|
_StrStream ss;
|
||||||
|
@ -142,7 +142,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void eatNumber() {
|
void eatNumber() {
|
||||||
static const std::regex pattern("^(0x)?[0-9a-f]+(\\.[0-9]+)?");
|
static const std::regex pattern("^(0x)?[0-9a-fA-F]+(\\.[0-9]+)?");
|
||||||
std::smatch m;
|
std::smatch m;
|
||||||
|
|
||||||
const char* i = parser->token_start;
|
const char* i = parser->token_start;
|
||||||
|
@ -193,7 +193,9 @@ void __initializeBuiltinFunctions(VM* _vm) {
|
|||||||
if (args[0]->isType(vm->_tp_str)) {
|
if (args[0]->isType(vm->_tp_str)) {
|
||||||
const _Str& s = vm->PyStr_AS_C(args[0]);
|
const _Str& s = vm->PyStr_AS_C(args[0]);
|
||||||
try{
|
try{
|
||||||
_Int val = std::stoll(s.str());
|
size_t parsed = 0;
|
||||||
|
_Int val = std::stoll(s.str(), &parsed, 10);
|
||||||
|
if(parsed != s.str().size()) throw std::invalid_argument("");
|
||||||
return vm->PyInt(val);
|
return vm->PyInt(val);
|
||||||
}catch(std::invalid_argument&){
|
}catch(std::invalid_argument&){
|
||||||
vm->valueError("invalid literal for int(): '" + s + "'");
|
vm->valueError("invalid literal for int(): '" + s + "'");
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
# generate assert test for int
|
# generate assert test for int
|
||||||
|
|
||||||
|
assert 0xffff == 65535
|
||||||
|
assert 0xAAFFFF == 11206655
|
||||||
|
assert 0x7fffffff == 2147483647
|
||||||
|
|
||||||
# test == != >= <= < >
|
# test == != >= <= < >
|
||||||
# generate 2 cases for each operator
|
# generate 2 cases for each operator
|
||||||
assert -1 == -1
|
assert -1 == -1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user