From 0f40de43a1118bdd4ea224a40101bb369e00e897 Mon Sep 17 00:00:00 2001 From: zzy <2450266535@qq.com> Date: Thu, 20 Aug 2026 19:51:08 +0800 Subject: [PATCH] =?UTF-8?q?stage1=20=E6=9B=B4=E5=A4=9A=E7=9A=84=E8=AF=AD?= =?UTF-8?q?=E4=B9=89=E5=8F=8A=E5=85=B6=E9=99=84=E5=B1=9E=E5=9F=BA=E7=A1=80?= =?UTF-8?q?=E8=AE=BE=E6=96=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- stage1/spl_ast.c | 5 +- stage1/spl_ast.h | 2 +- stage1/spl_ast2ir.c | 5 +- stage1/spl_sema.c | 594 ++++++++++++++++++++++++++++++++++++++------ stage1/spl_sema.h | 2 + stage1/spl_type.c | 22 +- stage1/spl_type.h | 2 + 7 files changed, 553 insertions(+), 79 deletions(-) diff --git a/stage1/spl_ast.c b/stage1/spl_ast.c index b604900..43a10a5 100644 --- a/stage1/spl_ast.c +++ b/stage1/spl_ast.c @@ -1848,9 +1848,10 @@ static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t node_ref, dump_stack_t for (usize i = 0; i < vec_size(*stack); i++) printf("%s", vec_at(*stack, i) ? " " : "| "); - printf("%s%s #%zu", last ? "`-" : "|-", spl_ast_kind_name(node->kind), node_ref); + printf("%s%s #%zu ID`%zu`", last ? "`-" : "|-", spl_ast_kind_name(node->kind), node_ref, + node->resolved_type_id); if (node->dbg.fname) - printf(" (%d:%d)", node->dbg.line, node->dbg.col); + printf(" [%d:%d]", node->dbg.line, node->dbg.col); printf("\n"); vec_push(*stack, last); diff --git a/stage1/spl_ast.h b/stage1/spl_ast.h index fabe367..f4f5985 100644 --- a/stage1/spl_ast.h +++ b/stage1/spl_ast.h @@ -155,7 +155,7 @@ struct spl_ast_node { spl_ast_node_ref_vec_t attr_list; /* attr_item */ const char *name; spl_ast_node_ref_vec_t param_list; /* param_decl */ - spl_ast_node_ref_t type_expr; + spl_ast_node_ref_t type_expr; /* ret type expr */ spl_ast_node_ref_vec_t block; /* 语句/尾表达式 */ } fn_decl; struct { diff --git a/stage1/spl_ast2ir.c b/stage1/spl_ast2ir.c index 441f1ca..2f0aa54 100644 --- a/stage1/spl_ast2ir.c +++ b/stage1/spl_ast2ir.c @@ -58,7 +58,7 @@ static spl_ir_node_ref_t transit(spl_ir_builder_t *ir, const spl_sema_t *sema, if (n->ret_statement.expr) { ret = transit(ir, sema, n->ret_statement.expr); } - ret = spl_ir_builder_control_ret(ir, tid_from_def(sema, n->resolved_def_id), ret); + ret = spl_ir_builder_control_ret(ir, n->resolved_type_id, ret); } break; case SPL_AST_BREAK_STATEMENT: case SPL_AST_CONTINUE_STATEMENT: @@ -111,8 +111,7 @@ static spl_ir_node_ref_t transit(spl_ir_builder_t *ir, const spl_sema_t *sema, TODO(); break; case SPL_AST_EXPR_INTEGER_LIT: { - ret = spl_ir_builder_type_const_int(ir, tid_from_def(sema, n->resolved_def_id), - n->primary_expr.integer_expr); + ret = spl_ir_builder_type_const_int(ir, n->resolved_type_id, n->primary_expr.integer_expr); break; } case SPL_AST_EXPR_FLOAT_LIT: diff --git a/stage1/spl_sema.c b/stage1/spl_sema.c index 9d4b5b9..250ec3b 100644 --- a/stage1/spl_sema.c +++ b/stage1/spl_sema.c @@ -82,6 +82,7 @@ static void sema_collect(spl_sema_t *sema, spl_ast_node_ref_t ref) { n = spl_ast_node(sema->ast, n->type_decl.type_expr); if (!n) { SPL_ERROR(&n->dbg, "type_decl must have type_expr"); + sema->error_count++; return; } @@ -103,9 +104,9 @@ static void sema_collect(spl_sema_t *sema, spl_ast_node_ref_t ref) { break; default: def->kind = SPL_DEF_SCALAR; + spl_scope_insert(sema->scope, sema->scope->current_scope, symbol); break; } - spl_scope_insert(sema->scope, sema->scope->current_scope, symbol); } break; case SPL_AST_FN_DECL: case SPL_AST_FN_DEFINE: { @@ -145,12 +146,136 @@ static void sema_collect(spl_sema_t *sema, spl_ast_node_ref_t ref) { } // Parse twice -static void sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { - if (ref == 0) - return; + +// use for assign_expr as_expr +static spl_type_id_t sema_coerce(spl_sema_t *sema, spl_type_id_t to, spl_type_id_t from) { + // var := from + if (to == 0) { + return from; + } + // error + if (from == 0) { + return 0; + } + // same + if (to == from) { + return to; + } + spl_type_node_t *tn = spl_type_node(sema->type, to); + spl_type_node_t *fn = spl_type_node(sema->type, from); + Assert(tn != NULL && fn != NULL); + switch (fn->kind) { + case SPL_TYPE_UNDEFINED: + return to; + case SPL_TYPE_NULL: + if (tn->kind == SPL_TYPE_PTR || tn->kind == SPL_TYPE_SLICE) { + return to; + } + break; + case SPL_TYPE_INT: + if (tn->kind != SPL_TYPE_INT) { + break; + } + + // var = comptime_int + if (tn->int_type.bits > 0 && fn->int_type.bits == 0) { + return to; + } + + // not same signed + if (tn->int_type.is_signed != fn->int_type.is_signed) { + break; + } + + // var i32 = i32/i16 + if (tn->int_type.bits >= fn->int_type.bits) { + return to; + } + break; + case SPL_TYPE_FLOAT: + // TODO + break; + case SPL_TYPE_ARRAY: + // TODO + break; + default: + break; + } + return 0; +} + +// use for op_expr +static spl_type_id_t sema_coerce_balance(spl_sema_t *sema, spl_type_id_t t1, spl_type_id_t t2) { + // error + if (t1 == 0 || t2 == 0) { + return 0; + } + // same + if (t1 == t2) { + return t1; + } + spl_type_node_t *n1 = spl_type_node(sema->type, t1); + spl_type_node_t *n2 = spl_type_node(sema->type, t2); + Assert(n1 != NULL && n2 != NULL); + + // TODO 应该推导类型 + if (n1->kind == SPL_TYPE_UNDEFINED && n1->kind == SPL_TYPE_UNDEFINED) { + return 0; + } + + if (n1->kind == SPL_TYPE_UNDEFINED) { + return t2; + } + if (n2->kind == SPL_TYPE_UNDEFINED) { + return t1; + } + if (n1->kind == SPL_TYPE_NULL) { + return (n2->kind == SPL_TYPE_PTR || n2->kind == SPL_TYPE_SLICE) ? t2 : 0; + } + if (n2->kind == SPL_TYPE_NULL) { + return (n1->kind == SPL_TYPE_PTR || n1->kind == SPL_TYPE_SLICE) ? t1 : 0; + } + + if (n1->kind != n2->kind) { + return 0; + } + + switch (n1->kind) { + case SPL_TYPE_INT: + if (n1->int_type.is_signed != n2->int_type.is_signed) { + return 0; + } + return n1->int_type.bits >= n2->int_type.bits ? t1 : t2; + case SPL_TYPE_FLOAT: + return n1->float_type.bits >= n2->float_type.bits ? t1 : t2; + default: + break; + } + return 0; +} + +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}); + return sema_coerce(sema, bool_tid, from) == bool_tid; +} + +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; + sema->scope->current_scope = scope_id; +} + +static inline void sema_pop_scope(spl_sema_t *sema) { + sema->scope->current_scope = sema->store_scope; +} + +static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { + if (ref == 0) { + return 0; + } Assert(sema != NULL); spl_ast_node_t *n = spl_ast_node(sema->ast, ref); - spl_symbol_t symbol = {0}; Assert(n != NULL); switch (n->kind) { case SPL_AST_NONE: @@ -160,42 +285,59 @@ static void sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { vec_for(n->container_members, i) { sema_parse(sema, vec_at(n->container_members, i)); } } break; case SPL_AST_FN_DECL: + 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_scope_id_t scope_id = spl_scope_alloc(sema->scope); - spl_scope_id_t old_id = sema->scope->current_scope; - sema->scope->current_scope = scope_id; + spl_var_def_vec_t params; + vec_init(params); vec_for(n->fn_decl.param_list, i) { spl_ast_node_ref_t ref = vec_at(n->fn_decl.param_list, i); - sema_parse(sema, ref); - def = spl_type_def(sema->type, n->resolved_def_id); + spl_type_id_t tid = sema_parse(sema, ref); spl_ast_node_t *node = spl_ast_node(sema->ast, 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(def->fn_params_def, var_def); - } - vec_for(n->fn_decl.block, i) { sema_parse(sema, vec_at(n->fn_decl.block, i)); } - sema->scope->current_scope = old_id; + vec_push(params, var_def); - // spl_type_def_fn_build(sema->type, n->resolved_def_id, ) + 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_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 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)); } + sema->current_fn_ret_tid = old_ret; + sema_pop_scope(sema); } break; case SPL_AST_TYPE_DECL: { - if (n->type_decl.type_expr) + if (n->type_decl.type_expr) { sema_parse(sema, n->type_decl.type_expr); + } } break; case SPL_AST_VAR_DECL: case SPL_AST_CONST_DECL: { if (n->resolved_def_id == 0) { + 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); @@ -205,20 +347,37 @@ static void sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { def->kind = SPL_DEF_VAR; spl_scope_insert(sema->scope, sema->scope->current_scope, symbol); } - if (n->var_const_decl.type_expr) - sema_parse(sema, n->var_const_decl.type_expr); - if (n->var_const_decl.expr) - sema_parse(sema, n->var_const_decl.expr); + 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); + } + if (n->var_const_decl.expr == 0) { + SPL_ERROR(&n->dbg, "must be assign"); + return 0; + } + + spl_type_id_t et = sema_parse(sema, n->var_const_decl.expr); + decl_tid = sema_coerce(sema, decl_tid, et); + if (decl_tid == 0) { + 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; } break; case SPL_AST_MEMBER_DECL: { - if (n->member_decl.type_expr) + if (n->member_decl.type_expr) { sema_parse(sema, n->member_decl.type_expr); + } } break; case SPL_AST__COMPTIME_STMT: case SPL_AST__DIRECTIVE_BLOCK: break; case SPL_AST_PARAM_DECL: { if (n->resolved_def_id == 0) { + 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); @@ -228,19 +387,32 @@ static void sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { def->kind = SPL_DEF_VAR; spl_scope_insert(sema->scope, sema->scope->current_scope, symbol); } - if (n->param_decl.type_expr) - sema_parse(sema, n->param_decl.type_expr); + 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; + return ptid; } break; case SPL_AST_ATTR_ITEM: vec_for(n->attr_item.expr_list, i) { sema_parse(sema, vec_at(n->attr_item.expr_list, i)); } break; case SPL_AST_ARGG_INIT_ITEM: { - if (n->aggregate_init_item.expr) + if (n->aggregate_init_item.expr) { sema_parse(sema, n->aggregate_init_item.expr); + } } break; case SPL_AST_IF_STATEMENT: { - if (n->if_statement.expr) - sema_parse(sema, n->if_statement.expr); + if (!n->if_statement.expr) { + SPL_ERROR(&n->dbg, "if statement not have condition expr"); + return 0; + } + spl_type_id_t ct = sema_parse(sema, n->if_statement.expr); + if (!sema_coerce_for_bool(sema, ct)) { + SPL_ERROR(&n->dbg, "if condition must be bool"); + sema->error_count++; + } vec_for(n->if_statement.if_block, i) { sema_parse(sema, vec_at(n->if_statement.if_block, i)); } @@ -249,8 +421,9 @@ static void sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { } } break; case SPL_AST_IFVAR_STATEMENT: { - if (n->ifvar_statement.packed_expr) + if (n->ifvar_statement.packed_expr) { sema_parse(sema, n->ifvar_statement.packed_expr); + } vec_for(n->ifvar_statement.if_block, i) { sema_parse(sema, vec_at(n->ifvar_statement.if_block, i)); } @@ -259,8 +432,15 @@ static void sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { } } break; case SPL_AST_WHILE_STATEMENT: { - if (n->while_statement.expr) - sema_parse(sema, n->while_statement.expr); + if (!n->while_statement.expr) { + SPL_ERROR(&n->dbg, "while statement not have condition expr"); + return 0; + } + spl_type_id_t ct = sema_parse(sema, n->while_statement.expr); + if (!sema_coerce_for_bool(sema, ct)) { + SPL_ERROR(&n->dbg, "while condition must be bool"); + sema->error_count++; + } vec_for(n->while_statement.while_block, i) { sema_parse(sema, vec_at(n->while_statement.while_block, i)); } @@ -277,8 +457,9 @@ static void sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { vec_for(n->for_statement.block, i) { sema_parse(sema, vec_at(n->for_statement.block, i)); } } break; case SPL_AST_MATCH_STATEMENT: { - if (n->match_statement.expr) + if (n->match_statement.expr) { sema_parse(sema, n->match_statement.expr); + } vec_for(n->match_statement.paced_exprs, i) { sema_parse(sema, vec_at(n->match_statement.paced_exprs, i)); } @@ -287,7 +468,14 @@ static void sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { } } break; case SPL_AST_RET_STATEMENT: { - sema_parse(sema, n->ret_statement.expr); + if (n->ret_statement.expr) { + spl_type_id_t tid = sema_parse(sema, n->ret_statement.expr); + if (sema_coerce(sema, sema->current_fn_ret_tid, tid) != sema->current_fn_ret_tid) { + SPL_ERROR(&n->dbg, "return type not match"); + sema->error_count += 1; + } + n->resolved_type_id = sema->current_fn_ret_tid; + } } break; case SPL_AST_BREAK_STATEMENT: case SPL_AST_CONTINUE_STATEMENT: @@ -305,7 +493,22 @@ static void sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { if (n->packed_expr.expr) sema_parse(sema, n->packed_expr.expr); } break; - case SPL_AST_ASSIGN_EXPR: + case SPL_AST_ASSIGN_EXPR: { + spl_type_id_t lt = sema_parse(sema, n->op_expr.left); + if (lt == 0) { + SPL_ERROR(&n->dbg, "assign target has no type"); + sema->error_count++; + break; + } + spl_type_id_t rt = sema_parse(sema, n->op_expr.right); + if (sema_coerce(sema, lt, rt) == 0) { + SPL_ERROR(&n->dbg, "assign type mismatch"); + sema->error_count++; + break; + } + n->resolved_type_id = lt; + return lt; + } case SPL_AST_ASSIGN_ADD_EXPR: case SPL_AST_ASSIGN_SUB_EXPR: case SPL_AST_ASSIGN_MUL_EXPR: @@ -315,45 +518,181 @@ static void sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { case SPL_AST_ASSIGN_OR_EXPR: case SPL_AST_ASSIGN_XOR_EXPR: case SPL_AST_ASSIGN_LSHIFT_EXPR: - case SPL_AST_ASSIGN_USHIFT_EXPR: + case SPL_AST_ASSIGN_USHIFT_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); + if (lt == 0) { + SPL_ERROR(&n->dbg, "assign target has no type"); + sema->error_count++; + break; + } + if (sema_coerce_balance(sema, lt, rt) != lt) { + SPL_ERROR(&n->dbg, "compound assign result would narrow or mismatch lhs type"); + sema->error_count++; + break; + } + n->resolved_type_id = lt; + return lt; + } case SPL_AST_BOOL_OR_EXPR: - case SPL_AST_BOOL_AND_EXPR: + case SPL_AST_BOOL_AND_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); + if (!ln || ln->kind != SPL_TYPE_BOOL || !rn || rn->kind != SPL_TYPE_BOOL) { + SPL_ERROR(&n->dbg, "logical operands must be bool"); + sema->error_count++; + break; + } + spl_type_id_t bt = spl_type_node_push(sema->type, (spl_type_node_t){.kind = SPL_TYPE_BOOL}); + n->resolved_type_id = bt; + return bt; + } case SPL_AST_BIT_OR_EXPR: case SPL_AST_BIT_XOR_EXPR: - case SPL_AST_BIT_AND_EXPR: + case SPL_AST_BIT_AND_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_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) { + SPL_ERROR(&n->dbg, "bitwise operands must be integers"); + sema->error_count++; + break; + } + n->resolved_type_id = peer; + return peer; + } 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_CMP_GT_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); + if (sema_coerce_balance(sema, lt, rt) == 0) { + SPL_ERROR(&n->dbg, "comparison operands type mismatch"); + sema->error_count++; + break; + } + spl_type_id_t bt = spl_type_node_push(sema->type, (spl_type_node_t){.kind = SPL_TYPE_BOOL}); + n->resolved_type_id = bt; + return bt; + } case SPL_AST_RANGE_EXPR: + break; case SPL_AST_LSHIFT_EXPR: - case SPL_AST_RSHIFT_EXPR: + case SPL_AST_RSHIFT_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); + if (!ln || ln->kind != SPL_TYPE_INT || !rn || rn->kind != SPL_TYPE_INT) { + SPL_ERROR(&n->dbg, "shift operands must be integers"); + sema->error_count++; + break; + } + n->resolved_type_id = lt; + return lt; + } 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: - if (n->op_expr.left) - sema_parse(sema, n->op_expr.left); - if (n->op_expr.right) - sema_parse(sema, n->op_expr.right); - break; - case SPL_AST_MINUS_EXPR: - case SPL_AST_NOT_EXPR: - case SPL_AST_BIT_NOT_EXPR: + 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_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)) { + SPL_ERROR(&n->dbg, "arithmetic operands type mismatch"); + sema->error_count++; + break; + } + n->resolved_type_id = peer; + return peer; + } + 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, + }); + 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, + }); + n->resolved_type_id = ct; + return ct; + } + spl_type_id_t t = sema_parse(sema, n->prefix_expr.postfix_expr); + spl_type_node_t *tn = spl_type_node(sema->type, t); + if (!tn || (tn->kind != SPL_TYPE_INT && tn->kind != SPL_TYPE_FLOAT)) { + SPL_ERROR(&n->dbg, "unary minus requires numeric operand"); + sema->error_count++; + break; + } + n->resolved_type_id = t; + return t; + } + case SPL_AST_NOT_EXPR: { + spl_type_id_t t = sema_parse(sema, n->prefix_expr.postfix_expr); + spl_type_node_t *tn = spl_type_node(sema->type, t); + if (!tn || tn->kind != SPL_TYPE_BOOL) { + SPL_ERROR(&n->dbg, "`not` requires bool operand"); + sema->error_count++; + break; + } + spl_type_id_t bt = spl_type_node_push(sema->type, (spl_type_node_t){.kind = SPL_TYPE_BOOL}); + n->resolved_type_id = bt; + return bt; + } + case SPL_AST_BIT_NOT_EXPR: { + spl_type_id_t t = sema_parse(sema, n->prefix_expr.postfix_expr); + spl_type_node_t *tn = spl_type_node(sema->type, t); + if (!tn || tn->kind != SPL_TYPE_INT) { + SPL_ERROR(&n->dbg, "bitnot requires integer operand"); + sema->error_count++; + break; + } + n->resolved_type_id = t; + return t; + } case SPL_AST_ADDRESS_EXPR: if (n->prefix_expr.postfix_expr) sema_parse(sema, n->prefix_expr.postfix_expr); break; - case SPL_AST_CALL_EXPR: - if (n->postfix_expr.primary_expr) - sema_parse(sema, n->postfix_expr.primary_expr); - vec_for(n->postfix_expr.call_expr, i) { - sema_parse(sema, vec_at(n->postfix_expr.call_expr, i)); + case SPL_AST_CALL_EXPR: { + spl_type_id_t fnt = sema_parse(sema, n->postfix_expr.primary_expr); + spl_type_node_t *fn = spl_type_node(sema->type, fnt); + if (!fn || fn->kind != SPL_TYPE_FN) { + SPL_ERROR(&n->dbg, "call target is not a function"); + sema->error_count++; + break; } - 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; + } + 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) { + SPL_ERROR(&n->dbg, "call argument type mismatch"); + sema->error_count++; + } + } + 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) @@ -373,38 +712,84 @@ static void sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { if (n->postfix_expr.slice_expr.end) sema_parse(sema, n->postfix_expr.slice_expr.end); break; - case SPL_AST_AS_EXPR: - if (n->postfix_expr.primary_expr) - sema_parse(sema, n->postfix_expr.primary_expr); - if (n->postfix_expr.type_expr) - sema_parse(sema, n->postfix_expr.type_expr); - break; - case SPL_AST_EXPR_INTEGER_LIT: - case SPL_AST_EXPR_FLOAT_LIT: + case SPL_AST_AS_EXPR: { + spl_type_id_t st = sema_parse(sema, n->postfix_expr.primary_expr); + spl_type_id_t tt = sema_parse(sema, n->postfix_expr.type_expr); + spl_type_node_t *sn = spl_type_node(sema->type, st); + if (tt == 0 || !sn || + (sn->kind != SPL_TYPE_INT && sn->kind != SPL_TYPE_FLOAT && sn->kind != SPL_TYPE_BOOL)) { + SPL_ERROR(&n->dbg, "invalid `as` cast"); + sema->error_count++; + break; + } + n->resolved_type_id = tt; + 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, + }); + 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, + }); + n->resolved_type_id = ct; + return ct; + } 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: break; + case SPL_AST_EXPR_NULL: { + spl_type_id_t nt = spl_type_node_push(sema->type, (spl_type_node_t){.kind = 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}); + 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}); + n->resolved_type_id = ut; + return ut; + } case SPL_AST_EXPR_IDENT: { + spl_symbol_t symbol = {0}; if (!spl_scope_find(sema->scope, n->primary_expr.ident, &symbol)) { SPL_ERROR(&n->dbg, "can't find ident `%s`", n->primary_expr.ident); - return; + sema->error_count++; + return 0; } Assert(symbol.node != 0); n->resolved_def_id = symbol.node; - } break; + 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; + } + 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)); } break; - case SPL_AST_EXPR_EXPR: - if (n->primary_expr.expr) - sema_parse(sema, n->primary_expr.expr); - break; + case SPL_AST_EXPR_EXPR: { + spl_type_id_t t = sema_parse(sema, n->primary_expr.expr); + n->resolved_type_id = t; + return t; + } case SPL_AST_ARRAY_LIT: if (n->primary_expr.array_lit_expr.type_expr) sema_parse(sema, n->primary_expr.array_lit_expr.type_expr); @@ -460,20 +845,85 @@ static void 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, + }); case SPL_AST_TYPE_BOOL: + return spl_type_node_push(sema->type, (spl_type_node_t){ + .kind = SPL_TYPE_BOOL, + }); case SPL_AST_TYPE_OPAQUE: + break; 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, + }); 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, + }); 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, + }); 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, + }); 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, + }); 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, + }); 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, + }); 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, + }); 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, + }); 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, + }); case SPL_AST_TYPE__F32: + return spl_type_node_push(sema->type, (spl_type_node_t){ + .kind = SPL_TYPE_FLOAT, + .float_type.bits = 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, + }); case SPL_AST_TYPE_ANY: case SPL_AST_TYPE_IDENT: break; @@ -481,6 +931,7 @@ static void sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { UNREACHABLE(); break; } + return 0; } void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_scope_t *scope) { @@ -489,6 +940,7 @@ void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_scope sema->type = type; sema->scope = scope; sema->error_count = 0; + sema->current_fn_ret_tid = 0; sema->root = (spl_symbol_t){0}; } diff --git a/stage1/spl_sema.h b/stage1/spl_sema.h index ea6b76c..366f131 100644 --- a/stage1/spl_sema.h +++ b/stage1/spl_sema.h @@ -43,6 +43,8 @@ typedef struct { spl_scope_t *scope; spl_symbol_t root; int error_count; + spl_scope_id_t store_scope; + spl_type_id_t current_fn_ret_tid; // TODO } spl_sema_t; void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_scope_t *scope); diff --git a/stage1/spl_type.c b/stage1/spl_type.c index 693f0a7..2936cd5 100644 --- a/stage1/spl_type.c +++ b/stage1/spl_type.c @@ -6,6 +6,8 @@ static usize spl_type_hash(spl_type_node_t n) { case SPL_TYPE_ERROR: case SPL_TYPE_VOID: case SPL_TYPE_BOOL: + case SPL_TYPE_UNDEFINED: + case SPL_TYPE_NULL: break; case SPL_TYPE_INT: hash += n.int_type.bits + n.int_type.is_signed; @@ -54,6 +56,8 @@ static int spl_type_eq(spl_type_node_t n1, spl_type_node_t n2) { case SPL_TYPE_ERROR: case SPL_TYPE_VOID: case SPL_TYPE_BOOL: + case SPL_TYPE_UNDEFINED: + case SPL_TYPE_NULL: break; case SPL_TYPE_INT: if (n1.int_type.bits != n2.int_type.bits) @@ -318,11 +322,25 @@ void spl_type_pure_dump(spl_type_t *type, spl_type_id_t id) { case SPL_TYPE_BOOL: printf("bool"); break; + case SPL_TYPE_UNDEFINED: + printf("undefined"); + break; + case SPL_TYPE_NULL: + printf("null"); + break; case SPL_TYPE_INT: - printf("%s%zu", n->int_type.is_signed ? "i" : "u", n->int_type.bits); + if (n->int_type.bits == 0) { + printf("comptime_int"); + } else { + printf("%s%zu", n->int_type.is_signed ? "i" : "u", n->int_type.bits); + } break; case SPL_TYPE_FLOAT: - printf("f%zu", n->float_type.bits); + if (n->float_type.bits == 0) { + printf("comptime_float"); + } else { + printf("f%zu", n->float_type.bits); + } break; case SPL_TYPE_PTR: printf("*"); diff --git a/stage1/spl_type.h b/stage1/spl_type.h index 2154494..b0f5987 100644 --- a/stage1/spl_type.h +++ b/stage1/spl_type.h @@ -15,6 +15,8 @@ typedef enum { SPL_TYPE_BOOL, SPL_TYPE_INT, SPL_TYPE_FLOAT, + SPL_TYPE_UNDEFINED, // 自动配对任意类型的字面量,值为 undefined + SPL_TYPE_NULL, // 自动配对指针/切片的字面量,值为 0 SPL_TYPE_PTR, SPL_TYPE_SLICE, // 未来拥有泛型后删除 SPL_TYPE_RANGE, // 未来拥有泛型后删除