use of org.lflang.lf.Assignment in project lingua-franca by lf-lang.
the class CParameterGenerator method getInitializer.
/**
* Return a C 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 self struct of the parents of those parameters.
*/
public static String getInitializer(ParameterInstance p) {
// Handle the bank_index parameter.
if (p.getName().equals("bank_index")) {
return CUtil.bankIndex(p.getParent());
}
// Handle overrides in the intantiation.
// In case there is more than one assignment to this parameter, we need to
// find the last one.
Assignment lastAssignment = null;
for (Assignment assignment : p.getParent().getDefinition().getParameters()) {
if (assignment.getLhs() == p.getDefinition()) {
lastAssignment = assignment;
}
}
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(CUtil.reactorRef(p.getParent().getParent()) + "->" + value.getParameter().getName());
} else {
list.add(GeneratorBase.getTargetTime(value));
}
}
} else {
// parameter's initial value.
for (Value i : p.getParent().initialParameterValue(p.getDefinition())) {
if (ASTUtils.isOfTimeType(p.getDefinition())) {
list.add(GeneratorBase.getTargetTime(i));
} else {
list.add(GeneratorBase.getTargetTime(i));
}
}
}
if (list.size() == 1) {
return list.get(0);
} else {
return "{" + String.join(", ", list) + "}";
}
}
use of org.lflang.lf.Assignment 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.Assignment 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.Assignment 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);
}
use of org.lflang.lf.Assignment in project lingua-franca by lf-lang.
the class ValueGenerator method getInitializerList.
/**
* Create a list of parameter initializers in target code in the context
* of an reactor instantiation.
*
* This respects the parameter assignments given in the reactor
* instantiation and falls back to the reactors default initializers
* if no value is assigned to it.
*
* @param param The parameter to create initializers for
* @return A list of initializers in target code
*/
public List<String> getInitializerList(Parameter param, Instantiation i) {
List<Assignment> assignments = i.getParameters().stream().filter(it -> it.getLhs() == param).collect(Collectors.toList());
if (// Case 0: The parameter was not overwritten in the instantiation
assignments.isEmpty())
return getInitializerList(param);
// Case 1: The parameter was overwritten in the instantiation
List<String> list = new ArrayList<>();
if (assignments.get(0) == null)
return list;
for (Value init : assignments.get(0).getRhs()) list.add(getTargetValue(init, ASTUtils.isOfTimeType(param)));
return list;
}
Aggregations