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