Search in sources :

Example 1 with ReactorDecl

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

the class ASTUtils method superClasses.

/**
 * Return all the superclasses of the specified reactor
 * in deepest-first order. For example, if A extends B and C, and
 * B and C both extend D, this will return the list [D, B, C, A].
 * Duplicates are removed. If the specified reactor does not extend
 * any other reactor, then return an empty list.
 * If a cycle is found, where X extends Y and Y extends X, or if
 * a superclass is declared that is not found, then return null.
 * @param reactor The specified reactor.
 * @param extensions A set of reactors extending the specified reactor
 *  (used to detect circular extensions).
 */
private static LinkedHashSet<Reactor> superClasses(Reactor reactor, Set<Reactor> extensions) {
    LinkedHashSet<Reactor> result = new LinkedHashSet<Reactor>();
    for (ReactorDecl superDecl : convertToEmptyListIfNull(reactor.getSuperClasses())) {
        Reactor r = toDefinition(superDecl);
        if (r == reactor || r == null)
            return null;
        // If r is in the extensions, then we have a circular inheritance structure.
        if (extensions.contains(r))
            return null;
        extensions.add(r);
        LinkedHashSet<Reactor> baseExtends = superClasses(r, extensions);
        extensions.remove(r);
        if (baseExtends == null)
            return null;
        result.addAll(baseExtends);
        result.add(r);
    }
    return result;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) ImportedReactor(org.lflang.lf.ImportedReactor) Reactor(org.lflang.lf.Reactor) ReactorDecl(org.lflang.lf.ReactorDecl)

Example 2 with ReactorDecl

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

the class PythonReactorGenerator method generatePythonClass.

/**
 * Generate a Python class corresponding to decl
 * @param instance The reactor instance to be generated
 * @param pythonClasses The class definition is appended to this code builder
 * @param federate The federate instance for the reactor instance
 * @param instantiatedClasses A list of visited instances to avoid generating duplicates
 */
public static String generatePythonClass(ReactorInstance instance, FederateInstance federate, List<String> instantiatedClasses, ReactorInstance main, PythonTypes types) {
    CodeBuilder pythonClasses = new CodeBuilder();
    ReactorDecl decl = instance.getDefinition().getReactorClass();
    Reactor reactor = ASTUtils.toDefinition(decl);
    String className = instance.getDefinition().getReactorClass().getName();
    if (instance != main && !federate.contains(instance) || instantiatedClasses == null || // Do not generate code for delay reactors in Python
    className.contains(GeneratorBase.GEN_DELAY_CLASS_NAME)) {
        return "";
    }
    if (federate.contains(instance) && !instantiatedClasses.contains(className)) {
        pythonClasses.pr(generatePythonClassHeader(className));
        // Generate preamble code
        pythonClasses.indent();
        pythonClasses.pr(PythonPreambleGenerator.generatePythonPreambles(reactor.getPreambles()));
        // Handle runtime initializations
        pythonClasses.pr(generatePythonConstructor(decl, types));
        pythonClasses.pr(PythonParameterGenerator.generatePythonGetters(decl));
        List<Reaction> reactionToGenerate = ASTUtils.allReactions(reactor);
        if (reactor.isFederated()) {
            // Filter out reactions that are automatically generated in C in the top level federated reactor
            reactionToGenerate.removeIf(it -> !federate.contains(it) || federate.networkReactions.contains(it));
        }
        pythonClasses.pr(PythonReactionGenerator.generatePythonReactions(reactor, reactionToGenerate));
        pythonClasses.unindent();
        instantiatedClasses.add(className);
    }
    for (ReactorInstance child : instance.children) {
        pythonClasses.pr(generatePythonClass(child, federate, instantiatedClasses, main, types));
    }
    return pythonClasses.getCode();
}
Also used : ReactorInstance(org.lflang.generator.ReactorInstance) ReactorDecl(org.lflang.lf.ReactorDecl) Reactor(org.lflang.lf.Reactor) Reaction(org.lflang.lf.Reaction) CodeBuilder(org.lflang.generator.CodeBuilder)

Example 3 with ReactorDecl

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

the class CGeneratorExtension method initializeTriggerForControlReactions.

/**
 * Generate C code that initializes three critical structures that support
 * network control reactions:
 *  - triggers_for_network_input_control_reactions: These are triggers that are
 *  used at runtime to insert network input control reactions into the
 *  reaction queue. There could be multiple network input control reactions
 *  for one network input at multiple levels in the hierarchy.
 *  - trigger_for_network_output_control_reactions: Triggers for
 *  network output control reactions, which are unique per each output port.
 *  There could be multiple network output control reactions for each network
 *  output port if it is connected to multiple downstream federates.
 *
 * @param instance  The reactor instance that is at any level of the
 *                  hierarchy within the federate.
 * @param federate  The top-level federate
 * @param generator The instance of the CGenerator passed to keep this
 *                  extension function static.
 * @return A string that initializes the aforementioned three structures.
 */
public static StringBuilder initializeTriggerForControlReactions(ReactorInstance instance, FederateInstance federate, CGenerator generator) {
    StringBuilder builder = new StringBuilder();
    // reactor
    if (instance != generator.main) {
        return builder;
    }
    ReactorDecl reactorClass = instance.getDefinition().getReactorClass();
    Reactor reactor = ASTUtils.toDefinition(reactorClass);
    String nameOfSelfStruct = CUtil.reactorRef(instance);
    // Initialize triggers for network input control reactions
    for (Action trigger : federate.networkInputControlReactionsTriggers) {
        // Check if the trigger belongs to this reactor instance
        if (ASTUtils.allReactions(reactor).stream().anyMatch(r -> {
            return r.getTriggers().stream().anyMatch(t -> {
                if (t instanceof VarRef) {
                    return ((VarRef) t).getVariable().equals(trigger);
                } else {
                    return false;
                }
            });
        })) {
            // Initialize the triggers_for_network_input_control_reactions for the input
            builder.append("// Add trigger " + nameOfSelfStruct + "->_lf__" + trigger.getName() + " to the global list of network input ports.\n" + "_fed.triggers_for_network_input_control_reactions[" + federate.networkInputControlReactionsTriggers.indexOf(trigger) + "]= &" + nameOfSelfStruct + "" + "->_lf__" + trigger.getName() + ";\n");
        }
    }
    nameOfSelfStruct = CUtil.reactorRef(instance);
    // Initialize the trigger for network output control reactions if it doesn't exist.
    if (federate.networkOutputControlReactionsTrigger != null) {
        builder.append("_fed.trigger_for_network_output_control_reactions=&" + nameOfSelfStruct + "->_lf__outputControlReactionTrigger;\n");
    }
    return builder;
}
Also used : VarRef(org.lflang.lf.VarRef) Action(org.lflang.lf.Action) ReactorDecl(org.lflang.lf.ReactorDecl) Reactor(org.lflang.lf.Reactor)

Example 4 with ReactorDecl

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

the class LFValidator method isUnused.

/**
 * Report whether a given imported reactor is used in this resource or not.
 * @param reactor The imported reactor to check whether it is used.
 */
private boolean isUnused(ImportedReactor reactor) {
    TreeIterator<EObject> instantiations = reactor.eResource().getAllContents();
    TreeIterator<EObject> subclasses = reactor.eResource().getAllContents();
    boolean instantiationsCheck = true;
    while (instantiations.hasNext() && instantiationsCheck) {
        EObject obj = instantiations.next();
        if (!(obj instanceof Instantiation)) {
            continue;
        }
        Instantiation inst = (Instantiation) obj;
        instantiationsCheck &= (inst.getReactorClass() != reactor && inst.getReactorClass() != reactor.getReactorClass());
    }
    boolean subclassesCheck = true;
    while (subclasses.hasNext() && subclassesCheck) {
        EObject obj = subclasses.next();
        if (!(obj instanceof Reactor)) {
            continue;
        }
        Reactor subclass = (Reactor) obj;
        for (ReactorDecl decl : subclass.getSuperClasses()) {
            subclassesCheck &= (decl != reactor && decl != reactor.getReactorClass());
        }
    }
    return instantiationsCheck && subclassesCheck;
}
Also used : EObject(org.eclipse.emf.ecore.EObject) Instantiation(org.lflang.lf.Instantiation) ImportedReactor(org.lflang.lf.ImportedReactor) Reactor(org.lflang.lf.Reactor) ReactorDecl(org.lflang.lf.ReactorDecl)

Example 5 with ReactorDecl

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

the class InstantiationGraph method buildGraph.

/**
 * Traverse the AST and build this precedence graph relating the
 * encountered instantiations. Also map each reactor to all
 * declarations associated with it and each reactor to the sites of
 * its instantiations.
 */
private void buildGraph(final Instantiation instantiation, final Set<Instantiation> visited) {
    final ReactorDecl decl = instantiation.getReactorClass();
    final Reactor reactor = ASTUtils.toDefinition(decl);
    if (reactor != null) {
        Reactor container = ASTUtils.getEnclosingReactor(instantiation);
        if (visited.add(instantiation)) {
            this.reactorToInstantiation.put(reactor, instantiation);
            this.reactorToDecl.put(reactor, decl);
            if (container != null) {
                this.addEdge(container, reactor);
            } else {
                this.addNode(reactor);
            }
            for (final Instantiation inst : reactor.getInstantiations()) {
                this.buildGraph(inst, visited);
            }
        }
    }
}
Also used : ReactorDecl(org.lflang.lf.ReactorDecl) Reactor(org.lflang.lf.Reactor) Instantiation(org.lflang.lf.Instantiation)

Aggregations

Reactor (org.lflang.lf.Reactor)5 ReactorDecl (org.lflang.lf.ReactorDecl)5 ImportedReactor (org.lflang.lf.ImportedReactor)2 Instantiation (org.lflang.lf.Instantiation)2 LinkedHashSet (java.util.LinkedHashSet)1 EObject (org.eclipse.emf.ecore.EObject)1 CodeBuilder (org.lflang.generator.CodeBuilder)1 ReactorInstance (org.lflang.generator.ReactorInstance)1 Action (org.lflang.lf.Action)1 Reaction (org.lflang.lf.Reaction)1 VarRef (org.lflang.lf.VarRef)1