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;
}
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();
}
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;
}
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;
}
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);
}
}
}
}
Aggregations