nx_probe_closure_lift.nx source
↩ module page · 73 lines · 4007 B
1// nx_probe_closure_lift.nx -- LN13b BEHAVIOUR WITNESS: a non-capturing function literal is lifted,
2// its address is a value, and CALLING that value computes what the body says.
3//
4// WHY THIS IS A SELF-CHECKING PROGRAM AND NOT A LIST OF ASSERTIONS IN A GATE. The defect this rung
5// closes is not "does it compile" -- the pre-fix compiler REFUSED the construct outright, which is
6// easy to detect. The defect worth guarding is the one that survives a green compile: a literal
7// that lifts to the wrong body, binds the wrong parameter, or returns the caller's first argument
8// because a synthesized return carried value id 0. None of those change the exit status of the
9// COMPILER; all of them change the exit status of THIS PROGRAM. So the witness is a run, and the
10// gate reads only its exit code -- 0 means every arithmetic identity below held.
11//
12// Each check returns a DISTINCT non-zero code so a failure names itself without a debugger.
13// license_tier: ORIGINAL. Pure arithmetic, no syscalls beyond exit. No hw writes (Rule 26).
14
15func plf_double(x: i64) -> i64 { return x + x }
16
17func plf_apply1(f: func(i64) -> i64, v: i64) -> i64 { return f(v) }
18
19func main(argc: i64, argv: **u8) -> i64 {
20 // 1. THE LIFT ITSELF: a literal bound to a local, then called through that local.
21 let f: func(i64) -> i64 = func(x: i64) -> i64 { return x + x }
22 if f(21) != 42 { return 11 }
23
24 // 2. NOT A CONSTANT: the same callee over a second input. A lift that folded to its first
25 // observed result would pass check 1 and fail here.
26 if f(0) != 0 { return 12 }
27 if f(0 - 5) != (0 - 10) { return 13 }
28
29 // 3. THE BODY IS THE LITERAL'S, NOT A NEIGHBOUR'S. Two literals with different bodies must
30 // stay distinct -- a synthesized name collision would resolve one address for both.
31 let g: func(i64) -> i64 = func(x: i64) -> i64 { return x + 1 }
32 if g(41) != 42 { return 14 }
33 if f(41) != 82 { return 15 }
34
35 // 4. PARAMETER ORDER, and a second parameter at all.
36 let sub: func(i64, i64) -> i64 = func(a: i64, b: i64) -> i64 { return a - b }
37 if sub(50, 8) != 42 { return 16 }
38 if sub(8, 50) != (0 - 42) { return 17 }
39
40 // 5. THE SPILL BOUNDARY. Six arguments fit the register set; the SEVENTH is the first that
41 // must travel on the stack, and it is exactly the case nx_tc_canary deliberately does not
42 // cover (tc_six stops at six on purpose). A lift that got the frame layout wrong reads a
43 // neighbouring slot and this is where it shows.
44 let s6: func(i64, i64, i64, i64, i64, i64) -> i64 =
45 func(a: i64, b: i64, c: i64, d: i64, e: i64, f6: i64) -> i64 {
46 return a + b + c + d + e + f6
47 }
48 if s6(1, 2, 4, 8, 16, 11) != 42 { return 18 }
49 let s7: func(i64, i64, i64, i64, i64, i64, i64) -> i64 =
50 func(a: i64, b: i64, c: i64, d: i64, e: i64, f7: i64, g7: i64) -> i64 {
51 return a + b + c + d + e + f7 + g7
52 }
53 if s7(1, 2, 4, 8, 16, 10, 1) != 42 { return 19 }
54 // The seventh argument must actually REACH the body: vary only it.
55 if s7(1, 2, 4, 8, 16, 10, 2) != 43 { return 20 }
56
57 // 6. THE LITERAL IS A VALUE, so it crosses a call boundary like any other. This is the shape
58 // nx_thread_pool and nx_parallel need, and it exercises the shipped indirect-call path rather
59 // than a local shortcut.
60 if plf_apply1(func(x: i64) -> i64 { return x * 2 }, 21) != 42 { return 21 }
61
62 // 7. NEG-CONTROL, IN-PROGRAM: a named function through the SAME func-typed slot must still
63 // work. If lifting had broken the pre-existing `&fn` path, this fails while everything above
64 // passes -- which is the regression a literal-only witness would miss.
65 let h: func(i64) -> i64 = plf_double
66 if h(21) != 42 { return 22 }
67 if plf_apply1(plf_double, 21) != 42 { return 23 }
68
69 // 8. A literal called immediately, never bound: proves the value needs no storage to be used.
70 if plf_apply1(func(x: i64) -> i64 { return x + 21 }, 21) != 42 { return 24 }
71
72 return 0
73}