// Comptime `#run` of a failable composes with the handlers exactly as at
// runtime: `catch` absorbs, `or` terminates, a successful bare `#run` yields the
// value (error channel stripped), and an `onfail` in the evaluated body still
// runs during comptime unwinding (E5.2).

#import "modules/std.sx";

E :: error { Bad, Empty }

parse :: (n: i32) -> (i32, !E) {
    if n < 0  { raise error.Bad; }
    if n == 0 { raise error.Empty; }
    return n * 2;
}

guard :: (ok: bool) -> !E {
    onfail print("comptime cleanup\n");
    if !ok { raise error.Bad; }
    return;
}

ok_v   :: #run parse(5);            // success → 10 (value, error stripped)
caught :: #run parse(-1) catch (e) 99; // Bad   → 99
ored   :: #run parse(0) or 55;       // Empty → 55

#run guard(false) catch (e) { };       // onfail fires during the comptime unwind

main :: () -> i32 {
    print("ok={} caught={} ored={}\n", ok_v, caught, ored);
    return ok_v + caught + ored;     // 10 + 99 + 55 = 164
}
