Search in sources :

Example 6 with Value

use of org.lflang.lf.Value 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)

Example 7 with Value

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

the class ASTUtils method initialValueInt.

/**
 * Given a parameter return its integer value or null
 * if it does not have an integer value.
 * If the value of the parameter is a list of integers,
 * return the sum of value in the list.
 * The instantiations parameter is as in
 * {@link initialValue(Parameter, List<Instantiation>)}.
 *
 * @param parameter The parameter.
 * @param instantiations The (optional) list of instantiations.
 *
 * @return The integer value of the parameter, or null if does not have an integer value.
 *
 * @throws IllegalArgumentException If an instantiation provided is not an
 *  instantiation of the reactor class that is parameterized by the
 *  respective parameter or if the chain of instantiations is not nested.
 */
public static Integer initialValueInt(Parameter parameter, List<Instantiation> instantiations) {
    List<Value> values = initialValue(parameter, instantiations);
    int result = 0;
    for (Value value : values) {
        if (value.getLiteral() == null) {
            return null;
        }
        try {
            result += Integer.decode(value.getLiteral());
        } catch (NumberFormatException ex) {
            return null;
        }
    }
    return result;
}
Also used : Value(org.lflang.lf.Value)

Example 8 with Value

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

the class ASTUtils method initialValue.

/**
 * Given a parameter, return its initial value.
 * The initial value is a list of instances of Value, where each
 * Value is either an instance of Time, Literal, or Code.
 *
 * If the instantiations argument is null or an empty list, then the
 * value returned is simply the default value given when the parameter
 * is defined.
 *
 * If a list of instantiations is given, then the first instantiation
 * is required to be an instantiation of the reactor class that is
 * parameterized by the parameter. I.e.,
 * ```
 *     parameter.eContainer == instantiations.get(0).reactorClass
 * ```
 * If a second instantiation is given, then it is required to be an instantiation of a
 * reactor class that contains the first instantiation.  That is,
 * ```
 *     instantiations.get(0).eContainer == instantiations.get(1).reactorClass
 * ```
 * More generally, for all 0 <= i < instantiations.size - 1,
 * ```
 *     instantiations.get(i).eContainer == instantiations.get(i + 1).reactorClass
 * ```
 * If any of these conditions is not satisfied, then an IllegalArgumentException
 * will be thrown.
 *
 * Note that this chain of reactions cannot be inferred from the parameter because
 * in each of the predicates above, there may be more than one instantiation that
 * can appear on the right hand side of the predicate.
 *
 * For example, consider the following program:
 * ```
 *     reactor A(x:int(1)) {}
 *     reactor B(y:int(2)) {
 *         a1 = new A(x = y);
 *         a2 = new A(x = -1);
 *     }
 *     reactor C(z:int(3)) {
 *         b1 = new B(y = z);
 *         b2 = new B(y = -2);
 *     }
 * ```
 * Notice that there are a total of four instances of reactor class A.
 * Then
 * ```
 *     initialValue(x, null) returns 1
 *     initialValue(x, [a1]) returns 2
 *     initialValue(x, [a2]) returns -1
 *     initialValue(x, [a1, b1]) returns 3
 *     initialValue(x, [a2, b1]) returns -1
 *     initialValue(x, [a1, b2]) returns -2
 *     initialValue(x, [a2, b2]) returns -1
 * ```
 * (Actually, in each of the above cases, the returned value is a list with
 * one entry, a Literal, e.g. ["1"]).
 *
 * There are two instances of reactor class B.
 * ```
 *     initialValue(y, null) returns 2
 *     initialValue(y, [a1]) throws an IllegalArgumentException
 *     initialValue(y, [b1]) returns 3
 *     initialValue(y, [b2]) returns -2
 * ```
 *
 * @param parameter The parameter.
 * @param instantiations The (optional) list of instantiations.
 *
 * @return The value of the parameter.
 *
 * @throws IllegalArgumentException If an instantiation provided is not an
 *  instantiation of the reactor class that is parameterized by the
 *  respective parameter or if the chain of instantiations is not nested.
 */
public static List<Value> initialValue(Parameter parameter, List<Instantiation> instantiations) {
    // the first of those instantiations.
    if (instantiations != null && instantiations.size() > 0) {
        // Check to be sure that the instantiation is in fact an instantiation
        // of the reactor class for which this is a parameter.
        Instantiation instantiation = instantiations.get(0);
        if (!belongsTo(parameter, instantiation)) {
            throw new IllegalArgumentException("Parameter " + parameter.getName() + " is not a parameter of reactor instance " + instantiation.getName() + ".");
        }
        // In case there is more than one assignment to this parameter, we need to
        // find the last one.
        Assignment lastAssignment = (Assignment) null;
        for (Assignment assignment : instantiation.getParameters()) {
            if (assignment.getLhs().equals(parameter)) {
                lastAssignment = assignment;
            }
        }
        if (lastAssignment != null) {
            // Right hand side can be a list. Collect the entries.
            List<Value> result = new ArrayList<>();
            for (Value value : lastAssignment.getRhs()) {
                if (value.getParameter() != null) {
                    if (instantiations.size() > 1 && instantiation.eContainer() != instantiations.get(1).getReactorClass()) {
                        throw new IllegalArgumentException("Reactor instance " + instantiation.getName() + " is not contained by instance " + instantiations.get(1).getName() + ".");
                    }
                    result.addAll(initialValue(value.getParameter(), instantiations.subList(1, instantiations.size())));
                } else {
                    result.add(value);
                }
            }
            return result;
        }
    }
    // parameter's initial value.
    return parameter.getInit();
}
Also used : Assignment(org.lflang.lf.Assignment) Value(org.lflang.lf.Value) ArrayList(java.util.ArrayList) Instantiation(org.lflang.lf.Instantiation)

Example 9 with Value

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

the class LFValidator method checkState.

@Check(CheckType.FAST)
public void checkState(StateVar stateVar) {
    checkName(stateVar.getName(), Literals.STATE_VAR__NAME);
    if (isOfTimeType(stateVar)) {
        // make sure that it is initialized correctly.
        if (stateVar.getInit() != null) {
            for (Value init : stateVar.getInit()) {
                if (stateVar.getType() != null && stateVar.getType().isTime() && !isValidTime(init)) {
                    if (isParameterized(stateVar)) {
                        error("Referenced parameter does not denote a time.", Literals.STATE_VAR__INIT);
                    } else {
                        if (init != null && !isZero(init)) {
                            if (isInteger(init)) {
                                error("Missing time unit.", Literals.STATE_VAR__INIT);
                            } else {
                                error("Invalid time literal.", Literals.STATE_VAR__INIT);
                            }
                        }
                    }
                }
            }
        }
    } else if (this.target.requiresTypes && (ASTUtils.getInferredType(stateVar)).isUndefined()) {
        // Report if a type is missing
        error("State must have a type.", Literals.STATE_VAR__TYPE);
    }
    if (isCBasedTarget() && stateVar.getInit().size() > 1) {
        // refer to parameters.
        for (Value it : stateVar.getInit()) {
            if (it.getParameter() != null) {
                error("List items cannot refer to a parameter.", Literals.STATE_VAR__INIT);
                break;
            }
        }
    }
    EList<String> braces = stateVar.getBraces();
    if (!(braces == null || braces.isEmpty()) && this.target != Target.CPP) {
        error("Brace initializers are only supported for the C++ target", Literals.STATE_VAR__BRACES);
    }
}
Also used : Value(org.lflang.lf.Value) TimeValue(org.lflang.TimeValue) Check(org.eclipse.xtext.validation.Check)

Example 10 with Value

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

the class PythonParameterGenerator method generatePythonInitializer.

/**
 * Return a Python expression that can be used to initialize the specified
 * parameter instance. If the parameter initializer refers to other
 * parameters, then those parameter references are replaced with
 * accesses to the Python reactor instance class of the parents of
 * those parameters.
 *
 * @param p The parameter instance to create initializer for
 * @return Initialization code
 */
public static String generatePythonInitializer(ParameterInstance p) {
    // Handle overrides in the instantiation.
    // In case there is more than one assignment to this parameter, we need to
    // find the last one.
    Assignment lastAssignment = getLastAssignment(p);
    List<String> list = new LinkedList<>();
    if (lastAssignment != null) {
        // Right hand side can be a list. Collect the entries.
        for (Value value : lastAssignment.getRhs()) {
            if (value.getParameter() != null) {
                // The parameter is being assigned a parameter value.
                // Assume that parameter belongs to the parent's parent.
                // This should have been checked by the validator.
                list.add(PyUtil.reactorRef(p.getParent().getParent()) + "." + value.getParameter().getName());
            } else {
                list.add(GeneratorBase.getTargetTime(value));
            }
        }
    } else {
        for (Value i : p.getParent().initialParameterValue(p.getDefinition())) {
            list.add(PyUtil.getPythonTargetValue(i));
        }
    }
    return list.size() > 1 ? "(" + String.join(", ", list) + ")" : list.get(0);
}
Also used : Assignment(org.lflang.lf.Assignment) Value(org.lflang.lf.Value) LinkedList(java.util.LinkedList)

Aggregations

Value (org.lflang.lf.Value)11 TimeValue (org.lflang.TimeValue)5 Assignment (org.lflang.lf.Assignment)5 Instantiation (org.lflang.lf.Instantiation)5 ArrayList (java.util.ArrayList)4 LinkedList (java.util.LinkedList)4 Delay (org.lflang.lf.Delay)4 Parameter (org.lflang.lf.Parameter)4 Reactor (org.lflang.lf.Reactor)4 VarRef (org.lflang.lf.VarRef)4 List (java.util.List)3 Collectors (java.util.stream.Collectors)3 ASTUtils (org.lflang.ASTUtils)3 Action (org.lflang.lf.Action)3 Reaction (org.lflang.lf.Reaction)3 Collections (java.util.Collections)2 Objects (java.util.Objects)2 Optional (java.util.Optional)2 EcoreUtil (org.eclipse.emf.ecore.util.EcoreUtil)2 Check (org.eclipse.xtext.validation.Check)2