|
| 1 | +# MeTTaScript 2.0.2 |
| 2 | + |
| 3 | +A correctness release. Recursion depth is now deterministic: a program's output no longer depends on how |
| 4 | +much native JavaScript stack the host gave the evaluation. Semantics are otherwise unchanged from 2.0.1, |
| 5 | +and every terminating program produces the same output, validated byte-identical on the conformance |
| 6 | +oracle, the full test suite, and all 103 terminating corpus programs. Upgrading from 2.0.1 is safe. |
| 7 | + |
| 8 | +## Deterministic recursion depth |
| 9 | + |
| 10 | +Before this release, a program whose control flow depends on recursion depth could observe different |
| 11 | +output depending on how deep the evaluation ran before the native stack overflowed. A compiled fragment |
| 12 | +uses fewer native frames per step than the interpreter, so the two paths could reach different depths and |
| 13 | +emit different results for the same program. One corpus program, `greedy_chess`, showed it directly: the |
| 14 | +compiled path emitted thousands more lines than the interpreted path purely because it overflowed later. |
| 15 | + |
| 16 | +Two changes remove the host stack from the picture. Recursion is counted as a logical depth of |
| 17 | +user-equation calls, the same way on the interpreted and compiled paths, so both reach the same bound. |
| 18 | +And once recursion passes a fixed native-frame threshold it is handed to a heap-driven trampoline that |
| 19 | +carries the rest of the evaluation without growing the native stack, so the logical bound is actually |
| 20 | +reachable no matter how much stack the host has. Output is now a function of the program and the bound, |
| 21 | +not of the environment. |
| 22 | + |
| 23 | +The default bound is 320 user-equation calls. This replaces the previous default, where recursion ran |
| 24 | +until the native stack overflowed at a host-dependent depth, with a deterministic limit that sits above |
| 25 | +the deepest terminating corpus program. A program that needs to recurse deeper can raise it with |
| 26 | +`(pragma! max-stack-depth N)` or the `maxStackDepth` option. |
| 27 | + |
| 28 | +`greedy_chess` now produces identical output through both engines, the result is independent of the V8 |
| 29 | +stack size across every size tested, and the full terminating corpus stays byte-identical. |
| 30 | + |
| 31 | +## Performance |
| 32 | + |
| 33 | +Determinism was the goal, not speed. On the workloads measured the change is within control noise. A |
| 34 | +clean-machine confirmation across the corpus is still pending. |
| 35 | + |
| 36 | +## Known limitation: a work budget for broad search (being fixed) |
| 37 | + |
| 38 | +A depth bound bounds depth, not total work. A program that branches broadly, such as the PLN direct proof |
| 39 | +search in `plntestdirect`, can now run all the way to the depth bound and take a long time, where before |
| 40 | +it failed fast by overflowing the native stack early. Its output is no longer host-dependent, but it is |
| 41 | +not yet bounded by a deterministic amount of work. A step budget that cuts broad search at an |
| 42 | +environment-independent point is in progress for a follow-up release. |
| 43 | + |
| 44 | +## Notes |
| 45 | + |
| 46 | +The guarantee covers recursion depth. The depth of a single deeply nested expression still follows the |
| 47 | +host stack, since evaluating nested arguments consumes native frames without adding logical depth. |
| 48 | +`(pragma! max-stack-depth N)` now counts user-equation calls, which is tail-transparent and differs from |
| 49 | +Hyperon's raw frame count. |
| 50 | + |
1 | 51 | # MeTTaScript 2.0.1 |
2 | 52 |
|
3 | 53 | A performance, robustness, and conformance patch. Semantics are unchanged from 2.0.0: every |
|
0 commit comments