test: reproduce the Lua parser-nesting crash behind #108#111
Merged
Conversation
#108) The #108 goldens (LongApplyChain etc.) only exercise the *fixed* path — the golden harness always runs the full optimizer, so they never show the red state, and the regression they guard was asserted rather than demonstrated. Add a focused test at the generated-Lua level: build a ~300-deep applicative spine (`apply (apply (apply 0 1) 2) … n`, depth in the first-argument position), compile it to Lua twice via `compileIr` — once WITHOUT `flattenDeepBinds`, once with — and parse-check each with `luac -p`. Without the pass the chunk fails to load with "chunk has too many syntax levels"; with it, it loads. Crucially the unflattened form is a single nested expression whose only `local` is the module table, so the test asserts exactly one `local` — proving the failure is parser *nesting*, not Lua 5.1's separate 200-locals-per-function cap (the limit a naive full A-normalisation would instead hit). This is the red-before-green check that pins the bug to the right cause.
There was a problem hiding this comment.
Pull request overview
Adds a regression-reproduction test in the Lua golden spec to demonstrate (red-before-green) the Lua 5.1 parser-nesting crash behind #108 by compiling a synthetic deep applicative spine with and without flattenDeepBinds, then validating parseability via luac -p.
Changes:
- Add a new golden-spec test that compiles a ~300-deep apply spine both unflattened and flattened, and asserts
luac -pfailure vs success. - Introduce helpers to build the synthetic
UberModuleand to parse-check generated Lua withluac -p.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Unisay
added a commit
that referenced
this pull request
Jun 23, 2026
…ew-fixes address copilot review on #111: robust luacParse + looser local-count check
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #110. The #108 goldens (
LongApplyChain,LongBindFlipped) only exercise the fixed path — the golden harness always runs the full optimizer, so they never show the red state, and the regression they guard was asserted rather than demonstrated. This adds the missing red-before-green reproduction.What it does
A new test in the Lua golden spec builds a ~300-deep applicative spine (
apply (apply (apply 0 1) 2) … n, depth in the first-argument position) as a syntheticUberModule, compiles it to Lua twice viacompileIr— once withoutflattenDeepBinds, once with — and parse-checks each withluac -p(parse only, no execution):luacfails withchunk has too many syntax levels;Why it pins the bug to the right cause
Lua 5.1 has two distinct per-function limits, and a wrong fix can trade one for the other (a naive full A-normalisation flattens the nesting but overflows the 200-locals cap). The unflattened spine here is a single nested expression whose only
localis the module table, so the test asserts exactly onelocal— which means the failure can only be parser nesting, not the locals cap. The error message (too many syntax levels) confirms it.This complements the empirical finding that nested call arguments (and nested function bodies, and nested parens) overflow the recursive-descent parser, while a flat curried suffix chain
f(a)(b)(c)…does not — i.e.spineDepthis a deliberately conservative over-approximation of the parser's actual nesting cost.Test-only; no production code changes.