Move examples/*.sx and their expected/ snapshots into per-category subfolders (examples/<category>/...). Folder = leading filename token, with ffi-objc/ffi-jni kept whole; filenames are unchanged. The corpus runner and LSP sweep now discover each category's expected/ dir, while issues/ stays flat. Example 1058's repo-root-relative companion import is made file-relative. Path strings embedded in 164 snapshots were regenerated (path-only changes). Test-layout docs in CLAUDE.md updated.
49 lines
2.2 KiB
Plaintext
49 lines
2.2 KiB
Plaintext
// Stream B1 (fibers) step B1.1 — per-fiber `context` root, via plain
|
|
// snapshot + `push` (NO compiler change — the substrate the fiber spawn relies on).
|
|
//
|
|
// `context` is an implicit `*Context` parameter (slot 0) threaded through every
|
|
// sx call, and `push Context` allocates the new context on the caller's stack
|
|
// frame — so a function's context is CALL-CARRIED and rides its own stack, never
|
|
// read from a global. That is exactly what a fiber needs: each fiber, on its own
|
|
// stack, reads its own root context.
|
|
//
|
|
// This locks the spawn convention end-to-end with ordinary language features:
|
|
// 1. capture the spawner's context as a value (`snap := context`)
|
|
// 2. store the snapshot in a struct (the stand-in `Fiber`)
|
|
// 3. a trampoline, running under a DIFFERENT ambient context, installs the
|
|
// fiber's stored root before entering the body (`push f.root { … }`)
|
|
// The body sees the snapshot (42), not the trampoline's ambient context (99),
|
|
// and the `push` scope restores the ambient context on exit. No fiber runtime
|
|
// exists yet (that is B1.3) — this proves the context plumbing it will build on.
|
|
#import "modules/std.sx";
|
|
|
|
// Stand-in for a Fiber: stores the spawner's snapshotted root Context.
|
|
Fiber :: struct { root: Context; }
|
|
|
|
// Reads this call's context sentinel (carried in `context.data` here for the
|
|
// test; a real fiber carries its allocator / io the same way).
|
|
sentinel :: () -> i64 { return xx context.data; }
|
|
|
|
// Trampoline: runs under its own ambient context, but installs the fiber's
|
|
// stored root before entering the fiber body.
|
|
run_fiber :: (f: *Fiber) -> i64 {
|
|
push f.root {
|
|
return sentinel();
|
|
}
|
|
}
|
|
|
|
main :: () {
|
|
snap := context;
|
|
snap.data = xx 42; // the spawner's sentinel
|
|
f := Fiber.{ root = snap }; // snapshot stored in the fiber
|
|
|
|
other := context;
|
|
other.data = xx 99; // a DIFFERENT ambient context
|
|
push other {
|
|
// Ambient is 99 here; the trampoline must install f.root (42).
|
|
print("fiber root: {}\n", run_fiber(@f));
|
|
// After run_fiber returns, this scope's ambient context is intact.
|
|
print("ambient after: {}\n", sentinel());
|
|
}
|
|
}
|