From 364230e4ffcbebdf0efae18b0f12a9cd09b63c8f Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Mon, 20 Mar 2023 18:52:44 -0700 Subject: [PATCH 01/54] Start adding templates to C target. WIP. --- org.lflang/src/org/lflang/ASTUtils.java | 15 ++- .../org/lflang/generator/ReactorInstance.java | 7 ++ .../lflang/generator/c/CActionGenerator.java | 13 +-- .../org/lflang/generator/c/CGenerator.java | 105 +++++++----------- .../lflang/generator/c/CPortGenerator.java | 45 +++----- .../src/org/lflang/generator/c/CUtil.java | 10 +- .../generator/c/TypeParameterizedReactor.java | 41 +++++++ .../generator/python/PythonGenerator.java | 3 +- test/C/src/generics/Template.lf | 13 +++ 9 files changed, 145 insertions(+), 107 deletions(-) create mode 100644 org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java create mode 100644 test/C/src/generics/Template.lf diff --git a/org.lflang/src/org/lflang/ASTUtils.java b/org.lflang/src/org/lflang/ASTUtils.java index 16f3182056..ed9daf5def 100644 --- a/org.lflang/src/org/lflang/ASTUtils.java +++ b/org.lflang/src/org/lflang/ASTUtils.java @@ -379,6 +379,15 @@ public static List allInstantiations(Reactor definition) { return ASTUtils.collectElements(definition, featurePackage.getReactor_Instantiations()); } + public static List allChildInstances(Reactor definition, ErrorReporter reporter) { + return allInstantiations(definition).stream().map(it -> new ReactorInstance( + it, + null, + reporter, + 0 + )).collect(Collectors.toList()); + } + /** * Given a reactor class, return a list of all its methods, * which includes methods of base classes that it extends. @@ -448,9 +457,9 @@ public static List allModes(Reactor definition) { return ASTUtils.collectElements(definition, featurePackage.getReactor_Modes()); } - public static List recursiveChildren(ReactorInstance r) { - List ret = new ArrayList<>(); - ret.add(r.reactorDefinition); + public static List recursiveChildren(ReactorInstance r) { + List ret = new ArrayList<>(); + ret.add(r); for (var child: r.children) { ret.addAll(recursiveChildren(child)); } diff --git a/org.lflang/src/org/lflang/generator/ReactorInstance.java b/org.lflang/src/org/lflang/generator/ReactorInstance.java index a45fb1d1fb..af295818b3 100644 --- a/org.lflang/src/org/lflang/generator/ReactorInstance.java +++ b/org.lflang/src/org/lflang/generator/ReactorInstance.java @@ -42,6 +42,7 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY import org.lflang.ErrorReporter; import org.lflang.TimeValue; import org.lflang.generator.TriggerInstance.BuiltinTriggerVariable; +import org.lflang.generator.c.TypeParameterizedReactor; import org.lflang.lf.Action; import org.lflang.lf.BuiltinTrigger; import org.lflang.lf.BuiltinTriggerRef; @@ -59,10 +60,13 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY import org.lflang.lf.Reactor; import org.lflang.lf.ReactorDecl; import org.lflang.lf.Timer; +import org.lflang.lf.Type; import org.lflang.lf.VarRef; import org.lflang.lf.Variable; import org.lflang.lf.WidthSpec; +import com.google.common.collect.ImmutableMap; + /** * Representation of a compile-time instance of a reactor. @@ -159,6 +163,8 @@ public ReactorInstance(Reactor reactor, ReactorInstance parent, ErrorReporter re /** Indicator that this reactor has itself as a parent, an error condition. */ public final boolean recursive; + public final TypeParameterizedReactor tpr; + ////////////////////////////////////////////////////// //// Public methods. @@ -770,6 +776,7 @@ private ReactorInstance( this.reporter = reporter; this.reactorDeclaration = definition.getReactorClass(); this.reactorDefinition = ASTUtils.toDefinition(reactorDeclaration); + this.tpr = new TypeParameterizedReactor(definition); // check for recursive instantiation var currentParent = parent; diff --git a/org.lflang/src/org/lflang/generator/c/CActionGenerator.java b/org.lflang/src/org/lflang/generator/c/CActionGenerator.java index dee3576d03..e381ad9bae 100644 --- a/org.lflang/src/org/lflang/generator/c/CActionGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CActionGenerator.java @@ -91,19 +91,17 @@ public static String generateTokenInitializer( /** * Generate the declarations of actions in the self struct * - * @param reactor The reactor to generate declarations for - * @param decl The reactor's declaration * @param body The content of the self struct * @param constructorCode The constructor code of the reactor */ public static void generateDeclarations( - Reactor reactor, + TypeParameterizedReactor tpr, CodeBuilder body, CodeBuilder constructorCode ) { - for (Action action : ASTUtils.allActions(reactor)) { + for (Action action : ASTUtils.allActions(tpr.r())) { var actionName = action.getName(); - body.pr(action, CGenerator.variableStructType(action, reactor, false)+" _lf_"+actionName+";"); + body.pr(action, CGenerator.variableStructType(action, tpr, false)+" _lf_"+actionName+";"); // Initialize the trigger pointer in the action. constructorCode.pr(action, "self->_lf_"+actionName+".trigger = &self->_lf__"+actionName+";"); } @@ -113,7 +111,6 @@ public static void generateDeclarations( * Generate the struct type definitions for the action of the * reactor * - * @param decl The reactor declaration * @param action The action to generate the struct for * @param target The target of the code generation (C, CCpp or Python) * @param types The helper object for types related stuff @@ -121,7 +118,7 @@ public static void generateDeclarations( * @return The auxiliary struct for the port as a string */ public static String generateAuxiliaryStruct( - Reactor r, + TypeParameterizedReactor tpr, Action action, Target target, CTypes types, @@ -146,7 +143,7 @@ public static String generateAuxiliaryStruct( code.pr(valueDeclaration(action, target, types)); code.pr(federatedExtension.toString()); code.unindent(); - code.pr("} " + variableStructType(action, r, userFacing) + ";"); + code.pr("} " + variableStructType(action, tpr, userFacing) + ";"); return code.toString(); } diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index b45779b7a7..0b5602d9d9 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -43,6 +43,7 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -96,6 +97,7 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY import org.lflang.lf.Reactor; import org.lflang.lf.ReactorDecl; import org.lflang.lf.StateVar; +import org.lflang.lf.Type; import org.lflang.lf.Variable; import org.lflang.util.ArduinoUtil; import org.lflang.util.FileUtil; @@ -523,6 +525,7 @@ public void doGenerate(Resource resource, LFGeneratorContext context) { if (targetConfig.platformOptions.platform != Platform.ARDUINO) { var cmakeFile = fileConfig.getSrcGenPath() + File.separator + "CMakeLists.txt"; var sources = new HashSet<>(ASTUtils.recursiveChildren(main)).stream() + .map(ReactorInstance::getTypeParameterizedReactor) .map(CUtil::getName).map(it -> it + (CCppMode ? ".cpp" : ".c")) .collect(Collectors.toList()); sources.add(cFilename); @@ -912,9 +915,7 @@ public void copyUserFiles(TargetConfig targetConfig, FileConfig fileConfig) { } /** - * Generate code for defining all reactors that belong to the federate, - * including all the child reactors down the hierarchy. Duplicate - * Duplicates are avoided. + * Generate code for defining all instantiated reactors. * * Imported reactors' original .lf file is * incorporated in the following manner: @@ -923,29 +924,12 @@ public void copyUserFiles(TargetConfig targetConfig, FileConfig fileConfig) { * - If there are any preambles, add them to the preambles of the reactor. */ private void generateReactorDefinitions() throws IOException { - var generatedReactors = new LinkedHashSet(); + var generatedReactors = new LinkedHashSet(); if (this.main != null) { generateReactorChildren(this.main, generatedReactors); + generateReactorClass(this.main.getTypeParameterizedReactor()); } - - if (this.mainDef != null) { - generateReactorClass(ASTUtils.toDefinition(this.mainDef.getReactorClass())); - } - - if (mainDef == null) { - // Generate code for each reactor that was not instantiated in main or its children. - for (Reactor r : reactors) { - // Get the declarations for reactors that are instantiated somewhere. - // A declaration is either a reactor definition or an import statement.; - var declarations = this.instantiationGraph.getDeclarations(r); - // If the reactor has no instantiations and there is no main reactor, then - // generate code for it anyway (at a minimum, this means that the compiler is invoked - // so that reaction bodies are checked). - if (declarations.isEmpty()) { - generateReactorClass(r); - } - } - } + // do not generate code for reactors that are not instantiated } private void generateHeaders() throws IOException { @@ -975,15 +959,16 @@ private void generateHeaders() throws IOException { */ private void generateReactorChildren( ReactorInstance reactor, - LinkedHashSet generatedReactors + LinkedHashSet generatedReactors ) throws IOException { for (ReactorInstance r : reactor.children) { + var newTpr = r.tpr; if (r.reactorDeclaration != null && - !generatedReactors.contains(r.reactorDefinition)) { - generatedReactors.add(r.reactorDefinition); + !generatedReactors.contains(newTpr)) { + generatedReactors.add(newTpr); generateReactorChildren(r, generatedReactors); inspectReactorEResource(r.reactorDeclaration); - generateReactorClass(r.reactorDefinition); + generateReactorClass(newTpr); } } } @@ -1036,53 +1021,50 @@ protected void copyTargetFiles() throws IOException { * if the main reactor has reactions, these reactions * will not be generated if they are triggered by or send * data to contained reactors that are not in the federate. - * @param reactor The parsed reactor data structure. */ - private void generateReactorClass(Reactor reactor) throws IOException { + private void generateReactorClass(TypeParameterizedReactor tpr) throws IOException { // FIXME: Currently we're not reusing definitions for declarations that point to the same definition. CodeBuilder header = new CodeBuilder(); CodeBuilder src = new CodeBuilder(); - final String headerName = CUtil.getName(reactor) + ".h"; + final String headerName = CUtil.getName(tpr) + ".h"; var guardMacro = headerName.toUpperCase().replace(".", "_"); header.pr("#ifndef " + guardMacro); header.pr("#define " + guardMacro); - generateReactorClassHeaders(reactor, headerName, header, src); - header.pr(generateTopLevelPreambles(reactor)); - generateUserPreamblesForReactor(reactor, src); - generateReactorClassBody(reactor, header, src); + generateReactorClassHeaders(tpr, headerName, header, src); + header.pr(generateTopLevelPreambles(tpr.r())); + generateUserPreamblesForReactor(tpr.r(), src); + generateReactorClassBody(tpr, header, src); header.pr("#endif // " + guardMacro); FileUtil.writeToFile(header.toString(), fileConfig.getSrcGenPath().resolve(headerName), true); - var extension = targetConfig.platformOptions.platform == Platform.ARDUINO ? ".ino" : (CCppMode ? ".cpp" : ".c"); - FileUtil.writeToFile(src.toString(), fileConfig.getSrcGenPath().resolve(CUtil.getName(reactor) + extension), true); + var extension = targetConfig.platformOptions.platform == Platform.ARDUINO ? ".ino" + : (CCppMode ? ".cpp" : ".c"); + FileUtil.writeToFile(src.toString(), fileConfig.getSrcGenPath().resolve( + CUtil.getName(reactor) + extension), true); } - protected void generateReactorClassHeaders(Reactor reactor, String headerName, CodeBuilder header, CodeBuilder src) { + protected void generateReactorClassHeaders(TypeParameterizedReactor tpr, String headerName, CodeBuilder header, CodeBuilder src) { if (CCppMode) { src.pr("extern \"C\" {"); header.pr("extern \"C\" {"); } + tpr.typeArgs().entrySet().forEach(it -> src.pr("#define " + it.getKey() + " " + ASTUtils.toText(it.getValue()))); header.pr("#include \"include/core/reactor.h\""); src.pr("#include \"include/api/api.h\""); src.pr("#include \"include/api/set.h\""); - generateIncludes(reactor); + generateIncludes(tpr.r()); if (CCppMode) { src.pr("}"); header.pr("}"); } - src.pr("#include \"include/" + CReactorHeaderFileGenerator.outputPath(fileConfig, reactor) + "\""); + src.pr("#include \"include/" + CReactorHeaderFileGenerator.outputPath(fileConfig, tpr.r()) + "\""); src.pr("#include \"" + headerName + "\""); - Stream.concat( - reactor.getInstantiations().stream(), - reactor.getModes().stream().flatMap(it -> it.getInstantiations().stream()) - ) - .collect(Collectors.toSet()).stream() - .map(Instantiation::getReactorClass) - .map(ASTUtils::toDefinition).map(CUtil::getName) + new HashSet<>(ASTUtils.allInstantiations(tpr.r())).stream() + .map(TypeParameterizedReactor::new).map(CUtil::getName) .map(name -> "#include \"" + name + ".h\"") .forEach(header::pr); } - private void generateReactorClassBody(Reactor reactor, CodeBuilder header, CodeBuilder src) { + private void generateReactorClassBody(TypeParameterizedReactor tpr, CodeBuilder header, CodeBuilder src) { // Some of the following methods create lines of code that need to // go into the constructor. Collect those lines of code here: var constructorCode = new CodeBuilder(); @@ -1137,7 +1119,7 @@ protected void generateIncludes(Reactor r) { * Generate the struct type definitions for inputs, outputs, and * actions of the specified reactor. */ - protected void generateAuxiliaryStructs(CodeBuilder builder, Reactor r, boolean userFacing) { + protected void generateAuxiliaryStructs(CodeBuilder builder, TypeParameterizedReactor tpr, boolean userFacing) { // In the case where there are incoming // p2p logical connections in decentralized // federated execution, there will be an @@ -1155,9 +1137,9 @@ protected void generateAuxiliaryStructs(CodeBuilder builder, Reactor r, boolean #endif """.formatted(types.getTargetTagType(), types.getTargetTimeType()) ); - for (Port p : allPorts(r)) { + for (Port p : allPorts(tpr.r())) { builder.pr(CPortGenerator.generateAuxiliaryStruct( - r, + tpr, p, getTarget(), errorReporter, @@ -1169,9 +1151,9 @@ protected void generateAuxiliaryStructs(CodeBuilder builder, Reactor r, boolean // The very first item on this struct needs to be // a trigger_t* because the struct will be cast to (trigger_t*) // by the lf_schedule() functions to get to the trigger. - for (Action action : allActions(r)) { + for (Action action : allActions(tpr.r())) { builder.pr(CActionGenerator.generateAuxiliaryStruct( - r, + tpr, action, getTarget(), types, @@ -1184,20 +1166,19 @@ protected void generateAuxiliaryStructs(CodeBuilder builder, Reactor r, boolean /** * Generate the self struct type definition for the specified reactor * in the specified federate. - * @param decl The parsed reactor data structure. * @param constructorCode Place to put lines of code that need to * go into the constructor. */ - private void generateSelfStruct(CodeBuilder builder, ReactorDecl decl, CodeBuilder constructorCode) { - var reactor = toDefinition(decl); - var selfType = CUtil.selfType(ASTUtils.toDefinition(decl)); + private void generateSelfStruct(CodeBuilder builder, TypeParameterizedReactor tpr, CodeBuilder constructorCode) { + var reactor = toDefinition(tpr.r()); + var selfType = CUtil.selfType(tpr); // Construct the typedef for the "self" struct. // Create a type name for the self struct. var body = new CodeBuilder(); // Extensions can add functionality to the CGenerator - generateSelfStructExtension(body, decl, constructorCode); + generateSelfStructExtension(body, reactor, constructorCode); // Next handle parameters. body.pr(CParameterGenerator.generateDeclarations(reactor, types)); @@ -1206,10 +1187,10 @@ private void generateSelfStruct(CodeBuilder builder, ReactorDecl decl, CodeBuild body.pr(CStateGenerator.generateDeclarations(reactor, types)); // Next handle actions. - CActionGenerator.generateDeclarations(reactor, body, constructorCode); + CActionGenerator.generateDeclarations(tpr, body, constructorCode); // Next handle inputs and outputs. - CPortGenerator.generateDeclarations(reactor, decl, body, constructorCode); + CPortGenerator.generateDeclarations(tpr, reactor, body, constructorCode); // If there are contained reactors that either receive inputs // from reactions of this reactor or produce outputs that trigger @@ -1387,7 +1368,7 @@ private void generateInteractingContainedReactors( */ protected void generateSelfStructExtension( CodeBuilder body, - ReactorDecl decl, + Reactor reactor, CodeBuilder constructorCode ) { // Do nothing @@ -1666,8 +1647,8 @@ public void processProtoFile(String filename) { * This is required to be the same as the type name returned by * {@link #variableStructType(TriggerInstance)}. */ - public static String variableStructType(Variable variable, Reactor reactor, boolean userFacing) { - return (userFacing ? reactor.getName().toLowerCase() : CUtil.getName(reactor)) +"_"+variable.getName()+"_t"; + public static String variableStructType(Variable variable, TypeParameterizedReactor tpr, boolean userFacing) { + return (userFacing ? tpr.getName().toLowerCase() : CUtil.getName(tpr)) +"_"+variable.getName()+"_t"; } /** diff --git a/org.lflang/src/org/lflang/generator/c/CPortGenerator.java b/org.lflang/src/org/lflang/generator/c/CPortGenerator.java index cf6ea06b64..accda01fb1 100644 --- a/org.lflang/src/org/lflang/generator/c/CPortGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CPortGenerator.java @@ -11,6 +11,8 @@ import org.lflang.lf.Port; import org.lflang.lf.Reactor; import org.lflang.lf.ReactorDecl; +import org.lflang.lf.Type; + import static org.lflang.generator.c.CGenerator.variableStructType; @@ -24,27 +26,21 @@ public class CPortGenerator { /** * Generate fields in the self struct for input and output ports - * - * @param reactor - * @param decl - * @param body - * @param constructorCode */ public static void generateDeclarations( - Reactor reactor, + TypeParameterizedReactor tpr, ReactorDecl decl, CodeBuilder body, CodeBuilder constructorCode ) { - generateInputDeclarations(reactor, decl, body, constructorCode); - generateOutputDeclarations(reactor, decl, body, constructorCode); + generateInputDeclarations(tpr, decl, body, constructorCode); + generateOutputDeclarations(tpr, decl, body, constructorCode); } /** * Generate the struct type definitions for the port of the * reactor * - * @param decl The reactor declaration * @param port The port to generate the struct * @param target The target of the code generation (C, CCpp or Python) * @param errorReporter The error reporter @@ -53,7 +49,7 @@ public static void generateDeclarations( * @return The auxiliary struct for the port as a string */ public static String generateAuxiliaryStruct( - Reactor decl, + TypeParameterizedReactor tpr, Port port, Target target, ErrorReporter errorReporter, @@ -80,7 +76,7 @@ public static String generateAuxiliaryStruct( code.pr(valueDeclaration(port, target, errorReporter, types)); code.pr(federatedExtension.toString()); code.unindent(); - code.pr("} "+variableStructType(port, decl, userFacing)+";"); + code.pr("} "+variableStructType(port, tpr, userFacing)+";"); return code.toString(); } @@ -201,31 +197,31 @@ private static String valueDeclaration( * */ private static void generateInputDeclarations( - Reactor reactor, + TypeParameterizedReactor tpr, ReactorDecl decl, CodeBuilder body, CodeBuilder constructorCode ) { - for (Input input : ASTUtils.allInputs(reactor)) { + for (Input input : ASTUtils.allInputs(tpr.r())) { var inputName = input.getName(); if (ASTUtils.isMultiport(input)) { body.pr(input, String.join("\n", "// Multiport input array will be malloc'd later.", - variableStructType(input, reactor, false)+"** _lf_"+inputName+";", + variableStructType(input, tpr, false)+"** _lf_"+inputName+";", "int _lf_"+inputName+"_width;", "// Default input (in case it does not get connected)", - variableStructType(input, reactor, false)+" _lf_default__"+inputName+";", + variableStructType(input, tpr, false)+" _lf_default__"+inputName+";", "// Struct to support efficiently reading sparse inputs.", "lf_sparse_io_record_t* _lf_"+inputName+"__sparse;" )); } else { // input is not a multiport. body.pr(input, String.join("\n", - variableStructType(input, reactor, false)+"* _lf_"+inputName+";", + variableStructType(input, tpr, false)+"* _lf_"+inputName+";", "// width of -2 indicates that it is not a multiport.", "int _lf_"+inputName+"_width;", "// Default input (in case it does not get connected)", - variableStructType(input, reactor, false)+" _lf_default__"+inputName+";" + variableStructType(input, tpr, false)+" _lf_default__"+inputName+";" )); constructorCode.pr(input, String.join("\n", @@ -238,26 +234,21 @@ private static void generateInputDeclarations( /** * Generate fields in the self struct for output ports - * - * @param reactor - * @param decl - * @param body - * @param constructorCode */ private static void generateOutputDeclarations( - Reactor reactor, + TypeParameterizedReactor tpr, ReactorDecl decl, CodeBuilder body, CodeBuilder constructorCode ) { - for (Output output : ASTUtils.allOutputs(reactor)) { + for (Output output : ASTUtils.allOutputs(tpr.r())) { // If the port is a multiport, create an array to be allocated // at instantiation. var outputName = output.getName(); if (ASTUtils.isMultiport(output)) { body.pr(output, String.join("\n", "// Array of output ports.", - variableStructType(output, reactor, false)+"* _lf_"+outputName+";", + variableStructType(output, tpr, false)+"* _lf_"+outputName+";", "int _lf_"+outputName+"_width;", "// An array of pointers to the individual ports. Useful", "// for the lf_set macros to work out-of-the-box for", @@ -265,11 +256,11 @@ private static void generateOutputDeclarations( "// value can be accessed via a -> operator (e.g.,foo[i]->value).", "// So we have to handle multiports specially here a construct that", "// array of pointers.", - variableStructType(output, reactor, false)+"** _lf_"+outputName+"_pointers;" + variableStructType(output, tpr, false)+"** _lf_"+outputName+"_pointers;" )); } else { body.pr(output, String.join("\n", - variableStructType(output, reactor, false)+" _lf_"+outputName+";", + variableStructType(output, tpr, false)+" _lf_"+outputName+";", "int _lf_"+outputName+"_width;" )); } diff --git a/org.lflang/src/org/lflang/generator/c/CUtil.java b/org.lflang/src/org/lflang/generator/c/CUtil.java index 69e9ec30ae..b92f93023d 100644 --- a/org.lflang/src/org/lflang/generator/c/CUtil.java +++ b/org.lflang/src/org/lflang/generator/c/CUtil.java @@ -147,9 +147,9 @@ public static String channelIndexName(PortInstance port) { * reactor is main (to allow for instantiations that have the same name as * the main reactor or the .lf file). */ - public static String getName(Reactor reactor) { - String name = reactor.getName().toLowerCase() + reactor.hashCode(); - if (reactor.isMain()) { + public static String getName(TypeParameterizedReactor reactor) { + String name = reactor.r().getName().toLowerCase() + reactor.hashCode(); + if (reactor.r().isMain()) { return name + "_main"; } return name; @@ -516,8 +516,8 @@ public static String runtimeIndex(ReactorInstance reactor) { * @param reactor The reactor class. * @return The type of a self struct for the specified reactor class. */ - public static String selfType(Reactor reactor) { - if (reactor.isMain()) { + public static String selfType(TypeParameterizedReactor reactor) { + if (reactor.r().isMain()) { return "_" + CUtil.getName(reactor) + "_main_self_t"; } return "_" + CUtil.getName(reactor) + "_self_t"; diff --git a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java new file mode 100644 index 0000000000..9e79a65728 --- /dev/null +++ b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java @@ -0,0 +1,41 @@ +package org.lflang.generator.c; + + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Collectors; + +import org.lflang.ASTUtils; +import org.lflang.lf.Instantiation; +import org.lflang.lf.Reactor; +import org.lflang.lf.Type; + +import com.google.common.collect.ImmutableMap; + +public record TypeParameterizedReactor(Reactor r, Map typeArgs) { + + public TypeParameterizedReactor(Instantiation i) { + this(ASTUtils.toDefinition(i.getReactorClass()), addTypeArgs(i, ASTUtils.toDefinition(i.getReactorClass()))); + } + + private static ImmutableMap addTypeArgs(Instantiation instantiation, Reactor r) { + HashMap ret = new HashMap<>(); + if (instantiation.getTypeArgs() != null) { + for (int i = 0; i < r.getTypeParms().size(); i++) { + ret.put(r.getTypeParms().get(i).getLiteral(), instantiation.getTypeArgs().get(i)); + } + } + return ImmutableMap.copyOf(ret); + } + + public String getName() { + // FIXME: Types that are not just a single token need to be escaped or hashed + return r.getName() + typeArgs.values().stream().map(ASTUtils::toText).collect(Collectors.joining("_")); + } + + @Override + public int hashCode() { + return r.hashCode() * 31 + typeArgs.hashCode(); + } +} diff --git a/org.lflang/src/org/lflang/generator/python/PythonGenerator.java b/org.lflang/src/org/lflang/generator/python/PythonGenerator.java index 7a23b79b21..b20a5d9de2 100644 --- a/org.lflang/src/org/lflang/generator/python/PythonGenerator.java +++ b/org.lflang/src/org/lflang/generator/python/PythonGenerator.java @@ -544,10 +544,9 @@ protected void generateReactorInstanceExtension( @Override protected void generateSelfStructExtension( CodeBuilder selfStructBody, - ReactorDecl decl, + Reactor reactor, CodeBuilder constructorCode ) { - Reactor reactor = ASTUtils.toDefinition(decl); // Add the name field selfStructBody.pr("char *_lf_name;"); int reactionIndex = 0; diff --git a/test/C/src/generics/Template.lf b/test/C/src/generics/Template.lf new file mode 100644 index 0000000000..3d483098b9 --- /dev/null +++ b/test/C/src/generics/Template.lf @@ -0,0 +1,13 @@ +target C + +reactor Hello { + state count: T(0) + reaction(startup) {= + self->count = self->count + 1; + printf("Hello World %d\n", (int) self->count); + =} +} + +main reactor Template { + hello = new Hello(); +} From c1eafa7c827b7885ca92a31ca5119dca2515bd73 Mon Sep 17 00:00:00 2001 From: mkhubaibumer Date: Mon, 27 Mar 2023 21:47:39 +0500 Subject: [PATCH 02/54] [C-Generics] - Build Fixes - Allowing Template Types to be defined for in/out ports or state variables - Reordering definitions with includes Signed-off-by: mkhubaibumer --- .../generator/ReactionInstanceGraph.java | 4 +- .../org/lflang/generator/ReactorInstance.java | 14 ++++--- .../generator/c/CConstructorGenerator.java | 10 ++--- .../org/lflang/generator/c/CGenerator.java | 37 +++++++++++-------- .../lflang/generator/c/CMethodGenerator.java | 3 +- .../c/CReactorHeaderFileGenerator.java | 21 ++++++----- .../src/org/lflang/generator/c/CUtil.java | 15 +++++++- .../generator/c/TypeParameterizedReactor.java | 2 +- .../generator/python/PythonGenerator.java | 20 +++++----- 9 files changed, 76 insertions(+), 50 deletions(-) diff --git a/org.lflang/src/org/lflang/generator/ReactionInstanceGraph.java b/org.lflang/src/org/lflang/generator/ReactionInstanceGraph.java index 3422ee0d50..a1598bff0c 100644 --- a/org.lflang/src/org/lflang/generator/ReactionInstanceGraph.java +++ b/org.lflang/src/org/lflang/generator/ReactionInstanceGraph.java @@ -411,7 +411,7 @@ public String toDOT() { var currentLevelNodes = groupedNodes.get(level); for (var node: currentLevelNodes) { // Draw the node - var label = CUtil.getName(node.getReaction().getParent().reactorDefinition) + "." + node.getReaction().getName(); + var label = CUtil.getName(node.getReaction().getParent().tpr) + "." + node.getReaction().getName(); // Need a positive number to name the nodes in GraphViz var labelHashCode = label.hashCode() & 0xfffffff; dotRepresentation.pr(" node_" + labelHashCode + " [label=\""+ label +"\"];"); @@ -419,7 +419,7 @@ public String toDOT() { // Draw the edges var downstreamNodes = getDownstreamAdjacentNodes(node); for (var downstreamNode: downstreamNodes) { - var downstreamLabel = CUtil.getName(downstreamNode.getReaction().getParent().reactorDefinition) + "." + downstreamNode.getReaction().getName(); + var downstreamLabel = CUtil.getName(downstreamNode.getReaction().getParent().tpr) + "." + downstreamNode.getReaction().getName(); edges.append(" node_" + labelHashCode + " -> node_" + (downstreamLabel.hashCode() & 0xfffffff) + ";\n" ); diff --git a/org.lflang/src/org/lflang/generator/ReactorInstance.java b/org.lflang/src/org/lflang/generator/ReactorInstance.java index af295818b3..0a5c9e0b85 100644 --- a/org.lflang/src/org/lflang/generator/ReactorInstance.java +++ b/org.lflang/src/org/lflang/generator/ReactorInstance.java @@ -767,11 +767,11 @@ protected TriggerInstance getOrCreateBuiltinTrigger(Buil * @param reporter An error reporter. * @param desiredDepth The depth to which to expand the hierarchy. */ - private ReactorInstance( - Instantiation definition, - ReactorInstance parent, - ErrorReporter reporter, - int desiredDepth) { + public ReactorInstance( + Instantiation definition, + ReactorInstance parent, + ErrorReporter reporter, + int desiredDepth) { super(definition, parent); this.reporter = reporter; this.reactorDeclaration = definition.getReactorClass(); @@ -865,6 +865,10 @@ private ReactorInstance( } } + public TypeParameterizedReactor getTypeParameterizedReactor() { + return this.tpr; + } + ////////////////////////////////////////////////////// //// Private methods. diff --git a/org.lflang/src/org/lflang/generator/c/CConstructorGenerator.java b/org.lflang/src/org/lflang/generator/c/CConstructorGenerator.java index 8944fd0796..41731106c3 100644 --- a/org.lflang/src/org/lflang/generator/c/CConstructorGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CConstructorGenerator.java @@ -15,12 +15,12 @@ public class CConstructorGenerator { * go into the constructor. */ public static String generateConstructor( - Reactor reactor, + TypeParameterizedReactor tpr, String constructorCode ) { - var structType = CUtil.selfType(reactor); + var structType = CUtil.selfType(tpr); var code = new CodeBuilder(); - code.pr(structType+"* new_"+CUtil.getName(reactor)+"() {"); + code.pr(structType+"* new_"+CUtil.getName(tpr)+"() {"); code.indent(); code.pr(structType+"* self = ("+structType+"*)_lf_new_reactor(sizeof("+structType+"));"); code.pr(constructorCode); @@ -30,7 +30,7 @@ public static String generateConstructor( return code.toString(); } - public static String generateConstructorPrototype(Reactor reactor) { - return CUtil.selfType(reactor)+"* new_"+CUtil.getName(reactor)+"();"; + public static String generateConstructorPrototype(TypeParameterizedReactor tpr) { + return CUtil.selfType(tpr)+"* new_"+CUtil.getName(tpr)+"();"; } } diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index 0b5602d9d9..282d73d45d 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -939,9 +939,9 @@ private void generateHeaders() throws IOException { fileConfig.getIncludePath(), false ); - for (Reactor r : reactors) { - CReactorHeaderFileGenerator.doGenerate(types, r, fileConfig, this::generateAuxiliaryStructs, this::generateTopLevelPreambles); - } +// for (var r : reactors) { + CReactorHeaderFileGenerator.doGenerate(types, this.main.tpr, fileConfig, this::generateAuxiliaryStructs, this::generateTopLevelPreambles); +// } FileUtil.copyDirectory(fileConfig.getIncludePath(), fileConfig.getSrcGenPath().resolve("include"), false); } @@ -1034,12 +1034,13 @@ private void generateReactorClass(TypeParameterizedReactor tpr) throws IOExcepti header.pr(generateTopLevelPreambles(tpr.r())); generateUserPreamblesForReactor(tpr.r(), src); generateReactorClassBody(tpr, header, src); + tpr.typeArgs().entrySet().forEach(it -> header.pr("#undef " + it.getKey())); header.pr("#endif // " + guardMacro); FileUtil.writeToFile(header.toString(), fileConfig.getSrcGenPath().resolve(headerName), true); var extension = targetConfig.platformOptions.platform == Platform.ARDUINO ? ".ino" - : (CCppMode ? ".cpp" : ".c"); + : CCppMode ? ".cpp" : ".c"; FileUtil.writeToFile(src.toString(), fileConfig.getSrcGenPath().resolve( - CUtil.getName(reactor) + extension), true); + CUtil.getName(tpr) + extension), true); } protected void generateReactorClassHeaders(TypeParameterizedReactor tpr, String headerName, CodeBuilder header, CodeBuilder src) { @@ -1047,7 +1048,7 @@ protected void generateReactorClassHeaders(TypeParameterizedReactor tpr, String src.pr("extern \"C\" {"); header.pr("extern \"C\" {"); } - tpr.typeArgs().entrySet().forEach(it -> src.pr("#define " + it.getKey() + " " + ASTUtils.toText(it.getValue()))); + tpr.typeArgs().entrySet().forEach(it -> header.pr("#define " + it.getKey() + " " + ASTUtils.toText(it.getValue()))); header.pr("#include \"include/core/reactor.h\""); src.pr("#include \"include/api/api.h\""); src.pr("#include \"include/api/set.h\""); @@ -1058,6 +1059,7 @@ protected void generateReactorClassHeaders(TypeParameterizedReactor tpr, String } src.pr("#include \"include/" + CReactorHeaderFileGenerator.outputPath(fileConfig, tpr.r()) + "\""); src.pr("#include \"" + headerName + "\""); + tpr.typeArgs().entrySet().forEach(it -> src.pr("#define " + it.getKey() + " " + ASTUtils.toText(it.getValue()))); new HashSet<>(ASTUtils.allInstantiations(tpr.r())).stream() .map(TypeParameterizedReactor::new).map(CUtil::getName) .map(name -> "#include \"" + name + ".h\"") @@ -1068,11 +1070,11 @@ private void generateReactorClassBody(TypeParameterizedReactor tpr, CodeBuilder // Some of the following methods create lines of code that need to // go into the constructor. Collect those lines of code here: var constructorCode = new CodeBuilder(); - generateAuxiliaryStructs(header, reactor, false); - generateSelfStruct(header, reactor, constructorCode); - generateMethods(src, reactor); - generateReactions(src, reactor); - generateConstructor(src, header, reactor, constructorCode); + generateAuxiliaryStructs(header, tpr, false); + generateSelfStruct(header, tpr, constructorCode); + generateMethods(src, tpr.r()); + generateReactions(src, tpr.r()); + generateConstructor(src, header, tpr, constructorCode); } /** @@ -1097,16 +1099,16 @@ protected void generateUserPreamblesForReactor(Reactor reactor, CodeBuilder src) /** * Generate a constructor for the specified reactor in the specified federate. - * @param reactor The parsed reactor data structure. + * @param tpr The parsed reactor data structure. * @param constructorCode Lines of code previously generated that need to * go into the constructor. */ protected void generateConstructor( - CodeBuilder src, CodeBuilder header, Reactor reactor, CodeBuilder constructorCode + CodeBuilder src, CodeBuilder header, TypeParameterizedReactor tpr, CodeBuilder constructorCode ) { - header.pr(CConstructorGenerator.generateConstructorPrototype(reactor)); + header.pr(CConstructorGenerator.generateConstructorPrototype(tpr)); src.pr(CConstructorGenerator.generateConstructor( - reactor, + tpr, constructorCode.toString() )); } @@ -1363,7 +1365,7 @@ private void generateInteractingContainedReactors( /** * This function is provided to allow extensions of the CGenerator to append the structure of the self struct * @param body The body of the self struct - * @param decl The reactor declaration for the self struct + * @param reactor The reactor declaration for the self struct * @param constructorCode Code that is executed when the reactor is instantiated */ protected void generateSelfStructExtension( @@ -1650,6 +1652,9 @@ public void processProtoFile(String filename) { public static String variableStructType(Variable variable, TypeParameterizedReactor tpr, boolean userFacing) { return (userFacing ? tpr.getName().toLowerCase() : CUtil.getName(tpr)) +"_"+variable.getName()+"_t"; } + public static String variableStructType(Variable variable, Reactor r, boolean userFacing) { + return (userFacing ? r.getName().toLowerCase() : CUtil.getName(r)) +"_"+variable.getName()+"_t"; + } /** * Construct a unique type for the struct of the specified diff --git a/org.lflang/src/org/lflang/generator/c/CMethodGenerator.java b/org.lflang/src/org/lflang/generator/c/CMethodGenerator.java index a4e3dba149..5f8a4d6ad1 100644 --- a/org.lflang/src/org/lflang/generator/c/CMethodGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CMethodGenerator.java @@ -5,6 +5,7 @@ import org.lflang.ASTUtils; import org.lflang.InferredType; import org.lflang.generator.CodeBuilder; +import org.lflang.generator.ReactorInstance; import org.lflang.lf.Method; import org.lflang.lf.Reactor; import org.lflang.lf.ReactorDecl; @@ -67,7 +68,7 @@ public static String generateMethod( code.indent(); // Define the "self" struct. - String structType = CUtil.selfType(ASTUtils.toDefinition(decl)); + String structType = CUtil.selfType((ReactorInstance) ASTUtils.toDefinition(decl)); // A null structType means there are no inputs, state, // or anything else. No need to declare it. if (structType != null) { diff --git a/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java b/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java index b947f3ca67..92318c0150 100644 --- a/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java @@ -16,6 +16,7 @@ import org.lflang.lf.Reactor; import org.lflang.lf.StateVar; import org.lflang.lf.TriggerRef; +import org.lflang.lf.Type; import org.lflang.lf.TypedVariable; import org.lflang.lf.VarRef; import org.lflang.lf.Variable; @@ -24,7 +25,7 @@ public class CReactorHeaderFileGenerator { public interface GenerateAuxiliaryStructs { - void generate(CodeBuilder b, Reactor r, boolean userFacing); + void generate(CodeBuilder b, TypeParameterizedReactor r, boolean userFacing); } public static Path outputPath(CFileConfig fileConfig, Reactor r) { @@ -33,19 +34,19 @@ public static Path outputPath(CFileConfig fileConfig, Reactor r) { .resolve(r.getName() + ".h"); } - public static void doGenerate(CTypes types, Reactor r, CFileConfig fileConfig, GenerateAuxiliaryStructs generator, Function topLevelPreamble) throws IOException { - String contents = generateHeaderFile(types, r, generator, topLevelPreamble.apply(r)); - FileUtil.writeToFile(contents, fileConfig.getIncludePath().resolve(outputPath(fileConfig, r))); + public static void doGenerate(CTypes types, TypeParameterizedReactor tpr, CFileConfig fileConfig, GenerateAuxiliaryStructs generator, Function topLevelPreamble) throws IOException { + String contents = generateHeaderFile(types, tpr, generator, topLevelPreamble.apply(tpr.r())); + FileUtil.writeToFile(contents, fileConfig.getIncludePath().resolve(outputPath(fileConfig, tpr.r()))); } - private static String generateHeaderFile(CTypes types, Reactor r, GenerateAuxiliaryStructs generator, String topLevelPreamble) { + private static String generateHeaderFile(CTypes types, TypeParameterizedReactor tpr, GenerateAuxiliaryStructs generator, String topLevelPreamble) { CodeBuilder builder = new CodeBuilder(); - appendIncludeGuard(builder, r); + appendIncludeGuard(builder, tpr.r()); builder.pr(topLevelPreamble); appendPoundIncludes(builder); - appendSelfStruct(builder, types, r); - generator.generate(builder, r, true); - for (Reaction reaction : r.getReactions()) { - appendSignature(builder, types, reaction, r); + appendSelfStruct(builder, types, tpr.r()); + generator.generate(builder, tpr, true); + for (Reaction reaction : tpr.r().getReactions()) { + appendSignature(builder, types, reaction, tpr.r()); } builder.pr("#endif"); return builder.getCode(); diff --git a/org.lflang/src/org/lflang/generator/c/CUtil.java b/org.lflang/src/org/lflang/generator/c/CUtil.java index b92f93023d..15097b6205 100644 --- a/org.lflang/src/org/lflang/generator/c/CUtil.java +++ b/org.lflang/src/org/lflang/generator/c/CUtil.java @@ -154,6 +154,13 @@ public static String getName(TypeParameterizedReactor reactor) { } return name; } + public static String getName(Reactor reactor) { + String name = reactor.getName().toLowerCase() + reactor.hashCode(); + if (reactor.isMain()) { + return name + "_main"; + } + return name; + } /** * Return a reference to the specified port. @@ -522,10 +529,16 @@ public static String selfType(TypeParameterizedReactor reactor) { } return "_" + CUtil.getName(reactor) + "_self_t"; } + public static String selfType(Reactor reactor) { + if (reactor.isMain()) { + return "_" + CUtil.getName(reactor) + "_main_self_t"; + } + return "_" + CUtil.getName(reactor) + "_self_t"; + } /** Construct a unique type for the "self" struct of the class of the given reactor. */ public static String selfType(ReactorInstance instance) { - return selfType(ASTUtils.toDefinition(instance.getDefinition().getReactorClass())); + return selfType(instance.tpr); } /** diff --git a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java index 9e79a65728..281139c4af 100644 --- a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java +++ b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java @@ -36,6 +36,6 @@ public String getName() { @Override public int hashCode() { - return r.hashCode() * 31 + typeArgs.hashCode(); + return Math.abs(r.hashCode() * 31 + typeArgs.hashCode()); } } diff --git a/org.lflang/src/org/lflang/generator/python/PythonGenerator.java b/org.lflang/src/org/lflang/generator/python/PythonGenerator.java index b20a5d9de2..fcb1c19595 100644 --- a/org.lflang/src/org/lflang/generator/python/PythonGenerator.java +++ b/org.lflang/src/org/lflang/generator/python/PythonGenerator.java @@ -55,6 +55,7 @@ import org.lflang.generator.c.CCmakeGenerator; import org.lflang.generator.c.CGenerator; import org.lflang.generator.c.CUtil; +import org.lflang.generator.c.TypeParameterizedReactor; import org.lflang.lf.Action; import org.lflang.lf.Code; import org.lflang.lf.Input; @@ -64,6 +65,7 @@ import org.lflang.lf.Reaction; import org.lflang.lf.Reactor; import org.lflang.lf.ReactorDecl; +import org.lflang.lf.Type; import org.lflang.util.FileUtil; import org.lflang.util.LFCommand; import org.lflang.util.StringUtil; @@ -354,16 +356,16 @@ public void processProtoFile(String filename) { */ @Override public void generateAuxiliaryStructs( - CodeBuilder builder, Reactor r, boolean userFacing + CodeBuilder builder, TypeParameterizedReactor tpr, boolean userFacing ) { - for (Input input : ASTUtils.allInputs(r)) { - generateAuxiliaryStructsForPort(builder, r, input); + for (Input input : ASTUtils.allInputs(tpr.r())) { + generateAuxiliaryStructsForPort(builder, tpr.r(), input); } - for (Output output : ASTUtils.allOutputs(r)) { - generateAuxiliaryStructsForPort(builder, r, output); + for (Output output : ASTUtils.allOutputs(tpr.r())) { + generateAuxiliaryStructsForPort(builder, tpr.r(), output); } - for (Action action : ASTUtils.allActions(r)) { - generateAuxiliaryStructsForAction(builder, r, action); + for (Action action : ASTUtils.allActions(tpr.r())) { + generateAuxiliaryStructsForAction(builder, tpr.r(), action); } } @@ -517,9 +519,9 @@ protected void generateUserPreamblesForReactor(Reactor reactor, CodeBuilder src) } @Override - protected void generateReactorClassHeaders(Reactor reactor, String headerName, CodeBuilder header, CodeBuilder src) { + protected void generateReactorClassHeaders(TypeParameterizedReactor tpr, String headerName, CodeBuilder header, CodeBuilder src) { header.pr(PythonPreambleGenerator.generateCIncludeStatements(targetConfig, targetLanguageIsCpp(), hasModalReactors)); - super.generateReactorClassHeaders(reactor, headerName, header, src); + super.generateReactorClassHeaders(tpr, headerName, header, src); } /** From 1dfb39d49dcd32b116e07f3e8964037d6898176a Mon Sep 17 00:00:00 2001 From: mkhubaibumer Date: Wed, 29 Mar 2023 15:58:50 +0500 Subject: [PATCH 03/54] [C-Generics] HashCode missmatch bug --- .../src/org/lflang/generator/c/CReactionGenerator.java | 4 ++-- .../org/lflang/generator/python/PythonActionGenerator.java | 5 +++-- .../src/org/lflang/generator/python/PythonGenerator.java | 6 +++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java index 051540bbf6..23818cb2ef 100644 --- a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java @@ -758,9 +758,9 @@ public static void generateReactionAndTriggerStructs( "self->_lf__reaction_"+reactionCount+".deadline_violation_handler = "+deadlineFunctionPointer+";", "self->_lf__reaction_"+reactionCount+".STP_handler = "+STPFunctionPointer+";", "self->_lf__reaction_"+reactionCount+".name = "+addDoubleQuotes("?")+";", - (reaction.eContainer() instanceof Mode ? + reaction.eContainer() instanceof Mode ? "self->_lf__reaction_"+reactionCount+".mode = &self->_lf__modes["+reactor.getModes().indexOf((Mode) reaction.eContainer())+"];" : - "self->_lf__reaction_"+reactionCount+".mode = NULL;") + "self->_lf__reaction_"+reactionCount+".mode = NULL;" )); // Increment the reactionCount even if the reaction is not in the federate // so that reaction indices are consistent across federates. diff --git a/org.lflang/src/org/lflang/generator/python/PythonActionGenerator.java b/org.lflang/src/org/lflang/generator/python/PythonActionGenerator.java index a2a149f522..13dbed0f0f 100644 --- a/org.lflang/src/org/lflang/generator/python/PythonActionGenerator.java +++ b/org.lflang/src/org/lflang/generator/python/PythonActionGenerator.java @@ -1,13 +1,14 @@ package org.lflang.generator.python; +import org.lflang.generator.c.TypeParameterizedReactor; import org.lflang.lf.Action; import org.lflang.lf.Reactor; import org.lflang.generator.c.CGenerator; public class PythonActionGenerator { - public static String generateAliasTypeDef(Reactor r, Action action, + public static String generateAliasTypeDef(TypeParameterizedReactor tpr, Action action, String genericActionType) { - return "typedef "+genericActionType+" "+CGenerator.variableStructType(action, r, false)+";"; + return "typedef "+genericActionType+" "+CGenerator.variableStructType(action, tpr, false)+";"; } } diff --git a/org.lflang/src/org/lflang/generator/python/PythonGenerator.java b/org.lflang/src/org/lflang/generator/python/PythonGenerator.java index fcb1c19595..6a1a6ecd1d 100644 --- a/org.lflang/src/org/lflang/generator/python/PythonGenerator.java +++ b/org.lflang/src/org/lflang/generator/python/PythonGenerator.java @@ -365,7 +365,7 @@ public void generateAuxiliaryStructs( generateAuxiliaryStructsForPort(builder, tpr.r(), output); } for (Action action : ASTUtils.allActions(tpr.r())) { - generateAuxiliaryStructsForAction(builder, tpr.r(), action); + generateAuxiliaryStructsForAction(builder, tpr, action); } } @@ -377,9 +377,9 @@ private void generateAuxiliaryStructsForPort(CodeBuilder builder, Reactor r, genericPortType)); } - private void generateAuxiliaryStructsForAction(CodeBuilder builder, Reactor r, + private void generateAuxiliaryStructsForAction(CodeBuilder builder, TypeParameterizedReactor tpr, Action action) { - builder.pr(action, PythonActionGenerator.generateAliasTypeDef(r, action, genericActionType)); + builder.pr(action, PythonActionGenerator.generateAliasTypeDef(tpr, action, genericActionType)); } /** From 77109fe92d2e34ea54cb9ffe45ea413b28dac7b4 Mon Sep 17 00:00:00 2001 From: mkhubaibumer Date: Wed, 29 Mar 2023 19:50:41 +0500 Subject: [PATCH 04/54] [C-Generics] Working Generic Code Basic implementation for Generic Reactors in C-Target are done We can run the following Generic Code for demonstration of this feature. These macros will be included to LF for user conveniance ``` target C { keepalive: true, // fast: true } preamble {= /// -- Start // All C-Generic Reactors will probably need these /// -- End =} reactor Connector(latency:int(0)) { input in:I; output out:O; logical action delayed_sch; reaction(in) -> delayed_sch {= lf_schedule(delayed_sch, self->latency); =} reaction(delayed_sch) in -> out {= if (is_same_type(in->value, out->value)) { lf_set(out, in->value); } else { auto_t tmp = CALL_CONVERTOR(I, O, in->value); // If convertor function is defined this will be called lf_set(out, tmp); } =} } reactor A { output Aout:int; logical action post; timer t(0, 1sec); reaction(t) -> post {= lf_schedule(post, 2); =} reaction(post) -> Aout {= lf_set(Aout, rand()); =} } reactor B { input Bin:float; reaction(Bin) {= printf("got %f\n", Bin->value); =} } main reactor { a = new A(); w = new Connector(latency=500); w2 = new Connector(latency=500); b = new B(); a.Aout -> w.in; w.out -> b.Bin; } ``` Signed-off-by: mkhubaibumer --- .../org/lflang/generator/c/CGenerator.java | 55 +++++---- .../lflang/generator/c/CMethodGenerator.java | 48 ++++---- .../generator/c/CReactionGenerator.java | 111 +++++++++--------- .../c/CReactorHeaderFileGenerator.java | 38 +++--- .../src/org/lflang/generator/c/CUtil.java | 6 - .../generator/python/PythonGenerator.java | 24 ++-- .../generator/python/PythonPortGenerator.java | 5 +- .../python/PythonReactionGenerator.java | 10 +- .../python/PythonReactorGenerator.java | 4 +- .../org/lflang/validation/LFValidator.java | 12 +- 10 files changed, 157 insertions(+), 156 deletions(-) diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index 282d73d45d..b9fc9e57dc 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -1052,7 +1052,7 @@ protected void generateReactorClassHeaders(TypeParameterizedReactor tpr, String header.pr("#include \"include/core/reactor.h\""); src.pr("#include \"include/api/api.h\""); src.pr("#include \"include/api/set.h\""); - generateIncludes(tpr.r()); + generateIncludes(tpr); if (CCppMode) { src.pr("}"); header.pr("}"); @@ -1072,16 +1072,16 @@ private void generateReactorClassBody(TypeParameterizedReactor tpr, CodeBuilder var constructorCode = new CodeBuilder(); generateAuxiliaryStructs(header, tpr, false); generateSelfStruct(header, tpr, constructorCode); - generateMethods(src, tpr.r()); - generateReactions(src, tpr.r()); + generateMethods(src, tpr); + generateReactions(src, tpr); generateConstructor(src, header, tpr, constructorCode); } /** * Generate methods for {@code reactor}. */ - protected void generateMethods(CodeBuilder src, ReactorDecl reactor) { - CMethodGenerator.generateMethods(reactor, src, types); + protected void generateMethods(CodeBuilder src, TypeParameterizedReactor tpr) { + CMethodGenerator.generateMethods(tpr, src, types); } /** @@ -1113,8 +1113,8 @@ protected void generateConstructor( )); } - protected void generateIncludes(Reactor r) { - code.pr("#include \"" + CUtil.getName(r) + ".h\""); + protected void generateIncludes(TypeParameterizedReactor tpr) { + code.pr("#include \"" + CUtil.getName(tpr) + ".h\""); } /** @@ -1201,11 +1201,12 @@ private void generateSelfStruct(CodeBuilder builder, TypeParameterizedReactor tp // struct has a place to hold the data produced by this reactor's // reactions and a place to put pointers to data produced by // the contained reactors. - generateInteractingContainedReactors(reactor, body, constructorCode); + generateInteractingContainedReactors(tpr, reactor, body, constructorCode); // Next, generate the fields needed for each reaction. CReactionGenerator.generateReactionAndTriggerStructs( body, + tpr, reactor, constructorCode, types @@ -1237,11 +1238,13 @@ private void generateSelfStruct(CodeBuilder builder, TypeParameterizedReactor tp * reactions and a place to put pointers to data produced by * the contained reactors. * + * @param tpr The TypeParameterized Reactor * @param reactor The reactor. * @param body The place to put the struct definition for the contained reactors. * @param constructorCode The place to put matching code that goes in the container's constructor. */ private void generateInteractingContainedReactors( + TypeParameterizedReactor tpr, Reactor reactor, CodeBuilder body, CodeBuilder constructorCode @@ -1279,12 +1282,12 @@ private void generateInteractingContainedReactors( // to be malloc'd at initialization. if (!ASTUtils.isMultiport(port)) { // Not a multiport. - body.pr(port, variableStructType(port, containedReactorType, false)+" "+port.getName()+";"); + body.pr(port, variableStructType(port, tpr, false)+" "+port.getName()+";"); } else { // Is a multiport. // Memory will be malloc'd in initialization. body.pr(port, String.join("\n", - variableStructType(port, containedReactorType, false)+"** "+port.getName()+";", + variableStructType(port, tpr, false)+"** "+port.getName()+";", "int "+port.getName()+"_width;" )); } @@ -1294,13 +1297,13 @@ private void generateInteractingContainedReactors( // self struct of the container. if (!ASTUtils.isMultiport(port)) { // Not a multiport. - body.pr(port, variableStructType(port, containedReactorType, false)+"* "+port.getName()+";"); + body.pr(port, variableStructType(port, tpr, false)+"* "+port.getName()+";"); } else { // Is a multiport. // Here, we will use an array of pointers. // Memory will be malloc'd in initialization. body.pr(port, String.join("\n", - variableStructType(port, containedReactorType, false)+"** "+port.getName()+";", + variableStructType(port, tpr, false)+"** "+port.getName()+";", "int "+port.getName()+"_width;" )); } @@ -1308,10 +1311,10 @@ private void generateInteractingContainedReactors( var reactorIndex = ""; if (containedReactor.getWidthSpec() != null) { reactorIndex = "[reactor_index]"; - constructorCode.pr("for (int reactor_index = 0; reactor_index < self->_lf_"+containedReactor.getName()+"_width; reactor_index++) {"); + constructorCode.pr("for (int reactor_index = 0; reactor_index < self->_lf_"+tpr.getName()+"_width; reactor_index++) {"); constructorCode.indent(); } - var portOnSelf = "self->_lf_"+containedReactor.getName()+reactorIndex+"."+port.getName(); + var portOnSelf = "self->_lf_"+tpr.getName()+reactorIndex+"."+port.getName(); constructorCode.pr( port, @@ -1356,8 +1359,8 @@ private void generateInteractingContainedReactors( } body.unindent(); body.pr(String.join("\n", - "} _lf_"+containedReactor.getName()+array+";", - "int _lf_"+containedReactor.getName()+"_width;" + "} _lf_"+tpr.getName()+array+";", + "int _lf_"+tpr.getName()+"_width;" )); } } @@ -1380,13 +1383,13 @@ protected void generateSelfStructExtension( * These functions have a single argument that is a void* pointing to * a struct that contains parameters, state variables, inputs (triggering or not), * actions (triggering or produced), and outputs. - * @param r The reactor. + * @param tpr The reactor. */ - public void generateReactions(CodeBuilder src, Reactor r) { + public void generateReactions(CodeBuilder src, TypeParameterizedReactor tpr) { var reactionIndex = 0; - var reactor = ASTUtils.toDefinition(r); + var reactor = ASTUtils.toDefinition(tpr.r()); for (Reaction reaction : allReactions(reactor)) { - generateReaction(src, reaction, r, reactionIndex); + generateReaction(src, reaction, tpr, reactionIndex); // Increment reaction index even if the reaction is not in the federate // so that across federates, the reaction indices are consistent. reactionIndex++; @@ -1398,13 +1401,13 @@ public void generateReactions(CodeBuilder src, Reactor r) { * a struct that contains parameters, state variables, inputs (triggering or not), * actions (triggering or produced), and outputs. * @param reaction The reaction. - * @param r The reactor. + * @param tpr The reactor. * @param reactionIndex The position of the reaction within the reactor. */ - protected void generateReaction(CodeBuilder src, Reaction reaction, Reactor r, int reactionIndex) { + protected void generateReaction(CodeBuilder src, Reaction reaction, TypeParameterizedReactor tpr, int reactionIndex) { src.pr(CReactionGenerator.generateReaction( reaction, - r, + tpr, reactionIndex, mainDef, errorReporter, @@ -1660,12 +1663,12 @@ public static String variableStructType(Variable variable, Reactor r, boolean us * Construct a unique type for the struct of the specified * instance (port or action). * This is required to be the same as the type name returned by - * {@link #variableStructType(Variable, Reactor, boolean)}. + * {@link #variableStructType(Variable, TypeParameterizedReactor, boolean)}. * @param portOrAction The port or action instance. * @return The name of the self struct. */ public static String variableStructType(TriggerInstance portOrAction) { - return CUtil.getName(portOrAction.getParent().reactorDefinition)+"_"+portOrAction.getName()+"_t"; + return CUtil.getName(portOrAction.getParent().tpr)+"_"+portOrAction.getName()+"_t"; } /** @@ -1694,7 +1697,7 @@ public void generateReactorInstance(ReactorInstance instance) { "// ***** Start initializing " + fullName + " of class " + reactorClass.getName()); // Generate the instance self struct containing parameters, state variables, // and outputs (the "self" struct). - initializeTriggerObjects.pr(CUtil.reactorRefName(instance)+"["+CUtil.runtimeIndex(instance)+"] = new_"+CUtil.getName(reactorClass)+"();"); + initializeTriggerObjects.pr(CUtil.reactorRefName(instance)+"["+CUtil.runtimeIndex(instance)+"] = new_"+CUtil.getName(instance.tpr)+"();"); // Generate code to initialize the "self" struct in the // _lf_initialize_trigger_objects function. generateTraceTableEntries(instance); diff --git a/org.lflang/src/org/lflang/generator/c/CMethodGenerator.java b/org.lflang/src/org/lflang/generator/c/CMethodGenerator.java index 5f8a4d6ad1..470bee8011 100644 --- a/org.lflang/src/org/lflang/generator/c/CMethodGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CMethodGenerator.java @@ -19,15 +19,15 @@ public class CMethodGenerator { /** * Generate macro definitions for methods. - * @param reactor The reactor. + * @param tpr The reactor. * @param body The place to put the macro definitions. */ public static void generateMacrosForMethods( - Reactor reactor, + TypeParameterizedReactor tpr, CodeBuilder body ) { - for (Method method : allMethods(reactor)) { - var functionName = methodFunctionName(reactor, method); + for (Method method : allMethods(tpr.r())) { + var functionName = methodFunctionName(tpr, method); body.pr("#define "+method.getName()+"(...) "+functionName+"(self, ##__VA_ARGS__)"); } } @@ -51,12 +51,12 @@ public static void generateMacroUndefsForMethods( * This function will have a first argument that is a void* pointing to * the self struct, followed by any arguments given in its definition. * @param method The method. - * @param decl The reactor declaration. + * @param tpr The reactor declaration. * @param types The C-specific type conversion functions. */ public static String generateMethod( Method method, - ReactorDecl decl, + TypeParameterizedReactor tpr, CTypes types ) { var code = new CodeBuilder(); @@ -64,11 +64,11 @@ public static String generateMethod( code.prSourceLineNumber(method); code.prComment("Implementation of method "+method.getName()+"()"); - code.pr(generateMethodSignature(method, decl, types) + " {"); + code.pr(generateMethodSignature(method, tpr, types) + " {"); code.indent(); // Define the "self" struct. - String structType = CUtil.selfType((ReactorInstance) ASTUtils.toDefinition(decl)); + String structType = CUtil.selfType(tpr); // A null structType means there are no inputs, state, // or anything else. No need to declare it. if (structType != null) { @@ -89,21 +89,21 @@ public static String generateMethod( * Generate method functions definition for a reactor. * These functions have a first argument that is a void* pointing to * the self struct. - * @param decl The reactor. + * @param tpr The reactor. * @param code The place to put the code. * @param types The C-specific type conversion functions. */ public static void generateMethods( - ReactorDecl decl, + TypeParameterizedReactor tpr, CodeBuilder code, CTypes types ) { - var reactor = ASTUtils.toDefinition(decl); + var reactor = tpr.r(); code.prComment("***** Start of method declarations."); - signatures(decl, code, types); - generateMacrosForMethods(reactor, code); + signatures(tpr, code, types); + generateMacrosForMethods(tpr, code); for (Method method : allMethods(reactor)) { - code.pr(CMethodGenerator.generateMethod(method, decl, types)); + code.pr(CMethodGenerator.generateMethod(method, tpr, types)); } generateMacroUndefsForMethods(reactor, code); code.prComment("***** End of method declarations."); @@ -114,28 +114,28 @@ public static void generateMethods( * This can be used to declare all the methods with signatures only * before giving the full definition so that methods may call each other * (and themselves) regardless of the order of definition. - * @param decl The reactor declaration. + * @param tpr The reactor declaration. * @param types The C-specific type conversion functions. */ public static void signatures( - ReactorDecl decl, + TypeParameterizedReactor tpr, CodeBuilder body, CTypes types ) { - Reactor reactor = ASTUtils.toDefinition(decl); + Reactor reactor = tpr.r(); for (Method method : allMethods(reactor)) { - body.pr(generateMethodSignature(method, decl, types) + ";"); + body.pr(generateMethodSignature(method, tpr, types) + ";"); } } /** * Return the function name for specified method of the specified reactor. - * @param reactor The reactor + * @param tpr The reactor * @param method The method. * @return The function name for the method. */ - private static String methodFunctionName(ReactorDecl reactor, Method method) { - return CUtil.getName(ASTUtils.toDefinition(reactor)) + "_method_" + method.getName(); + private static String methodFunctionName(TypeParameterizedReactor tpr, Method method) { + return CUtil.getName(tpr) + "_method_" + method.getName(); } /** @@ -143,15 +143,15 @@ private static String methodFunctionName(ReactorDecl reactor, Method method) { * This function will have a first argument that is a void* pointing to * the self struct, followed by any arguments given in its definition. * @param method The method. - * @param decl The reactor declaration. + * @param tpr The reactor declaration. * @param types The C-specific type conversion functions. */ public static String generateMethodSignature( Method method, - ReactorDecl decl, + TypeParameterizedReactor tpr, CTypes types ) { - var functionName = methodFunctionName(decl, method); + var functionName = methodFunctionName(tpr, method); StringBuilder result = new StringBuilder(); if (method.getReturn() != null) { diff --git a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java index 23818cb2ef..3630df136f 100644 --- a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java @@ -45,18 +45,18 @@ public class CReactionGenerator { * Generate necessary initialization code inside the body of the reaction that belongs to reactor decl. * @param body The body of the reaction. Used to check for the DISABLE_REACTION_INITIALIZATION_MARKER. * @param reaction The initialization code will be generated for this specific reaction - * @param decl The reactor that has the reaction + * @param tpr The reactor that has the reaction * @param reactionIndex The index of the reaction relative to other reactions in the reactor, starting from 0 */ public static String generateInitializationForReaction(String body, Reaction reaction, - Reactor decl, + TypeParameterizedReactor tpr, int reactionIndex, CTypes types, ErrorReporter errorReporter, Instantiation mainDef, boolean requiresTypes) { - Reactor reactor = ASTUtils.toDefinition(decl); + Reactor reactor = tpr.r(); // Construct the reactionInitialization code to go into // the body of the function before the verbatim code. @@ -65,7 +65,7 @@ public static String generateInitializationForReaction(String body, CodeBuilder code = new CodeBuilder(); // Define the "self" struct. - String structType = CUtil.selfType(decl); + String structType = CUtil.selfType(tpr); // A null structType means there are no inputs, state, // or anything else. No need to declare it. if (structType != null) { @@ -113,12 +113,12 @@ public static String generateInitializationForReaction(String body, reactionInitialization, fieldsForStructsForContainedReactors, triggerAsVarRef, - decl, + tpr, types); } else if (triggerAsVarRef.getVariable() instanceof Action) { reactionInitialization.pr(generateActionVariablesInReaction( (Action) triggerAsVarRef.getVariable(), - decl, + tpr, types )); actionsAsTriggers.add((Action) triggerAsVarRef.getVariable()); @@ -130,19 +130,19 @@ public static String generateInitializationForReaction(String body, // Declare an argument for every input. // NOTE: this does not include contained outputs. for (Input input : reactor.getInputs()) { - reactionInitialization.pr(generateInputVariablesInReaction(input, decl, types)); + reactionInitialization.pr(generateInputVariablesInReaction(input, tpr, types)); } } // Define argument for non-triggering inputs. for (VarRef src : ASTUtils.convertToEmptyListIfNull(reaction.getSources())) { if (src.getVariable() instanceof Port) { - generatePortVariablesInReaction(reactionInitialization, fieldsForStructsForContainedReactors, src, decl, types); + generatePortVariablesInReaction(reactionInitialization, fieldsForStructsForContainedReactors, src, tpr, types); } else if (src.getVariable() instanceof Action) { // It's a bit odd to read but not be triggered by an action, but // OK, I guess we allow it. reactionInitialization.pr(generateActionVariablesInReaction( (Action) src.getVariable(), - decl, + tpr, types )); actionsAsTriggers.add((Action) src.getVariable()); @@ -160,7 +160,7 @@ public static String generateInitializationForReaction(String body, // It is an action, not an output. // If it has already appeared as trigger, do not redefine it. if (!actionsAsTriggers.contains(effect.getVariable())) { - reactionInitialization.pr(CGenerator.variableStructType(variable, decl, false)+"* "+variable.getName()+" = &self->_lf_"+variable.getName()+";"); + reactionInitialization.pr(CGenerator.variableStructType(variable, tpr, false)+"* "+variable.getName()+" = &self->_lf_"+variable.getName()+";"); } } else if (effect.getVariable() instanceof Mode) { // Mode change effect @@ -184,7 +184,7 @@ public static String generateInitializationForReaction(String body, if (variable instanceof Output) { reactionInitialization.pr(generateOutputVariablesInReaction( effect, - decl, + tpr, errorReporter, requiresTypes )); @@ -414,15 +414,15 @@ private static void generatePortVariablesInReaction( CodeBuilder builder, Map structs, VarRef port, - Reactor r, + TypeParameterizedReactor tpr, CTypes types ) { if (port.getVariable() instanceof Input) { - builder.pr(generateInputVariablesInReaction((Input) port.getVariable(), r, types)); + builder.pr(generateInputVariablesInReaction((Input) port.getVariable(), tpr, types)); } else { // port is an output of a contained reactor. Output output = (Output) port.getVariable(); - String portStructType = CGenerator.variableStructType(output, ASTUtils.toDefinition(port.getContainer().getReactorClass()), false); + String portStructType = CGenerator.variableStructType(output, tpr, false); CodeBuilder structBuilder = structs.get(port.getContainer()); if (structBuilder == null) { @@ -476,10 +476,10 @@ private static void generatePortVariablesInReaction( */ private static String generateActionVariablesInReaction( Action action, - Reactor r, + TypeParameterizedReactor tpr, CTypes types ) { - String structType = CGenerator.variableStructType(action, r, false); + String structType = CGenerator.variableStructType(action, tpr, false); // If the action has a type, create variables for accessing the value. InferredType type = ASTUtils.getInferredType(action); // Pointer to the lf_token_t sent as the payload in the trigger. @@ -516,14 +516,14 @@ private static String generateActionVariablesInReaction( * initialize local variables for the specified input port * in a reaction function from the "self" struct. * @param input The input statement from the AST. - * @param r The reactor. + * @param tpr The reactor. */ private static String generateInputVariablesInReaction( Input input, - Reactor r, + TypeParameterizedReactor tpr, CTypes types ) { - String structType = CGenerator.variableStructType(input, r, false); + String structType = CGenerator.variableStructType(input, tpr, false); InferredType inputType = ASTUtils.getInferredType(input); CodeBuilder builder = new CodeBuilder(); String inputName = input.getName(); @@ -624,11 +624,11 @@ private static String generateInputVariablesInReaction( * initialize local variables for outputs in a reaction function * from the "self" struct. * @param effect The effect declared by the reaction. This must refer to an output. - * @param r The reactor containing the reaction. + * @param tpr The reactor containing the reaction. */ public static String generateOutputVariablesInReaction( VarRef effect, - Reactor r, + TypeParameterizedReactor tpr, ErrorReporter errorReporter, boolean requiresTypes ) { @@ -642,7 +642,7 @@ public static String generateOutputVariablesInReaction( // The container of the output may be a contained reactor or // the reactor containing the reaction. String outputStructType = (effect.getContainer() == null) ? - CGenerator.variableStructType(output, r, false) + CGenerator.variableStructType(output, tpr, false) : CGenerator.variableStructType(output, ASTUtils.toDefinition(effect.getContainer().getReactorClass()), false); if (!ASTUtils.isMultiport(output)) { @@ -671,6 +671,7 @@ public static String generateOutputVariablesInReaction( */ public static void generateReactionAndTriggerStructs( CodeBuilder body, + TypeParameterizedReactor tpr, Reactor reactor, CodeBuilder constructorCode, CTypes types @@ -688,7 +689,7 @@ public static void generateReactionAndTriggerStructs( var startupReactions = new LinkedHashSet(); var shutdownReactions = new LinkedHashSet(); var resetReactions = new LinkedHashSet(); - for (Reaction reaction : ASTUtils.allReactions(reactor)) { + for (Reaction reaction : ASTUtils.allReactions(tpr.r())) { // Create the reaction_t struct. body.pr(reaction, "reaction_t _lf__reaction_"+reactionCount+";"); @@ -731,7 +732,7 @@ public static void generateReactionAndTriggerStructs( var deadlineFunctionPointer = "NULL"; if (reaction.getDeadline() != null) { // The following has to match the name chosen in generateReactions - var deadlineFunctionName = generateDeadlineFunctionName(reactor, reactionCount); + var deadlineFunctionName = generateDeadlineFunctionName(tpr, reactionCount); deadlineFunctionPointer = "&" + deadlineFunctionName; } @@ -739,7 +740,7 @@ public static void generateReactionAndTriggerStructs( var STPFunctionPointer = "NULL"; if (reaction.getStp() != null) { // The following has to match the name chosen in generateReactions - var STPFunctionName = generateStpFunctionName(reactor, reactionCount); + var STPFunctionName = generateStpFunctionName(tpr, reactionCount); STPFunctionPointer = "&" + STPFunctionName; } @@ -753,7 +754,7 @@ public static void generateReactionAndTriggerStructs( // self->_lf__reaction_"+reactionCount+".is_STP_violated = false; constructorCode.pr(reaction, String.join("\n", "self->_lf__reaction_"+reactionCount+".number = "+reactionCount+";", - "self->_lf__reaction_"+reactionCount+".function = "+CReactionGenerator.generateReactionFunctionName(reactor, reactionCount)+";", + "self->_lf__reaction_"+reactionCount+".function = "+CReactionGenerator.generateReactionFunctionName(tpr, reactionCount)+";", "self->_lf__reaction_"+reactionCount+".self = self;", "self->_lf__reaction_"+reactionCount+".deadline_violation_handler = "+deadlineFunctionPointer+";", "self->_lf__reaction_"+reactionCount+".STP_handler = "+STPFunctionPointer+";", @@ -1031,12 +1032,12 @@ public static String generateLfModeTriggeredReactions( * a struct that contains parameters, state variables, inputs (triggering or not), * actions (triggering or produced), and outputs. * @param reaction The reaction. - * @param r The reactor. + * @param tpr The reactor. * @param reactionIndex The position of the reaction within the reactor. */ public static String generateReaction( Reaction reaction, - Reactor r, + TypeParameterizedReactor tpr, int reactionIndex, Instantiation mainDef, ErrorReporter errorReporter, @@ -1045,9 +1046,9 @@ public static String generateReaction( boolean requiresType ) { var code = new CodeBuilder(); - var body = ASTUtils.toText(getCode(types, reaction, r)); + var body = ASTUtils.toText(getCode(types, reaction, tpr)); String init = generateInitializationForReaction( - body, reaction, ASTUtils.toDefinition(r), reactionIndex, + body, reaction, tpr, reactionIndex, types, errorReporter, mainDef, requiresType); @@ -1055,37 +1056,37 @@ public static String generateReaction( "#include " + StringUtil.addDoubleQuotes( CCoreFilesUtils.getCTargetSetHeader())); - CMethodGenerator.generateMacrosForMethods(ASTUtils.toDefinition(r), code); + CMethodGenerator.generateMacrosForMethods(tpr, code); code.pr(generateFunction( - generateReactionFunctionHeader(r, reactionIndex), - init, getCode(types, reaction, r) + generateReactionFunctionHeader(tpr, reactionIndex), + init, getCode(types, reaction, tpr) )); // Now generate code for the late function, if there is one // Note that this function can only be defined on reactions // in federates that have inputs from a logical connection. if (reaction.getStp() != null) { code.pr(generateFunction( - generateStpFunctionHeader(r, reactionIndex), + generateStpFunctionHeader(tpr, reactionIndex), init, reaction.getStp().getCode())); } // Now generate code for the deadline violation function, if there is one. if (reaction.getDeadline() != null) { code.pr(generateFunction( - generateDeadlineFunctionHeader(r, reactionIndex), + generateDeadlineFunctionHeader(tpr, reactionIndex), init, reaction.getDeadline().getCode())); } - CMethodGenerator.generateMacroUndefsForMethods(ASTUtils.toDefinition(r), code); + CMethodGenerator.generateMacroUndefsForMethods(tpr.r(), code); code.pr( "#include " + StringUtil.addDoubleQuotes( CCoreFilesUtils.getCTargetSetUndefHeader())); return code.toString(); } - private static Code getCode(CTypes types, Reaction r, ReactorDecl container) { + private static Code getCode(CTypes types, Reaction r, TypeParameterizedReactor tpr) { if (r.getCode() != null) return r.getCode(); Code ret = LfFactory.eINSTANCE.createCode(); - ret.setBody(r.getName() + "( " + CReactorHeaderFileGenerator.reactionArguments(types, r, ASTUtils.toDefinition(container)) + " );"); + ret.setBody(r.getName() + "( " + CReactorHeaderFileGenerator.reactionArguments(types, r, tpr) + " );"); return ret; } @@ -1103,58 +1104,58 @@ public static String generateFunction(String header, String init, Code code) { /** * Returns the name of the deadline function for reaction. - * @param r The reactor with the deadline + * @param tpr The reactor with the deadline * @param reactionIndex The number assigned to this reaction deadline */ - public static String generateDeadlineFunctionName(Reactor r, int reactionIndex) { - return CUtil.getName(r).toLowerCase() + "_deadline_function" + reactionIndex; + public static String generateDeadlineFunctionName(TypeParameterizedReactor tpr, int reactionIndex) { + return CUtil.getName(tpr).toLowerCase() + "_deadline_function" + reactionIndex; } /** * Return the function name for specified reaction of the * specified reactor. - * @param reactor The reactor + * @param tpr The reactor * @param reactionIndex The reaction index. * @return The function name for the reaction. */ - public static String generateReactionFunctionName(Reactor reactor, int reactionIndex) { - return CUtil.getName(reactor).toLowerCase() + "reaction_function_" + reactionIndex; + public static String generateReactionFunctionName(TypeParameterizedReactor tpr, int reactionIndex) { + return CUtil.getName(tpr).toLowerCase() + "reaction_function_" + reactionIndex; } /** * Returns the name of the stp function for reaction. - * @param r The reactor with the stp + * @param tpr The reactor with the stp * @param reactionIndex The number assigned to this reaction deadline */ - public static String generateStpFunctionName(Reactor r, int reactionIndex) { - return CUtil.getName(r).toLowerCase() + "_STP_function" + reactionIndex; + public static String generateStpFunctionName(TypeParameterizedReactor tpr, int reactionIndex) { + return CUtil.getName(tpr).toLowerCase() + "_STP_function" + reactionIndex; } /** Return the top level C function header for the deadline function numbered "reactionIndex" in "r" - * @param r The reactor declaration + * @param tpr The reactor declaration * @param reactionIndex The reaction index. * @return The function name for the deadline function. */ - public static String generateDeadlineFunctionHeader(Reactor r, + public static String generateDeadlineFunctionHeader(TypeParameterizedReactor tpr, int reactionIndex) { - String functionName = generateDeadlineFunctionName(r, reactionIndex); + String functionName = generateDeadlineFunctionName(tpr, reactionIndex); return generateFunctionHeader(functionName); } /** Return the top level C function header for the reaction numbered "reactionIndex" in "r" - * @param r The reactor declaration + * @param tpr The reactor declaration * @param reactionIndex The reaction index. * @return The function name for the reaction. */ - public static String generateReactionFunctionHeader(Reactor r, + public static String generateReactionFunctionHeader(TypeParameterizedReactor tpr, int reactionIndex) { - String functionName = generateReactionFunctionName(r, reactionIndex); + String functionName = generateReactionFunctionName(tpr, reactionIndex); return generateFunctionHeader(functionName); } - public static String generateStpFunctionHeader(Reactor r, + public static String generateStpFunctionHeader(TypeParameterizedReactor tpr, int reactionIndex) { - String functionName = generateStpFunctionName(r, reactionIndex); + String functionName = generateStpFunctionName(tpr, reactionIndex); return generateFunctionHeader(functionName); } diff --git a/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java b/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java index 92318c0150..041baab112 100644 --- a/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java @@ -43,10 +43,10 @@ private static String generateHeaderFile(CTypes types, TypeParameterizedReactor appendIncludeGuard(builder, tpr.r()); builder.pr(topLevelPreamble); appendPoundIncludes(builder); - appendSelfStruct(builder, types, tpr.r()); + appendSelfStruct(builder, types, tpr); generator.generate(builder, tpr, true); for (Reaction reaction : tpr.r().getReactions()) { - appendSignature(builder, types, reaction, tpr.r()); + appendSignature(builder, types, reaction, tpr); } builder.pr("#endif"); return builder.getCode(); @@ -71,40 +71,40 @@ private static void appendPoundIncludes(CodeBuilder builder) { """); } - private static String userFacingSelfType(Reactor r) { - return r.getName().toLowerCase() + "_self_t"; + private static String userFacingSelfType(TypeParameterizedReactor tpr) { + return tpr.getName().toLowerCase() + "_self_t"; } - private static void appendSelfStruct(CodeBuilder builder, CTypes types, Reactor r) { - builder.pr("typedef struct " + userFacingSelfType(r) + "{"); - for (Parameter p : r.getParameters()) { + private static void appendSelfStruct(CodeBuilder builder, CTypes types, TypeParameterizedReactor tpr) { + builder.pr("typedef struct " + userFacingSelfType(tpr) + "{"); + for (Parameter p : tpr.r().getParameters()) { builder.pr(types.getTargetType(p) + " " + p.getName() + ";"); } - for (StateVar s : r.getStateVars()) { + for (StateVar s : tpr.r().getStateVars()) { builder.pr(types.getTargetType(s) + " " + s.getName() + ";"); } builder.pr("int end[0]; // placeholder; MSVC does not compile empty structs"); - builder.pr("} " + userFacingSelfType(r) + ";"); + builder.pr("} " + userFacingSelfType(tpr) + ";"); } - private static void appendSignature(CodeBuilder builder, CTypes types, Reaction r, Reactor reactor) { - if (r.getName() != null) builder.pr("void " + r.getName() + "(" + reactionParameters(types, r, reactor) + ");"); + private static void appendSignature(CodeBuilder builder, CTypes types, Reaction r, TypeParameterizedReactor tpr) { + if (r.getName() != null) builder.pr("void " + r.getName() + "(" + reactionParameters(types, r, tpr) + ");"); } - private static String reactionParameters(CTypes types, Reaction r, Reactor reactor) { - return Stream.concat(Stream.of(userFacingSelfType(reactor) + "* self"), ioTypedVariableStream(r) - .map((tv) -> reactor.getName().toLowerCase() + "_" + tv.getName() + "_t* " + tv.getName())) + private static String reactionParameters(CTypes types, Reaction r, TypeParameterizedReactor tpr) { + return Stream.concat(Stream.of(userFacingSelfType(tpr) + "* self"), ioTypedVariableStream(r) + .map((tv) -> tpr.getName().toLowerCase() + "_" + tv.getName() + "_t* " + tv.getName())) .collect(Collectors.joining(", ")); } - public static String reactionArguments(CTypes types, Reaction r, Reactor reactor) { - return Stream.concat(Stream.of(getApiSelfStruct(reactor)), ioTypedVariableStream(r) - .map(it -> String.format("((%s*) %s)", CGenerator.variableStructType(it, reactor, true), it.getName()))) + public static String reactionArguments(CTypes types, Reaction r, TypeParameterizedReactor tpr) { + return Stream.concat(Stream.of(getApiSelfStruct(tpr)), ioTypedVariableStream(r) + .map(it -> String.format("((%s*) %s)", CGenerator.variableStructType(it, tpr, true), it.getName()))) .collect(Collectors.joining(", ")); } - private static String getApiSelfStruct(Reactor reactor) { - return "(" + userFacingSelfType(reactor) + "*) (((char*) self) + sizeof(self_base_t))"; + private static String getApiSelfStruct(TypeParameterizedReactor tpr) { + return "(" + userFacingSelfType(tpr) + "*) (((char*) self) + sizeof(self_base_t))"; } private static Stream ioTypedVariableStream(Reaction r) { diff --git a/org.lflang/src/org/lflang/generator/c/CUtil.java b/org.lflang/src/org/lflang/generator/c/CUtil.java index 15097b6205..418c87157b 100644 --- a/org.lflang/src/org/lflang/generator/c/CUtil.java +++ b/org.lflang/src/org/lflang/generator/c/CUtil.java @@ -529,12 +529,6 @@ public static String selfType(TypeParameterizedReactor reactor) { } return "_" + CUtil.getName(reactor) + "_self_t"; } - public static String selfType(Reactor reactor) { - if (reactor.isMain()) { - return "_" + CUtil.getName(reactor) + "_main_self_t"; - } - return "_" + CUtil.getName(reactor) + "_self_t"; - } /** Construct a unique type for the "self" struct of the class of the given reactor. */ public static String selfType(ReactorInstance instance) { diff --git a/org.lflang/src/org/lflang/generator/python/PythonGenerator.java b/org.lflang/src/org/lflang/generator/python/PythonGenerator.java index 6a1a6ecd1d..e0ef28c192 100644 --- a/org.lflang/src/org/lflang/generator/python/PythonGenerator.java +++ b/org.lflang/src/org/lflang/generator/python/PythonGenerator.java @@ -352,28 +352,28 @@ public void processProtoFile(String filename) { /** * Generate the aliases for inputs, outputs, and struct type definitions for * actions of the specified reactor in the specified federate. - * @param r The parsed reactor data structure. + * @param tpr The parsed reactor data structure. */ @Override public void generateAuxiliaryStructs( CodeBuilder builder, TypeParameterizedReactor tpr, boolean userFacing ) { for (Input input : ASTUtils.allInputs(tpr.r())) { - generateAuxiliaryStructsForPort(builder, tpr.r(), input); + generateAuxiliaryStructsForPort(builder, tpr, input); } for (Output output : ASTUtils.allOutputs(tpr.r())) { - generateAuxiliaryStructsForPort(builder, tpr.r(), output); + generateAuxiliaryStructsForPort(builder, tpr, output); } for (Action action : ASTUtils.allActions(tpr.r())) { generateAuxiliaryStructsForAction(builder, tpr, action); } } - private void generateAuxiliaryStructsForPort(CodeBuilder builder, Reactor r, + private void generateAuxiliaryStructsForPort(CodeBuilder builder, TypeParameterizedReactor tpr, Port port) { boolean isTokenType = CUtil.isTokenType(ASTUtils.getInferredType(port), types); builder.pr(port, - PythonPortGenerator.generateAliasTypeDef(r, port, isTokenType, + PythonPortGenerator.generateAliasTypeDef(tpr, port, isTokenType, genericPortType)); } @@ -455,19 +455,19 @@ protected PythonDockerGenerator getDockerGenerator(LFGeneratorContext context) { * a struct that contains parameters, state variables, inputs (triggering or not), * actions (triggering or produced), and outputs. * @param reaction The reaction. - * @param r The reactor. + * @param tpr The reactor. * @param reactionIndex The position of the reaction within the reactor. */ @Override - protected void generateReaction(CodeBuilder src, Reaction reaction, Reactor r, int reactionIndex) { - Reactor reactor = ASTUtils.toDefinition(r); + protected void generateReaction(CodeBuilder src, Reaction reaction, TypeParameterizedReactor tpr, int reactionIndex) { + Reactor reactor = ASTUtils.toDefinition(tpr.r()); // Reactions marked with a `@_c_body` attribute are generated in C if (AttributeUtils.hasCBody(reaction)) { - super.generateReaction(src, reaction, r, reactionIndex); + super.generateReaction(src, reaction, tpr, reactionIndex); return; } - src.pr(PythonReactionGenerator.generateCReaction(reaction, reactor, reactionIndex, mainDef, errorReporter, types)); + src.pr(PythonReactionGenerator.generateCReaction(reaction, tpr, reactor, reactionIndex, mainDef, errorReporter, types)); } /** @@ -504,7 +504,7 @@ protected void generateParameterInitialization(ReactorInstance instance) { * @see PythonMethodGenerator */ @Override - protected void generateMethods(CodeBuilder src, ReactorDecl reactor) { } + protected void generateMethods(CodeBuilder src, TypeParameterizedReactor reactor) { } /** * Generate C preambles defined by user for a given reactor @@ -540,7 +540,7 @@ protected void generateReactorInstanceExtension( /** * This function is provided to allow extensions of the CGenerator to append the structure of the self struct * @param selfStructBody The body of the self struct - * @param decl The reactor declaration for the self struct + * @param reactor The reactor declaration for the self struct * @param constructorCode Code that is executed when the reactor is instantiated */ @Override diff --git a/org.lflang/src/org/lflang/generator/python/PythonPortGenerator.java b/org.lflang/src/org/lflang/generator/python/PythonPortGenerator.java index 9e0919b52c..a5308798d6 100644 --- a/org.lflang/src/org/lflang/generator/python/PythonPortGenerator.java +++ b/org.lflang/src/org/lflang/generator/python/PythonPortGenerator.java @@ -1,5 +1,6 @@ package org.lflang.generator.python; +import org.lflang.generator.c.TypeParameterizedReactor; import org.lflang.lf.Input; import org.lflang.lf.Instantiation; import org.lflang.lf.Output; @@ -195,8 +196,8 @@ public static String generatePythonListForContainedBank(String reactorName, Port ); } - public static String generateAliasTypeDef(Reactor r, Port port, boolean isTokenType, String genericPortType) { - return "typedef "+genericPortType+" "+CGenerator.variableStructType(port, r, false)+";"; + public static String generateAliasTypeDef(TypeParameterizedReactor tpr, Port port, boolean isTokenType, String genericPortType) { + return "typedef "+genericPortType+" "+CGenerator.variableStructType(port, tpr, false)+";"; } private static String generateConvertCPortToPy(String port) { diff --git a/org.lflang/src/org/lflang/generator/python/PythonReactionGenerator.java b/org.lflang/src/org/lflang/generator/python/PythonReactionGenerator.java index bcc1beeaed..62dd65ff5f 100644 --- a/org.lflang/src/org/lflang/generator/python/PythonReactionGenerator.java +++ b/org.lflang/src/org/lflang/generator/python/PythonReactionGenerator.java @@ -12,6 +12,7 @@ import org.lflang.Target; import org.lflang.generator.c.CReactionGenerator; +import org.lflang.generator.c.TypeParameterizedReactor; import org.lflang.lf.ReactorDecl; import org.lflang.lf.Reaction; import org.lflang.lf.Reactor; @@ -127,6 +128,7 @@ private static String generateCPythonFunctionCaller(String reactorDeclName, */ public static String generateCReaction( Reaction reaction, + TypeParameterizedReactor tpr, Reactor r, int reactionIndex, Instantiation mainDef, @@ -139,14 +141,14 @@ public static String generateCReaction( CodeBuilder code = new CodeBuilder(); String cPyInit = generateCPythonInitializers(reaction, r, pyObjects, errorReporter); String cInit = CReactionGenerator.generateInitializationForReaction( - "", reaction, r, reactionIndex, + "", reaction, tpr, reactionIndex, types, errorReporter, mainDef, Target.Python.requiresTypes); code.pr( "#include " + StringUtil.addDoubleQuotes( CCoreFilesUtils.getCTargetSetHeader())); code.pr(generateFunction( - CReactionGenerator.generateReactionFunctionHeader(r, reactionIndex), + CReactionGenerator.generateReactionFunctionHeader(tpr, reactionIndex), cInit, reaction.getCode(), generateCPythonReactionCaller(r, reactionIndex, pyObjects, cPyInit) )); @@ -154,7 +156,7 @@ public static String generateCReaction( // Generate code for the STP violation handler, if there is one. if (reaction.getStp() != null) { code.pr(generateFunction( - CReactionGenerator.generateStpFunctionHeader(r, reactionIndex), + CReactionGenerator.generateStpFunctionHeader(tpr, reactionIndex), cInit, reaction.getStp().getCode(), generateCPythonSTPCaller(r, reactionIndex, pyObjects) )); @@ -162,7 +164,7 @@ public static String generateCReaction( // Generate code for the deadline violation function, if there is one. if (reaction.getDeadline() != null) { code.pr(generateFunction( - CReactionGenerator.generateDeadlineFunctionHeader(r, reactionIndex), + CReactionGenerator.generateDeadlineFunctionHeader(tpr, reactionIndex), cInit, reaction.getDeadline().getCode(), generateCPythonDeadlineCaller(r, reactionIndex, pyObjects) )); diff --git a/org.lflang/src/org/lflang/generator/python/PythonReactorGenerator.java b/org.lflang/src/org/lflang/generator/python/PythonReactorGenerator.java index fd954ca956..e95e9766bd 100644 --- a/org.lflang/src/org/lflang/generator/python/PythonReactorGenerator.java +++ b/org.lflang/src/org/lflang/generator/python/PythonReactorGenerator.java @@ -34,7 +34,7 @@ public static String generatePythonClass(ReactorInstance instance, CodeBuilder pythonClasses = new CodeBuilder(); ReactorDecl decl = instance.getDefinition().getReactorClass(); Reactor reactor = ASTUtils.toDefinition(decl); - String className = PyUtil.getName(reactor); + String className = PyUtil.getName(instance.tpr); if (instantiatedClasses == null) { return ""; } @@ -113,7 +113,7 @@ public static String generatePythonClassInstantiations(ReactorInstance instance, ReactorInstance main) { CodeBuilder code = new CodeBuilder(); - String className = PyUtil.getName(instance.reactorDefinition); + String className = PyUtil.getName(instance.tpr); if (instance.getWidth() > 0) { // For each reactor instance, create a list regardless of whether it is a bank or not. diff --git a/org.lflang/src/org/lflang/validation/LFValidator.java b/org.lflang/src/org/lflang/validation/LFValidator.java index 394250d22c..7af840de3d 100644 --- a/org.lflang/src/org/lflang/validation/LFValidator.java +++ b/org.lflang/src/org/lflang/validation/LFValidator.java @@ -239,9 +239,9 @@ public void checkConnection(Connection connection) { } else { // Unfortunately, xtext does not generate a suitable equals() // method for AST types, so we have to manually check the types. - if (!sameType(type, ((Port) port.getVariable()).getType())) { - error("Types do not match.", Literals.CONNECTION__LEFT_PORTS); - } +// if (!sameType(type, ((Port) port.getVariable()).getType())) { +// error("Types do not match.", Literals.CONNECTION__LEFT_PORTS); +// } } } } @@ -252,9 +252,9 @@ public void checkConnection(Connection connection) { if (type == null) { type = ((Port) port.getVariable()).getType(); } else { - if (!sameType(type, type = ((Port) port.getVariable()).getType())) { - error("Types do not match.", Literals.CONNECTION__RIGHT_PORTS); - } +// if (!sameType(type, type = ((Port) port.getVariable()).getType())) { +// error("Types do not match.", Literals.CONNECTION__RIGHT_PORTS); +// } } } } From 4af90402d6fee68c42828edf1fb086452f2167c1 Mon Sep 17 00:00:00 2001 From: mkhubaibumer Date: Thu, 30 Mar 2023 17:03:09 +0500 Subject: [PATCH 05/54] [C-Generics] Working Generic Code Basic implementation for Generic Reactors in C-Target are done We can run the following Generic Code for demonstration of this feature. ``` target C { keepalive: true, cmake-include: [ "../lib/lib.cmake" ], files: [ "../lib/convertor.h", "../lib/convertor.c" ] } preamble {= =} reactor Connector(latency:int(0)) { input in:I; output out:O; logical action delayed_sch; reaction(in) -> delayed_sch {= lf_schedule(delayed_sch, self->latency); =} reaction(delayed_sch) in -> out {= if (is_same_type(in->value, out->value)) { lf_set(out, in->value); } else { auto_t tmp = CALL_CONVERTOR(I, O, in->value); lf_set(out, tmp); } =} } reactor A { output Aout:int; logical action post; timer t(0, 1sec); reaction(t) -> post {= lf_schedule(post, 2); =} reaction(post) -> Aout {= lf_set(Aout, rand()); =} } reactor B { input Bin:float; reaction(Bin) {= printf("got %f\n", Bin->value); =} } main reactor { a = new A(); w = new Connector(latency=500); b = new B(); a.Aout -> w.in; w.out -> b.Bin; } ``` Complete Working example can be fetched from: https://github.com/MagnitionIO/LF_Collaboration/blob/main/CGenericsProposal/src/CGenerics.lf Signed-off-by: mkhubaibumer --- org.lflang/src/lib/c/reactor-c | 2 +- .../src/org/lflang/generator/c/CCoreFilesUtils.java | 3 ++- org.lflang/src/org/lflang/generator/c/CGenerator.java | 8 +++++--- .../lflang/generator/c/CReactorHeaderFileGenerator.java | 9 +++++---- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/org.lflang/src/lib/c/reactor-c b/org.lflang/src/lib/c/reactor-c index d43e973780..f9dd92f15b 160000 --- a/org.lflang/src/lib/c/reactor-c +++ b/org.lflang/src/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit d43e9737804f2d984d52a99cac20d8e57adad543 +Subproject commit f9dd92f15b89ee57545b983bed45362a53a3375b diff --git a/org.lflang/src/org/lflang/generator/c/CCoreFilesUtils.java b/org.lflang/src/org/lflang/generator/c/CCoreFilesUtils.java index 46503d87cc..6022110943 100644 --- a/org.lflang/src/org/lflang/generator/c/CCoreFilesUtils.java +++ b/org.lflang/src/org/lflang/generator/c/CCoreFilesUtils.java @@ -18,7 +18,8 @@ public static List getCTargetSrc() { public static List getCTargetHeader() { return List.of( - "include/api/api.h" + "include/api/api.h", + "include/api/generics.h" ); } diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index b9fc9e57dc..bb0944d389 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -1048,18 +1048,20 @@ protected void generateReactorClassHeaders(TypeParameterizedReactor tpr, String src.pr("extern \"C\" {"); header.pr("extern \"C\" {"); } - tpr.typeArgs().entrySet().forEach(it -> header.pr("#define " + it.getKey() + " " + ASTUtils.toText(it.getValue()))); + tpr.typeArgs().forEach((literal, concreteType) -> header.pr( + "#define " + literal + " " + ASTUtils.toText(concreteType))); header.pr("#include \"include/core/reactor.h\""); src.pr("#include \"include/api/api.h\""); src.pr("#include \"include/api/set.h\""); + src.pr("#include \"include/api/generics.h\""); generateIncludes(tpr); if (CCppMode) { src.pr("}"); header.pr("}"); } - src.pr("#include \"include/" + CReactorHeaderFileGenerator.outputPath(fileConfig, tpr.r()) + "\""); src.pr("#include \"" + headerName + "\""); - tpr.typeArgs().entrySet().forEach(it -> src.pr("#define " + it.getKey() + " " + ASTUtils.toText(it.getValue()))); + tpr.typeArgs().forEach((literal, concreteType) -> src.pr( + "#define " + literal + " " + ASTUtils.toText(concreteType))); new HashSet<>(ASTUtils.allInstantiations(tpr.r())).stream() .map(TypeParameterizedReactor::new).map(CUtil::getName) .map(name -> "#include \"" + name + ".h\"") diff --git a/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java b/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java index 041baab112..9c820cd87c 100644 --- a/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java @@ -28,15 +28,15 @@ public interface GenerateAuxiliaryStructs { void generate(CodeBuilder b, TypeParameterizedReactor r, boolean userFacing); } - public static Path outputPath(CFileConfig fileConfig, Reactor r) { - return Path.of(Path.of(r.eResource().getURI().toFileString()) + public static Path outputPath(CFileConfig fileConfig, TypeParameterizedReactor tpr) { + return Path.of(Path.of(tpr.r().eResource().getURI().toFileString()) .getFileName().toString().replaceFirst("[.][^.]+$", "")) - .resolve(r.getName() + ".h"); + .resolve(tpr.getName() + ".h"); } public static void doGenerate(CTypes types, TypeParameterizedReactor tpr, CFileConfig fileConfig, GenerateAuxiliaryStructs generator, Function topLevelPreamble) throws IOException { String contents = generateHeaderFile(types, tpr, generator, topLevelPreamble.apply(tpr.r())); - FileUtil.writeToFile(contents, fileConfig.getIncludePath().resolve(outputPath(fileConfig, tpr.r()))); + FileUtil.writeToFile(contents, fileConfig.getIncludePath().resolve(outputPath(fileConfig, tpr))); } private static String generateHeaderFile(CTypes types, TypeParameterizedReactor tpr, GenerateAuxiliaryStructs generator, String topLevelPreamble) { CodeBuilder builder = new CodeBuilder(); @@ -64,6 +64,7 @@ private static void appendPoundIncludes(CodeBuilder builder) { #endif #include "../include/api/api.h" #include "../include/api/set.h" + #include "../include/api/generics.h" #include "../include/core/reactor.h" #ifdef __cplusplus } From 7208c8f2b4bf5056eeddefbf92359125a5f9a65c Mon Sep 17 00:00:00 2001 From: mkhubaibumer Date: Fri, 31 Mar 2023 15:51:16 +0500 Subject: [PATCH 06/54] [C-Generics] Moved type-converter macro to utils Signed-off-by: mkhubaibumer --- org.lflang/src/lib/c/reactor-c | 2 +- org.lflang/src/org/lflang/generator/c/CCoreFilesUtils.java | 3 ++- org.lflang/src/org/lflang/generator/c/CGenerator.java | 1 + .../org/lflang/generator/c/CReactorHeaderFileGenerator.java | 3 ++- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/org.lflang/src/lib/c/reactor-c b/org.lflang/src/lib/c/reactor-c index f9dd92f15b..c1ba14d32a 160000 --- a/org.lflang/src/lib/c/reactor-c +++ b/org.lflang/src/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit f9dd92f15b89ee57545b983bed45362a53a3375b +Subproject commit c1ba14d32a1288356609d59e9631286da52c9fee diff --git a/org.lflang/src/org/lflang/generator/c/CCoreFilesUtils.java b/org.lflang/src/org/lflang/generator/c/CCoreFilesUtils.java index 6022110943..c2ef81bf1d 100644 --- a/org.lflang/src/org/lflang/generator/c/CCoreFilesUtils.java +++ b/org.lflang/src/org/lflang/generator/c/CCoreFilesUtils.java @@ -19,7 +19,8 @@ public static List getCTargetSrc() { public static List getCTargetHeader() { return List.of( "include/api/api.h", - "include/api/generics.h" + "include/api/generics.h", + "include/utils/type_converter.h" ); } diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index bb0944d389..6cb187710a 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -1054,6 +1054,7 @@ protected void generateReactorClassHeaders(TypeParameterizedReactor tpr, String src.pr("#include \"include/api/api.h\""); src.pr("#include \"include/api/set.h\""); src.pr("#include \"include/api/generics.h\""); + src.pr("#include \"include/utils/type_converter.h\""); generateIncludes(tpr); if (CCppMode) { src.pr("}"); diff --git a/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java b/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java index 9c820cd87c..6bdb08f5a9 100644 --- a/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java @@ -65,7 +65,8 @@ private static void appendPoundIncludes(CodeBuilder builder) { #include "../include/api/api.h" #include "../include/api/set.h" #include "../include/api/generics.h" - #include "../include/core/reactor.h" + #include "../include/utils/type_converter.h" + #include "../include/core/reactor.h" #ifdef __cplusplus } #endif From 6477a99bd19260d7f58d4a3e4f88608095e0b063 Mon Sep 17 00:00:00 2001 From: mkhubaibumer Date: Fri, 31 Mar 2023 15:51:16 +0500 Subject: [PATCH 07/54] [C-Generics] Moved type-converter macro to utils Signed-off-by: mkhubaibumer --- org.lflang/src/lib/c/reactor-c | 2 +- org.lflang/src/org/lflang/generator/c/CCoreFilesUtils.java | 3 ++- org.lflang/src/org/lflang/generator/c/CGenerator.java | 1 + .../org/lflang/generator/c/CReactorHeaderFileGenerator.java | 3 ++- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/org.lflang/src/lib/c/reactor-c b/org.lflang/src/lib/c/reactor-c index f9dd92f15b..c1ba14d32a 160000 --- a/org.lflang/src/lib/c/reactor-c +++ b/org.lflang/src/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit f9dd92f15b89ee57545b983bed45362a53a3375b +Subproject commit c1ba14d32a1288356609d59e9631286da52c9fee diff --git a/org.lflang/src/org/lflang/generator/c/CCoreFilesUtils.java b/org.lflang/src/org/lflang/generator/c/CCoreFilesUtils.java index 6022110943..c2ef81bf1d 100644 --- a/org.lflang/src/org/lflang/generator/c/CCoreFilesUtils.java +++ b/org.lflang/src/org/lflang/generator/c/CCoreFilesUtils.java @@ -19,7 +19,8 @@ public static List getCTargetSrc() { public static List getCTargetHeader() { return List.of( "include/api/api.h", - "include/api/generics.h" + "include/api/generics.h", + "include/utils/type_converter.h" ); } diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index bb0944d389..6cb187710a 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -1054,6 +1054,7 @@ protected void generateReactorClassHeaders(TypeParameterizedReactor tpr, String src.pr("#include \"include/api/api.h\""); src.pr("#include \"include/api/set.h\""); src.pr("#include \"include/api/generics.h\""); + src.pr("#include \"include/utils/type_converter.h\""); generateIncludes(tpr); if (CCppMode) { src.pr("}"); diff --git a/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java b/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java index 9c820cd87c..6bdb08f5a9 100644 --- a/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java @@ -65,7 +65,8 @@ private static void appendPoundIncludes(CodeBuilder builder) { #include "../include/api/api.h" #include "../include/api/set.h" #include "../include/api/generics.h" - #include "../include/core/reactor.h" + #include "../include/utils/type_converter.h" + #include "../include/core/reactor.h" #ifdef __cplusplus } #endif From 38e0758838320c8bc76dd52de169c96eb99778f8 Mon Sep 17 00:00:00 2001 From: mkhubaibumer Date: Fri, 31 Mar 2023 16:14:48 +0500 Subject: [PATCH 08/54] Update submodule ref --- org.lflang/src/lib/c/reactor-c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.lflang/src/lib/c/reactor-c b/org.lflang/src/lib/c/reactor-c index c1ba14d32a..866b189a4f 160000 --- a/org.lflang/src/lib/c/reactor-c +++ b/org.lflang/src/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit c1ba14d32a1288356609d59e9631286da52c9fee +Subproject commit 866b189a4f04d3fae7a50a256b8ca3686ea1c509 From b59b3b7474caf09d189255fdf41990a7cd5615fb Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Fri, 31 Mar 2023 13:44:05 -0700 Subject: [PATCH 09/54] Temporarily remove the generics headers. --- org.lflang/src/org/lflang/generator/c/CCoreFilesUtils.java | 4 +--- org.lflang/src/org/lflang/generator/c/CGenerator.java | 2 -- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/org.lflang/src/org/lflang/generator/c/CCoreFilesUtils.java b/org.lflang/src/org/lflang/generator/c/CCoreFilesUtils.java index c2ef81bf1d..46503d87cc 100644 --- a/org.lflang/src/org/lflang/generator/c/CCoreFilesUtils.java +++ b/org.lflang/src/org/lflang/generator/c/CCoreFilesUtils.java @@ -18,9 +18,7 @@ public static List getCTargetSrc() { public static List getCTargetHeader() { return List.of( - "include/api/api.h", - "include/api/generics.h", - "include/utils/type_converter.h" + "include/api/api.h" ); } diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index acaef65b99..2d3c6e79e7 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -1062,8 +1062,6 @@ protected void generateReactorClassHeaders(TypeParameterizedReactor tpr, String header.pr("#include \"include/core/reactor.h\""); src.pr("#include \"include/api/api.h\""); src.pr("#include \"include/api/set.h\""); - src.pr("#include \"include/api/generics.h\""); - src.pr("#include \"include/utils/type_converter.h\""); generateIncludes(tpr); if (CCppMode) { src.pr("}"); From a55a886c5dd69d4025f37f7e3d5873d38d3d1097 Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Fri, 31 Mar 2023 15:12:29 -0700 Subject: [PATCH 10/54] Update submodule. --- org.lflang/src/lib/c/reactor-c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.lflang/src/lib/c/reactor-c b/org.lflang/src/lib/c/reactor-c index ac3d19a58a..ac05b8ebc8 160000 --- a/org.lflang/src/lib/c/reactor-c +++ b/org.lflang/src/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit ac3d19a58ad86dd57c14b2505289f64b8c651d79 +Subproject commit ac05b8ebc8aec4d5596ade92e39429846af51d45 From 25aace4fe165a7f59967c56420db4fa71ecc1ba6 Mon Sep 17 00:00:00 2001 From: mkhubaibumer Date: Tue, 4 Apr 2023 21:09:09 +0500 Subject: [PATCH 11/54] [C-Generics] Updates for resolving Actions/StateVariables typenames to concrete types Updates to remove COrresponding tags for declerations Signed-off-by: mkhubaibumer --- .../org/lflang/generator/c/CGenerator.java | 34 +++++++++++-------- .../generator/c/CParameterGenerator.java | 8 ++--- .../lflang/generator/c/CPortGenerator.java | 6 ++-- .../generator/c/CReactionGenerator.java | 16 ++++----- .../lflang/generator/c/CStateGenerator.java | 6 ++-- .../src/org/lflang/generator/c/CUtil.java | 18 ++++++++++ .../c/InteractingContainedReactors.java | 1 + .../generator/c/TypeParameterizedReactor.java | 2 +- 8 files changed, 55 insertions(+), 36 deletions(-) diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index 6cb187710a..611edf7c62 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -1048,8 +1048,6 @@ protected void generateReactorClassHeaders(TypeParameterizedReactor tpr, String src.pr("extern \"C\" {"); header.pr("extern \"C\" {"); } - tpr.typeArgs().forEach((literal, concreteType) -> header.pr( - "#define " + literal + " " + ASTUtils.toText(concreteType))); header.pr("#include \"include/core/reactor.h\""); src.pr("#include \"include/api/api.h\""); src.pr("#include \"include/api/set.h\""); @@ -1062,11 +1060,19 @@ protected void generateReactorClassHeaders(TypeParameterizedReactor tpr, String } src.pr("#include \"" + headerName + "\""); tpr.typeArgs().forEach((literal, concreteType) -> src.pr( - "#define " + literal + " " + ASTUtils.toText(concreteType))); + "#if defined " + literal + "\n" + + "#undef " + literal + "\n" + + "#endif // " + literal + "\n" + + "#define " + literal + " " + ASTUtils.toOriginalText(concreteType))); new HashSet<>(ASTUtils.allInstantiations(tpr.r())).stream() .map(TypeParameterizedReactor::new).map(CUtil::getName) .map(name -> "#include \"" + name + ".h\"") .forEach(header::pr); + tpr.typeArgs().forEach((literal, concreteType) -> header.pr( + "#if defined " + literal + "\n" + + "#undef " + literal + "\n" + + "#endif // " + literal + "\n" + + "#define " + literal + " " + ASTUtils.toOriginalText(concreteType))); } private void generateReactorClassBody(TypeParameterizedReactor tpr, CodeBuilder header, CodeBuilder src) { @@ -1186,10 +1192,10 @@ private void generateSelfStruct(CodeBuilder builder, TypeParameterizedReactor tp generateSelfStructExtension(body, reactor, constructorCode); // Next handle parameters. - body.pr(CParameterGenerator.generateDeclarations(reactor, types)); + body.pr(CParameterGenerator.generateDeclarations(tpr, types)); // Next handle states. - body.pr(CStateGenerator.generateDeclarations(reactor, types)); + body.pr(CStateGenerator.generateDeclarations(tpr, types)); // Next handle actions. CActionGenerator.generateDeclarations(tpr, body, constructorCode); @@ -1204,13 +1210,12 @@ private void generateSelfStruct(CodeBuilder builder, TypeParameterizedReactor tp // struct has a place to hold the data produced by this reactor's // reactions and a place to put pointers to data produced by // the contained reactors. - generateInteractingContainedReactors(tpr, reactor, body, constructorCode); + generateInteractingContainedReactors(tpr, body, constructorCode); // Next, generate the fields needed for each reaction. CReactionGenerator.generateReactionAndTriggerStructs( body, tpr, - reactor, constructorCode, types ); @@ -1241,20 +1246,18 @@ private void generateSelfStruct(CodeBuilder builder, TypeParameterizedReactor tp * reactions and a place to put pointers to data produced by * the contained reactors. * - * @param tpr The TypeParameterized Reactor - * @param reactor The reactor. + * @param tpr {@link TypeParameterizedReactor} * @param body The place to put the struct definition for the contained reactors. * @param constructorCode The place to put matching code that goes in the container's constructor. */ private void generateInteractingContainedReactors( TypeParameterizedReactor tpr, - Reactor reactor, CodeBuilder body, CodeBuilder constructorCode ) { // The contents of the struct will be collected first so that // we avoid duplicate entries and then the struct will be constructed. - var contained = new InteractingContainedReactors(reactor); + var contained = new InteractingContainedReactors(tpr.r()); // Next generate the relevant code. for (Instantiation containedReactor : contained.containedReactors()) { Reactor containedReactorType = ASTUtils.toDefinition(containedReactor.getReactorClass()); @@ -1285,12 +1288,12 @@ private void generateInteractingContainedReactors( // to be malloc'd at initialization. if (!ASTUtils.isMultiport(port)) { // Not a multiport. - body.pr(port, variableStructType(port, tpr, false)+" "+port.getName()+";"); + body.pr(port, variableStructType(port, containedReactorType, false)+" "+port.getName()+";"); } else { // Is a multiport. // Memory will be malloc'd in initialization. body.pr(port, String.join("\n", - variableStructType(port, tpr, false)+"** "+port.getName()+";", + variableStructType(port, containedReactorType, false)+"** "+port.getName()+";", "int "+port.getName()+"_width;" )); } @@ -1300,13 +1303,13 @@ private void generateInteractingContainedReactors( // self struct of the container. if (!ASTUtils.isMultiport(port)) { // Not a multiport. - body.pr(port, variableStructType(port, tpr, false)+"* "+port.getName()+";"); + body.pr(port, variableStructType(port, containedReactorType, false)+"* "+port.getName()+";"); } else { // Is a multiport. // Here, we will use an array of pointers. // Memory will be malloc'd in initialization. body.pr(port, String.join("\n", - variableStructType(port, tpr, false)+"** "+port.getName()+";", + variableStructType(port, containedReactorType, false)+"** "+port.getName()+";", "int "+port.getName()+"_width;" )); } @@ -1769,6 +1772,7 @@ private void generateInitializeActionToken(ReactorInstance reactor) { if (CUtil.isTokenType(type, types)) { typeStr = CUtil.rootType(typeStr); } + typeStr = CUtil.getConcreteType(reactor.tpr, typeStr); if (typeStr != null && !typeStr.equals("") && !typeStr.equals("void")) { payloadSize = "sizeof("+typeStr+")"; } diff --git a/org.lflang/src/org/lflang/generator/c/CParameterGenerator.java b/org.lflang/src/org/lflang/generator/c/CParameterGenerator.java index 23906eae73..70038648e9 100644 --- a/org.lflang/src/org/lflang/generator/c/CParameterGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CParameterGenerator.java @@ -76,14 +76,14 @@ public static String getInitializer(ParameterInstance p) { /** * Generate code for parameters variables of a reactor in the form "parameter.type parameter.name;" - * @param reactor The reactor + * @param reactor {@link TypeParameterizedReactor} * @param types A helper class for types */ - public static String generateDeclarations(Reactor reactor, CTypes types) { + public static String generateDeclarations(TypeParameterizedReactor reactor, CTypes types) { CodeBuilder code = new CodeBuilder(); - for (Parameter parameter : ASTUtils.allParameters(reactor)) { + for (Parameter parameter : ASTUtils.allParameters(reactor.r())) { code.prSourceLineNumber(parameter); - code.pr(types.getTargetType(parameter) + " " + parameter.getName() + ";"); + code.pr(CUtil.getConcreteType(reactor, types.getTargetType(parameter)) + " " + parameter.getName() + ";"); } return code.toString(); } diff --git a/org.lflang/src/org/lflang/generator/c/CPortGenerator.java b/org.lflang/src/org/lflang/generator/c/CPortGenerator.java index accda01fb1..5e6320dbfb 100644 --- a/org.lflang/src/org/lflang/generator/c/CPortGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CPortGenerator.java @@ -33,8 +33,8 @@ public static void generateDeclarations( CodeBuilder body, CodeBuilder constructorCode ) { - generateInputDeclarations(tpr, decl, body, constructorCode); - generateOutputDeclarations(tpr, decl, body, constructorCode); + generateInputDeclarations(tpr, body, constructorCode); + generateOutputDeclarations(tpr, body, constructorCode); } /** @@ -198,7 +198,6 @@ private static String valueDeclaration( */ private static void generateInputDeclarations( TypeParameterizedReactor tpr, - ReactorDecl decl, CodeBuilder body, CodeBuilder constructorCode ) { @@ -237,7 +236,6 @@ private static void generateInputDeclarations( */ private static void generateOutputDeclarations( TypeParameterizedReactor tpr, - ReactorDecl decl, CodeBuilder body, CodeBuilder constructorCode ) { diff --git a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java index 3630df136f..a336752280 100644 --- a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java @@ -56,8 +56,6 @@ public static String generateInitializationForReaction(String body, ErrorReporter errorReporter, Instantiation mainDef, boolean requiresTypes) { - Reactor reactor = tpr.r(); - // Construct the reactionInitialization code to go into // the body of the function before the verbatim code. CodeBuilder reactionInitialization = new CodeBuilder(); @@ -129,7 +127,7 @@ public static String generateInitializationForReaction(String body, // No triggers are given, which means react to any input. // Declare an argument for every input. // NOTE: this does not include contained outputs. - for (Input input : reactor.getInputs()) { + for (Input input : tpr.r().getInputs()) { reactionInitialization.pr(generateInputVariablesInReaction(input, tpr, types)); } } @@ -164,7 +162,7 @@ public static String generateInitializationForReaction(String body, } } else if (effect.getVariable() instanceof Mode) { // Mode change effect - int idx = ASTUtils.allModes(reactor).indexOf((Mode)effect.getVariable()); + int idx = ASTUtils.allModes(tpr.r()).indexOf((Mode)effect.getVariable()); String name = effect.getVariable().getName(); if (idx >= 0) { reactionInitialization.pr( @@ -350,6 +348,7 @@ private static void generateVariablesForSendingToContainedReactors( Instantiation definition, Input input ) { + // TODO: Get reactorInstance or TPR from Instantiation CodeBuilder structBuilder = structs.get(definition); if (structBuilder == null) { structBuilder = new CodeBuilder(); @@ -672,7 +671,6 @@ public static String generateOutputVariablesInReaction( public static void generateReactionAndTriggerStructs( CodeBuilder body, TypeParameterizedReactor tpr, - Reactor reactor, CodeBuilder constructorCode, CTypes types ) { @@ -760,7 +758,7 @@ public static void generateReactionAndTriggerStructs( "self->_lf__reaction_"+reactionCount+".STP_handler = "+STPFunctionPointer+";", "self->_lf__reaction_"+reactionCount+".name = "+addDoubleQuotes("?")+";", reaction.eContainer() instanceof Mode ? - "self->_lf__reaction_"+reactionCount+".mode = &self->_lf__modes["+reactor.getModes().indexOf((Mode) reaction.eContainer())+"];" : + "self->_lf__reaction_"+reactionCount+".mode = &self->_lf__modes["+tpr.r().getModes().indexOf((Mode) reaction.eContainer())+"];" : "self->_lf__reaction_"+reactionCount+".mode = NULL;" )); // Increment the reactionCount even if the reaction is not in the federate @@ -770,7 +768,7 @@ public static void generateReactionAndTriggerStructs( // Next, create and initialize the trigger_t objects. // Start with the timers. - for (Timer timer : ASTUtils.allTimers(reactor)) { + for (Timer timer : ASTUtils.allTimers(tpr.r())) { createTriggerT(body, timer, triggerMap, constructorCode, types); // Since the self struct is allocated using calloc, there is no need to set falsy fields. constructorCode.pr("self->_lf__"+timer.getName()+".is_timer = true;"); @@ -791,7 +789,7 @@ public static void generateReactionAndTriggerStructs( } // Next handle actions. - for (Action action : ASTUtils.allActions(reactor)) { + for (Action action : ASTUtils.allActions(tpr.r())) { createTriggerT(body, action, triggerMap, constructorCode, types); var isPhysical = "true"; if (action.getOrigin().equals(ActionOrigin.LOGICAL)) { @@ -821,7 +819,7 @@ public static void generateReactionAndTriggerStructs( } // Next handle inputs. - for (Input input : ASTUtils.allInputs(reactor)) { + for (Input input : ASTUtils.allInputs(tpr.r())) { createTriggerT(body, input, triggerMap, constructorCode, types); } } diff --git a/org.lflang/src/org/lflang/generator/c/CStateGenerator.java b/org.lflang/src/org/lflang/generator/c/CStateGenerator.java index a0bcf28823..029648844d 100644 --- a/org.lflang/src/org/lflang/generator/c/CStateGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CStateGenerator.java @@ -18,11 +18,11 @@ public class CStateGenerator { * @param reactor The reactor * @param types A helper object for types */ - public static String generateDeclarations(Reactor reactor, CTypes types) { + public static String generateDeclarations(TypeParameterizedReactor reactor, CTypes types) { CodeBuilder code = new CodeBuilder(); - for (StateVar stateVar : ASTUtils.allStateVars(reactor)) { + for (StateVar stateVar : ASTUtils.allStateVars(reactor.r())) { code.prSourceLineNumber(stateVar); - code.pr(types.getTargetType(stateVar) + " " + stateVar.getName() + ";"); + code.pr(CUtil.getConcreteType(reactor, types.getTargetType(stateVar)) + " " + stateVar.getName() + ";"); } return code.toString(); } diff --git a/org.lflang/src/org/lflang/generator/c/CUtil.java b/org.lflang/src/org/lflang/generator/c/CUtil.java index 418c87157b..d5580cefa5 100644 --- a/org.lflang/src/org/lflang/generator/c/CUtil.java +++ b/org.lflang/src/org/lflang/generator/c/CUtil.java @@ -882,6 +882,24 @@ public static boolean isTokenType(InferredType type, CTypes types) { return type.isVariableSizeList || targetType.trim().endsWith("*"); } + /** + * Given a type we need to check if the type is Generic Type literal and if + * it is we need to find the corresponding concrete type + * + * @param tpr {@link TypeParameterizedReactor} + * @param type Actual typename + */ + public static String getConcreteType(TypeParameterizedReactor tpr, final String type) { + var wrapper = new Object() { String concreteType = ""; }; + tpr.typeArgs().forEach((literal, concreteType) -> { + if (type.equals(literal)) + { + wrapper.concreteType = String.valueOf(concreteType.getId()); + } + }); + return (wrapper.concreteType.isEmpty()) ? type : wrapper.concreteType; + } + public static String generateWidthVariable(String var) { return var + "_width"; } diff --git a/org.lflang/src/org/lflang/generator/c/InteractingContainedReactors.java b/org.lflang/src/org/lflang/generator/c/InteractingContainedReactors.java index 6fd6175a6f..bc4d6893a1 100644 --- a/org.lflang/src/org/lflang/generator/c/InteractingContainedReactors.java +++ b/org.lflang/src/org/lflang/generator/c/InteractingContainedReactors.java @@ -101,6 +101,7 @@ public InteractingContainedReactors(Reactor reactor) { * @param port The port. */ private List addPort(Instantiation containedReactor, Port port) { + var parent = containedReactor.eContainer(); // Get or create the entry for the containedReactor. var containedReactorEntry = portsByContainedReactor.computeIfAbsent( containedReactor, diff --git a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java index 281139c4af..a903d5e9ae 100644 --- a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java +++ b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java @@ -31,7 +31,7 @@ private static ImmutableMap addTypeArgs(Instantiation instantiatio public String getName() { // FIXME: Types that are not just a single token need to be escaped or hashed - return r.getName() + typeArgs.values().stream().map(ASTUtils::toText).collect(Collectors.joining("_")); + return r.getName() + typeArgs.values().stream().map(ASTUtils::toOriginalText).collect(Collectors.joining("_")); } @Override From 03ef8de3a973237bd8b3c1d7cf748e5187303a54 Mon Sep 17 00:00:00 2001 From: mkhubaibumer Date: Wed, 5 Apr 2023 15:17:49 +0500 Subject: [PATCH 12/54] [C-Generics] Contained Reactor type collission Defining template types in header can cause redefinitions in case of contained reactors using `#if defined/#undef/#define` construct can cause type collission as contained reactor can use the same template literals for different types than the parent reactor To solve this issue we decided to go for string substitution in header file to rersolve templated types to their respective concrete types and we'll still be using `#define` in scource files as the template types need to be defined as per instantiation in the source file Signed-off-by: mkhubaibumer --- .../src/org/lflang/generator/c/CActionGenerator.java | 6 ++++-- org.lflang/src/org/lflang/generator/c/CGenerator.java | 7 +------ org.lflang/src/org/lflang/generator/c/CPortGenerator.java | 5 +++-- .../src/org/lflang/generator/c/CReactionGenerator.java | 2 +- org.lflang/src/org/lflang/generator/c/CStateGenerator.java | 7 ++++--- org.lflang/src/org/lflang/generator/c/CTypes.java | 3 ++- org.lflang/src/org/lflang/generator/c/CUtil.java | 4 +++- 7 files changed, 18 insertions(+), 16 deletions(-) diff --git a/org.lflang/src/org/lflang/generator/c/CActionGenerator.java b/org.lflang/src/org/lflang/generator/c/CActionGenerator.java index e381ad9bae..2699f276c9 100644 --- a/org.lflang/src/org/lflang/generator/c/CActionGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CActionGenerator.java @@ -140,7 +140,7 @@ public static String generateAuxiliaryStruct( "bool has_value;", // From lf_action_base_t "trigger_t* trigger;" // From lf_action_base_t )); - code.pr(valueDeclaration(action, target, types)); + code.pr(valueDeclaration(tpr, action, target, types)); code.pr(federatedExtension.toString()); code.unindent(); code.pr("} " + variableStructType(action, tpr, userFacing) + ";"); @@ -155,10 +155,12 @@ public static String generateAuxiliaryStruct( * int* value; * ``` * This will return an empty string for an action with no type. + * @param tpr {@link TypeParameterizedReactor} * @param action The action. * @return A string providing the value field of the action struct. */ private static String valueDeclaration( + TypeParameterizedReactor tpr, Action action, Target target, CTypes types @@ -170,6 +172,6 @@ private static String valueDeclaration( // will be a separate field pointing to the token. return action.getType() == null && target.requiresTypes ? "" : - types.getTargetType(action) + " value;"; + CUtil.getConcreteType(tpr, types.getTargetType(action)) + " value;"; } } diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index 611edf7c62..d0791230be 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -1068,11 +1068,6 @@ protected void generateReactorClassHeaders(TypeParameterizedReactor tpr, String .map(TypeParameterizedReactor::new).map(CUtil::getName) .map(name -> "#include \"" + name + ".h\"") .forEach(header::pr); - tpr.typeArgs().forEach((literal, concreteType) -> header.pr( - "#if defined " + literal + "\n" + - "#undef " + literal + "\n" + - "#endif // " + literal + "\n" + - "#define " + literal + " " + ASTUtils.toOriginalText(concreteType))); } private void generateReactorClassBody(TypeParameterizedReactor tpr, CodeBuilder header, CodeBuilder src) { @@ -1878,7 +1873,7 @@ protected void generateParameterInitialization(ReactorInstance instance) { if (initializer.startsWith("{")) { var temporaryVariableName = parameter.uniqueID(); initializeTriggerObjects.pr(String.join("\n", - "static "+types.getVariableDeclaration(parameter.type, temporaryVariableName, true)+" = "+initializer+";", + "static "+types.getVariableDeclaration(instance.tpr, parameter.type, temporaryVariableName, true)+" = "+initializer+";", selfRef+"->"+parameter.getName()+" = "+temporaryVariableName+";" )); } else { diff --git a/org.lflang/src/org/lflang/generator/c/CPortGenerator.java b/org.lflang/src/org/lflang/generator/c/CPortGenerator.java index 5e6320dbfb..0177868f1d 100644 --- a/org.lflang/src/org/lflang/generator/c/CPortGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CPortGenerator.java @@ -73,7 +73,7 @@ public static String generateAuxiliaryStruct( "int destination_channel;", // From lf_port_base_t "int num_destinations;" // From lf_port_base_t )); - code.pr(valueDeclaration(port, target, errorReporter, types)); + code.pr(valueDeclaration(tpr, port, target, errorReporter, types)); code.pr(federatedExtension.toString()); code.unindent(); code.pr("} "+variableStructType(port, tpr, userFacing)+";"); @@ -172,6 +172,7 @@ public static String initializeOutputMultiport( * @return A string providing the value field of the port struct. */ private static String valueDeclaration( + TypeParameterizedReactor tpr, Port port, Target target, ErrorReporter errorReporter, @@ -184,7 +185,7 @@ private static String valueDeclaration( } // Do not convert to lf_token_t* using lfTypeToTokenType because there // will be a separate field pointing to the token. - return types.getVariableDeclaration(ASTUtils.getInferredType(port), "value", false) + ";"; + return types.getVariableDeclaration(tpr, ASTUtils.getInferredType(port), "value", false) + ";"; } /** diff --git a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java index a336752280..d54e54d5ee 100644 --- a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java @@ -665,7 +665,7 @@ public static String generateOutputVariablesInReaction( * specified reactor and a trigger_t struct for each trigger (input, action, * timer, or output of a contained reactor). * @param body The place to put the code for the self struct. - * @param reactor The reactor. + * @param tpr {@link TypeParameterizedReactor} * @param constructorCode The place to put the constructor code. */ public static void generateReactionAndTriggerStructs( diff --git a/org.lflang/src/org/lflang/generator/c/CStateGenerator.java b/org.lflang/src/org/lflang/generator/c/CStateGenerator.java index 029648844d..fc66036511 100644 --- a/org.lflang/src/org/lflang/generator/c/CStateGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CStateGenerator.java @@ -47,7 +47,7 @@ public static String generateInitializer( CTypes types ) { var initExpr = getInitializerExpr(stateVar, instance); - String baseInitializer = generateBaseInitializer(selfRef, stateVar, initExpr, types); + String baseInitializer = generateBaseInitializer(instance.tpr, selfRef, stateVar, initExpr, types); String modalReset = generateModalReset(instance, selfRef, stateVar, initExpr, mode, types); return String.join("\n", baseInitializer, @@ -56,6 +56,7 @@ public static String generateInitializer( } private static String generateBaseInitializer( + TypeParameterizedReactor tpr, String selfRef, StateVar stateVar, String initExpr, @@ -67,7 +68,7 @@ private static String generateBaseInitializer( ) { return selfRef + "->" + stateVar.getName() + " = " + initExpr + ";"; } else { - var declaration = types.getVariableDeclaration( + var declaration = types.getVariableDeclaration(tpr, ASTUtils.getInferredType(stateVar), "_initial", true); return String.join("\n", @@ -103,7 +104,7 @@ private static String generateModalReset( } else { CodeBuilder code = new CodeBuilder(); var source = "_initial"; - var declaration = types.getVariableDeclaration( + var declaration = types.getVariableDeclaration(instance.tpr, ASTUtils.getInferredType(stateVar), source, true); code.pr("{ // For scoping"); diff --git a/org.lflang/src/org/lflang/generator/c/CTypes.java b/org.lflang/src/org/lflang/generator/c/CTypes.java index 803d9e8432..ebb9c894f4 100644 --- a/org.lflang/src/org/lflang/generator/c/CTypes.java +++ b/org.lflang/src/org/lflang/generator/c/CTypes.java @@ -97,11 +97,12 @@ public String getTargetType(InferredType type) { * @param initializer True to return a form usable in a static initializer. */ public String getVariableDeclaration( + TypeParameterizedReactor tpr, InferredType type, String variableName, boolean initializer ) { - String t = TargetTypes.super.getTargetType(type); + String t = CUtil.getConcreteType(tpr, TargetTypes.super.getTargetType(type)); Matcher matcher = arrayPattern.matcher(t); String declaration = String.format("%s %s", t, variableName); if (matcher.find()) { diff --git a/org.lflang/src/org/lflang/generator/c/CUtil.java b/org.lflang/src/org/lflang/generator/c/CUtil.java index d5580cefa5..87f75133dd 100644 --- a/org.lflang/src/org/lflang/generator/c/CUtil.java +++ b/org.lflang/src/org/lflang/generator/c/CUtil.java @@ -878,7 +878,7 @@ private static List multiportWidthTerms(Variable variable) { public static boolean isTokenType(InferredType type, CTypes types) { if (type.isUndefined()) return false; // This is a hacky way to do this. It is now considered to be a bug (#657) - String targetType = types.getVariableDeclaration(type, "", false); + String targetType = types.getVariableDeclaration(null, type, "", false); return type.isVariableSizeList || targetType.trim().endsWith("*"); } @@ -890,6 +890,8 @@ public static boolean isTokenType(InferredType type, CTypes types) { * @param type Actual typename */ public static String getConcreteType(TypeParameterizedReactor tpr, final String type) { + if (tpr == null) + return type; var wrapper = new Object() { String concreteType = ""; }; tpr.typeArgs().forEach((literal, concreteType) -> { if (type.equals(literal)) From ad9a226e83590079fa07d66644da4bce44ca7f8c Mon Sep 17 00:00:00 2001 From: mkhubaibumer Date: Thu, 6 Apr 2023 21:00:16 +0500 Subject: [PATCH 13/54] [C-Generics] Basic Support for Contained Reactors Signed-off-by: mkhubaibumer --- org.lflang/src/org/lflang/ASTUtils.java | 6 ++- org.lflang/src/org/lflang/cli/Lfc.java | 2 + .../org/lflang/generator/ReactorInstance.java | 43 +++++++++++++--- .../org/lflang/generator/c/CGenerator.java | 26 +++++----- .../generator/c/CReactionGenerator.java | 49 ++++++++++--------- .../lflang/generator/c/CStateGenerator.java | 12 ++--- .../src/org/lflang/generator/c/CTypes.java | 2 +- .../src/org/lflang/generator/c/CUtil.java | 2 +- .../c/InteractingContainedReactors.java | 3 +- 9 files changed, 90 insertions(+), 55 deletions(-) diff --git a/org.lflang/src/org/lflang/ASTUtils.java b/org.lflang/src/org/lflang/ASTUtils.java index ed9daf5def..558e262a59 100644 --- a/org.lflang/src/org/lflang/ASTUtils.java +++ b/org.lflang/src/org/lflang/ASTUtils.java @@ -58,7 +58,9 @@ import org.lflang.ast.ToText; import org.lflang.generator.CodeMap; import org.lflang.generator.InvalidSourceException; +import org.lflang.generator.NamedInstance; import org.lflang.generator.ReactorInstance; +import org.lflang.generator.c.TypeParameterizedReactor; import org.lflang.lf.Action; import org.lflang.lf.Assignment; import org.lflang.lf.AttrParm; @@ -899,12 +901,12 @@ public static boolean isFloat(String literal) { return true; } - /** + /** * Report whether the given code is an integer number or not. * @param code AST node to inspect. * @return True if the given code is an integer, false otherwise. */ - public static boolean isInteger(Code code) { + public static boolean isInteger(Code code) { return isInteger(toText(code)); } diff --git a/org.lflang/src/org/lflang/cli/Lfc.java b/org.lflang/src/org/lflang/cli/Lfc.java index 489e9cd2f4..a510a7f2d5 100644 --- a/org.lflang/src/org/lflang/cli/Lfc.java +++ b/org.lflang/src/org/lflang/cli/Lfc.java @@ -18,6 +18,7 @@ import org.lflang.generator.LFGeneratorContext; import org.lflang.generator.LFGeneratorContext.BuildParm; import org.lflang.generator.MainContext; +import org.lflang.generator.ReactorInstance; import com.google.inject.Inject; @@ -201,6 +202,7 @@ private void invokeGenerator( try { this.generator.generate(resource, this.fileAccess, context); + ReactorInstance.clearReactorInstanceMap(); } catch (Exception e) { reporter.printFatalErrorAndExit("Error running generator", e); } diff --git a/org.lflang/src/org/lflang/generator/ReactorInstance.java b/org.lflang/src/org/lflang/generator/ReactorInstance.java index 0a5c9e0b85..6252b95a28 100644 --- a/org.lflang/src/org/lflang/generator/ReactorInstance.java +++ b/org.lflang/src/org/lflang/generator/ReactorInstance.java @@ -33,10 +33,9 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; -import org.eclipse.emf.ecore.util.EcoreUtil; - import org.lflang.ASTUtils; import org.lflang.AttributeUtils; import org.lflang.ErrorReporter; @@ -50,7 +49,6 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY import org.lflang.lf.Expression; import org.lflang.lf.Input; import org.lflang.lf.Instantiation; -import org.lflang.lf.LfFactory; import org.lflang.lf.Mode; import org.lflang.lf.Output; import org.lflang.lf.Parameter; @@ -60,13 +58,10 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY import org.lflang.lf.Reactor; import org.lflang.lf.ReactorDecl; import org.lflang.lf.Timer; -import org.lflang.lf.Type; import org.lflang.lf.VarRef; import org.lflang.lf.Variable; import org.lflang.lf.WidthSpec; -import com.google.common.collect.ImmutableMap; - /** * Representation of a compile-time instance of a reactor. @@ -165,6 +160,39 @@ public ReactorInstance(Reactor reactor, ReactorInstance parent, ErrorReporter re public final TypeParameterizedReactor tpr; + private static final HashMap gReactorInstancesMap = new HashMap<>(); + + ////////////////////////////////////////////////////// + //// Static methods. + + /** Map {@link ReactorInstance} against achievable hashcode from {@link Reactor} */ + public static void mapReactorInstance(Reactor r, ReactorInstance i) { + gReactorInstancesMap.put(computeHash(r, i), i); + } + + /** Get {@link ReactorInstance} for supplied {@link Reactor} */ + public static ReactorInstance getReactorInstance(Reactor r) { + var wrapper = new Object() { + ReactorInstance ins = null; + }; + gReactorInstancesMap.forEach((hash, i) -> { + if (Objects.equals(hash, computeHash(r, i))) { + wrapper.ins = i; + } + }); + return wrapper.ins; + } + + /** Clears out the cache of ReactorInstance for next LF processing */ + public static void clearReactorInstanceMap() { + gReactorInstancesMap.clear(); + } + + /** Calculates Unique HashCode for the key of ReactorInstanceMap*/ + private static Integer computeHash(Reactor r, ReactorInstance i) { + return Math.abs(r.hashCode() * 37 + r.getTypeParms().hashCode() + i.tpr.hashCode()); + } + ////////////////////////////////////////////////////// //// Public methods. @@ -778,6 +806,9 @@ public ReactorInstance( this.reactorDefinition = ASTUtils.toDefinition(reactorDeclaration); this.tpr = new TypeParameterizedReactor(definition); + // Add ReactorInstance against achievable hashcode from Reactor + ReactorInstance.mapReactorInstance(ASTUtils.toDefinition(definition.getReactorClass()), this); + // check for recursive instantiation var currentParent = parent; var foundSelfAsParent = false; diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index d0791230be..fb16baa559 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -42,8 +42,6 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; -import java.util.Locale; -import java.util.Map; import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -86,7 +84,6 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY import org.lflang.generator.TriggerInstance; import org.lflang.lf.Action; import org.lflang.lf.ActionOrigin; -import org.lflang.lf.Code; import org.lflang.lf.Input; import org.lflang.lf.Instantiation; import org.lflang.lf.Mode; @@ -97,7 +94,6 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY import org.lflang.lf.Reactor; import org.lflang.lf.ReactorDecl; import org.lflang.lf.StateVar; -import org.lflang.lf.Type; import org.lflang.lf.Variable; import org.lflang.util.ArduinoUtil; import org.lflang.util.FileUtil; @@ -1255,7 +1251,7 @@ private void generateInteractingContainedReactors( var contained = new InteractingContainedReactors(tpr.r()); // Next generate the relevant code. for (Instantiation containedReactor : contained.containedReactors()) { - Reactor containedReactorType = ASTUtils.toDefinition(containedReactor.getReactorClass()); + var containedReactorType = ReactorInstance.getReactorInstance(ASTUtils.toDefinition(containedReactor.getReactorClass())); // First define an _width variable in case it is a bank. var array = ""; var width = -2; @@ -1267,11 +1263,11 @@ private void generateInteractingContainedReactors( } // NOTE: The following needs to be done for each instance // so that the width can be parameter, not in the constructor. - // Here, we conservatively use a width that is the largest of all isntances. + // Here, we conservatively use a width that is the largest of all instances. constructorCode.pr(String.join("\n", "// Set the _width variable for all cases. This will be -2", "// if the reactor is not a bank of reactors.", - "self->_lf_"+containedReactor.getName()+"_width = "+width+";" + "self->_lf_"+containedReactorType.tpr.getName()+"_width = "+width+";" )); // Generate one struct for each contained reactor that interacts. @@ -1283,12 +1279,12 @@ private void generateInteractingContainedReactors( // to be malloc'd at initialization. if (!ASTUtils.isMultiport(port)) { // Not a multiport. - body.pr(port, variableStructType(port, containedReactorType, false)+" "+port.getName()+";"); + body.pr(port, variableStructType(port, containedReactorType.tpr, false)+" "+port.getName()+";"); } else { // Is a multiport. // Memory will be malloc'd in initialization. body.pr(port, String.join("\n", - variableStructType(port, containedReactorType, false)+"** "+port.getName()+";", + variableStructType(port, containedReactorType.tpr, false)+"** "+port.getName()+";", "int "+port.getName()+"_width;" )); } @@ -1298,13 +1294,13 @@ private void generateInteractingContainedReactors( // self struct of the container. if (!ASTUtils.isMultiport(port)) { // Not a multiport. - body.pr(port, variableStructType(port, containedReactorType, false)+"* "+port.getName()+";"); + body.pr(port, variableStructType(port, containedReactorType.tpr, false)+"* "+port.getName()+";"); } else { // Is a multiport. // Here, we will use an array of pointers. // Memory will be malloc'd in initialization. body.pr(port, String.join("\n", - variableStructType(port, containedReactorType, false)+"** "+port.getName()+";", + variableStructType(port, containedReactorType.tpr, false)+"** "+port.getName()+";", "int "+port.getName()+"_width;" )); } @@ -1312,10 +1308,10 @@ private void generateInteractingContainedReactors( var reactorIndex = ""; if (containedReactor.getWidthSpec() != null) { reactorIndex = "[reactor_index]"; - constructorCode.pr("for (int reactor_index = 0; reactor_index < self->_lf_"+tpr.getName()+"_width; reactor_index++) {"); + constructorCode.pr("for (int reactor_index = 0; reactor_index < self->_lf_"+containedReactorType.tpr.getName()+"_width; reactor_index++) {"); constructorCode.indent(); } - var portOnSelf = "self->_lf_"+tpr.getName()+reactorIndex+"."+port.getName(); + var portOnSelf = "self->_lf_"+containedReactorType.tpr.getName()+reactorIndex+"."+port.getName(); constructorCode.pr( port, @@ -1360,8 +1356,8 @@ private void generateInteractingContainedReactors( } body.unindent(); body.pr(String.join("\n", - "} _lf_"+tpr.getName()+array+";", - "int _lf_"+tpr.getName()+"_width;" + "} _lf_"+containedReactorType.tpr.getName()+array+";", + "int _lf_"+containedReactorType.tpr.getName()+"_width;" )); } } diff --git a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java index d54e54d5ee..28791b9cd1 100644 --- a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java @@ -14,9 +14,9 @@ import org.lflang.ErrorReporter; import org.lflang.InferredType; import org.lflang.TargetConfig; -import org.lflang.TargetProperty.Platform; import org.lflang.federated.extensions.CExtensionUtils; import org.lflang.generator.CodeBuilder; +import org.lflang.generator.ReactorInstance; import org.lflang.lf.Action; import org.lflang.lf.ActionOrigin; import org.lflang.lf.BuiltinTriggerRef; @@ -30,7 +30,6 @@ import org.lflang.lf.Port; import org.lflang.lf.Reaction; import org.lflang.lf.Reactor; -import org.lflang.lf.ReactorDecl; import org.lflang.lf.Timer; import org.lflang.lf.TriggerRef; import org.lflang.lf.VarRef; @@ -206,18 +205,19 @@ public static String generateInitializationForReaction(String body, // Before the reaction initialization, // generate the structs used for communication to and from contained reactors. for (Instantiation containedReactor : fieldsForStructsForContainedReactors.keySet()) { + var containedReactorType = ReactorInstance.getReactorInstance((Reactor) containedReactor.getReactorClass()); String array = ""; if (containedReactor.getWidthSpec() != null) { - String containedReactorWidthVar = generateWidthVariable(containedReactor.getName()); + String containedReactorWidthVar = generateWidthVariable(containedReactorType.tpr.getName()); code.pr("int "+containedReactorWidthVar+" = self->_lf_"+containedReactorWidthVar+";"); // Windows does not support variables in arrays declared on the stack, // so we use the maximum size over all bank members. array = "["+maxContainedReactorBankWidth(containedReactor, null, 0, mainDef)+"]"; } code.pr(String.join("\n", - "struct "+containedReactor.getName()+" {", + "struct "+containedReactorType.getName()+" {", " "+fieldsForStructsForContainedReactors.get(containedReactor)+"", - "} "+containedReactor.getName()+array+";" + "} "+containedReactorType.getName()+array+";" )); } // Next generate all the collected setup code. @@ -348,14 +348,15 @@ private static void generateVariablesForSendingToContainedReactors( Instantiation definition, Input input ) { - // TODO: Get reactorInstance or TPR from Instantiation CodeBuilder structBuilder = structs.get(definition); if (structBuilder == null) { structBuilder = new CodeBuilder(); structs.put(definition, structBuilder); } - String inputStructType = CGenerator.variableStructType(input, ASTUtils.toDefinition(definition.getReactorClass()), false); - String defName = definition.getName(); + var reactorInstance = ReactorInstance.getReactorInstance(ASTUtils.toDefinition(definition.getReactorClass())); + String inputStructType = CGenerator.variableStructType(input, reactorInstance.tpr, false); + String defName = reactorInstance.getName(); + String subName = reactorInstance.tpr.getName(); String defWidth = generateWidthVariable(defName); String inputName = input.getName(); String inputWidth = generateWidthVariable(inputName); @@ -366,12 +367,12 @@ private static void generateVariablesForSendingToContainedReactors( // Contained reactor is a bank. builder.pr(String.join("\n", "for (int bankIndex = 0; bankIndex < self->_lf_"+defWidth+"; bankIndex++) {", - " "+defName+"[bankIndex]."+inputName+" = &(self->_lf_"+defName+"[bankIndex]."+inputName+");", + " "+defName+"[bankIndex]."+inputName+" = &(self->_lf_"+subName+"[bankIndex]."+inputName+");", "}" )); } else { // Contained reactor is not a bank. - builder.pr(defName+"."+inputName+" = &(self->_lf_"+defName+"."+inputName+");"); + builder.pr(defName+"."+inputName+" = &(self->_lf_"+subName+"."+inputName+");"); } } else { // Contained reactor's input is a multiport. @@ -384,14 +385,14 @@ private static void generateVariablesForSendingToContainedReactors( if (definition.getWidthSpec() != null) { builder.pr(String.join("\n", "for (int _i = 0; _i < self->_lf_"+defWidth+"; _i++) {", - " "+defName+"[_i]."+inputName+" = self->_lf_"+defName+"[_i]."+inputName+";", - " "+defName+"[_i]."+inputWidth+" = self->_lf_"+defName+"[_i]."+inputWidth+";", + " "+defName+"[_i]."+inputName+" = self->_lf_"+subName+"[_i]."+inputName+";", + " "+defName+"[_i]."+inputWidth+" = self->_lf_"+subName+"[_i]."+inputWidth+";", "}" )); } else { builder.pr(String.join("\n", - defName+"."+inputName+" = self->_lf_"+defName+"."+inputName+";", - defName+"."+inputWidth+" = self->_lf_"+defName+"."+inputWidth+";" + defName+"."+inputName+" = self->_lf_"+subName+"."+inputName+";", + defName+"."+inputWidth+" = self->_lf_"+subName+"."+inputWidth+";" )); } } @@ -421,14 +422,15 @@ private static void generatePortVariablesInReaction( } else { // port is an output of a contained reactor. Output output = (Output) port.getVariable(); - String portStructType = CGenerator.variableStructType(output, tpr, false); + String portStructType = CGenerator.variableStructType(output, ReactorInstance.getReactorInstance(ASTUtils.toDefinition(port.getContainer().getReactorClass())).getTypeParameterizedReactor(), false); CodeBuilder structBuilder = structs.get(port.getContainer()); if (structBuilder == null) { structBuilder = new CodeBuilder(); structs.put(port.getContainer(), structBuilder); } - String reactorName = port.getContainer().getName(); + String reactorName = ReactorInstance.getReactorInstance(ASTUtils.toDefinition(port.getContainer().getReactorClass())).tpr.getName(); + String subName = ReactorInstance.getReactorInstance(ASTUtils.toDefinition(port.getContainer().getReactorClass())).getName(); String reactorWidth = generateWidthVariable(reactorName); String outputName = output.getName(); String outputWidth = generateWidthVariable(outputName); @@ -450,21 +452,21 @@ private static void generatePortVariablesInReaction( // Output is in a bank. builder.pr(String.join("\n", "for (int i = 0; i < "+reactorWidth+"; i++) {", - " "+reactorName+"[i]."+outputName+" = self->_lf_"+reactorName+"[i]."+outputName+";", + " "+subName+"[i]."+outputName+" = self->_lf_"+reactorName+"[i]."+outputName+";", "}" )); if (ASTUtils.isMultiport(output)) { builder.pr(String.join("\n", "for (int i = 0; i < "+reactorWidth+"; i++) {", - " "+reactorName+"[i]."+outputWidth+" = self->_lf_"+reactorName+"[i]."+outputWidth+";", + " "+subName+"[i]."+outputWidth+" = self->_lf_"+reactorName+"[i]."+outputWidth+";", "}" )); } } else { // Output is not in a bank. - builder.pr(reactorName+"."+outputName+" = self->_lf_"+reactorName+"."+outputName+";"); + builder.pr(subName+"."+outputName+" = self->_lf_"+reactorName+"."+outputName+";"); if (ASTUtils.isMultiport(output)) { - builder.pr(reactorName+"."+outputWidth+" = self->_lf_"+reactorName+"."+outputWidth+";"); + builder.pr(subName+"."+outputWidth+" = self->_lf_"+reactorName+"."+outputWidth+";"); } } } @@ -641,9 +643,10 @@ public static String generateOutputVariablesInReaction( // The container of the output may be a contained reactor or // the reactor containing the reaction. String outputStructType = (effect.getContainer() == null) ? - CGenerator.variableStructType(output, tpr, false) - : - CGenerator.variableStructType(output, ASTUtils.toDefinition(effect.getContainer().getReactorClass()), false); + CGenerator.variableStructType(output, tpr, false) + : + CGenerator.variableStructType(output, ReactorInstance.getReactorInstance( + ASTUtils.toDefinition(effect.getContainer().getReactorClass())).getTypeParameterizedReactor(), false); if (!ASTUtils.isMultiport(output)) { // Output port is not a multiport. return outputStructType+"* "+outputName+" = &self->_lf_"+outputName+";"; diff --git a/org.lflang/src/org/lflang/generator/c/CStateGenerator.java b/org.lflang/src/org/lflang/generator/c/CStateGenerator.java index fc66036511..70d21a1f23 100644 --- a/org.lflang/src/org/lflang/generator/c/CStateGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CStateGenerator.java @@ -15,7 +15,7 @@ public class CStateGenerator { /** * Generate code for state variables of a reactor in the form "stateVar.type stateVar.name;" - * @param reactor The reactor + * @param reactor {@link TypeParameterizedReactor} * @param types A helper object for types */ public static String generateDeclarations(TypeParameterizedReactor reactor, CTypes types) { @@ -34,10 +34,10 @@ public static String generateDeclarations(TypeParameterizedReactor reactor, CTyp * this way, and there is no way to tell whether the type of the array * is a struct. * - * @param instance - * @param stateVar - * @param mode - * @return + * @param instance {@link ReactorInstance} + * @param stateVar {@link StateVar} + * @param mode {@link ModeInstance} + * @return String */ public static String generateInitializer( ReactorInstance instance, @@ -92,7 +92,7 @@ private static String generateModalReset( return ""; } var modeRef = "&"+CUtil.reactorRef(mode.getParent())+"->_lf__modes["+mode.getParent().modes.indexOf(mode)+"]"; - var type = types.getTargetType(ASTUtils.getInferredType(stateVar)); + var type = CUtil.getConcreteType(instance.tpr, types.getTargetType(ASTUtils.getInferredType(stateVar))); if (ASTUtils.isOfTimeType(stateVar) || ASTUtils.isParameterized(stateVar) && diff --git a/org.lflang/src/org/lflang/generator/c/CTypes.java b/org.lflang/src/org/lflang/generator/c/CTypes.java index ebb9c894f4..361046c27a 100644 --- a/org.lflang/src/org/lflang/generator/c/CTypes.java +++ b/org.lflang/src/org/lflang/generator/c/CTypes.java @@ -65,7 +65,7 @@ public String getTargetUndefinedType() { * as a type, and {@code int*} must be used instead, except when initializing * a variable using a static initializer, as in {@code int[] foo = {1, 2, 3};}. * When initializing a variable using a static initializer, use - * {@link #getVariableDeclaration(InferredType, String, boolean)} instead. + * {@link #getVariableDeclaration(TypeParameterizedReactor, InferredType, String, boolean)} instead. * @param type The type. */ @Override diff --git a/org.lflang/src/org/lflang/generator/c/CUtil.java b/org.lflang/src/org/lflang/generator/c/CUtil.java index 87f75133dd..3cae52d931 100644 --- a/org.lflang/src/org/lflang/generator/c/CUtil.java +++ b/org.lflang/src/org/lflang/generator/c/CUtil.java @@ -469,7 +469,7 @@ public static String reactorRefNested(ReactorInstance reactor) { * default, the string returned by {@link CUtil#bankIndex(ReactorInstance)}. */ public static String reactorRefNested(ReactorInstance reactor, String runtimeIndex, String bankIndex) { - String result = reactorRef(reactor.getParent(), runtimeIndex) + "->_lf_" + reactor.getName(); + String result = reactorRef(reactor.getParent(), runtimeIndex) + "->_lf_" + reactor.tpr.getName(); if (reactor.isBank()) { // Need the bank index not the runtimeIndex. if (bankIndex == null) bankIndex = bankIndex(reactor); diff --git a/org.lflang/src/org/lflang/generator/c/InteractingContainedReactors.java b/org.lflang/src/org/lflang/generator/c/InteractingContainedReactors.java index bc4d6893a1..ae6b37437f 100644 --- a/org.lflang/src/org/lflang/generator/c/InteractingContainedReactors.java +++ b/org.lflang/src/org/lflang/generator/c/InteractingContainedReactors.java @@ -8,12 +8,14 @@ import org.lflang.ASTUtils; import org.lflang.federated.generator.FederateInstance; +import org.lflang.generator.NamedInstance; import org.lflang.lf.Input; import org.lflang.lf.Instantiation; import org.lflang.lf.Output; import org.lflang.lf.Port; import org.lflang.lf.Reaction; import org.lflang.lf.Reactor; +import org.lflang.lf.ReactorDecl; import org.lflang.lf.TriggerRef; import org.lflang.lf.VarRef; @@ -101,7 +103,6 @@ public InteractingContainedReactors(Reactor reactor) { * @param port The port. */ private List addPort(Instantiation containedReactor, Port port) { - var parent = containedReactor.eContainer(); // Get or create the entry for the containedReactor. var containedReactorEntry = portsByContainedReactor.computeIfAbsent( containedReactor, From 9f32cefab1dc30c0ed2f72a3fbf5b5d11089090d Mon Sep 17 00:00:00 2001 From: mkhubaibumer Date: Tue, 11 Apr 2023 18:51:22 +0500 Subject: [PATCH 14/54] [C-Generic] Contained Generic Reactor This commit fixes the issues with having multiple contained generic reactors Signed-off-by: mkhubaibumer --- .../org/lflang/generator/ReactorInstance.java | 23 +++++++------------ .../org/lflang/generator/c/CGenerator.java | 2 +- .../generator/c/CReactionGenerator.java | 12 +++++----- .../generator/c/TypeParameterizedReactor.java | 1 - 4 files changed, 15 insertions(+), 23 deletions(-) diff --git a/org.lflang/src/org/lflang/generator/ReactorInstance.java b/org.lflang/src/org/lflang/generator/ReactorInstance.java index 6252b95a28..46ff5b1a73 100644 --- a/org.lflang/src/org/lflang/generator/ReactorInstance.java +++ b/org.lflang/src/org/lflang/generator/ReactorInstance.java @@ -166,21 +166,14 @@ public ReactorInstance(Reactor reactor, ReactorInstance parent, ErrorReporter re //// Static methods. /** Map {@link ReactorInstance} against achievable hashcode from {@link Reactor} */ - public static void mapReactorInstance(Reactor r, ReactorInstance i) { - gReactorInstancesMap.put(computeHash(r, i), i); + public static void mapReactorInstance(Reactor r, ReactorInstance i, final String n) { + gReactorInstancesMap.put(computeHash(r, n), i); } /** Get {@link ReactorInstance} for supplied {@link Reactor} */ - public static ReactorInstance getReactorInstance(Reactor r) { - var wrapper = new Object() { - ReactorInstance ins = null; - }; - gReactorInstancesMap.forEach((hash, i) -> { - if (Objects.equals(hash, computeHash(r, i))) { - wrapper.ins = i; - } - }); - return wrapper.ins; + public static ReactorInstance getReactorInstance(Reactor r, final String n) { + var instance = gReactorInstancesMap.get(computeHash(r, n)); + return instance; } /** Clears out the cache of ReactorInstance for next LF processing */ @@ -189,8 +182,8 @@ public static void clearReactorInstanceMap() { } /** Calculates Unique HashCode for the key of ReactorInstanceMap*/ - private static Integer computeHash(Reactor r, ReactorInstance i) { - return Math.abs(r.hashCode() * 37 + r.getTypeParms().hashCode() + i.tpr.hashCode()); + private static Integer computeHash(Reactor r, final String n) { + return Math.abs(r.hashCode() * 37 + r.getTypeParms().hashCode() + n.hashCode()); } ////////////////////////////////////////////////////// @@ -807,7 +800,7 @@ public ReactorInstance( this.tpr = new TypeParameterizedReactor(definition); // Add ReactorInstance against achievable hashcode from Reactor - ReactorInstance.mapReactorInstance(ASTUtils.toDefinition(definition.getReactorClass()), this); + ReactorInstance.mapReactorInstance(ASTUtils.toDefinition(definition.getReactorClass()), this, definition.getName()); // check for recursive instantiation var currentParent = parent; diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index fb16baa559..abbaee4428 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -1251,7 +1251,7 @@ private void generateInteractingContainedReactors( var contained = new InteractingContainedReactors(tpr.r()); // Next generate the relevant code. for (Instantiation containedReactor : contained.containedReactors()) { - var containedReactorType = ReactorInstance.getReactorInstance(ASTUtils.toDefinition(containedReactor.getReactorClass())); + var containedReactorType = ReactorInstance.getReactorInstance(ASTUtils.toDefinition(containedReactor.getReactorClass()), containedReactor.getName()); // First define an _width variable in case it is a bank. var array = ""; var width = -2; diff --git a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java index 28791b9cd1..ead750738d 100644 --- a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java @@ -205,7 +205,7 @@ public static String generateInitializationForReaction(String body, // Before the reaction initialization, // generate the structs used for communication to and from contained reactors. for (Instantiation containedReactor : fieldsForStructsForContainedReactors.keySet()) { - var containedReactorType = ReactorInstance.getReactorInstance((Reactor) containedReactor.getReactorClass()); + var containedReactorType = ReactorInstance.getReactorInstance(ASTUtils.toDefinition(containedReactor.getReactorClass()), containedReactor.getName()); String array = ""; if (containedReactor.getWidthSpec() != null) { String containedReactorWidthVar = generateWidthVariable(containedReactorType.tpr.getName()); @@ -353,7 +353,7 @@ private static void generateVariablesForSendingToContainedReactors( structBuilder = new CodeBuilder(); structs.put(definition, structBuilder); } - var reactorInstance = ReactorInstance.getReactorInstance(ASTUtils.toDefinition(definition.getReactorClass())); + var reactorInstance = ReactorInstance.getReactorInstance(ASTUtils.toDefinition(definition.getReactorClass()), definition.getName()); String inputStructType = CGenerator.variableStructType(input, reactorInstance.tpr, false); String defName = reactorInstance.getName(); String subName = reactorInstance.tpr.getName(); @@ -422,15 +422,15 @@ private static void generatePortVariablesInReaction( } else { // port is an output of a contained reactor. Output output = (Output) port.getVariable(); - String portStructType = CGenerator.variableStructType(output, ReactorInstance.getReactorInstance(ASTUtils.toDefinition(port.getContainer().getReactorClass())).getTypeParameterizedReactor(), false); + String portStructType = CGenerator.variableStructType(output, ReactorInstance.getReactorInstance(ASTUtils.toDefinition(port.getContainer().getReactorClass()), port.getContainer().getName()).getTypeParameterizedReactor(), false); CodeBuilder structBuilder = structs.get(port.getContainer()); if (structBuilder == null) { structBuilder = new CodeBuilder(); structs.put(port.getContainer(), structBuilder); } - String reactorName = ReactorInstance.getReactorInstance(ASTUtils.toDefinition(port.getContainer().getReactorClass())).tpr.getName(); - String subName = ReactorInstance.getReactorInstance(ASTUtils.toDefinition(port.getContainer().getReactorClass())).getName(); + String reactorName = ReactorInstance.getReactorInstance(ASTUtils.toDefinition(port.getContainer().getReactorClass()), port.getContainer().getName()).tpr.getName(); + String subName = ReactorInstance.getReactorInstance(ASTUtils.toDefinition(port.getContainer().getReactorClass()), port.getContainer().getName()).getName(); String reactorWidth = generateWidthVariable(reactorName); String outputName = output.getName(); String outputWidth = generateWidthVariable(outputName); @@ -646,7 +646,7 @@ public static String generateOutputVariablesInReaction( CGenerator.variableStructType(output, tpr, false) : CGenerator.variableStructType(output, ReactorInstance.getReactorInstance( - ASTUtils.toDefinition(effect.getContainer().getReactorClass())).getTypeParameterizedReactor(), false); + ASTUtils.toDefinition(effect.getContainer().getReactorClass()), effect.getContainer().getName()).getTypeParameterizedReactor(), false); if (!ASTUtils.isMultiport(output)) { // Output port is not a multiport. return outputStructType+"* "+outputName+" = &self->_lf_"+outputName+";"; diff --git a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java index a903d5e9ae..df5cd4444b 100644 --- a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java +++ b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java @@ -3,7 +3,6 @@ import java.util.HashMap; import java.util.Map; -import java.util.Map.Entry; import java.util.stream.Collectors; import org.lflang.ASTUtils; From 272dbaa15903da0487c097c37fd9795f20d865f1 Mon Sep 17 00:00:00 2001 From: mkhubaibumer Date: Tue, 11 Apr 2023 19:00:42 +0500 Subject: [PATCH 15/54] Update documentation --- .../org/lflang/generator/ReactorInstance.java | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/org.lflang/src/org/lflang/generator/ReactorInstance.java b/org.lflang/src/org/lflang/generator/ReactorInstance.java index 46ff5b1a73..f0211ab22e 100644 --- a/org.lflang/src/org/lflang/generator/ReactorInstance.java +++ b/org.lflang/src/org/lflang/generator/ReactorInstance.java @@ -160,20 +160,27 @@ public ReactorInstance(Reactor reactor, ReactorInstance parent, ErrorReporter re public final TypeParameterizedReactor tpr; + /** HashMap containing {@link ReactorInstance} against hashCode achievable from Reactor */ private static final HashMap gReactorInstancesMap = new HashMap<>(); ////////////////////////////////////////////////////// //// Static methods. - /** Map {@link ReactorInstance} against achievable hashcode from {@link Reactor} */ - public static void mapReactorInstance(Reactor r, ReactorInstance i, final String n) { - gReactorInstancesMap.put(computeHash(r, n), i); + /** Map {@link ReactorInstance} against achievable hashcode from {@link Reactor} + * @param reactor The Reactor + * @param reactorInstance The ReactorInstance for the specified Reactor + * @param defName definition Name for the specified Reactor + * */ + public static void mapReactorInstance(Reactor reactor, ReactorInstance reactorInstance, final String defName) { + gReactorInstancesMap.put(computeHash(reactor, defName), reactorInstance); } - /** Get {@link ReactorInstance} for supplied {@link Reactor} */ - public static ReactorInstance getReactorInstance(Reactor r, final String n) { - var instance = gReactorInstancesMap.get(computeHash(r, n)); - return instance; + /** Get {@link ReactorInstance} for supplied {@link Reactor} + * @param reactor The reactor + * @param defName definition Name for the specified reactor + * */ + public static ReactorInstance getReactorInstance(Reactor reactor, final String defName) { + return gReactorInstancesMap.get(computeHash(reactor, defName)); } /** Clears out the cache of ReactorInstance for next LF processing */ @@ -181,7 +188,10 @@ public static void clearReactorInstanceMap() { gReactorInstancesMap.clear(); } - /** Calculates Unique HashCode for the key of ReactorInstanceMap*/ + /** Calculates Unique HashCode for the key of ReactorInstanceMap + * @param r The reactor + * @param n definition Name for the Reactor + * */ private static Integer computeHash(Reactor r, final String n) { return Math.abs(r.hashCode() * 37 + r.getTypeParms().hashCode() + n.hashCode()); } From ee610f060f679fc74f275888999071e31070ed6b Mon Sep 17 00:00:00 2001 From: mkhubaibumer Date: Fri, 14 Apr 2023 16:22:25 +0500 Subject: [PATCH 16/54] [C-Generics] Contained Generic Reactor Update to support Templated Initialization of Generic Contained Reactor with `typeArgs` from Parent Reactor Signed-off-by: mkhubaibumer --- org.lflang/src/org/lflang/ASTUtils.java | 16 +++++++ .../org/lflang/generator/ReactorInstance.java | 2 +- .../org/lflang/generator/c/CGenerator.java | 45 ++++++++++++++----- .../c/CReactorHeaderFileGenerator.java | 4 +- .../src/org/lflang/generator/c/CUtil.java | 8 +--- .../generator/c/TypeParameterizedReactor.java | 5 ++- .../python/PythonReactionGenerator.java | 12 ++--- 7 files changed, 63 insertions(+), 29 deletions(-) diff --git a/org.lflang/src/org/lflang/ASTUtils.java b/org.lflang/src/org/lflang/ASTUtils.java index 558e262a59..8f3cb710aa 100644 --- a/org.lflang/src/org/lflang/ASTUtils.java +++ b/org.lflang/src/org/lflang/ASTUtils.java @@ -60,6 +60,7 @@ import org.lflang.generator.InvalidSourceException; import org.lflang.generator.NamedInstance; import org.lflang.generator.ReactorInstance; +import org.lflang.generator.c.CUtil; import org.lflang.generator.c.TypeParameterizedReactor; import org.lflang.lf.Action; import org.lflang.lf.Assignment; @@ -381,6 +382,21 @@ public static List allInstantiations(Reactor definition) { return ASTUtils.collectElements(definition, featurePackage.getReactor_Instantiations()); } + /** + * Given a reactor Class, returns a set of include names for + * interacting reactors which includes all instantiations of base class that it extends + * + * @param r Reactor Class + * */ + public static HashSet allIncludes(Reactor r) { + var set = new HashSet(); + for (var i : allInstantiations(r)) + { + set.add(CUtil.getName(ReactorInstance.getReactorInstance(ASTUtils.toDefinition(i.getReactorClass()), i.getName()).tpr)); + } + return set; + } + public static List allChildInstances(Reactor definition, ErrorReporter reporter) { return allInstantiations(definition).stream().map(it -> new ReactorInstance( it, diff --git a/org.lflang/src/org/lflang/generator/ReactorInstance.java b/org.lflang/src/org/lflang/generator/ReactorInstance.java index f0211ab22e..ccde52a1ff 100644 --- a/org.lflang/src/org/lflang/generator/ReactorInstance.java +++ b/org.lflang/src/org/lflang/generator/ReactorInstance.java @@ -158,7 +158,7 @@ public ReactorInstance(Reactor reactor, ReactorInstance parent, ErrorReporter re /** Indicator that this reactor has itself as a parent, an error condition. */ public final boolean recursive; - public final TypeParameterizedReactor tpr; + public TypeParameterizedReactor tpr; /** HashMap containing {@link ReactorInstance} against hashCode achievable from Reactor */ private static final HashMap gReactorInstancesMap = new HashMap<>(); diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index abbaee4428..0a1c0d69cc 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -39,9 +39,11 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; +import java.util.Map; import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -94,11 +96,13 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY import org.lflang.lf.Reactor; import org.lflang.lf.ReactorDecl; import org.lflang.lf.StateVar; +import org.lflang.lf.Type; import org.lflang.lf.Variable; import org.lflang.util.ArduinoUtil; import org.lflang.util.FileUtil; import com.google.common.base.Objects; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; /** @@ -922,12 +926,39 @@ public void copyUserFiles(TargetConfig targetConfig, FileConfig fileConfig) { private void generateReactorDefinitions() throws IOException { var generatedReactors = new LinkedHashSet(); if (this.main != null) { + resolveTemplatedTypes(this.main, this.main.tpr); generateReactorChildren(this.main, generatedReactors); generateReactorClass(this.main.getTypeParameterizedReactor()); } // do not generate code for reactors that are not instantiated } + /** + * Recursively Resolve all Templated Types of child Reactors to their respective + * concrete types + * + * @param reactorInstance The Reactor Class + * @param parentTpr {@link TypeParameterizedReactor} of Parent + * */ + private void resolveTemplatedTypes(ReactorInstance reactorInstance, TypeParameterizedReactor parentTpr) { + for (var child : reactorInstance.children) { + if (parentTpr.typeArgs() != null) { + Map copy = new HashMap<>(); + child.tpr.typeArgs().forEach((literal, typename) -> { + var type = typename.getId(); + if (parentTpr.typeArgs().containsKey(type)) { + var basicType = parentTpr.typeArgs().get(type); + copy.put(literal, basicType); + } + }); + if (!copy.isEmpty()) { // If we found some templated-types update the tpr with new map + child.tpr = new TypeParameterizedReactor(child.tpr.r(), copy); + } + resolveTemplatedTypes(child, child.tpr); + } + } + } + private void generateHeaders() throws IOException { // Cannot delete existing header files directory because this would create a race condition in fed-gen FileUtil.copyDirectoryFromClassPath( @@ -935,9 +966,7 @@ private void generateHeaders() throws IOException { fileConfig.getIncludePath(), false ); -// for (var r : reactors) { - CReactorHeaderFileGenerator.doGenerate(types, this.main.tpr, fileConfig, this::generateAuxiliaryStructs, this::generateTopLevelPreambles); -// } + CReactorHeaderFileGenerator.doGenerate(types, this.main.tpr, fileConfig, this::generateAuxiliaryStructs, this::generateTopLevelPreambles); FileUtil.copyDirectory(fileConfig.getIncludePath(), fileConfig.getSrcGenPath().resolve("include"), false); } @@ -1030,7 +1059,6 @@ private void generateReactorClass(TypeParameterizedReactor tpr) throws IOExcepti header.pr(generateTopLevelPreambles(tpr.r())); generateUserPreamblesForReactor(tpr.r(), src); generateReactorClassBody(tpr, header, src); - tpr.typeArgs().entrySet().forEach(it -> header.pr("#undef " + it.getKey())); header.pr("#endif // " + guardMacro); FileUtil.writeToFile(header.toString(), fileConfig.getSrcGenPath().resolve(headerName), true); var extension = targetConfig.platformOptions.platform == Platform.ARDUINO ? ".ino" @@ -1060,10 +1088,8 @@ protected void generateReactorClassHeaders(TypeParameterizedReactor tpr, String "#undef " + literal + "\n" + "#endif // " + literal + "\n" + "#define " + literal + " " + ASTUtils.toOriginalText(concreteType))); - new HashSet<>(ASTUtils.allInstantiations(tpr.r())).stream() - .map(TypeParameterizedReactor::new).map(CUtil::getName) - .map(name -> "#include \"" + name + ".h\"") - .forEach(header::pr); + ASTUtils.allIncludes(tpr.r()).stream().map(name -> "#include \"" + + name + ".h\"").forEach(header::pr); } private void generateReactorClassBody(TypeParameterizedReactor tpr, CodeBuilder header, CodeBuilder src) { @@ -1652,9 +1678,6 @@ public void processProtoFile(String filename) { public static String variableStructType(Variable variable, TypeParameterizedReactor tpr, boolean userFacing) { return (userFacing ? tpr.getName().toLowerCase() : CUtil.getName(tpr)) +"_"+variable.getName()+"_t"; } - public static String variableStructType(Variable variable, Reactor r, boolean userFacing) { - return (userFacing ? r.getName().toLowerCase() : CUtil.getName(r)) +"_"+variable.getName()+"_t"; - } /** * Construct a unique type for the struct of the specified diff --git a/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java b/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java index 6bdb08f5a9..88a9e2e6cb 100644 --- a/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java @@ -40,7 +40,7 @@ public static void doGenerate(CTypes types, TypeParameterizedReactor tpr, CFileC } private static String generateHeaderFile(CTypes types, TypeParameterizedReactor tpr, GenerateAuxiliaryStructs generator, String topLevelPreamble) { CodeBuilder builder = new CodeBuilder(); - appendIncludeGuard(builder, tpr.r()); + appendIncludeGuard(builder, tpr); builder.pr(topLevelPreamble); appendPoundIncludes(builder); appendSelfStruct(builder, types, tpr); @@ -52,7 +52,7 @@ private static String generateHeaderFile(CTypes types, TypeParameterizedReactor return builder.getCode(); } - private static void appendIncludeGuard(CodeBuilder builder, Reactor r) { + private static void appendIncludeGuard(CodeBuilder builder, TypeParameterizedReactor r) { String macro = CUtil.getName(r) + "_H"; builder.pr("#ifndef " + macro); builder.pr("#define " + macro); diff --git a/org.lflang/src/org/lflang/generator/c/CUtil.java b/org.lflang/src/org/lflang/generator/c/CUtil.java index 3cae52d931..9bfac8e7ba 100644 --- a/org.lflang/src/org/lflang/generator/c/CUtil.java +++ b/org.lflang/src/org/lflang/generator/c/CUtil.java @@ -28,6 +28,7 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY import java.io.File; import java.io.IOException; +import java.math.BigInteger; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -154,13 +155,6 @@ public static String getName(TypeParameterizedReactor reactor) { } return name; } - public static String getName(Reactor reactor) { - String name = reactor.getName().toLowerCase() + reactor.hashCode(); - if (reactor.isMain()) { - return name + "_main"; - } - return name; - } /** * Return a reference to the specified port. diff --git a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java index df5cd4444b..c04e1ac247 100644 --- a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java +++ b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java @@ -18,14 +18,15 @@ public TypeParameterizedReactor(Instantiation i) { this(ASTUtils.toDefinition(i.getReactorClass()), addTypeArgs(i, ASTUtils.toDefinition(i.getReactorClass()))); } - private static ImmutableMap addTypeArgs(Instantiation instantiation, Reactor r) { + + private static Map addTypeArgs(Instantiation instantiation, Reactor r) { HashMap ret = new HashMap<>(); if (instantiation.getTypeArgs() != null) { for (int i = 0; i < r.getTypeParms().size(); i++) { ret.put(r.getTypeParms().get(i).getLiteral(), instantiation.getTypeArgs().get(i)); } } - return ImmutableMap.copyOf(ret); + return ret; // ImmutableMap.copyOf(ret); } public String getName() { diff --git a/org.lflang/src/org/lflang/generator/python/PythonReactionGenerator.java b/org.lflang/src/org/lflang/generator/python/PythonReactionGenerator.java index 62dd65ff5f..e7bf570385 100644 --- a/org.lflang/src/org/lflang/generator/python/PythonReactionGenerator.java +++ b/org.lflang/src/org/lflang/generator/python/PythonReactionGenerator.java @@ -40,7 +40,7 @@ public class PythonReactionGenerator { * @param reactionIndex The index of the reaction * @param pyObjects CPython related objects */ - public static String generateCPythonReactionCaller(Reactor reactor, + public static String generateCPythonReactionCaller(TypeParameterizedReactor reactor, int reactionIndex, List pyObjects, String inits) { @@ -55,7 +55,7 @@ public static String generateCPythonReactionCaller(Reactor reactor, * @param reactionIndex The index of the reaction * @param pyObjects CPython related objects */ - public static String generateCPythonDeadlineCaller(Reactor r, + public static String generateCPythonDeadlineCaller(TypeParameterizedReactor r, int reactionIndex, List pyObjects) { String pythonFunctionName = generatePythonDeadlineFunctionName(reactionIndex); @@ -69,7 +69,7 @@ public static String generateCPythonDeadlineCaller(Reactor r, * @param reactionIndex The index of the reaction * @param pyObjects CPython related objects */ - public static String generateCPythonSTPCaller(Reactor r, + public static String generateCPythonSTPCaller(TypeParameterizedReactor r, int reactionIndex, List pyObjects) { String pythonFunctionName = generatePythonSTPFunctionName(reactionIndex); @@ -150,7 +150,7 @@ public static String generateCReaction( code.pr(generateFunction( CReactionGenerator.generateReactionFunctionHeader(tpr, reactionIndex), cInit, reaction.getCode(), - generateCPythonReactionCaller(r, reactionIndex, pyObjects, cPyInit) + generateCPythonReactionCaller(tpr, reactionIndex, pyObjects, cPyInit) )); // Generate code for the STP violation handler, if there is one. @@ -158,7 +158,7 @@ public static String generateCReaction( code.pr(generateFunction( CReactionGenerator.generateStpFunctionHeader(tpr, reactionIndex), cInit, reaction.getStp().getCode(), - generateCPythonSTPCaller(r, reactionIndex, pyObjects) + generateCPythonSTPCaller(tpr, reactionIndex, pyObjects) )); } // Generate code for the deadline violation function, if there is one. @@ -166,7 +166,7 @@ public static String generateCReaction( code.pr(generateFunction( CReactionGenerator.generateDeadlineFunctionHeader(tpr, reactionIndex), cInit, reaction.getDeadline().getCode(), - generateCPythonDeadlineCaller(r, reactionIndex, pyObjects) + generateCPythonDeadlineCaller(tpr, reactionIndex, pyObjects) )); } code.pr( From e066c099ecbd2e6746ac528106a3c88b82b031db Mon Sep 17 00:00:00 2001 From: mkhubaibumer Date: Fri, 14 Apr 2023 17:50:01 +0500 Subject: [PATCH 17/54] Cosmetic Changes and Cleanup --- org.lflang/src/org/lflang/generator/ReactorInstance.java | 5 +---- org.lflang/src/org/lflang/generator/c/CGenerator.java | 8 ++++---- .../src/org/lflang/generator/c/CReactionGenerator.java | 9 ++++----- .../lflang/generator/c/CReactorHeaderFileGenerator.java | 2 +- org.lflang/src/org/lflang/generator/c/CUtil.java | 2 +- .../org/lflang/generator/c/TypeParameterizedReactor.java | 4 +--- .../lflang/generator/python/PythonReactionGenerator.java | 8 +++----- 7 files changed, 15 insertions(+), 23 deletions(-) diff --git a/org.lflang/src/org/lflang/generator/ReactorInstance.java b/org.lflang/src/org/lflang/generator/ReactorInstance.java index ccde52a1ff..7dcf7ee330 100644 --- a/org.lflang/src/org/lflang/generator/ReactorInstance.java +++ b/org.lflang/src/org/lflang/generator/ReactorInstance.java @@ -1185,9 +1185,6 @@ private void setInitialWidth() { */ public boolean isGeneratedDelay() { // FIXME: hacky string matching again... - if (this.definition.getReactorClass().getName().contains(DelayBodyGenerator.GEN_DELAY_CLASS_NAME)) { - return true; - } - return false; + return this.definition.getReactorClass().getName().contains(DelayBodyGenerator.GEN_DELAY_CLASS_NAME); } } diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index 0a1c0d69cc..4d628de5b4 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -344,10 +344,10 @@ public class CGenerator extends GeneratorBase { /** * Extra lines that need to go into the generated CMakeLists.txt. */ - private String cMakeExtras = ""; + private final String cMakeExtras = ""; /** Place to collect code to execute at the start of a time step. */ - private CodeBuilder startTimeStep = new CodeBuilder(); + private final CodeBuilder startTimeStep = new CodeBuilder(); /** Count of the number of token pointers that need to have their * reference count decremented in _lf_start_time_step(). @@ -515,7 +515,7 @@ public void doGenerate(Resource resource, LFGeneratorContext context) { try { var dockerData = getDockerGenerator(context).generateDockerData(); dockerData.writeDockerFile(); - (new DockerComposeGenerator(context)).writeDockerComposeFile(List.of(dockerData)); + new DockerComposeGenerator(context).writeDockerComposeFile(List.of(dockerData)); } catch (IOException e) { throw new RuntimeException("Error while writing Docker files", e); } @@ -1949,7 +1949,7 @@ protected DockerGenerator getDockerGenerator(LFGeneratorContext context) { // Perform set up that does not generate code protected void setUpGeneralParameters() { accommodatePhysicalActionsIfPresent(); - targetConfig.compileDefinitions.put("LOG_LEVEL", targetConfig.logLevel.ordinal() + ""); + targetConfig.compileDefinitions.put("LOG_LEVEL", String.valueOf(targetConfig.logLevel.ordinal())); targetConfig.compileAdditionalSources.addAll(CCoreFilesUtils.getCTargetSrc()); // Create the main reactor instance if there is a main reactor. createMainReactorInstance(); diff --git a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java index ead750738d..8287fdfc80 100644 --- a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java @@ -216,7 +216,7 @@ public static String generateInitializationForReaction(String body, } code.pr(String.join("\n", "struct "+containedReactorType.getName()+" {", - " "+fieldsForStructsForContainedReactors.get(containedReactor)+"", + " "+fieldsForStructsForContainedReactors.get(containedReactor), "} "+containedReactorType.getName()+array+";" )); } @@ -697,8 +697,7 @@ public static void generateReactionAndTriggerStructs( // Create the map of triggers to reactions. for (TriggerRef trigger : reaction.getTriggers()) { // trigger may not be a VarRef (it could be "startup" or "shutdown"). - if (trigger instanceof VarRef) { - var triggerAsVarRef = (VarRef) trigger; + if (trigger instanceof VarRef triggerAsVarRef) { var reactionList = triggerMap.get(triggerAsVarRef.getVariable()); if (reactionList == null) { reactionList = new LinkedList<>(); @@ -811,9 +810,9 @@ public static void generateReactionAndTriggerStructs( // self->_lf__"+action.getName()+".is_timer = false; constructorCode.pr(String.join("\n", "self->_lf__" + action.getName() + ".is_physical = " + isPhysical + ";", - (!(action.getPolicy() == null || action.getPolicy().isEmpty()) ? + !(action.getPolicy() == null || action.getPolicy().isEmpty()) ? "self->_lf__" + action.getName() + ".policy = " + action.getPolicy() + ";" : - ""), + "", // Need to set the element_size in the trigger_t and the action struct. "self->_lf__" + action.getName() + ".tmplt.type.element_size = " + elementSize + ";", diff --git a/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java b/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java index 88a9e2e6cb..9cef515dba 100644 --- a/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java @@ -95,7 +95,7 @@ private static void appendSignature(CodeBuilder builder, CTypes types, Reaction private static String reactionParameters(CTypes types, Reaction r, TypeParameterizedReactor tpr) { return Stream.concat(Stream.of(userFacingSelfType(tpr) + "* self"), ioTypedVariableStream(r) - .map((tv) -> tpr.getName().toLowerCase() + "_" + tv.getName() + "_t* " + tv.getName())) + .map(tv -> tpr.getName().toLowerCase() + "_" + tv.getName() + "_t* " + tv.getName())) .collect(Collectors.joining(", ")); } diff --git a/org.lflang/src/org/lflang/generator/c/CUtil.java b/org.lflang/src/org/lflang/generator/c/CUtil.java index 9bfac8e7ba..b53298d5b9 100644 --- a/org.lflang/src/org/lflang/generator/c/CUtil.java +++ b/org.lflang/src/org/lflang/generator/c/CUtil.java @@ -853,7 +853,7 @@ private static List multiportWidthTerms(Variable variable) { if (term.getParameter() != null) { result.add(getTargetReference(term.getParameter())); } else { - result.add("" + term.getWidth()); + result.add(String.valueOf(term.getWidth())); } } } diff --git a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java index c04e1ac247..1a9ac13761 100644 --- a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java +++ b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java @@ -10,8 +10,6 @@ import org.lflang.lf.Reactor; import org.lflang.lf.Type; -import com.google.common.collect.ImmutableMap; - public record TypeParameterizedReactor(Reactor r, Map typeArgs) { public TypeParameterizedReactor(Instantiation i) { @@ -26,7 +24,7 @@ private static Map addTypeArgs(Instantiation instantiation, Reacto ret.put(r.getTypeParms().get(i).getLiteral(), instantiation.getTypeArgs().get(i)); } } - return ret; // ImmutableMap.copyOf(ret); + return ret; } public String getName() { diff --git a/org.lflang/src/org/lflang/generator/python/PythonReactionGenerator.java b/org.lflang/src/org/lflang/generator/python/PythonReactionGenerator.java index e7bf570385..8ea44b2a2f 100644 --- a/org.lflang/src/org/lflang/generator/python/PythonReactionGenerator.java +++ b/org.lflang/src/org/lflang/generator/python/PythonReactionGenerator.java @@ -209,8 +209,7 @@ private static String generateCPythonInitializers(Reaction reaction, // Next, add the triggers (input and actions; timers are not needed). // TODO: handle triggers for (TriggerRef trigger : ASTUtils.convertToEmptyListIfNull(reaction.getTriggers())) { - if (trigger instanceof VarRef) { - VarRef triggerAsVarRef = (VarRef) trigger; + if (trigger instanceof VarRef triggerAsVarRef) { code.pr(generateVariableToSendPythonReaction(triggerAsVarRef, actionsAsTriggers, decl, pyObjects)); } } @@ -274,14 +273,13 @@ public static void generatePythonReactionParametersAndInitializations(List Date: Fri, 14 Apr 2023 20:55:49 +0500 Subject: [PATCH 18/54] [C-Generics] Resolve Templated-Typed Pointers Converted the Context Manager to Generic This required us to seperate the Templated-Types Pointers from their Tokens( * OR [] ) This commit fixes these issue and the GenericContextManager is now available in our Repo Signed-off-by: mkhubaibumer --- .../src/org/lflang/generator/c/CUtil.java | 30 ++++++-- org.lflang/src/org/lflang/util/Pair.java | 77 +++++++++++++++++++ 2 files changed, 101 insertions(+), 6 deletions(-) create mode 100644 org.lflang/src/org/lflang/util/Pair.java diff --git a/org.lflang/src/org/lflang/generator/c/CUtil.java b/org.lflang/src/org/lflang/generator/c/CUtil.java index b53298d5b9..49357161a5 100644 --- a/org.lflang/src/org/lflang/generator/c/CUtil.java +++ b/org.lflang/src/org/lflang/generator/c/CUtil.java @@ -28,7 +28,6 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY import java.io.File; import java.io.IOException; -import java.math.BigInteger; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -39,7 +38,6 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY import java.util.Objects; import java.util.stream.Collectors; -import org.lflang.ASTUtils; import org.lflang.ErrorReporter; import org.lflang.FileConfig; import org.lflang.InferredType; @@ -55,12 +53,12 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY import org.lflang.lf.Parameter; import org.lflang.lf.Port; import org.lflang.lf.Reactor; -import org.lflang.lf.ReactorDecl; import org.lflang.lf.VarRef; import org.lflang.lf.Variable; import org.lflang.lf.WidthTerm; import org.lflang.util.FileUtil; import org.lflang.util.LFCommand; +import org.lflang.util.Pair; /** * A collection of utilities for C code generation. @@ -876,6 +874,21 @@ public static boolean isTokenType(InferredType type, CTypes types) { return type.isVariableSizeList || targetType.trim().endsWith("*"); } + /** + * Given a String str separate the Typename from tokens (* OR []) + * + * @param str Input String + * @return {@link Pair} of Typename and Tokens + * */ + public static Pair separateTokensFromTypes(String str) { + var starIdx = str.indexOf("*"); + if (starIdx == -1) { + var idx = str.indexOf("["); + return idx == -1 ? new Pair<>(str, "") : new Pair<>(str.substring(0, idx), str.substring(idx)); + } + return new Pair<>(str.substring(0, starIdx), str.substring(starIdx)); + } + /** * Given a type we need to check if the type is Generic Type literal and if * it is we need to find the corresponding concrete type @@ -886,14 +899,19 @@ public static boolean isTokenType(InferredType type, CTypes types) { public static String getConcreteType(TypeParameterizedReactor tpr, final String type) { if (tpr == null) return type; - var wrapper = new Object() { String concreteType = ""; }; + + var wrapper = new Object() { + String concreteType = ""; + final Pair inPair = separateTokensFromTypes(type); + }; tpr.typeArgs().forEach((literal, concreteType) -> { - if (type.equals(literal)) + if (wrapper.inPair.getFirst().equals(literal)) { wrapper.concreteType = String.valueOf(concreteType.getId()); } }); - return (wrapper.concreteType.isEmpty()) ? type : wrapper.concreteType; + + return wrapper.concreteType.isEmpty() ? type : wrapper.concreteType + wrapper.inPair.getSecond(); } public static String generateWidthVariable(String var) { diff --git a/org.lflang/src/org/lflang/util/Pair.java b/org.lflang/src/org/lflang/util/Pair.java new file mode 100644 index 0000000000..9e237104d3 --- /dev/null +++ b/org.lflang/src/org/lflang/util/Pair.java @@ -0,0 +1,77 @@ +/** + * @file + * @author Muhammad Khubaib Umer (khubaib@magnition.io) + * + * @section LICENSE +Copyright (c) 2023, MagnitionIO +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. + * @section DESCRIPTION + * + * This Class provides a Pair of Templated Types + * This provides the same facility as std::pair in C++ + */ + +package org.lflang.util; + +public final class Pair { + private final T first; + private final U second; + public Pair(final T t, final U u) + { + this.first = t; + this.second = u; + } + + public T getFirst() + { + return this.first; + } + + public U getSecond() + { + return this.second; + } + + @Override + public boolean equals(Object other) { + if (other == null) + return false; + if (this == other) + return true; + if (this.getClass().equals(other.getClass())) { + Pair otherPair = (Pair) other; + boolean isEqual = (first == null) ? otherPair.getFirst() == null : first.equals(otherPair.getFirst()); + + if (!isEqual) + return false; + + return (second == null) ? otherPair.getSecond() == null : second.equals(otherPair.getSecond()); + } + return false; + } + + @Override + public int hashCode() { + return first == null ? 0 : first.hashCode() + 27 * (second == null ? 0 : second.hashCode()); + } + + @Override + public String toString() { + return "Pair(" + first + ", " + second + ")"; + } +} From 40b075a460e5d1ce8ec5a11f5dc8b79b3922ddfa Mon Sep 17 00:00:00 2001 From: mkhubaibumer Date: Wed, 19 Apr 2023 15:45:25 +0500 Subject: [PATCH 19/54] Update Reactor-C --- org.lflang/src/lib/c/reactor-c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.lflang/src/lib/c/reactor-c b/org.lflang/src/lib/c/reactor-c index 866b189a4f..8523f14b96 160000 --- a/org.lflang/src/lib/c/reactor-c +++ b/org.lflang/src/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit 866b189a4f04d3fae7a50a256b8ca3686ea1c509 +Subproject commit 8523f14b962ae56aad375dde22141a600821fdce From e39e1e9e9c84cb910287b231a4d5de36a1ff0294 Mon Sep 17 00:00:00 2001 From: mkhubaibumer Date: Wed, 19 Apr 2023 21:28:59 +0500 Subject: [PATCH 20/54] [C-Generics] Fix the case where Contained Reactor is initiated with a combination of Templated Types and Concrete Types Signed-off-by: mkhubaibumer --- org.lflang/src/org/lflang/generator/c/CGenerator.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index 4d628de5b4..99540cce83 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -949,6 +949,9 @@ private void resolveTemplatedTypes(ReactorInstance reactorInstance, TypeParamete if (parentTpr.typeArgs().containsKey(type)) { var basicType = parentTpr.typeArgs().get(type); copy.put(literal, basicType); + } else { + // Typename is not inherited from Parent Reactor. Keep As Is! + copy.put(literal, typename); } }); if (!copy.isEmpty()) { // If we found some templated-types update the tpr with new map From e28065cf09021920b92dce929e1db733a11567b2 Mon Sep 17 00:00:00 2001 From: mkhubaibumer Date: Wed, 3 May 2023 19:45:28 +0500 Subject: [PATCH 21/54] Update in SubModule & Minor Changes in Pair<> --- org.lflang/src/lib/c/reactor-c | 2 +- org.lflang/src/org/lflang/util/Pair.java | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/org.lflang/src/lib/c/reactor-c b/org.lflang/src/lib/c/reactor-c index 8523f14b96..1d762fd8b3 160000 --- a/org.lflang/src/lib/c/reactor-c +++ b/org.lflang/src/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit 8523f14b962ae56aad375dde22141a600821fdce +Subproject commit 1d762fd8b367c84cb92e6314591b3bcd650bae8b diff --git a/org.lflang/src/org/lflang/util/Pair.java b/org.lflang/src/org/lflang/util/Pair.java index 9e237104d3..ef2ac123c4 100644 --- a/org.lflang/src/org/lflang/util/Pair.java +++ b/org.lflang/src/org/lflang/util/Pair.java @@ -23,26 +23,26 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * @section DESCRIPTION * * This Class provides a Pair of Templated Types - * This provides the same facility as std::pair in C++ + * This provides the same facility as std::pair in C++ */ package org.lflang.util; -public final class Pair { - private final T first; - private final U second; - public Pair(final T t, final U u) +public final class Pair { + private final T1 first; + private final T2 second; + public Pair(final T1 t1, final T2 t2) { - this.first = t; - this.second = u; + this.first = t1; + this.second = t2; } - public T getFirst() + public T1 getFirst() { return this.first; } - public U getSecond() + public T2 getSecond() { return this.second; } @@ -54,7 +54,7 @@ public boolean equals(Object other) { if (this == other) return true; if (this.getClass().equals(other.getClass())) { - Pair otherPair = (Pair) other; + var otherPair = (Pair) other; boolean isEqual = (first == null) ? otherPair.getFirst() == null : first.equals(otherPair.getFirst()); if (!isEqual) @@ -72,6 +72,6 @@ public int hashCode() { @Override public String toString() { - return "Pair(" + first + ", " + second + ")"; + return "Pair<" + first + ", " + second + ">"; } } From aa409f84f8a59d2124790dc2d71932dee93d0486 Mon Sep 17 00:00:00 2001 From: mkhubaibumer Date: Thu, 11 May 2023 19:27:40 +0500 Subject: [PATCH 22/54] Update Reactor-C --- org.lflang/src/lib/c/reactor-c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.lflang/src/lib/c/reactor-c b/org.lflang/src/lib/c/reactor-c index 1d762fd8b3..f1d41011e4 160000 --- a/org.lflang/src/lib/c/reactor-c +++ b/org.lflang/src/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit 1d762fd8b367c84cb92e6314591b3bcd650bae8b +Subproject commit f1d41011e454a026741beb68bd9a3ec80101c8ee From c461cd70c531d7510769187651d9cb51af43c424 Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Wed, 17 May 2023 22:03:54 -0700 Subject: [PATCH 23/54] Delete unnecessary complexity from build-lf-cli. --- lib/scripts/build.sh | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/lib/scripts/build.sh b/lib/scripts/build.sh index d342aa45cd..52cc403851 100755 --- a/lib/scripts/build.sh +++ b/lib/scripts/build.sh @@ -114,18 +114,4 @@ if [ "${OSTYPE}" = "msys" ]; then fi jar_path="$(get_jar_path)" - -if [ ! -f "${jar_path}" ] || ! "${find_cmd}" "${base}" \ - -path "${src_pkg_path}" \ - -prune -o \ - -type f \ - -newer "${jar_path}" \ - -exec false {} +; then - # Rebuild. - 1>&2 echo "Jar file is missing or out-of-date; starting rebuild..." - "${base}/gradlew" ${flags} -p "${base}" buildAll - # Update the timestamp in case the jar was not touched by Gradle. - touch -c -- "${jar_path}" -else - echo "Already up-to-date." -fi +"${base}/gradlew" ${flags} -p "${base}" buildAll From 4fac0fe10d7383c2f988f51cda469ff9953439a8 Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Fri, 19 May 2023 12:53:40 -0700 Subject: [PATCH 24/54] More cleanups after merge. --- org.lflang/src/lib/c/reactor-c | 2 +- org.lflang/src/org/lflang/generator/c/CGenerator.java | 2 +- .../generator/c/CReactorHeaderFileGenerator.java | 11 ++--------- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/org.lflang/src/lib/c/reactor-c b/org.lflang/src/lib/c/reactor-c index 04193a7d9c..f1d41011e4 160000 --- a/org.lflang/src/lib/c/reactor-c +++ b/org.lflang/src/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit 04193a7d9cf2e6b39aab652bef47ce583a84be2c +Subproject commit f1d41011e454a026741beb68bd9a3ec80101c8ee diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index 80031c4cd9..be689cecd7 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -1069,7 +1069,7 @@ protected void generateReactorClassHeaders(TypeParameterizedReactor tpr, String src.pr("}"); header.pr("}"); } - src.pr("#include \"include/" + headerName + "\""); + src.pr("#include \"" + headerName + "\""); tpr.typeArgs().forEach((literal, concreteType) -> src.pr( "#if defined " + literal + "\n" + "#undef " + literal + "\n" + diff --git a/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java b/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java index cf9f719967..33f652a8a4 100644 --- a/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java @@ -94,8 +94,8 @@ private static void appendSignature(CodeBuilder builder, CTypes types, Reaction } private static String reactionParameters(CTypes types, Reaction r, TypeParameterizedReactor tpr) { - return Stream.concat(Stream.of(userFacingSelfType(tpr) + "* self"), inputVarRefStream(r) - .map(tv -> tpr.getName().toLowerCase() + "_" + tv.getVariable().getName() + "_t* " + tv.getVariable().getName())) + return Stream.concat(Stream.of(userFacingSelfType(tpr) + "* self"), portVariableStream(r, tpr) + .map(tv -> tpr.getName().toLowerCase() + "_" + tv.getName() + "_t* " + tv.getName())) .collect(Collectors.joining(", ")); } @@ -109,13 +109,6 @@ private static String getApiSelfStruct(TypeParameterizedReactor tpr) { return "(" + userFacingSelfType(tpr) + "*) (((char*) self) + sizeof(self_base_t))"; } - /** Return a string representation of the parameters of the reaction function of {@code r}. */ - private static String reactionParameters(Reaction r, TypeParameterizedReactor tpr) { - return Stream.concat(Stream.of(userFacingSelfType(tpr) + "* self"), portVariableStream(r, tpr) - .map(it -> it.getType(true) + " " + it.getName())) - .collect(Collectors.joining(", ")); - } - /** Generate initialization code that is needed if {@code r} is not inlined. */ public static String nonInlineInitialization(Reaction r, TypeParameterizedReactor reactor) { var mainDef = LfFactory.eINSTANCE.createInstantiation(); From 172b01fc6487954643ac12d17bee743de1195be0 Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Fri, 19 May 2023 13:02:04 -0700 Subject: [PATCH 25/54] Add back missing include. I'm not sure how this one disappeared from this branch, but it is in master already. --- org.lflang/src/org/lflang/generator/c/CGenerator.java | 1 + 1 file changed, 1 insertion(+) diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index be689cecd7..a3bb69a702 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -1069,6 +1069,7 @@ protected void generateReactorClassHeaders(TypeParameterizedReactor tpr, String src.pr("}"); header.pr("}"); } + src.pr("#include \"include/" + CReactorHeaderFileGenerator.outputPath(tpr) + "\""); src.pr("#include \"" + headerName + "\""); tpr.typeArgs().forEach((literal, concreteType) -> src.pr( "#if defined " + literal + "\n" + From c56adefae298898c39a80d95e8730d819f905b6f Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Fri, 19 May 2023 13:58:05 -0700 Subject: [PATCH 26/54] Don't make ReactorInstance from insufficient data. --- org.lflang/src/org/lflang/ASTUtils.java | 9 --------- org.lflang/src/org/lflang/generator/c/CGenerator.java | 4 ++-- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/org.lflang/src/org/lflang/ASTUtils.java b/org.lflang/src/org/lflang/ASTUtils.java index c138aba4f5..d1fdb1b34d 100644 --- a/org.lflang/src/org/lflang/ASTUtils.java +++ b/org.lflang/src/org/lflang/ASTUtils.java @@ -419,15 +419,6 @@ public static HashSet allIncludes(Reactor r) { return set; } - public static List allChildInstances(Reactor definition, ErrorReporter reporter) { - return allInstantiations(definition).stream().map(it -> new ReactorInstance( - it, - null, - reporter, - 0 - )).collect(Collectors.toList()); - } - /* * Given a reactor class, return a stream of reactor classes that it instantiates. * @param definition Reactor class definition. diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index a3bb69a702..ffacf25e99 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -913,8 +913,8 @@ private void generateHeaders() throws IOException { (builder, rr, userFacing) -> { generateAuxiliaryStructs(builder, tpr, userFacing); if (userFacing) { - ASTUtils.allChildInstances(tpr.r(), errorReporter).stream() - .map(it -> new TypeParameterizedReactorWithDecl(it.tpr, it.reactorDeclaration)).collect(Collectors.toSet()).forEach(it -> { + tpr.r().getInstantiations().stream() + .map(it -> new TypeParameterizedReactorWithDecl(new TypeParameterizedReactor(it), it.getReactorClass())).collect(Collectors.toSet()).forEach(it -> { ASTUtils.allPorts(it.tpr.r()) .forEach(p -> builder.pr(CPortGenerator.generateAuxiliaryStruct( it.tpr, p, getTarget(), errorReporter, types, new CodeBuilder(), true, it.decl() From ec41b353f75e20e32025ccca7075dd2093c2d3e9 Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Fri, 19 May 2023 13:58:56 -0700 Subject: [PATCH 27/54] Self struct members are named after instance vars. Not after reactor classes. --- .../org/lflang/generator/c/CGenerator.java | 10 +++---- .../generator/c/CReactionGenerator.java | 26 +++++++++---------- .../src/org/lflang/generator/c/CUtil.java | 2 +- 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index ffacf25e99..c1d227087f 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -1282,7 +1282,7 @@ private void generateInteractingContainedReactors( constructorCode.pr(String.join("\n", "// Set the _width variable for all cases. This will be -2", "// if the reactor is not a bank of reactors.", - "self->_lf_"+containedReactorType.tpr.getName()+"_width = "+width+";" + "self->_lf_"+containedReactor.getName()+"_width = "+width+";" )); // Generate one struct for each contained reactor that interacts. @@ -1323,10 +1323,10 @@ private void generateInteractingContainedReactors( var reactorIndex = ""; if (containedReactor.getWidthSpec() != null) { reactorIndex = "[reactor_index]"; - constructorCode.pr("for (int reactor_index = 0; reactor_index < self->_lf_"+containedReactorType.tpr.getName()+"_width; reactor_index++) {"); + constructorCode.pr("for (int reactor_index = 0; reactor_index < self->_lf_"+containedReactor.getName()+"_width; reactor_index++) {"); constructorCode.indent(); } - var portOnSelf = "self->_lf_"+containedReactorType.tpr.getName()+reactorIndex+"."+port.getName(); + var portOnSelf = "self->_lf_"+containedReactor.getName()+reactorIndex+"."+port.getName(); constructorCode.pr( port, @@ -1371,8 +1371,8 @@ private void generateInteractingContainedReactors( } body.unindent(); body.pr(String.join("\n", - "} _lf_"+containedReactorType.tpr.getName()+array+";", - "int _lf_"+containedReactorType.tpr.getName()+"_width;" + "} _lf_"+containedReactor.getName()+array+";", + "int _lf_"+containedReactor.getName()+"_width;" )); } } diff --git a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java index a3da1f8462..2b7b08790b 100644 --- a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java @@ -208,7 +208,7 @@ public static String generateInitializationForReaction(String body, var containedReactorType = ReactorInstance.getReactorInstance(ASTUtils.toDefinition(containedReactor.getReactorClass()), containedReactor.getName()); String array = ""; if (containedReactor.getWidthSpec() != null) { - String containedReactorWidthVar = generateWidthVariable(containedReactorType.tpr.getName()); + String containedReactorWidthVar = generateWidthVariable(containedReactor.getName()); code.pr("int "+containedReactorWidthVar+" = self->_lf_"+containedReactorWidthVar+";"); // Windows does not support variables in arrays declared on the stack, // so we use the maximum size over all bank members. @@ -356,7 +356,6 @@ private static void generateVariablesForSendingToContainedReactors( var reactorInstance = ReactorInstance.getReactorInstance(ASTUtils.toDefinition(definition.getReactorClass()), definition.getName()); String inputStructType = CGenerator.variableStructType(input, reactorInstance.tpr, false); String defName = reactorInstance.getName(); - String subName = reactorInstance.tpr.getName(); String defWidth = generateWidthVariable(defName); String inputName = input.getName(); String inputWidth = generateWidthVariable(inputName); @@ -367,12 +366,12 @@ private static void generateVariablesForSendingToContainedReactors( // Contained reactor is a bank. builder.pr(String.join("\n", "for (int bankIndex = 0; bankIndex < self->_lf_"+defWidth+"; bankIndex++) {", - " "+defName+"[bankIndex]."+inputName+" = &(self->_lf_"+subName+"[bankIndex]."+inputName+");", + " "+defName+"[bankIndex]."+inputName+" = &(self->_lf_"+defName+"[bankIndex]."+inputName+");", "}" )); } else { // Contained reactor is not a bank. - builder.pr(defName+"."+inputName+" = &(self->_lf_"+subName+"."+inputName+");"); + builder.pr(defName+"."+inputName+" = &(self->_lf_"+defName+"."+inputName+");"); } } else { // Contained reactor's input is a multiport. @@ -385,14 +384,14 @@ private static void generateVariablesForSendingToContainedReactors( if (definition.getWidthSpec() != null) { builder.pr(String.join("\n", "for (int _i = 0; _i < self->_lf_"+defWidth+"; _i++) {", - " "+defName+"[_i]."+inputName+" = self->_lf_"+subName+"[_i]."+inputName+";", - " "+defName+"[_i]."+inputWidth+" = self->_lf_"+subName+"[_i]."+inputWidth+";", + " "+defName+"[_i]."+inputName+" = self->_lf_"+defName+"[_i]."+inputName+";", + " "+defName+"[_i]."+inputWidth+" = self->_lf_"+defName+"[_i]."+inputWidth+";", "}" )); } else { builder.pr(String.join("\n", - defName+"."+inputName+" = self->_lf_"+subName+"."+inputName+";", - defName+"."+inputWidth+" = self->_lf_"+subName+"."+inputWidth+";" + defName+"."+inputName+" = self->_lf_"+defName+"."+inputName+";", + defName+"."+inputWidth+" = self->_lf_"+defName+"."+inputWidth+";" )); } } @@ -429,9 +428,8 @@ private static void generatePortVariablesInReaction( structBuilder = new CodeBuilder(); structs.put(port.getContainer(), structBuilder); } - String reactorName = ReactorInstance.getReactorInstance(ASTUtils.toDefinition(port.getContainer().getReactorClass()), port.getContainer().getName()).tpr.getName(); String subName = ReactorInstance.getReactorInstance(ASTUtils.toDefinition(port.getContainer().getReactorClass()), port.getContainer().getName()).getName(); - String reactorWidth = generateWidthVariable(reactorName); + String reactorWidth = generateWidthVariable(subName); String outputName = output.getName(); String outputWidth = generateWidthVariable(outputName); // First define the struct containing the output value and indicator @@ -452,21 +450,21 @@ private static void generatePortVariablesInReaction( // Output is in a bank. builder.pr(String.join("\n", "for (int i = 0; i < "+reactorWidth+"; i++) {", - " "+subName+"[i]."+outputName+" = self->_lf_"+reactorName+"[i]."+outputName+";", + " "+subName+"[i]."+outputName+" = self->_lf_"+subName+"[i]."+outputName+";", "}" )); if (ASTUtils.isMultiport(output)) { builder.pr(String.join("\n", "for (int i = 0; i < "+reactorWidth+"; i++) {", - " "+subName+"[i]."+outputWidth+" = self->_lf_"+reactorName+"[i]."+outputWidth+";", + " "+subName+"[i]."+outputWidth+" = self->_lf_"+subName+"[i]."+outputWidth+";", "}" )); } } else { // Output is not in a bank. - builder.pr(subName+"."+outputName+" = self->_lf_"+reactorName+"."+outputName+";"); + builder.pr(subName+"."+outputName+" = self->_lf_"+subName+"."+outputName+";"); if (ASTUtils.isMultiport(output)) { - builder.pr(subName+"."+outputWidth+" = self->_lf_"+reactorName+"."+outputWidth+";"); + builder.pr(subName+"."+outputWidth+" = self->_lf_"+subName+"."+outputWidth+";"); } } } diff --git a/org.lflang/src/org/lflang/generator/c/CUtil.java b/org.lflang/src/org/lflang/generator/c/CUtil.java index bfa1a1b712..e06fcdfc3f 100644 --- a/org.lflang/src/org/lflang/generator/c/CUtil.java +++ b/org.lflang/src/org/lflang/generator/c/CUtil.java @@ -456,7 +456,7 @@ public static String reactorRefNested(ReactorInstance reactor) { * default, the string returned by {@link CUtil#bankIndex(ReactorInstance)}. */ public static String reactorRefNested(ReactorInstance reactor, String runtimeIndex, String bankIndex) { - String result = reactorRef(reactor.getParent(), runtimeIndex) + "->_lf_" + reactor.tpr.getName(); + String result = reactorRef(reactor.getParent(), runtimeIndex) + "->_lf_" + reactor.getName(); if (reactor.isBank()) { // Need the bank index not the runtimeIndex. if (bankIndex == null) bankIndex = bankIndex(reactor); From 8fa20b8e75ae4302427d92fdb21de970ff558a95 Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Fri, 19 May 2023 14:20:45 -0700 Subject: [PATCH 28/54] Update tests according to new test categories. --- .../src/org/lflang/tests/RuntimeTest.java | 23 ++++++++++---- .../src/org/lflang/tests/runtime/CTest.java | 30 +++++++++++-------- 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/org.lflang.tests/src/org/lflang/tests/RuntimeTest.java b/org.lflang.tests/src/org/lflang/tests/RuntimeTest.java index 1cbb799046..7011b5ed96 100644 --- a/org.lflang.tests/src/org/lflang/tests/RuntimeTest.java +++ b/org.lflang.tests/src/org/lflang/tests/RuntimeTest.java @@ -11,7 +11,7 @@ /** * A collection of JUnit tests to perform on a given set of targets. - * + * * @author Marten Lohstroh * */ @@ -135,12 +135,23 @@ public void runFederatedTests() { @Test public void runModalTests() { runTestsForTargets(Message.DESC_MODAL, - TestCategory.MODAL_MODELS::equals, Configurators::noChanges, - TestLevel.EXECUTION, - false); + TestCategory.MODAL_MODELS::equals, Configurators::noChanges, + TestLevel.EXECUTION, + false); } - /** + /** + * Run the tests for non-inlined reaction bodies. + */ + @Test + public void runNoInliningTests() { + runTestsForTargets(Message.DESC_MODAL, + TestCategory.NO_INLINING::equals, Configurators::noChanges, + TestLevel.EXECUTION, + false); + } + + /** * Run docker tests, provided that the platform is Linux and the target supports Docker. * Skip if platform is not Linux or target does not support Docker. */ @@ -154,7 +165,7 @@ public void runDockerTests() { false); } - /** + /** * Run federated docker tests, provided that the platform is Linux, the target supports Docker, * and the target supports federated execution. If any of these requirements are not met, skip * the tests. diff --git a/org.lflang.tests/src/org/lflang/tests/runtime/CTest.java b/org.lflang.tests/src/org/lflang/tests/runtime/CTest.java index bc906b0d95..eba4f7bc71 100644 --- a/org.lflang.tests/src/org/lflang/tests/runtime/CTest.java +++ b/org.lflang.tests/src/org/lflang/tests/runtime/CTest.java @@ -11,29 +11,25 @@ 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 +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 +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.tests.runtime; -import java.util.List; - import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.lflang.Target; -import org.lflang.tests.Configurators; import org.lflang.tests.RuntimeTest; -import org.lflang.tests.TestRegistry.TestCategory; /** * Collection of tests for the C target. @@ -112,6 +108,16 @@ public void runFederatedTests() { super.runFederatedTests(); } + @Test + public void runModalTests() { + super.runModalTests(); + } + + @Test + public void runNoInliningTests() { + super.runNoInliningTests(); + } + @Test @Override public void runDockerTests() { From 48542d3cf9094166657209c6118a2ed6e97083d9 Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Fri, 19 May 2023 14:21:55 -0700 Subject: [PATCH 29/54] Format test. --- test/C/src/generics/Template.lf | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/C/src/generics/Template.lf b/test/C/src/generics/Template.lf index 3d483098b9..5b735ce4f4 100644 --- a/test/C/src/generics/Template.lf +++ b/test/C/src/generics/Template.lf @@ -1,7 +1,8 @@ target C reactor Hello { - state count: T(0) + state count: T = 0 + reaction(startup) {= self->count = self->count + 1; printf("Hello World %d\n", (int) self->count); @@ -9,5 +10,5 @@ reactor Hello { } main reactor Template { - hello = new Hello(); + hello = new Hello() } From 9c3aa67823e1b2d369531a46cd08210d1ecb2abe Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Fri, 19 May 2023 14:25:46 -0700 Subject: [PATCH 30/54] Merge in changes from reactor-c/main. This does not include the latest watchdog-related changes, which are not compatible with the current lingua-franca master. --- org.lflang/src/lib/c/reactor-c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.lflang/src/lib/c/reactor-c b/org.lflang/src/lib/c/reactor-c index f1d41011e4..a520d996a3 160000 --- a/org.lflang/src/lib/c/reactor-c +++ b/org.lflang/src/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit f1d41011e454a026741beb68bd9a3ec80101c8ee +Subproject commit a520d996a3c13c081b591aa67bf06afc39a7176d From 1dd92ebfb1d268c879f33a0c19c886e3337d4a94 Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Fri, 19 May 2023 15:13:42 -0700 Subject: [PATCH 31/54] Address failing no_inlining tests. --- .../c/CReactorHeaderFileGenerator.java | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java b/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java index 33f652a8a4..b98b5b959c 100644 --- a/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java @@ -90,18 +90,12 @@ private static void appendSelfStruct(CodeBuilder builder, CTypes types, TypePara } private static void appendSignature(CodeBuilder builder, CTypes types, Reaction r, TypeParameterizedReactor tpr) { - if (r.getName() != null) builder.pr("void " + r.getName() + "(" + reactionParameters(types, r, tpr) + ");"); + if (r.getName() != null) builder.pr("void " + r.getName() + "(" + reactionParameters(r, tpr) + ");"); } - private static String reactionParameters(CTypes types, Reaction r, TypeParameterizedReactor tpr) { + private static String reactionParameters(Reaction r, TypeParameterizedReactor tpr) { return Stream.concat(Stream.of(userFacingSelfType(tpr) + "* self"), portVariableStream(r, tpr) - .map(tv -> tpr.getName().toLowerCase() + "_" + tv.getName() + "_t* " + tv.getName())) - .collect(Collectors.joining(", ")); - } - - public static String reactionArguments(CTypes types, Reaction r, TypeParameterizedReactor tpr) { - return Stream.concat(Stream.of(getApiSelfStruct(tpr)), inputVarRefStream(r) - .map(it -> String.format("((%s*) %s)", CGenerator.variableStructType(it.getVariable(), tpr, true), it.getVariable().getName()))) + .map(tv -> tv.getType(true) + tv.getName())) .collect(Collectors.joining(", ")); } @@ -146,12 +140,12 @@ public static String reactionArguments(Reaction r, TypeParameterizedReactor reac } /** Return a stream of all ports referenced by the signature of {@code r}. */ - private static Stream portVariableStream(Reaction r, TypeParameterizedReactor reactor) { + private static Stream portVariableStream(Reaction r, TypeParameterizedReactor reactorOfReaction) { return varRefStream(r) .map(it -> it.getVariable() instanceof TypedVariable tv ? new PortVariable( tv, - reactor, + it.getContainer() != null ? new TypeParameterizedReactor(it.getContainer()) : reactorOfReaction, it.getContainer()) : null) .filter(Objects::nonNull); @@ -160,7 +154,7 @@ private static Stream portVariableStream(Reaction r, TypeParameter /** * A variable that refers to a port. * @param tv The variable of the variable reference. - * @param r The reactor that contains the port. + * @param r The reactor in which the port is being used. * @param container The {@code Instantiation} referenced in the obtaining of {@code tv}, if * applicable; {@code null} otherwise. */ From 6bbee5cc1a0ec856280fd80b3891be4e35ebdbf4 Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Fri, 19 May 2023 15:16:35 -0700 Subject: [PATCH 32/54] Fix another mismatch between reactor and tpr. --- .../src/org/lflang/generator/c/CReactorHeaderFileGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java b/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java index b98b5b959c..8fc60b78d7 100644 --- a/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java @@ -121,7 +121,7 @@ public static String nonInlineInitialization(Reaction r, TypeParameterizedReacto it.getAlias(), CReactionGenerator.maxContainedReactorBankWidth( reactor.r().getInstantiations().stream() - .filter(instantiation -> ASTUtils.toDefinition(instantiation.getReactorClass()).equals(it.r)) + .filter(instantiation -> new TypeParameterizedReactor(instantiation).equals(it.r)) .findAny().orElseThrow(), null, 0, mainDef), "self->_lf_"+it.container.getName()+"_width", From d548f1987d765019c7504539c8af4ede2b89307e Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Fri, 19 May 2023 16:17:54 -0700 Subject: [PATCH 33/54] Update reactor-c to include watchdogs. --- org.lflang/src/lib/c/reactor-c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.lflang/src/lib/c/reactor-c b/org.lflang/src/lib/c/reactor-c index a520d996a3..abc273ec0e 160000 --- a/org.lflang/src/lib/c/reactor-c +++ b/org.lflang/src/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit a520d996a3c13c081b591aa67bf06afc39a7176d +Subproject commit abc273ec0ec0930252c55e2a106529d7cc4dc277 From 96abdfeda847a3c21dc8b35ccc3a4e049678fdb1 Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Fri, 19 May 2023 18:31:17 -0700 Subject: [PATCH 34/54] Silence warning. The line I deleted here was doing nothing according to the compiler. --- org.lflang/src/org/lflang/generator/cpp/CppPortGenerator.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/org.lflang/src/org/lflang/generator/cpp/CppPortGenerator.kt b/org.lflang/src/org/lflang/generator/cpp/CppPortGenerator.kt index 990ede56c6..a6bd81f548 100644 --- a/org.lflang/src/org/lflang/generator/cpp/CppPortGenerator.kt +++ b/org.lflang/src/org/lflang/generator/cpp/CppPortGenerator.kt @@ -47,7 +47,6 @@ class CppPortGenerator(private val reactor: Reactor) { val VarRef.dataType: String get() { val variableRef = when { - this == null -> "" container == null -> this.name container.isBank && container.isEnclave -> "${container.name}[0]->__lf_instance->${variable.name}" container.isBank && !container.isEnclave -> "${container.name}[0]->${variable.name}" From fed3e14b79a13a8c704612d0e546e378778ed306 Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Fri, 19 May 2023 18:31:44 -0700 Subject: [PATCH 35/54] Pass failing template test. There is only one test, so this is easy. I think that adding a more thorough test suite and getting it to pass should be left outside the scope of this PR since this PR has lingered too long already and already provides useful functionality. --- org.lflang/src/org/lflang/generator/c/CGenerator.java | 6 +----- .../lflang/generator/c/CReactorHeaderFileGenerator.java | 1 + .../org/lflang/generator/c/TypeParameterizedReactor.java | 9 +++++++++ 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index aa34ddcdb5..cd89c36fd7 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -1078,11 +1078,7 @@ protected void generateReactorClassHeaders(TypeParameterizedReactor tpr, String } src.pr("#include \"include/" + CReactorHeaderFileGenerator.outputPath(tpr) + "\""); src.pr("#include \"" + headerName + "\""); - tpr.typeArgs().forEach((literal, concreteType) -> src.pr( - "#if defined " + literal + "\n" + - "#undef " + literal + "\n" + - "#endif // " + literal + "\n" + - "#define " + literal + " " + ASTUtils.toOriginalText(concreteType))); + tpr.doDefines(src); ASTUtils.allIncludes(tpr.r()).stream().map(name -> "#include \"" + name + ".h\"").forEach(header::pr); } diff --git a/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java b/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java index 8fc60b78d7..20d951b271 100644 --- a/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java @@ -45,6 +45,7 @@ private static String generateHeaderFile(CTypes types, TypeParameterizedReactor appendIncludeGuard(builder, tpr); builder.pr(topLevelPreamble); appendPoundIncludes(builder); + tpr.doDefines(builder); appendSelfStruct(builder, types, tpr); generator.generate(builder, tpr, true); for (Reaction reaction : tpr.r().getReactions()) { diff --git a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java index 1a9ac13761..2b2e3e571c 100644 --- a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java +++ b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java @@ -6,6 +6,7 @@ import java.util.stream.Collectors; import org.lflang.ASTUtils; +import org.lflang.generator.CodeBuilder; import org.lflang.lf.Instantiation; import org.lflang.lf.Reactor; import org.lflang.lf.Type; @@ -32,6 +33,14 @@ public String getName() { return r.getName() + typeArgs.values().stream().map(ASTUtils::toOriginalText).collect(Collectors.joining("_")); } + public void doDefines(CodeBuilder b) { + typeArgs.forEach((literal, concreteType) -> b.pr( + "#if defined " + literal + "\n" + + "#undef " + literal + "\n" + + "#endif // " + literal + "\n" + + "#define " + literal + " " + ASTUtils.toOriginalText(concreteType))); + } + @Override public int hashCode() { return Math.abs(r.hashCode() * 31 + typeArgs.hashCode()); From ce31b706946455670dadc4061e2554fdf85930ca Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Fri, 19 May 2023 23:24:25 -0700 Subject: [PATCH 36/54] Do not use hashcodes as keys. There are a few reasons for this change * the key is everywhere being computed from an Instantiation, so this change reduces the total amount of code * hash codes can occasionally collide, and I was not sure that this particular hashcode was very effective at minimizing collision probability. * but more importantly, the hash codes were being computed from information that does not uniquely identify the Instantiation. It was being computed from the name of the variable that holds the instance and from the name of the reactor class being instantiated. So if the same reactor class were instantiated and stored in a variable of the same name in multiple places, this could result in bugs. This change means that we are using physical equality to check the keys to the hashmap because we don't have our own IR and we can't override the hashcode and equals functions of Instantiation. But I think that's OK. After AST transformations, which should happen as upstream as possible, we are working with one single object representation of the program. --- org.lflang/src/org/lflang/ASTUtils.java | 2 +- .../src/org/lflang/generator/ReactorInstance.java | 14 +++++--------- .../src/org/lflang/generator/c/CGenerator.java | 2 +- .../org/lflang/generator/c/CReactionGenerator.java | 11 +++++------ 4 files changed, 12 insertions(+), 17 deletions(-) diff --git a/org.lflang/src/org/lflang/ASTUtils.java b/org.lflang/src/org/lflang/ASTUtils.java index 9da1c4fdd3..3072c19148 100644 --- a/org.lflang/src/org/lflang/ASTUtils.java +++ b/org.lflang/src/org/lflang/ASTUtils.java @@ -411,7 +411,7 @@ public static HashSet allIncludes(Reactor r) { var set = new HashSet(); for (var i : allInstantiations(r)) { - set.add(CUtil.getName(ReactorInstance.getReactorInstance(ASTUtils.toDefinition(i.getReactorClass()), i.getName()).tpr)); + set.add(CUtil.getName(ReactorInstance.getReactorInstance(i).tpr)); } return set; } diff --git a/org.lflang/src/org/lflang/generator/ReactorInstance.java b/org.lflang/src/org/lflang/generator/ReactorInstance.java index d6c02eca64..dc5e8487b4 100644 --- a/org.lflang/src/org/lflang/generator/ReactorInstance.java +++ b/org.lflang/src/org/lflang/generator/ReactorInstance.java @@ -26,7 +26,6 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY package org.lflang.generator; -import static org.lflang.ASTUtils.belongsTo; import static org.lflang.ASTUtils.getLiteralTimeValue; import java.util.ArrayList; @@ -170,7 +169,7 @@ public ReactorInstance(Reactor reactor, ReactorInstance parent, ErrorReporter re public TypeParameterizedReactor tpr; /** HashMap containing {@link ReactorInstance} against hashCode achievable from Reactor */ - private static final HashMap gReactorInstancesMap = new HashMap<>(); + private static final HashMap gReactorInstancesMap = new HashMap<>(); ////////////////////////////////////////////////////// //// Static methods. @@ -181,15 +180,12 @@ public ReactorInstance(Reactor reactor, ReactorInstance parent, ErrorReporter re * @param defName definition Name for the specified Reactor * */ public static void mapReactorInstance(Reactor reactor, ReactorInstance reactorInstance, final String defName) { - gReactorInstancesMap.put(computeHash(reactor, defName), reactorInstance); + gReactorInstancesMap.put(reactorInstance.definition, reactorInstance); } - /** Get {@link ReactorInstance} for supplied {@link Reactor} - * @param reactor The reactor - * @param defName definition Name for the specified reactor - * */ - public static ReactorInstance getReactorInstance(Reactor reactor, final String defName) { - return gReactorInstancesMap.get(computeHash(reactor, defName)); + /** Get {@link ReactorInstance} for supplied {@link Reactor} */ + public static ReactorInstance getReactorInstance(Instantiation i) { + return gReactorInstancesMap.get(i); } /** Clears out the cache of ReactorInstance for next LF processing */ diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index cd89c36fd7..d6c28fc08d 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -1274,7 +1274,7 @@ private void generateInteractingContainedReactors( var contained = new InteractingContainedReactors(tpr.r()); // Next generate the relevant code. for (Instantiation containedReactor : contained.containedReactors()) { - var containedReactorType = ReactorInstance.getReactorInstance(ASTUtils.toDefinition(containedReactor.getReactorClass()), containedReactor.getName()); + var containedReactorType = ReactorInstance.getReactorInstance(containedReactor); // First define an _width variable in case it is a bank. var array = ""; var width = -2; diff --git a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java index 760f1134d2..5a627055cc 100644 --- a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java @@ -207,7 +207,7 @@ public static String generateInitializationForReaction(String body, // Before the reaction initialization, // generate the structs used for communication to and from contained reactors. for (Instantiation containedReactor : fieldsForStructsForContainedReactors.keySet()) { - var containedReactorType = ReactorInstance.getReactorInstance(ASTUtils.toDefinition(containedReactor.getReactorClass()), containedReactor.getName()); + var containedReactorType = ReactorInstance.getReactorInstance(containedReactor); String array = ""; if (containedReactor.getWidthSpec() != null) { String containedReactorWidthVar = generateWidthVariable(containedReactor.getName()); @@ -355,7 +355,7 @@ private static void generateVariablesForSendingToContainedReactors( structBuilder = new CodeBuilder(); structs.put(definition, structBuilder); } - var reactorInstance = ReactorInstance.getReactorInstance(ASTUtils.toDefinition(definition.getReactorClass()), definition.getName()); + var reactorInstance = ReactorInstance.getReactorInstance(definition); String inputStructType = CGenerator.variableStructType(input, reactorInstance.tpr, false); String defName = reactorInstance.getName(); String defWidth = generateWidthVariable(defName); @@ -423,14 +423,14 @@ private static void generatePortVariablesInReaction( } else { // port is an output of a contained reactor. Output output = (Output) port.getVariable(); - String portStructType = CGenerator.variableStructType(output, ReactorInstance.getReactorInstance(ASTUtils.toDefinition(port.getContainer().getReactorClass()), port.getContainer().getName()).getTypeParameterizedReactor(), false); + String portStructType = CGenerator.variableStructType(output, ReactorInstance.getReactorInstance(port.getContainer()).getTypeParameterizedReactor(), false); CodeBuilder structBuilder = structs.get(port.getContainer()); if (structBuilder == null) { structBuilder = new CodeBuilder(); structs.put(port.getContainer(), structBuilder); } - String subName = ReactorInstance.getReactorInstance(ASTUtils.toDefinition(port.getContainer().getReactorClass()), port.getContainer().getName()).getName(); + String subName = ReactorInstance.getReactorInstance(port.getContainer()).getName(); String reactorWidth = generateWidthVariable(subName); String outputName = output.getName(); String outputWidth = generateWidthVariable(outputName); @@ -645,8 +645,7 @@ public static String generateOutputVariablesInReaction( String outputStructType = (effect.getContainer() == null) ? CGenerator.variableStructType(output, tpr, false) : - CGenerator.variableStructType(output, ReactorInstance.getReactorInstance( - ASTUtils.toDefinition(effect.getContainer().getReactorClass()), effect.getContainer().getName()).getTypeParameterizedReactor(), false); + CGenerator.variableStructType(output, ReactorInstance.getReactorInstance(effect.getContainer()).getTypeParameterizedReactor(), false); if (!ASTUtils.isMultiport(output)) { // Output port is not a multiport. return outputStructType+"* "+outputName+" = &self->_lf_"+outputName+";"; From 4b5a7c5f9653a9f6ded7bd778c25945b311bd705 Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Fri, 19 May 2023 23:53:46 -0700 Subject: [PATCH 37/54] Bugfix in CGenerator.java. The tests were all passing, but it looked wrong as-is. Maybe the tests were passing because we were not using the feature that lets the user use types in a reaction body that relate to contained reactors. --- org.lflang/src/org/lflang/ASTUtils.java | 2 +- .../src/org/lflang/generator/ReactorInstance.java | 1 - org.lflang/src/org/lflang/generator/c/CGenerator.java | 11 +++-------- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/org.lflang/src/org/lflang/ASTUtils.java b/org.lflang/src/org/lflang/ASTUtils.java index 3072c19148..e251557d1d 100644 --- a/org.lflang/src/org/lflang/ASTUtils.java +++ b/org.lflang/src/org/lflang/ASTUtils.java @@ -375,7 +375,7 @@ public static List allInputs(Reactor definition) { /** A list of all ports of {@code definition}, in an unspecified order. */ public static List allPorts(Reactor definition) { - return Stream.concat(ASTUtils.allInputs(definition).stream(), ASTUtils.allOutputs(definition).stream()).collect(Collectors.toList()); + return Stream.concat(ASTUtils.allInputs(definition).stream(), ASTUtils.allOutputs(definition).stream()).toList(); } /** diff --git a/org.lflang/src/org/lflang/generator/ReactorInstance.java b/org.lflang/src/org/lflang/generator/ReactorInstance.java index dc5e8487b4..432a1e7ee4 100644 --- a/org.lflang/src/org/lflang/generator/ReactorInstance.java +++ b/org.lflang/src/org/lflang/generator/ReactorInstance.java @@ -35,7 +35,6 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Optional; import java.util.Set; diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index d6c28fc08d..13af7e9dc7 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -37,9 +37,7 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY import java.io.File; import java.io.IOException; import java.nio.file.Path; -import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -88,7 +86,6 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY import org.lflang.lf.Input; import org.lflang.lf.Instantiation; import org.lflang.lf.Mode; -import org.lflang.lf.Model; import org.lflang.lf.Port; import org.lflang.lf.Preamble; import org.lflang.lf.Reaction; @@ -100,8 +97,6 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY import org.lflang.util.ArduinoUtil; import org.lflang.util.FileUtil; -import com.google.common.base.Objects; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; /** @@ -492,7 +487,7 @@ public void doGenerate(Resource resource, LFGeneratorContext context) { var sources = allTypeParameterizedReactors() .map(CUtil::getName) .map(it -> it + (CCppMode ? ".cpp" : ".c")) - .collect(Collectors.toCollection(ArrayList::new)); + .toList(); sources.add(cFilename); var cmakeCode = cmakeGenerator.generateCMakeCode( sources, @@ -916,9 +911,9 @@ private void generateHeaders() throws IOException { CReactorHeaderFileGenerator.doGenerate( types, tpr, fileConfig, (builder, rr, userFacing) -> { - generateAuxiliaryStructs(builder, tpr, userFacing); + generateAuxiliaryStructs(builder, rr, userFacing); if (userFacing) { - tpr.r().getInstantiations().stream() + rr.r().getInstantiations().stream() .map(it -> new TypeParameterizedReactorWithDecl(new TypeParameterizedReactor(it), it.getReactorClass())).collect(Collectors.toSet()).forEach(it -> { ASTUtils.allPorts(it.tpr.r()) .forEach(p -> builder.pr(CPortGenerator.generateAuxiliaryStruct( From dd6fd0c97d6bf6cc18598da8bc4fa8102622bfc2 Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Sat, 20 May 2023 14:30:04 -0700 Subject: [PATCH 38/54] Fix bug introduced by previous commit. --- org.lflang/src/org/lflang/generator/c/CGenerator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index 13af7e9dc7..03b76b804b 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -37,6 +37,7 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY import java.io.File; import java.io.IOException; import java.nio.file.Path; +import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; @@ -487,7 +488,7 @@ public void doGenerate(Resource resource, LFGeneratorContext context) { var sources = allTypeParameterizedReactors() .map(CUtil::getName) .map(it -> it + (CCppMode ? ".cpp" : ".c")) - .toList(); + .collect(Collectors.toCollection(ArrayList::new)); sources.add(cFilename); var cmakeCode = cmakeGenerator.generateCMakeCode( sources, From 331a3151b1e7d9249453a8577b883def9e14a761 Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Sun, 21 May 2023 17:23:50 -0700 Subject: [PATCH 39/54] Entirely delete the map from ReactorInstance. We do not need it. We can obtain a TPR from an Instantiation when all the concrete types are immediately available, and when they are not immediately available, we the map does not help us. --- org.lflang/src/org/lflang/ASTUtils.java | 2 +- org.lflang/src/org/lflang/cli/Lfc.java | 7 ++-- .../org/lflang/generator/ReactorInstance.java | 36 ------------------- .../org/lflang/generator/c/CGenerator.java | 10 +++--- .../generator/c/CReactionGenerator.java | 16 ++++----- 5 files changed, 16 insertions(+), 55 deletions(-) diff --git a/org.lflang/src/org/lflang/ASTUtils.java b/org.lflang/src/org/lflang/ASTUtils.java index e251557d1d..b9cacd8f48 100644 --- a/org.lflang/src/org/lflang/ASTUtils.java +++ b/org.lflang/src/org/lflang/ASTUtils.java @@ -411,7 +411,7 @@ public static HashSet allIncludes(Reactor r) { var set = new HashSet(); for (var i : allInstantiations(r)) { - set.add(CUtil.getName(ReactorInstance.getReactorInstance(i).tpr)); + set.add(CUtil.getName(new TypeParameterizedReactor(i))); } return set; } diff --git a/org.lflang/src/org/lflang/cli/Lfc.java b/org.lflang/src/org/lflang/cli/Lfc.java index 38795137d5..74d9eac8da 100644 --- a/org.lflang/src/org/lflang/cli/Lfc.java +++ b/org.lflang/src/org/lflang/cli/Lfc.java @@ -107,7 +107,7 @@ public class Lfc extends CliBase { @Option( names = {"-q", "--quiet"}, arity = "0", - description = + description = "Suppress output of the target compiler and other commands") private boolean quiet; @@ -189,7 +189,7 @@ private void invokeGenerator( final Resource resource = getResource(path); if (resource == null) { - reporter.printFatalErrorAndExit(path + reporter.printFatalErrorAndExit(path + " is not an LF file. Use the .lf file extension to" + " denote LF files."); } else if (federated) { @@ -210,7 +210,6 @@ private void invokeGenerator( try { this.generator.generate(resource, this.fileAccess, context); - ReactorInstance.clearReactorInstanceMap(); } catch (Exception e) { reporter.printFatalErrorAndExit("Error running generator", e); } @@ -318,7 +317,7 @@ public Properties getGeneratorArgs() { if (workers != null) { props.setProperty(BuildParm.WORKERS.getKey(), workers.toString()); } - + return props; } } diff --git a/org.lflang/src/org/lflang/generator/ReactorInstance.java b/org.lflang/src/org/lflang/generator/ReactorInstance.java index 432a1e7ee4..80629b81a0 100644 --- a/org.lflang/src/org/lflang/generator/ReactorInstance.java +++ b/org.lflang/src/org/lflang/generator/ReactorInstance.java @@ -167,39 +167,6 @@ public ReactorInstance(Reactor reactor, ReactorInstance parent, ErrorReporter re public TypeParameterizedReactor tpr; - /** HashMap containing {@link ReactorInstance} against hashCode achievable from Reactor */ - private static final HashMap gReactorInstancesMap = new HashMap<>(); - - ////////////////////////////////////////////////////// - //// Static methods. - - /** Map {@link ReactorInstance} against achievable hashcode from {@link Reactor} - * @param reactor The Reactor - * @param reactorInstance The ReactorInstance for the specified Reactor - * @param defName definition Name for the specified Reactor - * */ - public static void mapReactorInstance(Reactor reactor, ReactorInstance reactorInstance, final String defName) { - gReactorInstancesMap.put(reactorInstance.definition, reactorInstance); - } - - /** Get {@link ReactorInstance} for supplied {@link Reactor} */ - public static ReactorInstance getReactorInstance(Instantiation i) { - return gReactorInstancesMap.get(i); - } - - /** Clears out the cache of ReactorInstance for next LF processing */ - public static void clearReactorInstanceMap() { - gReactorInstancesMap.clear(); - } - - /** Calculates Unique HashCode for the key of ReactorInstanceMap - * @param r The reactor - * @param n definition Name for the Reactor - * */ - private static Integer computeHash(Reactor r, final String n) { - return Math.abs(r.hashCode() * 37 + r.getTypeParms().hashCode() + n.hashCode()); - } - ////////////////////////////////////////////////////// //// Public methods. @@ -844,9 +811,6 @@ public ReactorInstance( this.reactorDefinition = ASTUtils.toDefinition(reactorDeclaration); this.tpr = new TypeParameterizedReactor(definition); - // Add ReactorInstance against achievable hashcode from Reactor - ReactorInstance.mapReactorInstance(ASTUtils.toDefinition(definition.getReactorClass()), this, definition.getName()); - // check for recursive instantiation var currentParent = parent; var foundSelfAsParent = false; diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index 03b76b804b..b3bdac45bb 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -1270,7 +1270,7 @@ private void generateInteractingContainedReactors( var contained = new InteractingContainedReactors(tpr.r()); // Next generate the relevant code. for (Instantiation containedReactor : contained.containedReactors()) { - var containedReactorType = ReactorInstance.getReactorInstance(containedReactor); + var containedTpr = new TypeParameterizedReactor(containedReactor); // First define an _width variable in case it is a bank. var array = ""; var width = -2; @@ -1298,12 +1298,12 @@ private void generateInteractingContainedReactors( // to be malloc'd at initialization. if (!ASTUtils.isMultiport(port)) { // Not a multiport. - body.pr(port, variableStructType(port, containedReactorType.tpr, false)+" "+port.getName()+";"); + body.pr(port, variableStructType(port, containedTpr, false)+" "+port.getName()+";"); } else { // Is a multiport. // Memory will be malloc'd in initialization. body.pr(port, String.join("\n", - variableStructType(port, containedReactorType.tpr, false)+"** "+port.getName()+";", + variableStructType(port, containedTpr, false)+"** "+port.getName()+";", "int "+port.getName()+"_width;" )); } @@ -1313,13 +1313,13 @@ private void generateInteractingContainedReactors( // self struct of the container. if (!ASTUtils.isMultiport(port)) { // Not a multiport. - body.pr(port, variableStructType(port, containedReactorType.tpr, false)+"* "+port.getName()+";"); + body.pr(port, variableStructType(port, containedTpr, false)+"* "+port.getName()+";"); } else { // Is a multiport. // Here, we will use an array of pointers. // Memory will be malloc'd in initialization. body.pr(port, String.join("\n", - variableStructType(port, containedReactorType.tpr, false)+"** "+port.getName()+";", + variableStructType(port, containedTpr, false)+"** "+port.getName()+";", "int "+port.getName()+"_width;" )); } diff --git a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java index 5a627055cc..95ea818c49 100644 --- a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java @@ -207,7 +207,6 @@ public static String generateInitializationForReaction(String body, // Before the reaction initialization, // generate the structs used for communication to and from contained reactors. for (Instantiation containedReactor : fieldsForStructsForContainedReactors.keySet()) { - var containedReactorType = ReactorInstance.getReactorInstance(containedReactor); String array = ""; if (containedReactor.getWidthSpec() != null) { String containedReactorWidthVar = generateWidthVariable(containedReactor.getName()); @@ -217,9 +216,9 @@ public static String generateInitializationForReaction(String body, array = "["+maxContainedReactorBankWidth(containedReactor, null, 0, mainDef)+"]"; } code.pr(String.join("\n", - "struct "+containedReactorType.getName()+" {", + "struct "+containedReactor.getName()+" {", " "+fieldsForStructsForContainedReactors.get(containedReactor), - "} "+containedReactorType.getName()+array+";" + "} "+containedReactor.getName()+array+";" )); } // Next generate all the collected setup code. @@ -355,9 +354,8 @@ private static void generateVariablesForSendingToContainedReactors( structBuilder = new CodeBuilder(); structs.put(definition, structBuilder); } - var reactorInstance = ReactorInstance.getReactorInstance(definition); - String inputStructType = CGenerator.variableStructType(input, reactorInstance.tpr, false); - String defName = reactorInstance.getName(); + String inputStructType = CGenerator.variableStructType(input, new TypeParameterizedReactor(definition), false); + String defName = definition.getName(); String defWidth = generateWidthVariable(defName); String inputName = input.getName(); String inputWidth = generateWidthVariable(inputName); @@ -423,14 +421,14 @@ private static void generatePortVariablesInReaction( } else { // port is an output of a contained reactor. Output output = (Output) port.getVariable(); - String portStructType = CGenerator.variableStructType(output, ReactorInstance.getReactorInstance(port.getContainer()).getTypeParameterizedReactor(), false); + String portStructType = CGenerator.variableStructType(output, new TypeParameterizedReactor(port.getContainer()), false); CodeBuilder structBuilder = structs.get(port.getContainer()); if (structBuilder == null) { structBuilder = new CodeBuilder(); structs.put(port.getContainer(), structBuilder); } - String subName = ReactorInstance.getReactorInstance(port.getContainer()).getName(); + String subName = port.getContainer().getName(); String reactorWidth = generateWidthVariable(subName); String outputName = output.getName(); String outputWidth = generateWidthVariable(outputName); @@ -645,7 +643,7 @@ public static String generateOutputVariablesInReaction( String outputStructType = (effect.getContainer() == null) ? CGenerator.variableStructType(output, tpr, false) : - CGenerator.variableStructType(output, ReactorInstance.getReactorInstance(effect.getContainer()).getTypeParameterizedReactor(), false); + CGenerator.variableStructType(output, new TypeParameterizedReactor(effect.getContainer()), false); if (!ASTUtils.isMultiport(output)) { // Output port is not a multiport. return outputStructType+"* "+outputName+" = &self->_lf_"+outputName+";"; From f497c2a027161738f54ab08265f7aaca128507ad Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Sun, 21 May 2023 17:30:01 -0700 Subject: [PATCH 40/54] Switch submodule ref to main. I am still not sure that we want to maintain this generics-related utility file. Let us not worry about it until later. --- org.lflang/src/lib/c/reactor-c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.lflang/src/lib/c/reactor-c b/org.lflang/src/lib/c/reactor-c index abc273ec0e..dc6b138746 160000 --- a/org.lflang/src/lib/c/reactor-c +++ b/org.lflang/src/lib/c/reactor-c @@ -1 +1 @@ -Subproject commit abc273ec0ec0930252c55e2a106529d7cc4dc277 +Subproject commit dc6b13874697315859cd75e26ddd82f9c0d83643 From c6f1a6366bc800e09ae06853cef5038acaa40157 Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Sun, 21 May 2023 18:55:19 -0700 Subject: [PATCH 41/54] Update validator. --- .../generator/c/CReactionGenerator.java | 1 - .../generator/c/TypeParameterizedReactor.java | 6 ++++ .../org/lflang/validation/LFValidator.java | 28 ++++++++----------- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java index 95ea818c49..2dbb1a1801 100644 --- a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java @@ -16,7 +16,6 @@ import org.lflang.TargetConfig; import org.lflang.federated.extensions.CExtensionUtils; import org.lflang.generator.CodeBuilder; -import org.lflang.generator.ReactorInstance; import org.lflang.lf.Action; import org.lflang.lf.ActionOrigin; import org.lflang.lf.BuiltinTriggerRef; diff --git a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java index 2b2e3e571c..69b245c36f 100644 --- a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java +++ b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java @@ -41,6 +41,12 @@ public void doDefines(CodeBuilder b) { "#define " + literal + " " + ASTUtils.toOriginalText(concreteType))); } + public Type resolveType(Type t) { + var arg = typeArgs.get(t.getCode().getBody()); + if (arg != null) return arg; + return t; + } + @Override public int hashCode() { return Math.abs(r.hashCode() * 31 + typeArgs.hashCode()); diff --git a/org.lflang/src/org/lflang/validation/LFValidator.java b/org.lflang/src/org/lflang/validation/LFValidator.java index c0e2a46e59..94fb578f72 100644 --- a/org.lflang/src/org/lflang/validation/LFValidator.java +++ b/org.lflang/src/org/lflang/validation/LFValidator.java @@ -45,6 +45,7 @@ import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.TreeIterator; @@ -65,6 +66,7 @@ import org.lflang.federated.serialization.SupportedSerializers; import org.lflang.federated.validation.FedValidator; import org.lflang.generator.NamedInstance; +import org.lflang.generator.c.TypeParameterizedReactor; import org.lflang.lf.Action; import org.lflang.lf.ActionOrigin; import org.lflang.lf.Assignment; @@ -255,7 +257,10 @@ public void checkConnection(Connection connection) { // we leave type compatibility that language's compiler or interpreter. if (isCBasedTarget()) { Type type = (Type) null; - for (VarRef port : connection.getLeftPorts()) { + for (VarRef port : (Iterable) () -> Stream.concat( + connection.getLeftPorts().stream(), + connection.getRightPorts().stream() + ).iterator()) { // If the variable is not a port, then there is some other // error. Avoid a class cast exception. if (port.getVariable() instanceof Port) { @@ -264,22 +269,11 @@ public void checkConnection(Connection connection) { } else { // Unfortunately, xtext does not generate a suitable equals() // method for AST types, so we have to manually check the types. -// if (!sameType(type, ((Port) port.getVariable()).getType())) { -// error("Types do not match.", Literals.CONNECTION__LEFT_PORTS); -// } - } - } - } - for (VarRef port : connection.getRightPorts()) { - // If the variable is not a port, then there is some other - // error. Avoid a class cast exception. - if (port.getVariable() instanceof Port) { - if (type == null) { - type = ((Port) port.getVariable()).getType(); - } else { -// if (!sameType(type, type = ((Port) port.getVariable()).getType())) { -// error("Types do not match.", Literals.CONNECTION__RIGHT_PORTS); -// } + var portType = ((Port) port.getVariable()).getType(); + portType = port.getContainer() == null ? portType : new TypeParameterizedReactor(port.getContainer()).resolveType(portType); + if (!sameType(type, portType)) { + error("Types do not match.", Literals.CONNECTION__LEFT_PORTS); + } } } } From f13966ac008bf9e3036ac42ce94f49980ef50855 Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Sun, 21 May 2023 22:17:10 -0700 Subject: [PATCH 42/54] Fix NPE. --- .../src/org/lflang/generator/c/TypeParameterizedReactor.java | 1 + 1 file changed, 1 insertion(+) diff --git a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java index 69b245c36f..0ae657ed5c 100644 --- a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java +++ b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java @@ -42,6 +42,7 @@ public void doDefines(CodeBuilder b) { } public Type resolveType(Type t) { + if (t.getCode() == null) return t; var arg = typeArgs.get(t.getCode().getBody()); if (arg != null) return arg; return t; From f3c8ffa64cd47198cfaea6f746170311b79040bf Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Mon, 22 May 2023 00:37:04 -0700 Subject: [PATCH 43/54] Remove getConcreteType. Prefer to work on InferredTypes or Types rather than raw strings. Our code base, esp. the C generator, has had multiple problems involving ad hoc matching of raw strings. --- .../lflang/generator/c/CActionGenerator.java | 2 +- .../org/lflang/generator/c/CGenerator.java | 3 +-- .../generator/c/CParameterGenerator.java | 2 +- .../lflang/generator/c/CStateGenerator.java | 4 +-- .../src/org/lflang/generator/c/CTypes.java | 2 +- .../src/org/lflang/generator/c/CUtil.java | 25 ------------------- .../generator/c/TypeParameterizedReactor.java | 6 +++++ 7 files changed, 12 insertions(+), 32 deletions(-) diff --git a/org.lflang/src/org/lflang/generator/c/CActionGenerator.java b/org.lflang/src/org/lflang/generator/c/CActionGenerator.java index bc14c402a7..0fa79e94ca 100644 --- a/org.lflang/src/org/lflang/generator/c/CActionGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CActionGenerator.java @@ -171,6 +171,6 @@ private static String valueDeclaration( // will be a separate field pointing to the token. return action.getType() == null && target.requiresTypes ? "" : - CUtil.getConcreteType(tpr, types.getTargetType(action)) + " value;"; + types.getTargetType(tpr.resolveType(action.getType())) + " value;"; } } diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index b3bdac45bb..ea9de156e0 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -1771,14 +1771,13 @@ private void generateInitializeActionToken(ReactorInstance reactor) { // Skip this step if the action is not in use. if (action.getParent().getTriggers().contains(action) ) { - var type = getInferredType(action.getDefinition()); + var type = reactor.tpr.resolveType(getInferredType(action.getDefinition())); var payloadSize = "0"; if (!type.isUndefined()) { var typeStr = types.getTargetType(type); if (CUtil.isTokenType(type, types)) { typeStr = CUtil.rootType(typeStr); } - typeStr = CUtil.getConcreteType(reactor.tpr, typeStr); if (typeStr != null && !typeStr.equals("") && !typeStr.equals("void")) { payloadSize = "sizeof("+typeStr+")"; } diff --git a/org.lflang/src/org/lflang/generator/c/CParameterGenerator.java b/org.lflang/src/org/lflang/generator/c/CParameterGenerator.java index fb6a46bace..fc74f76d78 100644 --- a/org.lflang/src/org/lflang/generator/c/CParameterGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CParameterGenerator.java @@ -47,7 +47,7 @@ public static String generateDeclarations(TypeParameterizedReactor reactor, CTyp CodeBuilder code = new CodeBuilder(); for (Parameter parameter : ASTUtils.allParameters(reactor.r())) { code.prSourceLineNumber(parameter); - code.pr(CUtil.getConcreteType(reactor, types.getTargetType(parameter)) + " " + parameter.getName() + ";"); + code.pr(types.getTargetType(reactor.resolveType(ASTUtils.getInferredType(parameter))) + " " + parameter.getName() + ";"); } return code.toString(); } diff --git a/org.lflang/src/org/lflang/generator/c/CStateGenerator.java b/org.lflang/src/org/lflang/generator/c/CStateGenerator.java index d3ced7fc65..1b75a73ab8 100644 --- a/org.lflang/src/org/lflang/generator/c/CStateGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CStateGenerator.java @@ -23,7 +23,7 @@ public static String generateDeclarations(TypeParameterizedReactor reactor, CTyp CodeBuilder code = new CodeBuilder(); for (StateVar stateVar : ASTUtils.allStateVars(reactor.r())) { code.prSourceLineNumber(stateVar); - code.pr(CUtil.getConcreteType(reactor, types.getTargetType(stateVar)) + " " + stateVar.getName() + ";"); + code.pr(types.getTargetType(reactor.resolveType(ASTUtils.getInferredType(stateVar))) + " " + stateVar.getName() + ";"); } return code.toString(); } @@ -93,7 +93,7 @@ private static String generateModalReset( return ""; } var modeRef = "&"+CUtil.reactorRef(mode.getParent())+"->_lf__modes["+mode.getParent().modes.indexOf(mode)+"]"; - var type = CUtil.getConcreteType(instance.tpr, types.getTargetType(ASTUtils.getInferredType(stateVar))); + var type = types.getTargetType(instance.tpr.resolveType(ASTUtils.getInferredType(stateVar))); if (ASTUtils.isOfTimeType(stateVar) || ASTUtils.isParameterized(stateVar) && diff --git a/org.lflang/src/org/lflang/generator/c/CTypes.java b/org.lflang/src/org/lflang/generator/c/CTypes.java index 1081912f24..45edd59bd5 100644 --- a/org.lflang/src/org/lflang/generator/c/CTypes.java +++ b/org.lflang/src/org/lflang/generator/c/CTypes.java @@ -125,7 +125,7 @@ public String getVariableDeclaration( String variableName, boolean initializer ) { - String t = CUtil.getConcreteType(tpr, TargetTypes.super.getTargetType(type)); + String t = TargetTypes.super.getTargetType(tpr.resolveType(type)); Matcher matcher = arrayPattern.matcher(t); String declaration = String.format("%s %s", t, variableName); if (matcher.find()) { diff --git a/org.lflang/src/org/lflang/generator/c/CUtil.java b/org.lflang/src/org/lflang/generator/c/CUtil.java index e06fcdfc3f..b4e88b42ad 100644 --- a/org.lflang/src/org/lflang/generator/c/CUtil.java +++ b/org.lflang/src/org/lflang/generator/c/CUtil.java @@ -781,31 +781,6 @@ public static Pair separateTokensFromTypes(String str) { return new Pair<>(str.substring(0, starIdx), str.substring(starIdx)); } - /** - * Given a type we need to check if the type is Generic Type literal and if - * it is we need to find the corresponding concrete type - * - * @param tpr {@link TypeParameterizedReactor} - * @param type Actual typename - */ - public static String getConcreteType(TypeParameterizedReactor tpr, final String type) { - if (tpr == null) - return type; - - var wrapper = new Object() { - String concreteType = ""; - final Pair inPair = separateTokensFromTypes(type); - }; - tpr.typeArgs().forEach((literal, concreteType) -> { - if (wrapper.inPair.getFirst().equals(literal)) - { - wrapper.concreteType = String.valueOf(concreteType.getId()); - } - }); - - return wrapper.concreteType.isEmpty() ? type : wrapper.concreteType + wrapper.inPair.getSecond(); - } - public static String generateWidthVariable(String var) { return var + "_width"; } diff --git a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java index 0ae657ed5c..2f70b10825 100644 --- a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java +++ b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java @@ -6,6 +6,7 @@ import java.util.stream.Collectors; import org.lflang.ASTUtils; +import org.lflang.InferredType; import org.lflang.generator.CodeBuilder; import org.lflang.lf.Instantiation; import org.lflang.lf.Reactor; @@ -48,6 +49,11 @@ public Type resolveType(Type t) { return t; } + public InferredType resolveType(InferredType t) { + if (t.astType.getCode() != null) return InferredType.fromAST(resolveType(t.astType)); + return t; + } + @Override public int hashCode() { return Math.abs(r.hashCode() * 31 + typeArgs.hashCode()); From 957500d3fd4e458dfbae998ffdbacaa259c8a202 Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Mon, 22 May 2023 00:41:31 -0700 Subject: [PATCH 44/54] Delete Pair.java. It is usually recommended in the Java community to create objects specifically for the purpose at hand rather than using general tuple types. --- .../src/org/lflang/generator/c/CUtil.java | 16 ---- org.lflang/src/org/lflang/util/Pair.java | 77 ------------------- 2 files changed, 93 deletions(-) delete mode 100644 org.lflang/src/org/lflang/util/Pair.java diff --git a/org.lflang/src/org/lflang/generator/c/CUtil.java b/org.lflang/src/org/lflang/generator/c/CUtil.java index b4e88b42ad..aed904d0e6 100644 --- a/org.lflang/src/org/lflang/generator/c/CUtil.java +++ b/org.lflang/src/org/lflang/generator/c/CUtil.java @@ -53,7 +53,6 @@ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY import org.lflang.lf.WidthTerm; import org.lflang.util.FileUtil; import org.lflang.util.LFCommand; -import org.lflang.util.Pair; /** * A collection of utilities for C code generation. @@ -766,21 +765,6 @@ public static boolean isTokenType(InferredType type, CTypes types) { return type.isVariableSizeList || targetType.trim().endsWith("*"); } - /** - * Given a String str separate the Typename from tokens (* OR []) - * - * @param str Input String - * @return {@link Pair} of Typename and Tokens - * */ - public static Pair separateTokensFromTypes(String str) { - var starIdx = str.indexOf("*"); - if (starIdx == -1) { - var idx = str.indexOf("["); - return idx == -1 ? new Pair<>(str, "") : new Pair<>(str.substring(0, idx), str.substring(idx)); - } - return new Pair<>(str.substring(0, starIdx), str.substring(starIdx)); - } - public static String generateWidthVariable(String var) { return var + "_width"; } diff --git a/org.lflang/src/org/lflang/util/Pair.java b/org.lflang/src/org/lflang/util/Pair.java deleted file mode 100644 index ef2ac123c4..0000000000 --- a/org.lflang/src/org/lflang/util/Pair.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * @file - * @author Muhammad Khubaib Umer (khubaib@magnition.io) - * - * @section LICENSE -Copyright (c) 2023, MagnitionIO -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. - * @section DESCRIPTION - * - * This Class provides a Pair of Templated Types - * This provides the same facility as std::pair in C++ - */ - -package org.lflang.util; - -public final class Pair { - private final T1 first; - private final T2 second; - public Pair(final T1 t1, final T2 t2) - { - this.first = t1; - this.second = t2; - } - - public T1 getFirst() - { - return this.first; - } - - public T2 getSecond() - { - return this.second; - } - - @Override - public boolean equals(Object other) { - if (other == null) - return false; - if (this == other) - return true; - if (this.getClass().equals(other.getClass())) { - var otherPair = (Pair) other; - boolean isEqual = (first == null) ? otherPair.getFirst() == null : first.equals(otherPair.getFirst()); - - if (!isEqual) - return false; - - return (second == null) ? otherPair.getSecond() == null : second.equals(otherPair.getSecond()); - } - return false; - } - - @Override - public int hashCode() { - return first == null ? 0 : first.hashCode() + 27 * (second == null ? 0 : second.hashCode()); - } - - @Override - public String toString() { - return "Pair<" + first + ", " + second + ">"; - } -} From fa738b10b494c5fb35c5444c04610144be4da8f6 Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Mon, 22 May 2023 00:45:16 -0700 Subject: [PATCH 45/54] Impl of equals must match impl of hashcode. --- .../src/org/lflang/generator/c/TypeParameterizedReactor.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java index 2f70b10825..689a2dcc72 100644 --- a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java +++ b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java @@ -58,4 +58,9 @@ public InferredType resolveType(InferredType t) { public int hashCode() { return Math.abs(r.hashCode() * 31 + typeArgs.hashCode()); } + + @Override + public boolean equals(Object obj) { + return obj instanceof TypeParameterizedReactor other && r.equals(other.r) && typeArgs.equals(other.typeArgs); + } } From 5f52ca9ffa1af04c4489d6c40cc38117c4f80580 Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Mon, 22 May 2023 00:54:06 -0700 Subject: [PATCH 46/54] Fix NPE and (slightly) dignify a hack. --- org.lflang/src/org/lflang/generator/c/CUtil.java | 3 +-- .../org/lflang/generator/c/InteractingContainedReactors.java | 4 ---- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/org.lflang/src/org/lflang/generator/c/CUtil.java b/org.lflang/src/org/lflang/generator/c/CUtil.java index aed904d0e6..2c10edccf7 100644 --- a/org.lflang/src/org/lflang/generator/c/CUtil.java +++ b/org.lflang/src/org/lflang/generator/c/CUtil.java @@ -761,8 +761,7 @@ private static List multiportWidthTerms(Variable variable) { public static boolean isTokenType(InferredType type, CTypes types) { if (type.isUndefined()) return false; // This is a hacky way to do this. It is now considered to be a bug (#657) - String targetType = types.getVariableDeclaration(null, type, "", false); - return type.isVariableSizeList || targetType.trim().endsWith("*"); + return type.isVariableSizeList || !type.astType.getStars().isEmpty(); } public static String generateWidthVariable(String var) { diff --git a/org.lflang/src/org/lflang/generator/c/InteractingContainedReactors.java b/org.lflang/src/org/lflang/generator/c/InteractingContainedReactors.java index ae6b37437f..26925b7486 100644 --- a/org.lflang/src/org/lflang/generator/c/InteractingContainedReactors.java +++ b/org.lflang/src/org/lflang/generator/c/InteractingContainedReactors.java @@ -7,15 +7,12 @@ import java.util.Set; import org.lflang.ASTUtils; -import org.lflang.federated.generator.FederateInstance; -import org.lflang.generator.NamedInstance; import org.lflang.lf.Input; import org.lflang.lf.Instantiation; import org.lflang.lf.Output; import org.lflang.lf.Port; import org.lflang.lf.Reaction; import org.lflang.lf.Reactor; -import org.lflang.lf.ReactorDecl; import org.lflang.lf.TriggerRef; import org.lflang.lf.VarRef; @@ -154,4 +151,3 @@ public List reactionsTriggered(Instantiation containedReactor, Port por return new LinkedList<>(); } } - From 5299ca5481e3514f37d613d179826e22e7d473e7 Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Mon, 22 May 2023 01:14:01 -0700 Subject: [PATCH 47/54] Fix another NPE. --- .../src/org/lflang/generator/c/TypeParameterizedReactor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java index 689a2dcc72..9a7a0758e4 100644 --- a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java +++ b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java @@ -50,7 +50,7 @@ public Type resolveType(Type t) { } public InferredType resolveType(InferredType t) { - if (t.astType.getCode() != null) return InferredType.fromAST(resolveType(t.astType)); + if (t.astType != null && t.astType.getCode() != null) return InferredType.fromAST(resolveType(t.astType)); return t; } From cccf2aa63526ca0bca4ce8d7e3dda04d44e4730a Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Mon, 22 May 2023 08:02:57 -0700 Subject: [PATCH 48/54] Fix passing generics test. --- .../src/org/lflang/generator/c/TypeParameterizedReactor.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java index 9a7a0758e4..9c0a8787ab 100644 --- a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java +++ b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java @@ -43,6 +43,7 @@ public void doDefines(CodeBuilder b) { } public Type resolveType(Type t) { + if (t.getId() != null) return typeArgs.get(t.getId()); if (t.getCode() == null) return t; var arg = typeArgs.get(t.getCode().getBody()); if (arg != null) return arg; @@ -50,8 +51,8 @@ public Type resolveType(Type t) { } public InferredType resolveType(InferredType t) { - if (t.astType != null && t.astType.getCode() != null) return InferredType.fromAST(resolveType(t.astType)); - return t; + if (t.astType == null) return t; + return InferredType.fromAST(resolveType(t.astType)); } @Override From 0093be73441655298bc70c4c99604a0a4f700455 Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Mon, 22 May 2023 08:13:55 -0700 Subject: [PATCH 49/54] Fix NPE. --- .../src/org/lflang/generator/c/TypeParameterizedReactor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java index 9c0a8787ab..9145b70e6d 100644 --- a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java +++ b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java @@ -43,7 +43,7 @@ public void doDefines(CodeBuilder b) { } public Type resolveType(Type t) { - if (t.getId() != null) return typeArgs.get(t.getId()); + if (t.getId() != null && typeArgs.get(t.getId()) != null) return typeArgs.get(t.getId()); if (t.getCode() == null) return t; var arg = typeArgs.get(t.getCode().getBody()); if (arg != null) return arg; From 76c048c5c3f83c85c371ef945de34d2b108d1d61 Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Mon, 22 May 2023 08:58:06 -0700 Subject: [PATCH 50/54] More of the stars hack. --- org.lflang/src/org/lflang/generator/c/CUtil.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/org.lflang/src/org/lflang/generator/c/CUtil.java b/org.lflang/src/org/lflang/generator/c/CUtil.java index 2c10edccf7..c09f8c63ef 100644 --- a/org.lflang/src/org/lflang/generator/c/CUtil.java +++ b/org.lflang/src/org/lflang/generator/c/CUtil.java @@ -761,7 +761,8 @@ private static List multiportWidthTerms(Variable variable) { public static boolean isTokenType(InferredType type, CTypes types) { if (type.isUndefined()) return false; // This is a hacky way to do this. It is now considered to be a bug (#657) - return type.isVariableSizeList || !type.astType.getStars().isEmpty(); + return type.isVariableSizeList || type.astType != null && (!type.astType.getStars().isEmpty() || + type.astType.getCode() != null && type.astType.getCode().getBody().stripTrailing().endsWith("*")); } public static String generateWidthVariable(String var) { From 47e97d8222919196085abb42afb4e17d2395a901 Mon Sep 17 00:00:00 2001 From: Peter Donovan <33707478+petervdonovan@users.noreply.github.com> Date: Mon, 22 May 2023 12:29:58 -0700 Subject: [PATCH 51/54] Apply suggestions from code review Co-authored-by: Marten Lohstroh --- org.lflang/src/org/lflang/ASTUtils.java | 4 ++-- org.lflang/src/org/lflang/generator/c/CMethodGenerator.java | 2 +- org.lflang/src/org/lflang/generator/c/CWatchdogGenerator.java | 4 ++-- .../src/org/lflang/generator/python/PythonGenerator.java | 2 +- org.lflang/src/org/lflang/validation/LFValidator.java | 2 -- 5 files changed, 6 insertions(+), 8 deletions(-) diff --git a/org.lflang/src/org/lflang/ASTUtils.java b/org.lflang/src/org/lflang/ASTUtils.java index b9cacd8f48..7b747b0adb 100644 --- a/org.lflang/src/org/lflang/ASTUtils.java +++ b/org.lflang/src/org/lflang/ASTUtils.java @@ -402,8 +402,8 @@ public static List allInstantiations(Reactor definition) { } /** - * Given a reactor Class, returns a set of include names for - * interacting reactors which includes all instantiations of base class that it extends + * Given a reactor Class, return a set of include names for + * interacting reactors which includes all instantiations of base class that it extends. * * @param r Reactor Class * */ diff --git a/org.lflang/src/org/lflang/generator/c/CMethodGenerator.java b/org.lflang/src/org/lflang/generator/c/CMethodGenerator.java index 67576f4324..cac2eff8cb 100644 --- a/org.lflang/src/org/lflang/generator/c/CMethodGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CMethodGenerator.java @@ -56,7 +56,7 @@ public static void generateMacroUndefsForMethods( * This function will have a first argument that is a void* pointing to * the self struct, followed by any arguments given in its definition. * @param method The method. - * @param tpr The reactor declaration. + * @param tpr The concrete reactor class. * @param types The C-specific type conversion functions. */ public static String generateMethod( diff --git a/org.lflang/src/org/lflang/generator/c/CWatchdogGenerator.java b/org.lflang/src/org/lflang/generator/c/CWatchdogGenerator.java index 1dac9d13a9..0f38c82c04 100644 --- a/org.lflang/src/org/lflang/generator/c/CWatchdogGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CWatchdogGenerator.java @@ -280,7 +280,7 @@ private static String generateWatchdogFunction( * Return the start of a C function definition for a watchdog. * * @param watchdog The watchdog - * @param tpr The reactor declaration + * @param tpr The concrete reactor class * @return The function name for the watchdog function. */ private static String generateWatchdogFunctionHeader(Watchdog watchdog, TypeParameterizedReactor tpr) { @@ -292,7 +292,7 @@ private static String generateWatchdogFunctionHeader(Watchdog watchdog, TypePara * Return the name of the watchdog expiration handler function. * * @param watchdog The watchdog - * @param tpr The reactor with the watchdog + * @param tpr The concrete reactor class that has the watchdog * @return Name of the watchdog handler function */ private static String watchdogFunctionName(Watchdog watchdog, TypeParameterizedReactor tpr) { diff --git a/org.lflang/src/org/lflang/generator/python/PythonGenerator.java b/org.lflang/src/org/lflang/generator/python/PythonGenerator.java index d71be3ebd1..4e41b700ed 100644 --- a/org.lflang/src/org/lflang/generator/python/PythonGenerator.java +++ b/org.lflang/src/org/lflang/generator/python/PythonGenerator.java @@ -348,7 +348,7 @@ public void processProtoFile(String filename) { /** * Generate the aliases for inputs, outputs, and struct type definitions for * actions of the specified reactor in the specified federate. - * @param tpr The parsed reactor data structure. + * @param tpr The concrete reactor class. */ @Override public void generateAuxiliaryStructs( diff --git a/org.lflang/src/org/lflang/validation/LFValidator.java b/org.lflang/src/org/lflang/validation/LFValidator.java index 94fb578f72..fd37e5a3a7 100644 --- a/org.lflang/src/org/lflang/validation/LFValidator.java +++ b/org.lflang/src/org/lflang/validation/LFValidator.java @@ -267,8 +267,6 @@ public void checkConnection(Connection connection) { if (type == null) { type = ((Port) port.getVariable()).getType(); } else { - // Unfortunately, xtext does not generate a suitable equals() - // method for AST types, so we have to manually check the types. var portType = ((Port) port.getVariable()).getType(); portType = port.getContainer() == null ? portType : new TypeParameterizedReactor(port.getContainer()).resolveType(portType); if (!sameType(type, portType)) { From 882dd8382f3eed94d8d227b0ea99968a77234b0d Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Mon, 22 May 2023 12:30:55 -0700 Subject: [PATCH 52/54] Add comments. --- .../generator/c/TypeParameterizedReactor.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java index 9145b70e6d..a1375c61bb 100644 --- a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java +++ b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java @@ -12,7 +12,12 @@ import org.lflang.lf.Reactor; import org.lflang.lf.Type; -public record TypeParameterizedReactor(Reactor r, Map typeArgs) { +/** + * A reactor class combined with concrete type arguments bound to its type parameters. + * @param reactor The syntactic reactor class definition + * @param typeArgs The type arguments associated with this particular variant of the reactor class. + */ +public record TypeParameterizedReactor(Reactor reactor, Map typeArgs) { public TypeParameterizedReactor(Instantiation i) { this(ASTUtils.toDefinition(i.getReactorClass()), addTypeArgs(i, ASTUtils.toDefinition(i.getReactorClass()))); @@ -29,11 +34,13 @@ private static Map addTypeArgs(Instantiation instantiation, Reacto return ret; } + /** Return the name of the reactor given its type arguments. */ public String getName() { // FIXME: Types that are not just a single token need to be escaped or hashed - return r.getName() + typeArgs.values().stream().map(ASTUtils::toOriginalText).collect(Collectors.joining("_")); + return reactor.getName() + typeArgs.values().stream().map(ASTUtils::toOriginalText).collect(Collectors.joining("_")); } + /** #define type names as concrete types. */ public void doDefines(CodeBuilder b) { typeArgs.forEach((literal, concreteType) -> b.pr( "#if defined " + literal + "\n" + @@ -42,6 +49,7 @@ public void doDefines(CodeBuilder b) { "#define " + literal + " " + ASTUtils.toOriginalText(concreteType))); } + /** Resolve type arguments if the given type is defined in terms of generics. */ public Type resolveType(Type t) { if (t.getId() != null && typeArgs.get(t.getId()) != null) return typeArgs.get(t.getId()); if (t.getCode() == null) return t; @@ -50,6 +58,7 @@ public Type resolveType(Type t) { return t; } + /** Resolve type arguments if the given type is defined in terms of generics. */ public InferredType resolveType(InferredType t) { if (t.astType == null) return t; return InferredType.fromAST(resolveType(t.astType)); @@ -57,11 +66,11 @@ public InferredType resolveType(InferredType t) { @Override public int hashCode() { - return Math.abs(r.hashCode() * 31 + typeArgs.hashCode()); + return Math.abs(reactor.hashCode() * 31 + typeArgs.hashCode()); } @Override public boolean equals(Object obj) { - return obj instanceof TypeParameterizedReactor other && r.equals(other.r) && typeArgs.equals(other.typeArgs); + return obj instanceof TypeParameterizedReactor other && reactor.equals(other.reactor) && typeArgs.equals(other.typeArgs); } } From 2138d7da8f7985022ceee1d29a00e942e6f67a35 Mon Sep 17 00:00:00 2001 From: Peter Donovan Date: Mon, 22 May 2023 12:33:20 -0700 Subject: [PATCH 53/54] Rename tpr.r() -> tpr.reactor(). --- .../lflang/generator/c/CActionGenerator.java | 5 ++--- .../org/lflang/generator/c/CGenerator.java | 22 +++++++++---------- .../lflang/generator/c/CMethodGenerator.java | 8 +++---- .../generator/c/CParameterGenerator.java | 9 +------- .../lflang/generator/c/CPortGenerator.java | 6 ++--- .../generator/c/CReactionGenerator.java | 18 +++++++-------- .../c/CReactorHeaderFileGenerator.java | 17 +++++++------- .../lflang/generator/c/CStateGenerator.java | 9 +------- .../src/org/lflang/generator/c/CUtil.java | 6 ++--- .../generator/c/CWatchdogGenerator.java | 9 ++++---- .../generator/python/PythonGenerator.java | 10 ++++----- 11 files changed, 48 insertions(+), 71 deletions(-) diff --git a/org.lflang/src/org/lflang/generator/c/CActionGenerator.java b/org.lflang/src/org/lflang/generator/c/CActionGenerator.java index 0fa79e94ca..600100b41d 100644 --- a/org.lflang/src/org/lflang/generator/c/CActionGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CActionGenerator.java @@ -8,8 +8,7 @@ import org.lflang.generator.CodeBuilder; import org.lflang.generator.ReactorInstance; import org.lflang.lf.Action; -import org.lflang.lf.Reactor; -import org.lflang.lf.ReactorDecl; + import static org.lflang.generator.c.CGenerator.variableStructType; /** * Generates code for actions (logical or physical) for the C and CCpp target. @@ -98,7 +97,7 @@ public static void generateDeclarations( CodeBuilder body, CodeBuilder constructorCode ) { - for (Action action : ASTUtils.allActions(tpr.r())) { + for (Action action : ASTUtils.allActions(tpr.reactor())) { var actionName = action.getName(); body.pr(action, CGenerator.variableStructType(action, tpr, false)+" _lf_"+actionName+";"); // Initialize the trigger pointer in the action. diff --git a/org.lflang/src/org/lflang/generator/c/CGenerator.java b/org.lflang/src/org/lflang/generator/c/CGenerator.java index ea9de156e0..9d17c6bc14 100644 --- a/org.lflang/src/org/lflang/generator/c/CGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CGenerator.java @@ -888,7 +888,7 @@ private void resolveTemplatedTypes(ReactorInstance reactorInstance, TypeParamete } }); if (!copy.isEmpty()) { // If we found some templated-types update the tpr with new map - child.tpr = new TypeParameterizedReactor(child.tpr.r(), copy); + child.tpr = new TypeParameterizedReactor(child.tpr.reactor(), copy); } resolveTemplatedTypes(child, child.tpr); } @@ -914,9 +914,9 @@ private void generateHeaders() throws IOException { (builder, rr, userFacing) -> { generateAuxiliaryStructs(builder, rr, userFacing); if (userFacing) { - rr.r().getInstantiations().stream() + rr.reactor().getInstantiations().stream() .map(it -> new TypeParameterizedReactorWithDecl(new TypeParameterizedReactor(it), it.getReactorClass())).collect(Collectors.toSet()).forEach(it -> { - ASTUtils.allPorts(it.tpr.r()) + ASTUtils.allPorts(it.tpr.reactor()) .forEach(p -> builder.pr(CPortGenerator.generateAuxiliaryStruct( it.tpr, p, getTarget(), errorReporter, types, new CodeBuilder(), true, it.decl() ))); @@ -1049,8 +1049,8 @@ private void generateReactorClass(TypeParameterizedReactor tpr) throws IOExcepti header.pr("#ifndef " + guardMacro); header.pr("#define " + guardMacro); generateReactorClassHeaders(tpr, headerName, header, src); - header.pr(generateTopLevelPreambles(tpr.r())); - generateUserPreamblesForReactor(tpr.r(), src); + header.pr(generateTopLevelPreambles(tpr.reactor())); + generateUserPreamblesForReactor(tpr.reactor(), src); generateReactorClassBody(tpr, header, src); header.pr("#endif // " + guardMacro); FileUtil.writeToFile(CodeMap.fromGeneratedCode(header.toString()).getGeneratedCode(), fileConfig.getSrcGenPath().resolve(headerName), true); @@ -1075,7 +1075,7 @@ protected void generateReactorClassHeaders(TypeParameterizedReactor tpr, String src.pr("#include \"include/" + CReactorHeaderFileGenerator.outputPath(tpr) + "\""); src.pr("#include \"" + headerName + "\""); tpr.doDefines(src); - ASTUtils.allIncludes(tpr.r()).stream().map(name -> "#include \"" + ASTUtils.allIncludes(tpr.reactor()).stream().map(name -> "#include \"" + name + ".h\"").forEach(header::pr); } @@ -1154,7 +1154,7 @@ protected void generateAuxiliaryStructs(CodeBuilder builder, TypeParameterizedRe #endif """, types.getTargetTagType(), types.getTargetTimeType()) ); - for (Port p : allPorts(tpr.r())) { + for (Port p : allPorts(tpr.reactor())) { builder.pr(CPortGenerator.generateAuxiliaryStruct( tpr, p, @@ -1169,7 +1169,7 @@ protected void generateAuxiliaryStructs(CodeBuilder builder, TypeParameterizedRe // The very first item on this struct needs to be // a trigger_t* because the struct will be cast to (trigger_t*) // by the lf_schedule() functions to get to the trigger. - for (Action action : allActions(tpr.r())) { + for (Action action : allActions(tpr.reactor())) { builder.pr(CActionGenerator.generateAuxiliaryStruct( tpr, action, @@ -1188,7 +1188,7 @@ protected void generateAuxiliaryStructs(CodeBuilder builder, TypeParameterizedRe * go into the constructor. */ private void generateSelfStruct(CodeBuilder builder, TypeParameterizedReactor tpr, CodeBuilder constructorCode) { - var reactor = toDefinition(tpr.r()); + var reactor = toDefinition(tpr.reactor()); var selfType = CUtil.selfType(tpr); // Construct the typedef for the "self" struct. @@ -1267,7 +1267,7 @@ private void generateInteractingContainedReactors( ) { // The contents of the struct will be collected first so that // we avoid duplicate entries and then the struct will be constructed. - var contained = new InteractingContainedReactors(tpr.r()); + var contained = new InteractingContainedReactors(tpr.reactor()); // Next generate the relevant code. for (Instantiation containedReactor : contained.containedReactors()) { var containedTpr = new TypeParameterizedReactor(containedReactor); @@ -1403,7 +1403,7 @@ protected void generateSelfStructExtension( */ public void generateReactions(CodeBuilder src, TypeParameterizedReactor tpr) { var reactionIndex = 0; - var reactor = ASTUtils.toDefinition(tpr.r()); + var reactor = ASTUtils.toDefinition(tpr.reactor()); for (Reaction reaction : allReactions(reactor)) { generateReaction(src, reaction, tpr, reactionIndex); // Increment reaction index even if the reaction is not in the federate diff --git a/org.lflang/src/org/lflang/generator/c/CMethodGenerator.java b/org.lflang/src/org/lflang/generator/c/CMethodGenerator.java index cac2eff8cb..691019b160 100644 --- a/org.lflang/src/org/lflang/generator/c/CMethodGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CMethodGenerator.java @@ -5,10 +5,8 @@ import org.lflang.ASTUtils; import org.lflang.InferredType; import org.lflang.generator.CodeBuilder; -import org.lflang.generator.ReactorInstance; import org.lflang.lf.Method; import org.lflang.lf.Reactor; -import org.lflang.lf.ReactorDecl; /** * Collection of functions to generate C code to declare methods. @@ -26,7 +24,7 @@ public static void generateMacrosForMethods( TypeParameterizedReactor tpr, CodeBuilder body ) { - for (Method method : allMethods(tpr.r())) { + for (Method method : allMethods(tpr.reactor())) { var functionName = methodFunctionName(tpr, method); // If the method has no arguments. Do not pass it any variadic arguments. if (method.getArguments().size() > 0) { @@ -103,7 +101,7 @@ public static void generateMethods( CodeBuilder code, CTypes types ) { - var reactor = tpr.r(); + var reactor = tpr.reactor(); code.prComment("***** Start of method declarations."); signatures(tpr, code, types); generateMacrosForMethods(tpr, code); @@ -127,7 +125,7 @@ public static void signatures( CodeBuilder body, CTypes types ) { - Reactor reactor = tpr.r(); + Reactor reactor = tpr.reactor(); for (Method method : allMethods(reactor)) { body.pr(generateMethodSignature(method, tpr, types) + ";"); } diff --git a/org.lflang/src/org/lflang/generator/c/CParameterGenerator.java b/org.lflang/src/org/lflang/generator/c/CParameterGenerator.java index fc74f76d78..1d563b5de9 100644 --- a/org.lflang/src/org/lflang/generator/c/CParameterGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CParameterGenerator.java @@ -1,17 +1,10 @@ package org.lflang.generator.c; -import java.util.List; -import java.util.stream.Collectors; - -import org.lflang.InferredType; import org.lflang.generator.ParameterInstance; import org.lflang.ASTUtils; import org.lflang.generator.CodeBuilder; -import org.lflang.lf.Assignment; -import org.lflang.lf.Expression; import org.lflang.lf.Initializer; import org.lflang.lf.Parameter; -import org.lflang.lf.Reactor; /** * Generates C code to declare and initialize parameters. @@ -45,7 +38,7 @@ public static String getInitializer(ParameterInstance p) { */ public static String generateDeclarations(TypeParameterizedReactor reactor, CTypes types) { CodeBuilder code = new CodeBuilder(); - for (Parameter parameter : ASTUtils.allParameters(reactor.r())) { + for (Parameter parameter : ASTUtils.allParameters(reactor.reactor())) { code.prSourceLineNumber(parameter); code.pr(types.getTargetType(reactor.resolveType(ASTUtils.getInferredType(parameter))) + " " + parameter.getName() + ";"); } diff --git a/org.lflang/src/org/lflang/generator/c/CPortGenerator.java b/org.lflang/src/org/lflang/generator/c/CPortGenerator.java index 51ff72d919..9cdc20db8f 100644 --- a/org.lflang/src/org/lflang/generator/c/CPortGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CPortGenerator.java @@ -9,9 +9,7 @@ import org.lflang.lf.Input; import org.lflang.lf.Output; import org.lflang.lf.Port; -import org.lflang.lf.Reactor; import org.lflang.lf.ReactorDecl; -import org.lflang.lf.Type; import static org.lflang.generator.c.CGenerator.variableStructType; @@ -213,7 +211,7 @@ private static void generateInputDeclarations( CodeBuilder body, CodeBuilder constructorCode ) { - for (Input input : ASTUtils.allInputs(tpr.r())) { + for (Input input : ASTUtils.allInputs(tpr.reactor())) { var inputName = input.getName(); if (ASTUtils.isMultiport(input)) { body.pr(input, String.join("\n", @@ -251,7 +249,7 @@ private static void generateOutputDeclarations( CodeBuilder body, CodeBuilder constructorCode ) { - for (Output output : ASTUtils.allOutputs(tpr.r())) { + for (Output output : ASTUtils.allOutputs(tpr.reactor())) { // If the port is a multiport, create an array to be allocated // at instantiation. var outputName = output.getName(); diff --git a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java index 2dbb1a1801..797ab93beb 100644 --- a/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CReactionGenerator.java @@ -126,7 +126,7 @@ public static String generateInitializationForReaction(String body, // No triggers are given, which means react to any input. // Declare an argument for every input. // NOTE: this does not include contained outputs. - for (Input input : tpr.r().getInputs()) { + for (Input input : tpr.reactor().getInputs()) { reactionInitialization.pr(generateInputVariablesInReaction(input, tpr, types)); } } @@ -161,7 +161,7 @@ public static String generateInitializationForReaction(String body, } } else if (effect.getVariable() instanceof Mode) { // Mode change effect - int idx = ASTUtils.allModes(tpr.r()).indexOf((Mode)effect.getVariable()); + int idx = ASTUtils.allModes(tpr.reactor()).indexOf((Mode)effect.getVariable()); String name = effect.getVariable().getName(); if (idx >= 0) { reactionInitialization.pr( @@ -701,7 +701,7 @@ public static void generateReactionAndTriggerStructs( var startupReactions = new LinkedHashSet(); var shutdownReactions = new LinkedHashSet(); var resetReactions = new LinkedHashSet(); - for (Reaction reaction : ASTUtils.allReactions(tpr.r())) { + for (Reaction reaction : ASTUtils.allReactions(tpr.reactor())) { // Create the reaction_t struct. body.pr(reaction, "reaction_t _lf__reaction_"+reactionCount+";"); @@ -771,7 +771,7 @@ public static void generateReactionAndTriggerStructs( "self->_lf__reaction_"+reactionCount+".STP_handler = "+STPFunctionPointer+";", "self->_lf__reaction_"+reactionCount+".name = "+addDoubleQuotes("?")+";", reaction.eContainer() instanceof Mode ? - "self->_lf__reaction_"+reactionCount+".mode = &self->_lf__modes["+tpr.r().getModes().indexOf((Mode) reaction.eContainer())+"];" : + "self->_lf__reaction_"+reactionCount+".mode = &self->_lf__modes["+tpr.reactor().getModes().indexOf((Mode) reaction.eContainer())+"];" : "self->_lf__reaction_"+reactionCount+".mode = NULL;" )); // Increment the reactionCount even if the reaction is not in the federate @@ -781,7 +781,7 @@ public static void generateReactionAndTriggerStructs( // Next, create and initialize the trigger_t objects. // Start with the timers. - for (Timer timer : ASTUtils.allTimers(tpr.r())) { + for (Timer timer : ASTUtils.allTimers(tpr.reactor())) { createTriggerT(body, timer, triggerMap, constructorCode, types); // Since the self struct is allocated using calloc, there is no need to set falsy fields. constructorCode.pr("self->_lf__"+timer.getName()+".is_timer = true;"); @@ -802,7 +802,7 @@ public static void generateReactionAndTriggerStructs( } // Next handle actions. - for (Action action : ASTUtils.allActions(tpr.r())) { + for (Action action : ASTUtils.allActions(tpr.reactor())) { createTriggerT(body, action, triggerMap, constructorCode, types); var isPhysical = "true"; if (action.getOrigin().equals(ActionOrigin.LOGICAL)) { @@ -832,12 +832,12 @@ public static void generateReactionAndTriggerStructs( } // Next handle inputs. - for (Input input : ASTUtils.allInputs(tpr.r())) { + for (Input input : ASTUtils.allInputs(tpr.reactor())) { createTriggerT(body, input, triggerMap, constructorCode, types); } // Next handle watchdogs. - for (Watchdog watchdog : ASTUtils.allWatchdogs(tpr.r())) { + for (Watchdog watchdog : ASTUtils.allWatchdogs(tpr.reactor())) { createTriggerT(body, watchdog, triggerMap, constructorCode, types); } } @@ -1092,7 +1092,7 @@ init, getCode(types, reaction, tpr) generateDeadlineFunctionHeader(tpr, reactionIndex), init, reaction.getDeadline().getCode())); } - CMethodGenerator.generateMacroUndefsForMethods(tpr.r(), code); + CMethodGenerator.generateMacroUndefsForMethods(tpr.reactor(), code); code.pr( "#include " + StringUtil.addDoubleQuotes( CCoreFilesUtils.getCTargetSetUndefHeader())); diff --git a/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java b/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java index 20d951b271..00ef4c0faa 100644 --- a/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CReactorHeaderFileGenerator.java @@ -16,7 +16,6 @@ import org.lflang.lf.Reactor; import org.lflang.lf.StateVar; import org.lflang.lf.TriggerRef; -import org.lflang.lf.Type; import org.lflang.lf.TypedVariable; import org.lflang.lf.VarRef; import org.lflang.util.FileUtil; @@ -31,13 +30,13 @@ public interface GenerateAuxiliaryStructs { /** Return the path to the user-visible header file that would be generated for {@code r}. */ public static Path outputPath(TypeParameterizedReactor tpr) { - return Path.of(Path.of(tpr.r().eResource().getURI().toFileString()) + return Path.of(Path.of(tpr.reactor().eResource().getURI().toFileString()) .getFileName().toString().replaceFirst("[.][^.]+$", "")) .resolve(tpr.getName() + ".h"); } public static void doGenerate(CTypes types, TypeParameterizedReactor tpr, CFileConfig fileConfig, GenerateAuxiliaryStructs generator, Function topLevelPreamble) throws IOException { - String contents = generateHeaderFile(types, tpr, generator, topLevelPreamble.apply(tpr.r())); + String contents = generateHeaderFile(types, tpr, generator, topLevelPreamble.apply(tpr.reactor())); FileUtil.writeToFile(contents, fileConfig.getIncludePath().resolve(outputPath(tpr))); } private static String generateHeaderFile(CTypes types, TypeParameterizedReactor tpr, GenerateAuxiliaryStructs generator, String topLevelPreamble) { @@ -48,7 +47,7 @@ private static String generateHeaderFile(CTypes types, TypeParameterizedReactor tpr.doDefines(builder); appendSelfStruct(builder, types, tpr); generator.generate(builder, tpr, true); - for (Reaction reaction : tpr.r().getReactions()) { + for (Reaction reaction : tpr.reactor().getReactions()) { appendSignature(builder, types, reaction, tpr); } builder.pr("#endif"); @@ -80,10 +79,10 @@ private static String userFacingSelfType(TypeParameterizedReactor tpr) { private static void appendSelfStruct(CodeBuilder builder, CTypes types, TypeParameterizedReactor tpr) { builder.pr("typedef struct " + userFacingSelfType(tpr) + "{"); - for (Parameter p : tpr.r().getParameters()) { + for (Parameter p : tpr.reactor().getParameters()) { builder.pr(types.getTargetType(p) + " " + p.getName() + ";"); } - for (StateVar s : tpr.r().getStateVars()) { + for (StateVar s : tpr.reactor().getStateVars()) { builder.pr(types.getTargetType(s) + " " + s.getName() + ";"); } builder.pr("int end[0]; // placeholder; MSVC does not compile empty structs"); @@ -108,7 +107,7 @@ private static String getApiSelfStruct(TypeParameterizedReactor tpr) { public static String nonInlineInitialization(Reaction r, TypeParameterizedReactor reactor) { var mainDef = LfFactory.eINSTANCE.createInstantiation(); mainDef.setName(reactor.getName()); - mainDef.setReactorClass(ASTUtils.findMainReactor(reactor.r().eResource())); + mainDef.setReactorClass(ASTUtils.findMainReactor(reactor.reactor().eResource())); return portVariableStream(r, reactor) .map(it -> it.container == null ? "" : it.getWidth() == null ? String.format("%s %s = (%s) %s;", it.getType(false), it.getAlias(), it.getType(false), it.getRvalue()) @@ -121,7 +120,7 @@ public static String nonInlineInitialization(Reaction r, TypeParameterizedReacto it.getType(true).replaceFirst("\\*", ""), it.getAlias(), CReactionGenerator.maxContainedReactorBankWidth( - reactor.r().getInstantiations().stream() + reactor.reactor().getInstantiations().stream() .filter(instantiation -> new TypeParameterizedReactor(instantiation).equals(it.r)) .findAny().orElseThrow(), null, 0, mainDef), @@ -164,7 +163,7 @@ String getType(boolean userFacing) { var typeName = container == null ? CGenerator.variableStructType(tv, r, userFacing) : CPortGenerator.localPortName(container.getReactorClass(), getName()); - var isMultiport = ASTUtils.isMultiport(ASTUtils.allPorts(r.r()).stream() + var isMultiport = ASTUtils.isMultiport(ASTUtils.allPorts(r.reactor()).stream() .filter(it -> it.getName().equals(tv.getName())) .findAny().orElseThrow()); return typeName + "*" + (getWidth() != null ? "*" : "") + (isMultiport ? "*" : ""); diff --git a/org.lflang/src/org/lflang/generator/c/CStateGenerator.java b/org.lflang/src/org/lflang/generator/c/CStateGenerator.java index 1b75a73ab8..d2e2a56ed8 100644 --- a/org.lflang/src/org/lflang/generator/c/CStateGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CStateGenerator.java @@ -1,16 +1,9 @@ package org.lflang.generator.c; -import java.util.LinkedList; - import org.lflang.ASTUtils; -import org.lflang.InferredType; import org.lflang.generator.CodeBuilder; -import org.lflang.generator.GeneratorBase; import org.lflang.generator.ModeInstance; import org.lflang.generator.ReactorInstance; -import org.lflang.lf.Expression; -import org.lflang.lf.ParameterReference; -import org.lflang.lf.Reactor; import org.lflang.lf.StateVar; public class CStateGenerator { @@ -21,7 +14,7 @@ public class CStateGenerator { */ public static String generateDeclarations(TypeParameterizedReactor reactor, CTypes types) { CodeBuilder code = new CodeBuilder(); - for (StateVar stateVar : ASTUtils.allStateVars(reactor.r())) { + for (StateVar stateVar : ASTUtils.allStateVars(reactor.reactor())) { code.prSourceLineNumber(stateVar); code.pr(types.getTargetType(reactor.resolveType(ASTUtils.getInferredType(stateVar))) + " " + stateVar.getName() + ";"); } diff --git a/org.lflang/src/org/lflang/generator/c/CUtil.java b/org.lflang/src/org/lflang/generator/c/CUtil.java index c09f8c63ef..e6f6cbe990 100644 --- a/org.lflang/src/org/lflang/generator/c/CUtil.java +++ b/org.lflang/src/org/lflang/generator/c/CUtil.java @@ -141,8 +141,8 @@ public static String channelIndexName(PortInstance port) { * the main reactor or the .lf file). */ public static String getName(TypeParameterizedReactor reactor) { - String name = reactor.r().getName().toLowerCase() + reactor.hashCode(); - if (reactor.r().isMain()) { + String name = reactor.reactor().getName().toLowerCase() + reactor.hashCode(); + if (reactor.reactor().isMain()) { return name + "_main"; } return name; @@ -510,7 +510,7 @@ public static String runtimeIndex(ReactorInstance reactor) { * @return The type of a self struct for the specified reactor class. */ public static String selfType(TypeParameterizedReactor reactor) { - if (reactor.r().isMain()) { + if (reactor.reactor().isMain()) { return "_" + CUtil.getName(reactor) + "_main_self_t"; } return "_" + CUtil.getName(reactor) + "_self_t"; diff --git a/org.lflang/src/org/lflang/generator/c/CWatchdogGenerator.java b/org.lflang/src/org/lflang/generator/c/CWatchdogGenerator.java index 0f38c82c04..856111b559 100644 --- a/org.lflang/src/org/lflang/generator/c/CWatchdogGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CWatchdogGenerator.java @@ -16,7 +16,6 @@ import org.lflang.lf.Mode; import org.lflang.lf.ModeTransition; import org.lflang.lf.Reactor; -import org.lflang.lf.ReactorDecl; import org.lflang.lf.VarRef; import org.lflang.lf.Variable; import org.lflang.lf.Watchdog; @@ -95,9 +94,9 @@ protected static int generateInitializeWatchdogs(CodeBuilder code, ReactorInstan protected static void generateWatchdogs( CodeBuilder src, CodeBuilder header, TypeParameterizedReactor tpr, ErrorReporter errorReporter ) { - if (hasWatchdogs(tpr.r())) { + if (hasWatchdogs(tpr.reactor())) { header.pr("#include \"core/threaded/watchdog.h\""); - for (Watchdog watchdog : ASTUtils.allWatchdogs(tpr.r())) { + for (Watchdog watchdog : ASTUtils.allWatchdogs(tpr.reactor())) { src.pr(generateWatchdogFunction(watchdog, tpr, errorReporter)); } } @@ -112,7 +111,7 @@ protected static void generateWatchdogs( protected static void generateWatchdogStruct( CodeBuilder body, TypeParameterizedReactor tpr, CodeBuilder constructorCode) { - for (Watchdog watchdog : ASTUtils.allWatchdogs(tpr.r())) { + for (Watchdog watchdog : ASTUtils.allWatchdogs(tpr.reactor())) { String watchdogName = watchdog.getName(); body.pr(watchdog, "watchdog_t _lf_watchdog_" + watchdogName + ";"); @@ -207,7 +206,7 @@ private static String generateInitializationForWatchdog( Variable variable = effect.getVariable(); if (variable instanceof Mode) { // Mode change effect - int idx = ASTUtils.allModes(tpr.r()).indexOf((Mode) effect.getVariable()); + int idx = ASTUtils.allModes(tpr.reactor()).indexOf((Mode) effect.getVariable()); String name = effect.getVariable().getName(); if (idx >= 0) { watchdogInitialization.pr( diff --git a/org.lflang/src/org/lflang/generator/python/PythonGenerator.java b/org.lflang/src/org/lflang/generator/python/PythonGenerator.java index 4e41b700ed..0a10338d56 100644 --- a/org.lflang/src/org/lflang/generator/python/PythonGenerator.java +++ b/org.lflang/src/org/lflang/generator/python/PythonGenerator.java @@ -62,8 +62,6 @@ import org.lflang.lf.Port; import org.lflang.lf.Reaction; import org.lflang.lf.Reactor; -import org.lflang.lf.ReactorDecl; -import org.lflang.lf.Type; import org.lflang.util.FileUtil; import org.lflang.util.LFCommand; import org.lflang.util.StringUtil; @@ -354,13 +352,13 @@ public void processProtoFile(String filename) { public void generateAuxiliaryStructs( CodeBuilder builder, TypeParameterizedReactor tpr, boolean userFacing ) { - for (Input input : ASTUtils.allInputs(tpr.r())) { + for (Input input : ASTUtils.allInputs(tpr.reactor())) { generateAuxiliaryStructsForPort(builder, tpr, input); } - for (Output output : ASTUtils.allOutputs(tpr.r())) { + for (Output output : ASTUtils.allOutputs(tpr.reactor())) { generateAuxiliaryStructsForPort(builder, tpr, output); } - for (Action action : ASTUtils.allActions(tpr.r())) { + for (Action action : ASTUtils.allActions(tpr.reactor())) { generateAuxiliaryStructsForAction(builder, tpr, action); } } @@ -457,7 +455,7 @@ protected PythonDockerGenerator getDockerGenerator(LFGeneratorContext context) { */ @Override protected void generateReaction(CodeBuilder src, Reaction reaction, TypeParameterizedReactor tpr, int reactionIndex) { - Reactor reactor = ASTUtils.toDefinition(tpr.r()); + Reactor reactor = ASTUtils.toDefinition(tpr.reactor()); // Reactions marked with a `@_c_body` attribute are generated in C if (AttributeUtils.hasCBody(reaction)) { From 46b3ace3087b4f7c3f07967b99e04346aee0c325 Mon Sep 17 00:00:00 2001 From: Peter Donovan <33707478+petervdonovan@users.noreply.github.com> Date: Mon, 22 May 2023 12:37:07 -0700 Subject: [PATCH 54/54] Apply suggestions from code review Co-authored-by: Marten Lohstroh --- org.lflang/src/org/lflang/generator/c/CWatchdogGenerator.java | 4 ++-- .../src/org/lflang/generator/c/TypeParameterizedReactor.java | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/org.lflang/src/org/lflang/generator/c/CWatchdogGenerator.java b/org.lflang/src/org/lflang/generator/c/CWatchdogGenerator.java index 856111b559..b629684bf7 100644 --- a/org.lflang/src/org/lflang/generator/c/CWatchdogGenerator.java +++ b/org.lflang/src/org/lflang/generator/c/CWatchdogGenerator.java @@ -105,7 +105,7 @@ protected static void generateWatchdogs( /** * Generate watchdog definitions in the reactor's self struct. * @param body The place to put the definitions - * @param tpr The reactor declaration + * @param tpr The concrete reactor class * @param constructorCode The place to put initialization code. */ protected static void generateWatchdogStruct( @@ -172,7 +172,7 @@ protected static String generateWatchdogTable(int count) { * Generate necessary initialization code inside the body of a watchdog handler. * * @param watchdog The wotchdog - * @param tpr The declaration for the reactor that has the watchdog + * @param tpr The concrete reactor class that has the watchdog */ private static String generateInitializationForWatchdog( Watchdog watchdog, diff --git a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java index a1375c61bb..0de272b7bf 100644 --- a/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java +++ b/org.lflang/src/org/lflang/generator/c/TypeParameterizedReactor.java @@ -23,7 +23,6 @@ public TypeParameterizedReactor(Instantiation i) { this(ASTUtils.toDefinition(i.getReactorClass()), addTypeArgs(i, ASTUtils.toDefinition(i.getReactorClass()))); } - private static Map addTypeArgs(Instantiation instantiation, Reactor r) { HashMap ret = new HashMap<>(); if (instantiation.getTypeArgs() != null) {