diff --git a/stage1/spl_ast2ir.c b/stage1/spl_ast2ir.c index ef3231f..39e96ab 100644 --- a/stage1/spl_ast2ir.c +++ b/stage1/spl_ast2ir.c @@ -44,7 +44,8 @@ static spl_ir_node_ref_t emit_zero_value(spl_ast2ir_t *a, spl_type_id_t tid) { spl_type_node_t *tn = spl_type_node(a->sema->type, tid); if (!tn) return 0; - switch (tn->kind) { + spl_type_node_kind_t tk = tn->kind; + switch (tk) { case SPL_TYPE_BOOL: return spl_ir_builder_type_const_bool(a->ir, tid, false); case SPL_TYPE_INT: @@ -55,9 +56,11 @@ static spl_ir_node_ref_t emit_zero_value(spl_ast2ir_t *a, spl_type_id_t tid) { case SPL_TYPE_FN: return spl_ir_builder_type_const_ptr(a->ir, tid, NULL); case SPL_TYPE_ARRAY: { + usize arr_len = tn->array_type.len; + spl_type_id_t arr_elem = tn->array_type.element; spl_ir_node_ref_t node = spl_ir_builder_agg_construct(a->ir, tid); - for (usize i = 0; i < tn->array_type.len; ++i) { - spl_ir_node_ref_t f = emit_zero_value(a, tn->array_type.element); + for (usize i = 0; i < arr_len; ++i) { + spl_ir_node_ref_t f = emit_zero_value(a, arr_elem); if (!f) return 0; spl_ir_builder_agg_construct_field(a->ir, node, f); @@ -66,20 +69,31 @@ static spl_ir_node_ref_t emit_zero_value(spl_ast2ir_t *a, spl_type_id_t tid) { } case SPL_TYPE_STRUCT: case SPL_TYPE_SHAPE: { + usize nfield = vec_size(tn->agg_type.variants); + spl_type_id_vec_t field_tids; + vec_init(field_tids); + for (usize i = 0; i < nfield; ++i) + vec_push(field_tids, vec_at(tn->agg_type.variants, i).type_id); + spl_ir_node_ref_t node = spl_ir_builder_agg_construct(a->ir, tid); - for (usize i = 0; i < vec_size(tn->agg_type.variants); ++i) { - spl_ir_node_ref_t f = emit_zero_value(a, vec_at(tn->agg_type.variants, i).type_id); - if (!f) + for (usize i = 0; i < nfield; ++i) { + spl_ir_node_ref_t f = emit_zero_value(a, vec_at(field_tids, i)); + if (!f) { + vec_free(field_tids); return 0; + } spl_ir_builder_agg_construct_field(a->ir, node, f); } + vec_free(field_tids); return node; } case SPL_TYPE_UNION: { + usize nfield = vec_size(tn->agg_type.variants); + if (nfield == 0) + return spl_ir_builder_agg_construct(a->ir, tid); + spl_type_id_t first_tid = vec_at(tn->agg_type.variants, 0).type_id; spl_ir_node_ref_t node = spl_ir_builder_agg_construct(a->ir, tid); - if (vec_size(tn->agg_type.variants) == 0) - return node; - spl_ir_node_ref_t f = emit_zero_value(a, vec_at(tn->agg_type.variants, 0).type_id); + spl_ir_node_ref_t f = emit_zero_value(a, first_tid); if (!f) return 0; spl_ir_builder_agg_construct_field(a->ir, node, f); @@ -89,7 +103,6 @@ static spl_ir_node_ref_t emit_zero_value(spl_ast2ir_t *a, spl_type_id_t tid) { return 0; } } - static void copy_attrs_to_ir_node(spl_ast2ir_t *a, spl_ast_node_t *n, spl_ir_node_ref_t ir_ref) { if (!ir_ref || !n || vec_size(n->attrs) == 0) return; @@ -234,14 +247,17 @@ static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { spl_lang_type_node_t *obj_ln = spl_lang_type_node(a->sema->type, obj_lang); if (!obj_ln) return 0; - if (spl_intrin_lookup_field(obj_ln->kind, n->field.field) != SPL_INTRIN_NONE) + spl_lang_type_kind_t obj_kind = obj_ln->kind; + spl_lang_type_id_t obj_elem = (obj_kind == SPL_LANG_TYPE_PTR) ? obj_ln->extra.elem : 0; + + if (spl_intrin_lookup_field(obj_kind, n->field.field) != SPL_INTRIN_NONE) return 0; /* 内建字段不是左值 */ spl_ir_node_ref_t base = 0; spl_lang_type_id_t agg_lang = 0; - if (obj_ln->kind == SPL_LANG_TYPE_PTR) { + if (obj_kind == SPL_LANG_TYPE_PTR) { base = emit_expr(a, n->field.obj); - agg_lang = obj_ln->extra.elem; + agg_lang = obj_elem; } else { base = emit_lvalue(a, n->field.obj); agg_lang = obj_lang; @@ -272,25 +288,43 @@ static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { if (!obj_ln) return 0; + spl_lang_type_kind_t obj_kind = obj_ln->kind; + spl_lang_type_id_t obj_elem = 0; + if (obj_kind == SPL_LANG_TYPE_PTR || obj_kind == SPL_LANG_TYPE_ARRAY || + obj_kind == SPL_LANG_TYPE_SLICE) + obj_elem = obj_ln->extra.elem; + + if (obj_kind == SPL_LANG_TYPE_TUPLE) { + spl_ast_node_t *idx_node = spl_ast_node(a->sema->ast, n->index.index); + if (!idx_node || idx_node->kind != SPL_AST_EXPR_INT_LIT) + return 0; + usize i = (usize)idx_node->int_lit.val; + spl_ir_node_ref_t base = emit_lvalue(a, n->index.obj); + if (!base) + return 0; + spl_type_id_t tuple_ir = to_ir_type(a, obj_lang); + if (!tuple_ir) + return 0; + return spl_ir_builder_mem_field(a->ir, tuple_ir, base, i); + } + spl_ir_node_ref_t base = 0; spl_lang_type_id_t elem_lang = 0; - if (obj_ln->kind == SPL_LANG_TYPE_PTR) { + if (obj_kind == SPL_LANG_TYPE_PTR) { base = emit_expr(a, n->index.obj); - elem_lang = obj_ln->extra.elem; - } else if (obj_ln->kind == SPL_LANG_TYPE_ARRAY) { + elem_lang = obj_elem; + } else if (obj_kind == SPL_LANG_TYPE_ARRAY) { base = emit_lvalue(a, n->index.obj); - elem_lang = obj_ln->extra.elem; - } else if (obj_ln->kind == SPL_LANG_TYPE_SLICE) { - /* 切片:取出切片值,再 agg_extract 出 ptr 字段 */ + elem_lang = obj_elem; + } else if (obj_kind == SPL_LANG_TYPE_SLICE) { spl_ir_node_ref_t slice_val = emit_expr(a, n->index.obj); if (!slice_val) return 0; - spl_lang_type_id_t elem = obj_ln->extra.elem; - spl_type_id_t ptr_ir = spl_type_builder_ptr(a->sema->type, to_ir_type(a, elem)); + spl_type_id_t ptr_ir = spl_type_builder_ptr(a->sema->type, to_ir_type(a, obj_elem)); spl_ir_node_ref_t ptr = spl_ir_builder_agg_extract(a->ir, ptr_ir, ptr_ir, SPL_SLICE_PTR_FIELD_IDX, slice_val); base = ptr; - elem_lang = elem; + elem_lang = obj_elem; } else { return 0; } @@ -673,7 +707,9 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref) if (!tn) Panic("aggregate type node missing"); - if (tn->kind == SPL_TYPE_ENUM) { + spl_type_node_kind_t tn_kind = tn->kind; + + if (tn_kind == SPL_TYPE_ENUM) { if (vec_size(n->aggregate_literal.fields) != 1) Panic("enum literal must have exactly one variant"); spl_ast_node_t *item = @@ -686,25 +722,30 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref) Panic("enum variant `%s` not found (sema should have caught this)", item->struct_init_item.name); + spl_type_id_t tag_ir = tn->agg_type.tag_type; + spl_type_id_t payload_ir = vec_at(tn->agg_type.variants, vidx).type_id; + spl_ir_node_ref_t eptr = spl_ir_builder_mem_alloca(a->ir, t, const_usize(a, 1)); - spl_type_id_t tag_ir = tn->agg_type.tag_type; spl_ir_node_ref_t tptr = spl_ir_builder_mem_field(a->ir, t, eptr, SPL_ENUM_TAG_FIELD_IDX); spl_ir_node_ref_t tag_val = spl_ir_builder_type_const_int(a->ir, tag_ir, vidx); spl_ir_builder_mem_store(a->ir, tag_ir, tptr, tag_val); - spl_type_id_t ftid = vec_at(tn->agg_type.variants, vidx).type_id; spl_ir_node_ref_t pptr = spl_ir_builder_mem_field(a->ir, t, eptr, vidx + 1); spl_ir_node_ref_t payload = emit_expr(a, item->struct_init_item.expr); if (!payload) Panic("enum payload emit failed"); - spl_ir_builder_mem_store(a->ir, ftid, pptr, payload); + spl_ir_builder_mem_store(a->ir, payload_ir, pptr, payload); return eptr; } usize nfields = vec_size(tn->agg_type.variants); + spl_type_id_vec_t field_tids; + vec_init(field_tids); + for (usize i = 0; i < nfields; ++i) + vec_push(field_tids, vec_at(tn->agg_type.variants, i).type_id); spl_ir_node_ref_vec_t fields; vec_init(fields); @@ -730,24 +771,34 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref) for (usize i = 0; i < nfields; ++i) { if (!vec_at(fields, i)) { - spl_type_id_t ftid = vec_at(tn->agg_type.variants, i).type_id; - spl_ir_node_ref_t f = emit_zero_value(a, ftid); - if (!f) + spl_ir_node_ref_t f = emit_zero_value(a, vec_at(field_tids, i)); + if (!f) { + vec_free(field_tids); + vec_free(fields); Panic("cannot zero-init aggregate field #%zu", i); + } vec_at(fields, i) = f; } } spl_ir_node_ref_t node = spl_ir_builder_agg_construct(a->ir, t); - if (!node) + if (!node) { + vec_free(field_tids); + vec_free(fields); Panic("agg_construct failed for aggregate literal"); + } for (usize i = 0; i < nfields; ++i) { spl_ir_node_ref_t f = vec_at(fields, i); - if (!f) + if (!f) { + vec_free(field_tids); + vec_free(fields); Panic("aggregate field #%zu missing (sema should have caught this)", i); + } spl_ir_builder_agg_construct_field(a->ir, node, f); } + + vec_free(field_tids); vec_free(fields); return node; } @@ -772,11 +823,15 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref) if (!obj_ln) return 0; + spl_lang_type_kind_t obj_kind = obj_ln->kind; + spl_lang_type_id_t obj_elem = obj_ln->extra.elem; + spl_type_id_t obj_ir = obj_ln->ir_type_id; + spl_type_id_t slice_ir = node_ir(a, n); if (!slice_ir) return 0; - spl_lang_type_id_t elem_lang = obj_ln->extra.elem; + spl_lang_type_id_t elem_lang = obj_elem; spl_type_id_t elem_ir = to_ir_type(a, elem_lang); spl_lang_type_id_t usize_lang = spl_lang_make_int(a->sema->type, sizeof(void *) * 8, 0); spl_type_id_t usize_ir = to_ir_type(a, usize_lang); @@ -800,13 +855,16 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref) spl_ir_node_ref_t end_v = 0; if (n->slice.end) { end_v = emit_expr(a, n->slice.end); - } else if (obj_ln->kind == SPL_LANG_TYPE_ARRAY) { - spl_type_node_t *arr = spl_type_node(a->sema->type, obj_ln->ir_type_id); - end_v = spl_ir_builder_type_const_int(a->ir, usize_ir, arr->array_type.len); - } else if (obj_ln->kind == SPL_LANG_TYPE_SLICE) { + } else if (obj_kind == SPL_LANG_TYPE_ARRAY) { + spl_type_node_t *arr = spl_type_node(a->sema->type, obj_ir); + if (!arr) + return 0; + usize arr_len = arr->array_type.len; + end_v = spl_ir_builder_type_const_int(a->ir, usize_ir, arr_len); + } else if (obj_kind == SPL_LANG_TYPE_SLICE) { spl_ir_node_ref_t slice_val = emit_expr(a, n->slice.obj); - end_v = spl_ir_builder_agg_extract(a->ir, obj_ln->ir_type_id, usize_ir, - SPL_SLICE_LEN_FIELD_IDX, slice_val); + end_v = spl_ir_builder_agg_extract(a->ir, obj_ir, usize_ir, SPL_SLICE_LEN_FIELD_IDX, + slice_val); } else { return 0; } @@ -1124,10 +1182,15 @@ static void emit_fn_body(spl_ast2ir_t *a, spl_ast_node_t *n) { if (!fn_ln || fn_ln->kind != SPL_LANG_TYPE_FN) return; + spl_lang_type_id_t ret_lang = fn_ln->extra.fn.ret; + spl_type_id_t ret_ir = to_ir_type(a, ret_lang); + spl_lang_type_node_t *ret_ln = spl_lang_type_node(a->sema->type, ret_lang); + int ret_is_unit = (ret_ln && ret_ln->kind == SPL_LANG_TYPE_UNIT) ? 1 : 0; + spl_ir_builder_fn_begin_at(a->ir, fn_ref); spl_lang_type_id_t saved_ret = a->cur_ret_lang; - a->cur_ret_lang = fn_ln->extra.fn.ret; + a->cur_ret_lang = ret_lang; usize defer_base = vec_size(a->defer_stack); usize loop_base = vec_size(a->loop_stack); @@ -1164,10 +1227,12 @@ static void emit_fn_body(spl_ast2ir_t *a, spl_ast_node_t *n) { spl_ast_node_ref_t d = vec_pop(a->defer_stack); emit_stmt(a, d); } - spl_lang_type_id_t ret_lang = fn_ln->extra.fn.ret; - spl_lang_type_node_t *ret_ln = spl_lang_type_node(a->sema->type, ret_lang); - if (ret_ln && ret_ln->kind == SPL_LANG_TYPE_UNIT) { - spl_ir_builder_control_ret(a->ir, to_ir_type(a, ret_lang), 0); + + if (ret_is_unit) { + spl_ir_builder_control_ret(a->ir, ret_ir, 0); + } else if (ret_ir) { + spl_ir_node_ref_t zero = emit_zero_value(a, ret_ir); + spl_ir_builder_control_ret(a->ir, ret_ir, zero); } else { spl_ir_builder_control_unreachable(a->ir); } diff --git a/stage1/spl_sema.c b/stage1/spl_sema.c index 4577f8d..34e87b6 100644 --- a/stage1/spl_sema.c +++ b/stage1/spl_sema.c @@ -361,7 +361,6 @@ static spl_lang_type_id_t sema_eval_decl(spl_sema_t *sema, spl_def_id_t def_id) } } - def->lang_id = result; spl_def_node_t *final_def = spl_def_node(sema->type, def_id); if (final_def) { final_def->lang_id = result; @@ -630,6 +629,28 @@ static spl_lang_type_id_t sema_check(spl_sema_t *sema, spl_ast_node_ref_t ref, break; /* 非数组 expected:退回通用逻辑 */ } + case SPL_AST_EXPR_TUPLE: { + spl_lang_type_node_t *en = spl_lang_type_node(sema->type, expected); + if (en && en->kind == SPL_LANG_TYPE_TUPLE) { + usize nelems = vec_size(n->tuple.elems); + usize ntypes = vec_size(en->extra.elems); + if (nelems != ntypes) { + SPL_ERROR(&n->dbg, "tuple arity mismatch (expected %zu, got %zu)", ntypes, nelems); + sema->error_count++; + return 0; + } + for (usize i = 0; i < nelems; ++i) { + spl_lang_type_id_t et = vec_at(en->extra.elems, i); + if (!sema_check(sema, vec_at(n->tuple.elems, i), et)) + return 0; + } + n->resolved_lang_tid = expected; + n->expected_lang_tid = 0; + return expected; + } + break; + } + case SPL_AST_EXPR_AGGREGATE_LIT: { spl_lang_type_node_t *en = spl_lang_type_node(sema->type, expected); if (!en || (en->kind != SPL_LANG_TYPE_STRUCT && en->kind != SPL_LANG_TYPE_UNION && @@ -710,8 +731,8 @@ static spl_lang_type_id_t sema_check(spl_sema_t *sema, spl_ast_node_ref_t ref, continue; } seen[idx] = true; - spl_type_member_t *m = &vec_at(irn->agg_type.variants, idx); - spl_lang_type_id_t ft = sema_lang_from_ir(sema, m->type_id); + usize field_tid_ir = vec_at(irn->agg_type.variants, idx).type_id; + spl_lang_type_id_t ft = sema_lang_from_ir(sema, field_tid_ir); if (!ft) continue; if (!item->struct_init_item.expr) { @@ -1078,7 +1099,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { /* 固定参数:check 到形参类型 */ for (usize i = 0; i < nargs && i < fixed; ++i) { - spl_lang_type_id_t pt = vec_at(fn->extra.fn.params, i); + spl_lang_type_id_t pt = + vec_at(spl_lang_type_node(sema->type, callee_tid)->extra.fn.params, i); sema_check(sema, vec_at(n->call.args, i), pt); } /* varargs:默认提升到 isize */ @@ -1131,11 +1153,11 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { } for (usize i = 0; i < vec_size(agg->methods); ++i) { - spl_lang_method_t *meth = &vec_at(agg->methods, i); - if (strcmp(meth->name, n->field.field) != 0) + spl_lang_method_t meth = vec_at(agg->methods, i); + if (strcmp(meth.name, n->field.field) != 0) continue; - n->resolved_def_id = meth->def_id; - spl_lang_type_id_t t = sema_eval_decl(sema, meth->def_id); + n->resolved_def_id = meth.def_id; + spl_lang_type_id_t t = sema_eval_decl(sema, meth.def_id); n->resolved_lang_tid = t; return t; } @@ -1160,10 +1182,22 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { case SPL_LANG_TYPE_PTR: elem = obj->extra.elem; break; - case SPL_LANG_TYPE_TUPLE: - if (vec_size(obj->extra.elems) > 0) - elem = vec_at(obj->extra.elems, 0); + case SPL_LANG_TYPE_TUPLE: { + spl_ast_node_t *idx_node = spl_ast_node(sema->ast, n->index.index); + if (!idx_node || idx_node->kind != SPL_AST_EXPR_INT_LIT) { + SPL_ERROR(&n->dbg, "tuple index must be an integer literal"); + sema->error_count++; + return 0; + } + isize i = idx_node->int_lit.val; + if (i < 0 || (usize)i >= vec_size(obj->extra.elems)) { + SPL_ERROR(&n->dbg, "tuple index out of range"); + sema->error_count++; + return 0; + } + elem = vec_at(obj->extra.elems, (usize)i); break; + } default: SPL_ERROR(&n->dbg, "index base must be array/slice/ptr/range/tuple"); sema->error_count++; @@ -1304,8 +1338,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { sema->error_count++; continue; } - spl_type_member_t *m = &vec_at(irn->agg_type.variants, idx); - spl_lang_type_id_t ft = sema_lang_from_ir(sema, m->type_id); + usize field_tid_ir = vec_at(irn->agg_type.variants, idx).type_id; + spl_lang_type_id_t ft = sema_lang_from_ir(sema, field_tid_ir); if (ft && item->struct_init_item.expr) sema_check(sema, item->struct_init_item.expr, ft); } @@ -1534,6 +1568,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { if (!def) return 0; + spl_def_id_t owner_def_id = def->owner_def; spl_lang_type_id_t fn_tid = def->lang_id; if (fn_tid == 0) fn_tid = sema_eval_decl(sema, n->resolved_def_id); @@ -1546,8 +1581,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { return fn_tid; spl_lang_type_id_t saved_agg = sema->current_aggregate_lang; - if (def->owner_def) { - spl_def_node_t *owner = spl_def_node(sema->type, def->owner_def); + if (owner_def_id) { + spl_def_node_t *owner = spl_def_node(sema->type, owner_def_id); if (owner && owner->lang_id != 0) sema->current_aggregate_lang = owner->lang_id; }