diff --git a/.run/Demo1.run.xml b/.run/Demo1.run.xml new file mode 100644 index 0000000..eb7dfb1 --- /dev/null +++ b/.run/Demo1.run.xml @@ -0,0 +1,17 @@ + + + + \ No newline at end of file diff --git a/.run/Demo2.run.xml b/.run/Demo2.run.xml new file mode 100644 index 0000000..59233b4 --- /dev/null +++ b/.run/Demo2.run.xml @@ -0,0 +1,17 @@ + + + + \ No newline at end of file diff --git a/.run/Demo3.run.xml b/.run/Demo3.run.xml new file mode 100644 index 0000000..31c1fdb --- /dev/null +++ b/.run/Demo3.run.xml @@ -0,0 +1,17 @@ + + + + \ No newline at end of file diff --git a/.run/Demo4.run.xml b/.run/Demo4.run.xml new file mode 100644 index 0000000..d325c13 --- /dev/null +++ b/.run/Demo4.run.xml @@ -0,0 +1,17 @@ + + + + \ No newline at end of file diff --git a/.run/Demo5.run.xml b/.run/Demo5.run.xml new file mode 100644 index 0000000..a12479e --- /dev/null +++ b/.run/Demo5.run.xml @@ -0,0 +1,17 @@ + + + + \ No newline at end of file diff --git a/.run/Run.run.xml b/.run/Run.run.xml index 421bd23..d9f745b 100644 --- a/.run/Run.run.xml +++ b/.run/Run.run.xml @@ -1,7 +1,7 @@ - + \ No newline at end of file diff --git a/.run/SnowCompiler.run.xml b/.run/SnowCompiler.run.xml deleted file mode 100644 index 8b7143b..0000000 --- a/.run/SnowCompiler.run.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/README.md b/README.md index f0d9cd6..5b23945 100644 --- a/README.md +++ b/README.md @@ -329,12 +329,9 @@ end module [Git 管理规范](doc/Git-Management/Git-Management.md) -## 开发计划 / TODO +## 开发计划 -* 扩展标准库支持和更多内置模块,如字符串,文件操作等常用功能。 -* 增强类型系统和错误检查,完善编译时诊断信息。 -* 优化 IR 和虚拟机性能,实现更多优化策略(如常量折叠等)。 -* 增加更多示例程序试,丰富项目文档和用例。 +[Snow 语言现状和下一阶段开发路线图-2025-06-11](doc/Snow's-current-language-situation-and-the-development-roadmap-for-the-next-stage/Snow's-current-language-situation-and-the-development-roadmap-for-the-next-stage.md) ## 加入我们 * 微信: `xuxiaolankaka` diff --git a/doc/Snow's-current-language-situation-and-the-development-roadmap-for-the-next-stage/Snow's-current-language-situation-and-the-development-roadmap-for-the-next-stage.md b/doc/Snow's-current-language-situation-and-the-development-roadmap-for-the-next-stage/Snow's-current-language-situation-and-the-development-roadmap-for-the-next-stage.md new file mode 100644 index 0000000..8e7ba82 --- /dev/null +++ b/doc/Snow's-current-language-situation-and-the-development-roadmap-for-the-next-stage/Snow's-current-language-situation-and-the-development-roadmap-for-the-next-stage.md @@ -0,0 +1,75 @@ +# Snow 语言现状和下一阶段开发路线图 + +> 日期:2025-06-11 + +## 1. 代码结构与职责 +| 层次 | 主要包/目录 | 说明 | +|--------|--------------------------|--------------------------------------------------------| +| 词法分析 | `snow/compiler/lexer` | 扫描器(Scanner)+ `TokenFactory`,可识别关键字、运算符、数字/字符串字面量等 | +| 语法分析 | `snow/compiler/parser` | Pratt 表达式解析器 + 各类语句解析器(声明、`if`、`loop`、`return`…)生成 AST | +| 语义分析 | `snow/compiler/semantic` | 符号表、类型系统(`BuiltinType`/`FunctionType`)与各节点分析器 | +| IR 构建 | `snow/compiler/ir` | SSA-风格中间表示、指令集、构建器 | +| 后端生成 | `snow/compiler/backend` | IR ➜ VM 指令的 `*Generator` 体系、寄存器分配 | +| 运行时 VM | `snow/vm` | 指令集实现(栈/寄存器/内存/控制流/函数)+ 启动器 | + +### 2 编译流程 + +1. **Lexer** 将源码映射为 `TokenStream` +2. **Parser** 生成 AST(19 种节点) +3. **Semantic** + + * 类型推断 / 兼容性校验 + * 符号绑定与引用解析 +4. **IR** + + * 虚拟寄存器 + 基本块 + 统一指令(算术、比较、跳转、调用、返回…) +5. **Backend** + + * 线性扫描寄存器分配 + * 指令生成器把 IR 转为 VM 指令 +6. **VM** + + * 栈-基 / 寄存器混合架构 + * 96 条已实现指令(按数据宽度泛化:B/S/I/L/F/D) + * 运行时启动器 `VMLauncher` + + +## 3. 测试中存在的问题记录 + +| 模块 | 现状 | +|----------------|---------------------------------------------------------------| +| **布尔类型** | 词法已识别 `bool`,但 `BuiltinType` 中缺失;比较运算目前回落为 `int` 0/1 | +| **一元/前缀运算** | VM 与 IR 有 `UnaryOperationInstruction`,Parser 未注册 `-x`, `!x` 等 | +| **数组/切片/Map** | 无 AST/Type/IR 支持 | +| **结构体 / 面向对象** | 无 结构体、对象 节点 | +| **异常处理** | 无 try/catch 指令或语义 | +| **优化 Pass** | 未见常量折叠 / 死代码删除等 | +| **标准库 & I/O** | 仅语言核心,无文件/网络/控制台 API | +| **测试矩阵** | 单元测试缺失,e2e 样例有限 | +| **CLI/包管理** | 缺少 `snowc` 命令与包版本语义 | + +## 4. 下一阶段开发路线图 + +> 优先级:P0 = 当前版本必须,P1 = 下一个小版本,P2 = 中长期 + +| 优先级 | 功能 | 关键任务 | +|--------|------------------|----------------------------------------------------------------------------------------------------------------------| +| **P0** | **布尔类型落地** | \* 在 `BuiltinType` 中补充 `BOOL`
\* 更新 `TokenFactory.TYPES` 映射
\* 比较/逻辑运算返回 `bool` 类型
\* VM 增加布尔专用指令或重用 `byte` | +| **P0** | **一元表达式解析** | \* 实现 `UnaryOperatorParselet`(`-`, `+`, `!`)
\* 对应 `UnaryOpGenerator` 注册 | +| **P1** | **数组与切片** | \* 设计 `ArrayType`(元素类型 + 维度)
\* 新增 `IndexExpressionNode`、`NewArrayNode`
\* VM 扩充 `ALOAD/ASTORE` 指令 | +| **P1** | **基础标准库** | \* `print/println`, 文件读写
\* 编译期内置绑定到 VM calls | +| **P1** | **测试与 CI** | \* JUnit5 单测:Lexer / Parser / Semantic / VM
\* CI/CD 自动构建、示例编译运行 | +| **P2** | **结构体 / 简单面向对象** | \* 结构体 语法、记录类型布局
\* 方法调度:静态 or 虚表 | +| **P2** | **优化管线** | \* 常量折叠、公共子表达式消除
\* 简易死代码清除 | +| **P2** | **错误与异常系统** | \* 语法:`try … catch … end`
\* VM:展开-收缩栈,异常表 | +| **P2** | **包管理 & CLI** | \* `snowc` 命令:`build`, `run`, `test`
\* 本地缓存 `.snowpkg`与包版本语义 | + + +## 5.1 里程碑排期 + +| 时间 | 目标 | +|---------|----------------------------------------| +| 2025-07 | 发布 **v0.2.0**:布尔类型 + 一元运算、20+ 单元测试 | +| 2025-08 | 发布 **v0.3.0**:数组/切片 & 基础标准库;引入 CLI | +| 2025-10 | 发布 **v0.4.0**:结构体支持、首批优化 Pass、>80% 覆盖率 | +| 2026-11 | 发布 **v1.0.0**:异常系统、稳定包管理、文档完善 | diff --git a/playground/Main.snow b/playground/Demo1/Main.snow similarity index 100% rename from playground/Main.snow rename to playground/Demo1/Main.snow diff --git a/playground/Math.snow b/playground/Demo1/Math.snow similarity index 95% rename from playground/Math.snow rename to playground/Demo1/Math.snow index 161b7b2..bfe8605 100644 --- a/playground/Math.snow +++ b/playground/Demo1/Math.snow @@ -8,4 +8,4 @@ module: Math return n1+n2 end body end function -end module +end module \ No newline at end of file diff --git a/playground/Demo2/Main.snow b/playground/Demo2/Main.snow new file mode 100644 index 0000000..1b1833f --- /dev/null +++ b/playground/Demo2/Main.snow @@ -0,0 +1,9 @@ +module: Main + function: main + parameter: + return_type: int + body: + return (1+2) / 3 * 4 + 2 *2 + end body + end function +end module \ No newline at end of file diff --git a/playground/Demo3/Main.snow b/playground/Demo3/Main.snow new file mode 100644 index 0000000..4a13b7d --- /dev/null +++ b/playground/Demo3/Main.snow @@ -0,0 +1,17 @@ +module: Main + function: main + parameter: + return_type: int + body: + declare n1: int =1 + declare n2: int =2 + declare n3: int =1 + if n1 ==1 then + if n2 ==2 then + n3 =3 + end if + end if + return n3 + end body + end function +end module \ No newline at end of file diff --git a/playground/Demo4/Main.snow b/playground/Demo4/Main.snow new file mode 100644 index 0000000..60d39a4 --- /dev/null +++ b/playground/Demo4/Main.snow @@ -0,0 +1,12 @@ +module: Main + function: main + parameter: + return_type: boolean + body: + declare b1: boolean =true + + + return b1 + end body + end function +end module diff --git a/playground/Demo5/Main.snow b/playground/Demo5/Main.snow new file mode 100644 index 0000000..75ae75f --- /dev/null +++ b/playground/Demo5/Main.snow @@ -0,0 +1,21 @@ +module: Main + function: main + parameter: + return_type: int + body: + declare b1: boolean = true + loop: + initializer: + declare i:int = 0 + condition: + b1 + update: + i = i + 1 + body: + + end body + end loop + return 0 + end body + end function +end module \ No newline at end of file diff --git a/pom.xml b/pom.xml index 927b989..768b6c7 100644 --- a/pom.xml +++ b/pom.xml @@ -41,7 +41,13 @@ test + + + --emit build-report + + + org.apache.maven.plugins maven-compiler-plugin diff --git a/src/main/java/org/jcnc/snow/compiler/backend/generator/LoadConstGenerator.java b/src/main/java/org/jcnc/snow/compiler/backend/generator/LoadConstGenerator.java index 8c8ee32..9e75f22 100644 --- a/src/main/java/org/jcnc/snow/compiler/backend/generator/LoadConstGenerator.java +++ b/src/main/java/org/jcnc/snow/compiler/backend/generator/LoadConstGenerator.java @@ -64,6 +64,7 @@ public class LoadConstGenerator implements InstructionGenerator 'B'; // 字节型 case Double _ -> 'D'; // 双精度浮点型 case Float _ -> 'F'; // 单精度浮点型 + case Boolean _ -> 'I'; // 布尔(作为 0/1 整型存储) case null, default -> throw new IllegalStateException("Unknown const type: " + (value != null ? value.getClass() : null)); }; diff --git a/src/main/java/org/jcnc/snow/compiler/backend/util/IROpCodeMapper.java b/src/main/java/org/jcnc/snow/compiler/backend/util/IROpCodeMapper.java index 4ff674d..757e8a8 100644 --- a/src/main/java/org/jcnc/snow/compiler/backend/util/IROpCodeMapper.java +++ b/src/main/java/org/jcnc/snow/compiler/backend/util/IROpCodeMapper.java @@ -82,7 +82,7 @@ public final class IROpCodeMapper { opcodeMap.put(IROpCode.NEG_D64, "D_NEG"); // 比较运算映射 - opcodeMap.put(IROpCode.CMP_EQ, "IC_EQ"); // 相等 + opcodeMap.put(IROpCode.CMP_EQ, "IC_E"); // 相等 opcodeMap.put(IROpCode.CMP_NE, "IC_NE"); // 不等 opcodeMap.put(IROpCode.CMP_LT, "IC_L"); // 小于 opcodeMap.put(IROpCode.CMP_GT, "IC_G"); // 大于 diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/ExpressionBuilder.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/ExpressionBuilder.java index a68120f..a658d9d 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/builder/ExpressionBuilder.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/ExpressionBuilder.java @@ -44,23 +44,27 @@ public record ExpressionBuilder(IRContext ctx) { */ public IRVirtualRegister build(ExpressionNode expr) { return switch (expr) { - // 数字字面量,如 "123", "1.0f" + // 数字字面量 case NumberLiteralNode n -> buildNumberLiteral(n.value()); - // 标识符,如变量x,直接查作用域 + // 布尔字面量 + case BoolLiteralNode b -> buildBoolLiteral(b.getValue()); + // 标识符 case IdentifierNode id -> { IRVirtualRegister reg = ctx.getScope().lookup(id.name()); - if (reg == null) throw new IllegalStateException("未定义标识符: " + id.name()); + if (reg == null) + throw new IllegalStateException("未定义标识符: " + id.name()); yield reg; } - // 二元表达式,如 "a + b" + // 二元表达式 case BinaryExpressionNode bin -> buildBinary(bin); - // 函数调用,如 foo(a, b) + // 函数调用 case CallExpressionNode call -> buildCall(call); - // 其它不支持 - default -> throw new IllegalStateException("不支持的表达式类型: " + expr.getClass().getSimpleName()); + default -> throw new IllegalStateException( + "不支持的表达式类型: " + expr.getClass().getSimpleName()); }; } + /** * 直接将表达式计算结果写入指定的目标寄存器(dest)。 *

@@ -91,8 +95,6 @@ public record ExpressionBuilder(IRContext ctx) { } } - // ===================== 内部私有方法 ===================== - /** * 构建二元表达式的IR,生成新寄存器存储结果。 *

@@ -179,4 +181,12 @@ public record ExpressionBuilder(IRContext ctx) { ctx.addInstruction(new LoadConstInstruction(reg, constant)); return reg; } + + /** 布尔字面量 → CONST (true=1,false=0)*/ + private IRVirtualRegister buildBoolLiteral(boolean value) { + IRConstant constant = new IRConstant(value ? 1 : 0); + IRVirtualRegister reg = ctx.newRegister(); + ctx.addInstruction(new LoadConstInstruction(reg, constant)); + return reg; + } } diff --git a/src/main/java/org/jcnc/snow/compiler/lexer/token/TokenFactory.java b/src/main/java/org/jcnc/snow/compiler/lexer/token/TokenFactory.java index ab7b9e3..98155f6 100644 --- a/src/main/java/org/jcnc/snow/compiler/lexer/token/TokenFactory.java +++ b/src/main/java/org/jcnc/snow/compiler/lexer/token/TokenFactory.java @@ -28,19 +28,12 @@ public class TokenFactory { /** * 语言的保留关键字集合。 */ - private static final Set KEYWORDS = Set.of( - "module", "function", "parameter", "return_type", - "body", "end", "if", "then", "else", "loop", - "declare", "return", "import", - "initializer", "condition", "update" - ); + private static final Set KEYWORDS = Set.of("module", "function", "parameter", "return_type", "body", "end", "if", "then", "else", "loop", "declare", "return", "import", "initializer", "condition", "update"); /** * 内置类型名称集合,如 int、string 等。 */ - private static final Set TYPES = Set.of( - "int", "string", "float", "bool", "void", "double", "long", "short", "byte" - ); + private static final Set TYPES = Set.of("int", "string", "float", "boolean", "void", "double", "long", "short", "byte"); /** * 创建一个根据内容自动推断类型的 {@link Token} 实例。 @@ -69,15 +62,30 @@ public class TokenFactory { * @return 推断出的 {@link TokenType} 类型 */ private static TokenType determineTokenType(String raw) { + if (isABoolean(raw)) return TokenType.BOOL_LITERAL; if (isType(raw)) return TokenType.TYPE; if (isKeyword(raw)) return TokenType.KEYWORD; if (isIdentifier(raw)) return TokenType.IDENTIFIER; return TokenType.UNKNOWN; } + /** + * 判断指定字符串是否为布尔字面量("true" 或 "false")。 + * + *

本方法通过字符串比较,判断输入是否严格等于 "true" 或 "false"。

+ * + * @param raw 待判断的字符串 + * @return 若为布尔字面量,则返回 {@code true};否则返回 {@code false} + */ + private static boolean isABoolean(String raw) { + return "true".equals(raw) || "false".equals(raw); + } + /** * 判断指定字符串是否为内置类型标识。 * + *

本方法用于辅助语义分析或类型识别,判断输入字符串是否存在于预定义的类型集合 {@code TYPES} 中。

+ * * @param raw 输入的字符串 * @return 若为类型名则返回 {@code true},否则返回 {@code false} */ @@ -85,6 +93,7 @@ public class TokenFactory { return TYPES.contains(raw); } + /** * 判断指定字符串是否为语言保留关键字。 * diff --git a/src/main/java/org/jcnc/snow/compiler/lexer/token/TokenType.java b/src/main/java/org/jcnc/snow/compiler/lexer/token/TokenType.java index db7f087..4ff4394 100644 --- a/src/main/java/org/jcnc/snow/compiler/lexer/token/TokenType.java +++ b/src/main/java/org/jcnc/snow/compiler/lexer/token/TokenType.java @@ -19,6 +19,8 @@ public enum TokenType { /** 内置类型名称(如 int、string、bool 等) */ TYPE, + /** 布尔字面量 (true / false) */ + BOOL_LITERAL, /** 字符串字面量(如 "hello") */ STRING_LITERAL, diff --git a/src/main/java/org/jcnc/snow/compiler/parser/ast/BoolLiteralNode.java b/src/main/java/org/jcnc/snow/compiler/parser/ast/BoolLiteralNode.java new file mode 100644 index 0000000..a82b98c --- /dev/null +++ b/src/main/java/org/jcnc/snow/compiler/parser/ast/BoolLiteralNode.java @@ -0,0 +1,39 @@ +package org.jcnc.snow.compiler.parser.ast; + +import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; + +/** + * 表示布尔字面量(boolean literal)的抽象语法树(AST)节点。 + *

+ * 本类实现了 {@link ExpressionNode} 接口,用于在编译器前端构建语法分析过程中, + * 表达布尔类型的字面量常量(如 "true" 或 "false")。 + *

+ */ +public class BoolLiteralNode implements ExpressionNode { + /** + * 字面量的布尔值。 + */ + private final boolean value; + + /** + * 使用布尔字面量字符串构造一个 {@code BoolLiteralNode} 实例。 + *

+ * 本构造方法接受一个字符串词素(lexeme),并通过 {@link Boolean#parseBoolean(String)} 解析为布尔值。 + * 如果传入的字符串为 "true"(忽略大小写),则解析结果为 {@code true};否则为 {@code false}。 + *

+ * + * @param lexeme 布尔字面量的字符串表示 + */ + public BoolLiteralNode(String lexeme) { + this.value = Boolean.parseBoolean(lexeme); + } + + /** + * 返回此布尔字面量节点的值。 + * + * @return 布尔值,代表源代码中的布尔字面量 + */ + public boolean getValue() { + return value; + } +} diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/BoolLiteralParselet.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/BoolLiteralParselet.java new file mode 100644 index 0000000..cb2ede5 --- /dev/null +++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/BoolLiteralParselet.java @@ -0,0 +1,33 @@ +package org.jcnc.snow.compiler.parser.expression; + +import org.jcnc.snow.compiler.lexer.token.Token; +import org.jcnc.snow.compiler.parser.ast.BoolLiteralNode; +import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode; +import org.jcnc.snow.compiler.parser.context.ParserContext; +import org.jcnc.snow.compiler.parser.expression.base.PrefixParselet; + +/** + * {@code BoolLiteralParselet} 是用于解析布尔字面量的前缀解析子(prefix parselet)。 + *

+ * 本类实现了 {@link PrefixParselet} 接口,用于在语法分析阶段将布尔类型的词法单元(如 "true" 或 "false") + * 转换为相应的抽象语法树(AST)节点 {@link BoolLiteralNode}。 + */ +public class BoolLiteralParselet implements PrefixParselet { + + /** + * 解析布尔字面量的词法单元,并返回对应的布尔字面量节点。 + *

+ * 本方法被语法分析器在遇到布尔字面量词法单元时调用。 + * 它将词法单元的词素(lexeme)传递给 {@link BoolLiteralNode} 构造器, + * 并返回构造得到的 AST 节点。 + *

+ * + * @param ctx 当前的语法分析上下文,用于提供所需的解析信息 + * @param token 代表布尔字面量的词法单元 + * @return 对应的 {@link BoolLiteralNode} 实例 + */ + @Override + public ExpressionNode parse(ParserContext ctx, Token token) { + return new BoolLiteralNode(token.getLexeme()); + } +} diff --git a/src/main/java/org/jcnc/snow/compiler/parser/expression/PrattExpressionParser.java b/src/main/java/org/jcnc/snow/compiler/parser/expression/PrattExpressionParser.java index 5edcf69..1a1d124 100644 --- a/src/main/java/org/jcnc/snow/compiler/parser/expression/PrattExpressionParser.java +++ b/src/main/java/org/jcnc/snow/compiler/parser/expression/PrattExpressionParser.java @@ -43,6 +43,7 @@ public class PrattExpressionParser implements ExpressionParser { prefixes.put(TokenType.IDENTIFIER.name(), new IdentifierParselet()); prefixes.put(TokenType.LPAREN.name(), new GroupingParselet()); prefixes.put(TokenType.STRING_LITERAL.name(), new StringLiteralParselet()); + prefixes.put(TokenType.BOOL_LITERAL.name(), new BoolLiteralParselet()); // 注册中缀解析器 infixes.put("+", new BinaryOperatorParselet(Precedence.SUM, true)); diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/TypeUtils.java b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/TypeUtils.java new file mode 100644 index 0000000..0ecfab1 --- /dev/null +++ b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/TypeUtils.java @@ -0,0 +1,33 @@ +package org.jcnc.snow.compiler.semantic.analyzers; + +import org.jcnc.snow.compiler.semantic.type.BuiltinType; +import org.jcnc.snow.compiler.semantic.type.Type; + +/** + * 实用类型辅助工具类,提供与类型相关的静态方法。 + *

+ * 本类为静态工具类,无法被实例化,仅用于类型判断等功能。 + *

+ */ +public final class TypeUtils { + /** + * 私有构造方法,防止实例化工具类。 + */ + private TypeUtils() { + // 工具类不允许被实例化 + } + + /** + * 判断给定类型是否为“逻辑类型”。 + *

+ * 当前的实现仅判断类型是否不是布尔类型(BOOLEAN)。 + * 如果类型不是 BOOLEAN,则认为是“逻辑类型”。 + *

+ * + * @param t 需要检查的类型对象 + * @return 如果 t 不是 {@link BuiltinType#BOOLEAN},则返回 {@code true},否则返回 {@code false} + */ + public static boolean isLogic(Type t) { + return t != BuiltinType.BOOLEAN; + } +} diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/BoolLiteralAnalyzer.java b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/BoolLiteralAnalyzer.java new file mode 100644 index 0000000..6824717 --- /dev/null +++ b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/expression/BoolLiteralAnalyzer.java @@ -0,0 +1,42 @@ +package org.jcnc.snow.compiler.semantic.analyzers.expression; + +import org.jcnc.snow.compiler.parser.ast.BoolLiteralNode; +import org.jcnc.snow.compiler.parser.ast.FunctionNode; +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.symbol.SymbolTable; +import org.jcnc.snow.compiler.semantic.type.BuiltinType; +import org.jcnc.snow.compiler.semantic.type.Type; + +/** + * {@code BoolLiteralAnalyzer} 是布尔字面量表达式的语义分析器。 + *

+ * 本类实现 {@link ExpressionAnalyzer} 接口,用于在语义分析阶段对 {@link BoolLiteralNode} + * 进行类型推断和校验。在此实现中,所有布尔字面量表达式都被直接视为内建布尔类型 {@link BuiltinType#BOOLEAN}。 + *

+ *

+ * 该分析器不涉及值检查,仅负责返回类型信息,用于后续的类型检查与代码生成阶段。 + *

+ */ +public class BoolLiteralAnalyzer implements ExpressionAnalyzer { + + /** + * 分析布尔字面量表达式的语义,并返回其类型。 + *

+ * 由于布尔字面量具有确定且固定的类型,本方法始终返回 {@link BuiltinType#BOOLEAN}。 + *

+ * + * @param ctx 当前的语义分析上下文,包含全局编译状态 + * @param mi 所在模块的信息对象 + * @param fn 当前分析所在的函数节点 + * @param locals 当前作用域下的符号表 + * @param expr 被分析的布尔字面量表达式节点 + * @return {@link BuiltinType#BOOLEAN},表示布尔类型 + */ + @Override + public Type analyze(Context ctx, ModuleInfo mi, FunctionNode fn, + SymbolTable locals, BoolLiteralNode expr) { + return BuiltinType.BOOLEAN; + } +} diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/statement/IfAnalyzer.java b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/statement/IfAnalyzer.java index 3483702..8b82080 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/statement/IfAnalyzer.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/statement/IfAnalyzer.java @@ -2,12 +2,12 @@ package org.jcnc.snow.compiler.semantic.analyzers.statement; import org.jcnc.snow.compiler.parser.ast.FunctionNode; import org.jcnc.snow.compiler.parser.ast.IfNode; +import org.jcnc.snow.compiler.semantic.analyzers.TypeUtils; 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.SymbolTable; -import org.jcnc.snow.compiler.semantic.type.BuiltinType; import org.jcnc.snow.compiler.semantic.type.Type; /** @@ -15,7 +15,7 @@ import org.jcnc.snow.compiler.semantic.type.Type; *

* 主要职责如下: *

    - *
  • 条件表达式类型检查:确认 if 的条件表达式类型为 int(用于真假判断),否则记录语义错误。
  • + *
  • 条件表达式类型检查:确认 if 的条件表达式类型为 boolean,否则记录语义错误。
  • *
  • 块级作用域:分别为 then 分支和 else 分支创建独立的符号表(SymbolTable), * 支持分支内变量的块级作用域,防止分支内声明的变量污染外部或互相干扰,允许分支内变量同名遮蔽。
  • *
  • 分支递归分析:对 then 和 else 分支的每条语句递归调用对应的语义分析器,进行语义检查。
  • @@ -48,9 +48,9 @@ public class IfAnalyzer implements StatementAnalyzer { var exprAnalyzer = ctx.getRegistry().getExpressionAnalyzer(ifn.condition()); // 对条件表达式执行类型分析 Type condType = exprAnalyzer.analyze(ctx, mi, fn, locals, ifn.condition()); - // 判断条件类型是否为 int(SCompiler 约定 int 表示真假),否则报错 - if (condType != BuiltinType.INT) { - ctx.getErrors().add(new SemanticError(ifn, "if 条件必须为 int 类型(表示真假)")); + // 判断条件类型是否为 boolean,否则报错 + if (TypeUtils.isLogic(condType)) { + ctx.getErrors().add(new SemanticError(ifn, "if 条件必须为 boolean")); } // 2. 分析 then 分支 diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/statement/LoopAnalyzer.java b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/statement/LoopAnalyzer.java index 7b67005..a00d993 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/statement/LoopAnalyzer.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/analyzers/statement/LoopAnalyzer.java @@ -2,12 +2,12 @@ package org.jcnc.snow.compiler.semantic.analyzers.statement; import org.jcnc.snow.compiler.parser.ast.FunctionNode; import org.jcnc.snow.compiler.parser.ast.LoopNode; +import org.jcnc.snow.compiler.semantic.analyzers.TypeUtils; 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.SymbolTable; -import org.jcnc.snow.compiler.semantic.type.BuiltinType; import org.jcnc.snow.compiler.semantic.type.Type; /** @@ -17,7 +17,7 @@ import org.jcnc.snow.compiler.semantic.type.Type; *
      *
    • 为整个循环体(包括初始化、条件、更新、循环体本身)创建独立的块级符号表(作用域),保证循环内变量与外部隔离。
    • *
    • 依次分析初始化语句、条件表达式、更新语句和循环体各语句,并递归检查嵌套的语法结构。
    • - *
    • 检查条件表达式的类型必须为 int(布尔条件),否则记录语义错误。
    • + *
    • 检查条件表达式的类型必须为 boolean,否则记录语义错误。
    • *
    • 支持所有错误的收集而不中断流程,便于一次性输出全部问题。
    • *
    * 该分析器实现了 SCompiler 语言的块级作用域循环与类型健壮性,是健全语义分析的基础部分。 @@ -53,9 +53,9 @@ public class LoopAnalyzer implements StatementAnalyzer { // 3. 分析条件表达式(如 for(...; cond; ...) 或 while(cond)) var condAnalyzer = ctx.getRegistry().getExpressionAnalyzer(ln.condition()); Type condType = condAnalyzer.analyze(ctx, mi, fn, loopScope, ln.condition()); - // 条件类型必须为 int(即 bool),否则记录错误 - if (condType != BuiltinType.INT) { - ctx.getErrors().add(new SemanticError(ln, "loop 条件必须为 int 类型(表示真假)")); + // 条件类型必须为 boolean,否则记录错误 + if (TypeUtils.isLogic(condType)) { + ctx.getErrors().add(new SemanticError(ln, "loop 条件必须为 boolean")); } // 4. 分析更新语句(如 for(...; ...; update)) diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/core/AnalyzerRegistrar.java b/src/main/java/org/jcnc/snow/compiler/semantic/core/AnalyzerRegistrar.java index d91d08c..865bb5e 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/core/AnalyzerRegistrar.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/core/AnalyzerRegistrar.java @@ -39,6 +39,7 @@ public final class AnalyzerRegistrar { registry.registerStatementAnalyzer(IfNode.class, new IfAnalyzer()); registry.registerStatementAnalyzer(LoopNode.class, new LoopAnalyzer()); registry.registerStatementAnalyzer(ReturnNode.class, new ReturnAnalyzer()); + registry.registerExpressionAnalyzer(BoolLiteralNode.class, new BoolLiteralAnalyzer()); // 特殊处理:表达式语句(如 "foo();")作为语句包装表达式 registry.registerStatementAnalyzer(ExpressionStatementNode.class, diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/core/BuiltinTypeRegistry.java b/src/main/java/org/jcnc/snow/compiler/semantic/core/BuiltinTypeRegistry.java index 876411e..498f4a9 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/core/BuiltinTypeRegistry.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/core/BuiltinTypeRegistry.java @@ -31,6 +31,7 @@ public final class BuiltinTypeRegistry { "float", BuiltinType.FLOAT, "double", BuiltinType.DOUBLE, "string", BuiltinType.STRING, + "boolean", BuiltinType.BOOLEAN, "void", BuiltinType.VOID ); diff --git a/src/main/java/org/jcnc/snow/compiler/semantic/type/BuiltinType.java b/src/main/java/org/jcnc/snow/compiler/semantic/type/BuiltinType.java index 0602510..213cd80 100644 --- a/src/main/java/org/jcnc/snow/compiler/semantic/type/BuiltinType.java +++ b/src/main/java/org/jcnc/snow/compiler/semantic/type/BuiltinType.java @@ -15,6 +15,7 @@ package org.jcnc.snow.compiler.semantic.type; *
  • {@link #FLOAT} - 单精度浮点数
  • *
  • {@link #DOUBLE} - 双精度浮点数
  • *
  • {@link #STRING} - 字符串类型
  • + *
  • {@link #BOOLEAN} - 布尔类型
  • *
  • {@link #VOID} - 空类型,用于表示无返回值的函数
  • *
* @@ -34,6 +35,7 @@ public enum BuiltinType implements Type { FLOAT, // 单精度浮点数 DOUBLE, // 双精度浮点数 STRING, // 字符串类型 + BOOLEAN, // 布尔类型 VOID; // 空类型,用于表示函数无返回值 /**