feat: folding logical operations

This commit is contained in:
Brett Broadhurst 2026-03-29 04:49:03 -06:00
parent 92e8bcd866
commit 2260ccda25
Failed to generate hash of commit
24 changed files with 310 additions and 151 deletions

View file

@ -630,38 +630,11 @@ fn binaryOp(
op: Ir.Inst.Tag,
) InnerError!Ir.Inst.Ref {
const data = expr_node.data.bin;
assert(data.lhs != null and data.rhs != null);
const lhs = try expr(gi, scope, data.lhs.?);
const rhs = try expr(gi, scope, data.rhs.?);
return gi.addBinaryNode(op, lhs, rhs);
}
fn logicalOp(
gen: *GenIr,
scope: *Scope,
node: *const Ast.Node,
op: Story.Opcode,
) InnerError!void {
const data = node.data.bin;
assert(data.lhs != null and data.rhs != null);
try expr(gen, scope, data.lhs);
const else_label = try gen.makeLabel();
const fixup_offset = try gen.emitJumpInst(op);
_ = try gen.makeFixup(.{
.mode = .relative,
.label_index = else_label,
.code_offset = fixup_offset,
});
try gen.emitSimpleInst(.pop);
const rhs_label = try gen.makeLabel();
gen.setLabel(rhs_label);
try expr(gen, scope, data.rhs);
gen.setLabel(else_label);
}
fn parseNumberLiteral(bytes: []const u8) union(enum) {
int: i64,
float: f64,
@ -731,39 +704,39 @@ fn identifier(
return block.addStrTok(.decl_ref, str.index, node.loc.start);
}
fn expr(gi: *GenIr, scope: *Scope, optional_expr: ?*const Ast.Node) InnerError!Ir.Inst.Ref {
const expr_node = optional_expr.?;
switch (expr_node.tag) {
fn expr(gi: *GenIr, scope: *Scope, optional_node: ?*const Ast.Node) InnerError!Ir.Inst.Ref {
const node = optional_node.?;
switch (node.tag) {
.file => unreachable,
.true_literal => return .bool_true,
.false_literal => return .bool_false,
.number_literal => return numberLiteral(gi, expr_node),
.string_literal => return stringLiteral(gi, expr_node),
.string_expr => return stringExpr(gi, expr_node),
.empty_string => return stringLiteral(gi, expr_node),
.identifier => return identifier(gi, scope, expr_node),
.add_expr => return binaryOp(gi, scope, expr_node, .add),
.subtract_expr => return binaryOp(gi, scope, expr_node, .sub),
.multiply_expr => return binaryOp(gi, scope, expr_node, .mul),
.divide_expr => return binaryOp(gi, scope, expr_node, .div),
.mod_expr => return binaryOp(gi, scope, expr_node, .mod),
.negate_expr => return unaryOp(gi, scope, expr_node, .neg),
.logical_and_expr => unreachable,
.logical_or_expr => unreachable,
.logical_not_expr => return unaryOp(gi, scope, expr_node, .not),
.logical_equality_expr => return binaryOp(gi, scope, expr_node, .cmp_eq),
.logical_inequality_expr => return binaryOp(gi, scope, expr_node, .cmp_neq),
.logical_greater_expr => return binaryOp(gi, scope, expr_node, .cmp_gt),
.logical_greater_or_equal_expr => return binaryOp(gi, scope, expr_node, .cmp_gte),
.logical_lesser_expr => return binaryOp(gi, scope, expr_node, .cmp_lt),
.logical_lesser_or_equal_expr => return binaryOp(gi, scope, expr_node, .cmp_lte),
.number_literal => return numberLiteral(gi, node),
.string_literal => return stringLiteral(gi, node),
.string_expr => return stringExpr(gi, node),
.empty_string => return stringLiteral(gi, node),
.identifier => return identifier(gi, scope, node),
.add_expr => return binaryOp(gi, scope, node, .add),
.subtract_expr => return binaryOp(gi, scope, node, .sub),
.multiply_expr => return binaryOp(gi, scope, node, .mul),
.divide_expr => return binaryOp(gi, scope, node, .div),
.mod_expr => return binaryOp(gi, scope, node, .mod),
.negate_expr => return unaryOp(gi, scope, node, .neg),
.logical_not_expr => return unaryOp(gi, scope, node, .not),
.logical_and_expr => return binaryOp(gi, scope, node, .bool_and),
.logical_or_expr => return binaryOp(gi, scope, node, .bool_or),
.logical_equality_expr => return binaryOp(gi, scope, node, .cmp_eq),
.logical_inequality_expr => return binaryOp(gi, scope, node, .cmp_neq),
.logical_greater_expr => return binaryOp(gi, scope, node, .cmp_gt),
.logical_greater_or_equal_expr => return binaryOp(gi, scope, node, .cmp_gte),
.logical_lesser_expr => return binaryOp(gi, scope, node, .cmp_lt),
.logical_lesser_or_equal_expr => return binaryOp(gi, scope, node, .cmp_lte),
.call_expr => unreachable,
.choice_expr => unreachable,
.choice_start_expr => unreachable,
.choice_option_expr => unreachable,
.choice_inner_expr => unreachable,
.divert_expr => unreachable,
.selector_expr => return fieldAccess(gi, scope, expr_node),
.selector_expr => return fieldAccess(gi, scope, node),
.assign_stmt => unreachable,
.block_stmt => unreachable,
.content_stmt => unreachable,