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 new file mode 100644 index 0000000..1d8f1fd --- /dev/null +++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/ExpressionBuilder.java @@ -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 指令,并返回结果寄存器。 + *

+ * 功能: + *

    + *
  1. 处理数字字面量节点,生成加载常量指令;
  2. + *
  3. 处理标识符节点,从作用域获取对应的虚拟寄存器;
  4. + *
  5. 处理二元表达式节点,递归构建左右操作数并生成二元运算指令;
  6. + *
+ */ +public class ExpressionBuilder { + /** + * 操作符到 IR 操作码的映射表 + */ + private static final Map 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() + ); + } +} diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/FunctionBuilder.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/FunctionBuilder.java index 25f6efe..7487aa4 100644 --- a/src/main/java/org/jcnc/snow/compiler/ir/builder/FunctionBuilder.java +++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/FunctionBuilder.java @@ -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。 * *

构建流程: *

    - *
  1. 创建 IRFunction 并绑定到作用域;
  2. - *
  3. 将函数参数声明为虚拟寄存器;
  4. - *
  5. 遍历函数体中的语句,生成对应的 IR 指令。
  6. + *
  7. 创建 IRFunction 实例并初始化 IRContext;
  8. + *
  9. 将函数签名中的参数声明为虚拟寄存器;
  10. + *
  11. 遍历函数体中的每个语句节点,通过 StatementBuilder 生成对应 IR 指令;
  12. + *
  13. 最终返回构建完成的 IRFunction 对象。
  14. *
*/ -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()); + 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()); } - for (StatementNode s : functionNode.body()) { - stmt(s); + + // 使用 StatementBuilder 遍历并生成函数体所有语句的 IR + StatementBuilder sb = new StatementBuilder(ctx); + for (StatementNode s : fn.body()) { + sb.build(s); } - return irFunction; + + // 返回构建好的 IRFunction + return irFunc; } - - /** - * 处理不同类型的语句节点,并生成相应的 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); - } - } - - /** - * 根据表达式类型生成对应的 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; - } -} \ No newline at end of file +} diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/IRContext.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/IRContext.java new file mode 100644 index 0000000..866de5f --- /dev/null +++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/IRContext.java @@ -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 指令的便利方法。 + * + *

主要功能: + *

+ */ +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); + } +} diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/InstrFactory.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/InstrFactory.java new file mode 100644 index 0000000..12479bc --- /dev/null +++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/InstrFactory.java @@ -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 指令的创建,并自动将生成的指令添加到上下文中。 + * + *

提供的功能包括: + *

+ */ +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)); + } +} diff --git a/src/main/java/org/jcnc/snow/compiler/ir/builder/StatementBuilder.java b/src/main/java/org/jcnc/snow/compiler/ir/builder/StatementBuilder.java new file mode 100644 index 0000000..b1fa215 --- /dev/null +++ b/src/main/java/org/jcnc/snow/compiler/ir/builder/StatementBuilder.java @@ -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()); + } +}