Skip to content

Commit bcf3826

Browse files
authored
Improve annotation name lookup (#12078)
- When in an annotation context, check the annotation scope first instead of last so that user classes do not override the builtin annotation classes. Fixes #12077
1 parent b6fa3c0 commit bcf3826

File tree

3 files changed

+120
-51
lines changed

3 files changed

+120
-51
lines changed

OMCompiler/Compiler/NFFrontEnd/NFLookup.mo

Lines changed: 32 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,15 @@ protected
439439
Boolean require_builtin = false;
440440
Boolean loaded = false;
441441
algorithm
442+
if InstContext.inAnnotation(context) then
443+
// If in an annotation context, check the annotation environment first.
444+
try
445+
node := lookupLocalSimpleName(name, InstNode.annotationScope(scope));
446+
return;
447+
else
448+
end try;
449+
end if;
450+
442451
// Look for the name in each enclosing scope, until it's either found or we
443452
// run out of scopes.
444453
for i in 1:Global.recursionDepthLimit loop
@@ -462,22 +471,11 @@ algorithm
462471
node := cur_scope;
463472
return;
464473
else
465-
if InstNode.isTopScope(cur_scope) then
466-
// If the name couldn't be found in any scope...
467-
if InstContext.inAnnotation(context) then
468-
// If we're in an annotation, check in the special scope where
469-
// annotation classes are defined.
470-
cur_scope := InstNode.annotationScope(cur_scope);
471-
elseif not loaded and not require_builtin then
472-
// If we haven't already tried and we're not trying to find a
473-
// builtin name, try to load a library with that name and then try
474-
// to look it up in the top scope again.
475-
loaded := true;
476-
loadLibrary(name, cur_scope);
477-
else
478-
// Nothing more to try, just fail.
479-
fail();
480-
end if;
474+
if InstNode.isTopScope(cur_scope) and not loaded and not require_builtin then
475+
// If the name couldn't be found in any scope, try to load a library
476+
// with that name and then try to look it up in the top scope again.
477+
loaded := true;
478+
loadLibrary(name, cur_scope);
481479
else
482480
// Otherwise, continue in the enclosing scope.
483481
cur_scope := InstNode.parentScope(cur_scope);
@@ -779,42 +777,36 @@ function lookupSimpleCref
779777
output Boolean inEnclosingScope = false;
780778
output LookupState state;
781779
protected
782-
Boolean is_import, require_builtin = false;
780+
Boolean require_builtin = false;
783781
Boolean loaded = false;
784782
Boolean is_enclosing = false;
785783
algorithm
786784
try
787785
(node, cref, state) := lookupSimpleBuiltinCref(name, subs);
788786
foundScope := InstNode.topScope(foundScope);
789787
else
788+
if InstContext.inAnnotation(context) then
789+
// If in an annotation context, check the annotation environment first.
790+
try
791+
(node, foundScope) := lookupLocalSimpleCref(name, InstNode.annotationScope(foundScope));
792+
state := LookupState.nodeState(node);
793+
cref := ComponentRef.fromAbsyn(node, subs);
794+
return;
795+
else
796+
end try;
797+
end if;
798+
790799
// Look for the name in the given scope, and if not found there continue
791800
// through the enclosing scopes of that scope until we either run out of
792801
// scopes or for some reason exceed the recursion depth limit.
793802
for i in 1:Global.recursionDepthLimit loop
794803
try
795-
(node, is_import) := match foundScope
796-
case InstNode.IMPLICIT_SCOPE()
797-
then (lookupIterator(name, foundScope.locals), false);
798-
case InstNode.CLASS_NODE()
799-
then Class.lookupElement(name, InstNode.getClass(foundScope));
800-
case InstNode.COMPONENT_NODE()
801-
then Class.lookupElement(name, InstNode.getClass(foundScope));
802-
case InstNode.INNER_OUTER_NODE()
803-
then Class.lookupElement(name, InstNode.getClass(foundScope.innerNode));
804-
end match;
804+
(node, foundScope) := lookupLocalSimpleCref(name, foundScope);
805805

806806
if require_builtin then
807807
true := InstNode.isBuiltin(node);
808808
end if;
809809

810-
if is_import then
811-
foundScope := InstNode.parent(node);
812-
elseif InstNode.isInnerOuterNode(node) then
813-
// If the node is an outer node, return the inner instead.
814-
node := InstNode.resolveInner(node);
815-
foundScope := InstNode.parent(node);
816-
end if;
817-
818810
// We found a node, return it.
819811
state := LookupState.nodeState(node);
820812
cref := ComponentRef.fromAbsyn(node, subs);
@@ -825,22 +817,11 @@ algorithm
825817
foundScope := InstNode.topScope(InstNode.parentScope(foundScope));
826818
require_builtin := true;
827819
else
828-
if InstNode.isTopScope(foundScope) then
829-
// If the name couldn't be found in any scope...
830-
if InstContext.inAnnotation(context) then
831-
// If we're in an annotation, check in the special scope where
832-
// annotation classes are defined.
833-
foundScope := InstNode.annotationScope(foundScope);
834-
elseif not loaded and not require_builtin then
835-
// If we haven't already tried and we're not trying to find a
836-
// builtin name, try to load a library with that name and then try
837-
// to look it up in the top scope again.
838-
loaded := true;
839-
loadLibrary(name, foundScope);
840-
else
841-
// Nothing more to try, just fail.
842-
fail();
843-
end if;
820+
if InstNode.isTopScope(foundScope) and not loaded and not require_builtin then
821+
// If the name couldn't be found in any scope, try to load a library
822+
// with that name and then try to look it up in the top scope again.
823+
loaded := true;
824+
loadLibrary(name, foundScope);
844825
else
845826
// Look in the next enclosing scope.
846827
inEnclosingScope := not InstNode.isImplicit(foundScope);
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// name: GetModelInstanceAnnotation11
2+
// keywords:
3+
// status: correct
4+
// cflags: -d=newInst
5+
//
6+
//
7+
8+
loadString("
9+
model M
10+
type Smooth = enumeration(one, two, fish);
11+
annotation(Icon(graphics={Line(origin = {-60, 0}, points = {{-20, -1}, {-20, 5}}, smooth = Smooth.Bezier)}));
12+
end M;
13+
");
14+
15+
getModelInstance(M, prettyPrint=true);
16+
17+
// Result:
18+
// true
19+
// "{
20+
// \"name\": \"M\",
21+
// \"restriction\": \"model\",
22+
// \"annotation\": {
23+
// \"Icon\": {
24+
// \"graphics\": [
25+
// {
26+
// \"$kind\": \"record\",
27+
// \"name\": \"Line\",
28+
// \"elements\": [
29+
// true,
30+
// [
31+
// -60,
32+
// 0
33+
// ],
34+
// 0,
35+
// [
36+
// [
37+
// -20,
38+
// -1
39+
// ],
40+
// [
41+
// -20,
42+
// 5
43+
// ]
44+
// ],
45+
// [
46+
// 0,
47+
// 0,
48+
// 0
49+
// ],
50+
// {
51+
// \"$kind\": \"enum\",
52+
// \"name\": \"LinePattern.Solid\",
53+
// \"index\": 2
54+
// },
55+
// 0.25,
56+
// [
57+
// {
58+
// \"$kind\": \"enum\",
59+
// \"name\": \"Arrow.None\",
60+
// \"index\": 1
61+
// },
62+
// {
63+
// \"$kind\": \"enum\",
64+
// \"name\": \"Arrow.None\",
65+
// \"index\": 1
66+
// }
67+
// ],
68+
// 3,
69+
// {
70+
// \"$kind\": \"enum\",
71+
// \"name\": \"Smooth.Bezier\",
72+
// \"index\": 2
73+
// }
74+
// ]
75+
// }
76+
// ]
77+
// }
78+
// },
79+
// \"source\": {
80+
// \"filename\": \"<interactive>\",
81+
// \"lineStart\": 2,
82+
// \"columnStart\": 3,
83+
// \"lineEnd\": 5,
84+
// \"columnEnd\": 8
85+
// }
86+
// }"
87+
// endResult

testsuite/openmodelica/instance-API/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ GetModelInstanceAnnotation7.mos \
1212
GetModelInstanceAnnotation8.mos \
1313
GetModelInstanceAnnotation9.mos \
1414
GetModelInstanceAnnotation10.mos \
15+
GetModelInstanceAnnotation11.mos \
1516
GetModelInstanceAttributes1.mos \
1617
GetModelInstanceAttributes2.mos \
1718
GetModelInstanceBinding1.mos \

0 commit comments

Comments
 (0)