code wiki / (root) / nx_token_merge_test.nx

nx_token_merge_test.nx source

↩ module page · 185 lines · 7524 B

1// nx_token_merge_test.nx -- smoke for H8 token merging plan. 2 3import "nx_syscalls.nx" 4import "nx_token_merge.nx" 5 6func main() -> i64 { 7 // ----- 1. Empty-plan construction ----- 8 let p: *NxTokenMergePlan = nx_token_merge_plan_new(16) 9 if nx_token_merge_plan_is_valid(p) != 1 { return 1 } 10 if nx_token_merge_n_tokens(p) != 16 { return 2 } 11 if nx_token_merge_n_merged(p) != 0 { return 3 } 12 if nx_token_merge_n_kept(p) != 16 { return 4 } 13 // Every token is its own root. 14 var i: i64 = 0 15 while i < 16 { 16 if nx_token_merge_target_for(p, i) != i { return 5 } 17 if nx_token_merge_is_kept(p, i) != 1 { return 6 } 18 i = i + 1 19 } 20 if nx_token_merge_reduction_q16(p) != 0 { return 7 } 21 22 // ----- 2. Apply 3 non-conflicting merges ----- 23 // sorted_pairs layout: 3 i64 per pair (left, right, score). 24 let pairs: *i64 = (sys_mmap(256)) as *i64 25 // Pair 0: (0, 1, score 1000) 26 pairs[0] = 0 27 pairs[1] = 1 28 pairs[2] = 1000 29 // Pair 1: (2, 3, 900) 30 pairs[3] = 2 31 pairs[4] = 3 32 pairs[5] = 900 33 // Pair 2: (4, 5, 800) 34 pairs[6] = 4 35 pairs[7] = 5 36 pairs[8] = 800 37 let merged: i64 = nx_token_merge_apply(p, pairs, 3, 3) 38 if merged != 3 { return 8 } 39 if nx_token_merge_n_merged(p) != 3 { return 9 } 40 if nx_token_merge_n_kept(p) != 13 { return 10 } 41 // Token 1 -> root 0; token 3 -> root 2; token 5 -> root 4. 42 if nx_token_merge_target_for(p, 1) != 0 { return 11 } 43 if nx_token_merge_target_for(p, 3) != 2 { return 12 } 44 if nx_token_merge_target_for(p, 5) != 4 { return 13 } 45 // Roots and unmentioned tokens are kept. 46 if nx_token_merge_is_kept(p, 0) != 1 { return 14 } 47 if nx_token_merge_is_kept(p, 2) != 1 { return 15 } 48 if nx_token_merge_is_kept(p, 4) != 1 { return 16 } 49 if nx_token_merge_is_kept(p, 6) != 1 { return 17 } 50 if nx_token_merge_is_kept(p, 1) != 0 { return 18 } 51 52 // Reduction ratio: 3/16 in Q16 = 12288 53 if nx_token_merge_reduction_q16(p) != 12288 { return 19 } 54 55 // ----- 3. Conflicting pair skipped ----- 56 let p2: *NxTokenMergePlan = nx_token_merge_plan_new(8) 57 // Pair 0: (0, 1) -- merges 58 pairs[0] = 0 59 pairs[1] = 1 60 pairs[2] = 99 61 // Pair 1: (0, 2) -- 0 is still root but the priority pair already 62 // claimed 0; in V1 we want CONFLICTS to skip, so (0, 2) where 0 is 63 // STILL root and 2 is fresh -- this is actually NOT a conflict 64 // under V1. Change to (1, 2) where 1 is no longer root. 65 pairs[3] = 1 66 pairs[4] = 2 67 pairs[5] = 98 68 // Pair 2: (3, 4) -- fresh, merges 69 pairs[6] = 3 70 pairs[7] = 4 71 pairs[8] = 97 72 let merged2: i64 = nx_token_merge_apply(p2, pairs, 3, 3) 73 if merged2 != 2 { return 20 } 74 if nx_token_merge_n_merged(p2) != 2 { return 21 } 75 // Token 2 stayed root because its conflict pair was skipped. 76 if nx_token_merge_is_kept(p2, 2) != 1 { return 22 } 77 78 // ----- 4. target_merges caps actual merges ----- 79 let p3: *NxTokenMergePlan = nx_token_merge_plan_new(8) 80 pairs[0] = 0 81 pairs[1] = 1 82 pairs[2] = 99 83 pairs[3] = 2 84 pairs[4] = 3 85 pairs[5] = 98 86 pairs[6] = 4 87 pairs[7] = 5 88 pairs[8] = 97 89 // 3 pairs available but only ask for 1. 90 let merged3: i64 = nx_token_merge_apply(p3, pairs, 3, 1) 91 if merged3 != 1 { return 23 } 92 if nx_token_merge_n_merged(p3) != 1 { return 24 } 93 // The first pair (top-score) wins. 94 if nx_token_merge_target_for(p3, 1) != 0 { return 25 } 95 // Subsequent pairs stay roots. 96 if nx_token_merge_is_kept(p3, 3) != 1 { return 26 } 97 if nx_token_merge_is_kept(p3, 5) != 1 { return 27 } 98 99 // ----- 5. Idempotent re-apply ----- 100 // Calling apply with an already-merged pair is a no-op. 101 let merged3b: i64 = nx_token_merge_apply(p3, pairs, 1, 1) // try (0,1) again 102 if merged3b != 0 { return 28 } // nothing more to do; both touched 103 104 // ----- 6. Exhausted pairs returns fewer than requested ----- 105 let p4: *NxTokenMergePlan = nx_token_merge_plan_new(8) 106 pairs[0] = 0 107 pairs[1] = 1 108 pairs[2] = 99 109 let merged4: i64 = nx_token_merge_apply(p4, pairs, 1, 5) 110 if merged4 != 1 { return 29 } 111 112 // ----- 7. Out-of-bound indices in pairs are skipped, not crashed ----- 113 let p5: *NxTokenMergePlan = nx_token_merge_plan_new(4) 114 pairs[0] = 0 115 pairs[1] = 99 // out of bounds 116 pairs[2] = 99 117 pairs[3] = 1 118 pairs[4] = 2 119 pairs[5] = 98 120 let merged5: i64 = nx_token_merge_apply(p5, pairs, 2, 5) 121 if merged5 != 1 { return 30 } 122 if nx_token_merge_is_kept(p5, 0) != 1 { return 31 } 123 124 // ----- 8. Self-merge (left == right) skipped ----- 125 let p6: *NxTokenMergePlan = nx_token_merge_plan_new(4) 126 pairs[0] = 2 127 pairs[1] = 2 128 pairs[2] = 99 129 let merged6: i64 = nx_token_merge_apply(p6, pairs, 1, 5) 130 if merged6 != 0 { return 32 } 131 if nx_token_merge_is_kept(p6, 2) != 1 { return 33 } 132 133 // ----- 9. Bad inputs ----- 134 let null_p: *i64 = (0 as i64) as *i64 135 if nx_token_merge_apply(p, null_p, 1, 1) != (0 - NX_TOMERGE_BAD_INPUT) { return 34 } 136 if nx_token_merge_apply(p, pairs, -1, 1) != (0 - NX_TOMERGE_BAD_INPUT) { return 35 } 137 if nx_token_merge_apply(p, pairs, 1, -1) != (0 - NX_TOMERGE_BAD_INPUT) { return 36 } 138 139 // ----- 10. Bad plan_new inputs ----- 140 if (nx_token_merge_plan_new(0) as i64) != 0 { return 37 } 141 if (nx_token_merge_plan_new(-1) as i64) != 0 { return 38 } 142 if (nx_token_merge_plan_new(NX_TOMERGE_MAX_TOKENS + 1) as i64) != 0 { return 39 } 143 144 // ----- 11. Out-of-range accessors ----- 145 if nx_token_merge_target_for(p, -1) != (0 - NX_TOMERGE_BAD_INPUT) { return 40 } 146 if nx_token_merge_target_for(p, 16) != (0 - NX_TOMERGE_BAD_INPUT) { return 41 } 147 if nx_token_merge_is_kept(p, -1) != (0 - NX_TOMERGE_BAD_INPUT) { return 42 } 148 if nx_token_merge_is_kept(p, 16) != (0 - NX_TOMERGE_BAD_INPUT) { return 43 } 149 150 // ----- 12. Tamper ----- 151 let tamper_p: *NxTokenMergePlan = nx_token_merge_plan_new(4) 152 tamper_p.canary_post = 0xDEADBEEF 153 if nx_token_merge_plan_is_valid(tamper_p) != 0 { return 44 } 154 if nx_token_merge_apply(tamper_p, pairs, 1, 1) != (0 - NX_TOMERGE_TAMPER) { return 45 } 155 if nx_token_merge_target_for(tamper_p, 0) != (0 - NX_TOMERGE_TAMPER) { return 46 } 156 if nx_token_merge_is_kept(tamper_p, 0) != (0 - NX_TOMERGE_TAMPER) { return 47 } 157 if nx_token_merge_n_kept(tamper_p) != -1 { return 48 } 158 if nx_token_merge_n_merged(tamper_p) != -1 { return 49 } 159 if nx_token_merge_n_tokens(tamper_p) != -1 { return 50 } 160 if nx_token_merge_reduction_q16(tamper_p) != -1 { return 51 } 161 162 // ----- 13. Sealed-enum verdict gates ----- 163 if nx_tomerge_verdict_is_valid(NX_TOMERGE_OK) != 1 { return 52 } 164 if nx_tomerge_verdict_is_valid(NX_TOMERGE_TAMPER) != 1 { return 53 } 165 if nx_tomerge_verdict_is_valid(-1) != 0 { return 54 } 166 if nx_tomerge_verdict_is_valid(NX_TOMERGE_N_VERDICTS) != 0 { return 55 } 167 168 // ----- 14. Root-invariant (no chain length > 1 in V1) ----- 169 // After our applied merges, every assignment[idx] either == idx 170 // OR points to a root. Verify on p (16 tokens, 3 merges done above). 171 var idx: i64 = 0 172 while idx < p.n_tokens { 173 let tgt: i64 = p.assignment[idx] 174 if tgt != idx { 175 // tgt must itself be a root. 176 if p.assignment[tgt] != tgt { return 56 } 177 } 178 idx = idx + 1 179 } 180 181 // ----- 15. n_kept + n_merged == n_tokens invariant ----- 182 if (nx_token_merge_n_kept(p) + nx_token_merge_n_merged(p)) != nx_token_merge_n_tokens(p) { return 57 } 183 184 return 0 185}