#include "spl_sema.h" void spl_scope_init(spl_scope_t *scope) { vec_init(scope->scopes); vec_push(scope->scopes, (spl_scope_node_t){0}); scope->current_scope = 0; scope->root_scope = 0; } void spl_scope_drop(spl_scope_t *scope) { vec_free(scope->scopes); scope->current_scope = 0; scope->root_scope = 0; } spl_scope_id_t spl_scope_alloc(spl_scope_t *scope) { spl_scope_node_t n; n.parent = scope->current_scope; map_init(n.symbols, MAP_HASH_STR, MAP_CMP_STR); vec_push(scope->scopes, n); return vec_size(scope->scopes) - 1; } bool spl_scope_insert(spl_scope_t *scope, spl_scope_id_t id, spl_symbol_t symbol) { if (!id || id >= vec_size(scope->scopes)) { LOG_FATAL("sema scope insert error"); return false; } spl_symbol_t old = {0}; spl_scope_node_t *node = &vec_at(scope->scopes, id); if (map_get(node->symbols, symbol.name, &old)) { // spl_type_def(sema->type, old); TODO debug node SPL_ERROR(&(spl_dbg_node_t){0}, "find same symbol %s", symbol.name); return false; } map_put(node->symbols, symbol.name, symbol); return true; } bool spl_scope_find(spl_scope_t *scope, const char *name, spl_symbol_t *out) { if (scope == NULL || name == NULL || out == NULL) { return false; } for (spl_scope_id_t id = scope->current_scope; id != 0; id = vec_at(scope->scopes, id).parent) { spl_scope_node_t *s = &vec_at(scope->scopes, id); if (map_get(s->symbols, name, out)) { Assert(out->kind != SPL_SYMBOL_KIND_ERROR); return true; } } return false; } // Parse once static void sema_collect(spl_sema_t *sema, spl_ast_node_ref_t ref) { Assert(sema != NULL && ref != 0); 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_CONTAINER_MEMBERS: { symbol.name = "$file"; symbol.kind = SPL_SYMBOL_KIND_TYPE; symbol.node = spl_type_def_alloc(sema->type); n->resolved_def_id = symbol.node; spl_scope_id_t scope_id = spl_scope_alloc(sema->scope); sema->scope->current_scope = scope_id; sema->scope->root_scope = scope_id; spl_scope_insert(sema->scope, scope_id, symbol); vec_for(n->container_members, i) { sema_collect(sema, vec_at(n->container_members, i)); } spl_def_node_t *def = spl_type_def(sema->type, symbol.node); def->kind = SPL_DEF_AGG; break; } case SPL_AST_TYPE_DECL: { symbol.name = n->type_decl.name; symbol.kind = SPL_SYMBOL_KIND_TYPE; symbol.node = spl_type_def_alloc(sema->type); n->resolved_def_id = symbol.node; n = spl_ast_node(sema->ast, n->type_decl.type_expr); if (!n) { SPL_ERROR(&n->dbg, "type_decl must have type_expr"); sema->error_count++; return; } spl_def_node_t *def = spl_type_def(sema->type, symbol.node); switch (n->kind) { case SPL_AST_TYPE_STRUCT: case SPL_AST_TYPE_UNION: case SPL_AST_TYPE_ENUM: case SPL_AST_TYPE_SHAPE: /* TODO for shape */ def->kind = SPL_DEF_AGG; spl_scope_id_t scope_id = spl_scope_alloc(sema->scope); spl_scope_id_t old_id = sema->scope->current_scope; spl_scope_insert(sema->scope, old_id, symbol); sema->scope->current_scope = scope_id; vec_for(n->type_expr.aggregate_list, i) { sema_collect(sema, vec_at(n->type_expr.aggregate_list, i)); } sema->scope->current_scope = old_id; break; default: def->kind = SPL_DEF_SCALAR; spl_scope_insert(sema->scope, sema->scope->current_scope, symbol); break; } } break; case SPL_AST_FN_DECL: case SPL_AST_FN_DEFINE: { symbol.name = n->fn_decl.name; symbol.kind = SPL_SYMBOL_KIND_FN; symbol.node = spl_type_def_alloc(sema->type); n->resolved_def_id = symbol.node; spl_def_node_t *def = spl_type_def(sema->type, symbol.node); def->kind = SPL_DEF_FN_PARAMS; spl_scope_insert(sema->scope, sema->scope->current_scope, symbol); } break; case SPL_AST_VAR_DECL: case SPL_AST_CONST_DECL: { symbol.name = n->var_const_decl.name; symbol.kind = SPL_SYMBOL_KIND_VAR; symbol.node = spl_type_def_alloc(sema->type); n->resolved_def_id = symbol.node; spl_def_node_t *def = spl_type_def(sema->type, symbol.node); def->kind = SPL_DEF_VAR; spl_scope_insert(sema->scope, sema->scope->current_scope, symbol); } break; case SPL_AST_MEMBER_DECL: { symbol.name = n->member_decl.name; symbol.kind = SPL_SYMBOL_KIND_MEMBER; symbol.node = spl_type_def_alloc(sema->type); n->resolved_def_id = symbol.node; spl_def_node_t *def = spl_type_def(sema->type, symbol.node); def->kind = SPL_DEF_MEMBER; spl_scope_insert(sema->scope, sema->scope->current_scope, symbol); } break; default: break; } } // Parse twice // 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); Assert(n != NULL); switch (n->kind) { case SPL_AST_NONE: UNREACHABLE(); break; case SPL_AST_CONTAINER_MEMBERS: { vec_for(n->container_members, i) { sema_parse(sema, vec_at(n->container_members, i)); } } break; case SPL_AST_FN_DECL: break; case SPL_AST_FN_DEFINE: { if (n->resolved_def_id == 0) { Panic("fn `%s` don't collect", n->fn_decl.name); } spl_def_node_t *def = spl_type_def(sema->type, n->resolved_def_id); def->kind = SPL_DEF_FN_PARAMS; vec_init(def->fn_params_def); sema_push_scope(sema); spl_var_def_vec_t params; vec_init(params); vec_for(n->fn_decl.param_list, i) { spl_ast_node_ref_t ref = vec_at(n->fn_decl.param_list, i); spl_type_id_t tid = sema_parse(sema, ref); spl_ast_node_t *node = spl_ast_node(sema->ast, ref); Assert(node->kind == SPL_AST_PARAM_DECL); spl_var_def_t var_def = {0}; var_def.name = node->param_decl.name; var_def.type_id = tid; var_def.def_id = node->resolved_def_id; var_def.scope_id = sema->scope->current_scope; vec_push(params, var_def); 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) { 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); n->resolved_def_id = symbol.node; spl_def_node_t *def = spl_type_def(sema->type, symbol.node); def->kind = SPL_DEF_VAR; spl_scope_insert(sema->scope, sema->scope->current_scope, symbol); } spl_def_node_t *def = spl_type_def(sema->type, n->resolved_def_id); Assert(def != NULL); spl_type_id_t decl_tid = 0; if (n->var_const_decl.type_expr) { decl_tid = sema_parse(sema, n->var_const_decl.type_expr); } 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) { 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); n->resolved_def_id = symbol.node; spl_def_node_t *def = spl_type_def(sema->type, symbol.node); def->kind = SPL_DEF_VAR; spl_scope_insert(sema->scope, sema->scope->current_scope, symbol); } spl_type_id_t ptid = 0; if (n->param_decl.type_expr) { ptid = sema_parse(sema, n->param_decl.type_expr); } spl_def_node_t *pd = spl_type_def(sema->type, n->resolved_def_id); pd->var_def.type_id = ptid; 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) { sema_parse(sema, n->aggregate_init_item.expr); } } break; case SPL_AST_IF_STATEMENT: { 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)); } vec_for(n->if_statement.else_block, i) { sema_parse(sema, vec_at(n->if_statement.else_block, i)); } } break; case SPL_AST_IFVAR_STATEMENT: { 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)); } vec_for(n->ifvar_statement.else_block, i) { sema_parse(sema, vec_at(n->ifvar_statement.else_block, i)); } } break; case SPL_AST_WHILE_STATEMENT: { 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)); } } break; case SPL_AST_LOOP_STATEMENT: { vec_for(n->loop_statement.loop_block, i) { sema_parse(sema, vec_at(n->loop_statement.loop_block, i)); } } break; case SPL_AST_FOR_STATEMENT: { vec_for(n->for_statement.expr_vec, i) { sema_parse(sema, vec_at(n->for_statement.expr_vec, i)); } 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) { 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)); } vec_for(n->match_statement.match_block, i) { sema_parse(sema, vec_at(n->match_statement.match_block, i)); } } break; case SPL_AST_RET_STATEMENT: { 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: case SPL_AST_DEFER_STATEMENT: { vec_for(n->defer_statement.block_or_statement, i) { sema_parse(sema, vec_at(n->defer_statement.block_or_statement, i)); } } break; case SPL_AST_TRY_STATEMENT: case SPL_AST_CATCH_STATEMENT: case SPL_AST_ERRDEFER_STATEMEMT: case SPL_AST_EXPR_STATEMENT: break; case SPL_AST_PACKED_EXPR: { if (n->packed_expr.expr) sema_parse(sema, n->packed_expr.expr); } break; 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: 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_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: { 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: { 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: { 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: { 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: { 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: { 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; } 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) sema_parse(sema, n->postfix_expr.primary_expr); break; case SPL_AST_INDEX_EXPR: if (n->postfix_expr.primary_expr) sema_parse(sema, n->postfix_expr.primary_expr); if (n->postfix_expr.index_expr) sema_parse(sema, n->postfix_expr.index_expr); break; case SPL_AST_SLICE_EXPR: if (n->postfix_expr.primary_expr) sema_parse(sema, n->postfix_expr.primary_expr); if (n->postfix_expr.slice_expr.begin) sema_parse(sema, n->postfix_expr.slice_expr.begin); if (n->postfix_expr.slice_expr.end) sema_parse(sema, n->postfix_expr.slice_expr.end); break; 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: 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); sema->error_count++; return 0; } Assert(symbol.node != 0); n->resolved_def_id = symbol.node; spl_def_node_t *d = spl_type_def(sema->type, symbol.node); if (!d) { return 0; } if (d->kind == SPL_DEF_VAR || d->kind == SPL_DEF_MEMBER) { return d->var_def.type_id; } 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: { 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); vec_for(n->primary_expr.array_lit_expr.expr_list, i) { sema_parse(sema, vec_at(n->primary_expr.array_lit_expr.expr_list, i)); } break; case SPL_AST_BUILTIN_EXPR: vec_for(n->primary_expr.builtin_expr.expr_list, i) { sema_parse(sema, vec_at(n->primary_expr.builtin_expr.expr_list, i)); } break; case SPL_AST_BLOCK_EXPR: vec_for(n->primary_expr.block_expr, i) { sema_parse(sema, vec_at(n->primary_expr.block_expr, i)); } break; case SPL_AST_BASE_TYPE_FN: vec_for(n->type_expr.attr_list, i) { sema_parse(sema, vec_at(n->type_expr.attr_list, i)); } vec_for(n->type_expr.fn_type.param_list, i) { sema_parse(sema, vec_at(n->type_expr.fn_type.param_list, i)); } if (n->type_expr.fn_type.type_expr) sema_parse(sema, n->type_expr.fn_type.type_expr); break; case SPL_AST_BASE_TYPE_PATH: vec_for(n->type_expr.attr_list, i) { sema_parse(sema, vec_at(n->type_expr.attr_list, i)); } break; case SPL_AST_TYPE_POINTER: vec_for(n->type_expr.attr_list, i) { sema_parse(sema, vec_at(n->type_expr.attr_list, i)); } if (n->type_expr.pointer_type.pointee) sema_parse(sema, n->type_expr.pointer_type.pointee); break; case SPL_AST_TYPE_ARRAY: vec_for(n->type_expr.attr_list, i) { sema_parse(sema, vec_at(n->type_expr.attr_list, i)); } if (n->type_expr.array_type.element) sema_parse(sema, n->type_expr.array_type.element); if (n->type_expr.array_type.size) sema_parse(sema, n->type_expr.array_type.size); break; case SPL_AST_TYPE_SLICE: vec_for(n->type_expr.attr_list, i) { sema_parse(sema, vec_at(n->type_expr.attr_list, i)); } if (n->type_expr.slice_type.element) sema_parse(sema, n->type_expr.slice_type.element); break; case SPL_AST_TYPE_STRUCT: case SPL_AST_TYPE_UNION: case SPL_AST_TYPE_SHAPE: case SPL_AST_TYPE_ENUM: vec_for(n->type_expr.attr_list, i) { sema_parse(sema, vec_at(n->type_expr.attr_list, i)); } vec_for(n->type_expr.aggregate_list, i) { sema_parse(sema, vec_at(n->type_expr.aggregate_list, i)); } 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; case SPL_AST_COUNT: UNREACHABLE(); break; } return 0; } void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_scope_t *scope) { Assert(sema && ast && type && scope); sema->ast = ast; sema->type = type; sema->scope = scope; sema->error_count = 0; sema->current_fn_ret_tid = 0; sema->root = (spl_symbol_t){0}; } void spl_sema_drop(spl_sema_t *sema) { (void)sema; } void spl_sema_run(spl_sema_t *sema) { if (!sema->ast || !sema->ast->root) return; spl_ast_node_t *ast_node = spl_ast_node(sema->ast, sema->ast->root); Assert(ast_node != NULL && ast_node->kind == SPL_AST_CONTAINER_MEMBERS); // 第一趟 实现顺序无关地相互引用 sema_collect(sema, sema->ast->root); // 第二趟 正式解析 sema_parse(sema, sema->ast->root); } void spl_sema_dump(spl_sema_t *sema) { printf("Scopes:\n"); vec_for(sema->scope->scopes, i) { if (i == 0) continue; spl_scope_node_t scope = vec_at(sema->scope->scopes, i); printf("scope[%zu] parent=%zu\n", i, scope.parent); map_for(scope.symbols, j) { spl_symbol_t *symbol = &unsafe_map_at(scope.symbols, j).val; printf(" %s -> def`%s`#%zu\n", unsafe_map_at(scope.symbols, j).key, symbol->name, symbol->node); } } printf("TypeTable:\n"); vec_for(sema->type->type_table, i) { printf(" id#%zu type=", i); spl_type_pure_dump(sema->type, i); printf("\n"); } printf("DefTable:\n"); vec_for(sema->type->def_table, i) { printf(" def#%zu ", i); spl_type_def_dump(sema->type, i); printf("\n"); } }