stage1 修复设计问题 实现ast2ir

This commit is contained in:
zzy
2026-08-05 08:14:23 +08:00
parent 8ac59dfaa1
commit 2ccee5f1cf
14 changed files with 3694 additions and 91 deletions

View File

@@ -151,7 +151,8 @@ static void parse_error(parser_t *p, spl_tok_t *t, const char *msg) {
const char *fn = (t && t->fname) ? t->fname : "<unknown>";
usize line = t ? t->line : 0;
usize col = t ? t->col : 0;
LOG_FATAL("%s:%llu:%llu: error: %s", fn, (unsigned long long)line, (unsigned long long)col, msg);
LOG_FATAL("%s:%llu:%llu: error: %s", fn, (unsigned long long)line, (unsigned long long)col,
msg);
}
static int expect(parser_t *p, spl_tok_type_t type, const char *what) {

View File

@@ -35,6 +35,8 @@ typedef VEC(spl_ast_node_ref_t) spl_ast_node_ref_vec_t;
struct spl_ast_node {
spl_ast_node_kind_t kind;
spl_ast_loc_t loc;
usize resolved_def_id;
union {
struct {
spl_ast_node_ref_vec_t attr_list; /* attr_item */

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,19 @@
#ifndef __SPL_AST2IR_H__
#define __SPL_AST2IR_H__
#include "spl_ir.h"
#include "spl_sema.h"
typedef struct {
const spl_sema_t *sema;
spl_ir_t ir;
VEC(char *) owned_names; /* 本模块 malloc 的函数名drop 时释放 */
int err_count;
} spl_ast2ir_t;
void spl_ast2ir_init(spl_ast2ir_t *ast2ir, const spl_sema_t *sema);
void spl_ast2ir_drop(spl_ast2ir_t *ast2ir);
void spl_ast2ir_run(spl_ast2ir_t *ast2ir);
#endif /* __SPL_AST2IR_H__ */

View File

@@ -1 +1,484 @@
/* spl_ir.c — function-based SIR IR (arena 容器 + 文本 dump) */
#include "spl_ir.h"
#include <stdio.h>
#include <string.h>
/* ---- 内置函数名字表(与 spl_ir_kind_t 枚举一一对应) ---- */
static const char *const ir_kind_names[] = {
#define X(a, b, c) #a,
SPL_IR_FN_TABLE
#undef X
};
void spl_ir_init(spl_ir_t *ir) {
memset(ir, 0, sizeof *ir);
vec_init(ir->funcs);
/* func ref 0 保留为 error占位 */
spl_ir_func_t f0;
memset(&f0, 0, sizeof f0);
vec_push(ir->funcs, f0);
}
static void node_drop_vecs(spl_ir_node_t *n) {
if (!n)
return;
switch (n->kind) {
case SPL_IR_AGG_CONSTRUCT:
vec_free(n->agg_construct.fields);
break;
case SPL_IR_CONTROL_CALL:
vec_free(n->control_call.params);
break;
default:
break;
}
}
void spl_ir_drop(spl_ir_t *ir) {
for (usize i = 0; i < ir->funcs.size; i++) {
spl_ir_func_t *f = &ir->funcs.data[i];
for (usize j = 0; j < f->nodes.size; j++)
node_drop_vecs(&f->nodes.data[j]);
vec_free(f->nodes);
vec_free(f->labels);
}
vec_free(ir->funcs);
}
spl_ir_func_ref_t spl_ir_alloc_fn(spl_ir_t *ir) {
spl_ir_func_t f;
memset(&f, 0, sizeof f);
vec_init(f.nodes);
vec_init(f.labels);
vec_push(ir->funcs, f);
return ir->funcs.size - 1;
}
spl_ir_node_ref_t spl_ir_alloc_node(spl_ir_t *ir, spl_ir_func_ref_t fn_id) {
if (!fn_id || fn_id >= ir->funcs.size)
return 0;
spl_ir_func_t *f = &ir->funcs.data[fn_id];
spl_ir_node_t n;
memset(&n, 0, sizeof n);
if (f->nodes.size == 0) {
vec_push(f->nodes, n); /* 占位node ref 0 保留为 error */
}
vec_push(f->nodes, n);
return f->nodes.size - 1;
}
spl_ir_node_t *spl_ir_node(spl_ir_t *ir, spl_ir_func_ref_t fn_id, spl_ir_node_ref_t node_id) {
if (!fn_id || fn_id >= ir->funcs.size)
return NULL;
spl_ir_func_t *f = &ir->funcs.data[fn_id];
if (!node_id || node_id >= f->nodes.size)
return NULL;
return &f->nodes.data[node_id];
}
spl_ir_func_t *spl_ir_func(spl_ir_t *ir, spl_ir_func_ref_t fn_id) {
if (!fn_id || fn_id >= ir->funcs.size)
return NULL;
return &ir->funcs.data[fn_id];
}
/* ================================================================
* dump
* ================================================================ */
static void ir_type_dump(const spl_type_t *ty, spl_type_id_t tid) {
spl_type_node_t *n = spl_type_node((spl_type_t *)ty, tid);
if (!n) {
printf("?");
return;
}
switch (n->kind) {
case SPL_TYPE_VOID:
printf("void");
break;
case SPL_TYPE_BOOL:
printf("bool");
break;
case SPL_TYPE_INT:
printf("%s%zu", n->int_type.is_signed ? "i" : "u", n->int_type.bits);
break;
case SPL_TYPE_FLOAT:
printf("f%zu", n->float_type.bits);
break;
case SPL_TYPE_PTR:
printf("*");
ir_type_dump(ty, n->ptr_pointee);
break;
case SPL_TYPE_SLICE:
printf("[]");
ir_type_dump(ty, n->slice_element);
break;
case SPL_TYPE_RANGE:
printf("range[");
ir_type_dump(ty, n->range_element);
printf("]");
break;
case SPL_TYPE_ARRAY:
printf("[%zu]", n->array_type.len);
ir_type_dump(ty, n->array_type.element);
break;
case SPL_TYPE_STRUCT:
printf("struct#%zu", tid);
break;
case SPL_TYPE_UNION:
printf("union#%zu", tid);
break;
case SPL_TYPE_ENUM:
printf("enum#%zu", tid);
break;
case SPL_TYPE_FN:
printf("fn<");
for (usize i = 0; i < n->fn_type.params.size; i++) {
if (i)
printf(",");
ir_type_dump(ty, n->fn_type.params.data[i]);
}
printf("->");
ir_type_dump(ty, n->fn_type.ret);
printf(">");
break;
case SPL_TYPE_ID:
ir_type_dump(ty, n->type_id);
break;
default:
printf("?%zu", tid);
break;
}
}
static const char *node_name(spl_ir_kind_t k) {
if ((usize)k < sizeof(ir_kind_names) / sizeof(ir_kind_names[0]))
return ir_kind_names[k];
return "?";
}
static int node_produces_value(spl_ir_kind_t k) {
switch (k) {
case SPL_IR_MEM_STORE:
case SPL_IR_MEM_COPY:
case SPL_IR_MEM_SET:
case SPL_IR_MEM_FENCE:
case SPL_IR_CONTROL_BR:
case SPL_IR_CONTROL_JMP:
case SPL_IR_CONTROL_RET:
case SPL_IR_CONTROL_UNREACHABLE:
case SPL_IR_CONTROL_TRAP:
case SPL_IR_DBG_BREAKPOINT:
case SPL_IR_DBG_DECLARE:
return 0;
default:
return 1;
}
}
static void dump_ref(spl_ir_node_ref_t r) { printf("%%%zu", r); }
static void dump_node(const spl_type_t *ty, const spl_ir_node_t *n) {
switch (n->kind) {
case SPL_IR_TYPE_CONST:
printf("@type.const(");
ir_type_dump(ty, n->type_const.tid);
printf(")(");
{
spl_type_node_t *t = spl_type_node((spl_type_t *)ty, n->type_const.tid);
if (t && t->kind == SPL_TYPE_INT)
printf("%lld", (long long)n->type_const.int_lit);
else if (t && t->kind == SPL_TYPE_FLOAT)
printf("%g", n->type_const.float_lit);
else if (t && t->kind == SPL_TYPE_FN)
printf("@fn#%zu", n->type_const.fn);
else if (t && (t->kind == SPL_TYPE_PTR || t->kind == SPL_TYPE_SLICE)) {
if (n->type_const.cstr_lit)
printf("\"%s\"", n->type_const.cstr_lit);
else
printf("0");
} else if (t && t->kind == SPL_TYPE_BOOL)
printf("%lld", (long long)n->type_const.int_lit);
else
printf("?");
}
printf(")");
break;
case SPL_IR_ARITH_ADD:
case SPL_IR_ARITH_SUB:
case SPL_IR_ARITH_MUL:
case SPL_IR_ARITH_DIV:
case SPL_IR_ARITH_REM:
case SPL_IR_ARITH_AND:
case SPL_IR_ARITH_OR:
case SPL_IR_ARITH_XOR:
case SPL_IR_ARITH_SHL:
case SPL_IR_ARITH_SHR:
printf("@%s(", node_name(n->kind));
ir_type_dump(ty, n->arith.tid);
printf(")(");
dump_ref(n->arith.left);
if (n->arith.right) {
printf(", ");
dump_ref(n->arith.right);
}
printf(")");
break;
case SPL_IR_ARITH_NEG:
case SPL_IR_ARITH_ABS:
case SPL_IR_ARITH_NOT:
printf("@%s(", node_name(n->kind));
ir_type_dump(ty, n->arith.tid);
printf(")(");
dump_ref(n->arith.left);
printf(")");
break;
case SPL_IR_CMP_EQ:
case SPL_IR_CMP_NE:
case SPL_IR_CMP_LT:
case SPL_IR_CMP_LE:
case SPL_IR_CMP_GT:
case SPL_IR_CMP_GE:
printf("@%s(", node_name(n->kind));
ir_type_dump(ty, n->cmp.tid);
printf(")(");
dump_ref(n->cmp.a);
printf(", ");
dump_ref(n->cmp.b);
printf(")");
break;
case SPL_IR_CAST_TRUNC:
case SPL_IR_CAST_ZEXT:
case SPL_IR_CAST_SEXT:
case SPL_IR_CAST_FEXT:
case SPL_IR_CAST_FTRUNC:
case SPL_IR_CAST_BITCAST:
case SPL_IR_CAST_PTR2INT:
case SPL_IR_CAST_INT2PTR:
case SPL_IR_CAST_BOOL2INT:
case SPL_IR_CASE_INT2FLOAT:
case SPL_IR_CASE_FLOAT2INT:
printf("@%s(", node_name(n->kind));
ir_type_dump(ty, n->cast.from_tid);
printf(", ");
ir_type_dump(ty, n->cast.to_tid);
printf(")(");
dump_ref(n->cast.val);
printf(")");
break;
case SPL_IR_MEM_ALLOCA:
printf("@mem.alloca(");
ir_type_dump(ty, n->mem_alloc.tid);
printf(")(");
dump_ref(n->mem_alloc.count);
printf(")");
break;
case SPL_IR_MEM_LOAD:
printf("@mem.load(");
ir_type_dump(ty, n->mem_load.tid);
printf(")(");
dump_ref(n->mem_load.ptr);
printf(")");
break;
case SPL_IR_MEM_STORE:
printf("@mem.store(");
ir_type_dump(ty, n->mem_store.tid);
printf(")(");
dump_ref(n->mem_store.ptr);
printf(", ");
dump_ref(n->mem_store.val);
printf(")");
break;
case SPL_IR_MEM_OFFSET:
printf("@mem.offset(");
ir_type_dump(ty, n->mem_offset.tid);
printf(")(");
dump_ref(n->mem_offset.ptr);
printf(", ");
dump_ref(n->mem_offset.offset);
printf(")");
break;
case SPL_IR_MEM_COPY:
printf("@mem.copy()(");
dump_ref(n->mem_copy.dst);
printf(", ");
dump_ref(n->mem_copy.src);
printf(", ");
dump_ref(n->mem_copy.size);
printf(")");
break;
case SPL_IR_MEM_SET:
printf("@mem.set()(");
dump_ref(n->mem_set.dst);
printf(", ");
dump_ref(n->mem_set.val);
printf(", ");
dump_ref(n->mem_set.size);
printf(")");
break;
case SPL_IR_MEM_FENCE:
printf("@mem.fence()(");
dump_ref(n->mem_fence.ordering);
printf(")");
break;
case SPL_IR_TYPE_BITSIZEOF:
printf("@type.bitsizeof(");
ir_type_dump(ty, n->bitsizeof.tid);
printf(")()");
break;
case SPL_IR_TYPE_SIZEOF:
printf("@type.sizeof(");
ir_type_dump(ty, n->ir_sizeof.tid);
printf(")()");
break;
case SPL_IR_TYPE_ALIGNOF:
printf("@type.alignof(");
ir_type_dump(ty, n->ir_alignof.tid);
printf(")()");
break;
case SPL_IR_TYPE_OFFSETOF:
printf("@type.offsetof(");
ir_type_dump(ty, n->ir_offsetof.tid);
printf(")(");
dump_ref(n->ir_offsetof.field_idx);
printf(")");
break;
case SPL_IR_TYPE_FIELD_COUNT:
printf("@type.field_count(");
ir_type_dump(ty, n->field_count.tid);
printf(")()");
break;
case SPL_IR_AGG_CONSTRUCT:
printf("@agg.construct(");
ir_type_dump(ty, n->agg_construct.tid);
printf(")(");
for (usize i = 0; i < n->agg_construct.fields.size; i++) {
if (i)
printf(", ");
dump_ref(n->agg_construct.fields.data[i]);
}
printf(")");
break;
case SPL_IR_AGG_EXTRACT:
printf("@agg.extract(");
ir_type_dump(ty, n->agg_extract.tid);
printf(", %lld)(", (long long)n->agg_extract.field_idx);
dump_ref(n->agg_extract.val);
printf(")");
break;
case SPL_IR_AGG_INSERT:
printf("@agg.insert(");
ir_type_dump(ty, n->agg_insert.tid);
printf(", %lld)(", (long long)n->agg_insert.field_idx);
dump_ref(n->agg_insert.agg);
printf(", ");
dump_ref(n->agg_insert.field);
printf(")");
break;
case SPL_IR_CONTROL_SELECT:
printf("@control.select(");
ir_type_dump(ty, n->control_select.tid);
printf(")(");
dump_ref(n->control_select.cond);
printf(", ");
dump_ref(n->control_select.true_val);
printf(", ");
dump_ref(n->control_select.false_val);
printf(")");
break;
case SPL_IR_CONTROL_BR:
printf("@control.br()(");
dump_ref(n->control_br.cond);
printf(", ");
dump_ref(n->control_br.true_label);
printf(", ");
dump_ref(n->control_br.false_label);
printf(")");
break;
case SPL_IR_CONTROL_JMP:
printf("@control.jmp()(");
dump_ref(n->control_jmp.label);
printf(")");
break;
case SPL_IR_CONTROL_CALL:
printf("@control.call(");
ir_type_dump(ty, n->control_call.tid);
printf(")(");
dump_ref(n->control_call.func);
for (usize i = 0; i < n->control_call.params.size; i++) {
printf(", ");
dump_ref(n->control_call.params.data[i]);
}
printf(")");
break;
case SPL_IR_CONTROL_PARAM:
printf("@control.param(");
ir_type_dump(ty, n->control_param.tid);
printf(")(%lld)", (long long)n->control_param.idx);
break;
case SPL_IR_CONTROL_RET:
printf("@control.ret(");
ir_type_dump(ty, n->control_ret.tid);
printf(")(");
if (n->control_ret.val)
dump_ref(n->control_ret.val);
printf(")");
break;
case SPL_IR_CONTROL_UNREACHABLE:
printf("@control.unreachable()()");
break;
case SPL_IR_CONTROL_TRAP:
printf("@control.trap()()");
break;
case SPL_IR_DBG_BREAKPOINT:
printf("@dbg.breakpoint()()");
break;
case SPL_IR_DBG_DECLARE:
printf("@dbg.declare()()");
break;
default:
printf("@%s()()", node_name(n->kind));
break;
}
}
static void dump_func(const spl_type_t *ty, const spl_ir_func_t *f) {
printf("func @%s", f->name ? f->name : "?");
if (f->fn_tid) {
spl_type_node_t *t = spl_type_node((spl_type_t *)ty, f->fn_tid);
if (t && t->kind == SPL_TYPE_FN) {
printf("(");
for (usize i = 0; i < t->fn_type.params.size; i++) {
if (i)
printf(", ");
ir_type_dump(ty, t->fn_type.params.data[i]);
}
printf(") -> ");
ir_type_dump(ty, t->fn_type.ret);
}
}
printf(" {\n");
usize li = 0;
for (usize i = 1; i < f->nodes.size; i++) {
if (li < f->labels.size && f->labels.data[li] == i) {
printf("#bb%zu:\n", li);
li++;
}
printf(" ");
if (node_produces_value(f->nodes.data[i].kind))
printf("%%%zu = ", i);
dump_node(ty, &f->nodes.data[i]);
printf("\n");
}
if (li < f->labels.size && f->labels.data[li] == f->nodes.size)
printf("#bb%zu:\n", li);
printf("}\n");
}
void spl_ir_dump(spl_ir_t *ir, const spl_type_t *ty) {
printf("; SPL IR module (%zu funcs)\n", ir->funcs.size - 1);
for (usize i = 1; i < ir->funcs.size; i++)
dump_func(ty, &ir->funcs.data[i]);
}

View File

@@ -2,6 +2,7 @@
#define __SPL_IR_H__
#include "../stage0/include/utils.h"
#include "spl_type.h"
/* clang-format off */
#define SPL_IR_FN_TABLE \
@@ -64,6 +65,7 @@
X(control.br, V0, SPL_IR_CONTROL_BR) \
X(control.jmp, V0, SPL_IR_CONTROL_JMP) \
X(control.call, V0, SPL_IR_CONTROL_CALL) \
X(control.param, V0, SPL_IR_CONTROL_PARAM) \
X(control.ret, V0, SPL_IR_CONTROL_RET) \
X(control.unreachable, V0, SPL_IR_CONTROL_UNREACHABLE) \
X(control.trap, V0, SPL_IR_CONTROL_TRAP) \
@@ -80,14 +82,136 @@ typedef enum {
} spl_ir_kind_t;
/* clang-format on */
typedef struct {
spl_ir_kind_t kind;
} spl_ir_node_t;
typedef VEC(spl_ir_node_t) spl_ir_node_vec_t;
typedef usize spl_ir_node_ref_t; /* 0 is error */
typedef VEC(spl_ir_node_ref_t) spl_ir_node_ref_vec_t;
typedef usize spl_ir_func_ref_t; /* 0 is error */
typedef struct {
spl_ir_kind_t kind;
union {
struct {
spl_type_id_t tid;
spl_ir_node_ref_t left;
spl_ir_node_ref_t right;
} arith;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t a;
spl_ir_node_ref_t b;
} cmp;
struct {
spl_type_id_t from_tid;
spl_type_id_t to_tid;
spl_ir_node_ref_t val;
} cast;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t count;
} mem_alloc;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t ptr;
} mem_load;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t ptr;
spl_ir_node_ref_t val;
} mem_store;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t ptr;
spl_ir_node_ref_t offset;
} mem_offset;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t dst;
spl_ir_node_ref_t src;
spl_ir_node_ref_t size;
} mem_copy;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t dst;
spl_ir_node_ref_t val;
spl_ir_node_ref_t size;
} mem_set;
struct {
spl_ir_node_ref_t ordering;
} mem_fence;
struct {
spl_type_id_t tid;
union {
usize int_lit;
double float_lit;
const char *cstr_lit;
char ch_lit;
spl_ir_func_ref_t fn;
};
} type_const;
struct {
spl_type_id_t tid;
} bitsizeof;
struct {
spl_type_id_t tid;
} ir_sizeof;
struct {
spl_type_id_t tid;
} ir_alignof;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t field_idx;
} ir_offsetof;
struct {
spl_type_id_t tid;
} field_count;
struct {
spl_type_id_t tid;
spl_ir_node_ref_vec_t fields;
} agg_construct;
struct {
spl_type_id_t tid;
isize field_idx;
spl_ir_node_ref_t val;
} agg_extract;
struct {
spl_type_id_t tid;
isize field_idx;
spl_ir_node_ref_t agg;
spl_ir_node_ref_t field;
} agg_insert;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t cond;
spl_ir_node_ref_t true_val;
spl_ir_node_ref_t false_val;
} control_select;
struct {
spl_ir_node_ref_t cond;
spl_ir_node_ref_t true_label;
spl_ir_node_ref_t false_label;
} control_br;
struct {
spl_ir_node_ref_t label;
} control_jmp;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t func;
spl_ir_node_ref_vec_t params;
} control_call;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t idx;
} control_param;
struct {
spl_type_id_t tid;
spl_ir_node_ref_t val;
} control_ret;
};
} spl_ir_node_t;
typedef VEC(spl_ir_node_t) spl_ir_node_vec_t;
typedef struct {
enum {
SPL_IR_ATTR_NONE,
@@ -103,12 +227,12 @@ typedef VEC(spl_ir_attr_t) spl_ir_attr_vec_t;
typedef struct {
const char *name;
spl_ir_attr_t attr;
spl_type_id_t fn_tid;
spl_ir_node_vec_t nodes;
spl_ir_node_ref_vec_t labels;
} spl_ir_func_t;
typedef usize spl_ir_func_ref_t; /* 0 is error */
typedef VEC(spl_ir_func_t) spl_ir_func_vec_t;
typedef VEC(spl_ir_func_t) spl_ir_func_vec_t;
typedef struct {
spl_ir_func_vec_t funcs;
} spl_ir_t;
@@ -122,6 +246,6 @@ spl_ir_func_ref_t spl_ir_alloc_fn(spl_ir_t *ir);
spl_ir_node_t *spl_ir_node(spl_ir_t *ir, spl_ir_func_ref_t fn_id, spl_ir_node_ref_t node_id);
spl_ir_func_t *spl_ir_func(spl_ir_t *ir, spl_ir_func_ref_t fn_id);
void spl_ir_dump(spl_ir_t *ir);
void spl_ir_dump(spl_ir_t *ir, const spl_type_t *ty);
#endif /* __SPL_IR_H__ */

View File

@@ -112,11 +112,11 @@ static spl_type_id_t find_type(spl_sema_t *sema, const char *name) {
/* ---- 聚合成员登记def 层 agg_def ---- */
static void agg_add_member(spl_sema_t *sema, spl_def_id_t def, const char *name, spl_type_id_t type,
spl_scope_id_t scope) {
spl_scope_id_t scope, spl_def_id_t member_def) {
spl_def_node_t *d = def_at(sema, def);
if (!d || d->kind != SPL_DEF_AGG)
return;
spl_var_def_t v = {name, 0, type, scope};
spl_var_def_t v = {name, member_def, type, scope};
vec_push(d->agg_def, v);
}
@@ -281,6 +281,9 @@ static spl_type_id_t resolve_type_expr(spl_sema_t *sema, spl_ast_node_ref_t ref)
(atom->type_atom.kind == SPL_AST_TYPE_ANY || atom->type_atom.kind == SPL_AST_TYPE_PTR))
sema_error(sema, ref, "bare `_` type only allowed as pointer target `*_`");
}
/* AST 注解:该 type_expr 解析到的 def聚合/别名/内置为 0ast2ir 据此直接取类型) */
if (base)
n->resolved_def_id = def_for_type(sema, base);
return base;
}
@@ -331,6 +334,7 @@ static agg_handle_t agg_prepare(spl_sema_t *sema, spl_ast_node_ref_t ref) {
spl_def_id_t def = def_alloc(sema, SPL_DEF_AGG);
def_at(sema, def)->type_id = tid;
vec_init(def_at(sema, def)->agg_def);
te->resolved_def_id = def; /* 注解:该 type_expr 解析到的 def */
h.tid = tid;
h.def = def;
return h;
@@ -366,13 +370,20 @@ static void agg_resolve(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_type_id_t
m->member_decl.type_expr ? resolve_type_expr(sema, m->member_decl.type_expr) : 0;
/* resolve_type_expr 可能 alloc 新类型 → 两表 realloc须重新取节点 */
spl_type_node_t *tn = spl_type_node(&sema->type, tid);
/* 每个 MEMBER_DECL 建一个 SPL_DEF_MEMBER def结构字段/枚举变体) */
spl_type_id_t mtype = 0;
if (tn->kind == SPL_TYPE_ENUM) {
vec_push(tn->enum_type.variants, ft ? ft : tid);
agg_add_member(sema, def, m->member_decl.name, ft ? ft : tid, agg_scope);
mtype = ft ? ft : tid; /* 哨兵:无载荷变体 = 枚举自身 tid */
vec_push(tn->enum_type.variants, mtype);
} else {
mtype = ft;
vec_push(tn->agg_field_types, ft);
agg_add_member(sema, def, m->member_decl.name, ft, agg_scope);
}
spl_def_id_t mdef = def_alloc(sema, SPL_DEF_MEMBER);
def_at(sema, mdef)->type_id = mtype;
def_at(sema, mdef)->var_def.name = m->member_decl.name;
agg_add_member(sema, def, m->member_decl.name, mtype, agg_scope, mdef);
m->resolved_def_id = mdef; /* 注解member_decl → 其 SPL_DEF_MEMBER def */
break;
}
case SPL_AST_FN_DECL:
@@ -416,13 +427,19 @@ static spl_type_id_t build_agg(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_sco
/* 变量/常量/绑定节点:建 VAR def不包 SPL_TYPE_ID */
static void register_binding(spl_sema_t *sema, const char *name, spl_ast_node_ref_t type_expr,
spl_scope_id_t scope, spl_def_id_t agg_def) {
spl_scope_id_t scope, spl_def_id_t agg_def,
spl_ast_node_ref_t node_ref) {
spl_type_id_t t = type_expr ? resolve_type_expr(sema, type_expr) : 0;
spl_def_id_t def = new_var_def(sema, name, t, scope);
if (!spl_sema_scope_insert(sema, scope, name, def))
sema_error(sema, 0, "duplicate symbol");
if (agg_def)
agg_add_member(sema, agg_def, name, t, scope);
agg_add_member(sema, agg_def, name, t, scope, def);
if (node_ref) {
spl_ast_node_t *nn = node_at(sema->ast, node_ref);
if (nn)
nn->resolved_def_id = def; /* 注解var/const 声明 → 其 VAR def */
}
}
static void sema_var_decl(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_scope_id_t scope,
@@ -430,7 +447,7 @@ static void sema_var_decl(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_scope_id
spl_ast_node_t *n = node_at(sema->ast, ref);
if (!n)
return;
register_binding(sema, n->var_decl.name, n->var_decl.type_expr, scope, agg_def);
register_binding(sema, n->var_decl.name, n->var_decl.type_expr, scope, agg_def, ref);
}
static void sema_const_decl(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_scope_id_t scope,
@@ -438,7 +455,7 @@ static void sema_const_decl(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_scope_
spl_ast_node_t *n = node_at(sema->ast, ref);
if (!n)
return;
register_binding(sema, n->const_decl.name, n->const_decl.type_expr, scope, agg_def);
register_binding(sema, n->const_decl.name, n->const_decl.type_expr, scope, agg_def, ref);
}
/* fn 声明:建 fn type + FN_PARAMS def + 登记名字。不建 fn_scope由 check 新建)。
@@ -477,7 +494,8 @@ static void sema_fn_decl(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_scope_id_
if (!spl_sema_scope_insert(sema, scope, n->fn_decl.name, fdef))
sema_error(sema, ref, "duplicate function name");
if (agg_def)
agg_add_member(sema, agg_def, n->fn_decl.name, fid, scope);
agg_add_member(sema, agg_def, n->fn_decl.name, fid, scope, fdef);
n->resolved_def_id = fdef; /* 注解fn 声明 → 其 FN_PARAMS def */
}
static void sema_type_decl(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_scope_id_t scope,
@@ -510,10 +528,11 @@ static void sema_type_decl(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_scope_i
if (!spl_sema_scope_insert(sema, scope, n->type_decl.name, def))
sema_error(sema, ref, "duplicate type name");
if (agg_def)
agg_add_member(sema, agg_def, n->type_decl.name, tid, scope);
agg_add_member(sema, agg_def, n->type_decl.name, tid, scope, def);
/* 嵌套类型提升到文件作用域:兄弟聚合可裸名引用(如 Lexer 方法内 Tag.eof */
if (agg_def)
spl_sema_scope_insert(sema, sema->root_scope, n->type_decl.name, def);
n->resolved_def_id = def; /* 注解type_decl → 其 AGG/ALIAS def */
}
/* ================================================================
@@ -937,14 +956,32 @@ static spl_type_id_t infer_array_lit(spl_sema_t *sema, spl_ast_node_ref_t ref, s
/* 标识符scope 查找def → 类型) */
static spl_type_id_t infer_ident(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_ast_node_t *n) {
spl_ast_node_t *pn = n->kind == SPL_AST_EXPR ? node_at(sema->ast, n->expr.op_expr.left) : n;
spl_type_id_t t = find_type(sema, pn->primary_expr.ident);
spl_def_id_t def = find_bare(sema, pn->primary_expr.ident);
spl_type_id_t t = def_type(sema, def);
if (!t) {
sema_error(sema, ref, "undefined identifier");
return 0;
}
/* 注解IDENT 引用 → 其符号 defvar 用 VAR、fn 用 FN_PARAMS 等) */
pn->resolved_def_id = def;
return t;
}
/* 表达式 ref 解析到的 def取内层节点注解裸 ident 兜底 find_bare */
static spl_def_id_t expr_def_at(spl_sema_t *sema, spl_ast_node_ref_t ref) {
spl_ast_node_t *n = node_at(sema->ast, ref);
if (!n || n->kind != SPL_AST_EXPR)
return 0;
spl_ast_node_t *inner = node_at(sema->ast, n->expr.op_expr.left);
if (!inner)
return 0;
if (inner->resolved_def_id)
return inner->resolved_def_id;
if (n->expr.op == SPL_AST_PRIMARY_EXPR && inner->primary_expr.kind == SPL_AST_IDENT)
return find_bare(sema, inner->primary_expr.ident);
return 0;
}
static spl_type_id_t infer_postfix(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_ast_node_t *n);
static spl_type_id_t infer_prefix(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_ast_node_t *n);
static void check_stmt(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_sema_ctx_t ctx);
@@ -1080,6 +1117,8 @@ static spl_type_id_t infer_postfix(spl_sema_t *sema, spl_ast_node_ref_t ref, spl
/* 指针自动解引用一层 */
if (t && t->kind == SPL_TYPE_PTR)
base = underlying(sema, t->ptr_pointee);
/* 注解FIELD 节点 → 被访问聚合(自动解引用后)的 AGG def非聚合为 0 */
pf->resolved_def_id = def_for_type(sema, base);
t = type_node(sema, base);
if (!t) {
sema_error(sema, ref, "field access on non-aggregate");
@@ -1171,6 +1210,8 @@ static spl_type_id_t infer_postfix(spl_sema_t *sema, spl_ast_node_ref_t ref, spl
sema_error(sema, ref, "call requires function type");
return 0;
}
/* 注解CALL 节点 → 被调 fn 的 def从 callee primary 节点/裸名解析) */
pf->resolved_def_id = expr_def_at(sema, pf->postfix_expr.primary_expr);
spl_ast_node_ref_vec_t *args = &pf->postfix_expr.call_expr;
/* 变参 fn如 vm_printf最后一个形参 name=NULL 且类型可为 0 */
/* 注意infer_expr 可能新分配类型使 type_table realloct 会失效,须每次刷新 */
@@ -1623,11 +1664,13 @@ static void check_block(spl_sema_t *sema, spl_ast_node_ref_vec_t *block, spl_sco
if (b->block_item.kind == SPL_AST_VARDECL) {
spl_ast_node_t *vd = node_at(sema->ast, b->block_item.var_decl);
if (vd)
register_binding(sema, vd->var_decl.name, vd->var_decl.type_expr, scope, 0);
register_binding(sema, vd->var_decl.name, vd->var_decl.type_expr, scope, 0,
b->block_item.var_decl);
} else if (b->block_item.kind == SPL_AST_CONSTDECL) {
spl_ast_node_t *cd = node_at(sema->ast, b->block_item.const_decl);
if (cd)
register_binding(sema, cd->const_decl.name, cd->const_decl.type_expr, scope, 0);
register_binding(sema, cd->const_decl.name, cd->const_decl.type_expr, scope, 0,
b->block_item.const_decl);
} else if (b->block_item.kind == SPL_AST_TYPEDECL) {
spl_ast_node_t *td = node_at(sema->ast, b->block_item.type_decl);
if (td)
@@ -1664,6 +1707,10 @@ static void check_fn_body(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_def_id_t
if (pv->name) {
spl_def_id_t pdef = new_var_def(sema, pv->name, pv->type_id, fn_scope);
spl_sema_scope_insert(sema, fn_scope, pv->name, pdef);
/* 注解param_decl → 其在 fn_scope 的 VAR def */
spl_ast_node_t *pd = node_at(sema->ast, n->fn_decl.param_list.data[i]);
if (pd)
pd->resolved_def_id = pdef;
}
}
check_block(sema, &n->fn_decl.block, fn_scope, ctx);
@@ -1745,7 +1792,7 @@ void spl_sema_run(spl_sema_t *sema) {
continue;
if (!spl_sema_scope_insert(sema, sema->root_scope, m->type_decl.name, h.def))
sema_error(sema, mref, "duplicate type name");
agg_add_member(sema, sema->root_def, m->type_decl.name, h.tid, sema->root_scope);
agg_add_member(sema, sema->root_def, m->type_decl.name, h.tid, sema->root_scope, h.def);
} else if (te) {
spl_type_id_t tid = resolve_type_expr(sema, m->type_decl.type_expr);
spl_def_id_t def = def_alloc(sema, SPL_DEF_ALIAS);
@@ -1757,7 +1804,7 @@ void spl_sema_run(spl_sema_t *sema) {
d->type_def.scope_id = sema->root_scope;
if (!spl_sema_scope_insert(sema, sema->root_scope, m->type_decl.name, def))
sema_error(sema, mref, "duplicate type name");
agg_add_member(sema, sema->root_def, m->type_decl.name, tid, sema->root_scope);
agg_add_member(sema, sema->root_def, m->type_decl.name, tid, sema->root_scope, def);
}
}
/* 1b. fn 名(建 fn type + def */

View File

@@ -211,6 +211,8 @@ static const char *def_kind_name(spl_def_node_t *d) {
return "builtin";
case SPL_DEF_VAR:
return "var";
case SPL_DEF_MEMBER:
return "member";
case SPL_DEF_FN_PARAMS:
return "fn_params";
case SPL_DEF_AGG:
@@ -296,6 +298,9 @@ void spl_type_def_dump(spl_type_t *type, spl_def_id_t id) {
case SPL_DEF_VAR:
printf(" var=%s", d->var_def.name ? d->var_def.name : "?");
break;
case SPL_DEF_MEMBER:
printf(" member=%s", d->var_def.name ? d->var_def.name : "?");
break;
case SPL_DEF_ALIAS:
case SPL_DEF_DISTINCT:
printf(" type=%s", d->type_def.name ? d->type_def.name : "?");

View File

@@ -65,6 +65,7 @@ typedef struct {
enum {
SPL_DEF_NONE,
SPL_DEF_BUILTIN,
SPL_DEF_MEMBER,
SPL_DEF_VAR,
SPL_DEF_FN_PARAMS,
SPL_DEF_AGG, // include enum variants

View File

@@ -11,6 +11,7 @@
#include <string.h>
#include "spl_ast.h"
#include "spl_ast2ir.h"
#include "spl_lexer.h"
#include "spl_sema.h"
#include "spl_tok.h"
@@ -102,6 +103,34 @@ static void dump_sema(const char *src, const char *fname) {
spl_ast_drop(&ast);
}
static void dump_ir(const char *src, const char *fname) {
spl_tok_vec_t toks = spl_lex(src, fname);
spl_ast_t ast;
spl_ast_init(&ast, &toks);
spl_ast_prase(&ast);
spl_ast_valid(&ast);
spl_sema_t sema;
spl_sema_init(&sema);
sema.ast = &ast;
spl_sema_run(&sema);
spl_sema_check(&sema);
if (sema.error_count) {
printf("sema errors=%d, skip IR\n", sema.error_count);
spl_sema_drop(&sema);
spl_ast_drop(&ast);
return;
}
spl_ast2ir_t a2ir;
spl_ast2ir_init(&a2ir, &sema);
spl_ast2ir_run(&a2ir);
if (a2ir.err_count)
printf("ast2ir errors=%d\n", a2ir.err_count);
spl_ir_dump(&a2ir.ir, &sema.type);
spl_ast2ir_drop(&a2ir);
spl_sema_drop(&sema);
spl_ast_drop(&ast);
}
static int cmd_dump(const char *flags, const char *path) {
long len;
char *src = read_file(path, &len);
@@ -110,12 +139,15 @@ static int cmd_dump(const char *flags, const char *path) {
int do_tokens = strstr(flags, "tokens") != NULL || strcmp(flags, "all") == 0;
int do_ast = strstr(flags, "ast") != NULL || strcmp(flags, "all") == 0;
int do_sema = strstr(flags, "sema") != NULL || strcmp(flags, "all") == 0;
int do_ir = strstr(flags, "ir") != NULL || strcmp(flags, "all") == 0;
if (do_tokens)
dump_tokens(src, path);
if (do_ast)
dump_ast(src, path);
if (do_sema)
dump_sema(src, path);
if (do_ir)
dump_ir(src, path);
free(src);
return 0;
}
@@ -127,7 +159,7 @@ int main(int argc, char **argv) {
}
if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0) {
LOG_INFO("splc0 <in> <out> compile (.spl -> .sir, 阶段 B)\n");
LOG_INFO("splc0 --dump <flags> <file> dump: tokens,ast,sema,all\n");
LOG_INFO("splc0 --dump <flags> <file> dump: tokens,ast,sema,ir,all\n");
return 0;
}
int argi = 1;

View File

@@ -20,8 +20,8 @@ type Optional = enum {
/* ---- 带结构体数据的枚举 ---- */
type Point = struct {
var x: i32;
var y: i32;
x: i32;
y: i32;
}
type Shape = enum {

View File

@@ -1,54 +1,54 @@
/* ===== å¤<C3A5>æ<EFBFBD>ç±»åžåµŒå¥—综å<C2BC>ˆæµè¯• =====
* test20_complex — 结构体嵌套、切片、数组、方法、类型别名、枚举等
* 难度5/5
* test20_complex â€?结构体嵌套ã€<C3A3>切片ã€<C3A3>数组ã€<C3A3>æ¹æ³•ã€<C3A3>ç±»åžåˆ«å<C2AB><C3A5>ã€<C3A3>枚举ç­
* 难度�/5
*/
/* ---- 基础结构体 ---- */
/* ---- 基础结构�---- */
type Point = struct {
var x: i32;
var y: i32;
x: i32,
y: i32,
}
/* ---- 嵌套结构体 ---- */
/* ---- 嵌套结构�---- */
type Rect = struct {
var min: Point;
var max: Point;
min: Point,
max: Point,
}
/* ---- 含切片字段的结构体 (核心 bug 测试) ---- */
/* ---- å<EFBFBD>«åˆ‡ç‰‡å­—段的结构ä½?(核心 bug 测试) ---- */
type Buffer = struct {
var data: []u8;
var len: usize;
data: []u8,
len: usize,
}
/* ---- 含数组字段的结构体 ---- */
/* ---- å<EFBFBD>«æ•°ç»„字段的结构ä½?---- */
type MatrixRow = struct {
var items: [4]i32;
items: [4]i32,
}
/* ---- 含指针字段的结构体 ---- */
/* ---- å<EFBFBD>«æŒ‡éˆå­—段的结构ä½?---- */
type Node = struct {
var ptr: *i32;
var val: i32;
ptr: *i32,
val: i32,
}
/* ---- 多层级嵌套:结构体里的结构体里的切片 ---- */
type Bundle = struct {
var name: *u8;
var buf: Buffer;
var row: MatrixRow;
var pt: Point;
name: *u8,
buf: Buffer,
row: MatrixRow,
pt: Point,
}
/* ---- 枚举含数据 ---- */
/* ---- 枚举å<EFBFBD>«æ•°æ<EFBFBD>?---- */
type Status = enum {
Active: i32;
Inactive;
Pending: Point;
}
/* ---- 含方法的结构体 (方法定义在结构体内部) ---- */
/* ---- å<EFBFBD>«æ¹æ³•的结构ä½?(方法定义在结构体内部) ---- */
type Counter = struct {
var val: i32;
val: i32,
fn inc(self: *Counter) i32 {
self.val = self.val + 1;
@@ -70,7 +70,7 @@ type Counter = struct {
}
/* ============================================================
* 测试 1: 切片在结构体内部初始化 (修复的核心 bug)
* 测试 1: 切片在结构体内部åˆ<C3A5>å§åŒ?(ä¿®å¤<C3A5>的核å¿?bug)
* ============================================================ */
fn test_slice_in_struct() i32 {
@@ -85,7 +85,7 @@ fn test_slice_in_struct() i32 {
if b.data[1] != 66 { ret 3; }
if b.data[3] != 68 { ret 4; }
/* Modify through slice verify reflection */
/* Modify through slice �verify reflection */
b.data[0] = 90;
if raw[0] != 90 { ret 5; }
@@ -150,7 +150,7 @@ fn test_nested_struct() i32 {
}
/* ============================================================
* 测试 4: 结构体成员方法 (实例方法调用)
* 测试 4: 结构体æˆ<C3A6>å˜æ¹æ³?(实例方法调用)
* ============================================================ */
fn test_struct_method() i32 {
@@ -161,7 +161,7 @@ fn test_struct_method() i32 {
if r1 != 1 { ret 1; }
if c.val != 1 { ret 2; }
/* 带参数方法调用 c.add(&c, n) */
/* 带å<EFBFBD>æ•°æ¹æ³•è°ƒç”?c.add(&c, n) */
var r2: i32 = c.add(&c, 5);
if r2 != 6 { ret 3; }
if c.val != 6 { ret 4; }
@@ -193,7 +193,7 @@ fn test_ptr_in_struct() i32 {
v = 100;
if n.ptr[0] != 100 { ret 3; }
/* 通过指针在结构体内修改 */
/* 通过指针在结构体内修�*/
n.ptr[0] = 200;
if v != 200 { ret 4; }
@@ -201,7 +201,7 @@ fn test_ptr_in_struct() i32 {
}
/* ============================================================
* 测试 6: 多层级复杂嵌套
* 测试 6: 多å±çº§å¤<C3A5>æ<EFBFBD>嵌å¥?
* ============================================================ */
fn test_complex_nesting() i32 {
@@ -289,7 +289,7 @@ fn test_enum_complex() i32 {
}
/* ============================================================
* 主函数
* 主函�
* ============================================================ */
fn main() i32 {