stage1 支持指针运算 提供新的类型检查计算

This commit is contained in:
zzy committed 2026-09-15 19:11:01 +08:00
1 parent be41a82d55
commit 06f3884c30
12 files changed
+546 -295

No files matched your search

+6
View File
@@ -376,6 +376,12 @@ int main(int argc, char **argv) {
strcmp(mode_name, "sema") == 0 || strcmp(mode_name, "ir") == 0 || strcmp(mode_name, "sema") == 0 || strcmp(mode_name, "ir") == 0 ||
strcmp(mode_name, "vm") == 0) { strcmp(mode_name, "vm") == 0) {
tfn = test_once_with_dump; tfn = test_once_with_dump;
} else if (strcmp(mode_name, "run") == 0) {
// HACK
Nob_Cmd cmd = {0};
nob_cmd_append(&cmd, BUILD_FOLDER "spl_cli");
nob_cmd_append(&cmd, BUILD_FOLDER "test.sir");
return nob_cmd_run(&cmd) ? 0 : 1;
} else { } else {
da_append(&files, mode_name); da_append(&files, mode_name);
} }
+4
View File
@@ -167,6 +167,9 @@ SYSCALL_2(vm_strcmp, const char *, const char *, strcmp(a1, a2))
/* vm_memcpy - copy memory, returns dst */ /* vm_memcpy - copy memory, returns dst */
SYSCALL_3(vm_memcpy, void *, const void *, size_t, (memcpy(a1, a2, a3), (uintptr_t)a1)) SYSCALL_3(vm_memcpy, void *, const void *, size_t, (memcpy(a1, a2, a3), (uintptr_t)a1))
/* vm_memcmp - compare two memory */
SYSCALL_3(vm_memcmp, void *, const void *, size_t, (memcmp(a1, a2, a3), (uintptr_t)a1))
static spl_vm_val_t vm_printf(int nargs, spl_vm_val_t *args) { static spl_vm_val_t vm_printf(int nargs, spl_vm_val_t *args) {
if (nargs <= 0) if (nargs <= 0)
return 0; return 0;
@@ -387,6 +390,7 @@ void spl_syscall_register(spl_prog_t *prog) {
{"vm_strlen", 0, vm_strlen}, {"vm_strlen", 0, vm_strlen},
{"vm_strcmp", 0, vm_strcmp}, {"vm_strcmp", 0, vm_strcmp},
{"vm_memcpy", 0, vm_memcpy}, {"vm_memcpy", 0, vm_memcpy},
{"vm_memcmp", 0, vm_memcmp},
{"vm_printf", 0, vm_printf}, {"vm_printf", 0, vm_printf},
/* VM operations (comptime) */ /* VM operations (comptime) */
{"vm_new", 0, vm_new}, {"vm_new", 0, vm_new},
+6 -4
View File
@@ -50,6 +50,8 @@ const char *spl_unary_op_name(spl_unary_op_t op) {
return "bitnot"; return "bitnot";
case SPL_UNARY_OP_ADDRESS: case SPL_UNARY_OP_ADDRESS:
return "addr"; return "addr";
case SPL_UNARY_OP_DEREF:
return "deref";
default: default:
return "?"; return "?";
} }
@@ -840,7 +842,7 @@ static spl_ast_node_ref_t parse_type_base(parser_t *p) {
} }
/* 内建类型和普通路径 */ /* 内建类型和普通路径 */
if (bt->type == TOK_IDENT) { if (bt->type == TOK_IDENT || bt->type == KW_BOOL) {
const char *name = bt->lexeme; const char *name = bt->lexeme;
usize len = bt->len; usize len = bt->len;
/* 内建类型关键字 */ /* 内建类型关键字 */
@@ -1353,7 +1355,7 @@ static spl_ast_node_ref_t parse_postfix(parser_t *p) {
expr = ref; expr = ref;
} else if (next->type == TOK_MUL) { } else if (next->type == TOK_MUL) {
advance(p); advance(p);
spl_ast_node_ref_t ref = mk_unary(p, t, SPL_UNARY_OP_ADDRESS, expr); spl_ast_node_ref_t ref = mk_unary(p, t, SPL_UNARY_OP_DEREF, expr);
expr = ref; expr = ref;
} else { } else {
SPL_FATAL(next, "expected identifier or '*' after '.'"); SPL_FATAL(next, "expected identifier or '*' after '.'");
@@ -1416,13 +1418,13 @@ static spl_ast_node_ref_t parse_primary(parser_t *p) {
case TOK_INT_LITERAL: { case TOK_INT_LITERAL: {
advance(p); advance(p);
spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_INT_LIT, t); spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_INT_LIT, t);
node_at(p->ast, ref)->int_lit.val = parse_int_literal(t); node_at(p->ast, ref)->int_lit.bits = parse_int_literal(t); // FIXME
return ref; return ref;
} }
case TOK_FLOAT_LITERAL: { case TOK_FLOAT_LITERAL: {
advance(p); advance(p);
spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_FLOAT_LIT, t); spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_FLOAT_LIT, t);
node_at(p->ast, ref)->float_lit.val = parse_float_literal(t); node_at(p->ast, ref)->float_lit.bits = parse_float_literal(t); // FIXME
return ref; return ref;
} }
case TOK_CHAR_LITERAL: { case TOK_CHAR_LITERAL: {
+5 -8
View File
@@ -2,12 +2,12 @@
#define __SPL_AST_H__ #define __SPL_AST_H__
#include "../stage0/include/utils.h" #include "../stage0/include/utils.h"
#include "spl_attr.h"
#include "spl_dbg.h" #include "spl_dbg.h"
#include "spl_lexer.h" #include "spl_lexer.h"
#include "spl_mpa.h"
#include "spl_tok.h" #include "spl_tok.h"
#include "spl_attr.h"
/* clang-format off */ /* clang-format off */
#define SPL_AST_KIND_TABLE \ #define SPL_AST_KIND_TABLE \
X(SPL_AST_NONE, V0, none) \ X(SPL_AST_NONE, V0, none) \
@@ -139,6 +139,7 @@ typedef enum {
SPL_UNARY_OP_NOT, SPL_UNARY_OP_NOT,
SPL_UNARY_OP_BIT_NOT, SPL_UNARY_OP_BIT_NOT,
SPL_UNARY_OP_ADDRESS, SPL_UNARY_OP_ADDRESS,
SPL_UNARY_OP_DEREF,
} spl_unary_op_t; } spl_unary_op_t;
const char *spl_binary_op_name(spl_binary_op_t op); const char *spl_binary_op_name(spl_binary_op_t op);
@@ -291,12 +292,8 @@ struct spl_ast_node {
} label; } label;
/* ---- 表达式子类型 ---- */ /* ---- 表达式子类型 ---- */
struct { spl_mpa_int_t int_lit;
isize val; spl_mpa_float_t float_lit;
} int_lit;
struct {
double val;
} float_lit;
struct { struct {
char val; char val;
} char_lit; } char_lit;
+45 -10
View File
@@ -239,6 +239,12 @@ static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
return 0; return 0;
return slot; return slot;
} }
case SPL_AST_EXPR_UNARY: {
if (n->unary.op != SPL_UNARY_OP_DEREF)
return 0;
/* *p 作为左值,地址就是指针 p 的值 */
return emit_expr(a, n->unary.operand);
}
case SPL_AST_EXPR_FIELD: { case SPL_AST_EXPR_FIELD: {
spl_ast_node_t *obj = spl_ast_node(a->sema->ast, n->field.obj); spl_ast_node_t *obj = spl_ast_node(a->sema->ast, n->field.obj);
if (!obj) if (!obj)
@@ -298,7 +304,7 @@ static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
spl_ast_node_t *idx_node = spl_ast_node(a->sema->ast, n->index.index); spl_ast_node_t *idx_node = spl_ast_node(a->sema->ast, n->index.index);
if (!idx_node || idx_node->kind != SPL_AST_EXPR_INT_LIT) if (!idx_node || idx_node->kind != SPL_AST_EXPR_INT_LIT)
return 0; return 0;
usize i = (usize)idx_node->int_lit.val; usize i = (usize)idx_node->int_lit.bits;
spl_ir_node_ref_t base = emit_lvalue(a, n->index.obj); spl_ir_node_ref_t base = emit_lvalue(a, n->index.obj);
if (!base) if (!base)
return 0; return 0;
@@ -415,10 +421,19 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
return 0; return 0;
switch (n->kind) { switch (n->kind) {
case SPL_AST_EXPR_INT_LIT: case SPL_AST_EXPR_INT_LIT: {
return spl_ir_builder_type_const_int(a->ir, node_ir(a, n), (usize)n->int_lit.val); /* 节点经 coerce 后 resolved 可能是具体 int 或 float。
* 值始终存在 int_lit.bits(补码);按 resolved 决定如何构造 IR 常量。 */
spl_type_id_t it = node_ir(a, n);
spl_type_node_t *itn = spl_type_node(a->sema->type, it);
if (itn && itn->kind == SPL_TYPE_FLOAT) {
double d = (double)(int64_t)n->int_lit.bits;
return spl_ir_builder_type_const_float(a->ir, it, d);
}
return spl_ir_builder_type_const_int(a->ir, it, (usize)n->int_lit.bits);
}
case SPL_AST_EXPR_FLOAT_LIT: case SPL_AST_EXPR_FLOAT_LIT:
return spl_ir_builder_type_const_float(a->ir, node_ir(a, n), n->float_lit.val); return spl_ir_builder_type_const_float(a->ir, node_ir(a, n), n->float_lit.bits);
case SPL_AST_EXPR_CHAR_LIT: case SPL_AST_EXPR_CHAR_LIT:
return spl_ir_builder_type_const_char(a->ir, node_ir(a, n), n->char_lit.val); return spl_ir_builder_type_const_char(a->ir, node_ir(a, n), n->char_lit.val);
case SPL_AST_EXPR_STRING_LIT: { case SPL_AST_EXPR_STRING_LIT: {
@@ -464,6 +479,12 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
case SPL_AST_EXPR_UNARY: { case SPL_AST_EXPR_UNARY: {
if (n->unary.op == SPL_UNARY_OP_ADDRESS) if (n->unary.op == SPL_UNARY_OP_ADDRESS)
return emit_lvalue(a, n->unary.operand); return emit_lvalue(a, n->unary.operand);
if (n->unary.op == SPL_UNARY_OP_DEREF) {
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);
}
spl_ir_node_ref_t v = emit_expr(a, n->unary.operand); spl_ir_node_ref_t v = emit_expr(a, n->unary.operand);
if (!v) if (!v)
return 0; return 0;
@@ -584,17 +605,31 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
case SPL_OP_RSHIFT: case SPL_OP_RSHIFT:
return spl_ir_builder_arith_shr(a->ir, t, l, r); return spl_ir_builder_arith_shr(a->ir, t, l, r);
case SPL_OP_CMP_EQ: case SPL_OP_CMP_EQ:
return spl_ir_builder_cmp_eq(a->ir, t, l, r);
case SPL_OP_CMP_NE: case SPL_OP_CMP_NE:
return spl_ir_builder_cmp_ne(a->ir, t, l, r);
case SPL_OP_CMP_LT: case SPL_OP_CMP_LT:
return spl_ir_builder_cmp_lt(a->ir, t, l, r);
case SPL_OP_CMP_LE: case SPL_OP_CMP_LE:
return spl_ir_builder_cmp_le(a->ir, t, l, r);
case SPL_OP_CMP_GT: case SPL_OP_CMP_GT:
return spl_ir_builder_cmp_gt(a->ir, t, l, r); case SPL_OP_CMP_GE: {
/* 比较的操作数类型从左侧子节点读(sema 已 coerce 到共同类型) */
spl_ast_node_t *cmln = spl_ast_node(a->sema->ast, n->binary.left);
spl_type_id_t op_tid = cmln ? node_ir(a, cmln) : 0;
switch (op) {
case SPL_OP_CMP_EQ:
return spl_ir_builder_cmp_eq(a->ir, op_tid, l, r);
case SPL_OP_CMP_NE:
return spl_ir_builder_cmp_ne(a->ir, op_tid, l, r);
case SPL_OP_CMP_LT:
return spl_ir_builder_cmp_lt(a->ir, op_tid, l, r);
case SPL_OP_CMP_LE:
return spl_ir_builder_cmp_le(a->ir, op_tid, l, r);
case SPL_OP_CMP_GT:
return spl_ir_builder_cmp_gt(a->ir, op_tid, l, r);
case SPL_OP_CMP_GE: case SPL_OP_CMP_GE:
return spl_ir_builder_cmp_ge(a->ir, t, l, r); return spl_ir_builder_cmp_ge(a->ir, op_tid, l, r);
default:
return 0;
}
}
default: default:
return 0; return 0;
} }
+1
View File
@@ -2,6 +2,7 @@
#define __SPL_ATTR_H__ #define __SPL_ATTR_H__
#include "../stage0/include/utils.h" #include "../stage0/include/utils.h"
#include "spl_mpa.h"
typedef enum { typedef enum {
SPL_ATTR_STAGE_SEMA, SPL_ATTR_STAGE_SEMA,
+3 -2
View File
@@ -333,7 +333,8 @@ spl_tok_vec_t spl_lex(const char *source, const char *fname) {
continue; continue;
} }
emit_int: { emit_int:
{
spl_tok_t tok; spl_tok_t tok;
memset(&tok, 0, sizeof(tok)); memset(&tok, 0, sizeof(tok));
tok.type = TOK_INT_LITERAL; tok.type = TOK_INT_LITERAL;
@@ -411,7 +412,7 @@ spl_tok_vec_t spl_lex(const char *source, const char *fname) {
/* Three-char operators first */ /* Three-char operators first */
TRY_OP3('<', '-', '>', TOK_ARROW_BOTH, TOK_RIGHT_ARROW, TOK_LT) TRY_OP3('<', '-', '>', TOK_ARROW_BOTH, TOK_RIGHT_ARROW, TOK_LT)
TRY_OP3('<', '=', '>', TOK_FAT_ARROW_BOTH, TOK_RIGHT_FAT_ARROW, TOK_LT) TRY_OP3('<', '=', '>', TOK_FAT_ARROW_BOTH, TOK_LE, TOK_LT)
TRY_OP3('<', '<', '=', TOK_ASSIGN_L_SH, TOK_L_SH, TOK_LT) TRY_OP3('<', '<', '=', TOK_ASSIGN_L_SH, TOK_L_SH, TOK_LT)
TRY_OP3('>', '>', '=', TOK_ASSIGN_R_SH, TOK_R_SH, TOK_GT) TRY_OP3('>', '>', '=', TOK_ASSIGN_R_SH, TOK_R_SH, TOK_GT)
TRY_OP3('.', '.', '.', TOK_ELLIPSIS, TOK_RANGE, TOK_DOT) TRY_OP3('.', '.', '.', TOK_ELLIPSIS, TOK_RANGE, TOK_DOT)
+14
View File
@@ -0,0 +1,14 @@
#ifndef __SPL_MPA_H__
#define __SPL_MPA_H__
#include <stdint.h>
typedef struct {
uint64_t bits;
} spl_mpa_int_t;
typedef struct {
double bits;
} spl_mpa_float_t;
#endif /* __SPL_MPA_H__ */
+282 -177
View File
@@ -117,7 +117,7 @@ static void sema_resolve_attrs(spl_sema_t *sema, spl_ast_node_ref_vec_t *raw,
break; break;
case SPL_AST_EXPR_INT_LIT: case SPL_AST_EXPR_INT_LIT:
oa.kind = SPL_ATTR_ARG_INT; oa.kind = SPL_ATTR_ARG_INT;
oa.value.i = arg->int_lit.val; oa.value.i = arg->int_lit.bits;
break; break;
default: default:
SPL_ERROR(&a->dbg, "attribute arg #%zu has unsupported form", j); SPL_ERROR(&a->dbg, "attribute arg #%zu has unsupported form", j);
@@ -140,7 +140,7 @@ 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_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, static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
spl_lang_type_id_t expected); 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, 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); spl_ast_node_ref_vec_t *args);
@@ -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) { static inline void sema_push_scope(spl_sema_t *sema) {
spl_scope_id_t new_scope = spl_scope_alloc(sema->scope); spl_scope_id_t new_scope = spl_scope_alloc(sema->scope);
sema->store_scope = sema->scope->current_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: { case SPL_INTRIN_ASSERT: {
spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); 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) if (nargs == 2)
sema_infer(sema, vec_at(*args, 1)); sema_infer(sema, vec_at(*args, 1));
return spl_lang_make_unit(sema->type); return spl_lang_make_unit(sema->type);
@@ -532,7 +608,7 @@ static spl_lang_type_id_t sema_intrin_field(spl_sema_t *sema, spl_ast_node_t *n,
return 0; return 0;
} }
static spl_lang_type_id_t sema_check(spl_sema_t *sema, spl_ast_node_ref_t ref, static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
spl_lang_type_id_t expected) { spl_lang_type_id_t expected) {
if (!ref || !expected) if (!ref || !expected)
return 0; return 0;
@@ -540,43 +616,70 @@ static spl_lang_type_id_t sema_check(spl_sema_t *sema, spl_ast_node_ref_t ref,
if (!n) if (!n)
return 0; 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) { switch (n->kind) {
case SPL_AST_EXPR_UNARY: { case SPL_AST_EXPR_UNARY: {
if (n->unary.op == SPL_UNARY_OP_ADDRESS) /* & 与 .* 的结果类型由操作数决定,不能靠 expected 反向定型 */
return sema_infer(sema, ref); /* &x 没有"被 check 到某类型"的语义 */ if (n->unary.op == SPL_UNARY_OP_ADDRESS || n->unary.op == SPL_UNARY_OP_DEREF)
if (!sema_check(sema, n->unary.operand, expected)) return sema_infer(sema, ref);
if (!sema_coerce(sema, n->unary.operand, expected))
return 0; return 0;
n->resolved_lang_tid = expected; n->resolved_lang_tid = expected;
n->expected_lang_tid = 0;
return expected; return expected;
} }
case SPL_AST_EXPR_BINARY: { case SPL_AST_EXPR_BINARY: {
spl_binary_op_t op = n->binary.op; spl_binary_op_t op = n->binary.op;
/* 赋值 / 复合赋值:右侧 check 到左侧类型 */
if (op == SPL_OP_ASSIGN || (op >= SPL_OP_ASSIGN_ADD && op <= SPL_OP_ASSIGN_RSHIFT)) { 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); spl_lang_type_id_t lt = sema_infer(sema, n->binary.left);
if (!lt) if (!lt)
return 0; return 0;
if (!sema_check(sema, n->binary.right, lt)) if (!sema_coerce(sema, n->binary.right, lt))
return 0; return 0;
n->resolved_lang_tid = lt; n->resolved_lang_tid = lt;
n->expected_lang_tid = 0;
return lt; return lt;
} }
/* 逻辑运算:两侧 check 到 bool */
if (op == SPL_OP_BOOL_OR || op == SPL_OP_BOOL_AND) { if (op == SPL_OP_BOOL_OR || op == SPL_OP_BOOL_AND) {
spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); 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; return 0;
if (!sema_check(sema, n->binary.right, bt)) if (!sema_coerce(sema, n->binary.right, bt))
return 0; return 0;
n->resolved_lang_tid = bt; n->resolved_lang_tid = bt;
n->expected_lang_tid = 0;
return bt; 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); spl_lang_type_id_t rt = sema_infer(sema, n->binary.right);
if (!lt || !rt) if (!lt || !rt)
return 0; return 0;
spl_lang_type_id_t common = (lt == rt) ? lt : spl_lang_type_join(sema->type, lt, rt);
spl_lang_type_id_t common = 0;
if (lt == rt)
common = lt;
else
common = spl_lang_type_balance(sema->type, lt, rt);
if (!common) { 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++; sema->error_count++;
return 0; return 0;
} }
sema_coerce(sema, n->binary.left, common);
sema_check(sema, n->binary.left, common); sema_coerce(sema, n->binary.right, common);
sema_check(sema, n->binary.right, common); spl_lang_type_id_t b = spl_lang_make_bool(sema->type);
n->resolved_lang_tid = b;
n->resolved_lang_tid = common; return b;
return spl_lang_make_bool(sema->type);
} }
/* ptr +/- int:右侧 check 到整数,节点类型仍为指针 */ /* ptr +/- int:expected 是 ptr 且左侧推断为 ptr。
* 右侧保留原整型;仅 comptime_int(bits==0)收紧到 isize。 */
if (op == SPL_OP_ADD || op == SPL_OP_SUB) { if (op == SPL_OP_ADD || op == SPL_OP_SUB) {
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_id_t lt = sema_infer(sema, n->binary.left);
if (!lt) 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; return 0;
spl_lang_type_node_t *lln = spl_lang_type_node(sema->type, lt); }
if (lln && lln->kind == SPL_LANG_TYPE_PTR) { spl_type_node_t *rn_ir = spl_type_node(sema->type, rn->ir_type_id);
spl_lang_type_id_t it = spl_lang_make_int(sema->type, sizeof(void *) * 8, 1); if (rn_ir && rn_ir->int_type.bits == 0) {
if (!sema_check(sema, n->binary.right, it)) 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; return 0;
n->resolved_lang_tid = lt; }
n->expected_lang_tid = expected; n->resolved_lang_tid = expected;
return expected; return expected;
} }
} }
}
/* 算术 / 位 / 移位:两侧 check 到 expected */ if (!sema_coerce(sema, n->binary.left, expected))
if (!sema_check(sema, n->binary.left, expected))
return 0; return 0;
if (!sema_check(sema, n->binary.right, expected)) if (!sema_coerce(sema, n->binary.right, expected))
return 0; return 0;
n->resolved_lang_tid = expected; n->resolved_lang_tid = expected;
n->expected_lang_tid = 0;
return expected; 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) { if (en && en->kind == SPL_LANG_TYPE_ARRAY) {
spl_lang_type_id_t et = en->extra.elem; spl_lang_type_id_t et = en->extra.elem;
for (usize i = 0; i < vec_size(n->array_literal.elems); ++i) 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; return 0;
n->resolved_lang_tid = expected; n->resolved_lang_tid = expected;
n->expected_lang_tid = 0;
return expected; return expected;
} }
break; /* 非数组 expected:退回通用逻辑 */ break;
} }
case SPL_AST_EXPR_TUPLE: { 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) { for (usize i = 0; i < nelems; ++i) {
spl_lang_type_id_t et = vec_at(en->extra.elems, 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; return 0;
} }
n->resolved_lang_tid = expected; n->resolved_lang_tid = expected;
n->expected_lang_tid = 0;
return expected; return expected;
} }
break; 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)) en->kind != SPL_LANG_TYPE_ENUM))
break; break;
/* 有名字时,名字必须与 expected 指向同一类型 */
if (n->aggregate_literal.name) { if (n->aggregate_literal.name) {
spl_symbol_t sym; spl_symbol_t sym;
if (!spl_scope_find(sema->scope, n->aggregate_literal.name, &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_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); 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; return 0;
}
if (en->kind == SPL_LANG_TYPE_ENUM) { if (en->kind == SPL_LANG_TYPE_ENUM) {
if (vec_size(n->aggregate_literal.fields) != 1) { 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++; sema->error_count++;
return 0; return 0;
} }
spl_type_member_t *m = &vec_at(irn->agg_type.variants, idx); usize field_tid_ir = vec_at(irn->agg_type.variants, idx).type_id;
spl_lang_type_id_t ft = sema_lang_from_ir(sema, m->type_id); spl_lang_type_id_t ft = sema_lang_from_ir(sema, field_tid_ir);
if (!ft) if (ft && item->struct_init_item.expr) {
return 0; if (!sema_coerce(sema, item->struct_init_item.expr, ft))
if (!item->struct_init_item.expr) {
SPL_ERROR(&item->dbg, "variant `%s` requires initializer",
item->struct_init_item.name);
sema->error_count++;
return 0; return 0;
} }
sema_check(sema, item->struct_init_item.expr, ft);
n->resolved_lang_tid = expected; n->resolved_lang_tid = expected;
n->expected_lang_tid = 0;
return expected; 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) { 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)); 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) 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++; sema->error_count++;
continue; 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; 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); spl_lang_type_id_t ft = sema_lang_from_ir(sema, field_tid_ir);
if (!ft) if (ft && item->struct_init_item.expr) {
continue; if (!sema_coerce(sema, item->struct_init_item.expr, ft))
if (!item->struct_init_item.expr) { return 0;
SPL_ERROR(&item->dbg, "field `%s` requires initializer",
item->struct_init_item.name);
sema->error_count++;
continue;
} }
sema_check(sema, item->struct_init_item.expr, ft);
} }
free(seen);
n->resolved_lang_tid = expected; n->resolved_lang_tid = expected;
n->expected_lang_tid = 0;
return expected; return expected;
} }
case SPL_AST_EXPR_IF: { case SPL_AST_EXPR_IF: {
spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); 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) 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) 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->resolved_lang_tid = expected;
n->expected_lang_tid = 0;
return expected; 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) for (usize i = 0; i < vec_size(n->block.stmts); ++i)
sema_infer(sema, vec_at(n->block.stmts, i)); sema_infer(sema, vec_at(n->block.stmts, i));
if (n->block.tail_expr) { 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) if (!t)
return 0; return 0;
n->resolved_lang_tid = t; n->resolved_lang_tid = t;
n->expected_lang_tid = 0;
return t; return t;
} }
spl_lang_type_id_t u = spl_lang_make_unit(sema->type); spl_lang_type_id_t u = spl_lang_make_unit(sema->type);
n->resolved_lang_tid = u; n->resolved_lang_tid = u;
n->expected_lang_tid = 0;
return u; 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; break;
} }
/* ============ 类 2:字面量 —— 就地定型 ============ */ /* 兜底:infer 后按子类型 / comptime 判定 */
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;
}
/* ============ 类 3:引用性节点 —— 只记 expected ============ */
{
spl_lang_type_id_t from = sema_infer(sema, ref); spl_lang_type_id_t from = sema_infer(sema, ref);
if (!from) if (!from)
return 0; return 0;
if (from == expected) { if (from == expected)
n->expected_lang_tid = 0;
return expected; return expected;
}
spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, expected, from); spl_lang_type_node_t *from_n = spl_lang_type_node(sema->type, from);
if (!r) { spl_lang_type_node_t *to_n = spl_lang_type_node(sema->type, expected);
SPL_ERROR(&n->dbg, "type mismatch: cannot coerce to expected type"); 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++; sema->error_count++;
return 0; return 0;
} }
n->expected_lang_tid = expected; /* 只记,不改 natural */ n->resolved_lang_tid = expected;
return 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) { 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: { 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; n->resolved_lang_tid = t;
return t; return t;
} }
case SPL_AST_EXPR_FLOAT_LIT: { 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; n->resolved_lang_tid = t;
return 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; return op;
case SPL_UNARY_OP_NOT: { case SPL_UNARY_OP_NOT: {
spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); 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; n->resolved_lang_tid = bt;
return 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; n->resolved_lang_tid = p;
return 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: default:
UNREACHABLE(); 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); spl_lang_type_id_t lt = sema_infer(sema, n->binary.left);
if (!lt) if (!lt)
return 0; return 0;
sema_check(sema, n->binary.right, lt); sema_coerce(sema, n->binary.right, lt);
n->resolved_lang_tid = lt; n->resolved_lang_tid = lt;
return 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) { if (op == SPL_OP_BOOL_OR || op == SPL_OP_BOOL_AND) {
spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); spl_lang_type_id_t bt = spl_lang_make_bool(sema->type);
sema_check(sema, n->binary.left, bt); sema_coerce(sema, n->binary.left, bt);
sema_check(sema, n->binary.right, bt); sema_coerce(sema, n->binary.right, bt);
n->resolved_lang_tid = bt; n->resolved_lang_tid = bt;
return 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) if (!lt || !rt)
return 0; return 0;
spl_lang_type_id_t common = 0; spl_lang_type_id_t common = (lt == rt) ? lt : spl_lang_type_join(sema->type, lt, rt);
if (lt == rt)
common = lt;
else
common = spl_lang_type_balance(sema->type, lt, rt);
if (!common) { 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++; sema->error_count++;
return 0; return 0;
} }
sema_check(sema, n->binary.left, common); sema_coerce(sema, n->binary.left, common);
sema_check(sema, n->binary.right, common); sema_coerce(sema, n->binary.right, common);
n->resolved_lang_tid = common; spl_lang_type_id_t b = spl_lang_make_bool(sema->type);
return spl_lang_make_bool(sema->type); n->resolved_lang_tid = b;
return b;
} }
/* Range */ /* 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; return lt;
} }
/* 算术 / 位运算 */
spl_lang_type_id_t lt = sema_infer(sema, n->binary.left); spl_lang_type_id_t lt = sema_infer(sema, n->binary.left);
spl_lang_type_id_t rt = sema_infer(sema, n->binary.right); spl_lang_type_id_t rt = sema_infer(sema, n->binary.right);
if (!lt || !rt) if (!lt || !rt)
return 0; return 0;
spl_lang_type_id_t common = 0;
if (lt == rt)
common = lt;
else
common = spl_lang_type_balance(sema->type, lt, rt);
/* balance 失败:comptime + 具体时取具体 */
if (!common) {
spl_lang_type_node_t *ln = spl_lang_type_node(sema->type, lt); 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); 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); /* ptr +/- int 特判:右侧保留自己的整型;
spl_type_node_t *rir = spl_type_node(sema->type, rn->ir_type_id); * 仅当右操作数是 comptime_int(bits==0)时收紧到 isize,
if (lir && lir->int_type.bits == 0) * 避免 comptime 类型泄漏到 IR。 */
common = rt; if (ln && ln->kind == SPL_LANG_TYPE_PTR && rn && rn->kind == SPL_LANG_TYPE_INT &&
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 特判 */
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)) { (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; n->resolved_lang_tid = lt;
n->expected_lang_tid = 0;
return lt; return lt;
} }
spl_lang_type_id_t common = (lt == rt) ? lt : spl_lang_type_join(sema->type, lt, rt);
if (!common) {
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; n->resolved_lang_tid = common;
return 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) { for (usize i = 0; i < nargs && i < fixed; ++i) {
spl_lang_type_id_t pt = spl_lang_type_id_t pt =
vec_at(spl_lang_type_node(sema->type, callee_tid)->extra.fn.params, i); 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 */ /* varargs:默认提升到 isize */
if (has_varargs) { if (has_varargs) {
spl_lang_type_id_t vt = spl_lang_make_int(sema->type, sizeof(void *) * 8, 1); spl_lang_type_id_t vt = spl_lang_make_int(sema->type, sizeof(void *) * 8, 1);
for (usize i = fixed; i < nargs; ++i) 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; 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++; sema->error_count++;
return 0; 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)) { if (i < 0 || (usize)i >= vec_size(obj->extra.elems)) {
SPL_ERROR(&n->dbg, "tuple index out of range"); SPL_ERROR(&n->dbg, "tuple index out of range");
sema->error_count++; 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 ---------- */ /* ---------- CAST ---------- */
case SPL_AST_EXPR_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); spl_lang_type_id_t dst = sema_infer(sema, n->cast.type);
if (!src || !dst) if (!dst)
return 0; 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_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 || 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)) { sn->kind == SPL_LANG_TYPE_BOOL || sn->kind == SPL_LANG_TYPE_PTR)) {
SPL_ERROR(&n->dbg, "invalid cast from non-primitive type"); SPL_ERROR(&n->dbg, "invalid cast from non-primitive type");
sema->error_count++; sema->error_count++;
return 0; return 0;
} }
n->resolved_lang_tid = dst; n->resolved_lang_tid = dst;
return 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)); spl_lang_type_id_t et = sema_infer(sema, vec_at(n->array_literal.elems, i));
if (!et) if (!et)
return 0; return 0;
if (elem_t == 0) if (elem_t == 0) {
elem_t = et; elem_t = et;
else { } else {
spl_lang_type_id_t c = spl_lang_type_balance(sema->type, elem_t, et); spl_lang_type_id_t c =
(elem_t == et) ? elem_t : spl_lang_type_join(sema->type, elem_t, et);
if (c) if (c)
elem_t = 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; 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); spl_lang_type_id_t ft = sema_lang_from_ir(sema, field_tid_ir);
if (ft && item->struct_init_item.expr) 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; 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 ---------- */ /* ---------- IF ---------- */
case SPL_AST_EXPR_IF: { case SPL_AST_EXPR_IF: {
spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); 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 = spl_lang_type_id_t then_t =
n->if_expr.then_block ? sema_infer(sema, n->if_expr.then_block) : 0; 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; n->if_expr.else_branch ? sema_infer(sema, n->if_expr.else_branch) : 0;
spl_lang_type_id_t result = 0; spl_lang_type_id_t result = 0;
if (then_t && else_t) 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 else
result = then_t ? then_t : else_t; result = then_t ? then_t : else_t;
n->resolved_lang_tid = result; 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); vec_push(sema->label_stack, lbl);
spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); 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) if (n->while_expr.body)
sema_infer(sema, n->while_expr.body); sema_infer(sema, n->while_expr.body);
if (n->while_expr.else_branch) 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) { 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 { } else {
decl_tid = sema_infer(sema, n->var_const_decl.init_expr); decl_tid = sema_infer(sema, n->var_const_decl.init_expr);
if (!decl_tid || sema_is_infer(sema, decl_tid)) { 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: { case SPL_AST_STATEMENT_RET: {
if (n->statement_ret.expr) { if (n->statement_ret.expr) {
if (sema->current_fn_ret_tid) 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 else
sema_infer(sema, n->statement_ret.expr); sema_infer(sema, n->statement_ret.expr);
} else if (sema->current_fn_ret_tid) { } else if (sema->current_fn_ret_tid) {
+1
View File
@@ -2,6 +2,7 @@
#define __SPL_SEMA_H__ #define __SPL_SEMA_H__
#include "spl_ast.h" #include "spl_ast.h"
#include "spl_mpa.h"
#include "spl_type.h" #include "spl_type.h"
#include "spl_attr.h" #include "spl_attr.h"
+175 -78
View File
@@ -380,122 +380,219 @@ bool spl_lang_type_is_subtype(const spl_type_t *type, spl_lang_type_id_t sub,
if (!nsub || !nsuper) if (!nsub || !nsuper)
return false; return false;
// 语言级特殊类型
if (nsub->kind == SPL_LANG_TYPE_NEVER) if (nsub->kind == SPL_LANG_TYPE_NEVER)
return true; return true;
if (nsuper->kind == SPL_LANG_TYPE_ANY) if (nsuper->kind == SPL_LANG_TYPE_ANY)
return true; return true;
if (nsub->kind == SPL_LANG_TYPE_INFER || nsuper->kind == SPL_LANG_TYPE_INFER) {
// 推断类型暂不处理子类型关系 if (nsub->kind == SPL_LANG_TYPE_INT && nsuper->kind == SPL_LANG_TYPE_INT) {
spl_type_node_t *ir_sub = spl_type_node(type, nsub->ir_type_id);
spl_type_node_t *ir_super = spl_type_node(type, nsuper->ir_type_id);
if (!ir_sub || !ir_super)
return false;
uint32_t sb = (uint32_t)ir_sub->int_type.bits;
uint32_t pb = (uint32_t)ir_super->int_type.bits;
/* comptime_int (bits==0) 是整数格的 top */
if (pb == 0)
return true; /* 任何具体整数 <: comptime_int */
if (sb == 0)
return false; /* comptime_int 不能隐式收窄到具体整数 */
bool ss = ir_sub->int_type.is_signed != 0;
bool ps = ir_super->int_type.is_signed != 0;
if (ss == ps)
return sb <= pb;
if (!ss && ps)
return sb < pb;
return false; return false;
} }
if (nsub->kind == SPL_LANG_TYPE_FLOAT && nsuper->kind == SPL_LANG_TYPE_FLOAT) {
spl_type_node_t *ir_sub = spl_type_node(type, nsub->ir_type_id);
spl_type_node_t *ir_super = spl_type_node(type, nsuper->ir_type_id);
if (!ir_sub || !ir_super)
return false;
uint32_t sb = (uint32_t)ir_sub->float_type.bits;
uint32_t pb = (uint32_t)ir_super->float_type.bits;
if (pb == 0)
return true;
if (sb == 0)
return false;
return sb <= pb;
}
if (nsub->kind == SPL_LANG_TYPE_PTR && nsuper->kind == SPL_LANG_TYPE_PTR) { if (nsub->kind == SPL_LANG_TYPE_PTR && nsuper->kind == SPL_LANG_TYPE_PTR) {
spl_lang_type_node_t *sub_elem = spl_lang_type_node(type, nsub->extra.elem); spl_lang_type_node_t *sub_elem = spl_lang_type_node(type, nsub->extra.elem);
spl_lang_type_node_t *super_elem = spl_lang_type_node(type, nsuper->extra.elem); spl_lang_type_node_t *super_elem = spl_lang_type_node(type, nsuper->extra.elem);
if (sub_elem && sub_elem->kind == SPL_LANG_TYPE_NEVER) if (sub_elem && sub_elem->kind == SPL_LANG_TYPE_NEVER)
return true; /* *never <: *T */ return true;
if (super_elem && super_elem->kind == SPL_LANG_TYPE_ANY) if (super_elem && super_elem->kind == SPL_LANG_TYPE_ANY)
return true; /* *T <: *any */ return true;
if (nsub->extra.elem == nsuper->extra.elem) if (nsub->extra.elem == nsuper->extra.elem)
return true; /* *T <: *T */ return true;
return false; return false;
} }
// 对于简单类型,委托给底层类型判断 if (nsub->kind == nsuper->kind)
// 如果语言级 kind 相同且底层类型可子类型,则成立
if (nsub->kind == nsuper->kind) {
return spl_type_is_subtype(type, nsub->ir_type_id, nsuper->ir_type_id); return spl_type_is_subtype(type, nsub->ir_type_id, nsuper->ir_type_id);
}
// 特殊情况:slice 可以看作 array 的超集?暂不处理
return false; return false;
} }
spl_lang_type_id_t spl_lang_type_coerce_to(spl_type_t *type, spl_lang_type_id_t to, static uint32_t spl_type_std_int_bits_up(uint32_t bits) {
spl_lang_type_id_t from) { if (bits <= 8)
if (to == 0 || from == 0) return 8;
if (bits <= 16)
return 16;
if (bits <= 32)
return 32;
if (bits <= 64)
return 64;
return 0; return 0;
if (to == from) }
return to;
spl_lang_type_node_t *to_node = spl_lang_type_node(type, to); spl_lang_type_id_t spl_lang_type_join(const spl_type_t *type, spl_lang_type_id_t a,
if (!to_node) spl_lang_type_id_t b) {
if (a == 0 || b == 0)
return 0;
if (a == b)
return a;
spl_lang_type_node_t *na = spl_lang_type_node(type, a);
spl_lang_type_node_t *nb = spl_lang_type_node(type, b);
if (!na || !nb)
return 0; return 0;
if (to_node->kind == SPL_LANG_TYPE_INFER) if (na->kind == SPL_LANG_TYPE_NEVER)
return from; return b;
if (nb->kind == SPL_LANG_TYPE_NEVER)
return a;
if (na->kind == SPL_LANG_TYPE_ANY || nb->kind == SPL_LANG_TYPE_ANY)
return spl_lang_make_any((spl_type_t *)type);
spl_lang_type_node_t *from_node = spl_lang_type_node(type, from); /* comptime 参与:返回另一侧的具体类型(comptime 是宽度未定,优先取具体) */
if (!from_node) bool a_int = na->kind == SPL_LANG_TYPE_INT;
bool b_int = nb->kind == SPL_LANG_TYPE_INT;
bool a_flt = na->kind == SPL_LANG_TYPE_FLOAT;
bool b_flt = nb->kind == SPL_LANG_TYPE_FLOAT;
if (a_int && b_int) {
spl_type_node_t *ira = spl_type_node(type, na->ir_type_id);
spl_type_node_t *irb = spl_type_node(type, nb->ir_type_id);
if (ira && irb) {
bool a_ct = ira->int_type.bits == 0;
bool b_ct = irb->int_type.bits == 0;
if (a_ct && b_ct)
return a; /* 都是 comptime_int */
if (a_ct)
return b;
if (b_ct)
return a;
}
}
if (a_flt && b_flt) {
spl_type_node_t *ira = spl_type_node(type, na->ir_type_id);
spl_type_node_t *irb = spl_type_node(type, nb->ir_type_id);
if (ira && irb) {
bool a_ct = ira->float_type.bits == 0;
bool b_ct = irb->float_type.bits == 0;
if (a_ct && b_ct)
return a;
if (a_ct)
return b;
if (b_ct)
return a;
}
}
/* int / float 混合:仅 comptime 混 comptime 视为 comptime_float */
if (a_int && b_flt) {
spl_type_node_t *ira = spl_type_node(type, na->ir_type_id);
spl_type_node_t *irb = spl_type_node(type, nb->ir_type_id);
if (ira && irb && ira->int_type.bits == 0 && irb->float_type.bits == 0)
return spl_lang_make_float((spl_type_t *)type, 0);
return 0;
}
if (a_flt && b_int) {
spl_type_node_t *ira = spl_type_node(type, na->ir_type_id);
spl_type_node_t *irb = spl_type_node(type, nb->ir_type_id);
if (ira && irb && ira->float_type.bits == 0 && irb->int_type.bits == 0)
return spl_lang_make_float((spl_type_t *)type, 0);
return 0;
}
/* 现在走子类型关系(两侧均为具体类型) */
if (spl_lang_type_is_subtype(type, a, b))
return b;
if (spl_lang_type_is_subtype(type, b, a))
return a;
if (na->kind != nb->kind)
return 0; return 0;
if (from_node->kind == SPL_LANG_TYPE_INT && to_node->kind == SPL_LANG_TYPE_INT) { if (a_int) {
spl_type_id_t from_ir = spl_lang_type_get_ir_type(type, from); spl_type_node_t *ira = spl_type_node(type, na->ir_type_id);
spl_type_node_t *from_ir_node = spl_type_node(type, from_ir); spl_type_node_t *irb = spl_type_node(type, nb->ir_type_id);
if (from_ir_node && from_ir_node->int_type.bits == 0) if (!ira || !irb)
return to; return 0;
uint32_t ba = (uint32_t)ira->int_type.bits;
uint32_t bb = (uint32_t)irb->int_type.bits;
bool sa = ira->int_type.is_signed != 0;
bool sb = irb->int_type.is_signed != 0;
if (sa == sb) {
uint32_t bits = ba > bb ? ba : bb;
return spl_lang_make_int((spl_type_t *)type, bits, sa);
}
uint32_t s_bits = sa ? ba : bb;
uint32_t u_bits = sa ? bb : ba;
uint32_t need = s_bits > (u_bits + 1) ? s_bits : (u_bits + 1);
uint32_t std_bits = spl_type_std_int_bits_up(need);
if (std_bits == 0)
return 0;
return spl_lang_make_int((spl_type_t *)type, std_bits, 1);
} }
if (from_node->kind == SPL_LANG_TYPE_FLOAT && to_node->kind == SPL_LANG_TYPE_FLOAT) { if (a_flt) {
spl_type_id_t from_ir = spl_lang_type_get_ir_type(type, from); spl_type_node_t *ira = spl_type_node(type, na->ir_type_id);
spl_type_node_t *from_ir_node = spl_type_node(type, from_ir); spl_type_node_t *irb = spl_type_node(type, nb->ir_type_id);
if (from_ir_node && from_ir_node->float_type.bits == 0) if (!ira || !irb)
return to; return 0;
uint32_t ba = (uint32_t)ira->float_type.bits;
uint32_t bb = (uint32_t)irb->float_type.bits;
uint32_t bits = ba > bb ? ba : bb;
return spl_lang_make_float((spl_type_t *)type, bits);
} }
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; return 0;
} }
spl_lang_type_id_t spl_lang_type_balance(spl_type_t *type, spl_lang_type_id_t t1, bool spl_lang_mpa_int_fits(const spl_type_t *type, spl_lang_type_id_t target, spl_mpa_int_t v) {
spl_lang_type_id_t t2) { spl_lang_type_node_t *nt = spl_lang_type_node(type, target);
if (t1 == 0 || t2 == 0) if (!nt || nt->kind != SPL_LANG_TYPE_INT)
return 0; return false;
if (t1 == t2) spl_type_node_t *ir = spl_type_node(type, nt->ir_type_id);
return t1; if (!ir)
return false;
uint32_t bits = (uint32_t)ir->int_type.bits;
if (bits == 0)
return true;
bool target_signed = ir->int_type.is_signed != 0;
spl_lang_type_node_t *n1 = spl_lang_type_node(type, t1); int64_t val = (int64_t)v.bits;
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) if (target_signed) {
return spl_lang_make_any(type); if (bits >= 64)
if (n1->kind == SPL_LANG_TYPE_NEVER) return true;
return t2; int64_t lo = -((int64_t)1 << (bits - 1));
if (n2->kind == SPL_LANG_TYPE_NEVER) int64_t hi = ((int64_t)1 << (bits - 1)) - 1;
return t1; return val >= lo && val <= hi;
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; if (val < 0)
return false;
uint64_t uval = (uint64_t)val;
if (bits >= 64)
return true;
uint64_t hi = ((uint64_t)1 << bits) - 1;
return uval <= hi;
} }
spl_def_id_t spl_def_alloc(spl_type_t *type, spl_def_node_kind_t kind, const char *name, spl_def_id_t spl_def_alloc(spl_type_t *type, spl_def_node_kind_t kind, const char *name,
+4 -16
View File
@@ -3,6 +3,7 @@
#include "../stage0/include/utils.h" #include "../stage0/include/utils.h"
#include "spl_dbg.h" #include "spl_dbg.h"
#include "spl_mpa.h"
typedef usize spl_type_id_t; /* 0 is error */ typedef usize spl_type_id_t; /* 0 is error */
typedef VEC(spl_type_id_t) spl_type_id_vec_t; typedef VEC(spl_type_id_t) spl_type_id_vec_t;
@@ -181,23 +182,10 @@ bool spl_lang_type_is_subtype(const spl_type_t *type, spl_lang_type_id_t sub,
bool spl_type_is_subtype(const spl_type_t *type, spl_type_id_t sub, spl_type_id_t super); bool spl_type_is_subtype(const spl_type_t *type, spl_type_id_t sub, spl_type_id_t super);
spl_lang_type_id_t spl_lang_node_push(spl_type_t *type, spl_lang_type_node_t *node); spl_lang_type_id_t spl_lang_node_push(spl_type_t *type, spl_lang_type_node_t *node);
/* 计算 from 是否可以隐式转换到 to。 spl_lang_type_id_t spl_lang_type_join(const spl_type_t *type, spl_lang_type_id_t a,
* - to 是 INFER 时视为"接受任意 from",返回 from。 spl_lang_type_id_t b);
* - 成功返回"转换后的类型"(正常是 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 分支、算术运算的对称平衡)。 bool spl_lang_mpa_int_fits(const spl_type_t *type, spl_lang_type_id_t target, spl_mpa_int_t v);
* - 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_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_dbg_node_t dbg, usize ast_node_ref);