refactor: TypeTable 数据驱动 — promote/convert/numeric/comparable 统一查表
新增 src/sema/type_table.h/c: TypeDesc{promote_rank, bit_width, is_signed, is_numeric}
promote/can_implicit_convert/is_numeric/is_comparable 从硬编码 switch 改为查表
新增类型只需在 TABLE[] 加一行, 从 7+ 文件改为 3-4 文件 (token + table + codegen)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+23
-25
@@ -100,47 +100,45 @@ size_t mono_count = 0;
|
||||
Arena* mono_arena = NULL;
|
||||
AstNode* g_program = NULL; // 当前 AST_PROGRAM(用于查找泛型函数模板)
|
||||
|
||||
// === 类型关系(基于 TypeTable 数据驱动)===
|
||||
TypeKind promote(TypeKind a, TypeKind b) {
|
||||
// 枚举在算术运算中视为 i64
|
||||
// 枚举在算术中视为 i64, char 视为 i32
|
||||
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;
|
||||
const TypeDesc* ta = type_lookup(a);
|
||||
const TypeDesc* tb = type_lookup(b);
|
||||
if (!ta->is_numeric || !tb->is_numeric) return TYPE_ERROR;
|
||||
return ta->promote_rank >= tb->promote_rank ? a : b;
|
||||
}
|
||||
|
||||
bool is_numeric(TypeKind t) {
|
||||
return t == TYPE_I32 || t == TYPE_I64 || t == TYPE_U64
|
||||
|| t == TYPE_F64 || t == TYPE_CHAR || t == TYPE_ENUM;
|
||||
return type_lookup(t)->is_numeric;
|
||||
}
|
||||
// 隐式类型转换规则: 无损加宽允许,有符号→无符号不允许
|
||||
// 隐式转换: 加宽允许, 同 bit_width 的有/无符号双向允许 (u64↔i64)
|
||||
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;
|
||||
if (to == TYPE_ENUM) to = TYPE_I64;
|
||||
if (from == to) return true;
|
||||
const TypeDesc* tf = type_lookup(from);
|
||||
const TypeDesc* tt = type_lookup(to);
|
||||
if (!tf->is_numeric || !tt->is_numeric) return false;
|
||||
// 同 bit_width: 有/无符号整数双向允许 (u64↔i64, 在 LLVM 中同为 64-bit)
|
||||
if (tf->bit_width == tt->bit_width && tf->bit_width >= 32)
|
||||
return true;
|
||||
// 加宽转换: 有符号→任意, 无符号→仅无符号
|
||||
if (tt->promote_rank > tf->promote_rank)
|
||||
return tf->is_signed || !tt->is_signed;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_comparable(TypeKind a, TypeKind b) {
|
||||
if (a == b) return true;
|
||||
// 枚举可以参与整数比较
|
||||
if ((a == TYPE_I64 && b == TYPE_ENUM) || (a == TYPE_ENUM && b == TYPE_I64)) return true;
|
||||
return false;
|
||||
if (a == TYPE_ENUM) a = TYPE_I64;
|
||||
if (b == TYPE_ENUM) b = TYPE_I64;
|
||||
return type_lookup(a)->is_numeric && type_lookup(b)->is_numeric;
|
||||
}
|
||||
|
||||
// === 向前声明 ===
|
||||
|
||||
Reference in New Issue
Block a user