This allows parsing some corner cases of the cond expression default values, in particular #1118.
The current condForm greedily parses the list of branches as, roughly speaking, valueLevel >> valueLevel (I'm omitting handling their results for brevity), and the default/fallback clause of the form (a b) gets consumed by this as well, so the final default clause parser doesn't see it and errors out.
To generalize, the problem is that we need to parse a list of ps followed by a single q, where p recognizes a (proper) subset of strings from q. The current parser effectively does some p >> q, which fails if that last element is in p (where, un-generalizing back to our problem, p is the branches parser, and q is the default clause parser).
Looks like the only solution (besides some post-processing and reshuffling of parsed terms, which is probably not something we'd like to do) is to do some lookahead. The way it's done here is as follows:
We first try to parse q ensuring it's not followed by another q. If it isn't followed, then it must be the final q and we're good.
If it is, then it must really be the (non-final) p, so we backtrack and parse with p.
As a side note, this parser now also accepts a cond with a single default clause and no branches — it makes the implementation a tad simpler and more readable in what's already a somewhat non-trivial code, without sacrificing correctness. If somebody wants an effectively no-op cond, shall we let them?
PR checklist:
[x] Test coverage for the proposed changes
[x] PR description contains example output from repl interaction or a snippet from unit test output
[x] Documentation has been updated if new natives or FV properties have been added. To generate new documentation, issue cabal run tests. If they pass locally, docs are generated.
Closing this without merging since getting corner cases ironed out in the type checker proves to be harder than expected. It seems to be more reasonable to delay this until type checker gets overhauled.
This allows parsing some corner cases of the
cond
expression default values, in particular #1118.The current
condForm
greedily parses the list of branches as, roughly speaking,valueLevel >> valueLevel
(I'm omitting handling their results for brevity), and the default/fallback clause of the form(a b)
gets consumed by this as well, so the final default clause parser doesn't see it and errors out.To generalize, the problem is that we need to parse a list of
p
s followed by a singleq
, wherep
recognizes a (proper) subset of strings fromq
. The current parser effectively doessome p >> q
, which fails if that last element is inp
(where, un-generalizing back to our problem,p
is the branches parser, andq
is the default clause parser).Looks like the only solution (besides some post-processing and reshuffling of parsed terms, which is probably not something we'd like to do) is to do some lookahead. The way it's done here is as follows:
q
ensuring it's not followed by anotherq
. If it isn't followed, then it must be the finalq
and we're good.p
, so we backtrack and parse withp
.As a side note, this parser now also accepts a
cond
with a single default clause and no branches — it makes the implementation a tad simpler and more readable in what's already a somewhat non-trivial code, without sacrificing correctness. If somebody wants an effectively no-opcond
, shall we let them?PR checklist:
cabal run tests
. If they pass locally, docs are generated.pact -t
), make sure pact-lsp is in sync.Additionally, please justify why you should or should not do the following: