Recursive let causes unbound match to fail
A recursive
let
causes any matching to unbound variables to fail.Here’s an example. Note that variable
x
is unbound, but the match fails and therefore the whole strategy fails. Removing the offending line causes the strategy to succeed, and return15
.example = let lambda = ?x ; // <- Offending line if <eq> (0, <id>) then !0 else <add> (<id>, <subt ; lambda> (<id>, 1)) end in <lambda> 5 end
This bug happens only when the
let
is recursive (so it gets its own strategy and is not optimized away). The variablex
is clearly an unbound variable, but the match fails.
The generated Java code shows why the match causes the strategy to fail. The
let
is represented as its own strategyu_19
that has fields for any captured variables. A match will fail ifx
is bound and not equal to the matched term. In this case, we would expectx
to be unbound, and therefore the match should always succeed.final class u_19 extends Strategy { TermReference x; public IStrategoTerm invoke(Context context, IStrategoTerm term) { ITermFactory termFactory = context.getFactory(); Fail22: { if(x.value == null) x.value = term; else if(x.value != term && !x.value.match(term)) break Fail22; // ... } return null; }
But here’s the generated Java code for the
example
strategy. It bindsx
in thelet
to aTermReference
. Sincex
is no longer an unbound variable, the match fails.Submitted by D. Pelsmaeker on 7 May 2015 at 13:20public class example_0_0 extends Strategy { public static example_0_0 instance = new example_0_0(); public IStrategoTerm invoke(Context context, IStrategoTerm term) { context.push("example_0_0"); Fail21: { TermReference x = new TermReference(); // ... u_19 u_190 = new u_19(); u_190.x = x; term = u_190.invoke(context, term); if(term == null) break Fail21; // ... } context.popOnFailure(); return null; } }
Log in to post comments