diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/CallExpressionAnalyzer.java b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/CallExpressionAnalyzer.java
index c71f54a..ee30418 100644
--- a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/CallExpressionAnalyzer.java
+++ b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/CallExpressionAnalyzer.java
@@ -1,44 +1,74 @@
package org.jcnc.snow.compiler.semantic.analyzers.expression;
-import org.jcnc.snow.compiler.parser.ast.*;
+import org.jcnc.snow.compiler.parser.ast.CallExpressionNode;
+import org.jcnc.snow.compiler.parser.ast.FunctionNode;
+import org.jcnc.snow.compiler.parser.ast.IdentifierNode;
+import org.jcnc.snow.compiler.parser.ast.MemberExpressionNode;
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
-import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
import org.jcnc.snow.compiler.semantic.analyzers.base.ExpressionAnalyzer;
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.Symbol;
import org.jcnc.snow.compiler.semantic.symbol.SymbolTable;
import org.jcnc.snow.compiler.semantic.type.BuiltinType;
import org.jcnc.snow.compiler.semantic.type.FunctionType;
+import org.jcnc.snow.compiler.semantic.type.StructType;
import org.jcnc.snow.compiler.semantic.type.Type;
import java.util.ArrayList;
import java.util.List;
/**
- * {@code CallExpressionAnalyzer} 是函数调用表达式的语义分析器。
- *
- * 它负责处理类似 {@code callee(arg1, arg2, ...)} 形式的调用表达式,执行如下操作:
+ * {@code CallExpressionAnalyzer} 是函数调用表达式 ({@link CallExpressionNode}) 的语义分析器。
+ *
+ *
它负责处理所有形式的调用表达式(如 {@code callee(arg1, arg2, ...)}),并执行如下操作:
*
- * - 识别调用目标(支持模块成员函数调用和当前模块函数调用,也支持自动在所有已导入模块中查找唯一同名函数);
- * - 根据被调用函数的参数签名检查实参数量和类型的兼容性;
- * - 支持数值参数的宽化转换(如 int → double);
- * - 支持数值到字符串的隐式转换(自动视为调用 {@code to_string});
- * - 在发生类型不匹配、未导入模块或函数未定义等情况下记录语义错误。
- * - 新增:以"_"开头的函数名只允许在本模块访问,禁止跨模块访问。
+ * - 识别调用目标:支持三种调用方式
+ *
+ * - 模块函数调用: {@code module.func(...)}
+ * - 结构体实例方法调用: {@code instance.method(...)}
+ * - 普通函数调用(当前模块或导入模块): {@code func(...)}
+ *
+ *
+ * - 在函数解析时遵循如下规则:
+ *
+ * - 若是模块调用,必须确认模块已导入。
+ * - 若是结构体实例调用,需先解析左侧表达式类型并确认方法存在。
+ * - 若是普通函数调用,优先在当前模块中查找,若未找到,则尝试唯一导入模块解析。
+ *
+ *
+ * - 参数检查与类型推断:
+ *
+ * - 检查实参与形参数量是否一致。
+ * - 检查类型兼容性,支持数值宽化转换 (int → double)。
+ * - 支持数值到字符串的隐式转换(自动视为调用 {@code to_string})。
+ *
+ *
+ * - 错误处理:
+ *
+ * - 函数/方法未定义时记录 {@link SemanticError}。
+ * - 访问未导入的模块时报错。
+ * - 跨模块访问私有函数(以 "_" 开头)时报错。
+ * - 参数数量或类型不匹配时报错。
+ *
+ *
+ * - 最终返回函数的返回类型;若分析过程中存在错误,返回 {@link BuiltinType#INT} 作为默认回退类型。
*
+ *
+ * 此分析器是编译器语义分析阶段的重要组成部分,确保调用表达式在类型系统和模块作用域中合法。
*/
public class CallExpressionAnalyzer implements ExpressionAnalyzer {
/**
- * 分析函数调用表达式并推断其类型。
+ * 分析函数调用表达式,推断返回类型并执行语义检查。
*
* @param ctx 当前语义分析上下文,提供日志、错误记录、模块访问等功能。
* @param mi 当前模块信息,用于函数查找及模块依赖判断。
- * @param fn 当前分析的函数节点。
- * @param locals 局部符号表,用于变量查找。
+ * @param fn 当前正在分析的函数节点(函数作用域)。
+ * @param locals 局部符号表,用于变量和结构体实例查找。
* @param call 待分析的函数调用表达式节点。
- * @return 表达式的返回类型。如果存在语义错误,默认返回 {@code BuiltinType.INT}。
+ * @return 调用表达式的返回类型;若存在语义错误,返回 {@link BuiltinType#INT}。
*/
@Override
public Type analyze(Context ctx,
@@ -46,88 +76,148 @@ public class CallExpressionAnalyzer implements ExpressionAnalyzer args = new ArrayList<>();
for (ExpressionNode arg : call.arguments()) {
args.add(ctx.getRegistry().getExpressionAnalyzer(arg)
.analyze(ctx, mi, fn, locals, arg));
}
- // 参数数量检查
- if (args.size() != ft.paramTypes().size()) {
+ // -------- 参数数量检查 --------
+ if (args.size() != funcType.paramTypes().size()) {
ctx.getErrors().add(new SemanticError(call,
- "参数数量不匹配: 期望 " + ft.paramTypes().size()
+ "参数数量不匹配: 期望 " + funcType.paramTypes().size()
+ " 个, 实际 " + args.size() + " 个"));
ctx.log("错误: 参数数量不匹配: 期望 "
- + ft.paramTypes().size() + ", 实际 " + args.size());
-
+ + funcType.paramTypes().size() + ", 实际 " + args.size());
} else {
- // 参数类型检查与转换支持
+ // -------- 参数类型检查与转换 --------
for (int i = 0; i < args.size(); i++) {
- Type expected = ft.paramTypes().get(i);
- Type actual = args.get(i);
+ Type expected = funcType.paramTypes().get(i);
+ Type actual = args.get(i);
- // 完全兼容或数值宽化转换
boolean ok = expected.isCompatible(actual)
|| (expected.isNumeric() && actual.isNumeric()
&& Type.widen(actual, expected) == expected);
- // 支持将数值自动转换为字符串
+ // 特殊情况:数值自动转 string
if (!ok && expected == BuiltinType.STRING && actual.isNumeric()) {
ctx.log(String.format(
"隐式将参数 %d 的数值类型 %s 转换为 string (to_string)",
@@ -136,7 +226,6 @@ public class CallExpressionAnalyzer implements ExpressionAnalyzer