blueloveTH před 1 rokem
rodič
revize
2ac2ff807f

+ 1 - 1
build_g.sh

@@ -4,7 +4,7 @@ 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" # -fsanitize=address,leak,undefined"
 
 echo "Compiling C files..."
 clang $FLAGS $SRC src2/main.c -o main

+ 2 - 0
include/pocketpy/interpreter/vm.h

@@ -82,6 +82,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,

+ 31 - 14
include/pocketpy/pocketpy.h

@@ -10,7 +10,7 @@ typedef struct pk_VM pk_VM;
 typedef uint16_t py_Name;
 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;
 
@@ -48,11 +48,37 @@ 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();
+
+/************* 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_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);
 
 /************* References *************/
 py_Ref py_getdict(const py_Ref self, py_Name name);
@@ -134,15 +160,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, py_Type);
-bool py_isinstance(const py_Ref obj, py_Type type);
-bool py_issubclass(py_Type derived, py_Type base);
-
 #ifdef __cplusplus
 }
 #endif

+ 293 - 0
src/interpreter/py_number.c

@@ -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));
+}

+ 1 - 47
src/interpreter/vm.c

@@ -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;
 
@@ -189,7 +143,7 @@ void pk_VM__ctor(pk_VM* 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);
 }
 

+ 46 - 0
src/public/cast.c

@@ -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;
+}

+ 39 - 18
src/public/values.c

@@ -4,24 +4,24 @@
 #include "pocketpy/objects/object.h"
 #include "pocketpy/interpreter/vm.h"
 
-void py_newint(py_Ref self, int64_t 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){
+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){
+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){
+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((py_Str*)PyObject__value(obj), data);
@@ -30,7 +30,7 @@ void py_newstr(py_Ref self, const char* data){
     self->_obj = obj;
 }
 
-void py_newstrn(py_Ref self, const char* data, int size){
+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);
@@ -39,16 +39,14 @@ void py_newstrn(py_Ref self, const char* data, int size){
     self->_obj = obj;
 }
 
-void py_newnone(py_Ref self){
+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_newnull(py_Ref self) { self->type = 0; }
 
-void py_newtuple(py_Ref self, int n){
+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;
@@ -56,18 +54,41 @@ void py_newtuple(py_Ref self, int n){
     self->_obj = obj;
 }
 
-void py_newfunction(py_Ref self, py_CFunction f, const char* sig, BindType bt){
-    py_newfunction2(self, f, sig, bt, NULL, NULL);
+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_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_newnativefunc(py_Ref self, py_CFunction f, int argc, BindType bt){
-    py_newnativefunc2(self, f, argc, bt, 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_newnativefunc2(py_Ref self, py_CFunction f, int argc, BindType bt, const char *docstring, const py_Ref userdata){
+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;
+}