feat: 新增 i32 / u64 / char 类型 + 字符字面量 "'a'"
This commit is contained in:
+38
-4
@@ -10,13 +10,38 @@ static TypeKind promote(TypeKind a, TypeKind b) {
|
||||
// 枚举在算术运算中视为 i64
|
||||
if (a == TYPE_ENUM) a = TYPE_I64;
|
||||
if (b == TYPE_ENUM) b = TYPE_I64;
|
||||
// char 在算术中提升为 i32
|
||||
if (a == TYPE_CHAR) a = TYPE_I32;
|
||||
if (b == TYPE_CHAR) b = TYPE_I32;
|
||||
if (a == TYPE_F64 || b == TYPE_F64) return TYPE_F64;
|
||||
if (a == TYPE_I64 || b == TYPE_I64) return TYPE_I64;
|
||||
if (a == TYPE_U64 || b == TYPE_U64) return TYPE_U64;
|
||||
if (a == TYPE_I32 || b == TYPE_I32) return TYPE_I32;
|
||||
if (a == TYPE_BOOL || b == TYPE_BOOL) return TYPE_BOOL;
|
||||
return TYPE_ERROR;
|
||||
}
|
||||
|
||||
static bool is_numeric(TypeKind t) { return t == TYPE_I64 || t == TYPE_F64 || t == TYPE_ENUM; }
|
||||
static bool is_numeric(TypeKind t) {
|
||||
return t == TYPE_I32 || t == TYPE_I64 || t == TYPE_U64
|
||||
|| t == TYPE_F64 || t == TYPE_CHAR || t == TYPE_ENUM;
|
||||
}
|
||||
// 隐式类型转换规则: 无损加宽允许,有符号→无符号不允许
|
||||
static bool can_implicit_convert(TypeKind from, TypeKind to) {
|
||||
if (from == to) return true;
|
||||
// 枚举视为 i64
|
||||
if (from == TYPE_ENUM) from = TYPE_I64;
|
||||
if (to == TYPE_ENUM) to = TYPE_I64;
|
||||
// char 可转为任意整数
|
||||
if (from == TYPE_CHAR) return to == TYPE_I32 || to == TYPE_I64 || to == TYPE_U64 || to == TYPE_F64;
|
||||
// i32 可加宽
|
||||
if (from == TYPE_I32) return to == TYPE_I64 || to == TYPE_F64;
|
||||
// i64 可转 f64
|
||||
if (from == TYPE_I64) return to == TYPE_F64;
|
||||
// u64 ↔ i64 双向允许(同一位宽,LLVM 同类型)
|
||||
if (from == TYPE_U64) return to == TYPE_F64 || to == TYPE_I64;
|
||||
if (from == TYPE_I64) return to == TYPE_F64 || to == TYPE_U64;
|
||||
return false;
|
||||
}
|
||||
static bool is_comparable(TypeKind a, TypeKind b) {
|
||||
if (a == b) return true;
|
||||
// 枚举可以参与整数比较
|
||||
@@ -184,7 +209,10 @@ static void analyze_expr(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
actual_name ? actual_name : type_name(actual));
|
||||
}
|
||||
} else if (actual != expected &&
|
||||
!(expected == TYPE_I64 && actual == TYPE_ENUM)) {
|
||||
!(expected == TYPE_I64 && actual == TYPE_ENUM) &&
|
||||
!can_implicit_convert(actual, expected) &&
|
||||
!(actual == TYPE_I64 && node->as.call.args[i]->kind == AST_LITERAL_EXPR
|
||||
&& (expected == TYPE_I32 || expected == TYPE_U64 || expected == TYPE_CHAR))) {
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"参数 %zu 类型不匹配: 期望 '%s',得到 '%s'",
|
||||
i + 1, type_name(expected), type_name(actual));
|
||||
@@ -380,7 +408,8 @@ static void analyze_expr(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
TypeKind actual = node->as.method_call.args[i]->type.kind;
|
||||
TypeKind expected = sym->param_types[i + 1];
|
||||
if (actual != TYPE_ERROR && actual != expected &&
|
||||
!(expected == TYPE_I64 && actual == TYPE_ENUM)) {
|
||||
!(expected == TYPE_I64 && actual == TYPE_ENUM) &&
|
||||
!can_implicit_convert(actual, expected)) {
|
||||
if (expected == TYPE_STRUCT) {
|
||||
// 结构体类型参数:比较具体类型名
|
||||
const char* actual_name = node->as.method_call.args[i]->type.struct_name;
|
||||
@@ -618,7 +647,12 @@ static void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
} else {
|
||||
var_type = node->as.let_stmt.annot_type;
|
||||
}
|
||||
if (inferred != TYPE_ERROR && inferred != var_type) {
|
||||
bool literal_to_int = (inferred == TYPE_I64
|
||||
&& node->as.let_stmt.init->kind == AST_LITERAL_EXPR
|
||||
&& (var_type == TYPE_I32 || var_type == TYPE_U64 || var_type == TYPE_CHAR));
|
||||
if (inferred != TYPE_ERROR && inferred != var_type
|
||||
&& !can_implicit_convert(inferred, var_type)
|
||||
&& !literal_to_int) {
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"变量 '%s' 类型标注为 '%s',但初始化表达式类型为 '%s'",
|
||||
node->as.let_stmt.name,
|
||||
|
||||
Reference in New Issue
Block a user