!5 feature: 支持boolean类型与适配loop和if条件为新的boolean

Merge pull request !5 from Luke/feat/add-boolean-type
This commit is contained in:
Luke 2025-06-11 15:21:17 +00:00 committed by Gitee
commit cc29e40cb1
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
31 changed files with 432 additions and 68 deletions

17
.run/Demo1.run.xml Normal file
View File

@ -0,0 +1,17 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Demo1" type="Application" factoryName="Application" folderName="Demo" activateToolWindowBeforeRun="false">
<option name="ALTERNATIVE_JRE_PATH" value="graalvm-ce-23" />
<option name="MAIN_CLASS_NAME" value="org.jcnc.snow.compiler.cli.SnowCompiler" />
<module name="Snow" />
<option name="PROGRAM_PARAMETERS" value="-d playground/Demo1" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="org.jcnc.snow.compiler.parser.preprocessor.lexer.impl.api.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

17
.run/Demo2.run.xml Normal file
View File

@ -0,0 +1,17 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Demo2" type="Application" factoryName="Application" folderName="Demo" activateToolWindowBeforeRun="false">
<option name="ALTERNATIVE_JRE_PATH" value="graalvm-ce-23" />
<option name="MAIN_CLASS_NAME" value="org.jcnc.snow.compiler.cli.SnowCompiler" />
<module name="Snow" />
<option name="PROGRAM_PARAMETERS" value="-d playground/Demo2" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="org.jcnc.snow.compiler.parser.preprocessor.lexer.impl.api.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

17
.run/Demo3.run.xml Normal file
View File

@ -0,0 +1,17 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Demo3" type="Application" factoryName="Application" folderName="Demo" activateToolWindowBeforeRun="false">
<option name="ALTERNATIVE_JRE_PATH" value="graalvm-ce-23" />
<option name="MAIN_CLASS_NAME" value="org.jcnc.snow.compiler.cli.SnowCompiler" />
<module name="Snow" />
<option name="PROGRAM_PARAMETERS" value="-d playground/Demo3" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="org.jcnc.snow.compiler.parser.preprocessor.lexer.impl.api.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

17
.run/Demo4.run.xml Normal file
View File

@ -0,0 +1,17 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Demo4" type="Application" factoryName="Application" folderName="Demo" activateToolWindowBeforeRun="false">
<option name="ALTERNATIVE_JRE_PATH" value="graalvm-ce-23" />
<option name="MAIN_CLASS_NAME" value="org.jcnc.snow.compiler.cli.SnowCompiler" />
<module name="Snow" />
<option name="PROGRAM_PARAMETERS" value="-d playground/Demo4" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="org.jcnc.snow.compiler.parser.preprocessor.lexer.impl.api.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

17
.run/Demo5.run.xml Normal file
View File

@ -0,0 +1,17 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Demo5" type="Application" factoryName="Application" folderName="Demo" activateToolWindowBeforeRun="false">
<option name="ALTERNATIVE_JRE_PATH" value="graalvm-ce-23" />
<option name="MAIN_CLASS_NAME" value="org.jcnc.snow.compiler.cli.SnowCompiler" />
<module name="Snow" />
<option name="PROGRAM_PARAMETERS" value="-d playground/Demo5" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="org.jcnc.snow.compiler.parser.preprocessor.lexer.impl.api.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@ -1,7 +1,7 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Run" type="CompoundRunConfigurationType">
<toRun name="build_project2tar.ps1" type="PowerShellRunType" />
<toRun name="SnowCompiler" type="Application" />
<toRun name="Demo1" type="Application" />
<method v="2" />
</configuration>
</component>

View File

@ -1,32 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="SnowCompiler" type="Application" factoryName="Application" activateToolWindowBeforeRun="false" nameIsGenerated="true">
<option name="ALTERNATIVE_JRE_PATH" value="23" />
<option name="MAIN_CLASS_NAME" value="org.jcnc.snow.compiler.cli.SnowCompiler" />
<module name="SCompiler" />
<option name="PROGRAM_PARAMETERS" value="test" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="org.jcnc.snow.compiler.parser.preprocessor.lexer.impl.api.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
<configuration default="false" name="SnowCompiler" type="Application" factoryName="Application" activateToolWindowBeforeRun="false" nameIsGenerated="true">
<option name="ALTERNATIVE_JRE_PATH" value="graalvm-ce-23" />
<option name="MAIN_CLASS_NAME" value="org.jcnc.snow.compiler.cli.SnowCompiler" />
<module name="Snow" />
<option name="PROGRAM_PARAMETERS" value="-d playground" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="org.jcnc.snow.compiler.parser.preprocessor.lexer.impl.api.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

View File

@ -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`

View File

@ -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** 生成 AST19 种节点)
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`<br>\* 更新 `TokenFactory.TYPES` 映射<br>\* 比较/逻辑运算返回 `bool` 类型<br>\* VM 增加布尔专用指令或重用 `byte` |
| **P0** | **一元表达式解析** | \* 实现 `UnaryOperatorParselet``-`, `+`, `!`)<br>\* 对应 `UnaryOpGenerator` 注册 |
| **P1** | **数组与切片** | \* 设计 `ArrayType`(元素类型 + 维度)<br>\* 新增 `IndexExpressionNode``NewArrayNode`<br>\* VM 扩充 `ALOAD/ASTORE` 指令 |
| **P1** | **基础标准库** | \* `print/println`, 文件读写<br>\* 编译期内置绑定到 VM calls |
| **P1** | **测试与 CI** | \* JUnit5 单测Lexer / Parser / Semantic / VM<br>\* CI/CD 自动构建、示例编译运行 |
| **P2** | **结构体 / 简单面向对象** | \* 结构体 语法、记录类型布局<br>\* 方法调度:静态 or 虚表 |
| **P2** | **优化管线** | \* 常量折叠、公共子表达式消除<br>\* 简易死代码清除 |
| **P2** | **错误与异常系统** | \* 语法:`try … catch … end`<br>\* VM展开-收缩栈,异常表 |
| **P2** | **包管理 & CLI** | \* `snowc` 命令:`build`, `run`, `test`<br>\* 本地缓存 `.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**:异常系统、稳定包管理、文档完善 |

View File

@ -8,4 +8,4 @@ module: Math
return n1+n2
end body
end function
end module
end module

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -41,7 +41,13 @@
<phase>test</phase>
</execution>
</executions>
<configuration>
<buildArgs>
<buildArg>--emit build-report</buildArg>
</buildArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>

View File

@ -64,6 +64,7 @@ public class LoadConstGenerator implements InstructionGenerator<LoadConstInstruc
case Byte _ -> '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));
};

View File

@ -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"); // 大于

View File

@ -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
* <p>
@ -91,8 +95,6 @@ public record ExpressionBuilder(IRContext ctx) {
}
}
// ===================== 内部私有方法 =====================
/**
* 构建二元表达式的IR生成新寄存器存储结果
* <p>
@ -179,4 +181,12 @@ public record ExpressionBuilder(IRContext ctx) {
ctx.addInstruction(new LoadConstInstruction(reg, constant));
return reg;
}
/** 布尔字面量 → CONST true=1false=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;
}
}

View File

@ -28,19 +28,12 @@ public class TokenFactory {
/**
* 语言的保留关键字集合
*/
private static final Set<String> KEYWORDS = Set.of(
"module", "function", "parameter", "return_type",
"body", "end", "if", "then", "else", "loop",
"declare", "return", "import",
"initializer", "condition", "update"
);
private static final Set<String> KEYWORDS = Set.of("module", "function", "parameter", "return_type", "body", "end", "if", "then", "else", "loop", "declare", "return", "import", "initializer", "condition", "update");
/**
* 内置类型名称集合 intstring
*/
private static final Set<String> TYPES = Set.of(
"int", "string", "float", "bool", "void", "double", "long", "short", "byte"
);
private static final Set<String> 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"
*
* <p>本方法通过字符串比较判断输入是否严格等于 "true" "false"</p>
*
* @param raw 待判断的字符串
* @return 若为布尔字面量则返回 {@code true}否则返回 {@code false}
*/
private static boolean isABoolean(String raw) {
return "true".equals(raw) || "false".equals(raw);
}
/**
* 判断指定字符串是否为内置类型标识
*
* <p>本方法用于辅助语义分析或类型识别判断输入字符串是否存在于预定义的类型集合 {@code TYPES} </p>
*
* @param raw 输入的字符串
* @return 若为类型名则返回 {@code true}否则返回 {@code false}
*/
@ -85,6 +93,7 @@ public class TokenFactory {
return TYPES.contains(raw);
}
/**
* 判断指定字符串是否为语言保留关键字
*

View File

@ -19,6 +19,8 @@ public enum TokenType {
/** 内置类型名称(如 int、string、bool 等) */
TYPE,
/** 布尔字面量 true / false */
BOOL_LITERAL,
/** 字符串字面量(如 "hello" */
STRING_LITERAL,

View File

@ -0,0 +1,39 @@
package org.jcnc.snow.compiler.parser.ast;
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
/**
* 表示布尔字面量boolean literal的抽象语法树AST节点
* <p>
* 本类实现了 {@link ExpressionNode} 接口用于在编译器前端构建语法分析过程中
* 表达布尔类型的字面量常量 "true" "false"
* </p>
*/
public class BoolLiteralNode implements ExpressionNode {
/**
* 字面量的布尔值
*/
private final boolean value;
/**
* 使用布尔字面量字符串构造一个 {@code BoolLiteralNode} 实例
* <p>
* 本构造方法接受一个字符串词素lexeme并通过 {@link Boolean#parseBoolean(String)} 解析为布尔值
* 如果传入的字符串为 "true"忽略大小写则解析结果为 {@code true}否则为 {@code false}
* </p>
*
* @param lexeme 布尔字面量的字符串表示
*/
public BoolLiteralNode(String lexeme) {
this.value = Boolean.parseBoolean(lexeme);
}
/**
* 返回此布尔字面量节点的值
*
* @return 布尔值代表源代码中的布尔字面量
*/
public boolean getValue() {
return value;
}
}

View File

@ -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
* <p>
* 本类实现了 {@link PrefixParselet} 接口用于在语法分析阶段将布尔类型的词法单元 "true" "false"
* 转换为相应的抽象语法树AST节点 {@link BoolLiteralNode}
*/
public class BoolLiteralParselet implements PrefixParselet {
/**
* 解析布尔字面量的词法单元并返回对应的布尔字面量节点
* <p>
* 本方法被语法分析器在遇到布尔字面量词法单元时调用
* 它将词法单元的词素lexeme传递给 {@link BoolLiteralNode} 构造器
* 并返回构造得到的 AST 节点
* </p>
*
* @param ctx 当前的语法分析上下文用于提供所需的解析信息
* @param token 代表布尔字面量的词法单元
* @return 对应的 {@link BoolLiteralNode} 实例
*/
@Override
public ExpressionNode parse(ParserContext ctx, Token token) {
return new BoolLiteralNode(token.getLexeme());
}
}

View File

@ -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));

View File

@ -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;
/**
* 实用类型辅助工具类提供与类型相关的静态方法
* <p>
* 本类为静态工具类无法被实例化仅用于类型判断等功能
* </p>
*/
public final class TypeUtils {
/**
* 私有构造方法防止实例化工具类
*/
private TypeUtils() {
// 工具类不允许被实例化
}
/**
* 判断给定类型是否为逻辑类型
* <p>
* 当前的实现仅判断类型是否不是布尔类型BOOLEAN
* 如果类型不是 BOOLEAN则认为是逻辑类型
* </p>
*
* @param t 需要检查的类型对象
* @return 如果 t 不是 {@link BuiltinType#BOOLEAN}则返回 {@code true}否则返回 {@code false}
*/
public static boolean isLogic(Type t) {
return t != BuiltinType.BOOLEAN;
}
}

View File

@ -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} 是布尔字面量表达式的语义分析器
* <p>
* 本类实现 {@link ExpressionAnalyzer} 接口用于在语义分析阶段对 {@link BoolLiteralNode}
* 进行类型推断和校验在此实现中所有布尔字面量表达式都被直接视为内建布尔类型 {@link BuiltinType#BOOLEAN}
* </p>
* <p>
* 该分析器不涉及值检查仅负责返回类型信息用于后续的类型检查与代码生成阶段
* </p>
*/
public class BoolLiteralAnalyzer implements ExpressionAnalyzer<BoolLiteralNode> {
/**
* 分析布尔字面量表达式的语义并返回其类型
* <p>
* 由于布尔字面量具有确定且固定的类型本方法始终返回 {@link BuiltinType#BOOLEAN}
* </p>
*
* @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;
}
}

View File

@ -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;
* <p>
* 主要职责如下
* <ul>
* <li>条件表达式类型检查确认 if 的条件表达式类型为 int用于真假判断否则记录语义错误</li>
* <li>条件表达式类型检查确认 if 的条件表达式类型为 boolean否则记录语义错误</li>
* <li>块级作用域分别为 then 分支和 else 分支创建独立的符号表SymbolTable
* 支持分支内变量的块级作用域防止分支内声明的变量污染外部或互相干扰允许分支内变量同名遮蔽</li>
* <li>分支递归分析 then else 分支的每条语句递归调用对应的语义分析器进行语义检查</li>
@ -48,9 +48,9 @@ public class IfAnalyzer implements StatementAnalyzer<IfNode> {
var exprAnalyzer = ctx.getRegistry().getExpressionAnalyzer(ifn.condition());
// 对条件表达式执行类型分析
Type condType = exprAnalyzer.analyze(ctx, mi, fn, locals, ifn.condition());
// 判断条件类型是否为 intSCompiler 约定 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 分支

View File

@ -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;
* <ul>
* <li>为整个循环体包括初始化条件更新循环体本身创建独立的块级符号表作用域保证循环内变量与外部隔离</li>
* <li>依次分析初始化语句条件表达式更新语句和循环体各语句并递归检查嵌套的语法结构</li>
* <li>检查条件表达式的类型必须为 int布尔条件否则记录语义错误</li>
* <li>检查条件表达式的类型必须为 boolean否则记录语义错误</li>
* <li>支持所有错误的收集而不中断流程便于一次性输出全部问题</li>
* </ul>
* 该分析器实现了 SCompiler 语言的块级作用域循环与类型健壮性是健全语义分析的基础部分
@ -53,9 +53,9 @@ public class LoopAnalyzer implements StatementAnalyzer<LoopNode> {
// 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)

View File

@ -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,

View File

@ -31,6 +31,7 @@ public final class BuiltinTypeRegistry {
"float", BuiltinType.FLOAT,
"double", BuiltinType.DOUBLE,
"string", BuiltinType.STRING,
"boolean", BuiltinType.BOOLEAN,
"void", BuiltinType.VOID
);

View File

@ -15,6 +15,7 @@ package org.jcnc.snow.compiler.semantic.type;
* <li>{@link #FLOAT} - 单精度浮点数</li>
* <li>{@link #DOUBLE} - 双精度浮点数</li>
* <li>{@link #STRING} - 字符串类型</li>
* <li>{@link #BOOLEAN} - 布尔类型</li>
* <li>{@link #VOID} - 空类型用于表示无返回值的函数</li>
* </ul>
*
@ -34,6 +35,7 @@ public enum BuiltinType implements Type {
FLOAT, // 单精度浮点数
DOUBLE, // 双精度浮点数
STRING, // 字符串类型
BOOLEAN, // 布尔类型
VOID; // 空类型用于表示函数无返回值
/**