This commit is contained in:
blueloveTH 2024-07-05 00:17:53 +08:00
parent 4569547161
commit c2944b7fd8
14 changed files with 94 additions and 78 deletions

View File

@ -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,7 +52,8 @@ typedef struct RefCounted {
} RefCounted;
#define PK_INCREF(obj) (obj)->rc.count++
#define PK_DECREF(obj) do { \
#define PK_DECREF(obj) \
do { \
if(--(obj)->rc.count == 0) { \
(obj)->rc.dtor(obj); \
free(obj); \

View File

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

View File

@ -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];

View File

@ -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.
*/

View File

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

View File

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

View File

@ -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 */

View File

@ -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

View File

@ -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]);
@ -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;
@ -333,9 +334,7 @@ static bool _py_float__new__(int argc, py_Ref argv) {
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;
}

View File

@ -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();
}
/****************************************/

View File

@ -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) {

View File

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

View File

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

View File

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