Recursive let causes unbound match to fail
A recursive
letcauses any matching to unbound variables to fail.Here’s an example. Note that variable
xis 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 endThis bug happens only when the
letis recursive (so it gets its own strategy and is not optimized away). The variablexis clearly an unbound variable, but the match fails.
The generated Java code shows why the match causes the strategy to fail. The
letis represented as its own strategyu_19that has fields for any captured variables. A match will fail ifxis bound and not equal to the matched term. In this case, we would expectxto 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
examplestrategy. It bindsxin theletto aTermReference. Sincexis 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