diff --git a/org.lflang/src/org/lflang/ASTUtils.java b/org.lflang/src/org/lflang/ASTUtils.java index d93c61c901..6f8ca4dbfa 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,16 @@ 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) { + try { + return inferWidthFromConnections(spec, instantiations); + } catch (InvalidSourceException e) { + // If the inference fails, return -1. + return -1; + } + } } } return result; @@ -1840,4 +1812,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 fcf2582ed9..20ccfcd896 100644 --- a/org.lflang/src/org/lflang/generator/RuntimeRange.java +++ b/org.lflang/src/org/lflang/generator/RuntimeRange.java @@ -508,4 +508,4 @@ public Port(PortInstance instance, int start, int width, Set in super(instance, start, width, interleaved); } } -} \ No newline at end of file +}