Skip to content

Commit

Permalink
Evaluate HideResult annotations (#12220)
Browse files Browse the repository at this point in the history
- 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.
  • Loading branch information
perost committed Apr 10, 2024
1 parent 6b6c11f commit 252fbdb
Show file tree
Hide file tree
Showing 11 changed files with 99 additions and 57 deletions.
2 changes: 1 addition & 1 deletion OMCompiler/Compiler/NFFrontEnd/NFAttributes.mo
Expand Up @@ -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.
Expand Down
1 change: 0 additions & 1 deletion OMCompiler/Compiler/NFFrontEnd/NFBuiltin.mo
Expand Up @@ -416,7 +416,6 @@ constant InstNode TIME =
NFBinding.EMPTY_BINDING,
NFAttributes.INPUT_ATTR,
NONE(),
NONE(),
ComponentState.TypeChecked,
AbsynUtil.dummyInfo)),
InstNode.EMPTY_NODE(),
Expand Down
12 changes: 6 additions & 6 deletions OMCompiler/Compiler/NFFrontEnd/NFBuiltinFuncs.mo
Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
11 changes: 0 additions & 11 deletions OMCompiler/Compiler/NFFrontEnd/NFComponent.mo
Expand Up @@ -71,7 +71,6 @@ public
Binding binding;
Binding condition;
Attributes attributes;
Option<Modifier> ann "the annotation from SCode.Comment as a modifier";
Option<SCode.Comment> comment;
ComponentState state;
SourceInfo info;
Expand Down Expand Up @@ -831,16 +830,6 @@ public
end match;
end comment;

function ann
input Component component;
output Option<Modifier> ann;
algorithm
ann := match component
case COMPONENT() then component.ann;
else NONE();
end match;
end ann;

function getEvaluateAnnotation
input Component component;
output Option<Boolean> evaluate;
Expand Down
6 changes: 3 additions & 3 deletions OMCompiler/Compiler/NFFrontEnd/NFInst.mo
Expand Up @@ -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);

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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
Expand Down
40 changes: 18 additions & 22 deletions OMCompiler/Compiler/NFFrontEnd/NFInstNode.mo
Expand Up @@ -1156,31 +1156,27 @@ uniontype InstNode
function getAnnotation
input String name;
input InstNode node;
output Option<SCode.SubMod> mod = NONE();
output SCode.Mod mod;
output InstNode scope = node;
protected
Option<SCode.Annotation> 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<SCode.SubMod> 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(
Expand Down
2 changes: 1 addition & 1 deletion OMCompiler/Compiler/NFFrontEnd/NFRecord.mo
Expand Up @@ -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);

Expand Down
41 changes: 30 additions & 11 deletions OMCompiler/Compiler/NFFrontEnd/NFVariable.mo
Expand Up @@ -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
Expand Down Expand Up @@ -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<SCode.SubMod> 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);
Expand Down
39 changes: 39 additions & 0 deletions 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
1 change: 1 addition & 0 deletions testsuite/flattening/modelica/others/Makefile
Expand Up @@ -41,6 +41,7 @@ ForIterator1.mo \
ForIterator2.mo \
ForIterator3.mo \
GetInstanceName.mo \
HideResult1.mo \
IconsRecursiveTest.mo \
if_then_elseif_else.mo \
IfExpCombiTable1.mo \
Expand Down
Expand Up @@ -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
Expand Down

0 comments on commit 252fbdb

Please sign in to comment.