diff --git a/stage1/spl_ast.c b/stage1/spl_ast.c index 8476125..82ae34c 100644 --- a/stage1/spl_ast.c +++ b/stage1/spl_ast.c @@ -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); diff --git a/stage1/spl_ast.h b/stage1/spl_ast.h index e0ba4cc..1288d56 100644 --- a/stage1/spl_ast.h +++ b/stage1/spl_ast.h @@ -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; diff --git a/stage1/spl_ast2ir.c b/stage1/spl_ast2ir.c index 6d77c4a..6a6294f 100644 --- a/stage1/spl_ast2ir.c +++ b/stage1/spl_ast2ir.c @@ -1,518 +1,848 @@ #include "spl_ast2ir.h" +#include -static spl_ir_node_ref_t spl_ir_const_comptime_int(spl_ir_builder_t *ir, const spl_sema_t *sema, - usize i) { - return spl_ir_builder_type_const_int(ir, spl_type_builder_int(sema->type, 0, 0), i); +static spl_type_id_t to_ir_type(spl_ast2ir_t *a, spl_lang_type_id_t lang) { + if (!lang) + return 0; + return spl_lang_type_get_ir_type(a->sema->type, lang); } -static spl_type_id_t tid_from_def(const spl_sema_t *sema, spl_def_id_t def) { - spl_def_node_t *d = spl_def_node(sema->type, def); - return d ? d->type_id : 0; +static spl_lang_type_id_t node_lang(spl_ast2ir_t *a, spl_ast_node_t *n) { + if (!n) + return 0; + if (n->kind == SPL_AST_EXPR_IDENT) + return spl_def_get_lang_id(a->sema->type, n->resolved_def_id); + return n->resolved_type_id; } -static spl_ir_node_ref_t transit(spl_ast2ir_t *ctx, spl_ast_node_ref_t ref); +static spl_type_id_t node_ir(spl_ast2ir_t *a, spl_ast_node_t *n) { + return to_ir_type(a, node_lang(a, n)); +} -static spl_ir_node_ref_t transit_op(spl_ir_builder_t *ir, spl_ast_node_kind_t kind, - spl_type_id_t tid, spl_ir_node_ref_t lref, - spl_ir_node_ref_t rref) { - spl_ir_node_ref_t ret = 0; - switch (kind) { - case SPL_AST_CMP_EQ_EXPR: { - ret = spl_ir_builder_cmp_eq(ir, tid, lref, rref); - } break; - case SPL_AST_CMP_NE_EXPR: { - ret = spl_ir_builder_cmp_ne(ir, tid, lref, rref); - } break; - case SPL_AST_CMP_LE_EXPR: { - ret = spl_ir_builder_cmp_le(ir, tid, lref, rref); - } break; - case SPL_AST_CMP_GE_EXPR: { - ret = spl_ir_builder_cmp_ge(ir, tid, lref, rref); - } break; - case SPL_AST_CMP_LT_EXPR: { - ret = spl_ir_builder_cmp_lt(ir, tid, lref, rref); - } break; - case SPL_AST_CMP_GT_EXPR: { - ret = spl_ir_builder_cmp_gt(ir, tid, lref, rref); - } break; - case SPL_AST_ASSIGN_EXPR: { - ret = rref; - } break; - case SPL_AST_ASSIGN_LSHIFT_EXPR: - case SPL_AST_LSHIFT_EXPR: { - ret = spl_ir_builder_arith_shl(ir, tid, lref, rref); - } break; - case SPL_AST_ASSIGN_RSHIFT_EXPR: - case SPL_AST_RSHIFT_EXPR: { - ret = spl_ir_builder_arith_shr(ir, tid, lref, rref); - } break; - case SPL_AST_ASSIGN_ADD_EXPR: - case SPL_AST_ADD_EXPR: { - ret = spl_ir_builder_arith_add(ir, tid, lref, rref); - } break; - case SPL_AST_SUB_EXPR: - case SPL_AST_ASSIGN_SUB_EXPR: { - ret = spl_ir_builder_arith_sub(ir, tid, lref, rref); - } break; - case SPL_AST_ASSIGN_MUL_EXPR: - case SPL_AST_MUL_EXPR: { - ret = spl_ir_builder_arith_mul(ir, tid, lref, rref); - } break; - case SPL_AST_DIV_EXPR: - case SPL_AST_ASSIGN_DIV_EXPR: { - ret = spl_ir_builder_arith_div(ir, tid, lref, rref); - } break; - case SPL_AST_ASSIGN_MOD_EXPR: - case SPL_AST_MOD_EXPR: { - ret = spl_ir_builder_arith_rem(ir, tid, lref, rref); - } break; - case SPL_AST_ASSIGN_AND_EXPR: - case SPL_AST_BIT_AND_EXPR: { - ret = spl_ir_builder_arith_and(ir, tid, lref, rref); - } break; - case SPL_AST_ASSIGN_OR_EXPR: - case SPL_AST_BIT_OR_EXPR: { - ret = spl_ir_builder_arith_or(ir, tid, lref, rref); - } break; - case SPL_AST_ASSIGN_XOR_EXPR: - case SPL_AST_BIT_XOR_EXPR: { - ret = spl_ir_builder_arith_xor(ir, tid, lref, rref); - } break; - default: - UNREACHABLE(); - break; - } - return ret; +static spl_ir_node_ref_t const_usize(spl_ast2ir_t *a, usize v) { + spl_lang_type_id_t t = spl_lang_make_int(a->sema->type, sizeof(void *) * 8, 0); + return spl_ir_builder_type_const_int(a->ir, to_ir_type(a, t), v); } + +static spl_ir_node_ref_t emit_expr(spl_ast2ir_t *a, spl_ast_node_ref_t ref); +static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref); +static void emit_stmt(spl_ast2ir_t *a, spl_ast_node_ref_t ref); +static void emit_decl(spl_ast2ir_t *a, spl_ast_node_ref_t ref); +static void emit_fn(spl_ast2ir_t *a, spl_ast_node_t *n); +static void emit_container(spl_ast2ir_t *a, spl_ast_node_ref_t ref); +static spl_ir_node_ref_t emit_cast(spl_ast2ir_t *a, spl_ast_node_t *n); -static spl_ir_node_ref_t transit_expr(spl_ast2ir_t *ctx, spl_ast_node_ref_t ref, bool is_lval) { - spl_ir_builder_t *ir = ctx->ir; - const spl_sema_t *sema = ctx->sema; - if (ref == 0) +static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { + spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref); + if (!n) return 0; - Assert(sema != NULL); - spl_ast_node_t *n = spl_ast_node(sema->ast, ref); - spl_ir_node_ref_t ret = 0; - Assert(n != NULL); switch (n->kind) { - case SPL_AST_PACKED_EXPR: { - TODO(); - } break; - case SPL_AST_ASSIGN_EXPR: { - spl_ir_node_ref_t rval = transit_expr(ctx, n->op_expr.right, false); - spl_ir_node_ref_t lval = transit_expr(ctx, n->op_expr.left, true); - ret = spl_ir_builder_mem_store(ir, n->resolved_type_id, lval, rval); - } break; - case SPL_AST_ASSIGN_ADD_EXPR: - case SPL_AST_ASSIGN_SUB_EXPR: - case SPL_AST_ASSIGN_MUL_EXPR: - case SPL_AST_ASSIGN_DIV_EXPR: - case SPL_AST_ASSIGN_MOD_EXPR: - case SPL_AST_ASSIGN_AND_EXPR: - case SPL_AST_ASSIGN_OR_EXPR: - case SPL_AST_ASSIGN_XOR_EXPR: - case SPL_AST_ASSIGN_LSHIFT_EXPR: - case SPL_AST_ASSIGN_RSHIFT_EXPR: { - spl_ir_node_ref_t rval = transit_expr(ctx, n->op_expr.right, false); - spl_ir_node_ref_t lval = transit_expr(ctx, n->op_expr.left, false); - rval = transit_op(ir, n->kind, n->resolved_type_id, lval, rval); - lval = transit_expr(ctx, n->op_expr.left, true); - ret = spl_ir_builder_mem_store(ir, n->resolved_type_id, lval, rval); - } break; - case SPL_AST_CMP_EQ_EXPR: - case SPL_AST_CMP_NE_EXPR: - case SPL_AST_CMP_LE_EXPR: - case SPL_AST_CMP_GE_EXPR: - case SPL_AST_CMP_LT_EXPR: - case SPL_AST_CMP_GT_EXPR: { - spl_ir_node_ref_t rval = transit_expr(ctx, n->op_expr.right, false); - spl_ir_node_ref_t lval = transit_expr(ctx, n->op_expr.left, false); - ret = transit_op(ir, n->kind, n->resolved_type_id, lval, rval); - } break; - case SPL_AST_RANGE_EXPR: { - TODO(); - } break; - case SPL_AST_BOOL_OR_EXPR: - case SPL_AST_BOOL_AND_EXPR: { - TODO(); - } break; - case SPL_AST_BIT_OR_EXPR: - case SPL_AST_BIT_XOR_EXPR: - case SPL_AST_BIT_AND_EXPR: - case SPL_AST_LSHIFT_EXPR: - case SPL_AST_RSHIFT_EXPR: - case SPL_AST_ADD_EXPR: - case SPL_AST_SUB_EXPR: - case SPL_AST_MUL_EXPR: - case SPL_AST_DIV_EXPR: - case SPL_AST_MOD_EXPR: { - spl_ir_node_ref_t rval = transit_expr(ctx, n->op_expr.right, false); - spl_ir_node_ref_t lval = transit_expr(ctx, n->op_expr.left, false); - // TODO assert type is bool - ret = transit_op(ir, n->kind, n->resolved_type_id, lval, rval); - } break; - case SPL_AST_MINUS_EXPR: { - ret = transit_expr(ctx, n->prefix_expr.postfix_expr, false); - ret = spl_ir_builder_arith_neg(ir, n->resolved_type_id, ret); - } break; - case SPL_AST_NOT_EXPR: { - ret = transit_expr(ctx, n->prefix_expr.postfix_expr, false); - ret = spl_ir_builder_arith_not(ir, n->resolved_type_id, ret); - TODO(); // return bool type - } break; - case SPL_AST_BIT_NOT_EXPR: { - ret = transit_expr(ctx, n->prefix_expr.postfix_expr, false); - ret = spl_ir_builder_arith_not(ir, n->resolved_type_id, ret); - } break; - case SPL_AST_ADDRESS_EXPR: { - TODO(); - } break; - case SPL_AST_CALL_EXPR: { - spl_ast_node_t *fn_sym = spl_ast_node(ctx->sema->ast, n->postfix_expr.primary_expr); - Assert(fn_sym != NULL); - spl_def_node_t *dn = spl_def_node(sema->type, fn_sym->resolved_def_id); - Assert(dn != NULL); - spl_ir_node_ref_t ir_ref = 0; - if (!map_get(ctx->def2ir_map, fn_sym->resolved_def_id, &ir_ref)) { - Panic("can't resolved ir map in def2ir"); - } - Assert(ir_ref != 0); + case SPL_AST_EXPR_IDENT: { + spl_def_node_t *def = spl_def_node(a->sema->type, n->resolved_def_id); + if (def && def->kind == SPL_DEF_FN) + return 0; + spl_ir_node_ref_t slot = 0; + if (!map_get(a->def2ir_map, n->resolved_def_id, &slot)) + return 0; + return slot; + } + case SPL_AST_EXPR_FIELD: { + spl_ast_node_t *obj = spl_ast_node(a->sema->ast, n->field.obj); + if (!obj) + return 0; + spl_lang_type_id_t obj_lang = node_lang(a, obj); + spl_lang_type_node_t *obj_ln = spl_lang_type_node(a->sema->type, obj_lang); + if (!obj_ln) + return 0; - VEC(spl_ir_node_ref_t) params; - vec_init(params); - vec_for(n->postfix_expr.call_expr, i) { - spl_ast_node_ref_t param_node = vec_at(n->postfix_expr.call_expr, i); - spl_ir_node_ref_t ref = transit_expr(ctx, param_node, false); - vec_push(params, ref); + spl_ir_node_ref_t base = 0; + spl_lang_type_id_t agg_lang = 0; + if (obj_ln->kind == SPL_LANG_TYPE_PTR) { + base = emit_expr(a, n->field.obj); + agg_lang = obj_ln->extra.elem; + } else { + base = emit_lvalue(a, n->field.obj); + agg_lang = obj_lang; } - spl_ir_node_ref_t call_ref = spl_ir_builder_control_call(ir, n->resolved_type_id, ir_ref); - vec_for(params, i) { spl_ir_builder_control_call_param(ir, call_ref, vec_at(params, i)); } - vec_free(params); - ret = call_ref; - } break; - case SPL_AST_FIELD_EXPR: - case SPL_AST_DEREF_EXPR: - case SPL_AST_INDEX_EXPR: - case SPL_AST_SLICE_EXPR: - case SPL_AST_AS_EXPR: - TODO(); - break; - case SPL_AST_EXPR_INTEGER_LIT: { - ret = spl_ir_builder_type_const_int(ir, n->resolved_type_id, n->primary_expr.integer_expr); - break; + if (!base) + return 0; + + spl_type_id_t agg_ir = to_ir_type(a, agg_lang); + if (!agg_ir) + return 0; + + usize idx = 0; + if (!spl_type_agg_member_idx(a->sema->type, agg_ir, n->field.field, &idx)) + return 0; + + spl_type_node_t *agg_n = spl_type_node(a->sema->type, agg_ir); + if (!agg_n) + return 0; + spl_type_id_t field_ir = vec_at(agg_n->agg_type.variants, idx).type_id; + + return spl_ir_builder_mem_field(a->ir, field_ir, base, idx); } + case SPL_AST_EXPR_INDEX: { + spl_ast_node_t *obj = spl_ast_node(a->sema->ast, n->index.obj); + if (!obj) + return 0; + spl_lang_type_id_t obj_lang = node_lang(a, obj); + spl_lang_type_node_t *obj_ln = spl_lang_type_node(a->sema->type, obj_lang); + if (!obj_ln) + return 0; + + spl_ir_node_ref_t base = 0; + spl_lang_type_id_t elem_lang = 0; + if (obj_ln->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 || obj_ln->kind == SPL_LANG_TYPE_SLICE) { + base = emit_lvalue(a, n->index.obj); + elem_lang = obj_ln->extra.elem; + } else { + return 0; + } + if (!base) + return 0; + + spl_ir_node_ref_t idx = emit_expr(a, n->index.index); + if (!idx) + return 0; + + spl_type_id_t elem_ir = to_ir_type(a, elem_lang); + if (!elem_ir) + return 0; + return spl_ir_builder_mem_offset(a->ir, elem_ir, base, idx); + } + default: + return 0; + } +} + +static spl_ir_node_ref_t emit_cast(spl_ast2ir_t *a, spl_ast_node_t *n) { + spl_ir_node_ref_t v = emit_expr(a, n->cast.expr); + if (!v) + return 0; + spl_ast_node_t *src = spl_ast_node(a->sema->ast, n->cast.expr); + spl_ast_node_t *dst = spl_ast_node(a->sema->ast, n->cast.type); + spl_type_id_t ft = node_ir(a, src); + spl_type_id_t tt = node_ir(a, dst); + spl_type_node_t *fs = spl_type_node(a->sema->type, ft); + spl_type_node_t *ts = spl_type_node(a->sema->type, tt); + if (!fs || !ts) + return 0; + + if (fs->kind == SPL_TYPE_INT && ts->kind == SPL_TYPE_INT) { + if (fs->int_type.bits == ts->int_type.bits) + return spl_ir_builder_cast_bitcast(a->ir, ft, tt, v); + if (fs->int_type.bits > ts->int_type.bits) + return spl_ir_builder_cast_trunc(a->ir, ft, tt, v); + if (fs->int_type.is_signed) + return spl_ir_builder_cast_sext(a->ir, ft, tt, v); + return spl_ir_builder_cast_zext(a->ir, ft, tt, v); + } + if (fs->kind == SPL_TYPE_INT && ts->kind == SPL_TYPE_FLOAT) + return spl_ir_builder_case_int2float(a->ir, ft, tt, v); + if (fs->kind == SPL_TYPE_FLOAT && ts->kind == SPL_TYPE_INT) + return spl_ir_builder_case_float2int(a->ir, ft, tt, v); + if (fs->kind == SPL_TYPE_FLOAT && ts->kind == SPL_TYPE_FLOAT) { + if (fs->float_type.bits > ts->float_type.bits) + return spl_ir_builder_cast_ftrunc(a->ir, ft, tt, v); + return spl_ir_builder_cast_fext(a->ir, ft, tt, v); + } + if (fs->kind == SPL_TYPE_BOOL && ts->kind == SPL_TYPE_INT) + return spl_ir_builder_cast_bool2int(a->ir, ft, tt, v); + if (fs->kind == SPL_TYPE_PTR && ts->kind == SPL_TYPE_INT) + return spl_ir_builder_cast_ptr2int(a->ir, ft, tt, v); + if (fs->kind == SPL_TYPE_INT && ts->kind == SPL_TYPE_PTR) + return spl_ir_builder_cast_int2ptr(a->ir, ft, tt, v); + return spl_ir_builder_cast_bitcast(a->ir, ft, tt, v); +} + +static spl_ir_node_ref_t emit_expr(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { + spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref); + if (!n) + return 0; + + switch (n->kind) { + case SPL_AST_EXPR_INT_LIT: + return spl_ir_builder_type_const_int(a->ir, node_ir(a, n), (usize)n->int_lit.val); case SPL_AST_EXPR_FLOAT_LIT: + return spl_ir_builder_type_const_float(a->ir, node_ir(a, n), n->float_lit.val); case SPL_AST_EXPR_CHAR_LIT: - case SPL_AST_EXPR_STRING_LIT: { - TODO(); - } break; - case SPL_AST_EXPR_TRUE: { - return spl_ir_builder_type_const_bool( - ir, spl_type_builder_simple(sema->type, SPL_TYPE_BOOL), true); - } break; - case SPL_AST_EXPR_FALSE: { - return spl_ir_builder_type_const_bool( - ir, spl_type_builder_simple(sema->type, SPL_TYPE_BOOL), false); - } - case SPL_AST_EXPR_NULL: { - return spl_ir_builder_type_const_bool(ir, n->resolved_type_id, 0); - } break; - case SPL_AST_EXPR_UNDEFINED: + return spl_ir_builder_type_const_char(a->ir, node_ir(a, n), n->char_lit.val); + case SPL_AST_EXPR_STRING_LIT: + return spl_ir_builder_type_const_cstr(a->ir, node_ir(a, n), n->string_lit.data); + case SPL_AST_EXPR_BOOL_LIT: + return spl_ir_builder_type_const_bool(a->ir, node_ir(a, n), n->bool_lit.val); + case SPL_AST_EXPR_NULL_LIT: + return spl_ir_builder_type_const_ptr(a->ir, node_ir(a, n), NULL); + case SPL_AST_EXPR_UNDEFINED_LIT: return 0; case SPL_AST_EXPR_IDENT: { - spl_def_node_t *dn = spl_def_node(sema->type, n->resolved_def_id); - Assert(dn != NULL); - spl_ir_node_ref_t ir_ref = 0; - if (!map_get(ctx->def2ir_map, n->resolved_def_id, &ir_ref)) { - Panic("can't resolved ir map in def2ir"); + spl_def_node_t *def = spl_def_node(a->sema->type, n->resolved_def_id); + if (def && def->kind == SPL_DEF_FN) { + spl_ir_node_ref_t fn_ref = 0; + if (!map_get(a->def2ir_map, n->resolved_def_id, &fn_ref)) + return 0; + return spl_ir_builder_type_const_fn(a->ir, node_ir(a, n), (spl_ir_func_ref_t)fn_ref); } - Assert(ir_ref != 0); - if (is_lval) { - return ir_ref; - } else { - return spl_ir_builder_mem_load(ir, dn->type_id, ir_ref); - } - } break; - case SPL_AST_ARGGREGATE_INIT: { - vec_for(n->primary_expr.aggregate_init.expr, i) { - transit_expr(ctx, vec_at(n->primary_expr.aggregate_init.expr, i), false); - } - } break; - case SPL_AST_EXPR_EXPR: { - transit_expr(ctx, n->primary_expr.expr, is_lval); - } break; - case SPL_AST_ARRAY_LIT: { - TODO(); - } break; - case SPL_AST_BUILTIN_EXPR: { - TODO(); - } break; - case SPL_AST_BLOCK_EXPR: { - vec_for(n->primary_expr.block_expr, i) { - transit(ctx, vec_at(n->primary_expr.block_expr, i)); - } - } break; + spl_ir_node_ref_t slot = 0; + if (!map_get(a->def2ir_map, n->resolved_def_id, &slot)) + return 0; + return spl_ir_builder_mem_load(a->ir, node_ir(a, n), slot); + } + case SPL_AST_EXPR_UNARY: { + if (n->unary.op == SPL_UNARY_OP_ADDRESS) + return emit_lvalue(a, n->unary.operand); + spl_ir_node_ref_t v = emit_expr(a, n->unary.operand); + if (!v) + return 0; + spl_type_id_t t = node_ir(a, n); + switch (n->unary.op) { + case SPL_UNARY_OP_MINUS: + return spl_ir_builder_arith_neg(a->ir, t, v); + case SPL_UNARY_OP_NOT: + case SPL_UNARY_OP_BIT_NOT: + return spl_ir_builder_arith_not(a->ir, t, v); + default: + return 0; + } + } + case SPL_AST_EXPR_BINARY: { + spl_binary_op_t op = n->binary.op; + if (op == SPL_OP_ASSIGN) { + spl_ir_node_ref_t ptr = emit_lvalue(a, n->binary.left); + spl_ir_node_ref_t v = emit_expr(a, n->binary.right); + if (!ptr || !v) + return 0; + spl_ast_node_t *ln = spl_ast_node(a->sema->ast, n->binary.left); + spl_type_id_t t = node_ir(a, ln); + spl_ir_builder_mem_store(a->ir, t, ptr, v); + return v; + } + if (op >= SPL_OP_ASSIGN_ADD && op <= SPL_OP_ASSIGN_RSHIFT) { + spl_ir_node_ref_t ptr = emit_lvalue(a, n->binary.left); + if (!ptr) + return 0; + spl_ast_node_t *ln = spl_ast_node(a->sema->ast, n->binary.left); + spl_type_id_t t = node_ir(a, ln); + spl_ir_node_ref_t lv = spl_ir_builder_mem_load(a->ir, t, ptr); + spl_ir_node_ref_t rv = emit_expr(a, n->binary.right); + if (!lv || !rv) + return 0; + spl_ir_node_ref_t res = 0; + switch (op) { + case SPL_OP_ASSIGN_ADD: + res = spl_ir_builder_arith_add(a->ir, t, lv, rv); + break; + case SPL_OP_ASSIGN_SUB: + res = spl_ir_builder_arith_sub(a->ir, t, lv, rv); + break; + case SPL_OP_ASSIGN_MUL: + res = spl_ir_builder_arith_mul(a->ir, t, lv, rv); + break; + case SPL_OP_ASSIGN_DIV: + res = spl_ir_builder_arith_div(a->ir, t, lv, rv); + break; + case SPL_OP_ASSIGN_MOD: + res = spl_ir_builder_arith_rem(a->ir, t, lv, rv); + break; + case SPL_OP_ASSIGN_AND: + res = spl_ir_builder_arith_and(a->ir, t, lv, rv); + break; + case SPL_OP_ASSIGN_OR: + res = spl_ir_builder_arith_or(a->ir, t, lv, rv); + break; + case SPL_OP_ASSIGN_XOR: + res = spl_ir_builder_arith_xor(a->ir, t, lv, rv); + break; + case SPL_OP_ASSIGN_LSHIFT: + res = spl_ir_builder_arith_shl(a->ir, t, lv, rv); + break; + case SPL_OP_ASSIGN_RSHIFT: + res = spl_ir_builder_arith_shr(a->ir, t, lv, rv); + break; + default: + return 0; + } + if (!res) + return 0; + spl_ir_builder_mem_store(a->ir, t, ptr, res); + return res; + } + spl_ir_node_ref_t l = emit_expr(a, n->binary.left); + spl_ir_node_ref_t r = emit_expr(a, n->binary.right); + if (!l || !r) + return 0; + spl_type_id_t t = node_ir(a, n); + switch (op) { + case SPL_OP_ADD: + return spl_ir_builder_arith_add(a->ir, t, l, r); + case SPL_OP_SUB: + return spl_ir_builder_arith_sub(a->ir, t, l, r); + case SPL_OP_MUL: + return spl_ir_builder_arith_mul(a->ir, t, l, r); + case SPL_OP_DIV: + return spl_ir_builder_arith_div(a->ir, t, l, r); + case SPL_OP_MOD: + return spl_ir_builder_arith_rem(a->ir, t, l, r); + case SPL_OP_BIT_AND: + return spl_ir_builder_arith_and(a->ir, t, l, r); + case SPL_OP_BIT_OR: + return spl_ir_builder_arith_or(a->ir, t, l, r); + case SPL_OP_BIT_XOR: + return spl_ir_builder_arith_xor(a->ir, t, l, r); + case SPL_OP_LSHIFT: + return spl_ir_builder_arith_shl(a->ir, t, l, r); + case SPL_OP_RSHIFT: + return spl_ir_builder_arith_shr(a->ir, t, l, r); + case SPL_OP_CMP_EQ: + return spl_ir_builder_cmp_eq(a->ir, t, l, r); + case SPL_OP_CMP_NE: + return spl_ir_builder_cmp_ne(a->ir, t, l, r); + case SPL_OP_CMP_LT: + return spl_ir_builder_cmp_lt(a->ir, t, l, r); + case SPL_OP_CMP_LE: + return spl_ir_builder_cmp_le(a->ir, t, l, r); + case SPL_OP_CMP_GT: + return spl_ir_builder_cmp_gt(a->ir, t, l, r); + case SPL_OP_CMP_GE: + return spl_ir_builder_cmp_ge(a->ir, t, l, r); + default: + return 0; + } + } + case SPL_AST_EXPR_CALL: { + spl_ir_node_ref_t fn = emit_expr(a, n->call.callee); + if (!fn) + return 0; + spl_type_id_t ret_t = node_ir(a, n); + spl_ir_node_ref_t call = spl_ir_builder_control_call(a->ir, ret_t, fn); + if (!call) + return 0; + for (usize i = 0; i < vec_size(n->call.args); ++i) { + spl_ir_node_ref_t arg = emit_expr(a, vec_at(n->call.args, i)); + if (!arg) + return 0; + spl_ir_builder_control_call_param(a->ir, call, arg); + } + return call; + } + case SPL_AST_EXPR_FIELD: { + spl_ir_node_ref_t ptr = emit_lvalue(a, ref); + if (!ptr) + return 0; + return spl_ir_builder_mem_load(a->ir, node_ir(a, n), ptr); + } + case SPL_AST_EXPR_INDEX: { + spl_ir_node_ref_t ptr = emit_lvalue(a, ref); + if (!ptr) + return 0; + return spl_ir_builder_mem_load(a->ir, node_ir(a, n), ptr); + } + case SPL_AST_EXPR_CAST: + return emit_cast(a, n); + case SPL_AST_EXPR_TUPLE: { + spl_type_id_t t = node_ir(a, n); + spl_ir_node_ref_t node = spl_ir_builder_agg_construct(a->ir, t); + if (!node) + return 0; + for (usize i = 0; i < vec_size(n->tuple.elems); ++i) { + spl_ir_node_ref_t f = emit_expr(a, vec_at(n->tuple.elems, i)); + if (!f) + return 0; + spl_ir_builder_agg_construct_field(a->ir, node, f); + } + return node; + } + case SPL_AST_EXPR_ARRAY_LIT: { + spl_type_id_t t = node_ir(a, n); + if (!t) + Panic("array literal has no type after sema"); + + spl_ir_node_ref_t node = spl_ir_builder_agg_construct(a->ir, t); + if (!node) + Panic("agg_construct failed for array literal"); + + for (usize i = 0; i < vec_size(n->array_literal.elems); ++i) { + spl_ir_node_ref_t f = emit_expr(a, vec_at(n->array_literal.elems, i)); + if (!f) + Panic("array element emit failed"); + spl_ir_builder_agg_construct_field(a->ir, node, f); + } + return node; + } + case SPL_AST_EXPR_AGGREGATE_LIT: { + spl_type_id_t t = node_ir(a, n); + if (!t) + Panic("aggregate literal has no type after sema"); + + spl_type_node_t *tn = spl_type_node(a->sema->type, t); + if (!tn) + Panic("aggregate type node missing"); + usize nfields = vec_size(tn->agg_type.variants); + + /* 按字段名定位到 index,缺省值填 0(sema 已保证无缺省) */ + spl_ir_node_ref_vec_t fields; + vec_init(fields); + for (usize i = 0; i < nfields; ++i) + vec_push(fields, 0); + + for (usize i = 0; i < vec_size(n->aggregate_literal.fields); ++i) { + spl_ast_node_t *item = + spl_ast_node(a->sema->ast, vec_at(n->aggregate_literal.fields, i)); + if (!item || item->kind != SPL_AST_STRUCT_INIT_ITEM) + continue; + + usize idx = 0; + if (!spl_type_agg_member_idx(a->sema->type, t, item->struct_init_item.name, &idx)) + Panic("aggregate field `%s` not found (sema should have caught this)", + item->struct_init_item.name); + + spl_ir_node_ref_t f = emit_expr(a, item->struct_init_item.expr); + if (!f) + Panic("aggregate field emit failed"); + vec_at(fields, idx) = f; + } + + spl_ir_node_ref_t node = spl_ir_builder_agg_construct(a->ir, t); + if (!node) + Panic("agg_construct failed for aggregate literal"); + + /* 顺序非常关键:agg_construct_field 是 vec_push, + 必须严格按字段 index 0..n-1 顺序 push */ + for (usize i = 0; i < nfields; ++i) { + spl_ir_node_ref_t f = vec_at(fields, i); + if (!f) + Panic("aggregate field #%zu missing (sema should have caught this)", i); + spl_ir_builder_agg_construct_field(a->ir, node, f); + } + vec_free(fields); + return node; + } + case SPL_AST_EXPR_BLOCK: { + for (usize i = 0; i < vec_size(n->block.stmts); ++i) + emit_stmt(a, vec_at(n->block.stmts, i)); + if (n->block.tail_expr) + return emit_expr(a, n->block.tail_expr); + return 0; + } + case SPL_AST_EXPR_IF: + case SPL_AST_EXPR_IFVAR: + case SPL_AST_EXPR_WHILE: + case SPL_AST_EXPR_LOOP: { + emit_stmt(a, ref); + return 0; + } default: - UNREACHABLE(); - break; + return 0; } - return ret; } -static spl_ir_node_ref_t transit(spl_ast2ir_t *ctx, spl_ast_node_ref_t ref) { - spl_ir_builder_t *ir = ctx->ir; - const spl_sema_t *sema = ctx->sema; - if (ref == 0) - return 0; - Assert(sema != NULL); - spl_ast_node_t *n = spl_ast_node(sema->ast, ref); - spl_ir_node_ref_t ret = 0; - Assert(n != NULL); +static void emit_stmt(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { + spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref); + if (!n) + return; switch (n->kind) { - case SPL_AST_NONE: - UNREACHABLE(); - break; - case SPL_AST_CONTAINER_MEMBERS: { - vec_for(n->container_members, i) { transit(ctx, vec_at(n->container_members, i)); } - } break; - case SPL_AST_FN_DECL: - TODO(); - break; - case SPL_AST_FN_DEFINE: { - spl_type_id_t tid = tid_from_def(sema, n->resolved_def_id); - spl_type_node_t *fn_type = spl_type_node(sema->type, tid); - Assert(fn_type && fn_type->kind == SPL_TYPE_FN); - // n->fn_decl.attr_list; TODO @extern(vm) using extern attribute - spl_ir_func_ref_t fn_ref = - spl_ir_builder_fn_begin(ir, n->fn_decl.name, tid, (spl_ir_attr_t){0} /*TODO*/); - Assert(fn_ref != 0); - spl_ir_builder_block_begin(ir); - - map_put(ctx->def2ir_map, n->resolved_def_id, fn_ref); - vec_for(n->fn_decl.param_list, i) { - spl_ast_node_ref_t nref = vec_at(n->fn_decl.param_list, i); - spl_ast_node_t *n = spl_ast_node(sema->ast, nref); - spl_type_id_t tid = tid_from_def(sema, n->resolved_def_id); - spl_ir_node_ref_t idx_ref = spl_ir_const_comptime_int(ir, sema, i); - spl_ir_node_ref_t var_ref = spl_ir_builder_control_param(ir, tid, idx_ref); - map_put(ctx->def2ir_map, n->resolved_def_id, var_ref); + case SPL_AST_STATEMENT_RET: { + while (vec_size(a->defer_stack) > 0) { + spl_ast_node_ref_t d = vec_at(a->defer_stack, vec_size(a->defer_stack) - 1); + vec_pop(a->defer_stack); + emit_stmt(a, d); } - - transit(ctx, n->fn_decl.block); - if (!ir->terminated) { - // FIXME - spl_ir_builder_control_ret(ir, n->fn_decl.type_expr, 0); + if (n->statement_ret.expr) { + spl_ast_node_t *en = spl_ast_node(a->sema->ast, n->statement_ret.expr); + spl_ir_node_ref_t v = emit_expr(a, n->statement_ret.expr); + spl_type_id_t t = node_ir(a, en); + spl_ir_builder_control_ret(a->ir, t, v); + } else { + spl_lang_type_id_t rt = a->sema->current_fn_ret_tid; + spl_ir_builder_control_ret(a->ir, to_ir_type(a, rt), 0); } - spl_ir_builder_block_end(ir); - spl_ir_builder_fn_end(ir); + return; + } + case SPL_AST_STATEMENT_BREAK: { + if (vec_size(a->loop_stack) == 0) + return; + spl_ir_node_ref_t jmp = spl_ir_builder_control_jmp(a->ir); + vec_push(vec_at(a->loop_stack, vec_size(a->loop_stack) - 1).breaks, jmp); + return; + } + case SPL_AST_STATEMENT_CONTINUE: { + if (vec_size(a->loop_stack) == 0) + return; + spl_ir_node_ref_t jmp = spl_ir_builder_control_jmp(a->ir); + usize cont = vec_at(a->loop_stack, vec_size(a->loop_stack) - 1).cont_blk; + spl_ir_builder_control_jmp_fixup(a->ir, jmp, cont); + return; + } + case SPL_AST_STATEMENT_DEFER: + if (n->statement_defer.body) + vec_push(a->defer_stack, n->statement_defer.body); + return; + case SPL_AST_STATEMENT_COMPTIME: + if (n->statement_comptime.body) + emit_expr(a, n->statement_comptime.body); + return; + case SPL_AST_STATEMENT_DECL: + if (n->statement_decl.decl) + emit_decl(a, n->statement_decl.decl); + return; + case SPL_AST_STATEMENT_EXPR: + if (n->statement_expr.expr) + emit_expr(a, n->statement_expr.expr); + return; + case SPL_AST_EXPR_IF: { + spl_type_id_t if_t = node_ir(a, n); + spl_ir_node_ref_t result_slot = 0; + if (if_t) + result_slot = spl_ir_builder_mem_alloca(a->ir, if_t, const_usize(a, 1)); - } break; - case SPL_AST_TYPE_DECL: { - transit(ctx, n->type_decl.type_expr); - } break; - case SPL_AST_VAR_DECL: { - spl_type_id_t tid = tid_from_def(sema, n->resolved_def_id); - spl_ir_node_ref_t var_ref = - spl_ir_builder_mem_alloca(ir, tid, spl_ir_const_comptime_int(ir, sema, 1)); - map_put(ctx->def2ir_map, n->resolved_def_id, var_ref); - if (n->var_const_decl.expr) { - spl_ir_node_ref_t expr_ref = transit_expr(ctx, n->var_const_decl.expr, false); - if (expr_ref != 0) { // 0 means undefined - spl_ir_builder_mem_store(ir, tid, var_ref, expr_ref); - } - } - } break; + spl_ir_node_ref_t cond = emit_expr(a, n->if_expr.cond); + if (!cond) + Panic("if cond emit failed"); + spl_ir_node_ref_t br = spl_ir_builder_control_br(a->ir, cond); + spl_ir_builder_block_end(a->ir); + + usize then_blk = spl_ir_builder_block_begin(a->ir); + spl_ir_node_ref_t then_v = 0; + if (n->if_expr.then_block) + then_v = emit_expr(a, n->if_expr.then_block); + if (result_slot && then_v) + spl_ir_builder_mem_store(a->ir, if_t, result_slot, then_v); + spl_ir_node_ref_t then_end = 0; + if (!a->ir->terminated) + then_end = spl_ir_builder_control_jmp(a->ir); + spl_ir_builder_block_end(a->ir); + + usize else_blk = spl_ir_builder_block_begin(a->ir); + spl_ir_node_ref_t else_v = 0; + if (n->if_expr.else_branch) + else_v = emit_expr(a, n->if_expr.else_branch); + if (result_slot && else_v) + spl_ir_builder_mem_store(a->ir, if_t, result_slot, else_v); + spl_ir_node_ref_t else_end = 0; + if (!a->ir->terminated) + else_end = spl_ir_builder_control_jmp(a->ir); + spl_ir_builder_block_end(a->ir); + + usize merge_blk = spl_ir_builder_block_begin(a->ir); + spl_ir_builder_control_br_fixup(a->ir, br, then_blk, else_blk); + if (then_end) + spl_ir_builder_control_jmp_fixup(a->ir, then_end, merge_blk); + if (else_end) + spl_ir_builder_control_jmp_fixup(a->ir, else_end, merge_blk); + return; + } + case SPL_AST_EXPR_IFVAR: { + emit_decl(a, n->ifvar_expr.var_decl); + spl_ast_node_t *vd = spl_ast_node(a->sema->ast, n->ifvar_expr.var_decl); + if (!vd || !vd->var_const_decl.init_expr) + Panic("ifvar requires initializer"); + + spl_ir_node_ref_t slot = 0; + if (!map_get(a->def2ir_map, vd->resolved_def_id, &slot)) + Panic("ifvar var slot not found"); + spl_ir_node_ref_t cond = spl_ir_builder_mem_load(a->ir, node_ir(a, vd), slot); + + spl_ir_node_ref_t br = spl_ir_builder_control_br(a->ir, cond); + spl_ir_builder_block_end(a->ir); + + usize then_blk = spl_ir_builder_block_begin(a->ir); + if (n->ifvar_expr.then_block) + emit_expr(a, n->ifvar_expr.then_block); + spl_ir_node_ref_t then_end = 0; + if (!a->ir->terminated) + then_end = spl_ir_builder_control_jmp(a->ir); + spl_ir_builder_block_end(a->ir); + + usize else_blk = spl_ir_builder_block_begin(a->ir); + if (n->ifvar_expr.else_branch) + emit_expr(a, n->ifvar_expr.else_branch); + spl_ir_node_ref_t else_end = 0; + if (!a->ir->terminated) + else_end = spl_ir_builder_control_jmp(a->ir); + spl_ir_builder_block_end(a->ir); + + usize merge_blk = spl_ir_builder_block_begin(a->ir); + spl_ir_builder_control_br_fixup(a->ir, br, then_blk, else_blk); + if (then_end) + spl_ir_builder_control_jmp_fixup(a->ir, then_end, merge_blk); + if (else_end) + spl_ir_builder_control_jmp_fixup(a->ir, else_end, merge_blk); + return; + } + case SPL_AST_EXPR_WHILE: { + spl_ir_node_ref_t pre_jmp = 0; + if (!a->ir->terminated) + pre_jmp = spl_ir_builder_control_jmp(a->ir); + spl_ir_builder_block_end(a->ir); + + usize head_blk = spl_ir_builder_block_begin(a->ir); + spl_ir_node_ref_t cond = emit_expr(a, n->while_expr.cond); + if (!cond) + Panic("while cond emit failed"); + spl_ir_node_ref_t br = spl_ir_builder_control_br(a->ir, cond); + spl_ir_builder_block_end(a->ir); + + usize body_blk = spl_ir_builder_block_begin(a->ir); + + spl_loop_ctx_t ctx = {0}; + ctx.cont_blk = head_blk; + ctx.brk_blk = 0; + vec_init(ctx.breaks); + vec_push(a->loop_stack, ctx); + + if (n->while_expr.body) + emit_expr(a, n->while_expr.body); + spl_ir_node_ref_t body_end = 0; + if (!a->ir->terminated) + body_end = spl_ir_builder_control_jmp(a->ir); + spl_ir_builder_block_end(a->ir); + + usize after_blk = spl_ir_builder_block_begin(a->ir); + if (n->while_expr.else_branch) + emit_expr(a, n->while_expr.else_branch); + + if (pre_jmp) + spl_ir_builder_control_jmp_fixup(a->ir, pre_jmp, head_blk); + spl_ir_builder_control_br_fixup(a->ir, br, body_blk, after_blk); + if (body_end) + spl_ir_builder_control_jmp_fixup(a->ir, body_end, head_blk); + + spl_loop_ctx_t *top = &vec_at(a->loop_stack, vec_size(a->loop_stack) - 1); + for (usize i = 0; i < vec_size(top->breaks); ++i) + spl_ir_builder_control_jmp_fixup(a->ir, vec_at(top->breaks, i), after_blk); + vec_free(top->breaks); + vec_pop(a->loop_stack); + return; + } + case SPL_AST_EXPR_LOOP: { + spl_ir_node_ref_t pre_jmp = 0; + if (!a->ir->terminated) + pre_jmp = spl_ir_builder_control_jmp(a->ir); + spl_ir_builder_block_end(a->ir); + + usize head_blk = spl_ir_builder_block_begin(a->ir); + + spl_loop_ctx_t ctx = {0}; + ctx.cont_blk = head_blk; + ctx.brk_blk = 0; + vec_init(ctx.breaks); + vec_push(a->loop_stack, ctx); + + if (n->loop_expr.body) + emit_expr(a, n->loop_expr.body); + spl_ir_node_ref_t body_end = 0; + if (!a->ir->terminated) + body_end = spl_ir_builder_control_jmp(a->ir); + spl_ir_builder_block_end(a->ir); + + usize after_blk = spl_ir_builder_block_begin(a->ir); + + if (pre_jmp) + spl_ir_builder_control_jmp_fixup(a->ir, pre_jmp, head_blk); + if (body_end) + spl_ir_builder_control_jmp_fixup(a->ir, body_end, head_blk); + + spl_loop_ctx_t *top = &vec_at(a->loop_stack, vec_size(a->loop_stack) - 1); + for (usize i = 0; i < vec_size(top->breaks); ++i) + spl_ir_builder_control_jmp_fixup(a->ir, vec_at(top->breaks, i), after_blk); + vec_free(top->breaks); + vec_pop(a->loop_stack); + return; + } + case SPL_AST_EXPR_BLOCK: + emit_expr(a, ref); + return; + default: + emit_expr(a, ref); + return; + } +} + +static void emit_decl(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { + spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref); + if (!n) + return; + + switch (n->kind) { + case SPL_AST_VAR_DECL: case SPL_AST_CONST_DECL: { - TODO(); - } break; - case SPL_AST_MEMBER_DECL: - TODO(); - break; - case SPL_AST__COMPTIME_STMT: - case SPL_AST__DIRECTIVE_BLOCK: - case SPL_AST_PARAM_DECL: { - UNREACHABLE(); - } break; - case SPL_AST_ATTR_ITEM: - case SPL_AST_ARGG_INIT_ITEM: { - TODO(); - } break; - case SPL_AST_IF_STATEMENT: { - spl_ir_node_ref_t ref = transit_expr(ctx, n->if_statement.expr, false); - ref = spl_ir_builder_control_br(ir, ref); - spl_ir_builder_block_end(ir); + if (!a->ir->current_fn) + return; + if (!n->resolved_def_id) + return; - usize true_block = spl_ir_builder_block_begin(ir); - transit_expr(ctx, n->if_statement.if_block, false); - usize true_ref = spl_ir_builder_control_jmp(ir); - spl_ir_builder_block_end(ir); + spl_ast_node_t *pat = spl_ast_node(a->sema->ast, n->var_const_decl.pattern); + if (!pat || pat->kind != SPL_AST_PATTERN_IDENT) + return; - usize false_block = spl_ir_builder_block_begin(ir); - transit_expr(ctx, n->if_statement.else_block, false); - usize false_ref = spl_ir_builder_control_jmp(ir); - spl_ir_builder_block_end(ir); + spl_lang_type_id_t var_lang = spl_def_get_lang_id(a->sema->type, n->resolved_def_id); + spl_type_id_t var_ir = to_ir_type(a, var_lang); + if (!var_ir) + return; - usize end_block = spl_ir_builder_block_begin(ir); - spl_ir_builder_control_jmp_fixup(ir, true_ref, end_block); - spl_ir_builder_control_jmp_fixup(ir, false_ref, end_block); - spl_ir_builder_control_br_fixup(ir, ref, true_block, false_block); - } break; - case SPL_AST_IFVAR_STATEMENT: { - TODO(); - } break; - case SPL_AST_WHILE_STATEMENT: { - spl_ir_node_ref_t end_ref = spl_ir_builder_control_jmp(ir); - spl_ir_builder_block_end(ir); + spl_ir_node_ref_t one = const_usize(a, 1); + spl_ir_node_ref_t slot = spl_ir_builder_mem_alloca(a->ir, var_ir, one); + map_put(a->def2ir_map, n->resolved_def_id, slot); - usize cond_block = spl_ir_builder_block_begin(ir); - spl_ir_node_ref_t cond_expr_ref = transit_expr(ctx, n->while_statement.expr, false); - spl_ir_node_ref_t cond_ref = spl_ir_builder_control_br(ir, cond_expr_ref); - spl_ir_builder_block_end(ir); - - usize true_block = spl_ir_builder_block_begin(ir); - transit_expr(ctx, n->while_statement.while_block, false); - usize true_ref = spl_ir_builder_control_jmp(ir); - spl_ir_builder_block_end(ir); - - usize end_block = spl_ir_builder_block_begin(ir); - spl_ir_builder_control_jmp_fixup(ir, true_ref, cond_block); - spl_ir_builder_control_br_fixup(ir, cond_ref, true_block, end_block); - } break; - case SPL_AST_LOOP_STATEMENT: { - usize end_ref = spl_ir_builder_control_jmp(ir); - spl_ir_builder_block_end(ir); - - usize loop_block = spl_ir_builder_block_begin(ir); - spl_ir_node_ref_t loop_expr_ref = transit_expr(ctx, n->loop_statement.loop_block, false); - usize loop_ref = spl_ir_builder_control_jmp(ir); - spl_ir_builder_block_end(ir); - - usize end_block = spl_ir_builder_block_begin(ir); - spl_ir_builder_control_jmp_fixup(ir, end_ref, loop_block); - spl_ir_builder_control_jmp_fixup(ir, loop_ref, loop_block); - } break; - case SPL_AST_FOR_STATEMENT: - case SPL_AST_MATCH_STATEMENT: - TODO(); - break; - case SPL_AST_RET_STATEMENT: { - if (n->ret_statement.expr) { - ret = transit(ctx, n->ret_statement.expr); + if (n->var_const_decl.init_expr) { + spl_ir_node_ref_t v = emit_expr(a, n->var_const_decl.init_expr); + if (v) + spl_ir_builder_mem_store(a->ir, var_ir, slot, v); } - ret = spl_ir_builder_control_ret(ir, n->resolved_type_id, ret); - } break; - case SPL_AST_BREAK_STATEMENT: - case SPL_AST_CONTINUE_STATEMENT: - case SPL_AST_DEFER_STATEMENT: - case SPL_AST_TRY_STATEMENT: - case SPL_AST_CATCH_STATEMENT: - case SPL_AST_ERRDEFER_STATEMEMT: - case SPL_AST_EXPR_STATEMENT: - TODO(); - break; - case SPL_AST_PACKED_EXPR: - case SPL_AST_ASSIGN_EXPR: - case SPL_AST_ASSIGN_ADD_EXPR: - case SPL_AST_ASSIGN_SUB_EXPR: - case SPL_AST_ASSIGN_MUL_EXPR: - case SPL_AST_ASSIGN_DIV_EXPR: - case SPL_AST_ASSIGN_MOD_EXPR: - case SPL_AST_ASSIGN_AND_EXPR: - case SPL_AST_ASSIGN_OR_EXPR: - case SPL_AST_ASSIGN_XOR_EXPR: - case SPL_AST_ASSIGN_LSHIFT_EXPR: - case SPL_AST_ASSIGN_RSHIFT_EXPR: - case SPL_AST_BOOL_OR_EXPR: - case SPL_AST_BOOL_AND_EXPR: - case SPL_AST_BIT_OR_EXPR: - case SPL_AST_BIT_XOR_EXPR: - case SPL_AST_BIT_AND_EXPR: - case SPL_AST_CMP_EQ_EXPR: - case SPL_AST_CMP_NE_EXPR: - case SPL_AST_CMP_LE_EXPR: - case SPL_AST_CMP_GE_EXPR: - case SPL_AST_CMP_LT_EXPR: - case SPL_AST_CMP_GT_EXPR: - case SPL_AST_RANGE_EXPR: - case SPL_AST_LSHIFT_EXPR: - case SPL_AST_RSHIFT_EXPR: - case SPL_AST_ADD_EXPR: - case SPL_AST_SUB_EXPR: - case SPL_AST_MUL_EXPR: - case SPL_AST_DIV_EXPR: - case SPL_AST_MOD_EXPR: - case SPL_AST_MINUS_EXPR: - case SPL_AST_NOT_EXPR: - case SPL_AST_BIT_NOT_EXPR: - case SPL_AST_ADDRESS_EXPR: - case SPL_AST_CALL_EXPR: - case SPL_AST_FIELD_EXPR: - case SPL_AST_DEREF_EXPR: - case SPL_AST_INDEX_EXPR: - case SPL_AST_SLICE_EXPR: - case SPL_AST_AS_EXPR: - case SPL_AST_EXPR_INTEGER_LIT: - case SPL_AST_EXPR_FLOAT_LIT: - case SPL_AST_EXPR_CHAR_LIT: - case SPL_AST_EXPR_STRING_LIT: - case SPL_AST_EXPR_TRUE: - case SPL_AST_EXPR_FALSE: - case SPL_AST_EXPR_NULL: - case SPL_AST_EXPR_UNDEFINED: - case SPL_AST_EXPR_IDENT: - case SPL_AST_ARGGREGATE_INIT: - case SPL_AST_EXPR_EXPR: - case SPL_AST_ARRAY_LIT: - case SPL_AST_BUILTIN_EXPR: - case SPL_AST_BLOCK_EXPR: { - return transit_expr(ctx, ref, false); + return; } - case SPL_AST_BASE_TYPE_FN: - case SPL_AST_BASE_TYPE_PATH: - case SPL_AST_TYPE_POINTER: - case SPL_AST_TYPE_ARRAY: - case SPL_AST_TYPE_SLICE: - case SPL_AST_TYPE_STRUCT: - case SPL_AST_TYPE_UNION: - case SPL_AST_TYPE_SHAPE: - case SPL_AST_TYPE_ENUM: - case SPL_AST_TYPE_VOID: - case SPL_AST_TYPE_BOOL: - case SPL_AST_TYPE_OPAQUE: - case SPL_AST_TYPE_I8: - case SPL_AST_TYPE_U8: - case SPL_AST_TYPE_I16: - case SPL_AST_TYPE_U16: - case SPL_AST_TYPE_I32: - case SPL_AST_TYPE_U32: - case SPL_AST_TYPE_I64: - case SPL_AST_TYPE_U64: - case SPL_AST_TYPE_ISIZE: - case SPL_AST_TYPE_USIZE: - case SPL_AST_TYPE__F32: - case SPL_AST_TYPE__F64: - case SPL_AST_TYPE_ANY: - case SPL_AST_TYPE_IDENT: - case SPL_AST_COUNT: { - UNREACHABLE(); - break; + case SPL_AST_FN_DECL: + emit_fn(a, n); + return; + default: + return; } - } - return ret; } -static usize hash_int(spl_def_id_t k) { return MAP_HASH_INT(k); } -static int cmp_int(spl_def_id_t k1, spl_def_id_t k2) { return MAP_CMP_INT(k1, k2); } +static void emit_fn(spl_ast2ir_t *a, spl_ast_node_t *n) { + if (!n->resolved_def_id) + return; -void spl_ast2ir_init(spl_ast2ir_t *ctx, spl_ir_builder_t *ir, const spl_sema_t *sema) { - ctx->sema = sema; - ctx->ir = ir; - map_init(ctx->def2ir_map, hash_int, cmp_int); - ctx->err_count = 0; + spl_lang_type_id_t fn_lang = spl_def_get_lang_id(a->sema->type, n->resolved_def_id); + spl_lang_type_node_t *fn_ln = spl_lang_type_node(a->sema->type, fn_lang); + if (!fn_ln || fn_ln->kind != SPL_LANG_TYPE_FN) + return; + + spl_type_id_t fn_ir = fn_ln->ir_type_id; + if (!fn_ir) + return; + + spl_ir_attr_t attr = {.kind = SPL_IR_ATTR_NONE}; + spl_ir_func_ref_t fn_ref = spl_ir_builder_fn_begin(a->ir, n->fn_decl.name, fn_ir, attr); + map_put(a->def2ir_map, n->resolved_def_id, (spl_ir_node_ref_t)fn_ref); + + usize defer_base = vec_size(a->defer_stack); + usize loop_base = vec_size(a->loop_stack); + + spl_ir_builder_block_begin(a->ir); + + for (usize i = 0; i < vec_size(n->fn_decl.params); ++i) { + spl_ast_node_ref_t pref = vec_at(n->fn_decl.params, i); + spl_ast_node_t *pd = spl_ast_node(a->sema->ast, pref); + if (!pd || pd->kind != SPL_AST_PARAM_DECL) + continue; + if (!pd->resolved_def_id) + continue; + + spl_lang_type_id_t p_lang = spl_def_get_lang_id(a->sema->type, pd->resolved_def_id); + spl_type_id_t p_ir = to_ir_type(a, p_lang); + if (!p_ir) + continue; + + spl_ir_node_ref_t idx = const_usize(a, i); + spl_ir_node_ref_t pv = spl_ir_builder_control_param(a->ir, p_ir, idx); + + spl_ir_node_ref_t one = const_usize(a, 1); + spl_ir_node_ref_t slot = spl_ir_builder_mem_alloca(a->ir, p_ir, one); + spl_ir_builder_mem_store(a->ir, p_ir, slot, pv); + map_put(a->def2ir_map, pd->resolved_def_id, slot); + } + + if (n->fn_decl.body) + emit_expr(a, n->fn_decl.body); + + if (!a->ir->terminated) { + /* 隐式返回路径:先跑 defer(LIFO),再 ret/unreachable */ + while (vec_size(a->defer_stack) > defer_base) { + 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); + } else { + spl_ir_builder_control_unreachable(a->ir); + } + } + + /* 兜底清理: + * - 若 body 已显式 return,defer 栈可能已被清空到 defer_base 之下 + * (被 return 逻辑弹过),此时 vec_size <= defer_base,无需处理。 + * - 若 body 里开了 loop 却没关(理论上不会,sema 已保证), + * 这里的 while 只是防止异常路径残留。 + */ + while (vec_size(a->defer_stack) > defer_base) { + spl_ast_node_ref_t d = vec_pop(a->defer_stack); + (void)d; + } + while (vec_size(a->loop_stack) > loop_base) { + spl_loop_ctx_t *top = &vec_at(a->loop_stack, vec_size(a->loop_stack) - 1); + vec_free(top->breaks); + vec_pop(a->loop_stack); + } + + spl_ir_builder_block_end(a->ir); + spl_ir_builder_fn_end(a->ir); } -void spl_ast2ir_drop(spl_ast2ir_t *ctx) { map_free(ctx->def2ir_map); } +static void emit_container(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { + spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref); + if (!n) + return; + if (n->kind == SPL_AST_TOP_LEVEL_BLOCK) { + if (n->top_level_block.block) + emit_container(a, n->top_level_block.block); + return; + } + if (n->kind != SPL_AST_CONTAINER_MEMBERS) + return; -void spl_ast2ir_run(spl_ast2ir_t *ctx) { transit(ctx, ctx->sema->ast->root); } + for (usize i = 0; i < vec_size(n->container_members.declarations); ++i) { + spl_ast_node_ref_t dref = vec_at(n->container_members.declarations, i); + spl_ast_node_t *d = spl_ast_node(a->sema->ast, dref); + if (!d) + continue; + switch (d->kind) { + case SPL_AST_FN_DECL: + emit_fn(a, d); + break; + case SPL_AST_TOP_LEVEL_BLOCK: + emit_container(a, dref); + break; + default: + break; + } + } +} + +static usize spl_int_map_hash(usize k) { return MAP_HASH_INT(k); } +static int spl_int_map_cmp(usize a, usize b) { return MAP_CMP_INT(a, b); } + +void spl_ast2ir_init(spl_ast2ir_t *ast2ir, spl_ir_builder_t *ir, const spl_sema_t *sema) { + ast2ir->sema = sema; + ast2ir->ir = ir; + map_init(ast2ir->def2ir_map, spl_int_map_hash, spl_int_map_cmp); + vec_init(ast2ir->loop_stack); + vec_init(ast2ir->defer_stack); + ast2ir->err_count = 0; +} + +void spl_ast2ir_drop(spl_ast2ir_t *ast2ir) { + for (usize i = 0; i < vec_size(ast2ir->loop_stack); ++i) + vec_free(vec_at(ast2ir->loop_stack, i).breaks); + vec_free(ast2ir->loop_stack); + vec_free(ast2ir->defer_stack); + map_free(ast2ir->def2ir_map); +} + +void spl_ast2ir_run(spl_ast2ir_t *ast2ir) { + spl_ast_t *ast = ast2ir->sema->ast; + if (!ast || !ast->root) + return; + spl_ast_node_t *root = spl_ast_node(ast, ast->root); + if (!root || root->kind != SPL_AST_ROOT) + return; + emit_container(ast2ir, root->root.members); +} \ No newline at end of file diff --git a/stage1/spl_ast2ir.h b/stage1/spl_ast2ir.h index 84542a9..3b5e271 100644 --- a/stage1/spl_ast2ir.h +++ b/stage1/spl_ast2ir.h @@ -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; @@ -17,4 +29,4 @@ void spl_ast2ir_drop(spl_ast2ir_t *ast2ir); void spl_ast2ir_run(spl_ast2ir_t *ast2ir); -#endif /* __SPL_AST2IR_H__ */ +#endif /* __SPL_AST2IR_H__ */ \ No newline at end of file diff --git a/stage1/spl_ir.c b/stage1/spl_ir.c index 327826d..ef41ad0 100644 --- a/stage1/spl_ir.c +++ b/stage1/spl_ir.c @@ -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) { diff --git a/stage1/spl_sema.c b/stage1/spl_sema.c index 08989e3..a4a948a 100644 --- a/stage1/spl_sema.c +++ b/stage1/spl_sema.c @@ -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) { diff --git a/stage1/spl_sema.h b/stage1/spl_sema.h index 366f131..3570004 100644 --- a/stage1/spl_sema.h +++ b/stage1/spl_sema.h @@ -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); diff --git a/stage1/spl_type.c b/stage1/spl_type.c index 2f72d59..0b8b967 100644 --- a/stage1/spl_type.c +++ b/stage1/spl_type.c @@ -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) { diff --git a/stage1/spl_type.h b/stage1/spl_type.h index 3bff951..05550ed 100644 --- a/stage1/spl_type.h +++ b/stage1/spl_type.h @@ -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); diff --git a/stage1/splc0.c b/stage1/splc0.c index eff6c12..078b310 100644 --- a/stage1/splc0.c +++ b/stage1/splc0.c @@ -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);