blueloveTH 1 년 전
부모
커밋
c2944b7fd8

+ 19 - 13
include/pocketpy/common/utils.h

@@ -15,7 +15,8 @@ extern "C" {
 
 #define PK_REGION(name) 1
 
-#define PK_SLICE_LOOP(i, start, stop, step) for(int i = start; step > 0 ? i < stop : i > stop; i += step)
+#define PK_SLICE_LOOP(i, start, stop, step)                                                        \
+    for(int i = start; step > 0 ? i < stop : i > stop; i += step)
 
 // global constants
 #define PK_HEX_TABLE "0123456789abcdef"
@@ -23,17 +24,21 @@ extern "C" {
 extern const char* kPlatformStrings[];
 
 #ifdef _MSC_VER
-#define PK_UNREACHABLE() __assume(0);
+#define c11__unreachedable() __assume(0)
 #else
-#define PK_UNREACHABLE() __builtin_unreachable();
+#define c11__unreachedable() __builtin_unreachable()
 #endif
 
-#define PK_FATAL_ERROR(...) { fprintf(stderr, __VA_ARGS__); abort(); }
+#define PK_FATAL_ERROR(...)                                                                        \
+    do {                                                                                           \
+        fprintf(stderr, __VA_ARGS__);                                                              \
+        abort();                                                                                   \
+    } while(0)
 
-#define PK_MIN(a, b) ((a) < (b) ? (a) : (b))
-#define PK_MAX(a, b) ((a) > (b) ? (a) : (b))
+#define c11__min(a, b) ((a) < (b) ? (a) : (b))
+#define c11__max(a, b) ((a) > (b) ? (a) : (b))
 
-#define PK_ARRAY_COUNT(a)   (sizeof(a) / sizeof(a[0]))
+#define c11__count_array(a) (sizeof(a) / sizeof(a[0]))
 
 // NARGS
 #define PK_NARGS_SEQ(_1, _2, _3, _4, N, ...) N
@@ -47,12 +52,13 @@ typedef struct RefCounted {
 } RefCounted;
 
 #define PK_INCREF(obj) (obj)->rc.count++
-#define PK_DECREF(obj) do { \
-    if(--(obj)->rc.count == 0) { \
-        (obj)->rc.dtor(obj); \
-        free(obj); \
-    } \
-} while(0)
+#define PK_DECREF(obj)                                                                             \
+    do {                                                                                           \
+        if(--(obj)->rc.count == 0) {                                                               \
+            (obj)->rc.dtor(obj);                                                                   \
+            free(obj);                                                                             \
+        }                                                                                          \
+    } while(0)
 
 #ifdef __cplusplus
 }

+ 0 - 1
include/pocketpy/common/vector.h

@@ -87,7 +87,6 @@ c11_array c11_vector__submit(c11_vector* self);
         }                                                                                          \
     } while(0)
 
-
 // NOTE: here we do an extra NULL check for it to avoid UB
 #define c11__foreach(T, self, it)                                                                  \
     for(T* it = (self)->data; it && it != (T*)(self)->data + (self)->count; it++)

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

@@ -57,7 +57,6 @@ typedef struct pk_VM {
     py_TValue reg[8];  // users' registers
 
     py_TValue __curr_class;
-    py_TValue __cached_object_new;
     FuncDecl_ __dynamic_func_decl;
     py_TValue __vectorcall_buffer[PK_MAX_CO_VARNAMES];
 

+ 15 - 2
include/pocketpy/pocketpy.h

@@ -115,10 +115,13 @@ bool py_isinstance(const py_Ref obj, py_Type type);
 bool py_issubclass(py_Type derived, py_Type base);
 
 /************* References *************/
+#define PY_CHECK_ARGC(n)                                                                            \
+    if(argc != n) return TypeError("expected %d arguments, got %d", n, argc)
+
+#define PY_CHECK_ARG_TYPE(i, type)   if(!py_checktype(py_arg(i), type)) return false
+
 #define py_offset(p, i) (py_Ref)((char*)p + ((i) << 4))
 #define py_arg(i) py_offset(argv, i)
-#define py_checkargc(n)                                                                            \
-    if(argc != n) return TypeError("expected %d arguments, got %d", n, argc)
 
 py_GlobalRef py_tpmagic(py_Type type, py_Name name);
 #define py_bindmagic(type, __magic__, f) py_newnativefunc(py_tpmagic((type), __magic__), (f))
@@ -375,3 +378,13 @@ enum py_PredefinedTypes {
 #ifdef __cplusplus
 }
 #endif
+
+
+/*
+Some notes:
+
+## Macros
+1. Function macros are partial functions. They can be used as normal expressions. Use the same naming convention as functions.
+2. Snippet macros are `do {...} while(0)` blocks. They cannot be used as expressions. Use `UPPER_CASE` naming convention.
+3. Constant macros are used for global constants. Use `UPPER_CASE` or k-prefix naming convention.
+*/

+ 4 - 4
src/common/str.c

@@ -197,14 +197,14 @@ int c11__byte_index_to_unicode(const char* data, int n) {
 //////////////
 
 int c11_sv__cmp(c11_sv self, c11_sv other) {
-    int res = strncmp(self.data, other.data, PK_MIN(self.size, other.size));
+    int res = strncmp(self.data, other.data, c11__min(self.size, other.size));
     if(res != 0) return res;
     return self.size - other.size;
 }
 
 int c11_sv__cmp2(c11_sv self, const char* other) {
     int size = strlen(other);
-    int res = strncmp(self.data, other, PK_MIN(self.size, size));
+    int res = strncmp(self.data, other, c11__min(self.size, size));
     if(res != 0) return res;
     return self.size - size;
 }
@@ -241,14 +241,14 @@ int c11__u8_header(unsigned char c, bool suppress) {
     if((c & 0b11111000) == 0b11110000) return 4;
     if((c & 0b11111100) == 0b11111000) return 5;
     if((c & 0b11111110) == 0b11111100) return 6;
-    if(!suppress) PK_FATAL_ERROR("invalid utf8 char\n")
+    if(!suppress) PK_FATAL_ERROR("invalid utf8 char\n");
     return 0;
 }
 
 IntParsingResult c11__parse_uint(c11_sv text, int64_t* out, int base) {
     *out = 0;
 
-    c11_sv prefix = {.data = text.data, .size = PK_MIN(2, text.size)};
+    c11_sv prefix = {.data = text.data, .size = c11__min(2, text.size)};
     if(base == -1) {
         if(c11__sveq(prefix, "0b"))
             base = 2;

+ 3 - 9
src/common/strname.c

@@ -31,16 +31,14 @@ void py_Name__finalize() {
     c11_vector__dtor(&_r_interned);
 }
 
-py_Name py_name(const char* name) {
-    return py_name2((c11_sv){name, strlen(name)});
-}
+py_Name py_name(const char* name) { return py_name2((c11_sv){name, strlen(name)}); }
 
 py_Name py_name2(c11_sv name) {
     // TODO: PK_GLOBAL_SCOPE_LOCK()
     uint16_t index = c11_smallmap_s2n__get(&_interned, name, 0);
     if(index != 0) return index;
     // generate new index
-    if(_interned.count > 65530) { PK_FATAL_ERROR("py_Name index overflow\n"); }
+    if(_interned.count > 65530) PK_FATAL_ERROR("py_Name index overflow\n");
     // NOTE: we must allocate the string in the heap so iterators are not invalidated
     char* p = malloc(name.size + 1);
     memcpy(p, name.data, name.size);
@@ -64,8 +62,4 @@ c11_sv py_name2sv(py_Name index) {
     return (c11_sv){p, strlen(p)};
 }
 
-
-bool py_ismagicname(py_Name name){
-    return name <= __missing__;
-}
-
+bool py_ismagicname(py_Name name) { return name <= __missing__; }

+ 4 - 3
src/compiler/compiler.c

@@ -129,7 +129,7 @@ bool NameExpr__emit_del(Expr* self_, Ctx* ctx) {
             break;
         case NAME_GLOBAL: Ctx__emit_(ctx, OP_DELETE_GLOBAL, self->name, self->line); break;
         case NAME_GLOBAL_UNKNOWN: Ctx__emit_(ctx, OP_DELETE_NAME, self->name, self->line); break;
-        default: PK_UNREACHABLE();
+        default: c11__unreachedable();
     }
     return true;
 }
@@ -294,7 +294,7 @@ void LiteralExpr__emit_(Expr* self_, Ctx* ctx) {
             Ctx__emit_(ctx, OP_LOAD_CONST, index, self->line);
             break;
         }
-        default: PK_UNREACHABLE();
+        default: c11__unreachedable();
     }
 }
 
@@ -1376,7 +1376,7 @@ static void Ctx__emit_store_name(Ctx* self, NameScope scope, py_Name name, int l
         case NAME_LOCAL: Ctx__emit_(self, OP_STORE_FAST, Ctx__add_varname(self, name), line); break;
         case NAME_GLOBAL: Ctx__emit_(self, OP_STORE_GLOBAL, name, line); break;
         case NAME_GLOBAL_UNKNOWN: Ctx__emit_(self, OP_STORE_NAME, name, line); break;
-        default: PK_UNREACHABLE();
+        default: c11__unreachedable();
     }
 }
 
@@ -1478,6 +1478,7 @@ static NameScope name_scope(Compiler* self) {
 }
 
 #define SyntaxError(...) NULL
+
 static Error* NeedMoreLines() { return NULL; }
 
 /* Matchers */

+ 2 - 2
src/interpreter/ceval.c

@@ -52,7 +52,7 @@ static bool stack_binaryop(pk_VM* self, py_Name op, py_Name rop);
                 PUSH(&self->last_retval);                                                          \
                 goto __NEXT_FRAME;                                                                 \
             case RES_ERROR: goto __ERROR;                                                          \
-            default: PK_UNREACHABLE();                                                             \
+            default: c11__unreachedable();                                                             \
         }                                                                                          \
     } while(0)
 
@@ -671,7 +671,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
                 *TOP() = self->last_retval;
                 DISPATCH();
             }
-            default: PK_UNREACHABLE();
+            default: c11__unreachedable();
         }
 
         assert(false);  // should never reach here

+ 24 - 25
src/interpreter/py_number.c

@@ -5,7 +5,7 @@
 
 #define DEF_NUM_BINARY_OP(name, op, rint, rfloat)                                                  \
     static bool _py_int##name(int argc, py_Ref argv) {                                             \
-        py_checkargc(2);                                                                           \
+        PY_CHECK_ARGC(2);                                                                          \
         if(py_isint(&argv[1])) {                                                                   \
             int64_t lhs = py_toint(&argv[0]);                                                      \
             int64_t rhs = py_toint(&argv[1]);                                                      \
@@ -20,7 +20,7 @@
         return true;                                                                               \
     }                                                                                              \
     static bool _py_float##name(int argc, py_Ref argv) {                                           \
-        py_checkargc(2);                                                                           \
+        PY_CHECK_ARGC(2);                                                                          \
         double lhs = py_tofloat(&argv[0]);                                                         \
         double rhs;                                                                                \
         if(py_castfloat(&argv[1], &rhs)) {                                                         \
@@ -45,21 +45,21 @@ DEF_NUM_BINARY_OP(__ge__, >=, py_newbool, py_newbool)
 #undef DEF_NUM_BINARY_OP
 
 static bool _py_int__neg__(int argc, py_Ref argv) {
-    py_checkargc(1);
+    PY_CHECK_ARGC(1);
     int64_t val = py_toint(&argv[0]);
     py_newint(py_retval(), -val);
     return true;
 }
 
 static bool _py_float__neg__(int argc, py_Ref argv) {
-    py_checkargc(1);
+    PY_CHECK_ARGC(1);
     double val = py_tofloat(&argv[0]);
     py_newfloat(py_retval(), -val);
     return true;
 }
 
 static bool _py_int__truediv__(int argc, py_Ref argv) {
-    py_checkargc(2);
+    PY_CHECK_ARGC(2);
     int64_t lhs = py_toint(&argv[0]);
     double rhs;
     if(py_castfloat(&argv[1], &rhs)) {
@@ -71,7 +71,7 @@ static bool _py_int__truediv__(int argc, py_Ref argv) {
 }
 
 static bool _py_float__truediv__(int argc, py_Ref argv) {
-    py_checkargc(2);
+    PY_CHECK_ARGC(2);
     double lhs = py_tofloat(&argv[0]);
     double rhs;
     if(py_castfloat(&argv[1], &rhs)) {
@@ -85,7 +85,7 @@ static bool _py_float__truediv__(int argc, py_Ref argv) {
 #define ZeroDivisionError(msg) false
 
 static bool _py_number__pow__(int argc, py_Ref argv) {
-    py_checkargc(2);
+    PY_CHECK_ARGC(2);
     if(py_isint(&argv[0]) && py_isint(&argv[1])) {
         int64_t lhs = py_toint(&argv[0]);
         int64_t rhs = py_toint(&argv[1]);
@@ -98,11 +98,11 @@ static bool _py_number__pow__(int argc, py_Ref argv) {
         } else {
             // rhs >= 0
             int64_t ret = 1;
-            while(true){
+            while(true) {
                 if(rhs & 1) ret *= lhs;
                 rhs >>= 1;
                 if(!rhs) break;
-                lhs *= lhs;     // place this here to avoid overflow
+                lhs *= lhs;  // place this here to avoid overflow
             }
             py_newint(py_retval(), ret);
         }
@@ -119,7 +119,7 @@ static bool _py_number__pow__(int argc, py_Ref argv) {
 }
 
 static bool _py_int__floordiv__(int argc, py_Ref argv) {
-    py_checkargc(2);
+    PY_CHECK_ARGC(2);
     int64_t lhs = py_toint(&argv[0]);
     if(py_isint(&argv[1])) {
         int64_t rhs = py_toint(&argv[1]);
@@ -132,7 +132,7 @@ static bool _py_int__floordiv__(int argc, py_Ref argv) {
 }
 
 static bool _py_int__mod__(int argc, py_Ref argv) {
-    py_checkargc(2);
+    PY_CHECK_ARGC(2);
     int64_t lhs = py_toint(&argv[0]);
     if(py_isint(&argv[1])) {
         int64_t rhs = py_toint(&argv[1]);
@@ -145,14 +145,14 @@ static bool _py_int__mod__(int argc, py_Ref argv) {
 }
 
 static bool _py_int__invert__(int argc, py_Ref argv) {
-    py_checkargc(1);
+    PY_CHECK_ARGC(1);
     int64_t val = py_toint(&argv[0]);
     py_newint(py_retval(), ~val);
     return true;
 }
 
 static bool _py_int__bit_length(int argc, py_Ref argv) {
-    py_checkargc(1);
+    PY_CHECK_ARGC(1);
     int64_t x = py_toint(py_arg(0));
     if(x < 0) x = -x;
     int bits = 0;
@@ -166,7 +166,7 @@ static bool _py_int__bit_length(int argc, py_Ref argv) {
 
 #define DEF_INT_BITWISE_OP(name, op)                                                               \
     static bool _py_int##name(int argc, py_Ref argv) {                                             \
-        py_checkargc(2);                                                                           \
+        PY_CHECK_ARGC(2);                                                                          \
         int64_t lhs = py_toint(&argv[0]);                                                          \
         if(py_isint(&argv[1])) {                                                                   \
             int64_t rhs = py_toint(&argv[1]);                                                      \
@@ -186,7 +186,7 @@ DEF_INT_BITWISE_OP(__rshift__, >>)
 #undef DEF_INT_BITWISE_OP
 
 static bool _py_int__repr__(int argc, py_Ref argv) {
-    py_checkargc(1);
+    PY_CHECK_ARGC(1);
     int64_t val = py_toint(&argv[0]);
     char buf[32];
     int size = snprintf(buf, sizeof(buf), "%lld", (long long)val);
@@ -195,7 +195,7 @@ static bool _py_int__repr__(int argc, py_Ref argv) {
 }
 
 static bool _py_float__repr__(int argc, py_Ref argv) {
-    py_checkargc(1);
+    PY_CHECK_ARGC(1);
     double val = py_tofloat(&argv[0]);
     char buf[32];
     int size = snprintf(buf, sizeof(buf), "%f", val);
@@ -222,7 +222,7 @@ static py_i64 c11_8bytes__hash(union c11_8bytes u) {
 }
 
 static bool _py_int__hash__(int argc, py_Ref argv) {
-    py_checkargc(1);
+    PY_CHECK_ARGC(1);
     int64_t val = py_toint(&argv[0]);
     union c11_8bytes u = {._i64 = val};
     py_newint(py_retval(), c11_8bytes__hash(u));
@@ -230,7 +230,7 @@ static bool _py_int__hash__(int argc, py_Ref argv) {
 }
 
 static bool _py_float__hash__(int argc, py_Ref argv) {
-    py_checkargc(1);
+    PY_CHECK_ARGC(1);
     double val = py_tofloat(&argv[0]);
     union c11_8bytes u = {._f64 = val};
     py_newint(py_retval(), c11_8bytes__hash(u));
@@ -270,11 +270,12 @@ static bool _py_int__new__(int argc, py_Ref argv) {
     // 1 or 2 args with str
     int base = 10;
     if(argc == 1 + 2) {
-        if(!py_checktype(py_arg(2), tp_int)) return false;
+        PY_CHECK_ARG_TYPE(2, tp_int);
         base = py_toint(py_arg(2));
     }
 
-    if(!py_checktype(py_arg(1), tp_str)) return false;
+    PY_CHECK_ARG_TYPE(1, tp_str);
+
     int size;
     const char* data = py_tostrn(py_arg(1), &size);
     bool negative = false;
@@ -322,20 +323,18 @@ static bool _py_float__new__(int argc, py_Ref argv) {
     int size;
     const char* data = py_tostrn(py_arg(1), &size);
 
-    if(c11__streq(data, "inf")){
+    if(c11__streq(data, "inf")) {
         py_newfloat(py_retval(), INFINITY);
         return true;
     }
-    if(c11__streq(data, "-inf")){
+    if(c11__streq(data, "-inf")) {
         py_newfloat(py_retval(), -INFINITY);
         return true;
     }
 
     char* p_end;
     py_f64 float_out = strtod(data, &p_end);
-    if(p_end != data + size){
-        return ValueError("invalid literal for float(): %q", data);
-    }
+    if(p_end != data + size) { return ValueError("invalid literal for float(): %q", data); }
     py_newfloat(py_retval(), float_out);
     return true;
 }

+ 4 - 5
src/interpreter/vm.c

@@ -82,7 +82,6 @@ void pk_VM__ctor(pk_VM* self) {
     self->has_error = false;
 
     self->__curr_class = PY_NIL;
-    self->__cached_object_new = PY_NIL;
     self->__dynamic_func_decl = NULL;
 
     pk_ManagedHeap__ctor(&self->heap, self);
@@ -99,6 +98,7 @@ void pk_VM__ctor(pk_VM* self) {
 
     validate(tp_int, pk_VM__new_type(self, "int", tp_object, NULL, false));
     validate(tp_float, pk_VM__new_type(self, "float", tp_object, NULL, false));
+    pk_number__register();
     validate(tp_bool, pk_VM__new_type(self, "bool", tp_object, NULL, false));
     validate(tp_str, pk_str__register());
 
@@ -155,7 +155,7 @@ void pk_VM__ctor(pk_VM* self) {
                               tp_stop_iteration,
                               tp_syntax_error};
 
-    for(int i = 0; i < PK_ARRAY_COUNT(public_types); i++) {
+    for(int i = 0; i < c11__count_array(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, py_tpobject(t));
@@ -166,7 +166,6 @@ void pk_VM__ctor(pk_VM* self) {
     py_setdict(&self->builtins, py_name("NotImplemented"), &tmp);
 
     /* Do Buildin Bindings*/
-    pk_number__register();
     // object.__new__
     py_bindmagic(tp_object, __new__, _py_object__new__);
 
@@ -286,7 +285,7 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bo
                 return __py_generator(
                     callstack.popx(),
                     ArgsView(__vectorcall_buffer, __vectorcall_buffer + co->nlocals));
-            default: PK_UNREACHABLE()
+            default: c11__unreachedable()
         };
 
         // simple or normal
@@ -373,7 +372,7 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bo
     }
 
     TypeError("'%t' object is not callable", p0->type);
-    PK_UNREACHABLE();
+    c11__unreachedable();
 }
 
 /****************************************/

+ 2 - 2
src/objects/dict.c

@@ -89,7 +89,7 @@ static int pkpy_Dict__probe0(const pkpy_Dict* self, py_TValue key, int hash) {
         struct pkpy_DictEntry* entry = &c11__getitem(struct pkpy_DictEntry, &self->_entries, idx);
         if(pkpy_Var__is_null(&entry->key)) return h;
     }
-    PK_UNREACHABLE();
+    c11__unreachedable();
 }
 
 static int pkpy_Dict__probe1(const pkpy_Dict* self, py_TValue key, int hash) {
@@ -103,7 +103,7 @@ static int pkpy_Dict__probe1(const pkpy_Dict* self, py_TValue key, int hash) {
         if(pkpy_Var__is_null(&entry->key)) continue;
         if(py_eq(&entry->key, &key)) return h;
     }
-    PK_UNREACHABLE();
+    c11__unreachedable();
 }
 
 static void pkpy_Dict__extendht(pkpy_Dict* self) {

+ 12 - 9
src/public/py_list.c

@@ -6,13 +6,6 @@
 
 typedef c11_vector List;
 
-py_Type pk_list__register() {
-    pk_VM* vm = pk_current_vm;
-    py_Type type = pk_VM__new_type(vm, "list", tp_object, NULL, false);
-    pk_TypeInfo* ti = c11__at(pk_TypeInfo, &vm->types, type);
-    ti->dtor = (void (*)(void*))c11_vector__dtor;
-    return type;
-}
 
 void py_newlist(py_Ref out) {
     pk_VM* vm = pk_current_vm;
@@ -67,9 +60,19 @@ void py_list__insert(py_Ref self, int i, const py_Ref val) {
 }
 
 ////////////////////////////////
-bool _py_list__len__(int argc, py_Ref argv){
-    py_checkargc(1);
+static bool _py_list__len__(int argc, py_Ref argv){
+    PY_CHECK_ARGC(1);
     py_i64 res = py_list__len(py_arg(0));
     py_newint(py_retval(), res);
     return true;
 }
+
+py_Type pk_list__register() {
+    pk_VM* vm = pk_current_vm;
+    py_Type type = pk_VM__new_type(vm, "list", tp_object, NULL, false);
+    pk_TypeInfo* ti = c11__at(pk_TypeInfo, &vm->types, type);
+    ti->dtor = (void (*)(void*))c11_vector__dtor;
+
+    py_bindmagic(type, __len__, _py_list__len__);
+    return type;
+}

+ 2 - 2
src/public/vm.c

@@ -177,7 +177,7 @@ static bool
     PK_DECREF(src);
     if(res == RES_ERROR) return false;
     if(res == RES_RETURN) return true;
-    PK_UNREACHABLE();
+    c11__unreachedable();
 }
 
 bool py_exec(const char* source) { return pk_VM__exec(pk_current_vm, source, "<exec>", EXEC_MODE); }
@@ -225,7 +225,7 @@ bool py_getunboundmethod(py_Ref self, py_Name name, py_Ref out, py_Ref out_self)
                 *out = *py_getslot(cls_var, 0);
                 *out_self = c11__getitem(pk_TypeInfo, &pk_current_vm->types, type).self;
                 break;
-            default: PK_UNREACHABLE();
+            default: c11__unreachedable();
         }
         return true;
     }

+ 3 - 0
tests/00_tmp.py

@@ -98,3 +98,6 @@ assert (-4)**13 == -67108864
 assert ~3 == -4
 assert ~-3 == 2
 assert ~0 == -1
+
+# tmp code
+assert [1, 2].__len__() == 2