mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-29 07:50:16 +00:00
Compare commits
2 Commits
841cc25a4e
...
8ae999ecdf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8ae999ecdf | ||
|
|
6ac3fdccdb |
@ -11,7 +11,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct c11_array{
|
typedef struct c11_array {
|
||||||
void* data;
|
void* data;
|
||||||
int count;
|
int count;
|
||||||
int elem_size;
|
int elem_size;
|
||||||
@ -21,7 +21,7 @@ void c11_array__ctor(c11_array* self, int elem_size, int count);
|
|||||||
void c11_array__dtor(c11_array* self);
|
void c11_array__dtor(c11_array* self);
|
||||||
c11_array c11_array__copy(const c11_array* self);
|
c11_array c11_array__copy(const c11_array* self);
|
||||||
|
|
||||||
typedef struct c11_vector{
|
typedef struct c11_vector {
|
||||||
void* data;
|
void* data;
|
||||||
int count;
|
int count;
|
||||||
int capacity;
|
int capacity;
|
||||||
@ -40,54 +40,57 @@ c11_array c11_vector__submit(c11_vector* self);
|
|||||||
#define c11__setitem(T, self, index, value) ((T*)(self)->data)[index] = value;
|
#define c11__setitem(T, self, index, value) ((T*)(self)->data)[index] = value;
|
||||||
#define c11__at(T, self, index) ((T*)(self)->data + index)
|
#define c11__at(T, self, index) ((T*)(self)->data + index)
|
||||||
|
|
||||||
#define c11_vector__push(T, self, elem) \
|
#define c11_vector__push(T, self, elem) \
|
||||||
do{ \
|
do { \
|
||||||
if((self)->count == (self)->capacity) c11_vector__reserve((self), (self)->capacity*2); \
|
if((self)->count == (self)->capacity) c11_vector__reserve((self), (self)->capacity * 2); \
|
||||||
((T*)(self)->data)[(self)->count] = (elem); \
|
((T*)(self)->data)[(self)->count] = (elem); \
|
||||||
(self)->count++; \
|
(self)->count++; \
|
||||||
}while(0)
|
} while(0)
|
||||||
|
|
||||||
#define c11_vector__pop(self) (--(self)->count)
|
#define c11_vector__pop(self) (--(self)->count)
|
||||||
|
|
||||||
#define c11_vector__back(T, self) \
|
#define c11_vector__back(T, self) (((T*)(self)->data)[(self)->count - 1])
|
||||||
(((T*)(self)->data)[(self)->count - 1])
|
|
||||||
|
|
||||||
#define c11_vector__extend(T, self, p, size) \
|
#define c11_vector__extend(T, self, p, size) \
|
||||||
do{ \
|
do { \
|
||||||
c11_vector__reserve((self), (self)->count + (size)); \
|
c11_vector__reserve((self), (self)->count + (size)); \
|
||||||
memcpy((T*)(self)->data + (self)->count, (p), (size) * sizeof(T)); \
|
memcpy((T*)(self)->data + (self)->count, (p), (size) * sizeof(T)); \
|
||||||
(self)->count += (size); \
|
(self)->count += (size); \
|
||||||
}while(0)
|
} while(0)
|
||||||
|
|
||||||
|
#define c11_vector__insert(T, self, index, elem) \
|
||||||
|
do { \
|
||||||
|
if((self)->count == (self)->capacity) c11_vector__reserve((self), (self)->capacity * 2); \
|
||||||
|
T* p = (T*)(self)->data + (index); \
|
||||||
|
memmove(p + 1, p, ((self)->count - (index)) * sizeof(T)); \
|
||||||
|
*p = (elem); \
|
||||||
|
(self)->count++; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define c11_vector__erase(T, self, index) \
|
||||||
|
do { \
|
||||||
|
T* p = (T*)(self)->data + (index); \
|
||||||
|
memmove(p, p + 1, ((self)->count - (index)-1) * sizeof(T)); \
|
||||||
|
(self)->count--; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define c11_vector__reverse(T, self, start, end) \
|
||||||
|
do { \
|
||||||
|
T* p = (T*)(self)->data + (start); \
|
||||||
|
T* q = (T*)(self)->data + (end); \
|
||||||
|
while(p < q) { \
|
||||||
|
T tmp = *p; \
|
||||||
|
*p = *q; \
|
||||||
|
*q = tmp; \
|
||||||
|
p++; \
|
||||||
|
q--; \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
|
||||||
#define c11_vector__insert(T, self, index, elem) \
|
// NOTE: here we do an extra NULL check for it to avoid UB
|
||||||
do{ \
|
#define c11__foreach(T, self, it) \
|
||||||
if((self)->count == (self)->capacity) c11_vector__reserve((self), (self)->capacity*2); \
|
for(T* it = (self)->data; it && it != (T*)(self)->data + (self)->count; it++)
|
||||||
T* p = (T*)(self)->data + (index); \
|
|
||||||
memmove(p + 1, p, ((self)->count - (index)) * sizeof(T)); \
|
|
||||||
*p = (elem); \
|
|
||||||
(self)->count++; \
|
|
||||||
}while(0)
|
|
||||||
|
|
||||||
#define c11_vector__erase(T, self, index) \
|
|
||||||
do{ \
|
|
||||||
T* p = (T*)(self)->data + (index); \
|
|
||||||
memmove(p, p + 1, ((self)->count - (index) - 1) * sizeof(T)); \
|
|
||||||
(self)->count--; \
|
|
||||||
}while(0)
|
|
||||||
|
|
||||||
#define c11_vector__reverse(T, self, start, end) \
|
|
||||||
do{ \
|
|
||||||
T* p = (T*)(self)->data + (start); \
|
|
||||||
T* q = (T*)(self)->data + (end); \
|
|
||||||
while(p < q){ \
|
|
||||||
T tmp = *p; *p = *q; *q = tmp; \
|
|
||||||
p++; q--; \
|
|
||||||
} \
|
|
||||||
}while(0)
|
|
||||||
|
|
||||||
#define c11__foreach(T, self, it) \
|
|
||||||
for(T* it = (T*)(self)->data; it != (T*)(self)->data + (self)->count; it++)
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -87,6 +87,8 @@ py_Type pk_VM__new_type(pk_VM* self,
|
|||||||
const py_TValue* module,
|
const py_TValue* module,
|
||||||
bool subclass_enabled);
|
bool subclass_enabled);
|
||||||
|
|
||||||
|
pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bool opcall);
|
||||||
|
|
||||||
// type registration
|
// type registration
|
||||||
py_Type pk_str__register();
|
py_Type pk_str__register();
|
||||||
py_Type pk_bytes__register();
|
py_Type pk_bytes__register();
|
||||||
|
|||||||
@ -128,11 +128,11 @@ py_GlobalRef py_tpmagic(py_Type type, py_Name name);
|
|||||||
// new style decl-based bindings
|
// new style decl-based bindings
|
||||||
py_TmpRef py_bind(py_Ref obj, const char* sig, py_CFunction f);
|
py_TmpRef py_bind(py_Ref obj, const char* sig, py_CFunction f);
|
||||||
py_TmpRef py_bind2(py_Ref obj,
|
py_TmpRef py_bind2(py_Ref obj,
|
||||||
const char* sig,
|
const char* sig,
|
||||||
py_CFunction f,
|
py_CFunction f,
|
||||||
BindType bt,
|
BindType bt,
|
||||||
const char* docstring,
|
const char* docstring,
|
||||||
const py_Ref upvalue);
|
const py_Ref upvalue);
|
||||||
// old style argc-based bindings
|
// old style argc-based bindings
|
||||||
void py_bindmethod(py_Type type, const char* name, py_CFunction f);
|
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_bindmethod2(py_Type type, const char* name, py_CFunction f, BindType bt);
|
||||||
@ -253,7 +253,7 @@ bool py_isidentical(const py_Ref, const py_Ref);
|
|||||||
/// It assumes `argc + kwargc` arguments are already pushed to the stack.
|
/// It assumes `argc + kwargc` arguments are already pushed to the stack.
|
||||||
/// The result will be set to `py_retval()`.
|
/// The result will be set to `py_retval()`.
|
||||||
/// The stack size will be reduced by `argc + kwargc`.
|
/// The stack size will be reduced by `argc + kwargc`.
|
||||||
bool pk_vectorcall(int argc, int kwargc, bool op_call);
|
bool py_vectorcall(uint16_t argc, uint16_t kwargc);
|
||||||
/// 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 `py_retval()`.
|
/// The result will be set to `py_retval()`.
|
||||||
@ -323,26 +323,43 @@ bool py_checktype(const py_Ref self, py_Type type);
|
|||||||
/// %t: py_Type
|
/// %t: py_Type
|
||||||
/// %n: py_Name
|
/// %n: py_Name
|
||||||
|
|
||||||
|
enum py_MagicNames {
|
||||||
enum py_MagicNames{
|
|
||||||
py_MagicNames__NULL, // 0 is reserved
|
py_MagicNames__NULL, // 0 is reserved
|
||||||
#define MAGIC_METHOD(x) x,
|
|
||||||
#include "pocketpy/xmacros/magics.h"
|
#define MAGIC_METHOD(x) x,
|
||||||
#undef MAGIC_METHOD
|
#include "pocketpy/xmacros/magics.h"
|
||||||
|
#undef MAGIC_METHOD
|
||||||
};
|
};
|
||||||
|
|
||||||
enum py_PredefinedTypes{
|
enum py_PredefinedTypes {
|
||||||
tp_object = 1, tp_type,
|
tp_object = 1,
|
||||||
tp_int, tp_float, tp_bool, tp_str,
|
tp_type,
|
||||||
tp_list, tp_tuple,
|
tp_int,
|
||||||
tp_slice, tp_range, tp_module,
|
tp_float,
|
||||||
tp_function, tp_nativefunc, tp_bound_method,
|
tp_bool,
|
||||||
tp_super, tp_exception, tp_bytes, tp_mappingproxy,
|
tp_str,
|
||||||
tp_dict, tp_property, tp_star_wrapper,
|
tp_list,
|
||||||
tp_staticmethod, tp_classmethod,
|
tp_tuple,
|
||||||
tp_none_type, tp_not_implemented_type,
|
tp_slice,
|
||||||
|
tp_range,
|
||||||
|
tp_module,
|
||||||
|
tp_function,
|
||||||
|
tp_nativefunc,
|
||||||
|
tp_bound_method,
|
||||||
|
tp_super,
|
||||||
|
tp_exception,
|
||||||
|
tp_bytes,
|
||||||
|
tp_mappingproxy,
|
||||||
|
tp_dict,
|
||||||
|
tp_property,
|
||||||
|
tp_star_wrapper,
|
||||||
|
tp_staticmethod,
|
||||||
|
tp_classmethod,
|
||||||
|
tp_none_type,
|
||||||
|
tp_not_implemented_type,
|
||||||
tp_ellipsis,
|
tp_ellipsis,
|
||||||
tp_syntax_error, tp_stop_iteration
|
tp_syntax_error,
|
||||||
|
tp_stop_iteration
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@ -48,8 +48,8 @@ c11_vector c11_vector__copy(const c11_vector* self){
|
|||||||
void c11_vector__reserve(c11_vector* self, int capacity){
|
void c11_vector__reserve(c11_vector* self, int capacity){
|
||||||
if(capacity < 4) capacity = 4;
|
if(capacity < 4) capacity = 4;
|
||||||
if(capacity <= self->capacity) return;
|
if(capacity <= self->capacity) return;
|
||||||
|
self->data = realloc(self->data, self->elem_size * capacity);
|
||||||
self->capacity = capacity;
|
self->capacity = capacity;
|
||||||
self->data = realloc(self->data, self->elem_size * self->capacity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void c11_vector__clear(c11_vector* self){
|
void c11_vector__clear(c11_vector* self){
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
#include "pocketpy/common/sstream.h"
|
#include "pocketpy/common/sstream.h"
|
||||||
#include "pocketpy/objects/codeobject.h"
|
#include "pocketpy/objects/codeobject.h"
|
||||||
#include "pocketpy/pocketpy.h"
|
#include "pocketpy/pocketpy.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
int UnboundLocalError(py_Name name) { return -1; }
|
int UnboundLocalError(py_Name name) { return -1; }
|
||||||
|
|
||||||
@ -48,9 +49,9 @@ static bool stack_binaryop(pk_VM* self, py_Name op, py_Name rop);
|
|||||||
*SECOND() = *THIRD(); \
|
*SECOND() = *THIRD(); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#define vectorcall_opcall(n) \
|
#define vectorcall_opcall(argc, kwargc) \
|
||||||
do { \
|
do { \
|
||||||
pk_FrameResult res = pk_vectorcall(n, 0, true); \
|
pk_FrameResult res = pk_VM__vectorcall(self, (argc), (kwargc), true); \
|
||||||
switch(res) { \
|
switch(res) { \
|
||||||
case RES_RETURN: PUSH(&self->last_retval); break; \
|
case RES_RETURN: PUSH(&self->last_retval); break; \
|
||||||
case RES_CALL: \
|
case RES_CALL: \
|
||||||
@ -268,7 +269,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
|||||||
} else {
|
} else {
|
||||||
INSERT_THIRD(); // [?, a, b]
|
INSERT_THIRD(); // [?, a, b]
|
||||||
*THIRD() = *magic; // [__getitem__, a, b]
|
*THIRD() = *magic; // [__getitem__, a, b]
|
||||||
vectorcall_opcall(2);
|
vectorcall_opcall(2, 0);
|
||||||
}
|
}
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
@ -321,7 +322,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
|||||||
} else {
|
} else {
|
||||||
INSERT_THIRD(); // [?, a, b]
|
INSERT_THIRD(); // [?, a, b]
|
||||||
*FOURTH() = *magic; // [__selitem__, a, b, val]
|
*FOURTH() = *magic; // [__selitem__, a, b, val]
|
||||||
vectorcall_opcall(3);
|
vectorcall_opcall(3, 0);
|
||||||
POP(); // discard retval
|
POP(); // discard retval
|
||||||
}
|
}
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
@ -391,7 +392,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
|||||||
} else {
|
} else {
|
||||||
INSERT_THIRD(); // [?, a, b]
|
INSERT_THIRD(); // [?, a, b]
|
||||||
*THIRD() = *magic; // [__delitem__, a, b]
|
*THIRD() = *magic; // [__delitem__, a, b]
|
||||||
vectorcall_opcall(2);
|
vectorcall_opcall(2, 0);
|
||||||
POP(); // discard retval
|
POP(); // discard retval
|
||||||
}
|
}
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
@ -415,11 +416,11 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
|||||||
py_Ref f = py_getdict(&self->builtins, py_name("complex"));
|
py_Ref f = py_getdict(&self->builtins, py_name("complex"));
|
||||||
assert(f != NULL);
|
assert(f != NULL);
|
||||||
py_TValue tmp = *TOP();
|
py_TValue tmp = *TOP();
|
||||||
*TOP() = *f; // [complex]
|
*TOP() = *f; // [complex]
|
||||||
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)]
|
vectorcall_opcall(2, 0); // [complex(x)]
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
case OP_BUILD_BYTES: {
|
case OP_BUILD_BYTES: {
|
||||||
@ -526,7 +527,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
|||||||
} else {
|
} else {
|
||||||
INSERT_THIRD(); // [?, b, a]
|
INSERT_THIRD(); // [?, b, a]
|
||||||
*THIRD() = *magic; // [__contains__, a, b]
|
*THIRD() = *magic; // [__contains__, a, b]
|
||||||
vectorcall_opcall(2);
|
vectorcall_opcall(2, 0);
|
||||||
}
|
}
|
||||||
bool res = py_tobool(TOP());
|
bool res = py_tobool(TOP());
|
||||||
if(byte.arg) py_newbool(TOP(), !res);
|
if(byte.arg) py_newbool(TOP(), !res);
|
||||||
@ -604,6 +605,19 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
|||||||
// DISPATCH_JUMP_ABSOLUTE(target)
|
// DISPATCH_JUMP_ABSOLUTE(target)
|
||||||
// }
|
// }
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
|
case OP_FSTRING_EVAL: {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
case OP_REPR: {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
case OP_CALL: {
|
||||||
|
pk_ManagedHeap__collect_if_needed(&self->heap);
|
||||||
|
vectorcall_opcall(byte.arg & 0xFF, byte.arg >> 8);
|
||||||
|
}
|
||||||
|
case OP_CALL_VARGS: {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
case OP_RETURN_VALUE: {
|
case OP_RETURN_VALUE: {
|
||||||
if(byte.arg == BC_NOARG) {
|
if(byte.arg == BC_NOARG) {
|
||||||
self->last_retval = POPX();
|
self->last_retval = POPX();
|
||||||
|
|||||||
@ -98,11 +98,13 @@ static bool _py_number__pow__(int argc, py_Ref argv) {
|
|||||||
py_newfloat(py_retval(), pow(lhs, rhs));
|
py_newfloat(py_retval(), pow(lhs, rhs));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// rhs >= 0
|
||||||
int64_t ret = 1;
|
int64_t ret = 1;
|
||||||
while(rhs) {
|
while(true){
|
||||||
if(rhs & 1) ret *= lhs;
|
if(rhs & 1) ret *= lhs;
|
||||||
lhs *= lhs;
|
|
||||||
rhs >>= 1;
|
rhs >>= 1;
|
||||||
|
if(!rhs) break;
|
||||||
|
lhs *= lhs; // place this here to avoid overflow
|
||||||
}
|
}
|
||||||
py_newint(py_retval(), ret);
|
py_newint(py_retval(), ret);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,13 @@
|
|||||||
#include "pocketpy/interpreter/vm.h"
|
#include "pocketpy/interpreter/vm.h"
|
||||||
#include "pocketpy/common/memorypool.h"
|
#include "pocketpy/common/memorypool.h"
|
||||||
#include "pocketpy/common/sstream.h"
|
#include "pocketpy/common/sstream.h"
|
||||||
|
#include "pocketpy/common/utils.h"
|
||||||
#include "pocketpy/objects/base.h"
|
#include "pocketpy/objects/base.h"
|
||||||
#include "pocketpy/pocketpy.h"
|
#include "pocketpy/pocketpy.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
static unsigned char* pk_default_import_file(const char* path) { return NULL; }
|
static unsigned char* pk_default_import_file(const char* path) { return NULL; }
|
||||||
|
|
||||||
@ -69,7 +72,7 @@ void pk_VM__ctor(pk_VM* self) {
|
|||||||
|
|
||||||
self->last_retval = PY_NULL;
|
self->last_retval = PY_NULL;
|
||||||
self->has_error = false;
|
self->has_error = false;
|
||||||
|
|
||||||
self->__curr_class = PY_NULL;
|
self->__curr_class = PY_NULL;
|
||||||
self->__cached_object_new = PY_NULL;
|
self->__cached_object_new = PY_NULL;
|
||||||
self->__dynamic_func_decl = NULL;
|
self->__dynamic_func_decl = NULL;
|
||||||
@ -196,6 +199,176 @@ py_Type pk_VM__new_type(pk_VM* self,
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t ARGC, uint16_t KWARGC, bool opcall) {
|
||||||
|
py_Ref p1 = self->stack.sp - KWARGC * 2;
|
||||||
|
py_Ref p0 = p1 - ARGC - 2;
|
||||||
|
// [callable, <self>, args..., kwargs...]
|
||||||
|
// ^p0 ^p1 ^_sp
|
||||||
|
|
||||||
|
// handle boundmethod, do a patch
|
||||||
|
if(p0->type == tp_bound_method) {
|
||||||
|
assert(false);
|
||||||
|
assert(py_isnull(p0+1)); // self must be NULL
|
||||||
|
// BoundMethod& bm = PK_OBJ_GET(BoundMethod, callable);
|
||||||
|
// callable = bm.func; // get unbound method
|
||||||
|
// callable_t = _tp(callable);
|
||||||
|
// p1[-(ARGC + 2)] = bm.func;
|
||||||
|
// p1[-(ARGC + 1)] = bm.self;
|
||||||
|
// [unbound, self, args..., kwargs...]
|
||||||
|
}
|
||||||
|
|
||||||
|
// PyVar* _base = args.begin();
|
||||||
|
py_Ref argv = py_isnull(p0+1) ? p0+2 : p0+1;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if(callable_t == tp_function) {
|
||||||
|
/*****************_py_call*****************/
|
||||||
|
// check stack overflow
|
||||||
|
if(self->stack.sp > self->stack.end){
|
||||||
|
StackOverflowError();
|
||||||
|
return RES_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Function& fn = PK_OBJ_GET(Function, callable);
|
||||||
|
const CodeObject* co = fn.decl->code;
|
||||||
|
|
||||||
|
switch(fn.decl->type) {
|
||||||
|
case FuncType_NORMAL:
|
||||||
|
__prepare_py_call(__vectorcall_buffer, args, kwargs, fn.decl);
|
||||||
|
// copy buffer back to stack
|
||||||
|
s_data.reset(_base + co->nlocals);
|
||||||
|
for(int j = 0; j < co->nlocals; j++)
|
||||||
|
_base[j] = __vectorcall_buffer[j];
|
||||||
|
break;
|
||||||
|
case FuncType_SIMPLE:
|
||||||
|
if(args.size() != fn.decl->args.count) {
|
||||||
|
TypeError(pk_format("{} takes {} positional arguments but {} were given",
|
||||||
|
&co->name,
|
||||||
|
fn.decl->args.count,
|
||||||
|
args.size()));
|
||||||
|
}
|
||||||
|
if(!kwargs.empty()) {
|
||||||
|
TypeError(pk_format("{} takes no keyword arguments", &co->name));
|
||||||
|
}
|
||||||
|
// [callable, <self>, args..., local_vars...]
|
||||||
|
// ^p0 ^p1 ^_sp
|
||||||
|
s_data.reset(_base + co->nlocals);
|
||||||
|
// initialize local variables to PY_NULL
|
||||||
|
std::memset(p1, 0, (char*)s_data._sp - (char*)p1);
|
||||||
|
break;
|
||||||
|
case FuncType_EMPTY:
|
||||||
|
if(args.size() != fn.decl->args.count) {
|
||||||
|
TypeError(pk_format("{} takes {} positional arguments but {} were given",
|
||||||
|
&co->name,
|
||||||
|
fn.decl->args.count,
|
||||||
|
args.size()));
|
||||||
|
}
|
||||||
|
if(!kwargs.empty()) {
|
||||||
|
TypeError(pk_format("{} takes no keyword arguments", &co->name));
|
||||||
|
}
|
||||||
|
s_data.reset(p0);
|
||||||
|
return None;
|
||||||
|
case FuncType_GENERATOR:
|
||||||
|
__prepare_py_call(__vectorcall_buffer, args, kwargs, fn.decl);
|
||||||
|
s_data.reset(p0);
|
||||||
|
callstack.emplace(nullptr, co, fn._module, callable.get(), nullptr);
|
||||||
|
return __py_generator(
|
||||||
|
callstack.popx(),
|
||||||
|
ArgsView(__vectorcall_buffer, __vectorcall_buffer + co->nlocals));
|
||||||
|
default: PK_UNREACHABLE()
|
||||||
|
};
|
||||||
|
|
||||||
|
// simple or normal
|
||||||
|
callstack.emplace(p0, co, fn._module, callable.get(), args.begin());
|
||||||
|
if(op_call) return pkpy_OP_CALL;
|
||||||
|
return __run_top_frame();
|
||||||
|
/*****************_py_call*****************/
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(p0->type == tp_nativefunc) {
|
||||||
|
// const auto& f = PK_OBJ_GET(NativeFunc, callable);
|
||||||
|
// PyVar ret;
|
||||||
|
// if(f.decl != nullptr) {
|
||||||
|
// int co_nlocals = f.decl->code->nlocals;
|
||||||
|
// __prepare_py_call(__vectorcall_buffer, args, kwargs, f.decl);
|
||||||
|
// // copy buffer back to stack
|
||||||
|
// s_data.reset(_base + co_nlocals);
|
||||||
|
// for(int j = 0; j < co_nlocals; j++)
|
||||||
|
// _base[j] = __vectorcall_buffer[j];
|
||||||
|
// ret = f.call(vm, ArgsView(s_data._sp - co_nlocals, s_data._sp));
|
||||||
|
// } else {
|
||||||
|
// if(f.argc != -1) {
|
||||||
|
// if(KWARGC != 0)
|
||||||
|
// TypeError(
|
||||||
|
// "old-style native_func does not accept keyword arguments. If you want to skip this check, specify `argc` to -1");
|
||||||
|
// if(args.size() != f.argc) {
|
||||||
|
// vm->TypeError(_S("expected ", f.argc, " arguments, got ", args.size()));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// ret = f.call(this, args);
|
||||||
|
// }
|
||||||
|
|
||||||
|
if(!p0->_cfunc(ARGC, argv)) return RES_ERROR;
|
||||||
|
self->stack.sp = p0;
|
||||||
|
return RES_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if(p0->type == tp_type) {
|
||||||
|
// [type, NULL, args..., kwargs...]
|
||||||
|
PyVar new_f = *find_name_in_mro(PK_OBJ_GET(Type, callable), __new__);
|
||||||
|
PyVar obj;
|
||||||
|
assert(new_f && (!p0[1]));
|
||||||
|
if(PyVar__IS_OP(&new_f, &__cached_object_new)) {
|
||||||
|
// fast path for object.__new__
|
||||||
|
obj = vm->new_object<DummyInstance>(PK_OBJ_GET(Type, callable));
|
||||||
|
} else {
|
||||||
|
PUSH(new_f);
|
||||||
|
PUSH(PY_NULL);
|
||||||
|
PUSH(callable); // cls
|
||||||
|
for(PyVar o: args)
|
||||||
|
PUSH(o);
|
||||||
|
for(PyVar o: kwargs)
|
||||||
|
PUSH(o);
|
||||||
|
// if obj is not an instance of `cls`, the behavior is undefined
|
||||||
|
obj = vectorcall(ARGC + 1, KWARGC);
|
||||||
|
}
|
||||||
|
|
||||||
|
// __init__
|
||||||
|
PyVar self;
|
||||||
|
callable = get_unbound_method(obj, __init__, &self, false);
|
||||||
|
if(callable) {
|
||||||
|
callable_t = _tp(callable);
|
||||||
|
// replace `NULL` with `self`
|
||||||
|
p1[-(ARGC + 2)] = callable;
|
||||||
|
p1[-(ARGC + 1)] = self;
|
||||||
|
// [init_f, self, args..., kwargs...]
|
||||||
|
vectorcall(ARGC, KWARGC);
|
||||||
|
// We just discard the return value of `__init__`
|
||||||
|
// in cpython it raises a TypeError if the return value is not None
|
||||||
|
} else {
|
||||||
|
// manually reset the stack
|
||||||
|
s_data.reset(p0);
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle `__call__` overload
|
||||||
|
PyVar self;
|
||||||
|
PyVar call_f = get_unbound_method(callable, __call__, &self, false);
|
||||||
|
if(self) {
|
||||||
|
p1[-(ARGC + 2)] = call_f;
|
||||||
|
p1[-(ARGC + 1)] = self;
|
||||||
|
// [call_f, self, args..., kwargs...]
|
||||||
|
return vectorcall(ARGC, KWARGC, op_call);
|
||||||
|
}
|
||||||
|
TypeError(_type_name(vm, callable_t).escape() + " object is not callable");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PK_UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************/
|
/****************************************/
|
||||||
void PyObject__delete(PyObject* self) {
|
void PyObject__delete(PyObject* self) {
|
||||||
pk_TypeInfo* ti = c11__at(pk_TypeInfo, &pk_current_vm->types, self->type);
|
pk_TypeInfo* ti = c11__at(pk_TypeInfo, &pk_current_vm->types, self->type);
|
||||||
@ -221,4 +394,4 @@ void pk_ManagedHeap__mark(pk_ManagedHeap* self) {
|
|||||||
// vm->obj_gc_mark(vm->__c.error);
|
// vm->obj_gc_mark(vm->__c.error);
|
||||||
// vm->__stack_gc_mark(vm->s_data.begin(), vm->s_data.end());
|
// vm->__stack_gc_mark(vm->s_data.begin(), vm->s_data.end());
|
||||||
// if(self->_gc_marker_ex) self->_gc_marker_ex((pkpy_VM*)vm);
|
// if(self->_gc_marker_ex) self->_gc_marker_ex((pkpy_VM*)vm);
|
||||||
}
|
}
|
||||||
@ -6,6 +6,7 @@
|
|||||||
#include "pocketpy/objects/object.h"
|
#include "pocketpy/objects/object.h"
|
||||||
#include "pocketpy/interpreter/vm.h"
|
#include "pocketpy/interpreter/vm.h"
|
||||||
#include "pocketpy/compiler/compiler.h"
|
#include "pocketpy/compiler/compiler.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
pk_VM* pk_current_vm;
|
pk_VM* pk_current_vm;
|
||||||
static pk_VM pk_default_vm;
|
static pk_VM pk_default_vm;
|
||||||
@ -67,12 +68,14 @@ static void disassemble(CodeObject* co) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
char buf[32];
|
char buf[32];
|
||||||
snprintf(buf, sizeof(buf), "%-8s%-3s%-3d", line, pointer, i);
|
snprintf(buf, sizeof(buf), "%-8s%-3s%-3d ", line, pointer, i);
|
||||||
c11_sbuf__write_cstr(&ss, buf);
|
c11_sbuf__write_cstr(&ss, buf);
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), " %-24s", OP_NAMES[byte.op]);
|
c11_sbuf__write_cstr(&ss, OP_NAMES[byte.op]);
|
||||||
c11_sbuf__write_cstr(&ss, buf);
|
|
||||||
c11_sbuf__write_char(&ss, ex.is_virtual ? '*' : ' ');
|
c11_sbuf__write_char(&ss, ex.is_virtual ? '*' : ' ');
|
||||||
|
int padding = 24 - strlen(OP_NAMES[byte.op]);
|
||||||
|
for(int j = 0; j < padding; j++)
|
||||||
|
c11_sbuf__write_char(&ss, ' ');
|
||||||
|
|
||||||
// _opcode_argstr(this, i, byte, co);
|
// _opcode_argstr(this, i, byte, co);
|
||||||
do {
|
do {
|
||||||
@ -181,7 +184,10 @@ bool py_call(py_Ref f, int argc, py_Ref argv) { return -1; }
|
|||||||
|
|
||||||
bool py_callmethod(py_Ref self, py_Name name, int argc, py_Ref argv) { return -1; }
|
bool py_callmethod(py_Ref self, py_Name name, int argc, py_Ref argv) { return -1; }
|
||||||
|
|
||||||
bool pk_vectorcall(int argc, int kwargc, bool op_call) { return -1; }
|
bool py_vectorcall(uint16_t argc, uint16_t kwargc) {
|
||||||
|
pk_VM* vm = pk_current_vm;
|
||||||
|
return pk_VM__vectorcall(vm, argc, kwargc, false) == RES_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
py_Ref py_retval() { return &pk_current_vm->last_retval; }
|
py_Ref py_retval() { return &pk_current_vm->last_retval; }
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user