Preserve bound vars in match compiler (13.1 expansion pass)
Motivation and Context
The pattern match compiler used to ignore the bound vars and generate fresh vars everywhere (and subsitute in the body of the case).
This MR tries to preserve bound vars in the match compiler (check Names.preserve
) and fix the regression.
Although in some cases bound vars cannot be preserved, which was the case in previous match compiler as well, so this MR conservatively tries to preserve bound wherever possible.
e.g.
type t = A of int | B of string
let _ = match A 1, B "hello" with
| A a1, B b1 -> 1
| A a2, A a3 -> 2
| _ -> 3
(* Here a1 & a2 cannot be preserved
...
match match_#423 with
| ( match_#4230#425sum[A -> int , B -> string] , match_#4231#426sum[A -> int , B -> string] ) ->
match match_#4230#425 with
| A match_#4230A#424 ->
match match_#4231#426 with
| B b1 -> 1
| A a3 -> 2
| B match_#4230B#427 -> 3 in
...
*)
Another large example
type t = A of int | B of string
let _ = match A 1, B "hello" with
| B b1, A a1 -> 1
| A a3, A a1 -> 2
| _ -> 3
let _ = match A 1, B "hello" with
| A a1, B b1 -> 1
| A a2, A a3 -> 2
| _ -> 3
let _ = match A 1, B "hello" with
| A a1, B b2 -> 1
| A a1, A a2 -> 2
| B b1, B b2 -> 3
| B b1, A a2 -> 4
let _ = match A 1, B "hello", A 2 with
| A a1, B b2, a -> 1
| A a1, A a2, a -> 2
| B b1, B b2, a -> 3
| B b1, A a2, a -> 4
(* Ast expanded:
let _#56 = let match_#422 = ( A(1) , B("hello") ) in
match match_#422 with
| ( match_#4220#423sum[A -> int , B -> string] ,
match_#4221#424sum[A -> int , B -> string] ) ->
match match_#4220#423 with
| B b1 ->
match match_#4221#424 with
| A a1 -> 1
| B match_#4221B#426 -> 3
| A a3 ->
match match_#4221#424 with
| A a1 -> 2
| B match_#4221B#425 -> 3 in
let _#58 = let match_#427 = ( A(1) , B("hello") ) in
match match_#427 with
| ( match_#4270#429sum[A -> int , B -> string] ,
match_#4271#430sum[A -> int , B -> string] ) ->
match match_#4270#429 with
| A match_#4270A#428 ->
match match_#4271#430 with
| B b1 -> 1
| A a3 -> 2
| B match_#4270B#431 -> 3 in
let _#59 = let match_#432 = ( A(1) , B("hello") ) in
match match_#432 with
| ( match_#4320#434sum[A -> int , B -> string] ,
match_#4321#435sum[A -> int , B -> string] ) ->
match match_#4320#434 with
| B b1 ->
match match_#4321#435 with
| B b2 -> 3
| A match_#4321A#433 -> 4
| A a1 ->
match match_#4321#435 with
| B b2 -> 1
| A match_#4321A#433 -> 2 in
let _#60 = let match_#436 = ( A(1) , B("hello") , A(2) ) in
match match_#436 with
| ( match_#4360#437sum[A -> int , B -> string] ,
match_#4361#438sum[A -> int , B -> string] ,
a sum[A -> int , B -> string] ) ->
match match_#4360#437 with
| B b1 ->
match match_#4361#438 with
| B b2 -> 3
| A a2 -> 4
| A a1 ->
match match_#4361#438 with
| B b2 -> 1
| A a2 -> 2 in
unit
*)
Description
Component
-
compiler -
website -
webide -
vscode-plugin -
debugger
Types of changes
-
Bug fix (non-breaking change which fixes an issue) -
New feature (non-breaking change which adds functionality) -
Breaking change (fix or feature that would cause existing functionality to not work as expected) -
Performance improvement (non-breaking change that improves performance) -
None (change with no changelog)
Changelog
Checklist:
-
If a new syntax has been introduced, put a message on slack ligo-lsp -
Changes follow the existing coding style (use dune @fmt
to check). -
Tests for the changes have been added (for bug fixes / feature). -
Documentation has been updated. -
Changelog description has been added (if appropriate). -
Start titles under ## Changelog
section with #### (if appropriate). -
There is no image or uploaded file in changelog -
Examples in changed behaviour have been added to the changelog (for breaking change / feature).
Edited by Melwyn Saldanha