style: migrate arrow-block lambdas () => { .. } to () { .. }
The canonical sx block-body lambda is `(params) { stmts }` (and
`(params) -> Ret { stmts }`); the arrow form `=>` is for EXPRESSION bodies
(`(params) => expr`). The arrow-block hybrid `(params) => { .. }` was being
used in 33 files — convert all of them by dropping the `=>`. The two forms are
exactly equivalent (verified: identical IR and identical runtime values — the
block tail is the value with or without a `-> Ret`), so this is a pure source
cleanup: no `.ir` churn, and the only snapshot change is 0923's diagnostic
COLUMN (a negative narrowing test whose error span shifted by the removed `=> `).
Arrow EXPRESSION bodies (`=> expr`, `=> .{..}`, `=> [..]`) and `=>` inside
comments/strings were left untouched. Migrated across examples/concurrency,
examples/{closures,ffi-objc,generics,optionals,types}, issues/, and the stdlib
(io.sx, sched.sx). Suite 855/0.
This commit is contained in:
@@ -46,7 +46,7 @@ main :: () -> i64 {
|
||||
// Three DIFFERENT fiber bodies (distinct captured ids), interleaving via
|
||||
// yield_now. Each appends its id once per round for 3 rounds.
|
||||
spawn_worker :: (ps: *sched.Scheduler, psh: *Shared, my_id: i64) {
|
||||
ps.spawn(() => {
|
||||
ps.spawn(() {
|
||||
r := 0;
|
||||
while r < 3 {
|
||||
append(psh, my_id);
|
||||
|
||||
@@ -36,7 +36,7 @@ main :: () -> i64 {
|
||||
// Fiber A: record 10, park, then (after wake) record 11. Store A's handle in
|
||||
// the shared state so B can wake it.
|
||||
mk_a :: (ps: *sched.Scheduler, psh: *Sh) {
|
||||
psh.parked = ps.spawn(() => {
|
||||
psh.parked = ps.spawn(() {
|
||||
rec(psh, 10);
|
||||
ps.suspend_self();
|
||||
rec(psh, 11);
|
||||
@@ -45,7 +45,7 @@ main :: () -> i64 {
|
||||
// Fiber B: record 20, wake A (legit) + a spurious second wake (safe no-op),
|
||||
// record 21.
|
||||
mk_b :: (ps: *sched.Scheduler, psh: *Sh) {
|
||||
ps.spawn(() => {
|
||||
ps.spawn(() {
|
||||
rec(psh, 20);
|
||||
ps.wake(psh.parked); // legitimate: A is parked
|
||||
ps.wake(psh.parked); // spurious: A is now .ready/queued — must no-op
|
||||
|
||||
@@ -43,16 +43,16 @@ main :: () -> i64 {
|
||||
// cancel. It runs as a fiber so `await` has a `self.current` to park. The
|
||||
// scheduler is installed as `context.io`, so the unified async layer reaches it.
|
||||
push .{ io = xx s } {
|
||||
ps.spawn(() => {
|
||||
ps.spawn(() {
|
||||
// Worker A yields mid-body so B interleaves before A completes.
|
||||
a := context.io.async(() -> (i64, !) => {
|
||||
a := context.io.async(() -> (i64, !) {
|
||||
rec(pl, 1);
|
||||
ps.yield_now(); // suspend A; B (already spawned) runs to completion
|
||||
rec(pl, 3);
|
||||
42
|
||||
});
|
||||
// Worker B runs straight through (no yield).
|
||||
b := context.io.async(() -> (i64, !) => {
|
||||
b := context.io.async(() -> (i64, !) {
|
||||
rec(pl, 2);
|
||||
100
|
||||
});
|
||||
|
||||
@@ -50,12 +50,12 @@ main :: () -> i64 {
|
||||
pl := @lg;
|
||||
|
||||
// Spawn order A, B, C, D, E — but the WAKE order is set by deadline.
|
||||
ps.spawn(() => { ps.sleep(30); rec(pl, 1, ps.now_ms()); }); // A: latest
|
||||
ps.spawn(() => { ps.sleep(10); rec(pl, 2, ps.now_ms()); }); // B: earliest
|
||||
ps.spawn(() => { ps.sleep(20); rec(pl, 3, ps.now_ms()); }); // C: middle
|
||||
ps.spawn(() { ps.sleep(30); rec(pl, 1, ps.now_ms()); }); // A: latest
|
||||
ps.spawn(() { ps.sleep(10); rec(pl, 2, ps.now_ms()); }); // B: earliest
|
||||
ps.spawn(() { ps.sleep(20); rec(pl, 3, ps.now_ms()); }); // C: middle
|
||||
// Same-deadline FIFO pair: D before E, both at t=15 → wake D then E.
|
||||
ps.spawn(() => { ps.sleep(15); rec(pl, 4, ps.now_ms()); }); // D
|
||||
ps.spawn(() => { ps.sleep(15); rec(pl, 5, ps.now_ms()); }); // E
|
||||
ps.spawn(() { ps.sleep(15); rec(pl, 4, ps.now_ms()); }); // D
|
||||
ps.spawn(() { ps.sleep(15); rec(pl, 5, ps.now_ms()); }); // E
|
||||
|
||||
s.run();
|
||||
|
||||
|
||||
@@ -29,11 +29,11 @@ main :: () -> i64 {
|
||||
|
||||
// Sleeper: arm sleep(100), park; when woken (early), record 1 and finish.
|
||||
mk_sleeper :: (ps: *sched.Scheduler, pst: *S) {
|
||||
pst.sleeper = ps.spawn(() => { ps.sleep(100); rec(pst, 1); });
|
||||
pst.sleeper = ps.spawn(() { ps.sleep(100); rec(pst, 1); });
|
||||
}
|
||||
// Waker: record 2, then wake the sleeper BEFORE its 100ms timer fires.
|
||||
mk_waker :: (ps: *sched.Scheduler, pst: *S) {
|
||||
ps.spawn(() => { rec(pst, 2); ps.wake(pst.sleeper); });
|
||||
ps.spawn(() { rec(pst, 2); ps.wake(pst.sleeper); });
|
||||
}
|
||||
mk_sleeper(ps, pst);
|
||||
mk_waker(ps, pst);
|
||||
|
||||
@@ -56,7 +56,7 @@ main :: () -> i64 {
|
||||
|
||||
// Reader: block on the (empty) pipe until it is readable, then read 3 bytes.
|
||||
mk_reader :: (ps: *sched.Scheduler, pst: *S, rfd: i32) {
|
||||
ps.spawn(() => {
|
||||
ps.spawn(() {
|
||||
ps.block_on_fd(rfd, true); // parks until read_fd is readable
|
||||
n := read(rfd, xx @pst.bytes[0], xx 3);
|
||||
pst.read_n = xx n;
|
||||
@@ -65,7 +65,7 @@ main :: () -> i64 {
|
||||
}
|
||||
// Writer: write 3 bytes ('a','b','c') to the write end.
|
||||
mk_writer :: (ps: *sched.Scheduler, pst: *S, wfd: i32) {
|
||||
ps.spawn(() => {
|
||||
ps.spawn(() {
|
||||
buf : [3]u8 = ---;
|
||||
buf[0] = xx 97; buf[1] = xx 98; buf[2] = xx 99; // 'a' 'b' 'c'
|
||||
write(wfd, xx @buf[0], xx 3);
|
||||
|
||||
@@ -40,11 +40,11 @@ main :: () -> i64 {
|
||||
// scheduler is installed as `context.io`, so the unified async layer
|
||||
// (`context.io.async`/`await`/`sleep`/`now_ms`) reaches it inside the workers.
|
||||
push .{ io = xx s } {
|
||||
ps.spawn(() => {
|
||||
ps.spawn(() {
|
||||
// Launch three async workers; each sleeps, logs its completion, returns.
|
||||
a := context.io.async(() -> (i64, !) => { try context.io.sleep(30); rec(pl, 1, context.io.now_ms()); 100 });
|
||||
b := context.io.async(() -> (i64, !) => { try context.io.sleep(10); rec(pl, 2, context.io.now_ms()); 20 });
|
||||
c := context.io.async(() -> (i64, !) => { try context.io.sleep(20); rec(pl, 3, context.io.now_ms()); 3 });
|
||||
a := context.io.async(() -> (i64, !) { try context.io.sleep(30); rec(pl, 1, context.io.now_ms()); 100 });
|
||||
b := context.io.async(() -> (i64, !) { try context.io.sleep(10); rec(pl, 2, context.io.now_ms()); 20 });
|
||||
c := context.io.async(() -> (i64, !) { try context.io.sleep(20); rec(pl, 3, context.io.now_ms()); 3 });
|
||||
|
||||
// Await in SPAWN order; results come back correct regardless.
|
||||
va := a.await() or { -1 };
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
sched :: #import "modules/std/sched.sx";
|
||||
main :: () -> i64 {
|
||||
s := sched.Scheduler.init(); ps := @s;
|
||||
ps.spawn(() => { ps.sleep(10); ps.sleep(-5); }); // -5 → loud abort
|
||||
ps.spawn(() { ps.sleep(10); ps.sleep(-5); }); // -5 → loud abort
|
||||
s.run();
|
||||
print("unreachable\n");
|
||||
return 0;
|
||||
|
||||
@@ -12,8 +12,8 @@ S :: struct { t: *Future(i64); }
|
||||
main :: () -> i64 {
|
||||
st : S = ---; st.t = null;
|
||||
s := sched.Scheduler.init(); ps := @s; pst := @st;
|
||||
mkprod :: (ps: *sched.Scheduler, pst: *S) { pst.t = context.io.async(() -> (i64, !) => { ps.yield_now(); 42 }); }
|
||||
mkw :: (ps: *sched.Scheduler, pst: *S) { ps.spawn(() => { x := pst.t.await() or { -1 }; print("got {}\n", x); }); }
|
||||
mkprod :: (ps: *sched.Scheduler, pst: *S) { pst.t = context.io.async(() -> (i64, !) { ps.yield_now(); 42 }); }
|
||||
mkw :: (ps: *sched.Scheduler, pst: *S) { ps.spawn(() { x := pst.t.await() or { -1 }; print("got {}\n", x); }); }
|
||||
push .{ io = xx s } {
|
||||
mkprod(ps, pst); mkw(ps, pst); mkw(ps, pst); // second waiter → loud abort
|
||||
s.run();
|
||||
|
||||
@@ -70,11 +70,11 @@ main :: () -> i64 {
|
||||
ps := @s; pst := @st;
|
||||
|
||||
// SLEEPER — arms a virtual-time timer, then parks.
|
||||
ps.spawn(() => { ps.sleep(5); });
|
||||
ps.spawn(() { ps.sleep(5); });
|
||||
|
||||
// READER — blocks on the empty pipe until kqueue reports it readable.
|
||||
mk_reader :: (ps: *sched.Scheduler, pst: *S, rfd: i32) {
|
||||
ps.spawn(() => {
|
||||
ps.spawn(() {
|
||||
ps.block_on_fd(rfd, true);
|
||||
n := read(rfd, xx @pst.bytes[0], xx 3);
|
||||
pst.read_n = xx n;
|
||||
@@ -83,7 +83,7 @@ main :: () -> i64 {
|
||||
}
|
||||
// WRITER — writes 'a' 'b' 'c', making the pipe readable.
|
||||
mk_writer :: (ps: *sched.Scheduler, wfd: i32) {
|
||||
ps.spawn(() => {
|
||||
ps.spawn(() {
|
||||
buf : [3]u8 = ---;
|
||||
buf[0] = xx 97; buf[1] = xx 98; buf[2] = xx 99;
|
||||
write(wfd, xx @buf[0], xx 3);
|
||||
|
||||
@@ -30,11 +30,11 @@ main :: () -> i64 {
|
||||
|
||||
// The coordinator runs as a fiber so `race` has a `current` to park.
|
||||
push .{ io = xx s } {
|
||||
ps.spawn(() => {
|
||||
ps.spawn(() {
|
||||
// Three async workers, DIFFERENT result types and sleep durations.
|
||||
a := context.io.async(() -> (i64, !) => { try context.io.sleep(10); rec(pl, 1, context.io.now_ms()); 111 });
|
||||
b := context.io.async(() -> (bool, !) => { try context.io.sleep(20); rec(pl, 2, context.io.now_ms()); true });
|
||||
c := context.io.async(() -> (f64, !) => { try context.io.sleep(30); rec(pl, 3, context.io.now_ms()); 2.5 });
|
||||
a := context.io.async(() -> (i64, !) { try context.io.sleep(10); rec(pl, 1, context.io.now_ms()); 111 });
|
||||
b := context.io.async(() -> (bool, !) { try context.io.sleep(20); rec(pl, 2, context.io.now_ms()); true });
|
||||
c := context.io.async(() -> (f64, !) { try context.io.sleep(30); rec(pl, 3, context.io.now_ms()); 2.5 });
|
||||
|
||||
// Race them. `a` (sleep 10) wins; `b` and `c` are cancelled — their
|
||||
// post-sleep work never runs (true cancellation).
|
||||
|
||||
@@ -24,7 +24,7 @@ main :: () -> i64 {
|
||||
ps := @s;
|
||||
print("outside: marker id = {}\n", mk.id);
|
||||
push .{ data = xx @mk } {
|
||||
ps.spawn(() => {
|
||||
ps.spawn(() {
|
||||
m : *Marker = xx context.data; // inherited from the spawn-time context
|
||||
print("inside fiber: context.data marker id = {}\n", m.id);
|
||||
});
|
||||
|
||||
@@ -23,10 +23,10 @@ main :: () -> i64 {
|
||||
s := sched.Scheduler.init();
|
||||
ps := @s; pl := @lg;
|
||||
push .{ io = xx s } {
|
||||
ps.spawn(() => {
|
||||
ps.spawn(() {
|
||||
rec(pl, 1); // coordinator starts
|
||||
a := context.io.async(() -> (i64, !) => { rec(pl, 10); 100 }); // worker A — deferred
|
||||
b := context.io.async(() -> (i64, !) => { rec(pl, 20); 23 }); // worker B — deferred
|
||||
a := context.io.async(() -> (i64, !) { rec(pl, 10); 100 }); // worker A — deferred
|
||||
b := context.io.async(() -> (i64, !) { rec(pl, 20); 23 }); // worker B — deferred
|
||||
rec(pl, 2); // both spawned, neither has run
|
||||
va := a.await() or { -1 }; // park; A runs, wakes us
|
||||
vb := b.await() or { -1 };
|
||||
|
||||
@@ -27,8 +27,8 @@ main :: () -> i64 {
|
||||
s := sched.Scheduler.init();
|
||||
ps := @s; pl := @lg;
|
||||
push .{ io = xx s } {
|
||||
ps.spawn(() => {
|
||||
w := context.io.async(() -> (i64, !) => {
|
||||
ps.spawn(() {
|
||||
w := context.io.async(() -> (i64, !) {
|
||||
rec(pl, 1); // worker started
|
||||
try context.io.sleep(10); // park; cancel delivers Canceled HERE
|
||||
rec(pl, 2); // POST-SUSPEND — must NEVER run
|
||||
|
||||
@@ -17,9 +17,9 @@ main :: () -> i64 {
|
||||
s := sched.Scheduler.init();
|
||||
ps := @s;
|
||||
push .{ io = xx s } {
|
||||
ps.spawn(() => {
|
||||
a := context.io.async(() -> (i64, !) => { try context.io.sleep(5); raise error.Boom; });
|
||||
b := context.io.async(() -> (i64, !) => { try context.io.sleep(10); 42 });
|
||||
ps.spawn(() {
|
||||
a := context.io.async(() -> (i64, !) { try context.io.sleep(5); raise error.Boom; });
|
||||
b := context.io.async(() -> (i64, !) { try context.io.sleep(10); 42 });
|
||||
winner := context.io.race(.(a = a, b = b));
|
||||
if winner == {
|
||||
case .a: (v) { print("winner: a = {}\n", v); }
|
||||
|
||||
@@ -28,10 +28,10 @@ main :: () -> i64 {
|
||||
ps := @s;
|
||||
pbase.* = gpa.alloc_count; // baseline: scheduler is live, no tasks yet
|
||||
push .{ io = xx s, allocator = xx gpa, data = null } {
|
||||
ps.spawn(() => {
|
||||
a := context.io.async(() -> (i64, !) => { try context.io.sleep(10); 100 });
|
||||
b := context.io.async(() -> (i64, !) => { try context.io.sleep(20); 20 });
|
||||
c := context.io.async(() -> (i64, !) => { try context.io.sleep(30); 3 });
|
||||
ps.spawn(() {
|
||||
a := context.io.async(() -> (i64, !) { try context.io.sleep(10); 100 });
|
||||
b := context.io.async(() -> (i64, !) { try context.io.sleep(20); 20 });
|
||||
c := context.io.async(() -> (i64, !) { try context.io.sleep(30); 3 });
|
||||
psum.* = (a.await() or 0) + (b.await() or 0) + (c.await() or 0);
|
||||
});
|
||||
ps.run();
|
||||
|
||||
Reference in New Issue
Block a user