mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20:18 +00:00
some move
This commit is contained in:
parent
6791c0c81e
commit
26815fae74
@ -1,5 +1,8 @@
|
||||
-Wall
|
||||
-W*
|
||||
-xc++
|
||||
|
||||
-std=c++17
|
||||
|
||||
-Iinclude/
|
||||
-I3rd/cjson/include/
|
||||
|
@ -11,7 +11,7 @@ extern "C" {
|
||||
#define SMALLMAP_T__HEADER
|
||||
#define K uint16_t
|
||||
#define V int
|
||||
#define TAG n2i
|
||||
#define NAME c11_smallmap_n2i
|
||||
#include "pocketpy/xmacros/smallmap.h"
|
||||
#undef SMALLMAP_T__HEADER
|
||||
|
||||
@ -19,7 +19,7 @@ extern "C" {
|
||||
#define SMALLMAP_T__HEADER
|
||||
#define K c11_string
|
||||
#define V uint16_t
|
||||
#define TAG s2n
|
||||
#define NAME c11_smallmap_s2n
|
||||
#define less(a, b) (c11_string__cmp((a), (b)) < 0)
|
||||
#define equal(a, b) (c11_string__cmp((a), (b)) == 0)
|
||||
#include "pocketpy/xmacros/smallmap.h"
|
||||
|
@ -39,7 +39,7 @@ struct VoidP {
|
||||
#define POINTER_VAR(Tp, NAME) \
|
||||
inline PyVar py_var(VM* vm, Tp val) { \
|
||||
const static pair<StrName, StrName> P("c", NAME); \
|
||||
PyVar type = vm->_modules[P.first]->attr(P.second); \
|
||||
PyVar type = vm->_modules[P.first]->attr()[P.second]; \
|
||||
return vm->new_object<VoidP>(type->as<Type>(), val); \
|
||||
}
|
||||
|
||||
|
@ -218,11 +218,11 @@ public:
|
||||
constexpr static Type tp_none_type = Type(kTpNoneTypeIndex), tp_not_implemented_type = Type(kTpNotImplementedTypeIndex);
|
||||
constexpr static Type tp_ellipsis = Type(26);
|
||||
|
||||
constexpr static PyVar True{const_sso_var(), tp_bool, 1};
|
||||
constexpr static PyVar False{const_sso_var(), tp_bool, 0};
|
||||
constexpr static PyVar None{const_sso_var(), tp_none_type, 0};
|
||||
constexpr static PyVar NotImplemented{const_sso_var(), tp_not_implemented_type, 0};
|
||||
constexpr static PyVar Ellipsis{const_sso_var(), tp_ellipsis, 0};
|
||||
inline static PyVar True = pkpy_True;
|
||||
inline static PyVar False = pkpy_False;
|
||||
inline static PyVar None = pkpy_None;
|
||||
inline static PyVar NotImplemented = pkpy_NotImplemented;
|
||||
inline static PyVar Ellipsis = pkpy_Ellipsis;
|
||||
|
||||
const bool enable_os;
|
||||
VM(bool enable_os = true);
|
||||
@ -242,7 +242,7 @@ public:
|
||||
List py_list(PyVar); // x -> list(x)
|
||||
bool py_callable(PyVar obj); // x -> callable(x)
|
||||
bool py_bool(PyVar obj){ // x -> bool(x)
|
||||
if(obj.type == tp_bool) return obj._0;
|
||||
if(obj.type == tp_bool) return obj._bool;
|
||||
return __py_bool_non_trivial(obj);
|
||||
}
|
||||
i64 py_hash(PyVar obj); // x -> hash(x)
|
||||
|
77
include/pocketpy/objects/base.h
Normal file
77
include/pocketpy/objects/base.h
Normal file
@ -0,0 +1,77 @@
|
||||
#pragma once
|
||||
|
||||
#include "stdint.h"
|
||||
#include "stdbool.h"
|
||||
#include "stdlib.h"
|
||||
#include "assert.h"
|
||||
#include "string.h"
|
||||
|
||||
#include "pocketpy/common/utils.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef int16_t pkpy_Type;
|
||||
|
||||
typedef struct PyObject PyObject;
|
||||
|
||||
typedef struct PyVar{
|
||||
pkpy_Type type;
|
||||
bool is_ptr;
|
||||
uint8_t flags;
|
||||
int flags_ex;
|
||||
union {
|
||||
int64_t _i64;
|
||||
double _f64;
|
||||
bool _bool;
|
||||
PyObject* _obj;
|
||||
void* _ptr;
|
||||
// Vec2
|
||||
};
|
||||
} PyVar;
|
||||
|
||||
static_assert(sizeof(PyVar) == 16, "sizeof(PyVar) != 16");
|
||||
|
||||
PK_INLINE bool PyVar__is_null(const PyVar* self) { return self->type == 0; }
|
||||
PK_INLINE PyObject* PyVar__get(const PyVar* self) { return self->_obj; }
|
||||
PK_INLINE int64_t PyVar__hash(const PyVar* self) { return self->flags_ex + self->_i64; }
|
||||
|
||||
PK_INLINE bool PyVar__less(const PyVar* self, const PyVar* other){
|
||||
return memcmp(self, other, sizeof(PyVar)) < 0;
|
||||
}
|
||||
PK_INLINE bool PyVar__equal(const PyVar* self, const PyVar* other){
|
||||
return memcmp(self, other, sizeof(PyVar)) == 0;
|
||||
}
|
||||
|
||||
PK_INLINE void PyVar__ctor(PyVar* self, pkpy_Type type, PyObject* obj){
|
||||
self->type = type;
|
||||
self->is_ptr = true;
|
||||
self->flags = 0;
|
||||
self->flags_ex = 0;
|
||||
self->_obj = obj;
|
||||
}
|
||||
|
||||
#define pkpy_Var__is_null(self) ((self)->type == 0)
|
||||
#define pkpy_Var__set_null(self) do { (self)->type = 0; } while(0)
|
||||
bool pkpy_Var__eq__(void *vm, PyVar a, PyVar b);
|
||||
int64_t pkpy_Var__hash__(void *vm, PyVar a);
|
||||
|
||||
extern const pkpy_Type tp_object, tp_type;
|
||||
extern const pkpy_Type tp_int, tp_float, tp_bool, tp_str;
|
||||
extern const pkpy_Type tp_list, tp_tuple;
|
||||
extern const pkpy_Type tp_slice, tp_range, tp_module;
|
||||
extern const pkpy_Type tp_function, tp_native_func, tp_bound_method;
|
||||
extern const pkpy_Type tp_super, tp_exception, tp_bytes, tp_mappingproxy;
|
||||
extern const pkpy_Type tp_dict, tp_property, tp_star_wrapper;
|
||||
extern const pkpy_Type tp_staticmethod, tp_classmethod;
|
||||
extern const pkpy_Type tp_none_type, tp_not_implemented_type;
|
||||
extern const pkpy_Type tp_ellipsis;
|
||||
|
||||
extern const PyVar pkpy_True, pkpy_False, pkpy_None;
|
||||
extern const PyVar pkpy_NotImplemented, pkpy_Ellipsis;
|
||||
extern const PyVar pkpy_NULL;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "pocketpy/common/types.hpp"
|
||||
#include "pocketpy/common/traits.hpp"
|
||||
#include "pocketpy/objects/base.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cassert>
|
||||
@ -11,29 +12,15 @@
|
||||
namespace pkpy {
|
||||
|
||||
struct Type {
|
||||
int16_t index;
|
||||
|
||||
pkpy_Type index;
|
||||
constexpr Type() : index(0) {}
|
||||
|
||||
explicit constexpr Type(int index) : index(index) {}
|
||||
|
||||
constexpr Type(pkpy_Type index) : index(index) {}
|
||||
bool operator== (Type other) const { return this->index == other.index; }
|
||||
|
||||
bool operator!= (Type other) const { return this->index != other.index; }
|
||||
|
||||
constexpr operator int () const { return index; }
|
||||
constexpr operator pkpy_Type () const { return index; }
|
||||
};
|
||||
|
||||
struct const_sso_var {};
|
||||
|
||||
struct PyVar final {
|
||||
Type type;
|
||||
bool is_ptr;
|
||||
uint8_t flags;
|
||||
// 12 bytes SSO
|
||||
int _0;
|
||||
i64 _1;
|
||||
|
||||
struct PyVar final: ::PyVar {
|
||||
// uninitialized
|
||||
PyVar() = default;
|
||||
|
||||
@ -41,20 +28,29 @@ struct PyVar final {
|
||||
PyVar(PyObject* p);
|
||||
|
||||
/* We must initialize all members to allow == operator to work correctly */
|
||||
// constexpr initialized
|
||||
constexpr PyVar(const const_sso_var&, Type type, int value) :
|
||||
type(type), is_ptr(false), flags(0), _0(value), _1(0) {}
|
||||
|
||||
// zero initialized
|
||||
constexpr PyVar(std::nullptr_t) : type(0), is_ptr(false), flags(0), _0(0), _1(0) {}
|
||||
PyVar(std::nullptr_t){
|
||||
set_null();
|
||||
}
|
||||
|
||||
// PyObject* initialized (is_sso = false)
|
||||
PyVar(Type type, PyObject* p) : type(type), is_ptr(true), flags(0), _0(0), _1(reinterpret_cast<i64>(p)) {}
|
||||
PyVar(Type type, PyObject* p){
|
||||
this->type = type;
|
||||
this->is_ptr = true;
|
||||
this->flags = 0;
|
||||
this->flags_ex = 0;
|
||||
this->_obj = (::PyObject*)p;
|
||||
}
|
||||
|
||||
// SSO initialized (is_sso = true)
|
||||
template <typename T>
|
||||
PyVar(Type type, T value) : type(type), is_ptr(false), flags(0), _0(0), _1(0) {
|
||||
PyVar(Type type, T value){
|
||||
static_assert(sizeof(T) <= 12, "SSO size exceeded");
|
||||
this->type = type;
|
||||
this->is_ptr = false;
|
||||
this->flags = 0;
|
||||
this->flags_ex = 0;
|
||||
this->_i64 = 0;
|
||||
as<T>() = value;
|
||||
}
|
||||
|
||||
@ -62,9 +58,9 @@ struct PyVar final {
|
||||
T& as() {
|
||||
static_assert(!std::is_reference_v<T>);
|
||||
if constexpr(sizeof(T) <= 8) {
|
||||
return reinterpret_cast<T&>(_1);
|
||||
return reinterpret_cast<T&>(_i64);
|
||||
} else {
|
||||
return reinterpret_cast<T&>(_0);
|
||||
return reinterpret_cast<T&>(flags_ex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,21 +85,26 @@ struct PyVar final {
|
||||
|
||||
PyObject* get() const {
|
||||
assert(is_ptr);
|
||||
return reinterpret_cast<PyObject*>(_1);
|
||||
return (PyObject*)_obj;
|
||||
}
|
||||
|
||||
PyObject* operator->() const {
|
||||
assert(is_ptr);
|
||||
return reinterpret_cast<PyObject*>(_1);
|
||||
return (PyObject*)_obj;
|
||||
}
|
||||
|
||||
i64 hash() const { return _0 + _1; }
|
||||
i64 hash() const { return PyVar__hash(this); }
|
||||
|
||||
template <typename T>
|
||||
obj_get_t<T> obj_get();
|
||||
|
||||
// std::less<> for map-like containers
|
||||
bool operator< (const PyVar& other) const { return memcmp(this, &other, sizeof(PyVar)) < 0; }
|
||||
|
||||
// implicit convert from ::PyVar
|
||||
PyVar(const ::PyVar& var) {
|
||||
memcpy(this, &var, sizeof(var));
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(PyVar) == 16 && is_pod_v<PyVar>);
|
||||
|
@ -82,13 +82,13 @@ const inline int16_t kTpNotImplementedTypeIndex = 25;
|
||||
|
||||
inline bool is_tagged(PyVar p) noexcept { return !p.is_ptr; }
|
||||
|
||||
inline bool is_float(PyVar p) noexcept { return p.type.index == kTpFloatIndex; }
|
||||
inline bool is_float(PyVar p) noexcept { return p.type == kTpFloatIndex; }
|
||||
|
||||
inline bool is_int(PyVar p) noexcept { return p.type.index == kTpIntIndex; }
|
||||
inline bool is_int(PyVar p) noexcept { return p.type == kTpIntIndex; }
|
||||
|
||||
inline bool is_none(PyVar p) noexcept { return p.type.index == kTpNoneTypeIndex; }
|
||||
inline bool is_none(PyVar p) noexcept { return p.type == kTpNoneTypeIndex; }
|
||||
|
||||
inline bool is_not_implemented(PyVar p) noexcept { return p.type.index == kTpNotImplementedTypeIndex; }
|
||||
inline bool is_not_implemented(PyVar p) noexcept { return p.type == kTpNotImplementedTypeIndex; }
|
||||
|
||||
inline bool is_type(PyVar obj, Type type) {
|
||||
assert(obj != nullptr);
|
||||
@ -121,7 +121,7 @@ obj_get_t<T> PyVar::obj_get() {
|
||||
return as<T>();
|
||||
} else {
|
||||
assert(is_ptr);
|
||||
void* v = ((PyObject*)_1)->_value_ptr();
|
||||
void* v = PyObject__value_ptr(_obj);
|
||||
return *reinterpret_cast<T*>(v);
|
||||
}
|
||||
}
|
||||
@ -139,9 +139,8 @@ obj_get_t<T> PyVar::obj_get() {
|
||||
#define CAST_DEFAULT(T, x, default_value) (x != vm->None) ? py_cast<T>(vm, x) : (default_value)
|
||||
|
||||
/*****************************************************************/
|
||||
|
||||
#define PY_NULL nullptr
|
||||
extern PyVar const PY_OP_CALL;
|
||||
extern const PyVar PY_OP_YIELD;
|
||||
extern PyVar PY_OP_CALL;
|
||||
extern PyVar PY_OP_YIELD;
|
||||
|
||||
} // namespace pkpy
|
||||
|
@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "pocketpy/objects/pyvar.h"
|
||||
#include "pocketpy/objects/base.h"
|
||||
#include "pocketpy/common/vector.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -49,7 +49,7 @@ pkpy_Dict pkpy_Dict__copy(const pkpy_Dict* self);
|
||||
* @param val value to set
|
||||
* @return `true` if the key is newly added, `false` if the key already exists
|
||||
*/
|
||||
bool pkpy_Dict__set(pkpy_Dict* self, void* vm, pkpy_Var key, pkpy_Var val);
|
||||
bool pkpy_Dict__set(pkpy_Dict* self, void* vm, PyVar key, PyVar val);
|
||||
|
||||
/**
|
||||
* @brief Check if a key exists in the `pkpy_Dict`
|
||||
@ -58,7 +58,7 @@ bool pkpy_Dict__set(pkpy_Dict* self, void* vm, pkpy_Var key, pkpy_Var val);
|
||||
* @param key key to check
|
||||
* @return `true` if the key exists, `false` otherwise
|
||||
*/
|
||||
bool pkpy_Dict__contains(const pkpy_Dict* self, void* vm, pkpy_Var key);
|
||||
bool pkpy_Dict__contains(const pkpy_Dict* self, void* vm, PyVar key);
|
||||
|
||||
/**
|
||||
* @brief Remove a key from the `pkpy_Dict`
|
||||
@ -67,7 +67,7 @@ bool pkpy_Dict__contains(const pkpy_Dict* self, void* vm, pkpy_Var key);
|
||||
* @param key key to remove
|
||||
* @return `true` if the key was found and removed, `false` if the key doesn't exist
|
||||
*/
|
||||
bool pkpy_Dict__del(pkpy_Dict* self, void* vm, pkpy_Var key);
|
||||
bool pkpy_Dict__del(pkpy_Dict* self, void* vm, PyVar key);
|
||||
|
||||
/**
|
||||
* @brief Try to get a value from the `pkpy_Dict`
|
||||
@ -76,7 +76,7 @@ bool pkpy_Dict__del(pkpy_Dict* self, void* vm, pkpy_Var key);
|
||||
* @param key key to get
|
||||
* @return the value associated with the key, `NULL` if the key doesn't exist
|
||||
*/
|
||||
const pkpy_Var* pkpy_Dict__try_get(const pkpy_Dict* self, void* vm, pkpy_Var key);
|
||||
const PyVar* pkpy_Dict__try_get(const pkpy_Dict* self, void* vm, PyVar key);
|
||||
|
||||
/**
|
||||
* @brief Update the `pkpy_Dict` with another one
|
||||
@ -106,7 +106,7 @@ pkpy_DictIter pkpy_Dict__iter(const pkpy_Dict* self);
|
||||
* @param value value will be filled with the current value, can be `NULL` if not needed
|
||||
* @return `true` if the iteration is still valid, `false` otherwise
|
||||
*/
|
||||
bool pkpy_DictIter__next(pkpy_DictIter* self, pkpy_Var* key, pkpy_Var* value);
|
||||
bool pkpy_DictIter__next(pkpy_DictIter* self, PyVar* key, PyVar* value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -28,21 +28,21 @@ struct Dict : private pkpy_Dict {
|
||||
int size() const { return count; }
|
||||
|
||||
void set(VM* vm, PyVar key, PyVar val) {
|
||||
pkpy_Dict__set(this, vm, *(pkpy_Var*)(&key), *(pkpy_Var*)(&val));
|
||||
pkpy_Dict__set(this, vm, *(::PyVar*)(&key), *(::PyVar*)(&val));
|
||||
}
|
||||
|
||||
PyVar try_get(VM* vm, PyVar key) const {
|
||||
auto res = pkpy_Dict__try_get(this, vm, *(pkpy_Var*)(&key));
|
||||
auto res = pkpy_Dict__try_get(this, vm, *(::PyVar*)(&key));
|
||||
if (!res) return nullptr;
|
||||
return *(const PyVar*)(res);
|
||||
}
|
||||
|
||||
bool contains(VM* vm, PyVar key) const {
|
||||
return pkpy_Dict__contains(this, vm, *(pkpy_Var*)(&key));
|
||||
return pkpy_Dict__contains(this, vm, *(::PyVar*)(&key));
|
||||
}
|
||||
|
||||
bool del(VM* vm, PyVar key) {
|
||||
return pkpy_Dict__del(this, vm, *(pkpy_Var*)(&key));
|
||||
return pkpy_Dict__del(this, vm, *(::PyVar*)(&key));
|
||||
}
|
||||
|
||||
void update(VM* vm, const Dict& other) {
|
||||
@ -53,7 +53,7 @@ struct Dict : private pkpy_Dict {
|
||||
void apply(__Func f) const {
|
||||
pkpy_DictIter it = iter();
|
||||
PyVar key, val;
|
||||
while(pkpy_DictIter__next(&it, (pkpy_Var*)(&key), (pkpy_Var*)(&val))) {
|
||||
while(pkpy_DictIter__next(&it, (::PyVar*)(&key), (::PyVar*)(&val))) {
|
||||
f(key, val);
|
||||
}
|
||||
}
|
||||
@ -63,7 +63,7 @@ struct Dict : private pkpy_Dict {
|
||||
pkpy_DictIter it = iter();
|
||||
PyVar key, val;
|
||||
int i = 0;
|
||||
while(pkpy_DictIter__next(&it, (pkpy_Var*)(&key), (pkpy_Var*)(&val))) {
|
||||
while(pkpy_DictIter__next(&it, (::PyVar*)(&key), (::PyVar*)(&val))) {
|
||||
res[i++] = key;
|
||||
}
|
||||
return res;
|
||||
@ -74,7 +74,7 @@ struct Dict : private pkpy_Dict {
|
||||
pkpy_DictIter it = iter();
|
||||
PyVar key, val;
|
||||
int i = 0;
|
||||
while(pkpy_DictIter__next(&it, (pkpy_Var*)(&key), (pkpy_Var*)(&val))) {
|
||||
while(pkpy_DictIter__next(&it, (::PyVar*)(&key), (::PyVar*)(&val))) {
|
||||
res[i++] = val;
|
||||
}
|
||||
return res;
|
||||
|
@ -2,23 +2,20 @@
|
||||
|
||||
#include "pocketpy/common/vector.h"
|
||||
#include "pocketpy/common/str.h"
|
||||
#include "pocketpy/objects/base.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#include "pocketpy/objects/pyvar.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SMALLMAP_T__HEADER
|
||||
#define K uint16_t
|
||||
#define V pkpy_Var
|
||||
#define TAG n2v
|
||||
#define V PyVar
|
||||
#define NAME pkpy_NameDict
|
||||
#include "pocketpy/xmacros/smallmap.h"
|
||||
#undef SMALLMAP_T__HEADER
|
||||
|
||||
typedef c11_smallmap_n2v pkpy_NameDict;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include "pocketpy/objects/object.hpp"
|
||||
#include "pocketpy/objects/namedict.h"
|
||||
|
||||
#include <string_view>
|
||||
|
||||
namespace pkpy {
|
||||
|
||||
struct NameDict: pkpy_NameDict {
|
||||
@ -14,11 +16,11 @@ struct NameDict: pkpy_NameDict {
|
||||
using Item = pair<StrName, PyVar>;
|
||||
|
||||
NameDict() {
|
||||
c11_smallmap_n2v__ctor(this);
|
||||
pkpy_NameDict__ctor(this);
|
||||
}
|
||||
|
||||
~NameDict() {
|
||||
c11_smallmap_n2v__dtor(this);
|
||||
pkpy_NameDict__dtor(this);
|
||||
}
|
||||
|
||||
uint16_t size() const {
|
||||
@ -26,18 +28,19 @@ struct NameDict: pkpy_NameDict {
|
||||
}
|
||||
|
||||
void set(StrName key, PyVar val){
|
||||
pkpy_Var* p = (pkpy_Var*)&val;
|
||||
c11_smallmap_n2v__set(this, key.index, *p);
|
||||
PyVar* p = (PyVar*)&val;
|
||||
pkpy_NameDict__set(this, key.index, *p);
|
||||
}
|
||||
|
||||
PyVar try_get(StrName key) const{
|
||||
PyVar* p = try_get_2(key);
|
||||
return p ? *p : nullptr;
|
||||
if(p) return *p;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PyVar* try_get_2(StrName key) const{
|
||||
pkpy_Var* p = c11_smallmap_n2v__try_get(this, key.index);
|
||||
return p ? (PyVar*)p : nullptr;
|
||||
PyVar* p = (PyVar*)pkpy_NameDict__try_get(this, key.index);
|
||||
return p;
|
||||
}
|
||||
|
||||
PyVar try_get_likely_found(StrName key) const{
|
||||
@ -49,11 +52,11 @@ struct NameDict: pkpy_NameDict {
|
||||
}
|
||||
|
||||
bool del(StrName key){
|
||||
return c11_smallmap_n2v__del(this, key.index);
|
||||
return pkpy_NameDict__del(this, key.index);
|
||||
}
|
||||
|
||||
bool contains(StrName key) const{
|
||||
return c11_smallmap_n2v__contains(this, key.index);
|
||||
return pkpy_NameDict__contains(this, key.index);
|
||||
}
|
||||
|
||||
PyVar operator[] (StrName key) const{
|
||||
@ -65,13 +68,13 @@ struct NameDict: pkpy_NameDict {
|
||||
}
|
||||
|
||||
void clear(){
|
||||
c11_smallmap_n2v__clear(this);
|
||||
pkpy_NameDict__clear(this);
|
||||
}
|
||||
|
||||
array<StrName> keys() const{
|
||||
array<StrName> retval((int)size());
|
||||
for(int i=0; i<size(); i++){
|
||||
auto it = c11__at(c11_smallmap_entry_n2v, this, i);
|
||||
auto it = c11__at(pkpy_NameDict_KV, this, i);
|
||||
retval[i] = StrName(it->key);
|
||||
}
|
||||
return retval;
|
||||
@ -80,7 +83,7 @@ struct NameDict: pkpy_NameDict {
|
||||
array<Item> items() const{
|
||||
array<Item> retval((int)size());
|
||||
for(int i=0; i<size(); i++){
|
||||
auto it = c11__at(c11_smallmap_entry_n2v, this, i);
|
||||
auto it = c11__at(pkpy_NameDict_KV, this, i);
|
||||
PyVar* p = (PyVar*)&it->value;
|
||||
retval[i] = Item(StrName(it->key), *p);
|
||||
}
|
||||
@ -89,7 +92,7 @@ struct NameDict: pkpy_NameDict {
|
||||
|
||||
void apply(void (*f)(StrName, PyVar, void*), void* data){
|
||||
for(int i=0; i<size(); i++){
|
||||
auto it = c11__at(c11_smallmap_entry_n2v, this, i);
|
||||
auto it = c11__at(pkpy_NameDict_KV, this, i);
|
||||
PyVar* p = (PyVar*)&it->value;
|
||||
f(StrName(it->key), *p, data);
|
||||
}
|
||||
|
41
include/pocketpy/objects/object.h
Normal file
41
include/pocketpy/objects/object.h
Normal file
@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include "pocketpy/objects/namedict.h"
|
||||
#include "pocketpy/objects/base.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct PyObject{
|
||||
pkpy_Type type; // we have a duplicated type here for convenience
|
||||
bool gc_is_large;
|
||||
bool gc_marked;
|
||||
pkpy_NameDict* _attr; // gc will delete this on destruction
|
||||
} PyObject;
|
||||
|
||||
static_assert(sizeof(PyObject) <= 16, "!(sizeof(PyObject) <= 16)");
|
||||
|
||||
#define PyObject__value_ptr(self) ((char*)self + 16)
|
||||
#define PyObject__as(T, self) (T*)(PyObject__value_ptr(self))
|
||||
|
||||
PK_INLINE void PyObject__ctor(PyObject* self, pkpy_Type type, bool gc_is_large){
|
||||
self->type = type;
|
||||
self->gc_is_large = gc_is_large;
|
||||
self->gc_marked = false;
|
||||
self->_attr = NULL;
|
||||
}
|
||||
|
||||
PK_INLINE PyVar PyVar__fromobj(PyObject* self){
|
||||
PyVar var;
|
||||
var.type = self->type;
|
||||
var.is_ptr = true;
|
||||
var.flags = 0;
|
||||
var.flags_ex = 0;
|
||||
var._obj = self;
|
||||
return var;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -3,35 +3,35 @@
|
||||
#include "pocketpy/common/str.hpp"
|
||||
#include "pocketpy/common/config.h"
|
||||
#include "pocketpy/objects/base.hpp"
|
||||
#include "pocketpy/objects/object.h"
|
||||
|
||||
namespace pkpy {
|
||||
|
||||
struct NameDict;
|
||||
|
||||
struct PyObject final {
|
||||
Type type; // we have a duplicated type here for convenience
|
||||
bool gc_is_large;
|
||||
bool gc_marked;
|
||||
NameDict* _attr; // gc will delete this on destruction
|
||||
|
||||
struct PyObject final: ::PyObject {
|
||||
bool is_attr_valid() const noexcept { return _attr != nullptr; }
|
||||
|
||||
void* _value_ptr() noexcept { return (char*)this + 16; }
|
||||
|
||||
NameDict& attr() const{
|
||||
return *(NameDict*)_attr;
|
||||
}
|
||||
|
||||
PyVar attr(StrName name) const;
|
||||
|
||||
template <typename T>
|
||||
T& as() noexcept {
|
||||
static_assert(std::is_same_v<T, std::decay_t<T>>);
|
||||
return *reinterpret_cast<T*>(_value_ptr());
|
||||
}
|
||||
|
||||
NameDict& attr() {
|
||||
assert(is_attr_valid());
|
||||
return *_attr;
|
||||
PyObject(Type type, bool gc_is_large){
|
||||
this->type = type;
|
||||
this->gc_is_large = gc_is_large;
|
||||
this->gc_marked = false;
|
||||
this->_attr = nullptr;
|
||||
}
|
||||
|
||||
PyObject(Type type, bool gc_is_large) : type(type), gc_is_large(gc_is_large), gc_marked(false), _attr(nullptr) {}
|
||||
|
||||
PyVar attr(StrName name) const;
|
||||
};
|
||||
|
||||
static_assert(sizeof(PyObject) <= 16);
|
||||
|
@ -1,51 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief A python value in pocketpy.
|
||||
*/
|
||||
typedef struct {
|
||||
int type;
|
||||
int _0;
|
||||
int64_t _1;
|
||||
} pkpy_Var;
|
||||
|
||||
/**
|
||||
* @brief Check if the pkpy_Var is null.
|
||||
* @param self The variable to check.
|
||||
* @return True if the variable is null, false otherwise.
|
||||
*/
|
||||
#define pkpy_Var__is_null(self) ((self)->type == 0)
|
||||
|
||||
/**
|
||||
* @brief Set the variable to null.
|
||||
* @param self The variable to set.
|
||||
*/
|
||||
#define pkpy_Var__set_null(self) do { (self)->type = 0; } while(0)
|
||||
|
||||
/**
|
||||
* @brief Check if two pkpy_Vars are equal, respects to __eq__ method.
|
||||
* @param vm The virtual machine.
|
||||
* @param a The first pkpy_Var.
|
||||
* @param b The second pkpy_Var.
|
||||
* @return True if the pkpy_Vars are equal, false otherwise.
|
||||
*/
|
||||
bool pkpy_Var__eq__(void *vm, pkpy_Var a, pkpy_Var b);
|
||||
|
||||
/**
|
||||
* @brief Get the hash of the pkpy_Var, respects to __hash__ method.
|
||||
* @param vm The virtual machine.
|
||||
* @param a The pkpy_Var to hash.
|
||||
* @return The hash of the pkpy_Var.
|
||||
*/
|
||||
int64_t pkpy_Var__hash__(void *vm, pkpy_Var a);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,15 +1,15 @@
|
||||
#ifndef POCKETPY_C_H
|
||||
#define POCKETPY_C_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "pocketpy/common/export.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
namespace pkpy{
|
||||
#endif
|
||||
typedef struct pkpy_vm_handle pkpy_vm;
|
||||
typedef int (*pkpy_CFunction)(pkpy_vm*);
|
||||
typedef void (*pkpy_COutputHandler)(const char*, int);
|
||||
@ -101,6 +101,7 @@ extern "C" {
|
||||
PK_EXPORT void pkpy_delete_repl(void* repl);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* Input */
|
||||
#define K int
|
||||
#define V float
|
||||
#define TAG int_float
|
||||
#define NAME c11_smallmap_i2f
|
||||
#endif
|
||||
|
||||
/* Optional Input */
|
||||
@ -23,9 +23,8 @@
|
||||
#define CONCAT(A, B) CONCAT_(A, B)
|
||||
#define CONCAT_(A, B) A##B
|
||||
|
||||
#define KV CONCAT(c11_smallmap_entry_, TAG)
|
||||
#define SMALLMAP CONCAT(c11_smallmap_, TAG)
|
||||
#define SMALLMAP_METHOD(name) CONCAT(SMALLMAP, CONCAT(__, name))
|
||||
#define KV CONCAT(NAME, _KV)
|
||||
#define METHOD(name) CONCAT(NAME, CONCAT(__, name))
|
||||
|
||||
#ifdef SMALLMAP_T__HEADER
|
||||
/* Declaration */
|
||||
@ -34,32 +33,32 @@ typedef struct {
|
||||
V value;
|
||||
} KV;
|
||||
|
||||
typedef c11_vector SMALLMAP;
|
||||
typedef c11_vector NAME;
|
||||
|
||||
void SMALLMAP_METHOD(ctor)(SMALLMAP* self);
|
||||
void SMALLMAP_METHOD(dtor)(SMALLMAP* self);
|
||||
void SMALLMAP_METHOD(set)(SMALLMAP* self, K key, V value);
|
||||
V* SMALLMAP_METHOD(try_get)(const SMALLMAP* self, K key);
|
||||
V SMALLMAP_METHOD(get)(const SMALLMAP* self, K key, V default_value);
|
||||
bool SMALLMAP_METHOD(contains)(const SMALLMAP* self, K key);
|
||||
bool SMALLMAP_METHOD(del)(SMALLMAP* self, K key);
|
||||
void SMALLMAP_METHOD(clear)(SMALLMAP* self);
|
||||
void METHOD(ctor)(NAME* self);
|
||||
void METHOD(dtor)(NAME* self);
|
||||
void METHOD(set)(NAME* self, K key, V value);
|
||||
V* METHOD(try_get)(const NAME* self, K key);
|
||||
V METHOD(get)(const NAME* self, K key, V default_value);
|
||||
bool METHOD(contains)(const NAME* self, K key);
|
||||
bool METHOD(del)(NAME* self, K key);
|
||||
void METHOD(clear)(NAME* self);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef SMALLMAP_T__SOURCE
|
||||
/* Implementation */
|
||||
|
||||
void SMALLMAP_METHOD(ctor)(SMALLMAP* self) {
|
||||
void METHOD(ctor)(NAME* self) {
|
||||
c11_vector__ctor(self, sizeof(KV));
|
||||
c11_vector__reserve(self, 4);
|
||||
}
|
||||
|
||||
void SMALLMAP_METHOD(dtor)(SMALLMAP* self) {
|
||||
void METHOD(dtor)(NAME* self) {
|
||||
c11_vector__dtor(self);
|
||||
}
|
||||
|
||||
void SMALLMAP_METHOD(set)(SMALLMAP* self, K key, V value) {
|
||||
void METHOD(set)(NAME* self, K key, V value) {
|
||||
int index;
|
||||
c11__lower_bound(KV, self->data, self->count, key, partial_less, &index);
|
||||
KV* it = c11__at(KV, self, index);
|
||||
@ -71,7 +70,7 @@ void SMALLMAP_METHOD(set)(SMALLMAP* self, K key, V value) {
|
||||
}
|
||||
}
|
||||
|
||||
V* SMALLMAP_METHOD(try_get)(const SMALLMAP* self, K key) {
|
||||
V* METHOD(try_get)(const NAME* self, K key) {
|
||||
// use `bsearch` which is faster than `lower_bound`
|
||||
int low = 0;
|
||||
int high = self->count - 1;
|
||||
@ -89,16 +88,16 @@ V* SMALLMAP_METHOD(try_get)(const SMALLMAP* self, K key) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
V SMALLMAP_METHOD(get)(const SMALLMAP* self, K key, V default_value) {
|
||||
V* p = SMALLMAP_METHOD(try_get)(self, key);
|
||||
V METHOD(get)(const NAME* self, K key, V default_value) {
|
||||
V* p = METHOD(try_get)(self, key);
|
||||
return p ? *p : default_value;
|
||||
}
|
||||
|
||||
bool SMALLMAP_METHOD(contains)(const SMALLMAP* self, K key) {
|
||||
return SMALLMAP_METHOD(try_get)(self, key) != NULL;
|
||||
bool METHOD(contains)(const NAME* self, K key) {
|
||||
return METHOD(try_get)(self, key) != NULL;
|
||||
}
|
||||
|
||||
bool SMALLMAP_METHOD(del)(SMALLMAP* self, K key) {
|
||||
bool METHOD(del)(NAME* self, K key) {
|
||||
int index;
|
||||
c11__lower_bound(KV, self->data, self->count, key, partial_less, &index);
|
||||
KV* it = c11__at(KV, self, index);
|
||||
@ -109,7 +108,7 @@ bool SMALLMAP_METHOD(del)(SMALLMAP* self, K key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void SMALLMAP_METHOD(clear)(SMALLMAP* self) {
|
||||
void METHOD(clear)(NAME* self) {
|
||||
c11_vector__clear(self);
|
||||
}
|
||||
|
||||
@ -117,14 +116,13 @@ void SMALLMAP_METHOD(clear)(SMALLMAP* self) {
|
||||
|
||||
/* Undefine all macros */
|
||||
#undef KV
|
||||
#undef SMALLMAP
|
||||
#undef SMALLMAP_METHOD
|
||||
#undef METHOD
|
||||
#undef CONCAT
|
||||
#undef CONCAT_
|
||||
|
||||
#undef K
|
||||
#undef V
|
||||
#undef TAG
|
||||
#undef NAME
|
||||
#undef less
|
||||
#undef partial_less
|
||||
#undef equal
|
||||
|
@ -3,7 +3,7 @@
|
||||
#define SMALLMAP_T__SOURCE
|
||||
#define K uint16_t
|
||||
#define V int
|
||||
#define TAG n2i
|
||||
#define NAME c11_smallmap_n2i
|
||||
#include "pocketpy/xmacros/smallmap.h"
|
||||
#undef SMALLMAP_T__SOURCE
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
#define SMALLMAP_T__SOURCE
|
||||
#define K c11_string
|
||||
#define V uint16_t
|
||||
#define TAG s2n
|
||||
#define NAME c11_smallmap_s2n
|
||||
#define less(a, b) (c11_string__cmp((a), (b)) < 0)
|
||||
#define equal(a, b) (c11_string__cmp((a), (b)) == 0)
|
||||
#include "pocketpy/xmacros/smallmap.h"
|
||||
|
@ -637,7 +637,7 @@ Error* Lexer::precompile(Str* out) noexcept{
|
||||
ss << "=" << (int)token_indices.count << '\n'; // L3: raw string count
|
||||
uint16_t index = 0;
|
||||
for(int i=0; i<token_indices.count; i++){
|
||||
c11_smallmap_entry_s2n* kv = c11__at(c11_smallmap_entry_s2n, &token_indices, i);
|
||||
auto kv = c11__at(c11_smallmap_s2n_KV, &token_indices, i);
|
||||
ss << kv->key << '\n'; // L4: raw strings
|
||||
kv->value = index++;
|
||||
}
|
||||
|
@ -475,7 +475,7 @@ PyVar VM::__run_top_frame() {
|
||||
DISPATCH()
|
||||
case OP_BUILD_SET: {
|
||||
PyVar _0 = VAR(STACK_VIEW(byte.arg).to_list());
|
||||
_0 = call(builtins->attr(pk_id_set), _0);
|
||||
_0 = call(builtins->attr()[pk_id_set], _0);
|
||||
STACK_SHRINK(byte.arg);
|
||||
PUSH(_0);
|
||||
}
|
||||
@ -526,7 +526,7 @@ PyVar VM::__run_top_frame() {
|
||||
__unpack_as_list(STACK_VIEW(byte.arg), list);
|
||||
STACK_SHRINK(byte.arg);
|
||||
PyVar _0 = VAR(std::move(list));
|
||||
_0 = call(builtins->attr(pk_id_set), _0);
|
||||
_0 = call(builtins->attr()[pk_id_set], _0);
|
||||
PUSH(_0);
|
||||
}
|
||||
DISPATCH()
|
||||
|
@ -267,7 +267,7 @@ void add_module_c(VM* vm) {
|
||||
|
||||
#undef BIND_PRIMITIVE
|
||||
|
||||
PyObject* char_p_t = mod->attr("char_p").get();
|
||||
PyObject* char_p_t = mod->attr()["char_p"].get();
|
||||
vm->bind(char_p_t, "read_string(self) -> str", [](VM* vm, ArgsView args) {
|
||||
obj_get_t<VoidP> voidp = PK_OBJ_GET(VoidP, args[0]);
|
||||
const char* target = (const char*)voidp.ptr;
|
||||
|
@ -11,7 +11,7 @@ PyVar* FastLocals::try_get_name(StrName name) {
|
||||
NameDict* FastLocals::to_namedict() {
|
||||
NameDict* dict = new NameDict();
|
||||
for(int i=0; i<co->varnames_inv.count; i++){
|
||||
auto entry = c11__getitem(c11_smallmap_entry_n2i, &co->varnames_inv, i);
|
||||
auto entry = c11__getitem(c11_smallmap_n2i_KV, &co->varnames_inv, i);
|
||||
PyVar value = a[entry.value];
|
||||
if(value) dict->set(StrName(entry.key), value);
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ void DictItemsIter::_register(VM* vm, PyObject* mod, PyObject* type) {
|
||||
vm->bind__next__(type->as<Type>(), [](VM* vm, PyVar _0) -> unsigned {
|
||||
DictItemsIter& self = _CAST(DictItemsIter&, _0);
|
||||
PyVar key, val;
|
||||
if (pkpy_DictIter__next(&self.it, (pkpy_Var*)(&key), (pkpy_Var*)(&val))) {
|
||||
if (pkpy_DictIter__next(&self.it, (PyVar*)(&key), (PyVar*)(&val))) {
|
||||
vm->s_data.push(key);
|
||||
vm->s_data.push(val);
|
||||
return 2;
|
||||
|
@ -254,7 +254,7 @@ PyVar VM::py_op(std::string_view name) {
|
||||
PyVar func;
|
||||
auto it = __cached_op_funcs.try_get(name);
|
||||
if(it == nullptr) {
|
||||
func = py_import("operator")->attr(StrName::get(name));
|
||||
func = py_import("operator")->attr()[StrName::get(name)];
|
||||
__cached_op_funcs.insert(name, func);
|
||||
} else {
|
||||
func = *it;
|
||||
@ -283,11 +283,11 @@ PyVar VM::py_next(PyVar obj) {
|
||||
|
||||
bool VM::py_callable(PyVar obj) {
|
||||
Type cls = vm->_tp(obj);
|
||||
switch(cls.index) {
|
||||
case VM::tp_function.index: return true;
|
||||
case VM::tp_native_func.index: return true;
|
||||
case VM::tp_bound_method.index: return true;
|
||||
case VM::tp_type.index: return true;
|
||||
switch(cls) {
|
||||
case VM::tp_function: return true;
|
||||
case VM::tp_native_func: return true;
|
||||
case VM::tp_bound_method: return true;
|
||||
case VM::tp_type: return true;
|
||||
}
|
||||
return vm->find_name_in_mro(cls, __call__) != nullptr;
|
||||
}
|
||||
@ -538,7 +538,7 @@ i64 VM::py_hash(PyVar obj) {
|
||||
has_custom_eq = true;
|
||||
else {
|
||||
f = get_unbound_method(obj, __eq__, &self, false);
|
||||
has_custom_eq = f != _t(tp_object)->attr(__eq__);
|
||||
has_custom_eq = f != _t(tp_object)->attr()[__eq__];
|
||||
}
|
||||
if(has_custom_eq) {
|
||||
TypeError(_S("unhashable type: ", ti->name.escape()));
|
||||
@ -1228,11 +1228,11 @@ PyVar VM::getattr(PyVar obj, StrName name, bool throw_err) {
|
||||
if(cls_var != nullptr) {
|
||||
// bound method is non-data descriptor
|
||||
if(!is_tagged(*cls_var)) {
|
||||
switch(cls_var->type.index) {
|
||||
case tp_function.index: return VAR(BoundMethod(obj, *cls_var));
|
||||
case tp_native_func.index: return VAR(BoundMethod(obj, *cls_var));
|
||||
case tp_staticmethod.index: return PK_OBJ_GET(StaticMethod, *cls_var).func;
|
||||
case tp_classmethod.index: return VAR(BoundMethod(_t(objtype), PK_OBJ_GET(ClassMethod, *cls_var).func));
|
||||
switch(cls_var->type) {
|
||||
case tp_function: return VAR(BoundMethod(obj, *cls_var));
|
||||
case tp_native_func: return VAR(BoundMethod(obj, *cls_var));
|
||||
case tp_staticmethod: return PK_OBJ_GET(StaticMethod, *cls_var).func;
|
||||
case tp_classmethod: return VAR(BoundMethod(_t(objtype), PK_OBJ_GET(ClassMethod, *cls_var).func));
|
||||
}
|
||||
}
|
||||
return *cls_var;
|
||||
@ -1291,11 +1291,11 @@ PyVar VM::get_unbound_method(PyVar obj, StrName name, PyVar* self, bool throw_er
|
||||
|
||||
if(cls_var != nullptr) {
|
||||
if(!is_tagged(*cls_var)) {
|
||||
switch(cls_var->type.index) {
|
||||
case tp_function.index: *self = obj; break;
|
||||
case tp_native_func.index: *self = obj; break;
|
||||
case tp_staticmethod.index: self->set_null(); return PK_OBJ_GET(StaticMethod, *cls_var).func;
|
||||
case tp_classmethod.index: *self = _t(objtype); return PK_OBJ_GET(ClassMethod, *cls_var).func;
|
||||
switch(cls_var->type) {
|
||||
case tp_function: *self = obj; break;
|
||||
case tp_native_func: *self = obj; break;
|
||||
case tp_staticmethod: self->set_null(); return PK_OBJ_GET(StaticMethod, *cls_var).func;
|
||||
case tp_classmethod: *self = _t(objtype); return PK_OBJ_GET(ClassMethod, *cls_var).func;
|
||||
}
|
||||
}
|
||||
return *cls_var;
|
||||
@ -1395,9 +1395,9 @@ PyObject* VM::bind_property(PyObject* obj, const char* name, NativeFuncC fget, N
|
||||
return prop;
|
||||
}
|
||||
|
||||
void VM::__builtin_error(StrName type) { _error(call(builtins->attr(type))); }
|
||||
void VM::__builtin_error(StrName type) { _error(call(builtins->attr()[type])); }
|
||||
|
||||
void VM::__builtin_error(StrName type, PyVar arg) { _error(call(builtins->attr(type), arg)); }
|
||||
void VM::__builtin_error(StrName type, PyVar arg) { _error(call(builtins->attr()[type], arg)); }
|
||||
|
||||
void VM::__builtin_error(StrName type, const Str& msg) { __builtin_error(type, VAR(msg)); }
|
||||
|
||||
@ -1796,11 +1796,8 @@ void VM::__breakpoint() {
|
||||
#endif
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
PyVar PyObject::attr(StrName name) const{
|
||||
assert(is_attr_valid());
|
||||
return (*_attr)[name];
|
||||
return attr()[name];
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
|
@ -149,11 +149,11 @@ struct Array2d {
|
||||
HANDLE_SLICE();
|
||||
|
||||
bool is_basic_type = false;
|
||||
switch(vm->_tp(_2).index) {
|
||||
case VM::tp_int.index: is_basic_type = true; break;
|
||||
case VM::tp_float.index: is_basic_type = true; break;
|
||||
case VM::tp_str.index: is_basic_type = true; break;
|
||||
case VM::tp_bool.index: is_basic_type = true; break;
|
||||
switch(vm->_tp(_2)) {
|
||||
case VM::tp_int: is_basic_type = true; break;
|
||||
case VM::tp_float: is_basic_type = true; break;
|
||||
case VM::tp_str: is_basic_type = true; break;
|
||||
case VM::tp_bool: is_basic_type = true; break;
|
||||
default: is_basic_type = is_none(_2);
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ void add_module_csv(VM* vm) {
|
||||
});
|
||||
|
||||
vm->bind(mod, "DictReader(csvfile: list[str]) -> list[dict]", [](VM* vm, ArgsView args) {
|
||||
PyVar csv_reader = vm->_modules["csv"]->attr("reader");
|
||||
PyVar csv_reader = vm->_modules["csv"]->attr()["reader"];
|
||||
PyVar ret_obj = vm->call(csv_reader, args[0]);
|
||||
const List& ret = CAST(List&, ret_obj);
|
||||
if(ret.size() == 0) { vm->ValueError("empty csvfile"); }
|
||||
|
@ -72,8 +72,8 @@ static void patch__eq__(VM* vm, Type cls) {
|
||||
const PyTypeInfo* cls_info = &vm->_all_types[vm->_tp(_0)];
|
||||
const auto& fields = cls_info->annotated_fields;
|
||||
for(StrName field: fields) {
|
||||
PyVar lhs = _0->attr(field);
|
||||
PyVar rhs = _1->attr(field);
|
||||
PyVar lhs = _0->attr()[field];
|
||||
PyVar rhs = _1->attr()[field];
|
||||
if(vm->py_ne(lhs, rhs)) return vm->False;
|
||||
}
|
||||
return vm->True;
|
||||
|
20
src/objects/base.c
Normal file
20
src/objects/base.c
Normal file
@ -0,0 +1,20 @@
|
||||
#include "pocketpy/objects/base.h"
|
||||
|
||||
/* predefined vars */
|
||||
const pkpy_Type tp_object = 1, tp_type = 2;
|
||||
const pkpy_Type tp_int = 3, tp_float = 4, tp_bool = 5, tp_str = 6;
|
||||
const pkpy_Type tp_list = 7, tp_tuple = 8;
|
||||
const pkpy_Type tp_slice = 9, tp_range = 10, tp_module = 11;
|
||||
const pkpy_Type tp_function = 12, tp_native_func = 13, tp_bound_method = 14;
|
||||
const pkpy_Type tp_super = 15, tp_exception = 16, tp_bytes = 17, tp_mappingproxy = 18;
|
||||
const pkpy_Type tp_dict = 19, tp_property = 20, tp_star_wrapper = 21;
|
||||
const pkpy_Type tp_staticmethod = 22, tp_classmethod = 23;
|
||||
const pkpy_Type tp_none_type = 24, tp_not_implemented_type = 25;
|
||||
const pkpy_Type tp_ellipsis = 26;
|
||||
|
||||
const PyVar pkpy_True = {.type=tp_bool, .is_ptr=false, .flags=0, .flags_ex=0, ._bool=true};
|
||||
const PyVar pkpy_False = {.type=tp_bool, .is_ptr=false, .flags=0, .flags_ex=0, ._bool=false};
|
||||
const PyVar pkpy_None = {.type=tp_none_type, .is_ptr=false, .flags=0, .flags_ex=0, ._i64=0};
|
||||
const PyVar pkpy_NotImplemented = {.type=tp_not_implemented_type, .is_ptr=false, .flags=0, .flags_ex=0, ._i64=0};
|
||||
const PyVar pkpy_Ellipsis = {.type=tp_ellipsis, .is_ptr=false, .flags=0, .flags_ex=0, ._i64=0};
|
||||
const PyVar pkpy_NULL = {.type=0, .is_ptr=false, .flags=0, .flags_ex=0, ._i64=0};
|
@ -1,6 +1,6 @@
|
||||
#include "pocketpy/objects/builtins.hpp"
|
||||
|
||||
namespace pkpy {
|
||||
const PyVar PY_OP_CALL(Type(), new PyObject(Type(), true));
|
||||
const PyVar PY_OP_YIELD(Type(), new PyObject(Type(), true));
|
||||
PyVar PY_OP_CALL(Type(), new PyObject(Type(), true));
|
||||
PyVar PY_OP_YIELD(Type(), new PyObject(Type(), true));
|
||||
} // namespace pkpy
|
||||
|
@ -10,8 +10,8 @@
|
||||
#define PK_DICT_COMPACT_MODE 1
|
||||
|
||||
struct pkpy_DictEntry {
|
||||
pkpy_Var key;
|
||||
pkpy_Var val;
|
||||
PyVar key;
|
||||
PyVar val;
|
||||
};
|
||||
|
||||
inline extern int pkpy_Dict__idx_size(const pkpy_Dict* self) {
|
||||
@ -73,7 +73,7 @@ static void pkpy_Dict__htset(pkpy_Dict* self, int h, int v) {
|
||||
#endif
|
||||
}
|
||||
|
||||
static int pkpy_Dict__probe0(const pkpy_Dict* self, void* vm, pkpy_Var key, int hash) {
|
||||
static int pkpy_Dict__probe0(const pkpy_Dict* self, void* vm, PyVar key, int hash) {
|
||||
const int null = pkpy_Dict__idx_null(self);
|
||||
const int mask = self->_htcap - 1;
|
||||
for(int h = hash & mask;; h = DICT_HASH_NEXT(h) & mask) {
|
||||
@ -86,7 +86,7 @@ static int pkpy_Dict__probe0(const pkpy_Dict* self, void* vm, pkpy_Var key, int
|
||||
PK_UNREACHABLE();
|
||||
}
|
||||
|
||||
static int pkpy_Dict__probe1(const pkpy_Dict* self, void* vm, pkpy_Var key, int hash) {
|
||||
static int pkpy_Dict__probe1(const pkpy_Dict* self, void* vm, PyVar key, int hash) {
|
||||
const int null = pkpy_Dict__idx_null(self);
|
||||
const int mask = self->_htcap - 1;
|
||||
for(int h = hash & mask;; h = DICT_HASH_NEXT(h) & mask) {
|
||||
@ -116,7 +116,7 @@ static void pkpy_Dict__extendht(pkpy_Dict* self, void* vm) {
|
||||
}
|
||||
}
|
||||
|
||||
bool pkpy_Dict__set(pkpy_Dict* self, void* vm, pkpy_Var key, pkpy_Var val) {
|
||||
bool pkpy_Dict__set(pkpy_Dict* self, void* vm, PyVar key, PyVar val) {
|
||||
int hash = DICT_HASH_TRANS(pkpy_Var__hash__(vm, key));
|
||||
int h = pkpy_Dict__probe1(self, vm, key, hash);
|
||||
|
||||
@ -151,7 +151,7 @@ bool pkpy_Dict__set(pkpy_Dict* self, void* vm, pkpy_Var key, pkpy_Var val) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool pkpy_Dict__contains(const pkpy_Dict* self, void* vm, pkpy_Var key) {
|
||||
bool pkpy_Dict__contains(const pkpy_Dict* self, void* vm, PyVar key) {
|
||||
int hash = DICT_HASH_TRANS(pkpy_Var__hash__(vm, key));
|
||||
int h = pkpy_Dict__probe1(self, vm, key, hash);
|
||||
|
||||
@ -191,7 +191,7 @@ static bool pkpy_Dict__refactor(pkpy_Dict* self, void* vm) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool pkpy_Dict__del(pkpy_Dict* self, void* vm, pkpy_Var key) {
|
||||
bool pkpy_Dict__del(pkpy_Dict* self, void* vm, PyVar key) {
|
||||
int hash = DICT_HASH_TRANS(pkpy_Var__hash__(vm, key));
|
||||
int h = pkpy_Dict__probe1(self, vm, key, hash);
|
||||
int idx = pkpy_Dict__htget(self, h), null = pkpy_Dict__idx_null(self);
|
||||
@ -204,7 +204,7 @@ bool pkpy_Dict__del(pkpy_Dict* self, void* vm, pkpy_Var key) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const pkpy_Var *pkpy_Dict__try_get(const pkpy_Dict* self, void* vm, pkpy_Var key) {
|
||||
const PyVar *pkpy_Dict__try_get(const pkpy_Dict* self, void* vm, PyVar key) {
|
||||
int hash = DICT_HASH_TRANS(pkpy_Var__hash__(vm, key));
|
||||
int h = pkpy_Dict__probe1(self, vm, key, hash);
|
||||
|
||||
@ -245,7 +245,7 @@ pkpy_DictIter pkpy_Dict__iter(const pkpy_Dict *self) {
|
||||
};
|
||||
}
|
||||
|
||||
bool pkpy_DictIter__next(pkpy_DictIter *self, pkpy_Var *key, pkpy_Var *val) {
|
||||
bool pkpy_DictIter__next(pkpy_DictIter *self, PyVar *key, PyVar *val) {
|
||||
if(self->_index >= self->_dict->_entries.count) return false;
|
||||
|
||||
struct pkpy_DictEntry* entry = &c11__getitem(struct pkpy_DictEntry, &self->_dict->_entries, self->_index);
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#define SMALLMAP_T__SOURCE
|
||||
#define K uint16_t
|
||||
#define V pkpy_Var
|
||||
#define TAG n2v
|
||||
#define V PyVar
|
||||
#define NAME pkpy_NameDict
|
||||
#include "pocketpy/xmacros/smallmap.h"
|
||||
#undef SMALLMAP_T__SOURCE
|
||||
|
@ -1,17 +1,16 @@
|
||||
#include "pocketpy/objects/base.hpp"
|
||||
#include "pocketpy/objects/pyvar.h"
|
||||
#include "pocketpy/objects/base.h"
|
||||
#include "pocketpy/interpreter/vm.hpp"
|
||||
|
||||
extern "C" {
|
||||
|
||||
bool pkpy_Var__eq__(void* vm_, pkpy_Var a, pkpy_Var b) {
|
||||
bool pkpy_Var__eq__(void* vm_, PyVar a, PyVar b) {
|
||||
auto vm = (pkpy::VM*)(vm_);
|
||||
return vm->py_eq(*(pkpy::PyVar*)(&a), *(pkpy::PyVar*)(&b));
|
||||
return vm->py_eq(*(PyVar*)(&a), *(PyVar*)(&b));
|
||||
}
|
||||
|
||||
int64_t pkpy_Var__hash__(void* vm_, pkpy_Var a) {
|
||||
int64_t pkpy_Var__hash__(void* vm_, PyVar a) {
|
||||
auto vm = (pkpy::VM*)(vm_);
|
||||
return vm->py_hash(*(pkpy::PyVar*)(&a));
|
||||
return vm->py_hash(*(PyVar*)(&a));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1495,7 +1495,7 @@ void __init_builtins(VM* _vm) {
|
||||
if(self.size() != other.size()) return vm->False;
|
||||
pkpy_DictIter it = self.iter();
|
||||
PyVar key, val;
|
||||
while(pkpy_DictIter__next(&it, (pkpy_Var*)(&key), (pkpy_Var*)(&val))) {
|
||||
while(pkpy_DictIter__next(&it, (PyVar*)(&key), (PyVar*)(&val))) {
|
||||
PyVar other_val = other.try_get(vm, key);
|
||||
if(other_val == nullptr) return vm->False;
|
||||
if(!vm->py_eq(val, other_val)) return vm->False;
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace pkpy;
|
||||
namespace pkpy{
|
||||
|
||||
#define PK_ASSERT_N_EXTRA_ELEMENTS(n) \
|
||||
int __ex_count = count_extra_elements(vm, n); \
|
||||
@ -567,3 +567,5 @@ bool pkpy_repl_input(void* r, const char* line) { return ((REPL*)r)->input(line)
|
||||
void pkpy_delete_repl(void* repl) { delete (REPL*)repl; }
|
||||
|
||||
#endif // PK_NO_EXPORT_C_API
|
||||
|
||||
} // namespace pkpy
|
@ -34,6 +34,8 @@ std::string pkpy_platform_getline(bool* eof) {
|
||||
|
||||
#else
|
||||
|
||||
using namespace pkpy;
|
||||
|
||||
std::string pkpy_platform_getline(bool* eof) {
|
||||
std::string output;
|
||||
if(!std::getline(std::cin, output)) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user