From 672e637a48dbfab4f7a6d27342e1f4117af52100 Mon Sep 17 00:00:00 2001 From: Marten Lohstroh Date: Thu, 6 Jul 2023 19:48:59 -0700 Subject: [PATCH 01/10] Fix inheritance problem exposed in examples --- .../main/java/org/lflang/ast/ASTUtils.java | 1 + .../federated/generator/FederateInstance.java | 20 ++++++++++++++----- .../federated/InheritanceFederatedImport.lf | 15 ++++++++++++++ 3 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 test/C/src/federated/InheritanceFederatedImport.lf diff --git a/core/src/main/java/org/lflang/ast/ASTUtils.java b/core/src/main/java/org/lflang/ast/ASTUtils.java index e5d0da81ac..6e466fef57 100644 --- a/core/src/main/java/org/lflang/ast/ASTUtils.java +++ b/core/src/main/java/org/lflang/ast/ASTUtils.java @@ -98,6 +98,7 @@ import org.lflang.lf.Watchdog; import org.lflang.lf.WidthSpec; import org.lflang.lf.WidthTerm; +import org.lflang.lf.impl.ReactorDeclImpl; import org.lflang.util.StringUtil; /** diff --git a/core/src/main/java/org/lflang/federated/generator/FederateInstance.java b/core/src/main/java/org/lflang/federated/generator/FederateInstance.java index 22e70a6c73..e17fcdd37b 100644 --- a/core/src/main/java/org/lflang/federated/generator/FederateInstance.java +++ b/core/src/main/java/org/lflang/federated/generator/FederateInstance.java @@ -73,7 +73,7 @@ * @author Edward A. Lee * @author Soroush Bateni */ -public class FederateInstance { // why does this not extend ReactorInstance? +public class FederateInstance { /** * Construct a new instance with the specified instantiation of of a top-level reactor. The @@ -258,15 +258,25 @@ private boolean contains(Instantiation instantiation, ReactorDecl reactor) { return true; } - boolean instantiationsCheck = false; - // For a federate, we don't need to look inside imported reactors. if (instantiation.getReactorClass() instanceof Reactor reactorDef) { + // Check whether the reactor is instantiated for (Instantiation child : reactorDef.getInstantiations()) { - instantiationsCheck |= contains(child, reactor); + if (contains(child, reactor)) { + return true; + } + } + // Check whether the reactor is a parent + for (var parent : reactorDef.getSuperClasses()) { + if (reactor instanceof Reactor r) { + return r.equals(parent); + } + if (reactor instanceof ImportedReactor i) { + return i.getReactorClass().equals(parent); + } } } - return instantiationsCheck; + return false; } /** diff --git a/test/C/src/federated/InheritanceFederatedImport.lf b/test/C/src/federated/InheritanceFederatedImport.lf new file mode 100644 index 0000000000..41adc90247 --- /dev/null +++ b/test/C/src/federated/InheritanceFederatedImport.lf @@ -0,0 +1,15 @@ +target C { + timeout: 10 secs +} + +import HelloWorld2 from "../HelloWorld.lf" + +reactor Print extends HelloWorld2 { + reaction(startup) {= + printf("Foo\n"); + =} +} + +federated reactor { + print = new Print() +} From 134c8768a2138a41a7a0d35111c7e3fefa1706e8 Mon Sep 17 00:00:00 2001 From: Marten Lohstroh Date: Thu, 6 Jul 2023 19:57:03 -0700 Subject: [PATCH 02/10] Apply formatter --- core/src/main/java/org/lflang/ast/ASTUtils.java | 1 - test/C/src/federated/InheritanceFederatedImport.lf | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/core/src/main/java/org/lflang/ast/ASTUtils.java b/core/src/main/java/org/lflang/ast/ASTUtils.java index 6e466fef57..e5d0da81ac 100644 --- a/core/src/main/java/org/lflang/ast/ASTUtils.java +++ b/core/src/main/java/org/lflang/ast/ASTUtils.java @@ -98,7 +98,6 @@ import org.lflang.lf.Watchdog; import org.lflang.lf.WidthSpec; import org.lflang.lf.WidthTerm; -import org.lflang.lf.impl.ReactorDeclImpl; import org.lflang.util.StringUtil; /** diff --git a/test/C/src/federated/InheritanceFederatedImport.lf b/test/C/src/federated/InheritanceFederatedImport.lf index 41adc90247..787c56b4bf 100644 --- a/test/C/src/federated/InheritanceFederatedImport.lf +++ b/test/C/src/federated/InheritanceFederatedImport.lf @@ -5,9 +5,7 @@ target C { import HelloWorld2 from "../HelloWorld.lf" reactor Print extends HelloWorld2 { - reaction(startup) {= - printf("Foo\n"); - =} + reaction(startup) {= printf("Foo\n"); =} } federated reactor { From 918b5fbc5c04894a95cebae0a3324a7c5a3182cf Mon Sep 17 00:00:00 2001 From: Marten Lohstroh Date: Fri, 7 Jul 2023 01:25:13 -0700 Subject: [PATCH 03/10] Fix #1733 --- .../federated/generator/FederateInstance.java | 21 ++++++++++++++----- test/C/src/federated/InheritanceFederated.lf | 16 ++++++++++++++ 2 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 test/C/src/federated/InheritanceFederated.lf diff --git a/core/src/main/java/org/lflang/federated/generator/FederateInstance.java b/core/src/main/java/org/lflang/federated/generator/FederateInstance.java index e17fcdd37b..8ec3334504 100644 --- a/core/src/main/java/org/lflang/federated/generator/FederateInstance.java +++ b/core/src/main/java/org/lflang/federated/generator/FederateInstance.java @@ -259,23 +259,34 @@ private boolean contains(Instantiation instantiation, ReactorDecl reactor) { } if (instantiation.getReactorClass() instanceof Reactor reactorDef) { - // Check whether the reactor is instantiated + // Check if the reactor is instantiated for (Instantiation child : reactorDef.getInstantiations()) { if (contains(child, reactor)) { return true; } } - // Check whether the reactor is a parent + // Check if the reactor is a super class for (var parent : reactorDef.getSuperClasses()) { if (reactor instanceof Reactor r) { - return r.equals(parent); + if (r.equals(parent)) { + return true; + } + // Check if there are instantiations of the reactor a super class + if (parent instanceof Reactor p) { + for (var inst : p.getInstantiations()) { + if (contains(inst, reactor)) { + return true; + } + } + } } if (reactor instanceof ImportedReactor i) { - return i.getReactorClass().equals(parent); + if (i.getReactorClass().equals(parent)) { + return true; + } } } } - return false; } diff --git a/test/C/src/federated/InheritanceFederated.lf b/test/C/src/federated/InheritanceFederated.lf new file mode 100644 index 0000000000..ea38674f91 --- /dev/null +++ b/test/C/src/federated/InheritanceFederated.lf @@ -0,0 +1,16 @@ +target C + +reactor A { + reaction(startup) {= printf("Hello\n"); =} +} + +reactor B { + a = new A() +} + +reactor C extends B { +} + +federated reactor { + c = new C() +} From bcfe566863bcb7664663709a6ed377f922093fe3 Mon Sep 17 00:00:00 2001 From: Marten Lohstroh Date: Fri, 7 Jul 2023 01:26:44 -0700 Subject: [PATCH 04/10] Fix typo --- .../java/org/lflang/federated/generator/FederateInstance.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/lflang/federated/generator/FederateInstance.java b/core/src/main/java/org/lflang/federated/generator/FederateInstance.java index 8ec3334504..fd6a59bbb6 100644 --- a/core/src/main/java/org/lflang/federated/generator/FederateInstance.java +++ b/core/src/main/java/org/lflang/federated/generator/FederateInstance.java @@ -271,7 +271,7 @@ private boolean contains(Instantiation instantiation, ReactorDecl reactor) { if (r.equals(parent)) { return true; } - // Check if there are instantiations of the reactor a super class + // Check if there are instantiations of the reactor in a super class if (parent instanceof Reactor p) { for (var inst : p.getInstantiations()) { if (contains(inst, reactor)) { From 8dc6d854512025b66ab0e212a20bacd90059fd64 Mon Sep 17 00:00:00 2001 From: Marten Lohstroh Date: Fri, 7 Jul 2023 09:17:05 -0700 Subject: [PATCH 05/10] Timeouts to let new tests terminate --- test/C/src/federated/InheritanceFederated.lf | 4 +++- test/C/src/federated/InheritanceFederatedImport.lf | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/test/C/src/federated/InheritanceFederated.lf b/test/C/src/federated/InheritanceFederated.lf index ea38674f91..7b5b0ca644 100644 --- a/test/C/src/federated/InheritanceFederated.lf +++ b/test/C/src/federated/InheritanceFederated.lf @@ -1,4 +1,6 @@ -target C +target C { + timeout: 1 ms +} reactor A { reaction(startup) {= printf("Hello\n"); =} diff --git a/test/C/src/federated/InheritanceFederatedImport.lf b/test/C/src/federated/InheritanceFederatedImport.lf index 787c56b4bf..f06356debd 100644 --- a/test/C/src/federated/InheritanceFederatedImport.lf +++ b/test/C/src/federated/InheritanceFederatedImport.lf @@ -1,5 +1,5 @@ target C { - timeout: 10 secs + timeout: 1 ms } import HelloWorld2 from "../HelloWorld.lf" From a2801f25feeade7b6bf0dbdc29ca2bfcffea4e9c Mon Sep 17 00:00:00 2001 From: Marten Lohstroh Date: Fri, 7 Jul 2023 22:51:15 -0700 Subject: [PATCH 06/10] Use Java's typesystem properly instead of relying on reflection and find out statically that an overload for Method was missing --- .../federated/generator/FedASTUtils.java | 2 +- .../federated/generator/FedImportEmitter.java | 4 +- .../federated/generator/FedMainEmitter.java | 12 +-- .../generator/FedReactorEmitter.java | 2 +- .../federated/generator/FederateInstance.java | 102 ++++++++---------- 5 files changed, 52 insertions(+), 70 deletions(-) diff --git a/core/src/main/java/org/lflang/federated/generator/FedASTUtils.java b/core/src/main/java/org/lflang/federated/generator/FedASTUtils.java index 71b809baf6..1c791c42ae 100644 --- a/core/src/main/java/org/lflang/federated/generator/FedASTUtils.java +++ b/core/src/main/java/org/lflang/federated/generator/FedASTUtils.java @@ -441,7 +441,7 @@ private static Set findUpstreamPortsInFederate( Set reactionVisited) { Set toReturn = new HashSet<>(); if (port == null) return toReturn; - else if (federate.contains(port.getParent())) { + else if (federate.references(port.getParent())) { // Reached the requested federate toReturn.add(port); visitedPorts.add(port); diff --git a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java index 2e21534fc4..bde700dbcf 100644 --- a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java +++ b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java @@ -23,7 +23,7 @@ public class FedImportEmitter { String generateImports(FederateInstance federate, FedFileConfig fileConfig) { var imports = ((Model) federate.instantiation.eContainer().eContainer()) - .getImports().stream().filter(federate::contains).toList(); + .getImports().stream().filter(federate::references).toList(); // Transform the URIs imports.stream() @@ -46,7 +46,7 @@ String generateImports(FederateInstance federate, FedFileConfig fileConfig) { var new_import = EcoreUtil.copy(i); new_import .getReactorClasses() - .removeIf(importedReactor -> !federate.contains(importedReactor)); + .removeIf(importedReactor -> !federate.references(importedReactor)); return new_import; }) .map(FormattingUtil.renderer(federate.targetConfig.target)) diff --git a/core/src/main/java/org/lflang/federated/generator/FedMainEmitter.java b/core/src/main/java/org/lflang/federated/generator/FedMainEmitter.java index 4d262d1bb4..d0638ccf38 100644 --- a/core/src/main/java/org/lflang/federated/generator/FedMainEmitter.java +++ b/core/src/main/java/org/lflang/federated/generator/FedMainEmitter.java @@ -37,23 +37,23 @@ String generateMainReactor( "\n", renderer.apply(federate.instantiation), ASTUtils.allStateVars(originalMainReactor).stream() - .filter(federate::contains) + .filter(federate::references) .map(renderer) .collect(Collectors.joining("\n")), ASTUtils.allActions(originalMainReactor).stream() - .filter(federate::contains) + .filter(federate::references) .map(renderer) .collect(Collectors.joining("\n")), ASTUtils.allTimers(originalMainReactor).stream() - .filter(federate::contains) + .filter(federate::references) .map(renderer) .collect(Collectors.joining("\n")), ASTUtils.allMethods(originalMainReactor).stream() - .filter(federate::contains) + .filter(federate::references) .map(renderer) .collect(Collectors.joining("\n")), ASTUtils.allReactions(originalMainReactor).stream() - .filter(federate::contains) + .filter(federate::references) .map(renderer) .collect(Collectors.joining("\n"))) .indent(4) @@ -72,7 +72,7 @@ private CharSequence generateMainSignature( FederateInstance federate, Reactor originalMainReactor, Function renderer) { var paramList = ASTUtils.allParameters(originalMainReactor).stream() - .filter(federate::contains) + .filter(federate::references) .map(renderer) .collect(Collectors.joining(",", "(", ")")); // Empty "()" is currently not allowed by the syntax diff --git a/core/src/main/java/org/lflang/federated/generator/FedReactorEmitter.java b/core/src/main/java/org/lflang/federated/generator/FedReactorEmitter.java index f00d590f12..bb33f6e624 100644 --- a/core/src/main/java/org/lflang/federated/generator/FedReactorEmitter.java +++ b/core/src/main/java/org/lflang/federated/generator/FedReactorEmitter.java @@ -15,7 +15,7 @@ public FedReactorEmitter() {} String generateReactorDefinitions(FederateInstance federate) { return ((Model) federate.instantiation.eContainer().eContainer()) .getReactors().stream() - .filter(federate::contains) + .filter(federate::references) .map(FormattingUtil.renderer(federate.targetConfig.target)) .collect(Collectors.joining("\n")); } diff --git a/core/src/main/java/org/lflang/federated/generator/FederateInstance.java b/core/src/main/java/org/lflang/federated/generator/FederateInstance.java index fd6a59bbb6..f9cf4bd3ad 100644 --- a/core/src/main/java/org/lflang/federated/generator/FederateInstance.java +++ b/core/src/main/java/org/lflang/federated/generator/FederateInstance.java @@ -35,7 +35,6 @@ import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; -import org.eclipse.emf.ecore.EObject; import org.lflang.MessageReporter; import org.lflang.TargetConfig; import org.lflang.TimeValue; @@ -53,6 +52,7 @@ import org.lflang.lf.ImportedReactor; import org.lflang.lf.Input; import org.lflang.lf.Instantiation; +import org.lflang.lf.Method; import org.lflang.lf.Output; import org.lflang.lf.Parameter; import org.lflang.lf.ParameterReference; @@ -115,10 +115,7 @@ public FederateInstance( * The position within a bank of reactors for this federate. This is 0 if the instantiation is not * a bank of reactors. */ - public int bankIndex = 0; - - /** A list of outputs that can be triggered directly or indirectly by physical actions. */ - public Set outputsConnectedToPhysicalActions = new LinkedHashSet<>(); + public int bankIndex; /** The host, if specified using the 'at' keyword. */ public String host = "localhost"; @@ -140,9 +137,6 @@ public Instantiation getInstantiation() { */ public Map> dependsOn = new LinkedHashMap<>(); - /** The directory, if specified using the 'at' keyword. */ - public String dir = null; - /** The port, if specified using the 'at' keyword. */ public int port = 0; @@ -157,7 +151,7 @@ public Instantiation getInstantiation() { public String user = null; /** The integer ID of this federate. */ - public int id = 0; + public int id; /** * The name of this federate instance. This will be the instantiation name, possibly appended with @@ -220,67 +214,54 @@ public Instantiation getInstantiation() { /** Keep a unique list of enabled serializers */ public HashSet enabledSerializers = new HashSet<>(); - /** - * Return true if the specified EObject should be included in the code generated for this - * federate. - * - * @param object An {@code EObject} - * @return True if this federate contains the EObject. - */ - public boolean contains(EObject object) { - if (object instanceof Action) { - return contains((Action) object); - } else if (object instanceof Reaction) { - return contains((Reaction) object); - } else if (object instanceof Timer) { - return contains((Timer) object); - } else if (object instanceof ReactorDecl) { - return contains(this.instantiation, (ReactorDecl) object); - } else if (object instanceof Import) { - return contains((Import) object); - } else if (object instanceof Parameter) { - return contains((Parameter) object); - } else if (object instanceof StateVar) { - return true; // FIXME: Should we disallow state vars at the top level? - } - throw new UnsupportedOperationException( - "EObject class " + object.eClass().getName() + " not supported."); + public boolean references(Method method) { + // FIXME + return true; + } + + public boolean references(StateVar var) { + return true; + } + + public boolean references(ReactorDecl declaration) { + return references(this.instantiation, declaration); } /** - * Return true if the specified reactor belongs to this federate. + * Return {@code true} if the class declaration of the given {@code instantiation} references the + * {@code reactor}, either directly or indirectly (e.g., via a superclass or a type parameter). * - * @param instantiation The instantiation to look inside - * @param reactor The reactor declaration to find + * @param instantiation The instantiation the class of which may refer to the reactor declaration. + * @param declaration The potentially referenced reactor declaration. */ - private boolean contains(Instantiation instantiation, ReactorDecl reactor) { - if (instantiation.getReactorClass().equals(ASTUtils.toDefinition(reactor))) { + private boolean references(Instantiation instantiation, ReactorDecl declaration) { + if (instantiation.getReactorClass().equals(ASTUtils.toDefinition(declaration))) { return true; } if (instantiation.getReactorClass() instanceof Reactor reactorDef) { // Check if the reactor is instantiated for (Instantiation child : reactorDef.getInstantiations()) { - if (contains(child, reactor)) { + if (references(child, declaration)) { return true; } } // Check if the reactor is a super class for (var parent : reactorDef.getSuperClasses()) { - if (reactor instanceof Reactor r) { + if (declaration instanceof Reactor r) { if (r.equals(parent)) { return true; } // Check if there are instantiations of the reactor in a super class if (parent instanceof Reactor p) { for (var inst : p.getInstantiations()) { - if (contains(inst, reactor)) { + if (references(inst, declaration)) { return true; } } } } - if (reactor instanceof ImportedReactor i) { + if (declaration instanceof ImportedReactor i) { if (i.getReactorClass().equals(parent)) { return true; } @@ -291,13 +272,13 @@ private boolean contains(Instantiation instantiation, ReactorDecl reactor) { } /** - * Return true if the specified import should be included in the code generated for this federate. + * Return {@code true} if this instance references the given import. * - * @param imp The import + * @param imp The import that may be referenced. */ - private boolean contains(Import imp) { + public boolean references(Import imp) { for (ImportedReactor reactor : imp.getReactorClasses()) { - if (contains(reactor)) { + if (this.references(reactor)) { return true; } } @@ -305,12 +286,11 @@ private boolean contains(Import imp) { } /** - * Return true if the specified parameter should be included in the code generated for this - * federate. + * Return {@code true} if this instance references the given parameter. * * @param param The parameter */ - private boolean contains(Parameter param) { + public boolean references(Parameter param) { boolean returnValue = false; // Check if param is referenced in this federate's instantiation returnValue = @@ -327,27 +307,29 @@ private boolean contains(Parameter param) { var topLevelUserDefinedReactions = ((Reactor) instantiation.eContainer()) .getReactions().stream() - .filter(r -> !networkReactions.contains(r) && contains(r)) + .filter(r -> !networkReactions.contains(r) && references(r)) .collect(Collectors.toCollection(ArrayList::new)); returnValue |= !topLevelUserDefinedReactions.isEmpty(); return returnValue; } /** - * Return true if the specified action should be included in the code generated for this federate. - * This means that either the action is used as a trigger, a source, or an effect in a top-level - * reaction that belongs to this federate. This returns true if the program is not federated. + * Return {@code true} if this instance references the given action. + * + *

This means that either the action is used as a trigger, a source, or an effect in a + * top-level reaction that belongs to this federate. This returns true if the program is not + * federated. * * @param action The action * @return True if this federate contains the action. */ - private boolean contains(Action action) { + public boolean references(Action action) { Reactor reactor = ASTUtils.getEnclosingReactor(action); // If the action is used as a trigger, a source, or an effect for a top-level reaction // that belongs to this federate, then generate it. for (Reaction react : ASTUtils.allReactions(reactor)) { - if (contains(react)) { + if (references(react)) { // Look in triggers for (TriggerRef trigger : convertToEmptyListIfNull(react.getTriggers())) { if (trigger instanceof VarRef triggerAsVarRef) { @@ -385,7 +367,7 @@ private boolean contains(Action action) { * * @param reaction The reaction. */ - private boolean contains(Reaction reaction) { + public boolean references(Reaction reaction) { Reactor reactor = ASTUtils.getEnclosingReactor(reaction); assert reactor != null; @@ -419,13 +401,13 @@ private boolean contains(Reaction reaction) { * * @return True if this federate contains the action in the specified reactor */ - private boolean contains(Timer timer) { + public boolean references(Timer timer) { Reactor reactor = ASTUtils.getEnclosingReactor(timer); // If the action is used as a trigger, a source, or an effect for a top-level reaction // that belongs to this federate, then generate it. for (Reaction r : ASTUtils.allReactions(reactor)) { - if (contains(r)) { + if (references(r)) { // Look in triggers for (TriggerRef trigger : convertToEmptyListIfNull(r.getTriggers())) { if (trigger instanceof VarRef triggerAsVarRef) { @@ -452,7 +434,7 @@ private boolean contains(Timer timer) { * @param instance The reactor instance. * @return True if this federate contains the reactor instance */ - public boolean contains(ReactorInstance instance) { + public boolean references(ReactorInstance instance) { if (instance.getParent() == null) { return true; // Top-level reactor } From 266c1155f5d199057bad445394c476601482b123 Mon Sep 17 00:00:00 2001 From: Marten Lohstroh Date: Fri, 7 Jul 2023 23:39:17 -0700 Subject: [PATCH 07/10] Cleanups --- .../federated/generator/FedASTUtils.java | 2 +- .../federated/generator/FedImportEmitter.java | 4 +- .../federated/generator/FedMainEmitter.java | 10 +- .../generator/FedReactorEmitter.java | 2 +- .../federated/generator/FederateInstance.java | 121 ++++++++---------- 5 files changed, 58 insertions(+), 81 deletions(-) diff --git a/core/src/main/java/org/lflang/federated/generator/FedASTUtils.java b/core/src/main/java/org/lflang/federated/generator/FedASTUtils.java index 1c791c42ae..57786fcb5b 100644 --- a/core/src/main/java/org/lflang/federated/generator/FedASTUtils.java +++ b/core/src/main/java/org/lflang/federated/generator/FedASTUtils.java @@ -441,7 +441,7 @@ private static Set findUpstreamPortsInFederate( Set reactionVisited) { Set toReturn = new HashSet<>(); if (port == null) return toReturn; - else if (federate.references(port.getParent())) { + else if (federate.inherits(port.getParent())) { // Reached the requested federate toReturn.add(port); visitedPorts.add(port); diff --git a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java index bde700dbcf..ba2e88925c 100644 --- a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java +++ b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java @@ -23,7 +23,7 @@ public class FedImportEmitter { String generateImports(FederateInstance federate, FedFileConfig fileConfig) { var imports = ((Model) federate.instantiation.eContainer().eContainer()) - .getImports().stream().filter(federate::references).toList(); + .getImports().stream().filter(federate::inherits).toList(); // Transform the URIs imports.stream() @@ -46,7 +46,7 @@ String generateImports(FederateInstance federate, FedFileConfig fileConfig) { var new_import = EcoreUtil.copy(i); new_import .getReactorClasses() - .removeIf(importedReactor -> !federate.references(importedReactor)); + .removeIf(importedReactor -> !federate.inherits(importedReactor)); return new_import; }) .map(FormattingUtil.renderer(federate.targetConfig.target)) diff --git a/core/src/main/java/org/lflang/federated/generator/FedMainEmitter.java b/core/src/main/java/org/lflang/federated/generator/FedMainEmitter.java index d0638ccf38..fbabaab74c 100644 --- a/core/src/main/java/org/lflang/federated/generator/FedMainEmitter.java +++ b/core/src/main/java/org/lflang/federated/generator/FedMainEmitter.java @@ -37,23 +37,21 @@ String generateMainReactor( "\n", renderer.apply(federate.instantiation), ASTUtils.allStateVars(originalMainReactor).stream() - .filter(federate::references) .map(renderer) .collect(Collectors.joining("\n")), ASTUtils.allActions(originalMainReactor).stream() - .filter(federate::references) + .filter(federate::inherits) .map(renderer) .collect(Collectors.joining("\n")), ASTUtils.allTimers(originalMainReactor).stream() - .filter(federate::references) + .filter(federate::inherits) .map(renderer) .collect(Collectors.joining("\n")), ASTUtils.allMethods(originalMainReactor).stream() - .filter(federate::references) .map(renderer) .collect(Collectors.joining("\n")), ASTUtils.allReactions(originalMainReactor).stream() - .filter(federate::references) + .filter(federate::inherits) .map(renderer) .collect(Collectors.joining("\n"))) .indent(4) @@ -72,7 +70,7 @@ private CharSequence generateMainSignature( FederateInstance federate, Reactor originalMainReactor, Function renderer) { var paramList = ASTUtils.allParameters(originalMainReactor).stream() - .filter(federate::references) + .filter(federate::inherits) .map(renderer) .collect(Collectors.joining(",", "(", ")")); // Empty "()" is currently not allowed by the syntax diff --git a/core/src/main/java/org/lflang/federated/generator/FedReactorEmitter.java b/core/src/main/java/org/lflang/federated/generator/FedReactorEmitter.java index bb33f6e624..552074f5a3 100644 --- a/core/src/main/java/org/lflang/federated/generator/FedReactorEmitter.java +++ b/core/src/main/java/org/lflang/federated/generator/FedReactorEmitter.java @@ -15,7 +15,7 @@ public FedReactorEmitter() {} String generateReactorDefinitions(FederateInstance federate) { return ((Model) federate.instantiation.eContainer().eContainer()) .getReactors().stream() - .filter(federate::references) + .filter(federate::inherits) .map(FormattingUtil.renderer(federate.targetConfig.target)) .collect(Collectors.joining("\n")); } diff --git a/core/src/main/java/org/lflang/federated/generator/FederateInstance.java b/core/src/main/java/org/lflang/federated/generator/FederateInstance.java index f9cf4bd3ad..b92c5e2ee1 100644 --- a/core/src/main/java/org/lflang/federated/generator/FederateInstance.java +++ b/core/src/main/java/org/lflang/federated/generator/FederateInstance.java @@ -52,23 +52,20 @@ import org.lflang.lf.ImportedReactor; import org.lflang.lf.Input; import org.lflang.lf.Instantiation; -import org.lflang.lf.Method; import org.lflang.lf.Output; import org.lflang.lf.Parameter; import org.lflang.lf.ParameterReference; import org.lflang.lf.Reaction; import org.lflang.lf.Reactor; import org.lflang.lf.ReactorDecl; -import org.lflang.lf.StateVar; import org.lflang.lf.Timer; import org.lflang.lf.TriggerRef; import org.lflang.lf.VarRef; import org.lflang.lf.Variable; /** - * Instance of a federate, or marker that no federation has been defined (if isSingleton() returns - * true) FIXME: this comment makes no sense. Every top-level reactor (contained directly by the main - * reactor) is a federate, so there will be one instance of this class for each top-level reactor. + * Class that represents an instance of a federate, i.e., a reactor that is instantiated at the top + * level of a federated reactor. * * @author Edward A. Lee * @author Soroush Bateni @@ -76,14 +73,12 @@ public class FederateInstance { /** - * Construct a new instance with the specified instantiation of of a top-level reactor. The - * federate will be given the specified integer ID. + * Construct a new federate instance on the basis of an instantiation in the federated reactor. * - * @param instantiation The instantiation of a top-level reactor, or null if no federation has - * been defined. - * @param id The federate ID. - * @param bankIndex If instantiation.widthSpec !== null, this gives the bank position. - * @param messageReporter The error reporter + * @param instantiation The AST node of the instantiation. + * @param id An identifier. + * @param bankIndex If {@code instantiation.widthSpec !== null}, this gives the bank position. + * @param messageReporter An object for reporting messages to the user. */ public FederateInstance( Instantiation instantiation, @@ -97,20 +92,15 @@ public FederateInstance( this.messageReporter = messageReporter; this.targetConfig = targetConfig; - if (instantiation != null) { - // If the instantiation is in a bank, then we have to append - // the bank index to the name. - if (instantiation.getWidthSpec() != null) { - this.name = "federate__" + instantiation.getName() + "__" + bankIndex; - } else { - this.name = "federate__" + instantiation.getName(); - } + // If the instantiation is in a bank, then we have to append + // the bank index to the name. + if (instantiation.getWidthSpec() != null) { + this.name = "federate__" + instantiation.getName() + "__" + bankIndex; + } else { + this.name = "federate__" + instantiation.getName(); } } - ///////////////////////////////////////////// - //// Public Fields - /** * The position within a bank of reactors for this federate. This is 0 if the instantiation is not * a bank of reactors. @@ -141,9 +131,9 @@ public Instantiation getInstantiation() { public int port = 0; /** - * Map from the federates that this federate sends messages to to the delays on connections to - * that federate. The delay set may may include null, meaning that there is a connection from the - * federate instance that has no delay. + * Map from the federates that this federate sends messages to the delays on connections to that + * federate. The delay set may include null, meaning that there is a connection from the federate + * instance that has no delay. */ public Map> sendsTo = new LinkedHashMap<>(); @@ -158,7 +148,7 @@ public Instantiation getInstantiation() { * "__n", where n is the bank position of this instance if the instantiation is of a bank of * reactors. */ - public String name = "Unnamed"; + public String name; /** * List of networkMessage actions. Each of these handles a message received from another federate @@ -214,16 +204,18 @@ public Instantiation getInstantiation() { /** Keep a unique list of enabled serializers */ public HashSet enabledSerializers = new HashSet<>(); - public boolean references(Method method) { - // FIXME - return true; - } + /** Cached result of analysis of which reactions to exclude from main. */ + private Set excludeReactions = null; - public boolean references(StateVar var) { - return true; - } + /** An error reporter */ + private final MessageReporter messageReporter; - public boolean references(ReactorDecl declaration) { + /** + * Return {@code true} if federate instance inherits the given reactor declaration. + * + * @param declaration The reactor declaration to inherit. + */ + public boolean inherits(ReactorDecl declaration) { return references(this.instantiation, declaration); } @@ -272,13 +264,13 @@ private boolean references(Instantiation instantiation, ReactorDecl declaration) } /** - * Return {@code true} if this instance references the given import. + * Return {@code true} if this federate inherits the given import. * - * @param imp The import that may be referenced. + * @param imp The import to inherit. */ - public boolean references(Import imp) { + public boolean inherits(Import imp) { for (ImportedReactor reactor : imp.getReactorClasses()) { - if (this.references(reactor)) { + if (this.inherits(reactor)) { return true; } } @@ -286,14 +278,13 @@ public boolean references(Import imp) { } /** - * Return {@code true} if this instance references the given parameter. + * Return {@code true} if this federate inherits the given parameter. * - * @param param The parameter + * @param param The parameter to inherit. */ - public boolean references(Parameter param) { - boolean returnValue = false; + public boolean inherits(Parameter param) { // Check if param is referenced in this federate's instantiation - returnValue = + var returnValue = instantiation.getParameters().stream() .anyMatch( assignment -> @@ -307,29 +298,28 @@ public boolean references(Parameter param) { var topLevelUserDefinedReactions = ((Reactor) instantiation.eContainer()) .getReactions().stream() - .filter(r -> !networkReactions.contains(r) && references(r)) + .filter(r -> !networkReactions.contains(r) && inherits(r)) .collect(Collectors.toCollection(ArrayList::new)); returnValue |= !topLevelUserDefinedReactions.isEmpty(); return returnValue; } /** - * Return {@code true} if this instance references the given action. + * Return {@code true} if this federate inherits the given action. * *

This means that either the action is used as a trigger, a source, or an effect in a * top-level reaction that belongs to this federate. This returns true if the program is not * federated. * - * @param action The action - * @return True if this federate contains the action. + * @param action The action to inherit. */ - public boolean references(Action action) { + public boolean inherits(Action action) { Reactor reactor = ASTUtils.getEnclosingReactor(action); // If the action is used as a trigger, a source, or an effect for a top-level reaction // that belongs to this federate, then generate it. for (Reaction react : ASTUtils.allReactions(reactor)) { - if (references(react)) { + if (inherits(react)) { // Look in triggers for (TriggerRef trigger : convertToEmptyListIfNull(react.getTriggers())) { if (trigger instanceof VarRef triggerAsVarRef) { @@ -365,9 +355,9 @@ public boolean references(Action action) { * other federates. It should only be called on reactions that are either at the top level or * within this federate. For this reason, for any reaction not at the top level, it returns true. * - * @param reaction The reaction. + * @param reaction The reaction to inherit. */ - public boolean references(Reaction reaction) { + public boolean inherits(Reaction reaction) { Reactor reactor = ASTUtils.getEnclosingReactor(reaction); assert reactor != null; @@ -395,19 +385,18 @@ public boolean references(Reaction reaction) { } /** - * Return true if the specified timer should be included in the code generated for the federate. - * This means that the timer is used as a trigger in a top-level reaction that belongs to this - * federate. This also returns true if the program is not federated. + * Return {@code true} if this federate inherits the given timer. * - * @return True if this federate contains the action in the specified reactor + *

This means that the timer is used as a trigger in a top-level reaction that is inherited by + * this federate. */ - public boolean references(Timer timer) { + public boolean inherits(Timer timer) { Reactor reactor = ASTUtils.getEnclosingReactor(timer); // If the action is used as a trigger, a source, or an effect for a top-level reaction // that belongs to this federate, then generate it. for (Reaction r : ASTUtils.allReactions(reactor)) { - if (references(r)) { + if (inherits(r)) { // Look in triggers for (TriggerRef trigger : convertToEmptyListIfNull(r.getTriggers())) { if (trigger instanceof VarRef triggerAsVarRef) { @@ -418,7 +407,6 @@ public boolean references(Timer timer) { } } } - return false; } @@ -426,7 +414,7 @@ public boolean references(Timer timer) { * Return true if the specified reactor instance or any parent reactor instance is contained by * this federate. If the specified instance is the top-level reactor, return true (the top-level * reactor belongs to all federates). If this federate instance is a singleton, then return true - * if the instance is non null. + * if the instance is non-null. * *

NOTE: If the instance is bank within the top level, then this returns true even though only * one of the bank members is in the federate. @@ -434,7 +422,7 @@ public boolean references(Timer timer) { * @param instance The reactor instance. * @return True if this federate contains the reactor instance */ - public boolean references(ReactorInstance instance) { + public boolean inherits(ReactorInstance instance) { if (instance.getParent() == null) { return true; // Top-level reactor } @@ -456,7 +444,7 @@ public boolean references(ReactorInstance instance) { * @param federatedReactor The top-level federated reactor */ private void indexExcludedTopLevelReactions(Reactor federatedReactor) { - boolean inFederate = false; + boolean inFederate; if (excludeReactions != null) { throw new IllegalStateException( "The index for excluded reactions at the top level is already built."); @@ -564,15 +552,6 @@ public String toString() { + ((instantiation != null) ? instantiation.getName() : "no name"); } - ///////////////////////////////////////////// - //// Private Fields - - /** Cached result of analysis of which reactions to exclude from main. */ - private Set excludeReactions = null; - - /** An error reporter */ - private final MessageReporter messageReporter; - /** * Find the nearest (shortest) path to a physical action trigger from this 'reaction' in terms of * minimum delay. From 0766b7a829c5404cdb758366020feb21f495163e Mon Sep 17 00:00:00 2001 From: Marten Lohstroh Date: Fri, 7 Jul 2023 23:47:06 -0700 Subject: [PATCH 08/10] Add comments --- test/C/src/federated/InheritanceFederated.lf | 3 +++ test/C/src/federated/InheritanceFederatedImport.lf | 2 ++ 2 files changed, 5 insertions(+) diff --git a/test/C/src/federated/InheritanceFederated.lf b/test/C/src/federated/InheritanceFederated.lf index 7b5b0ca644..70f429dbc8 100644 --- a/test/C/src/federated/InheritanceFederated.lf +++ b/test/C/src/federated/InheritanceFederated.lf @@ -1,3 +1,6 @@ +// Test for inheritance in a federated program. +// Compilation without errors is success. +// Based on https://github.com/lf-lang/lingua-franca/issues/1733. target C { timeout: 1 ms } diff --git a/test/C/src/federated/InheritanceFederatedImport.lf b/test/C/src/federated/InheritanceFederatedImport.lf index f06356debd..0918e6809b 100644 --- a/test/C/src/federated/InheritanceFederatedImport.lf +++ b/test/C/src/federated/InheritanceFederatedImport.lf @@ -1,3 +1,5 @@ +// Test for inheritance in a federated program where the superclass is imported from a different file. +// Compilation without errors is success. target C { timeout: 1 ms } From 13f84de1a77c035bc243a8bf3b660aaa66d267a6 Mon Sep 17 00:00:00 2001 From: Marten Lohstroh Date: Sat, 8 Jul 2023 13:36:19 -0700 Subject: [PATCH 09/10] Clean up terminology --- .../main/java/org/lflang/ast/ASTUtils.java | 10 +++ .../federated/generator/FedASTUtils.java | 2 +- .../federated/generator/FedImportEmitter.java | 4 +- .../federated/generator/FedMainEmitter.java | 8 +- .../generator/FedReactorEmitter.java | 2 +- .../federated/generator/FederateInstance.java | 89 ++++++++----------- 6 files changed, 54 insertions(+), 61 deletions(-) diff --git a/core/src/main/java/org/lflang/ast/ASTUtils.java b/core/src/main/java/org/lflang/ast/ASTUtils.java index e5d0da81ac..3484dbfe18 100644 --- a/core/src/main/java/org/lflang/ast/ASTUtils.java +++ b/core/src/main/java/org/lflang/ast/ASTUtils.java @@ -63,6 +63,7 @@ import org.lflang.TimeValue; import org.lflang.generator.CodeMap; import org.lflang.generator.InvalidSourceException; +import org.lflang.generator.NamedInstance; import org.lflang.generator.ReactorInstance; import org.lflang.lf.Action; import org.lflang.lf.Assignment; @@ -1662,6 +1663,15 @@ public static boolean isInCode(INode node) { && pri.getName().equals("Body"); } + /** + * Return {@code true} if the given instance is top-level, i.e., its parent is {@code null}. + * + * @param instance The instance to check. + */ + public static boolean isTopLevel(NamedInstance instance) { + return instance.getParent() == null; + } + /** Return true if the given node starts on the same line as the given other node. */ public static Predicate sameLine(ICompositeNode compNode) { return other -> { diff --git a/core/src/main/java/org/lflang/federated/generator/FedASTUtils.java b/core/src/main/java/org/lflang/federated/generator/FedASTUtils.java index 57786fcb5b..3b6ec8a2bb 100644 --- a/core/src/main/java/org/lflang/federated/generator/FedASTUtils.java +++ b/core/src/main/java/org/lflang/federated/generator/FedASTUtils.java @@ -441,7 +441,7 @@ private static Set findUpstreamPortsInFederate( Set reactionVisited) { Set toReturn = new HashSet<>(); if (port == null) return toReturn; - else if (federate.inherits(port.getParent())) { + else if (ASTUtils.isTopLevel(port.getParent()) || federate.includes(port.getParent())) { // Reached the requested federate toReturn.add(port); visitedPorts.add(port); diff --git a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java index ba2e88925c..bde700dbcf 100644 --- a/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java +++ b/core/src/main/java/org/lflang/federated/generator/FedImportEmitter.java @@ -23,7 +23,7 @@ public class FedImportEmitter { String generateImports(FederateInstance federate, FedFileConfig fileConfig) { var imports = ((Model) federate.instantiation.eContainer().eContainer()) - .getImports().stream().filter(federate::inherits).toList(); + .getImports().stream().filter(federate::references).toList(); // Transform the URIs imports.stream() @@ -46,7 +46,7 @@ String generateImports(FederateInstance federate, FedFileConfig fileConfig) { var new_import = EcoreUtil.copy(i); new_import .getReactorClasses() - .removeIf(importedReactor -> !federate.inherits(importedReactor)); + .removeIf(importedReactor -> !federate.references(importedReactor)); return new_import; }) .map(FormattingUtil.renderer(federate.targetConfig.target)) diff --git a/core/src/main/java/org/lflang/federated/generator/FedMainEmitter.java b/core/src/main/java/org/lflang/federated/generator/FedMainEmitter.java index fbabaab74c..74c398303b 100644 --- a/core/src/main/java/org/lflang/federated/generator/FedMainEmitter.java +++ b/core/src/main/java/org/lflang/federated/generator/FedMainEmitter.java @@ -40,18 +40,18 @@ String generateMainReactor( .map(renderer) .collect(Collectors.joining("\n")), ASTUtils.allActions(originalMainReactor).stream() - .filter(federate::inherits) + .filter(federate::includes) .map(renderer) .collect(Collectors.joining("\n")), ASTUtils.allTimers(originalMainReactor).stream() - .filter(federate::inherits) + .filter(federate::includes) .map(renderer) .collect(Collectors.joining("\n")), ASTUtils.allMethods(originalMainReactor).stream() .map(renderer) .collect(Collectors.joining("\n")), ASTUtils.allReactions(originalMainReactor).stream() - .filter(federate::inherits) + .filter(federate::includes) .map(renderer) .collect(Collectors.joining("\n"))) .indent(4) @@ -70,7 +70,7 @@ private CharSequence generateMainSignature( FederateInstance federate, Reactor originalMainReactor, Function renderer) { var paramList = ASTUtils.allParameters(originalMainReactor).stream() - .filter(federate::inherits) + .filter(federate::references) .map(renderer) .collect(Collectors.joining(",", "(", ")")); // Empty "()" is currently not allowed by the syntax diff --git a/core/src/main/java/org/lflang/federated/generator/FedReactorEmitter.java b/core/src/main/java/org/lflang/federated/generator/FedReactorEmitter.java index 552074f5a3..bb33f6e624 100644 --- a/core/src/main/java/org/lflang/federated/generator/FedReactorEmitter.java +++ b/core/src/main/java/org/lflang/federated/generator/FedReactorEmitter.java @@ -15,7 +15,7 @@ public FedReactorEmitter() {} String generateReactorDefinitions(FederateInstance federate) { return ((Model) federate.instantiation.eContainer().eContainer()) .getReactors().stream() - .filter(federate::inherits) + .filter(federate::references) .map(FormattingUtil.renderer(federate.targetConfig.target)) .collect(Collectors.joining("\n")); } diff --git a/core/src/main/java/org/lflang/federated/generator/FederateInstance.java b/core/src/main/java/org/lflang/federated/generator/FederateInstance.java index b92c5e2ee1..2626a4898f 100644 --- a/core/src/main/java/org/lflang/federated/generator/FederateInstance.java +++ b/core/src/main/java/org/lflang/federated/generator/FederateInstance.java @@ -211,11 +211,12 @@ public Instantiation getInstantiation() { private final MessageReporter messageReporter; /** - * Return {@code true} if federate instance inherits the given reactor declaration. + * Return {@code true} if the class declaration of the given {@code instantiation} references the + * {@code reactor}, either directly or indirectly (e.g., via a superclass or a type parameter). * - * @param declaration The reactor declaration to inherit. + * @param declaration The reactor declaration to check if it is referenced. */ - public boolean inherits(ReactorDecl declaration) { + public boolean references(ReactorDecl declaration) { return references(this.instantiation, declaration); } @@ -224,7 +225,7 @@ public boolean inherits(ReactorDecl declaration) { * {@code reactor}, either directly or indirectly (e.g., via a superclass or a type parameter). * * @param instantiation The instantiation the class of which may refer to the reactor declaration. - * @param declaration The potentially referenced reactor declaration. + * @param declaration The reactor declaration to check if it is referenced. */ private boolean references(Instantiation instantiation, ReactorDecl declaration) { if (instantiation.getReactorClass().equals(ASTUtils.toDefinition(declaration))) { @@ -264,13 +265,13 @@ private boolean references(Instantiation instantiation, ReactorDecl declaration) } /** - * Return {@code true} if this federate inherits the given import. + * Return {@code true} if this federate references the given import. * - * @param imp The import to inherit. + * @param imp The import to check if it is referenced. */ - public boolean inherits(Import imp) { + public boolean references(Import imp) { for (ImportedReactor reactor : imp.getReactorClasses()) { - if (this.inherits(reactor)) { + if (this.references(reactor)) { return true; } } @@ -278,11 +279,11 @@ public boolean inherits(Import imp) { } /** - * Return {@code true} if this federate inherits the given parameter. + * Return {@code true} if this federate references the given parameter. * - * @param param The parameter to inherit. + * @param param The parameter to check if it is referenced. */ - public boolean inherits(Parameter param) { + public boolean references(Parameter param) { // Check if param is referenced in this federate's instantiation var returnValue = instantiation.getParameters().stream() @@ -298,28 +299,27 @@ public boolean inherits(Parameter param) { var topLevelUserDefinedReactions = ((Reactor) instantiation.eContainer()) .getReactions().stream() - .filter(r -> !networkReactions.contains(r) && inherits(r)) + .filter(r -> !networkReactions.contains(r) && includes(r)) .collect(Collectors.toCollection(ArrayList::new)); returnValue |= !topLevelUserDefinedReactions.isEmpty(); return returnValue; } /** - * Return {@code true} if this federate inherits the given action. + * Return {@code true} if this federate includes the given action from the top-level of the + * federation, which is necessary when the federate adopts a reaction that uses the given action. * - *

This means that either the action is used as a trigger, a source, or an effect in a - * top-level reaction that belongs to this federate. This returns true if the program is not - * federated. + *

Specifically, this means that either the action is used as a trigger, a source, or an effect + * in a top-level reaction that is adopted by this federate. * - * @param action The action to inherit. + * @param action The action to check if it is to be included. */ - public boolean inherits(Action action) { + public boolean includes(Action action) { Reactor reactor = ASTUtils.getEnclosingReactor(action); - // If the action is used as a trigger, a source, or an effect for a top-level reaction // that belongs to this federate, then generate it. for (Reaction react : ASTUtils.allReactions(reactor)) { - if (inherits(react)) { + if (includes(react)) { // Look in triggers for (TriggerRef trigger : convertToEmptyListIfNull(react.getTriggers())) { if (trigger instanceof VarRef triggerAsVarRef) { @@ -347,7 +347,7 @@ public boolean inherits(Action action) { } /** - * Return true if the specified reaction should be included in the code generated for this + * Return {@code true} if the specified reaction should be included in the code generated for this * federate at the top-level. This means that if the reaction is triggered by or sends data to a * port of a contained reactor, then that reaction is in the federate. Otherwise, return false. * @@ -355,9 +355,9 @@ public boolean inherits(Action action) { * other federates. It should only be called on reactions that are either at the top level or * within this federate. For this reason, for any reaction not at the top level, it returns true. * - * @param reaction The reaction to inherit. + * @param reaction The reaction to check if it is to be included. */ - public boolean inherits(Reaction reaction) { + public boolean includes(Reaction reaction) { Reactor reactor = ASTUtils.getEnclosingReactor(reaction); assert reactor != null; @@ -385,18 +385,19 @@ public boolean inherits(Reaction reaction) { } /** - * Return {@code true} if this federate inherits the given timer. + * Return {@code true} if this federate includes the given timer from the top-level of the + * federation, which is necessary when the federate adopts a reaction that uses the given timer. * - *

This means that the timer is used as a trigger in a top-level reaction that is inherited by - * this federate. + *

Specifically, this means that either the timer is used as a trigger in a top-level reaction + * that is included by this federate. + * + * @param timer The action to check if it is to be included. */ - public boolean inherits(Timer timer) { + public boolean includes(Timer timer) { Reactor reactor = ASTUtils.getEnclosingReactor(timer); - // If the action is used as a trigger, a source, or an effect for a top-level reaction - // that belongs to this federate, then generate it. for (Reaction r : ASTUtils.allReactions(reactor)) { - if (inherits(r)) { + if (includes(r)) { // Look in triggers for (TriggerRef trigger : convertToEmptyListIfNull(r.getTriggers())) { if (trigger instanceof VarRef triggerAsVarRef) { @@ -411,21 +412,14 @@ public boolean inherits(Timer timer) { } /** - * Return true if the specified reactor instance or any parent reactor instance is contained by - * this federate. If the specified instance is the top-level reactor, return true (the top-level - * reactor belongs to all federates). If this federate instance is a singleton, then return true - * if the instance is non-null. + * Return {@code true} if this federate instance includes the given instance. * - *

NOTE: If the instance is bank within the top level, then this returns true even though only - * one of the bank members is in the federate. + *

NOTE: If the instance is bank within the top level, then this returns {@code true} even + * though only one of the bank members is included in the federate. * - * @param instance The reactor instance. - * @return True if this federate contains the reactor instance + * @param instance The reactor instance to check if it is to be included. */ - public boolean inherits(ReactorInstance instance) { - if (instance.getParent() == null) { - return true; // Top-level reactor - } + public boolean includes(ReactorInstance instance) { // Start with this instance, then check its parents. ReactorInstance i = instance; while (i != null) { @@ -533,17 +527,6 @@ public LinkedHashMap findOutputsConnectedToPhysicalActions( return physicalActionToOutputMinDelay; } - /** - * Return a list of federates that are upstream of this federate and have a zero-delay (direct) - * connection to this federate. - */ - public List getZeroDelayImmediateUpstreamFederates() { - return this.dependsOn.entrySet().stream() - .filter(e -> e.getValue().contains(null)) - .map(Map.Entry::getKey) - .toList(); - } - @Override public String toString() { return "Federate " From 91f95ab1c2f8abccbd91922cfa99655b1a6350f1 Mon Sep 17 00:00:00 2001 From: Marten Lohstroh Date: Sat, 8 Jul 2023 16:05:36 -0700 Subject: [PATCH 10/10] Use 'include' instead of 'adopt' in comments. --- .../org/lflang/federated/generator/FederateInstance.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/lflang/federated/generator/FederateInstance.java b/core/src/main/java/org/lflang/federated/generator/FederateInstance.java index 2626a4898f..dfefff5ae0 100644 --- a/core/src/main/java/org/lflang/federated/generator/FederateInstance.java +++ b/core/src/main/java/org/lflang/federated/generator/FederateInstance.java @@ -307,10 +307,11 @@ public boolean references(Parameter param) { /** * Return {@code true} if this federate includes the given action from the top-level of the - * federation, which is necessary when the federate adopts a reaction that uses the given action. + * federation, which is necessary when the federate includes a reaction that references the given + * action. * *

Specifically, this means that either the action is used as a trigger, a source, or an effect - * in a top-level reaction that is adopted by this federate. + * in a top-level reaction that is included by this federate. * * @param action The action to check if it is to be included. */ @@ -386,7 +387,7 @@ public boolean includes(Reaction reaction) { /** * Return {@code true} if this federate includes the given timer from the top-level of the - * federation, which is necessary when the federate adopts a reaction that uses the given timer. + * federation, which is necessary when the federate includes a reaction that uses the given timer. * *

Specifically, this means that either the timer is used as a trigger in a top-level reaction * that is included by this federate.