stage1 大量重构

This commit is contained in:
zzy committed 2026-09-16 20:09:24 +08:00
1 parent e4347cc3ea
commit 2a84b61e3d
18 files changed
+1819 -1342

No files matched your search

+3
View File
@@ -24,11 +24,14 @@ static const char *test_srcs[] = {"stage0/test_spl_vm.c", VM_SRCS};
static const char *splc0_srcs[] = { static const char *splc0_srcs[] = {
"stage1/splc0.c", "stage1/splc0.c",
"stage1/spl_diag.c", "stage1/spl_diag.c",
"stage1/spl_tok.c",
"stage1/spl_lexer.c", "stage1/spl_lexer.c",
"stage1/spl_ast.c", "stage1/spl_ast.c",
"stage1/spl_dumptree.c", "stage1/spl_dumptree.c",
"stage1/spl_type.c", "stage1/spl_type.c",
"stage1/spl_lang_type.c",
"stage1/spl_attr.c", "stage1/spl_attr.c",
"stage1/spl_scope.c",
"stage1/spl_sema.c", "stage1/spl_sema.c",
"stage1/spl_intrin.c", "stage1/spl_intrin.c",
"stage1/spl_ir.c", "stage1/spl_ir.c",
+3 -3
View File
@@ -555,8 +555,8 @@ void spl_vm_init_ex(spl_vm_t *vm, int stack_size, int call_depth) {
#endif #endif
if (!vm) if (!vm)
return; return;
vm->config.max_stack_depth = stack_size > 0 ? stack_size : 1024 * 1024 * 8; vm->config.max_stack_depth = stack_size > 0 ? stack_size : 1024 * 1024 * 64;
vm->config.max_call_depth = call_depth > 0 ? call_depth : 128; vm->config.max_call_depth = call_depth > 0 ? call_depth : 65536;
vec_init(vm->stacks); vec_init(vm->stacks);
vec_realloc(vm->stacks, (usize)vm->config.max_stack_depth); vec_realloc(vm->stacks, (usize)vm->config.max_stack_depth);
@@ -699,7 +699,7 @@ void spl_vm_set_debug(spl_vm_t *vm, int enabled) {
static inline int spl_vm_call(spl_vm_t *vm, spl_vm_val_t addr, spl_vm_val_t nargs) { static inline int spl_vm_call(spl_vm_t *vm, spl_vm_val_t addr, spl_vm_val_t nargs) {
if (vm->cp >= vm->config.max_call_depth) if (vm->cp >= vm->config.max_call_depth)
VM_ERROR("CALLI: call stack overflow"); VM_ERROR("call depth exceeded");
// spl_vm_stackdump(vm, vm->sp); // spl_vm_stackdump(vm, vm->sp);
PUSH(SPL_STACK_CANARY); PUSH(SPL_STACK_CANARY);
/* Shift args right by 1 to create gap for canary at fp-1 */ /* Shift args right by 1 to create gap for canary at fp-1 */
+48 -4
View File
@@ -77,13 +77,38 @@ static spl_dbg_node_t tok_to_dbg(const spl_tok_t *t) {
return d; return d;
} }
/* parser 层的 fatal 发射。diag 为 NULL 时静默。 /* 渲染 token:<KIND> `lexeme` at line:col。
* 调用者必须紧跟 return / break,因为 diag_fatal 不终止流程。 */ 传入 NULL 表示 parser 走到了输入流末尾。 */
static void tok_desc(const spl_tok_t *t, char *buf, usize cap) {
if (!t) {
snprintf(buf, cap, "<no token>");
return;
}
if (t->type == TOK_EOF) {
snprintf(buf, cap, "EOF");
return;
}
const char *kind = spl_tok_type_name(t->type);
if (t->type == TOK_ENDLINE) {
snprintf(buf, cap, "ENDLINE at %zu:%zu", t->line, t->col);
return;
}
if (!t->lexeme || t->len == 0) {
snprintf(buf, cap, "%s at %zu:%zu", kind, t->line, t->col);
return;
}
int n = (int)(t->len > 32 ? 32 : t->len);
snprintf(buf, cap, "%s `%.*s` at %s:%zu:%zu", kind, n, t->lexeme, t->fname, t->line, t->col);
}
#define PARSE_FATAL(p, kind, tok, ...) \ #define PARSE_FATAL(p, kind, tok, ...) \
do { \ do { \
(p)->failed = 1; \
if ((p)->diag) { \ if ((p)->diag) { \
char _tb[80]; \
tok_desc((tok), _tb, sizeof _tb); \
spl_dbg_node_t _pd = tok_to_dbg(tok); \ spl_dbg_node_t _pd = tok_to_dbg(tok); \
spl_diag_fatal((p)->diag, (kind), &_pd, __VA_ARGS__); \ spl_diag_fatal((p)->diag, (kind), &_pd, __VA_ARGS__ " (got %s)", _tb); \
} \ } \
} while (0) } while (0)
@@ -1058,7 +1083,26 @@ static spl_ast_node_ref_t parse_type_expr(parser_t *p) {
return ref; return ref;
} }
return parse_type_base(p); spl_ast_node_ref_t base = parse_type_base(p);
if (p->failed || !base)
return base;
while (peek(p) && peek(p)->type == TOK_DOT) {
const spl_tok_t *dot = peek(p);
advance(p);
const spl_tok_t *seg = peek(p);
if (!seg || seg->type != TOK_IDENT) {
PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, seg ? seg : dot,
"type: expected identifier after '.'");
return base;
}
advance(p);
spl_ast_node_ref_t sel = new_node(p, SPL_AST_EXPR_FIELD, dot);
node_at(p->ast, sel)->field.obj = base;
SET_STR_FIELD(p->ast, node_at(p->ast, sel)->field.field, seg);
base = sel;
}
return base;
} }
static spl_ast_node_ref_vec_t parse_expr_list(parser_t *p) { static spl_ast_node_ref_vec_t parse_expr_list(parser_t *p) {
+2 -1
View File
@@ -483,7 +483,7 @@ struct spl_ast_node {
typedef VEC(spl_ast_node_t) spl_ast_node_vec_t; typedef VEC(spl_ast_node_t) spl_ast_node_vec_t;
typedef VEC(char *) spl_ast_cstr_ref_vec_t; typedef VEC(char *) spl_ast_cstr_ref_vec_t;
typedef struct { typedef struct spl_ast {
spl_tok_vec_t input; spl_tok_vec_t input;
spl_ast_node_vec_t node_buckets; spl_ast_node_vec_t node_buckets;
spl_ast_cstr_ref_vec_t str_buckets; spl_ast_cstr_ref_vec_t str_buckets;
@@ -491,6 +491,7 @@ typedef struct {
spl_diag_t *diag; spl_diag_t *diag;
} spl_ast_t; } spl_ast_t;
typedef VEC(spl_ast_t *) spl_ast_ptr_vec_t;
void spl_ast_init(spl_ast_t *ast, const spl_tok_vec_t *tok_vec /*move*/); void spl_ast_init(spl_ast_t *ast, const spl_tok_vec_t *tok_vec /*move*/);
void spl_ast_drop(spl_ast_t *ast); void spl_ast_drop(spl_ast_t *ast);
+88 -73
View File
@@ -48,7 +48,7 @@ static spl_ir_node_ref_t ast2ir_intrin_field(spl_ast2ir_t *a, spl_ast_node_t *n,
static spl_ir_node_ref_t ast2ir_intrin_len(spl_ast2ir_t *a, spl_ast_node_t *n); static spl_ir_node_ref_t ast2ir_intrin_len(spl_ast2ir_t *a, spl_ast_node_t *n);
static spl_ir_node_ref_t emit_zero_value(spl_ast2ir_t *a, spl_type_id_t tid) { static spl_ir_node_ref_t emit_zero_value(spl_ast2ir_t *a, spl_type_id_t tid) {
spl_type_node_t *tn = spl_type_node(a->sema->type, tid); spl_type_node_t *tn = spl_type_node(&a->sema->type->ir, tid);
if (!tn) if (!tn)
return 0; return 0;
spl_type_node_kind_t tk = tn->kind; spl_type_node_kind_t tk = tn->kind;
@@ -142,12 +142,12 @@ static spl_ir_node_ref_t ast2ir_intrin_cast(spl_ast2ir_t *a, spl_ast_node_t *n,
spl_ir_node_ref_t v = emit_expr(a, vec_at(*args, 0)); spl_ir_node_ref_t v = emit_expr(a, vec_at(*args, 0));
if (!v) if (!v)
return 0; return 0;
spl_ast_node_t *src = spl_ast_node(a->sema->ast, vec_at(*args, 0)); spl_ast_node_t *src = spl_ast_node(a->ast, vec_at(*args, 0));
spl_type_id_t ft = node_ir(a, src); spl_type_id_t ft = node_ir(a, src);
spl_type_id_t tt = 0; spl_type_id_t tt = 0;
if (nargs >= 2) { if (nargs >= 2) {
spl_ast_node_t *targ = spl_ast_node(a->sema->ast, vec_at(*args, 1)); spl_ast_node_t *targ = spl_ast_node(a->ast, vec_at(*args, 1));
tt = node_ir(a, targ); tt = node_ir(a, targ);
} else { } else {
tt = node_ir(a, n); tt = node_ir(a, n);
@@ -161,11 +161,11 @@ static spl_ir_node_ref_t ast2ir_intrin_call(spl_ast2ir_t *a, spl_ast_node_t *n,
spl_ast_node_ref_vec_t *args) { spl_ast_node_ref_vec_t *args) {
switch (in) { switch (in) {
case SPL_INTRIN_SIZEOF: { case SPL_INTRIN_SIZEOF: {
spl_ast_node_t *arg = spl_ast_node(a->sema->ast, vec_at(*args, 0)); spl_ast_node_t *arg = spl_ast_node(a->ast, vec_at(*args, 0));
return spl_ir_builder_type_sizeof(a->ir, node_ir(a, arg)); return spl_ir_builder_type_sizeof(a->ir, node_ir(a, arg));
} }
case SPL_INTRIN_ALIGNOF: { case SPL_INTRIN_ALIGNOF: {
spl_ast_node_t *arg = spl_ast_node(a->sema->ast, vec_at(*args, 0)); spl_ast_node_t *arg = spl_ast_node(a->ast, vec_at(*args, 0));
return spl_ir_builder_type_alignof(a->ir, node_ir(a, arg)); return spl_ir_builder_type_alignof(a->ir, node_ir(a, arg));
} }
case SPL_INTRIN_ASSERT: { case SPL_INTRIN_ASSERT: {
@@ -183,7 +183,7 @@ static spl_ir_node_ref_t ast2ir_intrin_call(spl_ast2ir_t *a, spl_ast_node_t *n,
const char *fname = n->dbg.fname ? n->dbg.fname : "?"; const char *fname = n->dbg.fname ? n->dbg.fname : "?";
const char *user_msg = NULL; const char *user_msg = NULL;
if (vec_size(*args) == 2) { if (vec_size(*args) == 2) {
spl_ast_node_t *mn = spl_ast_node(a->sema->ast, vec_at(*args, 1)); spl_ast_node_t *mn = spl_ast_node(a->ast, vec_at(*args, 1));
if (mn && mn->kind == SPL_AST_EXPR_STRING_LIT && mn->string_lit.data) if (mn && mn->kind == SPL_AST_EXPR_STRING_LIT && mn->string_lit.data)
user_msg = mn->string_lit.data; user_msg = mn->string_lit.data;
} }
@@ -241,7 +241,7 @@ static spl_ir_node_ref_t ast2ir_intrin_field(spl_ast2ir_t *a, spl_ast_node_t *n,
} }
static spl_ir_node_ref_t ast2ir_intrin_len(spl_ast2ir_t *a, spl_ast_node_t *n) { static spl_ir_node_ref_t ast2ir_intrin_len(spl_ast2ir_t *a, spl_ast_node_t *n) {
spl_ast_node_t *obj = spl_ast_node(a->sema->ast, n->field.obj); spl_ast_node_t *obj = spl_ast_node(a->ast, n->field.obj);
spl_lang_type_id_t recv_lang = node_lang(a, obj); spl_lang_type_id_t recv_lang = node_lang(a, obj);
spl_lang_type_node_t *recv = spl_lang_type_node(a->sema->type, recv_lang); spl_lang_type_node_t *recv = spl_lang_type_node(a->sema->type, recv_lang);
if (!recv) if (!recv)
@@ -252,7 +252,7 @@ static spl_ir_node_ref_t ast2ir_intrin_len(spl_ast2ir_t *a, spl_ast_node_t *n) {
switch (recv->kind) { switch (recv->kind) {
case SPL_LANG_TYPE_ARRAY: { case SPL_LANG_TYPE_ARRAY: {
spl_type_node_t *arr = spl_type_node(a->sema->type, recv->ir_type_id); spl_type_node_t *arr = spl_type_node(&a->sema->type->ir, recv->ir_type_id);
if (!arr) if (!arr)
return 0; return 0;
return spl_ir_builder_type_const_int(a->ir, usize_ir, arr->array_type.len); return spl_ir_builder_type_const_int(a->ir, usize_ir, arr->array_type.len);
@@ -270,7 +270,7 @@ static spl_ir_node_ref_t ast2ir_intrin_len(spl_ast2ir_t *a, spl_ast_node_t *n) {
} }
static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref); spl_ast_node_t *n = spl_ast_node(a->ast, ref);
if (!n) if (!n)
return 0; return 0;
@@ -290,7 +290,7 @@ static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
return emit_expr(a, n->unary.operand); return emit_expr(a, n->unary.operand);
} }
case SPL_AST_EXPR_FIELD: { case SPL_AST_EXPR_FIELD: {
spl_ast_node_t *obj = spl_ast_node(a->sema->ast, n->field.obj); spl_ast_node_t *obj = spl_ast_node(a->ast, n->field.obj);
if (!obj) if (!obj)
return 0; return 0;
spl_lang_type_id_t obj_lang = node_lang(a, obj); spl_lang_type_id_t obj_lang = node_lang(a, obj);
@@ -320,7 +320,7 @@ static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
return 0; return 0;
usize idx = 0; usize idx = 0;
if (!spl_type_agg_member_idx(a->sema->type, agg_ir, n->field.field, &idx)) if (!spl_type_agg_member_idx(&a->sema->type->ir, agg_ir, n->field.field, &idx))
return 0; return 0;
spl_lang_type_node_t *agg_ln = spl_lang_type_node(a->sema->type, agg_lang); spl_lang_type_node_t *agg_ln = spl_lang_type_node(a->sema->type, agg_lang);
@@ -330,7 +330,7 @@ static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
return spl_ir_builder_mem_field(a->ir, agg_ir, base, idx); return spl_ir_builder_mem_field(a->ir, agg_ir, base, idx);
} }
case SPL_AST_EXPR_INDEX: { case SPL_AST_EXPR_INDEX: {
spl_ast_node_t *obj = spl_ast_node(a->sema->ast, n->index.obj); spl_ast_node_t *obj = spl_ast_node(a->ast, n->index.obj);
if (!obj) if (!obj)
return 0; return 0;
spl_lang_type_id_t obj_lang = node_lang(a, obj); spl_lang_type_id_t obj_lang = node_lang(a, obj);
@@ -345,7 +345,7 @@ static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
obj_elem = obj_ln->extra.elem; obj_elem = obj_ln->extra.elem;
if (obj_kind == SPL_LANG_TYPE_TUPLE) { if (obj_kind == SPL_LANG_TYPE_TUPLE) {
spl_ast_node_t *idx_node = spl_ast_node(a->sema->ast, n->index.index); spl_ast_node_t *idx_node = spl_ast_node(a->ast, n->index.index);
if (!idx_node || idx_node->kind != SPL_AST_EXPR_INT_LIT) if (!idx_node || idx_node->kind != SPL_AST_EXPR_INT_LIT)
return 0; return 0;
usize i = (usize)idx_node->int_lit.bits; usize i = (usize)idx_node->int_lit.bits;
@@ -370,7 +370,8 @@ static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
spl_ir_node_ref_t slice_val = emit_expr(a, n->index.obj); spl_ir_node_ref_t slice_val = emit_expr(a, n->index.obj);
if (!slice_val) if (!slice_val)
return 0; return 0;
spl_type_id_t ptr_ir = spl_type_builder_ptr(a->sema->type, to_ir_type(a, obj_elem)); spl_type_id_t ptr_ir =
spl_type_builder_ptr(&a->sema->type->ir, to_ir_type(a, obj_elem));
spl_ir_node_ref_t ptr = spl_ir_builder_agg_extract(a->ir, ptr_ir, ptr_ir, spl_ir_node_ref_t ptr = spl_ir_builder_agg_extract(a->ir, ptr_ir, ptr_ir,
SPL_SLICE_PTR_FIELD_IDX, slice_val); SPL_SLICE_PTR_FIELD_IDX, slice_val);
base = ptr; base = ptr;
@@ -400,7 +401,7 @@ static spl_ir_node_ref_t ast2ir_emit_cast_builtin(spl_ast2ir_t *a, spl_ast_node_
spl_type_id_t tt, spl_ir_node_ref_t v) { spl_type_id_t tt, spl_ir_node_ref_t v) {
switch (in) { switch (in) {
case SPL_INTRIN_INT_CAST: { case SPL_INTRIN_INT_CAST: {
spl_type_node_t *fs = spl_type_node(a->sema->type, ft); spl_type_node_t *fs = spl_type_node(&a->sema->type->ir, ft);
if (fs && fs->int_type.is_signed) if (fs && fs->int_type.is_signed)
return spl_ir_builder_cast_sext(a->ir, ft, tt, v); return spl_ir_builder_cast_sext(a->ir, ft, tt, v);
return spl_ir_builder_cast_zext(a->ir, ft, tt, v); return spl_ir_builder_cast_zext(a->ir, ft, tt, v);
@@ -410,8 +411,8 @@ static spl_ir_node_ref_t ast2ir_emit_cast_builtin(spl_ast2ir_t *a, spl_ast_node_
case SPL_INTRIN_BIT_CAST: case SPL_INTRIN_BIT_CAST:
return spl_ir_builder_cast_bitcast(a->ir, ft, tt, v); return spl_ir_builder_cast_bitcast(a->ir, ft, tt, v);
case SPL_INTRIN_FLOAT_CAST: { case SPL_INTRIN_FLOAT_CAST: {
spl_type_node_t *fs = spl_type_node(a->sema->type, ft); spl_type_node_t *fs = spl_type_node(&a->sema->type->ir, ft);
spl_type_node_t *ts = spl_type_node(a->sema->type, tt); spl_type_node_t *ts = spl_type_node(&a->sema->type->ir, tt);
if (fs && ts && fs->float_type.bits > ts->float_type.bits) if (fs && ts && fs->float_type.bits > ts->float_type.bits)
return spl_ir_builder_cast_ftrunc(a->ir, ft, tt, v); return spl_ir_builder_cast_ftrunc(a->ir, ft, tt, v);
return spl_ir_builder_cast_fext(a->ir, ft, tt, v); return spl_ir_builder_cast_fext(a->ir, ft, tt, v);
@@ -438,14 +439,14 @@ static spl_ir_node_ref_t emit_cast(spl_ast2ir_t *a, spl_ast_node_t *n) {
spl_ir_node_ref_t v = emit_expr_raw(a, n->cast.expr); spl_ir_node_ref_t v = emit_expr_raw(a, n->cast.expr);
if (!v) if (!v)
return 0; return 0;
spl_ast_node_t *src = spl_ast_node(a->sema->ast, n->cast.expr); spl_ast_node_t *src = spl_ast_node(a->ast, n->cast.expr);
spl_ast_node_t *dst = spl_ast_node(a->sema->ast, n->cast.type); spl_ast_node_t *dst = spl_ast_node(a->ast, n->cast.type);
spl_type_id_t ft = node_ir(a, src); spl_type_id_t ft = node_ir(a, src);
spl_type_id_t tt = node_ir(a, dst); spl_type_id_t tt = node_ir(a, dst);
if (!ft || !tt) if (!ft || !tt)
return 0; return 0;
spl_intrin_t in = spl_intrin_lookup_cast(a->sema->type, ft, tt); spl_intrin_t in = spl_intrin_lookup_cast(&a->sema->type->ir, ft, tt);
if (in == SPL_INTRIN_NONE) { if (in == SPL_INTRIN_NONE) {
spl_diag_error(a->diag, SPL_DIAG_KIND_CAST_INVALID, &n->dbg, spl_diag_error(a->diag, SPL_DIAG_KIND_CAST_INVALID, &n->dbg,
"as: no conversion between the given types"); "as: no conversion between the given types");
@@ -459,7 +460,7 @@ static spl_ir_node_ref_t emit_expr(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
if (!val) if (!val)
return 0; return 0;
spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref); spl_ast_node_t *n = spl_ast_node(a->ast, ref);
if (!n || n->expected_lang_tid == 0) if (!n || n->expected_lang_tid == 0)
return val; return val;
@@ -479,14 +480,14 @@ static spl_ir_node_ref_t emit_expr(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
} }
static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref); spl_ast_node_t *n = spl_ast_node(a->ast, ref);
if (!n) if (!n)
return 0; return 0;
switch (n->kind) { switch (n->kind) {
case SPL_AST_EXPR_INT_LIT: { case SPL_AST_EXPR_INT_LIT: {
spl_type_id_t it = node_ir(a, n); spl_type_id_t it = node_ir(a, n);
spl_type_node_t *itn = spl_type_node(a->sema->type, it); spl_type_node_t *itn = spl_type_node(&a->sema->type->ir, it);
if (itn && itn->kind == SPL_TYPE_FLOAT) { if (itn && itn->kind == SPL_TYPE_FLOAT) {
double d = (double)(int64_t)n->int_lit.bits; double d = (double)(int64_t)n->int_lit.bits;
return spl_ir_builder_type_const_float(a->ir, it, d); return spl_ir_builder_type_const_float(a->ir, it, d);
@@ -501,7 +502,7 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
usize len = n->string_lit.len; usize len = n->string_lit.len;
spl_lang_type_id_t u8_lang = spl_lang_make_int(a->sema->type, 8, 0); spl_lang_type_id_t u8_lang = spl_lang_make_int(a->sema->type, 8, 0);
spl_type_id_t u8_ir = to_ir_type(a, u8_lang); spl_type_id_t u8_ir = to_ir_type(a, u8_lang);
spl_type_id_t ptr_u8_ir = spl_type_builder_ptr(a->sema->type, u8_ir); spl_type_id_t ptr_u8_ir = spl_type_builder_ptr(&a->sema->type->ir, u8_ir);
spl_lang_type_id_t usize_lang = spl_lang_make_int(a->sema->type, sizeof(void *) * 8, 0); spl_lang_type_id_t usize_lang = spl_lang_make_int(a->sema->type, sizeof(void *) * 8, 0);
spl_type_id_t usize_ir = to_ir_type(a, usize_lang); spl_type_id_t usize_ir = to_ir_type(a, usize_lang);
spl_lang_type_id_t arr_lang = spl_lang_make_array(a->sema->type, u8_lang, len); spl_lang_type_id_t arr_lang = spl_lang_make_array(a->sema->type, u8_lang, len);
@@ -567,7 +568,7 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
spl_ir_node_ref_t v = emit_expr(a, n->binary.right); spl_ir_node_ref_t v = emit_expr(a, n->binary.right);
if (!ptr || !v) if (!ptr || !v)
return 0; return 0;
spl_ast_node_t *ln = spl_ast_node(a->sema->ast, n->binary.left); spl_ast_node_t *ln = spl_ast_node(a->ast, n->binary.left);
spl_type_id_t t = node_ir(a, ln); spl_type_id_t t = node_ir(a, ln);
spl_ir_builder_mem_store(a->ir, t, ptr, v); spl_ir_builder_mem_store(a->ir, t, ptr, v);
return v; return v;
@@ -576,7 +577,7 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
spl_ir_node_ref_t ptr = emit_lvalue(a, n->binary.left); spl_ir_node_ref_t ptr = emit_lvalue(a, n->binary.left);
if (!ptr) if (!ptr)
return 0; return 0;
spl_ast_node_t *ln = spl_ast_node(a->sema->ast, n->binary.left); spl_ast_node_t *ln = spl_ast_node(a->ast, n->binary.left);
spl_type_id_t t = node_ir(a, ln); spl_type_id_t t = node_ir(a, ln);
spl_ir_node_ref_t lv = spl_ir_builder_mem_load(a->ir, t, ptr); spl_ir_node_ref_t lv = spl_ir_builder_mem_load(a->ir, t, ptr);
spl_ir_node_ref_t rv = emit_expr(a, n->binary.right); spl_ir_node_ref_t rv = emit_expr(a, n->binary.right);
@@ -627,14 +628,14 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
if (!l || !r) if (!l || !r)
return 0; return 0;
spl_ast_node_t *ln = spl_ast_node(a->sema->ast, n->binary.left); spl_ast_node_t *ln = spl_ast_node(a->ast, n->binary.left);
spl_lang_type_id_t lt = node_lang(a, ln); spl_lang_type_id_t lt = node_lang(a, ln);
spl_lang_type_node_t *lln = spl_lang_type_node(a->sema->type, lt); spl_lang_type_node_t *lln = spl_lang_type_node(a->sema->type, lt);
if (lln && lln->kind == SPL_LANG_TYPE_PTR && (op == SPL_OP_ADD || op == SPL_OP_SUB)) { if (lln && lln->kind == SPL_LANG_TYPE_PTR && (op == SPL_OP_ADD || op == SPL_OP_SUB)) {
spl_lang_type_id_t elem_lang = lln->extra.elem; spl_lang_type_id_t elem_lang = lln->extra.elem;
spl_type_id_t elem_ir = to_ir_type(a, elem_lang); spl_type_id_t elem_ir = to_ir_type(a, elem_lang);
spl_type_id_t rt_ir = node_ir(a, spl_ast_node(a->sema->ast, n->binary.right)); spl_type_id_t rt_ir = node_ir(a, spl_ast_node(a->ast, n->binary.right));
spl_ir_node_ref_t off = r; spl_ir_node_ref_t off = r;
if (op == SPL_OP_SUB) if (op == SPL_OP_SUB)
@@ -671,7 +672,7 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
case SPL_OP_CMP_LE: case SPL_OP_CMP_LE:
case SPL_OP_CMP_GT: case SPL_OP_CMP_GT:
case SPL_OP_CMP_GE: { case SPL_OP_CMP_GE: {
spl_ast_node_t *cmln = spl_ast_node(a->sema->ast, n->binary.left); spl_ast_node_t *cmln = spl_ast_node(a->ast, n->binary.left);
spl_type_id_t op_tid = cmln ? node_ir(a, cmln) : 0; spl_type_id_t op_tid = cmln ? node_ir(a, cmln) : 0;
switch (op) { switch (op) {
case SPL_OP_CMP_EQ: case SPL_OP_CMP_EQ:
@@ -691,12 +692,12 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
} }
} }
case SPL_OP_BOOL_OR: { case SPL_OP_BOOL_OR: {
spl_ast_node_t *bmln = spl_ast_node(a->sema->ast, n->binary.left); spl_ast_node_t *bmln = spl_ast_node(a->ast, n->binary.left);
spl_type_id_t op_tid = bmln ? node_ir(a, bmln) : 0; spl_type_id_t op_tid = bmln ? node_ir(a, bmln) : 0;
return spl_ir_builder_arith_or(a->ir, op_tid, l, r); return spl_ir_builder_arith_or(a->ir, op_tid, l, r);
} }
case SPL_OP_BOOL_AND: { case SPL_OP_BOOL_AND: {
spl_ast_node_t *bmln = spl_ast_node(a->sema->ast, n->binary.left); spl_ast_node_t *bmln = spl_ast_node(a->ast, n->binary.left);
spl_type_id_t op_tid = bmln ? node_ir(a, bmln) : 0; spl_type_id_t op_tid = bmln ? node_ir(a, bmln) : 0;
return spl_ir_builder_arith_and(a->ir, op_tid, l, r); return spl_ir_builder_arith_and(a->ir, op_tid, l, r);
} }
@@ -705,7 +706,7 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
} }
} }
case SPL_AST_EXPR_CALL: { case SPL_AST_EXPR_CALL: {
spl_ast_node_t *callee = spl_ast_node(a->sema->ast, n->call.callee); spl_ast_node_t *callee = spl_ast_node(a->ast, n->call.callee);
if (callee && callee->kind == SPL_AST_EXPR_IDENT) { if (callee && callee->kind == SPL_AST_EXPR_IDENT) {
spl_intrin_t in = spl_intrin_lookup_call(callee->ident.name); spl_intrin_t in = spl_intrin_lookup_call(callee->ident.name);
if (in != SPL_INTRIN_NONE) if (in != SPL_INTRIN_NONE)
@@ -736,7 +737,7 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
return call; return call;
} }
case SPL_AST_EXPR_FIELD: { case SPL_AST_EXPR_FIELD: {
spl_ast_node_t *obj = spl_ast_node(a->sema->ast, n->field.obj); spl_ast_node_t *obj = spl_ast_node(a->ast, n->field.obj);
spl_lang_type_id_t obj_lang = node_lang(a, obj); spl_lang_type_id_t obj_lang = node_lang(a, obj);
spl_lang_type_node_t *obj_ln = spl_lang_type_node(a->sema->type, obj_lang); spl_lang_type_node_t *obj_ln = spl_lang_type_node(a->sema->type, obj_lang);
if (obj_ln) { if (obj_ln) {
@@ -823,7 +824,7 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
if (!t) if (!t)
Panic("aggregate literal has no type after sema"); Panic("aggregate literal has no type after sema");
spl_type_node_t *tn = spl_type_node(a->sema->type, t); spl_type_node_t *tn = spl_type_node(&a->sema->type->ir, t);
if (!tn) if (!tn)
Panic("aggregate type node missing"); Panic("aggregate type node missing");
@@ -832,13 +833,12 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
if (tn_kind == SPL_TYPE_ENUM) { if (tn_kind == SPL_TYPE_ENUM) {
if (vec_size(n->aggregate_literal.fields) != 1) if (vec_size(n->aggregate_literal.fields) != 1)
Panic("enum literal must have exactly one variant"); Panic("enum literal must have exactly one variant");
spl_ast_node_t *item = spl_ast_node_t *item = spl_ast_node(a->ast, vec_at(n->aggregate_literal.fields, 0));
spl_ast_node(a->sema->ast, vec_at(n->aggregate_literal.fields, 0));
if (!item || item->kind != SPL_AST_STRUCT_INIT_ITEM) if (!item || item->kind != SPL_AST_STRUCT_INIT_ITEM)
Panic("invalid enum literal"); Panic("invalid enum literal");
usize vidx = 0; usize vidx = 0;
if (!spl_type_agg_member_idx(a->sema->type, t, item->struct_init_item.name, &vidx)) if (!spl_type_agg_member_idx(&a->sema->type->ir, t, item->struct_init_item.name, &vidx))
Panic("enum variant `%s` not found (sema should have caught this)", Panic("enum variant `%s` not found (sema should have caught this)",
item->struct_init_item.name); item->struct_init_item.name);
@@ -873,13 +873,12 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
vec_push(fields, 0); vec_push(fields, 0);
for (usize i = 0; i < vec_size(n->aggregate_literal.fields); ++i) { for (usize i = 0; i < vec_size(n->aggregate_literal.fields); ++i) {
spl_ast_node_t *item = spl_ast_node_t *item = spl_ast_node(a->ast, vec_at(n->aggregate_literal.fields, i));
spl_ast_node(a->sema->ast, vec_at(n->aggregate_literal.fields, i));
if (!item || item->kind != SPL_AST_STRUCT_INIT_ITEM) if (!item || item->kind != SPL_AST_STRUCT_INIT_ITEM)
continue; continue;
usize idx = 0; usize idx = 0;
if (!spl_type_agg_member_idx(a->sema->type, t, item->struct_init_item.name, &idx)) if (!spl_type_agg_member_idx(&a->sema->type->ir, t, item->struct_init_item.name, &idx))
Panic("aggregate field `%s` not found (sema should have caught this)", Panic("aggregate field `%s` not found (sema should have caught this)",
item->struct_init_item.name); item->struct_init_item.name);
@@ -936,7 +935,7 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
case SPL_AST_EXPR_LOOP: case SPL_AST_EXPR_LOOP:
return emit_loop_like(a, ref); return emit_loop_like(a, ref);
case SPL_AST_EXPR_SLICE: { case SPL_AST_EXPR_SLICE: {
spl_ast_node_t *obj = spl_ast_node(a->sema->ast, n->slice.obj); spl_ast_node_t *obj = spl_ast_node(a->ast, n->slice.obj);
spl_lang_type_id_t obj_lang = node_lang(a, obj); spl_lang_type_id_t obj_lang = node_lang(a, obj);
spl_lang_type_node_t *obj_ln = spl_lang_type_node(a->sema->type, obj_lang); spl_lang_type_node_t *obj_ln = spl_lang_type_node(a->sema->type, obj_lang);
if (!obj_ln) if (!obj_ln)
@@ -962,7 +961,7 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
spl_ir_node_ref_t slice_val = emit_expr(a, n->slice.obj); spl_ir_node_ref_t slice_val = emit_expr(a, n->slice.obj);
if (!slice_val) if (!slice_val)
return 0; return 0;
spl_type_id_t ptr_ir = spl_type_builder_ptr((spl_type_t *)a->sema->type, elem_ir); spl_type_id_t ptr_ir = spl_type_builder_ptr(&a->sema->type->ir, elem_ir);
base = spl_ir_builder_agg_extract(a->ir, obj_ir, ptr_ir, SPL_SLICE_PTR_FIELD_IDX, base = spl_ir_builder_agg_extract(a->ir, obj_ir, ptr_ir, SPL_SLICE_PTR_FIELD_IDX,
slice_val); slice_val);
} else { } else {
@@ -987,7 +986,7 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
if (n->slice.end) { if (n->slice.end) {
end_v = emit_expr(a, n->slice.end); end_v = emit_expr(a, n->slice.end);
} else if (obj_kind == SPL_LANG_TYPE_ARRAY) { } else if (obj_kind == SPL_LANG_TYPE_ARRAY) {
spl_type_node_t *arr = spl_type_node(a->sema->type, obj_ir); spl_type_node_t *arr = spl_type_node(&a->sema->type->ir, obj_ir);
if (!arr) if (!arr)
return 0; return 0;
usize arr_len = arr->array_type.len; usize arr_len = arr->array_type.len;
@@ -1024,13 +1023,13 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
} }
static spl_ir_node_ref_t emit_if_like(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { static spl_ir_node_ref_t emit_if_like(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref); spl_ast_node_t *n = spl_ast_node(a->ast, ref);
if (!n) if (!n)
return 0; return 0;
bool is_ifvar = (n->kind == SPL_AST_EXPR_IFVAR); bool is_ifvar = (n->kind == SPL_AST_EXPR_IFVAR);
spl_type_id_t result_t = node_ir(a, n); spl_type_id_t result_t = node_ir(a, n);
spl_type_node_t *rtn = result_t ? spl_type_node(a->sema->type, result_t) : NULL; spl_type_node_t *rtn = result_t ? spl_type_node(&a->sema->type->ir, result_t) : NULL;
bool need_result = rtn && rtn->kind != SPL_TYPE_UNIT; bool need_result = rtn && rtn->kind != SPL_TYPE_UNIT;
spl_ir_node_ref_t result_slot = 0; spl_ir_node_ref_t result_slot = 0;
@@ -1043,7 +1042,7 @@ static spl_ir_node_ref_t emit_if_like(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
if (is_ifvar) { if (is_ifvar) {
emit_decl(a, n->ifvar_expr.var_decl); emit_decl(a, n->ifvar_expr.var_decl);
spl_ast_node_t *vd = spl_ast_node(a->sema->ast, n->ifvar_expr.var_decl); spl_ast_node_t *vd = spl_ast_node(a->ast, n->ifvar_expr.var_decl);
if (!vd || !vd->var_const_decl.init_expr) if (!vd || !vd->var_const_decl.init_expr)
Panic("ifvar requires initializer"); Panic("ifvar requires initializer");
spl_ir_node_ref_t slot = 0; spl_ir_node_ref_t slot = 0;
@@ -1098,13 +1097,13 @@ static spl_ir_node_ref_t emit_if_like(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
} }
static spl_ir_node_ref_t emit_loop_like(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { static spl_ir_node_ref_t emit_loop_like(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref); spl_ast_node_t *n = spl_ast_node(a->ast, ref);
if (!n) if (!n)
return 0; return 0;
bool is_while = (n->kind == SPL_AST_EXPR_WHILE); bool is_while = (n->kind == SPL_AST_EXPR_WHILE);
spl_type_id_t result_t = node_ir(a, n); spl_type_id_t result_t = node_ir(a, n);
spl_type_node_t *rtn = result_t ? spl_type_node(a->sema->type, result_t) : NULL; spl_type_node_t *rtn = result_t ? spl_type_node(&a->sema->type->ir, result_t) : NULL;
bool need_result = rtn && rtn->kind != SPL_TYPE_UNIT; bool need_result = rtn && rtn->kind != SPL_TYPE_UNIT;
spl_ir_node_ref_t result_slot = 0; spl_ir_node_ref_t result_slot = 0;
@@ -1139,7 +1138,7 @@ static spl_ir_node_ref_t emit_loop_like(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
spl_ast_node_ref_t label_ref = is_while ? n->while_expr.label : n->loop_expr.label; spl_ast_node_ref_t label_ref = is_while ? n->while_expr.label : n->loop_expr.label;
if (label_ref) { if (label_ref) {
spl_ast_node_t *ln = spl_ast_node(a->sema->ast, label_ref); spl_ast_node_t *ln = spl_ast_node(a->ast, label_ref);
if (ln && ln->kind == SPL_AST_LABEL) if (ln && ln->kind == SPL_AST_LABEL)
ctx.label = ln->label.name; ctx.label = ln->label.name;
} }
@@ -1186,7 +1185,7 @@ static void emit_break_stmt(spl_ast2ir_t *a, spl_ast_node_t *n) {
const char *lbl = NULL; const char *lbl = NULL;
if (n->statement_break.label) { if (n->statement_break.label) {
spl_ast_node_t *ln = spl_ast_node(a->sema->ast, n->statement_break.label); spl_ast_node_t *ln = spl_ast_node(a->ast, n->statement_break.label);
if (ln && ln->kind == SPL_AST_LABEL) if (ln && ln->kind == SPL_AST_LABEL)
lbl = ln->label.name; lbl = ln->label.name;
} }
@@ -1217,7 +1216,7 @@ static void emit_break_stmt(spl_ast2ir_t *a, spl_ast_node_t *n) {
} }
static void emit_stmt(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { static void emit_stmt(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref); spl_ast_node_t *n = spl_ast_node(a->ast, ref);
if (!n) if (!n)
return; return;
@@ -1272,7 +1271,7 @@ static void emit_stmt(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
const char *lbl = NULL; const char *lbl = NULL;
if (n->statement_continue.label) { if (n->statement_continue.label) {
spl_ast_node_t *ln = spl_ast_node(a->sema->ast, n->statement_continue.label); spl_ast_node_t *ln = spl_ast_node(a->ast, n->statement_continue.label);
if (ln && ln->kind == SPL_AST_LABEL) if (ln && ln->kind == SPL_AST_LABEL)
lbl = ln->label.name; lbl = ln->label.name;
} }
@@ -1304,7 +1303,7 @@ static void emit_stmt(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
} }
static void emit_decl(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { static void emit_decl(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref); spl_ast_node_t *n = spl_ast_node(a->ast, ref);
if (!n) if (!n)
return; return;
@@ -1316,7 +1315,7 @@ static void emit_decl(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
if (!n->resolved_def_id) if (!n->resolved_def_id)
return; return;
spl_ast_node_t *pat = spl_ast_node(a->sema->ast, n->var_const_decl.pattern); spl_ast_node_t *pat = spl_ast_node(a->ast, n->var_const_decl.pattern);
if (!pat || pat->kind != SPL_AST_PATTERN_IDENT) if (!pat || pat->kind != SPL_AST_PATTERN_IDENT)
return; return;
@@ -1393,7 +1392,7 @@ static void emit_fn_body(spl_ast2ir_t *a, spl_ast_node_t *n) {
for (usize i = 0; i < vec_size(n->fn_decl.params); ++i) { for (usize i = 0; i < vec_size(n->fn_decl.params); ++i) {
spl_ast_node_ref_t pref = vec_at(n->fn_decl.params, i); spl_ast_node_ref_t pref = vec_at(n->fn_decl.params, i);
spl_ast_node_t *pd = spl_ast_node(a->sema->ast, pref); spl_ast_node_t *pd = spl_ast_node(a->ast, pref);
if (!pd || pd->kind != SPL_AST_PARAM_DECL) if (!pd || pd->kind != SPL_AST_PARAM_DECL)
continue; continue;
if (!pd->resolved_def_id) if (!pd->resolved_def_id)
@@ -1451,13 +1450,13 @@ static void emit_fn_body(spl_ast2ir_t *a, spl_ast_node_t *n) {
static void emit_aggregate_fns_reserve(spl_ast2ir_t *a, spl_ast_node_t *te) { static void emit_aggregate_fns_reserve(spl_ast2ir_t *a, spl_ast_node_t *te) {
for (usize i = 0; i < vec_size(te->type_aggregate.members); ++i) { for (usize i = 0; i < vec_size(te->type_aggregate.members); ++i) {
spl_ast_node_t *mn = spl_ast_node(a->sema->ast, vec_at(te->type_aggregate.members, i)); spl_ast_node_t *mn = spl_ast_node(a->ast, vec_at(te->type_aggregate.members, i));
if (!mn) if (!mn)
continue; continue;
if (mn->kind == SPL_AST_FN_DECL) { if (mn->kind == SPL_AST_FN_DECL) {
emit_fn_reserve(a, mn); emit_fn_reserve(a, mn);
} else if (mn->kind == SPL_AST_MEMBER_DECL && mn->member_decl.type_expr) { } else if (mn->kind == SPL_AST_MEMBER_DECL && mn->member_decl.type_expr) {
spl_ast_node_t *mt = spl_ast_node(a->sema->ast, mn->member_decl.type_expr); spl_ast_node_t *mt = spl_ast_node(a->ast, mn->member_decl.type_expr);
if (mt && mt->kind == SPL_AST_TYPE_AGGREGATE) if (mt && mt->kind == SPL_AST_TYPE_AGGREGATE)
emit_aggregate_fns_reserve(a, mt); emit_aggregate_fns_reserve(a, mt);
} }
@@ -1466,13 +1465,13 @@ static void emit_aggregate_fns_reserve(spl_ast2ir_t *a, spl_ast_node_t *te) {
static void emit_aggregate_fns_body(spl_ast2ir_t *a, spl_ast_node_t *te) { static void emit_aggregate_fns_body(spl_ast2ir_t *a, spl_ast_node_t *te) {
for (usize i = 0; i < vec_size(te->type_aggregate.members); ++i) { for (usize i = 0; i < vec_size(te->type_aggregate.members); ++i) {
spl_ast_node_t *mn = spl_ast_node(a->sema->ast, vec_at(te->type_aggregate.members, i)); spl_ast_node_t *mn = spl_ast_node(a->ast, vec_at(te->type_aggregate.members, i));
if (!mn) if (!mn)
continue; continue;
if (mn->kind == SPL_AST_FN_DECL) { if (mn->kind == SPL_AST_FN_DECL) {
emit_fn_body(a, mn); emit_fn_body(a, mn);
} else if (mn->kind == SPL_AST_MEMBER_DECL && mn->member_decl.type_expr) { } else if (mn->kind == SPL_AST_MEMBER_DECL && mn->member_decl.type_expr) {
spl_ast_node_t *mt = spl_ast_node(a->sema->ast, mn->member_decl.type_expr); spl_ast_node_t *mt = spl_ast_node(a->ast, mn->member_decl.type_expr);
if (mt && mt->kind == SPL_AST_TYPE_AGGREGATE) if (mt && mt->kind == SPL_AST_TYPE_AGGREGATE)
emit_aggregate_fns_body(a, mt); emit_aggregate_fns_body(a, mt);
} }
@@ -1480,7 +1479,7 @@ static void emit_aggregate_fns_body(spl_ast2ir_t *a, spl_ast_node_t *te) {
} }
static void emit_container_reserve(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { static void emit_container_reserve(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref); spl_ast_node_t *n = spl_ast_node(a->ast, ref);
if (!n) if (!n)
return; return;
if (n->kind == SPL_AST_TOP_LEVEL_BLOCK) { if (n->kind == SPL_AST_TOP_LEVEL_BLOCK) {
@@ -1493,7 +1492,7 @@ static void emit_container_reserve(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
for (usize i = 0; i < vec_size(n->container_members.declarations); ++i) { for (usize i = 0; i < vec_size(n->container_members.declarations); ++i) {
spl_ast_node_ref_t dref = vec_at(n->container_members.declarations, i); spl_ast_node_ref_t dref = vec_at(n->container_members.declarations, i);
spl_ast_node_t *d = spl_ast_node(a->sema->ast, dref); spl_ast_node_t *d = spl_ast_node(a->ast, dref);
if (!d) if (!d)
continue; continue;
switch (d->kind) { switch (d->kind) {
@@ -1501,7 +1500,7 @@ static void emit_container_reserve(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
emit_fn_reserve(a, d); emit_fn_reserve(a, d);
break; break;
case SPL_AST_TYPE_DECL: { case SPL_AST_TYPE_DECL: {
spl_ast_node_t *te = spl_ast_node(a->sema->ast, d->type_decl.type_expr); spl_ast_node_t *te = spl_ast_node(a->ast, d->type_decl.type_expr);
if (te && te->kind == SPL_AST_TYPE_AGGREGATE) if (te && te->kind == SPL_AST_TYPE_AGGREGATE)
emit_aggregate_fns_reserve(a, te); emit_aggregate_fns_reserve(a, te);
break; break;
@@ -1516,7 +1515,7 @@ static void emit_container_reserve(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
} }
static void emit_container_body(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { static void emit_container_body(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref); spl_ast_node_t *n = spl_ast_node(a->ast, ref);
if (!n) if (!n)
return; return;
if (n->kind == SPL_AST_TOP_LEVEL_BLOCK) { if (n->kind == SPL_AST_TOP_LEVEL_BLOCK) {
@@ -1529,7 +1528,7 @@ static void emit_container_body(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
for (usize i = 0; i < vec_size(n->container_members.declarations); ++i) { for (usize i = 0; i < vec_size(n->container_members.declarations); ++i) {
spl_ast_node_ref_t dref = vec_at(n->container_members.declarations, i); spl_ast_node_ref_t dref = vec_at(n->container_members.declarations, i);
spl_ast_node_t *d = spl_ast_node(a->sema->ast, dref); spl_ast_node_t *d = spl_ast_node(a->ast, dref);
if (!d) if (!d)
continue; continue;
switch (d->kind) { switch (d->kind) {
@@ -1537,7 +1536,7 @@ static void emit_container_body(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
emit_fn_body(a, d); emit_fn_body(a, d);
break; break;
case SPL_AST_TYPE_DECL: { case SPL_AST_TYPE_DECL: {
spl_ast_node_t *te = spl_ast_node(a->sema->ast, d->type_decl.type_expr); spl_ast_node_t *te = spl_ast_node(a->ast, d->type_decl.type_expr);
if (te && te->kind == SPL_AST_TYPE_AGGREGATE) if (te && te->kind == SPL_AST_TYPE_AGGREGATE)
emit_aggregate_fns_body(a, te); emit_aggregate_fns_body(a, te);
break; break;
@@ -1555,8 +1554,8 @@ static spl_ir_node_ref_t emit_implicit_cast(spl_ast2ir_t *a, spl_ast_node_t *n,
spl_type_id_t tt, spl_ir_node_ref_t v) { spl_type_id_t tt, spl_ir_node_ref_t v) {
if (!ft || !tt || ft == tt) if (!ft || !tt || ft == tt)
return v; return v;
spl_type_node_t *fs = spl_type_node(a->sema->type, ft); spl_type_node_t *fs = spl_type_node(&a->sema->type->ir, ft);
spl_type_node_t *ts = spl_type_node(a->sema->type, tt); spl_type_node_t *ts = spl_type_node(&a->sema->type->ir, tt);
if (!fs || !ts) if (!fs || !ts)
return v; return v;
@@ -1577,8 +1576,6 @@ static spl_ir_node_ref_t emit_implicit_cast(spl_ast2ir_t *a, spl_ast_node_t *n,
if (fs->kind == SPL_TYPE_BOOL && ts->kind == SPL_TYPE_INT) if (fs->kind == SPL_TYPE_BOOL && ts->kind == SPL_TYPE_INT)
return spl_ir_builder_cast_bool2int(a->ir, ft, tt, v); return spl_ir_builder_cast_bool2int(a->ir, ft, tt, v);
/* 指针之间:IR 层不区分 pointee,值语义相同,直接透传。
覆盖 *never -> *T(null 字面量)和 *T -> *any。 */
if (fs->kind == SPL_TYPE_PTR && ts->kind == SPL_TYPE_PTR) if (fs->kind == SPL_TYPE_PTR && ts->kind == SPL_TYPE_PTR)
return v; return v;
@@ -1598,6 +1595,7 @@ static int spl_int_map_cmp(usize a, usize b) { return MAP_CMP_INT(a, b); }
void spl_ast2ir_init(spl_ast2ir_t *ast2ir, spl_ir_builder_t *ir, const spl_sema_t *sema) { void spl_ast2ir_init(spl_ast2ir_t *ast2ir, spl_ir_builder_t *ir, const spl_sema_t *sema) {
ast2ir->sema = sema; ast2ir->sema = sema;
ast2ir->ir = ir; ast2ir->ir = ir;
ast2ir->ast = sema->ast;
map_init(ast2ir->def2ir_map, spl_int_map_hash, spl_int_map_cmp); map_init(ast2ir->def2ir_map, spl_int_map_hash, spl_int_map_cmp);
vec_init(ast2ir->loop_stack); vec_init(ast2ir->loop_stack);
vec_init(ast2ir->defer_stack); vec_init(ast2ir->defer_stack);
@@ -1615,13 +1613,30 @@ void spl_ast2ir_drop(spl_ast2ir_t *ast2ir) {
map_free(ast2ir->def2ir_map); map_free(ast2ir->def2ir_map);
} }
void spl_ast2ir_run(spl_ast2ir_t *ast2ir) { void spl_ast2ir_run(spl_ast2ir_t *ast2ir, spl_ast_ptr_vec_t ast_vec) {
spl_ast_t *ast = ast2ir->sema->ast; usize n = vec_size(ast_vec);
for (usize i = 0; i < n; ++i) {
spl_ast_t *ast = vec_at(ast_vec, i);
if (!ast || !ast->root) if (!ast || !ast->root)
return; continue;
ast2ir->ast = ast;
spl_ast_node_t *root = spl_ast_node(ast, ast->root); spl_ast_node_t *root = spl_ast_node(ast, ast->root);
if (!root || root->kind != SPL_AST_ROOT) if (!root || root->kind != SPL_AST_ROOT)
return; continue;
emit_container_reserve(ast2ir, root->root.members); emit_container_reserve(ast2ir, root->root.members);
}
for (usize i = 0; i < n; ++i) {
spl_ast_t *ast = vec_at(ast_vec, i);
if (!ast || !ast->root)
continue;
ast2ir->ast = ast;
spl_ast_node_t *root = spl_ast_node(ast, ast->root);
if (!root || root->kind != SPL_AST_ROOT)
continue;
emit_container_body(ast2ir, root->root.members); emit_container_body(ast2ir, root->root.members);
} }
vec_free(ast_vec);
}
+2 -1
View File
@@ -21,6 +21,7 @@ typedef VEC(spl_ast_node_ref_t) spl_defer_stack_t;
typedef struct { typedef struct {
const spl_sema_t *sema; const spl_sema_t *sema;
spl_ir_builder_t *ir; spl_ir_builder_t *ir;
spl_ast_t *ast;
spl_def2ir_map_t def2ir_map; spl_def2ir_map_t def2ir_map;
spl_loop_ctx_vec_t loop_stack; spl_loop_ctx_vec_t loop_stack;
spl_defer_stack_t defer_stack; spl_defer_stack_t defer_stack;
@@ -33,6 +34,6 @@ typedef struct {
void spl_ast2ir_init(spl_ast2ir_t *ast2ir, spl_ir_builder_t *ir, const spl_sema_t *sema); void spl_ast2ir_init(spl_ast2ir_t *ast2ir, spl_ir_builder_t *ir, const spl_sema_t *sema);
void spl_ast2ir_drop(spl_ast2ir_t *ast2ir); void spl_ast2ir_drop(spl_ast2ir_t *ast2ir);
void spl_ast2ir_run(spl_ast2ir_t *ast2ir); void spl_ast2ir_run(spl_ast2ir_t *ast2ir, spl_ast_ptr_vec_t ast_vec);
#endif /* __SPL_AST2IR_H__ */ #endif /* __SPL_AST2IR_H__ */
+1 -1
View File
@@ -2,7 +2,7 @@
#define __SPL_INTRIN_H__ #define __SPL_INTRIN_H__
#include "../stage0/include/utils.h" #include "../stage0/include/utils.h"
#include "spl_type.h" #include "spl_lang_type.h"
typedef enum { typedef enum {
SPL_INTRIN_NONE = 0, SPL_INTRIN_NONE = 0,
+776
View File
@@ -0,0 +1,776 @@
#include "spl_lang_type.h"
static usize spl_lang_type_hash(spl_lang_type_node_t n) {
usize hash = (usize)n.kind * 131 + n.ir_type_id;
switch (n.kind) {
case SPL_LANG_TYPE_PTR:
case SPL_LANG_TYPE_SLICE:
case SPL_LANG_TYPE_RANGE:
hash += n.extra.elem;
break;
case SPL_LANG_TYPE_TUPLE:
for (usize i = 0; i < vec_size(n.extra.elems); i++) {
hash += vec_at(n.extra.elems, i);
}
break;
case SPL_LANG_TYPE_FN:
hash += n.extra.fn.ret;
for (usize i = 0; i < vec_size(n.extra.fn.params); i++) {
hash += vec_at(n.extra.fn.params, i);
}
break;
case SPL_LANG_TYPE_STRUCT:
case SPL_LANG_TYPE_UNION:
case SPL_LANG_TYPE_ENUM:
case SPL_LANG_TYPE_SHAPE:
for (usize i = 0; i < vec_size(n.methods); i++) {
spl_lang_method_t *m = &vec_at(n.methods, i);
hash += m->def_id * 31;
if (m->name) {
const char *s = m->name;
while (*s)
hash = hash * 31 + (usize)(*s++);
}
}
break;
default:
break;
}
return hash;
}
static int spl_lang_type_eq(spl_lang_type_node_t n1, spl_lang_type_node_t n2) {
if (n1.kind != n2.kind || n1.ir_type_id != n2.ir_type_id)
return 1;
switch (n1.kind) {
case SPL_LANG_TYPE_PTR:
case SPL_LANG_TYPE_SLICE:
case SPL_LANG_TYPE_RANGE:
return n1.extra.elem != n2.extra.elem;
case SPL_LANG_TYPE_TUPLE:
if (vec_size(n1.extra.elems) != vec_size(n2.extra.elems))
return 1;
for (usize i = 0; i < vec_size(n1.extra.elems); i++) {
if (vec_at(n1.extra.elems, i) != vec_at(n2.extra.elems, i))
return 1;
}
return 0;
case SPL_LANG_TYPE_FN:
if (n1.extra.fn.ret != n2.extra.fn.ret)
return 1;
if (vec_size(n1.extra.fn.params) != vec_size(n2.extra.fn.params))
return 1;
for (usize i = 0; i < vec_size(n1.extra.fn.params); i++) {
if (vec_at(n1.extra.fn.params, i) != vec_at(n2.extra.fn.params, i))
return 1;
}
return 0;
case SPL_LANG_TYPE_STRUCT:
case SPL_LANG_TYPE_UNION:
case SPL_LANG_TYPE_ENUM:
case SPL_LANG_TYPE_SHAPE:
if (vec_size(n1.methods) != vec_size(n2.methods))
return 1;
for (usize i = 0; i < vec_size(n1.methods); i++) {
spl_lang_method_t *a = &vec_at(n1.methods, i);
spl_lang_method_t *b = &vec_at(n2.methods, i);
if (a->def_id != b->def_id)
return 1;
if ((a->name == NULL) != (b->name == NULL))
return 1;
if (a->name && strcmp(a->name, b->name) != 0)
return 1;
}
return 0;
default:
return 0;
}
}
static usize spl_lang_map_hash(usize k) { return MAP_HASH_INT(k); }
static int spl_lang_map_cmp(usize a, usize b) { return MAP_CMP_INT(a, b); }
static void spl_lang_node_free_extra(spl_lang_type_node_t *n) {
switch (n->kind) {
case SPL_LANG_TYPE_TUPLE:
vec_free(n->extra.elems);
break;
case SPL_LANG_TYPE_FN:
vec_free(n->extra.fn.params);
break;
case SPL_LANG_TYPE_STRUCT:
case SPL_LANG_TYPE_UNION:
case SPL_LANG_TYPE_ENUM:
case SPL_LANG_TYPE_SHAPE:
vec_free(n->methods);
break;
default:
break;
}
}
spl_lang_type_id_t spl_lang_node_push(spl_lang_type_t *type, spl_lang_type_node_t *node) {
usize hash = spl_lang_type_hash(*node);
usize idx = (usize)-1;
spl_lang_type_id_t cand = 0;
while (map_get_continue(type->lang_map, hash, &cand, &idx)) {
spl_lang_type_node_t *existing = &vec_at(type->lang_table, cand);
if (spl_lang_type_eq(*existing, *node) == 0) {
spl_lang_node_free_extra(node);
return cand;
}
}
spl_lang_type_id_t id = vec_size(type->lang_table);
vec_push(type->lang_table, *node);
map_put_new(type->lang_map, hash, id);
node->kind = SPL_LANG_TYPE_ERROR;
return id;
}
void spl_lang_type_init(spl_lang_type_t *type) {
spl_type_init(&type->ir);
vec_init(type->lang_table);
spl_lang_type_node_t lang_node = {0};
vec_push(type->lang_table, lang_node);
map_init(type->lang_map, spl_lang_map_hash, spl_lang_map_cmp);
vec_init(type->def_table);
vec_push(type->def_table, (spl_def_node_t){0});
}
void spl_lang_type_drop(spl_lang_type_t *type) {
for (usize i = 0; i < vec_size(type->lang_table); i++) {
spl_lang_type_node_t *n = &vec_at(type->lang_table, i);
spl_lang_node_free_extra(n);
}
map_free(type->lang_map);
vec_free(type->lang_table);
vec_free(type->def_table);
spl_type_drop(&type->ir);
}
spl_lang_type_node_t *spl_lang_type_node(const spl_lang_type_t *type, spl_lang_type_id_t id) {
if (!id || id >= vec_size(type->lang_table))
return NULL;
return &vec_at(type->lang_table, id);
}
spl_def_node_t *spl_def_node(const spl_lang_type_t *type, spl_def_id_t id) {
if (!id || id >= vec_size(type->def_table))
return NULL;
return &vec_at(type->def_table, id);
}
spl_type_id_t spl_lang_type_get_ir_type(spl_lang_type_t *type, spl_lang_type_id_t lang_id) {
spl_lang_type_node_t *n = spl_lang_type_node(type, lang_id);
return n ? n->ir_type_id : 0;
}
spl_type_id_t spl_lang_reserve_ir(spl_lang_type_t *type) {
spl_type_node_t empty = {0};
empty.kind = SPL_TYPE_ERROR;
empty.layout.mode = SPL_TYPE_LAYOUT_AUTO;
vec_push(type->ir.type_table, empty);
return vec_size(type->ir.type_table) - 1;
}
void spl_lang_define_ir(spl_lang_type_t *type, spl_type_id_t id, spl_type_node_t *node) {
if (!id || id >= vec_size(type->ir.type_table))
return;
spl_type_node_t *slot = &vec_at(type->ir.type_table, id);
/* slot 原是空 ERROR 节点,无 vec 字段可释放。node 的 vec 字段 move 进 slot。
占位 id 不写 type_map,不参与 hash-consing。 */
*slot = *node;
node->kind = SPL_TYPE_ERROR;
}
static spl_lang_type_id_t spl_lang_node_simple(spl_lang_type_t *type,
spl_lang_type_kind_t lang_kind,
spl_type_id_t ir_type_id) {
spl_lang_type_node_t node = {0};
node.kind = lang_kind;
node.ir_type_id = ir_type_id;
return spl_lang_node_push(type, &node);
}
spl_lang_type_id_t spl_lang_make_error(spl_lang_type_t *type) {
spl_type_id_t ir = spl_type_builder_simple(&type->ir, SPL_TYPE_ERROR);
return spl_lang_node_simple(type, SPL_LANG_TYPE_ERROR, ir);
}
spl_lang_type_id_t spl_lang_make_infer(spl_lang_type_t *type) {
spl_type_id_t ir = spl_type_builder_simple(&type->ir, SPL_TYPE_INFER);
return spl_lang_node_simple(type, SPL_LANG_TYPE_INFER, ir);
}
spl_lang_type_id_t spl_lang_make_never(spl_lang_type_t *type) {
spl_type_id_t ir = spl_type_builder_simple(&type->ir, SPL_TYPE_NEVER);
return spl_lang_node_simple(type, SPL_LANG_TYPE_NEVER, ir);
}
spl_lang_type_id_t spl_lang_make_any(spl_lang_type_t *type) {
spl_type_id_t ir = spl_type_builder_simple(&type->ir, SPL_TYPE_ANY);
return spl_lang_node_simple(type, SPL_LANG_TYPE_ANY, ir);
}
spl_lang_type_id_t spl_lang_make_unit(spl_lang_type_t *type) {
spl_type_id_t ir = spl_type_builder_simple(&type->ir, SPL_TYPE_UNIT);
return spl_lang_node_simple(type, SPL_LANG_TYPE_UNIT, ir);
}
spl_lang_type_id_t spl_lang_make_bool(spl_lang_type_t *type) {
spl_type_id_t ir = spl_type_builder_simple(&type->ir, SPL_TYPE_BOOL);
return spl_lang_node_simple(type, SPL_LANG_TYPE_BOOL, ir);
}
spl_lang_type_id_t spl_lang_make_int(spl_lang_type_t *type, usize bits, int is_signed) {
spl_type_id_t ir = spl_type_builder_int(&type->ir, bits, is_signed);
return spl_lang_node_simple(type, SPL_LANG_TYPE_INT, ir);
}
spl_lang_type_id_t spl_lang_make_float(spl_lang_type_t *type, usize bits) {
spl_type_id_t ir = spl_type_builder_float(&type->ir, bits);
return spl_lang_node_simple(type, SPL_LANG_TYPE_FLOAT, ir);
}
spl_lang_type_id_t spl_lang_make_array(spl_lang_type_t *type, spl_lang_type_id_t elem_lang,
usize len) {
spl_type_id_t elem_ir = spl_lang_type_get_ir_type(type, elem_lang);
if (!elem_ir)
return 0;
spl_type_id_t ir = spl_type_builder_array(&type->ir, elem_ir, len);
spl_lang_type_node_t node = {0};
node.kind = SPL_LANG_TYPE_ARRAY;
node.ir_type_id = ir;
node.extra.elem = elem_lang;
return spl_lang_node_push(type, &node);
}
spl_lang_type_id_t spl_lang_make_ptr(spl_lang_type_t *type, spl_lang_type_id_t pointee_lang) {
spl_type_id_t pointee_ir = spl_lang_type_get_ir_type(type, pointee_lang);
if (!pointee_ir)
return 0;
spl_type_id_t ir = spl_type_builder_ptr(&type->ir, pointee_ir);
spl_lang_type_node_t node = {0};
node.kind = SPL_LANG_TYPE_PTR;
node.ir_type_id = ir;
node.extra.elem = pointee_lang;
return spl_lang_node_push(type, &node);
}
spl_lang_type_id_t spl_lang_make_slice(spl_lang_type_t *type, spl_lang_type_id_t elem_lang) {
spl_type_id_t elem_ir = spl_lang_type_get_ir_type(type, elem_lang);
if (!elem_ir)
return 0;
spl_lang_type_id_t ptr_lang = spl_lang_make_ptr(type, elem_lang);
spl_lang_type_id_t usize_lang = spl_lang_make_int(type, sizeof(void *) * 8, 0);
spl_type_id_t ptr_ir = spl_lang_type_get_ir_type(type, ptr_lang);
spl_type_id_t usize_ir = spl_lang_type_get_ir_type(type, usize_lang);
spl_type_member_vec_t members;
vec_init(members);
spl_type_member_t m1 = {.name = "ptr", .type_id = ptr_ir};
spl_type_member_t m2 = {.name = "len", .type_id = usize_ir};
vec_push(members, m1);
vec_push(members, m2);
spl_type_layout_t layout = {.mode = SPL_TYPE_LAYOUT_AUTO, .fixed_align_bits = 0};
spl_type_id_t struct_ir = spl_type_builder_agg(&type->ir, SPL_TYPE_STRUCT, &members, 0, layout);
spl_lang_type_node_t node = {0};
node.kind = SPL_LANG_TYPE_SLICE;
node.ir_type_id = struct_ir;
node.extra.elem = elem_lang;
return spl_lang_node_push(type, &node);
}
spl_lang_type_id_t spl_lang_make_tuple(spl_lang_type_t *type, const spl_lang_type_id_t *elems,
usize count) {
spl_type_member_vec_t members;
vec_init(members);
for (usize i = 0; i < count; i++) {
spl_type_id_t elem_ir = spl_lang_type_get_ir_type(type, elems[i]);
if (!elem_ir) {
vec_free(members);
return 0;
}
char name[32];
snprintf(name, sizeof(name), "%zu", i);
spl_type_member_t m = {.name = strdup(name), .type_id = elem_ir};
vec_push(members, m);
}
spl_type_layout_t layout = {.mode = SPL_TYPE_LAYOUT_AUTO, .fixed_align_bits = 0};
spl_type_id_t struct_ir = spl_type_builder_agg(&type->ir, SPL_TYPE_STRUCT, &members, 0, layout);
spl_lang_type_node_t node = {0};
node.kind = SPL_LANG_TYPE_TUPLE;
node.ir_type_id = struct_ir;
vec_init(node.extra.elems);
for (usize i = 0; i < count; i++) {
vec_push(node.extra.elems, elems[i]);
}
return spl_lang_node_push(type, &node);
}
spl_lang_type_id_t spl_lang_make_range(spl_lang_type_t *type, spl_lang_type_id_t elem_lang) {
spl_type_id_t elem_ir = spl_lang_type_get_ir_type(type, elem_lang);
if (!elem_ir)
return 0;
spl_type_member_vec_t members;
vec_init(members);
spl_type_member_t m1 = {.name = "start", .type_id = elem_ir};
spl_type_member_t m2 = {.name = "end", .type_id = elem_ir};
vec_push(members, m1);
vec_push(members, m2);
spl_type_layout_t layout = {.mode = SPL_TYPE_LAYOUT_AUTO, .fixed_align_bits = 0};
spl_type_id_t struct_ir = spl_type_builder_agg(&type->ir, SPL_TYPE_STRUCT, &members, 0, layout);
spl_lang_type_node_t node = {0};
node.kind = SPL_LANG_TYPE_RANGE;
node.ir_type_id = struct_ir;
node.extra.elem = elem_lang;
return spl_lang_node_push(type, &node);
}
spl_lang_type_id_t spl_lang_make_fn(spl_lang_type_t *type, spl_lang_type_id_t ret_lang,
const spl_lang_type_id_t *params_lang, usize nparams) {
spl_type_id_t ret_ir = spl_lang_type_get_ir_type(type, ret_lang);
if (!ret_ir)
return 0;
spl_type_id_vec_t param_irs;
vec_init(param_irs);
for (usize i = 0; i < nparams; i++) {
spl_type_id_t pir = spl_lang_type_get_ir_type(type, params_lang[i]);
if (!pir) {
vec_free(param_irs);
return 0;
}
vec_push(param_irs, pir);
}
spl_type_id_t fn_ir =
spl_type_builder_fn(&type->ir, ret_ir, param_irs.data, vec_size(param_irs));
vec_free(param_irs);
spl_lang_type_node_t node = {0};
node.kind = SPL_LANG_TYPE_FN;
node.ir_type_id = fn_ir;
node.extra.fn.ret = ret_lang;
vec_init(node.extra.fn.params);
for (usize i = 0; i < nparams; i++) {
vec_push(node.extra.fn.params, params_lang[i]);
}
return spl_lang_node_push(type, &node);
}
spl_lang_type_id_t spl_lang_make_aggregate(spl_lang_type_t *type, spl_lang_type_kind_t kind,
const char *name, const spl_lang_type_id_t *members_lang,
usize nmembers) {
spl_type_node_kind_t tk;
switch (kind) {
case SPL_LANG_TYPE_STRUCT:
tk = SPL_TYPE_STRUCT;
break;
case SPL_LANG_TYPE_UNION:
tk = SPL_TYPE_UNION;
break;
case SPL_LANG_TYPE_ENUM:
tk = SPL_TYPE_ENUM;
break;
case SPL_LANG_TYPE_SHAPE:
tk = SPL_TYPE_SHAPE;
break;
default:
return 0;
}
spl_type_member_vec_t members;
vec_init(members);
for (usize i = 0; i < nmembers; i++) {
spl_type_id_t member_ir = spl_lang_type_get_ir_type(type, members_lang[i]);
if (!member_ir) {
vec_free(members);
return 0;
}
char field_name[32];
snprintf(field_name, sizeof(field_name), "%zu", i);
spl_type_member_t m = {.name = strdup(field_name), .type_id = member_ir};
vec_push(members, m);
}
spl_type_layout_t layout = {.mode = SPL_TYPE_LAYOUT_AUTO, .fixed_align_bits = 0};
spl_type_id_t agg_ir = spl_type_builder_agg(&type->ir, tk, &members, 0, layout);
spl_lang_type_node_t node = {0};
node.kind = kind;
node.ir_type_id = agg_ir;
return spl_lang_node_push(type, &node);
}
spl_lang_type_id_t spl_lang_make_varargs(spl_lang_type_t *type) {
spl_type_id_t ir = spl_type_builder_simple(&type->ir, SPL_TYPE_UNIT);
spl_lang_type_node_t node = {0};
node.kind = SPL_LANG_TYPE_VARARGS;
node.ir_type_id = ir;
return spl_lang_node_push(type, &node);
}
spl_lang_type_id_t spl_type_lookup_builtin(spl_lang_type_t *type, const char *name) {
if (!name || !*name)
return 0;
if (strcmp(name, "bool") == 0)
return spl_lang_make_bool(type);
if (strcmp(name, "void") == 0)
return spl_lang_make_unit(type);
if (strcmp(name, "isize") == 0)
return spl_lang_make_int(type, sizeof(void *) * 8, 1);
if (strcmp(name, "usize") == 0)
return spl_lang_make_int(type, sizeof(void *) * 8, 0);
if (strcmp(name, "any") == 0)
return spl_lang_make_any(type);
char prefix = name[0];
if (prefix == 'i' || prefix == 'u' || prefix == 'f') {
const char *rest = name + 1;
char *end;
long bits = strtol(rest, &end, 10);
if (end != rest && *end == '\0' && bits > 0) {
if (prefix == 'i')
return spl_lang_make_int(type, (usize)bits, 1);
if (prefix == 'u')
return spl_lang_make_int(type, (usize)bits, 0);
if (prefix == 'f')
return spl_lang_make_float(type, (usize)bits);
}
}
return 0;
}
bool spl_lang_type_is_subtype(const spl_lang_type_t *type, spl_lang_type_id_t sub,
spl_lang_type_id_t super) {
if (sub == 0 || super == 0)
return false;
if (sub == super)
return true;
spl_lang_type_node_t *nsub = spl_lang_type_node(type, sub);
spl_lang_type_node_t *nsuper = spl_lang_type_node(type, super);
if (!nsub || !nsuper)
return false;
if (nsub->kind == SPL_LANG_TYPE_NEVER)
return true;
if (nsuper->kind == SPL_LANG_TYPE_ANY)
return true;
if (nsub->kind == SPL_LANG_TYPE_INT && nsuper->kind == SPL_LANG_TYPE_INT) {
spl_type_node_t *ir_sub = spl_type_node(&type->ir, nsub->ir_type_id);
if (!ir_sub)
return false;
return ir_sub->int_type.bits == 0;
}
if (nsub->kind == SPL_LANG_TYPE_FLOAT && nsuper->kind == SPL_LANG_TYPE_FLOAT) {
spl_type_node_t *ir_sub = spl_type_node(&type->ir, nsub->ir_type_id);
if (!ir_sub)
return false;
return ir_sub->float_type.bits == 0;
}
if (nsub->kind == SPL_LANG_TYPE_PTR && nsuper->kind == SPL_LANG_TYPE_PTR) {
if (nsub->extra.elem == nsuper->extra.elem)
return true;
spl_lang_type_node_t *sub_elem = spl_lang_type_node(type, nsub->extra.elem);
spl_lang_type_node_t *super_elem = spl_lang_type_node(type, nsuper->extra.elem);
if (sub_elem && sub_elem->kind == SPL_LANG_TYPE_NEVER)
return true;
if (super_elem && super_elem->kind == SPL_LANG_TYPE_ANY)
return true;
return false;
}
return false;
}
spl_lang_type_id_t spl_lang_type_join(const spl_lang_type_t *type, spl_lang_type_id_t a,
spl_lang_type_id_t b) {
if (a == 0 || b == 0)
return 0;
if (a == b)
return a;
spl_lang_type_node_t *na = spl_lang_type_node(type, a);
spl_lang_type_node_t *nb = spl_lang_type_node(type, b);
if (!na || !nb)
return 0;
if (na->kind == SPL_LANG_TYPE_NEVER)
return b;
if (nb->kind == SPL_LANG_TYPE_NEVER)
return a;
if (na->kind == SPL_LANG_TYPE_ANY || nb->kind == SPL_LANG_TYPE_ANY)
return spl_lang_make_any((spl_lang_type_t *)type);
bool a_int = na->kind == SPL_LANG_TYPE_INT;
bool b_int = nb->kind == SPL_LANG_TYPE_INT;
bool a_flt = na->kind == SPL_LANG_TYPE_FLOAT;
bool b_flt = nb->kind == SPL_LANG_TYPE_FLOAT;
if (a_int && b_int) {
spl_type_node_t *ira = spl_type_node(&type->ir, na->ir_type_id);
spl_type_node_t *irb = spl_type_node(&type->ir, nb->ir_type_id);
if (!ira || !irb)
return 0;
bool a_ct = ira->int_type.bits == 0;
bool b_ct = irb->int_type.bits == 0;
if (a_ct && b_ct)
return a;
if (a_ct)
return b;
if (b_ct)
return a;
return 0;
}
if (a_flt && b_flt) {
spl_type_node_t *ira = spl_type_node(&type->ir, na->ir_type_id);
spl_type_node_t *irb = spl_type_node(&type->ir, nb->ir_type_id);
if (!ira || !irb)
return 0;
bool a_ct = ira->float_type.bits == 0;
bool b_ct = irb->float_type.bits == 0;
if (a_ct && b_ct)
return a;
if (a_ct)
return b;
if (b_ct)
return a;
return 0;
}
if (a_int && b_flt) {
spl_type_node_t *ira = spl_type_node(&type->ir, na->ir_type_id);
spl_type_node_t *irb = spl_type_node(&type->ir, nb->ir_type_id);
if (ira && irb && ira->int_type.bits == 0 && irb->float_type.bits == 0)
return spl_lang_make_float((spl_lang_type_t *)type, 0);
return 0;
}
if (a_flt && b_int) {
spl_type_node_t *ira = spl_type_node(&type->ir, na->ir_type_id);
spl_type_node_t *irb = spl_type_node(&type->ir, nb->ir_type_id);
if (ira && irb && ira->float_type.bits == 0 && irb->int_type.bits == 0)
return spl_lang_make_float((spl_lang_type_t *)type, 0);
return 0;
}
if (na->kind == SPL_LANG_TYPE_PTR && nb->kind == SPL_LANG_TYPE_PTR) {
if (na->extra.elem == nb->extra.elem)
return a;
spl_lang_type_node_t *ea = spl_lang_type_node(type, na->extra.elem);
spl_lang_type_node_t *eb = spl_lang_type_node(type, nb->extra.elem);
if (ea && ea->kind == SPL_LANG_TYPE_NEVER)
return b;
if (eb && eb->kind == SPL_LANG_TYPE_NEVER)
return a;
if (ea && ea->kind == SPL_LANG_TYPE_ANY)
return a;
if (eb && eb->kind == SPL_LANG_TYPE_ANY)
return b;
return 0;
}
return 0;
}
bool spl_lang_mpa_int_fits(const spl_lang_type_t *type, spl_lang_type_id_t target,
spl_mpa_int_t v) {
spl_lang_type_node_t *nt = spl_lang_type_node(type, target);
if (!nt || nt->kind != SPL_LANG_TYPE_INT)
return false;
spl_type_node_t *ir = spl_type_node(&type->ir, nt->ir_type_id);
if (!ir)
return false;
uint32_t bits = (uint32_t)ir->int_type.bits;
if (bits == 0)
return true;
bool target_signed = ir->int_type.is_signed != 0;
uint64_t uval = v.bits;
if (target_signed) {
if (bits >= 64)
return true;
uint64_t hi = ((uint64_t)1 << (bits - 1)) - 1;
return uval <= hi;
}
if (bits >= 64)
return true;
uint64_t hi = ((uint64_t)1 << bits) - 1;
return uval <= hi;
}
spl_def_id_t spl_def_alloc(spl_lang_type_t *type, spl_def_node_kind_t kind, const char *name,
spl_dbg_node_t dbg, struct spl_ast *owner_ast, usize ast_node_ref) {
spl_def_node_t n = {0};
n.kind = kind;
n.name = name;
n.dbg_node = dbg;
n.lang_id = 0;
n.owner_ast = owner_ast;
n.ast_node_ref = ast_node_ref;
n.state = SPL_DECL_UNRESOLVED;
n.owner_def = 0;
vec_push(type->def_table, n);
return vec_size(type->def_table) - 1;
}
void spl_def_resolve(spl_lang_type_t *type, spl_def_id_t id, spl_lang_type_id_t lang_id) {
spl_def_node_t *d = spl_def_node(type, id);
if (d)
d->lang_id = lang_id;
}
spl_lang_type_id_t spl_def_get_lang_id(spl_lang_type_t *type, spl_def_id_t def_id) {
spl_def_node_t *d = spl_def_node(type, def_id);
return d ? d->lang_id : 0;
}
spl_type_id_t spl_def_get_type_id(spl_lang_type_t *type, spl_def_id_t def_id) {
spl_lang_type_id_t lang = spl_def_get_lang_id(type, def_id);
return lang ? spl_lang_type_get_ir_type(type, lang) : 0;
}
void spl_lang_type_dump(spl_lang_type_t *type, spl_lang_type_id_t id) {
spl_lang_type_node_t *n = spl_lang_type_node(type, id);
if (!n) {
printf("none");
return;
}
switch (n->kind) {
case SPL_LANG_TYPE_ERROR:
printf("error");
break;
case SPL_LANG_TYPE_INFER:
printf("infer");
break;
case SPL_LANG_TYPE_NEVER:
printf("never");
break;
case SPL_LANG_TYPE_ANY:
printf("any");
break;
case SPL_LANG_TYPE_UNIT:
printf("unit");
break;
case SPL_LANG_TYPE_BOOL:
printf("bool");
break;
case SPL_LANG_TYPE_VARARGS:
printf("...");
break;
case SPL_LANG_TYPE_INT: {
spl_type_node_t *tn = spl_type_node(&type->ir, n->ir_type_id);
if (tn && tn->int_type.bits == 0)
printf("comptime_int");
else
spl_type_pure_dump(&type->ir, n->ir_type_id);
break;
}
case SPL_LANG_TYPE_FLOAT: {
spl_type_node_t *tn = spl_type_node(&type->ir, n->ir_type_id);
if (tn && tn->float_type.bits == 0)
printf("comptime_float");
else
spl_type_pure_dump(&type->ir, n->ir_type_id);
break;
}
case SPL_LANG_TYPE_PTR:
printf("*");
spl_lang_type_dump(type, n->extra.elem);
break;
case SPL_LANG_TYPE_ARRAY: {
spl_type_node_t *tn = spl_type_node(&type->ir, n->ir_type_id);
printf("[%zu]", tn->array_type.len);
spl_type_pure_dump(&type->ir, n->ir_type_id);
} break;
case SPL_LANG_TYPE_SLICE:
printf("[]");
spl_lang_type_dump(type, n->extra.elem);
break;
case SPL_LANG_TYPE_TUPLE:
printf("(");
for (usize i = 0; i < vec_size(n->extra.elems); i++) {
if (i)
printf(",");
spl_lang_type_dump(type, vec_at(n->extra.elems, i));
}
printf(")");
break;
case SPL_LANG_TYPE_RANGE:
spl_lang_type_dump(type, n->extra.elem);
printf("..");
spl_lang_type_dump(type, n->extra.elem);
break;
case SPL_LANG_TYPE_FN:
printf("fn(");
for (usize i = 0; i < vec_size(n->extra.fn.params); i++) {
if (i)
printf(",");
spl_lang_type_dump(type, vec_at(n->extra.fn.params, i));
}
printf(")");
spl_lang_type_dump(type, n->extra.fn.ret);
break;
case SPL_LANG_TYPE_STRUCT:
case SPL_LANG_TYPE_UNION:
case SPL_LANG_TYPE_ENUM:
case SPL_LANG_TYPE_SHAPE:
spl_type_pure_dump(&type->ir, n->ir_type_id);
break;
}
}
void spl_type_def_dump(spl_lang_type_t *type, spl_def_id_t id) {
spl_def_node_t *node = spl_def_node(type, id);
if (!node) {
printf("none");
return;
}
const char *def_kind_name = "unknown";
switch (node->kind) {
case SPL_DEF_ERROR:
def_kind_name = "error";
break;
case SPL_DEF_SCALAR:
def_kind_name = "scalar";
break;
case SPL_DEF_MEMBER:
def_kind_name = "member";
break;
case SPL_DEF_VAR:
def_kind_name = "var";
break;
case SPL_DEF_FN:
def_kind_name = "fn";
break;
case SPL_DEF_AGG:
def_kind_name = "agg";
break;
case SPL_DEF_BUILTIN:
def_kind_name = "builtin";
break;
case SPL_DEF_DISTINCT:
def_kind_name = "distinct";
break;
case SPL_DEF_ALIAS:
def_kind_name = "alias";
break;
}
printf("kind=%s lang_id=%zu name=%s", def_kind_name, node->lang_id,
node->name ? node->name : "?");
}
+153
View File
@@ -0,0 +1,153 @@
#ifndef __SPL_LANG_TYPE_H__
#define __SPL_LANG_TYPE_H__
#include "../stage0/include/utils.h"
#include "spl_dbg.h"
#include "spl_mpa.h"
#include "spl_type.h"
typedef usize spl_lang_type_id_t;
typedef VEC(spl_lang_type_id_t) spl_lang_type_id_vec_t;
typedef usize spl_def_id_t;
typedef VEC(spl_def_id_t) spl_def_id_vec_t;
typedef enum {
SPL_LANG_TYPE_ERROR,
SPL_LANG_TYPE_INFER,
SPL_LANG_TYPE_NEVER,
SPL_LANG_TYPE_ANY,
SPL_LANG_TYPE_UNIT,
SPL_LANG_TYPE_BOOL,
SPL_LANG_TYPE_INT,
SPL_LANG_TYPE_FLOAT,
SPL_LANG_TYPE_PTR,
SPL_LANG_TYPE_ARRAY,
SPL_LANG_TYPE_SLICE,
SPL_LANG_TYPE_TUPLE,
SPL_LANG_TYPE_RANGE,
SPL_LANG_TYPE_FN,
SPL_LANG_TYPE_STRUCT,
SPL_LANG_TYPE_UNION,
SPL_LANG_TYPE_ENUM,
SPL_LANG_TYPE_SHAPE,
SPL_LANG_TYPE_VARARGS,
} spl_lang_type_kind_t;
typedef struct {
const char *name;
spl_def_id_t def_id;
} spl_lang_method_t;
typedef VEC(spl_lang_method_t) spl_lang_method_vec_t;
typedef struct {
spl_lang_type_kind_t kind;
spl_type_id_t ir_type_id;
spl_lang_method_vec_t methods;
union {
spl_lang_type_id_t elem;
spl_lang_type_id_vec_t elems;
struct {
spl_lang_type_id_vec_t params;
spl_lang_type_id_t ret;
} fn;
} extra;
} spl_lang_type_node_t;
typedef VEC(spl_lang_type_node_t) spl_lang_type_vec_t;
typedef MAP(usize, spl_lang_type_id_t) spl_lang_type_map_t;
typedef enum {
SPL_DEF_ERROR,
SPL_DEF_SCALAR,
SPL_DEF_MEMBER,
SPL_DEF_VAR,
SPL_DEF_FN,
SPL_DEF_AGG,
SPL_DEF_DISTINCT,
SPL_DEF_ALIAS,
SPL_DEF_BUILTIN,
} spl_def_node_kind_t;
typedef enum {
SPL_DECL_UNRESOLVED,
SPL_DECL_RESOLVING,
SPL_DECL_RESOLVED,
SPL_DECL_ERROR,
} spl_decl_state_t;
struct spl_ast;
typedef struct {
spl_def_node_kind_t kind;
const char *name;
spl_dbg_node_t dbg_node;
spl_lang_type_id_t lang_id;
struct spl_ast *owner_ast;
usize ast_node_ref;
spl_decl_state_t state;
spl_def_id_t owner_def;
} spl_def_node_t;
typedef VEC(spl_def_node_t) spl_def_node_vec_t;
typedef struct {
spl_type_t ir;
spl_lang_type_vec_t lang_table;
spl_lang_type_map_t lang_map;
spl_def_node_vec_t def_table;
} spl_lang_type_t;
void spl_lang_type_init(spl_lang_type_t *type);
void spl_lang_type_drop(spl_lang_type_t *type);
spl_lang_type_node_t *spl_lang_type_node(const spl_lang_type_t *type, spl_lang_type_id_t id);
spl_lang_type_id_t spl_lang_node_push(spl_lang_type_t *type, spl_lang_type_node_t *node);
spl_type_id_t spl_lang_type_get_ir_type(spl_lang_type_t *type, spl_lang_type_id_t lang_id);
/* 前向引用支持:reserve 一个 type_table 空槽位(kind=ERROR)作为身份锚点,
让 *Node / []Node 这类成员能拿到稳定 pointee;成员解析完后再调 define
把真实内容填进去。占位槽位**不写 type_map**,不参与 hash-consing——
后续相同形状的类型走 spl_type_node_push 会生成独立 id,语义等价。 */
spl_type_id_t spl_lang_reserve_ir(spl_lang_type_t *type);
void spl_lang_define_ir(spl_lang_type_t *type, spl_type_id_t id, spl_type_node_t *node);
spl_lang_type_id_t spl_lang_make_error(spl_lang_type_t *type);
spl_lang_type_id_t spl_lang_make_infer(spl_lang_type_t *type);
spl_lang_type_id_t spl_lang_make_never(spl_lang_type_t *type);
spl_lang_type_id_t spl_lang_make_any(spl_lang_type_t *type);
spl_lang_type_id_t spl_lang_make_unit(spl_lang_type_t *type);
spl_lang_type_id_t spl_lang_make_bool(spl_lang_type_t *type);
spl_lang_type_id_t spl_lang_make_int(spl_lang_type_t *type, usize bits, int is_signed);
spl_lang_type_id_t spl_lang_make_float(spl_lang_type_t *type, usize bits);
spl_lang_type_id_t spl_lang_make_ptr(spl_lang_type_t *type, spl_lang_type_id_t pointee);
spl_lang_type_id_t spl_lang_make_array(spl_lang_type_t *type, spl_lang_type_id_t elem, usize len);
spl_lang_type_id_t spl_lang_make_slice(spl_lang_type_t *type, spl_lang_type_id_t elem);
spl_lang_type_id_t spl_lang_make_tuple(spl_lang_type_t *type, const spl_lang_type_id_t *elems,
usize count);
spl_lang_type_id_t spl_lang_make_range(spl_lang_type_t *type, spl_lang_type_id_t elem);
spl_lang_type_id_t spl_lang_make_fn(spl_lang_type_t *type, spl_lang_type_id_t ret,
const spl_lang_type_id_t *params, usize nparams);
spl_lang_type_id_t spl_lang_make_aggregate(spl_lang_type_t *type, spl_lang_type_kind_t kind,
const char *name, const spl_lang_type_id_t *members,
usize nmembers);
spl_lang_type_id_t spl_lang_make_varargs(spl_lang_type_t *type);
spl_lang_type_id_t spl_type_lookup_builtin(spl_lang_type_t *type, const char *name);
bool spl_lang_type_is_subtype(const spl_lang_type_t *type, spl_lang_type_id_t sub,
spl_lang_type_id_t super);
spl_lang_type_id_t spl_lang_type_join(const spl_lang_type_t *type, spl_lang_type_id_t a,
spl_lang_type_id_t b);
bool spl_lang_mpa_int_fits(const spl_lang_type_t *type, spl_lang_type_id_t target, spl_mpa_int_t v);
spl_def_id_t spl_def_alloc(spl_lang_type_t *type, spl_def_node_kind_t kind, const char *name,
spl_dbg_node_t dbg, struct spl_ast *owner_ast, usize ast_node_ref);
void spl_def_resolve(spl_lang_type_t *type, spl_def_id_t id, spl_lang_type_id_t lang_id);
spl_def_node_t *spl_def_node(const spl_lang_type_t *type, spl_def_id_t id);
spl_lang_type_id_t spl_def_get_lang_id(spl_lang_type_t *type, spl_def_id_t def_id);
spl_type_id_t spl_def_get_type_id(spl_lang_type_t *type, spl_def_id_t def_id);
void spl_lang_type_dump(spl_lang_type_t *type, spl_lang_type_id_t id);
void spl_type_def_dump(spl_lang_type_t *type, spl_def_id_t id);
#endif /* __SPL_LANG_TYPE_H__ */
+46
View File
@@ -0,0 +1,46 @@
#include "spl_scope.h"
void spl_scope_init(spl_scope_t *scope) {
vec_init(scope->scopes);
vec_push(scope->scopes, (spl_scope_node_t){0});
scope->current_scope = 0;
scope->root_scope = 0;
}
void spl_scope_drop(spl_scope_t *scope) {
for (usize i = 0; i < vec_size(scope->scopes); ++i) {
map_free(vec_at(scope->scopes, i).symbols);
}
vec_free(scope->scopes);
scope->current_scope = 0;
scope->root_scope = 0;
}
spl_scope_id_t spl_scope_alloc(spl_scope_t *scope) {
spl_scope_node_t n = {0};
n.parent = scope->current_scope;
map_init(n.symbols, MAP_HASH_STR, MAP_CMP_STR);
vec_push(scope->scopes, n);
return vec_size(scope->scopes) - 1;
}
bool spl_scope_insert(spl_scope_t *scope, spl_scope_id_t id, spl_symbol_t symbol) {
Assert(id != 0 && id < vec_size(scope->scopes));
spl_scope_node_t *node = &vec_at(scope->scopes, id);
spl_symbol_t old = {0};
if (map_get(node->symbols, symbol.name, &old))
return false;
map_put(node->symbols, symbol.name, symbol);
return true;
}
bool spl_scope_find(spl_scope_t *scope, const char *name, spl_symbol_t *out) {
if (!scope || !name || !out)
return false;
for (spl_scope_id_t id = scope->current_scope; id != 0; id = vec_at(scope->scopes, id).parent) {
spl_scope_node_t *s = &vec_at(scope->scopes, id);
if (map_get(s->symbols, name, out))
return true;
}
return false;
}
+42
View File
@@ -0,0 +1,42 @@
#ifndef __SPL_SCOPE_H__
#define __SPL_SCOPE_H__
#include "spl_lang_type.h"
typedef usize spl_scope_id_t;
typedef enum {
SPL_SYMBOL_KIND_ERROR,
SPL_SYMBOL_KIND_VAR,
SPL_SYMBOL_KIND_MEMBER,
SPL_SYMBOL_KIND_FN,
SPL_SYMBOL_KIND_TYPE,
} spl_symbol_kind_t;
typedef struct {
const char *name;
spl_symbol_kind_t kind;
spl_def_id_t node;
} spl_symbol_t;
typedef VEC(const char *) spl_symbol_path_t;
typedef struct {
spl_scope_id_t parent;
MAP(const char *, spl_symbol_t) symbols;
} spl_scope_node_t;
typedef VEC(spl_scope_node_t) spl_scope_node_vec_t;
typedef struct {
spl_scope_node_vec_t scopes;
spl_scope_id_t root_scope;
spl_scope_id_t current_scope;
} spl_scope_t;
void spl_scope_init(spl_scope_t *scope);
void spl_scope_drop(spl_scope_t *scope);
spl_scope_id_t spl_scope_alloc(spl_scope_t *scope);
bool spl_scope_insert(spl_scope_t *scope, spl_scope_id_t id, spl_symbol_t symbol);
bool spl_scope_find(spl_scope_t *scop, const char *symbol_name, spl_symbol_t *out);
#endif /* __SPL_SCOPE_H__ */
+327 -143
View File
@@ -1,52 +1,8 @@
#include "spl_sema.h" #include "spl_sema.h"
#include "spl_intrin.h" #include "spl_intrin.h"
#include "spl_lang_type.h"
#include "spl_type.h" #include "spl_type.h"
void spl_scope_init(spl_scope_t *scope) {
vec_init(scope->scopes);
vec_push(scope->scopes, (spl_scope_node_t){0});
scope->current_scope = 0;
scope->root_scope = 0;
}
void spl_scope_drop(spl_scope_t *scope) {
for (usize i = 0; i < vec_size(scope->scopes); ++i) {
map_free(vec_at(scope->scopes, i).symbols);
}
vec_free(scope->scopes);
scope->current_scope = 0;
scope->root_scope = 0;
}
spl_scope_id_t spl_scope_alloc(spl_scope_t *scope) {
spl_scope_node_t n = {0};
n.parent = scope->current_scope;
map_init(n.symbols, MAP_HASH_STR, MAP_CMP_STR);
vec_push(scope->scopes, n);
return vec_size(scope->scopes) - 1;
}
bool spl_scope_insert(spl_scope_t *scope, spl_scope_id_t id, spl_symbol_t symbol) {
Assert(id != 0 && id < vec_size(scope->scopes));
spl_scope_node_t *node = &vec_at(scope->scopes, id);
spl_symbol_t old = {0};
if (map_get(node->symbols, symbol.name, &old))
return false;
map_put(node->symbols, symbol.name, symbol);
return true;
}
bool spl_scope_find(spl_scope_t *scope, const char *name, spl_symbol_t *out) {
if (!scope || !name || !out)
return false;
for (spl_scope_id_t id = scope->current_scope; id != 0; id = vec_at(scope->scopes, id).parent) {
spl_scope_node_t *s = &vec_at(scope->scopes, id);
if (map_get(s->symbols, name, out))
return true;
}
return false;
}
static spl_ast_node_ref_vec_t *node_attr_list(spl_ast_node_t *n) { static spl_ast_node_ref_vec_t *node_attr_list(spl_ast_node_t *n) {
switch (n->kind) { switch (n->kind) {
case SPL_AST_FN_DECL: case SPL_AST_FN_DECL:
@@ -168,7 +124,7 @@ static void sema_type_to_str(spl_sema_t *sema, spl_lang_type_id_t tid, char *buf
snprintf(buf, cap, "<invalid lang#%zu>", tid); snprintf(buf, cap, "<invalid lang#%zu>", tid);
return; return;
} }
spl_type_node_t *ir = spl_type_node(sema->type, n->ir_type_id); spl_type_node_t *ir = spl_type_node(&sema->type->ir, n->ir_type_id);
switch (n->kind) { switch (n->kind) {
case SPL_LANG_TYPE_INT: case SPL_LANG_TYPE_INT:
if (ir && ir->int_type.bits == 0) if (ir && ir->int_type.bits == 0)
@@ -285,37 +241,10 @@ static spl_lang_type_id_t sema_infer_fn_signature(spl_sema_t *sema, spl_ast_node
return fn_tid; return fn_tid;
} }
/* 构建聚合类型:reserve IR 槽位作为身份锚点,让 *Node / []Node 自引用能拿到
稳定 pointee;遍历成员后再 define 填内容。 */
static spl_lang_type_id_t sema_build_aggregate(spl_sema_t *sema, spl_ast_node_t *te, static spl_lang_type_id_t sema_build_aggregate(spl_sema_t *sema, spl_ast_node_t *te,
spl_def_id_t owner_def_id) { spl_def_id_t owner_def_id) {
spl_type_member_vec_t members;
vec_init(members);
spl_lang_method_vec_t methods;
vec_init(methods);
for (usize i = 0; i < vec_size(te->type_aggregate.members); ++i) {
spl_ast_node_ref_t mref = vec_at(te->type_aggregate.members, i);
spl_ast_node_t *mn = spl_ast_node(sema->ast, mref);
if (!mn)
continue;
if (mn->kind == SPL_AST_MEMBER_DECL) {
spl_lang_type_id_t mtid = sema_infer(sema, mn->member_decl.type_expr);
spl_type_member_t m = {.name = mn->member_decl.name,
.type_id = spl_lang_type_get_ir_type(sema->type, mtid),
.ast_node_ref = mref};
vec_push(members, m);
} else if (mn->kind == SPL_AST_FN_DECL) {
spl_def_id_t fn_def =
spl_def_alloc(sema->type, SPL_DEF_FN, mn->fn_decl.name, mn->dbg, mref);
mn->resolved_def_id = fn_def;
spl_def_node_t *fn_d = spl_def_node(sema->type, fn_def);
if (fn_d)
fn_d->owner_def = owner_def_id;
spl_lang_method_t meth = {.name = mn->fn_decl.name, .def_id = fn_def};
vec_push(methods, meth);
}
}
spl_type_node_kind_t tk; spl_type_node_kind_t tk;
if (strcmp(te->type_aggregate.kind_name, "struct") == 0) if (strcmp(te->type_aggregate.kind_name, "struct") == 0)
tk = SPL_TYPE_STRUCT; tk = SPL_TYPE_STRUCT;
@@ -326,11 +255,6 @@ static spl_lang_type_id_t sema_build_aggregate(spl_sema_t *sema, spl_ast_node_t
else else
tk = SPL_TYPE_STRUCT; tk = SPL_TYPE_STRUCT;
spl_type_layout_t layout = {.mode = SPL_TYPE_LAYOUT_AUTO};
spl_type_id_t agg_ir = spl_type_builder_agg(sema->type, tk, &members,
spl_type_builder_int(sema->type, 32, 1), layout);
vec_free(members);
spl_lang_type_kind_t lk; spl_lang_type_kind_t lk;
switch (tk) { switch (tk) {
case SPL_TYPE_STRUCT: case SPL_TYPE_STRUCT:
@@ -349,11 +273,229 @@ static spl_lang_type_id_t sema_build_aggregate(spl_sema_t *sema, spl_ast_node_t
lk = SPL_LANG_TYPE_STRUCT; lk = SPL_LANG_TYPE_STRUCT;
break; break;
} }
spl_type_id_t agg_ir = spl_lang_reserve_ir(sema->type);
spl_lang_type_node_t ln = {0}; spl_lang_type_node_t ln = {0};
ln.kind = lk; ln.kind = lk;
ln.ir_type_id = agg_ir; ln.ir_type_id = agg_ir;
ln.methods = methods; vec_init(ln.methods);
return spl_lang_node_push(sema->type, &ln); spl_lang_type_id_t agg_lang = spl_lang_node_push(sema->type, &ln);
if (owner_def_id) {
spl_def_node_t *d = spl_def_node(sema->type, owner_def_id);
if (d)
d->lang_id = agg_lang;
}
spl_lang_type_id_t saved_agg = sema->current_aggregate_lang;
sema->current_aggregate_lang = agg_lang;
spl_type_member_vec_t members;
vec_init(members);
spl_lang_method_vec_t methods;
vec_init(methods);
for (usize i = 0; i < vec_size(te->type_aggregate.members); ++i) {
spl_ast_node_ref_t mref = vec_at(te->type_aggregate.members, i);
spl_ast_node_t *mn = spl_ast_node(sema->ast, mref);
if (!mn)
continue;
if (mn->kind == SPL_AST_MEMBER_DECL) {
spl_lang_type_id_t mtid = 0;
if (mn->member_decl.type_expr)
mtid = sema_infer(sema, mn->member_decl.type_expr);
spl_type_member_t m = {.name = mn->member_decl.name,
.type_id = spl_lang_type_get_ir_type(sema->type, mtid),
.ast_node_ref = mref};
vec_push(members, m);
} else if (mn->kind == SPL_AST_FN_DECL) {
spl_def_id_t fn_def =
spl_def_alloc(sema->type, SPL_DEF_FN, mn->fn_decl.name, mn->dbg, sema->ast, mref);
mn->resolved_def_id = fn_def;
spl_def_node_t *fn_d = spl_def_node(sema->type, fn_def);
if (fn_d)
fn_d->owner_def = owner_def_id;
spl_lang_method_t meth = {.name = mn->fn_decl.name, .def_id = fn_def};
vec_push(methods, meth);
} else if (mn->kind == SPL_AST_TYPE_DECL) {
spl_def_id_t tdef = mn->resolved_def_id;
if (!tdef)
continue;
spl_lang_method_t meth = {.name = mn->type_decl.name, .def_id = tdef};
vec_push(methods, meth);
}
}
sema->current_aggregate_lang = saved_agg;
spl_type_node_t tn = {0};
tn.kind = tk;
tn.layout.mode = SPL_TYPE_LAYOUT_AUTO;
if (tk == SPL_TYPE_ENUM)
tn.agg_type.tag_type = spl_type_builder_int(&sema->type->ir, 32, 1);
tn.agg_type.variants = members;
vec_init(members);
spl_lang_define_ir(sema->type, agg_ir, &tn);
spl_lang_type_node_t *lslot = spl_lang_type_node(sema->type, agg_lang);
if (lslot) {
vec_free(lslot->methods);
lslot->methods = methods;
vec_init(methods);
}
return agg_lang;
}
/* 文件 container 建成匿名 struct:FN_DECL / TYPE_DECL / VAR_DECL / CONST_DECL
进 methods(复用为 names),MEMBER_DECL 进字段。 */
static spl_lang_type_id_t sema_build_container_aggregate(spl_sema_t *sema, spl_ast_node_t *n,
spl_def_id_t owner_def_id) {
spl_type_id_t agg_ir = spl_lang_reserve_ir(sema->type);
spl_lang_type_node_t ln = {0};
ln.kind = SPL_LANG_TYPE_STRUCT;
ln.ir_type_id = agg_ir;
vec_init(ln.methods);
spl_lang_type_id_t agg_lang = spl_lang_node_push(sema->type, &ln);
if (owner_def_id) {
spl_def_node_t *d = spl_def_node(sema->type, owner_def_id);
if (d)
d->lang_id = agg_lang;
}
spl_lang_type_id_t saved_agg = sema->current_aggregate_lang;
sema->current_aggregate_lang = agg_lang;
spl_type_member_vec_t members;
vec_init(members);
spl_lang_method_vec_t methods;
vec_init(methods);
for (usize i = 0; i < vec_size(n->container_members.declarations); ++i) {
spl_ast_node_ref_t dref = vec_at(n->container_members.declarations, i);
spl_ast_node_t *d = spl_ast_node(sema->ast, dref);
if (!d)
continue;
if (d->kind == SPL_AST_MEMBER_DECL) {
spl_lang_type_id_t mtid = 0;
if (d->member_decl.type_expr)
mtid = sema_infer(sema, d->member_decl.type_expr);
spl_type_member_t m = {.name = d->member_decl.name,
.type_id = spl_lang_type_get_ir_type(sema->type, mtid),
.ast_node_ref = dref};
vec_push(members, m);
} else if (d->kind == SPL_AST_FN_DECL) {
spl_def_id_t fn_def = d->resolved_def_id;
if (!fn_def)
continue;
spl_def_node_t *fn_d = spl_def_node(sema->type, fn_def);
if (fn_d)
fn_d->owner_def = owner_def_id;
spl_lang_method_t meth = {.name = d->fn_decl.name, .def_id = fn_def};
vec_push(methods, meth);
} else if (d->kind == SPL_AST_TYPE_DECL) {
spl_def_id_t tdef = d->resolved_def_id;
if (!tdef)
continue;
spl_lang_method_t meth = {.name = d->type_decl.name, .def_id = tdef};
vec_push(methods, meth);
} else if (d->kind == SPL_AST_VAR_DECL || d->kind == SPL_AST_CONST_DECL) {
spl_def_id_t vdef = d->resolved_def_id;
if (!vdef)
continue;
spl_ast_node_t *pat = spl_ast_node(sema->ast, d->var_const_decl.pattern);
if (!pat || pat->kind != SPL_AST_PATTERN_IDENT)
continue;
spl_lang_method_t meth = {.name = pat->pattern_ident.name, .def_id = vdef};
vec_push(methods, meth);
}
}
sema->current_aggregate_lang = saved_agg;
spl_type_node_t tn = {0};
tn.kind = SPL_TYPE_STRUCT;
tn.layout.mode = SPL_TYPE_LAYOUT_AUTO;
tn.agg_type.variants = members;
vec_init(members);
spl_lang_define_ir(sema->type, agg_ir, &tn);
spl_lang_type_node_t *lslot = spl_lang_type_node(sema->type, agg_lang);
if (lslot) {
vec_free(lslot->methods);
lslot->methods = methods;
vec_init(methods);
}
return agg_lang;
}
static spl_lang_type_id_t sema_import(spl_sema_t *sema, spl_ast_node_t *n,
spl_ast_node_ref_vec_t *args) {
if (!sema->loader || !sema->loader->load) {
spl_diag_error(sema->diag, SPL_DIAG_KIND_INTERNAL, &n->dbg,
"@import: no module loader configured");
return 0;
}
if (vec_size(*args) != 1) {
spl_diag_error(sema->diag, SPL_DIAG_KIND_INTRIN_ARG_COUNT, &n->dbg,
"@import expects 1 argument");
return 0;
}
spl_ast_node_t *arg = spl_ast_node(sema->ast, vec_at(*args, 0));
if (!arg || arg->kind != SPL_AST_EXPR_STRING_LIT || !arg->string_lit.data) {
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
"@import expects a string literal");
return 0;
}
const char *path = arg->string_lit.data;
spl_ast_t *mod_ast = sema->loader->load(sema->loader->user, n->dbg.fname, path, sema->diag);
if (!mod_ast || !mod_ast->root)
return 0;
spl_ast_node_t *mod_root = spl_ast_node(mod_ast, mod_ast->root);
if (!mod_root || mod_root->kind != SPL_AST_ROOT)
return 0;
spl_ast_node_ref_t cm_ref = mod_root->root.members;
if (!cm_ref)
return 0;
spl_ast_node_t *cm = spl_ast_node(mod_ast, cm_ref);
if (cm->resolved_def_id) {
spl_def_node_t *d = spl_def_node(sema->type, cm->resolved_def_id);
if (d && d->lang_id)
return d->lang_id;
}
spl_ast_t *saved_ast = sema->ast;
spl_scope_id_t saved_root = sema->scope->root_scope;
spl_scope_id_t saved_cur = sema->scope->current_scope;
spl_lang_type_id_t saved_agg = sema->current_aggregate_lang;
sema->ast = mod_ast;
sema->scope->root_scope = 0;
sema->scope->current_scope = 0;
sema->current_aggregate_lang = 0;
spl_sema_run_module(sema, cm_ref);
spl_lang_type_id_t t = 0;
spl_ast_node_t *cm_after = spl_ast_node(mod_ast, cm_ref);
if (cm_after->resolved_def_id)
t = sema_eval_decl(sema, cm_after->resolved_def_id);
sema->ast = saved_ast;
sema->scope->root_scope = saved_root;
sema->scope->current_scope = saved_cur;
sema->current_aggregate_lang = saved_agg;
return t;
} }
static spl_lang_type_id_t sema_eval_decl(spl_sema_t *sema, spl_def_id_t def_id) { static spl_lang_type_id_t sema_eval_decl(spl_sema_t *sema, spl_def_id_t def_id) {
@@ -364,7 +506,11 @@ static spl_lang_type_id_t sema_eval_decl(spl_sema_t *sema, spl_def_id_t def_id)
if (def->state == SPL_DECL_RESOLVED || def->state == SPL_DECL_ERROR) if (def->state == SPL_DECL_RESOLVED || def->state == SPL_DECL_ERROR)
return def->lang_id; return def->lang_id;
/* RESOLVING 中途但 lang_id 已被 reserve 阶段回填:直接返回。
A ↔ B 相互引用时 B 引用 A 就走这条短路。 */
if (def->lang_id != 0) { if (def->lang_id != 0) {
if (def->state == SPL_DECL_RESOLVING)
return def->lang_id;
def->state = SPL_DECL_RESOLVED; def->state = SPL_DECL_RESOLVED;
return def->lang_id; return def->lang_id;
} }
@@ -376,9 +522,29 @@ static spl_lang_type_id_t sema_eval_decl(spl_sema_t *sema, spl_def_id_t def_id)
return 0; return 0;
} }
/* 提前取所有 def 字段:sema_infer_* / sema_build_* 会 push def_table,def 悬垂。 */
spl_ast_t *owner_ast = def->owner_ast;
spl_def_id_t owner_def_id = def->owner_def;
usize ast_node_ref = def->ast_node_ref;
spl_dbg_node_t dbg_node = def->dbg_node;
if (!owner_ast) {
spl_diag_error(sema->diag, SPL_DIAG_KIND_INTERNAL, &dbg_node, "def#%zu has no owner_ast",
def_id);
spl_def_node_t *d2 = spl_def_node(sema->type, def_id);
if (d2)
d2->state = SPL_DECL_ERROR;
return 0;
}
spl_ast_t *saved_ast = sema->ast;
sema->ast = owner_ast;
def = spl_def_node(sema->type, def_id);
if (def)
def->state = SPL_DECL_RESOLVING; def->state = SPL_DECL_RESOLVING;
spl_ast_node_t *n = spl_ast_node(sema->ast, def->ast_node_ref); spl_ast_node_t *n = spl_ast_node(sema->ast, ast_node_ref);
spl_lang_type_id_t result = 0; spl_lang_type_id_t result = 0;
if (n) { if (n) {
@@ -396,8 +562,8 @@ static spl_lang_type_id_t sema_eval_decl(spl_sema_t *sema, spl_def_id_t def_id)
} }
case SPL_AST_FN_DECL: { case SPL_AST_FN_DECL: {
spl_lang_type_id_t saved_agg = sema->current_aggregate_lang; spl_lang_type_id_t saved_agg = sema->current_aggregate_lang;
if (def->owner_def) { if (owner_def_id) {
spl_def_node_t *owner = spl_def_node(sema->type, def->owner_def); spl_def_node_t *owner = spl_def_node(sema->type, owner_def_id);
if (owner && owner->lang_id != 0) if (owner && owner->lang_id != 0)
sema->current_aggregate_lang = owner->lang_id; sema->current_aggregate_lang = owner->lang_id;
} }
@@ -413,6 +579,10 @@ static spl_lang_type_id_t sema_eval_decl(spl_sema_t *sema, spl_def_id_t def_id)
result = sema_infer(sema, n->var_const_decl.init_expr); result = sema_infer(sema, n->var_const_decl.init_expr);
break; break;
} }
case SPL_AST_CONTAINER_MEMBERS:
result = sema_build_container_aggregate(sema, n, def_id);
n->resolved_lang_tid = result;
break;
default: default:
break; break;
} }
@@ -420,9 +590,14 @@ static spl_lang_type_id_t sema_eval_decl(spl_sema_t *sema, spl_def_id_t def_id)
spl_def_node_t *final_def = spl_def_node(sema->type, def_id); spl_def_node_t *final_def = spl_def_node(sema->type, def_id);
if (final_def) { if (final_def) {
/* reserve 阶段已回填 lang_id 时,即使 result==0(构建失败)也不清掉身份,
后续引用拿到 ERROR 状态节点而非报环。 */
if (result != 0)
final_def->lang_id = result; final_def->lang_id = result;
final_def->state = result ? SPL_DECL_RESOLVED : SPL_DECL_ERROR; final_def->state = result ? SPL_DECL_RESOLVED : SPL_DECL_ERROR;
} }
sema->ast = saved_ast;
return result; return result;
} }
@@ -443,7 +618,7 @@ static void sema_collect_names(spl_sema_t *sema, spl_ast_node_ref_t ref) {
sema->scope->current_scope = mod_scope; sema->scope->current_scope = mod_scope;
spl_symbol_t file_sym = {.name = "$file", .kind = SPL_SYMBOL_KIND_TYPE}; spl_symbol_t file_sym = {.name = "$file", .kind = SPL_SYMBOL_KIND_TYPE};
file_sym.node = spl_def_alloc(sema->type, SPL_DEF_AGG, "$file", n->dbg, ref); file_sym.node = spl_def_alloc(sema->type, SPL_DEF_AGG, "$file", n->dbg, sema->ast, ref);
n->resolved_def_id = file_sym.node; n->resolved_def_id = file_sym.node;
spl_scope_insert(sema->scope, mod_scope, file_sym); spl_scope_insert(sema->scope, mod_scope, file_sym);
@@ -461,9 +636,9 @@ static void sema_collect_names(spl_sema_t *sema, spl_ast_node_ref_t ref) {
return; return;
} }
if (te->kind == SPL_AST_TYPE_AGGREGATE) if (te->kind == SPL_AST_TYPE_AGGREGATE)
sym.node = spl_def_alloc(sema->type, SPL_DEF_AGG, sym.name, te->dbg, ref); sym.node = spl_def_alloc(sema->type, SPL_DEF_AGG, sym.name, te->dbg, sema->ast, ref);
else else
sym.node = spl_def_alloc(sema->type, SPL_DEF_SCALAR, sym.name, te->dbg, ref); sym.node = spl_def_alloc(sema->type, SPL_DEF_SCALAR, sym.name, te->dbg, sema->ast, ref);
n->resolved_def_id = sym.node; n->resolved_def_id = sym.node;
if (!spl_scope_insert(sema->scope, sema->scope->current_scope, sym)) { if (!spl_scope_insert(sema->scope, sema->scope->current_scope, sym)) {
spl_diag_error(sema->diag, SPL_DIAG_KIND_DUPLICATE_SYMBOL, &n->dbg, spl_diag_error(sema->diag, SPL_DIAG_KIND_DUPLICATE_SYMBOL, &n->dbg,
@@ -473,7 +648,7 @@ static void sema_collect_names(spl_sema_t *sema, spl_ast_node_ref_t ref) {
} }
case SPL_AST_FN_DECL: { case SPL_AST_FN_DECL: {
spl_symbol_t sym = {.name = n->fn_decl.name, .kind = SPL_SYMBOL_KIND_FN}; spl_symbol_t sym = {.name = n->fn_decl.name, .kind = SPL_SYMBOL_KIND_FN};
sym.node = spl_def_alloc(sema->type, SPL_DEF_FN, sym.name, n->dbg, ref); sym.node = spl_def_alloc(sema->type, SPL_DEF_FN, sym.name, n->dbg, sema->ast, ref);
n->resolved_def_id = sym.node; n->resolved_def_id = sym.node;
if (!spl_scope_insert(sema->scope, sema->scope->current_scope, sym)) { if (!spl_scope_insert(sema->scope, sema->scope->current_scope, sym)) {
spl_diag_error(sema->diag, SPL_DIAG_KIND_DUPLICATE_SYMBOL, &n->dbg, spl_diag_error(sema->diag, SPL_DIAG_KIND_DUPLICATE_SYMBOL, &n->dbg,
@@ -487,7 +662,7 @@ static void sema_collect_names(spl_sema_t *sema, spl_ast_node_ref_t ref) {
if (pat && pat->kind == SPL_AST_PATTERN_IDENT) { if (pat && pat->kind == SPL_AST_PATTERN_IDENT) {
const char *name = pat->pattern_ident.name; const char *name = pat->pattern_ident.name;
spl_symbol_t sym = {.name = name, .kind = SPL_SYMBOL_KIND_VAR}; spl_symbol_t sym = {.name = name, .kind = SPL_SYMBOL_KIND_VAR};
sym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, name, n->dbg, ref); sym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, name, n->dbg, sema->ast, ref);
n->resolved_def_id = sym.node; n->resolved_def_id = sym.node;
if (!spl_scope_insert(sema->scope, sema->scope->current_scope, sym)) { if (!spl_scope_insert(sema->scope, sema->scope->current_scope, sym)) {
spl_diag_error(sema->diag, SPL_DIAG_KIND_DUPLICATE_SYMBOL, &n->dbg, spl_diag_error(sema->diag, SPL_DIAG_KIND_DUPLICATE_SYMBOL, &n->dbg,
@@ -585,7 +760,7 @@ static spl_lang_type_id_t sema_intrin_call(spl_sema_t *sema, spl_ast_node_t *n,
return 0; return 0;
spl_type_id_t ft = spl_lang_type_get_ir_type(sema->type, src_lang); spl_type_id_t ft = spl_lang_type_get_ir_type(sema->type, src_lang);
spl_type_id_t tt = spl_lang_type_get_ir_type(sema->type, dst_lang); spl_type_id_t tt = spl_lang_type_get_ir_type(sema->type, dst_lang);
spl_intrin_t expected = spl_intrin_lookup_cast(sema->type, ft, tt); spl_intrin_t expected = spl_intrin_lookup_cast(&sema->type->ir, ft, tt);
if (expected == SPL_INTRIN_NONE) { if (expected == SPL_INTRIN_NONE) {
spl_diag_error(sema->diag, SPL_DIAG_KIND_CAST_INVALID, &n->dbg, spl_diag_error(sema->diag, SPL_DIAG_KIND_CAST_INVALID, &n->dbg,
"`%s`: incompatible types", info->name); "`%s`: incompatible types", info->name);
@@ -670,10 +845,9 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
if (already == expected) if (already == expected)
return expected; return expected;
/* 已定型 */
if (already != 0) { if (already != 0) {
spl_lang_type_node_t *an = spl_lang_type_node(sema->type, already); spl_lang_type_node_t *an = spl_lang_type_node(sema->type, already);
spl_type_node_t *air = an ? spl_type_node(sema->type, an->ir_type_id) : NULL; spl_type_node_t *air = an ? spl_type_node(&sema->type->ir, an->ir_type_id) : NULL;
bool a_rebindable = bool a_rebindable =
(an && an->kind == SPL_LANG_TYPE_INFER) || (an && an->kind == SPL_LANG_TYPE_INFER) ||
(an && an->kind == SPL_LANG_TYPE_INT && air && air->int_type.bits == 0) || (an && an->kind == SPL_LANG_TYPE_INT && air && air->int_type.bits == 0) ||
@@ -694,9 +868,7 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
n->resolved_lang_tid = 0; n->resolved_lang_tid = 0;
} }
/* 未定型的构造性节点 */
switch (n->kind) { switch (n->kind) {
case SPL_AST_EXPR_UNARY: { case SPL_AST_EXPR_UNARY: {
if (n->unary.op == SPL_UNARY_OP_ADDRESS || n->unary.op == SPL_UNARY_OP_DEREF) if (n->unary.op == SPL_UNARY_OP_ADDRESS || n->unary.op == SPL_UNARY_OP_DEREF)
break; break;
@@ -764,7 +936,7 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
"pointer offset must be integer"); "pointer offset must be integer");
return 0; return 0;
} }
spl_type_node_t *rn_ir = spl_type_node(sema->type, rn->ir_type_id); spl_type_node_t *rn_ir = spl_type_node(&sema->type->ir, rn->ir_type_id);
if (rn_ir && rn_ir->int_type.bits == 0) { if (rn_ir && rn_ir->int_type.bits == 0) {
spl_lang_type_id_t it = spl_lang_type_id_t it =
spl_lang_make_int(sema->type, sizeof(void *) * 8, 1); spl_lang_make_int(sema->type, sizeof(void *) * 8, 1);
@@ -842,7 +1014,7 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
} }
spl_type_id_t agg_ir = spl_lang_type_get_ir_type(sema->type, expected); spl_type_id_t agg_ir = spl_lang_type_get_ir_type(sema->type, expected);
spl_type_node_t *irn = spl_type_node(sema->type, agg_ir); spl_type_node_t *irn = spl_type_node(&sema->type->ir, agg_ir);
if (!irn) { if (!irn) {
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg, spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
"aggregate type unresolved"); "aggregate type unresolved");
@@ -862,7 +1034,8 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
return 0; return 0;
} }
usize idx = 0; usize idx = 0;
if (!spl_type_agg_member_idx(sema->type, agg_ir, item->struct_init_item.name, &idx)) { if (!spl_type_agg_member_idx(&sema->type->ir, agg_ir, item->struct_init_item.name,
&idx)) {
spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &item->dbg, "no variant `%s`", spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &item->dbg, "no variant `%s`",
item->struct_init_item.name); item->struct_init_item.name);
return 0; return 0;
@@ -882,7 +1055,8 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
if (!item || item->kind != SPL_AST_STRUCT_INIT_ITEM) if (!item || item->kind != SPL_AST_STRUCT_INIT_ITEM)
continue; continue;
usize idx = 0; usize idx = 0;
if (!spl_type_agg_member_idx(sema->type, agg_ir, item->struct_init_item.name, &idx)) { if (!spl_type_agg_member_idx(&sema->type->ir, agg_ir, item->struct_init_item.name,
&idx)) {
spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &item->dbg, "no field `%s`", spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &item->dbg, "no field `%s`",
item->struct_init_item.name); item->struct_init_item.name);
continue; continue;
@@ -925,7 +1099,6 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
break; break;
} }
/* 兜底:infer 后按子类型 / comptime 判定 */
spl_lang_type_id_t from = sema_infer(sema, ref); spl_lang_type_id_t from = sema_infer(sema, ref);
if (!from) if (!from)
return 0; return 0;
@@ -934,8 +1107,8 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
spl_lang_type_node_t *from_n = spl_lang_type_node(sema->type, from); spl_lang_type_node_t *from_n = spl_lang_type_node(sema->type, from);
spl_lang_type_node_t *to_n = spl_lang_type_node(sema->type, expected); spl_lang_type_node_t *to_n = spl_lang_type_node(sema->type, expected);
spl_type_node_t *from_ir = from_n ? spl_type_node(sema->type, from_n->ir_type_id) : NULL; spl_type_node_t *from_ir = from_n ? spl_type_node(&sema->type->ir, from_n->ir_type_id) : NULL;
spl_type_node_t *to_ir = to_n ? spl_type_node(sema->type, to_n->ir_type_id) : NULL; spl_type_node_t *to_ir = to_n ? spl_type_node(&sema->type->ir, to_n->ir_type_id) : NULL;
bool from_comptime_int = bool from_comptime_int =
from_n && from_n->kind == SPL_LANG_TYPE_INT && from_ir && from_ir->int_type.bits == 0; from_n && from_n->kind == SPL_LANG_TYPE_INT && from_ir && from_ir->int_type.bits == 0;
@@ -983,7 +1156,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
switch (n->kind) { switch (n->kind) {
/* ---------- 字面量 ---------- */
case SPL_AST_EXPR_INT_LIT: { case SPL_AST_EXPR_INT_LIT: {
spl_lang_type_id_t t = spl_lang_make_int(sema->type, 0, 1); spl_lang_type_id_t t = spl_lang_make_int(sema->type, 0, 1);
n->resolved_lang_tid = t; n->resolved_lang_tid = t;
@@ -1022,7 +1194,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
return t; return t;
} }
/* ---------- IDENT ---------- */
case SPL_AST_EXPR_IDENT: { case SPL_AST_EXPR_IDENT: {
const char *name = n->ident.name; const char *name = n->ident.name;
spl_symbol_t sym; spl_symbol_t sym;
@@ -1042,7 +1213,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
return t; return t;
} }
/* ---------- UNARY ---------- */
case SPL_AST_EXPR_UNARY: { case SPL_AST_EXPR_UNARY: {
spl_lang_type_id_t op = sema_infer(sema, n->unary.operand); spl_lang_type_id_t op = sema_infer(sema, n->unary.operand);
if (op == 0) if (op == 0)
@@ -1094,7 +1264,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
} }
} }
/* ---------- BINARY ---------- */
case SPL_AST_EXPR_BINARY: { case SPL_AST_EXPR_BINARY: {
spl_binary_op_t op = n->binary.op; spl_binary_op_t op = n->binary.op;
@@ -1174,7 +1343,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
if (ln && ln->kind == SPL_LANG_TYPE_PTR && rn && rn->kind == SPL_LANG_TYPE_INT && if (ln && ln->kind == SPL_LANG_TYPE_PTR && rn && rn->kind == SPL_LANG_TYPE_INT &&
(op == SPL_OP_ADD || op == SPL_OP_SUB)) { (op == SPL_OP_ADD || op == SPL_OP_SUB)) {
spl_type_node_t *rn_ir = spl_type_node(sema->type, rn->ir_type_id); spl_type_node_t *rn_ir = spl_type_node(&sema->type->ir, rn->ir_type_id);
if (rn_ir && rn_ir->int_type.bits == 0) { if (rn_ir && rn_ir->int_type.bits == 0) {
spl_lang_type_id_t it = spl_lang_make_int(sema->type, sizeof(void *) * 8, 1); spl_lang_type_id_t it = spl_lang_make_int(sema->type, sizeof(void *) * 8, 1);
sema_coerce(sema, n->binary.right, it); sema_coerce(sema, n->binary.right, it);
@@ -1200,7 +1369,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
return common; return common;
} }
/* ---------- CALL ---------- */
case SPL_AST_EXPR_CALL: { case SPL_AST_EXPR_CALL: {
spl_ast_node_t *callee = spl_ast_node(sema->ast, n->call.callee); spl_ast_node_t *callee = spl_ast_node(sema->ast, n->call.callee);
if (callee && callee->kind == SPL_AST_EXPR_IDENT) { if (callee && callee->kind == SPL_AST_EXPR_IDENT) {
@@ -1243,8 +1411,10 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
} }
for (usize i = 0; i < nargs && i < fixed; ++i) { for (usize i = 0; i < nargs && i < fixed; ++i) {
spl_lang_type_id_t pt = spl_lang_type_node_t *fn2 = spl_lang_type_node(sema->type, callee_tid);
vec_at(spl_lang_type_node(sema->type, callee_tid)->extra.fn.params, i); if (!fn2)
return 0;
spl_lang_type_id_t pt = vec_at(fn2->extra.fn.params, i);
if (!sema_coerce(sema, vec_at(n->call.args, i), pt)) if (!sema_coerce(sema, vec_at(n->call.args, i), pt))
return 0; return 0;
} }
@@ -1261,7 +1431,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
return ret; return ret;
} }
/* ---------- FIELD ---------- */
case SPL_AST_EXPR_FIELD: { case SPL_AST_EXPR_FIELD: {
spl_lang_type_id_t obj_tid = sema_infer(sema, n->field.obj); spl_lang_type_id_t obj_tid = sema_infer(sema, n->field.obj);
spl_lang_type_node_t *obj = spl_lang_type_node(sema->type, obj_tid); spl_lang_type_node_t *obj = spl_lang_type_node(sema->type, obj_tid);
@@ -1287,7 +1456,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
spl_type_id_t agg_ir = spl_lang_type_get_ir_type(sema->type, agg_lang); spl_type_id_t agg_ir = spl_lang_type_get_ir_type(sema->type, agg_lang);
if (agg_ir) { if (agg_ir) {
const spl_type_member_t *m = spl_type_agg_member(sema->type, agg_ir, n->field.field); const spl_type_member_t *m =
spl_type_agg_member(&sema->type->ir, agg_ir, n->field.field);
if (m) { if (m) {
spl_lang_type_id_t ft = sema_lang_from_ir(sema, m->type_id); spl_lang_type_id_t ft = sema_lang_from_ir(sema, m->type_id);
if (!ft) { if (!ft) {
@@ -1300,12 +1470,18 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
} }
} }
for (usize i = 0; i < vec_size(agg->methods); ++i) { const char *fname = n->field.field;
spl_lang_method_t *meth = &vec_at(agg->methods, i); usize nmethods = vec_size(agg->methods);
if (strcmp(meth->name, n->field.field) != 0) for (usize i = 0; i < nmethods; ++i) {
spl_lang_type_node_t *agg2 = spl_lang_type_node(sema->type, agg_lang);
if (!agg2)
break;
spl_lang_method_t *meth = &vec_at(agg2->methods, i);
if (strcmp(meth->name, fname) != 0)
continue; continue;
n->resolved_def_id = meth->def_id; spl_def_id_t did = meth->def_id;
spl_lang_type_id_t t = sema_eval_decl(sema, meth->def_id); n->resolved_def_id = did;
spl_lang_type_id_t t = sema_eval_decl(sema, did);
n->resolved_lang_tid = t; n->resolved_lang_tid = t;
return t; return t;
} }
@@ -1315,7 +1491,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
return 0; return 0;
} }
/* ---------- INDEX ---------- */
case SPL_AST_EXPR_INDEX: { case SPL_AST_EXPR_INDEX: {
spl_lang_type_id_t obj_tid = sema_infer(sema, n->index.obj); spl_lang_type_id_t obj_tid = sema_infer(sema, n->index.obj);
sema_infer(sema, n->index.index); sema_infer(sema, n->index.index);
@@ -1355,7 +1530,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
return elem; return elem;
} }
/* ---------- SLICE ---------- */
case SPL_AST_EXPR_SLICE: { case SPL_AST_EXPR_SLICE: {
spl_lang_type_id_t obj_tid = sema_infer(sema, n->slice.obj); spl_lang_type_id_t obj_tid = sema_infer(sema, n->slice.obj);
if (n->slice.begin) if (n->slice.begin)
@@ -1379,7 +1553,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
return s; return s;
} }
/* ---------- CAST ---------- */
case SPL_AST_EXPR_CAST: { case SPL_AST_EXPR_CAST: {
spl_lang_type_id_t dst_lang = sema_infer(sema, n->cast.type); spl_lang_type_id_t dst_lang = sema_infer(sema, n->cast.type);
if (!dst_lang) if (!dst_lang)
@@ -1389,7 +1562,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
return 0; return 0;
spl_lang_type_node_t *sn = spl_lang_type_node(sema->type, src_lang); spl_lang_type_node_t *sn = spl_lang_type_node(sema->type, src_lang);
spl_type_node_t *sir = sn ? spl_type_node(sema->type, sn->ir_type_id) : NULL; spl_type_node_t *sir = sn ? spl_type_node(&sema->type->ir, sn->ir_type_id) : NULL;
bool src_is_literal_int = bool src_is_literal_int =
sn && sn->kind == SPL_LANG_TYPE_INT && sir && sir->int_type.bits == 0; sn && sn->kind == SPL_LANG_TYPE_INT && sir && sir->int_type.bits == 0;
bool src_is_literal_float = bool src_is_literal_float =
@@ -1414,7 +1587,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
"as: unresolved source or target type"); "as: unresolved source or target type");
return 0; return 0;
} }
spl_intrin_t in = spl_intrin_lookup_cast(sema->type, ft, tt); spl_intrin_t in = spl_intrin_lookup_cast(&sema->type->ir, ft, tt);
if (in == SPL_INTRIN_NONE) { if (in == SPL_INTRIN_NONE) {
spl_diag_error(sema->diag, SPL_DIAG_KIND_CAST_INVALID, &n->dbg, spl_diag_error(sema->diag, SPL_DIAG_KIND_CAST_INVALID, &n->dbg,
"as: invalid conversion (not supported by as)"); "as: invalid conversion (not supported by as)");
@@ -1424,7 +1597,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
return dst_lang; return dst_lang;
} }
/* ---------- TUPLE ---------- */
case SPL_AST_EXPR_TUPLE: { case SPL_AST_EXPR_TUPLE: {
spl_lang_type_id_vec_t es; spl_lang_type_id_vec_t es;
vec_init(es); vec_init(es);
@@ -1437,7 +1609,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
return t; return t;
} }
/* ---------- ARRAY_LIT ---------- */
case SPL_AST_EXPR_ARRAY_LIT: { case SPL_AST_EXPR_ARRAY_LIT: {
spl_lang_type_id_t elem_t = 0; spl_lang_type_id_t elem_t = 0;
if (n->array_literal.elem_type) if (n->array_literal.elem_type)
@@ -1467,7 +1638,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
return arr; return arr;
} }
/* ---------- AGGREGATE_LIT ---------- */
case SPL_AST_EXPR_AGGREGATE_LIT: { case SPL_AST_EXPR_AGGREGATE_LIT: {
const char *type_name = n->aggregate_literal.name; const char *type_name = n->aggregate_literal.name;
if (!type_name) { if (!type_name) {
@@ -1501,7 +1671,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
return 0; return 0;
} }
spl_type_id_t agg_ir = spl_lang_type_get_ir_type(sema->type, agg); spl_type_id_t agg_ir = spl_lang_type_get_ir_type(sema->type, agg);
spl_type_node_t *irn = spl_type_node(sema->type, agg_ir); spl_type_node_t *irn = spl_type_node(&sema->type->ir, agg_ir);
if (irn) { if (irn) {
for (usize i = 0; i < vec_size(n->aggregate_literal.fields); ++i) { for (usize i = 0; i < vec_size(n->aggregate_literal.fields); ++i) {
spl_ast_node_t *item = spl_ast_node_t *item =
@@ -1509,7 +1679,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
if (!item || item->kind != SPL_AST_STRUCT_INIT_ITEM) if (!item || item->kind != SPL_AST_STRUCT_INIT_ITEM)
continue; continue;
usize idx = 0; usize idx = 0;
if (!spl_type_agg_member_idx(sema->type, agg_ir, item->struct_init_item.name, if (!spl_type_agg_member_idx(&sema->type->ir, agg_ir, item->struct_init_item.name,
&idx)) { &idx)) {
spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &item->dbg, "no field `%s`", spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &item->dbg, "no field `%s`",
item->struct_init_item.name); item->struct_init_item.name);
@@ -1525,8 +1695,21 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
return agg; return agg;
} }
/* ---------- COMPTIME_CALL ---------- */
case SPL_AST_EXPR_COMPTIME_CALL: { case SPL_AST_EXPR_COMPTIME_CALL: {
if (n->comptime_call.name && strcmp(n->comptime_call.name, "import") == 0) {
spl_lang_type_id_t t = sema_import(sema, n, &n->comptime_call.args);
n->resolved_lang_tid = t;
return t;
}
if (n->comptime_call.name && strcmp(n->comptime_call.name, "self") == 0) {
if (sema->current_aggregate_lang == 0) {
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNDEFINED_SYMBOL, &n->dbg,
"`@self` outside of aggregate");
return 0;
}
n->resolved_lang_tid = sema->current_aggregate_lang;
return sema->current_aggregate_lang;
}
spl_intrin_t in = spl_intrin_lookup_call(n->comptime_call.name); spl_intrin_t in = spl_intrin_lookup_call(n->comptime_call.name);
if (in == SPL_INTRIN_NONE) { if (in == SPL_INTRIN_NONE) {
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNKNOWN_INTRIN, &n->dbg, spl_diag_error(sema->diag, SPL_DIAG_KIND_UNKNOWN_INTRIN, &n->dbg,
@@ -1538,11 +1721,9 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
return t; return t;
} }
/* ---------- BLOCK ---------- */
case SPL_AST_EXPR_BLOCK: case SPL_AST_EXPR_BLOCK:
return sema_block_body(sema, n, 0); return sema_block_body(sema, n, 0);
/* ---------- IF ---------- */
case SPL_AST_EXPR_IF: { case SPL_AST_EXPR_IF: {
spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); spl_lang_type_id_t bt = spl_lang_make_bool(sema->type);
sema_coerce(sema, n->if_expr.cond, bt); sema_coerce(sema, n->if_expr.cond, bt);
@@ -1560,7 +1741,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
return result; return result;
} }
/* ---------- IFVAR / WHILE / LOOP / FOR / MATCH ---------- */
case SPL_AST_EXPR_IFVAR: { case SPL_AST_EXPR_IFVAR: {
sema_infer(sema, n->ifvar_expr.var_decl); sema_infer(sema, n->ifvar_expr.var_decl);
if (n->ifvar_expr.then_block) if (n->ifvar_expr.then_block)
@@ -1623,7 +1803,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
if (strcmp(var_name, "_") != 0) { if (strcmp(var_name, "_") != 0) {
spl_symbol_t sym = {.name = var_name, .kind = SPL_SYMBOL_KIND_VAR}; spl_symbol_t sym = {.name = var_name, .kind = SPL_SYMBOL_KIND_VAR};
sym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, var_name, id_node->dbg, sym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, var_name, id_node->dbg,
vec_at(n->for_expr.idents, i)); sema->ast, vec_at(n->for_expr.idents, i));
spl_def_resolve(sema->type, sym.node, elem_tid); spl_def_resolve(sema->type, sym.node, elem_tid);
if (!spl_scope_insert(sema->scope, sema->scope->current_scope, sym)) { if (!spl_scope_insert(sema->scope, sema->scope->current_scope, sym)) {
spl_diag_error(sema->diag, SPL_DIAG_KIND_DUPLICATE_SYMBOL, spl_diag_error(sema->diag, SPL_DIAG_KIND_DUPLICATE_SYMBOL,
@@ -1656,7 +1836,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
return 0; return 0;
} }
/* ---------- FN_TYPE ---------- */
case SPL_AST_EXPR_FN_TYPE: { case SPL_AST_EXPR_FN_TYPE: {
spl_lang_type_id_vec_t ps; spl_lang_type_id_vec_t ps;
vec_init(ps); vec_init(ps);
@@ -1670,7 +1849,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
return fn; return fn;
} }
/* ---------- 类型表达式 ---------- */
case SPL_AST_TYPE_PATH: { case SPL_AST_TYPE_PATH: {
const char *name = n->type_path.name; const char *name = n->type_path.name;
spl_lang_type_id_t b = spl_type_lookup_builtin(sema->type, name); spl_lang_type_id_t b = spl_type_lookup_builtin(sema->type, name);
@@ -1754,10 +1932,14 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
n->resolved_lang_tid = sema->current_aggregate_lang; n->resolved_lang_tid = sema->current_aggregate_lang;
return sema->current_aggregate_lang; return sema->current_aggregate_lang;
} }
if (name && strcmp(name, "import") == 0) {
spl_lang_type_id_t t = sema_import(sema, n, &n->type_comptime_call.args);
n->resolved_lang_tid = t;
return t;
}
return 0; return 0;
} }
/* ---------- 顶层声明 ---------- */
case SPL_AST_CONTAINER_MEMBERS: case SPL_AST_CONTAINER_MEMBERS:
for (usize i = 0; i < vec_size(n->container_members.declarations); ++i) for (usize i = 0; i < vec_size(n->container_members.declarations); ++i)
sema_infer(sema, vec_at(n->container_members.declarations, i)); sema_infer(sema, vec_at(n->container_members.declarations, i));
@@ -1795,7 +1977,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
spl_ast_node_t *pd = spl_ast_node(sema->ast, vec_at(n->fn_decl.params, i)); spl_ast_node_t *pd = spl_ast_node(sema->ast, vec_at(n->fn_decl.params, i));
if (pd && pd->kind == SPL_AST_PARAM_DECL) { if (pd && pd->kind == SPL_AST_PARAM_DECL) {
spl_symbol_t psym = {.name = pd->param_decl.name, .kind = SPL_SYMBOL_KIND_VAR}; spl_symbol_t psym = {.name = pd->param_decl.name, .kind = SPL_SYMBOL_KIND_VAR};
psym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, psym.name, pd->dbg, psym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, psym.name, pd->dbg, sema->ast,
vec_at(n->fn_decl.params, i)); vec_at(n->fn_decl.params, i));
spl_lang_type_id_t p_tid = sema_infer(sema, pd->param_decl.type_expr); spl_lang_type_id_t p_tid = sema_infer(sema, pd->param_decl.type_expr);
spl_def_node_t *pdef = spl_def_node(sema->type, psym.node); spl_def_node_t *pdef = spl_def_node(sema->type, psym.node);
@@ -1845,7 +2027,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
return lang; return lang;
} }
/* ---------- VAR / CONST ---------- */
case SPL_AST_VAR_DECL: case SPL_AST_VAR_DECL:
case SPL_AST_CONST_DECL: { case SPL_AST_CONST_DECL: {
spl_ast_node_t *pat = spl_ast_node(sema->ast, n->var_const_decl.pattern); spl_ast_node_t *pat = spl_ast_node(sema->ast, n->var_const_decl.pattern);
@@ -1858,7 +2039,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
if (n->resolved_def_id == 0) { if (n->resolved_def_id == 0) {
spl_symbol_t sym = {.name = name, .kind = SPL_SYMBOL_KIND_VAR}; spl_symbol_t sym = {.name = name, .kind = SPL_SYMBOL_KIND_VAR};
sym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, name, n->dbg, ref); sym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, name, n->dbg, sema->ast, ref);
n->resolved_def_id = sym.node; n->resolved_def_id = sym.node;
if (!spl_scope_insert(sema->scope, sema->scope->current_scope, sym)) { if (!spl_scope_insert(sema->scope, sema->scope->current_scope, sym)) {
spl_diag_error(sema->diag, SPL_DIAG_KIND_DUPLICATE_SYMBOL, &n->dbg, spl_diag_error(sema->diag, SPL_DIAG_KIND_DUPLICATE_SYMBOL, &n->dbg,
@@ -1892,7 +2073,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
return decl_tid; return decl_tid;
} }
/* ---------- MEMBER / PARAM ---------- */
case SPL_AST_MEMBER_DECL: case SPL_AST_MEMBER_DECL:
if (n->member_decl.type_expr) if (n->member_decl.type_expr)
return sema_infer(sema, n->member_decl.type_expr); return sema_infer(sema, n->member_decl.type_expr);
@@ -1902,7 +2082,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
return sema_infer(sema, n->param_decl.type_expr); return sema_infer(sema, n->param_decl.type_expr);
return 0; return 0;
/* ---------- 语句 ---------- */
case SPL_AST_STATEMENT_RET: { case SPL_AST_STATEMENT_RET: {
if (n->statement_ret.expr) { if (n->statement_ret.expr) {
if (sema->current_fn_ret_tid) if (sema->current_fn_ret_tid)
@@ -2009,7 +2188,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
return 0; return 0;
} }
void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_scope_t *scope, void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_lang_type_t *type, spl_scope_t *scope,
spl_attr_t *attr) { spl_attr_t *attr) {
Assert(sema != NULL && ast != NULL && type != NULL && scope != NULL && attr != NULL); Assert(sema != NULL && ast != NULL && type != NULL && scope != NULL && attr != NULL);
sema->ast = ast; sema->ast = ast;
@@ -2021,6 +2200,7 @@ void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_scope
sema->attr = attr; sema->attr = attr;
sema->root = (spl_symbol_t){0}; sema->root = (spl_symbol_t){0};
vec_init(sema->label_stack); vec_init(sema->label_stack);
sema->loader = NULL;
sema->diag = NULL; sema->diag = NULL;
} }
@@ -2046,6 +2226,10 @@ void spl_sema_run(spl_sema_t *sema) {
if (!root || root->kind != SPL_AST_ROOT) if (!root || root->kind != SPL_AST_ROOT)
return; return;
spl_sema_run_module(sema, root->root.members); spl_sema_run_module(sema, root->root.members);
spl_ast_node_t *cm = spl_ast_node(sema->ast, root->root.members);
if (cm && cm->resolved_def_id)
sema_eval_decl(sema, cm->resolved_def_id);
} }
void spl_sema_dump(spl_sema_t *sema) { void spl_sema_dump(spl_sema_t *sema) {
@@ -2066,9 +2250,9 @@ void spl_sema_dump(spl_sema_t *sema) {
printf("\n"); printf("\n");
} }
printf("TypeTable:\n"); printf("TypeTable:\n");
for (usize i = 1; i < vec_size(sema->type->type_table); ++i) { for (usize i = 1; i < vec_size(sema->type->ir.type_table); ++i) {
printf(" type_id#%zu ", i); printf(" type_id#%zu ", i);
spl_type_pure_dump(sema->type, i); spl_type_pure_dump(&sema->type->ir, i);
printf("\n"); printf("\n");
} }
printf("DefTable:\n"); printf("DefTable:\n");
+13 -38
View File
@@ -4,48 +4,23 @@
#include "spl_ast.h" #include "spl_ast.h"
#include "spl_attr.h" #include "spl_attr.h"
#include "spl_diag.h" #include "spl_diag.h"
#include "spl_lang_type.h"
#include "spl_mpa.h" #include "spl_mpa.h"
#include "spl_scope.h"
#include "spl_type.h" #include "spl_type.h"
typedef enum { typedef struct spl_module_loader spl_module_loader_t;
SPL_SYMBOL_KIND_ERROR, struct spl_module_loader {
SPL_SYMBOL_KIND_VAR, /* 从 from_fname 所在目录解析 path;返回该文件的 ast(已 init + parse)。
SPL_SYMBOL_KIND_MEMBER, 失败(文件不存在 / parse 错误 / 环)返回 NULL。
SPL_SYMBOL_KIND_FN, loader 拥有 ast 的生命周期;sema 不负责释放。 */
SPL_SYMBOL_KIND_TYPE, spl_ast_t *(*load)(void *user, const char *from_fname, const char *path, spl_diag_t *diag);
} spl_symbol_kind_t; void *user;
};
typedef struct {
const char *name;
spl_symbol_kind_t kind;
spl_def_id_t node;
} spl_symbol_t;
typedef usize spl_scope_id_t; /* 0 is error */
typedef struct {
spl_scope_id_t parent;
MAP(const char *, spl_symbol_t) symbols;
} spl_scope_node_t;
typedef VEC(spl_scope_node_t) spl_scope_node_vec_t;
typedef struct {
spl_scope_node_vec_t scopes;
spl_scope_id_t root_scope;
spl_scope_id_t current_scope;
} spl_scope_t;
void spl_scope_init(spl_scope_t *scope);
void spl_scope_drop(spl_scope_t *scope);
spl_scope_id_t spl_scope_alloc(spl_scope_t *scope);
bool spl_scope_insert(spl_scope_t *scope, spl_scope_id_t id, spl_symbol_t symbol);
bool spl_scope_find(spl_scope_t *scop, const char *symbol_name, spl_symbol_t *out);
typedef VEC(const char *) spl_symbol_path_t;
typedef struct { typedef struct {
spl_ast_t *ast; spl_ast_t *ast;
spl_type_t *type; spl_lang_type_t *type;
spl_scope_t *scope; spl_scope_t *scope;
spl_symbol_t root; spl_symbol_t root;
spl_attr_t *attr; spl_attr_t *attr;
@@ -53,11 +28,11 @@ typedef struct {
spl_lang_type_id_t current_fn_ret_tid; spl_lang_type_id_t current_fn_ret_tid;
spl_lang_type_id_t current_loop_break_tid; spl_lang_type_id_t current_loop_break_tid;
spl_symbol_path_t label_stack; spl_symbol_path_t label_stack;
const spl_module_loader_t *loader;
spl_diag_t *diag; spl_diag_t *diag;
} spl_sema_t; } spl_sema_t;
void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_scope_t *scope, void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_lang_type_t *type, spl_scope_t *scope,
spl_attr_t *attr); spl_attr_t *attr);
void spl_sema_drop(spl_sema_t *sema); void spl_sema_drop(spl_sema_t *sema);
+15
View File
@@ -0,0 +1,15 @@
#include "spl_tok.h"
const char *spl_tok_type_name(spl_tok_type_t t) {
static const char *const names[] = {
#define X(name, enum_name, dummy) #enum_name,
KEYWORD_TABLE
#undef X
#define X(name, enum_name, dummy) #enum_name,
TOKEN_TABLE
#undef X
};
if ((usize)t < sizeof(names) / sizeof(names[0]))
return names[t];
return "?";
}
+2
View File
@@ -127,4 +127,6 @@ typedef struct {
typedef VEC(spl_tok_t) spl_tok_vec_t; typedef VEC(spl_tok_t) spl_tok_vec_t;
const char *spl_tok_type_name(spl_tok_type_t t);
#endif /* __SPL_TOK_H__ */ #endif /* __SPL_TOK_H__ */
+80 -865
View File
File diff suppressed because it is too large. Load diff
+12 -138
View File
@@ -2,15 +2,9 @@
#define __SPL_TYPE_H__ #define __SPL_TYPE_H__
#include "../stage0/include/utils.h" #include "../stage0/include/utils.h"
#include "spl_dbg.h"
#include "spl_mpa.h"
typedef usize spl_type_id_t; /* 0 is error */ typedef usize spl_type_id_t;
typedef VEC(spl_type_id_t) spl_type_id_vec_t; typedef VEC(spl_type_id_t) spl_type_id_vec_t;
typedef usize spl_lang_type_id_t; /* 0 is error */
typedef VEC(spl_lang_type_id_t) spl_lang_type_id_vec_t;
typedef usize spl_def_id_t; /* 0 is error */
typedef VEC(spl_def_id_t) spl_def_id_vec_t;
typedef enum { typedef enum {
SPL_TYPE_ERROR, SPL_TYPE_ERROR,
@@ -46,13 +40,13 @@ typedef struct {
typedef struct { typedef struct {
const char *name; const char *name;
spl_type_id_t type_id; spl_type_id_t type_id;
usize ast_node_ref; // 回 AST member_decl 节点引用 dbg/IDE 定位用 不参与 hash usize ast_node_ref;
} spl_type_member_t; } spl_type_member_t;
typedef VEC(spl_type_member_t) spl_type_member_vec_t; typedef VEC(spl_type_member_t) spl_type_member_vec_t;
typedef struct { typedef struct {
spl_type_node_kind_t kind; spl_type_node_kind_t kind;
spl_type_layout_t layout; // attribute spl_type_layout_t layout;
union { union {
struct { struct {
usize bits; usize bits;
@@ -71,135 +65,30 @@ typedef struct {
struct { struct {
spl_type_member_vec_t variants; spl_type_member_vec_t variants;
spl_type_id_t tag_type; spl_type_id_t tag_type;
} agg_type; // adt record } agg_type;
struct { struct {
spl_type_id_vec_t params; spl_type_id_vec_t params;
spl_type_id_t ret; spl_type_id_t ret;
} fn_type; } fn_type;
struct { struct {
// TODO
} shape_type; } shape_type;
}; };
} spl_type_node_t; } spl_type_node_t;
typedef VEC(spl_type_node_t) spl_type_node_vec_t; typedef VEC(spl_type_node_t) spl_type_node_vec_t;
typedef enum {
SPL_LANG_TYPE_ERROR,
SPL_LANG_TYPE_INFER,
SPL_LANG_TYPE_NEVER,
SPL_LANG_TYPE_ANY,
SPL_LANG_TYPE_UNIT,
SPL_LANG_TYPE_BOOL,
SPL_LANG_TYPE_INT,
SPL_LANG_TYPE_FLOAT,
SPL_LANG_TYPE_PTR,
SPL_LANG_TYPE_ARRAY,
SPL_LANG_TYPE_SLICE,
SPL_LANG_TYPE_TUPLE,
SPL_LANG_TYPE_RANGE,
SPL_LANG_TYPE_FN,
SPL_LANG_TYPE_STRUCT,
SPL_LANG_TYPE_UNION,
SPL_LANG_TYPE_ENUM,
SPL_LANG_TYPE_SHAPE,
SPL_LANG_TYPE_VARARGS,
} spl_lang_type_kind_t;
typedef struct {
const char *name;
spl_def_id_t def_id;
} spl_lang_method_t;
typedef VEC(spl_lang_method_t) spl_lang_method_vec_t;
typedef struct {
spl_lang_type_kind_t kind;
spl_type_id_t ir_type_id;
spl_lang_method_vec_t methods;
union {
spl_lang_type_id_t elem;
spl_lang_type_id_vec_t elems;
struct {
spl_lang_type_id_vec_t params;
spl_lang_type_id_t ret;
} fn;
} extra;
} spl_lang_type_node_t;
typedef VEC(spl_lang_type_node_t) spl_lang_type_vec_t;
typedef MAP(usize, spl_lang_type_id_t) spl_lang_type_map_t;
typedef enum {
SPL_DEF_ERROR,
SPL_DEF_SCALAR,
SPL_DEF_MEMBER,
SPL_DEF_VAR,
SPL_DEF_FN,
SPL_DEF_AGG,
SPL_DEF_DISTINCT,
SPL_DEF_ALIAS,
SPL_DEF_BUILTIN,
} spl_def_node_kind_t;
typedef enum {
SPL_DECL_UNRESOLVED,
SPL_DECL_RESOLVING,
SPL_DECL_RESOLVED,
SPL_DECL_ERROR,
} spl_decl_state_t;
typedef struct {
spl_def_node_kind_t kind;
const char *name;
spl_dbg_node_t dbg_node;
spl_lang_type_id_t lang_id;
usize ast_node_ref;
spl_decl_state_t state;
spl_def_id_t owner_def;
} spl_def_node_t;
typedef VEC(spl_def_node_t) spl_def_node_vec_t;
typedef MAP(usize, spl_type_id_t) spl_type_node_map_t; typedef MAP(usize, spl_type_id_t) spl_type_node_map_t;
typedef struct { typedef struct {
spl_type_node_vec_t type_table; spl_type_node_vec_t type_table;
spl_type_node_map_t type_map; spl_type_node_map_t type_map;
spl_lang_type_vec_t lang_table;
spl_lang_type_map_t lang_map;
spl_def_node_vec_t def_table;
} spl_type_t; } spl_type_t;
void spl_type_init(spl_type_t *type); void spl_type_init(spl_type_t *type);
void spl_type_drop(spl_type_t *type); void spl_type_drop(spl_type_t *type);
void spl_type_def_dump(spl_type_t *type, spl_def_id_t id);
void spl_type_pure_dump(spl_type_t *type, spl_type_id_t id);
void spl_lang_type_dump(spl_type_t *type, spl_lang_type_id_t id);
spl_type_node_t *spl_type_node(const spl_type_t *type, spl_type_id_t id); spl_type_node_t *spl_type_node(const spl_type_t *type, spl_type_id_t id);
spl_lang_type_node_t *spl_lang_type_node(const spl_type_t *type, spl_lang_type_id_t id);
spl_def_node_t *spl_def_node(const spl_type_t *type, spl_def_id_t id);
bool spl_lang_type_is_subtype(const spl_type_t *type, spl_lang_type_id_t sub,
spl_lang_type_id_t super);
bool spl_type_is_subtype(const spl_type_t *type, spl_type_id_t sub, spl_type_id_t super);
spl_lang_type_id_t spl_lang_node_push(spl_type_t *type, spl_lang_type_node_t *node);
spl_lang_type_id_t spl_lang_type_join(const spl_type_t *type, spl_lang_type_id_t a,
spl_lang_type_id_t b);
bool spl_lang_mpa_int_fits(const spl_type_t *type, spl_lang_type_id_t target, spl_mpa_int_t v);
spl_def_id_t spl_def_alloc(spl_type_t *type, spl_def_node_kind_t kind, const char *name,
spl_dbg_node_t dbg, usize ast_node_ref);
void spl_def_resolve(spl_type_t *type, spl_def_id_t id, spl_lang_type_id_t lang_id);
spl_type_id_t spl_lang_type_get_ir_type(spl_type_t *type, spl_lang_type_id_t lang_id);
spl_lang_type_id_t spl_def_get_lang_id(spl_type_t *type, spl_def_id_t def_id);
spl_type_id_t spl_def_get_type_id(spl_type_t *type, spl_def_id_t def_id);
spl_type_id_t spl_type_fn_param_tid(spl_type_t *type, spl_type_id_t fn_tid, usize idx);
const spl_type_member_t *spl_type_agg_member(spl_type_t *type, spl_type_id_t tid, const char *name);
bool spl_type_agg_member_idx(spl_type_t *type, spl_type_id_t tid, const char *name, usize *out_idx);
spl_type_id_t spl_type_node_push(spl_type_t *type, spl_type_node_t *type_node); spl_type_id_t spl_type_node_push(spl_type_t *type, spl_type_node_t *type_node);
spl_type_id_t spl_type_builder_simple(spl_type_t *type, spl_type_node_kind_t kind); spl_type_id_t spl_type_builder_simple(spl_type_t *type, spl_type_node_kind_t kind);
spl_type_id_t spl_type_builder_int(spl_type_t *type, usize bits, int is_signed); spl_type_id_t spl_type_builder_int(spl_type_t *type, usize bits, int is_signed);
spl_type_id_t spl_type_builder_float(spl_type_t *type, usize bits); spl_type_id_t spl_type_builder_float(spl_type_t *type, usize bits);
@@ -211,27 +100,12 @@ spl_type_id_t spl_type_builder_agg(spl_type_t *type, spl_type_node_kind_t tk,
spl_type_member_vec_t *variants, spl_type_id_t tag_type, spl_type_member_vec_t *variants, spl_type_id_t tag_type,
spl_type_layout_t layout); spl_type_layout_t layout);
spl_lang_type_id_t spl_lang_make_error(spl_type_t *type); void spl_type_pure_dump(spl_type_t *type, spl_type_id_t id);
spl_lang_type_id_t spl_lang_make_infer(spl_type_t *type);
spl_lang_type_id_t spl_lang_make_never(spl_type_t *type);
spl_lang_type_id_t spl_lang_make_any(spl_type_t *type);
spl_lang_type_id_t spl_lang_make_unit(spl_type_t *type);
spl_lang_type_id_t spl_lang_make_bool(spl_type_t *type);
spl_lang_type_id_t spl_lang_make_int(spl_type_t *type, usize bits, int is_signed);
spl_lang_type_id_t spl_lang_make_float(spl_type_t *type, usize bits);
spl_lang_type_id_t spl_lang_make_ptr(spl_type_t *type, spl_lang_type_id_t pointee);
spl_lang_type_id_t spl_lang_make_array(spl_type_t *type, spl_lang_type_id_t elem, usize len);
spl_lang_type_id_t spl_lang_make_slice(spl_type_t *type, spl_lang_type_id_t elem);
spl_lang_type_id_t spl_lang_make_tuple(spl_type_t *type, const spl_lang_type_id_t *elems,
usize count);
spl_lang_type_id_t spl_lang_make_range(spl_type_t *type, spl_lang_type_id_t elem);
spl_lang_type_id_t spl_lang_make_fn(spl_type_t *type, spl_lang_type_id_t ret,
const spl_lang_type_id_t *params, usize nparams);
spl_lang_type_id_t spl_lang_make_aggregate(spl_type_t *type, spl_lang_type_kind_t kind,
const char *name, const spl_lang_type_id_t *members,
usize nmembers);
spl_lang_type_id_t spl_lang_make_varargs(spl_type_t *type);
spl_lang_type_id_t spl_type_lookup_builtin(spl_type_t *type, const char *name); bool spl_type_is_subtype(const spl_type_t *type, spl_type_id_t sub, spl_type_id_t super);
spl_type_id_t spl_type_fn_param_tid(spl_type_t *type, spl_type_id_t fn_tid, usize idx);
const spl_type_member_t *spl_type_agg_member(spl_type_t *type, spl_type_id_t tid, const char *name);
bool spl_type_agg_member_idx(spl_type_t *type, spl_type_id_t tid, const char *name, usize *out_idx);
#endif /* __SPL_TYPE_H__ */ #endif /* __SPL_TYPE_H__ */
+206 -75
View File
@@ -1,7 +1,7 @@
/* splc0.c - SPL compiler CLI (stage 1, 引导用) /* splc0.c - SPL compiler CLI (stage 1, 引导用)
* *
* splc0 --dump tokens|ast|all <file> dump 前端产物 * splc0 --dump tokens|ast|sema|ir|vm <file> dump 前端产物
* splc0 <in> <out> 编译 (阶段 B 实现) * splc0 <in> <out> 编译
*/ */
#define __SCC_LOG_IMPL_IMPORT_SRC__ #define __SCC_LOG_IMPL_IMPORT_SRC__
#include "../stage0/include/utils.h" #include "../stage0/include/utils.h"
@@ -27,6 +27,24 @@ typedef enum {
DUMP_VM, DUMP_VM,
} dump_t; } dump_t;
typedef struct {
spl_ast_t *ast;
char *abs_path;
char *src;
} spl_driver_module_t;
typedef VEC(spl_driver_module_t) spl_driver_module_vec_t;
typedef struct {
spl_ast_t main_ast;
spl_tok_vec_t main_toks;
char *main_path;
spl_driver_module_vec_t modules;
MAP(const char *, usize) path_to_idx;
spl_diag_t *diag;
} spl_driver_t;
static char *read_file(const char *path, long *out_len) { static char *read_file(const char *path, long *out_len) {
FILE *f = fopen(path, "rb"); FILE *f = fopen(path, "rb");
if (!f) { if (!f) {
@@ -42,132 +60,245 @@ static char *read_file(const char *path, long *out_len) {
fclose(f); fclose(f);
return NULL; return NULL;
} }
fread(buf, 1, (size_t)len, f); size_t nread = fread(buf, 1, (size_t)len, f);
fclose(f); fclose(f);
buf[len] = '\0'; buf[nread] = '\0';
*out_len = len; if (out_len)
*out_len = (long)nread;
return buf; return buf;
} }
static const char *const tok_type_names[] = { /* 注意:按值接收,内部 vec_free 释放与调用方共享的 data 指针。
#define X(name, enum_name, dummy) #enum_name, 调用后原 vec 视为已消费,不要再使用。 */
KEYWORD_TABLE
#undef X
#define X(name, enum_name, dummy) #enum_name,
TOKEN_TABLE
#undef X
};
static void dump_tokens(spl_tok_vec_t toks) { static void dump_tokens(spl_tok_vec_t toks) {
printf("tokens got (%zu)\n", toks.size); printf("tokens got (%zu)\n", toks.size);
for (usize i = 0; i < toks.size; i++) { for (usize i = 0; i < toks.size; i++) {
const spl_tok_t *t = &toks.data[i]; const spl_tok_t *t = &toks.data[i];
printf("[%s] %.*s (%zu:%zu)\n", tok_type_names[t->type], (int)t->len, t->lexeme, t->line, printf("[%s] %.*s (%zu:%zu)\n", spl_tok_type_name(t->type), (int)t->len, t->lexeme, t->line,
t->col); t->col);
} }
vec_free(toks); vec_free(toks);
} }
/* 把 import_path 拼接到 importing_file 所在目录。
from_fname 为空时按相对 cwd 处理。绝对路径直接透传。 */
static void resolve_relative(const char *from, const char *path, char *out, usize cap) {
if (!from || !path) {
if (cap)
out[0] = 0;
return;
}
if (path[0] == '/' || path[0] == '\\' || (path[0] && path[1] == ':')) {
snprintf(out, cap, "%s", path);
return;
}
const char *last_sep = NULL;
for (const char *p = from; *p; ++p)
if (*p == '/' || *p == '\\')
last_sep = p;
if (!last_sep) {
snprintf(out, cap, "%s", path);
return;
}
usize dir_len = (usize)(last_sep - from) + 1;
snprintf(out, cap, "%.*s%s", (int)dir_len, from, path);
}
static spl_ast_t *driver_load(void *user, const char *from_fname, const char *path,
spl_diag_t *diag) {
spl_driver_t *d = user;
char abs[1024];
resolve_relative(from_fname, path, abs, sizeof abs);
usize idx;
if (map_get(d->path_to_idx, abs, &idx)) {
spl_ast_t *a = vec_at(d->modules, idx).ast;
if (!a) {
spl_diag_error(diag, SPL_DIAG_KIND_CIRCULAR_DEP, NULL, "circular import: `%s`", abs);
return NULL;
}
return a;
}
/* 先登记 ast=NULL 占位:若后续解析过程中又有 @import 指回本路径,
会命中这里,判定为环。 */
char *key = strdup(abs);
idx = vec_size(d->modules);
spl_driver_module_t placeholder = {.ast = NULL, .abs_path = key, .src = NULL};
vec_push(d->modules, placeholder);
map_put(d->path_to_idx, key, idx);
long len = 0;
char *src = read_file(abs, &len);
if (!src) {
spl_diag_error(diag, SPL_DIAG_KIND_LEX_UNEXPECTED, NULL, "@import: cannot open `%s`", abs);
return NULL;
}
(void)len;
/* key 同时用作 lexer 的 fname:token.fname 与 map key 共享一份 strdup,
减少一次分配;cleanup 时只 free module.abs_path */
spl_tok_vec_t toks = spl_lex(src, key);
spl_ast_t *ast = malloc(sizeof *ast);
spl_ast_init(ast, &toks);
ast->diag = diag;
spl_ast_parse(ast);
vec_at(d->modules, idx).ast = ast;
vec_at(d->modules, idx).src = src;
return ast;
}
static int compile_spl(const char *src, const char *fname, const char *outpath, int gen_debug, static int compile_spl(const char *src, const char *fname, const char *outpath, int gen_debug,
dump_t dump) { dump_t dump) {
(void)gen_debug; (void)gen_debug;
spl_tok_vec_t toks = spl_lex(src, fname);
if (dump == DUMP_TOKEN) {
dump_tokens(toks);
// memory leak
return 0;
}
spl_diag_t diag; spl_diag_t diag;
spl_diag_init(&diag, stderr); spl_diag_init(&diag, stderr);
spl_ast_t ast; spl_driver_t drv = {0};
spl_ast_init(&ast, &toks); drv.diag = &diag;
spl_diag_set_stage(&diag, SPL_STAGE_PARSE); drv.main_path = strdup(fname);
ast.diag = &diag; drv.main_toks = spl_lex(src, drv.main_path);
spl_ast_parse(&ast); spl_ast_init(&drv.main_ast, &drv.main_toks);
if (spl_diag_has_error(&diag) || spl_diag_has_fatal(&diag)) { drv.main_ast.diag = &diag;
spl_diag_summary(&diag); map_init(drv.path_to_idx, MAP_HASH_STR, MAP_CMP_STR);
// memory leak vec_init(drv.modules);
return 1;
} int rc = 0;
// spl_ast_valid(&ast); TODO
if (dump == DUMP_AST) { /* dump_tokens 消费 drv.main_toks(共享 data),之后 main_ast.input 悬空,
spl_ast_dump(&ast, ast.root); 所以这条分支必须在 spl_ast_parse 之前、且不能再 drop main_ast。 */
// memory leak if (dump == DUMP_TOKEN) {
dump_tokens(drv.main_toks);
free(drv.main_path);
map_free(drv.path_to_idx);
spl_diag_drop(&diag);
return 0; return 0;
} }
spl_attr_t attr; spl_attr_t attr;
spl_attr_init(&attr); spl_lang_type_t lang_type;
spl_sema_t sema;
spl_type_t type;
spl_scope_t scope; spl_scope_t scope;
spl_type_init(&type); spl_sema_t sema;
spl_ast2ir_t a2ir;
spl_ir_builder_t ir_builder;
spl_ir2vm_t ir2vm;
spl_ast_ptr_vec_t all_asts;
int attr_ok = 0, lang_type_ok = 0, scope_ok = 0;
int sema_ok = 0, a2ir_ok = 0, irb_ok = 0, ir2vm_ok = 0;
spl_diag_set_stage(&diag, SPL_STAGE_PARSE);
spl_ast_parse(&drv.main_ast);
if (spl_diag_has_error(&diag) || spl_diag_has_fatal(&diag)) {
spl_diag_summary(&diag);
rc = 1;
goto cleanup;
}
if (dump == DUMP_AST) {
spl_ast_dump(&drv.main_ast, drv.main_ast.root);
goto cleanup;
}
spl_attr_init(&attr);
attr_ok = 1;
spl_lang_type_init(&lang_type);
lang_type_ok = 1;
spl_scope_init(&scope); spl_scope_init(&scope);
spl_sema_init(&sema, &ast, &type, &scope, &attr); scope_ok = 1;
sema.ast = &ast;
spl_sema_init(&sema, &drv.main_ast, &lang_type, &scope, &attr);
sema_ok = 1;
spl_module_loader_t loader = {.load = driver_load, .user = &drv};
sema.loader = &loader;
spl_diag_set_stage(&diag, SPL_STAGE_SEMA); spl_diag_set_stage(&diag, SPL_STAGE_SEMA);
sema.diag = &diag; sema.diag = &diag;
spl_sema_run(&sema); spl_sema_run(&sema);
if (spl_diag_has_error(&diag) || spl_diag_has_fatal(&diag)) { if (spl_diag_has_error(&diag) || spl_diag_has_fatal(&diag)) {
// memory leak
spl_diag_summary(&diag); spl_diag_summary(&diag);
return 1; rc = 1;
goto cleanup;
} }
if (dump == DUMP_SEMA) { if (dump == DUMP_SEMA) {
spl_sema_dump(&sema); spl_sema_dump(&sema);
spl_ast_dump(&ast, ast.root); spl_ast_dump(&drv.main_ast, drv.main_ast.root);
// memory leak goto cleanup;
return 0;
} }
spl_ast2ir_t a2ir; /* 收集所有 ast:主文件在前,被 import 的文件按加载顺序在后。
spl_ir_builder_t ir_builder; ast2ir 内部会 vec_free(all_asts)。 */
vec_init(all_asts);
vec_push(all_asts, &drv.main_ast);
for (usize i = 0; i < vec_size(drv.modules); ++i)
vec_push(all_asts, vec_at(drv.modules, i).ast);
spl_ir_builder_init(&ir_builder); spl_ir_builder_init(&ir_builder);
irb_ok = 1;
spl_ast2ir_init(&a2ir, &ir_builder, &sema); spl_ast2ir_init(&a2ir, &ir_builder, &sema);
a2ir_ok = 1;
spl_diag_set_stage(&diag, SPL_STAGE_AST2IR); spl_diag_set_stage(&diag, SPL_STAGE_AST2IR);
a2ir.diag = &diag; a2ir.diag = &diag;
spl_ast2ir_run(&a2ir); spl_ast2ir_run(&a2ir, all_asts);
if (spl_diag_has_error(&diag) || spl_diag_has_fatal(&diag)) { if (spl_diag_has_error(&diag) || spl_diag_has_fatal(&diag)) {
spl_diag_summary(&diag); spl_diag_summary(&diag);
// memory leak rc = 1;
spl_ast2ir_drop(&a2ir); goto cleanup;
spl_sema_drop(&sema);
spl_ast_drop(&ast);
return 1;
} }
if (dump == DUMP_IR) { if (dump == DUMP_IR) {
spl_ir_dump(&ir_builder.ir, &type, &attr); spl_ir_dump(&ir_builder.ir, &lang_type.ir, &attr);
// memory leak goto cleanup;
return 0;
} }
spl_ir2vm_t ir2vm; spl_ir2vm_init(&ir2vm, &a2ir.ir->ir, &lang_type.ir, &attr);
spl_ir2vm_init(&ir2vm, &a2ir.ir->ir, &type, &attr); ir2vm_ok = 1;
// ir2vm.diag = &diag;
spl_diag_set_stage(&diag, SPL_STAGE_IR2VM); spl_diag_set_stage(&diag, SPL_STAGE_IR2VM);
ir2vm.diag = &diag; ir2vm.diag = &diag;
int rc = spl_ir2vm_run(&ir2vm); rc = spl_ir2vm_run(&ir2vm);
if (spl_diag_has_error(&diag) || spl_diag_has_fatal(&diag)) { if (spl_diag_has_error(&diag) || spl_diag_has_fatal(&diag)) {
spl_diag_summary(&diag); spl_diag_summary(&diag);
return rc; goto cleanup;
} }
if (dump == DUMP_VM) { if (dump == DUMP_VM) {
spl_prog_dump(&ir2vm.prog); spl_prog_dump(&ir2vm.prog);
// memory leak goto cleanup;
return 0;
} }
spl_prog_store_to_file(outpath, &ir2vm.prog); spl_prog_store_to_file(outpath, &ir2vm.prog);
rc = 0;
cleanup:
if (ir2vm_ok)
spl_ir2vm_drop(&ir2vm); spl_ir2vm_drop(&ir2vm);
if (a2ir_ok)
spl_ast2ir_drop(&a2ir); spl_ast2ir_drop(&a2ir);
if (irb_ok)
spl_ir_builder_drop(&ir_builder);
if (sema_ok)
spl_sema_drop(&sema); spl_sema_drop(&sema);
spl_ast_drop(&ast); if (scope_ok)
// memory leak spl_scope_drop(&scope);
return 0; if (lang_type_ok)
spl_lang_type_drop(&lang_type);
if (attr_ok)
spl_attr_drop(&attr);
spl_ast_drop(&drv.main_ast);
for (usize i = 0; i < vec_size(drv.modules); ++i) {
spl_ast_t *a = vec_at(drv.modules, i).ast;
if (a) {
spl_ast_drop(a);
free(a);
}
free(vec_at(drv.modules, i).abs_path);
free(vec_at(drv.modules, i).src);
}
vec_free(drv.modules);
/* map 的 key 是 module 里 strdup 出的 abs_path,已随 module 释放 */
map_free(drv.path_to_idx);
free(drv.main_path);
spl_diag_drop(&diag);
return rc;
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
@@ -194,20 +325,20 @@ int main(int argc, char **argv) {
} }
const char *flags = argv[argi + 1]; const char *flags = argv[argi + 1];
if (strstr(flags, "lex") != NULL) { if (strcmp(flags, "lex") == 0) {
dump = DUMP_TOKEN; dump = DUMP_TOKEN;
} else if (strstr(flags, "ast") != NULL) { } else if (strcmp(flags, "ast") == 0) {
dump = DUMP_AST; dump = DUMP_AST;
} else if (strstr(flags, "sema") != NULL) { } else if (strcmp(flags, "sema") == 0) {
dump = DUMP_SEMA; dump = DUMP_SEMA;
} else if (strstr(flags, "ir") != NULL) { } else if (strcmp(flags, "ir") == 0) {
dump = DUMP_IR; dump = DUMP_IR;
} else if (strstr(flags, "vm") != NULL) { } else if (strcmp(flags, "vm") == 0) {
dump = DUMP_VM; dump = DUMP_VM;
} else if (strstr(flags, "none") != NULL) { } else if (strcmp(flags, "none") == 0) {
dump = DUMP_NONE; dump = DUMP_NONE;
} else { } else {
Panic("--dump unknown flags"); LOG_FATAL("splc0: --dump takes one of lex|ast|sema|ir|vm|none, got `%s`", flags);
return 1; return 1;
} }
argi += 2; argi += 2;