Search in sources :

Example 1 with SendRange

use of org.lflang.generator.SendRange in project lingua-franca by lf-lang.

the class PortInstanceTests method createRange.

@Test
public void createRange() throws Exception {
    Reactor main = factory.createReactor();
    ReactorInstance maini = new ReactorInstance(main, reporter);
    ReactorInstance a = newReactor("A", maini);
    ReactorInstance b = newReactor("B", maini);
    ReactorInstance c = newReactor("C", maini);
    PortInstance p = newOutputPort("p", a);
    PortInstance q = newInputPort("q", b);
    PortInstance r = newInputPort("r", c);
    Assertions.assertEquals(".A.p", p.getFullName());
    connect(p, q);
    connect(p, r);
    List<SendRange> sr = p.eventualDestinations();
    // Destinations should be empty because there are no reactions.
    Assertions.assertEquals("[]", sr.toString());
    // Clear caches to make a mutation.
    maini.clearCaches();
    newReaction(q);
    // Re-retrieve destinations.
    sr = p.eventualDestinations();
    Assertions.assertEquals("[.A.p(0,1)->[.B.q(0,1)]]", sr.toString());
    maini.clearCaches();
    newReaction(r);
    // Re-retrieve destinations.
    sr = p.eventualDestinations();
    Assertions.assertEquals("[.A.p(0,1)->[.B.q(0,1), .C.r(0,1)]]", sr.toString());
    // Now test multiports.
    p.setWidth(3);
    r.setWidth(2);
    // Have to redo the connections.
    clearConnections(maini);
    maini.clearCaches();
    connect(p, 0, 1, q, 0, 1);
    connect(p, 1, 2, r, 0, 2);
    // Re-retrieve destinations.
    sr = p.eventualDestinations();
    Assertions.assertEquals("[.A.p(0,1)->[.B.q(0,1)], .A.p(1,2)->[.C.r(0,2)]]", sr.toString());
    // More complicated multiport connection.
    clearConnections(maini);
    maini.clearCaches();
    ReactorInstance d = newReactor("D", maini);
    PortInstance v = newOutputPort("v", d);
    v.setWidth(2);
    q.setWidth(3);
    connect(v, 0, 2, q, 0, 2);
    connect(p, 0, 1, q, 2, 1);
    connect(p, 1, 2, r, 0, 2);
    sr = p.eventualDestinations();
    Assertions.assertEquals("[.A.p(0,1)->[.B.q(2,1)], .A.p(1,2)->[.C.r(0,2)]]", sr.toString());
    // Additional multicast connection.
    maini.clearCaches();
    ReactorInstance e = newReactor("E", maini);
    PortInstance s = newPort("s", e);
    s.setWidth(3);
    newReaction(s);
    connect(p, s);
    sr = p.eventualDestinations();
    Assertions.assertEquals("[.A.p(0,1)->[.B.q(2,1), .E.s(0,1)], .A.p(1,2)->[.C.r(0,2), .E.s(1,2)]]", sr.toString());
    // Add hierarchical reactors that further split the ranges.
    maini.clearCaches();
    ReactorInstance f = newReactor("F", e);
    PortInstance t = newPort("t", f);
    newReaction(t);
    ReactorInstance g = newReactor("G", e);
    PortInstance u = newPort("u", g);
    u.setWidth(2);
    newReaction(u);
    connect(s, 0, 1, t, 0, 1);
    connect(s, 1, 2, u, 0, 2);
    sr = p.eventualDestinations();
    // FIXME: Multicast destinations should be able to be reported in arbitrary order.
    Assertions.assertEquals("[.A.p(0,1)->[.E.F.t(0,1), .E.s(0,1), .B.q(2,1)], .A.p(1,2)->[.E.G.u(0,2), .E.s(1,2), .C.r(0,2)]]", sr.toString());
}
Also used : PortInstance(org.lflang.generator.PortInstance) ReactorInstance(org.lflang.generator.ReactorInstance) Reactor(org.lflang.lf.Reactor) SendRange(org.lflang.generator.SendRange) Test(org.junit.jupiter.api.Test)

Example 2 with SendRange

use of org.lflang.generator.SendRange in project lingua-franca by lf-lang.

the class TopologyGraph method addEffects.

/**
 * Given a reaction instance, record dependencies implied by its effects.
 *
 * Excluded from the recorded dependencies are those that are broken by
 * physical connections or "after" delays.
 *
 * @param reaction The reaction to record the dependencies of.
 */
private void addEffects(ReactionInstance reaction) {
    for (TriggerInstance<? extends Variable> effect : reaction.effects) {
        if (effect instanceof PortInstance) {
            addEdge(effect, reaction);
            PortInstance orig = (PortInstance) effect;
            for (SendRange sendRange : orig.getDependentPorts()) {
                sendRange.destinations.forEach(dest -> {
                    recordDependency(reaction, orig, dest.instance, sendRange.connection);
                });
            }
        }
    }
}
Also used : PortInstance(org.lflang.generator.PortInstance) SendRange(org.lflang.generator.SendRange)

Example 3 with SendRange

use of org.lflang.generator.SendRange in project lingua-franca by lf-lang.

the class LinguaFrancaSynthesis method transformReactorNetwork.

private Collection<KNode> transformReactorNetwork(ReactorInstance reactorInstance, Map<PortInstance, KPort> parentInputPorts, Map<PortInstance, KPort> parentOutputPorts, Map<ReactorInstance, KNode> allReactorNodes) {
    List<KNode> nodes = new ArrayList<>();
    Table<ReactorInstance, PortInstance, KPort> inputPorts = HashBasedTable.create();
    Table<ReactorInstance, PortInstance, KPort> outputPorts = HashBasedTable.create();
    Map<ReactionInstance, KNode> reactionNodes = new HashMap<>();
    Map<KPort, KNode> directConnectionDummyNodes = new HashMap<>();
    Multimap<ActionInstance, KPort> actionDestinations = HashMultimap.create();
    Multimap<ActionInstance, KPort> actionSources = HashMultimap.create();
    Map<TimerInstance, KNode> timerNodes = new HashMap<>();
    KNode startupNode = _kNodeExtensions.createNode();
    boolean startupUsed = false;
    KNode shutdownNode = _kNodeExtensions.createNode();
    boolean shutdownUsed = false;
    // Transform instances
    int index = 0;
    for (ReactorInstance child : ListExtensions.reverseView(reactorInstance.children)) {
        Boolean expansionState = MemorizingExpandCollapseAction.getExpansionState(child);
        Collection<KNode> rNodes = createReactorNode(child, expansionState != null ? expansionState : false, inputPorts, outputPorts, allReactorNodes);
        setLayoutOption(IterableExtensions.<KNode>head(rNodes), CoreOptions.PRIORITY, index);
        nodes.addAll(rNodes);
        index++;
    }
    // Create timers
    for (TimerInstance timer : reactorInstance.timers) {
        KNode node = associateWith(_kNodeExtensions.createNode(), timer.getDefinition());
        NamedInstanceUtil.linkInstance(node, timer);
        _utilityExtensions.setID(node, timer.uniqueID());
        nodes.add(node);
        Iterables.addAll(nodes, createUserComments(timer.getDefinition(), node));
        timerNodes.put(timer, node);
        _linguaFrancaShapeExtensions.addTimerFigure(node, timer);
    }
    // Create reactions
    for (ReactionInstance reaction : ListExtensions.reverseView(reactorInstance.reactions)) {
        int idx = reactorInstance.reactions.indexOf(reaction);
        KNode node = associateWith(_kNodeExtensions.createNode(), reaction.getDefinition());
        NamedInstanceUtil.linkInstance(node, reaction);
        _utilityExtensions.setID(node, reaction.uniqueID());
        nodes.add(node);
        Iterables.addAll(nodes, createUserComments(reaction.getDefinition(), node));
        reactionNodes.put(reaction, node);
        setLayoutOption(node, CoreOptions.PORT_CONSTRAINTS, PortConstraints.FIXED_SIDE);
        // always place with higher priority than reactor nodes
        setLayoutOption(node, CoreOptions.PRIORITY, (reactorInstance.reactions.size() - idx) * 10);
        // try order reactions vertically if in one layer
        setLayoutOption(node, LayeredOptions.POSITION, new KVector(0, idx));
        _linguaFrancaShapeExtensions.addReactionFigure(node, reaction);
        // connect input
        KPort port = null;
        for (TriggerInstance<?> trigger : reaction.triggers) {
            port = addInvisiblePort(node);
            setLayoutOption(port, CoreOptions.PORT_SIDE, PortSide.WEST);
            int triggersSize = reaction.triggers != null ? reaction.triggers.size() : 0;
            int sourcesSize = reaction.sources != null ? reaction.sources.size() : 0;
            if (getBooleanValue(REACTIONS_USE_HYPEREDGES) || triggersSize + sourcesSize == 1) {
                // manual adjustment disabling automatic one
                setLayoutOption(port, CoreOptions.PORT_BORDER_OFFSET, (double) -LinguaFrancaShapeExtensions.REACTION_POINTINESS);
            }
            if (trigger.isStartup()) {
                connect(createDependencyEdge(((TriggerInstance.BuiltinTriggerVariable) trigger.getDefinition()).definition), startupNode, port);
                startupUsed = true;
            } else if (trigger.isShutdown()) {
                connect(createDelayEdge(((TriggerInstance.BuiltinTriggerVariable) trigger.getDefinition()).definition), shutdownNode, port);
                shutdownUsed = true;
            } else if (trigger instanceof ActionInstance) {
                actionDestinations.put(((ActionInstance) trigger), port);
            } else if (trigger instanceof PortInstance) {
                KPort src = null;
                PortInstance triggerAsPort = (PortInstance) trigger;
                if (triggerAsPort.getParent() == reactorInstance) {
                    src = parentInputPorts.get(trigger);
                } else {
                    src = outputPorts.get(triggerAsPort.getParent(), trigger);
                }
                if (src != null) {
                    connect(createDependencyEdge(triggerAsPort.getDefinition()), src, port);
                }
            } else if (trigger instanceof TimerInstance) {
                KNode src = timerNodes.get(trigger);
                if (src != null) {
                    connect(createDependencyEdge(trigger.getDefinition()), src, port);
                }
            }
        }
        // port = null // create new ports
        for (TriggerInstance<?> dep : reaction.sources) {
            if (reaction.triggers.contains(dep))
                continue;
            if (!(getBooleanValue(REACTIONS_USE_HYPEREDGES) && port != null)) {
                port = addInvisiblePort(node);
                setLayoutOption(port, CoreOptions.PORT_SIDE, PortSide.WEST);
                int triggersSize = reaction.triggers != null ? reaction.triggers.size() : 0;
                int sourcesSize = reaction.sources != null ? reaction.sources.size() : 0;
                if (getBooleanValue(REACTIONS_USE_HYPEREDGES) || triggersSize + sourcesSize == 1) {
                    // manual adjustment disabling automatic one
                    setLayoutOption(port, CoreOptions.PORT_BORDER_OFFSET, (double) -LinguaFrancaShapeExtensions.REACTION_POINTINESS);
                }
            }
            if (dep instanceof PortInstance) {
                KPort src = null;
                PortInstance depAsPort = (PortInstance) dep;
                if (dep.getParent() == reactorInstance) {
                    src = parentInputPorts.get(dep);
                } else {
                    src = outputPorts.get(depAsPort.getParent(), dep);
                }
                if (src != null) {
                    connect(createDependencyEdge(dep.getDefinition()), src, port);
                }
            }
        }
        // connect outputs
        // create new ports
        port = null;
        Set<TriggerInstance<?>> iterSet = reaction.effects != null ? reaction.effects : new HashSet<>();
        for (TriggerInstance<?> effect : iterSet) {
            port = addInvisiblePort(node);
            setLayoutOption(port, CoreOptions.PORT_SIDE, PortSide.EAST);
            if (effect instanceof ActionInstance) {
                actionSources.put((ActionInstance) effect, port);
            } else if (effect instanceof PortInstance) {
                KPort dst = null;
                PortInstance effectAsPort = (PortInstance) effect;
                if (effectAsPort.isOutput()) {
                    dst = parentOutputPorts.get(effect);
                } else {
                    dst = inputPorts.get(effectAsPort.getParent(), effect);
                }
                if (dst != null) {
                    connect(createDependencyEdge(effect), port, dst);
                }
            }
        }
    }
    // Connect actions
    Set<ActionInstance> actions = new HashSet<>();
    actions.addAll(actionSources.keySet());
    actions.addAll(actionDestinations.keySet());
    for (ActionInstance action : actions) {
        KNode node = associateWith(_kNodeExtensions.createNode(), action.getDefinition());
        NamedInstanceUtil.linkInstance(node, action);
        _utilityExtensions.setID(node, action.uniqueID());
        nodes.add(node);
        Iterables.addAll(nodes, createUserComments(action.getDefinition(), node));
        setLayoutOption(node, CoreOptions.PORT_CONSTRAINTS, PortConstraints.FIXED_SIDE);
        Pair<KPort, KPort> ports = _linguaFrancaShapeExtensions.addActionFigureAndPorts(node, action.isPhysical() ? "P" : "L");
        // TODO handle variables?
        if (action.getMinDelay() != null && action.getMinDelay() != ActionInstance.DEFAULT_MIN_DELAY) {
            _kLabelExtensions.addOutsideBottomCenteredNodeLabel(node, String.format("min delay: %s", action.getMinDelay().toString()), 7);
        }
        // TODO default value?
        if (action.getDefinition().getMinSpacing() != null) {
            _kLabelExtensions.addOutsideBottomCenteredNodeLabel(node, String.format("min spacing: %s", action.getMinSpacing().toString()), 7);
        }
        if (!StringExtensions.isNullOrEmpty(action.getDefinition().getPolicy())) {
            _kLabelExtensions.addOutsideBottomCenteredNodeLabel(node, String.format("policy: %s", action.getPolicy().toString()), 7);
        }
        // connect source
        for (KPort source : actionSources.get(action)) {
            connect(createDelayEdge(action), source, ports.getKey());
        }
        // connect targets
        for (KPort target : actionDestinations.get(action)) {
            connect(createDelayEdge(action), ports.getValue(), target);
        }
    }
    // Transform connections.
    // First, collect all the source ports.
    List<PortInstance> sourcePorts = new LinkedList<>(reactorInstance.inputs);
    for (ReactorInstance child : reactorInstance.children) {
        sourcePorts.addAll(child.outputs);
    }
    for (PortInstance leftPort : sourcePorts) {
        KPort source = leftPort.getParent() == reactorInstance ? parentInputPorts.get(leftPort) : outputPorts.get(leftPort.getParent(), leftPort);
        for (SendRange sendRange : leftPort.getDependentPorts()) {
            for (RuntimeRange<PortInstance> rightRange : sendRange.destinations) {
                PortInstance rightPort = rightRange.instance;
                KPort target = rightPort.getParent() == reactorInstance ? parentOutputPorts.get(rightPort) : inputPorts.get(rightPort.getParent(), rightPort);
                // There should be a connection, but skip if not.
                Connection connection = sendRange.connection;
                if (connection != null) {
                    KEdge edge = createIODependencyEdge(connection, (leftPort.isMultiport() || rightPort.isMultiport()));
                    if (connection.getDelay() != null) {
                        KLabel delayLabel = _kLabelExtensions.addCenterEdgeLabel(edge, ASTUtils.toText(connection.getDelay()));
                        associateWith(delayLabel, connection.getDelay());
                        if (connection.isPhysical()) {
                            _linguaFrancaStyleExtensions.applyOnEdgePysicalDelayStyle(delayLabel, reactorInstance.isMainOrFederated() ? Colors.WHITE : Colors.GRAY_95);
                        } else {
                            _linguaFrancaStyleExtensions.applyOnEdgeDelayStyle(delayLabel);
                        }
                    } else if (connection.isPhysical()) {
                        KLabel physicalConnectionLabel = _kLabelExtensions.addCenterEdgeLabel(edge, "---");
                        _linguaFrancaStyleExtensions.applyOnEdgePysicalStyle(physicalConnectionLabel, reactorInstance.isMainOrFederated() ? Colors.WHITE : Colors.GRAY_95);
                    }
                    if (source != null && target != null) {
                        // check for inside loop (direct in -> out connection with delay)
                        if (parentInputPorts.values().contains(source) && parentOutputPorts.values().contains(target)) {
                            // edge.setLayoutOption(CoreOptions.INSIDE_SELF_LOOPS_YO, true) // Does not work as expected
                            // Introduce dummy node to enable direct connection (that is also hidden when collapsed)
                            KNode dummy = _kNodeExtensions.createNode();
                            if (directConnectionDummyNodes.containsKey(target)) {
                                dummy = directConnectionDummyNodes.get(target);
                            } else {
                                nodes.add(dummy);
                                directConnectionDummyNodes.put(target, dummy);
                                _kRenderingExtensions.addInvisibleContainerRendering(dummy);
                                _kNodeExtensions.setNodeSize(dummy, 0, 0);
                                KEdge extraEdge = createIODependencyEdge(null, (leftPort.isMultiport() || rightPort.isMultiport()));
                                connect(extraEdge, dummy, target);
                            }
                            connect(edge, source, dummy);
                        } else {
                            connect(edge, source, target);
                        }
                    }
                }
            }
        }
    }
    // Add startup/shutdown
    if (startupUsed) {
        _linguaFrancaShapeExtensions.addStartupFigure(startupNode);
        nodes.add(0, startupNode);
        setLayoutOption(startupNode, LayeredOptions.LAYERING_LAYER_CONSTRAINT, LayerConstraint.FIRST);
        if (getBooleanValue(REACTIONS_USE_HYPEREDGES)) {
            KPort port = addInvisiblePort(startupNode);
            startupNode.getOutgoingEdges().forEach(it -> {
                it.setSourcePort(port);
            });
        }
    }
    if (shutdownUsed) {
        _linguaFrancaShapeExtensions.addShutdownFigure(shutdownNode);
        nodes.add(0, shutdownNode);
        if (getBooleanValue(REACTIONS_USE_HYPEREDGES)) {
            // connect all edges to one port
            KPort port = addInvisiblePort(shutdownNode);
            shutdownNode.getOutgoingEdges().forEach(it -> {
                it.setSourcePort(port);
            });
        }
    }
    // Postprocess timer nodes
    if (getBooleanValue(REACTIONS_USE_HYPEREDGES)) {
        // connect all edges to one port
        for (KNode timerNode : timerNodes.values()) {
            KPort port = addInvisiblePort(timerNode);
            timerNode.getOutgoingEdges().forEach(it -> {
                it.setSourcePort(port);
            });
        }
    }
    // Add reaction order edges (add last to have them on top of other edges)
    if (reactorInstance.reactions.size() > 1) {
        KNode prevNode = reactionNodes.get(IterableExtensions.head(reactorInstance.reactions));
        Iterable<KNode> iterList = IterableExtensions.map(IterableExtensions.drop(reactorInstance.reactions, 1), reactionNodes::get);
        for (KNode node : iterList) {
            KEdge edge = createOrderEdge();
            edge.setSource(prevNode);
            edge.setTarget(node);
            edge.setProperty(CoreOptions.NO_LAYOUT, true);
            // Do not remove them, as they are needed for cycle detection
            KRendering edgeRendering = _kRenderingExtensions.getKRendering(edge);
            _kRenderingExtensions.setInvisible(edgeRendering, !getBooleanValue(SHOW_REACTION_ORDER_EDGES));
            _kRenderingExtensions.getInvisible(edgeRendering).setPropagateToChildren(true);
            // TODO this does not work work with incremental update (https://github.com/kieler/KLighD/issues/37)
            // if (!getBooleanValue(SHOW_REACTION_ORDER_EDGES)) edge.initiallyHide()
            prevNode = node;
        }
    }
    _modeDiagrams.handleModes(nodes, reactorInstance);
    return nodes;
}
Also used : PortInstance(org.lflang.generator.PortInstance) ReactionInstance(org.lflang.generator.ReactionInstance) HashMap(java.util.HashMap) TimerInstance(org.lflang.generator.TimerInstance) ArrayList(java.util.ArrayList) KVector(org.eclipse.elk.core.math.KVector) KRendering(de.cau.cs.kieler.klighd.krendering.KRendering) HashSet(java.util.HashSet) Connection(org.lflang.lf.Connection) KEdge(de.cau.cs.kieler.klighd.kgraph.KEdge) KPort(de.cau.cs.kieler.klighd.kgraph.KPort) KNode(de.cau.cs.kieler.klighd.kgraph.KNode) TriggerInstance(org.lflang.generator.TriggerInstance) SizeConstraint(org.eclipse.elk.core.options.SizeConstraint) LayerConstraint(org.eclipse.elk.alg.layered.options.LayerConstraint) LinkedList(java.util.LinkedList) KLabel(de.cau.cs.kieler.klighd.kgraph.KLabel) ReactorInstance(org.lflang.generator.ReactorInstance) ActionInstance(org.lflang.generator.ActionInstance) SendRange(org.lflang.generator.SendRange)

Example 4 with SendRange

use of org.lflang.generator.SendRange in project lingua-franca by lf-lang.

the class RangeTests method createRange.

@Test
public void createRange() throws Exception {
    Reactor main = factory.createReactor();
    ReactorInstance maini = new ReactorInstance(main, reporter);
    Reactor a = factory.createReactor();
    a.setName("A");
    ReactorInstance ai = new ReactorInstance(a, maini, reporter);
    ai.setWidth(2);
    Reactor b = factory.createReactor();
    b.setName("B");
    ReactorInstance bi = new ReactorInstance(b, ai, reporter);
    bi.setWidth(2);
    Port p = factory.createPort();
    p.setName("P");
    PortInstance pi = new PortInstance(p, bi, reporter);
    pi.setWidth(2);
    Assertions.assertEquals(".A.B.P", pi.getFullName());
    RuntimeRange<PortInstance> range = new RuntimeRange.Port(pi, 3, 4, null);
    Assertions.assertEquals(8, range.maxWidth);
    Assertions.assertEquals(".A.B.P(3,4)", range.toString());
    // The results expected below are derived from the class comment for RuntimeRange,
    // which includes this example.
    List<Integer> instances = range.instances();
    Assertions.assertEquals(List.of(3, 4, 5, 6), instances);
    Set<Integer> parents = range.parentInstances(1);
    Assertions.assertEquals(Set.of(1, 2, 3), parents);
    parents = range.parentInstances(2);
    Assertions.assertEquals(Set.of(0, 1), parents);
    // Test startMR().getDigits.
    Assertions.assertEquals(List.of(1, 1, 0), range.startMR().getDigits());
    // Create a SendRange sending from and to this range.
    SendRange sendRange = new SendRange(pi, 3, 4, null, null);
    sendRange.destinations.add(range);
    // Test getNumberOfDestinationReactors.
    Assertions.assertEquals(3, sendRange.getNumberOfDestinationReactors());
    // Make first interleaved version.
    range = range.toggleInterleaved(bi);
    instances = range.instances();
    Assertions.assertEquals(List.of(3, 4, 6, 5), instances);
    // Test startMR().getDigits.
    Assertions.assertEquals(List.of(1, 1, 0), range.startMR().getDigits());
    // Make second interleaved version.
    range = range.toggleInterleaved(ai);
    instances = range.instances();
    Assertions.assertEquals(List.of(6, 1, 5, 3), instances);
    // Test startMR().getDigits.
    Assertions.assertEquals(List.of(0, 1, 1), range.startMR().getDigits());
    // Test instances of the parent.
    Assertions.assertEquals(Set.of(3, 0, 2, 1), range.parentInstances(1));
    // Add this range to the sendRange destinations and verify
    // that the number of destination reactors becomes 4.
    sendRange.addDestination(range);
    Assertions.assertEquals(4, sendRange.getNumberOfDestinationReactors());
    // Make third interleaved version.
    range = range.toggleInterleaved(bi);
    instances = range.instances();
    Assertions.assertEquals(List.of(5, 2, 6, 3), instances);
    // Test startMR().getDigits.
    Assertions.assertEquals(List.of(1, 0, 1), range.startMR().getDigits());
}
Also used : PortInstance(org.lflang.generator.PortInstance) ReactorInstance(org.lflang.generator.ReactorInstance) Port(org.lflang.lf.Port) Reactor(org.lflang.lf.Reactor) SendRange(org.lflang.generator.SendRange) Test(org.junit.jupiter.api.Test)

Example 5 with SendRange

use of org.lflang.generator.SendRange in project lingua-franca by lf-lang.

the class PortInstanceTests method multiportDestination.

@Test
public void multiportDestination() throws Exception {
    Reactor main = factory.createReactor();
    ReactorInstance maini = new ReactorInstance(main, reporter);
    ReactorInstance a = newReactor("A", maini);
    ReactorInstance b = newReactor("B", maini);
    b.setWidth(4);
    PortInstance p = newOutputPort("p", a);
    PortInstance q = newInputPort("q", b);
    connect(p, 0, 1, q, 0, 4);
    List<SendRange> sr = p.eventualDestinations();
    // Destination has no reactions, so empty list is right.
    Assertions.assertEquals("[]", sr.toString());
    maini.clearCaches();
    newReaction(q);
    sr = p.eventualDestinations();
    Assertions.assertEquals("[.A.p(0,1)->[.B.q(0,4)]]", sr.toString());
}
Also used : PortInstance(org.lflang.generator.PortInstance) ReactorInstance(org.lflang.generator.ReactorInstance) Reactor(org.lflang.lf.Reactor) SendRange(org.lflang.generator.SendRange) Test(org.junit.jupiter.api.Test)

Aggregations

PortInstance (org.lflang.generator.PortInstance)5 SendRange (org.lflang.generator.SendRange)5 ReactorInstance (org.lflang.generator.ReactorInstance)4 Test (org.junit.jupiter.api.Test)3 Reactor (org.lflang.lf.Reactor)3 KEdge (de.cau.cs.kieler.klighd.kgraph.KEdge)1 KLabel (de.cau.cs.kieler.klighd.kgraph.KLabel)1 KNode (de.cau.cs.kieler.klighd.kgraph.KNode)1 KPort (de.cau.cs.kieler.klighd.kgraph.KPort)1 KRendering (de.cau.cs.kieler.klighd.krendering.KRendering)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 LinkedList (java.util.LinkedList)1 LayerConstraint (org.eclipse.elk.alg.layered.options.LayerConstraint)1 KVector (org.eclipse.elk.core.math.KVector)1 SizeConstraint (org.eclipse.elk.core.options.SizeConstraint)1 ActionInstance (org.lflang.generator.ActionInstance)1 ReactionInstance (org.lflang.generator.ReactionInstance)1 TimerInstance (org.lflang.generator.TimerInstance)1