From 5a10005f2374d6c6f4dd7c2d89bba8cefe3d8eb3 Mon Sep 17 00:00:00 2001 From: Hokeun Kim Date: Mon, 11 Jul 2022 13:28:31 -0700 Subject: [PATCH] Fix the issue with non-positive parent.width in RuntimeRange by adding logic for inferring width from connections into width() function of ASTUtils.java. --- org.lflang/src/org/lflang/ASTUtils.java | 93 +++++++++++-------- .../org/lflang/generator/RuntimeRange.java | 5 +- 2 files changed, 55 insertions(+), 43 deletions(-) diff --git a/org.lflang/src/org/lflang/ASTUtils.java b/org.lflang/src/org/lflang/ASTUtils.java index d93c61c901..a989a99f03 100644 --- a/org.lflang/src/org/lflang/ASTUtils.java +++ b/org.lflang/src/org/lflang/ASTUtils.java @@ -1434,44 +1434,7 @@ public static int width(WidthSpec spec, List instantiations) { return 1; } if (spec.isOfVariableLength() && spec.eContainer() instanceof Instantiation) { - // We may be able to infer the width by examining the connections of - // the enclosing reactor definition. This works, for example, with - // delays between multiports or banks of reactors. - // Attempt to infer the width. - for (Connection c : ((Reactor) spec.eContainer().eContainer()).getConnections()) { - int leftWidth = 0; - int rightWidth = 0; - int leftOrRight = 0; - for (VarRef leftPort : c.getLeftPorts()) { - if (leftPort.getContainer() == spec.eContainer()) { - if (leftOrRight != 0) { - throw new InvalidSourceException("Multiple ports with variable width on a connection."); - } - // Indicate that the port is on the left. - leftOrRight = -1; - } else { - leftWidth += inferPortWidth(leftPort, c, instantiations); - } - } - for (VarRef rightPort : c.getRightPorts()) { - if (rightPort.getContainer() == spec.eContainer()) { - if (leftOrRight != 0) { - throw new InvalidSourceException("Multiple ports with variable width on a connection."); - } - // Indicate that the port is on the right. - leftOrRight = 1; - } else { - rightWidth += inferPortWidth(rightPort, c, instantiations); - } - } - if (leftOrRight < 0) { - return rightWidth - leftWidth; - } else if (leftOrRight > 0) { - return leftWidth - rightWidth; - } - } - // A connection was not found with the instantiation. - return -1; + return inferWidthFromConnections(spec, instantiations); } var result = 0; for (WidthTerm term: spec.getTerms()) { @@ -1485,7 +1448,11 @@ public static int width(WidthSpec spec, List instantiations) { } else if (term.getWidth() > 0) { result += term.getWidth(); } else { - return -1; + // If the width cannot be determined because term's width <= 0, which means the term's width + // must be inferred, try to infer the width using connections. + if (spec.eContainer() instanceof Instantiation) { + return inferWidthFromConnections(spec, instantiations); + } } } return result; @@ -1840,4 +1807,52 @@ private static LinkedHashSet superClasses(Reactor reactor, Set } return result; } + + /** + * We may be able to infer the width by examining the connections of + * the enclosing reactor definition. This works, for example, with + * delays between multiports or banks of reactors. + * Attempt to infer the width from connections and return -1 if the width cannot be inferred. + * + * @param spec The width specification or null (to return 1). + * @param instantiations The (optional) list of instantiations. + * + * @return The width, or -1 if the width could not be inferred from connections. + */ + private static int inferWidthFromConnections(WidthSpec spec, List instantiations) { + for (Connection c : ((Reactor) spec.eContainer().eContainer()).getConnections()) { + int leftWidth = 0; + int rightWidth = 0; + int leftOrRight = 0; + for (VarRef leftPort : c.getLeftPorts()) { + if (leftPort.getContainer() == spec.eContainer()) { + if (leftOrRight != 0) { + throw new InvalidSourceException("Multiple ports with variable width on a connection."); + } + // Indicate that the port is on the left. + leftOrRight = -1; + } else { + leftWidth += inferPortWidth(leftPort, c, instantiations); + } + } + for (VarRef rightPort : c.getRightPorts()) { + if (rightPort.getContainer() == spec.eContainer()) { + if (leftOrRight != 0) { + throw new InvalidSourceException("Multiple ports with variable width on a connection."); + } + // Indicate that the port is on the right. + leftOrRight = 1; + } else { + rightWidth += inferPortWidth(rightPort, c, instantiations); + } + } + if (leftOrRight < 0) { + return rightWidth - leftWidth; + } else if (leftOrRight > 0) { + return leftWidth - rightWidth; + } + } + // A connection was not found with the instantiation. + return -1; + } } diff --git a/org.lflang/src/org/lflang/generator/RuntimeRange.java b/org.lflang/src/org/lflang/generator/RuntimeRange.java index c4dcc9aac0..20ccfcd896 100644 --- a/org.lflang/src/org/lflang/generator/RuntimeRange.java +++ b/org.lflang/src/org/lflang/generator/RuntimeRange.java @@ -210,10 +210,7 @@ public RuntimeRange( int maxWidth = instance.width; // Initial value. NamedInstance parent = instance.parent; while (parent.depth > 0) { - if (parent.width > 0) { - // Skip when width is not positive (e.g., delay reactor instance) - maxWidth *= parent.width; - } + maxWidth *= parent.width; parent = parent.parent; } this.maxWidth = maxWidth;