Search in sources :

Example 1 with TypeParm

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

the class ASTUtils method getDelayClass.

/**
 * Return a synthesized AST node that represents the definition of a delay
 * reactor. Depending on whether the target supports generics, either this
 * method will synthesize a generic definition and keep returning it upon
 * subsequent calls, or otherwise, it will synthesize a new definition for
 * each new type it hasn't yet created a compatible delay reactor for.
 * @param type The type the delay class must be compatible with.
 * @param generator A code generator.
 */
private static Reactor getDelayClass(Type type, GeneratorBase generator) {
    String className;
    if (generator.getTargetTypes().supportsGenerics()) {
        className = GeneratorBase.GEN_DELAY_CLASS_NAME;
    } else {
        String id = Integer.toHexString(InferredType.fromAST(type).toText().hashCode());
        className = String.format("%s_%s", GeneratorBase.GEN_DELAY_CLASS_NAME, id);
    }
    // Only add class definition if it is not already there.
    Reactor classDef = generator.findDelayClass(className);
    if ((classDef != null)) {
        return classDef;
    }
    Reactor delayClass = factory.createReactor();
    Parameter delayParameter = factory.createParameter();
    Action action = factory.createAction();
    VarRef triggerRef = factory.createVarRef();
    VarRef effectRef = factory.createVarRef();
    Input input = factory.createInput();
    Output output = factory.createOutput();
    VarRef inRef = factory.createVarRef();
    VarRef outRef = factory.createVarRef();
    Reaction r1 = factory.createReaction();
    Reaction r2 = factory.createReaction();
    delayParameter.setName("delay");
    delayParameter.setType(factory.createType());
    delayParameter.getType().setId("time");
    delayParameter.getType().setTime(true);
    Time defaultTime = factory.createTime();
    defaultTime.setUnit(null);
    defaultTime.setInterval(0);
    Value defaultValue = factory.createValue();
    defaultValue.setTime(defaultTime);
    delayParameter.getInit().add(defaultValue);
    // Name the newly created action; set its delay and type.
    action.setName("act");
    action.setMinDelay(factory.createValue());
    action.getMinDelay().setParameter(delayParameter);
    action.setOrigin(ActionOrigin.LOGICAL);
    if (generator.getTargetTypes().supportsGenerics()) {
        action.setType(factory.createType());
        action.getType().setId("T");
    } else {
        action.setType(EcoreUtil.copy(type));
    }
    input.setName("inp");
    input.setType(EcoreUtil.copy(action.getType()));
    output.setName("out");
    output.setType(EcoreUtil.copy(action.getType()));
    // Establish references to the involved ports.
    inRef.setVariable(input);
    outRef.setVariable(output);
    // Establish references to the action.
    triggerRef.setVariable(action);
    effectRef.setVariable(action);
    // Add the action to the reactor.
    delayClass.setName(className);
    delayClass.getActions().add(action);
    // Configure the second reaction, which reads the input.
    r1.getTriggers().add(inRef);
    r1.getEffects().add(effectRef);
    r1.setCode(factory.createCode());
    r1.getCode().setBody(generator.generateDelayBody(action, inRef));
    // Configure the first reaction, which produces the output.
    r2.getTriggers().add(triggerRef);
    r2.getEffects().add(outRef);
    r2.setCode(factory.createCode());
    r2.getCode().setBody(generator.generateForwardBody(action, outRef));
    // Add the reactions to the newly created reactor class.
    // These need to go in the opposite order in case
    // a new input arrives at the same time the delayed
    // output is delivered!
    delayClass.getReactions().add(r2);
    delayClass.getReactions().add(r1);
    // Add a type parameter if the target supports it.
    if (generator.getTargetTypes().supportsGenerics()) {
        TypeParm parm = factory.createTypeParm();
        parm.setLiteral(generator.generateDelayGeneric());
        delayClass.getTypeParms().add(parm);
    }
    delayClass.getInputs().add(input);
    delayClass.getOutputs().add(output);
    delayClass.getParameters().add(delayParameter);
    generator.addDelayClass(delayClass);
    return delayClass;
}
Also used : VarRef(org.lflang.lf.VarRef) Action(org.lflang.lf.Action) Input(org.lflang.lf.Input) Output(org.lflang.lf.Output) Value(org.lflang.lf.Value) Parameter(org.lflang.lf.Parameter) Time(org.lflang.lf.Time) ImportedReactor(org.lflang.lf.ImportedReactor) Reactor(org.lflang.lf.Reactor) Reaction(org.lflang.lf.Reaction) TypeParm(org.lflang.lf.TypeParm)

Example 2 with TypeParm

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

the class ASTUtils method getDelayInstance.

/**
 * Create a new instance delay instances using the given reactor class.
 * The supplied time value is used to override the default interval (which
 * is zero).
 * If the target supports parametric polymorphism, then a single class may
 * be used for each instantiation, in which case a non-empty string must
 * be supplied to parameterize the instance.
 * A default name ("delay") is assigned to the instantiation, but this
 * name must be overridden at the call site, where checks can be done to
 * avoid name collisions in the container in which the instantiation is
 * to be placed. Such checks (or modifications of the AST) are not
 * performed in this method in order to avoid causing concurrent
 * modification exceptions.
 * @param delayClass The class to create an instantiation for
 * @param connection The connection to create a delay instantiation foe
 * @param generic A string that denotes the appropriate type parameter,
 *  which should be null or empty if the target does not support generics.
 * @param defineWidthFromConnection If this is true and if the connection
 *  is a wide connection, then instantiate a bank of delays where the width
 *  is given by ports involved in the connection. Otherwise, the width will
 *  be  unspecified indicating a variable length.
 */
private static Instantiation getDelayInstance(Reactor delayClass, Connection connection, String generic, Boolean defineWidthFromConnection) {
    Delay delay = connection.getDelay();
    Instantiation delayInstance = factory.createInstantiation();
    delayInstance.setReactorClass(delayClass);
    if (!StringExtensions.isNullOrEmpty(generic)) {
        TypeParm typeParm = factory.createTypeParm();
        typeParm.setLiteral(generic);
        delayInstance.getTypeParms().add(typeParm);
    }
    if (hasMultipleConnections(connection)) {
        WidthSpec widthSpec = factory.createWidthSpec();
        if (defineWidthFromConnection) {
            // to delay the ports first, and then broadcast the output of the delays.
            for (VarRef port : connection.getLeftPorts()) {
                WidthTerm term = factory.createWidthTerm();
                term.setPort(EcoreUtil.copy(port));
                widthSpec.getTerms().add(term);
            }
        } else {
            widthSpec.setOfVariableLength(true);
        }
        delayInstance.setWidthSpec(widthSpec);
    }
    Assignment assignment = factory.createAssignment();
    assignment.setLhs(delayClass.getParameters().get(0));
    Value value = factory.createValue();
    if (delay.getParameter() != null) {
        value.setParameter(delay.getParameter());
    } else {
        value.setTime(delay.getTime());
    }
    assignment.getRhs().add(value);
    delayInstance.getParameters().add(assignment);
    // This has to be overridden.
    delayInstance.setName("delay");
    return delayInstance;
}
Also used : VarRef(org.lflang.lf.VarRef) Assignment(org.lflang.lf.Assignment) Value(org.lflang.lf.Value) Instantiation(org.lflang.lf.Instantiation) WidthTerm(org.lflang.lf.WidthTerm) Delay(org.lflang.lf.Delay) TypeParm(org.lflang.lf.TypeParm) WidthSpec(org.lflang.lf.WidthSpec)

Aggregations

TypeParm (org.lflang.lf.TypeParm)2 Value (org.lflang.lf.Value)2 VarRef (org.lflang.lf.VarRef)2 Action (org.lflang.lf.Action)1 Assignment (org.lflang.lf.Assignment)1 Delay (org.lflang.lf.Delay)1 ImportedReactor (org.lflang.lf.ImportedReactor)1 Input (org.lflang.lf.Input)1 Instantiation (org.lflang.lf.Instantiation)1 Output (org.lflang.lf.Output)1 Parameter (org.lflang.lf.Parameter)1 Reaction (org.lflang.lf.Reaction)1 Reactor (org.lflang.lf.Reactor)1 Time (org.lflang.lf.Time)1 WidthSpec (org.lflang.lf.WidthSpec)1 WidthTerm (org.lflang.lf.WidthTerm)1