Skip to content

fix: parenthesise table literals before bracket indexing#62

Merged
Unisay merged 2 commits into
mainfrom
fix/table-literal-indexing-parens
Jun 14, 2026
Merged

fix: parenthesise table literals before bracket indexing#62
Unisay merged 2 commits into
mainfrom
fix/table-literal-indexing-parens

Conversation

@Unisay

@Unisay Unisay commented Jun 14, 2026

Copy link
Copy Markdown
Collaborator

Carries @afcondon's fix from #40 (rebased onto current main) and adds the test it was missing.

The bug

In Lua a table constructor cannot be indexed directly: { ["k"] = v }["k"] is a syntax error, while ({ ["k"] = v })["k"] is valid. The Lua printer wrapped VarField targets in wrapPrec PrecAtom but not VarIndex, so a table literal in index position emitted invalid Lua.

The fix

VarIndex now wraps its target with wrapPrec PrecAtom, exactly like VarField already did. That commit is @afcondon's, preserved as-is.

Tests

  • A new Printer spec case mirroring the existing VarField one: ({ ["foo"] = 1 })["foo"]. Without the fix it renders { ["foo"] = 1 }["foo"] and the assertion fails with a clear diff, which is the regression guard the original PR was asked for.
  • The CharLiterals and StringCodePoints goldens are regenerated. The same wrapping now also parenthesises function-call results before ["$ctor"] indexing (e.g. f(x)(y)["$ctor"] becomes (f(x)(y))["$ctor"]). That change is purely syntactic: the IR and eval output are unchanged and both files pass luacheck.

Supersedes #40, whose branch predates the StringCodePoints golden, so the work has to sit on current main.

afcondon and others added 2 commits June 14, 2026 09:46
In Lua, table constructor literals cannot be directly indexed without
parentheses. The expression `{ ["key"] = val }["key"]` is a syntax error,
while `({ ["key"] = val })["key"]` is valid.

This fix adds the same `wrapPrec PrecAtom` wrapping to `VarIndex` that
was already applied to `VarField`, ensuring table literals are properly
parenthesized when used with bracket indexing.

Fixes pattern matching on ADT constructors that would generate invalid
Lua like:

  if "Mod∷Type.Ctor" == { ["$ctor"] = "Mod∷Type.Ctor" }["$ctor"] then

Now correctly generates:

  if "Mod∷Type.Ctor" == ({ ["$ctor"] = "Mod∷Type.Ctor" })["$ctor"] then

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Mirror the existing VarField spec case for VarIndex: a table constructor
must be parenthesised before bracket indexing, since
`{ ["foo"] = 1 }["foo"]` is a Lua syntax error while
`({ ["foo"] = 1 })["foo"]` is valid. Without the preceding fix this
assertion fails with a clear diff.

Regenerate the CharLiterals and StringCodePoints goldens, where the same
wrapPrec PrecAtom now parenthesises function-call results before
["$ctor"] indexing, matching VarField. Purely syntactic: IR and eval
output are unchanged and both files pass luacheck.
@Unisay Unisay requested a review from Copilot June 14, 2026 08:43
@Unisay Unisay self-assigned this Jun 14, 2026

This comment was marked as low quality.

@Unisay Unisay merged commit c1b9dd0 into main Jun 14, 2026
2 checks passed
@Unisay Unisay deleted the fix/table-literal-indexing-parens branch June 14, 2026 08:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants