From a738ef5ed5b46a6d85bb451bfd76ad3c47134fe9 Mon Sep 17 00:00:00 2001 From: Rahul P <26484864+rahulp13@users.noreply.github.com> Date: Fri, 24 Feb 2023 15:45:30 +0530 Subject: [PATCH] Fetch connection list API (#10042) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fetch connection list API * fixed indentation issue * removed duplicate flatten fn code * added testcases for connection list --------- Co-authored-by: rahulp13 Co-authored-by: Per Östlund --- .../Compiler/FrontEnd/ModelicaBuiltin.mo | 12 ++++ .../Compiler/NFFrontEnd/NFConnections.mo | 7 ++ OMCompiler/Compiler/NFFrontEnd/NFFlatten.mo | 34 +++++++-- OMCompiler/Compiler/NFFrontEnd/NFInst.mo | 41 +++++++++++ .../Compiler/NFFrontEnd/NFModelicaBuiltin.mo | 12 ++++ .../Compiler/Script/CevalScriptBackend.mo | 19 +++++ .../interactive-API/ConnectionList.mos | 69 +++++++++++++++++++ .../openmodelica/interactive-API/Makefile | 1 + 8 files changed, 188 insertions(+), 7 deletions(-) create mode 100644 testsuite/openmodelica/interactive-API/ConnectionList.mos diff --git a/OMCompiler/Compiler/FrontEnd/ModelicaBuiltin.mo b/OMCompiler/Compiler/FrontEnd/ModelicaBuiltin.mo index a576bc2af3d..c2f6f3aa104 100644 --- a/OMCompiler/Compiler/FrontEnd/ModelicaBuiltin.mo +++ b/OMCompiler/Compiler/FrontEnd/ModelicaBuiltin.mo @@ -3281,6 +3281,18 @@ external "builtin"; annotation(preferredView="text"); end getNthConnection; +function getConnectionList "returns an array of all connections including those within loops" + input TypeName className; + output String[:,:] result; +external "builtin"; +annotation( + Documentation(info=" +Returns a list of all connect equations including those in loops. For example: +
{{\"connection1.lhs\",\"connection1.rhs\"}, {\"connection2.lhs\",\"connection2.rhs\"}}
+"), + preferredView="text"); +end getConnectionList; + function getAlgorithmCount "Counts the number of Algorithm sections in a class." input TypeName class_; output Integer count; diff --git a/OMCompiler/Compiler/NFFrontEnd/NFConnections.mo b/OMCompiler/Compiler/NFFrontEnd/NFConnections.mo index 571551f3ee0..03eb719e192 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFConnections.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFConnections.mo @@ -309,5 +309,12 @@ public str := stringDelimitList(strl, "\n"); end toString; + function toStringList + input Connections conns; + output list> strl = {}; + algorithm + strl := list({Connector.toString(c.lhs), Connector.toString(c.rhs)} for c in conns.connections); + end toStringList; + annotation(__OpenModelica_Interface="frontend"); end NFConnections; diff --git a/OMCompiler/Compiler/NFFrontEnd/NFFlatten.mo b/OMCompiler/Compiler/NFFrontEnd/NFFlatten.mo index 40d1d58b716..7053734d3ef 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFFlatten.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFFlatten.mo @@ -278,6 +278,7 @@ constant Prefix EMPTY_INDEXED_PREFIX = Prefix.INDEXED_PREFIX(ComponentRef.EMPTY( function flatten input InstNode classInst; input String name; + input Boolean getConnectionResolved = true; output FlatModel flatModel; protected Sections sections; @@ -327,18 +328,37 @@ algorithm // get inputs and outputs for algorithms now that types are computed flatModel.algorithms := list(Algorithm.setInputsOutputs(al) for al in flatModel.algorithms); flatModel.initialAlgorithms := list(Algorithm.setInputsOutputs(al) for al in flatModel.initialAlgorithms); - + execStat(getInstanceName()); InstUtil.dumpFlatModelDebug("flatten", flatModel); - - if settings.arrayConnect then - flatModel := resolveArrayConnections(flatModel); - else - flatModel := resolveConnections(flatModel, deleted_vars, settings); + + if getConnectionResolved then + if settings.arrayConnect then + flatModel := resolveArrayConnections(flatModel); + else + flatModel := resolveConnections(flatModel, deleted_vars, settings); + end if; + InstUtil.dumpFlatModelDebug("connections", flatModel); end if; - InstUtil.dumpFlatModelDebug("connections", flatModel); end flatten; +function flattenConnection + input InstNode classInst; + input String name; + output Connections conns; +protected + FlatModel flatModel; + UnorderedSet deleted_vars; +algorithm + flatModel := flatten(classInst, name, false); + deleted_vars := UnorderedSet.new(ComponentRef.hash, ComponentRef.isEqual); + + // get the connections from the model + (flatModel, conns) := Connections.collect(flatModel, function isDeletedConnector(deletedVars = deleted_vars)); + // Elaborate expandable connectors. + (_, conns) := ExpandableConnectors.elaborate(flatModel, conns); +end flattenConnection; + function collectFunctions input FlatModel flatModel; output FunctionTree funcs; diff --git a/OMCompiler/Compiler/NFFrontEnd/NFInst.mo b/OMCompiler/Compiler/NFFrontEnd/NFInst.mo index ce483383ff8..7846332b607 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFInst.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFInst.mo @@ -70,6 +70,7 @@ import Array; import Error; import FlagsUtil; import Flatten = NFFlatten; +import Connections = NFConnections; import InstUtil = NFInstUtil; import List; import Lookup = NFLookup; @@ -237,6 +238,46 @@ algorithm //print(name + " has " + String(var_count) + " variable(s) and " + String(eq_count) + " equation(s).\n"); end instClassInProgram; +function instClassForConnection + "Instantiates a class given by its fully qualified path, with the result being + a list of all connections." + input Absyn.Path classPath; + input SCode.Program program; + input SCode.Program annotationProgram; + output list> connList = {}; +protected + Connections conns; + InstNode top, cls, inst_cls; + String name; + InstContext.Type context; +algorithm + resetGlobalFlags(); + context := if Flags.getConfigBool(Flags.CHECK_MODEL) or Flags.isSet(Flags.NF_API) then + NFInstContext.RELAXED else NFInstContext.NO_CONTEXT; + + // Create a top scope from the given top-level classes. + top := makeTopNode(program, annotationProgram); + name := AbsynUtil.pathString(classPath); + + // Look up the class to instantiate. + cls := lookupRootClass(classPath, top, context); + + // Instantiate the class. + inst_cls := instantiateRootClass(cls, context); + + // Instantiate expressions (i.e. anything that can contains crefs, like + // bindings, dimensions, etc). This is done as a separate step after + // instantiation to make sure that lookup is able to find the correct nodes. + instExpressions(inst_cls, context = context); + + // Type the class. + Typing.typeClass(inst_cls, context); + + // Flatten the model and get connections + conns := Flatten.flattenConnection(inst_cls, name); + connList := Connections.toStringList(conns); +end instClassForConnection; + function resetGlobalFlags "Resets the global flags that the frontend uses." algorithm diff --git a/OMCompiler/Compiler/NFFrontEnd/NFModelicaBuiltin.mo b/OMCompiler/Compiler/NFFrontEnd/NFModelicaBuiltin.mo index 8aa31351645..bfa56b3b032 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFModelicaBuiltin.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFModelicaBuiltin.mo @@ -3534,6 +3534,18 @@ external "builtin"; annotation(preferredView="text"); end getNthConnection; +function getConnectionList "returns an array of all connections including those within loops" + input TypeName className; + output String[:,:] result; +external "builtin"; +annotation( + Documentation(info=" +Returns a list of all connect equations including those in loops. For example: +
{{\"connection1.lhs\",\"connection1.rhs\"}, {\"connection2.lhs\",\"connection2.rhs\"}}
+"), + preferredView="text"); +end getConnectionList; + function getAlgorithmCount "Counts the number of Algorithm sections in a class." input TypeName class_; output Integer count; diff --git a/OMCompiler/Compiler/Script/CevalScriptBackend.mo b/OMCompiler/Compiler/Script/CevalScriptBackend.mo index 41f3f599cf0..5599bc93e15 100644 --- a/OMCompiler/Compiler/Script/CevalScriptBackend.mo +++ b/OMCompiler/Compiler/Script/CevalScriptBackend.mo @@ -2785,6 +2785,9 @@ algorithm case ("getNthConnection",_) then ValuesUtil.makeArray({}); + case ("getConnectionList", {Values.CODE(Absyn.C_TYPENAME(path))}) + then getConnectionList(path); + case ("getAlgorithmCount",{Values.CODE(Absyn.C_TYPENAME(path))}) equation absynClass = InteractiveUtil.getPathedClassInProgram(path, SymbolTable.getAbsyn()); @@ -8611,6 +8614,22 @@ algorithm result := Values.STRING(str); end instantiateModel; +protected function getConnectionList +"@author: rahulp + Returns a list of all connect equations including those in loops" + input Absyn.Path className; + output Values.Value valList; + protected + SCode.Program sp, annotation_sp; + list> connList; + algorithm + annotation_sp := AbsynToSCode.translateAbsyn2SCode(InteractiveUtil.modelicaAnnotationProgram(Config.getAnnotationVersion())); + (_, sp) := FBuiltin.getInitialFunctions(); + sp := listAppend(SymbolTable.getSCode(), sp); + connList := NFInst.instClassForConnection(className, sp, annotation_sp); + valList := ValuesUtil.makeArray(list(ValuesUtil.makeArray(List.map(conn, ValuesUtil.makeString)) for conn in connList)); +end getConnectionList; + protected function runConversionScript input Absyn.Path clsPath; input String scriptFile; diff --git a/testsuite/openmodelica/interactive-API/ConnectionList.mos b/testsuite/openmodelica/interactive-API/ConnectionList.mos new file mode 100644 index 00000000000..858bf736084 --- /dev/null +++ b/testsuite/openmodelica/interactive-API/ConnectionList.mos @@ -0,0 +1,69 @@ +// name: ConnectionList +// status: correct +// cflags: -d=newInst +// +// Tests the getConnectionList API function. +// + +loadString(" + model M + connector A + end A; + connector B + end B; + + parameter Integer n = 3; + A a[n], c; + B b[n], d; + equation + connect(a,b); + connect(c,d); + end M; +"); getErrorString(); + +getConnectionList(M); getErrorString(); + +deleteClass(M); getErrorString(); + + + +// Testing complex loop structure + +loadString(" + model M + connector A + end A; + connector B + end B; + + parameter Integer n = 5; + A a[n]; + B b[n]; + equation + for i in n-2:(n-2)*2-3 loop + for j in 1:n loop + if j <> i then + connect(a[j],b[j]); + end if; + end for; + + connect(a[i],b[i]); + end for; + end M; +"); getErrorString(); + +getConnectionList(M); getErrorString(); + + +// Result: +// true +// "" +// {{"c","d"},{"a[3]","b[3]"},{"a[2]","b[2]"},{"a[1]","b[1]"}} +// "" +// true +// "" +// true +// "" +// {{"a[3]","b[3]"},{"a[5]","b[5]"},{"a[4]","b[4]"},{"a[2]","b[2]"},{"a[1]","b[1]"}} +// "" +// endResult diff --git a/testsuite/openmodelica/interactive-API/Makefile b/testsuite/openmodelica/interactive-API/Makefile index a93b43949fd..cbd0e5aa707 100644 --- a/testsuite/openmodelica/interactive-API/Makefile +++ b/testsuite/openmodelica/interactive-API/Makefile @@ -21,6 +21,7 @@ checkAllModelsRecursive1.mos \ choicesAllMatching.mos \ ConvertUnits.mos \ ConversionVersions.mos \ +ConnectionList.mos \ CopyClass.mos \ DefaultComponentName.mos \ DeleteConnection.mos \