019 interpreter if

✓ Passing This code compiles and runs correctly.

Code

// Test: Interpreter Runtime ~if
// Tests the interpreter executing flows with ~if conditionals

~import "$std/runtime"
~import "$std/interpreter"


const std = @import("std");

// ============================================================================
// Test event that returns a score
// ============================================================================

~pub event get_score { value: []const u8 }
| score { amount: i32 }

~proc get_score {
    const num = std.fmt.parseInt(i32, value, 10) catch 0;
    return .{ .score = .{ .amount = num } };
}

// Register events for dispatch
~std.runtime:register(scope: "test") {
    get_score
}

// ============================================================================
// Entry point
// ============================================================================

pub fn main() void {
    const koru_parser = @import("koru_parser");
    const koru_errors = @import("koru_errors");

    std.debug.print("\n", .{});
    std.debug.print("╔══════════════════════════════════════════════════════════════╗\n", .{});
    std.debug.print("║     INTERPRETER RUNTIME ~if TEST                             ║\n", .{});
    std.debug.print("╚══════════════════════════════════════════════════════════════╝\n\n", .{});

    const dispatcher_fn = dispatch_test;

    // ========================================================================
    // Test 1: ~if(true) should take | then |> branch
    // ========================================================================
    std.debug.print("Test 1: ~if(true) - then branch\n", .{});
    {
        const test_source =
            \\~if(true)
            \\| then |> yes { answer: "correct" }
            \\| else |> no { answer: "wrong" }
        ;

        var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
        defer arena.deinit();
        const allocator = arena.allocator();

        var reporter = koru_errors.ErrorReporter.init(allocator, "test", test_source) catch return;
        defer reporter.deinit();

        var parser = koru_parser.Parser.init(allocator, test_source, "test", &[_][]const u8{}, null) catch return;
        defer parser.deinit();

        const parse_result = parser.parse() catch |err| {
            std.debug.print("  Parse error: {}\n", .{err});
            return;
        };

        std.debug.print("  Parsed {d} items\n", .{parse_result.source_file.items.len});

        for (parse_result.source_file.items) |item| {
            if (item == .flow) {
                const flow = &item.flow;
                std.debug.print("  Flow: path={s}\n", .{flow.invocation.path.segments[0]});
                std.debug.print("  Continuations: {d}\n", .{flow.continuations.len});
                for (flow.continuations) |cont| {
                    std.debug.print("    | {s} |>\n", .{cont.branch});
                }

                // Dispatch (will use special if handling)
                const ast_inv = &flow.invocation;
                const inv: *const Invocation = @ptrCast(ast_inv);
                var dispatch_result: DispatchResult = undefined;
                dispatcher_fn(inv, &dispatch_result) catch |err| {
                    // Expected - if is not in our registered scope
                    // The interpreter handles it specially
                    std.debug.print("  Dispatch result: {s} (handled specially)\n", .{@errorName(err)});
                };

                std.debug.print("  ✓ TEST 1 PARSED SUCCESSFULLY\n\n", .{});
                break;
            }
        }
    }

    // ========================================================================
    // Test 2: ~if(false) should take | else |> branch
    // ========================================================================
    std.debug.print("Test 2: ~if(false) - else branch\n", .{});
    {
        const test_source =
            \\~if(false)
            \\| then |> yes { answer: "wrong" }
            \\| else |> no { answer: "correct" }
        ;

        var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
        defer arena.deinit();
        const allocator = arena.allocator();

        var reporter = koru_errors.ErrorReporter.init(allocator, "test", test_source) catch return;
        defer reporter.deinit();

        var parser = koru_parser.Parser.init(allocator, test_source, "test", &[_][]const u8{}, null) catch return;
        defer parser.deinit();

        const parse_result = parser.parse() catch |err| {
            std.debug.print("  Parse error: {}\n", .{err});
            return;
        };

        std.debug.print("  Parsed successfully\n", .{});

        for (parse_result.source_file.items) |item| {
            if (item == .flow) {
                const flow = &item.flow;
                std.debug.print("  Flow: path={s}\n", .{flow.invocation.path.segments[0]});
                std.debug.print("  Args: {d}\n", .{flow.invocation.args.len});
                if (flow.invocation.args.len > 0) {
                    std.debug.print("    arg[0].value = {s}\n", .{flow.invocation.args[0].value});
                }
                std.debug.print("  ✓ TEST 2 PARSED SUCCESSFULLY\n\n", .{});
                break;
            }
        }
    }

    std.debug.print("╔══════════════════════════════════════════════════════════════╗\n", .{});
    std.debug.print("║     INTERPRETER ~if TESTS COMPLETE                           ║\n", .{});
    std.debug.print("╚══════════════════════════════════════════════════════════════╝\n", .{});
}
input.kz

Expected Output


╔══════════════════════════════════════════════════════════════╗
║     INTERPRETER RUNTIME ~if TEST                             ║
╚══════════════════════════════════════════════════════════════╝

Test 1: ~if(true) - then branch
  Parsed 1 items
  Flow: path=if
  Continuations: 2
    | then |>
    | else |>
  Dispatch result: EventDenied (handled specially)
  ✓ TEST 1 PARSED SUCCESSFULLY

Test 2: ~if(false) - else branch
  Parsed successfully
  Flow: path=if
  Args: 1
    arg[0].value = false
  ✓ TEST 2 PARSED SUCCESSFULLY

╔══════════════════════════════════════════════════════════════╗
║     INTERPRETER ~if TESTS COMPLETE                           ║
╚══════════════════════════════════════════════════════════════╝

Test Configuration

MUST_RUN