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

Commit c8394ea

Browse files
perostOpenModelica-Hudson
authored andcommitted
Handling of self-referencing extends in nfinst.
- Handle extending a local class via the scope itself. - Detect some cases of extends loops.
1 parent b2744b0 commit c8394ea

File tree

4 files changed

+50
-4
lines changed

4 files changed

+50
-4
lines changed

Compiler/NFFrontEnd/NFInst.mo

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@ algorithm
356356
// Look up the base class and expand it.
357357
scope := InstNode.parent(ext);
358358
base_node := Lookup.lookupBaseClassName(base_path, scope, info);
359+
checkExtendsLoop(base_node, base_path, info);
359360
checkReplaceableBaseClass(base_node, base_path, info);
360361
base_node := expand(base_node);
361362

@@ -370,6 +371,28 @@ algorithm
370371
end if;
371372
end expandExtends;
372373

374+
function checkExtendsLoop
375+
"Gives an error if a base node is in the process of being expanded itself,
376+
since that means we have an extends loop in the model."
377+
input InstNode node;
378+
input Absyn.Path path;
379+
input SourceInfo info;
380+
algorithm
381+
() := match InstNode.getClass(node)
382+
// expand begins by changing the class to an EXPANDED_CLASS, but keeps the
383+
// class tree. So finding a PARTIAL_TREE here means the class is in the
384+
// process of being expanded.
385+
case Class.EXPANDED_CLASS(elements = ClassTree.PARTIAL_TREE())
386+
algorithm
387+
Error.addSourceMessage(Error.EXTENDS_LOOP,
388+
{Absyn.pathString(path)}, info);
389+
then
390+
fail();
391+
392+
else ();
393+
end match;
394+
end checkExtendsLoop;
395+
373396
function checkReplaceableBaseClass
374397
"Checks that all parts of a name used as a base class are transitively
375398
non-replaceable."

Compiler/NFFrontEnd/NFInstNode.mo

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,24 @@ uniontype InstNode
715715
case IMPLICIT_SCOPE() then IMPLICIT_SCOPE(scope, iterator :: scope.locals);
716716
end match;
717717
end addIterator;
718+
719+
function refEqual
720+
"Returns true if two nodes references the same class or component,
721+
otherwise false."
722+
input InstNode node1;
723+
input InstNode node2;
724+
output Boolean refEqual;
725+
algorithm
726+
refEqual := match (node1, node2)
727+
case (CLASS_NODE(), CLASS_NODE())
728+
then referenceEq(Pointer.access(node1.cls), Pointer.access(node2.cls));
729+
case (COMPONENT_NODE(), COMPONENT_NODE())
730+
then referenceEq(Pointer.access(node1.component), Pointer.access(node2.component));
731+
// Other nodes like ref nodes might be equal, but we neither know nor care.
732+
else false;
733+
end match;
734+
end refEqual;
735+
718736
end InstNode;
719737

720738
annotation(__OpenModelica_Interface="frontend");

Compiler/NFFrontEnd/NFLookup.mo

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ algorithm
338338
algorithm
339339
(node, state) := lookupFirstIdent(name.name, scope);
340340
then
341-
lookupLocalName(name.path, node, state);
341+
lookupLocalName(name.path, node, state, InstNode.refEqual(node, scope));
342342

343343
// Fully qualified path, start from top scope.
344344
case Absyn.Path.FULLYQUALIFIED()
@@ -371,6 +371,7 @@ function lookupLocalName
371371
input Absyn.Path name;
372372
input output InstNode node;
373373
input output LookupState state;
374+
input Boolean selfReference = false;
374375
algorithm
375376
// Looking something up in a component is only legal when the name begins with
376377
// a component reference, and for that we use lookupCref. So if the given node
@@ -380,7 +381,11 @@ algorithm
380381
return;
381382
end if;
382383

383-
node := Inst.instPackage(node);
384+
// If the given node extends from itself, like 'extends Modelica.Icons.***' in
385+
// the MSL, then it's already being instantiated here.
386+
if not selfReference then
387+
node := Inst.instPackage(node);
388+
end if;
384389

385390
// Look up the path in the scope.
386391
() := match name

Compiler/Util/Error.mo

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,8 @@ public constant Message REM_ARG_ZERO = MESSAGE(17, TRANSLATION(), ERROR(),
164164
Util.gettext("Second argument in rem is zero in rem(%s,%s)."));
165165
public constant Message SCRIPT_READ_SIM_RES_ERROR = MESSAGE(18, SCRIPTING(), ERROR(),
166166
Util.gettext("Error reading simulation result."));
167-
public constant Message RECURSIVE_EXTENDS = MESSAGE(19, TRANSLATION(), ERROR(),
168-
Util.gettext("Extending %s is not allowed, since it is an enclosing class."));
167+
public constant Message EXTENDS_LOOP = MESSAGE(19, TRANSLATION(), ERROR(),
168+
Util.gettext("extends %s causes an instantiation loop."));
169169
public constant Message LOAD_MODEL_ERROR = MESSAGE(20, TRANSLATION(), ERROR(),
170170
Util.gettext("Class %s not found."));
171171
public constant Message WRITING_FILE_ERROR = MESSAGE(21, SCRIPTING(), ERROR(),

0 commit comments

Comments
 (0)