Conversation
|
This seems to fail for we get with unbound variable Apparently, when |
Thanks for spotting this problem! I have fixed it and added the example to the test suite. |
4f2536b to
61382a4
Compare
There was a problem hiding this comment.
The problem is only partially fixed, consider
data Bool = False | True;
contract CatchAll {
function catchAll(x, y) -> Bool{
match x, y {
| True, True => return True;
| z, w => return z;
}
}
function main() -> Bool {
catchAll(True, False)
}
}we get
$ esolc catchAll.solc --dump-ds -s -g
> Match compilation result:
data CatchAllCxt = CatchAllCxt ;
data Bool = False | True ;
contract CatchAll {
function catchAll (x<Bool> : Bool, y<Bool> : Bool) -> Bool {
match (x<Bool>) {
| True<Bool> =>
match (y<Bool>) {
| True<Bool> =>
return True<Bool>;
| v1<Bool> =>
return z<Bool>;
}
| v2<Bool> =>
return z<Bool>;
}
}
function main () -> Bool {
return catchAll<Bool -> Bool -> Bool>(True<Bool>, False<Bool>);
}
}
where z is undefined again.
The problem arises when specialize expands a PVar in the selected column
(the constructor column) and a different row's action references the variable
from a different column that was already consumed.
Consider a case where the default branch is taken:
data Bool = False | True;
function catchAll(x, y) {
match x, y {
| True, True => return True;
| z, w => return z;
}
}
Column 0: [PCon True, PVar z] — necessity 1. Column 1: [PCon True, PVar w]
— necessity 1. Tie at depth 1, pick column 0.
Head constructors: [True]. buildConSwitch on occ [0]:
Branch True: specialize produces [[PCon True []], [PVar w]] (row 0
matches True directly; row 1's PVar z expands to fresh patterns — 0 fields,
so just [PCon True []] from the remaining column and [PVar w]). Wait, let
me be precise:
- Row 0:
[PCon True [], PCon True []]→ first col matches True →
[] ++ [PCon True []]=[PCon True []] - Row 1:
[PVar z, PVar w]→ first col is PVar → fresh pats (0 for True) →
[] ++ [PVar w]=[PVar w]
specMat = [[PCon True []], [PVar w]]. specActs = [return True, return z].
Recurse on column 0 (the only column), occ [1]. headCons = [True].
Inner branch True: specialize → [[], []], acts = [return True, return z].
Recurse with empty cols: firstRow [] is all-vars. Leaf [] [return True].
Fine.
Inner default (True incomplete): defaultMatrix [[PCon True []], [PVar w]] =
[[]] (from the PVar w row). defaultActions = [return z].
Recurse: compileMatrix [] [] [[]] [return z]. firstRow [], all-vars.
Leaf [] [return z].
z is unbound. The varBinds is [] (empty row zipped with empty occs).
The action return z goes through with no substitution. But z should be
bound to x — it was the pattern variable in column 0, row 1.
The binding was lost at buildConSwitch's default path (line 202): defaultMatrix
strips the PVar z from the first column and defaultActions keeps [return z],
but no one records that z was bound to occurrence [0].
Similarly via specialize: In the True branch, row 1 had PVar z in column
0. specialize replaced it with fresh patterns (discarding z), but the
action return z survives with z still referencing the now-lost variable.
Root cause
The Maranget algorithm tracks pattern variables through a substitution
environment that maps pattern variables to occurrence paths. This environment
must be extended every time a column is consumed — whether by a constructor
switch, a literal switch, or the all-wildcards case. The current fix only
extends this environment at the Leaf node, which only captures variables from
columns that happen to still be present when the leaf is reached.
Suggested approach
Instead of carrying bindings only in Leaf, accumulate them throughout
compilation. One way: extend compileMatrix to also return a list of
bindings, so that each recursive call can propagate bindings from consumed
columns upward. Alternatively, perform the substitution eagerly: when
specialize or defaultMatrix consumes a column, immediately substitute the
PVar's variable in the corresponding action with the scrutinee expression for
that occurrence. This could be done by augmenting specializedActions and
defaultActions to also rewrite the actions.
|
Other issues mismatch in
|
901620b to
40318ef
Compare
* Implements the pattern matching compiler defined in "Compiling pattern matching to good decision trees". * Adds tests cases.
40318ef to
40e157f
Compare
|
The merge from main brought in synonym-expansion tests, but the merge of
|
|
There still is a problem with matches on single-constructor datatypes (mostly my fault). I have added a quick fix in #340, but we may need a more systematic solution.
|
ff5b015 to
a1e6fe5
Compare
mbenke
left a comment
There was a problem hiding this comment.
Great work! Looks good now. You may want to add fresh-variable-shadowing.solc to Cases.hs
Thanks! Added in the latest commit. |
This PR implements the pattern matching compiler proposed by the following papers:
Now, incomplete patterns are considered a compiler error and redundant patterns generate a warning.