test: group examples into per-category folders
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.
This commit is contained in:
17
examples/atomics/1700-atomics-load-store.sx
Normal file
17
examples/atomics/1700-atomics-load-store.sx
Normal file
@@ -0,0 +1,17 @@
|
||||
// Atomic($T) load/store with explicit memory orderings, single-thread.
|
||||
// Stream A (atomics) A.0 + A.0.5 — the ordering is a comptime `$o: Ordering`
|
||||
// param (explicit, Rust-style): a.load(.acquire) emits `load atomic … acquire`.
|
||||
// An invalid combination (a.load(.release)) is a compile error (see 1131).
|
||||
#import "modules/std.sx";
|
||||
#import "modules/std/atomic.sx";
|
||||
|
||||
main :: () {
|
||||
a := Atomic(i64).init(7);
|
||||
print("init: {}\n", a.load(.seq_cst));
|
||||
|
||||
a.store(42, .release);
|
||||
print("after store: {}\n", a.load(.acquire));
|
||||
|
||||
a.store(a.load(.relaxed) + 1, .seq_cst);
|
||||
print("incremented: {}\n", a.load(.seq_cst));
|
||||
}
|
||||
39
examples/atomics/1701-atomics-rmw.sx
Normal file
39
examples/atomics/1701-atomics-rmw.sx
Normal file
@@ -0,0 +1,39 @@
|
||||
// Atomic($T) read-modify-write: fetch_add/sub/and/or/xor/min/max → LLVM atomicrmw.
|
||||
// Each returns the OLD value. Stream A (atomics) A.1. Single-thread.
|
||||
// Also covers signed min/max with NEGATIVES at BOTH comptime (#run) and runtime —
|
||||
// they must agree (regression: comptime once did an unsigned compare).
|
||||
#import "modules/std.sx";
|
||||
#import "modules/std/atomic.sx";
|
||||
|
||||
// comptime (#run) signed min/max with a negative — must match runtime.
|
||||
c_max :: () -> i64 { a := Atomic(i64).init(-5); _ := a.fetch_max(3, .seq_cst); return a.load(.seq_cst); }
|
||||
c_min :: () -> i64 { a := Atomic(i64).init(-5); _ := a.fetch_min(3, .seq_cst); return a.load(.seq_cst); }
|
||||
G_MAX :: #run c_max();
|
||||
G_MIN :: #run c_min();
|
||||
|
||||
main :: () {
|
||||
a := Atomic(i64).init(10);
|
||||
print("old add: {}\n", a.fetch_add(5, .seq_cst)); // returns 10, now 15
|
||||
print("old sub: {}\n", a.fetch_sub(3, .acq_rel)); // returns 15, now 12
|
||||
print("now: {}\n", a.load(.acquire)); // 12
|
||||
|
||||
b := Atomic(i64).init(0xF0);
|
||||
print("old and: {}\n", b.fetch_and(0x3C, .relaxed));// returns 0xF0(240), now 0x30(48)
|
||||
print("old or: {}\n", b.fetch_or(0x03, .relaxed)); // returns 0x30(48), now 0x33(51)
|
||||
print("old xor: {}\n", b.fetch_xor(0x0F, .relaxed));// returns 0x33(51), now 0x3C(60)
|
||||
print("now: {}\n", b.load(.relaxed)); // 60
|
||||
|
||||
m := Atomic(i64).init(20);
|
||||
print("old min: {}\n", m.fetch_min(8, .seq_cst)); // returns 20, now 8
|
||||
print("old max: {}\n", m.fetch_max(15, .seq_cst)); // returns 8, now 15
|
||||
print("now: {}\n", m.load(.seq_cst)); // 15
|
||||
|
||||
// signed min/max with a negative — comptime (#run) and runtime must agree.
|
||||
s := Atomic(i64).init(-5);
|
||||
_ := s.fetch_max(3, .seq_cst);
|
||||
print("runtime signed max(-5,3): {}\n", s.load(.seq_cst)); // 3
|
||||
s.store(-5, .seq_cst);
|
||||
_ := s.fetch_min(3, .seq_cst);
|
||||
print("runtime signed min(-5,3): {}\n", s.load(.seq_cst)); // -5
|
||||
print("comptime signed max(-5,3)={} min(-5,3)={}\n", G_MAX, G_MIN); // 3 / -5
|
||||
}
|
||||
34
examples/atomics/1702-atomics-cas.sx
Normal file
34
examples/atomics/1702-atomics-cas.sx
Normal file
@@ -0,0 +1,34 @@
|
||||
// Atomic($T) compare-exchange: compare_exchange / compare_exchange_weak → LLVM
|
||||
// cmpxchg. Result is `?T` — null = SUCCESS; a present value is the ACTUAL current
|
||||
// value on failure (for a retry loop). Stream A (atomics) A.2. Single-thread.
|
||||
#import "modules/std.sx";
|
||||
#import "modules/std/atomic.sx";
|
||||
|
||||
main :: () {
|
||||
// Successful CAS: 10 == 10 → store 20, returns null.
|
||||
a := Atomic(i64).init(10);
|
||||
got := a.compare_exchange(10, 20, .acq_rel, .acquire);
|
||||
if got == null {
|
||||
print("cas ok, now: {}\n", a.load(.acquire)); // 20
|
||||
} else {
|
||||
print("cas unexpected fail: {}\n", got!);
|
||||
}
|
||||
|
||||
// Failing CAS: 99 != 20 → no store, returns the actual value (20), unchanged.
|
||||
got2 := a.compare_exchange(99, 0, .seq_cst, .seq_cst);
|
||||
if got2 == null {
|
||||
print("cas unexpected ok\n");
|
||||
} else {
|
||||
print("cas failed, actual: {}, still: {}\n", got2!, a.load(.seq_cst)); // 20, 20
|
||||
}
|
||||
|
||||
// Retry loop with the weak variant: increment a counter by 5.
|
||||
counter := Atomic(i64).init(100);
|
||||
cur := counter.load(.relaxed);
|
||||
while true {
|
||||
r := counter.compare_exchange_weak(cur, cur + 5, .acq_rel, .acquire);
|
||||
if r == null { break; }
|
||||
cur = r!; // retry with the observed value
|
||||
}
|
||||
print("after loop: {}\n", counter.load(.seq_cst)); // 105
|
||||
}
|
||||
16
examples/atomics/1703-atomics-swap.sx
Normal file
16
examples/atomics/1703-atomics-swap.sx
Normal file
@@ -0,0 +1,16 @@
|
||||
// Atomic($T).swap — atomic exchange (LLVM atomicrmw xchg): store the new value,
|
||||
// return the OLD one. Stream A (atomics) A.3. Single-thread.
|
||||
// Covers swap at BOTH comptime (#run) and runtime — they must agree.
|
||||
#import "modules/std.sx";
|
||||
#import "modules/std/atomic.sx";
|
||||
|
||||
c_swap :: () -> i64 { a := Atomic(i64).init(7); old := a.swap(42, .seq_cst); return old * 100 + a.load(.seq_cst); }
|
||||
G_SWAP :: #run c_swap(); // 742 (old 7, now 42)
|
||||
|
||||
main :: () {
|
||||
a := Atomic(i64).init(7);
|
||||
old := a.swap(42, .acq_rel);
|
||||
print("swap old: {}\n", old); // 7
|
||||
print("swap now: {}\n", a.load(.acquire)); // 42
|
||||
print("comptime swap: {}\n", G_SWAP); // 742 (matches runtime)
|
||||
}
|
||||
15
examples/atomics/1704-atomics-fence.sx
Normal file
15
examples/atomics/1704-atomics-fence.sx
Normal file
@@ -0,0 +1,15 @@
|
||||
// Standalone memory fence — fence(.ordering) → LLVM fence. Stream A (atomics) A.3.
|
||||
// (.relaxed is rejected; see 1187.) Single-thread: a fence is observable only as
|
||||
// "compiled + ran without error" here.
|
||||
#import "modules/std.sx";
|
||||
#import "modules/std/atomic.sx";
|
||||
|
||||
main :: () {
|
||||
a := Atomic(i64).init(1);
|
||||
a.store(2, .relaxed);
|
||||
fence(.release);
|
||||
a.store(3, .relaxed);
|
||||
fence(.acquire);
|
||||
fence(.seq_cst);
|
||||
print("after fences: {}\n", a.load(.relaxed)); // 3
|
||||
}
|
||||
20
examples/atomics/1705-atomics-bool-byte-promoted.sx
Normal file
20
examples/atomics/1705-atomics-bool-byte-promoted.sx
Normal file
@@ -0,0 +1,20 @@
|
||||
// Atomic(bool) — a sub-byte (i1) element atomically loaded/stored. LLVM
|
||||
// rejects a sub-byte atomic ("atomic memory access' size must be byte-
|
||||
// sized"), so codegen performs the access in the byte storage type (i8)
|
||||
// and trunc/zext's the value at the boundary. (rmw/cmpxchg on a bool is
|
||||
// rejected at the sx level — integer-only — so only load/store apply.)
|
||||
// Regression (issue 0152): Atomic(bool) emitted an i1 atomic that failed
|
||||
// LLVM verification; Future.canceled: Atomic(bool) in the async layer hit it.
|
||||
#import "modules/std.sx";
|
||||
#import "modules/std/atomic.sx";
|
||||
|
||||
main :: () {
|
||||
a := Atomic(bool).init(false);
|
||||
print("init: {}\n", a.load(.acquire)); // false
|
||||
|
||||
a.store(true, .release);
|
||||
print("after store: {}\n", a.load(.acquire)); // true
|
||||
|
||||
a.store(false, .seq_cst);
|
||||
print("after reset: {}\n", a.load(.seq_cst)); // false
|
||||
}
|
||||
1
examples/atomics/expected/1700-atomics-load-store.exit
Normal file
1
examples/atomics/expected/1700-atomics-load-store.exit
Normal file
@@ -0,0 +1 @@
|
||||
0
|
||||
1
examples/atomics/expected/1700-atomics-load-store.stderr
Normal file
1
examples/atomics/expected/1700-atomics-load-store.stderr
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
3
examples/atomics/expected/1700-atomics-load-store.stdout
Normal file
3
examples/atomics/expected/1700-atomics-load-store.stdout
Normal file
@@ -0,0 +1,3 @@
|
||||
init: 7
|
||||
after store: 42
|
||||
incremented: 43
|
||||
1
examples/atomics/expected/1701-atomics-rmw.exit
Normal file
1
examples/atomics/expected/1701-atomics-rmw.exit
Normal file
@@ -0,0 +1 @@
|
||||
0
|
||||
1
examples/atomics/expected/1701-atomics-rmw.stderr
Normal file
1
examples/atomics/expected/1701-atomics-rmw.stderr
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
13
examples/atomics/expected/1701-atomics-rmw.stdout
Normal file
13
examples/atomics/expected/1701-atomics-rmw.stdout
Normal file
@@ -0,0 +1,13 @@
|
||||
old add: 10
|
||||
old sub: 15
|
||||
now: 12
|
||||
old and: 240
|
||||
old or: 48
|
||||
old xor: 51
|
||||
now: 60
|
||||
old min: 20
|
||||
old max: 8
|
||||
now: 15
|
||||
runtime signed max(-5,3): 3
|
||||
runtime signed min(-5,3): -5
|
||||
comptime signed max(-5,3)=3 min(-5,3)=-5
|
||||
1
examples/atomics/expected/1702-atomics-cas.exit
Normal file
1
examples/atomics/expected/1702-atomics-cas.exit
Normal file
@@ -0,0 +1 @@
|
||||
0
|
||||
1
examples/atomics/expected/1702-atomics-cas.stderr
Normal file
1
examples/atomics/expected/1702-atomics-cas.stderr
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
3
examples/atomics/expected/1702-atomics-cas.stdout
Normal file
3
examples/atomics/expected/1702-atomics-cas.stdout
Normal file
@@ -0,0 +1,3 @@
|
||||
cas ok, now: 20
|
||||
cas failed, actual: 20, still: 20
|
||||
after loop: 105
|
||||
1
examples/atomics/expected/1703-atomics-swap.exit
Normal file
1
examples/atomics/expected/1703-atomics-swap.exit
Normal file
@@ -0,0 +1 @@
|
||||
0
|
||||
1
examples/atomics/expected/1703-atomics-swap.stderr
Normal file
1
examples/atomics/expected/1703-atomics-swap.stderr
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
3
examples/atomics/expected/1703-atomics-swap.stdout
Normal file
3
examples/atomics/expected/1703-atomics-swap.stdout
Normal file
@@ -0,0 +1,3 @@
|
||||
swap old: 7
|
||||
swap now: 42
|
||||
comptime swap: 742
|
||||
1
examples/atomics/expected/1704-atomics-fence.exit
Normal file
1
examples/atomics/expected/1704-atomics-fence.exit
Normal file
@@ -0,0 +1 @@
|
||||
0
|
||||
1
examples/atomics/expected/1704-atomics-fence.stderr
Normal file
1
examples/atomics/expected/1704-atomics-fence.stderr
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
1
examples/atomics/expected/1704-atomics-fence.stdout
Normal file
1
examples/atomics/expected/1704-atomics-fence.stdout
Normal file
@@ -0,0 +1 @@
|
||||
after fences: 3
|
||||
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
init: false
|
||||
after store: true
|
||||
after reset: false
|
||||
Reference in New Issue
Block a user