Compare commits
7 Commits
main
...
feature/fu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d065bf3cb | ||
|
|
538005b7dc | ||
|
|
7dca18b6f3 | ||
|
|
50cf0abf80 | ||
|
|
6ea8f88b0a | ||
|
|
6b56e65bce | ||
|
|
92bd94a563 |
10
.run/Demo22.run.xml
Normal file
10
.run/Demo22.run.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Demo22" type="Application" factoryName="Application" folderName="Demo">
|
||||||
|
<option name="MAIN_CLASS_NAME" value="org.jcnc.snow.cli.SnowCLI" />
|
||||||
|
<module name="Snow" />
|
||||||
|
<option name="PROGRAM_PARAMETERS" value="compile run -d playground/Demo/Demo22 -o target/Demo22 --debug" />
|
||||||
|
<method v="2">
|
||||||
|
<option name="Make" enabled="true" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
46
playground/Demo/Demo22/Main.snow
Normal file
46
playground/Demo/Demo22/Main.snow
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
module: Main
|
||||||
|
import: os
|
||||||
|
function: main
|
||||||
|
params:
|
||||||
|
returns: int
|
||||||
|
body:
|
||||||
|
declare x: int = 0
|
||||||
|
|
||||||
|
x = inc(x)
|
||||||
|
println(x)
|
||||||
|
|
||||||
|
x = inc(x, 7)
|
||||||
|
println(x)
|
||||||
|
|
||||||
|
return 0
|
||||||
|
end body
|
||||||
|
end function
|
||||||
|
|
||||||
|
function: inc
|
||||||
|
params:
|
||||||
|
declare num: int
|
||||||
|
returns: int
|
||||||
|
body:
|
||||||
|
return num + 1
|
||||||
|
end body
|
||||||
|
end function
|
||||||
|
|
||||||
|
function: inc
|
||||||
|
params:
|
||||||
|
declare num: int
|
||||||
|
declare v: int
|
||||||
|
returns: int
|
||||||
|
body:
|
||||||
|
return num + v
|
||||||
|
end body
|
||||||
|
end function
|
||||||
|
|
||||||
|
function: println
|
||||||
|
params:
|
||||||
|
declare i1: int
|
||||||
|
returns: void
|
||||||
|
body:
|
||||||
|
os.syscall("PRINTLN",i1)
|
||||||
|
end body
|
||||||
|
end function
|
||||||
|
end module
|
||||||
@ -72,7 +72,8 @@ public class CallGenerator implements InstructionGenerator<CallInstruction> {
|
|||||||
String fn = ins.getFunctionName();
|
String fn = ins.getFunctionName();
|
||||||
|
|
||||||
// 特殊处理 syscall 调用
|
// 特殊处理 syscall 调用
|
||||||
if ("syscall".equals(fn) || fn.endsWith(".syscall")) {
|
String tname = fn.substring(0, fn.lastIndexOf(':'));
|
||||||
|
if ("syscall".equals(tname) || tname.endsWith(".syscall")) {
|
||||||
generateSyscall(ins, out, slotMap, fn);
|
generateSyscall(ins, out, slotMap, fn);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,9 @@ import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.StringJoiner;
|
||||||
|
|
||||||
|
import static org.jcnc.snow.compiler.ir.utils.ExpressionUtils.looksLikeFloat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code ExpressionBuilder} 表达式 → IR 构建器。
|
* {@code ExpressionBuilder} 表达式 → IR 构建器。
|
||||||
@ -377,24 +380,73 @@ public record ExpressionBuilder(IRContext ctx) {
|
|||||||
// 1. 递归生成所有参数的寄存器
|
// 1. 递归生成所有参数的寄存器
|
||||||
List<IRVirtualRegister> argv = call.arguments().stream().map(this::build).toList();
|
List<IRVirtualRegister> argv = call.arguments().stream().map(this::build).toList();
|
||||||
|
|
||||||
// 2. 规范化被调用方法名(区分成员方法与普通函数)
|
// 2. 生成参数列表描述,即(类型_类型)这种格式
|
||||||
|
StringJoiner sj = new StringJoiner("_");
|
||||||
|
for (ExpressionNode param : call.arguments()) {
|
||||||
|
switch (param) {
|
||||||
|
case NumberLiteralNode n -> {
|
||||||
|
String value = n.value();
|
||||||
|
char suffix = value.isEmpty() ? '\0'
|
||||||
|
: Character.toLowerCase(value.charAt(value.length() - 1));
|
||||||
|
|
||||||
|
switch (suffix) {
|
||||||
|
case 'b' -> sj.add("byte");
|
||||||
|
case 's' -> sj.add("short");
|
||||||
|
case 'l' -> sj.add("long");
|
||||||
|
case 'f' -> sj.add("float");
|
||||||
|
case 'd' -> sj.add("double");
|
||||||
|
default -> {
|
||||||
|
if (looksLikeFloat(value)) {
|
||||||
|
sj.add("double");
|
||||||
|
} else {
|
||||||
|
sj.add("int");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case BoolLiteralNode _ -> sj.add("bool");
|
||||||
|
case StringLiteralNode _ -> sj.add("string");
|
||||||
|
case IdentifierNode id -> {
|
||||||
|
String type = ctx.getScope().lookupType(id.name());
|
||||||
|
sj.add(type);
|
||||||
|
}
|
||||||
|
// case CallExpressionNode ce -> {
|
||||||
|
// }
|
||||||
|
case null, default -> throw new IllegalArgumentException("(内部错误) 不支持的参数表达式: " + param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 规范化被调用方法名(区分成员方法与普通函数)
|
||||||
String callee = switch (call.callee()) {
|
String callee = switch (call.callee()) {
|
||||||
// 成员方法调用,如 obj.method()
|
// 成员方法调用,如 obj.method()
|
||||||
case MemberExpressionNode m when m.object() instanceof IdentifierNode id -> id.name() + "." + m.member();
|
case MemberExpressionNode m when m.object() instanceof IdentifierNode id -> {
|
||||||
|
String qualifiedName = id.name() + "." + m.member();
|
||||||
|
if (sj.length() > 0) {
|
||||||
|
qualifiedName = qualifiedName + ":" + sj;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield qualifiedName;
|
||||||
|
}
|
||||||
// 普通函数调用,或处理命名空间前缀(如当前方法名为 namespace.func)
|
// 普通函数调用,或处理命名空间前缀(如当前方法名为 namespace.func)
|
||||||
case IdentifierNode id -> {
|
case IdentifierNode id -> {
|
||||||
String current = ctx.getFunction().name();
|
String current = ctx.getFunction().name();
|
||||||
int dot = current.lastIndexOf('.');
|
int dot = current.lastIndexOf('.');
|
||||||
if (dot > 0)
|
|
||||||
yield current.substring(0, dot) + "." + id.name(); // 同命名空间内调用
|
String qualifiedName = dot > 0
|
||||||
yield id.name(); // 全局函数调用
|
? current.substring(0, dot) + "." + id.name()
|
||||||
|
: id.name();
|
||||||
|
if (sj.length() > 0) {
|
||||||
|
qualifiedName = qualifiedName + ":" + sj;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield qualifiedName; // 全局函数调用
|
||||||
}
|
}
|
||||||
// 其它类型不支持
|
// 其它类型不支持
|
||||||
default -> throw new IllegalStateException(
|
default -> throw new IllegalStateException(
|
||||||
"不支持的调用目标: " + call.callee().getClass().getSimpleName());
|
"不支持的调用目标: " + call.callee().getClass().getSimpleName());
|
||||||
};
|
};
|
||||||
|
|
||||||
// 3. 分配用于存放返回值的新寄存器,并生成 Call 指令
|
// 4. 分配用于存放返回值的新寄存器,并生成 Call 指令
|
||||||
IRVirtualRegister dest = ctx.newRegister();
|
IRVirtualRegister dest = ctx.newRegister();
|
||||||
ctx.addInstruction(new CallInstruction(dest, callee, new ArrayList<>(argv)));
|
ctx.addInstruction(new CallInstruction(dest, callee, new ArrayList<>(argv)));
|
||||||
return dest;
|
return dest;
|
||||||
|
|||||||
@ -57,7 +57,7 @@ public class FunctionBuilder {
|
|||||||
for (ParameterNode p : functionNode.parameters()) {
|
for (ParameterNode p : functionNode.parameters()) {
|
||||||
IRVirtualRegister reg = irFunction.newRegister(); // 新寄存器
|
IRVirtualRegister reg = irFunction.newRegister(); // 新寄存器
|
||||||
irContext.getScope().declare(p.name(), p.type(), reg); // 变量名→寄存器绑定
|
irContext.getScope().declare(p.name(), p.type(), reg); // 变量名→寄存器绑定
|
||||||
irFunction.addParameter(reg); // 添加到函数参数列表
|
irFunction.addParameter(reg, p.type()); // 添加到函数参数列表
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3) 生成函数体 IR: 遍历每条语句,逐一转化
|
// 3) 生成函数体 IR: 遍历每条语句,逐一转化
|
||||||
|
|||||||
@ -4,12 +4,14 @@ import org.jcnc.snow.compiler.ir.core.IRFunction;
|
|||||||
import org.jcnc.snow.compiler.ir.core.IRProgram;
|
import org.jcnc.snow.compiler.ir.core.IRProgram;
|
||||||
import org.jcnc.snow.compiler.parser.ast.FunctionNode;
|
import org.jcnc.snow.compiler.parser.ast.FunctionNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.ModuleNode;
|
import org.jcnc.snow.compiler.parser.ast.ModuleNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.ParameterNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.Node;
|
import org.jcnc.snow.compiler.parser.ast.base.Node;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
import org.jcnc.snow.compiler.parser.ast.base.NodeContext;
|
||||||
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.StringJoiner;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IRProgramBuilder 负责将 AST 根节点(如模块、函数、顶层语句)转换为可执行的 IRProgram 实例。
|
* IRProgramBuilder 负责将 AST 根节点(如模块、函数、顶层语句)转换为可执行的 IRProgram 实例。
|
||||||
@ -66,6 +68,15 @@ public final class IRProgramBuilder {
|
|||||||
private IRFunction buildFunctionWithGlobals(ModuleNode moduleNode, FunctionNode functionNode) {
|
private IRFunction buildFunctionWithGlobals(ModuleNode moduleNode, FunctionNode functionNode) {
|
||||||
// 拼接模块名和函数名,生成全限定名
|
// 拼接模块名和函数名,生成全限定名
|
||||||
String qualifiedName = moduleNode.name() + "." + functionNode.name();
|
String qualifiedName = moduleNode.name() + "." + functionNode.name();
|
||||||
|
|
||||||
|
StringJoiner sj = new StringJoiner("_");
|
||||||
|
for (ParameterNode param : functionNode.parameters()) {
|
||||||
|
sj.add(param.type());
|
||||||
|
}
|
||||||
|
if (sj.length() > 0) {
|
||||||
|
qualifiedName = qualifiedName + ":" + sj;
|
||||||
|
}
|
||||||
|
|
||||||
// 若无全局声明,仅重命名后直接构建
|
// 若无全局声明,仅重命名后直接构建
|
||||||
if (moduleNode.globals() == null || moduleNode.globals().isEmpty()) {
|
if (moduleNode.globals() == null || moduleNode.globals().isEmpty()) {
|
||||||
return buildFunction(renameFunction(functionNode, qualifiedName));
|
return buildFunction(renameFunction(functionNode, qualifiedName));
|
||||||
|
|||||||
@ -35,6 +35,11 @@ public class IRFunction {
|
|||||||
*/
|
*/
|
||||||
private final List<IRVirtualRegister> parameters = new ArrayList<>();
|
private final List<IRVirtualRegister> parameters = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 正式参数所对应的类型,按声明顺序排列。
|
||||||
|
*/
|
||||||
|
private final List<String> parametersType = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造一个具有指定名称的 IRFunction 实例。
|
* 构造一个具有指定名称的 IRFunction 实例。
|
||||||
*
|
*
|
||||||
@ -61,13 +66,15 @@ public class IRFunction {
|
|||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param vr 表示函数某个参数的虚拟寄存器
|
* @param vr 表示函数某个参数的虚拟寄存器
|
||||||
|
* @param type 表示函数某个参数的类型
|
||||||
*/
|
*/
|
||||||
public void addParameter(IRVirtualRegister vr) {
|
public void addParameter(IRVirtualRegister vr, String type) {
|
||||||
parameters.add(vr);
|
parameters.add(vr);
|
||||||
|
parametersType.add(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取函数正式参数的只读列表。
|
* 获取函数正式参数的虚拟寄存器只读列表。
|
||||||
*
|
*
|
||||||
* @return 按声明顺序排列的虚拟寄存器列表
|
* @return 按声明顺序排列的虚拟寄存器列表
|
||||||
*/
|
*/
|
||||||
@ -75,6 +82,15 @@ public class IRFunction {
|
|||||||
return List.copyOf(parameters);
|
return List.copyOf(parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取函数正式参数的类型只读列表。
|
||||||
|
*
|
||||||
|
* @return 按声明顺序排列的类型列表
|
||||||
|
*/
|
||||||
|
public List<String> parametersType() {
|
||||||
|
return List.copyOf(parametersType);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 向函数体末尾追加一条 IR 指令。
|
* 向函数体末尾追加一条 IR 指令。
|
||||||
*
|
*
|
||||||
@ -130,6 +146,7 @@ public class IRFunction {
|
|||||||
.append('(');
|
.append('(');
|
||||||
for (int i = 0; i < parameters.size(); i++) {
|
for (int i = 0; i < parameters.size(); i++) {
|
||||||
sb.append(parameters.get(i));
|
sb.append(parameters.get(i));
|
||||||
|
sb.append(": ").append(parametersType.get(i));
|
||||||
if (i < parameters.size() - 1) {
|
if (i < parameters.size() - 1) {
|
||||||
sb.append(", ");
|
sb.append(", ");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,7 +35,7 @@ public final class ExpressionUtils {
|
|||||||
/**
|
/**
|
||||||
* 设置当前线程的默认类型后缀。
|
* 设置当前线程的默认类型后缀。
|
||||||
*
|
*
|
||||||
* @param suffix 类型后缀字符(b/s/i/l/f/d),'\0'表示无
|
* @param suffix 类型后缀字符(b/s/l/f),'\0'表示无
|
||||||
*/
|
*/
|
||||||
public static void setDefaultSuffix(char suffix) { DEFAULT_SUFFIX.set(suffix); }
|
public static void setDefaultSuffix(char suffix) { DEFAULT_SUFFIX.set(suffix); }
|
||||||
|
|
||||||
@ -47,21 +47,21 @@ public final class ExpressionUtils {
|
|||||||
// ───────────── 字面量常量解析 ─────────────
|
// ───────────── 字面量常量解析 ─────────────
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 安全解析整数字面量字符串,自动去除单字符类型后缀(b/s/l/f/d,大小写均可),并转换为 int。
|
* 安全解析整数字面量字符串,自动去除单字符类型后缀(b/s/l/f,大小写均可),并转换为 int。
|
||||||
*
|
*
|
||||||
* @param literal 字面量字符串
|
* @param literal 字面量字符串
|
||||||
* @return 字面量对应的 int 数值
|
* @return 字面量对应的 int 数值
|
||||||
* @throws NumberFormatException 如果字面量无法转换为整数
|
* @throws NumberFormatException 如果字面量无法转换为整数
|
||||||
*/
|
*/
|
||||||
public static int parseIntSafely(String literal) {
|
public static int parseIntSafely(String literal) {
|
||||||
String digits = literal.replaceAll("[bslfdBSDLF]$", "");
|
String digits = literal.replaceAll("[bslfBSLF]$", "");
|
||||||
return Integer.parseInt(digits);
|
return Integer.parseInt(digits);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据数字字面量字符串推断类型并生成对应的 IRConstant 常量值。
|
* 根据数字字面量字符串推断类型并生成对应的 IRConstant 常量值。
|
||||||
* <p>
|
* <p>
|
||||||
* 支持的字面量后缀有 b/s/l/f/d(大小写均可)。
|
* 支持的字面量后缀有 b/s/l/f(大小写均可)。
|
||||||
* 无后缀时,优先参考 IRContext 当前变量类型,否则根据字面量格式(含'.'或'e'等)判断为 double,否则为 int。
|
* 无后缀时,优先参考 IRContext 当前变量类型,否则根据字面量格式(含'.'或'e'等)判断为 double,否则为 int。
|
||||||
*
|
*
|
||||||
* @param ctx IRContext,允许参考变量声明类型
|
* @param ctx IRContext,允许参考变量声明类型
|
||||||
@ -73,7 +73,7 @@ public final class ExpressionUtils {
|
|||||||
: Character.toLowerCase(value.charAt(value.length() - 1));
|
: Character.toLowerCase(value.charAt(value.length() - 1));
|
||||||
|
|
||||||
String digits = switch (suffix) {
|
String digits = switch (suffix) {
|
||||||
case 'b','s','l','f','d' -> value.substring(0, value.length() - 1);
|
case 'b','s','l','f' -> value.substring(0, value.length() - 1);
|
||||||
default -> {
|
default -> {
|
||||||
// 无后缀,优先参考变量类型
|
// 无后缀,优先参考变量类型
|
||||||
if (ctx.getVarType() != null) {
|
if (ctx.getVarType() != null) {
|
||||||
@ -249,7 +249,7 @@ public final class ExpressionUtils {
|
|||||||
* @param digits 字面量字符串
|
* @param digits 字面量字符串
|
||||||
* @return 是浮点格式则返回 true
|
* @return 是浮点格式则返回 true
|
||||||
*/
|
*/
|
||||||
private static boolean looksLikeFloat(String digits) {
|
public static boolean looksLikeFloat(String digits) {
|
||||||
return digits.indexOf('.') >= 0
|
return digits.indexOf('.') >= 0
|
||||||
|| digits.indexOf('e') >= 0
|
|| digits.indexOf('e') >= 0
|
||||||
|| digits.indexOf('E') >= 0;
|
|| digits.indexOf('E') >= 0;
|
||||||
|
|||||||
@ -77,8 +77,15 @@ public class CallExpressionAnalyzer implements ExpressionAnalyzer<CallExpression
|
|||||||
return BuiltinType.INT;
|
return BuiltinType.INT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 分析所有实参并获取类型
|
||||||
|
List<Type> args = new ArrayList<>();
|
||||||
|
for (ExpressionNode arg : call.arguments()) {
|
||||||
|
args.add(ctx.getRegistry().getExpressionAnalyzer(arg)
|
||||||
|
.analyze(ctx, mi, fn, locals, arg));
|
||||||
|
}
|
||||||
|
|
||||||
// 查找目标函数签名(先在当前模块/显式模块查找)
|
// 查找目标函数签名(先在当前模块/显式模块查找)
|
||||||
FunctionType ft = target.getFunctions().get(functionName);
|
FunctionType ft = target.retrieveFunction(functionName, args);
|
||||||
|
|
||||||
// 未找到则报错
|
// 未找到则报错
|
||||||
if (ft == null) {
|
if (ft == null) {
|
||||||
@ -88,13 +95,6 @@ public class CallExpressionAnalyzer implements ExpressionAnalyzer<CallExpression
|
|||||||
return BuiltinType.INT;
|
return BuiltinType.INT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 分析所有实参并获取类型
|
|
||||||
List<Type> 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() != ft.paramTypes().size()) {
|
||||||
ctx.getErrors().add(new SemanticError(call,
|
ctx.getErrors().add(new SemanticError(call,
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package org.jcnc.snow.compiler.semantic.analyzers.statement;
|
package org.jcnc.snow.compiler.semantic.analyzers.statement;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.parser.ast.FunctionNode;
|
import org.jcnc.snow.compiler.parser.ast.FunctionNode;
|
||||||
|
import org.jcnc.snow.compiler.parser.ast.ParameterNode;
|
||||||
import org.jcnc.snow.compiler.parser.ast.ReturnNode;
|
import org.jcnc.snow.compiler.parser.ast.ReturnNode;
|
||||||
import org.jcnc.snow.compiler.semantic.analyzers.base.StatementAnalyzer;
|
import org.jcnc.snow.compiler.semantic.analyzers.base.StatementAnalyzer;
|
||||||
import org.jcnc.snow.compiler.semantic.core.Context;
|
import org.jcnc.snow.compiler.semantic.core.Context;
|
||||||
@ -11,6 +12,9 @@ import org.jcnc.snow.compiler.semantic.type.BuiltinType;
|
|||||||
import org.jcnc.snow.compiler.semantic.type.FunctionType;
|
import org.jcnc.snow.compiler.semantic.type.FunctionType;
|
||||||
import org.jcnc.snow.compiler.semantic.type.Type;
|
import org.jcnc.snow.compiler.semantic.type.Type;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code ReturnAnalyzer} 是用于分析 {@link ReturnNode} 返回语句的语义分析器。
|
* {@code ReturnAnalyzer} 是用于分析 {@link ReturnNode} 返回语句的语义分析器。
|
||||||
* <p>
|
* <p>
|
||||||
@ -42,12 +46,32 @@ public class ReturnAnalyzer implements StatementAnalyzer<ReturnNode> {
|
|||||||
|
|
||||||
ctx.log("检查 return");
|
ctx.log("检查 return");
|
||||||
|
|
||||||
// 获取当前函数的定义信息
|
// 获取当前函数的重载列表
|
||||||
FunctionType expected = ctx.getModules()
|
var overloading = ctx.getModules()
|
||||||
.get(mi.getName())
|
.get(mi.getName())
|
||||||
.getFunctions()
|
.getFunctions()
|
||||||
.get(fn.name());
|
.get(fn.name());
|
||||||
|
|
||||||
|
List<Type> params = new ArrayList<>();
|
||||||
|
for (ParameterNode pn : fn.parameters()) {
|
||||||
|
params.add(locals.resolve(pn.name()).type());
|
||||||
|
}
|
||||||
|
|
||||||
|
// fn 对应的函数签名
|
||||||
|
FunctionType expected = overloading.stream()
|
||||||
|
.filter(ft -> ft.paramTypes().equals(params))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
if (expected == null) {
|
||||||
|
ctx.getErrors().add(new SemanticError(
|
||||||
|
fn,
|
||||||
|
"不存在的函数签名: " + params
|
||||||
|
));
|
||||||
|
ctx.log("不存在的函数签名: " + params);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 情况 1: 存在返回表达式,需进行类型检查
|
// 情况 1: 存在返回表达式,需进行类型检查
|
||||||
ret.getExpression().ifPresentOrElse(exp -> {
|
ret.getExpression().ifPresentOrElse(exp -> {
|
||||||
var exprAnalyzer = ctx.getRegistry().getExpressionAnalyzer(exp);
|
var exprAnalyzer = ctx.getRegistry().getExpressionAnalyzer(exp);
|
||||||
|
|||||||
@ -62,14 +62,54 @@ public final class BuiltinTypeRegistry {
|
|||||||
/* ---------- 注册标准库 os ---------- */
|
/* ---------- 注册标准库 os ---------- */
|
||||||
ModuleInfo utils = new ModuleInfo("os");
|
ModuleInfo utils = new ModuleInfo("os");
|
||||||
|
|
||||||
// syscall(string, int): void —— 供标准库内部使用的调用接口
|
/* syscall(string, type): void 的一组重载 */
|
||||||
utils.getFunctions().put(
|
List<FunctionType> overloading = new ArrayList<>();
|
||||||
"syscall",
|
{
|
||||||
new FunctionType(
|
// syscall(string, byte): void
|
||||||
Arrays.asList(BuiltinType.STRING, BuiltinType.INT),
|
overloading.add(new FunctionType(
|
||||||
BuiltinType.VOID
|
Arrays.asList(BuiltinType.STRING, BuiltinType.BYTE),
|
||||||
)
|
BuiltinType.VOID
|
||||||
);
|
));
|
||||||
|
|
||||||
|
// syscall(string, short): void
|
||||||
|
overloading.add(new FunctionType(
|
||||||
|
Arrays.asList(BuiltinType.STRING, BuiltinType.SHORT),
|
||||||
|
BuiltinType.VOID
|
||||||
|
));
|
||||||
|
|
||||||
|
// syscall(string, int): void
|
||||||
|
overloading.add(new FunctionType(
|
||||||
|
Arrays.asList(BuiltinType.STRING, BuiltinType.INT),
|
||||||
|
BuiltinType.VOID
|
||||||
|
));
|
||||||
|
|
||||||
|
// syscall(string, long): void
|
||||||
|
overloading.add(new FunctionType(
|
||||||
|
Arrays.asList(BuiltinType.STRING, BuiltinType.LONG),
|
||||||
|
BuiltinType.VOID
|
||||||
|
));
|
||||||
|
|
||||||
|
// syscall(string, float): void
|
||||||
|
overloading.add(new FunctionType(
|
||||||
|
Arrays.asList(BuiltinType.STRING, BuiltinType.FLOAT),
|
||||||
|
BuiltinType.VOID
|
||||||
|
));
|
||||||
|
|
||||||
|
// syscall(string, double): void
|
||||||
|
overloading.add(new FunctionType(
|
||||||
|
Arrays.asList(BuiltinType.STRING, BuiltinType.DOUBLE),
|
||||||
|
BuiltinType.VOID
|
||||||
|
));
|
||||||
|
|
||||||
|
// syscall(string, boolean): void
|
||||||
|
overloading.add(new FunctionType(
|
||||||
|
Arrays.asList(BuiltinType.STRING, BuiltinType.BOOLEAN),
|
||||||
|
BuiltinType.VOID
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// syscall(string, `type`): void —— 供标准库内部使用的调用接口
|
||||||
|
utils.getFunctions().put("syscall", overloading);
|
||||||
|
|
||||||
// 注册 BuiltinUtils 到上下文的模块表(若已存在则不重复添加)
|
// 注册 BuiltinUtils 到上下文的模块表(若已存在则不重复添加)
|
||||||
ctx.getModules().putIfAbsent("os", utils);
|
ctx.getModules().putIfAbsent("os", utils);
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package org.jcnc.snow.compiler.semantic.core;
|
package org.jcnc.snow.compiler.semantic.core;
|
||||||
|
|
||||||
import org.jcnc.snow.compiler.semantic.type.FunctionType;
|
import org.jcnc.snow.compiler.semantic.type.FunctionType;
|
||||||
|
import org.jcnc.snow.compiler.semantic.type.Type;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@ -25,8 +26,8 @@ public class ModuleInfo {
|
|||||||
/** 该模块显式导入的模块名集合(用于跨模块访问符号) */
|
/** 该模块显式导入的模块名集合(用于跨模块访问符号) */
|
||||||
private final Set<String> imports = new HashSet<>();
|
private final Set<String> imports = new HashSet<>();
|
||||||
|
|
||||||
/** 该模块中定义的函数名 → 函数类型映射 */
|
/** 该模块中定义的函数名 → 函数类型列表映射 */
|
||||||
private final Map<String, FunctionType> functions = new HashMap<>();
|
private final Map<String, List<FunctionType>> functions = new HashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造模块信息对象。
|
* 构造模块信息对象。
|
||||||
@ -65,8 +66,57 @@ public class ModuleInfo {
|
|||||||
*
|
*
|
||||||
* @return 模块内函数定义映射表
|
* @return 模块内函数定义映射表
|
||||||
*/
|
*/
|
||||||
public Map<String, FunctionType> getFunctions() {
|
public Map<String, List<FunctionType>> getFunctions() {
|
||||||
return functions;
|
return functions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加一个新的函数类型
|
||||||
|
*
|
||||||
|
* @param name 函数名
|
||||||
|
* @param ft 函数类型
|
||||||
|
*/
|
||||||
|
public void addFunction(String name, FunctionType ft) {
|
||||||
|
if (!functions.containsKey(name)) {
|
||||||
|
functions.put(name, new ArrayList<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
functions.get(name).add(ft);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断函数类型是否存在
|
||||||
|
*
|
||||||
|
* @param name 函数名
|
||||||
|
* @param ft 函数类型
|
||||||
|
* @return 函数类型存在则返回 true,否则 false
|
||||||
|
*/
|
||||||
|
public boolean existsFunction(String name, FunctionType ft) {
|
||||||
|
if (!functions.containsKey(name)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return functions.get(name).stream().anyMatch((t) -> t.equals(ft));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检索函数类型
|
||||||
|
* 通过函数名和参数列表唯一确定一个函数类型
|
||||||
|
*
|
||||||
|
* @param name 函数名
|
||||||
|
* @param params 参数列表
|
||||||
|
* @return 唯一确定的函数类型,不存在则返回 null
|
||||||
|
*/
|
||||||
|
public FunctionType retrieveFunction(String name, List<Type> params) {
|
||||||
|
List<FunctionType> fts = functions.get(name);
|
||||||
|
if (fts != null) {
|
||||||
|
for (FunctionType ft : fts) {
|
||||||
|
if (ft.paramTypes().equals(params)) {
|
||||||
|
return ft;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -78,8 +78,17 @@ public record SignatureRegistrar(Context ctx) {
|
|||||||
Type ret = Optional.ofNullable(ctx.parseType(fn.returnType()))
|
Type ret = Optional.ofNullable(ctx.parseType(fn.returnType()))
|
||||||
.orElse(BuiltinType.VOID);
|
.orElse(BuiltinType.VOID);
|
||||||
|
|
||||||
// 注册函数签名
|
FunctionType ft = new FunctionType(params, ret);
|
||||||
mi.getFunctions().put(fn.name(), new FunctionType(params, ret));
|
if (mi.existsFunction(fn.name(), ft)) {
|
||||||
|
ctx.errors().add(new SemanticError(
|
||||||
|
fn,
|
||||||
|
"有歧义的函数: " + fn.name()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// 注册函数签名
|
||||||
|
mi.addFunction(fn.name(), ft);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user