feat: 类型别名 type alias (P1 #10)
- lexer: TOK_TYPE 关键字 - ast: AST_TYPE_ALIAS + AST_PROGRAM aliases数组 - parser: parse_type_expr() 抽取, type Name = Type; 解析 - sema: 别名注册+解析, 类型标注/struct字段/函数参数均支持 - 新增测试: 15_type_alias.l, 16_type_alias_struct.l 测试: 112 通过 (41+15+41+15)
This commit is contained in:
+13
-1
@@ -9,12 +9,15 @@
|
||||
n->loc = loc
|
||||
|
||||
AstNode* ast_make_program(void* alloc, AstNode** fns, size_t fn_count,
|
||||
AstNode** structs, size_t struct_count, SourceLoc loc) {
|
||||
AstNode** structs, size_t struct_count,
|
||||
AstNode** aliases, size_t alias_count, SourceLoc loc) {
|
||||
NEW(alloc, AST_PROGRAM);
|
||||
n->as.program.functions = fns;
|
||||
n->as.program.fn_count = fn_count;
|
||||
n->as.program.structs = structs;
|
||||
n->as.program.struct_count = struct_count;
|
||||
n->as.program.type_aliases = aliases;
|
||||
n->as.program.alias_count = alias_count;
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -165,3 +168,12 @@ AstNode* ast_make_field_access(void* alloc, AstNode* object, const char* field,
|
||||
n->as.field_access.field_index = -1;
|
||||
return n;
|
||||
}
|
||||
|
||||
AstNode* ast_make_type_alias(void* alloc, const char* name, TypeKind aliased,
|
||||
const char* aliased_struct, SourceLoc loc) {
|
||||
NEW(alloc, AST_TYPE_ALIAS);
|
||||
n->as.type_alias.name = name;
|
||||
n->as.type_alias.aliased_type = aliased;
|
||||
n->as.type_alias.aliased_struct_name = aliased_struct;
|
||||
return n;
|
||||
}
|
||||
|
||||
+9
-2
@@ -23,6 +23,7 @@ typedef enum {
|
||||
AST_STRUCT_DECL, // struct Point { x: i64, y: i64 }
|
||||
AST_STRUCT_INIT, // Point { x: 10, y: 20 }
|
||||
AST_FIELD_ACCESS, // p.x
|
||||
AST_TYPE_ALIAS, // type Meters = i64
|
||||
} AstKind;
|
||||
|
||||
typedef enum {
|
||||
@@ -48,7 +49,8 @@ struct AstNode {
|
||||
union {
|
||||
// AST_PROGRAM
|
||||
struct { struct AstNode** functions; size_t fn_count;
|
||||
struct AstNode** structs; size_t struct_count; } program;
|
||||
struct AstNode** structs; size_t struct_count;
|
||||
struct AstNode** type_aliases; size_t alias_count; } program;
|
||||
// AST_FUNCTION
|
||||
struct { const char* name; struct AstNode** params; size_t param_count;
|
||||
TypeKind return_type; const char* return_struct_type_name;
|
||||
@@ -87,12 +89,15 @@ struct AstNode {
|
||||
struct AstNode** field_values; size_t field_count; } struct_init;
|
||||
// AST_FIELD_ACCESS
|
||||
struct { struct AstNode* object; const char* field; int field_index; } field_access;
|
||||
// AST_TYPE_ALIAS
|
||||
struct { const char* name; TypeKind aliased_type; const char* aliased_struct_name; } type_alias;
|
||||
} as;
|
||||
};
|
||||
|
||||
// 创建节点的辅助函数(内存来自 arena,通过 void* 传递避免循环依赖)
|
||||
AstNode* ast_make_program(void* alloc, AstNode** fns, size_t fn_count,
|
||||
AstNode** structs, size_t struct_count, SourceLoc loc);
|
||||
AstNode** structs, size_t struct_count,
|
||||
AstNode** aliases, size_t alias_count, SourceLoc loc);
|
||||
AstNode* ast_make_function(void* alloc, const char* name, AstNode** params, size_t pcount,
|
||||
TypeKind ret, const char* ret_struct_name, AstNode* body, SourceLoc loc);
|
||||
AstNode* ast_make_parameter(void* alloc, const char* name, TypeKind type, const char* struct_type_name, SourceLoc loc);
|
||||
@@ -115,5 +120,7 @@ AstNode* ast_make_ident(void* alloc, const char* name, SourceLoc loc);
|
||||
AstNode* ast_make_struct_decl(void* alloc, const char* name, AstNode** fields, size_t count, SourceLoc loc);
|
||||
AstNode* ast_make_struct_init(void* alloc, const char* type_name, const char** fnames, AstNode** fvals, size_t count, SourceLoc loc);
|
||||
AstNode* ast_make_field_access(void* alloc, AstNode* object, const char* field, SourceLoc loc);
|
||||
AstNode* ast_make_type_alias(void* alloc, const char* name, TypeKind aliased,
|
||||
const char* aliased_struct, SourceLoc loc);
|
||||
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -62,7 +62,7 @@ static TokenKind check_keyword(const Token* tok) {
|
||||
KW("i64", TOK_I64); KW("f64", TOK_F64);
|
||||
KW("bool", TOK_BOOL); KW("str", TOK_STR);
|
||||
KW("void", TOK_VOID);
|
||||
KW("struct", TOK_STRUCT);
|
||||
KW("struct", TOK_STRUCT); KW("type", TOK_TYPE);
|
||||
KW("true", TOK_TRUE); KW("false", TOK_FALSE);
|
||||
#undef KW
|
||||
return TOK_IDENT;
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
static const char* NAMES[] = {
|
||||
[TOK_FN] = "fn", [TOK_LET] = "let", [TOK_MUT] = "mut", [TOK_IF] = "if",
|
||||
[TOK_ELSE] = "else", [TOK_WHILE] = "while", [TOK_FOR] = "for", [TOK_IN] = "in", [TOK_RETURN] = "return",
|
||||
[TOK_STRUCT] = "struct",
|
||||
[TOK_STRUCT] = "struct", [TOK_TYPE] = "type",
|
||||
[TOK_I64] = "i64", [TOK_F64] = "f64", [TOK_BOOL] = "bool", [TOK_STR] = "str", [TOK_VOID] = "void",
|
||||
[TOK_INT_LIT] = "整数", [TOK_FLOAT_LIT] = "浮点数", [TOK_STR_LIT] = "字符串",
|
||||
[TOK_TRUE] = "true", [TOK_FALSE] = "false",
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
typedef enum {
|
||||
// 关键字
|
||||
TOK_FN, TOK_LET, TOK_MUT, TOK_IF, TOK_ELSE, TOK_WHILE, TOK_FOR, TOK_IN, TOK_RETURN,
|
||||
TOK_STRUCT,
|
||||
TOK_STRUCT, TOK_TYPE,
|
||||
// 类型关键字
|
||||
TOK_I64, TOK_F64, TOK_BOOL, TOK_STR, TOK_VOID,
|
||||
// 字面量
|
||||
|
||||
+53
-49
@@ -244,6 +244,25 @@ static TypeKind token_to_type(TokenKind k) {
|
||||
default: return TYPE_VOID; }
|
||||
}
|
||||
|
||||
// === 类型表达式解析(内置类型/结构体名)===
|
||||
static TypeInfo parse_type_expr(Parser* p, ErrorInfo* error) {
|
||||
const Token* t = peek(p);
|
||||
TypeInfo ti = {0};
|
||||
if (tok_is_type(t->kind)) {
|
||||
advance(p);
|
||||
ti.kind = token_to_type(t->kind);
|
||||
} else if (t->kind == TOK_IDENT) {
|
||||
advance(p);
|
||||
ti.kind = TYPE_STRUCT;
|
||||
ti.struct_name = arena_strdup_impl(p->arena, t->start, t->length);
|
||||
} else {
|
||||
error->message = "无效的类型"; error->filename = p->filename;
|
||||
error->line = t->line; error->col = t->col;
|
||||
ti.kind = TYPE_ERROR;
|
||||
}
|
||||
return ti;
|
||||
}
|
||||
|
||||
// === 结构体声明解析 ===
|
||||
static AstNode* parse_struct_decl(Parser* p, ErrorInfo* error) {
|
||||
const Token* s_tok = advance(p); // 跳过 'struct'
|
||||
@@ -257,21 +276,14 @@ static AstNode* parse_struct_decl(Parser* p, ErrorInfo* error) {
|
||||
const Token* fname = expect(p, TOK_IDENT, error, "字段名");
|
||||
if (!fname) return NULL;
|
||||
if (!expect(p, TOK_COLON, error, "缺少 ':'")) return NULL;
|
||||
const Token* ftype = advance(p);
|
||||
TypeKind field_kind;
|
||||
const char* field_struct_name = NULL;
|
||||
if (tok_is_type(ftype->kind)) {
|
||||
field_kind = token_to_type(ftype->kind);
|
||||
} else if (ftype->kind == TOK_IDENT) {
|
||||
field_kind = TYPE_STRUCT;
|
||||
field_struct_name = arena_strdup_impl(p->arena, ftype->start, ftype->length);
|
||||
} else {
|
||||
error->message = "无效的字段类型"; error->filename = p->filename;
|
||||
error->line = ftype->line; error->col = ftype->col; return NULL;
|
||||
TypeInfo fti = parse_type_expr(p, error);
|
||||
if (fti.kind == TYPE_ERROR) {
|
||||
error->filename = p->filename;
|
||||
return NULL;
|
||||
}
|
||||
fields[fcount++] = ast_make_parameter(p->arena,
|
||||
arena_strdup_impl(p->arena, fname->start, fname->length),
|
||||
field_kind, field_struct_name, tok_loc(fname));
|
||||
fti.kind, fti.struct_name, tok_loc(fname));
|
||||
if (peek(p)->kind == TOK_COMMA) advance(p);
|
||||
else break;
|
||||
}
|
||||
@@ -322,18 +334,10 @@ static AstNode* parse_statement(Parser* p, ErrorInfo* error) {
|
||||
bool has_type_annot = false;
|
||||
const char* struct_type_name = NULL;
|
||||
if (match(p, TOK_COLON)) {
|
||||
const Token* type_tok = advance(p);
|
||||
if (!tok_is_type(type_tok->kind) && type_tok->kind != TOK_IDENT) {
|
||||
error->message = "无效的类型标注"; error->filename = p->filename;
|
||||
error->line = type_tok->line; error->col = type_tok->col; return NULL;
|
||||
}
|
||||
if (tok_is_type(type_tok->kind)) {
|
||||
annot_type = token_to_type(type_tok->kind);
|
||||
} else {
|
||||
// struct 类型名
|
||||
annot_type = TYPE_STRUCT;
|
||||
struct_type_name = arena_strdup_impl(p->arena, type_tok->start, type_tok->length);
|
||||
}
|
||||
TypeInfo ti = parse_type_expr(p, error);
|
||||
if (ti.kind == TYPE_ERROR) return NULL;
|
||||
annot_type = ti.kind;
|
||||
struct_type_name = ti.struct_name;
|
||||
has_type_annot = true;
|
||||
}
|
||||
if (!expect(p, TOK_ASSIGN, error, "缺少 '='")) return NULL;
|
||||
@@ -511,21 +515,11 @@ static AstNode* parse_function(Parser* p, ErrorInfo* error) {
|
||||
const Token* pname = expect(p, TOK_IDENT, error, "参数名");
|
||||
if (!pname) return NULL;
|
||||
if (!expect(p, TOK_COLON, error, "缺少 ':'")) return NULL;
|
||||
const Token* ptype = advance(p);
|
||||
TypeKind param_kind;
|
||||
const char* param_struct_name = NULL;
|
||||
if (tok_is_type(ptype->kind)) {
|
||||
param_kind = token_to_type(ptype->kind);
|
||||
} else if (ptype->kind == TOK_IDENT) {
|
||||
param_kind = TYPE_STRUCT;
|
||||
param_struct_name = arena_strdup_impl(p->arena, ptype->start, ptype->length);
|
||||
} else {
|
||||
error->message = "无效的参数类型"; error->filename = p->filename;
|
||||
error->line = ptype->line; error->col = ptype->col; return NULL;
|
||||
}
|
||||
TypeInfo pti = parse_type_expr(p, error);
|
||||
if (pti.kind == TYPE_ERROR) return NULL;
|
||||
params[pcount++] = ast_make_parameter(p->arena,
|
||||
arena_strdup_impl(p->arena, pname->start, pname->length),
|
||||
param_kind, param_struct_name, tok_loc(pname));
|
||||
pti.kind, pti.struct_name, tok_loc(pname));
|
||||
if (match(p, TOK_COMMA)) continue;
|
||||
else break;
|
||||
}
|
||||
@@ -535,16 +529,10 @@ static AstNode* parse_function(Parser* p, ErrorInfo* error) {
|
||||
TypeKind ret = TYPE_VOID;
|
||||
const char* ret_struct_name = NULL;
|
||||
if (match(p, TOK_ARROW)) {
|
||||
const Token* rt = advance(p);
|
||||
if (tok_is_type(rt->kind)) {
|
||||
ret = token_to_type(rt->kind);
|
||||
} else if (rt->kind == TOK_IDENT) {
|
||||
ret = TYPE_STRUCT;
|
||||
ret_struct_name = arena_strdup_impl(p->arena, rt->start, rt->length);
|
||||
} else {
|
||||
error->message = "无效的返回类型"; error->filename = p->filename;
|
||||
error->line = rt->line; error->col = rt->col; return NULL;
|
||||
}
|
||||
TypeInfo rti = parse_type_expr(p, error);
|
||||
if (rti.kind == TYPE_ERROR) return NULL;
|
||||
ret = rti.kind;
|
||||
ret_struct_name = rti.struct_name;
|
||||
}
|
||||
|
||||
AstNode* body = parse_block(p, error);
|
||||
@@ -564,15 +552,28 @@ AstNode* parse(Arena* a, const Token* tokens, size_t count,
|
||||
.filename = filename, .arena = a};
|
||||
AstNode* functions[256]; int fn_count = 0;
|
||||
AstNode* structs[64]; int struct_count = 0;
|
||||
AstNode* aliases[64]; int alias_count = 0;
|
||||
while (peek(&p)->kind != TOK_EOF && !error->message) {
|
||||
if (peek(&p)->kind == TOK_STRUCT) {
|
||||
if (struct_count >= 64) { error->message = "结构体过多 (最多64)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
|
||||
structs[struct_count++] = parse_struct_decl(&p, error);
|
||||
} else if (peek(&p)->kind == TOK_TYPE) {
|
||||
if (alias_count >= 64) { error->message = "类型别名过多 (最多64)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
|
||||
const Token* type_tok = advance(&p); // 跳过 'type'
|
||||
const Token* alias_name = expect(&p, TOK_IDENT, error, "type 后应为别名");
|
||||
if (!alias_name) return NULL;
|
||||
if (!expect(&p, TOK_ASSIGN, error, "缺少 '='")) return NULL;
|
||||
TypeInfo rti = parse_type_expr(&p, error);
|
||||
if (rti.kind == TYPE_ERROR) return NULL;
|
||||
if (!expect(&p, TOK_SEMICOLON, error, "缺少 ';'")) return NULL;
|
||||
aliases[alias_count++] = ast_make_type_alias(a,
|
||||
arena_strdup_impl(a, alias_name->start, alias_name->length),
|
||||
rti.kind, rti.struct_name, tok_loc(type_tok));
|
||||
} else if (peek(&p)->kind == TOK_FN) {
|
||||
if (fn_count >= 256) { error->message = "函数过多 (最多256)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
|
||||
functions[fn_count++] = parse_function(&p, error);
|
||||
} else {
|
||||
error->message = "顶层只允许 fn 或 struct";
|
||||
error->message = "顶层只允许 fn、struct 或 type";
|
||||
error->filename = p.filename;
|
||||
error->line = peek(&p)->line;
|
||||
error->col = peek(&p)->col;
|
||||
@@ -584,5 +585,8 @@ AstNode* parse(Arena* a, const Token* tokens, size_t count,
|
||||
memcpy(fn_arr, functions, fn_count * sizeof(AstNode*));
|
||||
AstNode** st_arr = arena_alloc_impl(a, struct_count * sizeof(AstNode*));
|
||||
memcpy(st_arr, structs, struct_count * sizeof(AstNode*));
|
||||
return ast_make_program(a, fn_arr, fn_count, st_arr, struct_count, loc_at(0, 0));
|
||||
AstNode** al_arr = arena_alloc_impl(a, alias_count * sizeof(AstNode*));
|
||||
memcpy(al_arr, aliases, alias_count * sizeof(AstNode*));
|
||||
return ast_make_program(a, fn_arr, fn_count, st_arr, struct_count,
|
||||
al_arr, alias_count, loc_at(0, 0));
|
||||
}
|
||||
|
||||
+92
-18
@@ -30,6 +30,10 @@ static void analyze_expr(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"未定义的变量 '%s'", node->as.ident.name);
|
||||
node->type.kind = TYPE_ERROR;
|
||||
} else if (sym->is_type_alias) {
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"'%s' 是类型别名,不能作为表达式使用", node->as.ident.name);
|
||||
node->type.kind = TYPE_ERROR;
|
||||
} else if (sym->kind == SYM_FUNCTION) {
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"'%s' 是函数,不能作为表达式使用", node->as.ident.name);
|
||||
@@ -227,7 +231,18 @@ static void analyze_expr(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
}
|
||||
|
||||
case AST_STRUCT_INIT: {
|
||||
Symbol* struct_sym = scope_lookup_struct(scope, node->as.struct_init.type_name);
|
||||
const char* resolved_type_name = node->as.struct_init.type_name;
|
||||
Symbol* struct_sym = scope_lookup_struct(scope, resolved_type_name);
|
||||
if (!struct_sym) {
|
||||
// 检查是否是类型别名指向结构体
|
||||
Symbol* alias_sym = scope_lookup(scope, resolved_type_name);
|
||||
if (alias_sym && alias_sym->is_type_alias && alias_sym->struct_type_name) {
|
||||
resolved_type_name = alias_sym->struct_type_name;
|
||||
struct_sym = scope_lookup_struct(scope, resolved_type_name);
|
||||
// 更新 type_name 为真实结构体名(codegen 需要)
|
||||
node->as.struct_init.type_name = resolved_type_name;
|
||||
}
|
||||
}
|
||||
if (!struct_sym) {
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"未定义的结构体类型 '%s'", node->as.struct_init.type_name);
|
||||
@@ -267,7 +282,7 @@ static void analyze_expr(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
}
|
||||
if (node->type.kind != TYPE_ERROR) {
|
||||
node->type.kind = TYPE_STRUCT;
|
||||
node->type.struct_name = node->as.struct_init.type_name;
|
||||
node->type.struct_name = resolved_type_name;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -281,6 +296,18 @@ static void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
|
||||
switch (node->kind) {
|
||||
case AST_PROGRAM:
|
||||
// Pass 0: 注册类型别名
|
||||
for (size_t i = 0; i < node->as.program.alias_count; i++) {
|
||||
AstNode* alias = node->as.program.type_aliases[i];
|
||||
Symbol* sym = scope_insert(scope, a, alias->as.type_alias.name,
|
||||
SYM_VARIABLE, alias->as.type_alias.aliased_type);
|
||||
if (sym) {
|
||||
sym->is_type_alias = true;
|
||||
if (alias->as.type_alias.aliased_struct_name) {
|
||||
sym->struct_type_name = alias->as.type_alias.aliased_struct_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 第一遍:收集所有结构体定义
|
||||
for (size_t i = 0; i < node->as.program.struct_count; i++) {
|
||||
AstNode* sd = node->as.program.structs[i];
|
||||
@@ -305,12 +332,31 @@ static void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
TypeKind* pts = (TypeKind*)arena_alloc_impl(a, fn->as.function.param_count * sizeof(TypeKind));
|
||||
const char** pstruct_names = (const char**)arena_alloc_impl(a, fn->as.function.param_count * sizeof(const char*));
|
||||
for (size_t j = 0; j < fn->as.function.param_count; j++) {
|
||||
pts[j] = fn->as.function.params[j]->as.parameter.type;
|
||||
pstruct_names[j] = fn->as.function.params[j]->as.parameter.struct_type_name;
|
||||
TypeKind pt = fn->as.function.params[j]->as.parameter.type;
|
||||
const char* psn = fn->as.function.params[j]->as.parameter.struct_type_name;
|
||||
// 解析参数类型的别名
|
||||
if (psn) {
|
||||
Symbol* as = scope_lookup(scope, psn);
|
||||
if (as && as->is_type_alias) {
|
||||
pt = as->type;
|
||||
psn = as->struct_type_name;
|
||||
}
|
||||
}
|
||||
pts[j] = pt;
|
||||
pstruct_names[j] = psn;
|
||||
}
|
||||
// 解析返回类型的别名
|
||||
TypeKind ret_t = fn->as.function.return_type;
|
||||
const char* ret_sn = fn->as.function.return_struct_type_name;
|
||||
if (ret_sn) {
|
||||
Symbol* as = scope_lookup(scope, ret_sn);
|
||||
if (as && as->is_type_alias) {
|
||||
ret_t = as->type;
|
||||
ret_sn = as->struct_type_name;
|
||||
}
|
||||
}
|
||||
scope_insert_function(scope, a, fn->as.function.name,
|
||||
fn->as.function.return_type,
|
||||
fn->as.function.return_struct_type_name,
|
||||
ret_t, ret_sn,
|
||||
pts, pstruct_names,
|
||||
fn->as.function.param_count);
|
||||
}
|
||||
@@ -322,12 +368,33 @@ static void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
|
||||
case AST_FUNCTION: {
|
||||
Scope* fn_scope = scope_new(a, scope);
|
||||
// 注册参数
|
||||
// 注册参数(同时解析类型别名,更新 AST 节点供 codegen 使用)
|
||||
for (size_t i = 0; i < node->as.function.param_count; i++) {
|
||||
AstNode* p = node->as.function.params[i];
|
||||
Symbol* sym = scope_insert(fn_scope, a, p->as.parameter.name, SYM_PARAMETER, p->as.parameter.type);
|
||||
if (sym && p->as.parameter.type == TYPE_STRUCT && p->as.parameter.struct_type_name) {
|
||||
sym->struct_type_name = p->as.parameter.struct_type_name;
|
||||
TypeKind pt = p->as.parameter.type;
|
||||
const char* psn = p->as.parameter.struct_type_name;
|
||||
if (psn) {
|
||||
Symbol* as = scope_lookup(scope, psn);
|
||||
if (as && as->is_type_alias) {
|
||||
pt = as->type;
|
||||
psn = as->struct_type_name;
|
||||
// 更新 AST 节点
|
||||
p->as.parameter.type = pt;
|
||||
p->as.parameter.struct_type_name = psn;
|
||||
}
|
||||
}
|
||||
Symbol* sym = scope_insert(fn_scope, a, p->as.parameter.name, SYM_PARAMETER, pt);
|
||||
if (sym && pt == TYPE_STRUCT && psn) {
|
||||
sym->struct_type_name = psn;
|
||||
}
|
||||
}
|
||||
// 解析返回类型的别名
|
||||
const char* ret_sn = node->as.function.return_struct_type_name;
|
||||
if (ret_sn) {
|
||||
Symbol* as = scope_lookup(scope, ret_sn);
|
||||
if (as && as->is_type_alias) {
|
||||
node->as.function.return_type = as->type;
|
||||
node->as.function.return_struct_type_name = as->struct_type_name;
|
||||
}
|
||||
}
|
||||
TypeKind saved = current_return_type;
|
||||
@@ -355,15 +422,22 @@ static void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
if (node->as.let_stmt.has_type_annot) {
|
||||
const char* annot_struct = node->as.let_stmt.struct_type_name;
|
||||
if (annot_struct) {
|
||||
// struct 类型标注
|
||||
Symbol* st_sym = scope_lookup_struct(scope, annot_struct);
|
||||
if (!st_sym) {
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"未定义的结构体类型 '%s'", annot_struct);
|
||||
break;
|
||||
// 先检查是否是类型别名
|
||||
Symbol* alias_sym = scope_lookup(scope, annot_struct);
|
||||
if (alias_sym && alias_sym->is_type_alias) {
|
||||
var_type = alias_sym->type;
|
||||
var_struct_name = alias_sym->struct_type_name;
|
||||
} else {
|
||||
// struct 类型标注
|
||||
Symbol* st_sym = scope_lookup_struct(scope, annot_struct);
|
||||
if (!st_sym) {
|
||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||
"未定义的类型 '%s'", annot_struct);
|
||||
break;
|
||||
}
|
||||
var_type = TYPE_STRUCT;
|
||||
var_struct_name = annot_struct;
|
||||
}
|
||||
var_type = TYPE_STRUCT;
|
||||
var_struct_name = annot_struct;
|
||||
} else {
|
||||
var_type = node->as.let_stmt.annot_type;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ Symbol* scope_insert(Scope* scope, void* alloc, const char* name,
|
||||
sym->struct_field_types = NULL;
|
||||
sym->struct_field_count = 0;
|
||||
sym->struct_type_name = NULL;
|
||||
sym->is_type_alias = false;
|
||||
sym->next = scope->head;
|
||||
scope->head = sym;
|
||||
return sym;
|
||||
@@ -60,6 +61,7 @@ Symbol* scope_insert_function(Scope* scope, void* alloc, const char* name,
|
||||
sym->struct_field_types = NULL;
|
||||
sym->struct_field_count = 0;
|
||||
sym->struct_type_name = NULL;
|
||||
sym->is_type_alias = false;
|
||||
sym->next = scope->head;
|
||||
scope->head = sym;
|
||||
return sym;
|
||||
@@ -83,6 +85,7 @@ Symbol* scope_insert_struct(Scope* scope, void* alloc, const char* name,
|
||||
sym->struct_field_struct_names = fstruct_names;
|
||||
sym->struct_field_count = fc;
|
||||
sym->struct_type_name = NULL;
|
||||
sym->is_type_alias = false;
|
||||
sym->next = scope->head;
|
||||
scope->head = sym;
|
||||
return sym;
|
||||
|
||||
@@ -24,6 +24,8 @@ typedef struct Symbol {
|
||||
size_t struct_field_count;
|
||||
// 变量引用结构体类型时,记录具体类型名
|
||||
const char* struct_type_name;
|
||||
// 类型别名标记
|
||||
bool is_type_alias;
|
||||
// 链表(同一作用域内的下一个符号)
|
||||
struct Symbol* next;
|
||||
} Symbol;
|
||||
|
||||
Reference in New Issue
Block a user