From 252fbdb82a9a75944a465b7dd2b9272a5325696e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20=C3=96stlund?= Date: Wed, 10 Apr 2024 17:27:19 +0200 Subject: [PATCH] Evaluate HideResult annotations (#12220) - Rewrite `Variable.propagateAnnotation` to optionally evaluate the annotation value and use it when propagating HideResult. - Remove the annotation field from `Component.COMPONENT` since it's not actually used anywhere. --- .../Compiler/NFFrontEnd/NFAttributes.mo | 2 +- OMCompiler/Compiler/NFFrontEnd/NFBuiltin.mo | 1 - .../Compiler/NFFrontEnd/NFBuiltinFuncs.mo | 12 +++--- OMCompiler/Compiler/NFFrontEnd/NFComponent.mo | 11 ----- OMCompiler/Compiler/NFFrontEnd/NFInst.mo | 6 +-- OMCompiler/Compiler/NFFrontEnd/NFInstNode.mo | 40 ++++++++---------- OMCompiler/Compiler/NFFrontEnd/NFRecord.mo | 2 +- OMCompiler/Compiler/NFFrontEnd/NFVariable.mo | 41 ++++++++++++++----- .../flattening/modelica/others/HideResult1.mo | 39 ++++++++++++++++++ testsuite/flattening/modelica/others/Makefile | 1 + .../testDAEModeFileSplit_Issue4851.mos | 1 - 11 files changed, 99 insertions(+), 57 deletions(-) create mode 100644 testsuite/flattening/modelica/others/HideResult1.mo diff --git a/OMCompiler/Compiler/NFFrontEnd/NFAttributes.mo b/OMCompiler/Compiler/NFFrontEnd/NFAttributes.mo index ac74592d540..018f60ba720 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFAttributes.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFAttributes.mo @@ -533,7 +533,7 @@ public attr.variability := Variability.IMPLICITLY_DISCRETE; elseif var < Variability.CONTINUOUS and InstContext.inFunction(context) and attr.direction <> Direction.NONE and - isNone(InstNode.getAnnotation("__OpenModelica_functionVariability", compNode)) then + SCodeUtil.isEmptyMod(InstNode.getAnnotation("__OpenModelica_functionVariability", compNode)) then // Variability prefixes on function parameters has no semantic meaning, // remove them so we don't have to worry about accidentally evaluating // e.g. an input declared as constant/parameter. diff --git a/OMCompiler/Compiler/NFFrontEnd/NFBuiltin.mo b/OMCompiler/Compiler/NFFrontEnd/NFBuiltin.mo index 1acb8bb6cf1..878f7593dc9 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFBuiltin.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFBuiltin.mo @@ -416,7 +416,6 @@ constant InstNode TIME = NFBinding.EMPTY_BINDING, NFAttributes.INPUT_ATTR, NONE(), - NONE(), ComponentState.TypeChecked, AbsynUtil.dummyInfo)), InstNode.EMPTY_NODE(), diff --git a/OMCompiler/Compiler/NFFrontEnd/NFBuiltinFuncs.mo b/OMCompiler/Compiler/NFFrontEnd/NFBuiltinFuncs.mo index b4316a85ae6..97f0e596efe 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFBuiltinFuncs.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFBuiltinFuncs.mo @@ -81,7 +81,7 @@ constant SCode.Element DUMMY_ELEMENT = SCode.CLASS( // Default Integer parameter. constant Component INT_COMPONENT = Component.COMPONENT(NFInstNode.EMPTY_NODE(), Type.INTEGER(), NFBinding.EMPTY_BINDING, NFBinding.EMPTY_BINDING, - NFAttributes.DEFAULT_ATTR, NONE(), NONE(), ComponentState.TypeChecked, AbsynUtil.dummyInfo); + NFAttributes.DEFAULT_ATTR, NONE(), ComponentState.TypeChecked, AbsynUtil.dummyInfo); constant InstNode INT_PARAM = InstNode.COMPONENT_NODE("i", NONE(), Visibility.PUBLIC, @@ -91,7 +91,7 @@ constant InstNode INT_PARAM = InstNode.COMPONENT_NODE("i", // Default Real parameter. constant Component REAL_COMPONENT = Component.COMPONENT(NFInstNode.EMPTY_NODE(), Type.REAL(), NFBinding.EMPTY_BINDING, NFBinding.EMPTY_BINDING, - NFAttributes.DEFAULT_ATTR, NONE(), NONE(), ComponentState.TypeChecked, AbsynUtil.dummyInfo); + NFAttributes.DEFAULT_ATTR, NONE(), ComponentState.TypeChecked, AbsynUtil.dummyInfo); constant InstNode REAL_PARAM = InstNode.COMPONENT_NODE("r", NONE(), Visibility.PUBLIC, @@ -101,7 +101,7 @@ constant InstNode REAL_PARAM = InstNode.COMPONENT_NODE("r", // Default Boolean parameter. constant Component BOOL_COMPONENT = Component.COMPONENT(NFInstNode.EMPTY_NODE(), Type.BOOLEAN(), NFBinding.EMPTY_BINDING, NFBinding.EMPTY_BINDING, - NFAttributes.DEFAULT_ATTR, NONE(), NONE(), ComponentState.TypeChecked, AbsynUtil.dummyInfo); + NFAttributes.DEFAULT_ATTR, NONE(), ComponentState.TypeChecked, AbsynUtil.dummyInfo); constant InstNode BOOL_PARAM = InstNode.COMPONENT_NODE("b", NONE(), Visibility.PUBLIC, @@ -111,7 +111,7 @@ constant InstNode BOOL_PARAM = InstNode.COMPONENT_NODE("b", // Default String parameter. constant Component STRING_COMPONENT = Component.COMPONENT(NFInstNode.EMPTY_NODE(), Type.STRING(), NFBinding.EMPTY_BINDING, NFBinding.EMPTY_BINDING, - NFAttributes.DEFAULT_ATTR, NONE(), NONE(), ComponentState.TypeChecked, AbsynUtil.dummyInfo); + NFAttributes.DEFAULT_ATTR, NONE(), ComponentState.TypeChecked, AbsynUtil.dummyInfo); constant InstNode STRING_PARAM = InstNode.COMPONENT_NODE("s", NONE(), Visibility.PUBLIC, @@ -121,7 +121,7 @@ constant InstNode STRING_PARAM = InstNode.COMPONENT_NODE("s", // Default enumeration(:) parameter. constant Component ENUM_COMPONENT = Component.COMPONENT(NFInstNode.EMPTY_NODE(), Type.ENUMERATION(Absyn.Path.IDENT(":"), {}), NFBinding.EMPTY_BINDING, NFBinding.EMPTY_BINDING, - NFAttributes.DEFAULT_ATTR, NONE(), NONE(), ComponentState.TypeChecked, AbsynUtil.dummyInfo); + NFAttributes.DEFAULT_ATTR, NONE(), ComponentState.TypeChecked, AbsynUtil.dummyInfo); constant InstNode ENUM_PARAM = InstNode.COMPONENT_NODE("e", NONE(), Visibility.PUBLIC, @@ -391,7 +391,7 @@ constant Function SAMPLE = Function.FUNCTION(Path.QUALIFIED("OMC_NO_CLOCK", Path constant Component CLOCK_COMPONENT = Component.COMPONENT(NFInstNode.EMPTY_NODE(), Type.CLOCK(), NFBinding.EMPTY_BINDING, NFBinding.EMPTY_BINDING, - NFAttributes.DEFAULT_ATTR, NONE(), NONE(), ComponentState.TypeChecked, AbsynUtil.dummyInfo); + NFAttributes.DEFAULT_ATTR, NONE(), ComponentState.TypeChecked, AbsynUtil.dummyInfo); constant InstNode CLOCK_PARAM = InstNode.COMPONENT_NODE("s", NONE(), Visibility.PUBLIC, diff --git a/OMCompiler/Compiler/NFFrontEnd/NFComponent.mo b/OMCompiler/Compiler/NFFrontEnd/NFComponent.mo index 0706d7e6cbe..f1b712dfc25 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFComponent.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFComponent.mo @@ -71,7 +71,6 @@ public Binding binding; Binding condition; Attributes attributes; - Option ann "the annotation from SCode.Comment as a modifier"; Option comment; ComponentState state; SourceInfo info; @@ -831,16 +830,6 @@ public end match; end comment; - function ann - input Component component; - output Option ann; - algorithm - ann := match component - case COMPONENT() then component.ann; - else NONE(); - end match; - end ann; - function getEvaluateAnnotation input Component component; output Option evaluate; diff --git a/OMCompiler/Compiler/NFFrontEnd/NFInst.mo b/OMCompiler/Compiler/NFFrontEnd/NFInst.mo index 53f8c2362ad..afe04541c3b 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFInst.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFInst.mo @@ -244,7 +244,7 @@ algorithm // propagate hide result attribute // ticket #4346 - flatModel.variables := list(Variable.propagateAnnotation("HideResult", false, var) for var in flatModel.variables); + flatModel.variables := list(Variable.propagateAnnotation("HideResult", false, true, var) for var in flatModel.variables); flatModel := FlatModel.removeNonTopLevelDirections(flatModel); @@ -1885,7 +1885,7 @@ algorithm // is created by instClass. To break the circle we leave the class node // empty here, and let instClass set it for us instead. inst_comp := Component.COMPONENT(InstNode.EMPTY_NODE(), Type.UNKNOWN(), - binding, condition, attr, NONE(), SOME(component.comment), + binding, condition, attr, SOME(component.comment), ComponentState.PartiallyInstantiated, info); InstNode.updateComponent(inst_comp, node); @@ -2121,7 +2121,7 @@ algorithm cmt := orig_comp.comment; then Component.COMPONENT(rdcl_comp.classInst, rdcl_ty, binding, condition, - attr, NONE(), cmt, ComponentState.PartiallyInstantiated, rdcl_comp.info); + attr, cmt, ComponentState.PartiallyInstantiated, rdcl_comp.info); else algorithm diff --git a/OMCompiler/Compiler/NFFrontEnd/NFInstNode.mo b/OMCompiler/Compiler/NFFrontEnd/NFInstNode.mo index 7c990978b11..e1683002705 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFInstNode.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFInstNode.mo @@ -1156,31 +1156,27 @@ uniontype InstNode function getAnnotation input String name; input InstNode node; - output Option mod = NONE(); + output SCode.Mod mod; + output InstNode scope = node; + protected + Option ann; algorithm + while InstNode.isComponent(scope) loop + ann := SCodeUtil.optCommentAnnotation(Component.comment(InstNode.component(scope))); - if InstNode.isComponent(node) then - mod := match Component.comment(InstNode.component(node)) - local - list subModLst; - Boolean done = false; + if isSome(ann) then + mod := SCodeUtil.lookupAnnotation(Util.getOption(ann), name); - case SOME(SCode.COMMENT(annotation_=SOME(SCode.ANNOTATION(modification = SCode.MOD(subModLst = subModLst))))) - algorithm - for sm in subModLst loop - if sm.ident == name then - mod := SOME(sm); - done := true; - break; - end if; - end for; - if not done then - mod := getAnnotation(name, parent(node)); - end if; - then mod; - else getAnnotation(name, parent(node)); - end match; - end if; + if not SCodeUtil.isEmptyMod(mod) then + scope := parent(scope); + return; + end if; + end if; + + scope := parent(scope); + end while; + + mod := SCode.Mod.NOMOD(); end getAnnotation; type ScopeType = enumeration( diff --git a/OMCompiler/Compiler/NFFrontEnd/NFRecord.mo b/OMCompiler/Compiler/NFFrontEnd/NFRecord.mo index 8337dc82c8a..0d1c039122b 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFRecord.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFRecord.mo @@ -160,7 +160,7 @@ algorithm // Create the output record element, using the instance created above as both parent and type. out_comp := Component.COMPONENT(ctor_node, Type.UNTYPED(node, listArray({})), NFBinding.EMPTY_BINDING, NFBinding.EMPTY_BINDING, - NFAttributes.OUTPUT_ATTR, NONE(), NONE(), + NFAttributes.OUTPUT_ATTR, NONE(), ComponentState.FullyInstantiated, AbsynUtil.dummyInfo); out_rec := InstNode.fromComponent("$out" + InstNode.name(ctor_node), out_comp, ctor_node); diff --git a/OMCompiler/Compiler/NFFrontEnd/NFVariable.mo b/OMCompiler/Compiler/NFFrontEnd/NFVariable.mo index f4bbff1c8e4..ac7a43dfec2 100644 --- a/OMCompiler/Compiler/NFFrontEnd/NFVariable.mo +++ b/OMCompiler/Compiler/NFFrontEnd/NFVariable.mo @@ -48,13 +48,16 @@ encapsulated uniontype NFVariable import NFBackendExtension.BackendInfo; protected + import Ceval = NFCeval; import ExpandExp = NFExpandExp; import FlatModelicaUtil = NFFlatModelicaUtil; + import Inst = NFInst; import IOStream; + import MetaModelica.Dangerous.listReverseInPlace; import StringUtil; + import Typing = NFTyping; import Util; import Variable = NFVariable; - import MetaModelica.Dangerous.listReverseInPlace; public record VARIABLE @@ -363,31 +366,47 @@ public function propagateAnnotation input String name; input Boolean overwrite; + input Boolean evaluate = false; input output Variable var; protected InstNode node; - Option mod; + SCode.Mod mod; + Absyn.Exp aexp; + Expression exp; protected SCode.Annotation anno; + InstNode scope; algorithm if ComponentRef.isCref(var.name) then node := ComponentRef.node(var.name); // InstNode.getAnnotation is recursive and returns the first annotation found. // if the original is supposed to be overwritten, skip the node itself and look at the parent - if overwrite then - mod := match node - case InstNode.COMPONENT_NODE() then InstNode.getAnnotation(name, node.parent); - else NONE(); - end match; - else - mod := InstNode.getAnnotation(name, node); + if overwrite and InstNode.isComponent(node) then + node := InstNode.parent(node); end if; - if isSome(mod) then + (mod, scope) := InstNode.getAnnotation(name, node); + + if not SCodeUtil.isEmptyMod(mod) then + if evaluate then + () := matchcontinue mod + case SCode.Mod.MOD(binding = SOME(aexp)) + algorithm + exp := Inst.instExp(aexp, scope, NFInstContext.ANNOTATION, mod.info); + exp := Typing.typeExp(exp, NFInstContext.ANNOTATION, mod.info); + exp := Ceval.evalExp(exp); + mod.binding := SOME(Expression.toAbsyn(exp)); + then + (); + + else (); + end matchcontinue; + end if; + anno := SCode.ANNOTATION(modification = SCode.MOD( finalPrefix = SCode.NOT_FINAL(), eachPrefix = SCode.NOT_EACH(), - subModLst = {Util.getOption(mod)}, + subModLst = {SCode.SubMod.NAMEMOD(name, mod)}, binding = NONE(), info = sourceInfo())); var.comment := SCodeUtil.appendAnnotationToCommentOption(anno, var.comment, true); diff --git a/testsuite/flattening/modelica/others/HideResult1.mo b/testsuite/flattening/modelica/others/HideResult1.mo new file mode 100644 index 00000000000..9e9ab166601 --- /dev/null +++ b/testsuite/flattening/modelica/others/HideResult1.mo @@ -0,0 +1,39 @@ +// name: HideResult1 +// keywords: +// status: correct +// cflags: -d=newInst --showAnnotations +// +// + +model A + Real x; + Real y annotation(HideResult = false); +end A; + +model B + A a1 annotation(HideResult = true); + A a2; + Real z; +end B; + +model HideResult1 + B b1 annotation(HideResult = false); + parameter Boolean hide = true; + B b2 annotation(HideResult = hide); +end HideResult1; + +// Result: +// class HideResult1 +// Real b1.a1.x annotation(HideResult = true); +// Real b1.a1.y annotation(HideResult = false); +// Real b1.a2.x annotation(HideResult = false); +// Real b1.a2.y annotation(HideResult = false); +// Real b1.z annotation(HideResult = false); +// parameter Boolean hide = true; +// Real b2.a1.x annotation(HideResult = true); +// Real b2.a1.y annotation(HideResult = false); +// Real b2.a2.x annotation(HideResult = true); +// Real b2.a2.y annotation(HideResult = false); +// Real b2.z annotation(HideResult = true); +// end HideResult1; +// endResult diff --git a/testsuite/flattening/modelica/others/Makefile b/testsuite/flattening/modelica/others/Makefile index d50bfbe6869..d1b90a4e7d0 100644 --- a/testsuite/flattening/modelica/others/Makefile +++ b/testsuite/flattening/modelica/others/Makefile @@ -41,6 +41,7 @@ ForIterator1.mo \ ForIterator2.mo \ ForIterator3.mo \ GetInstanceName.mo \ +HideResult1.mo \ IconsRecursiveTest.mo \ if_then_elseif_else.mo \ IfExpCombiTable1.mo \ diff --git a/testsuite/simulation/modelica/daemode/testDAEModeFileSplit_Issue4851.mos b/testsuite/simulation/modelica/daemode/testDAEModeFileSplit_Issue4851.mos index c02098e06b4..6c2d04533ef 100644 --- a/testsuite/simulation/modelica/daemode/testDAEModeFileSplit_Issue4851.mos +++ b/testsuite/simulation/modelica/daemode/testDAEModeFileSplit_Issue4851.mos @@ -16,7 +16,6 @@ system("ls *16dae_part*.c"); getErrorString(); // true // {"PowerGrids.Examples.IEEE14bus.IEEE14busGen2Disconnection","PowerGrids.Examples.IEEE14bus.IEEE14busGen2Disconnection_init.xml"} // "Warning: The model contains alias variables with redundant start and/or conflicting nominal values. It is recommended to resolve the conflicts, because otherwise the system could be hard to solve. To print the conflicting alias sets and the chosen candidates please use -d=aliasConflicts. -// Warning: The hideResult annotation could not be evaluated, probably due to missing annotation(Evaluate=true). It is removed. // " // PowerGrids.Examples.IEEE14bus.IEEE14busGen2Disconnection_16dae_part0.c // PowerGrids.Examples.IEEE14bus.IEEE14busGen2Disconnection_16dae_part1.c