Search in sources :

Example 1 with CodeBuilder

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

the class PythonPortGenerator method generateVariablesForSendingToContainedReactors.

/**
 * Generate into the specified string builder the code to
 *  pass local variables for sending data to an input
 *  of a contained reaction (e.g. for a deadline violation).
 *  @param builder The string builder.
 *  @param definition AST node defining the reactor within which this occurs
 *  @param input Input of the contained reactor.
 */
public static String generateVariablesForSendingToContainedReactors(List<String> pyObjects, Instantiation definition, Port port) {
    CodeBuilder code = new CodeBuilder();
    if (definition.getWidthSpec() != null) {
        String widthSpec = NONMULTIPORT_WIDTHSPEC;
        if (ASTUtils.isMultiport(port)) {
            widthSpec = "self->_lf_" + definition.getName() + "[i]." + generateWidthVariable(port.getName());
        }
        // Contained reactor is a bank.
        // Create a Python list
        code.pr(generatePythonListForContainedBank(definition.getName(), port, widthSpec));
        pyObjects.add(definition.getName() + "_py_list");
    } else {
        if (ASTUtils.isMultiport(port)) {
            pyObjects.add(generateConvertCPortToPy(definition.getName() + "." + port.getName()));
        } else {
            pyObjects.add(generateConvertCPortToPy(definition.getName() + "." + port.getName(), NONMULTIPORT_WIDTHSPEC));
        }
    }
    return code.toString();
}
Also used : CodeBuilder(org.lflang.generator.CodeBuilder)

Example 2 with CodeBuilder

use of org.lflang.generator.CodeBuilder 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();
}
Also used : LinkedHashSet(java.util.LinkedHashSet) VarRef(org.lflang.lf.VarRef) Action(org.lflang.lf.Action) Input(org.lflang.lf.Input) Output(org.lflang.lf.Output) Reactor(org.lflang.lf.Reactor) TriggerRef(org.lflang.lf.TriggerRef) CodeBuilder(org.lflang.generator.CodeBuilder)

Example 3 with CodeBuilder

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

the class PythonReactionGenerator method generateCReaction.

/**
 * Generate the reaction in the .c file, which calls the Python reaction through the CPython interface.
 *
 * @param reaction The reaction to generate Python-specific initialization for.
 * @param decl The reactor to which <code>reaction<code> belongs to.
 * @param reactionIndex The index number of the reaction in decl.
 * @param mainDef The main reactor.
 * @param errorReporter An error reporter.
 * @param types A helper class for type-related stuff.
 * @param isFederatedAndDecentralized True if program is federated and coordination type is decentralized.
 */
public static String generateCReaction(Reaction reaction, ReactorDecl decl, int reactionIndex, Instantiation mainDef, ErrorReporter errorReporter, CTypes types, boolean isFederatedAndDecentralized) {
    // Contains the actual comma separated list of inputs to the reaction of type generic_port_instance_struct or generic_port_instance_with_token_struct.
    // Each input must be cast to (PyObject *) (aka their descriptors for Py_BuildValue are "O")
    List<String> pyObjects = new ArrayList<>();
    CodeBuilder code = new CodeBuilder();
    code.pr(generateCReactionFunctionHeader(decl, reactionIndex) + " {");
    code.indent();
    code.pr(CReactionGenerator.generateInitializationForReaction("", reaction, decl, reactionIndex, types, errorReporter, mainDef, isFederatedAndDecentralized, Target.Python.requiresTypes));
    code.prSourceLineNumber(reaction.getCode());
    code.pr(generateCPythonReactionCaller(decl, reactionIndex, pyObjects, generateCPythonInitializers(reaction, decl, pyObjects, errorReporter)));
    code.unindent();
    code.pr("}");
    // Now generate code for the deadline violation function, if there is one.
    if (reaction.getDeadline() != null) {
        code.pr(generateCDeadlineFunctionHeader(decl, reactionIndex) + " {");
        code.indent();
        code.pr(CReactionGenerator.generateInitializationForReaction("", reaction, decl, reactionIndex, types, errorReporter, mainDef, isFederatedAndDecentralized, Target.Python.requiresTypes));
        code.pr(generateCPythonDeadlineCaller(decl, reactionIndex, pyObjects));
        code.unindent();
        code.pr("}");
    }
    return code.toString();
}
Also used : ArrayList(java.util.ArrayList) CodeBuilder(org.lflang.generator.CodeBuilder)

Example 4 with CodeBuilder

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

the class PythonReactionGenerator method generateCPythonReactionLinkers.

/**
 * Generate Python code to link cpython functions to python functions for each reaction.
 * @param instance The reactor instance.
 * @param reactions The reactions of this instance.
 * @param mainDef The definition of the main reactor
 * @param topLevelName The name of the module
 */
public static String generateCPythonReactionLinkers(ReactorInstance instance, Instantiation mainDef, String topLevelName) {
    String nameOfSelfStruct = CUtil.reactorRef(instance);
    Reactor reactor = ASTUtils.toDefinition(instance.getDefinition().getReactorClass());
    CodeBuilder code = new CodeBuilder();
    // Delay reactors and top-level reactions used in the top-level reactor(s) in federated execution are generated in C
    if (reactor.getName().contains(GeneratorBase.GEN_DELAY_CLASS_NAME) || instance.getDefinition().getReactorClass() == (mainDef != null ? mainDef.getReactorClass() : null) && reactor.isFederated()) {
        return "";
    }
    // Initialize the name field to the unique name of the instance
    code.pr(nameOfSelfStruct + "->_lf_name = \"" + instance.uniqueID() + "_lf\";");
    for (ReactionInstance reaction : instance.reactions) {
        // Create a PyObject for each reaction
        code.pr(generateCPythonReactionLinker(instance, reaction, topLevelName, nameOfSelfStruct));
    }
    return code.toString();
}
Also used : ReactionInstance(org.lflang.generator.ReactionInstance) Reactor(org.lflang.lf.Reactor) CodeBuilder(org.lflang.generator.CodeBuilder)

Example 5 with CodeBuilder

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

the class PythonReactionGenerator method generatePythonFunction.

/**
 * Generate the function that is executed whenever the deadline of the reaction
 * with the given reaction index is missed
 * @param reaction The reaction to generate deadline miss code for
 * @param reactionIndex The agreed-upon index of the reaction in the reactor (should match the C generated code)
 * @param reactionParameters The parameters to the deadline violation function, which are the same as the reaction function
 */
public static String generatePythonFunction(String pythonFunctionName, String inits, String reactionBody, List<String> reactionParameters) {
    String params = reactionParameters.size() > 0 ? ", " + String.join(", ", reactionParameters) : "";
    CodeBuilder code = new CodeBuilder();
    code.pr("def " + pythonFunctionName + "(self" + params + "):");
    code.indent();
    code.pr(inits);
    code.pr(reactionBody);
    code.pr("return 0");
    return code.toString();
}
Also used : CodeBuilder(org.lflang.generator.CodeBuilder)

Aggregations

CodeBuilder (org.lflang.generator.CodeBuilder)23 Reactor (org.lflang.lf.Reactor)5 Input (org.lflang.lf.Input)4 Output (org.lflang.lf.Output)4 ArrayList (java.util.ArrayList)3 ReactorInstance (org.lflang.generator.ReactorInstance)3 Action (org.lflang.lf.Action)3 TriggerRef (org.lflang.lf.TriggerRef)3 VarRef (org.lflang.lf.VarRef)3 LinkedHashSet (java.util.LinkedHashSet)2 InferredType (org.lflang.InferredType)2 CUtil.generateWidthVariable (org.lflang.generator.c.CUtil.generateWidthVariable)2 Instantiation (org.lflang.lf.Instantiation)2 Port (org.lflang.lf.Port)2 Reaction (org.lflang.lf.Reaction)2 Variable (org.lflang.lf.Variable)2 IOException (java.io.IOException)1 Path (java.nio.file.Path)1 LinkedHashMap (java.util.LinkedHashMap)1 ParameterInstance (org.lflang.generator.ParameterInstance)1