022 combined continuation bugs

✗ Failing This test is currently failing.

Failed: backend-exec

Failure Output

Showing last 10 of 38 lines
                                                                                ^
/Users/larsde/src/koru/tests/regression/200_COMPILER_FEATURES/220_COMPILATION/220_022_combined_continuation_bugs/backend.zig:9778:51: 0x104df7077 in main (backend)
    const generated_code = try RuntimeEmitter.emit(compile_allocator, final_ast);
                                                  ^
/opt/homebrew/Cellar/zig/0.15.2_1/lib/zig/std/start.zig:627:37: 0x104dfe64b in main (backend)
            const result = root.main() catch |err| {
                                    ^
???:?:?: 0x19815dd53 in ??? (???)
???:?:?: 0x0 in ??? (???)
/Users/larsde/src/koru/scripts/regression_lib.sh: line 33: 69625 Abort trap: 6           ./backend output

Code

// PRIORITY: Combined test for all continuation codegen bugs
//
// This test exercises THREE bugs simultaneously:
// 1. Void event chaining (220_021) - switch on void
// 2. Nested branch shadowing (220_020) - |done| shadows |done|
// 3. Escape field name mismatch (330_052) - escape by name not value
//
// When all three are fixed, this test passes and Koru gets its signature syntax.

~import "$std/control"
~import "$std/build"

// Link libc for c_allocator
~std.build:requires { exe.linkLibC(); }

const std = @import("std");

const Resource = struct {
    id: usize,
    data: [64]u8,
};

const allocator = std.heap.c_allocator;

// ============================================================
// BUG #1: Void event chaining
// These are void events - no branches. Should chain with |>
// ============================================================

~event work_void { r: *Resource }

~proc work_void {
    r.data[0] +%= 1;
}

// ============================================================
// BUG #2: Nested branch shadowing
// Same branch name "done" at multiple nesting levels
// ============================================================

~event work_done { r: *Resource }
| done

~proc work_done {
    r.data[0] +%= 1;
    return .{ .done = .{} };
}

// ============================================================
// BUG #3: Escape field name mismatch
// Obligation escapes to differently-named field
// ============================================================

~event create { id: usize }
| created *Resource[active!]

~proc create {
    const r = allocator.create(Resource) catch unreachable;
    r.* = Resource{ .id = id, .data = undefined };
    return .{ .created = r };
}

~event destroy { r: *Resource[!active] }

~proc destroy {
    allocator.destroy(r);
}

// Factory with DIFFERENT field name than create
~event make_resource { id: usize }
| ready *Resource[active!]  // "resource" not "r"

// BUG #3: f.r -> resource field name mismatch
~make_resource = create(id: id)
| created f |> ready { resource: f.r }

// ============================================================
// COMBINED TEST: Bugs #2 and #3 (void chaining is parser issue)
// ============================================================

const N: usize = 10;

~for(0..N)
| each i |>
    make_resource(id: i)
    | ready r |>
        work_done(r: r.resource)
        | done |>
            work_done(r: r.resource)
            | done |>
                work_done(r: r.resource)
                | done |>
                    destroy(r: r.resource)

pub fn main() void {
    std.debug.print("All continuation bugs fixed!\n", .{});
}
input.kz

Test Configuration

MUST_RUN