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:
@@ -7,6 +7,7 @@
|
|||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "arena.h"
|
#include "arena.h"
|
||||||
#include "l_lang.h"
|
#include "l_lang.h"
|
||||||
|
#include "type_table.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
#include "type_table.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// 类型描述表 — 所有类型相关判断统一查此表
|
||||||
|
// 新增类型: 加一行即可, 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; }
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#ifndef TYPE_TABLE_H
|
||||||
|
#define TYPE_TABLE_H
|
||||||
|
|
||||||
|
#include "l_lang.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
// 类型元数据 — 新增类型只需在此表加一行
|
||||||
|
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
|
||||||
+22
-24
@@ -100,47 +100,45 @@ size_t mono_count = 0;
|
|||||||
Arena* mono_arena = NULL;
|
Arena* mono_arena = NULL;
|
||||||
AstNode* g_program = NULL; // 当前 AST_PROGRAM(用于查找泛型函数模板)
|
AstNode* g_program = NULL; // 当前 AST_PROGRAM(用于查找泛型函数模板)
|
||||||
|
|
||||||
|
// === 类型关系(基于 TypeTable 数据驱动)===
|
||||||
TypeKind promote(TypeKind a, TypeKind b) {
|
TypeKind promote(TypeKind a, TypeKind b) {
|
||||||
// 枚举在算术运算中视为 i64
|
// 枚举在算术中视为 i64, char 视为 i32
|
||||||
if (a == TYPE_ENUM) a = TYPE_I64;
|
if (a == TYPE_ENUM) a = TYPE_I64;
|
||||||
if (b == TYPE_ENUM) b = TYPE_I64;
|
if (b == TYPE_ENUM) b = TYPE_I64;
|
||||||
// char 在算术中提升为 i32
|
|
||||||
if (a == TYPE_CHAR) a = TYPE_I32;
|
if (a == TYPE_CHAR) a = TYPE_I32;
|
||||||
if (b == TYPE_CHAR) b = TYPE_I32;
|
if (b == TYPE_CHAR) b = TYPE_I32;
|
||||||
if (a == TYPE_F64 || b == TYPE_F64) return TYPE_F64;
|
const TypeDesc* ta = type_lookup(a);
|
||||||
if (a == TYPE_I64 || b == TYPE_I64) return TYPE_I64;
|
const TypeDesc* tb = type_lookup(b);
|
||||||
if (a == TYPE_U64 || b == TYPE_U64) return TYPE_U64;
|
if (!ta->is_numeric || !tb->is_numeric) return TYPE_ERROR;
|
||||||
if (a == TYPE_I32 || b == TYPE_I32) return TYPE_I32;
|
return ta->promote_rank >= tb->promote_rank ? a : b;
|
||||||
if (a == TYPE_BOOL || b == TYPE_BOOL) return TYPE_BOOL;
|
|
||||||
return TYPE_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_numeric(TypeKind t) {
|
bool is_numeric(TypeKind t) {
|
||||||
return t == TYPE_I32 || t == TYPE_I64 || t == TYPE_U64
|
return type_lookup(t)->is_numeric;
|
||||||
|| t == TYPE_F64 || t == TYPE_CHAR || t == TYPE_ENUM;
|
|
||||||
}
|
}
|
||||||
// 隐式类型转换规则: 无损加宽允许,有符号→无符号不允许
|
// 隐式转换: 加宽允许, 同 bit_width 的有/无符号双向允许 (u64↔i64)
|
||||||
bool can_implicit_convert(TypeKind from, TypeKind to) {
|
bool can_implicit_convert(TypeKind from, TypeKind to) {
|
||||||
if (from == to) return true;
|
if (from == to) return true;
|
||||||
// 枚举视为 i64
|
|
||||||
if (from == TYPE_ENUM) from = TYPE_I64;
|
if (from == TYPE_ENUM) from = TYPE_I64;
|
||||||
if (to == TYPE_ENUM) to = TYPE_I64;
|
if (to == TYPE_ENUM) to = TYPE_I64;
|
||||||
// char 可转为任意整数
|
if (from == to) return true;
|
||||||
if (from == TYPE_CHAR) return to == TYPE_I32 || to == TYPE_I64 || to == TYPE_U64 || to == TYPE_F64;
|
const TypeDesc* tf = type_lookup(from);
|
||||||
// i32 可加宽
|
const TypeDesc* tt = type_lookup(to);
|
||||||
if (from == TYPE_I32) return to == TYPE_I64 || to == TYPE_F64;
|
if (!tf->is_numeric || !tt->is_numeric) return false;
|
||||||
// i64 可转 f64
|
// 同 bit_width: 有/无符号整数双向允许 (u64↔i64, 在 LLVM 中同为 64-bit)
|
||||||
if (from == TYPE_I64) return to == TYPE_F64;
|
if (tf->bit_width == tt->bit_width && tf->bit_width >= 32)
|
||||||
// u64 ↔ i64 双向允许(同一位宽,LLVM 同类型)
|
return true;
|
||||||
if (from == TYPE_U64) return to == TYPE_F64 || to == TYPE_I64;
|
// 加宽转换: 有符号→任意, 无符号→仅无符号
|
||||||
if (from == TYPE_I64) return to == TYPE_F64 || to == TYPE_U64;
|
if (tt->promote_rank > tf->promote_rank)
|
||||||
|
return tf->is_signed || !tt->is_signed;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_comparable(TypeKind a, TypeKind b) {
|
bool is_comparable(TypeKind a, TypeKind b) {
|
||||||
if (a == b) return true;
|
if (a == b) return true;
|
||||||
// 枚举可以参与整数比较
|
if (a == TYPE_ENUM) a = TYPE_I64;
|
||||||
if ((a == TYPE_I64 && b == TYPE_ENUM) || (a == TYPE_ENUM && b == TYPE_I64)) return true;
|
if (b == TYPE_ENUM) b = TYPE_I64;
|
||||||
return false;
|
return type_lookup(a)->is_numeric && type_lookup(b)->is_numeric;
|
||||||
}
|
}
|
||||||
|
|
||||||
// === 向前声明 ===
|
// === 向前声明 ===
|
||||||
|
|||||||
Reference in New Issue
Block a user