package org.scribble.del.local; import org.scribble.ast.AstFactoryImpl; import org.scribble.ast.Recursion; import org.scribble.ast.ScribNode; import org.scribble.ast.local.LProtocolBlock; import org.scribble.ast.local.LRecursion; import org.scribble.ast.name.simple.RecVarNode; import org.scribble.del.RecursionDel; import org.scribble.main.ScribbleException; import org.scribble.sesstype.name.RecVar; import org.scribble.visit.ProtocolDefInliner; import org.scribble.visit.context.EGraphBuilder; import org.scribble.visit.context.ProjectedChoiceSubjectFixer; import org.scribble.visit.context.UnguardedChoiceDoProjectionChecker; import org.scribble.visit.context.env.UnguardedChoiceDoEnv; import org.scribble.visit.env.InlineProtocolEnv; import org.scribble.visit.wf.ReachabilityChecker; import org.scribble.visit.wf.env.ReachabilityEnv; public class LRecursionDel extends RecursionDel implements LCompoundInteractionNodeDel { @Override public ScribNode leaveUnguardedChoiceDoProjectionCheck(ScribNode parent, ScribNode child, UnguardedChoiceDoProjectionChecker checker, ScribNode visited) throws ScribbleException { Recursion<?> rec = (Recursion<?>) visited; UnguardedChoiceDoEnv merged = checker.popEnv().mergeContext((UnguardedChoiceDoEnv) rec.block.del().env()); checker.pushEnv(merged); return (Recursion<?>) super.leaveUnguardedChoiceDoProjectionCheck(parent, child, checker, rec); } @Override public ScribNode leaveProtocolInlining(ScribNode parent, ScribNode child, ProtocolDefInliner inl, ScribNode visited) throws ScribbleException { LRecursion lr = (LRecursion) visited; //RecVarNode recvar = lr.recvar.clone(); RecVarNode recvar = (RecVarNode) ((InlineProtocolEnv) lr.recvar.del().env()).getTranslation(); LProtocolBlock block = (LProtocolBlock) ((InlineProtocolEnv) lr.block.del().env()).getTranslation(); LRecursion inlined = AstFactoryImpl.FACTORY.LRecursion(lr.getSource(), recvar, block); inl.pushEnv(inl.popEnv().setTranslation(inlined)); return (LRecursion) super.leaveProtocolInlining(parent, child, inl, lr); } @Override public LRecursion leaveReachabilityCheck(ScribNode parent, ScribNode child, ReachabilityChecker checker, ScribNode visited) throws ScribbleException { LRecursion lr = (LRecursion) visited; ReachabilityEnv env = checker.popEnv().mergeContext((ReachabilityEnv) lr.block.del().env()); env = env.removeContinueLabel(lr.recvar.toName()); checker.pushEnv(env); return (LRecursion) LCompoundInteractionNodeDel.super.leaveReachabilityCheck(parent, child, checker, visited); // records the current checker Env to the current del; also pops and merges that env into the parent env*/ } @Override public void enterEGraphBuilding(ScribNode parent, ScribNode child, EGraphBuilder graph) { super.enterEGraphBuilding(parent, child, graph); LRecursion lr = (LRecursion) child; RecVar rv = lr.recvar.toName(); // Update existing state, not replace it -- cf. LDoDel /*if (graph.builder.isUnguardedInChoice()) // Actually, not needed since unfoldings are enough to make graph building work (and this makes combined unguarded choice-rec and continue protocols work) { // Using "previous" entry for this rec lab works because unguarded recs already unfolded (including nested recvar shadowing -- if unguarded choice-rec, it will be unfolded and rec entry recorded for guarded unfolding) graph.builder.pushRecursionEntry(rv, graph.builder.getRecursionEntry(rv)); } else*/ { graph.util.addEntryLabel(rv); graph.util.pushRecursionEntry(rv, graph.util.getEntry()); } } @Override public LRecursion leaveEGraphBuilding(ScribNode parent, ScribNode child, EGraphBuilder graph, ScribNode visited) throws ScribbleException { LRecursion lr = (LRecursion) visited; RecVar rv = lr.recvar.toName(); graph.util.popRecursionEntry(rv); return (LRecursion) super.leaveEGraphBuilding(parent, child, graph, lr); } @Override public void enterProjectedChoiceSubjectFixing(ScribNode parent, ScribNode child, ProjectedChoiceSubjectFixer fixer) { fixer.pushRec(((LRecursion) child).recvar.toName()); } @Override public ScribNode leaveProjectedChoiceSubjectFixing(ScribNode parent, ScribNode child, ProjectedChoiceSubjectFixer fixer, ScribNode visited) { fixer.popRec(((LRecursion) child).recvar.toName()); return visited; } }