✓
Passing This code compiles and runs correctly.
Code
// PIN (position-duality): twin of 320_001_std_if with the final flow transplanted
// into nested position (mechanically generated by scripts/position-oracle.sh,
// judged real on main). The my-if transform fires on the nested instance, then
// fails TransformDidNotReplace — no write-back path at nested position — and the
// walker continues on a WARNING, cascading KORU021/022. Expected output is the
// passing top-level original's. Goes green when transforms become position-agnostic.
//
// Test: Bespoke if-event - conditional flow control
//
// Pattern: comptime transform + runtime implementation
// - my-if: comptime transform captures Expression
// - my-if-impl: runtime implementation handles branching
~import std/io
const std = @import("std");
// ============================================================================
// RUNTIME IMPLEMENTATION - handles the actual branching
// ============================================================================
~event my-if-impl { condition: bool }
| then
| else
~proc my-if-impl|zig {
if (condition) {
return .{ .then = .{} };
} else {
return .{ .@"else" = .{} };
}
}
// ============================================================================
// COMPTIME TRANSFORM - rewrites my-if(expr) to my-if-impl(condition: expr)
// ============================================================================
~[comptime|transform]event my-if {
expr: Expression,
item: *const Item,
program: *const Program,
allocator: std.mem.Allocator
}
| transformed SiteResult
~proc my-if|zig {
const ast = @import("ast");
std.debug.print("my_if transform: expr=\"{s}\"\n", .{expr});
if (item.* != .flow) {
std.debug.print("my_if transform: item is not a flow, returning unchanged\n", .{});
return .{ .transformed = .{} };
}
const flow = &item.flow;
// Create new path: my_if -> my_if_impl
const new_path = ast.DottedPath{
.module_qualifier = flow.inv().path.module_qualifier,
.segments = &[_][]const u8{"my-if-impl"},
};
// Create new args: condition = expr
const new_args = allocator.alloc(ast.Arg, 1) catch unreachable;
new_args[0] = ast.Arg{
.name = allocator.dupe(u8, "condition") catch unreachable,
.value = allocator.dupe(u8, expr) catch unreachable,
.source_value = null,
.expression_value = null,
};
const new_annotations = allocator.alloc([]const u8, 1) catch unreachable;
new_annotations[0] = allocator.dupe(u8, "@pass_ran(\"transform\")") catch unreachable;
const transformed_flow = ast.Flow{
.body = ast.rootSite(ast.Invocation{
.path = new_path,
.args = new_args,
.annotations = new_annotations,
.inserted_by_tap = false,
.from_opaque_tap = false,
}, flow.body.continuations, flow.location),
.annotations = flow.annotations,
.pre_label = flow.pre_label,
.post_label = flow.post_label,
.super_shape = flow.super_shape,
.is_pure = flow.is_pure,
.is_transitively_pure = flow.is_transitively_pure,
.location = flow.location,
.module = flow.module,
};
const transformed_item = ast.Item{ .flow = transformed_flow };
// Site-local: just hand back the replacement; the runner places it.
return .{ .transformed = .{ .replacement = transformed_item } };
}
// ============================================================================
// TEST CASES
// ============================================================================
const value = 42;
~my-if(value > 10)
| then |> std/io:print.ln("Test 1: then branch")
| else |> std/io:print.ln("Test 1: else branch")
const small = 5;
~event position-oracle-setup {}
~proc position-oracle-setup|zig {
}
~position-oracle-setup() |> my-if(small > 10)
| then |> std/io:print.ln("Test 2: then branch")
| else |> std/io:print.ln("Test 2: else branch")
Actual
Test 1: then branch
Test 2: else branch
Expected output
Test 1: then branch
Test 2: else branch
Test Configuration
MUST_RUN