mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-22 04:20:17 +00:00
Compare commits
13 Commits
7ed09f927d
...
d00c058c46
Author | SHA1 | Date | |
---|---|---|---|
|
d00c058c46 | ||
|
69183e2d79 | ||
|
96d0c432c7 | ||
|
97cdfbedaf | ||
|
ac19ece535 | ||
|
c954431442 | ||
|
36b3c9ff8f | ||
|
5847586121 | ||
|
c5ab28d75b | ||
|
52b210b016 | ||
|
8270d9035b | ||
|
8bbb9fc5f3 | ||
|
25ceed2703 |
@ -1,33 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct c11_userdata{
|
|
||||||
void* _0;
|
|
||||||
void* _1;
|
|
||||||
} c11_userdata;
|
|
||||||
|
|
||||||
void c11_userdata__ctor(c11_userdata* self, void* ptr, int size);
|
|
||||||
#define c11_userdata__as(T, self) (*( (T*)(self) ))
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace pkpy{
|
|
||||||
struct any: c11_userdata{
|
|
||||||
template<typename T>
|
|
||||||
any(T value){
|
|
||||||
c11_userdata__ctor(this, &value, sizeof(T));
|
|
||||||
}
|
|
||||||
|
|
||||||
any(){ }
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
T as(){
|
|
||||||
return c11_userdata__as(T, this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // namespace pkpy
|
|
||||||
#endif
|
|
@ -1,23 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// ref counting
|
|
||||||
typedef struct RefCounted {
|
|
||||||
int count;
|
|
||||||
void (*dtor)(void*);
|
|
||||||
} RefCounted;
|
|
||||||
|
|
||||||
#define PK_INCREF(obj) (obj)->rc.count++
|
|
||||||
#define PK_DECREF(obj) do { \
|
|
||||||
if(--(obj)->rc.count == 0) { \
|
|
||||||
(obj)->rc.dtor(obj); \
|
|
||||||
free(obj); \
|
|
||||||
} \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "pocketpy/pocketpy.h"
|
||||||
#include "pocketpy/common/str.h"
|
#include "pocketpy/common/str.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@ -19,74 +20,11 @@ c11_string pk_StrName__rmap2(uint16_t index);
|
|||||||
void pk_StrName__initialize();
|
void pk_StrName__initialize();
|
||||||
void pk_StrName__finalize();
|
void pk_StrName__finalize();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* global names */
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
namespace pkpy {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// unary operators
|
|
||||||
extern uint16_t __repr__;
|
|
||||||
extern uint16_t __str__;
|
|
||||||
extern uint16_t __hash__;
|
|
||||||
extern uint16_t __len__;
|
|
||||||
extern uint16_t __iter__;
|
|
||||||
extern uint16_t __next__;
|
|
||||||
extern uint16_t __neg__;
|
|
||||||
// logical operators
|
|
||||||
extern uint16_t __eq__;
|
|
||||||
extern uint16_t __lt__;
|
|
||||||
extern uint16_t __le__;
|
|
||||||
extern uint16_t __gt__;
|
|
||||||
extern uint16_t __ge__;
|
|
||||||
extern uint16_t __contains__;
|
|
||||||
// binary operators
|
|
||||||
extern uint16_t __add__;
|
|
||||||
extern uint16_t __radd__;
|
|
||||||
extern uint16_t __sub__;
|
|
||||||
extern uint16_t __rsub__;
|
|
||||||
extern uint16_t __mul__;
|
|
||||||
extern uint16_t __rmul__;
|
|
||||||
extern uint16_t __truediv__;
|
|
||||||
extern uint16_t __floordiv__;
|
|
||||||
extern uint16_t __mod__;
|
|
||||||
extern uint16_t __pow__;
|
|
||||||
extern uint16_t __matmul__;
|
|
||||||
extern uint16_t __lshift__;
|
|
||||||
extern uint16_t __rshift__;
|
|
||||||
extern uint16_t __and__;
|
|
||||||
extern uint16_t __or__;
|
|
||||||
extern uint16_t __xor__;
|
|
||||||
extern uint16_t __invert__;
|
|
||||||
// indexer
|
|
||||||
extern uint16_t __getitem__;
|
|
||||||
extern uint16_t __setitem__;
|
|
||||||
extern uint16_t __delitem__;
|
|
||||||
|
|
||||||
// specials
|
|
||||||
extern uint16_t __new__;
|
|
||||||
extern uint16_t __init__;
|
|
||||||
extern uint16_t __call__;
|
|
||||||
extern uint16_t __divmod__;
|
|
||||||
extern uint16_t __enter__;
|
|
||||||
extern uint16_t __exit__;
|
|
||||||
extern uint16_t __name__;
|
|
||||||
extern uint16_t __all__;
|
|
||||||
extern uint16_t __package__;
|
|
||||||
extern uint16_t __path__;
|
|
||||||
extern uint16_t __class__;
|
|
||||||
extern uint16_t __missing__;
|
|
||||||
|
|
||||||
extern uint16_t pk_id_add;
|
extern uint16_t pk_id_add;
|
||||||
extern uint16_t pk_id_set;
|
extern uint16_t pk_id_set;
|
||||||
extern uint16_t pk_id_long;
|
extern uint16_t pk_id_long;
|
||||||
extern uint16_t pk_id_complex;
|
extern uint16_t pk_id_complex;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // namespace pkpy
|
}
|
||||||
} // extern "C"
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -40,6 +40,20 @@ extern const char* kPlatformStrings[];
|
|||||||
#define PK_NARGS(...) PK_NARGS_SEQ(__VA_ARGS__, 4, 3, 2, 1, 0)
|
#define PK_NARGS(...) PK_NARGS_SEQ(__VA_ARGS__, 4, 3, 2, 1, 0)
|
||||||
#define PK_NPTRS(...) PK_NARGS_SEQ(__VA_ARGS__, int****, int***, int**, int*, int)
|
#define PK_NPTRS(...) PK_NARGS_SEQ(__VA_ARGS__, int****, int***, int**, int*, int)
|
||||||
|
|
||||||
|
// ref counting
|
||||||
|
typedef struct RefCounted {
|
||||||
|
int count;
|
||||||
|
void (*dtor)(void*);
|
||||||
|
} RefCounted;
|
||||||
|
|
||||||
|
#define PK_INCREF(obj) (obj)->rc.count++
|
||||||
|
#define PK_DECREF(obj) do { \
|
||||||
|
if(--(obj)->rc.count == 0) { \
|
||||||
|
(obj)->rc.dtor(obj); \
|
||||||
|
free(obj); \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
@ -15,7 +15,8 @@ py_TValue* FastLocals__try_get_by_name(py_TValue* locals, const CodeObject* co,
|
|||||||
pk_NameDict* FastLocals__to_namedict(py_TValue* locals, const CodeObject* co);
|
pk_NameDict* FastLocals__to_namedict(py_TValue* locals, const CodeObject* co);
|
||||||
|
|
||||||
typedef struct ValueStack {
|
typedef struct ValueStack {
|
||||||
// We allocate extra PK_VM_STACK_SIZE/128 places to keep `_sp` valid when `is_overflow() == true`.
|
// We allocate extra PK_VM_STACK_SIZE/128 places to keep `_sp` valid when `is_overflow() ==
|
||||||
|
// true`.
|
||||||
py_TValue* sp;
|
py_TValue* sp;
|
||||||
py_TValue* end;
|
py_TValue* end;
|
||||||
py_TValue begin[PK_VM_STACK_SIZE + PK_VM_STACK_SIZE / 128];
|
py_TValue begin[PK_VM_STACK_SIZE + PK_VM_STACK_SIZE / 128];
|
||||||
@ -34,7 +35,7 @@ UnwindTarget* UnwindTarget__new(UnwindTarget* next, int iblock, int offset);
|
|||||||
void UnwindTarget__delete(UnwindTarget* self);
|
void UnwindTarget__delete(UnwindTarget* self);
|
||||||
|
|
||||||
typedef struct Frame {
|
typedef struct Frame {
|
||||||
struct Frame* f_back; // TODO: set this
|
struct Frame* f_back;
|
||||||
const Bytecode* ip;
|
const Bytecode* ip;
|
||||||
const CodeObject* co;
|
const CodeObject* co;
|
||||||
PyObject* module;
|
PyObject* module;
|
||||||
@ -45,13 +46,15 @@ typedef struct Frame {
|
|||||||
UnwindTarget* uw_list;
|
UnwindTarget* uw_list;
|
||||||
} Frame;
|
} Frame;
|
||||||
|
|
||||||
|
Frame* Frame__new(const CodeObject* co,
|
||||||
Frame* Frame__new(const CodeObject* co, const py_TValue* module, const py_TValue* function, py_TValue* p0, py_TValue* locals, const CodeObject* locals_co);
|
const py_TValue* module,
|
||||||
|
const py_TValue* function,
|
||||||
|
py_TValue* p0,
|
||||||
|
py_TValue* locals,
|
||||||
|
const CodeObject* locals_co);
|
||||||
void Frame__delete(Frame* self);
|
void Frame__delete(Frame* self);
|
||||||
|
|
||||||
PK_INLINE int Frame__ip(const Frame* self){
|
PK_INLINE int Frame__ip(const Frame* self) { return self->ip - (Bytecode*)self->co->codes.data; }
|
||||||
return self->ip - (Bytecode*)self->co->codes.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
PK_INLINE int Frame__lineno(const Frame* self) {
|
PK_INLINE int Frame__lineno(const Frame* self) {
|
||||||
int ip = Frame__ip(self);
|
int ip = Frame__ip(self);
|
||||||
@ -63,9 +66,7 @@ PK_INLINE int Frame__iblock(const Frame* self){
|
|||||||
return c11__getitem(BytecodeEx, &self->co->codes_ex, ip).iblock;
|
return c11__getitem(BytecodeEx, &self->co->codes_ex, ip).iblock;
|
||||||
}
|
}
|
||||||
|
|
||||||
PK_INLINE pk_NameDict* Frame__f_globals(Frame* self){
|
PK_INLINE pk_NameDict* Frame__f_globals(Frame* self) { return PyObject__dict(self->module); }
|
||||||
return PyObject__dict(self->module);
|
|
||||||
}
|
|
||||||
|
|
||||||
PK_INLINE py_TValue* Frame__f_globals_try_get(Frame* self, py_Name name) {
|
PK_INLINE py_TValue* Frame__f_globals_try_get(Frame* self, py_Name name) {
|
||||||
return pk_NameDict__try_get(Frame__f_globals(self), name);
|
return pk_NameDict__try_get(Frame__f_globals(self), name);
|
||||||
|
@ -21,21 +21,22 @@ typedef struct pk_TypeInfo{
|
|||||||
|
|
||||||
c11_vector/*T=StrName*/ annotated_fields;
|
c11_vector/*T=StrName*/ annotated_fields;
|
||||||
|
|
||||||
|
py_CFunction on_end_subclass; // backdoor for enum module
|
||||||
|
|
||||||
/* Magic Caches */
|
/* Magic Caches */
|
||||||
// unary operators
|
py_TValue magic[64];
|
||||||
py_CFunction m__repr__, m__str__, m__hash__, m__len__;
|
// // unary operators
|
||||||
py_CFunction m__iter__, m__next__, m__neg__, m__invert__;
|
// py_CFunction m__repr__, m__str__, m__hash__, m__len__;
|
||||||
// binary operators
|
// py_CFunction m__iter__, m__next__, m__neg__, m__invert__;
|
||||||
py_CFunction m__eq__, m__lt__, m__le__, m__gt__, m__ge__, m__contains__;
|
// // binary operators
|
||||||
py_CFunction m__add__, m__sub__, m__mul__, m__truediv__, m__floordiv__;
|
// py_CFunction m__eq__, m__lt__, m__le__, m__gt__, m__ge__, m__contains__;
|
||||||
py_CFunction m__mod__, m__pow__, m__matmul__;
|
// py_CFunction m__add__, m__sub__, m__mul__, m__truediv__, m__floordiv__;
|
||||||
py_CFunction m__lshift__, m__rshift__, m__and__, m__xor__, m__or__;
|
// py_CFunction m__mod__, m__pow__, m__matmul__;
|
||||||
// indexer
|
// py_CFunction m__lshift__, m__rshift__, m__and__, m__xor__, m__or__;
|
||||||
py_CFunction m__getitem__, m__setitem__, m__delitem__;
|
// // indexer
|
||||||
// attribute access (internal use only)
|
// py_CFunction m__getitem__, m__setitem__, m__delitem__;
|
||||||
py_CFunction m__getattr__, m__setattr__, m__delattr__;
|
// // attribute access (internal use only)
|
||||||
// backdoors
|
// py_CFunction m__getattr__, m__setattr__, m__delattr__;
|
||||||
py_CFunction on_end_subclass; // for enum module
|
|
||||||
} pk_TypeInfo;
|
} pk_TypeInfo;
|
||||||
|
|
||||||
void pk_TypeInfo__ctor(pk_TypeInfo* self, py_Name name, py_Type base, PyObject* obj, const py_TValue* module, bool subclass_enabled);
|
void pk_TypeInfo__ctor(pk_TypeInfo* self, py_Name name, py_Type base, PyObject* obj, const py_TValue* module, bool subclass_enabled);
|
||||||
@ -91,6 +92,9 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self);
|
|||||||
|
|
||||||
py_Type pk_VM__new_type(pk_VM* self, const char* name, py_Type base, const py_TValue* module, bool subclass_enabled);
|
py_Type pk_VM__new_type(pk_VM* self, const char* name, py_Type base, const py_TValue* module, bool subclass_enabled);
|
||||||
|
|
||||||
|
// type registration
|
||||||
|
py_Type pk_list__register();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
@ -20,31 +20,34 @@ typedef struct py_TValue{
|
|||||||
py_Type type;
|
py_Type type;
|
||||||
bool is_ptr;
|
bool is_ptr;
|
||||||
int extra;
|
int extra;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
int64_t _i64;
|
int64_t _i64;
|
||||||
double _f64;
|
double _f64;
|
||||||
PyObject* _obj;
|
PyObject* _obj;
|
||||||
void* _ptr;
|
void* _ptr;
|
||||||
|
py_CFunction _cfunc;
|
||||||
// Vec2
|
// Vec2
|
||||||
};
|
};
|
||||||
} py_TValue;
|
} py_TValue;
|
||||||
|
|
||||||
// 16 bytes to make py_arg() macro work
|
// 16 bytes to make py_arg() macro work
|
||||||
|
static_assert(sizeof(py_CFunction) <= 8, "sizeof(py_CFunction) > 8");
|
||||||
static_assert(sizeof(py_TValue) == 16, "sizeof(py_TValue) != 16");
|
static_assert(sizeof(py_TValue) == 16, "sizeof(py_TValue) != 16");
|
||||||
|
|
||||||
/* predefined vars */
|
/* predefined vars */
|
||||||
static const py_Type tp_object = {1}, tp_type = {2};
|
const static py_Type tp_object = {1}, tp_type = {2};
|
||||||
static const py_Type tp_int = {3}, tp_float = {4}, tp_bool = {5}, tp_str = {6};
|
const static py_Type tp_int = {3}, tp_float = {4}, tp_bool = {5}, tp_str = {6};
|
||||||
static const py_Type tp_list = {7}, tp_tuple = {8};
|
const static py_Type tp_list = {7}, tp_tuple = {8};
|
||||||
static const py_Type tp_slice = {9}, tp_range = {10}, tp_module = {11};
|
const static py_Type tp_slice = {9}, tp_range = {10}, tp_module = {11};
|
||||||
static const py_Type tp_function = {12}, tp_nativefunc = {13}, tp_bound_method = {14};
|
const static py_Type tp_function = {12}, tp_nativefunc = {13}, tp_bound_method = {14};
|
||||||
static const py_Type tp_super = {15}, tp_exception = {16}, tp_bytes = {17}, tp_mappingproxy = {18};
|
const static py_Type tp_super = {15}, tp_exception = {16}, tp_bytes = {17}, tp_mappingproxy = {18};
|
||||||
static const py_Type tp_dict = {19}, tp_property = {20}, tp_star_wrapper = {21};
|
const static py_Type tp_dict = {19}, tp_property = {20}, tp_star_wrapper = {21};
|
||||||
static const py_Type tp_staticmethod = {22}, tp_classmethod = {23};
|
const static py_Type tp_staticmethod = {22}, tp_classmethod = {23};
|
||||||
static const py_Type tp_none_type = {24}, tp_not_implemented_type = {25};
|
const static py_Type tp_none_type = {24}, tp_not_implemented_type = {25};
|
||||||
static const py_Type tp_ellipsis = {26};
|
const static py_Type tp_ellipsis = {26};
|
||||||
static const py_Type tp_op_call = {27}, tp_op_yield = {28};
|
const static py_Type tp_op_call = {27}, tp_op_yield = {28};
|
||||||
static const py_Type tp_syntax_error = {29}, tp_stop_iteration = {30};
|
const static py_Type tp_syntax_error = {29}, tp_stop_iteration = {30};
|
||||||
|
|
||||||
extern py_TValue PY_NULL, PY_OP_CALL, PY_OP_YIELD;
|
extern py_TValue PY_NULL, PY_OP_CALL, PY_OP_YIELD;
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
#include "pocketpy/common/smallmap.h"
|
#include "pocketpy/common/smallmap.h"
|
||||||
#include "pocketpy/objects/base.h"
|
#include "pocketpy/objects/base.h"
|
||||||
#include "pocketpy/objects/sourcedata.h"
|
#include "pocketpy/objects/sourcedata.h"
|
||||||
#include "pocketpy/common/refcount.h"
|
|
||||||
#include "pocketpy/pocketpy.h"
|
#include "pocketpy/pocketpy.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "pocketpy/common/str.h"
|
#include "pocketpy/common/str.h"
|
||||||
#include "pocketpy/common/vector.h"
|
#include "pocketpy/common/vector.h"
|
||||||
#include "pocketpy/common/refcount.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -18,9 +18,8 @@ typedef struct py_Error {
|
|||||||
/// Native function signature.
|
/// Native function signature.
|
||||||
/// @param argc number of arguments.
|
/// @param argc number of arguments.
|
||||||
/// @param argv array of arguments. Use `py_arg(i)` macro to get the i-th argument.
|
/// @param argv array of arguments. Use `py_arg(i)` macro to get the i-th argument.
|
||||||
/// @param out output reference to the result.
|
|
||||||
/// @return true if the function is successful.
|
/// @return true if the function is successful.
|
||||||
typedef bool (*py_CFunction)(int argc, py_TValue* argv, py_TValue* out);
|
typedef bool (*py_CFunction)(int argc, py_TValue* argv);
|
||||||
|
|
||||||
typedef enum BindType {
|
typedef enum BindType {
|
||||||
BindType_FUNCTION,
|
BindType_FUNCTION,
|
||||||
@ -35,9 +34,10 @@ void py_initialize();
|
|||||||
void py_finalize();
|
void py_finalize();
|
||||||
|
|
||||||
/// Run a simple source string. Do not change the stack.
|
/// Run a simple source string. Do not change the stack.
|
||||||
int py_exec(const char*);
|
bool py_exec(const char*);
|
||||||
/// Eval a simple expression. The result is pushed to the stack.
|
/// Eval a simple expression.
|
||||||
int py_eval(const char*, py_Ref out);
|
/// The result will be set to `vm->last_retval`.
|
||||||
|
bool py_eval(const char*);
|
||||||
|
|
||||||
/************* Values Creation *************/
|
/************* Values Creation *************/
|
||||||
void py_newint(py_Ref, int64_t);
|
void py_newint(py_Ref, int64_t);
|
||||||
@ -74,13 +74,7 @@ void py_newfunction2(py_Ref out,
|
|||||||
const char* docstring,
|
const char* docstring,
|
||||||
const py_Ref upvalue);
|
const py_Ref upvalue);
|
||||||
// old style argc-based function
|
// old style argc-based function
|
||||||
void py_newnativefunc(py_Ref out, py_CFunction, int argc);
|
void py_newnativefunc(py_Ref out, py_CFunction);
|
||||||
void py_newnativefunc2(py_Ref out,
|
|
||||||
py_CFunction,
|
|
||||||
int argc,
|
|
||||||
BindType bt,
|
|
||||||
const char* docstring,
|
|
||||||
const py_Ref upvalue);
|
|
||||||
|
|
||||||
void py_newnotimplemented(py_Ref out);
|
void py_newnotimplemented(py_Ref out);
|
||||||
|
|
||||||
@ -96,7 +90,7 @@ double py_tofloat(const py_Ref);
|
|||||||
bool py_castfloat(const py_Ref, double* out);
|
bool py_castfloat(const py_Ref, double* out);
|
||||||
bool py_tobool(const py_Ref);
|
bool py_tobool(const py_Ref);
|
||||||
const char* py_tostr(const py_Ref);
|
const char* py_tostr(const py_Ref);
|
||||||
const char* py_tostrn(const py_Ref, int* out);
|
const char* py_tostrn(const py_Ref, int* size);
|
||||||
|
|
||||||
void* py_touserdata(const py_Ref);
|
void* py_touserdata(const py_Ref);
|
||||||
|
|
||||||
@ -106,27 +100,59 @@ void* py_touserdata(const py_Ref);
|
|||||||
#define py_isstr(self) py_istype(self, tp_str)
|
#define py_isstr(self) py_istype(self, tp_str)
|
||||||
|
|
||||||
bool py_istype(const py_Ref, py_Type);
|
bool py_istype(const py_Ref, py_Type);
|
||||||
// bool py_isinstance(const py_Ref obj, py_Type type);
|
bool py_isinstance(const py_Ref obj, py_Type type);
|
||||||
// bool py_issubclass(py_Type derived, py_Type base);
|
bool py_issubclass(py_Type derived, py_Type base);
|
||||||
|
|
||||||
/************* References *************/
|
/************* References *************/
|
||||||
|
#define TypeError(x) false
|
||||||
#define py_arg(i) (py_Ref)((char*)argv + ((i) << 4))
|
#define py_arg(i) (py_Ref)((char*)argv + ((i) << 4))
|
||||||
|
#define py_checkargc(n) \
|
||||||
|
if(argc != n) return TypeError()
|
||||||
|
|
||||||
|
py_Ref py_tpmagic(py_Type type, py_Name name);
|
||||||
|
#define py_bindmagic(type, __magic__, f) py_newnativefunc(py_tpmagic((type), __magic__), (f))
|
||||||
|
|
||||||
|
// new style decl-based bindings
|
||||||
|
py_Ref py_bind(py_Ref obj, const char* sig, py_CFunction f);
|
||||||
|
py_Ref py_bind2(py_Ref obj,
|
||||||
|
const char* sig,
|
||||||
|
py_CFunction f,
|
||||||
|
BindType bt,
|
||||||
|
const char* docstring,
|
||||||
|
const py_Ref upvalue);
|
||||||
|
// old style argc-based bindings
|
||||||
|
void py_bindmethod(py_Type type, const char* name, py_CFunction f);
|
||||||
|
void py_bindmethod2(py_Type type, const char* name, py_CFunction f, BindType bt);
|
||||||
|
void py_bindnativefunc(py_Ref obj, const char* name, py_CFunction f);
|
||||||
|
|
||||||
|
/// Get the reference to the i-th register.
|
||||||
|
/// @lifespan: Permanent.
|
||||||
py_Ref py_reg(int i);
|
py_Ref py_reg(int i);
|
||||||
|
|
||||||
|
/// Get the reference of the object's `__dict__`.
|
||||||
|
/// The object must have a `__dict__`.
|
||||||
|
/// Returns a reference to the value or NULL if not found.
|
||||||
|
/// @lifespan: Object.
|
||||||
py_Ref py_getdict(const py_Ref self, py_Name name);
|
py_Ref py_getdict(const py_Ref self, py_Name name);
|
||||||
void py_setdict(py_Ref self, py_Name name, const py_Ref val);
|
void py_setdict(py_Ref self, py_Name name, const py_Ref val);
|
||||||
|
|
||||||
|
/// Get the reference of the i-th slot of the object.
|
||||||
|
/// The object must have slots and `i` must be in range.
|
||||||
|
/// @lifespan: Object.
|
||||||
py_Ref py_getslot(const py_Ref self, int i);
|
py_Ref py_getslot(const py_Ref self, int i);
|
||||||
void py_setslot(py_Ref self, int i, const py_Ref val);
|
void py_setslot(py_Ref self, int i, const py_Ref val);
|
||||||
|
|
||||||
py_Ref py_getupvalue(py_Ref self);
|
py_Ref py_getupvalue(py_Ref argv);
|
||||||
void py_setupvalue(py_Ref self, const py_Ref val);
|
void py_setupvalue(py_Ref argv, const py_Ref val);
|
||||||
|
|
||||||
/// Gets the attribute of the object.
|
/// Gets the attribute of the object.
|
||||||
bool py_getattr(const py_Ref self, py_Name name, py_Ref out);
|
bool py_getattr(const py_Ref self, py_Name name, py_Ref out);
|
||||||
/// Gets the unbound method of the object.
|
/// Gets the unbound method of the object.
|
||||||
bool py_getunboundmethod(const py_Ref self, py_Name name, bool fallback, py_Ref out, py_Ref out_self);
|
bool py_getunboundmethod(const py_Ref self,
|
||||||
|
py_Name name,
|
||||||
|
bool fallback,
|
||||||
|
py_Ref out,
|
||||||
|
py_Ref out_self);
|
||||||
/// Sets the attribute of the object.
|
/// Sets the attribute of the object.
|
||||||
bool py_setattr(py_Ref self, py_Name name, const py_Ref val);
|
bool py_setattr(py_Ref self, py_Name name, const py_Ref val);
|
||||||
/// Deletes the attribute of the object.
|
/// Deletes the attribute of the object.
|
||||||
@ -136,62 +162,102 @@ bool py_getitem(const py_Ref self, const py_Ref key, py_Ref out);
|
|||||||
bool py_setitem(py_Ref self, const py_Ref key, const py_Ref val);
|
bool py_setitem(py_Ref self, const py_Ref key, const py_Ref val);
|
||||||
bool py_delitem(py_Ref self, const py_Ref key);
|
bool py_delitem(py_Ref self, const py_Ref key);
|
||||||
|
|
||||||
|
/// Perform a binary operation on the stack.
|
||||||
|
/// It assumes `lhs` and `rhs` are already pushed to the stack.
|
||||||
|
/// The result will be set to `vm->last_retval`.
|
||||||
|
bool py_binaryop(const py_Ref lhs, const py_Ref rhs, py_Name op, py_Name rop);
|
||||||
|
|
||||||
|
#define py_binaryadd(lhs, rhs) py_binaryop(lhs, rhs, __add__, __radd__)
|
||||||
|
#define py_binarysub(lhs, rhs) py_binaryop(lhs, rhs, __sub__, __rsub__)
|
||||||
|
#define py_binarymul(lhs, rhs) py_binaryop(lhs, rhs, __mul__, __rmul__)
|
||||||
|
#define py_binarytruediv(lhs, rhs) py_binaryop(lhs, rhs, __truediv__, __rtruediv__)
|
||||||
|
#define py_binaryfloordiv(lhs, rhs) py_binaryop(lhs, rhs, __floordiv__, __rfloordiv__)
|
||||||
|
#define py_binarymod(lhs, rhs) py_binaryop(lhs, rhs, __mod__, __rmod__)
|
||||||
|
#define py_binarypow(lhs, rhs) py_binaryop(lhs, rhs, __pow__, __rpow__)
|
||||||
|
|
||||||
|
#define py_binarylshift(lhs, rhs) py_binaryop(lhs, rhs, __lshift__, 0)
|
||||||
|
#define py_binaryrshift(lhs, rhs) py_binaryop(lhs, rhs, __rshift__, 0)
|
||||||
|
#define py_binaryand(lhs, rhs) py_binaryop(lhs, rhs, __and__, 0)
|
||||||
|
#define py_binaryor(lhs, rhs) py_binaryop(lhs, rhs, __or__, 0)
|
||||||
|
#define py_binaryxor(lhs, rhs) py_binaryop(lhs, rhs, __xor__, 0)
|
||||||
|
#define py_binarymatmul(lhs, rhs) py_binaryop(lhs, rhs, __matmul__, 0)
|
||||||
|
|
||||||
/// Equivalent to `*dst = *src`.
|
/// Equivalent to `*dst = *src`.
|
||||||
void py_assign(py_Ref dst, const py_Ref src);
|
void py_assign(py_Ref dst, const py_Ref src);
|
||||||
|
|
||||||
/************* Stack Operations *************/
|
/************* Stack Operations *************/
|
||||||
py_Ref py_gettop();
|
|
||||||
void py_settop(const py_Ref);
|
|
||||||
py_Ref py_getsecond();
|
|
||||||
void py_setsecond(const py_Ref);
|
|
||||||
void py_duptop();
|
|
||||||
void py_dupsecond();
|
|
||||||
/// Returns a reference to the i-th object from the top of the stack.
|
/// Returns a reference to the i-th object from the top of the stack.
|
||||||
/// i should be negative, e.g. (-1) means TOS.
|
/// i should be negative, e.g. (-1) means TOS.
|
||||||
py_Ref py_peek(int i);
|
py_Ref py_peek(int i);
|
||||||
/// Pops an object from the stack.
|
|
||||||
void py_pop();
|
|
||||||
void py_shrink(int n);
|
|
||||||
|
|
||||||
/// Pushes the object to the stack.
|
/// Pushes the object to the stack.
|
||||||
void py_push(const py_Ref src);
|
void py_push(const py_Ref src);
|
||||||
|
/// Pops an object from the stack.
|
||||||
|
void py_pop();
|
||||||
|
/// Shrink the stack by n.
|
||||||
|
void py_shrink(int n);
|
||||||
/// Get a temporary variable from the stack and returns the reference to it.
|
/// Get a temporary variable from the stack and returns the reference to it.
|
||||||
py_Ref py_pushtmp();
|
py_Ref py_pushtmp();
|
||||||
/// Free n temporary variable.
|
/// Free n temporary variable.
|
||||||
void py_poptmp(int n);
|
#define py_poptmp(n) py_shrink(n)
|
||||||
|
|
||||||
|
#define py_gettop() py_peek(-1)
|
||||||
|
#define py_getsecond() py_peek(-2)
|
||||||
|
#define py_settop(v) py_assign(py_peek(-1), v)
|
||||||
|
#define py_setsecond(v) py_assign(py_peek(-2), v)
|
||||||
|
#define py_duptop() py_push(py_peek(-1))
|
||||||
|
#define py_dupsecond() py_push(py_peek(-2))
|
||||||
/************* Modules *************/
|
/************* Modules *************/
|
||||||
py_Ref py_newmodule(const char* name, const char* package);
|
py_Ref py_newmodule(const char* name, const char* package);
|
||||||
py_Ref py_getmodule(const char* name);
|
py_Ref py_getmodule(const char* name);
|
||||||
|
|
||||||
/// Import a module.
|
/// Import a module.
|
||||||
int py_import(const char* name, py_Ref out);
|
bool py_import(const char* name, py_Ref out);
|
||||||
|
|
||||||
/************* Errors *************/
|
/************* Errors *************/
|
||||||
py_Error* py_lasterror();
|
py_Error* py_lasterror();
|
||||||
void py_Error__print(py_Error*);
|
void py_Error__print(py_Error*);
|
||||||
|
|
||||||
/************* Operators *************/
|
/************* Operators *************/
|
||||||
|
/// Equivalent to `bool(val)`.
|
||||||
|
/// Returns 1 if `val` is truthy, otherwise 0.
|
||||||
|
/// Returns -1 if an error occurred.
|
||||||
|
int py_bool(const py_Ref val);
|
||||||
|
|
||||||
int py_eq(const py_Ref, const py_Ref);
|
int py_eq(const py_Ref, const py_Ref);
|
||||||
|
int py_ne(const py_Ref, const py_Ref);
|
||||||
int py_le(const py_Ref, const py_Ref);
|
int py_le(const py_Ref, const py_Ref);
|
||||||
|
int py_lt(const py_Ref, const py_Ref);
|
||||||
|
int py_ge(const py_Ref, const py_Ref);
|
||||||
|
int py_gt(const py_Ref, const py_Ref);
|
||||||
|
|
||||||
bool py_hash(const py_Ref, int64_t* out);
|
bool py_hash(const py_Ref, int64_t* out);
|
||||||
|
|
||||||
bool py_str(const py_Ref, py_Ref out);
|
/// Compare two objects without using magic methods.
|
||||||
bool py_repr(const py_Ref, py_Ref out);
|
bool py_isidentical(const py_Ref, const py_Ref);
|
||||||
|
|
||||||
/// A stack operation that calls a function.
|
/// A stack operation that calls a function.
|
||||||
/// It consumes `argc + kwargc` arguments from the stack.
|
/// It assumes `argc + kwargc` arguments are already pushed to the stack.
|
||||||
/// The result will be set to `vm->last_retval`.
|
/// The result will be set to `vm->last_retval`.
|
||||||
int pk_vectorcall(int argc, int kwargc, bool op_call);
|
/// The stack size will be reduced by `argc + kwargc`.
|
||||||
|
bool pk_vectorcall(int argc, int kwargc, bool op_call);
|
||||||
/// Call a function.
|
/// Call a function.
|
||||||
/// It prepares the stack and then performs a `vectorcall(argc, 0, false)`.
|
/// It prepares the stack and then performs a `vectorcall(argc, 0, false)`.
|
||||||
/// The result will be set to `vm->last_retval`.
|
/// The result will be set to `vm->last_retval`.
|
||||||
|
/// The stack remains unchanged after the operation.
|
||||||
bool py_call(py_Ref f, int argc, py_Ref argv);
|
bool py_call(py_Ref f, int argc, py_Ref argv);
|
||||||
/// Call a method.
|
/// Call a non-magic method.
|
||||||
/// It prepares the stack and then performs a `vectorcall(argc+1, 0, false)`.
|
/// It prepares the stack and then performs a `vectorcall(argc+1, 0, false)`.
|
||||||
/// The result will be set to `vm->last_retval`.
|
/// The result will be set to `vm->last_retval`.
|
||||||
bool py_callmethod(py_Ref self, py_Name name, int argc, py_Ref argv);
|
/// The stack remains unchanged after the operation.
|
||||||
|
bool py_callmethod(py_Ref self, py_Name, int argc, py_Ref argv);
|
||||||
|
/// Call a magic method.
|
||||||
|
/// The result will be set to `vm->last_retval`.
|
||||||
|
/// The stack remains unchanged after the operation.
|
||||||
|
bool py_callmagic(py_Name name, int argc, py_Ref argv);
|
||||||
|
|
||||||
|
#define py_repr(self) py_callmagic(__repr__, 1, self)
|
||||||
|
#define py_str(self) py_callmagic(__str__, 1, self)
|
||||||
|
|
||||||
/// The return value of the most recent vectorcall.
|
/// The return value of the most recent vectorcall.
|
||||||
py_Ref py_lastretval();
|
py_Ref py_lastretval();
|
||||||
|
|
||||||
@ -217,6 +283,19 @@ void py_list__insert(py_Ref self, int i, const py_Ref val);
|
|||||||
typedef struct pk_TypeInfo pk_TypeInfo;
|
typedef struct pk_TypeInfo pk_TypeInfo;
|
||||||
pk_TypeInfo* pk_tpinfo(const py_Ref self);
|
pk_TypeInfo* pk_tpinfo(const py_Ref self);
|
||||||
|
|
||||||
|
/// Search the magic method from the given type to the base type.
|
||||||
|
/// Returns the reference or NULL if not found.
|
||||||
|
/// @lifespan: Permanent.
|
||||||
|
py_Ref py_tpfindmagic(py_Type, py_Name name);
|
||||||
|
|
||||||
|
/// Get the type object of the given type.
|
||||||
|
/// @lifespan: Permanent.
|
||||||
|
py_Ref py_tpobject(py_Type type);
|
||||||
|
|
||||||
|
#define MAGIC_METHOD(x) extern uint16_t x;
|
||||||
|
#include "pocketpy/xmacros/magics.h"
|
||||||
|
#undef MAGIC_METHOD
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
62
include/pocketpy/xmacros/magics.h
Normal file
62
include/pocketpy/xmacros/magics.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#ifdef MAGIC_METHOD
|
||||||
|
|
||||||
|
// unary operators
|
||||||
|
MAGIC_METHOD(__repr__)
|
||||||
|
MAGIC_METHOD(__str__)
|
||||||
|
MAGIC_METHOD(__hash__)
|
||||||
|
MAGIC_METHOD(__len__)
|
||||||
|
MAGIC_METHOD(__iter__)
|
||||||
|
MAGIC_METHOD(__next__)
|
||||||
|
MAGIC_METHOD(__neg__)
|
||||||
|
MAGIC_METHOD(__invert__)
|
||||||
|
// logical operators
|
||||||
|
MAGIC_METHOD(__contains__)
|
||||||
|
/////////////////////////////
|
||||||
|
MAGIC_METHOD(__eq__)
|
||||||
|
MAGIC_METHOD(__ne__)
|
||||||
|
MAGIC_METHOD(__lt__)
|
||||||
|
MAGIC_METHOD(__le__)
|
||||||
|
MAGIC_METHOD(__gt__)
|
||||||
|
MAGIC_METHOD(__ge__)
|
||||||
|
// binary operators
|
||||||
|
MAGIC_METHOD(__add__)
|
||||||
|
MAGIC_METHOD(__radd__)
|
||||||
|
MAGIC_METHOD(__sub__)
|
||||||
|
MAGIC_METHOD(__rsub__)
|
||||||
|
MAGIC_METHOD(__mul__)
|
||||||
|
MAGIC_METHOD(__rmul__)
|
||||||
|
MAGIC_METHOD(__truediv__)
|
||||||
|
MAGIC_METHOD(__rtruediv__)
|
||||||
|
MAGIC_METHOD(__floordiv__)
|
||||||
|
MAGIC_METHOD(__rfloordiv__)
|
||||||
|
MAGIC_METHOD(__mod__)
|
||||||
|
MAGIC_METHOD(__rmod__)
|
||||||
|
MAGIC_METHOD(__pow__)
|
||||||
|
MAGIC_METHOD(__rpow__)
|
||||||
|
MAGIC_METHOD(__matmul__)
|
||||||
|
MAGIC_METHOD(__lshift__)
|
||||||
|
MAGIC_METHOD(__rshift__)
|
||||||
|
MAGIC_METHOD(__and__)
|
||||||
|
MAGIC_METHOD(__or__)
|
||||||
|
MAGIC_METHOD(__xor__)
|
||||||
|
/////////////////////////////
|
||||||
|
// indexer
|
||||||
|
MAGIC_METHOD(__getitem__)
|
||||||
|
MAGIC_METHOD(__setitem__)
|
||||||
|
MAGIC_METHOD(__delitem__)
|
||||||
|
|
||||||
|
// specials
|
||||||
|
MAGIC_METHOD(__new__)
|
||||||
|
MAGIC_METHOD(__init__)
|
||||||
|
MAGIC_METHOD(__call__)
|
||||||
|
MAGIC_METHOD(__divmod__)
|
||||||
|
MAGIC_METHOD(__enter__)
|
||||||
|
MAGIC_METHOD(__exit__)
|
||||||
|
MAGIC_METHOD(__name__)
|
||||||
|
MAGIC_METHOD(__all__)
|
||||||
|
MAGIC_METHOD(__package__)
|
||||||
|
MAGIC_METHOD(__path__)
|
||||||
|
MAGIC_METHOD(__class__)
|
||||||
|
MAGIC_METHOD(__missing__)
|
||||||
|
|
||||||
|
#endif
|
@ -52,39 +52,9 @@ OPCODE(BUILD_SET)
|
|||||||
OPCODE(BUILD_SLICE)
|
OPCODE(BUILD_SLICE)
|
||||||
OPCODE(BUILD_STRING)
|
OPCODE(BUILD_STRING)
|
||||||
/**************************/
|
/**************************/
|
||||||
OPCODE(BUILD_TUPLE_UNPACK)
|
OPCODE(BINARY_OP)
|
||||||
OPCODE(BUILD_LIST_UNPACK)
|
|
||||||
OPCODE(BUILD_DICT_UNPACK)
|
|
||||||
OPCODE(BUILD_SET_UNPACK)
|
|
||||||
/**************************/
|
|
||||||
OPCODE(BINARY_TRUEDIV)
|
|
||||||
OPCODE(BINARY_POW)
|
|
||||||
|
|
||||||
OPCODE(BINARY_ADD)
|
|
||||||
OPCODE(BINARY_SUB)
|
|
||||||
OPCODE(BINARY_MUL)
|
|
||||||
OPCODE(BINARY_FLOORDIV)
|
|
||||||
OPCODE(BINARY_MOD)
|
|
||||||
|
|
||||||
OPCODE(COMPARE_LT)
|
|
||||||
OPCODE(COMPARE_LE)
|
|
||||||
OPCODE(COMPARE_EQ)
|
|
||||||
OPCODE(COMPARE_NE)
|
|
||||||
OPCODE(COMPARE_GT)
|
|
||||||
OPCODE(COMPARE_GE)
|
|
||||||
|
|
||||||
OPCODE(BITWISE_LSHIFT)
|
|
||||||
OPCODE(BITWISE_RSHIFT)
|
|
||||||
OPCODE(BITWISE_AND)
|
|
||||||
OPCODE(BITWISE_OR)
|
|
||||||
OPCODE(BITWISE_XOR)
|
|
||||||
|
|
||||||
OPCODE(BINARY_MATMUL)
|
|
||||||
|
|
||||||
OPCODE(IS_OP)
|
OPCODE(IS_OP)
|
||||||
OPCODE(IS_NOT_OP)
|
OPCODE(CONTAINS_OP)
|
||||||
OPCODE(IN_OP)
|
|
||||||
OPCODE(NOT_IN_OP)
|
|
||||||
/**************************/
|
/**************************/
|
||||||
OPCODE(JUMP_FORWARD)
|
OPCODE(JUMP_FORWARD)
|
||||||
OPCODE(POP_JUMP_IF_FALSE)
|
OPCODE(POP_JUMP_IF_FALSE)
|
||||||
@ -101,7 +71,7 @@ OPCODE(GOTO)
|
|||||||
OPCODE(FSTRING_EVAL)
|
OPCODE(FSTRING_EVAL)
|
||||||
OPCODE(REPR)
|
OPCODE(REPR)
|
||||||
OPCODE(CALL)
|
OPCODE(CALL)
|
||||||
OPCODE(CALL_TP)
|
OPCODE(CALL_VARGS)
|
||||||
OPCODE(RETURN_VALUE)
|
OPCODE(RETURN_VALUE)
|
||||||
OPCODE(YIELD_VALUE)
|
OPCODE(YIELD_VALUE)
|
||||||
/**************************/
|
/**************************/
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
#include "pocketpy/common/any.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
void c11_userdata__ctor(c11_userdata* self, void* ptr, int size){
|
|
||||||
memcpy(self, ptr, size);
|
|
||||||
}
|
|
@ -19,57 +19,14 @@ void pk_StrName__initialize(){
|
|||||||
c11_vector__ctor(&_r_interned, sizeof(c11_string));
|
c11_vector__ctor(&_r_interned, sizeof(c11_string));
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
|
|
||||||
// unary operators
|
#define MAGIC_METHOD(x) x = pk_StrName__map(#x);
|
||||||
__repr__ = pk_StrName__map("__repr__");
|
#include "pocketpy/xmacros/magics.h"
|
||||||
__str__ = pk_StrName__map("__str__");
|
#undef MAGIC_METHOD
|
||||||
__hash__ = pk_StrName__map("__hash__");
|
|
||||||
__len__ = pk_StrName__map("__len__");
|
|
||||||
__iter__ = pk_StrName__map("__iter__");
|
|
||||||
__next__ = pk_StrName__map("__next__");
|
|
||||||
__neg__ = pk_StrName__map("__neg__");
|
|
||||||
// logical operators
|
|
||||||
__eq__ = pk_StrName__map("__eq__");
|
|
||||||
__lt__ = pk_StrName__map("__lt__");
|
|
||||||
__le__ = pk_StrName__map("__le__");
|
|
||||||
__gt__ = pk_StrName__map("__gt__");
|
|
||||||
__ge__ = pk_StrName__map("__ge__");
|
|
||||||
__contains__ = pk_StrName__map("__contains__");
|
|
||||||
// binary operators
|
|
||||||
__add__ = pk_StrName__map("__add__");
|
|
||||||
__radd__ = pk_StrName__map("__radd__");
|
|
||||||
__sub__ = pk_StrName__map("__sub__");
|
|
||||||
__rsub__ = pk_StrName__map("__rsub__");
|
|
||||||
__mul__ = pk_StrName__map("__mul__");
|
|
||||||
__rmul__ = pk_StrName__map("__rmul__");
|
|
||||||
__truediv__ = pk_StrName__map("__truediv__");
|
|
||||||
__floordiv__ = pk_StrName__map("__floordiv__");
|
|
||||||
__mod__ = pk_StrName__map("__mod__");
|
|
||||||
__pow__ = pk_StrName__map("__pow__");
|
|
||||||
__matmul__ = pk_StrName__map("__matmul__");
|
|
||||||
__lshift__ = pk_StrName__map("__lshift__");
|
|
||||||
__rshift__ = pk_StrName__map("__rshift__");
|
|
||||||
__and__ = pk_StrName__map("__and__");
|
|
||||||
__or__ = pk_StrName__map("__or__");
|
|
||||||
__xor__ = pk_StrName__map("__xor__");
|
|
||||||
__invert__ = pk_StrName__map("__invert__");
|
|
||||||
// indexer
|
|
||||||
__getitem__ = pk_StrName__map("__getitem__");
|
|
||||||
__setitem__ = pk_StrName__map("__setitem__");
|
|
||||||
__delitem__ = pk_StrName__map("__delitem__");
|
|
||||||
|
|
||||||
// specials
|
// print all names
|
||||||
__new__ = pk_StrName__map("__new__");
|
for(int i = 0; i < _interned.count; i++) {
|
||||||
__init__ = pk_StrName__map("__init__");
|
printf("%d: %s\n", i + 1, c11__getitem(char*, &_r_interned, i));
|
||||||
__call__ = pk_StrName__map("__call__");
|
}
|
||||||
__divmod__ = pk_StrName__map("__divmod__");
|
|
||||||
__enter__ = pk_StrName__map("__enter__");
|
|
||||||
__exit__ = pk_StrName__map("__exit__");
|
|
||||||
__name__ = pk_StrName__map("__name__");
|
|
||||||
__all__ = pk_StrName__map("__all__");
|
|
||||||
__package__ = pk_StrName__map("__package__");
|
|
||||||
__path__ = pk_StrName__map("__path__");
|
|
||||||
__class__ = pk_StrName__map("__class__");
|
|
||||||
__missing__ = pk_StrName__map("__missing__");
|
|
||||||
|
|
||||||
pk_id_add = pk_StrName__map("add");
|
pk_id_add = pk_StrName__map("add");
|
||||||
pk_id_set = pk_StrName__map("set");
|
pk_id_set = pk_StrName__map("set");
|
||||||
@ -99,9 +56,7 @@ uint16_t pk_StrName__map2(c11_string name){
|
|||||||
uint16_t index = c11_smallmap_s2n__get(&_interned, name, 0);
|
uint16_t index = c11_smallmap_s2n__get(&_interned, name, 0);
|
||||||
if(index != 0) return index;
|
if(index != 0) return index;
|
||||||
// generate new index
|
// generate new index
|
||||||
if(_interned.count > 65530){
|
if(_interned.count > 65530) { PK_FATAL_ERROR("StrName index overflow\n"); }
|
||||||
PK_FATAL_ERROR("StrName index overflow\n");
|
|
||||||
}
|
|
||||||
// NOTE: we must allocate the string in the heap so iterators are not invalidated
|
// NOTE: we must allocate the string in the heap so iterators are not invalidated
|
||||||
char* p = malloc(name.size + 1);
|
char* p = malloc(name.size + 1);
|
||||||
memcpy(p, name.data, name.size);
|
memcpy(p, name.data, name.size);
|
||||||
@ -125,59 +80,10 @@ c11_string pk_StrName__rmap2(uint16_t index){
|
|||||||
return (c11_string){p, strlen(p)};
|
return (c11_string){p, strlen(p)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////
|
||||||
|
#define MAGIC_METHOD(x) uint16_t x;
|
||||||
// unary operators
|
#include "pocketpy/xmacros/magics.h"
|
||||||
uint16_t __repr__;
|
#undef MAGIC_METHOD
|
||||||
uint16_t __str__;
|
|
||||||
uint16_t __hash__;
|
|
||||||
uint16_t __len__;
|
|
||||||
uint16_t __iter__;
|
|
||||||
uint16_t __next__;
|
|
||||||
uint16_t __neg__;
|
|
||||||
// logical operators
|
|
||||||
uint16_t __eq__;
|
|
||||||
uint16_t __lt__;
|
|
||||||
uint16_t __le__;
|
|
||||||
uint16_t __gt__;
|
|
||||||
uint16_t __ge__;
|
|
||||||
uint16_t __contains__;
|
|
||||||
// binary operators
|
|
||||||
uint16_t __add__;
|
|
||||||
uint16_t __radd__;
|
|
||||||
uint16_t __sub__;
|
|
||||||
uint16_t __rsub__;
|
|
||||||
uint16_t __mul__;
|
|
||||||
uint16_t __rmul__;
|
|
||||||
uint16_t __truediv__;
|
|
||||||
uint16_t __floordiv__;
|
|
||||||
uint16_t __mod__;
|
|
||||||
uint16_t __pow__;
|
|
||||||
uint16_t __matmul__;
|
|
||||||
uint16_t __lshift__;
|
|
||||||
uint16_t __rshift__;
|
|
||||||
uint16_t __and__;
|
|
||||||
uint16_t __or__;
|
|
||||||
uint16_t __xor__;
|
|
||||||
uint16_t __invert__;
|
|
||||||
// indexer
|
|
||||||
uint16_t __getitem__;
|
|
||||||
uint16_t __setitem__;
|
|
||||||
uint16_t __delitem__;
|
|
||||||
|
|
||||||
// specials
|
|
||||||
uint16_t __new__;
|
|
||||||
uint16_t __init__;
|
|
||||||
uint16_t __call__;
|
|
||||||
uint16_t __divmod__;
|
|
||||||
uint16_t __enter__;
|
|
||||||
uint16_t __exit__;
|
|
||||||
uint16_t __name__;
|
|
||||||
uint16_t __all__;
|
|
||||||
uint16_t __package__;
|
|
||||||
uint16_t __path__;
|
|
||||||
uint16_t __class__;
|
|
||||||
uint16_t __missing__;
|
|
||||||
|
|
||||||
uint16_t pk_id_add;
|
uint16_t pk_id_add;
|
||||||
uint16_t pk_id_set;
|
uint16_t pk_id_set;
|
||||||
|
@ -849,19 +849,19 @@ static void BinaryExpr__dtor(Expr* self_) {
|
|||||||
vtdelete(self->rhs);
|
vtdelete(self->rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Opcode cmp_token2op(TokenIndex token) {
|
static Opcode cmp_token2name(TokenIndex token) {
|
||||||
switch(token) {
|
switch(token) {
|
||||||
case TK_LT: return OP_COMPARE_LT; break;
|
case TK_LT: return __lt__;
|
||||||
case TK_LE: return OP_COMPARE_LE; break;
|
case TK_LE: return __le__;
|
||||||
case TK_EQ: return OP_COMPARE_EQ; break;
|
case TK_EQ: return __eq__;
|
||||||
case TK_NE: return OP_COMPARE_NE; break;
|
case TK_NE: return __ne__;
|
||||||
case TK_GT: return OP_COMPARE_GT; break;
|
case TK_GT: return __gt__;
|
||||||
case TK_GE: return OP_COMPARE_GE; break;
|
case TK_GE: return __ge__;
|
||||||
default: return OP_NO_OP; // 0
|
default: return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define is_compare_expr(e) ((e)->vt->is_binary && cmp_token2op(((BinaryExpr*)(e))->op))
|
#define is_compare_expr(e) ((e)->vt->is_binary && cmp_token2name(((BinaryExpr*)(e))->op))
|
||||||
|
|
||||||
static void _emit_compare(BinaryExpr* self, Ctx* ctx, c11_vector* jmps) {
|
static void _emit_compare(BinaryExpr* self, Ctx* ctx, c11_vector* jmps) {
|
||||||
if(is_compare_expr(self->lhs)) {
|
if(is_compare_expr(self->lhs)) {
|
||||||
@ -872,8 +872,7 @@ static void _emit_compare(BinaryExpr* self, Ctx* ctx, c11_vector* jmps) {
|
|||||||
vtemit_(self->rhs, ctx); // [a, b]
|
vtemit_(self->rhs, ctx); // [a, b]
|
||||||
Ctx__emit_(ctx, OP_DUP_TOP, BC_NOARG, self->line); // [a, b, b]
|
Ctx__emit_(ctx, OP_DUP_TOP, BC_NOARG, self->line); // [a, b, b]
|
||||||
Ctx__emit_(ctx, OP_ROT_THREE, BC_NOARG, self->line); // [b, a, b]
|
Ctx__emit_(ctx, OP_ROT_THREE, BC_NOARG, self->line); // [b, a, b]
|
||||||
Opcode opcode = cmp_token2op(self->op);
|
Ctx__emit_(ctx, OP_BINARY_OP, cmp_token2name(self->op), self->line);
|
||||||
Ctx__emit_(ctx, opcode, BC_NOARG, self->line);
|
|
||||||
// [b, RES]
|
// [b, RES]
|
||||||
int index = Ctx__emit_(ctx, OP_JUMP_IF_FALSE_OR_POP, BC_NOARG, self->line);
|
int index = Ctx__emit_(ctx, OP_JUMP_IF_FALSE_OR_POP, BC_NOARG, self->line);
|
||||||
c11_vector__push(int, jmps, index);
|
c11_vector__push(int, jmps, index);
|
||||||
@ -883,7 +882,7 @@ static void BinaryExpr__emit_(Expr* self_, Ctx* ctx) {
|
|||||||
BinaryExpr* self = (BinaryExpr*)self_;
|
BinaryExpr* self = (BinaryExpr*)self_;
|
||||||
c11_vector /*T=int*/ jmps;
|
c11_vector /*T=int*/ jmps;
|
||||||
c11_vector__ctor(&jmps, sizeof(int));
|
c11_vector__ctor(&jmps, sizeof(int));
|
||||||
if(cmp_token2op(self->op) && is_compare_expr(self->lhs)) {
|
if(cmp_token2name(self->op) && is_compare_expr(self->lhs)) {
|
||||||
// (a < b) < c
|
// (a < b) < c
|
||||||
BinaryExpr* e = (BinaryExpr*)self->lhs;
|
BinaryExpr* e = (BinaryExpr*)self->lhs;
|
||||||
_emit_compare(e, ctx, &jmps);
|
_emit_compare(e, ctx, &jmps);
|
||||||
@ -898,41 +897,57 @@ static void BinaryExpr__emit_(Expr* self_, Ctx* ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vtemit_(self->rhs, ctx);
|
vtemit_(self->rhs, ctx);
|
||||||
Opcode opcode;
|
|
||||||
|
Opcode opcode = OP_BINARY_OP;
|
||||||
|
uint16_t arg = BC_NOARG;
|
||||||
|
|
||||||
switch(self->op) {
|
switch(self->op) {
|
||||||
case TK_ADD: opcode = OP_BINARY_ADD; break;
|
case TK_ADD: arg = __add__ | (__radd__ << 8); break;
|
||||||
case TK_SUB: opcode = OP_BINARY_SUB; break;
|
case TK_SUB: arg = __sub__ | (__rsub__ << 8); break;
|
||||||
case TK_MUL: opcode = OP_BINARY_MUL; break;
|
case TK_MUL: arg = __mul__ | (__rmul__ << 8); break;
|
||||||
case TK_DIV: opcode = OP_BINARY_TRUEDIV; break;
|
case TK_DIV: arg = __truediv__ | (__rtruediv__ << 8); break;
|
||||||
case TK_FLOORDIV: opcode = OP_BINARY_FLOORDIV; break;
|
case TK_FLOORDIV: arg = __floordiv__ | (__rfloordiv__ << 8); break;
|
||||||
case TK_MOD: opcode = OP_BINARY_MOD; break;
|
case TK_MOD: arg = __mod__ | (__rmod__ << 8); break;
|
||||||
case TK_POW: opcode = OP_BINARY_POW; break;
|
case TK_POW: arg = __pow__ | (__rpow__ << 8); break;
|
||||||
|
|
||||||
case TK_LT: opcode = OP_COMPARE_LT; break;
|
case TK_LT: arg = __lt__ | (__gt__ << 8); break;
|
||||||
case TK_LE: opcode = OP_COMPARE_LE; break;
|
case TK_LE: arg = __le__ | (__ge__ << 8); break;
|
||||||
case TK_EQ: opcode = OP_COMPARE_EQ; break;
|
case TK_EQ: arg = __eq__ | (__eq__ << 8); break;
|
||||||
case TK_NE: opcode = OP_COMPARE_NE; break;
|
case TK_NE: arg = __ne__ | (__ne__ << 8); break;
|
||||||
case TK_GT: opcode = OP_COMPARE_GT; break;
|
case TK_GT: arg = __gt__ | (__lt__ << 8); break;
|
||||||
case TK_GE: opcode = OP_COMPARE_GE; break;
|
case TK_GE: arg = __ge__ | (__le__ << 8); break;
|
||||||
|
|
||||||
case TK_IN: opcode = OP_IN_OP; break;
|
case TK_IN:
|
||||||
case TK_NOT_IN: opcode = OP_NOT_IN_OP; break;
|
opcode = OP_CONTAINS_OP;
|
||||||
case TK_IS: opcode = OP_IS_OP; break;
|
arg = 0;
|
||||||
case TK_IS_NOT: opcode = OP_IS_NOT_OP; break;
|
break;
|
||||||
|
case TK_NOT_IN:
|
||||||
|
opcode = OP_CONTAINS_OP;
|
||||||
|
arg = 1;
|
||||||
|
break;
|
||||||
|
case TK_IS:
|
||||||
|
opcode = OP_IS_OP;
|
||||||
|
arg = 0;
|
||||||
|
break;
|
||||||
|
case TK_IS_NOT:
|
||||||
|
opcode = OP_IS_OP;
|
||||||
|
arg = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
case TK_LSHIFT: opcode = OP_BITWISE_LSHIFT; break;
|
case TK_LSHIFT: arg = __lshift__; break;
|
||||||
case TK_RSHIFT: opcode = OP_BITWISE_RSHIFT; break;
|
case TK_RSHIFT: arg = __rshift__; break;
|
||||||
case TK_AND: opcode = OP_BITWISE_AND; break;
|
case TK_AND: arg = __and__; break;
|
||||||
case TK_OR: opcode = OP_BITWISE_OR; break;
|
case TK_OR: arg = __or__; break;
|
||||||
case TK_XOR: opcode = OP_BITWISE_XOR; break;
|
case TK_XOR: arg = __xor__; break;
|
||||||
|
case TK_DECORATOR: arg = __matmul__; break;
|
||||||
case TK_DECORATOR: opcode = OP_BINARY_MATMUL; break;
|
|
||||||
default: assert(false);
|
default: assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ctx__emit_(ctx, opcode, BC_NOARG, self->line);
|
Ctx__emit_(ctx, opcode, arg, self->line);
|
||||||
|
|
||||||
c11__foreach(int, &jmps, i) { Ctx__patch_jump(ctx, *i); }
|
for(int i = 0; i < jmps.count; i++) {
|
||||||
|
Ctx__patch_jump(ctx, c11__getitem(int, &jmps, i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BinaryExpr* BinaryExpr__new(int line, TokenIndex op, bool inplace) {
|
BinaryExpr* BinaryExpr__new(int line, TokenIndex op, bool inplace) {
|
||||||
@ -1137,8 +1152,8 @@ void CallExpr__dtor(Expr* self_) {
|
|||||||
void CallExpr__emit_(Expr* self_, Ctx* ctx) {
|
void CallExpr__emit_(Expr* self_, Ctx* ctx) {
|
||||||
CallExpr* self = (CallExpr*)self_;
|
CallExpr* self = (CallExpr*)self_;
|
||||||
|
|
||||||
bool vargs = false;
|
bool vargs = false; // whether there is *args as input
|
||||||
bool vkwargs = false;
|
bool vkwargs = false; // whether there is **kwargs as input
|
||||||
c11__foreach(Expr*, &self->args, e) {
|
c11__foreach(Expr*, &self->args, e) {
|
||||||
if((*e)->vt->is_starred) vargs = true;
|
if((*e)->vt->is_starred) vargs = true;
|
||||||
}
|
}
|
||||||
@ -1147,7 +1162,6 @@ void CallExpr__emit_(Expr* self_, Ctx* ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if callable is a AttrExpr, we should try to use `fast_call` instead of use `boundmethod`
|
// if callable is a AttrExpr, we should try to use `fast_call` instead of use `boundmethod`
|
||||||
// proxy
|
|
||||||
if(self->callable->vt->is_attrib) {
|
if(self->callable->vt->is_attrib) {
|
||||||
AttribExpr* p = (AttribExpr*)self->callable;
|
AttribExpr* p = (AttribExpr*)self->callable;
|
||||||
vtemit_(p->child, ctx);
|
vtemit_(p->child, ctx);
|
||||||
@ -1157,41 +1171,22 @@ void CallExpr__emit_(Expr* self_, Ctx* ctx) {
|
|||||||
Ctx__emit_(ctx, OP_LOAD_NULL, BC_NOARG, BC_KEEPLINE);
|
Ctx__emit_(ctx, OP_LOAD_NULL, BC_NOARG, BC_KEEPLINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
c11__foreach(Expr*, &self->args, e) { vtemit_(*e, ctx); }
|
Opcode opcode = OP_CALL;
|
||||||
|
|
||||||
if(vargs || vkwargs) {
|
if(vargs || vkwargs) {
|
||||||
Ctx__emit_(ctx, OP_BUILD_TUPLE_UNPACK, (uint16_t)self->args.count, self->line);
|
// in this case, there is at least one *args or **kwargs as StarredExpr
|
||||||
|
// OP_CALL_VARGS needs to unpack them via __vectorcall_buffer
|
||||||
|
opcode = OP_CALL_VARGS;
|
||||||
|
}
|
||||||
|
|
||||||
if(self->kwargs.count != 0) {
|
c11__foreach(Expr*, &self->args, e) { vtemit_(*e, ctx); }
|
||||||
c11__foreach(CallExprKwArg, &self->kwargs, e) {
|
|
||||||
if(e->val->vt->is_starred) {
|
|
||||||
// **kwargs
|
|
||||||
StarredExpr* se = (StarredExpr*)e->val;
|
|
||||||
assert(se->level == 2 && e->key == 0);
|
|
||||||
vtemit_(e->val, ctx);
|
|
||||||
} else {
|
|
||||||
// k=v
|
|
||||||
int index = Ctx__add_const_string(ctx, pk_StrName__rmap2(e->key));
|
|
||||||
Ctx__emit_(ctx, OP_LOAD_CONST, index, self->line);
|
|
||||||
vtemit_(e->val, ctx);
|
|
||||||
Ctx__emit_(ctx, OP_BUILD_TUPLE, 2, self->line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ctx__emit_(ctx, OP_BUILD_DICT_UNPACK, self->kwargs.count, self->line);
|
|
||||||
Ctx__emit_(ctx, OP_CALL_TP, 1, self->line);
|
|
||||||
} else {
|
|
||||||
Ctx__emit_(ctx, OP_CALL_TP, 0, self->line);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// vectorcall protocol
|
|
||||||
c11__foreach(CallExprKwArg, &self->kwargs, e) {
|
c11__foreach(CallExprKwArg, &self->kwargs, e) {
|
||||||
Ctx__emit_int(ctx, e->key, self->line);
|
Ctx__emit_int(ctx, e->key, self->line);
|
||||||
vtemit_(e->val, ctx);
|
vtemit_(e->val, ctx);
|
||||||
}
|
}
|
||||||
int KWARGC = self->kwargs.count;
|
int KWARGC = self->kwargs.count;
|
||||||
int ARGC = self->args.count;
|
int ARGC = self->args.count;
|
||||||
Ctx__emit_(ctx, OP_CALL, (KWARGC << 8) | ARGC, self->line);
|
assert(KWARGC < 256 && ARGC < 256);
|
||||||
}
|
Ctx__emit_(ctx, opcode, (KWARGC << 8) | ARGC, self->line);
|
||||||
}
|
}
|
||||||
|
|
||||||
CallExpr* CallExpr__new(int line, Expr* callable) {
|
CallExpr* CallExpr__new(int line, Expr* callable) {
|
||||||
@ -1750,8 +1745,13 @@ static Error* exprBinaryOp(Compiler* self) {
|
|||||||
TokenIndex op = prev()->type;
|
TokenIndex op = prev()->type;
|
||||||
check(parse_expression(self, rules[op].precedence + 1, false));
|
check(parse_expression(self, rules[op].precedence + 1, false));
|
||||||
BinaryExpr* e = BinaryExpr__new(line, op, false);
|
BinaryExpr* e = BinaryExpr__new(line, op, false);
|
||||||
|
if(op == TK_IN || op == TK_NOT_IN) {
|
||||||
|
e->lhs = Ctx__s_popx(ctx());
|
||||||
|
e->rhs = Ctx__s_popx(ctx());
|
||||||
|
} else {
|
||||||
e->rhs = Ctx__s_popx(ctx());
|
e->rhs = Ctx__s_popx(ctx());
|
||||||
e->lhs = Ctx__s_popx(ctx());
|
e->lhs = Ctx__s_popx(ctx());
|
||||||
|
}
|
||||||
Ctx__s_push(ctx(), (Expr*)e);
|
Ctx__s_push(ctx(), (Expr*)e);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,10 @@ int UnboundLocalError(py_Name name) { return -1; }
|
|||||||
|
|
||||||
int NameError(py_Name name) { return -1; }
|
int NameError(py_Name name) { return -1; }
|
||||||
|
|
||||||
#define AttributeError(obj, name)
|
#define AttributeError(obj, name) false
|
||||||
|
#define BinaryOptError(op) false
|
||||||
|
|
||||||
|
static bool stack_binaryop(pk_VM* self, py_Name op, py_Name rop);
|
||||||
|
|
||||||
#define DISPATCH() \
|
#define DISPATCH() \
|
||||||
do { \
|
do { \
|
||||||
@ -38,6 +41,13 @@ int NameError(py_Name name) { return -1; }
|
|||||||
#define POPX() (*--self->stack.sp)
|
#define POPX() (*--self->stack.sp)
|
||||||
#define SP() (self->stack.sp)
|
#define SP() (self->stack.sp)
|
||||||
|
|
||||||
|
// [a, b] -> [?, a, b]
|
||||||
|
#define INSERT_THIRD() \
|
||||||
|
do { \
|
||||||
|
PUSH(TOP()); \
|
||||||
|
*SECOND() = *THIRD(); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
#define vectorcall_opcall(n) \
|
#define vectorcall_opcall(n) \
|
||||||
do { \
|
do { \
|
||||||
pk_FrameResult res = pk_vectorcall(n, 0, true); \
|
pk_FrameResult res = pk_vectorcall(n, 0, true); \
|
||||||
@ -104,8 +114,9 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
|||||||
}
|
}
|
||||||
case OP_PRINT_EXPR:
|
case OP_PRINT_EXPR:
|
||||||
if(TOP()->type != tp_none_type) {
|
if(TOP()->type != tp_none_type) {
|
||||||
py_TValue tmp;
|
bool ok = py_repr(TOP());
|
||||||
if(py_repr(TOP(), &tmp)) self->_stdout("%s\n", py_tostr(&tmp));
|
if(!ok) goto __ERROR;
|
||||||
|
self->_stdout("%s\n", py_tostr(&self->last_retval));
|
||||||
}
|
}
|
||||||
POP();
|
POP();
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
@ -247,20 +258,23 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
|||||||
}
|
}
|
||||||
case OP_LOAD_SUBSCR: {
|
case OP_LOAD_SUBSCR: {
|
||||||
// [a, b] -> a[b]
|
// [a, b] -> a[b]
|
||||||
pk_TypeInfo* ti = pk_tpinfo(SECOND());
|
py_Ref magic = py_tpfindmagic(SECOND()->type, __getitem__);
|
||||||
if(ti->m__getitem__) {
|
if(magic) {
|
||||||
if(!ti->m__getitem__(2, SECOND(), SECOND())) goto __ERROR;
|
if(magic->type == tp_nativefunc) {
|
||||||
} else {
|
bool ok = magic->_cfunc(2, SECOND());
|
||||||
// [a, b] -> [?, a, b]
|
|
||||||
PUSH(TOP()); // [a, b, b]
|
|
||||||
*SECOND() = *THIRD(); // [a, a, b]
|
|
||||||
bool ok = py_getunboundmethod(SECOND(), __getitem__, false, THIRD(), SECOND());
|
|
||||||
// [__getitem__, self, b]
|
|
||||||
if(!ok) goto __ERROR;
|
if(!ok) goto __ERROR;
|
||||||
|
POP();
|
||||||
|
*TOP() = self->last_retval;
|
||||||
|
} else {
|
||||||
|
INSERT_THIRD(); // [?, a, b]
|
||||||
|
*THIRD() = *magic; // [__getitem__, a, b]
|
||||||
vectorcall_opcall(2);
|
vectorcall_opcall(2);
|
||||||
}
|
}
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
TypeError();
|
||||||
|
goto __ERROR;
|
||||||
|
}
|
||||||
case OP_STORE_FAST: frame->locals[byte.arg] = POPX(); DISPATCH();
|
case OP_STORE_FAST: frame->locals[byte.arg] = POPX(); DISPATCH();
|
||||||
case OP_STORE_NAME: {
|
case OP_STORE_NAME: {
|
||||||
py_Name _name = byte.arg;
|
py_Name _name = byte.arg;
|
||||||
@ -296,20 +310,25 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
|||||||
}
|
}
|
||||||
case OP_STORE_SUBSCR: {
|
case OP_STORE_SUBSCR: {
|
||||||
// [val, a, b] -> a[b] = val
|
// [val, a, b] -> a[b] = val
|
||||||
pk_TypeInfo* ti = pk_tpinfo(SECOND());
|
|
||||||
PUSH(THIRD()); // [val, a, b, val]
|
PUSH(THIRD()); // [val, a, b, val]
|
||||||
if(ti->m__setitem__) {
|
py_Ref magic = py_tpfindmagic(SECOND()->type, __setitem__);
|
||||||
if(!ti->m__setitem__(3, THIRD(), FOURTH())) goto __ERROR;
|
if(magic) {
|
||||||
STACK_SHRINK(3); // [retval]
|
if(magic->type == tp_nativefunc) {
|
||||||
} else {
|
bool ok = magic->_cfunc(3, THIRD());
|
||||||
bool ok = py_getunboundmethod(THIRD(), __setitem__, false, FOURTH(), THIRD());
|
|
||||||
if(!ok) goto __ERROR;
|
if(!ok) goto __ERROR;
|
||||||
// [__setitem__, self, b, val]
|
STACK_SHRINK(3);
|
||||||
|
*TOP() = self->last_retval;
|
||||||
|
} else {
|
||||||
|
INSERT_THIRD(); // [?, a, b]
|
||||||
|
*FOURTH() = *magic; // [__selitem__, a, b, val]
|
||||||
vectorcall_opcall(3);
|
vectorcall_opcall(3);
|
||||||
POP(); // discard retval
|
POP(); // discard retval
|
||||||
}
|
}
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
TypeError();
|
||||||
|
goto __ERROR;
|
||||||
|
}
|
||||||
case OP_DELETE_FAST: {
|
case OP_DELETE_FAST: {
|
||||||
py_Ref tmp = &frame->locals[byte.arg];
|
py_Ref tmp = &frame->locals[byte.arg];
|
||||||
if(py_isnull(tmp)) {
|
if(py_isnull(tmp)) {
|
||||||
@ -362,22 +381,24 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
|||||||
|
|
||||||
case OP_DELETE_SUBSCR: {
|
case OP_DELETE_SUBSCR: {
|
||||||
// [a, b] -> del a[b]
|
// [a, b] -> del a[b]
|
||||||
pk_TypeInfo* ti = pk_tpinfo(SECOND());
|
py_Ref magic = py_tpfindmagic(SECOND()->type, __delitem__);
|
||||||
if(ti->m__delitem__) {
|
if(magic) {
|
||||||
if(!ti->m__delitem__(2, SECOND(), SECOND())) goto __ERROR;
|
if(magic->type == tp_nativefunc) {
|
||||||
POP();
|
bool ok = magic->_cfunc(2, SECOND());
|
||||||
} else {
|
|
||||||
PUSH(TOP()); // [a, b, b]
|
|
||||||
*SECOND() = *THIRD(); // [a, a, b]
|
|
||||||
bool ok = py_getunboundmethod(SECOND(), __delitem__, false, THIRD(), SECOND());
|
|
||||||
// [__delitem__, self, b]
|
|
||||||
if(!ok) goto __ERROR;
|
if(!ok) goto __ERROR;
|
||||||
|
POP();
|
||||||
|
*TOP() = self->last_retval;
|
||||||
|
} else {
|
||||||
|
INSERT_THIRD(); // [?, a, b]
|
||||||
|
*THIRD() = *magic; // [__delitem__, a, b]
|
||||||
vectorcall_opcall(2);
|
vectorcall_opcall(2);
|
||||||
POP(); // discard retval
|
POP(); // discard retval
|
||||||
}
|
}
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
TypeError();
|
||||||
|
goto __ERROR;
|
||||||
|
}
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
|
|
||||||
case OP_BUILD_LONG: {
|
case OP_BUILD_LONG: {
|
||||||
@ -398,7 +419,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
|||||||
py_newnull(SP()++); // [complex, NULL]
|
py_newnull(SP()++); // [complex, NULL]
|
||||||
py_newint(SP()++, 0); // [complex, NULL, 0]
|
py_newint(SP()++, 0); // [complex, NULL, 0]
|
||||||
*SP()++ = tmp; // [complex, NULL, 0, x]
|
*SP()++ = tmp; // [complex, NULL, 0, x]
|
||||||
vectorcall_opcall(2); // [complex(x, 0)]
|
vectorcall_opcall(2); // [complex(x)]
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
case OP_BUILD_BYTES: {
|
case OP_BUILD_BYTES: {
|
||||||
@ -462,20 +483,123 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
|||||||
}
|
}
|
||||||
case OP_BUILD_STRING: {
|
case OP_BUILD_STRING: {
|
||||||
py_TValue* begin = SP() - byte.arg;
|
py_TValue* begin = SP() - byte.arg;
|
||||||
py_Ref tmp = py_pushtmp();
|
|
||||||
pk_SStream ss;
|
pk_SStream ss;
|
||||||
pk_SStream__ctor(&ss);
|
pk_SStream__ctor(&ss);
|
||||||
for(int i = 0; i < byte.arg; i++) {
|
for(int i = 0; i < byte.arg; i++) {
|
||||||
if(!py_str(begin + i, tmp)) goto __ERROR;
|
if(!py_str(begin + i)) goto __ERROR;
|
||||||
py_Str* item = py_touserdata(tmp);
|
py_Str* item = py_touserdata(&self->last_retval);
|
||||||
pk_SStream__write_Str(&ss, item);
|
pk_SStream__write_Str(&ss, item);
|
||||||
}
|
}
|
||||||
SP() = begin;
|
SP() = begin;
|
||||||
py_newStr_(tmp, pk_SStream__submit(&ss));
|
py_newStr_(SP()++, pk_SStream__submit(&ss));
|
||||||
PUSH(tmp);
|
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
/*****************************/
|
/*****************************/
|
||||||
|
case OP_BINARY_OP: {
|
||||||
|
py_Name op = byte.arg & 0xFF;
|
||||||
|
py_Name rop = byte.arg >> 8;
|
||||||
|
if(!stack_binaryop(self, op, rop)) goto __ERROR;
|
||||||
|
POP();
|
||||||
|
*TOP() = self->last_retval;
|
||||||
|
DISPATCH();
|
||||||
|
}
|
||||||
|
case OP_IS_OP: {
|
||||||
|
bool res = py_isidentical(SECOND(), TOP());
|
||||||
|
POP();
|
||||||
|
if(byte.arg) res = !res;
|
||||||
|
*TOP() = res ? self->True : self->False;
|
||||||
|
DISPATCH();
|
||||||
|
}
|
||||||
|
case OP_CONTAINS_OP: {
|
||||||
|
// [b, a] -> b __contains__ a (a in b)
|
||||||
|
py_Ref magic = py_tpfindmagic(SECOND()->type, __contains__);
|
||||||
|
if(magic) {
|
||||||
|
if(magic->type == tp_nativefunc) {
|
||||||
|
bool ok = magic->_cfunc(2, SECOND());
|
||||||
|
if(!ok) goto __ERROR;
|
||||||
|
POP();
|
||||||
|
*TOP() = self->last_retval;
|
||||||
|
} else {
|
||||||
|
INSERT_THIRD(); // [?, b, a]
|
||||||
|
*THIRD() = *magic; // [__contains__, a, b]
|
||||||
|
vectorcall_opcall(2);
|
||||||
|
}
|
||||||
|
bool res = py_tobool(TOP());
|
||||||
|
if(byte.arg) py_newbool(TOP(), !res);
|
||||||
|
DISPATCH();
|
||||||
|
}
|
||||||
|
TypeError();
|
||||||
|
goto __ERROR;
|
||||||
|
}
|
||||||
|
/*****************************************/
|
||||||
|
case OP_JUMP_FORWARD: DISPATCH_JUMP((int16_t)byte.arg);
|
||||||
|
case OP_POP_JUMP_IF_FALSE: {
|
||||||
|
int res = py_bool(TOP());
|
||||||
|
if(res < 0) goto __ERROR;
|
||||||
|
POP();
|
||||||
|
if(!res) DISPATCH_JUMP((int16_t)byte.arg);
|
||||||
|
DISPATCH();
|
||||||
|
}
|
||||||
|
case OP_POP_JUMP_IF_TRUE: {
|
||||||
|
int res = py_bool(TOP());
|
||||||
|
if(res < 0) goto __ERROR;
|
||||||
|
POP();
|
||||||
|
if(res) DISPATCH_JUMP((int16_t)byte.arg);
|
||||||
|
DISPATCH();
|
||||||
|
}
|
||||||
|
case OP_JUMP_IF_TRUE_OR_POP: {
|
||||||
|
int res = py_bool(TOP());
|
||||||
|
if(res < 0) goto __ERROR;
|
||||||
|
if(res) {
|
||||||
|
DISPATCH_JUMP((int16_t)byte.arg);
|
||||||
|
} else {
|
||||||
|
POP();
|
||||||
|
DISPATCH();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case OP_JUMP_IF_FALSE_OR_POP: {
|
||||||
|
int res = py_bool(TOP());
|
||||||
|
if(res < 0) goto __ERROR;
|
||||||
|
if(!res) {
|
||||||
|
DISPATCH_JUMP((int16_t)byte.arg);
|
||||||
|
} else {
|
||||||
|
POP();
|
||||||
|
DISPATCH();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case OP_SHORTCUT_IF_FALSE_OR_POP: {
|
||||||
|
int res = py_bool(TOP());
|
||||||
|
if(res < 0) goto __ERROR;
|
||||||
|
if(!res) { // [b, False]
|
||||||
|
STACK_SHRINK(2); // []
|
||||||
|
PUSH(&self->False); // [False]
|
||||||
|
DISPATCH_JUMP((int16_t)byte.arg);
|
||||||
|
} else {
|
||||||
|
POP(); // [b]
|
||||||
|
DISPATCH();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case OP_LOOP_CONTINUE:
|
||||||
|
// just an alias of OP_JUMP_FORWARD
|
||||||
|
DISPATCH_JUMP((int16_t)byte.arg);
|
||||||
|
case OP_LOOP_BREAK: {
|
||||||
|
int target = Frame__ip(frame) + byte.arg;
|
||||||
|
Frame__prepare_jump_break(frame, &self->stack, target);
|
||||||
|
DISPATCH_JUMP((int16_t)byte.arg);
|
||||||
|
}
|
||||||
|
case OP_JUMP_ABSOLUTE_TOP: {
|
||||||
|
int target = py_toint(TOP());
|
||||||
|
POP();
|
||||||
|
DISPATCH_JUMP_ABSOLUTE(target);
|
||||||
|
}
|
||||||
|
// case OP_GOTO: {
|
||||||
|
// StrName _name(byte.arg);
|
||||||
|
// int target = c11_smallmap_n2i__get(&frame->co->labels, byte.arg, -1);
|
||||||
|
// if(target < 0) RuntimeError(_S("label ", _name.escape(), " not found"));
|
||||||
|
// frame->prepare_jump_break(&s_data, target);
|
||||||
|
// DISPATCH_JUMP_ABSOLUTE(target)
|
||||||
|
// }
|
||||||
|
/*****************************************/
|
||||||
case OP_RETURN_VALUE: {
|
case OP_RETURN_VALUE: {
|
||||||
self->last_retval = byte.arg == BC_NOARG ? POPX() : self->None;
|
self->last_retval = byte.arg == BC_NOARG ? POPX() : self->None;
|
||||||
pk_VM__pop_frame(self);
|
pk_VM__pop_frame(self);
|
||||||
@ -502,3 +626,56 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
|||||||
|
|
||||||
return RES_RETURN;
|
return RES_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Assumes [a, b] are on the stack, performs a binary op.
|
||||||
|
/// The result is stored in `self->last_retval`.
|
||||||
|
/// The stack remains unchanged.
|
||||||
|
static bool stack_binaryop(pk_VM* self, py_Name op, py_Name rop) {
|
||||||
|
// [a, b]
|
||||||
|
py_Ref magic = py_tpfindmagic(SECOND()->type, op);
|
||||||
|
if(magic) {
|
||||||
|
if(magic->type == tp_nativefunc) {
|
||||||
|
bool ok = magic->_cfunc(2, SECOND());
|
||||||
|
if(!ok) return false;
|
||||||
|
if(self->last_retval.type != tp_not_implemented_type) return true;
|
||||||
|
} else {
|
||||||
|
// standard call
|
||||||
|
bool ok = py_call(magic, 2, SECOND());
|
||||||
|
if(!ok) return false;
|
||||||
|
if(self->last_retval.type != tp_not_implemented_type) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// try reverse operation
|
||||||
|
if(rop) {
|
||||||
|
// [a, b] -> [b, a]
|
||||||
|
py_TValue tmp = *TOP();
|
||||||
|
*TOP() = *SECOND();
|
||||||
|
*SECOND() = tmp;
|
||||||
|
magic = py_tpfindmagic(SECOND()->type, rop);
|
||||||
|
if(magic) {
|
||||||
|
if(magic->type == tp_nativefunc) {
|
||||||
|
bool ok = magic->_cfunc(2, SECOND());
|
||||||
|
if(!ok) return false;
|
||||||
|
if(self->last_retval.type != tp_not_implemented_type) return true;
|
||||||
|
} else {
|
||||||
|
// standard call
|
||||||
|
bool ok = py_call(magic, 2, SECOND());
|
||||||
|
if(!ok) return false;
|
||||||
|
if(self->last_retval.type != tp_not_implemented_type) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// eq/ne op never fails
|
||||||
|
if(op == __eq__ || op == __ne__) {
|
||||||
|
self->last_retval = (op == __eq__) ? self->False : self->True;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return BinaryOptError(byte.arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool py_binaryop(const py_Ref lhs, const py_Ref rhs, py_Name op, py_Name rop) {
|
||||||
|
pk_VM* self = pk_current_vm;
|
||||||
|
PUSH(lhs);
|
||||||
|
PUSH(rhs);
|
||||||
|
return stack_binaryop(self, op, rop);
|
||||||
|
}
|
@ -39,81 +39,89 @@
|
|||||||
// return 0;
|
// return 0;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
#define DEF_NUM_BINARY_OP(name, op) \
|
#define DEF_NUM_BINARY_OP(name, op, rint, rfloat) \
|
||||||
static bool _py_int##name(int argc, py_Ref argv, py_Ref out) { \
|
static bool _py_int##name(int argc, py_Ref argv) { \
|
||||||
|
py_checkargc(2); \
|
||||||
if(py_isint(&argv[1])) { \
|
if(py_isint(&argv[1])) { \
|
||||||
int64_t lhs = py_toint(&argv[0]); \
|
int64_t lhs = py_toint(&argv[0]); \
|
||||||
int64_t rhs = py_toint(&argv[1]); \
|
int64_t rhs = py_toint(&argv[1]); \
|
||||||
py_newint(out, lhs op rhs); \
|
rint(py_lastretval(), lhs op rhs); \
|
||||||
} else if(py_isfloat(&argv[1])) { \
|
} else if(py_isfloat(&argv[1])) { \
|
||||||
int64_t lhs = py_toint(&argv[0]); \
|
int64_t lhs = py_toint(&argv[0]); \
|
||||||
double rhs = py_tofloat(&argv[1]); \
|
double rhs = py_tofloat(&argv[1]); \
|
||||||
py_newfloat(out, lhs op rhs); \
|
rfloat(py_lastretval(), lhs op rhs); \
|
||||||
} else { \
|
} else { \
|
||||||
py_newnotimplemented(out); \
|
py_newnotimplemented(py_lastretval()); \
|
||||||
} \
|
} \
|
||||||
return true; \
|
return true; \
|
||||||
} \
|
} \
|
||||||
static bool _py_float##name(int argc, py_Ref argv, py_Ref out) { \
|
static bool _py_float##name(int argc, py_Ref argv) { \
|
||||||
|
py_checkargc(2); \
|
||||||
double lhs = py_tofloat(&argv[0]); \
|
double lhs = py_tofloat(&argv[0]); \
|
||||||
double rhs; \
|
double rhs; \
|
||||||
if(py_castfloat(&argv[1], &rhs)) { \
|
if(py_castfloat(&argv[1], &rhs)) { \
|
||||||
py_newfloat(out, lhs op rhs); \
|
rfloat(py_lastretval(), lhs op rhs); \
|
||||||
} else { \
|
} else { \
|
||||||
py_newnotimplemented(out); \
|
py_newnotimplemented(py_lastretval()); \
|
||||||
} \
|
} \
|
||||||
return true; \
|
return true; \
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF_NUM_BINARY_OP(__add__, +)
|
DEF_NUM_BINARY_OP(__add__, +, py_newint, py_newfloat)
|
||||||
DEF_NUM_BINARY_OP(__sub__, -)
|
DEF_NUM_BINARY_OP(__sub__, -, py_newint, py_newfloat)
|
||||||
DEF_NUM_BINARY_OP(__mul__, *)
|
DEF_NUM_BINARY_OP(__mul__, *, py_newint, py_newfloat)
|
||||||
|
|
||||||
DEF_NUM_BINARY_OP(__eq__, ==)
|
DEF_NUM_BINARY_OP(__eq__, ==, py_newbool, py_newbool)
|
||||||
DEF_NUM_BINARY_OP(__lt__, <)
|
DEF_NUM_BINARY_OP(__ne__, ==, py_newbool, py_newbool)
|
||||||
DEF_NUM_BINARY_OP(__le__, <=)
|
DEF_NUM_BINARY_OP(__lt__, <, py_newbool, py_newbool)
|
||||||
DEF_NUM_BINARY_OP(__gt__, >)
|
DEF_NUM_BINARY_OP(__le__, <=, py_newbool, py_newbool)
|
||||||
DEF_NUM_BINARY_OP(__ge__, >=)
|
DEF_NUM_BINARY_OP(__gt__, >, py_newbool, py_newbool)
|
||||||
|
DEF_NUM_BINARY_OP(__ge__, >=, py_newbool, py_newbool)
|
||||||
|
|
||||||
#undef DEF_NUM_BINARY_OP
|
#undef DEF_NUM_BINARY_OP
|
||||||
|
|
||||||
static bool _py_int__neg__(int argc, py_Ref argv, py_Ref out) {
|
static bool _py_int__neg__(int argc, py_Ref argv) {
|
||||||
|
py_checkargc(1);
|
||||||
int64_t val = py_toint(&argv[0]);
|
int64_t val = py_toint(&argv[0]);
|
||||||
py_newint(out, -val);
|
py_newint(py_lastretval(), -val);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _py_float__neg__(int argc, py_Ref argv, py_Ref out) {
|
static bool _py_float__neg__(int argc, py_Ref argv) {
|
||||||
|
py_checkargc(1);
|
||||||
double val = py_tofloat(&argv[0]);
|
double val = py_tofloat(&argv[0]);
|
||||||
py_newfloat(out, -val);
|
py_newfloat(py_lastretval(), -val);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _py_int__truediv__(int argc, py_Ref argv, py_Ref out) {
|
static bool _py_int__truediv__(int argc, py_Ref argv) {
|
||||||
|
py_checkargc(2);
|
||||||
int64_t lhs = py_toint(&argv[0]);
|
int64_t lhs = py_toint(&argv[0]);
|
||||||
double rhs;
|
double rhs;
|
||||||
if(py_castfloat(&argv[1], &rhs)) {
|
if(py_castfloat(&argv[1], &rhs)) {
|
||||||
py_newfloat(out, lhs / rhs);
|
py_newfloat(py_lastretval(), lhs / rhs);
|
||||||
} else {
|
} else {
|
||||||
py_newnotimplemented(out);
|
py_newnotimplemented(py_lastretval());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _py_float__truediv__(int argc, py_Ref argv, py_Ref out) {
|
static bool _py_float__truediv__(int argc, py_Ref argv) {
|
||||||
|
py_checkargc(2);
|
||||||
double lhs = py_tofloat(&argv[0]);
|
double lhs = py_tofloat(&argv[0]);
|
||||||
double rhs;
|
double rhs;
|
||||||
if(py_castfloat(&argv[1], &rhs)) {
|
if(py_castfloat(&argv[1], &rhs)) {
|
||||||
py_newfloat(out, lhs / rhs);
|
py_newfloat(py_lastretval(), lhs / rhs);
|
||||||
} else {
|
} else {
|
||||||
py_newnotimplemented(out);
|
py_newnotimplemented(py_lastretval());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ZeroDivisionError(msg) false
|
#define ZeroDivisionError(msg) false
|
||||||
|
|
||||||
static bool _py_number__pow__(int argc, py_Ref argv, py_Ref out) {
|
static bool _py_number__pow__(int argc, py_Ref argv) {
|
||||||
|
py_checkargc(2);
|
||||||
if(py_isint(&argv[0]) && py_isint(&argv[1])) {
|
if(py_isint(&argv[0]) && py_isint(&argv[1])) {
|
||||||
int64_t lhs = py_toint(&argv[0]);
|
int64_t lhs = py_toint(&argv[0]);
|
||||||
int64_t rhs = py_toint(&argv[1]);
|
int64_t rhs = py_toint(&argv[1]);
|
||||||
@ -121,7 +129,7 @@ static bool _py_number__pow__(int argc, py_Ref argv, py_Ref out) {
|
|||||||
if(lhs == 0) {
|
if(lhs == 0) {
|
||||||
return ZeroDivisionError("0.0 cannot be raised to a negative power");
|
return ZeroDivisionError("0.0 cannot be raised to a negative power");
|
||||||
} else {
|
} else {
|
||||||
py_newfloat(out, pow(lhs, rhs));
|
py_newfloat(py_lastretval(), pow(lhs, rhs));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int64_t ret = 1;
|
int64_t ret = 1;
|
||||||
@ -130,51 +138,55 @@ static bool _py_number__pow__(int argc, py_Ref argv, py_Ref out) {
|
|||||||
lhs *= lhs;
|
lhs *= lhs;
|
||||||
rhs >>= 1;
|
rhs >>= 1;
|
||||||
}
|
}
|
||||||
py_newint(out, ret);
|
py_newint(py_lastretval(), ret);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
double lhs, rhs;
|
double lhs, rhs;
|
||||||
py_castfloat(&argv[0], &lhs);
|
py_castfloat(&argv[0], &lhs);
|
||||||
if(py_castfloat(&argv[1], &rhs)) {
|
if(py_castfloat(&argv[1], &rhs)) {
|
||||||
py_newfloat(out, pow(lhs, rhs));
|
py_newfloat(py_lastretval(), pow(lhs, rhs));
|
||||||
} else {
|
} else {
|
||||||
py_newnotimplemented(out);
|
py_newnotimplemented(py_lastretval());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _py_int__floordiv__(int argc, py_Ref argv, py_Ref out) {
|
static bool _py_int__floordiv__(int argc, py_Ref argv) {
|
||||||
|
py_checkargc(2);
|
||||||
int64_t lhs = py_toint(&argv[0]);
|
int64_t lhs = py_toint(&argv[0]);
|
||||||
if(py_isint(&argv[1])) {
|
if(py_isint(&argv[1])) {
|
||||||
int64_t rhs = py_toint(&argv[1]);
|
int64_t rhs = py_toint(&argv[1]);
|
||||||
if(rhs == 0) return -1;
|
if(rhs == 0) return -1;
|
||||||
py_newint(out, lhs / rhs);
|
py_newint(py_lastretval(), lhs / rhs);
|
||||||
} else {
|
} else {
|
||||||
py_newnotimplemented(out);
|
py_newnotimplemented(py_lastretval());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _py_int__mod__(int argc, py_Ref argv, py_Ref out) {
|
static bool _py_int__mod__(int argc, py_Ref argv) {
|
||||||
|
py_checkargc(2);
|
||||||
int64_t lhs = py_toint(&argv[0]);
|
int64_t lhs = py_toint(&argv[0]);
|
||||||
if(py_isint(&argv[1])) {
|
if(py_isint(&argv[1])) {
|
||||||
int64_t rhs = py_toint(&argv[1]);
|
int64_t rhs = py_toint(&argv[1]);
|
||||||
if(rhs == 0) return ZeroDivisionError("integer division or modulo by zero");
|
if(rhs == 0) return ZeroDivisionError("integer division or modulo by zero");
|
||||||
py_newint(out, lhs % rhs);
|
py_newint(py_lastretval(), lhs % rhs);
|
||||||
} else {
|
} else {
|
||||||
py_newnotimplemented(out);
|
py_newnotimplemented(py_lastretval());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _py_int__invert__(int argc, py_Ref argv, py_Ref out) {
|
static bool _py_int__invert__(int argc, py_Ref argv) {
|
||||||
|
py_checkargc(1);
|
||||||
int64_t val = py_toint(&argv[0]);
|
int64_t val = py_toint(&argv[0]);
|
||||||
py_newint(out, ~val);
|
py_newint(py_lastretval(), ~val);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _py_int__bit_length(int argc, py_Ref argv, py_Ref out) {
|
static bool _py_int__bit_length(int argc, py_Ref argv) {
|
||||||
|
py_checkargc(1);
|
||||||
int64_t x = py_toint(py_arg(0));
|
int64_t x = py_toint(py_arg(0));
|
||||||
if(x < 0) x = -x;
|
if(x < 0) x = -x;
|
||||||
int bits = 0;
|
int bits = 0;
|
||||||
@ -182,18 +194,19 @@ static bool _py_int__bit_length(int argc, py_Ref argv, py_Ref out) {
|
|||||||
x >>= 1;
|
x >>= 1;
|
||||||
bits++;
|
bits++;
|
||||||
}
|
}
|
||||||
py_newint(out, bits);
|
py_newint(py_lastretval(), bits);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DEF_INT_BITWISE_OP(name, op) \
|
#define DEF_INT_BITWISE_OP(name, op) \
|
||||||
static bool _py_int##name(int argc, py_Ref argv, py_Ref out) { \
|
static bool _py_int##name(int argc, py_Ref argv) { \
|
||||||
|
py_checkargc(2); \
|
||||||
int64_t lhs = py_toint(&argv[0]); \
|
int64_t lhs = py_toint(&argv[0]); \
|
||||||
if(py_isint(&argv[1])) { \
|
if(py_isint(&argv[1])) { \
|
||||||
int64_t rhs = py_toint(&argv[1]); \
|
int64_t rhs = py_toint(&argv[1]); \
|
||||||
py_newint(out, lhs op rhs); \
|
py_newint(py_lastretval(), lhs op rhs); \
|
||||||
} else { \
|
} else { \
|
||||||
py_newnotimplemented(out); \
|
py_newnotimplemented(py_lastretval()); \
|
||||||
} \
|
} \
|
||||||
return true; \
|
return true; \
|
||||||
}
|
}
|
||||||
@ -208,81 +221,55 @@ DEF_INT_BITWISE_OP(__rshift__, >>)
|
|||||||
|
|
||||||
void pk_VM__init_builtins(pk_VM* self) {
|
void pk_VM__init_builtins(pk_VM* self) {
|
||||||
/****** tp_int & tp_float ******/
|
/****** tp_int & tp_float ******/
|
||||||
py_Ref tmp = py_pushtmp();
|
py_bindmagic(tp_int, __add__, _py_int__add__);
|
||||||
py_Ref int_type = py_pushtmp();
|
py_bindmagic(tp_float, __add__, _py_float__add__);
|
||||||
*int_type = *py_getdict(&self->builtins, py_name("int"));
|
py_bindmagic(tp_int, __sub__, _py_int__sub__);
|
||||||
py_Ref float_type = py_pushtmp();
|
py_bindmagic(tp_float, __sub__, _py_float__sub__);
|
||||||
*float_type = *py_getdict(&self->builtins, py_name("float"));
|
py_bindmagic(tp_int, __mul__, _py_int__mul__);
|
||||||
|
py_bindmagic(tp_float, __mul__, _py_float__mul__);
|
||||||
|
|
||||||
#define BIND_INT_BINARY_OP(name) \
|
py_bindmagic(tp_int, __eq__, _py_int__eq__);
|
||||||
py_newnativefunc(tmp, _py_int##name, 2); \
|
py_bindmagic(tp_float, __eq__, _py_float__eq__);
|
||||||
py_setdict(int_type, name, tmp);
|
py_bindmagic(tp_int, __ne__, _py_int__ne__);
|
||||||
|
py_bindmagic(tp_float, __ne__, _py_float__ne__);
|
||||||
#define BIND_FLOAT_BINARY_OP(name) \
|
py_bindmagic(tp_int, __lt__, _py_int__lt__);
|
||||||
py_newnativefunc(tmp, _py_float##name, 2); \
|
py_bindmagic(tp_float, __lt__, _py_float__lt__);
|
||||||
py_setdict(float_type, name, tmp);
|
py_bindmagic(tp_int, __le__, _py_int__le__);
|
||||||
|
py_bindmagic(tp_float, __le__, _py_float__le__);
|
||||||
BIND_INT_BINARY_OP(__add__);
|
py_bindmagic(tp_int, __gt__, _py_int__gt__);
|
||||||
BIND_FLOAT_BINARY_OP(__add__);
|
py_bindmagic(tp_float, __gt__, _py_float__gt__);
|
||||||
BIND_INT_BINARY_OP(__sub__);
|
py_bindmagic(tp_int, __ge__, _py_int__ge__);
|
||||||
BIND_FLOAT_BINARY_OP(__sub__);
|
py_bindmagic(tp_float, __ge__, _py_float__ge__);
|
||||||
BIND_INT_BINARY_OP(__mul__);
|
|
||||||
BIND_FLOAT_BINARY_OP(__mul__);
|
|
||||||
|
|
||||||
BIND_INT_BINARY_OP(__eq__);
|
|
||||||
BIND_FLOAT_BINARY_OP(__eq__);
|
|
||||||
BIND_INT_BINARY_OP(__lt__);
|
|
||||||
BIND_FLOAT_BINARY_OP(__lt__);
|
|
||||||
BIND_INT_BINARY_OP(__le__);
|
|
||||||
BIND_FLOAT_BINARY_OP(__le__);
|
|
||||||
BIND_INT_BINARY_OP(__gt__);
|
|
||||||
BIND_FLOAT_BINARY_OP(__gt__);
|
|
||||||
BIND_INT_BINARY_OP(__ge__);
|
|
||||||
BIND_FLOAT_BINARY_OP(__ge__);
|
|
||||||
|
|
||||||
// __neg__
|
// __neg__
|
||||||
py_newnativefunc(tmp, _py_int__neg__, 1);
|
py_bindmagic(tp_int, __neg__, _py_int__neg__);
|
||||||
py_setdict(int_type, __neg__, tmp);
|
py_bindmagic(tp_float, __neg__, _py_float__neg__);
|
||||||
py_newnativefunc(tmp, _py_float__neg__, 1);
|
|
||||||
py_setdict(float_type, __neg__, tmp);
|
|
||||||
|
|
||||||
// TODO: __repr__, __new__, __hash__
|
// TODO: __repr__, __new__, __hash__
|
||||||
|
|
||||||
// __truediv__
|
// __truediv__
|
||||||
py_newnativefunc(tmp, _py_int__truediv__, 2);
|
py_bindmagic(tp_int, __truediv__, _py_int__truediv__);
|
||||||
py_setdict(int_type, __truediv__, tmp);
|
py_bindmagic(tp_float, __truediv__, _py_float__truediv__);
|
||||||
py_newnativefunc(tmp, _py_float__truediv__, 2);
|
|
||||||
py_setdict(float_type, __truediv__, tmp);
|
|
||||||
|
|
||||||
// __pow__
|
// __pow__
|
||||||
py_newnativefunc(tmp, _py_number__pow__, 2);
|
py_bindmagic(tp_int, __pow__, _py_number__pow__);
|
||||||
py_setdict(int_type, __pow__, tmp);
|
py_bindmagic(tp_float, __pow__, _py_number__pow__);
|
||||||
py_setdict(float_type, __pow__, tmp);
|
|
||||||
|
|
||||||
// __floordiv__ & __mod__
|
// __floordiv__ & __mod__
|
||||||
py_newnativefunc(tmp, _py_int__floordiv__, 2);
|
py_bindmagic(tp_int, __floordiv__, _py_int__floordiv__);
|
||||||
py_setdict(int_type, __floordiv__, tmp);
|
py_bindmagic(tp_int, __mod__, _py_int__mod__);
|
||||||
py_newnativefunc(tmp, _py_int__mod__, 2);
|
|
||||||
py_setdict(int_type, __mod__, tmp);
|
|
||||||
|
|
||||||
// int.__invert__ & int.<BITWISE OP>
|
// int.__invert__ & int.<BITWISE OP>
|
||||||
py_newnativefunc(tmp, _py_int__invert__, 1);
|
py_bindmagic(tp_int, __invert__, _py_int__invert__);
|
||||||
py_setdict(int_type, __invert__, tmp);
|
|
||||||
|
|
||||||
BIND_INT_BINARY_OP(__and__);
|
py_bindmagic(tp_int, __and__, _py_int__and__);
|
||||||
BIND_INT_BINARY_OP(__or__);
|
py_bindmagic(tp_int, __or__, _py_int__or__);
|
||||||
BIND_INT_BINARY_OP(__xor__);
|
py_bindmagic(tp_int, __xor__, _py_int__xor__);
|
||||||
BIND_INT_BINARY_OP(__lshift__);
|
py_bindmagic(tp_int, __lshift__, _py_int__lshift__);
|
||||||
BIND_INT_BINARY_OP(__rshift__);
|
py_bindmagic(tp_int, __rshift__, _py_int__rshift__);
|
||||||
|
|
||||||
// int.bit_length
|
// int.bit_length
|
||||||
py_newnativefunc(tmp, _py_int__bit_length, 1);
|
py_bindmethod(tp_int, "bit_length", _py_int__bit_length);
|
||||||
py_setdict(int_type, py_name("bit_length"), tmp);
|
|
||||||
|
|
||||||
#undef BIND_INT_BINARY_OP
|
|
||||||
#undef BIND_FLOAT_BINARY_OP
|
|
||||||
|
|
||||||
py_poptmp(3);
|
|
||||||
|
|
||||||
// py_Ref builtins = py_getmodule("builtins");
|
// py_Ref builtins = py_getmodule("builtins");
|
||||||
// py_newfunction(py_reg(0), _py_print,
|
// py_newfunction(py_reg(0), _py_print,
|
||||||
|
@ -108,10 +108,7 @@ void pk_VM__ctor(pk_VM* self) {
|
|||||||
validate(tp_bool, pk_VM__new_type(self, "bool", tp_object, NULL, false));
|
validate(tp_bool, pk_VM__new_type(self, "bool", tp_object, NULL, false));
|
||||||
validate(tp_str, pk_VM__new_type(self, "str", tp_object, NULL, false));
|
validate(tp_str, pk_VM__new_type(self, "str", tp_object, NULL, false));
|
||||||
|
|
||||||
validate(tp_list, pk_VM__new_type(self, "list", tp_object, NULL, false));
|
validate(tp_list, pk_list__register());
|
||||||
pk_TypeInfo* ti = c11__at(pk_TypeInfo, &self->types, tp_list);
|
|
||||||
ti->dtor = (void (*)(void*))c11_vector__dtor;
|
|
||||||
|
|
||||||
validate(tp_tuple, pk_VM__new_type(self, "tuple", tp_object, NULL, false));
|
validate(tp_tuple, pk_VM__new_type(self, "tuple", tp_object, NULL, false));
|
||||||
|
|
||||||
validate(tp_slice, pk_VM__new_type(self, "slice", tp_object, NULL, false));
|
validate(tp_slice, pk_VM__new_type(self, "slice", tp_object, NULL, false));
|
||||||
|
@ -5,10 +5,12 @@
|
|||||||
#include "pocketpy/interpreter/vm.h"
|
#include "pocketpy/interpreter/vm.h"
|
||||||
|
|
||||||
int64_t py_toint(const py_Ref self){
|
int64_t py_toint(const py_Ref self){
|
||||||
|
assert(self->type == tp_int);
|
||||||
return self->_i64;
|
return self->_i64;
|
||||||
}
|
}
|
||||||
|
|
||||||
double py_tofloat(const py_Ref self){
|
double py_tofloat(const py_Ref self){
|
||||||
|
assert(self->type == tp_float);
|
||||||
return self->_f64;
|
return self->_f64;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,26 +22,26 @@ bool py_castfloat(const py_Ref self, double* out){
|
|||||||
case tp_float:
|
case tp_float:
|
||||||
*out = self->_f64;
|
*out = self->_f64;
|
||||||
return true;
|
return true;
|
||||||
case tp_bool:
|
|
||||||
*out = self->extra;
|
|
||||||
return true;
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool py_tobool(const py_Ref self){
|
bool py_tobool(const py_Ref self){
|
||||||
|
assert(self->type == tp_bool);
|
||||||
return self->extra;
|
return self->extra;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* py_tostr(const py_Ref self){
|
const char* py_tostr(const py_Ref self){
|
||||||
|
assert(self->type == tp_str);
|
||||||
py_Str* ud = PyObject__value(self->_obj);
|
py_Str* ud = PyObject__value(self->_obj);
|
||||||
return py_Str__data(ud);
|
return py_Str__data(ud);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* py_tostrn(const py_Ref self, int* out){
|
const char* py_tostrn(const py_Ref self, int* size){
|
||||||
|
assert(self->type == tp_str);
|
||||||
py_Str* ud = PyObject__value(self->_obj);
|
py_Str* ud = PyObject__value(self->_obj);
|
||||||
*out = ud->size;
|
*size = ud->size;
|
||||||
return py_Str__data(ud);
|
return py_Str__data(ud);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,14 @@
|
|||||||
|
|
||||||
typedef c11_vector List;
|
typedef c11_vector List;
|
||||||
|
|
||||||
|
py_Type pk_list__register() {
|
||||||
|
pk_VM* vm = pk_current_vm;
|
||||||
|
py_Type type = pk_VM__new_type(vm, "list", tp_object, NULL, false);
|
||||||
|
pk_TypeInfo* ti = c11__at(pk_TypeInfo, &vm->types, type);
|
||||||
|
ti->dtor = (void (*)(void*))c11_vector__dtor;
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
void py_newlist(py_Ref out) {
|
void py_newlist(py_Ref out) {
|
||||||
pk_VM* vm = pk_current_vm;
|
pk_VM* vm = pk_current_vm;
|
||||||
PyObject* obj = pk_ManagedHeap__gcnew(&vm->heap, tp_list, 0, sizeof(List));
|
PyObject* obj = pk_ManagedHeap__gcnew(&vm->heap, tp_list, 0, sizeof(List));
|
||||||
|
@ -1,25 +1,15 @@
|
|||||||
#include "pocketpy/interpreter/vm.h"
|
#include "pocketpy/interpreter/vm.h"
|
||||||
#include "pocketpy/pocketpy.h"
|
#include "pocketpy/pocketpy.h"
|
||||||
|
|
||||||
int py_eq(const py_Ref lhs, const py_Ref rhs) { return 0; }
|
bool py_isidentical(const py_Ref lhs, const py_Ref rhs) {
|
||||||
|
if(lhs->is_ptr && rhs->is_ptr) { return lhs->_obj == rhs->_obj; }
|
||||||
int py_le(const py_Ref lhs, const py_Ref rhs) { return 0; }
|
|
||||||
|
|
||||||
bool py_hash(const py_Ref val, int64_t* out) { return 0; }
|
|
||||||
|
|
||||||
bool py_str(const py_Ref val, py_Ref out) { return 0; }
|
|
||||||
|
|
||||||
bool py_repr(const py_Ref val, py_Ref out) {
|
|
||||||
const pk_TypeInfo* ti = pk_tpinfo(val);
|
|
||||||
if(ti->m__repr__) return ti->m__repr__(1, val, out);
|
|
||||||
bool ok = py_callmethod(val, __repr__, 0, NULL);
|
|
||||||
if(ok) {
|
|
||||||
*out = pk_current_vm->last_retval;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int py_bool(const py_Ref val) { return 1; }
|
||||||
|
|
||||||
|
bool py_hash(const py_Ref val, int64_t* out) { return 0; }
|
||||||
|
|
||||||
bool py_getattr(const py_Ref self, py_Name name, py_Ref out) { return true; }
|
bool py_getattr(const py_Ref self, py_Name name, py_Ref out) { return true; }
|
||||||
|
|
||||||
bool py_setattr(py_Ref self, py_Name name, const py_Ref val) { return -1; }
|
bool py_setattr(py_Ref self, py_Name name, const py_Ref val) { return -1; }
|
||||||
@ -31,3 +21,17 @@ bool py_getitem(const py_Ref self, const py_Ref key, py_Ref out) { return -1; }
|
|||||||
bool py_setitem(py_Ref self, const py_Ref key, const py_Ref val) { return -1; }
|
bool py_setitem(py_Ref self, const py_Ref key, const py_Ref val) { return -1; }
|
||||||
|
|
||||||
bool py_delitem(py_Ref self, const py_Ref key) { return -1; }
|
bool py_delitem(py_Ref self, const py_Ref key) { return -1; }
|
||||||
|
|
||||||
|
#define COMPARE_OP_IMPL(name, op, rop) \
|
||||||
|
int py_##name(const py_Ref lhs, const py_Ref rhs) { \
|
||||||
|
bool ok = py_binaryop(lhs, rhs, op, rop); \
|
||||||
|
if(!ok) return -1; \
|
||||||
|
return py_tobool(py_lastretval()); \
|
||||||
|
}
|
||||||
|
|
||||||
|
COMPARE_OP_IMPL(eq, __eq__, __eq__)
|
||||||
|
COMPARE_OP_IMPL(ne, __ne__, __ne__)
|
||||||
|
COMPARE_OP_IMPL(lt, __lt__, __gt__)
|
||||||
|
COMPARE_OP_IMPL(le, __le__, __ge__)
|
||||||
|
COMPARE_OP_IMPL(gt, __gt__, __lt__)
|
||||||
|
COMPARE_OP_IMPL(ge, __ge__, __le__)
|
@ -35,34 +35,6 @@ void py_assign(py_Ref dst, const py_Ref src){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Stack References */
|
/* Stack References */
|
||||||
py_Ref py_gettop(){
|
|
||||||
return pk_current_vm->stack.sp - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void py_settop(const py_Ref val){
|
|
||||||
pk_current_vm->stack.sp[-1] = *val;
|
|
||||||
}
|
|
||||||
|
|
||||||
py_Ref py_getsecond(){
|
|
||||||
return pk_current_vm->stack.sp - 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
void py_setsecond(const py_Ref val){
|
|
||||||
pk_current_vm->stack.sp[-2] = *val;
|
|
||||||
}
|
|
||||||
|
|
||||||
void py_duptop(){
|
|
||||||
pk_VM* vm = pk_current_vm;
|
|
||||||
*vm->stack.sp = vm->stack.sp[-1];
|
|
||||||
vm->stack.sp++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void py_dupsecond(){
|
|
||||||
pk_VM* vm = pk_current_vm;
|
|
||||||
*vm->stack.sp = vm->stack.sp[-2];
|
|
||||||
vm->stack.sp++;
|
|
||||||
}
|
|
||||||
|
|
||||||
py_Ref py_peek(int i){
|
py_Ref py_peek(int i){
|
||||||
assert(i < 0);
|
assert(i < 0);
|
||||||
return pk_current_vm->stack.sp + i;
|
return pk_current_vm->stack.sp + i;
|
||||||
@ -88,7 +60,3 @@ py_Ref py_pushtmp(){
|
|||||||
py_newnull(vm->stack.sp++);
|
py_newnull(vm->stack.sp++);
|
||||||
return py_gettop();
|
return py_gettop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void py_poptmp(int n){
|
|
||||||
py_shrink(n);
|
|
||||||
}
|
|
@ -79,16 +79,27 @@ void py_newfunction2(py_Ref out,
|
|||||||
const char* docstring,
|
const char* docstring,
|
||||||
const py_Ref upvalue) {}
|
const py_Ref upvalue) {}
|
||||||
|
|
||||||
void py_newnativefunc(py_Ref out, py_CFunction f, int argc) {
|
void py_newnativefunc(py_Ref out, py_CFunction f) {
|
||||||
py_newnativefunc2(out, f, argc, BindType_FUNCTION, NULL, NULL);
|
out->type = tp_nativefunc;
|
||||||
|
out->is_ptr = false;
|
||||||
|
out->_cfunc = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void py_newnativefunc2(py_Ref out,
|
void py_bindmethod(py_Type type, const char *name, py_CFunction f){
|
||||||
py_CFunction f,
|
py_bindmethod2(type, name, f, BindType_FUNCTION);
|
||||||
int argc,
|
}
|
||||||
BindType bt,
|
|
||||||
const char* docstring,
|
void py_bindmethod2(py_Type type, const char *name, py_CFunction f, BindType bt){
|
||||||
const py_Ref upvalue) {}
|
py_TValue tmp;
|
||||||
|
py_newnativefunc(&tmp, f);
|
||||||
|
py_setdict(py_tpobject(type), py_name(name), &tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void py_bindnativefunc(py_Ref obj, const char *name, py_CFunction f){
|
||||||
|
py_TValue tmp;
|
||||||
|
py_newnativefunc(&tmp, f);
|
||||||
|
py_setdict(obj, py_name(name), &tmp);
|
||||||
|
}
|
||||||
|
|
||||||
void py_newnotimplemented(py_Ref out) {
|
void py_newnotimplemented(py_Ref out) {
|
||||||
pk_VM* vm = pk_current_vm;
|
pk_VM* vm = pk_current_vm;
|
||||||
|
@ -23,15 +23,15 @@ void py_finalize() {
|
|||||||
pk_MemoryPools__finalize();
|
pk_MemoryPools__finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
int py_exec(const char* source) { PK_UNREACHABLE(); }
|
bool py_exec(const char* source) { PK_UNREACHABLE(); }
|
||||||
|
|
||||||
int py_eval(const char* source, py_Ref out) {
|
bool py_eval(const char* source) {
|
||||||
CodeObject co;
|
CodeObject co;
|
||||||
pk_SourceData_ src = pk_SourceData__rcnew(source, "main.py", EVAL_MODE, false);
|
pk_SourceData_ src = pk_SourceData__rcnew(source, "main.py", EVAL_MODE, false);
|
||||||
Error* err = pk_compile(src, &co);
|
Error* err = pk_compile(src, &co);
|
||||||
if(err) {
|
if(err) {
|
||||||
PK_DECREF(src);
|
PK_DECREF(src);
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
pk_VM* vm = pk_current_vm;
|
pk_VM* vm = pk_current_vm;
|
||||||
Frame* frame = Frame__new(&co, &vm->main, NULL, vm->stack.sp, vm->stack.sp, &co);
|
Frame* frame = Frame__new(&co, &vm->main, NULL, vm->stack.sp, vm->stack.sp, &co);
|
||||||
@ -39,31 +39,24 @@ int py_eval(const char* source, py_Ref out) {
|
|||||||
pk_FrameResult res = pk_VM__run_top_frame(vm);
|
pk_FrameResult res = pk_VM__run_top_frame(vm);
|
||||||
CodeObject__dtor(&co);
|
CodeObject__dtor(&co);
|
||||||
PK_DECREF(src);
|
PK_DECREF(src);
|
||||||
if(res == RES_ERROR) return vm->last_error->type;
|
if(res == RES_ERROR) return false;
|
||||||
if(res == RES_RETURN){
|
if(res == RES_RETURN) return true;
|
||||||
*out = vm->last_retval;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
PK_UNREACHABLE();
|
PK_UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool py_call(py_Ref f, int argc, py_Ref argv){
|
bool py_call(py_Ref f, int argc, py_Ref argv) { return -1; }
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool py_callmethod(py_Ref self, py_Name name, int argc, py_Ref argv){
|
bool py_callmethod(py_Ref self, py_Name name, int argc, py_Ref argv) { return -1; }
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pk_vectorcall(int argc, int kwargc, bool op_call){
|
bool pk_vectorcall(int argc, int kwargc, bool op_call) { return -1; }
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
py_Ref py_lastretval(){
|
py_Ref py_lastretval() { return &pk_current_vm->last_retval; }
|
||||||
return &pk_current_vm->last_retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool py_getunboundmethod(const py_Ref self, py_Name name, bool fallback, py_Ref out, py_Ref out_self){
|
bool py_getunboundmethod(const py_Ref self,
|
||||||
|
py_Name name,
|
||||||
|
bool fallback,
|
||||||
|
py_Ref out,
|
||||||
|
py_Ref out_self) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,3 +65,32 @@ pk_TypeInfo* pk_tpinfo(const py_Ref self){
|
|||||||
return c11__at(pk_TypeInfo, &vm->types, self->type);
|
return c11__at(pk_TypeInfo, &vm->types, self->type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
py_Ref py_tpfindmagic(py_Type t, py_Name name) {
|
||||||
|
assert(name < 64);
|
||||||
|
pk_TypeInfo* types = (pk_TypeInfo*)pk_current_vm->types.data;
|
||||||
|
do {
|
||||||
|
py_Ref f = &types[t].magic[name];
|
||||||
|
if(!py_isnull(f)) return f;
|
||||||
|
t = types[t].base;
|
||||||
|
} while(t);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
py_Ref py_tpmagic(py_Type type, py_Name name) {
|
||||||
|
assert(name < 64);
|
||||||
|
pk_VM* vm = pk_current_vm;
|
||||||
|
return &c11__at(pk_TypeInfo, &vm->types, type)->magic[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
py_Ref py_tpobject(py_Type type) {
|
||||||
|
pk_VM* vm = pk_current_vm;
|
||||||
|
return &c11__at(pk_TypeInfo, &vm->types, type)->self;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool py_callmagic(py_Name name, int argc, py_Ref argv) {
|
||||||
|
assert(argc >= 1);
|
||||||
|
py_Ref tmp = py_tpfindmagic(argv->type, name);
|
||||||
|
if(!tmp) return TypeError(name);
|
||||||
|
if(tmp->type == tp_nativefunc) { return tmp->_cfunc(argc, argv); }
|
||||||
|
return py_call(tmp, argc, argv);
|
||||||
|
}
|
29
src2/main.c
29
src2/main.c
@ -1,5 +1,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "pocketpy.h"
|
#include "pocketpy.h"
|
||||||
|
|
||||||
@ -25,20 +26,24 @@ int main(int argc, char** argv) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
py_initialize();
|
py_initialize();
|
||||||
const char* source = "[1, 'a']";
|
const char* source = "1 < 2";
|
||||||
|
|
||||||
|
if(py_eval(source)) {
|
||||||
|
// handle the result
|
||||||
|
bool _L0 = py_tobool(py_lastretval());
|
||||||
|
printf("%d\n", _L0);
|
||||||
|
}
|
||||||
|
|
||||||
py_Ref r0 = py_reg(0);
|
py_Ref r0 = py_reg(0);
|
||||||
if(py_eval(source, r0)){
|
py_Ref r1 = py_reg(1);
|
||||||
py_Error* err = py_lasterror();
|
|
||||||
py_Error__print(err);
|
py_newint(r0, 1);
|
||||||
}else{
|
py_newfloat(r1, 2.5);
|
||||||
// handle the result
|
|
||||||
py_Ref _0 = py_list__getitem(r0, 0);
|
bool ok = py_binaryadd(r0, r1);
|
||||||
py_Ref _1 = py_list__getitem(r0, 1);
|
assert(ok);
|
||||||
int _L0 = py_toint(_0);
|
double res = py_tofloat(py_lastretval());
|
||||||
const char* _L1 = py_tostr(_1);
|
printf("%f\n", res);
|
||||||
printf("%d, %s\n", _L0, _L1);
|
|
||||||
}
|
|
||||||
|
|
||||||
py_finalize();
|
py_finalize();
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user