package org.scribble.del.global;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.scribble.ast.AstFactoryImpl;
import org.scribble.ast.ScribNode;
import org.scribble.ast.global.GInteractionNode;
import org.scribble.ast.global.GInteractionSeq;
import org.scribble.ast.global.GRecursion;
import org.scribble.ast.local.LInteractionNode;
import org.scribble.ast.local.LInteractionSeq;
import org.scribble.ast.local.LNode;
import org.scribble.del.InteractionSeqDel;
import org.scribble.del.ScribDelBase;
import org.scribble.main.ScribbleException;
import org.scribble.visit.ProtocolDefInliner;
import org.scribble.visit.context.Projector;
import org.scribble.visit.context.RecRemover;
import org.scribble.visit.context.env.ProjectionEnv;
import org.scribble.visit.env.InlineProtocolEnv;
public class GInteractionSeqDel extends InteractionSeqDel
{
// enter in super
@Override
public ScribNode leaveProtocolInlining(ScribNode parent, ScribNode child, ProtocolDefInliner inl, ScribNode visited) throws ScribbleException
{
GInteractionSeq gis = (GInteractionSeq) visited;
List<GInteractionNode> gins = new LinkedList<GInteractionNode>();
for (GInteractionNode gi : gis.getInteractions())
{
ScribNode inlined = ((InlineProtocolEnv) gi.del().env()).getTranslation();
if (inlined instanceof GInteractionSeq) // A do got inlined
{
gins.addAll(((GInteractionSeq) inlined).getInteractions());
}
else
{
gins.add((GInteractionNode) inlined);
}
}
GInteractionSeq inlined = AstFactoryImpl.FACTORY.GInteractionSeq(gis.getSource(), gins);
inl.pushEnv(inl.popEnv().setTranslation(inlined));
return (GInteractionSeq) ScribDelBase.popAndSetVisitorEnv(this, inl, gis);
}
@Override
public void enterProjection(ScribNode parent, ScribNode child, Projector proj) throws ScribbleException
{
ScribDelBase.pushVisitorEnv(this, proj); // Unlike WF-choice and Reachability, Projection uses an Env for InteractionSequences
}
@Override
public GInteractionSeq leaveProjection(ScribNode parent, ScribNode child, Projector proj, ScribNode visited) throws ScribbleException
{
GInteractionSeq gis = (GInteractionSeq) visited;
List<LInteractionNode> lis = new LinkedList<>();
for (GInteractionNode gi : gis.getInteractions()) // FIXME: rewrite using flatMap
{
LNode ln = (LNode) ((ProjectionEnv) gi.del().env()).getProjection();
//LNode ln = ((GInteractionNodeDel) gi.del()).project(gi, self); // FIXME: won't work for do
// FIXME: move node-specific projects to G nodes (not dels) and take child projections as params, bit like reconstruct
if (ln instanceof LInteractionSeq) // Self comm sequence
{
lis.addAll(((LInteractionSeq) ln).getInteractions());
}
else if (ln != null) // null is used for empty projection
{
lis.add((LInteractionNode) ln);
}
}
/*if (lis.size() == 1) // NO: needed for e.g. rec X { 1() from A to B; choice at A { continue X; } or { 2() from A to B; } } -- do instead in GRecursion
{
if (lis.get(0) instanceof Continue)
{
lis.clear();
}
}*/
LInteractionSeq projection = gis.project(proj.peekSelf(), lis);
proj.pushEnv(proj.popEnv().setProjection(projection));
return (GInteractionSeq) ScribDelBase.popAndSetVisitorEnv(this, proj, gis);
}
/*@Override
public GInteractionSeq leaveF17Parsing(ScribNode parent, ScribNode child, F17Parser parser, ScribNode visited) throws ScribbleException
{
GInteractionSeq gis = (GInteractionSeq) visited;
List<GInteractionNode> gins = gis.getInteractions();
Iterator<GInteractionNode> i = gins.iterator();
while (i.hasNext())
{
GInteractionNode gin = i.next();
if (!i.hasNext())
{
break;
}
/*F17ParserEnv env = (F17ParserEnv) gin.del().env();
if (env.isUnguarded())
{
throw new ScribbleException("[FASE17] unguarded choice case: " + gin);
}* /
if (!(gin instanceof GMessageTransfer || gin instanceof GConnect || gin instanceof GDisconnect))
{
throw new ScribbleException("[FASE17] Bad sequence composition following:\n" + gin);
}
}
return gis;
}*/
@Override
public GInteractionSeq leaveRecRemoval(ScribNode parent, ScribNode child, RecRemover rem, ScribNode visited)
throws ScribbleException
{
GInteractionSeq gis = (GInteractionSeq) visited;
List<GInteractionNode> gins = gis.getInteractions().stream().flatMap((gi) ->
(gi instanceof GRecursion && rem.toRemove(((GRecursion) gi).recvar.toName()))
? ((GRecursion) gi).getBlock().getInteractionSeq().getInteractions().stream()
: Stream.of(gi)
).collect(Collectors.toList());
return AstFactoryImpl.FACTORY.GInteractionSeq(gis.getSource(), gins);
}
}