diff --git a/stage0/include/core_map.h b/stage0/include/core_map.h index 096e68f..938591d 100644 --- a/stage0/include/core_map.h +++ b/stage0/include/core_map.h @@ -130,6 +130,56 @@ static inline usize map_hash_str(const char *s) { } \ } while (0) +/** + * 插入(仅当键不存在时),若键已存在则静默跳过,不更新值 + * 与 map_put 的差异仅在"键已存在时":map_put 更新值,map_put_new 放弃 + */ +#define map_put_new(map, _key, _val) \ + do { \ + /* 扩容 */ \ + if ((map).cap == 0 || (map).size * 128 / (map).cap >= MAP_DEFAULT_LOAD_FACTOR) { \ + usize new_cap = (map).cap == 0 ? 8 : (map).cap * 2; \ + MAP_SLOT(MAP_TYPEOF((map).data->key), MAP_TYPEOF((map).data->val)) *new_data = \ + calloc(new_cap, sizeof(*new_data)); \ + if (!new_data) \ + abort(); \ + /* 重新插入旧元素 */ \ + for (usize _i = 0; _i < (map).cap; ++_i) { \ + if ((map).data[_i].state == __MAP_SLOT_OCCUPIED) { \ + usize _h = (map).hash((map).data[_i].key) & (new_cap - 1); \ + while (new_data[_h].state == __MAP_SLOT_OCCUPIED) \ + _h = (_h + 1) & (new_cap - 1); \ + new_data[_h].key = (map).data[_i].key; \ + new_data[_h].val = (map).data[_i].val; \ + new_data[_h].state = __MAP_SLOT_OCCUPIED; \ + } \ + } \ + free((map).data); \ + (map).data = (void *)new_data; \ + (map).cap = new_cap; \ + } \ + /* 查找 */ \ + usize _mask = (map).cap - 1; \ + usize _idx = (map).hash(_key) & _mask; \ + usize _first_del = (usize) - 1; \ + while ((map).data[_idx].state != __MAP_SLOT_EMPTY) { \ + if ((map).data[_idx].state == __MAP_SLOT_OCCUPIED && \ + (map).cmp((map).data[_idx].key, _key) == 0) { \ + break; /* 已存在,不更新 */ \ + } \ + if ((map).data[_idx].state == __MAP_SLOT_DELETED && _first_del == (usize) - 1) \ + _first_del = _idx; \ + _idx = (_idx + 1) & _mask; \ + } \ + if ((map).data[_idx].state == __MAP_SLOT_EMPTY) { \ + usize _target = (_first_del != (usize) - 1) ? _first_del : _idx; \ + (map).data[_target].key = _key; \ + (map).data[_target].val = _val; \ + (map).data[_target].state = __MAP_SLOT_OCCUPIED; \ + ++(map).size; \ + } \ + } while (0) + /** * 查询:若找到,*out_val 被赋值为对应值并返回 1;否则返回 0 */ @@ -152,6 +202,33 @@ static inline usize map_hash_str(const char *s) { _found; \ })) +/** + * 查询(续探):首次调用前将 *in_out_idx 置为 (usize)-1, + * 则从键自身的 hash 桶开始查找;命中后 *out_val 被赋值、返回 1, + * 且 *in_out_idx 更新为命中槽位,下次调用从该槽的下一个继续探测(碰撞续探)。 + * 扫描到空槽返回 0。用于 key 碰撞后需要回表二次比较的场景。 + */ +#define map_get_continue(map, _key, out_val, in_out_idx) \ + (({ \ + int _found = 0; \ + if ((map).cap > 0) { \ + usize _mask = (map).cap - 1; \ + usize _idx = (*(in_out_idx) == (usize) - 1) ? (map).hash(_key) & _mask \ + : (*(in_out_idx) + 1) & _mask; \ + while ((map).data[_idx].state != __MAP_SLOT_EMPTY) { \ + if ((map).data[_idx].state == __MAP_SLOT_OCCUPIED && \ + (map).cmp((map).data[_idx].key, _key) == 0) { \ + *out_val = (map).data[_idx].val; \ + *(in_out_idx) = _idx; \ + _found = 1; \ + break; \ + } \ + _idx = (_idx + 1) & _mask; \ + } \ + } \ + _found; \ + })) + /** * 删除指定键 */ diff --git a/stage1/spl_sema.c b/stage1/spl_sema.c index 250ec3b..87a2c64 100644 --- a/stage1/spl_sema.c +++ b/stage1/spl_sema.c @@ -61,7 +61,7 @@ static void sema_collect(spl_sema_t *sema, spl_ast_node_ref_t ref) { case SPL_AST_CONTAINER_MEMBERS: { symbol.name = "$file"; symbol.kind = SPL_SYMBOL_KIND_TYPE; - symbol.node = spl_type_def_alloc(sema->type); + symbol.node = spl_type_def_alloc(sema->type, SPL_DEF_AGG, "$file", n->dbg, ref); n->resolved_def_id = symbol.node; spl_scope_id_t scope_id = spl_scope_alloc(sema->scope); @@ -69,41 +69,38 @@ static void sema_collect(spl_sema_t *sema, spl_ast_node_ref_t ref) { sema->scope->root_scope = scope_id; spl_scope_insert(sema->scope, scope_id, symbol); vec_for(n->container_members, i) { sema_collect(sema, vec_at(n->container_members, i)); } - - spl_def_node_t *def = spl_type_def(sema->type, symbol.node); - def->kind = SPL_DEF_AGG; break; } case SPL_AST_TYPE_DECL: { symbol.name = n->type_decl.name; symbol.kind = SPL_SYMBOL_KIND_TYPE; - symbol.node = spl_type_def_alloc(sema->type); - n->resolved_def_id = symbol.node; - n = spl_ast_node(sema->ast, n->type_decl.type_expr); - if (!n) { + spl_ast_node_t *te = spl_ast_node(sema->ast, n->type_decl.type_expr); + if (!te) { SPL_ERROR(&n->dbg, "type_decl must have type_expr"); sema->error_count++; return; } - spl_def_node_t *def = spl_type_def(sema->type, symbol.node); - switch (n->kind) { + switch (te->kind) { case SPL_AST_TYPE_STRUCT: case SPL_AST_TYPE_UNION: case SPL_AST_TYPE_ENUM: case SPL_AST_TYPE_SHAPE: /* TODO for shape */ - def->kind = SPL_DEF_AGG; + symbol.node = spl_type_def_alloc(sema->type, SPL_DEF_AGG, symbol.name, te->dbg, ref); + n->resolved_def_id = symbol.node; spl_scope_id_t scope_id = spl_scope_alloc(sema->scope); spl_scope_id_t old_id = sema->scope->current_scope; spl_scope_insert(sema->scope, old_id, symbol); sema->scope->current_scope = scope_id; - vec_for(n->type_expr.aggregate_list, i) { - sema_collect(sema, vec_at(n->type_expr.aggregate_list, i)); + vec_for(te->type_expr.aggregate_list, i) { + spl_ast_node_ref_t mref = vec_at(te->type_expr.aggregate_list, i); + sema_collect(sema, mref); } sema->scope->current_scope = old_id; break; default: - def->kind = SPL_DEF_SCALAR; + symbol.node = spl_type_def_alloc(sema->type, SPL_DEF_SCALAR, symbol.name, te->dbg, ref); + n->resolved_def_id = symbol.node; spl_scope_insert(sema->scope, sema->scope->current_scope, symbol); break; } @@ -112,32 +109,17 @@ static void sema_collect(spl_sema_t *sema, spl_ast_node_ref_t ref) { case SPL_AST_FN_DEFINE: { symbol.name = n->fn_decl.name; symbol.kind = SPL_SYMBOL_KIND_FN; - symbol.node = spl_type_def_alloc(sema->type); + symbol.node = spl_type_def_alloc(sema->type, SPL_DEF_FN_PARAMS, symbol.name, n->dbg, ref); n->resolved_def_id = symbol.node; - - spl_def_node_t *def = spl_type_def(sema->type, symbol.node); - def->kind = SPL_DEF_FN_PARAMS; + // TODO same type avaliable insert twice for decl and define but define must only once spl_scope_insert(sema->scope, sema->scope->current_scope, symbol); } break; case SPL_AST_VAR_DECL: case SPL_AST_CONST_DECL: { symbol.name = n->var_const_decl.name; symbol.kind = SPL_SYMBOL_KIND_VAR; - symbol.node = spl_type_def_alloc(sema->type); + symbol.node = spl_type_def_alloc(sema->type, SPL_DEF_VAR, symbol.name, n->dbg, ref); n->resolved_def_id = symbol.node; - - spl_def_node_t *def = spl_type_def(sema->type, symbol.node); - def->kind = SPL_DEF_VAR; - spl_scope_insert(sema->scope, sema->scope->current_scope, symbol); - } break; - case SPL_AST_MEMBER_DECL: { - symbol.name = n->member_decl.name; - symbol.kind = SPL_SYMBOL_KIND_MEMBER; - symbol.node = spl_type_def_alloc(sema->type); - n->resolved_def_id = symbol.node; - - spl_def_node_t *def = spl_type_def(sema->type, symbol.node); - def->kind = SPL_DEF_MEMBER; spl_scope_insert(sema->scope, sema->scope->current_scope, symbol); } break; default: @@ -255,11 +237,29 @@ static spl_type_id_t sema_coerce_balance(spl_sema_t *sema, spl_type_id_t t1, spl } static bool sema_coerce_for_bool(spl_sema_t *sema, spl_type_id_t from) { - spl_type_id_t bool_tid = - spl_type_node_push(sema->type, (spl_type_node_t){.kind = SPL_TYPE_BOOL}); + spl_type_id_t bool_tid = spl_type_builder_simple(sema->type, SPL_TYPE_BOOL); return sema_coerce(sema, bool_tid, from) == bool_tid; } +// FIXME using lib ops +static spl_type_id_t sema_for_elem_type(spl_sema_t *sema, spl_type_id_t tid) { + spl_type_node_t *n = spl_type_node(sema->type, tid); + if (!n) + return 0; + switch (n->kind) { + case SPL_TYPE_SLICE: + return n->slice_element; + case SPL_TYPE_ARRAY: + return n->array_type.element; + case SPL_TYPE_PTR: + return n->ptr_pointee; + case SPL_TYPE_RANGE: + return n->range_element; + default: + return 0; + } +} + static inline void sema_push_scope(spl_sema_t *sema) { spl_scope_id_t scope_id = spl_scope_alloc(sema->scope); sema->store_scope = sema->scope->current_scope; @@ -284,45 +284,61 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { case SPL_AST_CONTAINER_MEMBERS: { vec_for(n->container_members, i) { sema_parse(sema, vec_at(n->container_members, i)); } } break; - case SPL_AST_FN_DECL: + case SPL_AST_FN_DECL: { + if (n->resolved_def_id == 0) { + Panic("fn `%s` don't collect", n->fn_decl.name); + } + /* 前向/extern 声明:只解析签名并构建 fn 类型,不进入 scope */ + spl_type_id_vec_t params_type; + vec_init(params_type); + vec_for(n->fn_decl.param_list, i) { + spl_ast_node_ref_t ref = vec_at(n->fn_decl.param_list, i); + spl_ast_node_t *pd = spl_ast_node(sema->ast, ref); + if (pd && pd->kind == SPL_AST_PARAM_DECL && pd->param_decl.type_expr) { + vec_push(params_type, sema_parse(sema, pd->param_decl.type_expr)); + } else { + // TODO variadic + } + } + spl_type_id_t ret_id = sema_parse(sema, n->fn_decl.type_expr); + spl_type_id_t fntid = spl_type_builder_fn( + sema->type, ret_id, vec_unsafe_get_data(params_type), vec_size(params_type)); + // Move params_type don't need free + spl_type_def_resolve(sema->type, n->resolved_def_id, fntid); break; + } case SPL_AST_FN_DEFINE: { if (n->resolved_def_id == 0) { Panic("fn `%s` don't collect", n->fn_decl.name); } - spl_def_node_t *def = spl_type_def(sema->type, n->resolved_def_id); - def->kind = SPL_DEF_FN_PARAMS; - vec_init(def->fn_params_def); sema_push_scope(sema); - spl_var_def_vec_t params; - vec_init(params); + spl_type_id_vec_t params_type; + vec_init(params_type); + vec_for(n->fn_decl.param_list, i) { spl_ast_node_ref_t ref = vec_at(n->fn_decl.param_list, i); - spl_type_id_t tid = sema_parse(sema, ref); spl_ast_node_t *node = spl_ast_node(sema->ast, ref); + if (!node || node->kind != SPL_AST_PARAM_DECL || !node->param_decl.type_expr) { + // TODO variadic + continue; + } + spl_type_id_t tid = sema_parse(sema, ref); Assert(node->kind == SPL_AST_PARAM_DECL); - spl_var_def_t var_def = {0}; - var_def.name = node->param_decl.name; - var_def.type_id = tid; - var_def.def_id = node->resolved_def_id; - var_def.scope_id = sema->scope->current_scope; - vec_push(params, var_def); + vec_push(params_type, tid); if (node->resolved_def_id) { - spl_def_node_t *pd = spl_type_def(sema->type, node->resolved_def_id); - Assert(pd != NULL); - pd->var_def.type_id = tid; + spl_type_def_resolve(sema->type, node->resolved_def_id, tid); } } - - spl_def_node_t *def2 = spl_type_def(sema->type, n->resolved_def_id); - vec_free(def2->fn_params_def); - def2->fn_params_def = params; - spl_type_id_t ret_id = sema_parse(sema, n->fn_decl.type_expr); - spl_type_def_fn_build(sema->type, n->resolved_def_id, ret_id); + + spl_type_id_t fntid = spl_type_builder_fn( + sema->type, ret_id, vec_unsafe_get_data(params_type), vec_size(params_type)); + // Move params_type don't need free + spl_type_def_resolve(sema->type, n->resolved_def_id, fntid); + spl_type_id_t old_ret = sema->current_fn_ret_tid; sema->current_fn_ret_tid = ret_id; vec_for(n->fn_decl.block, i) { sema_parse(sema, vec_at(n->fn_decl.block, i)); } @@ -330,8 +346,64 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { sema_pop_scope(sema); } break; case SPL_AST_TYPE_DECL: { - if (n->type_decl.type_expr) { - sema_parse(sema, n->type_decl.type_expr); + if (!n->type_decl.type_expr) { + break; + } + spl_ast_node_t *te = spl_ast_node(sema->ast, n->type_decl.type_expr); + if (!te) { + break; + } + switch (te->kind) { + case SPL_AST_TYPE_STRUCT: + case SPL_AST_TYPE_UNION: + case SPL_AST_TYPE_ENUM: { + spl_type_member_vec_t members; + vec_init(members); + /* 第一遍:只收字段(MEMBER_DECL)的类型,构建容器类型并 resolve; + * 方法(fn)留到类型 resolve 后再处理,否则方法体引用自身类型会拿到未解析的 0 */ + vec_for(te->type_expr.aggregate_list, i) { + spl_ast_node_ref_t mref = vec_at(te->type_expr.aggregate_list, i); + spl_ast_node_t *mn = spl_ast_node(sema->ast, mref); + if (!mn || mn->kind != SPL_AST_MEMBER_DECL) + continue; + spl_type_id_t mtid = sema_parse(sema, mref); + spl_type_member_t m = {0}; + m.name = mn->member_decl.name; + m.type_id = mtid; + m.ast_node_ref = mref; + vec_push(members, m); + } + spl_type_node_kind_t tk = te->kind == SPL_AST_TYPE_UNION ? SPL_TYPE_UNION + : te->kind == SPL_AST_TYPE_ENUM ? SPL_TYPE_ENUM + : SPL_TYPE_STRUCT; + spl_type_layout_t layout = {.mode = SPL_TYPE_LAYOUT_AUTO, .fixed_align_bits = 0}; + + // TODO tag type + spl_type_id_t tid = spl_type_builder_agg( + sema->type, tk, vec_unsafe_get_data(members), vec_size(members), + spl_type_builder_int(sema->type, 32, 1), layout); + // Move members don't need free + + spl_type_def_resolve(sema->type, n->resolved_def_id, tid); + /* 第二遍:方法 body(struct 类型已 resolve,可引用自身类型) */ + vec_for(te->type_expr.aggregate_list, i) { + spl_ast_node_ref_t mref = vec_at(te->type_expr.aggregate_list, i); + spl_ast_node_t *mn = spl_ast_node(sema->ast, mref); + if (mn && mn->kind == SPL_AST_FN_DEFINE) + sema_parse(sema, mref); + } + break; + } + case SPL_AST_TYPE_SHAPE: /* TODO */ + vec_for(te->type_expr.aggregate_list, i) { + sema_parse(sema, vec_at(te->type_expr.aggregate_list, i)); + } + break; + default: { + spl_type_id_t tid = sema_parse(sema, n->type_decl.type_expr); + spl_type_def_resolve(sema->type, n->resolved_def_id, tid); + break; + } } } break; case SPL_AST_VAR_DECL: @@ -340,15 +412,10 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { spl_symbol_t symbol = {0}; symbol.name = n->var_const_decl.name; symbol.kind = SPL_SYMBOL_KIND_VAR; - symbol.node = spl_type_def_alloc(sema->type); + symbol.node = spl_type_def_alloc(sema->type, SPL_DEF_VAR, symbol.name, n->dbg, ref); n->resolved_def_id = symbol.node; - - spl_def_node_t *def = spl_type_def(sema->type, symbol.node); - def->kind = SPL_DEF_VAR; spl_scope_insert(sema->scope, sema->scope->current_scope, symbol); } - spl_def_node_t *def = spl_type_def(sema->type, n->resolved_def_id); - Assert(def != NULL); spl_type_id_t decl_tid = 0; if (n->var_const_decl.type_expr) { decl_tid = sema_parse(sema, n->var_const_decl.type_expr); @@ -364,13 +431,15 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { SPL_ERROR(&n->dbg, "decl type must not none %d"); sema->error_count += 1; } - def->type_id = decl_tid; - def->var_def.type_id = decl_tid; + spl_type_def_resolve(sema->type, n->resolved_def_id, decl_tid); } break; case SPL_AST_MEMBER_DECL: { + /* 字段/变体不建 def, 类型由 TYPE_DECL 组装成员时统一构造 */ + spl_type_id_t mtid = 0; if (n->member_decl.type_expr) { - sema_parse(sema, n->member_decl.type_expr); + mtid = sema_parse(sema, n->member_decl.type_expr); } + return mtid; } break; case SPL_AST__COMPTIME_STMT: case SPL_AST__DIRECTIVE_BLOCK: @@ -380,19 +449,15 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { spl_symbol_t symbol = {0}; symbol.name = n->param_decl.name; symbol.kind = SPL_SYMBOL_KIND_VAR; - symbol.node = spl_type_def_alloc(sema->type); + symbol.node = spl_type_def_alloc(sema->type, SPL_DEF_VAR, symbol.name, n->dbg, ref); n->resolved_def_id = symbol.node; - - spl_def_node_t *def = spl_type_def(sema->type, symbol.node); - def->kind = SPL_DEF_VAR; spl_scope_insert(sema->scope, sema->scope->current_scope, symbol); } spl_type_id_t ptid = 0; if (n->param_decl.type_expr) { ptid = sema_parse(sema, n->param_decl.type_expr); } - spl_def_node_t *pd = spl_type_def(sema->type, n->resolved_def_id); - pd->var_def.type_id = ptid; + spl_type_def_resolve(sema->type, n->resolved_def_id, ptid); return ptid; } break; case SPL_AST_ATTR_ITEM: @@ -451,10 +516,23 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { } } break; case SPL_AST_FOR_STATEMENT: { + sema_push_scope(sema); vec_for(n->for_statement.expr_vec, i) { - sema_parse(sema, vec_at(n->for_statement.expr_vec, i)); + spl_ast_node_ref_t eref = vec_at(n->for_statement.expr_vec, i); + spl_type_id_t stid = sema_parse(sema, eref); + spl_type_id_t etid = sema_for_elem_type(sema, stid); + if (i < vec_size(n->for_statement.ident_vec)) { + const char *vname = vec_at(n->for_statement.ident_vec, i); + spl_symbol_t symbol = {0}; + symbol.name = vname; + symbol.kind = SPL_SYMBOL_KIND_VAR; + symbol.node = spl_type_def_alloc(sema->type, SPL_DEF_VAR, vname, n->dbg, eref); + spl_type_def_resolve(sema->type, symbol.node, etid); + spl_scope_insert(sema->scope, sema->scope->current_scope, symbol); + } } - vec_for(n->for_statement.block, i) { sema_parse(sema, vec_at(n->for_statement.block, i)); } + vec_for(n->for_statement.block, j) { sema_parse(sema, vec_at(n->for_statement.block, j)); } + sema_pop_scope(sema); } break; case SPL_AST_MATCH_STATEMENT: { if (n->match_statement.expr) { @@ -545,7 +623,7 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { sema->error_count++; break; } - spl_type_id_t bt = spl_type_node_push(sema->type, (spl_type_node_t){.kind = SPL_TYPE_BOOL}); + spl_type_id_t bt = spl_type_builder_simple(sema->type, SPL_TYPE_BOOL); n->resolved_type_id = bt; return bt; } @@ -577,12 +655,20 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { sema->error_count++; break; } - spl_type_id_t bt = spl_type_node_push(sema->type, (spl_type_node_t){.kind = SPL_TYPE_BOOL}); + spl_type_id_t bt = spl_type_builder_simple(sema->type, SPL_TYPE_BOOL); n->resolved_type_id = bt; return bt; } - case SPL_AST_RANGE_EXPR: - break; + case SPL_AST_RANGE_EXPR: { + if (n->op_expr.left) + sema_parse(sema, n->op_expr.left); + if (n->op_expr.right) + sema_parse(sema, n->op_expr.right); + spl_type_id_t i64 = spl_type_builder_int(sema->type, 64, true); + spl_type_id_t rt = spl_type_builder_range(sema->type, i64); + n->resolved_type_id = rt; + return rt; + } case SPL_AST_LSHIFT_EXPR: case SPL_AST_RSHIFT_EXPR: { spl_type_id_t lt = sema_parse(sema, n->op_expr.left); @@ -604,6 +690,8 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { case SPL_AST_MOD_EXPR: { spl_type_id_t lt = sema_parse(sema, n->op_expr.left); spl_type_id_t rt = sema_parse(sema, n->op_expr.right); + spl_type_node_t *ln = spl_type_node(sema->type, lt); + spl_type_node_t *rn = spl_type_node(sema->type, rt); spl_type_id_t peer = sema_coerce_balance(sema, lt, rt); spl_type_node_t *pn = spl_type_node(sema->type, peer); if (!pn || (pn->kind != SPL_TYPE_INT && pn->kind != SPL_TYPE_FLOAT)) { @@ -617,19 +705,12 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { case SPL_AST_MINUS_EXPR: { spl_ast_node_t *op = spl_ast_node(sema->ast, n->prefix_expr.postfix_expr); if (op && op->kind == SPL_AST_EXPR_INTEGER_LIT) { - spl_type_id_t ct = spl_type_node_push(sema->type, (spl_type_node_t){ - .kind = SPL_TYPE_INT, - .int_type.bits = 0, - .int_type.is_signed = true, - }); + spl_type_id_t ct = spl_type_builder_int(sema->type, 0, true); n->resolved_type_id = ct; return ct; } if (op && op->kind == SPL_AST_EXPR_FLOAT_LIT) { - spl_type_id_t ct = spl_type_node_push(sema->type, (spl_type_node_t){ - .kind = SPL_TYPE_FLOAT, - .float_type.bits = 0, - }); + spl_type_id_t ct = spl_type_builder_float(sema->type, 0); n->resolved_type_id = ct; return ct; } @@ -651,7 +732,7 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { sema->error_count++; break; } - spl_type_id_t bt = spl_type_node_push(sema->type, (spl_type_node_t){.kind = SPL_TYPE_BOOL}); + spl_type_id_t bt = spl_type_builder_simple(sema->type, SPL_TYPE_BOOL); n->resolved_type_id = bt; return bt; } @@ -678,11 +759,7 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { sema->error_count++; break; } - if (vec_size(n->postfix_expr.call_expr) != vec_size(fn->fn_type.params)) { - SPL_ERROR(&n->dbg, "call argument count mismatch"); - sema->error_count++; - break; - } + // TODO type check vec_for(n->postfix_expr.call_expr, i) { spl_type_id_t at = sema_parse(sema, vec_at(n->postfix_expr.call_expr, i)); if (sema_coerce(sema, vec_at(fn->fn_type.params, i), at) == 0) { @@ -693,17 +770,65 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { n->resolved_type_id = fn->fn_type.ret; return fn->fn_type.ret; } - case SPL_AST_FIELD_EXPR: - case SPL_AST_DEREF_EXPR: - if (n->postfix_expr.primary_expr) - sema_parse(sema, n->postfix_expr.primary_expr); - break; - case SPL_AST_INDEX_EXPR: - if (n->postfix_expr.primary_expr) - sema_parse(sema, n->postfix_expr.primary_expr); + case SPL_AST_DEREF_EXPR: { + spl_type_id_t btid = sema_parse(sema, n->postfix_expr.primary_expr); + spl_type_node_t *bn = spl_type_node(sema->type, btid); + if (!bn || bn->kind != SPL_TYPE_PTR) { + SPL_ERROR(&n->dbg, "deref requires pointer"); + sema->error_count++; + break; + } + n->resolved_type_id = bn->ptr_pointee; + return bn->ptr_pointee; + } + case SPL_AST_FIELD_EXPR: { + spl_type_id_t btid = sema_parse(sema, n->postfix_expr.primary_expr); + spl_type_node_t *bn = spl_type_node(sema->type, btid); + spl_type_id_t agg_tid = btid; + if (bn && bn->kind == SPL_TYPE_PTR) + agg_tid = bn->ptr_pointee; /* 自动单层解引用 */ + spl_type_node_t *an = spl_type_node(sema->type, agg_tid); + const char *fname = n->postfix_expr.field_expr; + const spl_type_member_t *m = NULL; + if (an && (an->kind == SPL_TYPE_STRUCT || an->kind == SPL_TYPE_UNION)) + m = spl_type_agg_member(sema->type, agg_tid, fname); + if (!m) { + SPL_ERROR(&n->dbg, "no field `%s`", fname); + sema->error_count++; + break; + } + n->resolved_type_id = m->type_id; + return m->type_id; + } + case SPL_AST_INDEX_EXPR: { + spl_type_id_t btid = sema_parse(sema, n->postfix_expr.primary_expr); if (n->postfix_expr.index_expr) sema_parse(sema, n->postfix_expr.index_expr); - break; + spl_type_node_t *bn = spl_type_node(sema->type, btid); + spl_type_id_t etid = 0; + if (bn) { + switch (bn->kind) { + case SPL_TYPE_SLICE: + etid = bn->slice_element; + break; + case SPL_TYPE_ARRAY: + etid = bn->array_type.element; + break; + case SPL_TYPE_PTR: + etid = bn->ptr_pointee; + break; + default: + break; + } + } + if (etid == 0) { + SPL_ERROR(&n->dbg, "index base must be slice/array/ptr"); + sema->error_count++; + break; + } + n->resolved_type_id = etid; + return etid; + } case SPL_AST_SLICE_EXPR: if (n->postfix_expr.primary_expr) sema_parse(sema, n->postfix_expr.primary_expr); @@ -726,39 +851,37 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { return tt; } case SPL_AST_EXPR_INTEGER_LIT: { - spl_type_id_t ct = spl_type_node_push(sema->type, (spl_type_node_t){ - .kind = SPL_TYPE_INT, - .int_type.bits = 0, - .int_type.is_signed = true, - }); + spl_type_id_t ct = spl_type_builder_int(sema->type, 0, true); n->resolved_type_id = ct; return ct; } case SPL_AST_EXPR_FLOAT_LIT: { - spl_type_id_t ct = spl_type_node_push(sema->type, (spl_type_node_t){ - .kind = SPL_TYPE_FLOAT, - .float_type.bits = 0, - }); + spl_type_id_t ct = spl_type_builder_float(sema->type, 0); n->resolved_type_id = ct; return ct; } case SPL_AST_EXPR_CHAR_LIT: - case SPL_AST_EXPR_STRING_LIT: break; + case SPL_AST_EXPR_STRING_LIT: { + /* SPL.md: 字符串字面量 -> []u8 */ + spl_type_id_t u8 = spl_type_builder_int(sema->type, 8, false); + spl_type_id_t st = spl_type_builder_slice(sema->type, u8); + n->resolved_type_id = st; + return st; + } case SPL_AST_EXPR_NULL: { - spl_type_id_t nt = spl_type_node_push(sema->type, (spl_type_node_t){.kind = SPL_TYPE_NULL}); + spl_type_id_t nt = spl_type_builder_simple(sema->type, SPL_TYPE_NULL); n->resolved_type_id = nt; return nt; } case SPL_AST_EXPR_TRUE: case SPL_AST_EXPR_FALSE: { - spl_type_id_t bt = spl_type_node_push(sema->type, (spl_type_node_t){.kind = SPL_TYPE_BOOL}); + spl_type_id_t bt = spl_type_builder_simple(sema->type, SPL_TYPE_BOOL); n->resolved_type_id = bt; return bt; } case SPL_AST_EXPR_UNDEFINED: { - spl_type_id_t ut = - spl_type_node_push(sema->type, (spl_type_node_t){.kind = SPL_TYPE_UNDEFINED}); + spl_type_id_t ut = spl_type_builder_simple(sema->type, SPL_TYPE_UNDEFINED); n->resolved_type_id = ut; return ut; } @@ -772,19 +895,60 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { Assert(symbol.node != 0); n->resolved_def_id = symbol.node; spl_def_node_t *d = spl_type_def(sema->type, symbol.node); - if (!d) { - return 0; - } - if (d->kind == SPL_DEF_VAR || d->kind == SPL_DEF_MEMBER) { - return d->var_def.type_id; - } + Assert(d != 0); return d->type_id; } - case SPL_AST_ARGGREGATE_INIT: - vec_for(n->primary_expr.aggregate_init.expr, i) { - sema_parse(sema, vec_at(n->primary_expr.aggregate_init.expr, i)); + case SPL_AST_ARGGREGATE_INIT: { + const char *tname = n->primary_expr.aggregate_init.name; + if (!tname) { + SPL_ERROR(&n->dbg, "anonymous aggregate init TODO"); + sema->error_count++; + break; } - break; + spl_symbol_t sym = {0}; + if (!spl_scope_find(sema->scope, tname, &sym)) { + SPL_ERROR(&n->dbg, "aggregate init: unknown type `%s`", tname); + sema->error_count++; + break; + } + spl_def_node_t *d = spl_type_def(sema->type, sym.node); + spl_type_id_t tid = d ? d->type_id : 0; + spl_type_node_t *tn = spl_type_node(sema->type, tid); + if (!tn || (tn->kind != SPL_TYPE_STRUCT && tn->kind != SPL_TYPE_UNION)) { + SPL_ERROR(&n->dbg, "aggregate init: `%s` is not a struct", tname); + sema->error_count++; + break; + } + usize got = 0; + vec_for(n->primary_expr.aggregate_init.expr, i) { + spl_ast_node_t *item = + spl_ast_node(sema->ast, vec_at(n->primary_expr.aggregate_init.expr, i)); + if (!item || item->kind != SPL_AST_ARGG_INIT_ITEM) + continue; + got++; + const char *fname = item->aggregate_init_item.ident; + spl_type_id_t etid = item->aggregate_init_item.expr + ? sema_parse(sema, item->aggregate_init_item.expr) + : 0; + const spl_type_member_t *m = spl_type_agg_member(sema->type, tid, fname); + if (!m) { + SPL_ERROR(&item->dbg, "aggregate init: no field `%s` in `%s`", fname, tname); + sema->error_count++; + continue; + } + if (sema_coerce(sema, m->type_id, etid) == 0) { + SPL_ERROR(&item->dbg, "aggregate init: field `%s` type mismatch", fname); + sema->error_count++; + } + } + if (tn->kind == SPL_TYPE_STRUCT && got != vec_size(tn->agg_members)) { + SPL_ERROR(&n->dbg, "aggregate init: field count mismatch (%zu/%zu)", got, + vec_size(tn->agg_members)); + sema->error_count++; + } + n->resolved_type_id = tid; + return tid; + } case SPL_AST_EXPR_EXPR: { spl_type_id_t t = sema_parse(sema, n->primary_expr.expr); n->resolved_type_id = t; @@ -815,26 +979,65 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { if (n->type_expr.fn_type.type_expr) sema_parse(sema, n->type_expr.fn_type.type_expr); break; - case SPL_AST_BASE_TYPE_PATH: + case SPL_AST_BASE_TYPE_PATH: { vec_for(n->type_expr.attr_list, i) { sema_parse(sema, vec_at(n->type_expr.attr_list, i)); } + if (vec_size(n->type_expr.type_path.ident_vec) == 0) + break; + const char *tname = vec_at(n->type_expr.type_path.ident_vec, 0); + if (vec_size(n->type_expr.type_path.ident_vec) == 1) { + spl_symbol_t sym = {0}; + if (spl_scope_find(sema->scope, tname, &sym)) { + spl_def_node_t *d = spl_type_def(sema->type, sym.node); + if (d && d->type_id) { + n->resolved_type_id = d->type_id; + return d->type_id; + } + } + SPL_ERROR(&n->dbg, "type `%s` not found", tname); + sema->error_count++; + break; + } + /* 多段命名空间路径(如 Str.Inner):TODO */ + SPL_ERROR(&n->dbg, "nested type path TODO"); + sema->error_count++; break; - case SPL_AST_TYPE_POINTER: + } + case SPL_AST_TYPE_POINTER: { vec_for(n->type_expr.attr_list, i) { sema_parse(sema, vec_at(n->type_expr.attr_list, i)); } + spl_type_id_t ptid = 0; if (n->type_expr.pointer_type.pointee) - sema_parse(sema, n->type_expr.pointer_type.pointee); - break; - case SPL_AST_TYPE_ARRAY: + ptid = sema_parse(sema, n->type_expr.pointer_type.pointee); + spl_type_id_t tid = spl_type_builder_ptr(sema->type, ptid); + n->resolved_type_id = tid; + return tid; + } + case SPL_AST_TYPE_ARRAY: { vec_for(n->type_expr.attr_list, i) { sema_parse(sema, vec_at(n->type_expr.attr_list, i)); } + spl_type_id_t etid = 0; if (n->type_expr.array_type.element) - sema_parse(sema, n->type_expr.array_type.element); - if (n->type_expr.array_type.size) - sema_parse(sema, n->type_expr.array_type.size); - break; - case SPL_AST_TYPE_SLICE: + etid = sema_parse(sema, n->type_expr.array_type.element); + usize len = 0; + if (n->type_expr.array_type.size) { + spl_ast_node_t *sz = spl_ast_node(sema->ast, n->type_expr.array_type.size); + if (sz && sz->kind == SPL_AST_EXPR_INTEGER_LIT) { + len = (usize)sz->primary_expr.integer_expr; + } else { + sema_parse(sema, n->type_expr.array_type.size); + } + } + spl_type_id_t tid = spl_type_builder_array(sema->type, etid, len); + n->resolved_type_id = tid; + return tid; + } + case SPL_AST_TYPE_SLICE: { vec_for(n->type_expr.attr_list, i) { sema_parse(sema, vec_at(n->type_expr.attr_list, i)); } + spl_type_id_t etid = 0; if (n->type_expr.slice_type.element) - sema_parse(sema, n->type_expr.slice_type.element); - break; + etid = sema_parse(sema, n->type_expr.slice_type.element); + spl_type_id_t tid = spl_type_builder_slice(sema->type, etid); + n->resolved_type_id = tid; + return tid; + } case SPL_AST_TYPE_STRUCT: case SPL_AST_TYPE_UNION: case SPL_AST_TYPE_SHAPE: @@ -845,85 +1048,35 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { } break; case SPL_AST_TYPE_VOID: - return spl_type_node_push(sema->type, (spl_type_node_t){ - .kind = SPL_TYPE_VOID, - }); + return spl_type_builder_simple(sema->type, SPL_TYPE_VOID); case SPL_AST_TYPE_BOOL: - return spl_type_node_push(sema->type, (spl_type_node_t){ - .kind = SPL_TYPE_BOOL, - }); + return spl_type_builder_simple(sema->type, SPL_TYPE_BOOL); case SPL_AST_TYPE_OPAQUE: - break; + return 0; case SPL_AST_TYPE_I8: - return spl_type_node_push(sema->type, (spl_type_node_t){ - .kind = SPL_TYPE_INT, - .int_type.bits = 8, - .int_type.is_signed = true, - }); + return spl_type_builder_int(sema->type, 8, true); case SPL_AST_TYPE_U8: - return spl_type_node_push(sema->type, (spl_type_node_t){ - .kind = SPL_TYPE_INT, - .int_type.bits = 8, - .int_type.is_signed = false, - }); + return spl_type_builder_int(sema->type, 8, false); case SPL_AST_TYPE_I16: - return spl_type_node_push(sema->type, (spl_type_node_t){ - .kind = SPL_TYPE_INT, - .int_type.bits = 16, - .int_type.is_signed = true, - }); + return spl_type_builder_int(sema->type, 16, true); case SPL_AST_TYPE_U16: - return spl_type_node_push(sema->type, (spl_type_node_t){ - .kind = SPL_TYPE_INT, - .int_type.bits = 16, - .int_type.is_signed = false, - }); + return spl_type_builder_int(sema->type, 16, false); case SPL_AST_TYPE_I32: - return spl_type_node_push(sema->type, (spl_type_node_t){ - .kind = SPL_TYPE_INT, - .int_type.bits = 32, - .int_type.is_signed = true, - }); + return spl_type_builder_int(sema->type, 32, true); case SPL_AST_TYPE_U32: - return spl_type_node_push(sema->type, (spl_type_node_t){ - .kind = SPL_TYPE_INT, - .int_type.bits = 32, - .int_type.is_signed = false, - }); + return spl_type_builder_int(sema->type, 32, false); case SPL_AST_TYPE_I64: - return spl_type_node_push(sema->type, (spl_type_node_t){ - .kind = SPL_TYPE_INT, - .int_type.bits = 64, - .int_type.is_signed = true, - }); + return spl_type_builder_int(sema->type, 64, true); case SPL_AST_TYPE_U64: - return spl_type_node_push(sema->type, (spl_type_node_t){ - .kind = SPL_TYPE_INT, - .int_type.bits = 64, - .int_type.is_signed = false, - }); + return spl_type_builder_int(sema->type, 64, false); case SPL_AST_TYPE_ISIZE: - return spl_type_node_push(sema->type, (spl_type_node_t){ - .kind = SPL_TYPE_INT, - .int_type.bits = sizeof(void *) * 8, /* FIXME */ - .int_type.is_signed = true, - }); + return spl_type_builder_int(sema->type, sizeof(void *) * 8, true); /* FIXME */ case SPL_AST_TYPE_USIZE: - return spl_type_node_push(sema->type, (spl_type_node_t){ - .kind = SPL_TYPE_INT, - .int_type.bits = sizeof(void *) * 8, /* FIXME */ - .int_type.is_signed = false, - }); + return spl_type_builder_int(sema->type, sizeof(void *) * 8, false); /* FIXME */ case SPL_AST_TYPE__F32: - return spl_type_node_push(sema->type, (spl_type_node_t){ - .kind = SPL_TYPE_FLOAT, - .float_type.bits = 32, - }); + return spl_type_builder_float(sema->type, 32); case SPL_AST_TYPE__F64: - return spl_type_node_push(sema->type, (spl_type_node_t){ - .kind = SPL_TYPE_FLOAT, - .float_type.bits = 64, - }); + return spl_type_builder_float(sema->type, 64); case SPL_AST_TYPE_ANY: case SPL_AST_TYPE_IDENT: break; @@ -983,6 +1136,7 @@ void spl_sema_dump(spl_sema_t *sema) { vec_for(sema->type->def_table, i) { printf(" def#%zu ", i); spl_type_def_dump(sema->type, i); + spl_def_node_t *d = spl_type_def(sema->type, i); printf("\n"); } } diff --git a/stage1/spl_type.c b/stage1/spl_type.c index 2936cd5..5bea977 100644 --- a/stage1/spl_type.c +++ b/stage1/spl_type.c @@ -29,15 +29,21 @@ static usize spl_type_hash(spl_type_node_t n) { break; case SPL_TYPE_STRUCT: case SPL_TYPE_UNION: - hash += n.layout.mode; - hash += n.layout.fixed_align_bits; - vec_for(n.agg_field_types, i) { hash += vec_at(n.agg_field_types, i); } + hash += n.layout.mode * 31 + n.layout.fixed_align_bits; + vec_for(n.agg_members, i) { + hash += (n.agg_members.data[i].name ? map_hash_str(n.agg_members.data[i].name) : 0) + + n.agg_members.data[i].type_id; + } break; case SPL_TYPE_ENUM: - hash += n.layout.mode; - hash += n.layout.fixed_align_bits; + hash += n.layout.mode * 31 + n.layout.fixed_align_bits; hash += n.adt_type.tag_type; - vec_for(n.adt_type.variants, i) { hash += vec_at(n.adt_type.variants, i); } + vec_for(n.adt_type.variants, i) { + hash += + (n.adt_type.variants.data[i].name ? map_hash_str(n.adt_type.variants.data[i].name) + : 0) + + n.adt_type.variants.data[i].type_id; + } break; case SPL_TYPE_FN: hash += n.fn_type.ret; @@ -92,10 +98,14 @@ static int spl_type_eq(spl_type_node_t n1, spl_type_node_t n2) { if (n1.layout.mode != n2.layout.mode || n1.layout.fixed_align_bits != n2.layout.fixed_align_bits) return 1; - if (vec_size(n1.agg_field_types) != vec_size(n2.agg_field_types)) + if (vec_size(n1.agg_members) != vec_size(n2.agg_members)) return 1; - vec_for(n1.agg_field_types, i) { - if (vec_at(n1.agg_field_types, i) != vec_at(n2.agg_field_types, i)) + vec_for(n1.agg_members, i) { + const char *na = n1.agg_members.data[i].name; + const char *nb = n2.agg_members.data[i].name; + if (strcmp(na ? na : "", nb ? nb : "") != 0) + return 1; + if (n1.agg_members.data[i].type_id != n2.agg_members.data[i].type_id) return 1; } break; @@ -108,7 +118,11 @@ static int spl_type_eq(spl_type_node_t n1, spl_type_node_t n2) { if (vec_size(n1.adt_type.variants) != vec_size(n2.adt_type.variants)) return 1; vec_for(n1.adt_type.variants, i) { - if (vec_at(n1.adt_type.variants, i) != vec_at(n2.adt_type.variants, i)) + const char *na = n1.adt_type.variants.data[i].name; + const char *nb = n2.adt_type.variants.data[i].name; + if (strcmp(na ? na : "", nb ? nb : "") != 0) + return 1; + if (n1.adt_type.variants.data[i].type_id != n2.adt_type.variants.data[i].type_id) return 1; } break; @@ -128,132 +142,215 @@ static int spl_type_eq(spl_type_node_t n1, spl_type_node_t n2) { return 0; } -spl_type_id_t spl_type_node_push(spl_type_t *type, spl_type_node_t type_node) { - spl_type_id_t ret = 0; - int ok = map_get(type->type_map, type_node, &ret); - if (ok) { - return ret; +static usize spl_type_map_hash(usize k) { return MAP_HASH_INT(k); } + +static int spl_type_map_cmp(usize a, usize b) { return MAP_CMP_INT(a, b); } + +static void spl_type_node_free_vecs(spl_type_node_t *tn) { + switch (tn->kind) { + case SPL_TYPE_STRUCT: + case SPL_TYPE_UNION: + vec_free(tn->agg_members); + break; + case SPL_TYPE_ENUM: + vec_free(tn->adt_type.variants); + break; + case SPL_TYPE_FN: + vec_free(tn->fn_type.params); + break; + default: + break; } - map_put(type->type_map, type_node, vec_size(type->type_table)); - vec_push(type->type_table, type_node); - return vec_size(type->type_table) - 1; } -spl_type_id_t spl_type_def_alloc(spl_type_t *type) { - vec_push(type->def_table, (spl_def_node_t){0}); - return vec_size(type->def_table) - 1; +spl_type_id_t spl_type_node_push(spl_type_t *type, spl_type_node_t *tn) { + usize hash = spl_type_hash(*tn); + usize idx = (usize)-1; + spl_type_id_t cand = 0; + while (map_get_continue(type->type_map, hash, &cand, &idx)) { + spl_type_node_t *existing = &vec_at(type->type_table, cand); + if (spl_type_eq(*existing, *tn) == 0) { + spl_type_node_free_vecs(tn); + return cand; + } + } + spl_type_id_t id = vec_size(type->type_table); + vec_push(type->type_table, *tn); + map_put_new(type->type_map, hash, id); + tn->kind = SPL_TYPE_ERROR; + return id; } -spl_type_id_t spl_type_def_agg_build(spl_type_t *type, spl_def_id_t def, spl_type_node_kind_t tk, - spl_type_id_t tag_type, spl_type_layout_t layout) { - if (tk != SPL_TYPE_STRUCT && tk != SPL_TYPE_UNION && tk != SPL_TYPE_ENUM) { - return 0; +static const spl_type_member_t *spl_type_agg_member_find(spl_type_t *type, spl_type_id_t tid, + const char *name, usize *out_idx) { + spl_type_node_t *n = spl_type_node(type, tid); + if (!n || !name) { + return NULL; } - spl_def_node_t *d = spl_type_def(type, def); - if (!d) { - return 0; + if (n->kind == SPL_TYPE_STRUCT || n->kind == SPL_TYPE_UNION) { + vec_for(n->agg_members, i) { + const char *mn = n->agg_members.data[i].name; + if (strcmp(mn ? mn : "", name) == 0) { + if (out_idx) { + *out_idx = i; + } + return &n->agg_members.data[i]; + } + } + } else if (n->kind == SPL_TYPE_ENUM) { + vec_for(n->adt_type.variants, i) { + const char *mn = n->adt_type.variants.data[i].name; + if (strcmp(mn ? mn : "", name) == 0) { + if (out_idx) { + *out_idx = i; + } + return &n->adt_type.variants.data[i]; + } + } } + return NULL; +} + +const spl_type_member_t *spl_type_agg_member(spl_type_t *type, spl_type_id_t tid, + const char *name) { + return spl_type_agg_member_find(type, tid, name, NULL); +} + +bool spl_type_agg_member_idx(spl_type_t *type, spl_type_id_t tid, const char *name, + usize *out_idx) { + return spl_type_agg_member_find(type, tid, name, out_idx) != NULL; +} + +spl_type_id_t spl_type_builder_simple(spl_type_t *type, spl_type_node_kind_t kind) { + spl_type_node_t tn = {0}; + tn.kind = kind; + return spl_type_node_push(type, &tn); +} + +spl_type_id_t spl_type_builder_int(spl_type_t *type, usize bits, int is_signed) { + spl_type_node_t tn = {0}; + tn.kind = SPL_TYPE_INT; + tn.int_type.bits = bits; + tn.int_type.is_signed = is_signed; + return spl_type_node_push(type, &tn); +} + +spl_type_id_t spl_type_builder_float(spl_type_t *type, usize bits) { + spl_type_node_t tn = {0}; + tn.kind = SPL_TYPE_FLOAT; + tn.float_type.bits = bits; + return spl_type_node_push(type, &tn); +} + +spl_type_id_t spl_type_builder_ptr(spl_type_t *type, spl_type_id_t pointee) { + spl_type_node_t tn = {0}; + tn.kind = SPL_TYPE_PTR; + tn.ptr_pointee = pointee; + return spl_type_node_push(type, &tn); +} + +spl_type_id_t spl_type_builder_slice(spl_type_t *type, spl_type_id_t element) { + spl_type_node_t tn = {0}; + tn.kind = SPL_TYPE_SLICE; + tn.slice_element = element; + return spl_type_node_push(type, &tn); +} + +spl_type_id_t spl_type_builder_range(spl_type_t *type, spl_type_id_t element) { + spl_type_node_t tn = {0}; + tn.kind = SPL_TYPE_RANGE; + tn.range_element = element; + return spl_type_node_push(type, &tn); +} + +spl_type_id_t spl_type_builder_array(spl_type_t *type, spl_type_id_t element, usize len) { + spl_type_node_t tn = {0}; + tn.kind = SPL_TYPE_ARRAY; + tn.array_type.element = element; + tn.array_type.len = len; + return spl_type_node_push(type, &tn); +} + +spl_type_id_t spl_type_builder_fn(spl_type_t *type, spl_type_id_t ret, const spl_type_id_t *params, + usize nparams) { + spl_type_node_t tn = {0}; + tn.kind = SPL_TYPE_FN; + vec_init(tn.fn_type.params); + for (usize i = 0; i < nparams; i++) { + vec_push(tn.fn_type.params, params[i]); + } + tn.fn_type.ret = ret; + return spl_type_node_push(type, &tn); +} + +spl_type_id_t spl_type_builder_agg(spl_type_t *type, spl_type_node_kind_t tk, + const spl_type_member_t *members, usize nmembers, + spl_type_id_t tag_type, spl_type_layout_t layout) { spl_type_node_t tn = {0}; tn.kind = tk; tn.layout = layout; if (tk == SPL_TYPE_ENUM) { vec_init(tn.adt_type.variants); + for (usize i = 0; i < nmembers; i++) { + vec_push(tn.adt_type.variants, members[i]); + } tn.adt_type.tag_type = tag_type; } else { - vec_init(tn.agg_field_types); - } - vec_for(d->agg_def, i) { - if (tk == SPL_TYPE_ENUM) { - vec_push(tn.adt_type.variants, vec_at(d->agg_def, i).type_id); - } else { - vec_push(tn.agg_field_types, vec_at(d->agg_def, i).type_id); + vec_init(tn.agg_members); + for (usize i = 0; i < nmembers; i++) { + vec_push(tn.agg_members, members[i]); } } - usize old = vec_size(type->type_table); - spl_type_id_t tid = spl_type_node_push(type, tn); - if (tid < old) { - if (tk == SPL_TYPE_ENUM) { - vec_free(tn.adt_type.variants); - } else { - vec_free(tn.agg_field_types); - } - } - d->type_id = tid; - return tid; + return spl_type_node_push(type, &tn); } -spl_type_id_t spl_type_def_fn_build(spl_type_t *type, spl_def_id_t def, spl_type_id_t ret) { - spl_def_node_t *d = spl_type_def(type, def); +spl_def_id_t spl_type_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}; + n.kind = kind; + n.name = name; + n.dbg_node = dbg; + n.ast_node_ref = ast_node_ref; + vec_push(type->def_table, n); + return vec_size(type->def_table) - 1; +} + +void spl_type_def_resolve(spl_type_t *type, spl_def_id_t id, spl_type_id_t tid) { + spl_def_node_t *d = spl_type_def(type, id); if (!d) { - return 0; - } - spl_type_node_t tn = {0}; - tn.kind = SPL_TYPE_FN; - vec_init(tn.fn_type.params); - vec_for(d->fn_params_def, i) { - vec_push(tn.fn_type.params, vec_at(d->fn_params_def, i).type_id); - } - tn.fn_type.ret = ret; - usize old = vec_size(type->type_table); - spl_type_id_t tid = spl_type_node_push(type, tn); - if (tid < old) { - vec_free(tn.fn_type.params); + return; } d->type_id = tid; - return tid; +} + +spl_type_id_t spl_type_fn_param_tid(spl_type_t *type, spl_type_id_t fn_tid, usize idx) { + spl_type_node_t *n = spl_type_node(type, fn_tid); + if (!n || n->kind != SPL_TYPE_FN || idx >= vec_size(n->fn_type.params)) + return 0; + return vec_at(n->fn_type.params, idx); } void spl_type_init(spl_type_t *type) { vec_init(type->type_table); vec_push(type->type_table, (spl_type_node_t){0}); - map_init(type->type_map, spl_type_hash, spl_type_eq); + map_init(type->type_map, spl_type_map_hash, spl_type_map_cmp); vec_init(type->def_table); vec_push(type->def_table, (spl_def_node_t){0}); - spl_type_node_push(type, (spl_type_node_t){.kind = SPL_TYPE_VOID}); - spl_type_node_push(type, (spl_type_node_t){.kind = SPL_TYPE_BOOL}); - spl_type_node_push(type, (spl_type_node_t){ - .kind = SPL_TYPE_INT, - .int_type.bits = 8, - .int_type.is_signed = false, - }); - spl_type_node_push(type, (spl_type_node_t){ - .kind = SPL_TYPE_INT, - .int_type.bits = 16, - .int_type.is_signed = false, - }); - spl_type_node_push(type, (spl_type_node_t){ - .kind = SPL_TYPE_INT, - .int_type.bits = 32, - .int_type.is_signed = false, - }); - spl_type_node_push(type, (spl_type_node_t){ - .kind = SPL_TYPE_INT, - .int_type.bits = 64, - .int_type.is_signed = false, - }); - spl_type_node_push(type, (spl_type_node_t){ - .kind = SPL_TYPE_INT, - .int_type.bits = 8, - .int_type.is_signed = true, - }); - spl_type_node_push(type, (spl_type_node_t){ - .kind = SPL_TYPE_INT, - .int_type.bits = 16, - .int_type.is_signed = true, - }); - spl_type_node_push(type, (spl_type_node_t){ - .kind = SPL_TYPE_INT, - .int_type.bits = 32, - .int_type.is_signed = true, - }); - spl_type_node_push(type, (spl_type_node_t){ - .kind = SPL_TYPE_INT, - .int_type.bits = 64, - .int_type.is_signed = true, - }); - spl_type_node_push(type, (spl_type_node_t){.kind = SPL_TYPE_FLOAT, .float_type.bits = 32}); - spl_type_node_push(type, (spl_type_node_t){.kind = SPL_TYPE_FLOAT, .float_type.bits = 64}); + spl_type_builder_simple(type, SPL_TYPE_VOID); + spl_type_builder_simple(type, SPL_TYPE_BOOL); + spl_type_builder_simple(type, SPL_TYPE_UNDEFINED); + spl_type_builder_simple(type, SPL_TYPE_NULL); + spl_type_builder_int(type, 8, false); + spl_type_builder_int(type, 16, false); + spl_type_builder_int(type, 32, false); + spl_type_builder_int(type, 64, false); + spl_type_builder_int(type, 8, true); + spl_type_builder_int(type, 16, true); + spl_type_builder_int(type, 32, true); + spl_type_builder_int(type, 64, true); + spl_type_builder_float(type, 32); + spl_type_builder_float(type, 64); } void spl_type_drop(spl_type_t *type) { @@ -262,7 +359,7 @@ void spl_type_drop(spl_type_t *type) { switch (n->kind) { case SPL_TYPE_STRUCT: case SPL_TYPE_UNION: - vec_free(n->agg_field_types); + vec_free(n->agg_members); break; case SPL_TYPE_ENUM: vec_free(n->adt_type.variants); @@ -275,20 +372,6 @@ void spl_type_drop(spl_type_t *type) { } } - vec_for(type->def_table, i) { - spl_def_node_t *d = &vec_at(type->def_table, i); - switch (d->kind) { - case SPL_DEF_AGG: - vec_free(d->agg_def); - break; - case SPL_DEF_FN_PARAMS: - vec_free(d->fn_params_def); - break; - default: - break; - } - } - map_free(type->type_map); vec_free(type->type_table); vec_free(type->def_table); @@ -360,20 +443,48 @@ void spl_type_pure_dump(spl_type_t *type, spl_type_id_t id) { spl_type_pure_dump(type, n->array_type.element); break; case SPL_TYPE_STRUCT: - printf("struct{%zu fields}", n->agg_field_types.size); + printf("struct{"); + vec_for(n->agg_members, i) { + if (i) { + printf(", "); + } + spl_type_member_t *member = &vec_at(n->agg_members, i); + printf("%s:", member->name ? member->name : "?"); + spl_type_pure_dump(type, member->type_id); + } + printf("}"); break; case SPL_TYPE_UNION: - printf("union{%zu fields}", n->agg_field_types.size); + printf("union{"); + vec_for(n->agg_members, i) { + if (i) { + printf(", "); + } + spl_type_member_t *member = &vec_at(n->agg_members, i); + printf("%s:", member->name ? member->name : "?"); + spl_type_pure_dump(type, member->type_id); + } + printf("}"); break; case SPL_TYPE_ENUM: - printf("enum{%zu variants}", n->adt_type.variants.size); + printf("enum{"); // TODO tag_type + vec_for(n->adt_type.variants, i) { + if (i) { + printf(", "); + } + spl_type_member_t *member = &vec_at(n->adt_type.variants, i); + printf("%s:", member->name ? member->name : "?"); + spl_type_pure_dump(type, member->type_id); + } + printf("}"); break; case SPL_TYPE_FN: { printf("fn("); - for (usize i = 0; i < n->fn_type.params.size; i++) { - if (i) + vec_for(n->fn_type.params, i) { + if (i) { printf(","); - spl_type_pure_dump(type, n->fn_type.params.data[i]); + } + spl_type_pure_dump(type, vec_at(n->fn_type.params, i)); } printf(") -> "); spl_type_pure_dump(type, n->fn_type.ret); @@ -407,7 +518,7 @@ void spl_type_def_dump(spl_type_t *type, spl_def_id_t id) { def_kind_name = "var"; break; case SPL_DEF_FN_PARAMS: - def_kind_name = "params"; + def_kind_name = "fn_params"; break; case SPL_DEF_AGG: def_kind_name = "agg"; @@ -419,37 +530,6 @@ void spl_type_def_dump(spl_type_t *type, spl_def_id_t id) { def_kind_name = "sametypes"; break; } - printf("kind=%s type_id=%zu", def_kind_name, node->type_id); - switch (node->kind) { - case SPL_DEF_VAR: - printf(" var=%s", node->var_def.name ? node->var_def.name : "?"); - break; - case SPL_DEF_MEMBER: - printf(" member=%s", node->var_def.name ? node->var_def.name : "?"); - break; - case SPL_DEF_ALIAS: - case SPL_DEF_DISTINCT: - printf(" type=%s", node->type_def.name ? node->type_def.name : "?"); - break; - case SPL_DEF_AGG: - printf(" agg{"); - for (usize i = 0; i < node->agg_def.size; i++) { - if (i) - printf(","); - printf("%s", node->agg_def.data[i].name ? node->agg_def.data[i].name : "?"); - } - printf("}"); - break; - case SPL_DEF_FN_PARAMS: - printf(" fn("); - for (usize i = 0; i < node->fn_params_def.size; i++) { - if (i) - printf(","); - printf("%s", node->fn_params_def.data[i].name ? node->fn_params_def.data[i].name : "?"); - } - printf(")"); - break; - default: - break; - } + printf("kind=%s type_id=%zu name=%s", def_kind_name, node->type_id, + node->name ? node->name : "?"); } diff --git a/stage1/spl_type.h b/stage1/spl_type.h index b0f5987..654f293 100644 --- a/stage1/spl_type.h +++ b/stage1/spl_type.h @@ -39,6 +39,13 @@ typedef struct { usize fixed_align_bits; } spl_type_layout_t; +typedef struct { + const char *name; + spl_type_id_t type_id; + usize ast_node_ref; // 回 AST member_decl 节点引用 dbg/IDE 定位用 不参与 hash +} spl_type_member_t; +typedef VEC(spl_type_member_t) spl_type_member_vec_t; + typedef struct { spl_type_node_kind_t kind; spl_type_layout_t layout; @@ -57,9 +64,9 @@ typedef struct { spl_type_id_t element; usize len; } array_type; - spl_type_id_vec_t agg_field_types; + spl_type_member_vec_t agg_members; struct { - spl_type_id_vec_t variants; + spl_type_member_vec_t variants; spl_type_id_t tag_type; } adt_type; // ADT struct { @@ -71,40 +78,29 @@ typedef struct { } spl_type_node_t; typedef VEC(spl_type_node_t) spl_type_node_vec_t; -typedef struct { - const char *name; - spl_def_id_t def_id; - spl_type_id_t type_id; - usize scope_id; -} spl_var_def_t; -typedef VEC(spl_var_def_t) spl_var_def_vec_t; +typedef enum { + SPL_DEF_ERROR, + SPL_DEF_SCALAR, + SPL_DEF_MEMBER, + SPL_DEF_VAR, + SPL_DEF_FN_PARAMS, + SPL_DEF_AGG, // include enum variants + SPL_DEF_DISTINCT, // newtype + SPL_DEF_ALIAS, // sametypes +} spl_def_node_kind_t; typedef struct { - enum { - SPL_DEF_ERROR, - SPL_DEF_SCALAR, - SPL_DEF_MEMBER, - SPL_DEF_VAR, - SPL_DEF_FN_PARAMS, - SPL_DEF_AGG, // include enum variants - SPL_DEF_DISTINCT, // newtype - SPL_DEF_ALIAS, // sametypes - } kind; + spl_def_node_kind_t kind; + const char *name; spl_dbg_node_t dbg_node; spl_type_id_t type_id; - union { - spl_var_def_t var_def; - spl_var_def_vec_t agg_def; // include enum variants - spl_var_def_vec_t fn_params_def; - spl_var_def_t type_def; - }; + usize ast_node_ref; } spl_def_node_t; typedef VEC(spl_def_node_t) spl_def_node_vec_t; -typedef MAP(spl_type_node_t, usize) spl_type_node_map_t; +typedef MAP(usize, spl_type_id_t) spl_type_node_map_t; typedef struct { spl_type_node_vec_t type_table; - // TODO hashconsing spl_type_node_map_t type_map; spl_def_node_vec_t def_table; } spl_type_t; @@ -118,11 +114,25 @@ void spl_type_pure_dump(spl_type_t *type, spl_type_id_t id); spl_type_node_t *spl_type_node(spl_type_t *type, spl_type_id_t id); spl_def_node_t *spl_type_def(spl_type_t *type, spl_def_id_t id); -spl_type_id_t spl_type_def_alloc(spl_type_t *type); -spl_type_id_t spl_type_node_push(spl_type_t *type, spl_type_node_t type_node); +spl_type_id_t spl_type_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_type_def_resolve(spl_type_t *type, spl_def_id_t id, spl_type_id_t tid); -spl_type_id_t spl_type_def_agg_build(spl_type_t *type, spl_def_id_t def, spl_type_node_kind_t tk, - spl_type_id_t tag_type, spl_type_layout_t layout); -spl_type_id_t spl_type_def_fn_build(spl_type_t *type, spl_def_id_t def, spl_type_id_t ret); +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_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_float(spl_type_t *type, usize bits); +spl_type_id_t spl_type_builder_ptr(spl_type_t *type, spl_type_id_t pointee); +spl_type_id_t spl_type_builder_slice(spl_type_t *type, spl_type_id_t element); +spl_type_id_t spl_type_builder_range(spl_type_t *type, spl_type_id_t element); +spl_type_id_t spl_type_builder_array(spl_type_t *type, spl_type_id_t element, usize len); +spl_type_id_t spl_type_builder_fn(spl_type_t *type, spl_type_id_t ret, const spl_type_id_t *params, + usize nparams); +spl_type_id_t spl_type_builder_agg(spl_type_t *type, spl_type_node_kind_t tk, + const spl_type_member_t *members, usize nmembers, + spl_type_id_t tag_type, spl_type_layout_t layout); #endif /* __SPL_TYPE_H__ */