This commit is contained in:
blueloveTH 2025-06-03 02:31:15 +08:00
parent a0bd1a3f3b
commit 2f2a7b53fd
13 changed files with 111 additions and 94 deletions

View File

@ -2,6 +2,7 @@ name: build
on: on:
push: push:
branches: [ main ]
paths-ignore: paths-ignore:
- 'docs/**' - 'docs/**'
- 'web/**' - 'web/**'

View File

@ -2,6 +2,7 @@ name: PKBIND Build and Test
on: on:
push: push:
branches: [ main ]
paths-ignore: paths-ignore:
- "docs/**" - "docs/**"
- "web/**" - "web/**"

View File

@ -0,0 +1,5 @@
#pragma once
typedef struct NameDict {
} NameDict;

View File

@ -5,7 +5,7 @@
#include <stdint.h> #include <stdint.h>
#define SMALLMAP_T__HEADER #define SMALLMAP_T__HEADER
#define K uint16_t #define K py_Name
#define V int #define V int
#define NAME c11_smallmap_n2i #define NAME c11_smallmap_n2i
#include "pocketpy/xmacros/smallmap.h" #include "pocketpy/xmacros/smallmap.h"
@ -14,7 +14,7 @@
#define SMALLMAP_T__HEADER #define SMALLMAP_T__HEADER
#define K c11_sv #define K c11_sv
#define V uint16_t #define V py_Name
#define NAME c11_smallmap_s2n #define NAME c11_smallmap_s2n
#define less(a, b) (c11_sv__cmp((a), (b)) < 0) #define less(a, b) (c11_sv__cmp((a), (b)) < 0)
#define equal(a, b) (c11_sv__cmp((a), (b)) == 0) #define equal(a, b) (c11_sv__cmp((a), (b)) == 0)

View File

@ -4,15 +4,18 @@
#include "pocketpy/common/smallmap.h" #include "pocketpy/common/smallmap.h"
typedef struct { typedef struct {
char* data; // null-terminated data
int size; // size of the data excluding the null-terminator int size; // size of the data excluding the null-terminator
py_TValue obj; // cached `str` object (lazy initialized) py_TValue obj; // cached `str` object (lazy initialized)
} RInternedEntry; char data[]; // null-terminated data
} InternedEntry;
typedef struct { typedef struct {
c11_smallmap_s2n interned; c11_smallmap_s2n interned;
c11_vector /* T=RInternedEntry */ r_interned;
} InternedNames; } InternedNames;
void InternedNames__ctor(InternedNames* self); void InternedNames__ctor(InternedNames* self);
void InternedNames__dtor(InternedNames* self); void InternedNames__dtor(InternedNames* self);
#define MAGIC_METHOD(x) extern py_Name x;
#include "pocketpy/xmacros/magics.h"
#undef MAGIC_METHOD

View File

@ -75,9 +75,11 @@ typedef struct CodeObject {
c11_vector /*T=py_TValue*/ consts; // constants c11_vector /*T=py_TValue*/ consts; // constants
c11_vector /*T=py_Name*/ varnames; // local variables c11_vector /*T=py_Name*/ varnames; // local variables
int nlocals; // cached varnames.size() c11_vector /*T=py_Name*/ names;
int nlocals;
c11_smallmap_n2i varnames_inv; c11_smallmap_n2i varnames_inv;
c11_smallmap_n2i names_inv;
c11_vector /*T=CodeBlock*/ blocks; c11_vector /*T=CodeBlock*/ blocks;
c11_vector /*T=FuncDecl_*/ func_decls; c11_vector /*T=FuncDecl_*/ func_decls;
@ -89,6 +91,7 @@ typedef struct CodeObject {
void CodeObject__ctor(CodeObject* self, SourceData_ src, c11_sv name); void CodeObject__ctor(CodeObject* self, SourceData_ src, c11_sv name);
void CodeObject__dtor(CodeObject* self); void CodeObject__dtor(CodeObject* self);
int CodeObject__add_varname(CodeObject* self, py_Name name); int CodeObject__add_varname(CodeObject* self, py_Name name);
int CodeObject__add_name(CodeObject* self, py_Name name);
void CodeObject__gc_mark(const CodeObject* self, c11_vector* p_stack); void CodeObject__gc_mark(const CodeObject* self, c11_vector* p_stack);
typedef struct FuncDeclKwArg { typedef struct FuncDeclKwArg {

View File

@ -13,12 +13,12 @@ extern "C" {
#endif #endif
/************* Public Types *************/ /************* Public Types *************/
/// A helper struct for `py_Name`.
typedef struct py_OpaqueName py_OpaqueName;
/// A pointer that represents a python identifier. For fast name resolution.
typedef py_OpaqueName* py_Name;
/// A opaque type that represents a python object. You cannot access its members directly. /// A opaque type that represents a python object. You cannot access its members directly.
typedef struct py_TValue py_TValue; typedef struct py_TValue py_TValue;
/// An integer that represents a python identifier. This is to achieve string pooling and fast name
/// resolution.
typedef uint16_t py_Name;
/// An integer that represents a python type. `0` is invalid. /// An integer that represents a python type. `0` is invalid.
typedef int16_t py_Type; typedef int16_t py_Type;
/// A 64-bit integer type. Corresponds to `int` in python. /// A 64-bit integer type. Corresponds to `int` in python.
@ -710,14 +710,6 @@ PK_API int py_replinput(char* buf, int max_size);
/// %t: py_Type /// %t: py_Type
/// %n: py_Name /// %n: py_Name
enum py_MagicName {
py_MagicName__NULL, // 0 is reserved
#define MAGIC_METHOD(x) x,
#include "pocketpy/xmacros/magics.h"
#undef MAGIC_METHOD
};
enum py_PredefinedType { enum py_PredefinedType {
tp_nil = 0, tp_nil = 0,
tp_object = 1, tp_object = 1,

View File

@ -1,7 +1,7 @@
#include "pocketpy/common/smallmap.h" #include "pocketpy/common/smallmap.h"
#define SMALLMAP_T__SOURCE #define SMALLMAP_T__SOURCE
#define K uint16_t #define K py_Name
#define V int #define V int
#define NAME c11_smallmap_n2i #define NAME c11_smallmap_n2i
#include "pocketpy/xmacros/smallmap.h" #include "pocketpy/xmacros/smallmap.h"
@ -10,7 +10,7 @@
#define SMALLMAP_T__SOURCE #define SMALLMAP_T__SOURCE
#define K c11_sv #define K c11_sv
#define V uint16_t #define V py_Name
#define NAME c11_smallmap_s2n #define NAME c11_smallmap_s2n
#define less(a, b) (c11_sv__cmp((a), (b)) < 0) #define less(a, b) (c11_sv__cmp((a), (b)) < 0)
#define equal(a, b) (c11_sv__cmp((a), (b)) == 0) #define equal(a, b) (c11_sv__cmp((a), (b)) == 0)

View File

@ -61,9 +61,9 @@ typedef struct Ctx {
int level; int level;
int curr_iblock; int curr_iblock;
bool is_compiling_class; bool is_compiling_class;
c11_vector /*T=Expr* */ s_expr; c11_vector /*T=Expr_p*/ s_expr;
c11_smallmap_n2i global_names; c11_smallmap_n2i global_names;
c11_smallmap_s2n co_consts_string_dedup_map; c11_smallmap_s2n co_consts_string_dedup_map; // this stores 0-based index instead of pointer
} Ctx; } Ctx;
typedef struct Expr Expr; typedef struct Expr Expr;
@ -75,11 +75,12 @@ static int Ctx__enter_block(Ctx* self, CodeBlockType type);
static void Ctx__exit_block(Ctx* self); static void Ctx__exit_block(Ctx* self);
static int Ctx__emit_(Ctx* self, Opcode opcode, uint16_t arg, int line); static int Ctx__emit_(Ctx* self, Opcode opcode, uint16_t arg, int line);
static int Ctx__emit_virtual(Ctx* self, Opcode opcode, uint16_t arg, int line, bool virtual); static int Ctx__emit_virtual(Ctx* self, Opcode opcode, uint16_t arg, int line, bool virtual);
static void Ctx__revert_last_emit_(Ctx* self); // static void Ctx__revert_last_emit_(Ctx* self);
static int Ctx__emit_int(Ctx* self, int64_t value, int line); static int Ctx__emit_int(Ctx* self, int64_t value, int line);
static void Ctx__patch_jump(Ctx* self, int index); static void Ctx__patch_jump(Ctx* self, int index);
static void Ctx__emit_jump(Ctx* self, int target, int line); static void Ctx__emit_jump(Ctx* self, int target, int line);
static int Ctx__add_varname(Ctx* self, py_Name name); static int Ctx__add_varname(Ctx* self, py_Name name);
static int Ctx__add_name(Ctx* self, py_Name name);
static int Ctx__add_const(Ctx* self, py_Ref); static int Ctx__add_const(Ctx* self, py_Ref);
static int Ctx__add_const_string(Ctx* self, c11_sv); static int Ctx__add_const_string(Ctx* self, c11_sv);
static void Ctx__emit_store_name(Ctx* self, NameScope scope, py_Name name, int line); static void Ctx__emit_store_name(Ctx* self, NameScope scope, py_Name name, int line);
@ -117,7 +118,7 @@ void NameExpr__emit_(Expr* self_, Ctx* ctx) {
} }
} }
} }
Ctx__emit_(ctx, op, self->name, self->line); Ctx__emit_(ctx, op, Ctx__add_name(ctx, self->name), self->line);
} }
} }
@ -129,7 +130,7 @@ bool NameExpr__emit_del(Expr* self_, Ctx* ctx) {
break; break;
case NAME_GLOBAL: { case NAME_GLOBAL: {
Opcode op = ctx->co->src->is_dynamic ? OP_DELETE_NAME : OP_DELETE_GLOBAL; Opcode op = ctx->co->src->is_dynamic ? OP_DELETE_NAME : OP_DELETE_GLOBAL;
Ctx__emit_(ctx, op, self->name, self->line); Ctx__emit_(ctx, op, Ctx__add_name(ctx, self->name), self->line);
break; break;
} }
default: c11__unreachable(); default: c11__unreachable();
@ -140,7 +141,7 @@ bool NameExpr__emit_del(Expr* self_, Ctx* ctx) {
bool NameExpr__emit_store(Expr* self_, Ctx* ctx) { bool NameExpr__emit_store(Expr* self_, Ctx* ctx) {
NameExpr* self = (NameExpr*)self_; NameExpr* self = (NameExpr*)self_;
if(ctx->is_compiling_class) { if(ctx->is_compiling_class) {
Ctx__emit_(ctx, OP_STORE_CLASS_ATTR, self->name, self->line); Ctx__emit_(ctx, OP_STORE_CLASS_ATTR, Ctx__add_name(ctx, self->name), self->line);
return true; return true;
} }
Ctx__emit_store_name(ctx, self->scope, self->name, self->line); Ctx__emit_store_name(ctx, self->scope, self->name, self->line);
@ -710,7 +711,7 @@ static void BinaryExpr__dtor(Expr* self_) {
vtdelete(self->rhs); vtdelete(self->rhs);
} }
static py_Name cmp_token2name(TokenIndex token) { static uint16_t cmp_token2name(TokenIndex token) {
switch(token) { switch(token) {
case TK_LT: return __lt__; case TK_LT: return __lt__;
case TK_LE: return __le__; case TK_LE: return __le__;
@ -945,20 +946,20 @@ void AttribExpr__dtor(Expr* self_) {
void AttribExpr__emit_(Expr* self_, Ctx* ctx) { void AttribExpr__emit_(Expr* self_, Ctx* ctx) {
AttribExpr* self = (AttribExpr*)self_; AttribExpr* self = (AttribExpr*)self_;
vtemit_(self->child, ctx); vtemit_(self->child, ctx);
Ctx__emit_(ctx, OP_LOAD_ATTR, self->name, self->line); Ctx__emit_(ctx, OP_LOAD_ATTR, Ctx__add_name(ctx, self->name), self->line);
} }
bool AttribExpr__emit_del(Expr* self_, Ctx* ctx) { bool AttribExpr__emit_del(Expr* self_, Ctx* ctx) {
AttribExpr* self = (AttribExpr*)self_; AttribExpr* self = (AttribExpr*)self_;
vtemit_(self->child, ctx); vtemit_(self->child, ctx);
Ctx__emit_(ctx, OP_DELETE_ATTR, self->name, self->line); Ctx__emit_(ctx, OP_DELETE_ATTR, Ctx__add_name(ctx, self->name), self->line);
return true; return true;
} }
bool AttribExpr__emit_store(Expr* self_, Ctx* ctx) { bool AttribExpr__emit_store(Expr* self_, Ctx* ctx) {
AttribExpr* self = (AttribExpr*)self_; AttribExpr* self = (AttribExpr*)self_;
vtemit_(self->child, ctx); vtemit_(self->child, ctx);
Ctx__emit_(ctx, OP_STORE_ATTR, self->name, self->line); Ctx__emit_(ctx, OP_STORE_ATTR, Ctx__add_name(ctx, self->name), self->line);
return true; return true;
} }
@ -966,14 +967,14 @@ void AttribExpr__emit_inplace(Expr* self_, Ctx* ctx) {
AttribExpr* self = (AttribExpr*)self_; AttribExpr* self = (AttribExpr*)self_;
vtemit_(self->child, ctx); vtemit_(self->child, ctx);
Ctx__emit_(ctx, OP_DUP_TOP, BC_NOARG, self->line); Ctx__emit_(ctx, OP_DUP_TOP, BC_NOARG, self->line);
Ctx__emit_(ctx, OP_LOAD_ATTR, self->name, self->line); Ctx__emit_(ctx, OP_LOAD_ATTR, Ctx__add_name(ctx, self->name), self->line);
} }
bool AttribExpr__emit_istore(Expr* self_, Ctx* ctx) { bool AttribExpr__emit_istore(Expr* self_, Ctx* ctx) {
// [a, val] -> [val, a] // [a, val] -> [val, a]
AttribExpr* self = (AttribExpr*)self_; AttribExpr* self = (AttribExpr*)self_;
Ctx__emit_(ctx, OP_ROT_TWO, BC_NOARG, self->line); Ctx__emit_(ctx, OP_ROT_TWO, BC_NOARG, self->line);
Ctx__emit_(ctx, OP_STORE_ATTR, self->name, self->line); Ctx__emit_(ctx, OP_STORE_ATTR, Ctx__add_name(ctx, self->name), self->line);
return true; return true;
} }
@ -1031,7 +1032,7 @@ void CallExpr__emit_(Expr* self_, Ctx* ctx) {
if(self->callable->vt->is_attrib) { if(self->callable->vt->is_attrib) {
AttribExpr* p = (AttribExpr*)self->callable; AttribExpr* p = (AttribExpr*)self->callable;
vtemit_(p->child, ctx); vtemit_(p->child, ctx);
Ctx__emit_(ctx, OP_LOAD_METHOD, p->name, p->line); Ctx__emit_(ctx, OP_LOAD_METHOD, Ctx__add_name(ctx, p->name), p->line);
} else { } else {
vtemit_(self->callable, ctx); vtemit_(self->callable, ctx);
Ctx__emit_(ctx, OP_LOAD_NULL, BC_NOARG, BC_KEEPLINE); Ctx__emit_(ctx, OP_LOAD_NULL, BC_NOARG, BC_KEEPLINE);
@ -1046,7 +1047,7 @@ void CallExpr__emit_(Expr* self_, Ctx* ctx) {
c11__foreach(Expr*, &self->args, e) { vtemit_(*e, ctx); } c11__foreach(Expr*, &self->args, e) { vtemit_(*e, ctx); }
c11__foreach(CallExprKwArg, &self->kwargs, e) { c11__foreach(CallExprKwArg, &self->kwargs, e) {
Ctx__emit_int(ctx, e->key, self->line); Ctx__emit_int(ctx, (uintptr_t)e->key, self->line);
vtemit_(e->val, ctx); vtemit_(e->val, ctx);
} }
int KWARGC = self->kwargs.length; int KWARGC = self->kwargs.length;
@ -1166,10 +1167,10 @@ static int Ctx__emit_(Ctx* self, Opcode opcode, uint16_t arg, int line) {
return Ctx__emit_virtual(self, opcode, arg, line, false); return Ctx__emit_virtual(self, opcode, arg, line, false);
} }
static void Ctx__revert_last_emit_(Ctx* self) { // static void Ctx__revert_last_emit_(Ctx* self) {
c11_vector__pop(&self->co->codes); // c11_vector__pop(&self->co->codes);
c11_vector__pop(&self->co->codes_ex); // c11_vector__pop(&self->co->codes_ex);
} // }
static int Ctx__emit_int(Ctx* self, int64_t value, int line) { static int Ctx__emit_int(Ctx* self, int64_t value, int line) {
if(INT16_MIN <= value && value <= INT16_MAX) { if(INT16_MIN <= value && value <= INT16_MAX) {
@ -1199,6 +1200,10 @@ static int Ctx__add_varname(Ctx* self, py_Name name) {
return CodeObject__add_varname(self->co, name); return CodeObject__add_varname(self->co, name);
} }
static int Ctx__add_name(Ctx* self, py_Name name) {
return CodeObject__add_name(self->co, name);
}
static int Ctx__add_const_string(Ctx* self, c11_sv key) { static int Ctx__add_const_string(Ctx* self, c11_sv key) {
if(key.size > 100) { if(key.size > 100) {
py_Ref tmp = c11_vector__emplace(&self->co->consts); py_Ref tmp = c11_vector__emplace(&self->co->consts);
@ -1206,7 +1211,7 @@ static int Ctx__add_const_string(Ctx* self, c11_sv key) {
int index = self->co->consts.length - 1; int index = self->co->consts.length - 1;
return index; return index;
} }
uint16_t* val = c11_smallmap_s2n__try_get(&self->co_consts_string_dedup_map, key); uintptr_t* val = c11_smallmap_s2n__try_get(&self->co_consts_string_dedup_map, key);
if(val) { if(val) {
return *val; return *val;
} else { } else {
@ -1235,7 +1240,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_LOCAL: Ctx__emit_(self, OP_STORE_FAST, Ctx__add_varname(self, name), line); break;
case NAME_GLOBAL: { case NAME_GLOBAL: {
Opcode op = self->co->src->is_dynamic ? OP_STORE_NAME : OP_STORE_GLOBAL; Opcode op = self->co->src->is_dynamic ? OP_STORE_NAME : OP_STORE_GLOBAL;
Ctx__emit_(self, op, name, line); Ctx__emit_(self, op, Ctx__add_name(self, name), line);
} break; } break;
default: c11__unreachable(); default: c11__unreachable();
} }
@ -2409,7 +2414,7 @@ static Error* compile_class(Compiler* self, int decorators) {
ctx()->is_compiling_class = false; ctx()->is_compiling_class = false;
Ctx__s_emit_decorators(ctx(), decorators); Ctx__s_emit_decorators(ctx(), decorators);
Ctx__emit_(ctx(), OP_END_CLASS, name, BC_KEEPLINE); Ctx__emit_(ctx(), OP_END_CLASS, Ctx__add_name(ctx(), name), BC_KEEPLINE);
return NULL; return NULL;
} }
@ -2517,7 +2522,7 @@ __EAT_DOTS_END:
Ctx__emit_(ctx(), OP_DUP_TOP, BC_NOARG, BC_KEEPLINE); Ctx__emit_(ctx(), OP_DUP_TOP, BC_NOARG, BC_KEEPLINE);
consume(TK_ID); consume(TK_ID);
c11_sv name = Token__sv(prev()); c11_sv name = Token__sv(prev());
Ctx__emit_(ctx(), OP_LOAD_ATTR, py_namev(name), prev()->line); Ctx__emit_(ctx(), OP_LOAD_ATTR, Ctx__add_name(ctx(), py_namev(name)), prev()->line);
if(match(TK_AS)) { if(match(TK_AS)) {
consume(TK_ID); consume(TK_ID);
name = Token__sv(prev()); name = Token__sv(prev());
@ -2783,7 +2788,7 @@ static Error* compile_stmt(Compiler* self) {
NameExpr* ne = (NameExpr*)Ctx__s_top(ctx()); NameExpr* ne = (NameExpr*)Ctx__s_top(ctx());
int index = Ctx__add_const_string(ctx(), type_hint); int index = Ctx__add_const_string(ctx(), type_hint);
Ctx__emit_(ctx(), OP_LOAD_CONST, index, BC_KEEPLINE); Ctx__emit_(ctx(), OP_LOAD_CONST, index, BC_KEEPLINE);
Ctx__emit_(ctx(), OP_ADD_CLASS_ANNOTATION, ne->name, BC_KEEPLINE); Ctx__emit_(ctx(), OP_ADD_CLASS_ANNOTATION, Ctx__add_name(ctx(), ne->name), BC_KEEPLINE);
} }
} }
} }

View File

@ -211,13 +211,13 @@ FrameResult VM__run_top_frame(VM* self) {
PUSH(val); PUSH(val);
DISPATCH(); DISPATCH();
} }
py_Name name = c11__getitem(uint16_t, &frame->co->varnames, byte.arg); py_Name name = c11__getitem(py_Name, &frame->co->varnames, byte.arg);
UnboundLocalError(name); UnboundLocalError(name);
goto __ERROR; goto __ERROR;
} }
case OP_LOAD_NAME: { case OP_LOAD_NAME: {
assert(frame->is_locals_special); assert(frame->is_locals_special);
py_Name name = byte.arg; py_Name name = c11__getitem(py_Name, &frame->co->names, byte.arg);
// locals // locals
switch(frame->locals->type) { switch(frame->locals->type) {
case tp_locals: { case tp_locals: {
@ -261,7 +261,7 @@ FrameResult VM__run_top_frame(VM* self) {
goto __ERROR; goto __ERROR;
} }
case OP_LOAD_NONLOCAL: { case OP_LOAD_NONLOCAL: {
py_Name name = byte.arg; py_Name name = c11__getitem(py_Name, &frame->co->names, byte.arg);
py_Ref tmp = Frame__getclosure(frame, name); py_Ref tmp = Frame__getclosure(frame, name);
if(tmp != NULL) { if(tmp != NULL) {
PUSH(tmp); PUSH(tmp);
@ -283,7 +283,7 @@ FrameResult VM__run_top_frame(VM* self) {
goto __ERROR; goto __ERROR;
} }
case OP_LOAD_GLOBAL: { case OP_LOAD_GLOBAL: {
py_Name name = byte.arg; py_Name name = c11__getitem(py_Name, &frame->co->names, byte.arg);
int res = Frame__getglobal(frame, name); int res = Frame__getglobal(frame, name);
if(res == 1) { if(res == 1) {
PUSH(&self->last_retval); PUSH(&self->last_retval);
@ -308,7 +308,7 @@ FrameResult VM__run_top_frame(VM* self) {
} }
case OP_LOAD_CLASS_GLOBAL: { case OP_LOAD_CLASS_GLOBAL: {
assert(self->curr_class); assert(self->curr_class);
py_Name name = byte.arg; py_Name name = c11__getitem(py_Name, &frame->co->names, byte.arg);
py_Ref tmp = py_getdict(self->curr_class, name); py_Ref tmp = py_getdict(self->curr_class, name);
if(tmp) { if(tmp) {
PUSH(tmp); PUSH(tmp);
@ -368,7 +368,7 @@ FrameResult VM__run_top_frame(VM* self) {
} }
case OP_STORE_NAME: { case OP_STORE_NAME: {
assert(frame->is_locals_special); assert(frame->is_locals_special);
py_Name name = byte.arg; py_Name name = c11__getitem(py_Name, &frame->co->names, byte.arg);
switch(frame->locals->type) { switch(frame->locals->type) {
case tp_locals: { case tp_locals: {
py_Frame* noproxy = frame->locals->_ptr; py_Frame* noproxy = frame->locals->_ptr;
@ -435,7 +435,7 @@ FrameResult VM__run_top_frame(VM* self) {
} }
case OP_DELETE_NAME: { case OP_DELETE_NAME: {
assert(frame->is_locals_special); assert(frame->is_locals_special);
py_Name name = byte.arg; py_Name name = c11__getitem(py_Name, &frame->co->names, byte.arg);
switch(frame->locals->type) { switch(frame->locals->type) {
case tp_locals: { case tp_locals: {
py_Frame* noproxy = frame->locals->_ptr; py_Frame* noproxy = frame->locals->_ptr;
@ -464,7 +464,7 @@ FrameResult VM__run_top_frame(VM* self) {
} }
} }
case OP_DELETE_GLOBAL: { case OP_DELETE_GLOBAL: {
py_Name name = byte.arg; py_Name name = c11__getitem(py_Name, &frame->co->names, byte.arg);
int res = Frame__delglobal(frame, name); int res = Frame__delglobal(frame, name);
if(res == 1) DISPATCH(); if(res == 1) DISPATCH();
if(res == -1) goto __ERROR; if(res == -1) goto __ERROR;
@ -473,7 +473,8 @@ FrameResult VM__run_top_frame(VM* self) {
} }
case OP_DELETE_ATTR: { case OP_DELETE_ATTR: {
if(!py_delattr(TOP(), byte.arg)) goto __ERROR; py_Name name = c11__getitem(py_Name, &frame->co->names, byte.arg);
if(!py_delattr(TOP(), name)) goto __ERROR;
DISPATCH(); DISPATCH();
} }
@ -999,7 +1000,7 @@ FrameResult VM__run_top_frame(VM* self) {
/////////// ///////////
case OP_BEGIN_CLASS: { case OP_BEGIN_CLASS: {
// [base] // [base]
py_Name name = byte.arg; py_Name name = c11__getitem(py_Name, &frame->co->names, byte.arg);
py_Type base; py_Type base;
if(py_isnone(TOP())) { if(py_isnone(TOP())) {
base = tp_object; base = tp_object;
@ -1027,7 +1028,7 @@ FrameResult VM__run_top_frame(VM* self) {
} }
case OP_END_CLASS: { case OP_END_CLASS: {
// [cls or decorated] // [cls or decorated]
py_Name name = byte.arg; py_Name name = c11__getitem(py_Name, &frame->co->names, byte.arg);
if(!Frame__setglobal(frame, name, TOP())) goto __ERROR; if(!Frame__setglobal(frame, name, TOP())) goto __ERROR;
if(py_istype(TOP(), tp_type)) { if(py_istype(TOP(), tp_type)) {
@ -1052,7 +1053,7 @@ FrameResult VM__run_top_frame(VM* self) {
} }
case OP_STORE_CLASS_ATTR: { case OP_STORE_CLASS_ATTR: {
assert(self->curr_class); assert(self->curr_class);
py_Name name = byte.arg; py_Name name = c11__getitem(py_Name, &frame->co->names, byte.arg);
// TOP() can be a function, classmethod or custom decorator // TOP() can be a function, classmethod or custom decorator
py_Ref actual_func = TOP(); py_Ref actual_func = TOP();
if(actual_func->type == tp_classmethod) { if(actual_func->type == tp_classmethod) {

View File

@ -1,23 +1,25 @@
#include "pocketpy/interpreter/name.h" #include "pocketpy/interpreter/name.h"
#include "pocketpy/interpreter/vm.h" #include "pocketpy/interpreter/vm.h"
#define MAGIC_METHOD(x) py_Name x;
#include "pocketpy/xmacros/magics.h"
#undef MAGIC_METHOD
void InternedNames__ctor(InternedNames* self) { void InternedNames__ctor(InternedNames* self) {
c11_smallmap_s2n__ctor(&self->interned); c11_smallmap_s2n__ctor(&self->interned);
c11_vector__ctor(&self->r_interned, sizeof(RInternedEntry));
// initialize all magic names // initialize all magic names
#define MAGIC_METHOD(x) \ #define MAGIC_METHOD(x) x = py_name(#x);
if(x != py_name(#x)) abort();
#include "pocketpy/xmacros/magics.h" #include "pocketpy/xmacros/magics.h"
#undef MAGIC_METHOD #undef MAGIC_METHOD
} }
void InternedNames__dtor(InternedNames* self) { void InternedNames__dtor(InternedNames* self) {
for(int i = 0; i < self->r_interned.length; i++) { for(int i = 0; i < self->interned.length; i++) {
PK_FREE(c11__getitem(RInternedEntry, &self->r_interned, i).data); c11_smallmap_s2n_KV* kv = c11__at(c11_smallmap_s2n_KV, &self->interned, i);
PK_FREE((void*)kv->value);
} }
c11_smallmap_s2n__dtor(&self->interned); c11_smallmap_s2n__dtor(&self->interned);
c11_vector__dtor(&self->r_interned);
} }
py_Name py_name(const char* name) { py_Name py_name(const char* name) {
@ -29,47 +31,37 @@ py_Name py_name(const char* name) {
py_Name py_namev(c11_sv name) { py_Name py_namev(c11_sv name) {
InternedNames* self = &pk_current_vm->names; InternedNames* self = &pk_current_vm->names;
uint16_t index = c11_smallmap_s2n__get(&self->interned, name, 0); py_Name index = c11_smallmap_s2n__get(&self->interned, name, 0);
if(index != 0) return index; if(index != 0) return index;
// generate new index // generate new index
if(self->interned.length > 65530) c11__abort("py_Name index overflow"); InternedEntry* p = PK_MALLOC(sizeof(InternedEntry) + name.size + 1);
// NOTE: we must allocate the string in the heap so iterators are not invalidated p->size = name.size;
char* p = PK_MALLOC(name.size + 1); memcpy(p->data, name.data, name.size);
memcpy(p, name.data, name.size); p->data[name.size] = '\0';
p[name.size] = '\0'; memset(&p->obj, 0, sizeof(py_TValue));
RInternedEntry* entry = c11_vector__emplace(&self->r_interned); index = (py_Name)p;
entry->data = p;
entry->size = name.size;
memset(&entry->obj, 0, sizeof(py_TValue));
index = self->r_interned.length; // 1-based
// save to _interned // save to _interned
c11_smallmap_s2n__set(&self->interned, (c11_sv){p, name.size}, index); c11_smallmap_s2n__set(&self->interned, (c11_sv){p->data, name.size}, index);
assert(self->interned.length == self->r_interned.length);
return index; return index;
} }
const char* py_name2str(py_Name index) { const char* py_name2str(py_Name index) {
InternedNames* self = &pk_current_vm->names; InternedEntry* p = (InternedEntry*)index;
assert(index > 0 && index <= self->interned.length); return p->data;
return c11__getitem(RInternedEntry, &self->r_interned, index - 1).data;
} }
c11_sv py_name2sv(py_Name index) { c11_sv py_name2sv(py_Name index) {
InternedNames* self = &pk_current_vm->names; InternedEntry* p = (InternedEntry*)index;
assert(index > 0 && index <= self->interned.length); return (c11_sv){p->data, p->size};
RInternedEntry entry = c11__getitem(RInternedEntry, &self->r_interned, index - 1);
return (c11_sv){entry.data, entry.size};
} }
py_GlobalRef py_name2ref(py_Name index) { py_GlobalRef py_name2ref(py_Name index) {
InternedNames* self = &pk_current_vm->names; InternedEntry* p = (InternedEntry*)index;
assert(index > 0 && index <= self->interned.length); if(p->obj.type == tp_nil) {
RInternedEntry* entry = c11__at(RInternedEntry, &self->r_interned, index - 1);
if(entry->obj.type == tp_nil) {
c11_sv sv; c11_sv sv;
sv.data = entry->data; sv.data = p->data;
sv.size = entry->size; sv.size = p->size;
py_newstrv(&entry->obj, sv); py_newstrv(&p->obj, sv);
} }
return &entry->obj; return &p->obj;
} }

View File

@ -442,7 +442,7 @@ static bool
if(decl->starred_kwarg != -1) py_newdict(&buffer[decl->starred_kwarg]); if(decl->starred_kwarg != -1) py_newdict(&buffer[decl->starred_kwarg]);
for(int j = 0; j < kwargc; j++) { for(int j = 0; j < kwargc; j++) {
py_Name key = py_toint(&p1[2 * j]); py_Name key = (py_Name)py_toint(&p1[2 * j]);
int index = c11_smallmap_n2i__get(&decl->kw_to_index, key, -1); int index = c11_smallmap_n2i__get(&decl->kw_to_index, key, -1);
// if key is an explicit key, set as local variable // if key is an explicit key, set as local variable
if(index >= 0) { if(index >= 0) {
@ -681,8 +681,9 @@ void ManagedHeap__mark(ManagedHeap* self) {
pk__mark_value(&vm->reg[i]); pk__mark_value(&vm->reg[i]);
} }
// mark interned names // mark interned names
for(int i = 0; i < vm->names.r_interned.length; i++) { for(int i = 0; i < vm->names.interned.length; i++) {
RInternedEntry* entry = c11__at(RInternedEntry, &vm->names.r_interned, i); c11_smallmap_s2n_KV* kv = c11__at(c11_smallmap_s2n_KV, &vm->names.interned, i);
InternedEntry* entry = (InternedEntry*)kv->value;
pk__mark_value(&entry->obj); pk__mark_value(&entry->obj);
} }

View File

@ -123,10 +123,12 @@ void CodeObject__ctor(CodeObject* self, SourceData_ src, c11_sv name) {
c11_vector__ctor(&self->codes_ex, sizeof(BytecodeEx)); c11_vector__ctor(&self->codes_ex, sizeof(BytecodeEx));
c11_vector__ctor(&self->consts, sizeof(py_TValue)); c11_vector__ctor(&self->consts, sizeof(py_TValue));
c11_vector__ctor(&self->varnames, sizeof(uint16_t)); c11_vector__ctor(&self->varnames, sizeof(py_Name));
c11_vector__ctor(&self->names, sizeof(py_Name));
self->nlocals = 0; self->nlocals = 0;
c11_smallmap_n2i__ctor(&self->varnames_inv); c11_smallmap_n2i__ctor(&self->varnames_inv);
c11_smallmap_n2i__ctor(&self->names_inv);
c11_vector__ctor(&self->blocks, sizeof(CodeBlock)); c11_vector__ctor(&self->blocks, sizeof(CodeBlock));
c11_vector__ctor(&self->func_decls, sizeof(FuncDecl_)); c11_vector__ctor(&self->func_decls, sizeof(FuncDecl_));
@ -147,8 +149,10 @@ void CodeObject__dtor(CodeObject* self) {
c11_vector__dtor(&self->consts); c11_vector__dtor(&self->consts);
c11_vector__dtor(&self->varnames); c11_vector__dtor(&self->varnames);
c11_vector__dtor(&self->names);
c11_smallmap_n2i__dtor(&self->varnames_inv); c11_smallmap_n2i__dtor(&self->varnames_inv);
c11_smallmap_n2i__dtor(&self->names_inv);
c11_vector__dtor(&self->blocks); c11_vector__dtor(&self->blocks);
@ -172,13 +176,22 @@ void Function__ctor(Function* self, FuncDecl_ decl, py_GlobalRef module, py_Ref
int CodeObject__add_varname(CodeObject* self, py_Name name) { int CodeObject__add_varname(CodeObject* self, py_Name name) {
int index = c11_smallmap_n2i__get(&self->varnames_inv, name, -1); int index = c11_smallmap_n2i__get(&self->varnames_inv, name, -1);
if(index >= 0) return index; if(index >= 0) return index;
c11_vector__push(uint16_t, &self->varnames, name); c11_vector__push(py_Name, &self->varnames, name);
self->nlocals++; self->nlocals++;
index = self->varnames.length - 1; index = self->varnames.length - 1;
c11_smallmap_n2i__set(&self->varnames_inv, name, index); c11_smallmap_n2i__set(&self->varnames_inv, name, index);
return index; return index;
} }
int CodeObject__add_name(CodeObject* self, py_Name name) {
int index = c11_smallmap_n2i__get(&self->names_inv, name, -1);
if(index >= 0) return index;
c11_vector__push(py_Name, &self->names, name);
index = self->names.length - 1;
c11_smallmap_n2i__set(&self->names_inv, name, index);
return index;
}
void Function__dtor(Function* self) { void Function__dtor(Function* self) {
// printf("%s() in %s freed!\n", self->decl->code.name->data, // printf("%s() in %s freed!\n", self->decl->code.name->data,
// self->decl->code.src->filename->data); // self->decl->code.src->filename->data);