From 3733b41453f25bb79617021283b1d5eb4a1ff7c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=88=AA=E5=AE=87?= <3364451258@qq.com> Date: Sat, 6 Jun 2026 20:31:32 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20TypeTable=20=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E9=A9=B1=E5=8A=A8=20=E2=80=94=20promote/convert/numeric/compar?= =?UTF-8?q?able=20=E7=BB=9F=E4=B8=80=E6=9F=A5=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增 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 --- src/sema/sema_internal.h | 1 + src/sema/type_table.c | 36 ++++++++++++++++++++++++++++++ src/sema/type_table.h | 22 ++++++++++++++++++ src/sema/typeck.c | 48 +++++++++++++++++++--------------------- 4 files changed, 82 insertions(+), 25 deletions(-) create mode 100644 src/sema/type_table.c create mode 100644 src/sema/type_table.h diff --git a/src/sema/sema_internal.h b/src/sema/sema_internal.h index 31f9c6e..857a3ee 100644 --- a/src/sema/sema_internal.h +++ b/src/sema/sema_internal.h @@ -7,6 +7,7 @@ #include "error.h" #include "arena.h" #include "l_lang.h" +#include "type_table.h" #include #include diff --git a/src/sema/type_table.c b/src/sema/type_table.c new file mode 100644 index 0000000..7f36918 --- /dev/null +++ b/src/sema/type_table.c @@ -0,0 +1,36 @@ +#include "type_table.h" +#include + +// 类型描述表 — 所有类型相关判断统一查此表 +// 新增类型: 加一行即可, promote/convert/numeric/comparable 自动生效 +static const TypeDesc TABLE[] = { + {TYPE_BOOL, "bool", 0, 1, false, false}, + {TYPE_CHAR, "char", 1, 8, true, true}, + {TYPE_I32, "i32", 2, 32, true, true}, + {TYPE_U64, "u64", 3, 64, false, true}, + {TYPE_I64, "i64", 4, 64, true, true}, + {TYPE_ENUM, "enum", 4, 64, false, true}, + {TYPE_F64, "f64", 5, 64, true, true}, + {TYPE_STR, "str", 0, 0, false, false}, + {TYPE_STRUCT,"struct",0, 0, false, false}, + {TYPE_ARRAY,"array", 0, 0, false, false}, + {TYPE_VOID, "void", 0, 0, false, false}, + {TYPE_UNKNOWN,"?", 0, 0, false, false}, + {TYPE_ERROR,"err", 0, 0, false, false}, +}; + +static const size_t TABLE_SIZE = sizeof(TABLE) / sizeof(TABLE[0]); + +const TypeDesc* type_lookup(TypeKind kind) { + for (size_t i = 0; i < TABLE_SIZE; i++) + if (TABLE[i].kind == kind) return &TABLE[i]; + return &TABLE[TABLE_SIZE - 1]; +} + +const TypeDesc* type_by_name(const char* name) { + for (size_t i = 0; i < TABLE_SIZE; i++) + if (strcmp(TABLE[i].name, name) == 0) return &TABLE[i]; + return NULL; +} + +size_t type_count(void) { return TABLE_SIZE; } diff --git a/src/sema/type_table.h b/src/sema/type_table.h new file mode 100644 index 0000000..18a5edd --- /dev/null +++ b/src/sema/type_table.h @@ -0,0 +1,22 @@ +#ifndef TYPE_TABLE_H +#define TYPE_TABLE_H + +#include "l_lang.h" +#include +#include + +// 类型元数据 — 新增类型只需在此表加一行 +typedef struct { + TypeKind kind; + const char* name; + int promote_rank; // 越高越宽: bool=0, char=1, i32=2, u64=3, i64=4, f64=5 + int bit_width; // LLVM 位宽: 1, 8, 32, 64 + bool is_signed; // 有符号(用于隐式转换判断) + bool is_numeric; // 是否参与算术 +} TypeDesc; + +const TypeDesc* type_lookup(TypeKind kind); +const TypeDesc* type_by_name(const char* name); +size_t type_count(void); + +#endif diff --git a/src/sema/typeck.c b/src/sema/typeck.c index cb7d339..d91e3f5 100644 --- a/src/sema/typeck.c +++ b/src/sema/typeck.c @@ -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; } // === 向前声明 ===