use of org.lflang.lf.TriggerRef in project lingua-franca by lf-lang.
the class PythonReactionGenerator method generateCPythonInitializers.
/**
* Generate necessary Python-specific initialization code for <code>reaction<code> that belongs to reactor
* <code>decl<code>.
*
* @param reaction The reaction to generate Python-specific initialization for.
* @param decl The reactor to which <code>reaction<code> belongs to.
* @param pyObjectDescriptor For each port object created, a Python-specific descriptor will be added to this that
* then can be used as an argument to <code>Py_BuildValue<code>
* (@see <a href="https://docs.python.org/3/c-api/arg.html#c.Py_BuildValue">docs.python.org/3/c-api</a>).
* @param pyObjects A "," delimited list of expressions that would be (or result in a creation of) a PyObject.
*/
private static String generateCPythonInitializers(Reaction reaction, ReactorDecl decl, List<String> pyObjects, ErrorReporter errorReporter) {
Set<Action> actionsAsTriggers = new LinkedHashSet<>();
Reactor reactor = ASTUtils.toDefinition(decl);
CodeBuilder code = new CodeBuilder();
// TODO: handle triggers
for (TriggerRef trigger : ASTUtils.convertToEmptyListIfNull(reaction.getTriggers())) {
if (trigger instanceof VarRef) {
VarRef triggerAsVarRef = (VarRef) trigger;
code.pr(generateVariableToSendPythonReaction(triggerAsVarRef, actionsAsTriggers, decl, pyObjects));
}
}
if (reaction.getTriggers() == null || reaction.getTriggers().size() == 0) {
// NOTE: this does not include contained outputs.
for (Input input : reactor.getInputs()) {
PythonPortGenerator.generateInputVariablesToSendToPythonReaction(pyObjects, input, decl);
}
}
// Next add non-triggering inputs.
for (VarRef src : ASTUtils.convertToEmptyListIfNull(reaction.getSources())) {
code.pr(generateVariableToSendPythonReaction(src, actionsAsTriggers, decl, pyObjects));
}
// Next, handle effects
if (reaction.getEffects() != null) {
for (VarRef effect : reaction.getEffects()) {
if (effect.getVariable() instanceof Action) {
// If it has already appeared as trigger, do not redefine it.
if (!actionsAsTriggers.contains(effect.getVariable())) {
PythonPortGenerator.generateActionVariableToSendToPythonReaction(pyObjects, (Action) effect.getVariable(), decl);
}
} else {
if (effect.getVariable() instanceof Output) {
PythonPortGenerator.generateOutputVariablesToSendToPythonReaction(pyObjects, (Output) effect.getVariable());
} else if (effect.getVariable() instanceof Input) {
// It is the input of a contained reactor.
code.pr(PythonPortGenerator.generateVariablesForSendingToContainedReactors(pyObjects, effect.getContainer(), (Input) effect.getVariable()));
} else {
errorReporter.reportError(reaction, "In generateReaction(): " + effect.getVariable().getName() + " is neither an input nor an output.");
}
}
}
}
return code.toString();
}
use of org.lflang.lf.TriggerRef in project lingua-franca by lf-lang.
the class PythonReactionGenerator method generatePythonReactionParametersAndInitializations.
/**
* Generate parameters and their respective initialization code for a reaction function
* The initialization code is put at the beginning of the reaction before user code
* @param parameters The parameters used for function definition
* @param inits The initialization code for those paramters
* @param decl Reactor declaration
* @param reaction The reaction to be used to generate parameters for
*/
public static void generatePythonReactionParametersAndInitializations(List<String> parameters, CodeBuilder inits, ReactorDecl decl, Reaction reaction) {
Reactor reactor = ASTUtils.toDefinition(decl);
LinkedHashSet<String> generatedParams = new LinkedHashSet<>();
// Handle triggers
for (TriggerRef trigger : ASTUtils.convertToEmptyListIfNull(reaction.getTriggers())) {
if (!(trigger instanceof VarRef)) {
continue;
}
VarRef triggerAsVarRef = (VarRef) trigger;
if (triggerAsVarRef.getVariable() instanceof Port) {
if (triggerAsVarRef.getVariable() instanceof Input) {
if (((Input) triggerAsVarRef.getVariable()).isMutable()) {
generatedParams.add("mutable_" + triggerAsVarRef.getVariable().getName() + "");
// Create a deep copy
if (ASTUtils.isMultiport((Input) triggerAsVarRef.getVariable())) {
inits.pr(triggerAsVarRef.getVariable().getName() + " = [Make() for i in range(len(mutable_" + triggerAsVarRef.getVariable().getName() + "))]");
inits.pr("for i in range(len(mutable_" + triggerAsVarRef.getVariable().getName() + ")):");
inits.pr(" " + triggerAsVarRef.getVariable().getName() + "[i].value = copy.deepcopy(mutable_" + triggerAsVarRef.getVariable().getName() + "[i].value)");
} else {
inits.pr(triggerAsVarRef.getVariable().getName() + " = Make()");
inits.pr(triggerAsVarRef.getVariable().getName() + ".value = copy.deepcopy(mutable_" + triggerAsVarRef.getVariable().getName() + ".value)");
}
} else {
generatedParams.add(triggerAsVarRef.getVariable().getName());
}
} else {
// Handle contained reactors' ports
generatedParams.add(triggerAsVarRef.getContainer().getName() + "_" + triggerAsVarRef.getVariable().getName());
inits.pr(PythonPortGenerator.generatePythonPortVariableInReaction(triggerAsVarRef));
}
} else if (triggerAsVarRef.getVariable() instanceof Action) {
generatedParams.add(triggerAsVarRef.getVariable().getName());
}
}
// Handle non-triggering inputs
if (reaction.getTriggers() == null || reaction.getTriggers().size() == 0) {
for (Input input : ASTUtils.convertToEmptyListIfNull(reactor.getInputs())) {
generatedParams.add(input.getName());
if (input.isMutable()) {
// Create a deep copy
inits.pr(input.getName() + " = copy.deepcopy(" + input.getName() + ")");
}
}
}
for (VarRef src : ASTUtils.convertToEmptyListIfNull(reaction.getSources())) {
if (src.getVariable() instanceof Output) {
// Output of a contained reactor
generatedParams.add(src.getContainer().getName() + "_" + src.getVariable().getName());
inits.pr(PythonPortGenerator.generatePythonPortVariableInReaction(src));
} else {
generatedParams.add(src.getVariable().getName());
if (src.getVariable() instanceof Input) {
if (((Input) src.getVariable()).isMutable()) {
// Create a deep copy
inits.pr(src.getVariable().getName() + " = copy.deepcopy(" + src.getVariable().getName() + ")");
}
}
}
}
// Handle effects
for (VarRef effect : ASTUtils.convertToEmptyListIfNull(reaction.getEffects())) {
if (effect.getVariable() instanceof Input) {
generatedParams.add(effect.getContainer().getName() + "_" + effect.getVariable().getName());
inits.pr(PythonPortGenerator.generatePythonPortVariableInReaction(effect));
} else {
generatedParams.add(effect.getVariable().getName());
if (effect.getVariable() instanceof Port) {
if (ASTUtils.isMultiport((Port) effect.getVariable())) {
// Handle multiports
}
}
}
}
for (String s : generatedParams) {
parameters.add(s);
}
}
use of org.lflang.lf.TriggerRef in project lingua-franca by lf-lang.
the class LFValidator method checkReaction.
@Check(CheckType.FAST)
public void checkReaction(Reaction reaction) {
if (reaction.getTriggers() == null || reaction.getTriggers().size() == 0) {
warning("Reaction has no trigger.", Literals.REACTION__TRIGGERS);
}
HashSet<Variable> triggers = new HashSet<>();
// Make sure input triggers have no container and output sources do.
for (TriggerRef trigger : reaction.getTriggers()) {
if (trigger instanceof VarRef) {
VarRef triggerVarRef = (VarRef) trigger;
triggers.add(triggerVarRef.getVariable());
if (triggerVarRef instanceof Input) {
if (triggerVarRef.getContainer() != null) {
error(String.format("Cannot have an input of a contained reactor as a trigger: %s.%s", triggerVarRef.getContainer().getName(), triggerVarRef.getVariable().getName()), Literals.REACTION__TRIGGERS);
}
} else if (triggerVarRef.getVariable() instanceof Output) {
if (triggerVarRef.getContainer() == null) {
error(String.format("Cannot have an output of this reactor as a trigger: %s", triggerVarRef.getVariable().getName()), Literals.REACTION__TRIGGERS);
}
}
}
}
// Also check that a source is not already listed as a trigger.
for (VarRef source : reaction.getSources()) {
if (triggers.contains(source.getVariable())) {
error(String.format("Source is already listed as a trigger: %s", source.getVariable().getName()), Literals.REACTION__SOURCES);
}
if (source.getVariable() instanceof Input) {
if (source.getContainer() != null) {
error(String.format("Cannot have an input of a contained reactor as a source: %s.%s", source.getContainer().getName(), source.getVariable().getName()), Literals.REACTION__SOURCES);
}
} else if (source.getVariable() instanceof Output) {
if (source.getContainer() == null) {
error(String.format("Cannot have an output of this reactor as a source: %s", source.getVariable().getName()), Literals.REACTION__SOURCES);
}
}
}
// Make sure output effects have no container and input effects do.
for (VarRef effect : reaction.getEffects()) {
if (effect.getVariable() instanceof Input) {
if (effect.getContainer() == null) {
error(String.format("Cannot have an input of this reactor as an effect: %s", effect.getVariable().getName()), Literals.REACTION__EFFECTS);
}
} else if (effect.getVariable() instanceof Output) {
if (effect.getContainer() != null) {
error(String.format("Cannot have an output of a contained reactor as an effect: %s.%s", effect.getContainer().getName(), effect.getVariable().getName()), Literals.REACTION__EFFECTS);
}
}
}
// // Report error if this reaction is part of a cycle.
Set<NamedInstance<?>> cycles = this.info.topologyCycles();
Reactor reactor = ASTUtils.getEnclosingReactor(reaction);
boolean reactionInCycle = false;
for (NamedInstance<?> it : cycles) {
if (it.getDefinition().equals(reaction)) {
reactionInCycle = true;
}
}
if (reactionInCycle) {
// Report involved triggers.
List<CharSequence> trigs = new ArrayList<>();
for (TriggerRef t : reaction.getTriggers()) {
if (!(t instanceof VarRef)) {
continue;
}
VarRef tVarRef = (VarRef) t;
boolean triggerExistsInCycle = false;
for (NamedInstance<?> c : cycles) {
if (c.getDefinition().equals(tVarRef.getVariable())) {
triggerExistsInCycle = true;
break;
}
}
if (triggerExistsInCycle) {
trigs.add(toText(tVarRef));
}
}
if (trigs.size() > 0) {
error(String.format("Reaction triggers involved in cyclic dependency in reactor %s: %s.", reactor.getName(), String.join(", ", trigs)), Literals.REACTION__TRIGGERS);
}
// Report involved sources.
List<CharSequence> sources = new ArrayList<>();
for (VarRef t : reaction.getSources()) {
boolean sourceExistInCycle = false;
for (NamedInstance<?> c : cycles) {
if (c.getDefinition().equals(t.getVariable())) {
sourceExistInCycle = true;
break;
}
}
if (sourceExistInCycle) {
sources.add(toText(t));
}
}
if (sources.size() > 0) {
error(String.format("Reaction sources involved in cyclic dependency in reactor %s: %s.", reactor.getName(), String.join(", ", sources)), Literals.REACTION__SOURCES);
}
// Report involved effects.
List<CharSequence> effects = new ArrayList<>();
for (VarRef t : reaction.getEffects()) {
boolean effectExistInCycle = false;
for (NamedInstance<?> c : cycles) {
if (c.getDefinition().equals(t.getVariable())) {
effectExistInCycle = true;
break;
}
}
if (effectExistInCycle) {
effects.add(toText(t));
}
}
if (effects.size() > 0) {
error(String.format("Reaction effects involved in cyclic dependency in reactor %s: %s.", reactor.getName(), String.join(", ", effects)), Literals.REACTION__EFFECTS);
}
if (trigs.size() + sources.size() == 0) {
error(String.format("Cyclic dependency due to preceding reaction. Consider reordering reactions within reactor %s to avoid causality loop.", reactor.getName()), reaction.eContainer(), Literals.REACTOR__REACTIONS, reactor.getReactions().indexOf(reaction));
} else if (effects.size() == 0) {
error(String.format("Cyclic dependency due to succeeding reaction. Consider reordering reactions within reactor %s to avoid causality loop.", reactor.getName()), reaction.eContainer(), Literals.REACTOR__REACTIONS, reactor.getReactions().indexOf(reaction));
}
// Not reporting reactions that are part of cycle _only_ due to reaction ordering.
// Moving them won't help solve the problem.
}
// FIXME: improve error message.
}
use of org.lflang.lf.TriggerRef in project lingua-franca by lf-lang.
the class CReactionGenerator method generateIntendedTagInheritence.
/**
* Generate code that passes existing intended tag to all output ports
* and actions. This intended tag is the minimum intended tag of the
* triggering inputs of the reaction.
*
* @param body The body of the reaction. Used to check for the DISABLE_REACTION_INITIALIZATION_MARKER.
* @param reaction The initialization code will be generated for this specific reaction
* @param decl The reactor that has the reaction
* @param reactionIndex The index of the reaction relative to other reactions in the reactor, starting from 0
*/
public static String generateIntendedTagInheritence(String body, Reaction reaction, ReactorDecl decl, int reactionIndex, CTypes types, boolean isFederatedAndDecentralized) {
// Construct the intended_tag inheritance code to go into
// the body of the function.
CodeBuilder intendedTagInheritenceCode = new CodeBuilder();
// Check if the coordination mode is decentralized and if the reaction has any effects to inherit the STP violation
if (isFederatedAndDecentralized && !(reaction.getEffects() == null || reaction.getEffects().isEmpty())) {
intendedTagInheritenceCode.pr(String.join("\n", "#pragma GCC diagnostic push", "#pragma GCC diagnostic ignored \"-Wunused-variable\"", "if (self->_lf__reaction_" + reactionIndex + ".is_STP_violated == true) {"));
intendedTagInheritenceCode.indent();
intendedTagInheritenceCode.pr(String.join("\n", "// The operations inside this if clause (if any exists) are expensive ", "// and must only be done if the reaction has unhandled STP violation.", "// Otherwise, all intended_tag values are (NEVER, 0) by default.", "", "// Inherited intended tag. This will take the minimum", "// intended_tag of all input triggers", types.getTargetTagType() + " inherited_min_intended_tag = (" + types.getTargetTagType() + ") { .time = FOREVER, .microstep = UINT_MAX };"));
intendedTagInheritenceCode.pr("// Find the minimum intended tag");
// value of intended_tag to choose the minimum.
for (TriggerRef inputTrigger : ASTUtils.convertToEmptyListIfNull(reaction.getTriggers())) {
if (inputTrigger instanceof VarRef) {
VarRef inputTriggerAsVarRef = (VarRef) inputTrigger;
Variable variable = inputTriggerAsVarRef.getVariable();
String variableName = inputTriggerAsVarRef.getVariable().getName();
if (variable instanceof Output) {
// Output from a contained reactor
String containerName = inputTriggerAsVarRef.getContainer().getName();
Output outputPort = (Output) variable;
if (ASTUtils.isMultiport(outputPort)) {
intendedTagInheritenceCode.pr(String.join("\n", "for (int i=0; i < " + containerName + "." + generateWidthVariable(variableName) + "; i++) {", " if (compare_tags(" + containerName + "." + variableName + "[i]->intended_tag,", " inherited_min_intended_tag) < 0) {", " inherited_min_intended_tag = " + containerName + "." + variableName + "[i]->intended_tag;", " }", "}"));
} else
intendedTagInheritenceCode.pr(String.join("\n", "if (compare_tags(" + containerName + "." + variableName + "->intended_tag,", " inherited_min_intended_tag) < 0) {", " inherited_min_intended_tag = " + containerName + "." + variableName + "->intended_tag;", "}"));
} else if (variable instanceof Port) {
// Input port
Port inputPort = (Port) variable;
if (ASTUtils.isMultiport(inputPort)) {
intendedTagInheritenceCode.pr(String.join("\n", "for (int i=0; i < " + generateWidthVariable(variableName) + "; i++) {", " if (compare_tags(" + variableName + "[i]->intended_tag, inherited_min_intended_tag) < 0) {", " inherited_min_intended_tag = " + variableName + "[i]->intended_tag;", " }", "}"));
} else {
intendedTagInheritenceCode.pr(String.join("\n", "if (compare_tags(" + variableName + "->intended_tag, inherited_min_intended_tag) < 0) {", " inherited_min_intended_tag = " + variableName + "->intended_tag;", "}"));
}
} else if (variable instanceof Action) {
intendedTagInheritenceCode.pr(String.join("\n", "if (compare_tags(" + variableName + "->trigger->intended_tag, inherited_min_intended_tag) < 0) {", " inherited_min_intended_tag = " + variableName + "->trigger->intended_tag;", "}"));
}
}
}
if (reaction.getTriggers() == null || reaction.getTriggers().size() == 0) {
// NOTE: this does not include contained outputs.
for (Input input : ((Reactor) reaction.eContainer()).getInputs()) {
intendedTagInheritenceCode.pr(String.join("\n", "if (compare_tags(" + input.getName() + "->intended_tag, inherited_min_intended_tag) > 0) {", " inherited_min_intended_tag = " + input.getName() + "->intended_tag;", "}"));
}
}
// Once the minimum intended tag has been found,
// it will be passed down to the port effects
// of the reaction. Note that the intended tag
// will not pass on to actions downstream.
// Last reaction that sets the intended tag for the effect
// will be seen.
intendedTagInheritenceCode.pr(String.join("\n", "// All effects inherit the minimum intended tag of input triggers", "if (inherited_min_intended_tag.time != NEVER) {"));
intendedTagInheritenceCode.indent();
for (VarRef effect : ASTUtils.convertToEmptyListIfNull(reaction.getEffects())) {
Variable effectVar = effect.getVariable();
Instantiation effContainer = effect.getContainer();
if (effectVar instanceof Input) {
if (ASTUtils.isMultiport((Port) effectVar)) {
intendedTagInheritenceCode.pr(String.join("\n", "for(int i=0; i < " + effContainer.getName() + "." + generateWidthVariable(effectVar.getName()) + "; i++) {", " " + effContainer.getName() + "." + effectVar.getName() + "[i]->intended_tag = inherited_min_intended_tag;", "}"));
} else {
if (effContainer.getWidthSpec() != null) {
// Contained reactor is a bank.
intendedTagInheritenceCode.pr(String.join("\n", "for (int bankIndex = 0; bankIndex < self->_lf_" + generateWidthVariable(effContainer.getName()) + "; bankIndex++) {", " " + effContainer.getName() + "[bankIndex]." + effectVar.getName() + " = &(self->_lf_" + effContainer.getName() + "[bankIndex]." + effectVar.getName() + ");", "}"));
} else {
// Input to a contained reaction
intendedTagInheritenceCode.pr(String.join("\n", "// Don't reset the intended tag of the output port if it has already been set.", effContainer.getName() + "." + effectVar.getName() + "->intended_tag = inherited_min_intended_tag;"));
}
}
}
}
intendedTagInheritenceCode.unindent();
intendedTagInheritenceCode.pr("}");
intendedTagInheritenceCode.unindent();
intendedTagInheritenceCode.pr("#pragma GCC diagnostic pop");
intendedTagInheritenceCode.pr("}");
}
return intendedTagInheritenceCode.toString();
}
use of org.lflang.lf.TriggerRef in project lingua-franca by lf-lang.
the class CReactionGenerator method generateInitializationForReaction.
/**
* Generate necessary initialization code inside the body of the reaction that belongs to reactor decl.
* @param body The body of the reaction. Used to check for the DISABLE_REACTION_INITIALIZATION_MARKER.
* @param reaction The initialization code will be generated for this specific reaction
* @param decl The reactor that has the reaction
* @param reactionIndex The index of the reaction relative to other reactions in the reactor, starting from 0
*/
public static String generateInitializationForReaction(String body, Reaction reaction, ReactorDecl decl, int reactionIndex, CTypes types, ErrorReporter errorReporter, Instantiation mainDef, boolean isFederatedAndDecentralized, boolean requiresTypes) {
Reactor reactor = ASTUtils.toDefinition(decl);
// Construct the reactionInitialization code to go into
// the body of the function before the verbatim code.
CodeBuilder reactionInitialization = new CodeBuilder();
CodeBuilder code = new CodeBuilder();
// Define the "self" struct.
String structType = CUtil.selfType(decl);
// or anything else. No need to declare it.
if (structType != null) {
code.pr(String.join("\n", "#pragma GCC diagnostic push", "#pragma GCC diagnostic ignored \"-Wunused-variable\"", structType + "* self = (" + structType + "*)instance_args;"));
}
// to not generate it.
if (body.startsWith(CGenerator.DISABLE_REACTION_INITIALIZATION_MARKER)) {
code.pr("#pragma GCC diagnostic pop");
return code.toString();
}
// A reaction may send to or receive from multiple ports of
// a contained reactor. The variables for these ports need to
// all be declared as fields of the same struct. Hence, we first
// collect the fields to be defined in the structs and then
// generate the structs.
Map<Instantiation, CodeBuilder> fieldsForStructsForContainedReactors = new LinkedHashMap<>();
// Actions may appear twice, first as a trigger, then with the outputs.
// But we need to declare it only once. Collect in this data structure
// the actions that are declared as triggered so that if they appear
// again with the outputs, they are not defined a second time.
// That second redefinition would trigger a compile error.
Set<Action> actionsAsTriggers = new LinkedHashSet<>();
// defined so that they can be used in the verbatim code.
for (TriggerRef trigger : ASTUtils.convertToEmptyListIfNull(reaction.getTriggers())) {
if (trigger instanceof VarRef) {
VarRef triggerAsVarRef = (VarRef) trigger;
if (triggerAsVarRef.getVariable() instanceof Port) {
generatePortVariablesInReaction(reactionInitialization, fieldsForStructsForContainedReactors, triggerAsVarRef, decl, types);
} else if (triggerAsVarRef.getVariable() instanceof Action) {
reactionInitialization.pr(generateActionVariablesInReaction((Action) triggerAsVarRef.getVariable(), decl, types));
actionsAsTriggers.add((Action) triggerAsVarRef.getVariable());
}
}
}
if (reaction.getTriggers() == null || reaction.getTriggers().size() == 0) {
// NOTE: this does not include contained outputs.
for (Input input : reactor.getInputs()) {
reactionInitialization.pr(generateInputVariablesInReaction(input, decl, types));
}
}
// Define argument for non-triggering inputs.
for (VarRef src : ASTUtils.convertToEmptyListIfNull(reaction.getSources())) {
if (src.getVariable() instanceof Port) {
generatePortVariablesInReaction(reactionInitialization, fieldsForStructsForContainedReactors, src, decl, types);
} else if (src.getVariable() instanceof Action) {
// It's a bit odd to read but not be triggered by an action, but
// OK, I guess we allow it.
reactionInitialization.pr(generateActionVariablesInReaction((Action) src.getVariable(), decl, types));
actionsAsTriggers.add((Action) src.getVariable());
}
}
// value that may have been written to that output in an earlier reaction.
if (reaction.getEffects() != null) {
for (VarRef effect : reaction.getEffects()) {
Variable variable = effect.getVariable();
if (variable instanceof Action) {
// If it has already appeared as trigger, do not redefine it.
if (!actionsAsTriggers.contains(effect.getVariable())) {
reactionInitialization.pr(CGenerator.variableStructType(variable, decl) + "* " + variable.getName() + " = &self->_lf_" + variable.getName() + ";");
}
} else if (effect.getVariable() instanceof Mode) {
// Mode change effect
int idx = ASTUtils.allModes(reactor).indexOf((Mode) effect.getVariable());
String name = effect.getVariable().getName();
if (idx >= 0) {
reactionInitialization.pr("reactor_mode_t* " + name + " = &self->_lf__modes[" + idx + "];\n" + "char _lf_" + name + "_change_type = " + (ModeTransitionType.getModeTransitionType(effect) == ModeTransitionType.HISTORY ? 2 : 1) + ";");
} else {
errorReporter.reportError(reaction, "In generateReaction(): " + name + " not a valid mode of this reactor.");
}
} else {
if (variable instanceof Output) {
reactionInitialization.pr(generateOutputVariablesInReaction(effect, decl, errorReporter, requiresTypes));
} else if (variable instanceof Input) {
// It is the input of a contained reactor.
generateVariablesForSendingToContainedReactors(reactionInitialization, fieldsForStructsForContainedReactors, effect.getContainer(), (Input) variable);
} else {
errorReporter.reportError(reaction, "In generateReaction(): effect is neither an input nor an output.");
}
}
}
}
// generate the structs used for communication to and from contained reactors.
for (Instantiation containedReactor : fieldsForStructsForContainedReactors.keySet()) {
String array = "";
if (containedReactor.getWidthSpec() != null) {
String containedReactorWidthVar = generateWidthVariable(containedReactor.getName());
code.pr("int " + containedReactorWidthVar + " = self->_lf_" + containedReactorWidthVar + ";");
// Windows does not support variables in arrays declared on the stack,
// so we use the maximum size over all bank members.
array = "[" + maxContainedReactorBankWidth(containedReactor, null, 0, mainDef) + "]";
}
code.pr(String.join("\n", "struct " + containedReactor.getName() + " {", " " + fieldsForStructsForContainedReactors.get(containedReactor) + "", "} " + containedReactor.getName() + array + ";"));
}
// Next generate all the collected setup code.
code.pr(reactionInitialization.toString());
code.pr("#pragma GCC diagnostic pop");
if (reaction.getStp() == null) {
// Pass down the intended_tag to all input and output effects
// downstream if the current reaction does not have a STP
// handler.
code.pr(generateIntendedTagInheritence(body, reaction, decl, reactionIndex, types, isFederatedAndDecentralized));
}
return code.toString();
}
Aggregations