This commit is contained in:
blueloveTH 2024-07-01 11:38:53 +08:00
parent d00c058c46
commit 15fd2ef8a0
16 changed files with 164 additions and 148 deletions

View File

@ -5,8 +5,12 @@ python prebuild.py
SRC=$(find src/ -name "*.c") SRC=$(find src/ -name "*.c")
FLAGS="-std=c11 -lm -Iinclude -O0 -Wfatal-errors -g -DDEBUG -DPK_ENABLE_OS=1" FLAGS="-std=c11 -lm -Iinclude -O0 -Wfatal-errors -g -DDEBUG -DPK_ENABLE_OS=1"
SANITIZE_FLAGS="-fsanitize=address,leak,undefined" SANITIZE_FLAGS="-fsanitize=address,leak,undefined"
# SANITIZE_FLAGS=""
if [ "$(uname)" == "Darwin" ]; then
SANITIZE_FLAGS="-fsanitize=address,undefined"
fi
echo "Compiling C files..." echo "Compiling C files..."
clang $FLAGS $SANITIZE_FLAGS $SRC src2/main.c -o main clang $FLAGS $SANITIZE_FLAGS $SRC src2/main.c -o main

View File

@ -10,8 +10,6 @@ extern "C" {
typedef uint16_t StrName; typedef uint16_t StrName;
#define py_name(name) pk_StrName__map(name)
uint16_t pk_StrName__map(const char*); uint16_t pk_StrName__map(const char*);
uint16_t pk_StrName__map2(c11_string); uint16_t pk_StrName__map2(c11_string);
const char* pk_StrName__rmap(uint16_t index); const char* pk_StrName__rmap(uint16_t index);

View File

@ -8,61 +8,54 @@
extern "C" { extern "C" {
#endif #endif
typedef struct pk_TypeInfo{ typedef struct pk_TypeInfo {
py_Name name; py_Name name;
py_Type base; py_Type base;
py_TValue self; // the type object itself py_TValue self;
py_TValue module; // the module where the type is defined py_TValue module; // the module where the type is defined
bool subclass_enabled; bool subclass_enabled;
void (*dtor)(void*); void (*dtor)(void*);
void (*gc_mark)(void*); void (*gc_mark)(void*);
c11_vector/*T=StrName*/ annotated_fields; c11_vector /*T=StrName*/ annotated_fields;
py_CFunction on_end_subclass; // backdoor for enum module py_CFunction on_end_subclass; // backdoor for enum module
/* Magic Caches */ /* Magic Slots */
py_TValue magic[64]; py_TValue magic[64];
// // unary operators
// py_CFunction m__repr__, m__str__, m__hash__, m__len__;
// py_CFunction m__iter__, m__next__, m__neg__, m__invert__;
// // binary operators
// py_CFunction m__eq__, m__lt__, m__le__, m__gt__, m__ge__, m__contains__;
// py_CFunction m__add__, m__sub__, m__mul__, m__truediv__, m__floordiv__;
// py_CFunction m__mod__, m__pow__, m__matmul__;
// py_CFunction m__lshift__, m__rshift__, m__and__, m__xor__, m__or__;
// // indexer
// py_CFunction m__getitem__, m__setitem__, m__delitem__;
// // attribute access (internal use only)
// py_CFunction m__getattr__, m__setattr__, m__delattr__;
} 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 index,
py_Type base,
const py_TValue* module,
bool subclass_enabled);
void pk_TypeInfo__dtor(pk_TypeInfo* self); void pk_TypeInfo__dtor(pk_TypeInfo* self);
typedef struct pk_VM { typedef struct pk_VM {
Frame* top_frame; Frame* top_frame;
pk_NameDict modules;
c11_vector/*T=pk_TypeInfo*/ types;
py_TValue StopIteration; // a special Exception class pk_NameDict modules;
py_TValue builtins; // builtins module c11_vector /*T=pk_TypeInfo*/ types;
py_TValue main; // __main__ module
py_TValue StopIteration; // a special Exception class
py_TValue builtins; // builtins module
py_TValue main; // __main__ module
void (*_ceval_on_step)(Frame*, Bytecode); void (*_ceval_on_step)(Frame*, Bytecode);
unsigned char* (*_import_file)(const char*); unsigned char* (*_import_file)(const char*);
void (*_stdout)(const char*, ...); void (*_stdout)(const char*, ...);
void (*_stderr)(const char*, ...); void (*_stderr)(const char*, ...);
// singleton objects // singleton objects
py_TValue True, False, None, NotImplemented, Ellipsis; py_TValue True, False, None, NotImplemented, Ellipsis;
py_Error* last_error; py_Error* last_error;
py_TValue last_retval; py_TValue last_retval;
py_TValue reg[8]; // users' registers py_TValue reg[8]; // users' registers
py_TValue __curr_class; py_TValue __curr_class;
py_TValue __cached_object_new; py_TValue __cached_object_new;
@ -70,7 +63,7 @@ typedef struct pk_VM {
py_TValue __vectorcall_buffer[PK_MAX_CO_VARNAMES]; py_TValue __vectorcall_buffer[PK_MAX_CO_VARNAMES];
pk_ManagedHeap heap; pk_ManagedHeap heap;
ValueStack stack; // put `stack` at the end for better cache locality ValueStack stack; // put `stack` at the end for better cache locality
} pk_VM; } pk_VM;
void pk_VM__ctor(pk_VM* self); void pk_VM__ctor(pk_VM* self);
@ -81,7 +74,7 @@ void pk_VM__pop_frame(pk_VM* self);
void pk_VM__init_builtins(pk_VM* self); void pk_VM__init_builtins(pk_VM* self);
typedef enum pk_FrameResult{ typedef enum pk_FrameResult {
RES_RETURN, RES_RETURN,
RES_CALL, RES_CALL,
RES_YIELD, RES_YIELD,
@ -90,7 +83,11 @@ typedef enum pk_FrameResult{
pk_FrameResult pk_VM__run_top_frame(pk_VM* self); 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 // type registration
py_Type pk_list__register(); py_Type pk_list__register();

View File

@ -24,9 +24,9 @@ typedef struct py_TValue {
union { union {
int64_t _i64; int64_t _i64;
double _f64; double _f64;
PyObject* _obj; bool _bool;
void* _ptr;
py_CFunction _cfunc; py_CFunction _cfunc;
PyObject* _obj;
// Vec2 // Vec2
}; };
} py_TValue; } py_TValue;
@ -46,20 +46,10 @@ const static py_Type tp_dict = {19}, tp_property = {20}, tp_star_wrapper = {21};
const static py_Type tp_staticmethod = {22}, tp_classmethod = {23}; const static py_Type tp_staticmethod = {22}, tp_classmethod = {23};
const static py_Type tp_none_type = {24}, tp_not_implemented_type = {25}; const static py_Type tp_none_type = {24}, tp_not_implemented_type = {25};
const static py_Type tp_ellipsis = {26}; const static py_Type tp_ellipsis = {26};
const static py_Type tp_op_call = {27}, tp_op_yield = {28}; const static py_Type tp_syntax_error = {27}, tp_stop_iteration = {28};
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;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
/*
SSO types:
1. int64_t
2. double
3. bool (dummy)
4. tuple (extra + void*)
5. string (extra + void* or buf)
*/

View File

@ -36,7 +36,7 @@ void py_finalize();
/// Run a simple source string. Do not change the stack. /// Run a simple source string. Do not change the stack.
bool py_exec(const char*); bool py_exec(const char*);
/// Eval a simple expression. /// Eval a simple expression.
/// The result will be set to `vm->last_retval`. /// The result will be set to `py_retval()`.
bool py_eval(const char*); bool py_eval(const char*);
/************* Values Creation *************/ /************* Values Creation *************/
@ -45,10 +45,11 @@ void py_newfloat(py_Ref, double);
void py_newbool(py_Ref, bool); void py_newbool(py_Ref, bool);
void py_newstr(py_Ref, const char*); void py_newstr(py_Ref, const char*);
void py_newstrn(py_Ref, const char*, int); void py_newstrn(py_Ref, const char*, int);
void py_newStr_(py_Ref, py_Str);
// void py_newfstr(py_Ref, const char*, ...); // void py_newfstr(py_Ref, const char*, ...);
void py_newbytes(py_Ref, const unsigned char*, int); void py_newbytes(py_Ref, const unsigned char*, int);
void py_newnone(py_Ref); void py_newnone(py_Ref);
void py_newnotimplemented(py_Ref out);
void py_newellipsis(py_Ref out);
void py_newnull(py_Ref); void py_newnull(py_Ref);
/// Create a tuple with n UNINITIALIZED elements. /// Create a tuple with n UNINITIALIZED elements.
@ -60,6 +61,10 @@ void py_newlist(py_Ref);
/// You should initialize all elements before using it. /// You should initialize all elements before using it.
void py_newlistn(py_Ref, int n); void py_newlistn(py_Ref, int n);
py_Name py_name(const char*);
const char* py_name2str(py_Name);
bool py_ismagicname(py_Name);
// opaque types // opaque types
void py_newdict(py_Ref); void py_newdict(py_Ref);
void py_newset(py_Ref); void py_newset(py_Ref);
@ -76,8 +81,6 @@ void py_newfunction2(py_Ref out,
// old style argc-based function // old style argc-based function
void py_newnativefunc(py_Ref out, py_CFunction); void py_newnativefunc(py_Ref out, py_CFunction);
void py_newnotimplemented(py_Ref out);
/// Create a new object. /// Create a new object.
/// @param out output reference. /// @param out output reference.
/// @param type type of the object. /// @param type type of the object.
@ -89,6 +92,7 @@ int64_t py_toint(const py_Ref);
double py_tofloat(const py_Ref); 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);
py_Type py_totype(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* size); const char* py_tostrn(const py_Ref, int* size);
@ -104,8 +108,10 @@ 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 py_offset(p, i) (py_Ref)((char*)p + ((i) << 4))
#define TypeError(x) false #define TypeError(x) false
#define py_arg(i) (py_Ref)((char*)argv + ((i) << 4)) #define py_arg(i) py_offset(argv, i)
#define py_checkargc(n) \ #define py_checkargc(n) \
if(argc != n) return TypeError() if(argc != n) return TypeError()
@ -164,7 +170,7 @@ bool py_delitem(py_Ref self, const py_Ref key);
/// Perform a binary operation on the stack. /// Perform a binary operation on the stack.
/// It assumes `lhs` and `rhs` are already pushed to the stack. /// It assumes `lhs` and `rhs` are already pushed to the stack.
/// The result will be set to `vm->last_retval`. /// The result will be set to `py_retval()`.
bool py_binaryop(const py_Ref lhs, const py_Ref rhs, py_Name op, py_Name rop); 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_binaryadd(lhs, rhs) py_binaryop(lhs, rhs, __add__, __radd__)
@ -237,21 +243,21 @@ bool py_isidentical(const py_Ref, const py_Ref);
/// A stack operation that calls a function. /// A stack operation that calls a function.
/// 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 `vm->last_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 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 `py_retval()`.
/// The stack remains unchanged after the operation. /// 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 non-magic 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 `py_retval()`.
/// The stack remains unchanged after the operation. /// The stack remains unchanged after the operation.
bool py_callmethod(py_Ref self, py_Name, int argc, py_Ref argv); bool py_callmethod(py_Ref self, py_Name, int argc, py_Ref argv);
/// Call a magic method. /// Call a magic method.
/// The result will be set to `vm->last_retval`. /// The result will be set to `py_retval()`.
/// The stack remains unchanged after the operation. /// The stack remains unchanged after the operation.
bool py_callmagic(py_Name name, int argc, py_Ref argv); bool py_callmagic(py_Name name, int argc, py_Ref argv);
@ -259,7 +265,7 @@ bool py_callmagic(py_Name name, int argc, py_Ref argv);
#define py_str(self) py_callmagic(__str__, 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_retval();
#define py_isnull(self) ((self)->type == 0) #define py_isnull(self) ((self)->type == 0)

View File

@ -2,6 +2,7 @@
#include "pocketpy/common/smallmap.h" #include "pocketpy/common/smallmap.h"
#include "pocketpy/common/utils.h" #include "pocketpy/common/utils.h"
#include "pocketpy/common/vector.h" #include "pocketpy/common/vector.h"
#include "pocketpy/pocketpy.h"
#include <stdio.h> #include <stdio.h>
@ -80,6 +81,18 @@ c11_string pk_StrName__rmap2(uint16_t index) {
return (c11_string){p, strlen(p)}; return (c11_string){p, strlen(p)};
} }
py_Name py_name(const char* name) {
return pk_StrName__map(name);
}
const char* py_name2str(py_Name name) {
return pk_StrName__rmap(name);
}
bool py_ismagicname(py_Name name){
return name <= __missing__;
}
/////////////////////////////////// ///////////////////////////////////
#define MAGIC_METHOD(x) uint16_t x; #define MAGIC_METHOD(x) uint16_t x;
#include "pocketpy/xmacros/magics.h" #include "pocketpy/xmacros/magics.h"

View File

@ -13,6 +13,9 @@ int NameError(py_Name name) { return -1; }
static bool stack_binaryop(pk_VM* self, py_Name op, py_Name rop); static bool stack_binaryop(pk_VM* self, py_Name op, py_Name rop);
// private
void py_newStr_(py_Ref, py_Str);
#define DISPATCH() \ #define DISPATCH() \
do { \ do { \
frame->ip++; \ frame->ip++; \

View File

@ -45,13 +45,13 @@
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]); \
rint(py_lastretval(), lhs op rhs); \ rint(py_retval(), 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]); \
rfloat(py_lastretval(), lhs op rhs); \ rfloat(py_retval(), lhs op rhs); \
} else { \ } else { \
py_newnotimplemented(py_lastretval()); \ py_newnotimplemented(py_retval()); \
} \ } \
return true; \ return true; \
} \ } \
@ -60,9 +60,9 @@
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)) { \
rfloat(py_lastretval(), lhs op rhs); \ rfloat(py_retval(), lhs op rhs); \
} else { \ } else { \
py_newnotimplemented(py_lastretval()); \ py_newnotimplemented(py_retval()); \
} \ } \
return true; \ return true; \
} }
@ -83,14 +83,14 @@ DEF_NUM_BINARY_OP(__ge__, >=, py_newbool, py_newbool)
static bool _py_int__neg__(int argc, py_Ref argv) { static bool _py_int__neg__(int argc, py_Ref argv) {
py_checkargc(1); py_checkargc(1);
int64_t val = py_toint(&argv[0]); int64_t val = py_toint(&argv[0]);
py_newint(py_lastretval(), -val); py_newint(py_retval(), -val);
return true; return true;
} }
static bool _py_float__neg__(int argc, py_Ref argv) { static bool _py_float__neg__(int argc, py_Ref argv) {
py_checkargc(1); py_checkargc(1);
double val = py_tofloat(&argv[0]); double val = py_tofloat(&argv[0]);
py_newfloat(py_lastretval(), -val); py_newfloat(py_retval(), -val);
return true; return true;
} }
@ -99,9 +99,9 @@ static bool _py_int__truediv__(int argc, py_Ref argv) {
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(py_lastretval(), lhs / rhs); py_newfloat(py_retval(), lhs / rhs);
} else { } else {
py_newnotimplemented(py_lastretval()); py_newnotimplemented(py_retval());
} }
return true; return true;
} }
@ -111,9 +111,9 @@ static bool _py_float__truediv__(int argc, py_Ref argv) {
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(py_lastretval(), lhs / rhs); py_newfloat(py_retval(), lhs / rhs);
} else { } else {
py_newnotimplemented(py_lastretval()); py_newnotimplemented(py_retval());
} }
return true; return true;
} }
@ -129,7 +129,7 @@ static bool _py_number__pow__(int argc, py_Ref argv) {
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(py_lastretval(), pow(lhs, rhs)); py_newfloat(py_retval(), pow(lhs, rhs));
} }
} else { } else {
int64_t ret = 1; int64_t ret = 1;
@ -138,15 +138,15 @@ static bool _py_number__pow__(int argc, py_Ref argv) {
lhs *= lhs; lhs *= lhs;
rhs >>= 1; rhs >>= 1;
} }
py_newint(py_lastretval(), ret); py_newint(py_retval(), 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(py_lastretval(), pow(lhs, rhs)); py_newfloat(py_retval(), pow(lhs, rhs));
} else { } else {
py_newnotimplemented(py_lastretval()); py_newnotimplemented(py_retval());
} }
} }
return true; return true;
@ -158,9 +158,9 @@ static bool _py_int__floordiv__(int argc, py_Ref argv) {
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(py_lastretval(), lhs / rhs); py_newint(py_retval(), lhs / rhs);
} else { } else {
py_newnotimplemented(py_lastretval()); py_newnotimplemented(py_retval());
} }
return true; return true;
} }
@ -171,9 +171,9 @@ static bool _py_int__mod__(int argc, py_Ref argv) {
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(py_lastretval(), lhs % rhs); py_newint(py_retval(), lhs % rhs);
} else { } else {
py_newnotimplemented(py_lastretval()); py_newnotimplemented(py_retval());
} }
return true; return true;
} }
@ -181,7 +181,7 @@ static bool _py_int__mod__(int argc, py_Ref argv) {
static bool _py_int__invert__(int argc, py_Ref argv) { static bool _py_int__invert__(int argc, py_Ref argv) {
py_checkargc(1); py_checkargc(1);
int64_t val = py_toint(&argv[0]); int64_t val = py_toint(&argv[0]);
py_newint(py_lastretval(), ~val); py_newint(py_retval(), ~val);
return true; return true;
} }
@ -194,7 +194,7 @@ static bool _py_int__bit_length(int argc, py_Ref argv) {
x >>= 1; x >>= 1;
bits++; bits++;
} }
py_newint(py_lastretval(), bits); py_newint(py_retval(), bits);
return true; return true;
} }
@ -204,9 +204,9 @@ static bool _py_int__bit_length(int argc, py_Ref argv) {
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(py_lastretval(), lhs op rhs); \ py_newint(py_retval(), lhs op rhs); \
} else { \ } else { \
py_newnotimplemented(py_lastretval()); \ py_newnotimplemented(py_retval()); \
} \ } \
return true; \ return true; \
} }

View File

@ -1,8 +1,11 @@
#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/objects/base.h"
#include "pocketpy/pocketpy.h" #include "pocketpy/pocketpy.h"
#include <stdarg.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; }
static void pk_default_stdout(const char* fmt, ...) { static void pk_default_stdout(const char* fmt, ...) {
@ -23,8 +26,8 @@ static void pk_default_stderr(const char* fmt, ...) {
void pk_TypeInfo__ctor(pk_TypeInfo* self, void pk_TypeInfo__ctor(pk_TypeInfo* self,
py_Name name, py_Name name,
py_Type index,
py_Type base, py_Type base,
PyObject* obj,
const py_TValue* module, const py_TValue* module,
bool subclass_enabled) { bool subclass_enabled) {
memset(self, 0, sizeof(pk_TypeInfo)); memset(self, 0, sizeof(pk_TypeInfo));
@ -32,7 +35,11 @@ void pk_TypeInfo__ctor(pk_TypeInfo* self,
self->name = name; self->name = name;
self->base = base; self->base = base;
self->self = PyVar__fromobj(obj); // create type object with __dict__
pk_ManagedHeap* heap = &pk_current_vm->heap;
PyObject* typeobj = pk_ManagedHeap__new(heap, tp_type, -1, sizeof(py_Type));
self->self = PyVar__fromobj(typeobj);
self->module = module ? *module : PY_NULL; self->module = module ? *module : PY_NULL;
self->subclass_enabled = subclass_enabled; self->subclass_enabled = subclass_enabled;
@ -66,37 +73,9 @@ void pk_VM__ctor(pk_VM* self) {
pk_ManagedHeap__ctor(&self->heap, self); pk_ManagedHeap__ctor(&self->heap, self);
ValueStack__ctor(&self->stack); ValueStack__ctor(&self->stack);
self->True = (py_TValue){
.type = tp_bool,
.is_ptr = true,
.extra = 1,
._obj = pk_ManagedHeap__gcnew(&self->heap, tp_bool, 0, 0),
};
self->False = (py_TValue){
.type = tp_bool,
.is_ptr = true,
.extra = 0,
._obj = pk_ManagedHeap__gcnew(&self->heap, tp_bool, 0, 0),
};
self->None = (py_TValue){
.type = tp_none_type,
.is_ptr = true,
._obj = pk_ManagedHeap__gcnew(&self->heap, tp_none_type, 0, 0),
};
self->NotImplemented = (py_TValue){
.type = tp_not_implemented_type,
.is_ptr = true,
._obj = pk_ManagedHeap__gcnew(&self->heap, tp_not_implemented_type, 0, 0),
};
self->Ellipsis = (py_TValue){
.type = tp_ellipsis,
.is_ptr = true,
._obj = pk_ManagedHeap__gcnew(&self->heap, tp_ellipsis, 0, 0),
};
/* Init Builtin Types */ /* Init Builtin Types */
// 0: unused // 0: unused
pk_TypeInfo__ctor(c11_vector__emplace(&self->types), 0, 0, NULL, NULL, false); pk_TypeInfo__ctor(c11_vector__emplace(&self->types), 0, 0, 0, NULL, false);
#define validate(t, expr) \ #define validate(t, expr) \
if(t != (expr)) abort() if(t != (expr)) abort()
@ -136,14 +115,11 @@ void pk_VM__ctor(pk_VM* self) {
pk_VM__new_type(self, "NotImplementedType", tp_object, NULL, false)); pk_VM__new_type(self, "NotImplementedType", tp_object, NULL, false));
validate(tp_ellipsis, pk_VM__new_type(self, "ellipsis", tp_object, NULL, false)); validate(tp_ellipsis, pk_VM__new_type(self, "ellipsis", tp_object, NULL, false));
validate(tp_op_call, pk_VM__new_type(self, "__op_call", tp_object, NULL, false));
validate(tp_op_yield, pk_VM__new_type(self, "__op_yield", tp_object, NULL, false));
validate(tp_syntax_error, pk_VM__new_type(self, "SyntaxError", tp_exception, NULL, false)); validate(tp_syntax_error, pk_VM__new_type(self, "SyntaxError", tp_exception, NULL, false));
validate(tp_stop_iteration, pk_VM__new_type(self, "StopIteration", tp_exception, NULL, false)); validate(tp_stop_iteration, pk_VM__new_type(self, "StopIteration", tp_exception, NULL, false));
#undef validate #undef validate
self->StopIteration = c11__at(pk_TypeInfo, &self->types, tp_stop_iteration)->self; self->StopIteration = *py_tpobject(tp_stop_iteration);
self->builtins = *py_newmodule("builtins", NULL); self->builtins = *py_newmodule("builtins", NULL);
/* Setup Public Builtin Types */ /* Setup Public Builtin Types */
@ -167,7 +143,7 @@ void pk_VM__ctor(pk_VM* self) {
for(int i = 0; i < PK_ARRAY_COUNT(public_types); i++) { for(int i = 0; i < PK_ARRAY_COUNT(public_types); i++) {
py_Type t = public_types[i]; py_Type t = public_types[i];
pk_TypeInfo* ti = c11__at(pk_TypeInfo, &self->types, t); pk_TypeInfo* ti = c11__at(pk_TypeInfo, &self->types, t);
py_setdict(&self->builtins, ti->name, &ti->self); py_setdict(&self->builtins, ti->name, py_tpobject(t));
} }
py_setdict(&self->builtins, py_name("NotImplemented"), &self->NotImplemented); py_setdict(&self->builtins, py_name("NotImplemented"), &self->NotImplemented);
@ -207,13 +183,10 @@ py_Type pk_VM__new_type(pk_VM* self,
py_Type base, py_Type base,
const py_TValue* module, const py_TValue* module,
bool subclass_enabled) { bool subclass_enabled) {
py_Type type = self->types.count; py_Type index = self->types.count;
pk_TypeInfo* ti = c11_vector__emplace(&self->types); pk_TypeInfo* ti = c11_vector__emplace(&self->types);
PyObject* typeobj = pk_ManagedHeap__gcnew(&self->heap, tp_type, -1, sizeof(py_Type)); pk_TypeInfo__ctor(ti, py_name(name), index, base, module, subclass_enabled);
py_Type* value = PyObject__value(typeobj); return index;
*value = type;
pk_TypeInfo__ctor(ti, py_name(name), base, typeobj, module, subclass_enabled);
return type;
} }
/****************************************/ /****************************************/

View File

@ -1,6 +1,4 @@
#include "pocketpy/objects/base.h" #include "pocketpy/objects/base.h"
py_TValue PY_NULL = {.type=0, .is_ptr=false, .extra=0, ._i64=0}; py_TValue PY_NULL = {.type=0, .is_ptr=false, .extra=0, ._i64=0};
py_TValue PY_OP_CALL = {.type=27, .is_ptr=false, .extra=0, ._i64=0};
py_TValue PY_OP_YIELD = {.type=28, .is_ptr=false, .extra=0, ._i64=0};

View File

@ -29,7 +29,13 @@ bool py_castfloat(const py_Ref self, double* out){
bool py_tobool(const py_Ref self){ bool py_tobool(const py_Ref self){
assert(self->type == tp_bool); assert(self->type == tp_bool);
return self->extra; return self->_bool;
}
py_Type py_totype(const py_Ref self){
assert(self->type == tp_type);
py_Type* ud = py_touserdata(self);
return *ud;
} }
const char* py_tostr(const py_Ref self){ const char* py_tostr(const py_Ref self){

View File

@ -1,9 +1,20 @@
#include "pocketpy/interpreter/vm.h" #include "pocketpy/interpreter/vm.h"
#include "pocketpy/objects/base.h"
#include "pocketpy/pocketpy.h" #include "pocketpy/pocketpy.h"
bool py_isidentical(const py_Ref lhs, const py_Ref rhs) { bool py_isidentical(const py_Ref lhs, const py_Ref rhs) {
if(lhs->is_ptr && rhs->is_ptr) { return lhs->_obj == rhs->_obj; } if(lhs->type != rhs->type) return false;
return false; switch(lhs->type){
case tp_int: return lhs->_i64 == rhs->_i64;
case tp_float: return lhs->_f64 == rhs->_f64;
case tp_bool: return lhs->_bool == rhs->_bool;
case tp_nativefunc: return lhs->_cfunc == rhs->_cfunc;
case tp_none_type: return true;
case tp_not_implemented_type: return true;
case tp_ellipsis: return true;
// fallback to pointer comparison
default: return lhs->is_ptr && rhs->is_ptr && lhs->_obj == rhs->_obj;
}
} }
int py_bool(const py_Ref val) { return 1; } int py_bool(const py_Ref val) { return 1; }
@ -26,7 +37,7 @@ bool py_delitem(py_Ref self, const py_Ref key) { return -1; }
int py_##name(const py_Ref lhs, const py_Ref rhs) { \ int py_##name(const py_Ref lhs, const py_Ref rhs) { \
bool ok = py_binaryop(lhs, rhs, op, rop); \ bool ok = py_binaryop(lhs, rhs, op, rop); \
if(!ok) return -1; \ if(!ok) return -1; \
return py_tobool(py_lastretval()); \ return py_tobool(py_retval()); \
} }
COMPARE_OP_IMPL(eq, __eq__, __eq__) COMPARE_OP_IMPL(eq, __eq__, __eq__)

View File

@ -10,11 +10,20 @@ py_Ref py_reg(int i){
py_Ref py_getdict(const py_Ref self, py_Name name){ py_Ref py_getdict(const py_Ref self, py_Name name){
assert(self && self->is_ptr); assert(self && self->is_ptr);
if(self->type == tp_type && py_ismagicname(name)){
py_Type* ud = py_touserdata(self);
py_Ref slot = py_tpmagic(*ud, name);
return py_isnull(slot) ? NULL : slot;
}
return pk_NameDict__try_get(PyObject__dict(self->_obj), name); return pk_NameDict__try_get(PyObject__dict(self->_obj), 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){
assert(self && self->is_ptr); assert(self && self->is_ptr);
if(self->type == tp_type && py_ismagicname(name)){
py_Type* ud = py_touserdata(self);
*py_tpmagic(*ud, name) = *val;
}
pk_NameDict__set(PyObject__dict(self->_obj), name, *val); pk_NameDict__set(PyObject__dict(self->_obj), name, *val);
} }

View File

@ -17,10 +17,29 @@ void py_newfloat(py_Ref out, double val) {
} }
void py_newbool(py_Ref out, bool val) { void py_newbool(py_Ref out, bool val) {
pk_VM* vm = pk_current_vm; out->type = tp_bool;
*out = val ? vm->True : vm->False; out->is_ptr = false;
out->_bool = val;
} }
void py_newnone(py_Ref out) {
out->type = tp_none_type;
out->is_ptr = false;
}
void py_newnotimplemented(py_Ref out) {
out->type = tp_not_implemented_type;
out->is_ptr = false;
}
void py_newellipsis(py_Ref out) {
out->type = tp_ellipsis;
out->is_ptr = false;
}
void py_newnull(py_Ref out) { out->type = 0; }
void py_newstr(py_Ref out, const char* data) { void py_newstr(py_Ref out, const char* data) {
pk_ManagedHeap* heap = &pk_current_vm->heap; pk_ManagedHeap* heap = &pk_current_vm->heap;
PyObject* obj = pk_ManagedHeap__gcnew(heap, tp_str, 0, sizeof(py_Str)); PyObject* obj = pk_ManagedHeap__gcnew(heap, tp_str, 0, sizeof(py_Str));
@ -61,13 +80,6 @@ void py_newbytes(py_Ref out, const unsigned char* data, int size) {
out->_obj = obj; out->_obj = obj;
} }
void py_newnone(py_Ref out) {
pk_VM* vm = pk_current_vm;
*out = vm->None;
}
void py_newnull(py_Ref out) { out->type = 0; }
void py_newfunction(py_Ref out, py_CFunction f, const char* sig) { void py_newfunction(py_Ref out, py_CFunction f, const char* sig) {
py_newfunction2(out, f, sig, BindType_FUNCTION, NULL, NULL); py_newfunction2(out, f, sig, BindType_FUNCTION, NULL, NULL);
} }
@ -101,11 +113,6 @@ void py_bindnativefunc(py_Ref obj, const char *name, py_CFunction f){
py_setdict(obj, py_name(name), &tmp); py_setdict(obj, py_name(name), &tmp);
} }
void py_newnotimplemented(py_Ref out) {
pk_VM* vm = pk_current_vm;
*out = vm->NotImplemented;
}
void py_newslice(py_Ref out, const py_Ref start, const py_Ref stop, const py_Ref step) { void py_newslice(py_Ref out, const py_Ref start, const py_Ref stop, const py_Ref step) {
py_newobject(out, tp_slice, 3, 0); py_newobject(out, tp_slice, 3, 0);
py_setslot(out, 0, start); py_setslot(out, 0, start);

View File

@ -50,7 +50,7 @@ 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 pk_vectorcall(int argc, int kwargc, bool op_call) { return -1; }
py_Ref py_lastretval() { return &pk_current_vm->last_retval; } py_Ref py_retval() { return &pk_current_vm->last_retval; }
bool py_getunboundmethod(const py_Ref self, bool py_getunboundmethod(const py_Ref self,
py_Name name, py_Name name,
@ -66,7 +66,7 @@ pk_TypeInfo* pk_tpinfo(const py_Ref self) {
} }
py_Ref py_tpfindmagic(py_Type t, py_Name name) { py_Ref py_tpfindmagic(py_Type t, py_Name name) {
assert(name < 64); assert(py_ismagicname(name));
pk_TypeInfo* types = (pk_TypeInfo*)pk_current_vm->types.data; pk_TypeInfo* types = (pk_TypeInfo*)pk_current_vm->types.data;
do { do {
py_Ref f = &types[t].magic[name]; py_Ref f = &types[t].magic[name];
@ -77,7 +77,7 @@ py_Ref py_tpfindmagic(py_Type t, py_Name name) {
} }
py_Ref py_tpmagic(py_Type type, py_Name name) { py_Ref py_tpmagic(py_Type type, py_Name name) {
assert(name < 64); assert(py_ismagicname(name));
pk_VM* vm = pk_current_vm; pk_VM* vm = pk_current_vm;
return &c11__at(pk_TypeInfo, &vm->types, type)->magic[name]; return &c11__at(pk_TypeInfo, &vm->types, type)->magic[name];
} }
@ -89,6 +89,7 @@ py_Ref py_tpobject(py_Type type) {
bool py_callmagic(py_Name name, int argc, py_Ref argv) { bool py_callmagic(py_Name name, int argc, py_Ref argv) {
assert(argc >= 1); assert(argc >= 1);
assert(py_ismagicname(name));
py_Ref tmp = py_tpfindmagic(argv->type, name); py_Ref tmp = py_tpfindmagic(argv->type, name);
if(!tmp) return TypeError(name); if(!tmp) return TypeError(name);
if(tmp->type == tp_nativefunc) { return tmp->_cfunc(argc, argv); } if(tmp->type == tp_nativefunc) { return tmp->_cfunc(argc, argv); }

View File

@ -30,7 +30,7 @@ int main(int argc, char** argv) {
if(py_eval(source)) { if(py_eval(source)) {
// handle the result // handle the result
bool _L0 = py_tobool(py_lastretval()); bool _L0 = py_tobool(py_retval());
printf("%d\n", _L0); printf("%d\n", _L0);
} }
@ -42,7 +42,7 @@ int main(int argc, char** argv) {
bool ok = py_binaryadd(r0, r1); bool ok = py_binaryadd(r0, r1);
assert(ok); assert(ok);
double res = py_tofloat(py_lastretval()); double res = py_tofloat(py_retval());
printf("%f\n", res); printf("%f\n", res);
py_finalize(); py_finalize();