This commit is contained in:
Luke 2025-05-07 17:18:45 +08:00
parent 7a6ad2fb8c
commit 11159d783d
5 changed files with 324 additions and 128 deletions

View File

@ -0,0 +1,88 @@
package org.jcnc.snow.compiler.ir.builder;
import org.jcnc.snow.compiler.ir.core.IROp;
import org.jcnc.snow.compiler.ir.value.VirtualRegister;
import org.jcnc.snow.compiler.parser.ast.BinaryExpressionNode;
import org.jcnc.snow.compiler.parser.ast.IdentifierNode;
import org.jcnc.snow.compiler.parser.ast.NumberLiteralNode;
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
import java.util.Map;
/**
* ExpressionBuilder 负责将 AST 中的 ExpressionNode 构建为 IR 指令并返回结果寄存器
* <p>
* 功能
* <ol>
* <li>处理数字字面量节点生成加载常量指令</li>
* <li>处理标识符节点从作用域获取对应的虚拟寄存器</li>
* <li>处理二元表达式节点递归构建左右操作数并生成二元运算指令</li>
* </ol>
*/
public class ExpressionBuilder {
/**
* 操作符到 IR 操作码的映射表
*/
private static final Map<String, IROp> OP_MAP = Map.of(
"+", IROp.ADD_I32,
"-", IROp.SUB_I32,
"*", IROp.MUL_I32,
"/", IROp.DIV_I32
);
/**
* 当前 IR 构建上下文包含 IRFunction Scope
*/
private final IRContext ctx;
/**
* 构造方法注入 IRContext
*
* @param ctx 构建 IR 所需上下文管理函数作用域和指令添加
*/
public ExpressionBuilder(IRContext ctx) {
this.ctx = ctx;
}
/**
* 将给定的表达式节点转换为 IR并返回存放结果的虚拟寄存器
*
* @param expr 要构建的表达式节点
* @return 存放表达式计算结果的虚拟寄存器
* @throws IllegalStateException 若遇到不支持的表达式节点或未定义变量
*/
public VirtualRegister build(ExpressionNode expr) {
// 处理数字常量
if (expr instanceof NumberLiteralNode(String value)) {
int v = Integer.parseInt(value);
// 生成加载常量指令并返回结果寄存器
return InstrFactory.loadConst(ctx, v);
}
// 处理变量引用
if (expr instanceof IdentifierNode(String name)) {
// 从作用域查找已声明的寄存器
VirtualRegister vr = ctx.getScope().lookup(name);
if (vr == null) {
throw new IllegalStateException("未定义的变量: " + name);
}
return vr;
}
// 处理二元表达式
if (expr instanceof BinaryExpressionNode(ExpressionNode left, String operator, ExpressionNode right)) {
// 递归构建左右子表达式
VirtualRegister l = build(left);
VirtualRegister r = build(right);
// 根据操作符获取 IR 操作码
IROp op = OP_MAP.get(operator);
if (op == null) {
throw new IllegalStateException("不支持的运算符: " + operator);
}
// 生成二元运算指令并返回结果寄存器
return InstrFactory.binOp(ctx, op, l, r);
}
// 其他表达式类型暂不支持
throw new IllegalStateException(
"不支持的表达式类型: " + expr.getClass().getSimpleName()
);
}
}

View File

@ -1,145 +1,46 @@
package org.jcnc.snow.compiler.ir.builder;
import org.jcnc.snow.compiler.ir.core.IRFunction;
import org.jcnc.snow.compiler.ir.core.IROp;
import org.jcnc.snow.compiler.ir.instr.BinOpInstruction;
import org.jcnc.snow.compiler.ir.instr.LoadConstInstruction;
import org.jcnc.snow.compiler.ir.instr.ReturnInstruction;
import org.jcnc.snow.compiler.ir.value.Constant;
import org.jcnc.snow.compiler.ir.value.VirtualRegister;
import org.jcnc.snow.compiler.parser.ast.*;
import org.jcnc.snow.compiler.parser.ast.base.ExpressionNode;
import org.jcnc.snow.compiler.parser.ast.FunctionNode;
import org.jcnc.snow.compiler.parser.ast.ParameterNode;
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
/**
* FunctionBuilder 负责将 AST 中的 FunctionNode 构建为 IRFunction
* FunctionBuilder 负责将 AST 中的 FunctionNode 构建为可执行的 IRFunction
*
* <p>构建流程
* <ol>
* <li>创建 IRFunction 并绑定到作用域</li>
* <li>将函数参数声明为虚拟寄存器</li>
* <li>遍历函数体中的语句生成对应的 IR 指令</li>
* <li>创建 IRFunction 实例并初始化 IRContext</li>
* <li>将函数签名中的参数声明为虚拟寄存器</li>
* <li>遍历函数体中的每个语句节点通过 StatementBuilder 生成对应 IR 指令</li>
* <li>最终返回构建完成的 IRFunction 对象</li>
* </ol>
*/
final class FunctionBuilder {
/** 当前正在构建的 IRFunction 实例 */
private IRFunction irFunction;
/** 管理变量名到虚拟寄存器的映射 */
private final Scope scope = new Scope();
public class FunctionBuilder {
/**
* 将给定的 FunctionNode 转换为 IRFunction
* 构建函数的 IR 表示
*
* @param functionNode 要转换的函数节点
* @return 构建完成的 IRFunction
* @param fn 要构建的函数 AST 节点
* @return 构建完成的 IRFunction 对象
*/
IRFunction build(FunctionNode functionNode) {
irFunction = new IRFunction(functionNode.name());
scope.attachFunction(irFunction);
for (ParameterNode p : functionNode.parameters()) {
scope.declare(p.name());
}
for (StatementNode s : functionNode.body()) {
stmt(s);
}
return irFunction;
public IRFunction build(FunctionNode fn) {
// 创建 IRFunction 并包装到上下文
IRFunction irFunc = new IRFunction(fn.name());
IRContext ctx = new IRContext(irFunc);
// 声明函数参数
for (ParameterNode p : fn.parameters()) {
// 在当前作用域中声明参数名称对应的虚拟寄存器
ctx.getScope().declare(p.name());
}
/**
* 处理不同类型的语句节点并生成相应的 IR 指令
*
* @param s 要处理的语句节点
*/
private void stmt(StatementNode s) {
switch (s) {
case ExpressionStatementNode(ExpressionNode expression) ->
// 处理表达式语句无需保存结果
expr(expression);
case AssignmentNode(String variable, ExpressionNode value) -> {
// 处理赋值语句计算右侧表达式并赋值
VirtualRegister result = expr(value);
if (scope.lookup(variable) == null) {
scope.declare(variable, result);
} else {
scope.put(variable, result);
}
}
case DeclarationNode d -> {
// 处理声明语句可能带初始化
if (d.getInitializer().isPresent()) {
scope.declare(d.getName(), expr(d.getInitializer().get()));
} else {
scope.declare(d.getName());
}
}
case ReturnNode r -> {
// 处理返回语句区分是否带返回值
if (r.getExpression().isPresent()) {
irFunction.add(new ReturnInstruction(expr(r.getExpression().get())));
} else {
irFunction.add(new ReturnInstruction(null));
}
}
case null, default -> throw new IllegalStateException("Unsupported statement: " + s);
}
// 使用 StatementBuilder 遍历并生成函数体所有语句的 IR
StatementBuilder sb = new StatementBuilder(ctx);
for (StatementNode s : fn.body()) {
sb.build(s);
}
/**
* 根据表达式类型生成对应的 IR 并返回结果寄存器
*
* @param e 要处理的表达式节点
* @return 存放表达式结果的虚拟寄存器
*/
private VirtualRegister expr(ExpressionNode e) {
if (e instanceof NumberLiteralNode num) {
return number(num);
} else if (e instanceof IdentifierNode(String name)) {
// 处理变量引用从作用域获取寄存器
VirtualRegister vr = scope.lookup(name);
if (vr == null) {
throw new IllegalStateException("Undefined variable " + name);
}
return vr;
} else if (e instanceof BinaryExpressionNode bin) {
return bin(bin);
}
throw new IllegalStateException("Unsupported expression: " + e);
}
/**
* 生成加载数值常量的指令
*
* @param n 数字字面量节点
* @return 存放常量的虚拟寄存器
*/
private VirtualRegister number(NumberLiteralNode n) {
VirtualRegister vr = irFunction.newRegister();
irFunction.add(new LoadConstInstruction(vr, new Constant(Integer.parseInt(n.value()))));
return vr;
}
/**
* 生成二元运算指令并返回结果寄存器
*
* @param b 二元表达式节点
* @return 存放运算结果的虚拟寄存器
*/
private VirtualRegister bin(BinaryExpressionNode b) {
VirtualRegister l = expr(b.left());
VirtualRegister r = expr(b.right());
VirtualRegister d = irFunction.newRegister();
IROp op = switch (b.operator()) {
case "+" -> IROp.ADD_I32;
case "-" -> IROp.SUB_I32;
case "*" -> IROp.MUL_I32;
case "/" -> IROp.DIV_I32;
default -> throw new IllegalStateException("Unknown operator " + b.operator());
};
irFunction.add(new BinOpInstruction(op, d, l, r));
return d;
// 返回构建好的 IRFunction
return irFunc;
}
}

View File

@ -0,0 +1,78 @@
package org.jcnc.snow.compiler.ir.builder;
import org.jcnc.snow.compiler.ir.core.IRFunction;
import org.jcnc.snow.compiler.ir.core.IRInstruction;
import org.jcnc.snow.compiler.parser.ast.*;
import org.jcnc.snow.compiler.ir.value.VirtualRegister;
/**
* IRContext 封装了当前函数的 IRFunction 实例和作用域管理Scope
* 并提供分配寄存器和添加 IR 指令的便利方法
*
* <p>主要功能
* <ul>
* <li>持有正在构建的 IRFunction 对象</li>
* <li>管理变量名到虚拟寄存器的映射作用域</li>
* <li>分配新的虚拟寄存器</li>
* <li>将生成的 IRInstruction 自动添加到 IRFunction</li>
* </ul>
*/
public class IRContext {
/**
* 正在构建的 IRFunction 对象
*/
private final IRFunction function;
/**
* 管理变量和寄存器映射的作用域
*/
private final Scope scope;
/**
* 构造 IRContext并绑定要构建的 IRFunction
*
* @param function 要构建的 IRFunction 对象
*/
public IRContext(IRFunction function) {
this.function = function;
this.scope = new Scope();
// IRFunction 与作用域关联以便指令生成时使用
this.scope.attachFunction(function);
}
/**
* 获取当前 IRFunction
*
* @return 当前正在构建的 IRFunction 对象
*/
public IRFunction getFunction() {
return function;
}
/**
* 获取当前作用域用于变量声明和查找
*
* @return 作用域对象 Scope
*/
/* 包内可见:仅在 builder 包内部使用 Scope */
Scope getScope() {
return scope;
}
/**
* 分配一个新的虚拟寄存器
*
* @return 新分配的 VirtualRegister 对象
*/
public VirtualRegister newRegister() {
return function.newRegister();
}
/**
* 将给定的 IRInstruction 添加到 IRFunction
*
* @param instr 要添加的 IR 指令
*/
public void addInstruction(IRInstruction instr) {
function.add(instr);
}
}

View File

@ -0,0 +1,72 @@
package org.jcnc.snow.compiler.ir.builder;
import org.jcnc.snow.compiler.ir.core.IROp;
import org.jcnc.snow.compiler.ir.instr.BinOpInstruction;
import org.jcnc.snow.compiler.ir.instr.LoadConstInstruction;
import org.jcnc.snow.compiler.ir.instr.ReturnInstruction;
import org.jcnc.snow.compiler.ir.value.Constant;
import org.jcnc.snow.compiler.ir.value.VirtualRegister;
/**
* InstrFactory 统一管理 IR 指令的创建并自动将生成的指令添加到上下文中
*
* <p>提供的功能包括
* <ul>
* <li>生成加载常量指令LoadConstInstruction</li>
* <li>生成二元运算指令BinOpInstruction</li>
* <li>生成返回指令ReturnInstruction支持有返回值和无返回值两种情况</li>
* </ul>
*/
public class InstrFactory {
/**
* 生成加载整数常量的指令并返回对应的结果寄存器
*
* @param ctx 当前 IR 构建上下文
* @param value 要加载的整数值
* @return 存放常量的虚拟寄存器
*/
public static VirtualRegister loadConst(IRContext ctx, int value) {
VirtualRegister vr = ctx.newRegister();
LoadConstInstruction instr = new LoadConstInstruction(vr, new Constant(value));
ctx.addInstruction(instr);
return vr;
}
/**
* 生成二元运算指令并返回运算结果寄存器
*
* @param ctx 当前 IR 构建上下文
* @param op 要执行的 IR 运算符
* @param left 左操作数寄存器
* @param right 右操作数寄存器
* @return 存放运算结果的虚拟寄存器
*/
public static VirtualRegister binOp(IRContext ctx, IROp op,
VirtualRegister left,
VirtualRegister right) {
VirtualRegister dest = ctx.newRegister();
BinOpInstruction instr = new BinOpInstruction(op, dest, left, right);
ctx.addInstruction(instr);
return dest;
}
/**
* 生成带返回值的返回指令
*
* @param ctx 当前 IR 构建上下文
* @param value 需要返回的虚拟寄存器
*/
public static void ret(IRContext ctx, VirtualRegister value) {
ctx.addInstruction(new ReturnInstruction(value));
}
/**
* 生成无返回值的返回指令
*
* @param ctx 当前 IR 构建上下文
*/
public static void retVoid(IRContext ctx) {
ctx.addInstruction(new ReturnInstruction(null));
}
}

View File

@ -0,0 +1,57 @@
package org.jcnc.snow.compiler.ir.builder;
import org.jcnc.snow.compiler.ir.value.VirtualRegister;
import org.jcnc.snow.compiler.parser.ast.AssignmentNode;
import org.jcnc.snow.compiler.parser.ast.DeclarationNode;
import org.jcnc.snow.compiler.parser.ast.ExpressionStatementNode;
import org.jcnc.snow.compiler.parser.ast.ReturnNode;
import org.jcnc.snow.compiler.parser.ast.base.StatementNode;
/**
* 负责语句节点到 IR 的转换
*/
public class StatementBuilder {
private final IRContext ctx;
private final ExpressionBuilder exprBuilder;
public StatementBuilder(IRContext ctx) {
this.ctx = ctx;
this.exprBuilder = new ExpressionBuilder(ctx);
}
/** 入口:根据不同语句类型分发 */
public void build(StatementNode stmt) {
if (stmt instanceof ExpressionStatementNode es) {
exprBuilder.build(es.expression());
return;
}
if (stmt instanceof AssignmentNode an) {
VirtualRegister vr = exprBuilder.build(an.value());
if (ctx.getScope().lookup(an.variable()) == null) {
ctx.getScope().declare(an.variable(), vr);
} else {
ctx.getScope().put(an.variable(), vr);
}
return;
}
if (stmt instanceof DeclarationNode dn) {
if (dn.getInitializer().isPresent()) {
VirtualRegister init = exprBuilder.build(dn.getInitializer().get());
ctx.getScope().declare(dn.getName(), init);
} else {
ctx.getScope().declare(dn.getName());
}
return;
}
if (stmt instanceof ReturnNode rn) {
if (rn.getExpression().isPresent()) {
VirtualRegister vr = exprBuilder.build(rn.getExpression().get());
InstrFactory.ret(ctx, vr);
} else {
InstrFactory.retVoid(ctx);
}
return;
}
throw new IllegalStateException("Unsupported statement: " + stmt.getClass().getSimpleName());
}
}