feat: 数组+索引 [T;N], arr[i] (P1 #6)

- lexer: TOK_LBRACKET, TOK_RBRACKET
- type: TYPE_ARRAY + TypeInfo扩展(element_type/array_size)
- ast: AST_INDEX_EXPR, AST_ARRAY_ASSIGN_STMT
- parser: parse_type_expr()支持[T;N], Pratt加[索引], 数组元素赋值
- sema: 数组类型检查, 索引必须i64, 元素赋值类型匹配
- codegen: type_info_to_llvm(TYPE_ARRAY), GEP+load/store
- 新增集成测试: 18_array.l

测试: 136 通过 (41+15+59+21)
This commit is contained in:
2026-06-05 14:19:01 +08:00
parent 5237398245
commit 2923e7574d
14 changed files with 512 additions and 58 deletions
+106 -28
View File
@@ -51,6 +51,11 @@ static void analyze_expr(AstNode* node, Scope* scope, ErrorList* errors, Arena*
if (sym->type == TYPE_STRUCT && sym->struct_type_name) {
node->type.struct_name = sym->struct_type_name;
}
if (sym->type == TYPE_ARRAY) {
node->type.element_type = sym->array_element_type;
node->type.element_struct_name = sym->array_element_struct_name;
node->type.array_size = sym->array_size;
}
}
break;
}
@@ -316,6 +321,30 @@ static void analyze_expr(AstNode* node, Scope* scope, ErrorList* errors, Arena*
break;
}
case AST_INDEX_EXPR: {
analyze_expr(node->as.index_expr.array, scope, errors, a);
analyze_expr(node->as.index_expr.index, scope, errors, a);
AstNode* arr = node->as.index_expr.array;
AstNode* idx = node->as.index_expr.index;
if (arr->type.kind == TYPE_ERROR) { node->type.kind = TYPE_ERROR; break; }
if (arr->type.kind != TYPE_ARRAY) {
error_add(errors, "<sema>", node->loc.line, node->loc.col,
"类型 '%s' 不支持索引操作", type_name(arr->type.kind));
node->type.kind = TYPE_ERROR; break;
}
if (idx->type.kind == TYPE_ERROR) { node->type.kind = TYPE_ERROR; break; }
if (idx->type.kind != TYPE_I64) {
error_add(errors, "<sema>", node->loc.line, node->loc.col,
"数组索引必须是 i64 类型, 得到 '%s'", type_name(idx->type.kind));
node->type.kind = TYPE_ERROR; break;
}
// 结果类型 = 元素类型
node->type.kind = arr->type.element_type;
node->type.struct_name = arr->type.element_struct_name;
break;
}
default: break;
}
}
@@ -450,41 +479,50 @@ static void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena*
break;
case AST_LET_STMT: {
analyze_expr(node->as.let_stmt.init, scope, errors, a);
TypeKind inferred = node->as.let_stmt.init->type.kind;
TypeKind var_type;
const char* var_struct_name = NULL;
bool is_array_type = false;
if (node->as.let_stmt.has_type_annot) {
const char* annot_struct = node->as.let_stmt.struct_type_name;
if (annot_struct) {
// 先检查是否是类型别名
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;
}
if (node->as.let_stmt.annot_type == TYPE_ARRAY) {
// 数组类型标注: 跳过 init 分析 (init 是自引用的占位符)
is_array_type = true;
var_type = TYPE_ARRAY;
} else {
var_type = node->as.let_stmt.annot_type;
}
if (inferred != TYPE_ERROR && inferred != var_type) {
error_add(errors, "<sema>", node->loc.line, node->loc.col,
"变量 '%s' 类型标注为 '%s',但初始化表达式类型为 '%s'",
node->as.let_stmt.name,
annot_struct ? annot_struct : type_name(var_type),
type_name(inferred));
analyze_expr(node->as.let_stmt.init, scope, errors, a);
TypeKind inferred = node->as.let_stmt.init->type.kind;
const char* annot_struct = node->as.let_stmt.struct_type_name;
if (annot_struct) {
// 先检查是否是类型别名
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;
}
} else {
var_type = node->as.let_stmt.annot_type;
}
if (inferred != TYPE_ERROR && inferred != var_type) {
error_add(errors, "<sema>", node->loc.line, node->loc.col,
"变量 '%s' 类型标注为 '%s',但初始化表达式类型为 '%s'",
node->as.let_stmt.name,
annot_struct ? annot_struct : type_name(var_type),
type_name(inferred));
}
}
} else {
analyze_expr(node->as.let_stmt.init, scope, errors, a);
TypeKind inferred = node->as.let_stmt.init->type.kind;
// 类型推断
if (inferred == TYPE_ERROR || inferred == TYPE_VOID) {
error_add(errors, "<sema>", node->loc.line, node->loc.col,
@@ -499,6 +537,11 @@ static void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena*
node->type.kind = var_type;
node->type.struct_name = var_struct_name;
if (is_array_type) {
node->type.element_type = node->as.let_stmt.annot_element_type;
node->type.element_struct_name = node->as.let_stmt.annot_element_struct_name;
node->type.array_size = node->as.let_stmt.annot_array_size;
}
Symbol* sym = scope_insert(scope, a, node->as.let_stmt.name, SYM_VARIABLE, var_type);
if (!sym) {
error_add(errors, "<sema>", node->loc.line, node->loc.col,
@@ -509,6 +552,11 @@ static void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena*
sym->type = TYPE_STRUCT;
sym->struct_type_name = var_struct_name;
}
if (is_array_type) {
sym->array_element_type = node->type.element_type;
sym->array_element_struct_name = node->type.element_struct_name;
sym->array_size = node->type.array_size;
}
}
break;
}
@@ -545,6 +593,36 @@ static void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena*
break;
}
case AST_ARRAY_ASSIGN_STMT: {
Symbol* sym = scope_lookup(scope, node->as.array_assign.name);
if (!sym) {
error_add(errors, "<sema>", node->loc.line, node->loc.col,
"未定义的变量 '%s'", node->as.array_assign.name);
node->type.kind = TYPE_ERROR; break;
}
if (sym->type != TYPE_ARRAY) {
error_add(errors, "<sema>", node->loc.line, node->loc.col,
"'%s' 不是数组类型,不能使用索引赋值", node->as.array_assign.name);
node->type.kind = TYPE_ERROR; break;
}
analyze_expr(node->as.array_assign.index, scope, errors, a);
analyze_expr(node->as.array_assign.value, scope, errors, a);
AstNode* idx = node->as.array_assign.index;
AstNode* val = node->as.array_assign.value;
if (idx->type.kind != TYPE_ERROR && idx->type.kind != TYPE_I64) {
error_add(errors, "<sema>", node->loc.line, node->loc.col,
"数组索引必须是 i64 类型, 得到 '%s'", type_name(idx->type.kind));
}
TypeKind elem_kind = sym->type == TYPE_ARRAY ? TYPE_I64 : sym->type;
if (val->type.kind != TYPE_ERROR && val->type.kind != elem_kind) {
error_add(errors, "<sema>", node->loc.line, node->loc.col,
"数组元素类型不匹配: 期望 '%s',得到 '%s'",
type_name(elem_kind), type_name(val->type.kind));
}
node->type.kind = TYPE_VOID;
break;
}
case AST_IF_STMT:
analyze_expr(node->as.if_stmt.cond, scope, errors, a);
if (node->as.if_stmt.cond->type.kind != TYPE_BOOL &&