From 06bb647c831dcfd560d4ded31ef98fddf5f14ba5 Mon Sep 17 00:00:00 2001 From: Luke Date: Tue, 26 Aug 2025 11:44:04 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=E5=85=A8=E5=B1=80?= =?UTF-8?q?=E5=B8=B8=E9=87=8F=E9=A2=84=E5=8A=A0=E8=BD=BD=E5=8F=8A=E8=B7=A8?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E5=B8=B8=E9=87=8F=E6=8A=98=E5=8F=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 preloadGlobals 方法,扫描所有模块节点,将常量注册到全局常量表- 支持整数、浮点数、字符串和布尔字面量的直接评估 - 优化了 IRProgram 的构建过程,增加了对全局常量的处理 --- .../compiler/ir/builder/IRProgramBuilder.java | 71 ++++++++++++++++--- 1 file changed, 63 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/IRProgramBuilder.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/IRProgramBuilder.java index 28e89c2..290cbb4 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/builder/IRProgramBuilder.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/IRProgramBuilder.java @@ -1,9 +1,10 @@ package org.jcnc.snow.compiler.ir.builder; +import org.jcnc.snow.compiler.ir.common.GlobalConstTable; import org.jcnc.snow.compiler.ir.core.IRFunction; import org.jcnc.snow.compiler.ir.core.IRProgram; -import org.jcnc.snow.compiler.parser.ast.FunctionNode; -import org.jcnc.snow.compiler.parser.ast.ModuleNode; +import org.jcnc.snow.compiler.parser.ast.*; +import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; 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.StatementNode; @@ -12,13 +13,12 @@ import java.util.ArrayList; import java.util.List; /** - * IRProgramBuilder 负责将 AST 根节点(如模块、函数、顶层语句)转换为可执行的 IRProgram 实例。 - *

- * 主要职责: + * IRProgramBuilder 负责将 AST 顶层节点转换为可执行的 {@link IRProgram}。 + * *

*/ public final class IRProgramBuilder { @@ -31,6 +31,9 @@ public final class IRProgramBuilder { * @throws IllegalStateException 遇到不支持的顶层节点类型时抛出 */ public IRProgram buildProgram(List roots) { + // 预先收集并登记全部模块常量到全局常量表 + preloadGlobals(roots); + IRProgram irProgram = new IRProgram(); for (Node node : roots) { switch (node) { @@ -54,6 +57,58 @@ public final class IRProgramBuilder { return irProgram; } + // ===================== 全局常量收集 ===================== + /** + * 扫描所有模块节点,将其中声明的 const 全局变量(compile-time 常量) + * 以 "模块名.常量名" 形式注册到全局常量表。 + *

+ * 只处理直接字面量(数字、字符串、布尔),暂不支持复杂表达式。 + * + * @param roots 所有顶层 AST 节点 + */ + private void preloadGlobals(List roots) { + for (Node n : roots) { + if (n instanceof ModuleNode mod) { + String moduleName = mod.name(); + if (mod.globals() == null) continue; + for (DeclarationNode decl : mod.globals()) { + if (!decl.isConst() || decl.getInitializer().isEmpty()) continue; + ExpressionNode init = decl.getInitializer().get(); + Object value = evalLiteral(init); + if (value != null) { + GlobalConstTable.register(moduleName + "." + decl.getName(), value); + } + } + } + } + } + + /** + * 字面量提取工具。仅支持整数/浮点、字符串、布尔字面量,其它返回 null。 + * + * @param expr 常量初始化表达式 + * @return 字面量值(如 123, 3.14, "abc", 1/0),否则 null + */ + private Object evalLiteral(ExpressionNode expr) { + return switch (expr) { + case NumberLiteralNode num -> { + String s = num.value(); + try { + if (s.contains(".") || s.contains("e") || s.contains("E")) + yield Double.parseDouble(s); + yield Integer.parseInt(s); + } catch (NumberFormatException ignore) { + yield null; + } + } + case StringLiteralNode str -> str.value(); + case BoolLiteralNode b -> b.getValue() ? 1 : 0; + default -> null; + }; + } + + // ===================== IRFunction 构建辅助 ===================== + /** * 构建带有模块全局声明“注入”的函数,并将函数名加上模块前缀,保证模块内函数名唯一。 *