stage1 支持指针运算 提供新的类型检查计算
This commit is contained in:
1 parent
be41a82d55
commit
06f3884c30
12 files changed
+572
-321
No files matched your search
+294
-189
@@ -117,7 +117,7 @@ static void sema_resolve_attrs(spl_sema_t *sema, spl_ast_node_ref_vec_t *raw,
|
||||
break;
|
||||
case SPL_AST_EXPR_INT_LIT:
|
||||
oa.kind = SPL_ATTR_ARG_INT;
|
||||
oa.value.i = arg->int_lit.val;
|
||||
oa.value.i = arg->int_lit.bits;
|
||||
break;
|
||||
default:
|
||||
SPL_ERROR(&a->dbg, "attribute arg #%zu has unsupported form", j);
|
||||
@@ -140,8 +140,8 @@ static void sema_resolve_attrs(spl_sema_t *sema, spl_ast_node_ref_vec_t *raw,
|
||||
}
|
||||
|
||||
static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref);
|
||||
static spl_lang_type_id_t sema_check(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
spl_lang_type_id_t expected);
|
||||
static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
spl_lang_type_id_t expected);
|
||||
static spl_lang_type_id_t sema_intrin_call(spl_sema_t *sema, spl_ast_node_t *n, spl_intrin_t in,
|
||||
spl_ast_node_ref_vec_t *args);
|
||||
static spl_lang_type_id_t sema_intrin_field(spl_sema_t *sema, spl_ast_node_t *n, spl_intrin_t in);
|
||||
@@ -177,6 +177,82 @@ static bool sema_is_literal(spl_ast_node_t *n) {
|
||||
}
|
||||
}
|
||||
|
||||
static void sema_type_to_str(spl_sema_t *sema, spl_lang_type_id_t tid, char *buf, usize cap) {
|
||||
if (!buf || cap == 0)
|
||||
return;
|
||||
if (tid == 0) {
|
||||
snprintf(buf, cap, "<none>");
|
||||
return;
|
||||
}
|
||||
spl_lang_type_node_t *n = spl_lang_type_node(sema->type, tid);
|
||||
if (!n) {
|
||||
snprintf(buf, cap, "<invalid lang#%zu>", tid);
|
||||
return;
|
||||
}
|
||||
spl_type_node_t *ir = spl_type_node(sema->type, n->ir_type_id);
|
||||
switch (n->kind) {
|
||||
case SPL_LANG_TYPE_INT:
|
||||
if (ir && ir->int_type.bits == 0)
|
||||
snprintf(buf, cap, "comptime_int(#%zu)", tid);
|
||||
else if (ir)
|
||||
snprintf(buf, cap, "%s%zu(#%zu)", ir->int_type.is_signed ? "i" : "u", ir->int_type.bits,
|
||||
tid);
|
||||
else
|
||||
snprintf(buf, cap, "int?(#%zu)", tid);
|
||||
break;
|
||||
case SPL_LANG_TYPE_FLOAT:
|
||||
if (ir && ir->float_type.bits == 0)
|
||||
snprintf(buf, cap, "comptime_float(#%zu)", tid);
|
||||
else if (ir)
|
||||
snprintf(buf, cap, "f%zu(#%zu)", ir->float_type.bits, tid);
|
||||
else
|
||||
snprintf(buf, cap, "float?(#%zu)", tid);
|
||||
break;
|
||||
case SPL_LANG_TYPE_BOOL:
|
||||
snprintf(buf, cap, "bool(#%zu)", tid);
|
||||
break;
|
||||
case SPL_LANG_TYPE_UNIT:
|
||||
snprintf(buf, cap, "unit(#%zu)", tid);
|
||||
break;
|
||||
case SPL_LANG_TYPE_NEVER:
|
||||
snprintf(buf, cap, "never(#%zu)", tid);
|
||||
break;
|
||||
case SPL_LANG_TYPE_ANY:
|
||||
snprintf(buf, cap, "any(#%zu)", tid);
|
||||
break;
|
||||
case SPL_LANG_TYPE_INFER:
|
||||
snprintf(buf, cap, "infer(#%zu)", tid);
|
||||
break;
|
||||
case SPL_LANG_TYPE_ERROR:
|
||||
snprintf(buf, cap, "error(#%zu)", tid);
|
||||
break;
|
||||
case SPL_LANG_TYPE_PTR:
|
||||
snprintf(buf, cap, "ptr(#%zu)", tid);
|
||||
break;
|
||||
case SPL_LANG_TYPE_ARRAY:
|
||||
snprintf(buf, cap, "array(#%zu)", tid);
|
||||
break;
|
||||
case SPL_LANG_TYPE_SLICE:
|
||||
snprintf(buf, cap, "slice(#%zu)", tid);
|
||||
break;
|
||||
case SPL_LANG_TYPE_TUPLE:
|
||||
snprintf(buf, cap, "tuple(#%zu)", tid);
|
||||
break;
|
||||
case SPL_LANG_TYPE_RANGE:
|
||||
snprintf(buf, cap, "range(#%zu)", tid);
|
||||
break;
|
||||
case SPL_LANG_TYPE_FN:
|
||||
snprintf(buf, cap, "fn(#%zu)", tid);
|
||||
break;
|
||||
case SPL_LANG_TYPE_VARARGS:
|
||||
snprintf(buf, cap, "varargs(#%zu)", tid);
|
||||
break;
|
||||
default:
|
||||
snprintf(buf, cap, "langkind=%d ir=%zu(#%zu)", (int)n->kind, n->ir_type_id, tid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void sema_push_scope(spl_sema_t *sema) {
|
||||
spl_scope_id_t new_scope = spl_scope_alloc(sema->scope);
|
||||
sema->store_scope = sema->scope->current_scope;
|
||||
@@ -505,7 +581,7 @@ static spl_lang_type_id_t sema_intrin_call(spl_sema_t *sema, spl_ast_node_t *n,
|
||||
}
|
||||
case SPL_INTRIN_ASSERT: {
|
||||
spl_lang_type_id_t bt = spl_lang_make_bool(sema->type);
|
||||
sema_check(sema, vec_at(*args, 0), bt);
|
||||
sema_coerce(sema, vec_at(*args, 0), bt);
|
||||
if (nargs == 2)
|
||||
sema_infer(sema, vec_at(*args, 1));
|
||||
return spl_lang_make_unit(sema->type);
|
||||
@@ -532,51 +608,78 @@ static spl_lang_type_id_t sema_intrin_field(spl_sema_t *sema, spl_ast_node_t *n,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static spl_lang_type_id_t sema_check(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
spl_lang_type_id_t expected) {
|
||||
static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
spl_lang_type_id_t expected) {
|
||||
if (!ref || !expected)
|
||||
return 0;
|
||||
spl_ast_node_t *n = spl_ast_node(sema->ast, ref);
|
||||
if (!n)
|
||||
return 0;
|
||||
|
||||
/* ============ 类 1:构造性节点 —— 就地定型为 expected ============ */
|
||||
spl_lang_type_id_t already = n->resolved_lang_tid;
|
||||
if (already == expected)
|
||||
return expected;
|
||||
|
||||
/* 已定型 */
|
||||
if (already != 0) {
|
||||
spl_lang_type_node_t *an = spl_lang_type_node(sema->type, already);
|
||||
spl_type_node_t *air = an ? spl_type_node(sema->type, an->ir_type_id) : NULL;
|
||||
/* comptime 与 infer 都属于"可重定型":清空 resolved 后按 expected 重新推导 */
|
||||
bool a_rebindable =
|
||||
(an && an->kind == SPL_LANG_TYPE_INFER) ||
|
||||
(an && an->kind == SPL_LANG_TYPE_INT && air && air->int_type.bits == 0) ||
|
||||
(an && an->kind == SPL_LANG_TYPE_FLOAT && air && air->float_type.bits == 0);
|
||||
if (!a_rebindable) {
|
||||
/* 具体类型:只接受子类型方向 */
|
||||
if (spl_lang_type_is_subtype(sema->type, already, expected)) {
|
||||
n->expected_lang_tid = expected;
|
||||
return expected;
|
||||
}
|
||||
char ebuf[128], gbuf[128];
|
||||
sema_type_to_str(sema, expected, ebuf, sizeof(ebuf));
|
||||
sema_type_to_str(sema, already, gbuf, sizeof(gbuf));
|
||||
SPL_ERROR(&n->dbg, "type mismatch: node kind=%d already typed as %s, expected %s",
|
||||
(int)n->kind, gbuf, ebuf);
|
||||
sema->error_count++;
|
||||
return 0;
|
||||
}
|
||||
/* 清空 resolved,走未定型路径,让递归按 expected 下推子节点 */
|
||||
n->resolved_lang_tid = 0;
|
||||
}
|
||||
|
||||
/* 未定型的构造性节点 */
|
||||
switch (n->kind) {
|
||||
|
||||
case SPL_AST_EXPR_UNARY: {
|
||||
if (n->unary.op == SPL_UNARY_OP_ADDRESS)
|
||||
return sema_infer(sema, ref); /* &x 没有"被 check 到某类型"的语义 */
|
||||
if (!sema_check(sema, n->unary.operand, expected))
|
||||
/* & 与 .* 的结果类型由操作数决定,不能靠 expected 反向定型 */
|
||||
if (n->unary.op == SPL_UNARY_OP_ADDRESS || n->unary.op == SPL_UNARY_OP_DEREF)
|
||||
return sema_infer(sema, ref);
|
||||
if (!sema_coerce(sema, n->unary.operand, expected))
|
||||
return 0;
|
||||
n->resolved_lang_tid = expected;
|
||||
n->expected_lang_tid = 0;
|
||||
return expected;
|
||||
}
|
||||
|
||||
case SPL_AST_EXPR_BINARY: {
|
||||
spl_binary_op_t op = n->binary.op;
|
||||
|
||||
/* 赋值 / 复合赋值:右侧 check 到左侧类型 */
|
||||
if (op == SPL_OP_ASSIGN || (op >= SPL_OP_ASSIGN_ADD && op <= SPL_OP_ASSIGN_RSHIFT)) {
|
||||
spl_lang_type_id_t lt = sema_infer(sema, n->binary.left);
|
||||
if (!lt)
|
||||
return 0;
|
||||
if (!sema_check(sema, n->binary.right, lt))
|
||||
if (!sema_coerce(sema, n->binary.right, lt))
|
||||
return 0;
|
||||
n->resolved_lang_tid = lt;
|
||||
n->expected_lang_tid = 0;
|
||||
return lt;
|
||||
}
|
||||
|
||||
/* 逻辑运算:两侧 check 到 bool */
|
||||
if (op == SPL_OP_BOOL_OR || op == SPL_OP_BOOL_AND) {
|
||||
spl_lang_type_id_t bt = spl_lang_make_bool(sema->type);
|
||||
if (!sema_check(sema, n->binary.left, bt))
|
||||
if (!sema_coerce(sema, n->binary.left, bt))
|
||||
return 0;
|
||||
if (!sema_check(sema, n->binary.right, bt))
|
||||
if (!sema_coerce(sema, n->binary.right, bt))
|
||||
return 0;
|
||||
n->resolved_lang_tid = bt;
|
||||
n->expected_lang_tid = 0;
|
||||
return bt;
|
||||
}
|
||||
|
||||
@@ -586,48 +689,55 @@ static spl_lang_type_id_t sema_check(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
spl_lang_type_id_t rt = sema_infer(sema, n->binary.right);
|
||||
if (!lt || !rt)
|
||||
return 0;
|
||||
|
||||
spl_lang_type_id_t common = 0;
|
||||
if (lt == rt)
|
||||
common = lt;
|
||||
else
|
||||
common = spl_lang_type_balance(sema->type, lt, rt);
|
||||
spl_lang_type_id_t common = (lt == rt) ? lt : spl_lang_type_join(sema->type, lt, rt);
|
||||
if (!common) {
|
||||
SPL_ERROR(&n->dbg, "comparison operands type mismatch");
|
||||
char lbuf[128], rbuf[128];
|
||||
sema_type_to_str(sema, lt, lbuf, sizeof(lbuf));
|
||||
sema_type_to_str(sema, rt, rbuf, sizeof(rbuf));
|
||||
SPL_ERROR(&n->dbg, "comparison operands type mismatch: lhs=%s rhs=%s", lbuf, rbuf);
|
||||
sema->error_count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
sema_check(sema, n->binary.left, common);
|
||||
sema_check(sema, n->binary.right, common);
|
||||
|
||||
n->resolved_lang_tid = common;
|
||||
return spl_lang_make_bool(sema->type);
|
||||
sema_coerce(sema, n->binary.left, common);
|
||||
sema_coerce(sema, n->binary.right, common);
|
||||
spl_lang_type_id_t b = spl_lang_make_bool(sema->type);
|
||||
n->resolved_lang_tid = b;
|
||||
return b;
|
||||
}
|
||||
|
||||
/* ptr +/- int:右侧 check 到整数,节点类型仍为指针 */
|
||||
/* ptr +/- int:expected 是 ptr 且左侧推断为 ptr。
|
||||
* 右侧保留原整型;仅 comptime_int(bits==0)收紧到 isize。 */
|
||||
if (op == SPL_OP_ADD || op == SPL_OP_SUB) {
|
||||
spl_lang_type_id_t lt = sema_infer(sema, n->binary.left);
|
||||
if (!lt)
|
||||
return 0;
|
||||
spl_lang_type_node_t *lln = spl_lang_type_node(sema->type, lt);
|
||||
if (lln && lln->kind == SPL_LANG_TYPE_PTR) {
|
||||
spl_lang_type_id_t it = spl_lang_make_int(sema->type, sizeof(void *) * 8, 1);
|
||||
if (!sema_check(sema, n->binary.right, it))
|
||||
return 0;
|
||||
n->resolved_lang_tid = lt;
|
||||
n->expected_lang_tid = expected;
|
||||
return expected;
|
||||
spl_lang_type_node_t *en = spl_lang_type_node(sema->type, expected);
|
||||
if (en && en->kind == SPL_LANG_TYPE_PTR) {
|
||||
spl_lang_type_id_t lt = sema_infer(sema, n->binary.left);
|
||||
spl_lang_type_node_t *ln = spl_lang_type_node(sema->type, lt);
|
||||
if (ln && ln->kind == SPL_LANG_TYPE_PTR) {
|
||||
spl_lang_type_id_t rt = sema_infer(sema, n->binary.right);
|
||||
spl_lang_type_node_t *rn = spl_lang_type_node(sema->type, rt);
|
||||
if (!rn || rn->kind != SPL_LANG_TYPE_INT) {
|
||||
SPL_ERROR(&n->dbg, "pointer offset must be integer");
|
||||
sema->error_count++;
|
||||
return 0;
|
||||
}
|
||||
spl_type_node_t *rn_ir = spl_type_node(sema->type, rn->ir_type_id);
|
||||
if (rn_ir && rn_ir->int_type.bits == 0) {
|
||||
spl_lang_type_id_t it =
|
||||
spl_lang_make_int(sema->type, sizeof(void *) * 8, 1);
|
||||
if (!sema_coerce(sema, n->binary.right, it))
|
||||
return 0;
|
||||
}
|
||||
n->resolved_lang_tid = expected;
|
||||
return expected;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 算术 / 位 / 移位:两侧 check 到 expected */
|
||||
if (!sema_check(sema, n->binary.left, expected))
|
||||
if (!sema_coerce(sema, n->binary.left, expected))
|
||||
return 0;
|
||||
if (!sema_check(sema, n->binary.right, expected))
|
||||
if (!sema_coerce(sema, n->binary.right, expected))
|
||||
return 0;
|
||||
n->resolved_lang_tid = expected;
|
||||
n->expected_lang_tid = 0;
|
||||
return expected;
|
||||
}
|
||||
|
||||
@@ -636,13 +746,12 @@ static spl_lang_type_id_t sema_check(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
if (en && en->kind == SPL_LANG_TYPE_ARRAY) {
|
||||
spl_lang_type_id_t et = en->extra.elem;
|
||||
for (usize i = 0; i < vec_size(n->array_literal.elems); ++i)
|
||||
if (!sema_check(sema, vec_at(n->array_literal.elems, i), et))
|
||||
if (!sema_coerce(sema, vec_at(n->array_literal.elems, i), et))
|
||||
return 0;
|
||||
n->resolved_lang_tid = expected;
|
||||
n->expected_lang_tid = 0;
|
||||
return expected;
|
||||
}
|
||||
break; /* 非数组 expected:退回通用逻辑 */
|
||||
break;
|
||||
}
|
||||
|
||||
case SPL_AST_EXPR_TUPLE: {
|
||||
@@ -657,11 +766,10 @@ static spl_lang_type_id_t sema_check(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
}
|
||||
for (usize i = 0; i < nelems; ++i) {
|
||||
spl_lang_type_id_t et = vec_at(en->extra.elems, i);
|
||||
if (!sema_check(sema, vec_at(n->tuple.elems, i), et))
|
||||
if (!sema_coerce(sema, vec_at(n->tuple.elems, i), et))
|
||||
return 0;
|
||||
}
|
||||
n->resolved_lang_tid = expected;
|
||||
n->expected_lang_tid = 0;
|
||||
return expected;
|
||||
}
|
||||
break;
|
||||
@@ -673,6 +781,7 @@ static spl_lang_type_id_t sema_check(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
en->kind != SPL_LANG_TYPE_ENUM))
|
||||
break;
|
||||
|
||||
/* 有名字时,名字必须与 expected 指向同一类型 */
|
||||
if (n->aggregate_literal.name) {
|
||||
spl_symbol_t sym;
|
||||
if (!spl_scope_find(sema->scope, n->aggregate_literal.name, &sym)) {
|
||||
@@ -691,8 +800,11 @@ static spl_lang_type_id_t sema_check(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
|
||||
spl_type_id_t agg_ir = spl_lang_type_get_ir_type(sema->type, expected);
|
||||
spl_type_node_t *irn = spl_type_node(sema->type, agg_ir);
|
||||
if (!irn)
|
||||
if (!irn) {
|
||||
SPL_ERROR(&n->dbg, "aggregate type unresolved");
|
||||
sema->error_count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (en->kind == SPL_LANG_TYPE_ENUM) {
|
||||
if (vec_size(n->aggregate_literal.fields) != 1) {
|
||||
@@ -712,25 +824,16 @@ static spl_lang_type_id_t sema_check(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
sema->error_count++;
|
||||
return 0;
|
||||
}
|
||||
spl_type_member_t *m = &vec_at(irn->agg_type.variants, idx);
|
||||
spl_lang_type_id_t ft = sema_lang_from_ir(sema, m->type_id);
|
||||
if (!ft)
|
||||
return 0;
|
||||
if (!item->struct_init_item.expr) {
|
||||
SPL_ERROR(&item->dbg, "variant `%s` requires initializer",
|
||||
item->struct_init_item.name);
|
||||
sema->error_count++;
|
||||
return 0;
|
||||
usize field_tid_ir = vec_at(irn->agg_type.variants, idx).type_id;
|
||||
spl_lang_type_id_t ft = sema_lang_from_ir(sema, field_tid_ir);
|
||||
if (ft && item->struct_init_item.expr) {
|
||||
if (!sema_coerce(sema, item->struct_init_item.expr, ft))
|
||||
return 0;
|
||||
}
|
||||
sema_check(sema, item->struct_init_item.expr, ft);
|
||||
n->resolved_lang_tid = expected;
|
||||
n->expected_lang_tid = 0;
|
||||
return expected;
|
||||
}
|
||||
|
||||
usize nfields = vec_size(irn->agg_type.variants);
|
||||
bool *seen = calloc(nfields ? nfields : 1, sizeof(bool));
|
||||
|
||||
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)
|
||||
@@ -741,39 +844,25 @@ static spl_lang_type_id_t sema_check(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
sema->error_count++;
|
||||
continue;
|
||||
}
|
||||
if (seen[idx]) {
|
||||
SPL_ERROR(&item->dbg, "duplicate field `%s`", item->struct_init_item.name);
|
||||
sema->error_count++;
|
||||
continue;
|
||||
}
|
||||
seen[idx] = true;
|
||||
usize field_tid_ir = vec_at(irn->agg_type.variants, idx).type_id;
|
||||
spl_lang_type_id_t ft = sema_lang_from_ir(sema, field_tid_ir);
|
||||
if (!ft)
|
||||
continue;
|
||||
if (!item->struct_init_item.expr) {
|
||||
SPL_ERROR(&item->dbg, "field `%s` requires initializer",
|
||||
item->struct_init_item.name);
|
||||
sema->error_count++;
|
||||
continue;
|
||||
if (ft && item->struct_init_item.expr) {
|
||||
if (!sema_coerce(sema, item->struct_init_item.expr, ft))
|
||||
return 0;
|
||||
}
|
||||
sema_check(sema, item->struct_init_item.expr, ft);
|
||||
}
|
||||
free(seen);
|
||||
n->resolved_lang_tid = expected;
|
||||
n->expected_lang_tid = 0;
|
||||
return expected;
|
||||
}
|
||||
|
||||
case SPL_AST_EXPR_IF: {
|
||||
spl_lang_type_id_t bt = spl_lang_make_bool(sema->type);
|
||||
sema_check(sema, n->if_expr.cond, bt);
|
||||
sema_coerce(sema, n->if_expr.cond, bt);
|
||||
if (n->if_expr.then_block)
|
||||
sema_check(sema, n->if_expr.then_block, expected);
|
||||
sema_coerce(sema, n->if_expr.then_block, expected);
|
||||
if (n->if_expr.else_branch)
|
||||
sema_check(sema, n->if_expr.else_branch, expected);
|
||||
sema_coerce(sema, n->if_expr.else_branch, expected);
|
||||
n->resolved_lang_tid = expected;
|
||||
n->expected_lang_tid = 0;
|
||||
return expected;
|
||||
}
|
||||
|
||||
@@ -781,16 +870,14 @@ static spl_lang_type_id_t sema_check(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
for (usize i = 0; i < vec_size(n->block.stmts); ++i)
|
||||
sema_infer(sema, vec_at(n->block.stmts, i));
|
||||
if (n->block.tail_expr) {
|
||||
spl_lang_type_id_t t = sema_check(sema, n->block.tail_expr, expected);
|
||||
spl_lang_type_id_t t = sema_coerce(sema, n->block.tail_expr, expected);
|
||||
if (!t)
|
||||
return 0;
|
||||
n->resolved_lang_tid = t;
|
||||
n->expected_lang_tid = 0;
|
||||
return t;
|
||||
}
|
||||
spl_lang_type_id_t u = spl_lang_make_unit(sema->type);
|
||||
n->resolved_lang_tid = u;
|
||||
n->expected_lang_tid = 0;
|
||||
return u;
|
||||
}
|
||||
|
||||
@@ -798,45 +885,49 @@ static spl_lang_type_id_t sema_check(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
break;
|
||||
}
|
||||
|
||||
/* ============ 类 2:字面量 —— 就地定型 ============ */
|
||||
if (sema_is_literal(n)) {
|
||||
spl_lang_type_id_t from = n->resolved_lang_tid;
|
||||
if (!from) {
|
||||
from = sema_infer(sema, ref);
|
||||
if (!from)
|
||||
return 0;
|
||||
}
|
||||
if (from == expected)
|
||||
return expected;
|
||||
spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, expected, from);
|
||||
if (!r) {
|
||||
SPL_ERROR(&n->dbg, "literal cannot coerce to expected type");
|
||||
sema->error_count++;
|
||||
return 0;
|
||||
}
|
||||
n->resolved_lang_tid = r;
|
||||
n->expected_lang_tid = 0;
|
||||
return r;
|
||||
}
|
||||
/* 兜底:infer 后按子类型 / comptime 判定 */
|
||||
spl_lang_type_id_t from = sema_infer(sema, ref);
|
||||
if (!from)
|
||||
return 0;
|
||||
if (from == expected)
|
||||
return expected;
|
||||
|
||||
/* ============ 类 3:引用性节点 —— 只记 expected ============ */
|
||||
{
|
||||
spl_lang_type_id_t from = sema_infer(sema, ref);
|
||||
if (!from)
|
||||
return 0;
|
||||
if (from == expected) {
|
||||
n->expected_lang_tid = 0;
|
||||
return expected;
|
||||
}
|
||||
spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, expected, from);
|
||||
if (!r) {
|
||||
SPL_ERROR(&n->dbg, "type mismatch: cannot coerce to expected type");
|
||||
spl_lang_type_node_t *from_n = spl_lang_type_node(sema->type, from);
|
||||
spl_lang_type_node_t *to_n = spl_lang_type_node(sema->type, expected);
|
||||
spl_type_node_t *from_ir = from_n ? spl_type_node(sema->type, from_n->ir_type_id) : NULL;
|
||||
spl_type_node_t *to_ir = to_n ? spl_type_node(sema->type, to_n->ir_type_id) : NULL;
|
||||
|
||||
bool from_comptime_int =
|
||||
from_n && from_n->kind == SPL_LANG_TYPE_INT && from_ir && from_ir->int_type.bits == 0;
|
||||
bool from_comptime_float =
|
||||
from_n && from_n->kind == SPL_LANG_TYPE_FLOAT && from_ir && from_ir->float_type.bits == 0;
|
||||
if (from_comptime_int && to_n && to_n->kind == SPL_LANG_TYPE_INT) {
|
||||
uint32_t bits = to_ir ? (uint32_t)to_ir->int_type.bits : 0;
|
||||
if (n->kind == SPL_AST_EXPR_INT_LIT && bits != 0 &&
|
||||
!spl_lang_mpa_int_fits(sema->type, expected, n->int_lit)) {
|
||||
SPL_ERROR(&n->dbg, "comptime value does not fit target type");
|
||||
sema->error_count++;
|
||||
return 0;
|
||||
}
|
||||
n->expected_lang_tid = expected; /* 只记,不改 natural */
|
||||
n->resolved_lang_tid = expected;
|
||||
return expected;
|
||||
}
|
||||
if (from_comptime_float && to_n && to_n->kind == SPL_LANG_TYPE_FLOAT) {
|
||||
n->resolved_lang_tid = expected;
|
||||
return expected;
|
||||
}
|
||||
|
||||
if (spl_lang_type_is_subtype(sema->type, from, expected)) {
|
||||
n->expected_lang_tid = expected;
|
||||
return expected;
|
||||
}
|
||||
|
||||
char ebuf[128], gbuf[128];
|
||||
sema_type_to_str(sema, expected, ebuf, sizeof(ebuf));
|
||||
sema_type_to_str(sema, from, gbuf, sizeof(gbuf));
|
||||
SPL_ERROR(&n->dbg, "type mismatch: expect %s, got %s (node kind=%d)", ebuf, gbuf, (int)n->kind);
|
||||
sema->error_count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
@@ -854,12 +945,12 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
|
||||
/* ---------- 字面量 ---------- */
|
||||
case SPL_AST_EXPR_INT_LIT: {
|
||||
spl_lang_type_id_t t = spl_lang_make_int(sema->type, 0, 1); /* comptime_int */
|
||||
spl_lang_type_id_t t = spl_lang_make_int(sema->type, 0, 1);
|
||||
n->resolved_lang_tid = t;
|
||||
return t;
|
||||
}
|
||||
case SPL_AST_EXPR_FLOAT_LIT: {
|
||||
spl_lang_type_id_t t = spl_lang_make_float(sema->type, 0); /* comptime_float */
|
||||
spl_lang_type_id_t t = spl_lang_make_float(sema->type, 0);
|
||||
n->resolved_lang_tid = t;
|
||||
return t;
|
||||
}
|
||||
@@ -939,7 +1030,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
return op;
|
||||
case SPL_UNARY_OP_NOT: {
|
||||
spl_lang_type_id_t bt = spl_lang_make_bool(sema->type);
|
||||
sema_check(sema, n->unary.operand, bt);
|
||||
sema_coerce(sema, n->unary.operand, bt);
|
||||
n->resolved_lang_tid = bt;
|
||||
return bt;
|
||||
}
|
||||
@@ -948,6 +1039,16 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
n->resolved_lang_tid = p;
|
||||
return p;
|
||||
}
|
||||
case SPL_UNARY_OP_DEREF: {
|
||||
if (tn->kind != SPL_LANG_TYPE_PTR) {
|
||||
SPL_ERROR(&n->dbg, "deref requires pointer operand");
|
||||
sema->error_count++;
|
||||
return 0;
|
||||
}
|
||||
spl_lang_type_id_t elem = tn->extra.elem;
|
||||
n->resolved_lang_tid = elem;
|
||||
return elem;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
@@ -962,7 +1063,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
spl_lang_type_id_t lt = sema_infer(sema, n->binary.left);
|
||||
if (!lt)
|
||||
return 0;
|
||||
sema_check(sema, n->binary.right, lt);
|
||||
sema_coerce(sema, n->binary.right, lt);
|
||||
n->resolved_lang_tid = lt;
|
||||
return lt;
|
||||
}
|
||||
@@ -970,8 +1071,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
/* 逻辑 */
|
||||
if (op == SPL_OP_BOOL_OR || op == SPL_OP_BOOL_AND) {
|
||||
spl_lang_type_id_t bt = spl_lang_make_bool(sema->type);
|
||||
sema_check(sema, n->binary.left, bt);
|
||||
sema_check(sema, n->binary.right, bt);
|
||||
sema_coerce(sema, n->binary.left, bt);
|
||||
sema_coerce(sema, n->binary.right, bt);
|
||||
n->resolved_lang_tid = bt;
|
||||
return bt;
|
||||
}
|
||||
@@ -983,22 +1084,22 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
if (!lt || !rt)
|
||||
return 0;
|
||||
|
||||
spl_lang_type_id_t common = 0;
|
||||
if (lt == rt)
|
||||
common = lt;
|
||||
else
|
||||
common = spl_lang_type_balance(sema->type, lt, rt);
|
||||
spl_lang_type_id_t common = (lt == rt) ? lt : spl_lang_type_join(sema->type, lt, rt);
|
||||
if (!common) {
|
||||
SPL_ERROR(&n->dbg, "comparison operands type mismatch");
|
||||
char lbuf[128], rbuf[128];
|
||||
sema_type_to_str(sema, lt, lbuf, sizeof(lbuf));
|
||||
sema_type_to_str(sema, rt, rbuf, sizeof(rbuf));
|
||||
SPL_ERROR(&n->dbg, "comparison operands type mismatch: lhs=%s rhs=%s", lbuf, rbuf);
|
||||
sema->error_count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
sema_check(sema, n->binary.left, common);
|
||||
sema_check(sema, n->binary.right, common);
|
||||
sema_coerce(sema, n->binary.left, common);
|
||||
sema_coerce(sema, n->binary.right, common);
|
||||
|
||||
n->resolved_lang_tid = common;
|
||||
return spl_lang_make_bool(sema->type);
|
||||
spl_lang_type_id_t b = spl_lang_make_bool(sema->type);
|
||||
n->resolved_lang_tid = b;
|
||||
return b;
|
||||
}
|
||||
|
||||
/* Range */
|
||||
@@ -1027,52 +1128,41 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
return lt;
|
||||
}
|
||||
|
||||
/* 算术 / 位运算 */
|
||||
spl_lang_type_id_t lt = sema_infer(sema, n->binary.left);
|
||||
spl_lang_type_id_t rt = sema_infer(sema, n->binary.right);
|
||||
if (!lt || !rt)
|
||||
return 0;
|
||||
|
||||
spl_lang_type_id_t common = 0;
|
||||
if (lt == rt)
|
||||
common = lt;
|
||||
else
|
||||
common = spl_lang_type_balance(sema->type, lt, rt);
|
||||
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);
|
||||
|
||||
/* balance 失败:comptime + 具体时取具体 */
|
||||
if (!common) {
|
||||
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);
|
||||
if (ln && ln->kind == SPL_LANG_TYPE_INT && rn && rn->kind == SPL_LANG_TYPE_INT) {
|
||||
spl_type_node_t *lir = spl_type_node(sema->type, ln->ir_type_id);
|
||||
spl_type_node_t *rir = spl_type_node(sema->type, rn->ir_type_id);
|
||||
if (lir && lir->int_type.bits == 0)
|
||||
common = rt;
|
||||
else if (rir && rir->int_type.bits == 0)
|
||||
common = lt;
|
||||
} else if (ln && ln->kind == SPL_LANG_TYPE_FLOAT && rn &&
|
||||
rn->kind == SPL_LANG_TYPE_FLOAT) {
|
||||
spl_type_node_t *lir = spl_type_node(sema->type, ln->ir_type_id);
|
||||
spl_type_node_t *rir = spl_type_node(sema->type, rn->ir_type_id);
|
||||
if (lir && lir->float_type.bits == 0)
|
||||
common = rt;
|
||||
else if (rir && rir->float_type.bits == 0)
|
||||
common = lt;
|
||||
/* ptr +/- int 特判:右侧保留自己的整型;
|
||||
* 仅当右操作数是 comptime_int(bits==0)时收紧到 isize,
|
||||
* 避免 comptime 类型泄漏到 IR。 */
|
||||
if (ln && ln->kind == SPL_LANG_TYPE_PTR && rn && rn->kind == SPL_LANG_TYPE_INT &&
|
||||
(op == SPL_OP_ADD || op == SPL_OP_SUB)) {
|
||||
spl_type_node_t *rn_ir = spl_type_node(sema->type, rn->ir_type_id);
|
||||
if (rn_ir && rn_ir->int_type.bits == 0) {
|
||||
spl_lang_type_id_t it = spl_lang_make_int(sema->type, sizeof(void *) * 8, 1);
|
||||
sema_coerce(sema, n->binary.right, it);
|
||||
}
|
||||
n->resolved_lang_tid = lt;
|
||||
return lt;
|
||||
}
|
||||
/* ptr +/- int 特判 */
|
||||
|
||||
spl_lang_type_id_t common = (lt == rt) ? lt : spl_lang_type_join(sema->type, lt, rt);
|
||||
if (!common) {
|
||||
spl_lang_type_node_t *pln = spl_lang_type_node(sema->type, lt);
|
||||
spl_lang_type_node_t *prn = spl_lang_type_node(sema->type, rt);
|
||||
if (pln && pln->kind == SPL_LANG_TYPE_PTR && prn && prn->kind == SPL_LANG_TYPE_INT &&
|
||||
(op == SPL_OP_ADD || op == SPL_OP_SUB)) {
|
||||
n->resolved_lang_tid = lt;
|
||||
n->expected_lang_tid = 0;
|
||||
return lt;
|
||||
}
|
||||
char lbuf[128], rbuf[128];
|
||||
sema_type_to_str(sema, lt, lbuf, sizeof(lbuf));
|
||||
sema_type_to_str(sema, rt, rbuf, sizeof(rbuf));
|
||||
SPL_ERROR(&n->dbg, "operand types cannot be joined: lhs=%s rhs=%s", lbuf, rbuf);
|
||||
sema->error_count++;
|
||||
return 0;
|
||||
}
|
||||
sema_check(sema, n->binary.left, common);
|
||||
sema_check(sema, n->binary.right, common);
|
||||
|
||||
sema_coerce(sema, n->binary.left, common);
|
||||
sema_coerce(sema, n->binary.right, common);
|
||||
|
||||
n->resolved_lang_tid = common;
|
||||
return common;
|
||||
}
|
||||
@@ -1123,13 +1213,13 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
for (usize i = 0; i < nargs && i < fixed; ++i) {
|
||||
spl_lang_type_id_t pt =
|
||||
vec_at(spl_lang_type_node(sema->type, callee_tid)->extra.fn.params, i);
|
||||
sema_check(sema, vec_at(n->call.args, i), pt);
|
||||
sema_coerce(sema, vec_at(n->call.args, i), pt);
|
||||
}
|
||||
/* varargs:默认提升到 isize */
|
||||
if (has_varargs) {
|
||||
spl_lang_type_id_t vt = spl_lang_make_int(sema->type, sizeof(void *) * 8, 1);
|
||||
for (usize i = fixed; i < nargs; ++i)
|
||||
sema_check(sema, vec_at(n->call.args, i), vt);
|
||||
sema_coerce(sema, vec_at(n->call.args, i), vt);
|
||||
}
|
||||
|
||||
spl_lang_type_id_t ret = fn->extra.fn.ret;
|
||||
@@ -1213,7 +1303,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
sema->error_count++;
|
||||
return 0;
|
||||
}
|
||||
isize i = idx_node->int_lit.val;
|
||||
isize i = (isize)idx_node->int_lit.bits;
|
||||
if (i < 0 || (usize)i >= vec_size(obj->extra.elems)) {
|
||||
SPL_ERROR(&n->dbg, "tuple index out of range");
|
||||
sema->error_count++;
|
||||
@@ -1257,17 +1347,31 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
|
||||
/* ---------- CAST ---------- */
|
||||
case SPL_AST_EXPR_CAST: {
|
||||
spl_lang_type_id_t src = sema_infer(sema, n->cast.expr);
|
||||
spl_lang_type_id_t dst = sema_infer(sema, n->cast.type);
|
||||
if (!src || !dst)
|
||||
if (!dst)
|
||||
return 0;
|
||||
spl_lang_type_id_t src = sema_infer(sema, n->cast.expr);
|
||||
if (!src)
|
||||
return 0;
|
||||
|
||||
/* 仅当 src 是 comptime 时收紧到 dst;具体类型间的 as 直接放行(截断/扩展由 ast2ir 生成) */
|
||||
spl_lang_type_node_t *sn = spl_lang_type_node(sema->type, src);
|
||||
spl_type_node_t *sir = sn ? spl_type_node(sema->type, sn->ir_type_id) : NULL;
|
||||
bool src_comptime =
|
||||
(sn && sn->kind == SPL_LANG_TYPE_INT && sir && sir->int_type.bits == 0) ||
|
||||
(sn && sn->kind == SPL_LANG_TYPE_FLOAT && sir && sir->float_type.bits == 0);
|
||||
if (src_comptime) {
|
||||
if (!sema_coerce(sema, n->cast.expr, dst))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sn && !(sn->kind == SPL_LANG_TYPE_INT || sn->kind == SPL_LANG_TYPE_FLOAT ||
|
||||
sn->kind == SPL_LANG_TYPE_BOOL || sn->kind == SPL_LANG_TYPE_PTR)) {
|
||||
SPL_ERROR(&n->dbg, "invalid cast from non-primitive type");
|
||||
sema->error_count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
n->resolved_lang_tid = dst;
|
||||
return dst;
|
||||
}
|
||||
@@ -1296,10 +1400,11 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
spl_lang_type_id_t et = sema_infer(sema, vec_at(n->array_literal.elems, i));
|
||||
if (!et)
|
||||
return 0;
|
||||
if (elem_t == 0)
|
||||
if (elem_t == 0) {
|
||||
elem_t = et;
|
||||
else {
|
||||
spl_lang_type_id_t c = spl_lang_type_balance(sema->type, elem_t, et);
|
||||
} else {
|
||||
spl_lang_type_id_t c =
|
||||
(elem_t == et) ? elem_t : spl_lang_type_join(sema->type, elem_t, et);
|
||||
if (c)
|
||||
elem_t = c;
|
||||
}
|
||||
@@ -1365,7 +1470,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
usize field_tid_ir = vec_at(irn->agg_type.variants, idx).type_id;
|
||||
spl_lang_type_id_t ft = sema_lang_from_ir(sema, field_tid_ir);
|
||||
if (ft && item->struct_init_item.expr)
|
||||
sema_check(sema, item->struct_init_item.expr, ft);
|
||||
sema_coerce(sema, item->struct_init_item.expr, ft);
|
||||
}
|
||||
}
|
||||
n->resolved_lang_tid = agg;
|
||||
@@ -1399,7 +1504,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
/* ---------- IF ---------- */
|
||||
case SPL_AST_EXPR_IF: {
|
||||
spl_lang_type_id_t bt = spl_lang_make_bool(sema->type);
|
||||
sema_check(sema, n->if_expr.cond, bt);
|
||||
sema_coerce(sema, n->if_expr.cond, bt);
|
||||
|
||||
spl_lang_type_id_t then_t =
|
||||
n->if_expr.then_block ? sema_infer(sema, n->if_expr.then_block) : 0;
|
||||
@@ -1407,7 +1512,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
n->if_expr.else_branch ? sema_infer(sema, n->if_expr.else_branch) : 0;
|
||||
spl_lang_type_id_t result = 0;
|
||||
if (then_t && else_t)
|
||||
result = spl_lang_type_balance(sema->type, then_t, else_t);
|
||||
result = (then_t == else_t) ? then_t : spl_lang_type_join(sema->type, then_t, else_t);
|
||||
else
|
||||
result = then_t ? then_t : else_t;
|
||||
n->resolved_lang_tid = result;
|
||||
@@ -1433,7 +1538,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
vec_push(sema->label_stack, lbl);
|
||||
|
||||
spl_lang_type_id_t bt = spl_lang_make_bool(sema->type);
|
||||
sema_check(sema, n->while_expr.cond, bt);
|
||||
sema_coerce(sema, n->while_expr.cond, bt);
|
||||
if (n->while_expr.body)
|
||||
sema_infer(sema, n->while_expr.body);
|
||||
if (n->while_expr.else_branch)
|
||||
@@ -1722,7 +1827,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
}
|
||||
|
||||
if (decl_tid) {
|
||||
sema_check(sema, n->var_const_decl.init_expr, decl_tid);
|
||||
sema_coerce(sema, n->var_const_decl.init_expr, decl_tid);
|
||||
} else {
|
||||
decl_tid = sema_infer(sema, n->var_const_decl.init_expr);
|
||||
if (!decl_tid || sema_is_infer(sema, decl_tid)) {
|
||||
@@ -1753,7 +1858,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
case SPL_AST_STATEMENT_RET: {
|
||||
if (n->statement_ret.expr) {
|
||||
if (sema->current_fn_ret_tid)
|
||||
sema_check(sema, n->statement_ret.expr, sema->current_fn_ret_tid);
|
||||
sema_coerce(sema, n->statement_ret.expr, sema->current_fn_ret_tid);
|
||||
else
|
||||
sema_infer(sema, n->statement_ret.expr);
|
||||
} else if (sema->current_fn_ret_tid) {
|
||||
|
||||
Reference in new issue
Block a user