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:
+106
-28
@@ -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 &&
|
||||
|
||||
Reference in New Issue
Block a user