From 18722216664752d8db013fa3d3c96bbf9fe242ce Mon Sep 17 00:00:00 2001 From: Luke Date: Tue, 26 Aug 2025 01:16:26 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E4=BC=98=E5=8C=96=E8=B5=8B?= =?UTF-8?q?=E5=80=BC=E8=AF=AD=E5=8F=A5=E8=AF=AD=E4=B9=89=E5=88=86=E6=9E=90?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../statement/AssignmentAnalyzer.java | 64 +++++++++++-------- 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/statement/AssignmentAnalyzer.java b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/statement/AssignmentAnalyzer.java index 3cd43f4..2ad7232 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/statement/AssignmentAnalyzer.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/statement/AssignmentAnalyzer.java @@ -6,22 +6,28 @@ import org.jcnc.snow.compiler.semantic.analyzers.base.StatementAnalyzer; import org.jcnc.snow.compiler.semantic.core.Context; import org.jcnc.snow.compiler.semantic.core.ModuleInfo; import org.jcnc.snow.compiler.semantic.error.SemanticError; -import org.jcnc.snow.compiler.semantic.symbol.*; +import org.jcnc.snow.compiler.semantic.symbol.Symbol; +import org.jcnc.snow.compiler.semantic.symbol.SymbolKind; +import org.jcnc.snow.compiler.semantic.symbol.SymbolTable; import org.jcnc.snow.compiler.semantic.type.Type; /** - * {@code AssignmentAnalyzer} 是赋值语句的语义分析器。 - *

- * 负责分析和验证赋值语句的合法性,包括: + * {@code AssignmentAnalyzer} 负责对赋值语句进行语义校验。 + * + *

校验要点

* - * 若类型不兼容且无法自动宽化,则将记录语义错误并输出日志信息。 + * + * 任何不满足条件的情况都会向 {@link Context#getErrors()} 记录 {@link SemanticError}。 */ public class AssignmentAnalyzer implements StatementAnalyzer { + /** 错误消息前缀,统一便于搜索定位 */ + private static final String ERR_PREFIX = "赋值错误: "; + /** * 分析赋值语句的语义有效性,包括左值合法性与类型匹配性。 * @@ -41,29 +47,37 @@ public class AssignmentAnalyzer implements StatementAnalyzer { // 获取赋值左值变量名并进行符号解析 ctx.log("赋值检查: " + asg.variable()); Symbol sym = locals.resolve(asg.variable()); - - // 检查变量是否已声明且为可赋值的变量类型 - if (sym == null || sym.kind() != SymbolKind.VARIABLE) { + if (sym == null) { ctx.getErrors().add(new SemanticError(asg, - "未声明的变量: " + asg.variable())); - ctx.log("错误: 未声明的变量 " + asg.variable()); + ERR_PREFIX + "未声明的变量: " + asg.variable())); + ctx.log(ERR_PREFIX + "未声明的变量 " + asg.variable()); + return; // 无需继续后续检查 + } + + /* ---------- 2. 常量不可修改 ---------- */ + if (sym.kind() == SymbolKind.CONSTANT) { + ctx.getErrors().add(new SemanticError(asg, + ERR_PREFIX + "无法修改常量: " + asg.variable())); + ctx.log(ERR_PREFIX + "尝试修改常量 " + asg.variable()); return; } - // 分析右值表达式类型 - Type valType = ctx.getRegistry().getExpressionAnalyzer(asg.value()) + /* ---------- 3. 右值类型分析 ---------- */ + Type rhsType = ctx.getRegistry() + .getExpressionAnalyzer(asg.value()) .analyze(ctx, mi, fn, locals, asg.value()); - // 类型检查: 若类型不兼容,则尝试判断是否允许宽化转换 - if (!sym.type().isCompatible(valType)) { - // 数值类型允许自动宽化转换(如 int → double) - if (!(sym.type().isNumeric() && valType.isNumeric() - && Type.widen(valType, sym.type()) == sym.type())) { - ctx.getErrors().add(new SemanticError(asg, - "赋值类型不匹配: 期望 " + sym.type() - + ", 实际 " + valType)); - ctx.log("错误: 赋值类型不匹配 " + asg.variable()); - } + /* ---------- 4. 类型兼容性检查 ---------- */ + boolean compatible = sym.type().isCompatible(rhsType); + boolean widenOK = sym.type().isNumeric() + && rhsType.isNumeric() + && Type.widen(rhsType, sym.type()) == sym.type(); + + if (!compatible && !widenOK) { + ctx.getErrors().add(new SemanticError(asg, + ERR_PREFIX + "类型不匹配: 期望 " + + sym.type() + ", 实际 " + rhsType)); + ctx.log(ERR_PREFIX + "类型不匹配 " + asg.variable()); } } }