From 9eb52328240efba720d3deee8bc8cfff7e51059c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20=C3=96stlund?= Date: Mon, 8 Apr 2024 14:34:07 +0200 Subject: [PATCH] Handle invalid components better in instance API (#12211) - Mark components as invalid if the typing of them fails in any way with the instance API, and dump them similar to deleted components along with any error messages. --- OMCompiler/Compiler/NFFrontEnd/NFComponent.mo | 16 ++++- OMCompiler/Compiler/NFFrontEnd/NFTyping.mo | 34 ++++++++-- OMCompiler/Compiler/Script/NFApi.mo | 12 ++++ .../GetModelInstanceBinding10.mos | 63 +++++++++++++++++++ .../instance-API/GetModelInstanceBinding9.mos | 2 +- testsuite/openmodelica/instance-API/Makefile | 1 + 6 files changed, 121 insertions(+), 7 deletions(-) create mode 100644 testsuite/openmodelica/instance-API/GetModelInstanceBinding10.mos diff --git a/OMCompiler/Compiler/NFFrontEnd/NFComponent.mo b/OMCompiler/Compiler/NFFrontEnd/NFComponent.mo index 39a592fb69a..0706d7e6cbe 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFComponent.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFComponent.mo @@ -93,9 +93,10 @@ public Modifier modifier; end TYPE_ATTRIBUTE; - record DELETED_COMPONENT + record INVALID_COMPONENT Component component; - end DELETED_COMPONENT; + String errors; + end INVALID_COMPONENT; record WILD "needed for new crefs in the backend" end WILD; @@ -236,6 +237,7 @@ public case COMPONENT() then component.ty; case ITERATOR() then component.ty; case TYPE_ATTRIBUTE() then component.ty; + case INVALID_COMPONENT() then getType(component.component); else Type.UNKNOWN(); end match; end getType; @@ -906,6 +908,16 @@ public end match; end isDeleted; + function isInvalid + input Component component; + output Boolean invalid; + algorithm + invalid := match component + case INVALID_COMPONENT() then true; + else false; + end match; + end isInvalid; + function isTypeAttribute input Component component; output Boolean isAttribute; diff --git a/OMCompiler/Compiler/NFFrontEnd/NFTyping.mo b/OMCompiler/Compiler/NFFrontEnd/NFTyping.mo index 8c463c3f708..250dc7006e3 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFTyping.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFTyping.mo @@ -144,9 +144,15 @@ algorithm case Class.INSTANCED_CLASS(elements = cls_tree as ClassTree.FLAT_TREE()) algorithm - for c in cls_tree.components loop - typeComponent(c, context); - end for; + if InstContext.inInstanceAPI(context) then + for c in cls_tree.components loop + typeComponentTry(c, context); + end for; + else + for c in cls_tree.components loop + typeComponent(c, context); + end for; + end if; () := match c.ty case Type.COMPLEX(complexTy = ComplexType.RECORD(constructor = con)) @@ -476,6 +482,7 @@ algorithm case Component.COMPONENT() then c.ty; case Component.ITERATOR() then c.ty; case Component.ENUM_LITERAL(literal = Expression.ENUM_LITERAL(ty = ty)) then ty; + case Component.INVALID_COMPONENT() then Component.getType(c); // Any other type of component shouldn't show up here. else @@ -487,6 +494,23 @@ algorithm end match; end typeComponent; +function typeComponentTry + input InstNode componentNode; + input InstContext.Type context; +protected + Component comp; +algorithm + ErrorExt.setCheckpoint(getInstanceName()); + try + typeComponent(componentNode, context); + else + comp := InstNode.component(componentNode); + comp := Component.INVALID_COMPONENT(comp, ErrorExt.printCheckpointMessagesStr()); + InstNode.updateComponent(comp, componentNode); + end try; + ErrorExt.delCheckpoint(getInstanceName()); +end typeComponentTry; + function checkComponentStreamAttribute input ConnectorType.Type cty; input Type ty; @@ -976,7 +1000,7 @@ algorithm () := match c case Component.COMPONENT() - guard Component.isDeleted(c) + guard Component.isDeleted(c) or Component.isInvalid(c) then (); case Component.COMPONENT(binding = Binding.UNTYPED_BINDING(), attributes = attrs) @@ -1075,6 +1099,8 @@ algorithm then (); + case Component.INVALID_COMPONENT() then (); + else algorithm Error.assertion(false, getInstanceName() + " got invalid node " + InstNode.name(node), sourceInfo()); diff --git a/OMCompiler/Compiler/Script/NFApi.mo b/OMCompiler/Compiler/Script/NFApi.mo index a07771768d0..2ba367881fb 100644 --- a/OMCompiler/Compiler/Script/NFApi.mo +++ b/OMCompiler/Compiler/Script/NFApi.mo @@ -1356,6 +1356,18 @@ algorithm then (); + case (Component.INVALID_COMPONENT(), SCode.Element.COMPONENT()) + algorithm + json := JSON.addPair("$kind", JSON.makeString("component"), json); + json := JSON.addPair("name", JSON.makeString(InstNode.name(node)), json); + json := JSON.addPair("type", dumpJSONComponentType(cls, node, Component.getType(comp)), json); + json := dumpJSONSCodeMod(elem.modifications, scope, json); + json := JSON.addPairNotNull("prefixes", dumpJSONAttributes(elem.attributes, elem.prefixes, scope), json); + json := dumpJSONCommentOpt(SOME(elem.comment), scope, json); + json := JSON.addPair("$error", JSON.makeString(comp.errors), json); + then + (); + case (Component.COMPONENT(), SCode.Element.COMPONENT()) algorithm json := JSON.addPair("$kind", JSON.makeString("component"), json); diff --git a/testsuite/openmodelica/instance-API/GetModelInstanceBinding10.mos b/testsuite/openmodelica/instance-API/GetModelInstanceBinding10.mos new file mode 100644 index 00000000000..9c72726f293 --- /dev/null +++ b/testsuite/openmodelica/instance-API/GetModelInstanceBinding10.mos @@ -0,0 +1,63 @@ +// name: GetModelInstanceBinding10 +// keywords: +// status: correct +// cflags: -d=newInst +// +// + +loadString(" + model A + Real x[:, :]; + end A; + + model M + A a(x = [0, -1; 1, 1, 1.1, -1]); + end M; +"); + +getModelInstance(M, 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\", +// \"$error\": \"[:3:5-3:17:writable] Error: Type mismatch for positional argument 2 in cat(arg=cat(2, {{0}}, {{-1}})). The argument has type:\\n Real[1, 2]\\nexpected type:\\n Real[:, 4]\\n\" +// } +// ], +// \"source\": { +// \"filename\": \"\", +// \"lineStart\": 2, +// \"columnStart\": 3, +// \"lineEnd\": 4, +// \"columnEnd\": 8 +// } +// }, +// \"modifiers\": { +// \"x\": \"[0, -1; 1, 1, 1.1, -1]\" +// } +// } +// ], +// \"source\": { +// \"filename\": \"\", +// \"lineStart\": 6, +// \"columnStart\": 3, +// \"lineEnd\": 8, +// \"columnEnd\": 8 +// } +// }" +// "" +// endResult diff --git a/testsuite/openmodelica/instance-API/GetModelInstanceBinding9.mos b/testsuite/openmodelica/instance-API/GetModelInstanceBinding9.mos index cd0a3a8df8f..9429802a098 100644 --- a/testsuite/openmodelica/instance-API/GetModelInstanceBinding9.mos +++ b/testsuite/openmodelica/instance-API/GetModelInstanceBinding9.mos @@ -1,4 +1,4 @@ -// name: GetModelInstanceBinding8 +// name: GetModelInstanceBinding9 // keywords: // status: correct // cflags: -d=newInst diff --git a/testsuite/openmodelica/instance-API/Makefile b/testsuite/openmodelica/instance-API/Makefile index 8b88c72cb04..5008bcbb5c7 100644 --- a/testsuite/openmodelica/instance-API/Makefile +++ b/testsuite/openmodelica/instance-API/Makefile @@ -24,6 +24,7 @@ GetModelInstanceBinding6.mos \ GetModelInstanceBinding7.mos \ GetModelInstanceBinding8.mos \ GetModelInstanceBinding9.mos \ +GetModelInstanceBinding10.mos \ GetModelInstanceBreak1.mos \ GetModelInstanceChoices1.mos \ GetModelInstanceChoices2.mos \