Matching on an array literal pattern crashes at runtime. The binders are addressed with the de Bruijn-style 0-based index straight from the IR, but arrays are stored as 1-based Lua tables, so every element is read one slot too low — the first read is always nil.
Repro:
module Main where
import Prelude
import Effect (Effect)
import Effect.Console (log)
firstTwo :: Array Int -> Int
firstTwo = case _ of
[a, b] -> a + b
_ -> -1
main :: Effect Unit
main = log (show (firstTwo [10, 20]))
Generated Lua for the match (note v[0]/v[1] against a { [1]=10, [2]=20 } table):
if 2 == #(v) then
return M.Data_Semiring_semiringInt.add(v[0])(v[1])
Running it:
lua: attempt to perform arithmetic on upvalue 'x' (a nil value)
The index originates in fromCfn in lib/Language/PureScript/Backend/IR.hs, where array binders are numbered zip [0 ..] binders and turned into TakeIndex index. IR.ArrayIndex is then emitted in lib/Language/PureScript/Backend/Lua.hs as Lua.varIndex (Lua.Integer index) with no offset, while the array constructor and the arrays FFI (indexImpl returns xs[i + 1]) are 1-based. The Lua-level ArrayIndex needs index + 1, or the offset has to be applied somewhere on the way to codegen.
No golden currently exercises array-literal patterns, which is why this went unnoticed. A fix should add an eval golden over the repro above.
Matching on an array literal pattern crashes at runtime. The binders are addressed with the de Bruijn-style 0-based index straight from the IR, but arrays are stored as 1-based Lua tables, so every element is read one slot too low — the first read is always
nil.Repro:
Generated Lua for the match (note
v[0]/v[1]against a{ [1]=10, [2]=20 }table):Running it:
The index originates in
fromCfninlib/Language/PureScript/Backend/IR.hs, where array binders are numberedzip [0 ..] bindersand turned intoTakeIndex index.IR.ArrayIndexis then emitted inlib/Language/PureScript/Backend/Lua.hsasLua.varIndex (Lua.Integer index)with no offset, while the array constructor and thearraysFFI (indexImplreturnsxs[i + 1]) are 1-based. The Lua-levelArrayIndexneedsindex + 1, or the offset has to be applied somewhere on the way to codegen.No golden currently exercises array-literal patterns, which is why this went unnoticed. A fix should add an eval golden over the repro above.