mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
some ptr impl
This commit is contained in:
parent
978e04cdfd
commit
0a2453a20a
78
src/cffi.h
78
src/cffi.h
@ -9,13 +9,16 @@ namespace pkpy {
|
|||||||
|
|
||||||
template<typename Ret, typename... Params>
|
template<typename Ret, typename... Params>
|
||||||
struct NativeProxyFunc {
|
struct NativeProxyFunc {
|
||||||
using T = Ret(*)(Params...);
|
//using T = Ret(*)(Params...);
|
||||||
|
using T = std::function<Ret(Params...)>;
|
||||||
static constexpr int N = sizeof...(Params);
|
static constexpr int N = sizeof...(Params);
|
||||||
T func;
|
T func;
|
||||||
NativeProxyFunc(T func) : func(func) {}
|
NativeProxyFunc(T func) : func(func) {}
|
||||||
|
|
||||||
PyVar operator()(VM* vm, Args& args) {
|
PyVar operator()(VM* vm, Args& args) {
|
||||||
if (args.size() != N) vm->TypeError("invalid number of arguments");
|
if (args.size() != N) {
|
||||||
|
vm->TypeError("expected " + std::to_string(N) + " arguments, but got " + std::to_string(args.size()));
|
||||||
|
}
|
||||||
return call<Ret>(vm, args, std::make_index_sequence<N>());
|
return call<Ret>(vm, args, std::make_index_sequence<N>());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,31 +102,27 @@ auto _ = [](){
|
|||||||
return 0;
|
return 0;
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
|
||||||
struct Pointer{
|
struct Pointer{
|
||||||
PY_CLASS(Pointer, c, ptr_)
|
PY_CLASS(Pointer, c, ptr_)
|
||||||
|
|
||||||
|
const TypeInfo* ctype; // this is immutable
|
||||||
|
int level; // level of pointer
|
||||||
char* ptr;
|
char* ptr;
|
||||||
TypeInfo* ctype;
|
|
||||||
int level; // level of pointer
|
|
||||||
|
|
||||||
i64 unit_size() const {
|
i64 unit_size() const {
|
||||||
return level == 1 ? ctype->size : sizeof(void*);
|
return level == 1 ? ctype->size : sizeof(void*);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool type_equal(const Pointer& other) const {
|
Pointer() : ctype(&_type_infos["void"]), level(1), ptr(nullptr) {}
|
||||||
return level == other.level && ctype == other.ctype;
|
Pointer(const TypeInfo* ctype, int level, char* ptr): ctype(ctype), level(level), ptr(ptr) {}
|
||||||
}
|
Pointer(const TypeInfo* ctype, char* ptr): ctype(ctype), level(1), ptr(ptr) {}
|
||||||
|
|
||||||
Pointer() : ptr(nullptr), ctype(&_type_infos["void"]), level(1) {}
|
|
||||||
Pointer(char* ptr, TypeInfo* ctype, int level=1) : ptr(ptr), ctype(ctype), level(level) {}
|
|
||||||
|
|
||||||
Pointer operator+(i64 offset) const {
|
Pointer operator+(i64 offset) const {
|
||||||
return Pointer(ptr + offset * unit_size(), ctype, level);
|
return Pointer(ctype, level, ptr+offset*unit_size());
|
||||||
}
|
}
|
||||||
|
|
||||||
Pointer operator-(i64 offset) const {
|
Pointer operator-(i64 offset) const {
|
||||||
return Pointer(ptr - offset * unit_size(), ctype, level);
|
return Pointer(ctype, level, ptr-offset*unit_size());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _register(VM* vm, PyVar mod, PyVar type){
|
static void _register(VM* vm, PyVar mod, PyVar type){
|
||||||
@ -173,6 +172,12 @@ struct Pointer{
|
|||||||
return vm->None;
|
return vm->None;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
vm->bind_method<1>(type, "__getattr__", [](VM* vm, Args& args) {
|
||||||
|
Pointer& self = CAST(Pointer&, args[0]);
|
||||||
|
const Str& name = CAST(Str&, args[1]);
|
||||||
|
return VAR_T(Pointer, self._to(vm, name));
|
||||||
|
});
|
||||||
|
|
||||||
vm->bind_method<0>(type, "get", [](VM* vm, Args& args) {
|
vm->bind_method<0>(type, "get", [](VM* vm, Args& args) {
|
||||||
Pointer& self = CAST(Pointer&, args[0]);
|
Pointer& self = CAST(Pointer&, args[0]);
|
||||||
return self.get(vm);
|
return self.get(vm);
|
||||||
@ -183,13 +188,28 @@ struct Pointer{
|
|||||||
self.set(vm, args[1]);
|
self.set(vm, args[1]);
|
||||||
return vm->None;
|
return vm->None;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
vm->bind_method<1>(type, "cast", [](VM* vm, Args& args) {
|
||||||
|
Pointer& self = CAST(Pointer&, args[0]);
|
||||||
|
const Str& name = CAST(Str&, args[1]);
|
||||||
|
int level = 0;
|
||||||
|
for(int i=name.size()-1; i>=0; i--){
|
||||||
|
if(name[i] == '*') level++;
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
if(level == 0) vm->TypeError("expect a pointer type, such as 'int*'");
|
||||||
|
Str type = name.substr(0, name.size()-level);
|
||||||
|
auto it = _type_infos.find(type);
|
||||||
|
if(it == _type_infos.end()) vm->TypeError("unknown type: " + type.escape(true));
|
||||||
|
return VAR_T(Pointer, &it->second, level, self.ptr);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline T& ref() noexcept { return *reinterpret_cast<T*>(ptr); }
|
inline T& ref() noexcept { return *reinterpret_cast<T*>(ptr); }
|
||||||
|
|
||||||
PyVar get(VM* vm){
|
PyVar get(VM* vm){
|
||||||
if(level > 1) return VAR_T(Pointer, ptr, ctype, level-1);
|
if(level > 1) return VAR_T(Pointer, ctype, level-1, ref<char*>());
|
||||||
switch(ctype->index){
|
switch(ctype->index){
|
||||||
#define CASE(T) case type_index<T>(): return VAR(ref<T>())
|
#define CASE(T) case type_index<T>(): return VAR(ref<T>())
|
||||||
case type_index<void>(): vm->ValueError("cannot get void*"); break;
|
case type_index<void>(): vm->ValueError("cannot get void*"); break;
|
||||||
@ -214,7 +234,7 @@ struct Pointer{
|
|||||||
void set(VM* vm, const PyVar& val){
|
void set(VM* vm, const PyVar& val){
|
||||||
if(level > 1) {
|
if(level > 1) {
|
||||||
Pointer& p = CAST(Pointer&, val);
|
Pointer& p = CAST(Pointer&, val);
|
||||||
ref<void*>() = p.ptr; // We don't check the type, just copy the underlying address
|
ref<char*>() = p.ptr; // We don't check the type, just copy the underlying address
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch(ctype->index){
|
switch(ctype->index){
|
||||||
@ -234,17 +254,17 @@ struct Pointer{
|
|||||||
CASE(double, f64);
|
CASE(double, f64);
|
||||||
CASE(bool, bool);
|
CASE(bool, bool);
|
||||||
#undef CASE
|
#undef CASE
|
||||||
|
default: UNREACHABLE();
|
||||||
}
|
}
|
||||||
UNREACHABLE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Pointer address(VM* vm, StrName name){
|
Pointer _to(VM* vm, StrName name){
|
||||||
auto it = ctype->members.find(name);
|
auto it = ctype->members.find(name);
|
||||||
if(it == ctype->members.end()){
|
if(it == ctype->members.end()){
|
||||||
vm->AttributeError(Str("struct '") + ctype->name + "' has no member " + name.str().escape(true));
|
vm->AttributeError(Str("struct '") + ctype->name + "' has no member " + name.str().escape(true));
|
||||||
}
|
}
|
||||||
MemberInfo& info = it->second;
|
const MemberInfo& info = it->second;
|
||||||
return {ptr+info.offset, info.type, level};
|
return {info.type, level, ptr+info.offset};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -255,12 +275,12 @@ struct Struct {
|
|||||||
char* data;
|
char* data;
|
||||||
Pointer head;
|
Pointer head;
|
||||||
|
|
||||||
TypeInfo* ctype() const { return head.ctype; }
|
const TypeInfo* ctype() const { return head.ctype; }
|
||||||
|
|
||||||
Struct(const Pointer& head) {
|
Struct(const Pointer& head) {
|
||||||
data = new char[head.ctype->size];
|
data = new char[head.ctype->size];
|
||||||
memcpy(data, head.ptr, head.ctype->size);
|
memcpy(data, head.ptr, head.ctype->size);
|
||||||
this->head = Pointer(data, head.ctype, head.level);
|
this->head = Pointer(head.ctype, head.level, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _register(VM* vm, PyVar mod, PyVar type){
|
static void _register(VM* vm, PyVar mod, PyVar type){
|
||||||
@ -280,11 +300,11 @@ void add_module_c(VM* vm){
|
|||||||
PyVar ptr_t = Pointer::register_class(vm, mod);
|
PyVar ptr_t = Pointer::register_class(vm, mod);
|
||||||
Struct::register_class(vm, mod);
|
Struct::register_class(vm, mod);
|
||||||
|
|
||||||
vm->setattr(mod, "nullptr", VAR_T(Pointer, nullptr, &_type_infos["void"]));
|
vm->setattr(mod, "nullptr", VAR_T(Pointer));
|
||||||
|
|
||||||
vm->bind_func<1>(mod, "malloc", [](VM* vm, Args& args) {
|
vm->bind_func<1>(mod, "malloc", [](VM* vm, Args& args) {
|
||||||
i64 size = CAST(i64, args[0]);
|
i64 size = CAST(i64, args[0]);
|
||||||
return VAR_T(Pointer, (char*)malloc(size), &_type_infos["void"]);
|
return VAR_T(Pointer, &_type_infos["void"], (char*)malloc(size));
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind_func<1>(mod, "free", [](VM* vm, Args& args) {
|
vm->bind_func<1>(mod, "free", [](VM* vm, Args& args) {
|
||||||
@ -301,6 +321,14 @@ void add_module_c(VM* vm){
|
|||||||
return vm->None;
|
return vm->None;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
vm->bind_func<1>(mod, "sizeof", [](VM* vm, Args& args) {
|
||||||
|
const Str& name = CAST(Str&, args[0]);
|
||||||
|
if(name.find('*') != Str::npos) return VAR(sizeof(void*));
|
||||||
|
auto it = _type_infos.find(name);
|
||||||
|
if(it == _type_infos.end()) vm->TypeError("unknown type: " + name.escape(true));
|
||||||
|
return VAR(it->second.size);
|
||||||
|
});
|
||||||
|
|
||||||
vm->bind_func<3>(mod, "memset", [](VM* vm, Args& args) {
|
vm->bind_func<3>(mod, "memset", [](VM* vm, Args& args) {
|
||||||
Pointer& dst = CAST(Pointer&, args[0]);
|
Pointer& dst = CAST(Pointer&, args[0]);
|
||||||
i64 val = CAST(i64, args[1]);
|
i64 val = CAST(i64, args[1]);
|
||||||
@ -311,11 +339,11 @@ void add_module_c(VM* vm){
|
|||||||
}
|
}
|
||||||
|
|
||||||
PyVar py_var(VM* vm, void* p){
|
PyVar py_var(VM* vm, void* p){
|
||||||
return VAR_T(Pointer, (char*)p, &_type_infos["void"]);
|
return VAR_T(Pointer, &_type_infos["void"], (char*)p);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyVar py_var(VM* vm, char* p){
|
PyVar py_var(VM* vm, char* p){
|
||||||
return VAR_T(Pointer, (char*)p, &_type_infos["char"]);
|
return VAR_T(Pointer, &_type_infos["char"], (char*)p);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace pkpy
|
} // namespace pkpy
|
@ -28,7 +28,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
#define PK_VERSION "0.9.1"
|
#define PK_VERSION "0.9.2"
|
||||||
|
|
||||||
#if defined(__EMSCRIPTEN__) || defined(__arm__) || defined(__i386__)
|
#if defined(__EMSCRIPTEN__) || defined(__arm__) || defined(__i386__)
|
||||||
typedef int32_t i64;
|
typedef int32_t i64;
|
||||||
|
26
src/str.h
26
src/str.h
@ -20,6 +20,8 @@ class Str : public std::string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
|
uint16_t _cached_sn_index = 0;
|
||||||
|
|
||||||
Str() : std::string() {}
|
Str() : std::string() {}
|
||||||
Str(const char* s) : std::string(s) {}
|
Str(const char* s) : std::string(s) {}
|
||||||
Str(const char* s, size_t n) : std::string(s, n) {}
|
Str(const char* s, size_t n) : std::string(s, n) {}
|
||||||
@ -139,30 +141,36 @@ struct StrName {
|
|||||||
StrName(): index(0) {}
|
StrName(): index(0) {}
|
||||||
StrName(uint16_t index): index(index) {}
|
StrName(uint16_t index): index(index) {}
|
||||||
StrName(const char* s): index(get(s).index) {}
|
StrName(const char* s): index(get(s).index) {}
|
||||||
StrName(const Str& s): index(get(s).index) {}
|
StrName(const Str& s){
|
||||||
inline const Str& str() const { return _r_interned[index-1]; }
|
if(s._cached_sn_index != 0){
|
||||||
inline bool empty() const { return index == 0; }
|
index = s._cached_sn_index;
|
||||||
|
} else {
|
||||||
|
index = get(s).index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const Str& str() const { return _r_interned[index-1]; }
|
||||||
|
bool empty() const { return index == 0; }
|
||||||
|
|
||||||
inline bool operator==(const StrName& other) const noexcept {
|
bool operator==(const StrName& other) const noexcept {
|
||||||
return this->index == other.index;
|
return this->index == other.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator!=(const StrName& other) const noexcept {
|
bool operator!=(const StrName& other) const noexcept {
|
||||||
return this->index != other.index;
|
return this->index != other.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator<(const StrName& other) const noexcept {
|
bool operator<(const StrName& other) const noexcept {
|
||||||
return this->index < other.index;
|
return this->index < other.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator>(const StrName& other) const noexcept {
|
bool operator>(const StrName& other) const noexcept {
|
||||||
return this->index > other.index;
|
return this->index > other.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::map<Str, uint16_t, std::less<>> _interned;
|
static std::map<Str, uint16_t, std::less<>> _interned;
|
||||||
static std::vector<Str> _r_interned;
|
static std::vector<Str> _r_interned;
|
||||||
|
|
||||||
inline static StrName get(const Str& s){
|
static StrName get(const Str& s){
|
||||||
return get(s.c_str());
|
return get(s.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,6 +202,8 @@ const StrName __json__ = StrName::get("__json__");
|
|||||||
const StrName __name__ = StrName::get("__name__");
|
const StrName __name__ = StrName::get("__name__");
|
||||||
const StrName __len__ = StrName::get("__len__");
|
const StrName __len__ = StrName::get("__len__");
|
||||||
const StrName __get__ = StrName::get("__get__");
|
const StrName __get__ = StrName::get("__get__");
|
||||||
|
const StrName __getattr__ = StrName::get("__getattr__");
|
||||||
|
const StrName __setattr__ = StrName::get("__setattr__");
|
||||||
|
|
||||||
const StrName m_eval = StrName::get("eval");
|
const StrName m_eval = StrName::get("eval");
|
||||||
const StrName m_self = StrName::get("self");
|
const StrName m_self = StrName::get("self");
|
||||||
|
16
src/vm.h
16
src/vm.h
@ -359,6 +359,14 @@ void CodeObject::optimize(VM* vm){
|
|||||||
codes[i-2].op = OP_NO_OP;
|
codes[i-2].op = OP_NO_OP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pre-compute sn in co_consts
|
||||||
|
for(int i=0; i<consts.size(); i++){
|
||||||
|
if(is_type(consts[i], vm->tp_str)){
|
||||||
|
Str& s = OBJ_GET(Str, consts[i]);
|
||||||
|
s._cached_sn_index = StrName::get(s.c_str()).index;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF_NATIVE_2(Str, tp_str)
|
DEF_NATIVE_2(Str, tp_str)
|
||||||
@ -765,7 +773,7 @@ PyVarOrNull VM::getattr(const PyVar& obj, StrName name, bool throw_err, bool cla
|
|||||||
|
|
||||||
if(!class_only){
|
if(!class_only){
|
||||||
val = (*root)->attr().try_get(name);
|
val = (*root)->attr().try_get(name);
|
||||||
if(val != nullptr) return *val;
|
if(val != nullptr) return *val;
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
if(!class_only && !obj.is_tagged() && obj->is_attr_valid()){
|
if(!class_only && !obj.is_tagged() && obj->is_attr_valid()){
|
||||||
@ -785,6 +793,12 @@ PyVarOrNull VM::getattr(const PyVar& obj, StrName name, bool throw_err, bool cla
|
|||||||
}else{
|
}else{
|
||||||
return *val;
|
return *val;
|
||||||
}
|
}
|
||||||
|
}else{
|
||||||
|
// this operation is expensive!!!
|
||||||
|
PyVar* interceptor = cls->attr().try_get(__getattr__);
|
||||||
|
if(interceptor != nullptr){
|
||||||
|
return call(*interceptor, two_args(obj, VAR(name.str())));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cls = cls->attr(__base__).get();
|
cls = cls->attr(__base__).get();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user