diff --git a/org.lflang.tests/src/org/lflang/tests/compiler/LinguaFrancaValidationTest.java b/org.lflang.tests/src/org/lflang/tests/compiler/LinguaFrancaValidationTest.java
index 77fa72d11f..d3a64e19d8 100644
--- a/org.lflang.tests/src/org/lflang/tests/compiler/LinguaFrancaValidationTest.java
+++ b/org.lflang.tests/src/org/lflang/tests/compiler/LinguaFrancaValidationTest.java
@@ -907,7 +907,7 @@ public void nonzeroAfterMustHaveUnits() throws Exception {
" a.y -> b.x after 1",
"}");
validator.assertError(parseWithoutError(testCase), LfPackage.eINSTANCE.getTime(),
- null, "Missing time unit.");
+ null, "Missing or invalid time unit.");
}
diff --git a/org.lflang/src/org/lflang/ASTUtils.java b/org.lflang/src/org/lflang/ASTUtils.java
index ca7659ee5f..953cb38bfb 100644
--- a/org.lflang/src/org/lflang/ASTUtils.java
+++ b/org.lflang/src/org/lflang/ASTUtils.java
@@ -35,6 +35,8 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
@@ -89,6 +91,7 @@
import org.lflang.lf.Variable;
import org.lflang.lf.WidthSpec;
import org.lflang.lf.WidthTerm;
+import org.lflang.util.StringUtil;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Iterables;
@@ -111,6 +114,9 @@ public class ASTUtils {
* The Lingua Franca feature package.
*/
public static final LfPackage featurePackage = LfPackage.eINSTANCE;
+
+ /* Match an abbreviated form of a float literal. */
+ private static final Pattern ABBREVIATED_FLOAT = Pattern.compile("[+\\-]?\\.\\d+[\\deE+\\-]*");
/**
* A mapping from Reactor features to corresponding Mode features for collecting contained elements.
@@ -771,7 +777,7 @@ private static String toUntaggedText(Code code) {
str = str.substring(start + 2, end);
if (str.split("\n").length > 1) {
// multi line code
- text = trimCodeBlock(str);
+ text = StringUtil.trimCodeBlock(str);
} else {
// single line code
text = str.trim();
@@ -788,76 +794,6 @@ public static String toText(TypeParm t) {
return !StringExtensions.isNullOrEmpty(t.getLiteral()) ? t.getLiteral() : toText(t.getCode());
}
- /**
- * Intelligently trim the white space in a code block.
- *
- * The leading whitespaces of the first non-empty
- * code line is considered as a common prefix across all code lines. If the
- * remaining code lines indeed start with this prefix, it removes the prefix
- * from the code line.
- *
- * For examples, this code
- *
{@code
- * int test = 4;
- * if (test == 42) {
- * printf("Hello\n");
- * }
- * }
- * will be trimmed to this:
- * {@code
- * int test = 4;
- * if (test == 42) {
- * printf("Hello\n");
- * }
- * }
- *
- * In addition, if the very first line has whitespace only, then
- * that line is removed. This just means that the {= delimiter
- * is followed by a newline.
- *
- * @param code the code block to be trimmed
- * @return trimmed code block
- */
- public static String trimCodeBlock(String code) {
- String[] codeLines = code.split("\n");
- String prefix = null;
- StringBuilder buffer = new StringBuilder();
- for (String line : codeLines) {
- if (prefix == null) {
- if (line.trim().length() > 0) {
- // this is the first code line
- // find the index of the first code line
- char[] characters = line.toCharArray();
- boolean foundFirstCharacter = false;
- int firstCharacter = 0;
- for (var i = 0; i < characters.length; i++) {
- if (!foundFirstCharacter && !Character.isWhitespace(characters[i])) {
- foundFirstCharacter = true;
- firstCharacter = i;
- }
- }
- // extract the whitespace prefix
- prefix = line.substring(0, firstCharacter);
- }
- }
-
- // try to remove the prefix from all subsequent lines
- if (prefix != null) {
- if (line.startsWith(prefix)) {
- buffer.append(line.substring(prefix.length()));
- buffer.append("\n");
- } else {
- buffer.append(line);
- buffer.append("\n");
- }
- }
- }
- if (buffer.length() > 1) {
- buffer.deleteCharAt(buffer.length() - 1); // remove the last newline
- }
- return buffer.toString();
- }
-
/**
* Return a textual representation of the given element,
* without quotes if there are any. Leading or trailing
@@ -897,6 +833,17 @@ public static TimeValue toTimeValue(Element e) {
return new TimeValue(e.getTime(), TimeUnit.fromName(e.getUnit()));
}
+ /**
+ * Returns the time value represented by the given AST node.
+ */
+ public static TimeValue toTimeValue(Time e) {
+ if (!isValidTime(e)) {
+ // invalid unit, will have been reported by validator
+ throw new IllegalArgumentException();
+ }
+ return new TimeValue(e.getInterval(), TimeUnit.fromName(e.getUnit()));
+ }
+
/**
* Return a boolean based on the given element.
*
@@ -914,7 +861,7 @@ public static boolean toBoolean(Element e) {
* @return A textual representation
*/
public static String toText(Time t) {
- return JavaAstUtils.toTimeValue(t).toString();
+ return toTimeValue(t).toString();
}
/**
@@ -1130,7 +1077,7 @@ public static boolean isInteger(Value value) {
public static boolean isValidTime(Value value) {
if (value != null) {
if (value.getParameter() != null) {
- if (JavaAstUtils.isOfTimeType(value.getParameter())) {
+ if (isOfTimeType(value.getParameter())) {
return true;
}
} else if (value.getTime() != null) {
@@ -1154,10 +1101,10 @@ public static boolean isValidTime(Value value) {
* @return True if the argument denotes a valid time, false otherwise.
*/
public static boolean isValidTime(Time t) {
- if (t != null && t.getUnit() != null) {
- return true;
- }
- return false;
+ if (t == null) return false;
+ String unit = t.getUnit();
+ return t.getInterval() == 0 ||
+ TimeUnit.isValidUnit(unit);
}
/**
@@ -1180,6 +1127,200 @@ public static boolean isValidTimeList(Parameter p) {
return true;
}
+ /**
+ * Return the type of a declaration with the given
+ * (nullable) explicit type, and the given (nullable)
+ * initializer. If the explicit type is null, then the
+ * type is inferred from the initializer. Only two types
+ * can be inferred: "time" and "timeList". Return the
+ * "undefined" type if neither can be inferred.
+ *
+ * @param type Explicit type declared on the declaration
+ * @param initList A list of values used to initialize a parameter or
+ * state variable.
+ * @return The inferred type, or "undefined" if none could be inferred.
+ */
+ public static InferredType getInferredType(Type type, List initList) {
+ if (type != null) {
+ return InferredType.fromAST(type);
+ } else if (initList == null) {
+ return InferredType.undefined();
+ }
+
+ if (initList.size() == 1) {
+ // If there is a single element in the list, and it is a proper
+ // time value with units, we infer the type "time".
+ Value init = initList.get(0);
+ if (init.getParameter() != null) {
+ return getInferredType(init.getParameter());
+ } else if (ASTUtils.isValidTime(init) && !ASTUtils.isZero(init)) {
+ return InferredType.time();
+ }
+ } else if (initList.size() > 1) {
+ // If there are multiple elements in the list, and there is at
+ // least one proper time value with units, and all other elements
+ // are valid times (including zero without units), we infer the
+ // type "time list".
+ var allValidTime = true;
+ var foundNonZero = false;
+
+ for (var init : initList) {
+ if (!ASTUtils.isValidTime(init)) {
+ allValidTime = false;
+ }
+ if (!ASTUtils.isZero(init)) {
+ foundNonZero = true;
+ }
+ }
+
+ if (allValidTime && foundNonZero) {
+ // Conservatively, no bounds are inferred; the returned type
+ // is a variable-size list.
+ return InferredType.timeList();
+ }
+ }
+ return InferredType.undefined();
+ }
+
+ /**
+ * Given a parameter, return an inferred type. Only two types can be
+ * inferred: "time" and "timeList". Return the "undefined" type if
+ * neither can be inferred.
+ *
+ * @param p A parameter to infer the type of.
+ * @return The inferred type, or "undefined" if none could be inferred.
+ */
+ public static InferredType getInferredType(Parameter p) {
+ return getInferredType(p.getType(), p.getInit());
+ }
+
+ /**
+ * Given a state variable, return an inferred type. Only two types can be
+ * inferred: "time" and "timeList". Return the "undefined" type if
+ * neither can be inferred.
+ *
+ * @param s A state variable to infer the type of.
+ * @return The inferred type, or "undefined" if none could be inferred.
+ */
+ public static InferredType getInferredType(StateVar s) {
+ return getInferredType(s.getType(), s.getInit());
+ }
+
+ /**
+ * Construct an inferred type from an "action" AST node based
+ * on its declared type. If no type is declared, return the "undefined"
+ * type.
+ *
+ * @param a An action to construct an inferred type object for.
+ * @return The inferred type, or "undefined" if none was declared.
+ */
+ public static InferredType getInferredType(Action a) {
+ return getInferredType(a.getType(), null);
+ }
+
+ /**
+ * Construct an inferred type from a "port" AST node based on its declared
+ * type. If no type is declared, return the "undefined" type.
+ *
+ * @param p A port to construct an inferred type object for.
+ * @return The inferred type, or "undefined" if none was declared.
+ */
+ public static InferredType getInferredType(Port p) {
+ return getInferredType(p.getType(), null);
+ }
+
+
+
+ /**
+ * If the given string can be recognized as a floating-point number that has a leading decimal point,
+ * prepend the string with a zero and return it. Otherwise, return the original string.
+ *
+ * @param literal A string might be recognizable as a floating point number with a leading decimal point.
+ * @return an equivalent representation of literal
+ *
+ */
+ public static String addZeroToLeadingDot(String literal) {
+ Matcher m = ABBREVIATED_FLOAT.matcher(literal);
+ if (m.matches()) {
+ return literal.replace(".", "0.");
+ }
+ return literal;
+ }
+
+ /**
+ * Return true if the specified port is a multiport.
+ * @param port The port.
+ * @return True if the port is a multiport.
+ */
+ public static boolean isMultiport(Port port) {
+ return port.getWidthSpec() != null;
+ }
+
+ ////////////////////////////////
+ //// Utility functions for translating AST nodes into text
+ // This is a continuation of a large section of ASTUtils.xtend
+ // with the same name.
+
+ /**
+ * Generate code for referencing a port, action, or timer.
+ * @param reference The reference to the variable.
+ */
+ public static String generateVarRef(VarRef reference) {
+ var prefix = "";
+ if (reference.getContainer() != null) {
+ prefix = reference.getContainer().getName() + ".";
+ }
+ return prefix + reference.getVariable().getName();
+ }
+
+ /**
+ * Assuming that the given value denotes a valid time literal,
+ * return a time value.
+ */
+ public static TimeValue getLiteralTimeValue(Value v) {;
+ if (v.getTime() != null) {
+ return toTimeValue(v.getTime());
+ } else if (v.getLiteral() != null && v.getLiteral().equals("0")) {
+ return TimeValue.ZERO;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * If the parameter is of time type, return its default value.
+ * Otherwise, return null.
+ */
+ public static TimeValue getDefaultAsTimeValue(Parameter p) {
+ if (isOfTimeType(p)) {
+ var init = p.getInit().get(0);
+ if (init != null) {
+ return getLiteralTimeValue(init);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Return whether the given state variable is inferred
+ * to a time type.
+ */
+ public static boolean isOfTimeType(StateVar state) {
+ InferredType t = getInferredType(state);
+ return t.isTime && !t.isList;
+ }
+
+ /**
+ * Return whether the given parameter is inferred
+ * to a time type.
+ */
+ public static boolean isOfTimeType(Parameter param) {
+ InferredType t = getInferredType(param);
+ return t.isTime && !t.isList;
+ }
+
+
+
/**
* Given a parameter, return its initial value.
@@ -1596,6 +1737,7 @@ public static int inferPortWidth(
* @return The width, if it can be determined.
* @deprecated
*/
+ @Deprecated
public static int widthSpecification(Instantiation instantiation) {
int result = width(instantiation.getWidthSpec(), null);
if (result < 0) {
diff --git a/org.lflang/src/org/lflang/AstExtensions.kt b/org.lflang/src/org/lflang/AstExtensions.kt
index 9821e36fa6..efeb0994c8 100644
--- a/org.lflang/src/org/lflang/AstExtensions.kt
+++ b/org.lflang/src/org/lflang/AstExtensions.kt
@@ -125,17 +125,17 @@ val Reactor.isGeneric get() = ASTUtils.isGeneric(toDefinition())
* inferred to be a type. Note that if the parameter was declared to be a
* time, its initialization may still be faulty (assigning a value that is
* not actually a valid time).
- * @see JavaAstUtils.isOfTimeType
+ * @see ASTUtils.isOfTimeType
* @return True if the receiver denotes a time, false otherwise.
*/
-val Parameter.isOfTimeType: Boolean get() = JavaAstUtils.isOfTimeType(this)
+val Parameter.isOfTimeType: Boolean get() = ASTUtils.isOfTimeType(this)
/**
* Report whether the given state variable denotes a time or not.
- * @see JavaAstUtils.isOfTimeType
+ * @see ASTUtils.isOfTimeType
* @return True if the receiver denotes a time, false otherwise.
*/
-val StateVar.isOfTimeType: Boolean get() = JavaAstUtils.isOfTimeType(this)
+val StateVar.isOfTimeType: Boolean get() = ASTUtils.isOfTimeType(this)
/**
* Translate this code element into its textual representation.
@@ -276,39 +276,39 @@ val Value.isZero: Boolean
* inferred: "time" and "timeList". Return the "undefined" type if
* neither can be inferred.
*
- * @see JavaAstUtils.getInferredType
+ * @see ASTUtils.getInferredType
* @return The inferred type, or "undefined" if none could be inferred.
*/
-val Parameter.inferredType: InferredType get() = JavaAstUtils.getInferredType(this)
+val Parameter.inferredType: InferredType get() = ASTUtils.getInferredType(this)
/**
* Given a state variable, return an inferred type. Only two types can be
* inferred: "time" and "timeList". Return the "undefined" type if
* neither can be inferred.
*
- * @see JavaAstUtils.getInferredType
+ * @see ASTUtils.getInferredType
* @return The inferred type, or "undefined" if none could be inferred.
*/
-val StateVar.inferredType: InferredType get() = JavaAstUtils.getInferredType(this)
+val StateVar.inferredType: InferredType get() = ASTUtils.getInferredType(this)
/**
* Construct an inferred type from an "action" AST node based
* on its declared type. If no type is declared, return the "undefined"
* type.
*
- * @see JavaAstUtils.getInferredType
+ * @see ASTUtils.getInferredType
* @return The inferred type, or "undefined" if none was declared.
*/
-val Action.inferredType: InferredType get() = JavaAstUtils.getInferredType(this)
+val Action.inferredType: InferredType get() = ASTUtils.getInferredType(this)
/**
* Construct an inferred type from a "port" AST node based on its declared
* type. If no type is declared, return the "undefined" type.
*
- * @see JavaAstUtils.getInferredType
+ * @see ASTUtils.getInferredType
* @return The inferred type, or "undefined" if none was declared.
*/
-val Port.inferredType: InferredType get() = JavaAstUtils.getInferredType(this)
+val Port.inferredType: InferredType get() = ASTUtils.getInferredType(this)
/**
* Report whether a state variable has been initialized or not.
@@ -371,7 +371,7 @@ val Action.isPhysical get() = this.origin == ActionOrigin.PHYSICAL
/**
* Return true if the receiving is a multiport.
*/
-val Port.isMultiport get() = JavaAstUtils.isMultiport(this)
+val Port.isMultiport get() = ASTUtils.isMultiport(this)
/** Get the reactor that is instantiated in the receiving instantiation. */
val Instantiation.reactor get() = this.reactorClass.toDefinition()
diff --git a/org.lflang/src/org/lflang/JavaAstUtils.java b/org.lflang/src/org/lflang/JavaAstUtils.java
deleted file mode 100644
index 865915d743..0000000000
--- a/org.lflang/src/org/lflang/JavaAstUtils.java
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * Copyright (c) 2021, TU Dresden.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package org.lflang;
-
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.lflang.lf.Action;
-import org.lflang.lf.Parameter;
-import org.lflang.lf.Port;
-import org.lflang.lf.StateVar;
-import org.lflang.lf.Time;
-import org.lflang.lf.Type;
-import org.lflang.lf.Value;
-import org.lflang.lf.VarRef;
-
-/**
- * Helper class to manipulate the LF AST. This is partly
- * converted from {@link ASTUtils}.
- */
-public final class JavaAstUtils {
- /* Match an abbreviated form of a float literal. */
- private static final Pattern ABBREVIATED_FLOAT = Pattern.compile("[+\\-]?\\.\\d+[\\deE+\\-]*");
-
- private JavaAstUtils() {
- // utility class
- }
-
- /**
- * Return the type of a declaration with the given
- * (nullable) explicit type, and the given (nullable)
- * initializer. If the explicit type is null, then the
- * type is inferred from the initializer. Only two types
- * can be inferred: "time" and "timeList". Return the
- * "undefined" type if neither can be inferred.
- *
- * @param type Explicit type declared on the declaration
- * @param initList A list of values used to initialize a parameter or
- * state variable.
- * @return The inferred type, or "undefined" if none could be inferred.
- */
- public static InferredType getInferredType(Type type, List initList) {
- if (type != null) {
- return InferredType.fromAST(type);
- } else if (initList == null) {
- return InferredType.undefined();
- }
-
- if (initList.size() == 1) {
- // If there is a single element in the list, and it is a proper
- // time value with units, we infer the type "time".
- Value init = initList.get(0);
- if (init.getParameter() != null) {
- return getInferredType(init.getParameter());
- } else if (ASTUtils.isValidTime(init) && !ASTUtils.isZero(init)) {
- return InferredType.time();
- }
- } else if (initList.size() > 1) {
- // If there are multiple elements in the list, and there is at
- // least one proper time value with units, and all other elements
- // are valid times (including zero without units), we infer the
- // type "time list".
- var allValidTime = true;
- var foundNonZero = false;
-
- for (var init : initList) {
- if (!ASTUtils.isValidTime(init)) {
- allValidTime = false;
- }
- if (!ASTUtils.isZero(init)) {
- foundNonZero = true;
- }
- }
-
- if (allValidTime && foundNonZero) {
- // Conservatively, no bounds are inferred; the returned type
- // is a variable-size list.
- return InferredType.timeList();
- }
- }
- return InferredType.undefined();
- }
-
- /**
- * Given a parameter, return an inferred type. Only two types can be
- * inferred: "time" and "timeList". Return the "undefined" type if
- * neither can be inferred.
- *
- * @param p A parameter to infer the type of.
- * @return The inferred type, or "undefined" if none could be inferred.
- */
- public static InferredType getInferredType(Parameter p) {
- return getInferredType(p.getType(), p.getInit());
- }
-
- /**
- * Given a state variable, return an inferred type. Only two types can be
- * inferred: "time" and "timeList". Return the "undefined" type if
- * neither can be inferred.
- *
- * @param s A state variable to infer the type of.
- * @return The inferred type, or "undefined" if none could be inferred.
- */
- public static InferredType getInferredType(StateVar s) {
- return getInferredType(s.getType(), s.getInit());
- }
-
- /**
- * Construct an inferred type from an "action" AST node based
- * on its declared type. If no type is declared, return the "undefined"
- * type.
- *
- * @param a An action to construct an inferred type object for.
- * @return The inferred type, or "undefined" if none was declared.
- */
- public static InferredType getInferredType(Action a) {
- return getInferredType(a.getType(), null);
- }
-
- /**
- * Construct an inferred type from a "port" AST node based on its declared
- * type. If no type is declared, return the "undefined" type.
- *
- * @param p A port to construct an inferred type object for.
- * @return The inferred type, or "undefined" if none was declared.
- */
- public static InferredType getInferredType(Port p) {
- return getInferredType(p.getType(), null);
- }
-
- /**
- * Returns the time value represented by the given AST node.
- */
- public static TimeValue toTimeValue(Time e) {
- if (!isValidTime(e)) {
- // invalid unit, will have been reported by validator
- throw new IllegalArgumentException();
- }
- return new TimeValue(e.getInterval(), TimeUnit.fromName(e.getUnit()));
- }
-
- /**
- * If the given string can be recognized as a floating-point number that has a leading decimal point,
- * prepend the string with a zero and return it. Otherwise, return the original string.
- *
- * @param literal A string might be recognizable as a floating point number with a leading decimal point.
- * @return an equivalent representation of literal
- *
- */
- public static String addZeroToLeadingDot(String literal) {
- Matcher m = ABBREVIATED_FLOAT.matcher(literal);
- if (m.matches()) {
- return literal.replace(".", "0.");
- }
- return literal;
- }
-
- /**
- * Return true if the specified port is a multiport.
- * @param port The port.
- * @return True if the port is a multiport.
- */
- public static boolean isMultiport(Port port) {
- return port.getWidthSpec() != null;
- }
-
- ////////////////////////////////
- //// Utility functions for translating AST nodes into text
- // This is a continuation of a large section of ASTUtils.xtend
- // with the same name.
-
- /**
- * Generate code for referencing a port, action, or timer.
- * @param reference The reference to the variable.
- */
- public static String generateVarRef(VarRef reference) {
- var prefix = "";
- if (reference.getContainer() != null) {
- prefix = reference.getContainer().getName() + ".";
- }
- return prefix + reference.getVariable().getName();
- }
-
- /**
- * Assuming that the given value denotes a valid time literal,
- * return a time value.
- */
- public static TimeValue getLiteralTimeValue(Value v) {;
- if (v.getTime() != null) {
- return toTimeValue(v.getTime());
- } else if (v.getLiteral() != null && v.getLiteral().equals("0")) {
- return TimeValue.ZERO;
- } else {
- return null;
- }
- }
-
- /**
- * If the parameter is of time type, return its default value.
- * Otherwise, return null.
- */
- public static TimeValue getDefaultAsTimeValue(Parameter p) {
- if (isOfTimeType(p)) {
- var init = p.getInit().get(0);
- if (init != null) {
- return getLiteralTimeValue(init);
- }
- }
- return null;
- }
-
- /**
- * Return whether the given state variable is inferred
- * to a time type.
- */
- public static boolean isOfTimeType(StateVar state) {
- InferredType t = getInferredType(state);
- return t.isTime && !t.isList;
- }
-
- /**
- * Return whether the given parameter is inferred
- * to a time type.
- */
- public static boolean isOfTimeType(Parameter param) {
- InferredType t = getInferredType(param);
- return t.isTime && !t.isList;
- }
-
- /**
- * Returns true if the argument denotes a valid time, false otherwise.
- *
- * @param t AST node to inspect (non-null).
- */
- public static boolean isValidTime(Time t) {
- return t != null && TimeUnit.isValidUnit(t.getUnit())
- && (t.getUnit() != null || t.getInterval() == 0);
- }
-}
diff --git a/org.lflang/src/org/lflang/ModelInfo.java b/org.lflang/src/org/lflang/ModelInfo.java
index d1748040a9..dda094baaf 100644
--- a/org.lflang/src/org/lflang/ModelInfo.java
+++ b/org.lflang/src/org/lflang/ModelInfo.java
@@ -157,7 +157,7 @@ private void collectOverflowingNodes() {
// Visit all deadlines in the model; detect possible overflow.
for (var deadline : filter(toIterable(model.eAllContents()), Deadline.class)) {
// If the time value overflows, mark this deadline as overflowing.
- if (isTooLarge(JavaAstUtils.getLiteralTimeValue(deadline.getDelay()))) {
+ if (isTooLarge(ASTUtils.getLiteralTimeValue(deadline.getDelay()))) {
this.overflowingDeadlines.add(deadline);
}
@@ -169,7 +169,7 @@ private void collectOverflowingNodes() {
// Visit all STP offsets in the model; detect possible overflow.
for (var stp : filter(toIterable(model.eAllContents()), STP.class)) {
// If the time value overflows, mark this deadline as overflowing.
- if (isTooLarge(JavaAstUtils.getLiteralTimeValue(stp.getValue()))) {
+ if (isTooLarge(ASTUtils.getLiteralTimeValue(stp.getValue()))) {
this.overflowingSTP.add(stp);
}
}
@@ -196,7 +196,7 @@ private boolean detectOverflow(Set visited, Parameter current) {
var overflow = false;
// Determine whether the parameter's default value overflows or not.
- if (isTooLarge(JavaAstUtils.getDefaultAsTimeValue(current))) {
+ if (isTooLarge(ASTUtils.getDefaultAsTimeValue(current))) {
this.overflowingParameters.add(current);
overflow = true;
}
@@ -218,7 +218,7 @@ private boolean detectOverflow(Set visited, Parameter current) {
} else {
// The right-hand side of the assignment is a
// constant; check whether it is too large.
- if (isTooLarge(JavaAstUtils.getLiteralTimeValue(assignment.getRhs().get(0)))) {
+ if (isTooLarge(ASTUtils.getLiteralTimeValue(assignment.getRhs().get(0)))) {
this.overflowingAssignments.add(assignment);
overflow = true;
}
diff --git a/org.lflang/src/org/lflang/TimeUnit.java b/org.lflang/src/org/lflang/TimeUnit.java
index e3dc2fce78..96ec7caf8b 100644
--- a/org.lflang/src/org/lflang/TimeUnit.java
+++ b/org.lflang/src/org/lflang/TimeUnit.java
@@ -100,7 +100,7 @@ public static TimeUnit fromName(String name) {
*/
public static boolean isValidUnit(String name) {
if (name == null) {
- return true;
+ return false;
}
return Arrays.stream(values()).anyMatch(it -> it.hasAlias(name));
}
diff --git a/org.lflang/src/org/lflang/federated/CGeneratorExtension.java b/org.lflang/src/org/lflang/federated/CGeneratorExtension.java
index 90d3ba2994..1dbcf6c942 100644
--- a/org.lflang/src/org/lflang/federated/CGeneratorExtension.java
+++ b/org.lflang/src/org/lflang/federated/CGeneratorExtension.java
@@ -27,7 +27,7 @@
package org.lflang.federated;
import org.lflang.ASTUtils;
-import org.lflang.JavaAstUtils;
+import org.lflang.ASTUtils;
import org.lflang.TimeValue;
import org.lflang.generator.ReactorInstance;
import org.lflang.generator.c.CGenerator;
@@ -196,7 +196,7 @@ public static String createPortStatusFieldForInput(Input input,
CGenerator generator) {
StringBuilder builder = new StringBuilder();
// Check if the port is a multiport
- if (JavaAstUtils.isMultiport(input)) {
+ if (ASTUtils.isMultiport(input)) {
// If it is a multiport, then create an auxiliary list of port
// triggers for each channel of
// the multiport to keep track of the status of each channel
@@ -238,9 +238,9 @@ public static String getNetworkDelayLiteral(Delay delay) {
if (delay.getParameter() != null) {
// The parameter has to be parameter of the main reactor.
// And that value has to be a Time.
- tv = JavaAstUtils.getDefaultAsTimeValue(p);
+ tv = ASTUtils.getDefaultAsTimeValue(p);
} else {
- tv = JavaAstUtils.toTimeValue(delay.getTime());
+ tv = ASTUtils.toTimeValue(delay.getTime());
}
additionalDelayString = Long.toString(tv.toNanoSeconds());
}
diff --git a/org.lflang/src/org/lflang/federated/FedASTUtils.java b/org.lflang/src/org/lflang/federated/FedASTUtils.java
index 03c408eef8..55a05f2bc2 100644
--- a/org.lflang/src/org/lflang/federated/FedASTUtils.java
+++ b/org.lflang/src/org/lflang/federated/FedASTUtils.java
@@ -38,7 +38,7 @@
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.lflang.ASTUtils;
import org.lflang.InferredType;
-import org.lflang.JavaAstUtils;
+import org.lflang.ASTUtils;
import org.lflang.TargetProperty.CoordinationType;
import org.lflang.TimeValue;
import org.lflang.federated.serialization.SupportedSerializers;
@@ -241,7 +241,7 @@ private static void addNetworkReceiverReaction(
destinationFederate,
rightBankIndex,
rightChannelIndex,
- JavaAstUtils.getInferredType(networkAction),
+ ASTUtils.getInferredType(networkAction),
connection.isPhysical(),
serializer
));
@@ -455,7 +455,7 @@ private static TimeValue findMaxSTP(Variable port,
}
return STPList.stream()
- .map(JavaAstUtils::getLiteralTimeValue)
+ .map(ASTUtils::getLiteralTimeValue)
.filter(Objects::nonNull)
.reduce(TimeValue.ZERO, TimeValue::max);
}
diff --git a/org.lflang/src/org/lflang/federated/PythonGeneratorExtension.java b/org.lflang/src/org/lflang/federated/PythonGeneratorExtension.java
index 32de20d71b..81b6a456d6 100644
--- a/org.lflang/src/org/lflang/federated/PythonGeneratorExtension.java
+++ b/org.lflang/src/org/lflang/federated/PythonGeneratorExtension.java
@@ -27,7 +27,7 @@
package org.lflang.federated;
import org.lflang.InferredType;
-import org.lflang.JavaAstUtils;
+import org.lflang.ASTUtils;
import org.lflang.TargetProperty.CoordinationType;
import org.lflang.federated.serialization.FedNativePythonSerialization;
import org.lflang.federated.serialization.FedSerialization;
@@ -76,7 +76,7 @@ public static String generateNetworkSenderBody(
CoordinationType coordinationType
) {
String sendRef = CUtil.portRefInReaction(sendingPort, sendingBankIndex, sendingChannelIndex);
- String receiveRef = JavaAstUtils.generateVarRef(receivingPort); // Used for comments only, so no need for bank/multiport index.
+ String receiveRef = ASTUtils.generateVarRef(receivingPort); // Used for comments only, so no need for bank/multiport index.
StringBuilder result = new StringBuilder();
result.append("// Sending from " + sendRef +
" in federate " + sendingFed.name + " to " + receiveRef + " in federate " + receivingFed.name + "\n");
diff --git a/org.lflang/src/org/lflang/generator/DeadlineInstance.java b/org.lflang/src/org/lflang/generator/DeadlineInstance.java
index 6b18ef7f1a..395e823d1a 100644
--- a/org.lflang/src/org/lflang/generator/DeadlineInstance.java
+++ b/org.lflang/src/org/lflang/generator/DeadlineInstance.java
@@ -27,7 +27,7 @@
package org.lflang.generator;
-import org.lflang.JavaAstUtils;
+import org.lflang.ASTUtils;
import org.lflang.TimeValue;
import org.lflang.lf.Deadline;
import org.lflang.lf.Parameter;
diff --git a/org.lflang/src/org/lflang/generator/ParameterInstance.java b/org.lflang/src/org/lflang/generator/ParameterInstance.java
index ee2d044e6e..84c3ccac7b 100644
--- a/org.lflang/src/org/lflang/generator/ParameterInstance.java
+++ b/org.lflang/src/org/lflang/generator/ParameterInstance.java
@@ -31,7 +31,7 @@
import java.util.Optional;
import org.lflang.InferredType;
-import org.lflang.JavaAstUtils;
+import org.lflang.ASTUtils;
import org.lflang.lf.Assignment;
import org.lflang.lf.Parameter;
import org.lflang.lf.Value;
@@ -59,7 +59,7 @@ public ParameterInstance(Parameter definition, ReactorInstance parent) {
throw new InvalidSourceException("Cannot create a ParameterInstance with no parent.");
}
- this.type = JavaAstUtils.getInferredType(definition);
+ this.type = ASTUtils.getInferredType(definition);
}
/////////////////////////////////////////////
diff --git a/org.lflang/src/org/lflang/generator/ReactorInstance.java b/org.lflang/src/org/lflang/generator/ReactorInstance.java
index 50be730c05..1693a25913 100644
--- a/org.lflang/src/org/lflang/generator/ReactorInstance.java
+++ b/org.lflang/src/org/lflang/generator/ReactorInstance.java
@@ -35,7 +35,7 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
import org.lflang.ASTUtils;
import org.lflang.ErrorReporter;
-import org.lflang.JavaAstUtils;
+import org.lflang.ASTUtils;
import org.lflang.TimeValue;
import org.lflang.generator.TriggerInstance.BuiltinTriggerVariable;
import org.lflang.lf.Action;
@@ -649,9 +649,9 @@ public String toString() {
public TimeValue getTimeValue(Value v) {
Parameter p = v.getParameter();
if (p != null) {
- return JavaAstUtils.getLiteralTimeValue(lookupParameterInstance(p).getInitialValue().get(0));
+ return ASTUtils.getLiteralTimeValue(lookupParameterInstance(p).getInitialValue().get(0));
} else {
- return JavaAstUtils.getLiteralTimeValue(v);
+ return ASTUtils.getLiteralTimeValue(v);
}
}
@@ -664,9 +664,9 @@ public TimeValue getTimeValue(Value v) {
public TimeValue getTimeValue(Delay d) {
Parameter p = d.getParameter();
if (p != null) {
- return JavaAstUtils.getLiteralTimeValue(lookupParameterInstance(p).getInitialValue().get(0));
+ return ASTUtils.getLiteralTimeValue(lookupParameterInstance(p).getInitialValue().get(0));
} else {
- return JavaAstUtils.toTimeValue(d.getTime());
+ return ASTUtils.toTimeValue(d.getTime());
}
}
diff --git a/org.lflang/src/org/lflang/generator/TargetTypes.java b/org.lflang/src/org/lflang/generator/TargetTypes.java
index d52c6341c5..82925c4a95 100644
--- a/org.lflang/src/org/lflang/generator/TargetTypes.java
+++ b/org.lflang/src/org/lflang/generator/TargetTypes.java
@@ -6,7 +6,7 @@
import org.lflang.ASTUtils;
import org.lflang.InferredType;
-import org.lflang.JavaAstUtils;
+import org.lflang.ASTUtils;
import org.lflang.TimeUnit;
import org.lflang.TimeValue;
import org.lflang.lf.Action;
@@ -129,7 +129,7 @@ default String getMissingExpr(InferredType type) {
* type is returned.
*/
default String getTargetType(Type type, List init) {
- return getTargetType(JavaAstUtils.getInferredType(type, init));
+ return getTargetType(ASTUtils.getInferredType(type, init));
}
/**
@@ -169,7 +169,7 @@ default String getTargetType(InferredType type) {
* parameter.
*/
default String getTargetType(Parameter p) {
- return getTargetType(JavaAstUtils.getInferredType(p));
+ return getTargetType(ASTUtils.getInferredType(p));
}
/**
@@ -177,7 +177,7 @@ default String getTargetType(Parameter p) {
* state variable.
*/
default String getTargetType(StateVar s) {
- return getTargetType(JavaAstUtils.getInferredType(s));
+ return getTargetType(ASTUtils.getInferredType(s));
}
/**
@@ -185,7 +185,7 @@ default String getTargetType(StateVar s) {
* action.
*/
default String getTargetType(Action a) {
- return getTargetType(JavaAstUtils.getInferredType(a));
+ return getTargetType(ASTUtils.getInferredType(a));
}
/**
@@ -193,7 +193,7 @@ default String getTargetType(Action a) {
* port.
*/
default String getTargetType(Port p) {
- return getTargetType(JavaAstUtils.getInferredType(p));
+ return getTargetType(ASTUtils.getInferredType(p));
}
/**
@@ -207,7 +207,7 @@ default String getTargetType(Port p) {
*/
default String getTargetInitializer(List init, Type type, boolean initWithBraces) {
Objects.requireNonNull(init);
- var inferredType = JavaAstUtils.getInferredType(type, init);
+ var inferredType = ASTUtils.getInferredType(type, init);
if (init.size() == 1) {
return getTargetExpr(init.get(0), inferredType);
}
@@ -234,7 +234,7 @@ default String getTargetExpr(Value value, InferredType type) {
} else if (value.getTime() != null) {
return getTargetTimeExpr(value.getTime());
} else if (value.getLiteral() != null) {
- return JavaAstUtils.addZeroToLeadingDot(value.getLiteral()); // here we don't escape
+ return ASTUtils.addZeroToLeadingDot(value.getLiteral()); // here we don't escape
} else if (value.getCode() != null) {
return ASTUtils.toText(value.getCode());
} else {
diff --git a/org.lflang/src/org/lflang/generator/ValueGenerator.java b/org.lflang/src/org/lflang/generator/ValueGenerator.java
index 190777f764..2272c24884 100644
--- a/org.lflang/src/org/lflang/generator/ValueGenerator.java
+++ b/org.lflang/src/org/lflang/generator/ValueGenerator.java
@@ -5,7 +5,7 @@
import java.util.stream.Collectors;
import org.lflang.ASTUtils;
-import org.lflang.JavaAstUtils;
+import org.lflang.ASTUtils;
import org.lflang.TimeValue;
import org.lflang.lf.Assignment;
import org.lflang.lf.Delay;
@@ -69,7 +69,7 @@ public List getInitializerList(StateVar state) {
if (v.getParameter() != null) {
list.add(getTargetReference.apply(v.getParameter()));
} else {
- list.add(getTargetValue(v, JavaAstUtils.isOfTimeType(state)));
+ list.add(getTargetValue(v, ASTUtils.isOfTimeType(state)));
}
}
return list;
@@ -85,7 +85,7 @@ public List getInitializerList(Parameter param) {
List list = new ArrayList<>();
if (param == null) return list;
for (Value v : param.getInit())
- list.add(getTargetValue(v, JavaAstUtils.isOfTimeType(param)));
+ list.add(getTargetValue(v, ASTUtils.isOfTimeType(param)));
return list;
}
@@ -110,7 +110,7 @@ public List getInitializerList(Parameter param, Instantiation i) {
List list = new ArrayList<>();
if (assignments.get(0) == null) return list;
for (Value init : assignments.get(0).getRhs())
- list.add(getTargetValue(init, JavaAstUtils.isOfTimeType(param)));
+ list.add(getTargetValue(init, ASTUtils.isOfTimeType(param)));
return list;
}
@@ -136,7 +136,7 @@ public String getTargetTime(Time t) {
*/
public String getTargetTime(Delay d) {
return d.getParameter() != null ? ASTUtils.toText(d) : timeInTargetLanguage.apply(
- JavaAstUtils.toTimeValue(d.getTime()) // The time is given as a parameter reference.
+ ASTUtils.toTimeValue(d.getTime()) // The time is given as a parameter reference.
);
}
diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.xtend b/org.lflang/src/org/lflang/generator/c/CGenerator.xtend
index c67557701d..56c7ba5fc2 100644
--- a/org.lflang/src/org/lflang/generator/c/CGenerator.xtend
+++ b/org.lflang/src/org/lflang/generator/c/CGenerator.xtend
@@ -44,7 +44,7 @@ import org.eclipse.xtext.util.CancelIndicator
import org.lflang.ErrorReporter
import org.lflang.FileConfig
import org.lflang.InferredType
-import org.lflang.JavaAstUtils
+import org.lflang.ASTUtils
import org.lflang.Target
import org.lflang.TargetConfig
import org.lflang.TargetProperty
@@ -94,7 +94,7 @@ import org.lflang.util.FileUtil
import org.lflang.util.XtendUtil
import static extension org.lflang.ASTUtils.*
-import static extension org.lflang.JavaAstUtils.*
+import static extension org.lflang.ASTUtils.*
/**
* Generator for C target. This class generates C code defining each reactor
@@ -2031,7 +2031,7 @@ class CGenerator extends GeneratorBase {
// pointers that will be allocated separately for each instance
// because the sizes may be different. Otherwise, it is a simple
// pointer.
- if (JavaAstUtils.isMultiport(input)) {
+ if (ASTUtils.isMultiport(input)) {
body.pr(input, '''
// Multiport input array will be malloc'd later.
«variableStructType(input, decl)»** _lf_«input.name»;
@@ -2060,7 +2060,7 @@ class CGenerator extends GeneratorBase {
for (output : reactor.allOutputs) {
// If the port is a multiport, create an array to be allocated
// at instantiation.
- if (JavaAstUtils.isMultiport(output)) {
+ if (ASTUtils.isMultiport(output)) {
body.pr(output, '''
// Array of output ports.
«variableStructType(output, decl)»* _lf_«output.name»;
@@ -2187,7 +2187,7 @@ class CGenerator extends GeneratorBase {
if (port instanceof Input) {
// If the variable is a multiport, then the place to store the data has
// to be malloc'd at initialization.
- if (!JavaAstUtils.isMultiport(port)) {
+ if (!ASTUtils.isMultiport(port)) {
// Not a multiport.
body.pr(port, '''
«variableStructType(port, containedReactor.reactorClass)» «port.name»;
@@ -2204,7 +2204,7 @@ class CGenerator extends GeneratorBase {
// Must be an output port.
// Outputs of contained reactors are pointers to the source of data on the
// self struct of the container.
- if (!JavaAstUtils.isMultiport(port)) {
+ if (!ASTUtils.isMultiport(port)) {
// Not a multiport.
body.pr(port, '''
«variableStructType(port, containedReactor.reactorClass)»* «port.name»;
@@ -3703,7 +3703,7 @@ class CGenerator extends GeneratorBase {
* @param port The port to read from
*/
override generateDelayBody(Action action, VarRef port) {
- val ref = JavaAstUtils.generateVarRef(port);
+ val ref = ASTUtils.generateVarRef(port);
// Note that the action.type set by the base class is actually
// the port type.
if (CUtil.isTokenType(action.inferredType, types)) {
@@ -3730,7 +3730,7 @@ class CGenerator extends GeneratorBase {
* @param port The port to write to.
*/
override generateForwardBody(Action action, VarRef port) {
- val outputName = JavaAstUtils.generateVarRef(port)
+ val outputName = ASTUtils.generateVarRef(port)
if (CUtil.isTokenType(action.inferredType, types)) {
// Forward the entire token and prevent freeing.
// Increment the ref_count because it will be decremented
@@ -3894,7 +3894,7 @@ class CGenerator extends GeneratorBase {
SupportedSerializers serializer
) {
var sendRef = CUtil.portRefInReaction(sendingPort, sendingBankIndex, sendingChannelIndex);
- val receiveRef = JavaAstUtils.generateVarRef(receivingPort); // Used for comments only, so no need for bank/multiport index.
+ val receiveRef = ASTUtils.generateVarRef(receivingPort); // Used for comments only, so no need for bank/multiport index.
val result = new StringBuilder()
// We currently have no way to mark a reaction "unordered"
diff --git a/org.lflang/src/org/lflang/generator/c/CParameterGenerator.java b/org.lflang/src/org/lflang/generator/c/CParameterGenerator.java
index 56b11c9c5b..54d47005a5 100644
--- a/org.lflang/src/org/lflang/generator/c/CParameterGenerator.java
+++ b/org.lflang/src/org/lflang/generator/c/CParameterGenerator.java
@@ -3,7 +3,7 @@
import java.util.LinkedList;
import java.util.List;
import org.lflang.generator.ParameterInstance;
-import org.lflang.JavaAstUtils;
+import org.lflang.ASTUtils;
import org.lflang.generator.GeneratorBase;
import org.lflang.lf.Assignment;
import org.lflang.lf.Value;
@@ -48,7 +48,7 @@ public static String getInitializer(ParameterInstance p) {
// there was no assignment in the instantiation. So just use the
// parameter's initial value.
for (Value i : p.getParent().initialParameterValue(p.getDefinition())) {
- if (JavaAstUtils.isOfTimeType(p.getDefinition())) {
+ if (ASTUtils.isOfTimeType(p.getDefinition())) {
list.add(GeneratorBase.getTargetTime(i));
} else {
list.add(GeneratorBase.getTargetTime(i));
diff --git a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java
index 0b45d9f647..135a855c37 100644
--- a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java
+++ b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java
@@ -11,7 +11,7 @@
import org.lflang.ASTUtils;
import org.lflang.ErrorReporter;
import org.lflang.InferredType;
-import org.lflang.JavaAstUtils;
+import org.lflang.ASTUtils;
import org.lflang.generator.CodeBuilder;
import org.lflang.generator.ModeInstance.ModeTransitionType;
import org.lflang.lf.Action;
@@ -343,7 +343,7 @@ public static String generateIntendedTagInheritence(String body, Reaction reacti
// Output from a contained reactor
String containerName = inputTriggerAsVarRef.getContainer().getName();
Output outputPort = (Output) variable;
- if (JavaAstUtils.isMultiport(outputPort)) {
+ if (ASTUtils.isMultiport(outputPort)) {
intendedTagInheritenceCode.pr(String.join("\n",
"for (int i=0; i < "+containerName+"."+generateWidthVariable(variableName)+"; i++) {",
" if (compare_tags("+containerName+"."+variableName+"[i]->intended_tag,",
@@ -362,7 +362,7 @@ public static String generateIntendedTagInheritence(String body, Reaction reacti
} else if (variable instanceof Port) {
// Input port
Port inputPort = (Port) variable;
- if (JavaAstUtils.isMultiport(inputPort)) {
+ if (ASTUtils.isMultiport(inputPort)) {
intendedTagInheritenceCode.pr(String.join("\n",
"for (int i=0; i < "+generateWidthVariable(variableName)+"; i++) {",
" if (compare_tags("+variableName+"[i]->intended_tag, inherited_min_intended_tag) < 0) {",
@@ -415,7 +415,7 @@ public static String generateIntendedTagInheritence(String body, Reaction reacti
Variable effectVar = effect.getVariable();
Instantiation effContainer = effect.getContainer();
if (effectVar instanceof Input) {
- if (JavaAstUtils.isMultiport((Port) effectVar)) {
+ if (ASTUtils.isMultiport((Port) effectVar)) {
intendedTagInheritenceCode.pr(String.join("\n",
"for(int i=0; i < "+effContainer.getName()+"."+generateWidthVariable(effectVar.getName())+"; i++) {",
" "+effContainer.getName()+"."+effectVar.getName()+"[i]->intended_tag = inherited_min_intended_tag;",
@@ -479,7 +479,7 @@ private static void generateVariablesForSendingToContainedReactors(
String defWidth = generateWidthVariable(defName);
String inputName = input.getName();
String inputWidth = generateWidthVariable(inputName);
- if (!JavaAstUtils.isMultiport(input)) {
+ if (!ASTUtils.isMultiport(input)) {
// Contained reactor's input is not a multiport.
structBuilder.pr(inputStructType+"* "+inputName+";");
if (definition.getWidthSpec() != null) {
@@ -556,7 +556,7 @@ private static void generatePortVariablesInReaction(
String outputWidth = generateWidthVariable(outputName);
// First define the struct containing the output value and indicator
// of its presence.
- if (!JavaAstUtils.isMultiport(output)) {
+ if (!ASTUtils.isMultiport(output)) {
// Output is not a multiport.
structBuilder.pr(portStructType+"* "+outputName+";");
} else {
@@ -575,7 +575,7 @@ private static void generatePortVariablesInReaction(
" "+reactorName+"[i]."+outputName+" = self->_lf_"+reactorName+"[i]."+outputName+";",
"}"
));
- if (JavaAstUtils.isMultiport(output)) {
+ if (ASTUtils.isMultiport(output)) {
builder.pr(String.join("\n",
"for (int i = 0; i < "+reactorWidth+"; i++) {",
" "+reactorName+"[i]."+outputWidth+" = self->_lf_"+reactorName+"[i]."+outputWidth+";",
@@ -585,7 +585,7 @@ private static void generatePortVariablesInReaction(
} else {
// Output is not in a bank.
builder.pr(reactorName+"."+outputName+" = self->_lf_"+reactorName+"."+outputName+";");
- if (JavaAstUtils.isMultiport(output)) {
+ if (ASTUtils.isMultiport(output)) {
builder.pr(reactorName+"."+outputWidth+" = self->_lf_"+reactorName+"."+outputWidth+";");
}
}
@@ -604,7 +604,7 @@ private static String generateActionVariablesInReaction(
) {
String structType = CGenerator.variableStructType(action, decl).toString();
// If the action has a type, create variables for accessing the value.
- InferredType type = JavaAstUtils.getInferredType(action);
+ InferredType type = ASTUtils.getInferredType(action);
// Pointer to the lf_token_t sent as the payload in the trigger.
String tokenPointer = "(self->_lf__"+action.getName()+".token)";
CodeBuilder builder = new CodeBuilder();
@@ -648,7 +648,7 @@ private static String generateInputVariablesInReaction(
CTypes types
) {
String structType = CGenerator.variableStructType(input, decl).toString();
- InferredType inputType = JavaAstUtils.getInferredType(input);
+ InferredType inputType = ASTUtils.getInferredType(input);
CodeBuilder builder = new CodeBuilder();
String inputName = input.getName();
String inputWidth = generateWidthVariable(inputName);
@@ -661,10 +661,10 @@ private static String generateInputVariablesInReaction(
// depending on whether the input is mutable, whether it is a multiport,
// and whether it is a token type.
// Easy case first.
- if (!input.isMutable() && !CUtil.isTokenType(inputType, types) && !JavaAstUtils.isMultiport(input)) {
+ if (!input.isMutable() && !CUtil.isTokenType(inputType, types) && !ASTUtils.isMultiport(input)) {
// Non-mutable, non-multiport, primitive type.
builder.pr(structType+"* "+inputName+" = self->_lf_"+inputName+";");
- } else if (input.isMutable()&& !CUtil.isTokenType(inputType, types) && !JavaAstUtils.isMultiport(input)) {
+ } else if (input.isMutable()&& !CUtil.isTokenType(inputType, types) && !ASTUtils.isMultiport(input)) {
// Mutable, non-multiport, primitive type.
builder.pr(String.join("\n",
"// Mutable input, so copy the input into a temporary variable.",
@@ -672,7 +672,7 @@ private static String generateInputVariablesInReaction(
structType+" _lf_tmp_"+inputName+" = *(self->_lf_"+inputName+");",
structType+"* "+inputName+" = &_lf_tmp_"+inputName+";"
));
- } else if (!input.isMutable()&& CUtil.isTokenType(inputType, types) && !JavaAstUtils.isMultiport(input)) {
+ } else if (!input.isMutable()&& CUtil.isTokenType(inputType, types) && !ASTUtils.isMultiport(input)) {
// Non-mutable, non-multiport, token type.
builder.pr(String.join("\n",
structType+"* "+inputName+" = self->_lf_"+inputName+";",
@@ -683,7 +683,7 @@ private static String generateInputVariablesInReaction(
" "+inputName+"->length = 0;",
"}"
));
- } else if (input.isMutable()&& CUtil.isTokenType(inputType, types) && !JavaAstUtils.isMultiport(input)) {
+ } else if (input.isMutable()&& CUtil.isTokenType(inputType, types) && !ASTUtils.isMultiport(input)) {
// Mutable, non-multiport, token type.
builder.pr(String.join("\n",
"// Mutable input, so copy the input struct into a temporary variable.",
@@ -706,7 +706,7 @@ private static String generateInputVariablesInReaction(
" "+inputName+"->length = 0;",
"}"
));
- } else if (!input.isMutable()&& JavaAstUtils.isMultiport(input)) {
+ } else if (!input.isMutable()&& ASTUtils.isMultiport(input)) {
// Non-mutable, multiport, primitive or token type.
builder.pr(structType+"** "+inputName+" = self->_lf_"+inputName+";");
} else if (CUtil.isTokenType(inputType, types)) {
@@ -785,7 +785,7 @@ public static String generateOutputVariablesInReaction(
CGenerator.variableStructType(output, decl).toString()
:
CGenerator.variableStructType(output, effect.getContainer().getReactorClass()).toString();
- if (!JavaAstUtils.isMultiport(output)) {
+ if (!ASTUtils.isMultiport(output)) {
// Output port is not a multiport.
return outputStructType+"* "+outputName+" = &self->_lf_"+outputName+";";
} else {
diff --git a/org.lflang/src/org/lflang/generator/python/PythonGenerator.java b/org.lflang/src/org/lflang/generator/python/PythonGenerator.java
index e52db93876..58c4443d96 100644
--- a/org.lflang/src/org/lflang/generator/python/PythonGenerator.java
+++ b/org.lflang/src/org/lflang/generator/python/PythonGenerator.java
@@ -48,7 +48,7 @@
import org.lflang.ErrorReporter;
import org.lflang.FileConfig;
import org.lflang.InferredType;
-import org.lflang.JavaAstUtils;
+import org.lflang.ASTUtils;
import org.lflang.Target;
import org.lflang.federated.FedFileConfig;
import org.lflang.federated.FederateInstance;
@@ -578,7 +578,7 @@ public void generateAuxiliaryStructs(
private void generateAuxiliaryStructsForPort(ReactorDecl decl,
Port port) {
- boolean isTokenType = CUtil.isTokenType(JavaAstUtils.getInferredType(port), types);
+ boolean isTokenType = CUtil.isTokenType(ASTUtils.getInferredType(port), types);
code.pr(port,
PythonPortGenerator.generateAliasTypeDef(decl, port, isTokenType,
genericPortTypeWithToken,
@@ -750,7 +750,7 @@ public void doGenerate(Resource resource, LFGeneratorContext context) {
*/
@Override
public String generateDelayBody(Action action, VarRef port) {
- return PythonReactionGenerator.generateCDelayBody(action, port, CUtil.isTokenType(JavaAstUtils.getInferredType(action), types));
+ return PythonReactionGenerator.generateCDelayBody(action, port, CUtil.isTokenType(ASTUtils.getInferredType(action), types));
}
/**
@@ -763,8 +763,8 @@ public String generateDelayBody(Action action, VarRef port) {
*/
@Override
public String generateForwardBody(Action action, VarRef port) {
- String outputName = JavaAstUtils.generateVarRef(port);
- if (CUtil.isTokenType(JavaAstUtils.getInferredType(action), types)) {
+ String outputName = ASTUtils.generateVarRef(port);
+ if (CUtil.isTokenType(ASTUtils.getInferredType(action), types)) {
return super.generateForwardBody(action, port);
} else {
return "SET("+outputName+", "+action.getName()+"->token->value);";
diff --git a/org.lflang/src/org/lflang/generator/python/PythonParameterGenerator.java b/org.lflang/src/org/lflang/generator/python/PythonParameterGenerator.java
index 046971f795..fafabdc0ec 100644
--- a/org.lflang/src/org/lflang/generator/python/PythonParameterGenerator.java
+++ b/org.lflang/src/org/lflang/generator/python/PythonParameterGenerator.java
@@ -8,7 +8,7 @@
import com.google.common.base.Objects;
import org.lflang.ASTUtils;
-import org.lflang.JavaAstUtils;
+import org.lflang.ASTUtils;
import org.lflang.generator.CodeBuilder;
import org.lflang.generator.GeneratorBase;
import org.lflang.generator.ParameterInstance;
@@ -36,7 +36,7 @@ public static String generatePythonInstantiations(ReactorDecl decl, PythonTypes
for (Parameter param : getAllParameters(decl)) {
if (!types.getTargetType(param).equals("PyObject*")) {
// If type is given, use it
- String type = types.getPythonType(JavaAstUtils.getInferredType(param));
+ String type = types.getPythonType(ASTUtils.getInferredType(param));
lines.add("self._"+param.getName()+":"+type+" = "+generatePythonInitializer(param));
} else {
// If type is not given, just pass along the initialization
diff --git a/org.lflang/src/org/lflang/generator/python/PythonPortGenerator.java b/org.lflang/src/org/lflang/generator/python/PythonPortGenerator.java
index 75befe9c00..efbb111e1d 100644
--- a/org.lflang/src/org/lflang/generator/python/PythonPortGenerator.java
+++ b/org.lflang/src/org/lflang/generator/python/PythonPortGenerator.java
@@ -8,7 +8,7 @@
import org.lflang.lf.ReactorDecl;
import org.lflang.lf.VarRef;
import java.util.List;
-import org.lflang.JavaAstUtils;
+import org.lflang.ASTUtils;
import org.lflang.generator.CodeBuilder;
import org.lflang.generator.c.CGenerator;
import static org.lflang.generator.c.CUtil.generateWidthVariable;
@@ -82,7 +82,7 @@ public static void generateOutputVariablesToSendToPythonReaction(
// FIXME: The C Generator also has this awkwardness. It makes the code generators
// unnecessarily difficult to maintain, and it may have performance consequences as well.
// Maybe we should change the SET macros.
- if (!JavaAstUtils.isMultiport(output)) {
+ if (!ASTUtils.isMultiport(output)) {
pyObjects.add(generateConvertCPortToPy(output.getName(), NONMULTIPORT_WIDTHSPEC));
} else {
pyObjects.add(generateConvertCPortToPy(output.getName()));
@@ -111,14 +111,14 @@ public static void generateInputVariablesToSendToPythonReaction(
// depending on whether the input is mutable, whether it is a multiport,
// and whether it is a token type.
// Easy case first.
- if (!input.isMutable() && !JavaAstUtils.isMultiport(input)) {
+ if (!input.isMutable() && !ASTUtils.isMultiport(input)) {
// Non-mutable, non-multiport, primitive type.
pyObjects.add(generateConvertCPortToPy(input.getName()));
- } else if (input.isMutable() && !JavaAstUtils.isMultiport(input)) {
+ } else if (input.isMutable() && !ASTUtils.isMultiport(input)) {
// Mutable, non-multiport, primitive type.
// TODO: handle mutable
pyObjects.add(generateConvertCPortToPy(input.getName()));
- } else if (!input.isMutable() && JavaAstUtils.isMultiport(input)) {
+ } else if (!input.isMutable() && ASTUtils.isMultiport(input)) {
// Non-mutable, multiport, primitive.
// TODO: support multiports
pyObjects.add(generateConvertCPortToPy(input.getName()));
@@ -144,7 +144,7 @@ public static String generateVariablesForSendingToContainedReactors(
CodeBuilder code = new CodeBuilder();
if (definition.getWidthSpec() != null) {
String widthSpec = NONMULTIPORT_WIDTHSPEC;
- if (JavaAstUtils.isMultiport(port)) {
+ if (ASTUtils.isMultiport(port)) {
widthSpec = "self->_lf_"+definition.getName()+"[i]."+generateWidthVariable(port.getName());
}
// Contained reactor is a bank.
@@ -153,7 +153,7 @@ public static String generateVariablesForSendingToContainedReactors(
pyObjects.add(definition.getName()+"_py_list");
}
else {
- if (JavaAstUtils.isMultiport(port)) {
+ if (ASTUtils.isMultiport(port)) {
pyObjects.add(generateConvertCPortToPy(definition.getName()+"."+port.getName()));
} else {
pyObjects.add(generateConvertCPortToPy(definition.getName()+"."+port.getName(), NONMULTIPORT_WIDTHSPEC));
diff --git a/org.lflang/src/org/lflang/generator/python/PythonReactionGenerator.java b/org.lflang/src/org/lflang/generator/python/PythonReactionGenerator.java
index c984b9934e..8aa4494a29 100644
--- a/org.lflang/src/org/lflang/generator/python/PythonReactionGenerator.java
+++ b/org.lflang/src/org/lflang/generator/python/PythonReactionGenerator.java
@@ -23,7 +23,7 @@
import org.lflang.generator.ReactionInstance;
import org.lflang.generator.ReactorInstance;
import org.lflang.ErrorReporter;
-import org.lflang.JavaAstUtils;
+import org.lflang.ASTUtils;
import org.lflang.Target;
import org.lflang.ASTUtils;
@@ -241,7 +241,7 @@ public static void generatePythonReactionParametersAndInitializations(List{@code
+ * int test = 4;
+ * if (test == 42) {
+ * printf("Hello\n");
+ * }
+ * }
+ * will be trimmed to this:
+ * {@code
+ * int test = 4;
+ * if (test == 42) {
+ * printf("Hello\n");
+ * }
+ * }
+ *
+ * In addition, if the very first line has whitespace only, then
+ * that line is removed. This just means that the {= delimiter
+ * is followed by a newline.
+ *
+ * @param code the code block to be trimmed
+ * @return trimmed code block
+ */
+ public static String trimCodeBlock(String code) {
+ String[] codeLines = code.split("\n");
+ String prefix = null;
+ StringBuilder buffer = new StringBuilder();
+ for (String line : codeLines) {
+ if (prefix == null && line.trim().length() > 0) {
+ // this is the first code line
+ // find the index of the first code line
+ int firstCharacter = 0;
+ for (var i = 0; i < line.length(); i++) {
+ if (!Character.isWhitespace(line.charAt(i))) {
+ firstCharacter = i;
+ break;
+ }
+ }
+ // extract the whitespace prefix
+ prefix = line.substring(0, firstCharacter);
+ }
+
+ // try to remove the prefix from all subsequent lines
+ if (prefix != null) {
+ if (line.startsWith(prefix)) {
+ buffer.append(line.substring(prefix.length()));
+ } else {
+ buffer.append(line);
+ }
+ buffer.append("\n");
+ }
+ }
+ if (buffer.length() > 1) {
+ buffer.deleteCharAt(buffer.length() - 1); // remove the last newline
+ }
+ return buffer.toString();
+ }
}
diff --git a/org.lflang/src/org/lflang/validation/BaseLFValidator.java b/org.lflang/src/org/lflang/validation/BaseLFValidator.java
index c96e93f953..1ce506efb3 100644
--- a/org.lflang/src/org/lflang/validation/BaseLFValidator.java
+++ b/org.lflang/src/org/lflang/validation/BaseLFValidator.java
@@ -34,9 +34,8 @@
import org.eclipse.xtext.validation.Check;
import org.eclipse.xtext.validation.CheckMode;
import org.eclipse.xtext.validation.CheckType;
-
+import org.lflang.ASTUtils;
import org.lflang.TimeUnit;
-import org.lflang.lf.Delay;
import org.lflang.lf.LfPackage.Literals;
import org.lflang.lf.Time;
@@ -44,12 +43,10 @@ public class BaseLFValidator extends AbstractLFValidator {
@Check(CheckType.FAST)
public void checkTime(Time time) {
- int magnitude = time.getInterval();
- String unit = time.getUnit();
- if (unit == null && magnitude != 0) {
- error("Missing time unit.", Literals.TIME__UNIT);
- } if (!TimeUnit.isValidUnit(unit)) {
- error("Invalid time unit '" + unit + "'. Should be one of " + TimeUnit.list() + ".", Literals.TIME__UNIT);
+ if (!ASTUtils.isValidTime(time)) {
+ error("Missing or invalid time unit. " +
+ "Should be one of " +
+ TimeUnit.list() + ".", Literals.TIME__UNIT);
}
}
diff --git a/org.lflang/src/org/lflang/validation/LFValidator.java b/org.lflang/src/org/lflang/validation/LFValidator.java
index d66f10ebb5..d1d9f338fd 100644
--- a/org.lflang/src/org/lflang/validation/LFValidator.java
+++ b/org.lflang/src/org/lflang/validation/LFValidator.java
@@ -34,7 +34,7 @@
import static org.lflang.ASTUtils.isZero;
import static org.lflang.ASTUtils.toDefinition;
import static org.lflang.ASTUtils.toText;
-import static org.lflang.JavaAstUtils.isOfTimeType;
+import static org.lflang.ASTUtils.isOfTimeType;
import java.io.IOException;
import java.util.ArrayList;
@@ -56,7 +56,7 @@
import org.eclipse.xtext.validation.CheckType;
import org.eclipse.xtext.validation.ValidationMessageAcceptor;
import org.lflang.ASTUtils;
-import org.lflang.JavaAstUtils;
+import org.lflang.ASTUtils;
import org.lflang.ModelInfo;
import org.lflang.Target;
import org.lflang.TargetProperty;
@@ -623,7 +623,7 @@ public void checkParameter(Parameter param) {
}
} else if (this.target.requiresTypes) {
// Report missing target type. param.inferredType.undefine
- if ((JavaAstUtils.getInferredType(param).isUndefined())) {
+ if ((ASTUtils.getInferredType(param).isUndefined())) {
error("Type declaration missing.", Literals.PARAMETER__TYPE);
}
}
@@ -1005,7 +1005,7 @@ public void checkState(StateVar stateVar) {
}
}
}
- } else if (this.target.requiresTypes && (JavaAstUtils.getInferredType(stateVar)).isUndefined()) {
+ } 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);
}