diff --git a/include/pocketpy/common/name.h b/include/pocketpy/common/name.h new file mode 100644 index 00000000..3fb81a3b --- /dev/null +++ b/include/pocketpy/common/name.h @@ -0,0 +1,10 @@ +#pragma once + +#include "pocketpy/pocketpy.h" + +void pk_names_initialize(); +void pk_names_finalize(); + +#define MAGIC_METHOD(x) extern py_Name x; +#include "pocketpy/xmacros/magics.h" +#undef MAGIC_METHOD \ No newline at end of file diff --git a/include/pocketpy/common/str.h b/include/pocketpy/common/str.h index 92ec1071..83fcf20f 100644 --- a/include/pocketpy/common/str.h +++ b/include/pocketpy/common/str.h @@ -60,6 +60,7 @@ int c11_sv__index2(c11_sv self, c11_sv sub, int start); int c11_sv__count(c11_sv self, c11_sv sub); bool c11_sv__startswith(c11_sv self, c11_sv prefix); bool c11_sv__endswith(c11_sv self, c11_sv suffix); +uint64_t c11_sv__hash(c11_sv self); c11_string* c11_sv__replace(c11_sv self, char old, char new_); c11_string* c11_sv__replace2(c11_sv self, c11_sv old, c11_sv new_); diff --git a/include/pocketpy/export.h b/include/pocketpy/export.h index d60e9ca3..d115a8e0 100644 --- a/include/pocketpy/export.h +++ b/include/pocketpy/export.h @@ -57,7 +57,7 @@ #endif #if defined(__GNUC__) || defined(__clang__) - #define PK_DEPRECATED [[deprecated]] + #define PK_DEPRECATED __attribute__((deprecated)) #else #define PK_DEPRECATED #endif \ No newline at end of file diff --git a/include/pocketpy/interpreter/name.h b/include/pocketpy/interpreter/name.h index d1fa99b9..e69de29b 100644 --- a/include/pocketpy/interpreter/name.h +++ b/include/pocketpy/interpreter/name.h @@ -1,21 +0,0 @@ -#pragma once - -#include "pocketpy/objects/base.h" -#include "pocketpy/common/smallmap.h" - -typedef struct { - int size; // size of the data excluding the null-terminator - py_TValue obj; // cached `str` object (lazy initialized) - char data[]; // null-terminated data -} InternedEntry; - -typedef struct { - c11_smallmap_v2n interned; -} InternedNames; - -void InternedNames__ctor(InternedNames* self); -void InternedNames__dtor(InternedNames* self); - -#define MAGIC_METHOD(x) extern py_Name x; -#include "pocketpy/xmacros/magics.h" -#undef MAGIC_METHOD \ No newline at end of file diff --git a/include/pocketpy/xmacros/opcodes.h b/include/pocketpy/xmacros/opcodes.h index d27a66d1..99f3e448 100644 --- a/include/pocketpy/xmacros/opcodes.h +++ b/include/pocketpy/xmacros/opcodes.h @@ -51,7 +51,25 @@ OPCODE(BUILD_SET) OPCODE(BUILD_SLICE) OPCODE(BUILD_STRING) /**************************/ -OPCODE(BINARY_OP) +OPCODE(BINARY_ADD) +OPCODE(BINARY_SUB) +OPCODE(BINARY_MUL) +OPCODE(BINARY_TRUEDIV) +OPCODE(BINARY_FLOORDIV) +OPCODE(BINARY_MOD) +OPCODE(BINARY_POW) +OPCODE(BINARY_LSHIFT) +OPCODE(BINARY_RSHIFT) +OPCODE(BINARY_AND) +OPCODE(BINARY_OR) +OPCODE(BINARY_XOR) +OPCODE(BINARY_MATMUL) +OPCODE(COMPARE_LT) +OPCODE(COMPARE_LE) +OPCODE(COMPARE_EQ) +OPCODE(COMPARE_NE) +OPCODE(COMPARE_GT) +OPCODE(COMPARE_GE) OPCODE(IS_OP) OPCODE(CONTAINS_OP) /**************************/ diff --git a/src/common/name.c b/src/common/name.c new file mode 100644 index 00000000..191d9480 --- /dev/null +++ b/src/common/name.c @@ -0,0 +1,25 @@ +#include "pocketpy/common/name.h" +#include + +typedef struct InternedEntry InternedEntry; +typedef struct InternedEntry{ + InternedEntry* prev; + InternedEntry* next; + py_i64 hash; + int size; // size of the data excluding the null-terminator + char data[]; // null-terminated data +} InternedEntry; + +typedef struct { + InternedEntry* table[1 << 16]; + atomic_bool lock; +} InternedNames; + +void pk_names_initialize() { + +} + + +void pk_names_finalize() { + +} \ No newline at end of file diff --git a/src/common/str.c b/src/common/str.c index 876c2c20..0982c455 100644 --- a/src/common/str.c +++ b/src/common/str.c @@ -181,6 +181,15 @@ bool c11_sv__endswith(c11_sv self, c11_sv suffix) { return memcmp(self.data + self.size - suffix.size, suffix.data, suffix.size) == 0; } +uint64_t c11_sv__hash(c11_sv self) { + uint64_t hash = 5381; + for(int i = 0; i < self.size; i++) { + // hash * 33 + c + hash = ((hash << 5) + hash) + (unsigned char)self.data[i]; + } + return hash; +} + c11_vector /* T=c11_sv */ c11_sv__split(c11_sv self, char sep) { c11_vector retval; c11_vector__ctor(&retval, sizeof(c11_sv)); diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index daab384d..4ca7785e 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -711,19 +711,19 @@ static void BinaryExpr__dtor(Expr* self_) { vtdelete(self->rhs); } -static py_Name cmp_token2name(TokenIndex token) { +static Opcode cmp_token2op(TokenIndex token) { switch(token) { - case TK_LT: return __lt__; - case TK_LE: return __le__; - case TK_EQ: return __eq__; - case TK_NE: return __ne__; - case TK_GT: return __gt__; - case TK_GE: return __ge__; + case TK_LT: return OP_COMPARE_LT; + case TK_LE: return OP_COMPARE_LE; + case TK_EQ: return OP_COMPARE_EQ; + case TK_NE: return OP_COMPARE_NE; + case TK_GT: return OP_COMPARE_GT; + case TK_GE: return OP_COMPARE_GE; default: return 0; } } -#define is_compare_expr(e) ((e)->vt->is_binary && cmp_token2name(((BinaryExpr*)(e))->op)) +#define is_compare_expr(e) ((e)->vt->is_binary && cmp_token2op(((BinaryExpr*)(e))->op)) static void _emit_compare(BinaryExpr* self, Ctx* ctx, c11_vector* jmps) { if(is_compare_expr(self->lhs)) { @@ -734,7 +734,7 @@ static void _emit_compare(BinaryExpr* self, Ctx* ctx, c11_vector* jmps) { vtemit_(self->rhs, ctx); // [a, b] Ctx__emit_(ctx, OP_DUP_TOP, BC_NOARG, self->line); // [a, b, b] Ctx__emit_(ctx, OP_ROT_THREE, BC_NOARG, self->line); // [b, a, b] - Ctx__emit_(ctx, OP_BINARY_OP, cmp_token2name(self->op), self->line); + Ctx__emit_(ctx, cmp_token2op(self->op), BC_NOARG, self->line); // [b, RES] int index = Ctx__emit_(ctx, OP_SHORTCUT_IF_FALSE_OR_POP, BC_NOARG, self->line); c11_vector__push(int, jmps, index); @@ -744,7 +744,7 @@ static void BinaryExpr__emit_(Expr* self_, Ctx* ctx) { BinaryExpr* self = (BinaryExpr*)self_; c11_vector /*T=int*/ jmps; c11_vector__ctor(&jmps, sizeof(int)); - if(cmp_token2name(self->op) && is_compare_expr(self->lhs)) { + if(cmp_token2op(self->op) && is_compare_expr(self->lhs)) { // (a < b) < c BinaryExpr* e = (BinaryExpr*)self->lhs; _emit_compare(e, ctx, &jmps); @@ -760,24 +760,24 @@ static void BinaryExpr__emit_(Expr* self_, Ctx* ctx) { vtemit_(self->rhs, ctx); - Opcode opcode = OP_BINARY_OP; + Opcode opcode; uint16_t arg = BC_NOARG; switch(self->op) { - case TK_ADD: arg = __add__ | (__radd__ << 8); break; - case TK_SUB: arg = __sub__ | (__rsub__ << 8); break; - case TK_MUL: arg = __mul__ | (__rmul__ << 8); break; - case TK_DIV: arg = __truediv__ | (__rtruediv__ << 8); break; - case TK_FLOORDIV: arg = __floordiv__ | (__rfloordiv__ << 8); break; - case TK_MOD: arg = __mod__ | (__rmod__ << 8); break; - case TK_POW: arg = __pow__ | (__rpow__ << 8); break; + case TK_ADD: opcode = OP_BINARY_ADD; break; + case TK_SUB: opcode = OP_BINARY_SUB; break; + case TK_MUL: opcode = OP_BINARY_MUL; break; + case TK_DIV: opcode = OP_BINARY_TRUEDIV; break; + case TK_FLOORDIV: opcode = OP_BINARY_FLOORDIV; break; + case TK_MOD: opcode = OP_BINARY_MOD; break; + case TK_POW: opcode = OP_BINARY_POW; break; - case TK_LT: arg = __lt__ | (__gt__ << 8); break; - case TK_LE: arg = __le__ | (__ge__ << 8); break; - case TK_EQ: arg = __eq__ | (__eq__ << 8); break; - case TK_NE: arg = __ne__ | (__ne__ << 8); break; - case TK_GT: arg = __gt__ | (__lt__ << 8); break; - case TK_GE: arg = __ge__ | (__le__ << 8); break; + case TK_LT: opcode = OP_COMPARE_LT; break; + case TK_LE: opcode = OP_COMPARE_LE; break; + case TK_EQ: opcode = OP_COMPARE_EQ; break; + case TK_NE: opcode = OP_COMPARE_NE; break; + case TK_GT: opcode = OP_COMPARE_GT; break; + case TK_GE: opcode = OP_COMPARE_GE; break; case TK_IN: opcode = OP_CONTAINS_OP; @@ -796,13 +796,13 @@ static void BinaryExpr__emit_(Expr* self_, Ctx* ctx) { arg = 1; break; - case TK_LSHIFT: arg = __lshift__; break; - case TK_RSHIFT: arg = __rshift__; break; - case TK_AND: arg = __and__; break; - case TK_OR: arg = __or__; break; - case TK_XOR: arg = __xor__; break; - case TK_DECORATOR: arg = __matmul__; break; - default: assert(false); + case TK_LSHIFT: opcode = OP_BINARY_LSHIFT; break; + case TK_RSHIFT: opcode = OP_BINARY_RSHIFT; break; + case TK_AND: opcode = OP_BINARY_AND; break; + case TK_OR: opcode = OP_BINARY_OR; break; + case TK_XOR: opcode = OP_BINARY_XOR; break; + case TK_DECORATOR: opcode = OP_BINARY_MATMUL; break; + default: c11__unreachable(); } Ctx__emit_(ctx, opcode, arg, self->line); diff --git a/src/interpreter/ceval.c b/src/interpreter/ceval.c index f606860f..24696983 100644 --- a/src/interpreter/ceval.c +++ b/src/interpreter/ceval.c @@ -601,14 +601,33 @@ FrameResult VM__run_top_frame(VM* self) { DISPATCH(); } /*****************************/ - case OP_BINARY_OP: { - py_Name op = byte.arg & 0xFF; - py_Name rop = byte.arg >> 8; - if(!pk_stack_binaryop(self, op, rop)) goto __ERROR; - POP(); - *TOP() = self->last_retval; - DISPATCH(); +#define CASE_BINARY_OP(label, op, rop)\ + case label: {\ + if(!pk_stack_binaryop(self, op, rop)) goto __ERROR;\ + POP();\ + *TOP() = self->last_retval;\ + DISPATCH();\ } + CASE_BINARY_OP(OP_BINARY_ADD, __add__, __radd__) + CASE_BINARY_OP(OP_BINARY_SUB, __sub__, __rsub__) + CASE_BINARY_OP(OP_BINARY_MUL, __mul__, __rmul__) + CASE_BINARY_OP(OP_BINARY_TRUEDIV, __truediv__, __rtruediv__) + CASE_BINARY_OP(OP_BINARY_FLOORDIV, __floordiv__, __rfloordiv__) + CASE_BINARY_OP(OP_BINARY_MOD, __mod__, __rmod__) + CASE_BINARY_OP(OP_BINARY_POW, __pow__, __rpow__) + CASE_BINARY_OP(OP_BINARY_LSHIFT, __lshift__, 0) + CASE_BINARY_OP(OP_BINARY_RSHIFT, __rshift__, 0) + CASE_BINARY_OP(OP_BINARY_AND, __and__, 0) + CASE_BINARY_OP(OP_BINARY_OR, __or__, 0) + CASE_BINARY_OP(OP_BINARY_XOR, __xor__, 0) + CASE_BINARY_OP(OP_BINARY_MATMUL, __matmul__, 0) + CASE_BINARY_OP(OP_COMPARE_LT, __lt__, __gt__) + CASE_BINARY_OP(OP_COMPARE_LE, __le__, __ge__) + CASE_BINARY_OP(OP_COMPARE_EQ, __eq__, __eq__) + CASE_BINARY_OP(OP_COMPARE_NE, __ne__, __ne__) + CASE_BINARY_OP(OP_COMPARE_GT, __gt__, __lt__) + CASE_BINARY_OP(OP_COMPARE_GE, __ge__, __le__) +#undef CASE_BINARY_OP case OP_IS_OP: { bool res = py_isidentical(SECOND(), TOP()); POP(); diff --git a/src/public/py_str.c b/src/public/py_str.c index 06175ec2..e7145ca1 100644 --- a/src/public/py_str.c +++ b/src/public/py_str.c @@ -103,13 +103,8 @@ static bool str__new__(int argc, py_Ref argv) { static bool str__hash__(int argc, py_Ref argv) { PY_CHECK_ARGC(1); - int size; - const char* data = py_tostrn(&argv[0], &size); - uint64_t res = 0; - for(int i = 0; i < size; i++) { - res = res * 31 + data[i]; - } - py_newint(py_retval(), res); + uint64_t res = c11_sv__hash(py_tosv(argv)); + py_newint(py_retval(), (py_i64)res); return true; }