Compare commits

...

6 Commits

Author SHA1 Message Date
blueloveTH
13b1fbe17a cleanup 2024-06-26 03:29:25 +08:00
blueloveTH
7e35fa2d56 some fix 2024-06-26 03:23:46 +08:00
blueloveTH
fb0ec57f38 up 2024-06-26 02:50:02 +08:00
blueloveTH
2ac2ff807f up 2024-06-26 02:36:14 +08:00
blueloveTH
6f99ebed88 rename py_Type 2024-06-26 01:03:53 +08:00
blueloveTH
5bdbec273e some tidy 2024-06-26 01:02:45 +08:00
22 changed files with 778 additions and 324 deletions

View File

@ -4,8 +4,9 @@ python prebuild.py
SRC=$(find src/ -name "*.c")
FLAGS="-std=c11 -Iinclude -O0 -Wfatal-errors -g -DDEBUG -DPK_ENABLE_OS=1" # -fsanitize=address,leak,undefined"
FLAGS="-std=c11 -lm -Iinclude -O0 -Wfatal-errors -g -DDEBUG -DPK_ENABLE_OS=1"
SANITIZE_FLAGS="-fsanitize=address,leak,undefined"
echo "Compiling C files..."
clang $FLAGS $SRC src2/main.c -o main
clang $FLAGS $SANITIZE_FLAGS $SRC src2/main.c -o main

View File

@ -9,7 +9,7 @@ extern "C" {
typedef uint16_t StrName;
#define py_name(name) pk_StrName__map(#name)
#define py_name(name) pk_StrName__map(name)
uint16_t pk_StrName__map(const char*);
uint16_t pk_StrName__map2(c11_string);

View File

@ -28,8 +28,8 @@ void pk_ManagedHeap__collect_if_needed(pk_ManagedHeap* self);
int pk_ManagedHeap__collect(pk_ManagedHeap* self);
int pk_ManagedHeap__sweep(pk_ManagedHeap* self);
PyObject* pk_ManagedHeap__new(pk_ManagedHeap* self, Type type, int slots, int size);
PyObject* pk_ManagedHeap__gcnew(pk_ManagedHeap* self, Type type, int slots, int size);
PyObject* pk_ManagedHeap__new(pk_ManagedHeap* self, py_Type type, int slots, int size);
PyObject* pk_ManagedHeap__gcnew(pk_ManagedHeap* self, py_Type type, int slots, int size);
// external implementation
void pk_ManagedHeap__mark(pk_ManagedHeap* self);

View File

@ -10,7 +10,7 @@ extern "C" {
typedef struct pk_TypeInfo{
py_Name name;
Type base;
py_Type base;
PyVar self; // the type object itself
PyVar module; // the module where the type is defined
@ -38,7 +38,7 @@ typedef struct pk_TypeInfo{
py_CFunction on_end_subclass; // for enum module
} pk_TypeInfo;
void pk_TypeInfo__ctor(pk_TypeInfo* self, py_Name name, Type base, PyObject* obj, const PyVar* module, bool subclass_enabled);
void pk_TypeInfo__ctor(pk_TypeInfo* self, py_Name name, py_Type base, PyObject* obj, const PyVar* module, bool subclass_enabled);
void pk_TypeInfo__dtor(pk_TypeInfo* self);
typedef struct pk_VM {
@ -60,11 +60,6 @@ typedef struct pk_VM {
PyVar True, False, None, NotImplemented, Ellipsis;
// last error
py_Error* last_error;
// last retval
PyVar last_retval;
// registers
PyVar reg[8];
PyVar sysreg[8];
PyObject* __curr_class;
PyObject* __cached_object_new;
@ -83,6 +78,8 @@ void pk_VM__dtor(pk_VM* self);
void pk_VM__push_frame(pk_VM* self, Frame* frame);
void pk_VM__pop_frame(pk_VM* self);
void pk_VM__init_builtins(pk_VM* self);
typedef enum pk_FrameResult{
RES_RETURN,
RES_CALL,
@ -92,7 +89,7 @@ typedef enum pk_FrameResult{
pk_FrameResult pk_VM__run_top_frame(pk_VM* self);
Type pk_VM__new_type(pk_VM* self, const char* name, Type base, const PyVar* module, bool subclass_enabled);
py_Type pk_VM__new_type(pk_VM* self, const char* name, py_Type base, const PyVar* module, bool subclass_enabled);
#ifdef __cplusplus
}

View File

@ -13,10 +13,10 @@
extern "C" {
#endif
typedef int16_t Type;
typedef int16_t py_Type;
typedef struct PyVar{
Type type;
py_Type type;
bool is_ptr;
int extra;
union {
@ -28,47 +28,21 @@ typedef struct PyVar{
};
} PyVar;
#define PyVar__as(T, self) _Generic((T), \
int64_t: self->_i64, \
double: self->_f64, \
PyObject*: self->_obj, \
void*: self->_ptr, \
)
static_assert(sizeof(PyVar) == 16, "sizeof(PyVar) != 16");
static_assert(sizeof(PyVar) <= 16, "!sizeof(PyVar) <= 16");
/* predefined vars */
static const Type tp_object = {1}, tp_type = {2};
static const Type tp_int = {3}, tp_float = {4}, tp_bool = {5}, tp_str = {6};
static const Type tp_list = {7}, tp_tuple = {8};
static const Type tp_slice = {9}, tp_range = {10}, tp_module = {11};
static const Type tp_function = {12}, tp_nativefunc = {13}, tp_bound_method = {14};
static const Type tp_super = {15}, tp_exception = {16}, tp_bytes = {17}, tp_mappingproxy = {18};
static const Type tp_dict = {19}, tp_property = {20}, tp_star_wrapper = {21};
static const Type tp_staticmethod = {22}, tp_classmethod = {23};
static const Type tp_none_type = {24}, tp_not_implemented_type = {25};
static const Type tp_ellipsis = {26};
static const Type tp_op_call = {27}, tp_op_yield = {28};
static const Type tp_syntax_error = {29}, tp_stop_iteration = {30};
PK_INLINE bool PyVar__is_null(const PyVar* self) { return self->type == 0; }
PK_INLINE int64_t PyVar__hash(const PyVar* self) { return self->extra + self->_i64; }
PK_INLINE void PyVar__ctor(PyVar* self, Type type, PyObject* obj){
self->type = type;
self->is_ptr = true;
self->_obj = obj;
}
void PyVar__ctor3(PyVar* self, PyObject* existing);
PK_INLINE bool PyVar__IS_OP(const PyVar* a, const PyVar* b){
return a->is_ptr && b->is_ptr && a->_obj == b->_obj;
}
#define pkpy_Var__is_null(self) ((self)->type == 0)
#define pkpy_Var__set_null(self) do { (self)->type = 0; } while(0)
static const py_Type tp_object = {1}, tp_type = {2};
static const py_Type tp_int = {3}, tp_float = {4}, tp_bool = {5}, tp_str = {6};
static const py_Type tp_list = {7}, tp_tuple = {8};
static const 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};
static const 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};
static const py_Type tp_staticmethod = {22}, tp_classmethod = {23};
static const py_Type tp_none_type = {24}, tp_not_implemented_type = {25};
static const py_Type tp_ellipsis = {26};
static const py_Type tp_op_call = {27}, tp_op_yield = {28};
static const py_Type tp_syntax_error = {29}, tp_stop_iteration = {30};
extern PyVar PY_NULL, PY_OP_CALL, PY_OP_YIELD;

View File

@ -8,7 +8,7 @@ extern "C" {
#endif
typedef struct PyObject{
Type type; // we have a duplicated type here for convenience
py_Type type; // we have a duplicated type here for convenience
bool gc_is_large;
bool gc_marked;
int slots; // number of slots in the object
@ -28,7 +28,7 @@ void* PyObject__value(PyObject* self);
#define PK_OBJ_HEADER_SIZE(slots) ((slots)>=0 ? 8+sizeof(PyVar)*(slots) : 8+sizeof(pk_NameDict))
PyObject* PyObject__new(Type type, int slots, int size);
PyObject* PyObject__new(py_Type type, int slots, int size);
void PyObject__delete(PyObject* self);
PK_INLINE PyVar PyVar__fromobj(PyObject* obj){

View File

@ -1,24 +1,21 @@
#pragma once
#include "stdint.h"
#include "stdbool.h"
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
/************* Public Types *************/
typedef struct PyObject PyObject;
typedef struct PyVar PyVar;
typedef struct pk_VM pk_VM;
typedef uint16_t py_Name;
typedef int16_t Type;
typedef int16_t py_Type;
typedef PyVar* py_Ref;
typedef int (*py_CFunction)(const py_Ref, int);
typedef int (*py_CFunction)(int argc, py_Ref argv);
typedef struct py_Str py_Str;
typedef struct py_Error{
Type type;
py_Type type;
} py_Error;
typedef enum BindType {
@ -27,88 +24,112 @@ typedef enum BindType {
BindType_CLASSMETHOD,
} BindType;
extern pk_VM* pk_current_vm;
/************* Global VMs *************/
void py_initialize();
// void py_switch_vm(const char* name);
void py_finalize();
int py_exec_simple(const char*);
int py_eval_simple(const char*, py_Ref);
/// Run a simple source string. Do not change the stack.
int py_exec(const char*);
/// Eval a simple expression. If succeed, the result will be pushed onto the stack.
int py_eval(const char*);
/* py_error */
py_Error* py_getlasterror();
void py_Error__print(py_Error*);
int py_eq(const py_Ref, const py_Ref);
int py_le(const py_Ref, const py_Ref);
int py_hash(const py_Ref, int64_t* out);
/* py_var */
/************* Values Creation *************/
void py_newint(py_Ref, int64_t);
void py_newfloat(py_Ref, double);
void py_newbool(py_Ref, bool);
void py_newstr(py_Ref, const char*);
void py_newstrn(py_Ref, const char*, int);
// void py_newfstr(py_Ref, const char*, ...);
void py_newbytes(py_Ref, const uint8_t*, int);
// void py_newbytes(py_Ref, const uint8_t*, int);
void py_newnone(py_Ref);
void py_newnull(py_Ref);
void py_newtuple(py_Ref, int);
// void py_newlist(py_Ref);
// new style decl-based function
void py_newfunction(py_Ref, py_CFunction, const char* sig, BindType bt);
void py_newfunction2(py_Ref, py_CFunction, const char* sig, BindType bt, const char* docstring, const py_Ref userdata);
void py_newfunction(py_Ref self, py_CFunction, const char* sig);
void py_newfunction2(py_Ref self, py_CFunction, const char* sig, BindType bt, const char* docstring, const py_Ref userdata);
// old style argc-based function
void py_newnativefunc(py_Ref, py_CFunction, int argc, BindType bt);
void py_newnativefunc2(py_Ref, py_CFunction, int argc, BindType bt, const char* docstring, const py_Ref userdata);
void py_newnativefunc(py_Ref self, py_CFunction, int argc);
void py_newnativefunc2(py_Ref self, py_CFunction, int argc, BindType bt, const char* docstring, const py_Ref userdata);
/************* Stack Values Creation *************/
void py_pushint(int64_t);
void py_pushfloat(double);
void py_pushbool(bool);
void py_pushstr(const py_Str*);
void py_pushcstr(const char*);
void py_pushcstrn(const char*, int);
void py_push_notimplemented();
py_Ref py_newmodule(const char* name, const char* package);
py_Ref py_getmodule(const char* name);
const py_Ref py_import(const char* name);
/************* Type Cast *************/
int64_t py_toint(py_Ref);
double py_tofloat(py_Ref);
bool py_castfloat(py_Ref, double* out);
bool py_tobool(py_Ref);
const py_Str* py_tostr(py_Ref);
const char* py_tocstr(py_Ref);
#define py_isnull(self) ((self)->type == 0)
#define py_isint(self) py_istype(self, tp_int)
#define py_isfloat(self) py_istype(self, tp_float)
#define py_isbool(self) py_istype(self, tp_bool)
#define py_isstr(self) py_istype(self, tp_str)
bool py_istype(const py_Ref, py_Type);
// bool py_isinstance(const py_Ref obj, py_Type type);
// bool py_issubclass(py_Type derived, py_Type base);
/// Sets the name of the object to the given value.
void py_setdict(py_Ref self, py_Name name, const py_Ref val);
/// Returns a reference to the name of the object.
/************* References *************/
py_Ref py_getdict(const py_Ref self, py_Name name);
void py_setdict(py_Ref self, py_Name name, const py_Ref val);
/// Sets the i-th slot of the object to the given value.
void py_setslot(py_Ref self, int i, const py_Ref val);
/// Returns a reference to the i-th slot of the object.
py_Ref py_getslot(const py_Ref self, int i);
void py_setslot(py_Ref self, int i, const py_Ref val);
/// Equivalent to `self.name = val`.
/// Returns 0 | err
int py_setattr(py_Ref self, py_Name name, const py_Ref val);
// int py_getattr(const py_Ref self, py_Name name, py_Ref out);
// int py_setattr(py_Ref self, py_Name name, const py_Ref val);
/// Equivalent to `self.name`.
/// Returns 0 | err
int py_getattr(const py_Ref self, py_Name name, py_Ref out);
/// Copies src to dst.
void py_copyref(const py_Ref src, py_Ref dst);
/************* Stack Operations *************/
py_Ref py_gettop();
void py_settop(const py_Ref);
py_Ref py_getsecond();
void py_setsecond(const py_Ref);
/// Returns a reference to the i-th object from the top of the stack.
/// i should be negative, e.g. (-1) means TOS.
py_Ref py_stack(int i);
/// Returns a reference to the i-th register.
py_Ref py_reg(int i);
/// Returns a reference to the i-th system register.
py_Ref py_sysreg(int i);
/// Prepares a push and returns an uninitialized reference.
py_Ref py_push();
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.
void py_pushref(const py_Ref src);
/// Pops the object from the stack.
void py_copyref(const py_Ref src, py_Ref dst);
/// Get a temporary variable from the stack and returns the reference to it.
py_Ref py_pushtmp();
/// Free n temporary variable.
void py_poptmp(int n);
/************* Modules *************/
py_Ref py_newmodule(const char* name, const char* package);
py_Ref py_getmodule(const char* name);
void py_import(const char* name, py_Ref out);
/************* Errors *************/
py_Error* py_getlasterror();
void py_Error__print(py_Error*);
/************* Operators *************/
int py_eq(const py_Ref, const py_Ref);
int py_le(const py_Ref, const py_Ref);
int py_hash(const py_Ref, int64_t* out);
#define py_isnull(self) ((self)->type == 0)
/* tuple */
@ -140,15 +161,6 @@ void py_dict__clear(py_Ref self);
int py_str(const py_Ref, py_Str* out);
int py_repr(const py_Ref, py_Str* out);
int py_toint(py_Ref, int64_t* out);
int py_tofloat(py_Ref, double* out);
int py_tostr(py_Ref, py_Str** out);
int py_tobool(py_Ref, bool* out);
bool py_istype(const py_Ref, Type);
bool py_isinstance(const py_Ref obj, Type type);
bool py_issubclass(Type derived, Type base);
#ifdef __cplusplus
}
#endif

View File

@ -74,13 +74,15 @@ void METHOD(delete)(NAME* self) {
void METHOD(set)(NAME* self, K key, V value) {
int index;
c11__lower_bound(KV, self->data, self->count, key, partial_less, &index);
KV* it = c11__at(KV, self, index);
if(index != self->count && equal(it->key, key)) {
it->value = value;
} else {
KV kv = {key, value};
c11_vector__insert(KV, self, index, kv);
if(index != self->count){
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)){
it->value = value;
return;
}
}
KV kv = {key, value};
c11_vector__insert(KV, self, index, kv);
}
V* METHOD(try_get)(const NAME* self, K key) {
@ -113,10 +115,12 @@ bool METHOD(contains)(const NAME* self, K key) {
bool METHOD(del)(NAME* self, K key) {
int index;
c11__lower_bound(KV, self->data, self->count, key, partial_less, &index);
KV* it = c11__at(KV, self, index);
if(index != self->count && equal(it->key, key)) {
c11_vector__erase(KV, self, index);
return true;
if(index != self->count){
KV* it = c11__at(KV, self, index);
if(equal(it->key, key)){
c11_vector__erase(KV, self, index);
return true;
}
}
return false;
}

View File

@ -88,20 +88,20 @@ int pk_ManagedHeap__sweep(pk_ManagedHeap *self){
return freed;
}
PyObject* pk_ManagedHeap__new(pk_ManagedHeap *self, Type type, int slots, int size){
PyObject* pk_ManagedHeap__new(pk_ManagedHeap *self, py_Type type, int slots, int size){
PyObject* obj = PyObject__new(type, slots, size);
c11_vector__push(PyObject*, &self->no_gc, obj);
return obj;
}
PyObject* pk_ManagedHeap__gcnew(pk_ManagedHeap *self, Type type, int slots, int size){
PyObject* pk_ManagedHeap__gcnew(pk_ManagedHeap *self, py_Type type, int slots, int size){
PyObject* obj = PyObject__new(type, slots, size);
c11_vector__push(PyObject*, &self->gen, obj);
self->gc_counter++;
return obj;
}
PyObject* PyObject__new(Type type, int slots, int size){
PyObject* PyObject__new(py_Type type, int slots, int size){
assert(slots >= 0 || slots == -1);
PyObject* self;
size += PK_OBJ_HEADER_SIZE(slots);
@ -115,5 +115,13 @@ PyObject* PyObject__new(Type type, int slots, int size){
self->type = type;
self->gc_marked = false;
self->slots = slots;
// initialize slots or dict
void* p = (char*)self + 8;
if(slots >= 0){
memset(p, 0, slots*sizeof(PyVar));
}else{
pk_NameDict__ctor(p);
}
return self;
}

293
src/interpreter/py_number.c Normal file
View File

@ -0,0 +1,293 @@
#include "pocketpy/interpreter/vm.h"
#include <math.h>
// static int _py_print(const py_Ref args, int argc){
// int length = py_tuple__len(args+0);
// py_Str* sep;
// py_Str* end;
// int err;
// err = py_tostr(args+1, &sep);
// if(err) return err;
// err = py_tostr(args+2, &end);
// if(err) return err;
// pk_SStream ss;
// pk_SStream__ctor(&ss);
// for(int i=0; i<length; i++){
// const py_Ref item = py_tuple__getitem(args+0, i);
// py_Str tmp;
// int err = py_str(item, &tmp);
// if(!err){
// pk_SStream__write_Str(&ss, &tmp);
// py_Str__dtor(&tmp);
// if(i != length-1){
// pk_SStream__write_Str(&ss, sep);
// }
// }else{
// py_Str__dtor(&tmp);
// pk_SStream__dtor(&ss);
// return err;
// }
// }
// pk_SStream__write_Str(&ss, end);
// py_Str out = pk_SStream__submit(&ss);
// pk_current_vm->_stdout(py_Str__data(&out));
// py_Str__dtor(&out);
// return 0;
// }
#define DEF_NUM_BINARY_OP(name, op) \
static int _py_int##name(int argc, py_Ref argv) { \
if(py_isint(&argv[1])) { \
int64_t lhs = py_toint(&argv[0]); \
int64_t rhs = py_toint(&argv[1]); \
py_pushint(lhs op rhs); \
} else if(py_isfloat(&argv[1])) { \
int64_t lhs = py_toint(&argv[0]); \
double rhs = py_tofloat(&argv[1]); \
py_pushfloat(lhs op rhs); \
} else { \
py_push_notimplemented(); \
} \
return 1; \
} \
static int _py_float##name(int argc, py_Ref argv) { \
double lhs = py_tofloat(&argv[0]); \
double rhs; \
if(py_castfloat(&argv[1], &rhs)) { \
py_pushfloat(lhs op rhs); \
} else { \
py_push_notimplemented(); \
} \
return 1; \
}
DEF_NUM_BINARY_OP(__add__, +)
DEF_NUM_BINARY_OP(__sub__, -)
DEF_NUM_BINARY_OP(__mul__, *)
DEF_NUM_BINARY_OP(__eq__, ==)
DEF_NUM_BINARY_OP(__lt__, <)
DEF_NUM_BINARY_OP(__le__, <=)
DEF_NUM_BINARY_OP(__gt__, >)
DEF_NUM_BINARY_OP(__ge__, >=)
#undef DEF_NUM_BINARY_OP
static int _py_int__neg__(int argc, py_Ref argv) {
int64_t val = py_toint(&argv[0]);
py_pushint(-val);
return 1;
}
static int _py_float__neg__(int argc, py_Ref argv) {
double val = py_tofloat(&argv[0]);
py_pushfloat(-val);
return 1;
}
static int _py_int__truediv__(int argc, py_Ref argv) {
int64_t lhs = py_toint(&argv[0]);
double rhs;
if(py_castfloat(&argv[1], &rhs)) {
py_pushfloat(lhs / rhs);
} else {
py_push_notimplemented();
}
return 1;
}
static int _py_float__truediv__(int argc, py_Ref argv) {
double lhs = py_tofloat(&argv[0]);
double rhs;
if(py_castfloat(&argv[1], &rhs)) {
py_pushfloat(lhs / rhs);
} else {
py_push_notimplemented();
}
return 1;
}
static int _py_number__pow__(int argc, py_Ref argv) {
if(py_isint(&argv[0]) && py_isint(&argv[1])) {
int64_t lhs = py_toint(&argv[0]);
int64_t rhs = py_toint(&argv[1]);
if(rhs < 0) {
if(lhs == 0) {
// py_pusherror("0.0 cannot be raised to a negative power");
// TODO: ZeroDivisionError
return -1;
} else {
py_pushfloat(pow(lhs, rhs));
}
} else {
int64_t ret = 1;
while(rhs) {
if(rhs & 1) ret *= lhs;
lhs *= lhs;
rhs >>= 1;
}
py_pushint(ret);
}
} else {
double lhs, rhs;
py_castfloat(&argv[0], &lhs);
if(py_castfloat(&argv[1], &rhs)) {
py_pushfloat(pow(lhs, rhs));
} else {
py_push_notimplemented();
}
}
return 1;
}
static int _py_int__floordiv__(int argc, py_Ref argv) {
int64_t lhs = py_toint(&argv[0]);
if(py_isint(&argv[1])) {
int64_t rhs = py_toint(&argv[1]);
if(rhs == 0) return -1;
py_pushint(lhs / rhs);
} else {
py_push_notimplemented();
}
return 1;
}
static int _py_int__mod__(int argc, py_Ref argv) {
int64_t lhs = py_toint(&argv[0]);
if(py_isint(&argv[1])) {
int64_t rhs = py_toint(&argv[1]);
if(rhs == 0) return -1;
py_pushint(lhs % rhs);
} else {
py_push_notimplemented();
}
return 1;
}
static int _py_int__invert__(int argc, py_Ref argv) {
int64_t val = py_toint(&argv[0]);
py_pushint(~val);
return 1;
}
static int _py_int__bit_length(int argc, py_Ref argv) {
int64_t x = py_toint(&argv[0]);
if(x < 0) x = -x;
int bits = 0;
while(x) {
x >>= 1;
bits++;
}
py_pushint(bits);
return 1;
}
#define DEF_INT_BITWISE_OP(name, op) \
static int _py_int##name(int argc, py_Ref argv) { \
int64_t lhs = py_toint(&argv[0]); \
if(py_isint(&argv[1])) { \
int64_t rhs = py_toint(&argv[1]); \
py_pushint(lhs op rhs); \
} else { \
py_push_notimplemented(); \
} \
return 1; \
}
DEF_INT_BITWISE_OP(__and__, &)
DEF_INT_BITWISE_OP(__or__, |)
DEF_INT_BITWISE_OP(__xor__, ^)
DEF_INT_BITWISE_OP(__lshift__, <<)
DEF_INT_BITWISE_OP(__rshift__, >>)
#undef DEF_INT_BITWISE_OP
void pk_VM__init_builtins(pk_VM* self) {
/****** tp_int & tp_float ******/
py_Ref tmp = py_pushtmp();
py_Ref int_type = py_pushtmp();
*int_type = *py_getdict(&self->builtins, py_name("int"));
py_Ref float_type = py_pushtmp();
*float_type = *py_getdict(&self->builtins, py_name("float"));
#define BIND_INT_BINARY_OP(name) \
py_newnativefunc(tmp, _py_int##name, 2); \
py_setdict(int_type, name, tmp);
#define BIND_FLOAT_BINARY_OP(name) \
py_newnativefunc(tmp, _py_float##name, 2); \
py_setdict(float_type, name, tmp);
BIND_INT_BINARY_OP(__add__);
BIND_FLOAT_BINARY_OP(__add__);
BIND_INT_BINARY_OP(__sub__);
BIND_FLOAT_BINARY_OP(__sub__);
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__
py_newnativefunc(tmp, _py_int__neg__, 1);
py_setdict(int_type, __neg__, tmp);
py_newnativefunc(tmp, _py_float__neg__, 1);
py_setdict(float_type, __neg__, tmp);
// TODO: __repr__, __new__, __hash__
// __truediv__
py_newnativefunc(tmp, _py_int__truediv__, 2);
py_setdict(int_type, __truediv__, tmp);
py_newnativefunc(tmp, _py_float__truediv__, 2);
py_setdict(float_type, __truediv__, tmp);
// __pow__
py_newnativefunc(tmp, _py_number__pow__, 2);
py_setdict(int_type, __pow__, tmp);
py_setdict(float_type, __pow__, tmp);
// __floordiv__ & __mod__
py_newnativefunc(tmp, _py_int__floordiv__, 2);
py_setdict(int_type, __floordiv__, tmp);
py_newnativefunc(tmp, _py_int__mod__, 2);
py_setdict(int_type, __mod__, tmp);
// int.__invert__ & int.<BITWISE OP>
py_newnativefunc(tmp, _py_int__invert__, 1);
py_setdict(int_type, __invert__, tmp);
BIND_INT_BINARY_OP(__and__);
BIND_INT_BINARY_OP(__or__);
BIND_INT_BINARY_OP(__xor__);
BIND_INT_BINARY_OP(__lshift__);
BIND_INT_BINARY_OP(__rshift__);
// int.bit_length
py_newnativefunc(tmp, _py_int__bit_length, 1);
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_newfunction(py_reg(0), _py_print,
// "print(*args, sep=' ', end='\\n')",
// BindType_FUNCTION
// );
// py_setdict(builtins, py_name("hello"), py_reg(0));
}

14
src/interpreter/py_ops.c Normal file
View File

@ -0,0 +1,14 @@
#include "pocketpy/interpreter/vm.h"
#include "pocketpy/pocketpy.h"
int py_eq(const py_Ref lhs, const py_Ref rhs){
return 0;
}
int py_le(const py_Ref lhs, const py_Ref rhs){
return 0;
}
int py_hash(const py_Ref self, int64_t* out){
return 0;
}

View File

@ -17,7 +17,7 @@ static void pk_default_stderr(const char* s){
fflush(stderr);
}
void pk_TypeInfo__ctor(pk_TypeInfo *self, py_Name name, Type base, PyObject* obj, const PyVar* module, bool subclass_enabled){
void pk_TypeInfo__ctor(pk_TypeInfo *self, py_Name name, py_Type base, PyObject* obj, const PyVar* module, bool subclass_enabled){
memset(self, 0, sizeof(pk_TypeInfo));
self->name = name;
@ -34,52 +34,6 @@ void pk_TypeInfo__dtor(pk_TypeInfo *self){
c11_vector__dtor(&self->annotated_fields);
}
// static int _py_print(const py_Ref args, int argc){
// int length = py_tuple__len(args+0);
// py_Str* sep;
// py_Str* end;
// int err;
// err = py_tostr(args+1, &sep);
// if(err) return err;
// err = py_tostr(args+2, &end);
// if(err) return err;
// pk_SStream ss;
// pk_SStream__ctor(&ss);
// for(int i=0; i<length; i++){
// const py_Ref item = py_tuple__getitem(args+0, i);
// py_Str tmp;
// int err = py_str(item, &tmp);
// if(!err){
// pk_SStream__write_Str(&ss, &tmp);
// py_Str__dtor(&tmp);
// if(i != length-1){
// pk_SStream__write_Str(&ss, sep);
// }
// }else{
// py_Str__dtor(&tmp);
// pk_SStream__dtor(&ss);
// return err;
// }
// }
// pk_SStream__write_Str(&ss, end);
// py_Str out = pk_SStream__submit(&ss);
// pk_current_vm->_stdout(py_Str__data(&out));
// py_Str__dtor(&out);
// return 0;
// }
static void do_builtin_bindings(){
// py_Ref builtins = py_getmodule("builtins");
// py_newfunction(py_reg(0), _py_print,
// "print(*args, sep=' ', end='\\n')",
// BindType_FUNCTION
// );
// py_setdict(builtins, py_name("hello"), py_reg(0));
}
void pk_VM__ctor(pk_VM* self){
self->top_frame = NULL;
@ -96,7 +50,6 @@ void pk_VM__ctor(pk_VM* self){
self->_stderr = pk_default_stderr;
self->last_error = NULL;
self->last_retval = PY_NULL;
self->__curr_class = NULL;
self->__cached_object_new = NULL;
@ -106,19 +59,19 @@ void pk_VM__ctor(pk_VM* self){
ValueStack__ctor(&self->stack);
self->True = (PyVar){.type=tp_bool, .is_ptr=true, .extra=1,
._obj=pk_ManagedHeap__gcnew(&self->heap, tp_bool, 0, 1),
._obj=pk_ManagedHeap__gcnew(&self->heap, tp_bool, 0, 0),
};
self->False = (PyVar){.type=tp_bool, .is_ptr=true, .extra=0,
._obj=pk_ManagedHeap__gcnew(&self->heap, tp_bool, 0, 1),
._obj=pk_ManagedHeap__gcnew(&self->heap, tp_bool, 0, 0),
};
self->None = (PyVar){.type=tp_none_type, .is_ptr=true,
._obj=pk_ManagedHeap__gcnew(&self->heap, tp_none_type, 0, 1),
._obj=pk_ManagedHeap__gcnew(&self->heap, tp_none_type, 0, 0),
};
self->NotImplemented = (PyVar){.type=tp_not_implemented_type, .is_ptr=true,
._obj=pk_ManagedHeap__gcnew(&self->heap, tp_not_implemented_type, 0, 1),
._obj=pk_ManagedHeap__gcnew(&self->heap, tp_not_implemented_type, 0, 0),
};
self->Ellipsis = (PyVar){.type=tp_ellipsis, .is_ptr=true,
._obj=pk_ManagedHeap__gcnew(&self->heap, tp_ellipsis, 0, 1),
._obj=pk_ManagedHeap__gcnew(&self->heap, tp_ellipsis, 0, 0),
};
/* Init Builtin Types */
@ -172,7 +125,7 @@ void pk_VM__ctor(pk_VM* self){
self->builtins = *py_newmodule("builtins", NULL);
/* Setup Public Builtin Types */
Type public_types[] = {
py_Type public_types[] = {
tp_object, tp_type,
tp_int, tp_float, tp_bool, tp_str,
tp_list, tp_tuple,
@ -182,14 +135,14 @@ void pk_VM__ctor(pk_VM* self){
};
for(int i=0; i<PK_ARRAY_COUNT(public_types); i++){
Type t = public_types[i];
py_Type t = public_types[i];
pk_TypeInfo* ti = c11__at(pk_TypeInfo, &self->types, t);
py_setdict(&self->builtins, ti->name, &ti->self);
}
py_setdict(&self->builtins, py_name("NotImplemented"), &self->NotImplemented);
/* Do Buildin Bindings*/
do_builtin_bindings();
pk_VM__init_builtins(self);
self->main = *py_newmodule("__main__", NULL);
}
@ -220,11 +173,11 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self){
return RES_RETURN;
}
Type pk_VM__new_type(pk_VM* self, const char* name, Type base, const PyVar* module, bool subclass_enabled){
Type type = self->types.count;
py_Type pk_VM__new_type(pk_VM* self, const char* name, py_Type base, const PyVar* module, bool subclass_enabled){
py_Type type = self->types.count;
pk_TypeInfo* ti = c11_vector__emplace(&self->types);
PyObject* typeobj = pk_ManagedHeap__gcnew(&self->heap, tp_type, 0, sizeof(Type));
Type* value = PyObject__value(typeobj);
PyObject* typeobj = pk_ManagedHeap__gcnew(&self->heap, tp_type, -1, sizeof(py_Type));
py_Type* value = PyObject__value(typeobj);
*value = type;
pk_TypeInfo__ctor(ti, py_name(name), base, typeobj, module, subclass_enabled);
return type;

View File

@ -9,6 +9,8 @@
#define DICT_HASH_NEXT(h) ((h) * 5 + 1)
#define DICT_HASH_TRANS(h) ((int)((h) & 0xffffffff)) // used for tansform value from __hash__
#define PK_DICT_COMPACT_MODE 1
#define pkpy_Var__is_null(self) ((self)->type == 0)
#define pkpy_Var__set_null(self) do { (self)->type = 0; } while(0)
struct pkpy_DictEntry {
PyVar key;

View File

@ -2,13 +2,6 @@
#include "pocketpy/pocketpy.h"
#include <assert.h>
void PyVar__ctor3(PyVar* self, PyObject* existing){
assert(existing);
self->type = existing->type;
self->is_ptr = true;
self->_obj = existing;
}
void* PyObject__value(PyObject* self){
return (char*)self + PK_OBJ_HEADER_SIZE(self->slots);
}

View File

@ -5,135 +5,13 @@
#include <assert.h>
#include <stdlib.h>
pk_VM* pk_current_vm;
static pk_VM pk_default_vm;
void py_initialize(){
Pools_initialize();
pk_StrName__initialize();
pk_current_vm = &pk_default_vm;
pk_VM__ctor(&pk_default_vm);
}
int py_exec_simple(const char* source){
CodeObject* co = NULL;
pk_VM* vm = pk_current_vm;
Frame* frame = Frame__new(
co,
&vm->main,
NULL,
vm->stack.sp,
vm->stack.sp,
co
);
pk_VM__push_frame(vm, frame);
pk_FrameResult res = pk_VM__run_top_frame(vm);
if(res == RES_ERROR) return vm->last_error->type;
if(res == RES_RETURN) return 0; // vm->last_retval;
assert(0); // unreachable
}
py_Ref py_getmodule(const char *name){
pk_VM* vm = pk_current_vm;
return pk_NameDict__try_get(&vm->modules, py_name(name));
}
py_Ref py_newmodule(const char *name, const char *package){
pk_ManagedHeap* heap = &pk_current_vm->heap;
PyObject* obj = pk_ManagedHeap__gcnew(heap, tp_module, -1, 0);
py_Ref r0 = py_sysreg(0);
py_Ref r1 = py_sysreg(1);
*r0 = PyVar__fromobj(obj);
py_newstr(r1, name);
py_setdict(r0, __name__, r1);
package = package ? package : "";
py_newstr(r1, package);
py_setdict(r0, __package__, r1);
// convert to fullname
if(package[0] != '\0'){
// package.name
char buf[256];
snprintf(buf, sizeof(buf), "%s.%s", package, name);
name = buf;
}
py_newstr(r1, name);
py_setdict(r0, __path__, r1);
// we do not allow override in order to avoid memory leak
// it is because Module objects are not garbage collected
bool exists = pk_NameDict__contains(&pk_current_vm->modules, py_name(name));
if(exists) abort();
pk_NameDict__set(&pk_current_vm->modules, py_name(name), *r0);
return py_getmodule(name);
}
py_Error* py_getlasterror(){
return pk_current_vm->last_error;
}
void py_Error__print(py_Error* self){
abort();
}
py_Ref py_reg(int i){
assert(i >= 0 && i < 8);
return &pk_current_vm->reg[i];
}
py_Ref py_sysreg(int i){
assert(i >= 0 && i < 8);
return &pk_current_vm->sysreg[i];
}
py_Ref py_stack(int i){
assert(i < 0);
return &pk_current_vm->stack.sp[i];
}
void py_finalize(){
pk_VM__dtor(&pk_default_vm);
pk_current_vm = NULL;
pk_StrName__finalize();
Pools_finalize();
}
void py_setdict(py_Ref self, py_Name name, const py_Ref val){
pk_NameDict__set(
PyObject__dict(self->_obj),
name,
*val
);
}
void py_newint(py_Ref self, int64_t val){
self->type = tp_int;
self->is_ptr = false;
self->_i64 = val;
}
void py_newfloat(py_Ref self, double val){
self->type = tp_float;
self->is_ptr = false;
self->_f64 = val;
}
void py_newbool(py_Ref self, bool val){
pk_VM* vm = pk_current_vm;
*self = val ? vm->True : vm->False;
}
void py_newstr(py_Ref self, const char* val){
pk_VM* vm = pk_current_vm;
PyObject* obj = pk_ManagedHeap__gcnew(&vm->heap, tp_str, 0, sizeof(py_Str));
py_Str__ctor((py_Str*)PyObject__value(obj), val);
self->type = tp_str;
self->is_ptr = true;
self->_obj = obj;
}

46
src/public/cast.c Normal file
View File

@ -0,0 +1,46 @@
#include "pocketpy/pocketpy.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/objects/object.h"
#include "pocketpy/interpreter/vm.h"
int64_t py_toint(py_Ref self){
return self->_i64;
}
double py_tofloat(py_Ref self){
return self->_f64;
}
bool py_castfloat(py_Ref self, double* out){
switch(self->type){
case tp_int:
*out = (double)self->_i64;
return true;
case tp_float:
*out = self->_f64;
return true;
case tp_bool:
*out = self->extra;
return true;
default:
return false;
}
}
bool py_tobool(py_Ref self){
return self->extra;
}
const py_Str* py_tostr(py_Ref self){
return PyObject__value(self->_obj);
}
const char* py_tocstr(py_Ref self){
const py_Str* s = PyObject__value(self->_obj);
return py_Str__data(s);
}
bool py_istype(const py_Ref self, py_Type type){
return self->type == type;
}

15
src/public/error.c Normal file
View File

@ -0,0 +1,15 @@
#include "pocketpy/pocketpy.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/objects/object.h"
#include "pocketpy/interpreter/vm.h"
py_Error* py_getlasterror(){
return pk_current_vm->last_error;
}
void py_Error__print(py_Error* self){
abort();
}

48
src/public/modules.c Normal file
View File

@ -0,0 +1,48 @@
#include "pocketpy/pocketpy.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/objects/object.h"
#include "pocketpy/interpreter/vm.h"
py_Ref py_getmodule(const char *name){
pk_VM* vm = pk_current_vm;
return pk_NameDict__try_get(&vm->modules, py_name(name));
}
py_Ref py_newmodule(const char *name, const char *package){
pk_ManagedHeap* heap = &pk_current_vm->heap;
PyObject* obj = pk_ManagedHeap__gcnew(heap, tp_module, -1, 0);
py_Ref r0 = py_pushtmp();
py_Ref r1 = py_pushtmp();
*r0 = PyVar__fromobj(obj);
py_newstr(r1, name);
py_setdict(r0, __name__, r1);
package = package ? package : "";
py_newstr(r1, package);
py_setdict(r0, __package__, r1);
// convert to fullname
if(package[0] != '\0'){
// package.name
char buf[256];
snprintf(buf, sizeof(buf), "%s.%s", package, name);
name = buf;
}
py_newstr(r1, name);
py_setdict(r0, __path__, r1);
// we do not allow override in order to avoid memory leak
// it is because Module objects are not garbage collected
bool exists = pk_NameDict__contains(&pk_current_vm->modules, py_name(name));
if(exists) abort();
pk_NameDict__set(&pk_current_vm->modules, py_name(name), *r0);
py_poptmp(2);
return py_getmodule(name);
}

78
src/public/stackops.c Normal file
View File

@ -0,0 +1,78 @@
#include "pocketpy/pocketpy.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/objects/object.h"
#include "pocketpy/interpreter/vm.h"
py_Ref py_getdict(const py_Ref self, py_Name name){
assert(self && self->is_ptr);
return pk_NameDict__try_get(PyObject__dict(self->_obj), name);
}
void py_setdict(py_Ref self, py_Name name, const py_Ref val){
assert(self && self->is_ptr);
pk_NameDict__set(PyObject__dict(self->_obj), name, *val);
}
py_Ref py_getslot(const py_Ref self, int i){
assert(self && self->is_ptr);
assert(i >= 0 && i < self->_obj->slots);
return PyObject__slots(self->_obj) + i;
}
void py_setslot(py_Ref self, int i, const py_Ref val){
assert(self && self->is_ptr);
assert(i >= 0 && i < self->_obj->slots);
PyObject__slots(self->_obj)[i] = *val;
}
void py_copyref(const py_Ref src, py_Ref dst){
*dst = *src;
}
/* 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;
}
py_Ref py_peek(int i){
assert(i < 0);
return pk_current_vm->stack.sp + i;
}
void py_pop(){
pk_VM* vm = pk_current_vm;
vm->stack.sp--;
}
void py_shrink(int n){
pk_VM* vm = pk_current_vm;
vm->stack.sp -= n;
}
void py_pushref(const py_Ref src){
pk_VM* vm = pk_current_vm;
*vm->stack.sp++ = *src;
}
py_Ref py_pushtmp(){
pk_VM* vm = pk_current_vm;
py_newnull(vm->stack.sp++);
return py_gettop();
}
void py_poptmp(int n){
py_shrink(n);
}

94
src/public/values.c Normal file
View File

@ -0,0 +1,94 @@
#include "pocketpy/pocketpy.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/objects/object.h"
#include "pocketpy/interpreter/vm.h"
void py_newint(py_Ref self, int64_t val) {
self->type = tp_int;
self->is_ptr = false;
self->_i64 = val;
}
void py_newfloat(py_Ref self, double val) {
self->type = tp_float;
self->is_ptr = false;
self->_f64 = val;
}
void py_newbool(py_Ref self, bool val) {
pk_VM* vm = pk_current_vm;
*self = val ? vm->True : vm->False;
}
void py_newstr(py_Ref self, const char* data) {
pk_ManagedHeap* heap = &pk_current_vm->heap;
PyObject* obj = pk_ManagedHeap__gcnew(heap, tp_str, 0, sizeof(py_Str));
py_Str__ctor(PyObject__value(obj), data);
self->type = tp_str;
self->is_ptr = true;
self->_obj = obj;
}
void py_newstrn(py_Ref self, const char* data, int size) {
pk_ManagedHeap* heap = &pk_current_vm->heap;
PyObject* obj = pk_ManagedHeap__gcnew(heap, tp_str, 0, sizeof(py_Str));
py_Str__ctor2((py_Str*)PyObject__value(obj), data, size);
self->type = tp_str;
self->is_ptr = true;
self->_obj = obj;
}
void py_newnone(py_Ref self) {
pk_VM* vm = pk_current_vm;
*self = vm->None;
}
void py_newnull(py_Ref self) { self->type = 0; }
void py_newtuple(py_Ref self, int n) {
pk_VM* vm = pk_current_vm;
PyObject* obj = pk_ManagedHeap__gcnew(&vm->heap, tp_tuple, n, 0);
self->type = tp_tuple;
self->is_ptr = true;
self->_obj = obj;
}
void py_newfunction(py_Ref self, py_CFunction f, const char* sig) {
py_newfunction2(self, f, sig, BindType_FUNCTION, NULL, NULL);
}
void py_newfunction2(py_Ref self,
py_CFunction f,
const char* sig,
BindType bt,
const char* docstring,
const py_Ref userdata) {}
void py_newnativefunc(py_Ref self, py_CFunction f, int argc) {
py_newnativefunc2(self, f, argc, BindType_FUNCTION, NULL, NULL);
}
void py_newnativefunc2(py_Ref self,
py_CFunction f,
int argc,
BindType bt,
const char* docstring,
const py_Ref userdata) {}
void py_pushint(int64_t val) { py_newint(pk_current_vm->stack.sp++, val); }
void py_pushfloat(double val) { py_newfloat(pk_current_vm->stack.sp++, val); }
void py_pushbool(bool val) { py_newbool(pk_current_vm->stack.sp++, val); }
void py_pushstr(const py_Str* val) { py_newstr(pk_current_vm->stack.sp++, py_Str__data(val)); }
void py_pushcstr(const char* val) { py_newstr(pk_current_vm->stack.sp++, val); }
void py_pushcstrn(const char* val, int size) { py_newstrn(pk_current_vm->stack.sp++, val, size); }
void py_push_notimplemented() {
pk_VM* vm = pk_current_vm;
*vm->stack.sp++ = vm->NotImplemented;
}

44
src/public/vm.c Normal file
View File

@ -0,0 +1,44 @@
#include "pocketpy/pocketpy.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/objects/object.h"
#include "pocketpy/interpreter/vm.h"
pk_VM* pk_current_vm;
static pk_VM pk_default_vm;
void py_initialize() {
Pools_initialize();
pk_StrName__initialize();
pk_current_vm = &pk_default_vm;
pk_VM__ctor(&pk_default_vm);
}
void py_finalize() {
pk_VM__dtor(&pk_default_vm);
pk_current_vm = NULL;
pk_StrName__finalize();
Pools_finalize();
}
int py_exec(const char* source) {
CodeObject* co = NULL;
pk_VM* vm = pk_current_vm;
Frame* frame = Frame__new(co, &vm->main, NULL, vm->stack.sp, vm->stack.sp, co);
pk_VM__push_frame(vm, frame);
pk_FrameResult res = pk_VM__run_top_frame(vm);
if(res == RES_ERROR) return vm->last_error->type;
if(res == RES_RETURN) return 0;
PK_UNREACHABLE();
}
int py_eval(const char* source) {
CodeObject* co = NULL;
pk_VM* vm = pk_current_vm;
Frame* frame = Frame__new(co, &vm->main, NULL, vm->stack.sp, vm->stack.sp, co);
pk_VM__push_frame(vm, frame);
pk_FrameResult res = pk_VM__run_top_frame(vm);
if(res == RES_ERROR) return vm->last_error->type;
if(res == RES_RETURN) return 0;
PK_UNREACHABLE();
}

View File

@ -1,7 +1,7 @@
#include <stdio.h>
#include <stdlib.h>
#include "pocketpy.h"
#include "pocketpy/pocketpy.h"
char* read_file(const char* path) {
FILE* file = fopen(path, "r");
@ -28,7 +28,7 @@ int main(int argc, char** argv) {
char* source = read_file(argv[1]);
py_initialize();
if(py_exec_simple(source)){
if(py_exec(source)){
py_Error* err = py_getlasterror();
py_Error__print(err);
}