ERR/E2.1a: value-carrying failable producer (return value + raise → tuple ABI)
The producer side of the error-channel tuple ABI for value-carrying `-> (T, !)`
functions. A failable that returns a value OR an error now lowers correctly;
the result is consumed via destructure (`v, err := f()`). Single-value
`-> (T, !)`; multi-value `-> (T1, T2, !)` and the value-carrying try/catch
consumers (E2.1b) follow.
- lowerReturn: a value-carrying failable's `return v;` assembles the success
tuple `{v, 0}` (compiler appends the no-error slot) via lowerFailableSuccessReturn
(tuple_init). Forwarding a full failable tuple (`return other_failable()` /
explicit `return (v, e)`) returns as-is. Multi-value returns bail loudly (E2).
- lowerRaise: the value-carrying branch (previously a loud bail) now builds
`{undef value slots..., tag}` (constUndef per value slot + the error tag) and
returns it — any arity.
- helpers: buildFailableTuple (tuple_init from value refs + tag) + emitTupleRet
(return honoring inline-comptime targets).
Value-carrying `try` / `catch` still bail (E2.1b). Tests:
examples/228-value-failable.sx (return value + both raises, consumed by
destructure; exit 60). Gates: zig build, zig build test, 266/266 examples.
This commit is contained in:
35
examples/228-value-failable.sx
Normal file
35
examples/228-value-failable.sx
Normal file
@@ -0,0 +1,35 @@
|
||||
// Value-carrying failable functions (ERR step E2.1a — the producer side of the
|
||||
// error-channel tuple ABI). A `-> (T, !E)` function returns EITHER a value OR
|
||||
// an error: `return v;` yields the success tuple `{v, 0}` (the compiler appends
|
||||
// the no-error slot), and `raise error.X` yields `{undef, tag}` (value slot
|
||||
// undefined, error slot = the tag). Today the result is consumed by
|
||||
// destructuring `v, err := f()` (which extracts both slots); the value-carrying
|
||||
// `try` / `catch` consumers land in E2.1b.
|
||||
|
||||
#import "modules/std.sx";
|
||||
|
||||
E :: error { Bad, Empty }
|
||||
|
||||
parse :: (n: s32) -> (s32, !E) {
|
||||
if n < 0 { raise error.Bad; }
|
||||
if n == 0 { raise error.Empty; }
|
||||
return n * 10; // success → {n*10, 0}
|
||||
}
|
||||
|
||||
main :: () -> s32 {
|
||||
r : s32 = 0;
|
||||
|
||||
v1, e1 := parse(5); // success → v1 = 50, e1 = no error
|
||||
if e1 == error.Bad { r = r + 1000; } // false
|
||||
r = r + v1; // +50
|
||||
|
||||
v2, e2 := parse(-1); // Bad
|
||||
if e2 == error.Bad { r = r + 7; } // true → +7
|
||||
if e2 == error.Empty { r = r + 200; } // false
|
||||
|
||||
v3, e3 := parse(0); // Empty
|
||||
if e3 == error.Empty { r = r + 3; } // true → +3
|
||||
|
||||
print("value-failable result: {}\n", r); // 50 + 7 + 3 = 60
|
||||
return r;
|
||||
}
|
||||
Reference in New Issue
Block a user