From c29595b321f943982d6d4b2f94d7bf0bf0df1b64 Mon Sep 17 00:00:00 2001 From: Omer Majeed Date: Tue, 19 Sep 2023 02:49:38 +0500 Subject: [PATCH 1/8] parent_bank_index and parent params made available when initializing nested child reactors --- .../org/lflang/generator/TargetTypes.java | 14 ++++++++ .../org/lflang/generator/c/CGenerator.java | 11 +++++++ .../generator/c/CParameterGenerator.java | 32 ++++++++++++++++++- 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/lflang/generator/TargetTypes.java b/core/src/main/java/org/lflang/generator/TargetTypes.java index 65552edc59..f48dacb93d 100644 --- a/core/src/main/java/org/lflang/generator/TargetTypes.java +++ b/core/src/main/java/org/lflang/generator/TargetTypes.java @@ -216,6 +216,20 @@ default String getTargetInitializer(Initializer init, Type type) { } } + /** + * Returns true if given initializer is a code expression otherwise returns false + * + * @param init Initializer node (nullable) + */ + default Boolean checkForCodeExp(Initializer init) { + var single = ASTUtils.asSingleExpr(init); + if ((single != null) && (single instanceof CodeExpr)) { + return true; + } else { + return false; + } + } + /** * Returns the representation of the given expression in target code. The given type, if non-null, * may inform the code generation. diff --git a/core/src/main/java/org/lflang/generator/c/CGenerator.java b/core/src/main/java/org/lflang/generator/c/CGenerator.java index 1c277f5d29..fdb0642732 100644 --- a/core/src/main/java/org/lflang/generator/c/CGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CGenerator.java @@ -594,6 +594,8 @@ private void generateCodeFor(String lfModuleName) throws IOException { "\n", "int bank_index;", "SUPPRESS_UNUSED_WARNING(bank_index);", + "int parent_bank_index;", + "SUPPRESS_UNUSED_WARNING(parent_bank_index);", "int watchdog_number = 0;", "SUPPRESS_UNUSED_WARNING(watchdog_number);")); // Add counters for modal initialization @@ -1680,6 +1682,7 @@ public void generateReactorInstance(ReactorInstance instance) { var fullName = instance.getFullName(); initializeTriggerObjects.pr( "// ***** Start initializing " + fullName + " of class " + reactorClass.getName()); + // Generate the instance self struct containing parameters, state variables, // and outputs (the "self" struct). initializeTriggerObjects.pr( @@ -1853,12 +1856,20 @@ private void generateModeStructure(ReactorInstance instance) { */ protected void generateParameterInitialization(ReactorInstance instance) { var selfRef = CUtil.reactorRef(instance); + ReactorInstance parent = instance.getParent(); // Set the local bank_index variable so that initializers can use it. initializeTriggerObjects.pr( "bank_index = " + CUtil.bankIndex(instance) + ";" + " SUPPRESS_UNUSED_WARNING(bank_index);"); + if (parent != null) { + initializeTriggerObjects.pr( + "parent_bank_index = " + + CUtil.bankIndex(parent) + + ";" + + " SUPPRESS_UNUSED_WARNING(parent_bank_index);"); + } for (ParameterInstance parameter : instance.parameters) { // NOTE: we now use the resolved literal value. For better efficiency, we could // store constants in a global array and refer to its elements to avoid duplicate diff --git a/core/src/main/java/org/lflang/generator/c/CParameterGenerator.java b/core/src/main/java/org/lflang/generator/c/CParameterGenerator.java index 21a4803a5f..dbd56a7ed2 100644 --- a/core/src/main/java/org/lflang/generator/c/CParameterGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CParameterGenerator.java @@ -1,8 +1,12 @@ package org.lflang.generator.c; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + import org.lflang.ast.ASTUtils; import org.lflang.generator.CodeBuilder; import org.lflang.generator.ParameterInstance; +import org.lflang.generator.ReactorInstance; import org.lflang.lf.Initializer; import org.lflang.lf.Parameter; @@ -24,10 +28,36 @@ public static String getInitializer(ParameterInstance p) { if (p.getName().equals("bank_index") && p.getOverride() == null) { return CUtil.bankIndex(p.getParent()); } + String initializer = null; CTypes ctypes = CTypes.generateParametersIn(p.getParent().getParent()); Initializer values = p.getActualValue(); - return ctypes.getTargetInitializer(values, p.getDefinition().getType()); + initializer = ctypes.getTargetInitializer(values, p.getDefinition().getType()); + + // If Initializer is a code expression + // parse for parent parameter values being used inside expressions + // Look for encapsulated inside ${ } + if (ctypes.checkForCodeExp(values)) { + ReactorInstance parent = p.getParent().getParent(); + if (parent != null) { + for (ParameterInstance parameter : parent.parameters) { + String search_param = "(\\$\\{\s*" + parameter.getName() + "\s*\\})"; + Pattern pt = Pattern.compile(search_param); + Matcher m = pt.matcher(initializer); + + if (m.find()) { + StringBuilder tmp_init = new StringBuilder(); + do { + String replacement = CUtil.reactorRef(parent) + "->" + parameter.getName(); + m.appendReplacement(tmp_init, replacement); + } while (m.find()); + m.appendTail(tmp_init); + initializer = tmp_init.toString(); + } + } + } + } + return initializer; } /** From 578f47984c58466aa83229dae2b5ec2bf7603922 Mon Sep 17 00:00:00 2001 From: Omer Majeed Date: Tue, 19 Sep 2023 17:30:15 +0500 Subject: [PATCH 2/8] removed parent_bank_index changes, parent's variable made available inside code expression is enough of a change --- .../main/java/org/lflang/generator/c/CGenerator.java | 10 ---------- .../org/lflang/generator/c/CParameterGenerator.java | 1 - 2 files changed, 11 deletions(-) diff --git a/core/src/main/java/org/lflang/generator/c/CGenerator.java b/core/src/main/java/org/lflang/generator/c/CGenerator.java index fdb0642732..cbc8504484 100644 --- a/core/src/main/java/org/lflang/generator/c/CGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CGenerator.java @@ -594,8 +594,6 @@ private void generateCodeFor(String lfModuleName) throws IOException { "\n", "int bank_index;", "SUPPRESS_UNUSED_WARNING(bank_index);", - "int parent_bank_index;", - "SUPPRESS_UNUSED_WARNING(parent_bank_index);", "int watchdog_number = 0;", "SUPPRESS_UNUSED_WARNING(watchdog_number);")); // Add counters for modal initialization @@ -1856,20 +1854,12 @@ private void generateModeStructure(ReactorInstance instance) { */ protected void generateParameterInitialization(ReactorInstance instance) { var selfRef = CUtil.reactorRef(instance); - ReactorInstance parent = instance.getParent(); // Set the local bank_index variable so that initializers can use it. initializeTriggerObjects.pr( "bank_index = " + CUtil.bankIndex(instance) + ";" + " SUPPRESS_UNUSED_WARNING(bank_index);"); - if (parent != null) { - initializeTriggerObjects.pr( - "parent_bank_index = " - + CUtil.bankIndex(parent) - + ";" - + " SUPPRESS_UNUSED_WARNING(parent_bank_index);"); - } for (ParameterInstance parameter : instance.parameters) { // NOTE: we now use the resolved literal value. For better efficiency, we could // store constants in a global array and refer to its elements to avoid duplicate diff --git a/core/src/main/java/org/lflang/generator/c/CParameterGenerator.java b/core/src/main/java/org/lflang/generator/c/CParameterGenerator.java index dbd56a7ed2..83657809d6 100644 --- a/core/src/main/java/org/lflang/generator/c/CParameterGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CParameterGenerator.java @@ -2,7 +2,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; - import org.lflang.ast.ASTUtils; import org.lflang.generator.CodeBuilder; import org.lflang.generator.ParameterInstance; From 32033ffcf8e5c967f7c6d3e7940680ffff2123b7 Mon Sep 17 00:00:00 2001 From: Omer Majeed Date: Tue, 19 Sep 2023 17:31:27 +0500 Subject: [PATCH 3/8] removed accidentally added new line --- core/src/main/java/org/lflang/generator/c/CGenerator.java | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/main/java/org/lflang/generator/c/CGenerator.java b/core/src/main/java/org/lflang/generator/c/CGenerator.java index cbc8504484..1c277f5d29 100644 --- a/core/src/main/java/org/lflang/generator/c/CGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CGenerator.java @@ -1680,7 +1680,6 @@ public void generateReactorInstance(ReactorInstance instance) { var fullName = instance.getFullName(); initializeTriggerObjects.pr( "// ***** Start initializing " + fullName + " of class " + reactorClass.getName()); - // Generate the instance self struct containing parameters, state variables, // and outputs (the "self" struct). initializeTriggerObjects.pr( From b7397496d2bc31c93400df96245b7149623dd816 Mon Sep 17 00:00:00 2001 From: Omer Majeed Date: Fri, 3 Nov 2023 21:10:50 +0500 Subject: [PATCH 4/8] expose self pointer of parent to children during initialization --- .../org/lflang/generator/TargetTypes.java | 14 --------- .../org/lflang/generator/c/CGenerator.java | 8 +++++ .../generator/c/CParameterGenerator.java | 30 +------------------ 3 files changed, 9 insertions(+), 43 deletions(-) diff --git a/core/src/main/java/org/lflang/generator/TargetTypes.java b/core/src/main/java/org/lflang/generator/TargetTypes.java index f48dacb93d..65552edc59 100644 --- a/core/src/main/java/org/lflang/generator/TargetTypes.java +++ b/core/src/main/java/org/lflang/generator/TargetTypes.java @@ -216,20 +216,6 @@ default String getTargetInitializer(Initializer init, Type type) { } } - /** - * Returns true if given initializer is a code expression otherwise returns false - * - * @param init Initializer node (nullable) - */ - default Boolean checkForCodeExp(Initializer init) { - var single = ASTUtils.asSingleExpr(init); - if ((single != null) && (single instanceof CodeExpr)) { - return true; - } else { - return false; - } - } - /** * Returns the representation of the given expression in target code. The given type, if non-null, * may inform the code generation. diff --git a/core/src/main/java/org/lflang/generator/c/CGenerator.java b/core/src/main/java/org/lflang/generator/c/CGenerator.java index 1c277f5d29..21d097d023 100644 --- a/core/src/main/java/org/lflang/generator/c/CGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CGenerator.java @@ -1725,6 +1725,14 @@ public void generateReactorInstance(ReactorInstance instance) { // Need to do this for each of the builders into which the code writes. startTimeStep.startScopedBlock(child); initializeTriggerObjects.startScopedBlock(child); + // Generate the parent self struct for children to access its params + initializeTriggerObjects.pr( + CUtil.selfType(instance) + + " *self = " + + CUtil.reactorRefName(instance) + + "[" + + CUtil.runtimeIndex(instance) + + "];"); generateReactorInstance(child); initializeTriggerObjects.endScopedBlock(); startTimeStep.endScopedBlock(); diff --git a/core/src/main/java/org/lflang/generator/c/CParameterGenerator.java b/core/src/main/java/org/lflang/generator/c/CParameterGenerator.java index 83657809d6..27fd9d6234 100644 --- a/core/src/main/java/org/lflang/generator/c/CParameterGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CParameterGenerator.java @@ -1,7 +1,5 @@ package org.lflang.generator.c; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import org.lflang.ast.ASTUtils; import org.lflang.generator.CodeBuilder; import org.lflang.generator.ParameterInstance; @@ -27,36 +25,10 @@ public static String getInitializer(ParameterInstance p) { if (p.getName().equals("bank_index") && p.getOverride() == null) { return CUtil.bankIndex(p.getParent()); } - String initializer = null; CTypes ctypes = CTypes.generateParametersIn(p.getParent().getParent()); Initializer values = p.getActualValue(); - initializer = ctypes.getTargetInitializer(values, p.getDefinition().getType()); - - // If Initializer is a code expression - // parse for parent parameter values being used inside expressions - // Look for encapsulated inside ${ } - if (ctypes.checkForCodeExp(values)) { - ReactorInstance parent = p.getParent().getParent(); - if (parent != null) { - for (ParameterInstance parameter : parent.parameters) { - String search_param = "(\\$\\{\s*" + parameter.getName() + "\s*\\})"; - Pattern pt = Pattern.compile(search_param); - Matcher m = pt.matcher(initializer); - - if (m.find()) { - StringBuilder tmp_init = new StringBuilder(); - do { - String replacement = CUtil.reactorRef(parent) + "->" + parameter.getName(); - m.appendReplacement(tmp_init, replacement); - } while (m.find()); - m.appendTail(tmp_init); - initializer = tmp_init.toString(); - } - } - } - } - return initializer; + return ctypes.getTargetInitializer(values, p.getDefinition().getType()); } /** From 3e88f680dca324abe7b546b166009a708c8851b9 Mon Sep 17 00:00:00 2001 From: Omer Majeed Date: Fri, 3 Nov 2023 21:12:39 +0500 Subject: [PATCH 5/8] remove unnecessary import --- .../main/java/org/lflang/generator/c/CParameterGenerator.java | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/main/java/org/lflang/generator/c/CParameterGenerator.java b/core/src/main/java/org/lflang/generator/c/CParameterGenerator.java index 27fd9d6234..21a4803a5f 100644 --- a/core/src/main/java/org/lflang/generator/c/CParameterGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CParameterGenerator.java @@ -3,7 +3,6 @@ import org.lflang.ast.ASTUtils; import org.lflang.generator.CodeBuilder; import org.lflang.generator.ParameterInstance; -import org.lflang.generator.ReactorInstance; import org.lflang.lf.Initializer; import org.lflang.lf.Parameter; From cdf27410d3a169b23cf5bf0a0dcee9b90b777b7d Mon Sep 17 00:00:00 2001 From: Omer Majeed Date: Fri, 3 Nov 2023 21:16:05 +0500 Subject: [PATCH 6/8] updated indentation as per exisitng norm --- core/src/main/java/org/lflang/generator/c/CGenerator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/lflang/generator/c/CGenerator.java b/core/src/main/java/org/lflang/generator/c/CGenerator.java index 21d097d023..cc3a383500 100644 --- a/core/src/main/java/org/lflang/generator/c/CGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CGenerator.java @@ -1728,8 +1728,8 @@ public void generateReactorInstance(ReactorInstance instance) { // Generate the parent self struct for children to access its params initializeTriggerObjects.pr( CUtil.selfType(instance) - + " *self = " + - CUtil.reactorRefName(instance) + + " *self = " + + CUtil.reactorRefName(instance) + "[" + CUtil.runtimeIndex(instance) + "];"); From 0893ceb1071b9d9aff234b6f24db70c22f348610 Mon Sep 17 00:00:00 2001 From: Omer Majeed Date: Sat, 4 Nov 2023 01:21:11 +0500 Subject: [PATCH 7/8] test lf code to demonstrate use of parent variables within code expression when declaring child reactors --- test/C/src/ParentParamsAccessToChildInit.lf | 24 +++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 test/C/src/ParentParamsAccessToChildInit.lf diff --git a/test/C/src/ParentParamsAccessToChildInit.lf b/test/C/src/ParentParamsAccessToChildInit.lf new file mode 100644 index 0000000000..e1f0eb4aa4 --- /dev/null +++ b/test/C/src/ParentParamsAccessToChildInit.lf @@ -0,0 +1,24 @@ +target C; +preamble {= + extern int child_ids[10]; +=} + +reactor Child (bank_index:int = 0, parent_index:int = 0, value:int = 0) { + preamble {= + int child_ids[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + =} + reaction (startup) {= + printf("Child bank_index:%d parent_index:%d value:%d\n", self->bank_index, self->parent_index, self->value); + =} +} + +reactor Parent (bank_index:int = 0, n_parents:int = 0, n_children:int = 1) { + c = new [n_children] Child (parent_index = {=self->bank_index=}, value = {=child_ids[(self->bank_index * self->n_children + bank_index) % (sizeof(child_ids) / sizeof(*child_ids))]=}) + reaction (startup) {= + printf("Parent[%d/%d] bank_index:%d\n", self->bank_index + 1, self->n_parents, self->bank_index); + =} +} + +main reactor ParentParamsAccessToChildInit (n_parents:int = 2, per_parent_n_children:int = 3) { + p = new [n_parents] Parent (n_parents = n_parents, n_children = per_parent_n_children); +} \ No newline at end of file From 7b0bd7ea3c0f942b696c9a2b0632fbfba81d80bb Mon Sep 17 00:00:00 2001 From: Omer Majeed Date: Sat, 4 Nov 2023 01:36:22 +0500 Subject: [PATCH 8/8] spotlessApply to fix the indentation --- .../org/lflang/generator/c/CGenerator.java | 14 +++---- test/C/src/ParentParamsAccessToChildInit.lf | 41 +++++++++++-------- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/core/src/main/java/org/lflang/generator/c/CGenerator.java b/core/src/main/java/org/lflang/generator/c/CGenerator.java index cc3a383500..4d77463c4f 100644 --- a/core/src/main/java/org/lflang/generator/c/CGenerator.java +++ b/core/src/main/java/org/lflang/generator/c/CGenerator.java @@ -1726,13 +1726,13 @@ public void generateReactorInstance(ReactorInstance instance) { startTimeStep.startScopedBlock(child); initializeTriggerObjects.startScopedBlock(child); // Generate the parent self struct for children to access its params - initializeTriggerObjects.pr( - CUtil.selfType(instance) - + " *self = " - + CUtil.reactorRefName(instance) - + "[" - + CUtil.runtimeIndex(instance) - + "];"); + initializeTriggerObjects.pr( + CUtil.selfType(instance) + + " *self = " + + CUtil.reactorRefName(instance) + + "[" + + CUtil.runtimeIndex(instance) + + "];"); generateReactorInstance(child); initializeTriggerObjects.endScopedBlock(); startTimeStep.endScopedBlock(); diff --git a/test/C/src/ParentParamsAccessToChildInit.lf b/test/C/src/ParentParamsAccessToChildInit.lf index e1f0eb4aa4..8325d65150 100644 --- a/test/C/src/ParentParamsAccessToChildInit.lf +++ b/test/C/src/ParentParamsAccessToChildInit.lf @@ -1,24 +1,31 @@ -target C; +target C + preamble {= - extern int child_ids[10]; + extern int child_ids[10]; =} -reactor Child (bank_index:int = 0, parent_index:int = 0, value:int = 0) { - preamble {= - int child_ids[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - =} - reaction (startup) {= - printf("Child bank_index:%d parent_index:%d value:%d\n", self->bank_index, self->parent_index, self->value); - =} +reactor Child(bank_index: int = 0, parent_index: int = 0, value: int = 0) { + preamble {= + int child_ids[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + =} + + reaction(startup) {= + printf("Child bank_index:%d parent_index:%d value:%d\n", self->bank_index, self->parent_index, self->value); + =} } -reactor Parent (bank_index:int = 0, n_parents:int = 0, n_children:int = 1) { - c = new [n_children] Child (parent_index = {=self->bank_index=}, value = {=child_ids[(self->bank_index * self->n_children + bank_index) % (sizeof(child_ids) / sizeof(*child_ids))]=}) - reaction (startup) {= - printf("Parent[%d/%d] bank_index:%d\n", self->bank_index + 1, self->n_parents, self->bank_index); - =} +reactor Parent(bank_index: int = 0, n_parents: int = 0, n_children: int = 1) { + c = new[n_children] Child( + parent_index=bank_index, + value = {= + child_ids[(self->bank_index * self->n_children + bank_index) % (sizeof(child_ids) / sizeof(*child_ids))] + =}) + + reaction(startup) {= + printf("Parent[%d/%d] bank_index:%d\n", self->bank_index + 1, self->n_parents, self->bank_index); + =} } -main reactor ParentParamsAccessToChildInit (n_parents:int = 2, per_parent_n_children:int = 3) { - p = new [n_parents] Parent (n_parents = n_parents, n_children = per_parent_n_children); -} \ No newline at end of file +main reactor ParentParamsAccessToChildInit(n_parents: int = 2, per_parent_n_children: int = 3) { + p = new[n_parents] Parent(n_parents=n_parents, n_children=per_parent_n_children) +}