Skip to content

Commit

Permalink
Change __OpenModelica_tearingSelect to use enum (#12005)
Browse files Browse the repository at this point in the history
- Add `TearingSelect` enumeration type to the annotation environment.
- Change `__OpenModelica_tearingSelect` to also accept `TearingSelect`
  values in addition to the existing identifiers such as `always`.
- Give a deprecation warning when using the old identifiers with
  `__OpenModelica_tearingSelect`.

Fixes #11949
  • Loading branch information
perost committed Feb 20, 2024
1 parent a10c18c commit da36889
Show file tree
Hide file tree
Showing 21 changed files with 502 additions and 337 deletions.
103 changes: 79 additions & 24 deletions OMCompiler/Compiler/BackEnd/BackendDAEUtil.mo
Expand Up @@ -1129,36 +1129,91 @@ algorithm
end matchcontinue;
end simplifySubscript;


public function setTearingSelectAttribute
"Returns the expression of the __OpenModelica_tearingSelect annotation"
input Option<SCode.Comment> comment;
output Option<BackendDAE.TearingSelect> ts;
"__OpenModelica_tearingSelect is an annotation and has to be extracted from the comment."
input Option<SCode.Comment> optComment;
output Option<BackendDAE.TearingSelect> tearingSelect = NONE();
protected
SCode.Annotation ann;
Option<SCode.Annotation> opt_anno;
SCode.Annotation anno;
SCode.Mod mod;
Option<Absyn.Exp> opt_val;
Absyn.Exp val;
String name;
SourceInfo info;
algorithm
try
SOME(SCode.COMMENT(annotation_=SOME(ann))) := comment;
try
SOME(val) := SCodeUtil.lookupAnnotationBinding(ann, "__OpenModelica_tearingSelect");
else
SOME(val) := SCodeUtil.lookupAnnotationBinding(ann, "tearingSelect");
Error.addCompilerWarning("Deprecated vendor annotation 'tearingSelect' found. Use '__OpenModelica_tearingSelect' instead.");
end try;
ts := match AbsynUtil.crefIdent(AbsynUtil.expCref(val))
case "always" then SOME(BackendDAE.ALWAYS());
case "prefer" then SOME(BackendDAE.PREFER());
case "avoid" then SOME(BackendDAE.AVOID());
case "never" then SOME(BackendDAE.NEVER());
case "default" then SOME(BackendDAE.DEFAULT());
else NONE();
end match;
else
ts := NONE();
end try;
opt_anno := SCodeUtil.optCommentAnnotation(optComment);

if isNone(opt_anno) then
// No annotation.
return;
end if;

SOME(anno) := opt_anno;
mod := SCodeUtil.lookupAnnotation(anno, "__OpenModelica_tearingSelect");

if SCodeUtil.isEmptyMod(mod) then
mod := SCodeUtil.lookupAnnotation(anno, "tearingSelect");

if not SCodeUtil.isEmptyMod(mod) then
Error.addSourceMessage(Error.DEPRECATED_EXPRESSION,
{"tearingSelect", "__OpenModelica_tearingSelect"}, SCodeUtil.getModifierInfo(mod));
end if;
end if;

opt_val := SCodeUtil.getModifierBinding(mod);

if isNone(opt_val) then
// Annotation exists but has no value.
return;
end if;

SOME(val) := opt_val;
info := SCodeUtil.getModifierInfo(mod);
name := getTearingSelectName(val, info);
tearingSelect := lookupTearingSelectMember(name);

if isNone(tearingSelect) then
Error.addSourceMessage(Error.UNKNOWN_ANNOTATION_VALUE, {Dump.printExpStr(val)}, info);
end if;
end setTearingSelectAttribute;

protected function getTearingSelectName
input Absyn.Exp exp;
input SourceInfo info;
output String name;
algorithm
name := match exp
// TearingSelect.name
case Absyn.Exp.CREF(componentRef =
Absyn.ComponentRef.CREF_QUAL(name = "TearingSelect", subscripts = {}, componentRef =
Absyn.ComponentRef.CREF_IDENT(name = name, subscripts = {})))
then name;

// Single name without the TearingSelect prefix is deprecated but still accepted.
case Absyn.Exp.CREF(componentRef = Absyn.ComponentRef.CREF_IDENT(name = name, subscripts = {}))
algorithm
Error.addSourceMessage(Error.DEPRECATED_EXPRESSION, {name, "TearingSelect." + name}, info);
then
name;

else "";
end match;
end getTearingSelectName;

protected function lookupTearingSelectMember
input String name;
output Option<BackendDAE.TearingSelect> tearingSelect;
algorithm
tearingSelect := match name
case "never" then SOME(BackendDAE.TearingSelect.NEVER());
case "avoid" then SOME(BackendDAE.TearingSelect.AVOID());
case "default" then SOME(BackendDAE.TearingSelect.DEFAULT());
case "prefer" then SOME(BackendDAE.TearingSelect.PREFER());
case "always" then SOME(BackendDAE.TearingSelect.ALWAYS());
else NONE();
end match;
end lookupTearingSelectMember;

public function setHideResultAttribute
"Returns the expression of the hideResult annotation.
Expand Down
32 changes: 16 additions & 16 deletions OMCompiler/Compiler/BackEnd/Tearing.mo
Expand Up @@ -917,7 +917,7 @@ algorithm
case (tvar::rest,{})
equation
if listMember(tvar,tSel_never) then
Error.addCompilerWarning("There are tearing variables with annotation attribute '__OpenModelica_tearingSelect = never'. Use -d=tearingdump and -d=tearingdumpV for more information.");
Error.addCompilerWarning("There are tearing variables with annotation attribute '__OpenModelica_tearingSelect = TearingSelect.never'. Use -d=tearingdump and -d=tearingdumpV for more information.");
end if;
if Flags.isSet(Flags.TEARING_DUMP) or Flags.isSet(Flags.TEARING_DUMPVERBOSE) then
print("\nForced selection of Tearing Variable:\n" + UNDERLINE + "\n");
Expand Down Expand Up @@ -1017,7 +1017,7 @@ algorithm
false = listEmpty(unsolvables);
tvar = listHead(unsolvables);
if listMember(tvar,tSel_never) then
Error.addCompilerWarning("There are tearing variables with annotation attribute '__OpenModelica_tearingSelect = never'. Use -d=tearingdump and -d=tearingdumpV for more information.");
Error.addCompilerWarning("There are tearing variables with annotation attribute '__OpenModelica_tearingSelect = TearingSelect.never'. Use -d=tearingdump and -d=tearingdumpV for more information.");
end if;
if Flags.isSet(Flags.TEARING_DUMP) or Flags.isSet(Flags.TEARING_DUMPVERBOSE) then
print("\nForced selection of Tearing Variable:\n" + UNDERLINE + "\n");
Expand Down Expand Up @@ -1063,12 +1063,12 @@ algorithm
if Flags.isSet(Flags.TEARING_DUMPVERBOSE) then
print("Points after 'discriminateDiscrete':\n" + stringDelimitList(List.map(arrayList(points),intString),",") + "\n\n");
end if;
// 4th: Prefer variables with annotation attribute '__OpenModelica_tearingSelect = prefer'
// 4th: Prefer variables with annotation attribute // '__OpenModelica_tearingSelect = TearingSelect.prefer'
pointsLst = preferAvoidVariables(freeVars, arrayList(points), tSel_prefer, 3.0);
if Flags.isSet(Flags.TEARING_DUMPVERBOSE) then
print("Points after preferring variables with attribute 'prefer':\n" + stringDelimitList(List.map(pointsLst,intString),",") + "\n\n");
end if;
// 5th: Avoid variables with annotation attribute '__OpenModelica_tearingSelect = avoid'
// 5th: Avoid variables with annotation attribute // '__OpenModelica_tearingSelect = TearingSelect.avoid'
pointsLst = preferAvoidVariables(freeVars, pointsLst, tSel_avoid, 0.334);
if Flags.isSet(Flags.TEARING_DUMPVERBOSE) then
print("Points after discrimination against variables with attribute 'avoid':\n" + stringDelimitList(List.map(pointsLst,intString),",") + "\n\n");
Expand All @@ -1079,7 +1079,7 @@ algorithm
if Flags.isSet(Flags.TEARING_DUMPVERBOSE) then
print("tVar: " + intString(tvar) + " (" + intString(listGet(pointsLst,tvar)) + " points)\n\n");
elseif listMember(tvar,tSel_avoid) then
Error.addCompilerWarning("The Tearing heuristic has chosen variables with annotation attribute '__OpenModelica_tearingSelect = avoid'. Use -d=tearingdump and -d=tearingdumpV for more information.");
Error.addCompilerWarning("The Tearing heuristic has chosen variables with annotation attribute '__OpenModelica_tearingSelect = TearingSelect.avoid'. Use -d=tearingdump and -d=tearingdumpV for more information.");
end if;
then
tvar;
Expand Down Expand Up @@ -1728,7 +1728,7 @@ try
unsolvedDiscreteVars := findDiscreteWarnTearingSelect(var_lst);
// print("All discrete Vars: " + stringDelimitList(List.map(unsolvedDiscreteVars,intString),",") + "\n");

// also find $cse vars and try to make them inner vars since they have implicit '__OpenModelica_tearingSelect = never'
// also find $cse vars and try to make them inner vars since they have implicit '__OpenModelica_tearingSelect = TearingSelect.never'
unsolvedCSEVars := findCSE(var_lst);
// print("All CSE Vars: " + stringDelimitList(List.map(unsolvedCSEVars,intString),",") + "\n");

Expand Down Expand Up @@ -2375,11 +2375,11 @@ algorithm

_ := match(var.tearingSelectOption)
case SOME(BackendDAE.ALWAYS()) algorithm
Error.addSourceMessage(Error.COMPILER_WARNING,{"Minimal Tearing is ignoring '__OpenModelica_tearingSelect = always' annotation for discrete variable: "
Error.addSourceMessage(Error.COMPILER_WARNING,{"Minimal Tearing is ignoring '__OpenModelica_tearingSelect = TearingSelect.always' annotation for discrete variable: "
+ BackendDump.varString(var)},ElementSource.getInfo(var.source));
then ();
case SOME(BackendDAE.PREFER()) algorithm
Error.addSourceMessage(Error.COMPILER_WARNING,{"Minimal Tearing is ignoring '__OpenModelica_tearingSelect = prefer' annotation for discrete variable: "
Error.addSourceMessage(Error.COMPILER_WARNING,{"Minimal Tearing is ignoring '__OpenModelica_tearingSelect = TearingSelect.prefer' annotation for discrete variable: "
+ BackendDump.varString(var)},ElementSource.getInfo(var.source));
then ();
else ();
Expand Down Expand Up @@ -2476,7 +2476,7 @@ algorithm
list<Integer> tvars,unsolvables,tVar_never,tVar_discrete,order;
Boolean causal;
// case: There are no unsolvables and no variables with annotation '__OpenModelica_tearingSelect = always'
// case: There are no unsolvables and no variables with annotation '__OpenModelica_tearingSelect = TearingSelect.always'
case ({},{})
equation
// select tearing Var
Expand Down Expand Up @@ -2538,15 +2538,15 @@ algorithm
then
(tvars,order);
// case: There are unsolvables and/or variables with annotation '__OpenModelica_tearingSelect = always'
// case: There are unsolvables and/or variables with annotation '__OpenModelica_tearingSelect = TearingSelect.always'
else
equation
// First choose unsolvables and 'always'-vars as tVars
tvars = List.unique(listAppend(Unsolvables,tSel_always));
tVar_never = List.intersectionOnTrue(tSel_never,tvars,intEq);
tVar_discrete = List.intersectionOnTrue(discreteVars,tvars,intEq);
if not listEmpty(tVar_never) then
Error.addCompilerWarning("There are tearing variables with annotation attribute '__OpenModelica_tearingSelect = never'. Use -d=tearingdump and -d=tearingdumpV for more information.");
Error.addCompilerWarning("There are tearing variables with annotation attribute '__OpenModelica_tearingSelect = TearingSelect.never'. Use -d=tearingdump and -d=tearingdumpV for more information.");
end if;
if not listEmpty(tVar_discrete) then
Error.addCompilerWarning("There are discrete tearing variables because otherwise the system could not have been torn (unsolvables). This may lead to problems during simulation.");
Expand Down Expand Up @@ -2653,7 +2653,7 @@ algorithm
end try;
if listMember(OutTVar,tSel_avoid) then
Error.addCompilerWarning("The Tearing heuristic has chosen variables with annotation attribute '__OpenModelica_tearingSelect = avoid'. Use -d=tearingdump and -d=tearingdumpV for more information.");
Error.addCompilerWarning("The Tearing heuristic has chosen variables with annotation attribute '__OpenModelica_tearingSelect = TearingSelect.avoid'. Use -d=tearingdump and -d=tearingdumpV for more information.");
end if;
if Flags.isSet(Flags.TEARING_DUMPVERBOSE) then
print("\nEND of TearingHeuristic\n" + BORDER + "\n\n");
Expand Down Expand Up @@ -3154,10 +3154,10 @@ algorithm
// 3. Remove variables we don't want as tearing variables
// ******************************************************
// Remove variables with attribute '__OpenModelica_tearingSelect = never'
// Remove variables with attribute '__OpenModelica_tearingSelect = TearingSelect.never'
(_,potentialTVars,_) := List.intersection1OnTrue(potentialTVars,tSel_never,intEq);
if listEmpty(potentialTVars) then
Error.addCompilerError("It is not possible to select a new tearing variable, because all remaining variables have the attribute '__OpenModelica_tearingSelect = never'.");
Error.addCompilerError("It is not possible to select a new tearing variable, because all remaining variables have the attribute '__OpenModelica_tearingSelect = TearingSelect.never'.");
return;
end if;
Expand Down Expand Up @@ -3201,7 +3201,7 @@ algorithm
end if;
if debug then execStat("TEARINGHEURISTIC4_3"); end if;
// 4.4 Prefer variables with annotation attribute '__OpenModelica_tearingSelect = prefer'
// 4.4 Prefer variables with annotation attribute '__OpenModelica_tearingSelect = TearingSelect.prefer'
if not listEmpty(tSel_prefer) then
points := preferAvoidVariables(potentialTVars, points, tSel_prefer, 3.0);
if Flags.isSet(Flags.TEARING_DUMPVERBOSE) then
Expand All @@ -3210,7 +3210,7 @@ algorithm
end if;
if debug then execStat("TEARINGHEURISTIC4_4"); end if;
// 4.5 Avoid variables with annotation attribute '__OpenModelica_tearingSelect = avoid'
// 4.5 Avoid variables with annotation attribute '__OpenModelica_tearingSelect = TearingSelect.avoid'
if not listEmpty(tSel_avoid) then
points := preferAvoidVariables(potentialTVars, points, tSel_avoid, 0.334);
if Flags.isSet(Flags.TEARING_DUMPVERBOSE) then
Expand Down
2 changes: 2 additions & 0 deletions OMCompiler/Compiler/FrontEnd/AnnotationsBuiltin_3_x.mo
Expand Up @@ -370,3 +370,5 @@ record Documentation
String revisions = "" "Revision history";
// Spec 3.5 Figure[:] figures = {}; "Simulation result figures";
end Documentation;

type TearingSelect = enumeration(never, avoid, default, prefer, always);
10 changes: 10 additions & 0 deletions OMCompiler/Compiler/FrontEnd/SCodeUtil.mo
Expand Up @@ -3347,6 +3347,16 @@ algorithm
end match;
end hasBooleanNamedAnnotationInComponent;

public function optCommentAnnotation
input Option<SCode.Comment> cmt;
output Option<SCode.Annotation> ann;
algorithm
ann := match cmt
case SOME(SCode.COMMENT(annotation_ = ann)) then ann;
else NONE();
end match;
end optCommentAnnotation;

public function optCommentHasBooleanNamedAnnotation
"check if the named annotation is present and has value true"
input Option<SCode.Comment> comm;
Expand Down

0 comments on commit da36889

Please sign in to comment.