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