This commit is contained in:
blueloveTH 2024-06-28 23:07:26 +08:00
parent 6f4617b83d
commit c4b52ef684
10 changed files with 565 additions and 96 deletions

View File

@ -47,10 +47,7 @@ c11_array c11_vector__submit(c11_vector* self);
(self)->count++; \ (self)->count++; \
}while(0) }while(0)
#define c11_vector__pop(T, self) \ #define c11_vector__pop(self) (--(self)->count)
do{ \
(self)->count--; \
}while(0)
#define c11_vector__back(T, self) \ #define c11_vector__back(T, self) \
(((T*)(self)->data)[(self)->count - 1]) (((T*)(self)->data)[(self)->count - 1])
@ -89,7 +86,7 @@ c11_array c11_vector__submit(c11_vector* self);
} \ } \
}while(0) }while(0)
#define c11_vector__foreach(T, self, it) \ #define c11__foreach(T, self, it) \
for(T* it = (T*)(self)->data; it != (T*)(self)->data + (self)->count; it++) for(T* it = (T*)(self)->data; it != (T*)(self)->data + (self)->count; it++)
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -10,6 +10,7 @@ extern "C" {
#endif #endif
Error* pk_compile(pk_SourceData_ src, CodeObject* out); Error* pk_compile(pk_SourceData_ src, CodeObject* out);
void pk_Compiler__initialize(); void pk_Compiler__initialize();
#define pk_Compiler__finalize() // do nothing #define pk_Compiler__finalize() // do nothing

View File

@ -0,0 +1,60 @@
#pragma once
#include "pocketpy/objects/codeobject.h"
#include "pocketpy/common/strname.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct pk_CodeEmitContext{
CodeObject* co; // 1 CodeEmitContext <=> 1 CodeObject*
FuncDecl* func; // optional, weakref
int level;
int curr_iblock;
bool is_compiling_class;
c11_vector/*T=Expr* */ s_expr;
c11_vector/*T=StrName*/ global_names;
c11_smallmap_s2n co_consts_string_dedup_map;
} pk_CodeEmitContext;
typedef struct pk_Expr pk_Expr;
void pk_CodeEmitContext__ctor(pk_CodeEmitContext* self, CodeObject* co, FuncDecl* func, int level);
void pk_CodeEmitContext__dtor(pk_CodeEmitContext* self);
int pk_CodeEmitContext__get_loop(pk_CodeEmitContext* self);
CodeBlock* pk_CodeEmitContext__enter_block(pk_CodeEmitContext* self, CodeBlockType type);
void pk_CodeEmitContext__exit_block(pk_CodeEmitContext* self);
int pk_CodeEmitContext__emit_(pk_CodeEmitContext* self, Opcode opcode, uint16_t arg, int line);
int pk_CodeEmitContext__emit_virtual(pk_CodeEmitContext* self, Opcode opcode, uint16_t arg, int line);
void pk_CodeEmitContext__revert_last_emit_(pk_CodeEmitContext* self);
int pk_CodeEmitContext__emit_int(pk_CodeEmitContext* self, int64_t value, int line);
void pk_CodeEmitContext__patch_jump(pk_CodeEmitContext* self, int index);
bool pk_CodeEmitContext__add_label(pk_CodeEmitContext* self, StrName name);
int pk_CodeEmitContext__add_varname(pk_CodeEmitContext* self, StrName name);
int pk_CodeEmitContext__add_const(pk_CodeEmitContext* self, py_Ref);
int pk_CodeEmitContext__add_const_string(pk_CodeEmitContext* self, c11_string);
void pk_CodeEmitContext__emit_store_name(pk_CodeEmitContext* self, NameScope scope, StrName name, int line);
void pk_CodeEmitContext__try_merge_for_iter_store(pk_CodeEmitContext* self, int);
// emit top -> pop -> delete
void pk_CodeEmitContext__s_emit_top(pk_CodeEmitContext*);
// push
void pk_CodeEmitContext__s_push(pk_CodeEmitContext*, pk_Expr*);
// top
pk_Expr* pk_CodeEmitContext__s_top(pk_CodeEmitContext*);
// size
int pk_CodeEmitContext__s_size(pk_CodeEmitContext*);
// pop -> delete
void pk_CodeEmitContext__s_pop(pk_CodeEmitContext*);
// pop move
pk_Expr* pk_CodeEmitContext__s_popx(pk_CodeEmitContext*);
// clean
void pk_CodeEmitContext__s_clean(pk_CodeEmitContext*);
// emit decorators
void pk_CodeEmitContext__s_emit_decorators(pk_CodeEmitContext*, int count);
#ifdef __cplusplus
}
#endif

View File

@ -3,6 +3,7 @@
#include <stdbool.h> #include <stdbool.h>
#include "pocketpy/common/memorypool.h" #include "pocketpy/common/memorypool.h"
#include "pocketpy/compiler/lexer.h" #include "pocketpy/compiler/lexer.h"
#include "pocketpy/common/strname.h"
#include "pocketpy/objects/codeobject.h" #include "pocketpy/objects/codeobject.h"
#ifdef __cplusplus #ifdef __cplusplus
@ -15,14 +16,14 @@ typedef struct pk_CodeEmitContext pk_CodeEmitContext;
typedef struct pk_ExprVt{ typedef struct pk_ExprVt{
void (*dtor)(pk_Expr*); void (*dtor)(pk_Expr*);
/* reflections */ /* reflections */
bool (*is_literal)(const pk_Expr*); bool is_literal;
bool (*is_json_object)(const pk_Expr*); bool is_json_object;
bool (*is_attrib)(const pk_Expr*); bool is_name;
bool (*is_subscr)(const pk_Expr*); bool is_tuple;
bool is_attrib;
bool is_subscr;
bool (*is_compare)(const pk_Expr*); bool (*is_compare)(const pk_Expr*);
int (*star_level)(const pk_Expr*); int (*star_level)(const pk_Expr*);
bool (*is_tuple)(const pk_Expr*);
bool (*is_name)(const pk_Expr*);
/* emit */ /* emit */
void (*emit_)(pk_Expr*, pk_CodeEmitContext*); void (*emit_)(pk_Expr*, pk_CodeEmitContext*);
bool (*emit_del)(pk_Expr*, pk_CodeEmitContext*); bool (*emit_del)(pk_Expr*, pk_CodeEmitContext*);
@ -31,32 +32,70 @@ typedef struct pk_ExprVt{
bool (*emit_store_inplace)(pk_Expr*, pk_CodeEmitContext*); bool (*emit_store_inplace)(pk_Expr*, pk_CodeEmitContext*);
} pk_ExprVt; } pk_ExprVt;
typedef struct pk_Expr{ #define COMMON_HEADER \
pk_ExprVt* vt; pk_ExprVt* vt; \
int line; int line;
typedef struct pk_Expr{
COMMON_HEADER
} pk_Expr; } pk_Expr;
void pk_ExprVt__ctor(pk_ExprVt* vt); void pk_ExprVt__ctor(pk_ExprVt* vt);
void pk_Expr__emit_(pk_Expr* self, pk_CodeEmitContext* ctx);
bool pk_Expr__emit_del(pk_Expr* self, pk_CodeEmitContext* ctx);
bool pk_Expr__emit_store(pk_Expr* self, pk_CodeEmitContext* ctx);
void pk_Expr__emit_inplace(pk_Expr* self, pk_CodeEmitContext* ctx);
bool pk_Expr__emit_store_inplace(pk_Expr* self, pk_CodeEmitContext* ctx);
void pk_Expr__delete(pk_Expr* self); void pk_Expr__delete(pk_Expr* self);
typedef struct pk_CodeEmitContext{ void pk_Expr__initialize();
CodeObject* co; // 1 CodeEmitContext <=> 1 CodeObject* #define pk_Expr__finalize() // do nothing
FuncDecl* func; // optional, weakref
int level;
int curr_iblock;
bool is_compiling_class;
c11_vector/*T=Expr* */ s_expr;
c11_vector/*T=StrName*/ global_names;
c11_smallmap_s2n co_consts_string_dedup_map;
} pk_CodeEmitContext;
void pk_CodeEmitContext__ctor(pk_CodeEmitContext* self, CodeObject* co, FuncDecl* func, int level); typedef struct pk_NameExpr{
void pk_CodeEmitContext__dtor(pk_CodeEmitContext* self); COMMON_HEADER
StrName name;
NameScope scope;
} pk_NameExpr;
typedef struct pk_StarredExpr{
COMMON_HEADER
pk_Expr* child;
int level;
} pk_StarredExpr;
// InvertExpr, NotExpr, AndExpr, OrExpr, NegatedExpr
// NOTE: NegatedExpr always contains a non-const child. Should not generate -1 or -0.1
typedef struct pk_UnaryExpr{
COMMON_HEADER
pk_Expr* child;
Opcode opcode;
} pk_UnaryExpr;
// LongExpr, BytesExpr
typedef struct pk_RawStringExpr{
COMMON_HEADER
c11_string value;
Opcode opcode;
} pk_RawStringExpr;
typedef struct pk_ImagExpr{
COMMON_HEADER
double value;
} pk_ImagExpr;
typedef struct pk_LiteralExpr{
COMMON_HEADER
const TokenValue* value;
} pk_LiteralExpr;
typedef struct pk_SliceExpr{
COMMON_HEADER
pk_Expr* start;
pk_Expr* stop;
pk_Expr* step;
} pk_SliceExpr;
// ListExpr, DictExpr, SetExpr, TupleExpr
typedef struct pk_SequenceExpr{
COMMON_HEADER
c11_array/*T=Expr* */ items;
Opcode opcode;
} pk_SequenceExpr;
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -77,10 +77,10 @@ Error* Compiler::pop_context() noexcept{
FuncDecl* func = contexts.back().func; FuncDecl* func = contexts.back().func;
if(func) { if(func) {
// check generator // check generator
c11_vector__foreach(Bytecode, &func->code->codes, bc) { c11__foreach(Bytecode, &func->code->codes, bc) {
if(bc->op == OP_YIELD_VALUE || bc->op == OP_FOR_ITER_YIELD_VALUE) { if(bc->op == OP_YIELD_VALUE || bc->op == OP_FOR_ITER_YIELD_VALUE) {
func->type = FuncType_GENERATOR; func->type = FuncType_GENERATOR;
c11_vector__foreach(Bytecode, &func->code->codes, bc) { c11__foreach(Bytecode, &func->code->codes, bc) {
if(bc->op == OP_RETURN_VALUE && bc->arg == BC_NOARG) { if(bc->op == OP_RETURN_VALUE && bc->arg == BC_NOARG) {
return SyntaxError("'return' with argument inside generator function"); return SyntaxError("'return' with argument inside generator function");
} }
@ -1119,11 +1119,11 @@ Error* Compiler::_compile_f_args(FuncDecl* decl, bool enable_type_hints) noexcep
// check duplicate argument name // check duplicate argument name
uint16_t tmp_name; uint16_t tmp_name;
c11_vector__foreach(int, &decl->args, j) { c11__foreach(int, &decl->args, j) {
tmp_name = c11__getitem(uint16_t, &decl->args, *j); tmp_name = c11__getitem(uint16_t, &decl->args, *j);
if(tmp_name == name.index) return SyntaxError("duplicate argument name"); if(tmp_name == name.index) return SyntaxError("duplicate argument name");
} }
c11_vector__foreach(FuncDeclKwArg, &decl->kwargs, kv) { c11__foreach(FuncDeclKwArg, &decl->kwargs, kv) {
tmp_name = c11__getitem(uint16_t, &decl->code->varnames, kv->index); tmp_name = c11__getitem(uint16_t, &decl->code->varnames, kv->index);
if(tmp_name == name.index) return SyntaxError("duplicate argument name"); if(tmp_name == name.index) return SyntaxError("duplicate argument name");
} }

58
src/compiler/context.c Normal file
View File

@ -0,0 +1,58 @@
#include "pocketpy/compiler/context.h"
#include "pocketpy/compiler/expr.h"
void pk_CodeEmitContext__ctor(pk_CodeEmitContext* self, CodeObject* co, FuncDecl* func, int level){
self->co = co;
self->func = func;
self->level = level;
self->curr_iblock = 0;
self->is_compiling_class = false;
c11_vector__ctor(&self->s_expr, sizeof(pk_Expr*));
c11_vector__ctor(&self->global_names, sizeof(StrName));
c11_smallmap_s2n__ctor(&self->co_consts_string_dedup_map);
}
void pk_CodeEmitContext__dtor(pk_CodeEmitContext* self){
c11_vector__dtor(&self->s_expr);
c11_vector__dtor(&self->global_names);
c11_smallmap_s2n__dtor(&self->co_consts_string_dedup_map);
}
// emit top -> pop -> delete
void pk_CodeEmitContext__s_emit_top(pk_CodeEmitContext* self) {
pk_Expr* top = c11_vector__back(pk_Expr*, &self->s_expr);
top->vt->emit_(top, self);
c11_vector__pop(&self->s_expr);
pk_Expr__delete(top);
}
// push
void pk_CodeEmitContext__s_push(pk_CodeEmitContext* self, pk_Expr* expr) {
c11_vector__push(pk_Expr*, &self->s_expr, expr);
}
// top
pk_Expr* pk_CodeEmitContext__s_top(pk_CodeEmitContext* self){
return c11_vector__back(pk_Expr*, &self->s_expr);
}
// size
int pk_CodeEmitContext__s_size(pk_CodeEmitContext* self) {
return self->s_expr.count;
}
// pop -> delete
void pk_CodeEmitContext__s_pop(pk_CodeEmitContext* self){
pk_Expr__delete(c11_vector__back(pk_Expr*, &self->s_expr));
c11_vector__pop(&self->s_expr);
}
// pop move
pk_Expr* pk_CodeEmitContext__s_popx(pk_CodeEmitContext* self){
pk_Expr* e = c11_vector__back(pk_Expr*, &self->s_expr);
c11_vector__pop(&self->s_expr);
return e;
}
// clean
void pk_CodeEmitContext__s_clean(pk_CodeEmitContext* self){
c11_smallmap_s2n__dtor(&self->co_consts_string_dedup_map); // ??
for(int i=0; i<self->s_expr.count; i++){
pk_Expr__delete(c11__getitem(pk_Expr*, &self->s_expr, i));
}
c11_vector__clear(&self->s_expr);
}

View File

@ -1,4 +1,5 @@
#include "pocketpy/compiler/expr.h" #include "pocketpy/compiler/expr.h"
#include "pocketpy/compiler/context.h"
#include "pocketpy/common/memorypool.h" #include "pocketpy/common/memorypool.h"
#include "pocketpy/common/strname.h" #include "pocketpy/common/strname.h"
@ -6,51 +7,20 @@ static bool default_false(const pk_Expr* e) { return false; }
static int default_zero(const pk_Expr* e) { return 0; } static int default_zero(const pk_Expr* e) { return 0; }
static void default_dtor(pk_Expr* e) {} static void default_dtor(pk_Expr* e) {}
static bool default_emit_del(pk_Expr* e, pk_CodeEmitContext* ctx) { return false; }
static bool default_emit_store(pk_Expr* e, pk_CodeEmitContext* ctx) { return false; }
static void default_emit_inplace(pk_Expr* e, pk_CodeEmitContext* ctx) { e->vt->emit_(e, ctx); }
static bool default_emit_store_inplace(pk_Expr* e, pk_CodeEmitContext* ctx) { return e->vt->emit_store(e, ctx); }
void pk_ExprVt__ctor(pk_ExprVt* vt){ void pk_ExprVt__ctor(pk_ExprVt* vt){
vt->dtor = default_dtor; vt->dtor = default_dtor;
vt->is_literal = default_false;
vt->is_json_object = default_false;
vt->is_attrib = default_false;
vt->is_subscr = default_false;
vt->is_compare = default_false;
vt->star_level = default_zero; vt->star_level = default_zero;
vt->is_tuple = default_false; vt->is_compare = default_false;
vt->is_name = default_false;
vt->emit_ = NULL; // must be set vt->emit_ = NULL; // must be set
vt->emit_del = NULL; vt->emit_del = default_emit_del;
vt->emit_store = NULL; vt->emit_store = default_emit_store;
vt->emit_inplace = NULL; vt->emit_inplace = default_emit_inplace;
vt->emit_store_inplace = NULL; vt->emit_store_inplace = default_emit_store_inplace;
}
void pk_Expr__emit_(pk_Expr* self, pk_CodeEmitContext* ctx){
assert(self->vt->emit_);
self->vt->emit_(self, ctx);
}
bool pk_Expr__emit_del(pk_Expr* self, pk_CodeEmitContext* ctx){
if(!self->vt->emit_del) return false;
return self->vt->emit_del(self, ctx);
}
bool pk_Expr__emit_store(pk_Expr* self, pk_CodeEmitContext* ctx){
if(!self->vt->emit_store) return false;
return self->vt->emit_store(self, ctx);
}
void pk_Expr__emit_inplace(pk_Expr* self, pk_CodeEmitContext* ctx){
if(!self->vt->emit_inplace){
pk_Expr__emit_(self, ctx);
return;
}
self->vt->emit_inplace(self, ctx);
}
bool pk_Expr__emit_store_inplace(pk_Expr* self, pk_CodeEmitContext* ctx){
if(!self->vt->emit_store_inplace){
return pk_Expr__emit_store(self, ctx);
}
return self->vt->emit_store_inplace(self, ctx);
} }
void pk_Expr__delete(pk_Expr* self){ void pk_Expr__delete(pk_Expr* self){
@ -59,21 +29,365 @@ void pk_Expr__delete(pk_Expr* self){
PoolExpr_dealloc(self); PoolExpr_dealloc(self);
} }
/* CodeEmitContext */ /* Implementations */
#define static_assert_expr_size(T) static_assert(sizeof(T) <= kPoolExprBlockSize, "size is too large")
void pk_CodeEmitContext__ctor(pk_CodeEmitContext* self, CodeObject* co, FuncDecl* func, int level){ static pk_ExprVt NameExprVt;
self->co = co;
self->func = func; void pk_NameExpr__emit_(pk_Expr* self_, pk_CodeEmitContext* ctx) {
self->level = level; pk_NameExpr* self = (pk_NameExpr*)self_;
self->curr_iblock = 0; int index = c11_smallmap_n2i__get(&ctx->co->varnames_inv, self->name, -1);
self->is_compiling_class = false; if(self->scope == NAME_LOCAL && index >= 0) {
c11_vector__ctor(&self->s_expr, sizeof(pk_Expr*)); pk_CodeEmitContext__emit_(ctx, OP_LOAD_FAST, index, self->line);
c11_vector__ctor(&self->global_names, sizeof(StrName)); } else {
c11_smallmap_s2n__ctor(&self->co_consts_string_dedup_map); Opcode op = ctx->level <= 1 ? OP_LOAD_GLOBAL : OP_LOAD_NONLOCAL;
if(ctx->is_compiling_class && self->scope == NAME_GLOBAL) {
// if we are compiling a class, we should use OP_LOAD_ATTR_GLOBAL instead of OP_LOAD_GLOBAL
// this supports @property.setter
op = OP_LOAD_CLASS_GLOBAL;
// exec()/eval() won't work with OP_LOAD_ATTR_GLOBAL in class body
} else {
// we cannot determine the scope when calling exec()/eval()
if(self->scope == NAME_GLOBAL_UNKNOWN) op = OP_LOAD_NAME;
}
pk_CodeEmitContext__emit_(ctx, op, self->name, self->line);
}
} }
void pk_CodeEmitContext__dtor(pk_CodeEmitContext* self){ bool pk_NameExpr__emit_del(pk_Expr* self_, pk_CodeEmitContext* ctx) {
c11_vector__dtor(&self->s_expr); pk_NameExpr* self = (pk_NameExpr*)self_;
c11_vector__dtor(&self->global_names); switch(self->scope) {
c11_smallmap_s2n__dtor(&self->co_consts_string_dedup_map); case NAME_LOCAL:
} pk_CodeEmitContext__emit_(
ctx, OP_DELETE_FAST,
pk_CodeEmitContext__add_varname(ctx, self->name),
self->line
);
break;
case NAME_GLOBAL:
pk_CodeEmitContext__emit_(ctx, OP_DELETE_GLOBAL, self->name, self->line);
break;
case NAME_GLOBAL_UNKNOWN:
pk_CodeEmitContext__emit_(ctx, OP_DELETE_NAME, self->name, self->line);
break;
default: PK_UNREACHABLE();
}
return true;
}
bool pk_NameExpr__emit_store(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_NameExpr* self = (pk_NameExpr*)self_;
if(ctx->is_compiling_class) {
pk_CodeEmitContext__emit_(ctx, OP_STORE_CLASS_ATTR, self->name, self->line);
return true;
}
pk_CodeEmitContext__emit_store_name(ctx, self->scope, self->name, self->line);
return true;
}
pk_NameExpr* pk_NameExpr__new(StrName name, NameScope scope){
static_assert_expr_size(pk_NameExpr);
pk_NameExpr* self = PoolExpr_alloc();
self->vt = &NameExprVt;
self->line = -1;
self->name = name;
self->scope = scope;
return self;
}
static pk_ExprVt StarredExprVt;
int pk_ExprVt__star_level(const pk_Expr* self) {
return ((pk_StarredExpr*)self)->level;
}
void pk_StarredExpr__emit_(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_StarredExpr* self = (pk_StarredExpr*)self_;
self->child->vt->emit_(self->child, ctx);
pk_CodeEmitContext__emit_(ctx, OP_UNARY_STAR, self->level, self->line);
}
bool pk_StarredExpr__emit_store(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_StarredExpr* self = (pk_StarredExpr*)self_;
if(self->level != 1) return false;
// simply proxy to child
return self->child->vt->emit_store(self->child, ctx);
}
pk_StarredExpr* pk_StarredExpr__new(pk_Expr* child, int level){
static_assert_expr_size(pk_StarredExpr);
pk_StarredExpr* self = PoolExpr_alloc();
self->vt = &StarredExprVt;
self->line = -1;
self->child = child;
self->level = level;
return self;
}
static pk_ExprVt UnaryExprVt;
void pk_UnaryExpr__dtor(pk_Expr* self_){
pk_UnaryExpr* self = (pk_UnaryExpr*)self_;
pk_Expr__delete(self->child);
}
static void pk_UnaryExpr__emit_(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_UnaryExpr* self = (pk_UnaryExpr*)self_;
self->child->vt->emit_(self->child, ctx);
pk_CodeEmitContext__emit_(ctx, self->opcode, BC_NOARG, self->line);
}
pk_UnaryExpr* pk_UnaryExpr__new(pk_Expr* child, Opcode opcode){
static_assert_expr_size(pk_UnaryExpr);
pk_UnaryExpr* self = PoolExpr_alloc();
self->vt = &UnaryExprVt;
self->line = -1;
self->child = child;
self->opcode = opcode;
return self;
}
static pk_ExprVt RawStringExprVt;
void pk_RawStringExpr__emit_(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_RawStringExpr* self = (pk_RawStringExpr*)self_;
int index = pk_CodeEmitContext__add_const_string(ctx, self->value);
pk_CodeEmitContext__emit_(ctx, OP_LOAD_CONST, index, self->line);
pk_CodeEmitContext__emit_(ctx, self->opcode, BC_NOARG, self->line);
}
pk_RawStringExpr* pk_RawStringExpr__new(c11_string value, Opcode opcode){
static_assert_expr_size(pk_RawStringExpr);
pk_RawStringExpr* self = PoolExpr_alloc();
self->vt = &RawStringExprVt;
self->line = -1;
self->value = value;
self->opcode = opcode;
return self;
}
static pk_ExprVt ImagExprVt;
void pk_ImagExpr__emit_(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_ImagExpr* self = (pk_ImagExpr*)self_;
PyVar value;
py_newfloat(&value, self->value);
int index = pk_CodeEmitContext__add_const(ctx, &value);
pk_CodeEmitContext__emit_(ctx, OP_LOAD_CONST, index, self->line);
pk_CodeEmitContext__emit_(ctx, OP_BUILD_IMAG, BC_NOARG, self->line);
}
pk_ImagExpr* pk_ImagExpr__new(double value){
static_assert_expr_size(pk_ImagExpr);
pk_ImagExpr* self = PoolExpr_alloc();
self->vt = &ImagExprVt;
self->line = -1;
self->value = value;
return self;
}
static pk_ExprVt LiteralExprVt;
void pk_LiteralExpr__emit_(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_LiteralExpr* self = (pk_LiteralExpr*)self_;
switch(self->value->index){
case TokenValue_I64: {
int64_t val = self->value->_i64;
pk_CodeEmitContext__emit_int(ctx, val, self->line);
break;
}
case TokenValue_F64: {
PyVar value;
py_newfloat(&value, self->value->_f64);
int index = pk_CodeEmitContext__add_const(ctx, &value);
pk_CodeEmitContext__emit_(ctx, OP_LOAD_CONST, index, self->line);
break;
}
case TokenValue_STR: {
c11_string sv = py_Str__sv(&self->value->_str);
int index = pk_CodeEmitContext__add_const_string(ctx, sv);
pk_CodeEmitContext__emit_(ctx, OP_LOAD_CONST, index, self->line);
break;
}
default: PK_UNREACHABLE();
}
}
pk_LiteralExpr* pk_LiteralExpr__new(const TokenValue* value){
static_assert_expr_size(pk_LiteralExpr);
pk_LiteralExpr* self = PoolExpr_alloc();
self->vt = &LiteralExprVt;
self->line = -1;
self->value = value;
return self;
}
static pk_ExprVt SliceExprVt;
void pk_SliceExpr__dtor(pk_Expr* self_){
pk_SliceExpr* self = (pk_SliceExpr*)self_;
pk_Expr__delete(self->start);
pk_Expr__delete(self->stop);
pk_Expr__delete(self->step);
}
void pk_SliceExpr__emit_(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_SliceExpr* self = (pk_SliceExpr*)self_;
if(self->start) self->start->vt->emit_(self->start, ctx);
else pk_CodeEmitContext__emit_(ctx, OP_LOAD_NONE, BC_NOARG, self->line);
if(self->stop) self->stop->vt->emit_(self->stop, ctx);
else pk_CodeEmitContext__emit_(ctx, OP_LOAD_NONE, BC_NOARG, self->line);
if(self->step) self->step->vt->emit_(self->step, ctx);
else pk_CodeEmitContext__emit_(ctx, OP_LOAD_NONE, BC_NOARG, self->line);
pk_CodeEmitContext__emit_(ctx, OP_BUILD_SLICE, BC_NOARG, self->line);
}
pk_SliceExpr* pk_SliceExpr__new(){
static_assert_expr_size(pk_SliceExpr);
pk_SliceExpr* self = PoolExpr_alloc();
self->vt = &SliceExprVt;
self->line = -1;
self->start = NULL;
self->stop = NULL;
self->step = NULL;
return self;
}
static pk_ExprVt ListExprVt;
static pk_ExprVt DictExprVt;
static pk_ExprVt SetExprVt;
static pk_ExprVt TupleExprVt;
pk_SequenceExpr* pk_SequenceExpr__new(pk_ExprVt* vt, int count, Opcode opcode){
static_assert_expr_size(pk_SequenceExpr);
pk_SequenceExpr* self = PoolExpr_alloc();
self->vt = vt;
self->line = -1;
self->opcode = opcode;
c11_array__ctor(&self->items, count, sizeof(pk_Expr*));
return self;
}
static void pk_SequenceExpr__emit_(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_SequenceExpr* self = (pk_SequenceExpr*)self_;
for(int i=0; i<self->items.count; i++){
pk_Expr* item = c11__getitem(pk_Expr*, &self->items, i);
item->vt->emit_(item, ctx);
}
pk_CodeEmitContext__emit_(ctx, self->opcode, self->items.count, self->line);
}
void pk_SequenceExpr__dtor(pk_Expr* self_){
pk_SequenceExpr* self = (pk_SequenceExpr*)self_;
c11__foreach(pk_Expr*, &self->items, e){
pk_Expr__delete(*e);
}
c11_array__dtor(&self->items);
}
bool pk_TupleExpr__emit_store(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_SequenceExpr* self = (pk_SequenceExpr*)self_;
// TOS is an iterable
// items may contain StarredExpr, we should check it
int starred_i = -1;
for(int i = 0; i < self->items.count; i++) {
pk_Expr* e = c11__getitem(pk_Expr*, &self->items, i);
if(e->vt->star_level(e) == 0) continue;
if(starred_i == -1) starred_i = i;
else return false; // multiple StarredExpr not allowed
}
if(starred_i == -1) {
Bytecode* prev = c11__at(Bytecode, &ctx->co->codes, ctx->co->codes.count - 1);
if(prev->op == OP_BUILD_TUPLE && prev->arg == self->items.count) {
// build tuple and unpack it is meaningless
pk_CodeEmitContext__revert_last_emit_(ctx);
} else {
if(prev->op == OP_FOR_ITER) {
prev->op = OP_FOR_ITER_UNPACK;
prev->arg = self->items.count;
} else {
pk_CodeEmitContext__emit_(ctx, OP_UNPACK_SEQUENCE, self->items.count, self->line);
}
}
} else {
// starred assignment target must be in a tuple
if(self->items.count == 1) return false;
// starred assignment target must be the last one (differ from cpython)
if(starred_i != self->items.count - 1) return false;
// a,*b = [1,2,3]
// stack is [1,2,3] -> [1,[2,3]]
pk_CodeEmitContext__emit_(ctx, OP_UNPACK_EX, self->items.count - 1, self->line);
}
// do reverse emit
for(int i = self->items.count - 1; i >= 0; i--) {
pk_Expr* e = c11__getitem(pk_Expr*, &self->items, i);
bool ok = e->vt->emit_store(e, ctx);
if(!ok) return false;
}
return true;
}
bool pk_TupleExpr__emit_del(pk_Expr* self_, pk_CodeEmitContext* ctx) {
pk_SequenceExpr* self = (pk_SequenceExpr*)self_;
c11__foreach(pk_Expr*, &self->items, e){
bool ok = (*e)->vt->emit_del(*e, ctx);
if(!ok) return false;
}
return true;
}
/////////////////////////////////////////////
void pk_Expr__initialize(){
pk_ExprVt__ctor(&NameExprVt);
pk_ExprVt* vt = &NameExprVt;
vt->emit_ = pk_NameExpr__emit_;
vt->emit_del = pk_NameExpr__emit_del;
vt->emit_store = pk_NameExpr__emit_store;
pk_ExprVt__ctor(&StarredExprVt);
vt = &StarredExprVt;
vt->dtor = pk_UnaryExpr__dtor;
vt->star_level = pk_ExprVt__star_level;
vt->emit_ = pk_StarredExpr__emit_;
vt->emit_store = pk_StarredExpr__emit_store;
pk_ExprVt__ctor(&UnaryExprVt);
vt = &UnaryExprVt;
vt->dtor = pk_UnaryExpr__dtor;
vt->emit_ = pk_UnaryExpr__emit_;
pk_ExprVt__ctor(&RawStringExprVt);
vt = &RawStringExprVt;
vt->emit_ = pk_RawStringExpr__emit_;
pk_ExprVt__ctor(&ImagExprVt);
vt = &ImagExprVt;
vt->emit_ = pk_ImagExpr__emit_;
pk_ExprVt__ctor(&LiteralExprVt);
vt = &LiteralExprVt;
vt->emit_ = pk_LiteralExpr__emit_;
vt->is_literal = true;
vt->is_json_object = true;
pk_ExprVt__ctor(&SliceExprVt);
vt = &SliceExprVt;
vt->dtor = pk_SliceExpr__dtor;
vt->emit_ = pk_SliceExpr__emit_;
pk_ExprVt* seqVt[] = {&ListExprVt, &DictExprVt, &SetExprVt, &TupleExprVt};
for(int i=0; i<4; i++){
pk_ExprVt__ctor(seqVt[i]);
vt = seqVt[i];
vt->dtor = pk_SequenceExpr__dtor;
vt->emit_ = pk_SequenceExpr__emit_;
}
ListExprVt.is_json_object = true;
DictExprVt.is_json_object = true;
TupleExprVt.is_tuple = true;
TupleExprVt.emit_store = pk_TupleExpr__emit_store;
TupleExprVt.emit_del = pk_TupleExpr__emit_del;
}

View File

@ -71,8 +71,8 @@ int CodeEmitContext::emit_(Opcode opcode, uint16_t arg, int line, bool is_virtua
} }
void CodeEmitContext::revert_last_emit_() noexcept{ void CodeEmitContext::revert_last_emit_() noexcept{
c11_vector__pop(Bytecode, &co->codes); c11_vector__pop(&co->codes);
c11_vector__pop(BytecodeEx, &co->codes_ex); c11_vector__pop(&co->codes_ex);
} }
void CodeEmitContext::try_merge_for_iter_store(int i) noexcept{ void CodeEmitContext::try_merge_for_iter_store(int i) noexcept{

View File

@ -168,7 +168,7 @@ static bool eat_indentation(pk_Lexer* self){
c11_vector__push(Token, &self->nexts, t); c11_vector__push(Token, &self->nexts, t);
} else if(spaces < indents_back) { } else if(spaces < indents_back) {
do { do {
c11_vector__pop(int, &self->indents); c11_vector__pop(&self->indents);
Token t = {TK_DEDENT, self->token_start, 0, self->current_line, self->brackets_level, EmptyTokenValue}; Token t = {TK_DEDENT, self->token_start, 0, self->current_line, self->brackets_level, EmptyTokenValue};
c11_vector__push(Token, &self->nexts, t); c11_vector__push(Token, &self->nexts, t);
indents_back = c11_vector__back(int, &self->indents); indents_back = c11_vector__back(int, &self->indents);
@ -543,7 +543,7 @@ static Error* lex_one_token(pk_Lexer* self, bool* eof){
self->token_start = self->curr_char; self->token_start = self->curr_char;
while(self->indents.count > 1) { while(self->indents.count > 1) {
c11_vector__pop(int, &self->indents); c11_vector__pop(&self->indents);
add_token(self, TK_DEDENT); add_token(self, TK_DEDENT);
return NULL; return NULL;
} }
@ -763,7 +763,7 @@ Error* pk_Lexer__process_and_dump(pk_SourceData_ src, py_Str* out) {
c11_smallmap_s2n token_indices; c11_smallmap_s2n token_indices;
c11_smallmap_s2n__ctor(&token_indices); c11_smallmap_s2n__ctor(&token_indices);
c11_vector__foreach(Token, &nexts, token) { c11__foreach(Token, &nexts, token) {
if(is_raw_string_used(token->type)) { if(is_raw_string_used(token->type)) {
c11_string token_sv = {token->start, token->length}; c11_string token_sv = {token->start, token->length};
if(!c11_smallmap_s2n__contains(&token_indices, token_sv)) { if(!c11_smallmap_s2n__contains(&token_indices, token_sv)) {

View File

@ -18,7 +18,7 @@ PyVar* FastLocals__try_get_by_name(PyVar* locals, const CodeObject* co, py_Name
pk_NameDict* FastLocals__to_namedict(PyVar* locals, const CodeObject* co) { pk_NameDict* FastLocals__to_namedict(PyVar* locals, const CodeObject* co) {
pk_NameDict* dict = pk_NameDict__new(); pk_NameDict* dict = pk_NameDict__new();
c11_vector__foreach(c11_smallmap_n2i_KV, &co->varnames_inv, entry) { c11__foreach(c11_smallmap_n2i_KV, &co->varnames_inv, entry) {
PyVar value = locals[entry->value]; PyVar value = locals[entry->value];
if(!py_isnull(&value)){ if(!py_isnull(&value)){
pk_NameDict__set(dict, entry->key, value); pk_NameDict__set(dict, entry->key, value);