feat: 枚举 enum (P1 #7)
- lexer: TOK_ENUM, TOK_COLON_COLON
- ast: AST_ENUM_DECL, AST_ENUM_VARIANT + AST_PROGRAM enums数组
- parser: enum Name { A, B } + Enum::Variant语法
- sema: SYM_ENUM, 变体验证, enum→i64类型兼容
- codegen: TYPE_ENUM→i64, 变体→ConstInt(索引值)
- 新增集成测试: 17_enum.l
测试: 121 通过 (41+15+47+18)
This commit is contained in:
+41
-4
@@ -6,14 +6,22 @@ static TypeKind current_return_type = TYPE_VOID;
|
||||
static const char* current_return_struct_name = NULL;
|
||||
|
||||
static TypeKind promote(TypeKind a, TypeKind b) {
|
||||
// 枚举在算术运算中视为 i64
|
||||
if (a == TYPE_ENUM) a = TYPE_I64;
|
||||
if (b == TYPE_ENUM) b = TYPE_I64;
|
||||
if (a == TYPE_F64 || b == TYPE_F64) return TYPE_F64;
|
||||
if (a == TYPE_I64 || b == TYPE_I64) return TYPE_I64;
|
||||
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; }
|
||||
static bool is_comparable(TypeKind a, TypeKind b) { return a == b; }
|
||||
static bool is_numeric(TypeKind t) { return t == TYPE_I64 || t == TYPE_F64 || t == TYPE_ENUM; }
|
||||
static 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;
|
||||
}
|
||||
|
||||
// === 向前声明 ===
|
||||
static void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena* a);
|
||||
@@ -169,7 +177,8 @@ static void analyze_expr(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
expected_name ? expected_name : "struct",
|
||||
actual_name ? actual_name : type_name(actual));
|
||||
}
|
||||
} else if (actual != expected) {
|
||||
} else if (actual != expected &&
|
||||
!(expected == TYPE_I64 && actual == TYPE_ENUM)) {
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"参数 %zu 类型不匹配: 期望 '%s',得到 '%s'",
|
||||
i + 1, type_name(expected), type_name(actual));
|
||||
@@ -287,6 +296,26 @@ static void analyze_expr(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
break;
|
||||
}
|
||||
|
||||
case AST_ENUM_VARIANT: {
|
||||
Symbol* enum_sym = scope_lookup_struct(scope, node->as.enum_variant.enum_name);
|
||||
if (!enum_sym || enum_sym->kind != SYM_ENUM) {
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"未定义的枚举 '%s'", node->as.enum_variant.enum_name);
|
||||
node->type.kind = TYPE_ERROR; break;
|
||||
}
|
||||
int vi = scope_enum_variant_index(enum_sym, node->as.enum_variant.variant_name);
|
||||
if (vi < 0) {
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"枚举 '%s' 没有变体 '%s'",
|
||||
node->as.enum_variant.enum_name,
|
||||
node->as.enum_variant.variant_name);
|
||||
node->type.kind = TYPE_ERROR; break;
|
||||
}
|
||||
node->as.enum_variant.variant_index = vi;
|
||||
node->type.kind = TYPE_ENUM;
|
||||
break;
|
||||
}
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
@@ -308,6 +337,13 @@ static void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
}
|
||||
}
|
||||
}
|
||||
// 注册枚举
|
||||
for (size_t i = 0; i < node->as.program.enum_count; i++) {
|
||||
AstNode* ed = node->as.program.enums[i];
|
||||
scope_insert_enum(scope, a, ed->as.enum_decl.name,
|
||||
ed->as.enum_decl.variants,
|
||||
ed->as.enum_decl.variant_count);
|
||||
}
|
||||
// 第一遍:收集所有结构体定义
|
||||
for (size_t i = 0; i < node->as.program.struct_count; i++) {
|
||||
AstNode* sd = node->as.program.structs[i];
|
||||
@@ -548,7 +584,8 @@ static void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
expected_name ? expected_name : "struct",
|
||||
actual_name ? actual_name : type_name(actual));
|
||||
}
|
||||
} else if (actual != expected) {
|
||||
} else if (actual != expected &&
|
||||
!(expected == TYPE_I64 && actual == TYPE_ENUM)) {
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"返回类型不匹配: 期望 '%s',得到 '%s'",
|
||||
type_name(expected), type_name(actual));
|
||||
|
||||
+33
-1
@@ -94,7 +94,7 @@ Symbol* scope_insert_struct(Scope* scope, void* alloc, const char* name,
|
||||
Symbol* scope_lookup_struct(const Scope* scope, const char* name) {
|
||||
for (const Scope* s = scope; s; s = s->parent) {
|
||||
for (Symbol* sym = s->head; sym; sym = sym->next) {
|
||||
if (sym->kind == SYM_STRUCT && strcmp(sym->name, name) == 0)
|
||||
if ((sym->kind == SYM_STRUCT || sym->kind == SYM_ENUM) && strcmp(sym->name, name) == 0)
|
||||
return sym;
|
||||
}
|
||||
}
|
||||
@@ -109,3 +109,35 @@ int scope_struct_field_index(const Symbol* sym, const char* field_name) {
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
Symbol* scope_insert_enum(Scope* scope, void* alloc, const char* name,
|
||||
const char** vnames, size_t vc) {
|
||||
if (scope->head) {
|
||||
for (Symbol* sym = scope->head; sym; sym = sym->next) {
|
||||
if (strcmp(sym->name, name) == 0) return NULL;
|
||||
}
|
||||
}
|
||||
Symbol* sym = (Symbol*)arena_alloc_impl(alloc, sizeof(Symbol));
|
||||
if (!sym) return NULL;
|
||||
sym->name = name; sym->kind = SYM_ENUM; sym->type = TYPE_ENUM;
|
||||
sym->is_mut = false; sym->return_type = TYPE_VOID;
|
||||
sym->param_types = NULL; sym->param_count = 0;
|
||||
sym->struct_field_names = vnames;
|
||||
sym->struct_field_types = NULL;
|
||||
sym->struct_field_struct_names = NULL;
|
||||
sym->struct_field_count = vc;
|
||||
sym->struct_type_name = NULL;
|
||||
sym->is_type_alias = false;
|
||||
sym->next = scope->head;
|
||||
scope->head = sym;
|
||||
return sym;
|
||||
}
|
||||
|
||||
int scope_enum_variant_index(const Symbol* sym, const char* variant_name) {
|
||||
if (sym->kind != SYM_ENUM) return -1;
|
||||
for (size_t i = 0; i < sym->struct_field_count; i++) {
|
||||
if (strcmp(sym->struct_field_names[i], variant_name) == 0)
|
||||
return (int)i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
+8
-1
@@ -4,7 +4,7 @@
|
||||
#include "l_lang.h"
|
||||
#include "ast.h"
|
||||
|
||||
typedef enum { SYM_VARIABLE, SYM_PARAMETER, SYM_FUNCTION, SYM_STRUCT } SymbolKind;
|
||||
typedef enum { SYM_VARIABLE, SYM_PARAMETER, SYM_FUNCTION, SYM_STRUCT, SYM_ENUM } SymbolKind;
|
||||
|
||||
typedef struct Symbol {
|
||||
const char* name;
|
||||
@@ -61,4 +61,11 @@ Symbol* scope_lookup_struct(const Scope* scope, const char* name);
|
||||
// 在结构体符号中查找字段索引(返回 -1 表示未找到)
|
||||
int scope_struct_field_index(const Symbol* sym, const char* field_name);
|
||||
|
||||
// 插入枚举符号
|
||||
Symbol* scope_insert_enum(Scope* scope, void* alloc, const char* name,
|
||||
const char** vnames, size_t vc);
|
||||
|
||||
// 在枚举符号中查找变体索引(返回 -1 表示未找到)
|
||||
int scope_enum_variant_index(const Symbol* sym, const char* variant_name);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user