From 7ce7c538b58d29c6f84a0b27d8ccedc34ec9b07b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20=C3=96stlund?= Date: Fri, 17 Mar 2023 11:50:32 +0100 Subject: [PATCH] Add modifier argument to getModelInstance (#10412) - Add an argument to getModelInstance that makes it possible to supply a modifier to use when instantiating the model. - Fix Static.elabCodeType to make it possible to use modifiers and expressions as default arguments in ModelicaBuiltin. Fixes #10349 --- .../Compiler/FrontEnd/ModelicaBuiltin.mo | 1 + OMCompiler/Compiler/FrontEnd/Static.mo | 4 +- OMCompiler/Compiler/NFFrontEnd/NFInst.mo | 6 +- .../Compiler/NFFrontEnd/NFModelicaBuiltin.mo | 1 + .../Compiler/Script/CevalScriptBackend.mo | 4 +- OMCompiler/Compiler/Script/NFApi.mo | 34 +++++- OMEdit/OMEditLIB/OMC/OMCProxy.cpp | 4 +- .../instance-API/GetModelInstanceDerived1.mos | 2 +- .../instance-API/GetModelInstanceDerived2.mos | 4 +- .../instance-API/GetModelInstanceMod4.mos | 105 ++++++++++++++++++ testsuite/openmodelica/instance-API/Makefile | 1 + 11 files changed, 153 insertions(+), 13 deletions(-) create mode 100644 testsuite/openmodelica/instance-API/GetModelInstanceMod4.mos diff --git a/OMCompiler/Compiler/FrontEnd/ModelicaBuiltin.mo b/OMCompiler/Compiler/FrontEnd/ModelicaBuiltin.mo index 709826cc1ff..e0dc3c76509 100644 --- a/OMCompiler/Compiler/FrontEnd/ModelicaBuiltin.mo +++ b/OMCompiler/Compiler/FrontEnd/ModelicaBuiltin.mo @@ -4405,6 +4405,7 @@ end convertPackageToLibrary; function getModelInstance "Dumps a model instance as a JSON string." input TypeName className; + input String modifier = ""; input Boolean prettyPrint = false; output String result; external "builtin"; diff --git a/OMCompiler/Compiler/FrontEnd/Static.mo b/OMCompiler/Compiler/FrontEnd/Static.mo index 0afc9b6dbfa..f85976831f6 100644 --- a/OMCompiler/Compiler/FrontEnd/Static.mo +++ b/OMCompiler/Compiler/FrontEnd/Static.mo @@ -2155,10 +2155,10 @@ algorithm then DAE.T_COMPLEX(ClassInf.UNKNOWN(Absyn.IDENT("Element")),{},NONE(), false); case Absyn.C_EXPRESSION() - then DAE.T_COMPLEX(ClassInf.UNKNOWN(Absyn.IDENT("Expression")),{},NONE(), false); + then DAE.T_CODE(DAE.C_EXPRESSION_OR_MODIFICATION()); case Absyn.C_MODIFICATION() - then DAE.T_COMPLEX(ClassInf.UNKNOWN(Absyn.IDENT("Modification")),{},NONE(), false); + then DAE.T_CODE(DAE.C_EXPRESSION_OR_MODIFICATION()); end match; end elabCodeType; diff --git a/OMCompiler/Compiler/NFFrontEnd/NFInst.mo b/OMCompiler/Compiler/NFFrontEnd/NFInst.mo index 2bc56ee835a..3f1e5c0bf20 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFInst.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFInst.mo @@ -315,8 +315,9 @@ end lookupRootClass; function instantiateRootClass input output InstNode clsNode; input InstContext.Type context; + input Modifier mod = Modifier.NOMOD(); algorithm - clsNode := instantiate(clsNode, context = context); + clsNode := instantiate(clsNode, mod, context = context); checkPartialClass(clsNode, context); insertGeneratedInners(clsNode, InstNode.topScope(clsNode), context); @@ -324,6 +325,7 @@ end instantiateRootClass; function instantiate input output InstNode node; + input Modifier mod = Modifier.NOMOD(); input InstNode parent = InstNode.EMPTY_NODE(); input InstContext.Type context; input Boolean instPartial = false "Whether to instantiate a partial class or not."; @@ -331,7 +333,7 @@ algorithm node := expand(node); if instPartial or not InstNode.isPartial(node) or InstContext.inRelaxed(context) then - node := instClass(node, Modifier.NOMOD(), NFAttributes.DEFAULT_ATTR, true, 0, parent, context); + node := instClass(node, mod, NFAttributes.DEFAULT_ATTR, true, 0, parent, context); end if; end instantiate; diff --git a/OMCompiler/Compiler/NFFrontEnd/NFModelicaBuiltin.mo b/OMCompiler/Compiler/NFFrontEnd/NFModelicaBuiltin.mo index 57e7172d83a..9032370d057 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFModelicaBuiltin.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFModelicaBuiltin.mo @@ -4658,6 +4658,7 @@ end convertPackageToLibrary; function getModelInstance "Dumps a model instance as a JSON string." input TypeName className; + input String modifier = ""; input Boolean prettyPrint = false; output String result; external "builtin"; diff --git a/OMCompiler/Compiler/Script/CevalScriptBackend.mo b/OMCompiler/Compiler/Script/CevalScriptBackend.mo index c1c5723473c..835d8a4fdca 100644 --- a/OMCompiler/Compiler/Script/CevalScriptBackend.mo +++ b/OMCompiler/Compiler/Script/CevalScriptBackend.mo @@ -3085,8 +3085,8 @@ algorithm case ("convertPackageToLibrary", {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.CODE(Absyn.C_TYPENAME(path)), Values.STRING(str)}) then convertPackageToLibrary(classpath, path, str); - case ("getModelInstance", {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.BOOL(b)}) - then NFApi.getModelInstance(classpath, b); + case ("getModelInstance", {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(str), Values.BOOL(b)}) + then NFApi.getModelInstance(classpath, str, b); case ("getModelInstanceIcon", {Values.CODE(Absyn.C_TYPENAME(classpath)), Values.BOOL(b)}) then NFApi.getModelInstanceIcon(classpath, b); diff --git a/OMCompiler/Compiler/Script/NFApi.mo b/OMCompiler/Compiler/Script/NFApi.mo index d2bf567f878..49e4320eeb4 100644 --- a/OMCompiler/Compiler/Script/NFApi.mo +++ b/OMCompiler/Compiler/Script/NFApi.mo @@ -35,6 +35,7 @@ import Absyn; import AbsynUtil; import SCode; import DAE; +import NFModifier.Modifier; protected @@ -47,7 +48,6 @@ import Expression = NFExpression; import NFClass.Class; import NFInstNode.InstNode; import NFInstNode.InstNodeType; -import NFModifier.Modifier; import NFModifier.ModifierScope; import Equation = NFEquation; import NFType.Type; @@ -82,6 +82,7 @@ import NFFlatten.FunctionTree; import NFPrefixes.{Variability}; import NFSections.Sections; import Package = NFPackage; +import Parser; import Prefixes = NFPrefixes; import Restriction = NFRestriction; import Scalarize = NFScalarize; @@ -850,6 +851,7 @@ end InstanceTree; function getModelInstance input Absyn.Path classPath; + input String modifier; input Boolean prettyPrint; output Values.Value res; protected @@ -859,14 +861,16 @@ protected InstanceTree inst_tree; InstSettings inst_settings; String str; + Modifier mod; algorithm context := InstContext.set(NFInstContext.RELAXED, NFInstContext.CLASS); context := InstContext.set(context, NFInstContext.INSTANCE_API); inst_settings := InstSettings.SETTINGS(mergeExtendsSections = false); (_, top) := mkTop(SymbolTable.getAbsyn(), AbsynUtil.pathString(classPath)); + mod := parseModifier(modifier, top); cls_node := Inst.lookupRootClass(classPath, top, context); - cls_node := Inst.instantiateRootClass(cls_node, context); + cls_node := Inst.instantiateRootClass(cls_node, context, mod); inst_tree := buildInstanceTree(cls_node); Inst.instExpressions(cls_node, context = context, settings = inst_settings); Inst.updateImplicitVariability(cls_node, Flags.isSet(Flags.EVAL_PARAM)); @@ -899,6 +903,32 @@ algorithm res := Values.STRING(JSON.toString(json, prettyPrint)); end getModelInstanceIcon; +function parseModifier + input String modifierValue; + input InstNode scope; + output Modifier outMod; +protected + Absyn.Modification amod; + SCode.Mod smod; +algorithm + try + // stringMod parses a single modifier ("x(start = 1) = 2"), but here we want + // to parse just a class modifier ("(x = 1, y = 2)"). So we add a dummy name + // to the string and then extract the modifier from the ElementArg. + Absyn.ElementArg.MODIFICATION(modification = SOME(amod)) := + Parser.stringMod("dummy" + modifierValue); + + // Then translate the Absyn mod to a Modifier, using the given scope (it + // doesn't matter much which scope it is, it just needs some scope or the + // instantiation will fail later). + smod := AbsynToSCode.translateMod(SOME(amod), + SCode.Final.NOT_FINAL(), SCode.Each.NOT_EACH(), AbsynUtil.dummyInfo); + outMod := Modifier.create(smod, "", NFModifier.ModifierScope.COMPONENT(""), scope); + else + outMod := Modifier.NOMOD(); + end try; +end parseModifier; + function buildInstanceTree input InstNode node; input Boolean isDerived = false; diff --git a/OMEdit/OMEditLIB/OMC/OMCProxy.cpp b/OMEdit/OMEditLIB/OMC/OMCProxy.cpp index f12cd37cd9c..d51fdcaa215 100644 --- a/OMEdit/OMEditLIB/OMC/OMCProxy.cpp +++ b/OMEdit/OMEditLIB/OMC/OMCProxy.cpp @@ -3417,10 +3417,10 @@ QJsonObject OMCProxy::getModelInstance(const QString &className, bool prettyPrin } else { getErrorString(); } - modelInstanceJson = mpOMCInterface->getModelInstance(className, prettyPrint); + modelInstanceJson = mpOMCInterface->getModelInstance(className, QString(), prettyPrint); } } else { - modelInstanceJson = mpOMCInterface->getModelInstance(className, prettyPrint); + modelInstanceJson = mpOMCInterface->getModelInstance(className, QString(), prettyPrint); } printMessagesStringInternal(); if (!modelInstanceJson.isEmpty()) { diff --git a/testsuite/openmodelica/instance-API/GetModelInstanceDerived1.mos b/testsuite/openmodelica/instance-API/GetModelInstanceDerived1.mos index 2d48befc501..41d9bc2f79e 100644 --- a/testsuite/openmodelica/instance-API/GetModelInstanceDerived1.mos +++ b/testsuite/openmodelica/instance-API/GetModelInstanceDerived1.mos @@ -15,7 +15,7 @@ loadString(" end M; "); -getModelInstance(M, true); +getModelInstance(M, prettyPrint = true); getErrorString(); // Result: diff --git a/testsuite/openmodelica/instance-API/GetModelInstanceDerived2.mos b/testsuite/openmodelica/instance-API/GetModelInstanceDerived2.mos index 5e7fd397f62..0668056324b 100644 --- a/testsuite/openmodelica/instance-API/GetModelInstanceDerived2.mos +++ b/testsuite/openmodelica/instance-API/GetModelInstanceDerived2.mos @@ -10,8 +10,8 @@ loadString(" type RealInput2 = RealInput(start = 1.0); "); -getModelInstance(RealInput, true); getErrorString(); -getModelInstance(RealInput2, true); getErrorString(); +getModelInstance(RealInput, prettyPrint = true); getErrorString(); +getModelInstance(RealInput2, prettyPrint = true); getErrorString(); // Result: // true diff --git a/testsuite/openmodelica/instance-API/GetModelInstanceMod4.mos b/testsuite/openmodelica/instance-API/GetModelInstanceMod4.mos new file mode 100644 index 00000000000..5458253370b --- /dev/null +++ b/testsuite/openmodelica/instance-API/GetModelInstanceMod4.mos @@ -0,0 +1,105 @@ +// name: GetModelInstanceMod4 +// keywords: +// status: correct +// cflags: -d=newInst +// +// + +loadString(" + type MyReal = Real; + + model A + Real x; + replaceable Real y; + end A; + + model M + A a(x = 1, y = 2); + Real z; + end M; +"); + +getModelInstance(M, modifier = "(a(redeclare MyReal y = 4, x = 3), z = 5)", prettyPrint = true); +getErrorString(); + +// Result: +// true +// "{ +// \"name\": \"M\", +// \"restriction\": \"model\", +// \"elements\": [ +// { +// \"$kind\": \"component\", +// \"name\": \"a\", +// \"type\": { +// \"name\": \"A\", +// \"restriction\": \"model\", +// \"elements\": [ +// { +// \"$kind\": \"component\", +// \"name\": \"x\", +// \"type\": \"Real\", +// \"value\": { +// \"binding\": 3 +// } +// }, +// { +// \"$kind\": \"component\", +// \"name\": \"y\", +// \"type\": { +// \"name\": \"MyReal\", +// \"restriction\": \"type\", +// \"elements\": [ +// { +// \"$kind\": \"extends\", +// \"baseClass\": \"Real\" +// } +// ], +// \"source\": { +// \"filename\": \"\", +// \"lineStart\": 2, +// \"columnStart\": 3, +// \"lineEnd\": 2, +// \"columnEnd\": 21 +// } +// }, +// \"value\": { +// \"binding\": 4 +// }, +// \"prefixes\": { +// \"replaceable\": true +// } +// } +// ], +// \"source\": { +// \"filename\": \"\", +// \"lineStart\": 4, +// \"columnStart\": 3, +// \"lineEnd\": 7, +// \"columnEnd\": 8 +// } +// }, +// \"modifiers\": { +// \"x\": \"1\", +// \"y\": \"2\" +// } +// }, +// { +// \"$kind\": \"component\", +// \"name\": \"z\", +// \"type\": \"Real\", +// \"value\": { +// \"binding\": 5 +// } +// } +// ], +// \"source\": { +// \"filename\": \"\", +// \"lineStart\": 9, +// \"columnStart\": 3, +// \"lineEnd\": 12, +// \"columnEnd\": 8 +// } +// }" +// "" +// endResult diff --git a/testsuite/openmodelica/instance-API/Makefile b/testsuite/openmodelica/instance-API/Makefile index 9c38331c733..1564326f6d1 100644 --- a/testsuite/openmodelica/instance-API/Makefile +++ b/testsuite/openmodelica/instance-API/Makefile @@ -41,6 +41,7 @@ GetModelInstanceMissingClass2.mos \ GetModelInstanceMod1.mos \ GetModelInstanceMod2.mos \ GetModelInstanceMod3.mos \ +GetModelInstanceMod4.mos \ GetModelInstanceReplaceable1.mos \ GetModelInstanceReplaceable2.mos \ GetModelInstanceReplaceable3.mos \