feat: let mut + 赋值语句 — while 循环可修改变量
- lexer: 新增 TOK_MUT 关键字 - ast: AST_ASSIGN_STMT 节点 + let_stmt.is_mut 标志 - parser: ‘let mut’ 前缀识别 + ‘ident = expr;’ 赋值语句 - sema: Symbol.is_mut 可变性检查(不可变变量赋值报错) - codegen: AST_ASSIGN_STMT → store 指令 - 新增集成测试 06_mut_while.l(while 循环 + 计数器) 基于 Codex 分析报告 P0 建议。
This commit is contained in:
+36
-1
@@ -204,13 +204,48 @@ static void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
||||
}
|
||||
|
||||
node->type.kind = var_type;
|
||||
if (!scope_insert(scope, a, node->as.let_stmt.name, SYM_VARIABLE, var_type)) {
|
||||
Symbol* sym = scope_insert(scope, a, node->as.let_stmt.name, SYM_VARIABLE, var_type);
|
||||
if (!sym) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
"变量 '%s' 重复定义", node->as.let_stmt.name);
|
||||
} else {
|
||||
sym->is_mut = node->as.let_stmt.is_mut;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case AST_ASSIGN_STMT: {
|
||||
Symbol* sym = scope_lookup(scope, node->as.assign_stmt.name);
|
||||
if (!sym) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
"未定义的变量 '%s'", node->as.assign_stmt.name);
|
||||
node->type.kind = TYPE_ERROR;
|
||||
break;
|
||||
}
|
||||
if (sym->kind != SYM_VARIABLE) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
"'%s' 不是变量,不能赋值", node->as.assign_stmt.name);
|
||||
node->type.kind = TYPE_ERROR;
|
||||
break;
|
||||
}
|
||||
if (!sym->is_mut) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
"不能对不可变变量 '%s' 赋值(需用 let mut 声明)",
|
||||
node->as.assign_stmt.name);
|
||||
node->type.kind = TYPE_ERROR;
|
||||
break;
|
||||
}
|
||||
analyze_expr(node->as.assign_stmt.value, scope, errors, a);
|
||||
TypeKind value_ty = node->as.assign_stmt.value->type.kind;
|
||||
if (value_ty != TYPE_ERROR && value_ty != sym->type) {
|
||||
error_add(errors, "<sema>", node->line, node->col,
|
||||
"赋值类型不匹配: 变量 '%s' 类型为 '%s',但表达式类型为 '%s'",
|
||||
node->as.assign_stmt.name, type_name(sym->type), type_name(value_ty));
|
||||
}
|
||||
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