Skip to content
This repository was archived by the owner on May 18, 2019. It is now read-only.

Commit d71fe29

Browse files
perostOpenModelica-Hudson
authored andcommitted
[NF] Fix external object calls.
- Change external object calls so they call the constructor instead. - Use an empty class tree for external object so the constructor or destructor can't be called explicitly. - Fix error message for when a function can't be found to say function instead of variable. Belonging to [master]: - #2077 - OpenModelica/OpenModelica-testsuite#806
1 parent f37e029 commit d71fe29

6 files changed

Lines changed: 80 additions & 51 deletions

File tree

Compiler/NFFrontEnd/NFClass.mo

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ uniontype Class
395395
case INSTANCED_CLASS() algorithm cls.restriction := res; then ();
396396
case INSTANCED_BUILTIN() algorithm cls.restriction := res; then ();
397397
case EXPANDED_CLASS() algorithm cls.restriction := res; then ();
398+
// PARTIAL_BUILTIN is only used for predefined builtin types and not needed here.
398399
case DERIVED_CLASS() algorithm cls.restriction := res; then ();
399400
end match;
400401
end setRestriction;

Compiler/NFFrontEnd/NFClassTree.mo

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ public
153153

154154
constant ClassTree EMPTY = ClassTree.PARTIAL_TREE(LookupTree.EMPTY(),
155155
listArray({}), listArray({}), listArray({}), listArray({}), DuplicateTree.EMPTY());
156+
constant ClassTree EMPTY_FLAT = ClassTree.FLAT_TREE(LookupTree.EMPTY(),
157+
listArray({}), listArray({}), listArray({}), DuplicateTree.EMPTY());
156158

157159
uniontype ClassTree
158160
record PARTIAL_TREE

Compiler/NFFrontEnd/NFFunction.mo

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ uniontype Function
207207
{Dump.printComponentRefStr(functionName)}, info);
208208
end try;
209209

210-
(functionRef, found_scope) := Lookup.lookupCallableName(functionName, scope, info);
210+
(functionRef, found_scope) := Lookup.lookupFunctionName(functionName, scope, info);
211211
prefix := ComponentRef.fromNodeList(InstNode.scopeList(found_scope));
212212
functionRef := ComponentRef.append(functionRef, prefix);
213213
end lookupFunction;
@@ -258,11 +258,8 @@ uniontype Function
258258
input SourceInfo info;
259259
output Boolean specialBuiltin;
260260
protected
261-
SCode.Element def;
261+
SCode.Element def = InstNode.definition(fnNode);
262262
algorithm
263-
264-
def := InstNode.definition(fnNode);
265-
266263
(fnNode, specialBuiltin) := match def
267264
local
268265
SCode.ClassDef cdef;

Compiler/NFFrontEnd/NFInst.mo

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -560,10 +560,14 @@ algorithm
560560
node := match InstNode.name(builtin_ext)
561561
case "ExternalObject"
562562
algorithm
563-
(tree, eo_ty) := makeExternalObjectType(scope, node);
564-
tree := ClassTree.expand(tree);
565-
c := Class.PARTIAL_BUILTIN(Type.COMPLEX(node, eo_ty), tree, Modifier.NOMOD(),
566-
Restriction.EXTERNAL_OBJECT());
563+
// Construct the ComplexType for the external object.
564+
eo_ty := makeExternalObjectType(scope, node);
565+
// Construct the Class for the external object. We use an empty class
566+
// tree here, since the constructor and destructor is embedded in the
567+
// ComplexType instead. Using an empty class tree makes sure it's not
568+
// possible to call the constructor or destructor explicitly.
569+
c := Class.PARTIAL_BUILTIN(Type.COMPLEX(node, eo_ty), NFClassTree.EMPTY_FLAT,
570+
Modifier.NOMOD(), Restriction.EXTERNAL_OBJECT());
567571
node := InstNode.updateClass(c, node);
568572
then
569573
node;
@@ -592,14 +596,14 @@ end expandBuiltinExtends;
592596
function makeExternalObjectType
593597
"Constructs a ComplexType for an external object, and also checks that the
594598
external object declaration is valid."
595-
input output ClassTree tree;
599+
input ClassTree tree;
596600
input InstNode node;
597-
output ComplexType ty;
601+
output ComplexType ty;
598602
protected
599603
Absyn.Path base_path;
600604
InstNode constructor = InstNode.EMPTY_NODE(), destructor = InstNode.EMPTY_NODE();
601605
algorithm
602-
(tree, ty) := match tree
606+
ty := match tree
603607
case ClassTree.PARTIAL_TREE()
604608
algorithm
605609
// An external object may not contain components.
@@ -664,18 +668,8 @@ algorithm
664668
{InstNode.name(node), "destructor"}, InstNode.info(node));
665669
fail();
666670
end if;
667-
668-
// We don't need the ExternalObject extends anymore, get rid of it so we
669-
// don't have to handle it later.
670-
tree.exts := arrayCreate(0, InstNode.EMPTY_NODE());
671-
// The component array will only contain a reference node to the
672-
// ExternalObject extends, so get rid of it too.
673-
tree.components := arrayCreate(0, InstNode.EMPTY_NODE());
674-
675-
// Construct the ComplexType for the external object.
676-
ty := ComplexType.EXTERNAL_OBJECT(constructor, destructor);
677671
then
678-
(tree, ty);
672+
ComplexType.EXTERNAL_OBJECT(constructor, destructor);
679673

680674
end match;
681675
end makeExternalObjectType;

Compiler/NFFrontEnd/NFLookup.mo

Lines changed: 48 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ import NFInstNode.NodeTree;
5252
import NFInstNode.CachedData;
5353
import NFComponent.Component;
5454
import Subscript = NFSubscript;
55+
import ComplexType = NFComplexType;
5556

5657
public
5758
type MatchType = enumeration(FOUND, NOT_FOUND, PARTIAL);
@@ -97,7 +98,8 @@ protected
9798
LookupState state;
9899
InstNode node;
99100
algorithm
100-
(foundCref, foundScope, state) := lookupCref(cref, scope, info);
101+
(foundCref, foundScope, state) := lookupCref(cref, scope, info,
102+
Error.LOOKUP_VARIABLE_ERROR);
101103
node := ComponentRef.node(foundCref);
102104
state := fixTypenameState(node, state);
103105
LookupState.assertComponent(state, node, cref, info);
@@ -137,26 +139,6 @@ algorithm
137139
LookupState.assertComponent(state, ComponentRef.node(foundCref), cref, info);
138140
end lookupLocalComponent;
139141

140-
function lookupCallableName
141-
input Absyn.ComponentRef cref;
142-
input InstNode scope "The scope to look in.";
143-
input SourceInfo info;
144-
output ComponentRef foundCref;
145-
output InstNode foundScope;
146-
protected
147-
LookupState state;
148-
InstNode node;
149-
algorithm
150-
(foundCref, foundScope, state) := lookupCref(cref, scope, info);
151-
node := ComponentRef.node(foundCref);
152-
153-
//try
154-
LookupState.assertFunction(state, node, cref, info);
155-
//else
156-
//end try;
157-
158-
end lookupCallableName;
159-
160142
function lookupFunctionName
161143
input Absyn.ComponentRef cref;
162144
input InstNode scope "The scope to look in.";
@@ -167,11 +149,52 @@ protected
167149
LookupState state;
168150
InstNode node;
169151
algorithm
170-
(foundCref, foundScope, state) := lookupCref(cref, scope, info);
152+
(foundCref, foundScope, state) := lookupCref(cref, scope, info,
153+
Error.LOOKUP_FUNCTION_ERROR);
171154
node := ComponentRef.node(foundCref);
155+
(foundCref, state) := fixExternalObjectCall(node, foundCref, state);
172156
LookupState.assertFunction(state, node, cref, info);
173157
end lookupFunctionName;
174158

159+
function fixExternalObjectCall
160+
"Changes calls to external objects so that the constructor is called instead,
161+
i.e. a call such as
162+
'ExtObj eo = ExtObj(...)'
163+
is changed to
164+
'ExtObj eo = ExtObj.constructor(...)'"
165+
input InstNode node;
166+
input output ComponentRef cref;
167+
input output LookupState state;
168+
protected
169+
Class cls;
170+
InstNode constructor;
171+
algorithm
172+
// If it's not a class it can't be an external object.
173+
if not LookupState.isClass(state) then
174+
return;
175+
end if;
176+
177+
// External objects are identified by extending from ExternalObject, so the
178+
// node needs to be expanded before we know whether it's an external object or
179+
// not. Components are instantiated before their bindings, so in proper models
180+
// we shouldn't get any non-expanded external objects here. But to avoid
181+
// getting weird errors in erroneous models we make sure it's expanded anyway.
182+
Inst.expand(node);
183+
cls := InstNode.getClass(node);
184+
185+
() := match cls
186+
case Class.PARTIAL_BUILTIN(ty = Type.COMPLEX(complexTy =
187+
ComplexType.EXTERNAL_OBJECT(constructor = constructor)))
188+
algorithm
189+
cref := ComponentRef.prefixCref(constructor, Type.UNKNOWN(), {}, cref);
190+
state := LookupState.FUNC();
191+
then
192+
();
193+
194+
else ();
195+
end match;
196+
end fixExternalObjectCall;
197+
175198
function lookupImport
176199
input Absyn.Path name;
177200
input InstNode scope;
@@ -188,6 +211,7 @@ function lookupCref
188211
input Absyn.ComponentRef cref;
189212
input InstNode scope "The scope to look in.";
190213
input SourceInfo info;
214+
input Error.Message errMsg;
191215
output ComponentRef foundCref;
192216
output InstNode foundScope "The scope where the first part of the cref was found.";
193217
output LookupState state;
@@ -224,7 +248,7 @@ algorithm
224248
(foundCref, foundScope, state);
225249

226250
case Absyn.ComponentRef.CREF_FULLYQUALIFIED()
227-
then lookupCref(cref.componentRef, InstNode.topScope(scope), info);
251+
then lookupCref(cref.componentRef, InstNode.topScope(scope), info, errMsg);
228252

229253
case Absyn.ComponentRef.WILD() then (ComponentRef.WILD(), scope, LookupState.PREDEF_COMP());
230254
case Absyn.ComponentRef.ALLWILD() then (ComponentRef.WILD(), scope, LookupState.PREDEF_COMP());
@@ -242,7 +266,7 @@ algorithm
242266
end if;
243267

244268
if match_ty <> MatchType.FOUND then
245-
Error.addSourceMessage(Error.LOOKUP_VARIABLE_ERROR,
269+
Error.addSourceMessage(errMsg,
246270
{Dump.printComponentRefStr(cref), InstNode.name(scope)}, info);
247271
fail();
248272
end if;

Compiler/NFFrontEnd/NFLookupState.mo

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,14 +132,25 @@ uniontype LookupState
132132

133133
function isCallable
134134
input InstNode node;
135-
output Boolean b = false;
135+
output Boolean callable;
136136
protected
137-
SCode.Element def;
137+
SCode.Element def = InstNode.definition(node);
138138
algorithm
139-
def := InstNode.definition(node);
140-
b := SCode.isRecord(def) or SCode.isOperator(def);
139+
callable := SCode.isRecord(def) or SCode.isOperator(def);
141140
end isCallable;
142141

142+
function isClass
143+
input LookupState state;
144+
output Boolean isClass;
145+
algorithm
146+
isClass := match state
147+
case COMP_CLASS() then true;
148+
case CLASS() then true;
149+
case PREDEF_CLASS() then true;
150+
else false;
151+
end match;
152+
end isClass;
153+
143154
function assertState
144155
input LookupState endState;
145156
input LookupState expectedState;

0 commit comments

Comments
 (0)