stage1 重新实现ast2ir

This commit is contained in:
zzy committed 2026-09-10 23:20:09 +08:00
1 parent bcd26d3021
commit ab6e99c958
10 files changed
+1174 -676

No files matched your search

+3 -6
View File
@@ -1452,9 +1452,10 @@ static spl_ast_node_ref_t parse_primary(parser_t *p) {
return 0;
}
advance(p); // 消费 ']'
spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_ANON_ARRAY_LIT, t);
spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_ARRAY_LIT, t);
spl_ast_node_t *arr = node_at(p->ast, ref);
arr->anon_array_literal.elems = elems;
arr->array_literal.elems = elems;
arr->array_literal.elem_type = 0;
return ref;
} else {
SPL_FATAL(nx, "expected '{' or '[' after '.'");
@@ -2463,10 +2464,6 @@ static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t node_ref, dump_stack_t
dump_vec(ast, node->array_literal.elems, stack);
break;
case SPL_AST_EXPR_ANON_ARRAY_LIT:
dump_vec(ast, node->anon_array_literal.elems, stack);
break;
case SPL_AST_EXPR_AGGREGATE_LIT:
dump_vec(ast, node->aggregate_literal.fields, stack);
+4 -12
View File
@@ -49,7 +49,6 @@
X(SPL_AST_EXPR_CAST, V0, cast) \
X(SPL_AST_EXPR_TUPLE, V0, tuple) \
X(SPL_AST_EXPR_ARRAY_LIT, V0, array_literal) \
X(SPL_AST_EXPR_ANON_ARRAY_LIT, V0, anon_array_literal) \
X(SPL_AST_EXPR_AGGREGATE_LIT, V0, aggregate_literal) \
X(SPL_AST_EXPR_COMPTIME_CALL, V0, comptime_call) \
X(SPL_AST_EXPR_BLOCK, V0, block) \
@@ -151,11 +150,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_dbg_node_t dbg;
union {
usize resolved_def_id;
usize resolved_type_id;
};
usize resolved_def_id;
usize resolved_type_id;
union {
/* SPL_AST_ROOT */
@@ -356,16 +352,12 @@ struct spl_ast_node {
bool has_len;
usize len;
bool is_underscore_len;
spl_ast_node_ref_t elem_type;
spl_ast_node_ref_t elem_type; /* 可空 匿名时为 NULL */
spl_ast_node_ref_vec_t elems;
} array_literal;
struct {
spl_ast_node_ref_vec_t elems;
} anon_array_literal;
struct {
const char *name; /* 可空,匿名时为 NULL */
const char *name; /* 可空 匿名时为 NULL */
spl_ast_node_ref_vec_t fields; /* struct_init_item 节点列表 */
} aggregate_literal;
+805 -475
View File
File diff suppressed because it is too large. Load diff
+12
View File
@@ -5,10 +5,22 @@
#include "spl_sema.h"
typedef MAP(spl_def_id_t, spl_ir_node_ref_t) spl_def2ir_map_t;
typedef struct {
usize cont_blk;
usize brk_blk;
spl_ir_node_ref_vec_t breaks;
} spl_loop_ctx_t;
typedef VEC(spl_loop_ctx_t) spl_loop_ctx_vec_t;
typedef VEC(spl_ast_node_ref_t) spl_defer_stack_t;
typedef struct {
const spl_sema_t *sema;
spl_ir_builder_t *ir;
spl_def2ir_map_t def2ir_map;
spl_loop_ctx_vec_t loop_stack;
spl_defer_stack_t defer_stack;
int err_count;
} spl_ast2ir_t;
+2 -2
View File
@@ -196,7 +196,7 @@ static void ir_dump_node(const spl_type_t *ty, spl_ir_node_t *n) {
printf(" float=%f", 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_SLICE) {
} else if (t && t->kind == SPL_TYPE_PTR) {
printf(" str=\"%s\"", n->type_const.cstr_lit ? n->type_const.cstr_lit : "?");
} else if (t && t->kind == SPL_TYPE_INT && t->int_type.bits == 8) {
printf(" char='%c'", n->type_const.ch_lit);
@@ -276,7 +276,7 @@ void spl_ir_dump(spl_ir_t *ir, const spl_type_t *ty) {
continue;
spl_ir_func_t *func = &vec_at(ir->funcs, i);
printf("func %s %%%zu", func->name ? func->name : "?", i);
printf(" tid=");
printf(" tid = ");
spl_type_pure_dump((spl_type_t *)ty, func->fn_tid);
printf("\n");
vec_for(func->nodes, j) {
+225 -163
View File
@@ -62,98 +62,6 @@ static inline void sema_pop_scope(spl_sema_t *sema) {
sema->scope->current_scope = sema->store_scope;
}
static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_lang_type_id_t to,
spl_lang_type_id_t from) {
if (to == 0 || from == 0)
return 0;
spl_lang_type_node_t *to_node = spl_lang_type_node(sema->type, to);
if (!to_node)
return 0;
if (to_node->kind == SPL_LANG_TYPE_INFER)
return from;
spl_lang_type_node_t *from_node = spl_lang_type_node(sema->type, from);
if (!from_node)
return 0;
if (from_node->kind == SPL_LANG_TYPE_INT) {
spl_type_id_t from_ir = spl_lang_type_get_ir_type(sema->type, from);
spl_type_node_t *from_ir_node = spl_type_node(sema->type, from_ir);
if (from_ir_node && from_ir_node->int_type.bits == 0 && to_node->kind == SPL_LANG_TYPE_INT)
return to;
}
if (from_node->kind == SPL_LANG_TYPE_FLOAT) {
spl_type_id_t from_ir = spl_lang_type_get_ir_type(sema->type, from);
spl_type_node_t *from_ir_node = spl_type_node(sema->type, from_ir);
if (from_ir_node && from_ir_node->float_type.bits == 0 &&
to_node->kind == SPL_LANG_TYPE_FLOAT)
return to;
}
if (to_node->kind == SPL_LANG_TYPE_ARRAY && from_node->kind == SPL_LANG_TYPE_ARRAY) {
spl_lang_type_id_t to_elem = to_node->extra.elem;
spl_lang_type_id_t from_elem = from_node->extra.elem;
if (sema_coerce(sema, to_elem, from_elem) != 0)
return to;
}
if (spl_lang_type_is_subtype(sema->type, from, to))
return to;
return 0;
}
static spl_lang_type_id_t sema_coerce_balance(spl_sema_t *sema, spl_lang_type_id_t t1,
spl_lang_type_id_t t2) {
if (t1 == 0 || t2 == 0)
return 0;
if (t1 == t2)
return t1;
spl_lang_type_node_t *n1 = spl_lang_type_node(sema->type, t1);
spl_lang_type_node_t *n2 = spl_lang_type_node(sema->type, t2);
if (!n1 || !n2)
return 0;
if (n1->kind == SPL_LANG_TYPE_ANY || n2->kind == SPL_LANG_TYPE_ANY)
return spl_lang_make_any(sema->type);
if (n1->kind == SPL_LANG_TYPE_NEVER)
return t2;
if (n2->kind == SPL_LANG_TYPE_NEVER)
return t1;
if (spl_lang_type_is_subtype(sema->type, t1, t2))
return t2;
if (spl_lang_type_is_subtype(sema->type, t2, t1))
return t1;
if (n1->kind == SPL_LANG_TYPE_INT && n2->kind == SPL_LANG_TYPE_INT) {
// 如果一个是另一个的子类型,直接返回父类型(已在前面通用检查中处理)
// 否则符号不同且无法安全提升,返回 0
return 0;
}
if (n1->kind == SPL_LANG_TYPE_FLOAT && n2->kind == SPL_LANG_TYPE_FLOAT) {
spl_type_id_t ir1 = spl_lang_type_get_ir_type(sema->type, t1);
spl_type_id_t ir2 = spl_lang_type_get_ir_type(sema->type, t2);
spl_type_node_t *irn1 = spl_type_node(sema->type, ir1);
spl_type_node_t *irn2 = spl_type_node(sema->type, ir2);
if (irn1 && irn2) {
usize bits = irn1->float_type.bits > irn2->float_type.bits ? irn1->float_type.bits
: irn2->float_type.bits;
return spl_lang_make_float(sema->type, bits);
}
}
return 0;
}
static bool sema_coerce_for_bool(spl_sema_t *sema, spl_lang_type_id_t from) {
spl_lang_type_id_t bool_tid = spl_lang_make_bool(sema->type);
return sema_coerce(sema, bool_tid, from) == bool_tid;
}
static spl_lang_type_id_t sema_for_elem_type(spl_sema_t *sema, spl_lang_type_id_t lang_tid) {
spl_lang_type_node_t *n = spl_lang_type_node(sema->type, lang_tid);
if (!n)
@@ -176,18 +84,29 @@ static void sema_collect(spl_sema_t *sema, spl_ast_node_ref_t ref) {
switch (n->kind) {
case SPL_AST_CONTAINER_MEMBERS: {
/* root_scope 只在第一次创建,后续 module 复用 */
if (sema->scope->root_scope == 0) {
spl_scope_id_t root = spl_scope_alloc(sema->scope);
sema->scope->root_scope = root;
}
/* 进入 root_scope,再为当前 module 开一个子 scope */
sema->scope->current_scope = sema->scope->root_scope;
spl_scope_id_t mod_scope = spl_scope_alloc(sema->scope);
sema->scope->current_scope = mod_scope;
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);
n->resolved_def_id = file_sym.node;
spl_scope_id_t root_scope = spl_scope_alloc(sema->scope);
sema->scope->current_scope = root_scope;
sema->scope->root_scope = root_scope;
spl_scope_insert(sema->scope, root_scope, file_sym);
spl_scope_insert(sema->scope, mod_scope, file_sym);
for (usize i = 0; i < vec_size(n->container_members.declarations); ++i) {
sema_collect(sema, vec_at(n->container_members.declarations, i));
}
/* 故意不恢复 current_scope
保持 mod_scope 交给随后的 sema_parse 使用。
恢复由 spl_sema_run_module 统一负责 */
break;
}
case SPL_AST_TYPE_DECL: {
@@ -417,15 +336,19 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
return 0;
}
spl_ast_node_t *init_node = spl_ast_node(sema->ast, n->var_const_decl.init_expr);
spl_lang_type_id_t init_tid = sema_parse(sema, n->var_const_decl.init_expr);
decl_tid = sema_coerce(sema, decl_tid, init_tid);
if (decl_tid == 0) {
SPL_ERROR(&n->dbg, "cannot infer type for variable `%s`", name);
spl_lang_type_id_t coerce_result = spl_lang_type_coerce_to(sema->type, decl_tid, init_tid);
if (coerce_result == 0) {
SPL_ERROR(&n->dbg, "cannot coerce initializer to declared type");
sema->error_count++;
return 0;
}
init_node->resolved_type_id = coerce_result;
decl_tid = coerce_result;
spl_def_resolve(sema->type, n->resolved_def_id, decl_tid);
n->resolved_type_id = decl_tid; // 存储 lang_id
n->resolved_type_id = decl_tid;
return decl_tid;
}
@@ -500,6 +423,7 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
sema->error_count++;
return 0;
}
n->resolved_type_id = def->lang_id;
return def->lang_id;
}
@@ -556,14 +480,18 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
spl_binary_op_t op = n->binary.op;
switch (op) {
case SPL_OP_ASSIGN:
if (sema_coerce(sema, lt, rt) == 0) {
case SPL_OP_ASSIGN: {
spl_ast_node_t *rhs = spl_ast_node(sema->ast, n->binary.right);
spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, lt, rt);
if (r == 0) {
SPL_ERROR(&n->dbg, "assignment type mismatch");
sema->error_count++;
return 0;
}
rhs->resolved_type_id = r;
n->resolved_type_id = lt;
return lt;
}
case SPL_OP_ASSIGN_ADD:
case SPL_OP_ASSIGN_SUB:
@@ -575,12 +503,20 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
case SPL_OP_ASSIGN_XOR:
case SPL_OP_ASSIGN_LSHIFT:
case SPL_OP_ASSIGN_RSHIFT: {
spl_lang_type_id_t balanced = sema_coerce_balance(sema, lt, rt);
spl_lang_type_id_t balanced = spl_lang_type_balance(sema->type, lt, rt);
if (balanced == 0 || balanced != lt) {
SPL_ERROR(&n->dbg, "compound assignment type mismatch");
sema->error_count++;
return 0;
}
spl_ast_node_t *rhs = spl_ast_node(sema->ast, n->binary.right);
spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, lt, rt);
if (r == 0) {
SPL_ERROR(&n->dbg, "compound assignment right type mismatch");
sema->error_count++;
return 0;
}
rhs->resolved_type_id = r;
n->resolved_type_id = lt;
return lt;
}
@@ -602,13 +538,22 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
case SPL_OP_BIT_OR:
case SPL_OP_BIT_XOR:
case SPL_OP_BIT_AND: {
spl_lang_type_id_t bal = sema_coerce_balance(sema, lt, rt);
spl_lang_type_id_t bal = spl_lang_type_balance(sema->type, lt, rt);
spl_lang_type_node_t *bn = spl_lang_type_node(sema->type, bal);
if (!bn || bn->kind != SPL_LANG_TYPE_INT) {
SPL_ERROR(&n->dbg, "bitwise operands must be integers");
sema->error_count++;
return 0;
}
/* 两边都 coerce 到 bal */
if (lt != bal) {
spl_ast_node_t *ln = spl_ast_node(sema->ast, n->binary.left);
ln->resolved_type_id = spl_lang_type_coerce_to(sema->type, bal, lt);
}
if (rt != bal) {
spl_ast_node_t *rn = spl_ast_node(sema->ast, n->binary.right);
rn->resolved_type_id = spl_lang_type_coerce_to(sema->type, bal, rt);
}
n->resolved_type_id = bal;
return bal;
}
@@ -619,13 +564,12 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
case SPL_OP_CMP_GE:
case SPL_OP_CMP_LT:
case SPL_OP_CMP_GT: {
// FIXME 不一定合理
spl_lang_type_node_t *ln = spl_lang_type_node(sema->type, lt);
spl_lang_type_node_t *rn = spl_lang_type_node(sema->type, rt);
bool numeric =
(ln && (ln->kind == SPL_LANG_TYPE_INT || ln->kind == SPL_LANG_TYPE_FLOAT)) &&
(rn && (rn->kind == SPL_LANG_TYPE_INT || rn->kind == SPL_LANG_TYPE_FLOAT));
if (!numeric && sema_coerce_balance(sema, lt, rt) == 0) {
if (!numeric && spl_lang_type_balance(sema->type, lt, rt) == 0) {
SPL_ERROR(&n->dbg, "comparison operands type mismatch");
sema->error_count++;
return 0;
@@ -653,13 +597,21 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
case SPL_OP_MUL:
case SPL_OP_DIV:
case SPL_OP_MOD: {
spl_lang_type_id_t bal = sema_coerce_balance(sema, lt, rt);
spl_lang_type_id_t bal = spl_lang_type_balance(sema->type, lt, rt);
spl_lang_type_node_t *bn = spl_lang_type_node(sema->type, bal);
if (!bn || (bn->kind != SPL_LANG_TYPE_INT && bn->kind != SPL_LANG_TYPE_FLOAT)) {
SPL_ERROR(&n->dbg, "arithmetic operands type mismatch");
sema->error_count++;
return 0;
}
if (lt != bal) {
spl_ast_node_t *ln = spl_ast_node(sema->ast, n->binary.left);
ln->resolved_type_id = spl_lang_type_coerce_to(sema->type, bal, lt);
}
if (rt != bal) {
spl_ast_node_t *rn = spl_ast_node(sema->ast, n->binary.right);
rn->resolved_type_id = spl_lang_type_coerce_to(sema->type, bal, rt);
}
n->resolved_type_id = bal;
return bal;
}
@@ -699,35 +651,41 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
}
if (has_varargs) {
// 可变参数函数:实参数量至少等于固定参数数量
if (vec_size(n->call.args) < fixed_param_count) {
SPL_ERROR(&n->dbg, "too few arguments (expected at least %zu)", fixed_param_count);
sema->error_count++;
} else {
// 检查固定参数部分
for (usize i = 0; i < fixed_param_count; ++i) {
spl_lang_type_id_t arg_tid = sema_parse(sema, vec_at(n->call.args, i));
spl_ast_node_ref_t arg_ref = vec_at(n->call.args, i);
spl_ast_node_t *arg_node = spl_ast_node(sema->ast, arg_ref);
spl_lang_type_id_t arg_tid = sema_parse(sema, arg_ref);
spl_lang_type_id_t param_tid = vec_at(fn->extra.fn.params, i);
if (sema_coerce(sema, param_tid, arg_tid) == 0) {
spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, param_tid, arg_tid);
if (r == 0) {
SPL_ERROR(&n->dbg, "argument %zu type mismatch", i + 1);
sema->error_count++;
} else {
arg_node->resolved_type_id = r;
}
}
// 额外参数不进行类型检查(或可扩展为元组类型检查)
}
} else {
// 非可变参数函数:实参数量必须严格匹配
if (vec_size(n->call.args) != vec_size(fn->extra.fn.params)) {
SPL_ERROR(&n->dbg, "argument count mismatch (expected %zu, got %zu)",
vec_size(fn->extra.fn.params), vec_size(n->call.args));
sema->error_count++;
} else {
for (usize i = 0; i < vec_size(n->call.args); ++i) {
spl_lang_type_id_t arg_tid = sema_parse(sema, vec_at(n->call.args, i));
spl_ast_node_ref_t arg_ref = vec_at(n->call.args, i);
spl_ast_node_t *arg_node = spl_ast_node(sema->ast, arg_ref);
spl_lang_type_id_t arg_tid = sema_parse(sema, arg_ref);
spl_lang_type_id_t param_tid = vec_at(fn->extra.fn.params, i);
if (sema_coerce(sema, param_tid, arg_tid) == 0) {
spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, param_tid, arg_tid);
if (r == 0) {
SPL_ERROR(&n->dbg, "argument %zu type mismatch", i + 1);
sema->error_count++;
} else {
arg_node->resolved_type_id = r;
}
}
}
@@ -880,56 +838,68 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
}
case SPL_AST_EXPR_ARRAY_LIT: {
/* elem_type 可空:匿名 .[...] 时从元素推导 */
spl_lang_type_id_t elem_tid = 0;
if (n->array_literal.elem_type) {
elem_tid = sema_parse(sema, n->array_literal.elem_type);
}
for (usize i = 0; i < vec_size(n->array_literal.elems); ++i) {
spl_lang_type_id_t et = sema_parse(sema, vec_at(n->array_literal.elems, i));
if (elem_tid == 0)
spl_ast_node_ref_t elem_ref = vec_at(n->array_literal.elems, i);
spl_ast_node_t *elem_node = spl_ast_node(sema->ast, elem_ref);
spl_lang_type_id_t et = sema_parse(sema, elem_ref);
if (elem_tid == 0) {
elem_tid = et;
else if (sema_coerce(sema, elem_tid, et) == 0) {
SPL_ERROR(&n->dbg, "array element type mismatch");
sema->error_count++;
} else {
spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, elem_tid, et);
if (r == 0) {
SPL_ERROR(&n->dbg, "array element type mismatch");
sema->error_count++;
} else {
elem_node->resolved_type_id = r;
}
}
}
if (elem_tid == 0) {
SPL_ERROR(&n->dbg, "cannot infer array element type "
"(empty literal without element type annotation)");
sema->error_count++;
return 0;
}
usize len;
if (n->array_literal.is_underscore_len) {
len = vec_size(n->array_literal.elems);
} else {
len =
n->array_literal.has_len ? n->array_literal.len : vec_size(n->array_literal.elems);
}
spl_lang_type_id_t arr_tid = spl_lang_make_array(sema->type, elem_tid, len);
n->resolved_type_id = arr_tid;
return arr_tid;
}
case SPL_AST_EXPR_ANON_ARRAY_LIT: {
spl_lang_type_id_t elem_tid = 0;
for (usize i = 0; i < vec_size(n->anon_array_literal.elems); ++i) {
spl_lang_type_id_t et = sema_parse(sema, vec_at(n->anon_array_literal.elems, i));
if (elem_tid == 0)
elem_tid = et;
else if (sema_coerce(sema, elem_tid, et) == 0) {
SPL_ERROR(&n->dbg, "array element type mismatch");
} else if (n->array_literal.has_len) {
len = (usize)n->array_literal.len;
if (len != vec_size(n->array_literal.elems)) {
SPL_ERROR(&n->dbg, "array literal length mismatch: declared %zu, got %zu", len,
vec_size(n->array_literal.elems));
sema->error_count++;
}
} else {
len = vec_size(n->array_literal.elems);
}
usize len = vec_size(n->anon_array_literal.elems);
spl_lang_type_id_t arr_tid = spl_lang_make_array(sema->type, elem_tid, len);
n->resolved_type_id = arr_tid;
return arr_tid;
}
case SPL_AST_EXPR_AGGREGATE_LIT: {
const char *type_name = n->aggregate_literal.name;
/* 匿名 .{...}:需要类型上下文。
SEMA 当前为自底向上,尚无"预期类型"传播机制;
待上层注解散布到 init_expr 之前时启用。
结构上已统一,只需在这里读取 n->resolved_type_id 即可。 */
if (!type_name) {
SPL_ERROR(&n->dbg, "anonymous aggregate literal not supported yet");
SPL_ERROR(&n->dbg, "anonymous aggregate literal requires expected type context "
"(not yet supported)");
sema->error_count++;
return 0;
}
spl_symbol_t sym;
if (!spl_scope_find(sema->scope, type_name, &sym)) {
SPL_ERROR(&n->dbg, "unknown type `%s`", type_name);
@@ -952,23 +922,44 @@ static spl_lang_type_id_t sema_parse(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_node_t *agg_ir_node = spl_type_node(sema->type, agg_ir);
if (!agg_ir_node) {
SPL_ERROR(&n->dbg, "aggregate IR type `%s` not found", type_name);
sema->error_count++;
return 0;
}
usize total_fields = vec_size(agg_ir_node->agg_type.variants);
/* 记录每个字段是否被初始化,最后检查缺省 */
bool *seen = calloc(total_fields, sizeof(bool));
if (!seen) {
SPL_ERROR(&n->dbg, "out of memory");
sema->error_count++;
return 0;
}
for (usize i = 0; i < vec_size(n->aggregate_literal.fields); ++i) {
spl_ast_node_t *item = spl_ast_node(sema->ast, vec_at(n->aggregate_literal.fields, i));
if (!item || item->kind != SPL_AST_STRUCT_INIT_ITEM)
continue;
const char *fname = item->struct_init_item.name;
spl_lang_type_id_t field_lang = 0;
if (item->struct_init_item.expr) {
field_lang = sema_parse(sema, item->struct_init_item.expr);
}
const spl_type_member_t *member = spl_type_agg_member(sema->type, agg_ir, fname);
if (!member) {
usize field_idx = 0;
if (!spl_type_agg_member_idx(sema->type, agg_ir, fname, &field_idx)) {
SPL_ERROR(&item->dbg, "no field `%s` in `%s`", fname, type_name);
sema->error_count++;
continue;
}
// 映射到底层类型对应的语言级类型
if (seen[field_idx]) {
SPL_ERROR(&item->dbg, "duplicate field `%s` in `%s`", fname, type_name);
sema->error_count++;
continue;
}
seen[field_idx] = true;
const spl_type_member_t *member = &vec_at(agg_ir_node->agg_type.variants, field_idx);
/* 通过字段的 ir 类型反查 lang 类型 */
spl_lang_type_id_t expected_lang = 0;
for (usize j = 1; j < vec_size(sema->type->lang_table); ++j) {
spl_lang_type_node_t *ln = &vec_at(sema->type->lang_table, j);
@@ -978,15 +969,37 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
}
}
if (!expected_lang) {
SPL_ERROR(&item->dbg, "cannot resolve field type for `%s`", fname);
SPL_ERROR(&item->dbg, "cannot resolve lang type for field `%s`", fname);
sema->error_count++;
continue;
}
if (sema_coerce(sema, expected_lang, field_lang) == 0) {
if (!item->struct_init_item.expr) {
SPL_ERROR(&item->dbg, "field `%s` requires an initializer", fname);
sema->error_count++;
continue;
}
spl_ast_node_t *fv = spl_ast_node(sema->ast, item->struct_init_item.expr);
spl_lang_type_id_t field_lang = sema_parse(sema, item->struct_init_item.expr);
spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, expected_lang, field_lang);
if (r == 0) {
SPL_ERROR(&item->dbg, "field `%s` type mismatch", fname);
sema->error_count++;
} else {
fv->resolved_type_id = r;
}
}
/* 检查缺省字段 */
for (usize i = 0; i < total_fields; ++i) {
if (!seen[i]) {
const spl_type_member_t *m = &vec_at(agg_ir_node->agg_type.variants, i);
SPL_ERROR(&n->dbg, "missing field `%s` in `%s`", m->name, type_name);
sema->error_count++;
}
}
free(seen);
n->resolved_type_id = agg_lang;
return agg_lang;
@@ -1007,15 +1020,43 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
case SPL_AST_EXPR_IF: {
spl_lang_type_id_t cond_tid = sema_parse(sema, n->if_expr.cond);
if (!sema_coerce_for_bool(sema, cond_tid)) {
spl_lang_type_id_t bool_tid = spl_lang_make_bool(sema->type);
if (spl_lang_type_coerce_to(sema->type, bool_tid, cond_tid) == 0) {
SPL_ERROR(&n->dbg, "if condition must be bool");
sema->error_count++;
}
sema_parse(sema, n->if_expr.then_block);
if (n->if_expr.else_branch) {
sema_parse(sema, n->if_expr.else_branch);
spl_lang_type_id_t then_t =
n->if_expr.then_block ? sema_parse(sema, n->if_expr.then_block) : 0;
spl_lang_type_id_t else_t =
n->if_expr.else_branch ? sema_parse(sema, n->if_expr.else_branch) : 0;
spl_lang_type_id_t result_t = 0;
if (then_t && else_t) {
result_t = spl_lang_type_balance(sema->type, then_t, else_t);
if (result_t == 0) {
SPL_ERROR(&n->dbg, "if branches type mismatch");
sema->error_count++;
} else {
if (then_t != result_t) {
spl_ast_node_t *tn = spl_ast_node(sema->ast, n->if_expr.then_block);
spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, result_t, then_t);
if (r)
tn->resolved_type_id = r;
}
if (else_t != result_t) {
spl_ast_node_t *en = spl_ast_node(sema->ast, n->if_expr.else_branch);
spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, result_t, else_t);
if (r)
en->resolved_type_id = r;
}
}
} else {
result_t = then_t ? then_t : else_t;
}
return 0;
n->resolved_type_id = result_t;
return result_t;
}
case SPL_AST_EXPR_IFVAR: {
@@ -1029,7 +1070,8 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
case SPL_AST_EXPR_WHILE: {
spl_lang_type_id_t cond_tid = sema_parse(sema, n->while_expr.cond);
if (!sema_coerce_for_bool(sema, cond_tid)) {
spl_lang_type_id_t bool_tid = spl_lang_make_bool(sema->type);
if (spl_lang_type_coerce_to(sema->type, bool_tid, cond_tid) == 0) {
SPL_ERROR(&n->dbg, "while condition must be bool");
sema->error_count++;
}
@@ -1189,16 +1231,21 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
case SPL_AST_STATEMENT_RET: {
if (n->statement_ret.expr) {
spl_ast_node_t *en = spl_ast_node(sema->ast, n->statement_ret.expr);
spl_lang_type_id_t ret_tid = sema_parse(sema, n->statement_ret.expr);
if (sema->current_fn_ret_tid != 0 &&
sema_coerce(sema, sema->current_fn_ret_tid, ret_tid) == 0) {
SPL_ERROR(&n->dbg, "return type mismatch");
sema->error_count++;
if (sema->current_fn_ret_tid != 0) {
spl_lang_type_id_t r =
spl_lang_type_coerce_to(sema->type, sema->current_fn_ret_tid, ret_tid);
if (r == 0) {
SPL_ERROR(&n->dbg, "return type mismatch");
sema->error_count++;
} else {
en->resolved_type_id = r;
}
}
}
return 0;
}
case SPL_AST_STATEMENT_BREAK:
case SPL_AST_STATEMENT_CONTINUE:
return 0;
@@ -1245,6 +1292,22 @@ void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_scope
void spl_sema_drop(spl_sema_t *sema) { (void)sema; }
void spl_sema_run_module(spl_sema_t *sema, spl_ast_node_ref_t module_ref) {
if (!sema->ast || !module_ref)
return;
spl_ast_node_t *mod = spl_ast_node(sema->ast, module_ref);
if (!mod || mod->kind != SPL_AST_CONTAINER_MEMBERS)
return;
spl_scope_id_t saved = sema->scope->current_scope;
sema_collect(sema, module_ref);
/* 此时 current_scope == 该 module 的 mod_scope */
sema_parse(sema, module_ref);
sema->scope->current_scope = saved;
}
void spl_sema_run(spl_sema_t *sema) {
if (!sema->ast || !sema->ast->root)
return;
@@ -1253,8 +1316,7 @@ void spl_sema_run(spl_sema_t *sema) {
if (!root || root->kind != SPL_AST_ROOT)
return;
sema_collect(sema, root->root.members);
sema_parse(sema, root->root.members);
spl_sema_run_module(sema, root->root.members);
}
void spl_sema_dump(spl_sema_t *sema) {
+1
View File
@@ -50,6 +50,7 @@ typedef struct {
void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_scope_t *scope);
void spl_sema_drop(spl_sema_t *sema);
void spl_sema_run_module(spl_sema_t *sema, spl_ast_node_ref_t module_ref);
void spl_sema_run(spl_sema_t *sema);
void spl_sema_dump(spl_sema_t *sema);
+87 -1
View File
@@ -363,6 +363,93 @@ bool spl_lang_type_is_subtype(const spl_type_t *type, spl_lang_type_id_t sub,
return false;
}
spl_lang_type_id_t spl_lang_type_coerce_to(spl_type_t *type, spl_lang_type_id_t to,
spl_lang_type_id_t from) {
if (to == 0 || from == 0)
return 0;
if (to == from)
return to;
spl_lang_type_node_t *to_node = spl_lang_type_node(type, to);
if (!to_node)
return 0;
if (to_node->kind == SPL_LANG_TYPE_INFER)
return from;
spl_lang_type_node_t *from_node = spl_lang_type_node(type, from);
if (!from_node)
return 0;
if (from_node->kind == SPL_LANG_TYPE_INT && to_node->kind == SPL_LANG_TYPE_INT) {
spl_type_id_t from_ir = spl_lang_type_get_ir_type(type, from);
spl_type_node_t *from_ir_node = spl_type_node(type, from_ir);
if (from_ir_node && from_ir_node->int_type.bits == 0)
return to;
}
if (from_node->kind == SPL_LANG_TYPE_FLOAT && to_node->kind == SPL_LANG_TYPE_FLOAT) {
spl_type_id_t from_ir = spl_lang_type_get_ir_type(type, from);
spl_type_node_t *from_ir_node = spl_type_node(type, from_ir);
if (from_ir_node && from_ir_node->float_type.bits == 0)
return to;
}
if (to_node->kind == SPL_LANG_TYPE_ARRAY && from_node->kind == SPL_LANG_TYPE_ARRAY) {
spl_lang_type_id_t to_elem = to_node->extra.elem;
spl_lang_type_id_t from_elem = from_node->extra.elem;
if (spl_lang_type_coerce_to(type, to_elem, from_elem) != 0)
return to;
}
if (spl_lang_type_is_subtype(type, from, to))
return to;
return 0;
}
spl_lang_type_id_t spl_lang_type_balance(spl_type_t *type, spl_lang_type_id_t t1,
spl_lang_type_id_t t2) {
if (t1 == 0 || t2 == 0)
return 0;
if (t1 == t2)
return t1;
spl_lang_type_node_t *n1 = spl_lang_type_node(type, t1);
spl_lang_type_node_t *n2 = spl_lang_type_node(type, t2);
if (!n1 || !n2)
return 0;
if (n1->kind == SPL_LANG_TYPE_ANY || n2->kind == SPL_LANG_TYPE_ANY)
return spl_lang_make_any(type);
if (n1->kind == SPL_LANG_TYPE_NEVER)
return t2;
if (n2->kind == SPL_LANG_TYPE_NEVER)
return t1;
if (spl_lang_type_is_subtype(type, t1, t2))
return t2;
if (spl_lang_type_is_subtype(type, t2, t1))
return t1;
if (n1->kind == SPL_LANG_TYPE_INT && n2->kind == SPL_LANG_TYPE_INT)
return 0;
if (n1->kind == SPL_LANG_TYPE_FLOAT && n2->kind == SPL_LANG_TYPE_FLOAT) {
spl_type_id_t ir1 = spl_lang_type_get_ir_type(type, t1);
spl_type_id_t ir2 = spl_lang_type_get_ir_type(type, t2);
spl_type_node_t *irn1 = spl_type_node(type, ir1);
spl_type_node_t *irn2 = spl_type_node(type, ir2);
if (irn1 && irn2) {
usize bits = irn1->float_type.bits > irn2->float_type.bits ? irn1->float_type.bits
: irn2->float_type.bits;
return spl_lang_make_float(type, bits);
}
}
return 0;
}
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) {
spl_def_node_t n = {0};
@@ -766,7 +853,6 @@ spl_lang_type_id_t spl_type_lookup_builtin(spl_type_t *type, const char *name) {
return 0;
}
/* ========== 转储函数 ========== */
void spl_type_pure_dump(spl_type_t *type, spl_type_id_t id) {
spl_type_node_t *n = spl_type_node(type, id);
if (!n) {
+18
View File
@@ -169,6 +169,24 @@ 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);
/* 计算 from 是否可以隐式转换到 to。
* - to 是 INFER 时视为"接受任意 from",返回 from。
* - 成功返回"转换后的类型"(正常是 to,INFER 时是 from)。
* - 失败返回 0。
* 纯函数:不修改任何 AST,不产生副作用。 */
spl_lang_type_id_t spl_lang_type_coerce_to(spl_type_t *type, spl_lang_type_id_t to,
spl_lang_type_id_t from);
/* 合并两个类型(用于 if 分支、算术运算的对称平衡)。
* - NEVER 与任意 T 平衡得到 T。
* - ANY 与任意 T 平衡得到 ANY。
* - 子类型与父类型平衡得到父类型。
* - 两个浮点取位宽较大者。
* - 两个整数不自动提升,除非一方是另一方的子类型。
* 无法合并返回 0。纯函数。 */
spl_lang_type_id_t spl_lang_type_balance(spl_type_t *type, spl_lang_type_id_t t1,
spl_lang_type_id_t t2);
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);
+17 -17
View File
@@ -111,23 +111,23 @@ static int compile_spl(const char *src, const char *fname, const char *outpath,
return 0;
}
// spl_ast2ir_t a2ir;
// spl_ir_builder_t ir_builder;
// spl_ir_builder_init(&ir_builder);
// spl_ast2ir_init(&a2ir, &ir_builder, &sema);
// spl_ast2ir_run(&a2ir);
// if (a2ir.err_count) {
// printf("ast2ir errors=%d, no output\n", a2ir.err_count);
// spl_ast2ir_drop(&a2ir);
// spl_sema_drop(&sema);
// spl_ast_drop(&ast);
// return 1;
// }
// if (dump == DUMP_IR) {
// spl_ir_dump(&ir_builder.ir, &type);
// // memory leak
// return 0;
// }
spl_ast2ir_t a2ir;
spl_ir_builder_t ir_builder;
spl_ir_builder_init(&ir_builder);
spl_ast2ir_init(&a2ir, &ir_builder, &sema);
spl_ast2ir_run(&a2ir);
if (a2ir.err_count) {
printf("ast2ir errors=%d, no output\n", a2ir.err_count);
spl_ast2ir_drop(&a2ir);
spl_sema_drop(&sema);
spl_ast_drop(&ast);
return 1;
}
if (dump == DUMP_IR) {
spl_ir_dump(&ir_builder.ir, &type);
// memory leak
return 0;
}
// spl_ir2vm_t ir2vm;
// spl_ir2vm_init(&ir2vm, &a2ir.ir->ir, sema.type);