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

Commit ebf70e3

Browse files
perostOpenModelica-Hudson
authored andcommitted
inner/outer handling for nfinst.
- Implemented handling of inner/outer, including automatic generation of inner elements when missing. - Moved setting the type of a component from instComponent to instClass, to allow lookup in a component's parent component during instantiation. - Fixed scoping of builtin variables (i.e. time), to avoid them being incorrectly prefixed. - Fixed lookup of self-referencing extends and added check for inherited base classes.
1 parent 669df41 commit ebf70e3

File tree

13 files changed

+721
-74
lines changed

13 files changed

+721
-74
lines changed

Compiler/FrontEnd/SCode.mo

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3871,6 +3871,24 @@ algorithm
38713871
end match;
38723872
end isNotBuiltinClass;
38733873

3874+
public function getElementNamedAnnotation
3875+
"Returns the annotation with the given name in the element, or fails if no
3876+
such annotation could be found."
3877+
input Element element;
3878+
input String name;
3879+
output Absyn.Exp exp;
3880+
protected
3881+
Annotation ann;
3882+
algorithm
3883+
ann := match element
3884+
case EXTENDS(ann = SOME(ann)) then ann;
3885+
case CLASS(cmt = COMMENT(annotation_ = SOME(ann))) then ann;
3886+
case COMPONENT(comment = COMMENT(annotation_ = SOME(ann))) then ann;
3887+
end match;
3888+
3889+
exp := getNamedAnnotation(ann, name);
3890+
end getElementNamedAnnotation;
3891+
38743892
public function getNamedAnnotation
38753893
"Checks if the given annotation contains an entry with the given name with the
38763894
value true."

Compiler/NFFrontEnd/NFClassTree.mo

Lines changed: 113 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ protected
4343
import NFComponent.Component;
4444
import Inst = NFInst;
4545
import List;
46+
import Lookup = NFLookup;
47+
import SCodeDump;
4648

4749
public
4850
encapsulated package LookupTree
@@ -445,8 +447,9 @@ public
445447
array<Mutable<InstNode>> clss, comps, ext_clss;
446448
list<Integer> local_comps = {};
447449
Integer cls_idx = 1, comp_idx = 1, cls_count, comp_count;
448-
InstNode node;
450+
InstNode node, parent_scope, inner_node;
449451
DuplicateTree.Tree dups;
452+
Component comp;
450453
algorithm
451454
// TODO: If we don't have any extends we could probably generate a flat
452455
// tree directly and skip a lot of this.
@@ -461,6 +464,9 @@ public
461464
// If the instance is an empty node, use the cloned clsNode as the instance.
462465
if InstNode.isEmpty(instance) then
463466
instance := clsNode;
467+
parent_scope := InstNode.parent(clsNode);
468+
else
469+
parent_scope := instance;
464470
end if;
465471

466472
// Fetch the elements from the class tree.
@@ -490,6 +496,14 @@ public
490496
// class we're instantiating to be their parent.
491497
for c in old_clss loop
492498
c := InstNode.setParent(clsNode, c);
499+
500+
// If the class is outer, check that it's valid and link it with
501+
// the corresponding inner class.
502+
if InstNode.isOuter(c) then
503+
checkOuterClass(c);
504+
c := linkInnerOuter(c, parent_scope);
505+
end if;
506+
493507
arrayUpdateNoBoundsChecking(clss, cls_idx, Mutable.create(c));
494508
cls_idx := cls_idx + 1;
495509
end for;
@@ -513,9 +527,18 @@ public
513527
() := match c
514528
case InstNode.COMPONENT_NODE()
515529
algorithm
516-
// Set the components parent and create a unique instance for it.
530+
// Set the component's parent and create a unique instance for it.
517531
node := InstNode.setParent(instance, c);
518-
node := InstNode.replaceComponent(InstNode.component(node), node);
532+
comp := InstNode.component(node);
533+
node := InstNode.replaceComponent(comp, node);
534+
535+
// If the component is outer, link it with the corresponding
536+
// inner component.
537+
if Component.isOuter(comp) then
538+
node := linkInnerOuter(node, instance);
539+
end if;
540+
541+
// Add the node to the component array.
519542
arrayUpdateNoBoundsChecking(comps, comp_idx, Mutable.create(node));
520543
local_comps := comp_idx :: local_comps;
521544
comp_idx := comp_idx + 1;
@@ -574,6 +597,36 @@ public
574597
end match;
575598
end replaceDuplicates;
576599

600+
function appendComponentsToInstTree
601+
"Appens a list of local components to an instantiated class tree."
602+
input list<Mutable<InstNode>> components;
603+
input output ClassTree tree;
604+
algorithm
605+
if listEmpty(components) then
606+
return;
607+
else
608+
() := match tree
609+
local
610+
Integer comp_idx;
611+
list<Integer> local_comps;
612+
613+
case INSTANTIATED_TREE()
614+
algorithm
615+
comp_idx := arrayLength(tree.components);
616+
tree.components := Array.appendList(tree.components, components);
617+
local_comps := tree.localComponents;
618+
619+
for i in comp_idx+1:comp_idx+listLength(components) loop
620+
local_comps := i :: local_comps;
621+
end for;
622+
623+
tree.localComponents := local_comps;
624+
then
625+
();
626+
end match;
627+
end if;
628+
end appendComponentsToInstTree;
629+
577630
function flatten
578631
input output ClassTree tree;
579632
algorithm
@@ -1512,6 +1565,63 @@ public
15121565
entry.children := list(replaceDuplicates3(c, parent, tree) for c in entry.children);
15131566
end replaceDuplicates3;
15141567

1568+
function linkInnerOuter
1569+
"Looks up the corresponding inner node for the given outer node,
1570+
and returns an INNER_OUTER_NODE containing them both."
1571+
input InstNode outerNode;
1572+
input InstNode scope;
1573+
output InstNode innerOuterNode;
1574+
protected
1575+
InstNode inner_node;
1576+
algorithm
1577+
inner_node := Lookup.lookupInner(outerNode, scope);
1578+
1579+
// Make sure we found a node of the same kind.
1580+
if valueConstructor(outerNode) <> valueConstructor(inner_node) then
1581+
Error.addMultiSourceMessage(Error.FOUND_WRONG_INNER_ELEMENT,
1582+
{InstNode.typeName(inner_node), InstNode.name(outerNode), InstNode.typeName(outerNode)},
1583+
{InstNode.info(outerNode), InstNode.info(inner_node)});
1584+
fail();
1585+
end if;
1586+
1587+
innerOuterNode := InstNode.INNER_OUTER_NODE(inner_node, outerNode);
1588+
end linkInnerOuter;
1589+
1590+
function checkOuterClass
1591+
"Checks that a class used as outer is valid, i.e. is a short class
1592+
definition with no modifier."
1593+
input InstNode outerCls;
1594+
protected
1595+
SCode.ClassDef def;
1596+
algorithm
1597+
if InstNode.isOnlyOuter(outerCls) then
1598+
def := SCode.getClassDef(InstNode.definition(outerCls));
1599+
1600+
() := match def
1601+
// Outer short class definition without mod is ok.
1602+
case SCode.ClassDef.DERIVED(modifications = SCode.Mod.NOMOD()) then ();
1603+
1604+
// Outer short class definition with mod is an error.
1605+
case SCode.ClassDef.DERIVED()
1606+
algorithm
1607+
Error.addSourceMessage(Error.OUTER_ELEMENT_MOD,
1608+
{SCodeDump.printModStr(def.modifications), InstNode.name(outerCls)},
1609+
InstNode.info(outerCls));
1610+
then
1611+
fail();
1612+
1613+
// Outer long class definition is an error.
1614+
else
1615+
algorithm
1616+
Error.addSourceMessage(Error.OUTER_LONG_CLASS,
1617+
{InstNode.name(outerCls)}, InstNode.info(outerCls));
1618+
then
1619+
fail();
1620+
1621+
end match;
1622+
end if;
1623+
end checkOuterClass;
1624+
15151625
end ClassTree;
15161626

15171627
annotation(__OpenModelica_Interface="frontend");

Compiler/NFFrontEnd/NFComponent.mo

Lines changed: 55 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,12 @@ import SCode.Element;
4141
import SCode;
4242
import Type = NFType;
4343
import Expression = NFExpression;
44-
import NFPrefixes.Variability;
44+
import NFPrefixes.{Variability, InnerOuter};
4545

4646
protected
4747
import NFInstUtil;
4848
import List;
49+
import Prefixes = NFPrefixes;
4950

5051
public
5152
constant Component.Attributes CONST_ATTR =
@@ -54,7 +55,7 @@ constant Component.Attributes CONST_ATTR =
5455
DAE.NON_PARALLEL(),
5556
Variability.CONTINUOUS,
5657
DAE.BIDIR(),
57-
DAE.NOT_INNER_OUTER(),
58+
InnerOuter.NOT_INNER_OUTER,
5859
DAE.PUBLIC());
5960

6061
constant Component.Attributes INPUT_ATTR =
@@ -63,7 +64,7 @@ constant Component.Attributes INPUT_ATTR =
6364
DAE.NON_PARALLEL(),
6465
Variability.CONTINUOUS,
6566
DAE.INPUT(),
66-
DAE.NOT_INNER_OUTER(),
67+
InnerOuter.NOT_INNER_OUTER,
6768
DAE.PUBLIC());
6869

6970
constant Component.Attributes OUTPUT_ATTR =
@@ -72,7 +73,7 @@ constant Component.Attributes OUTPUT_ATTR =
7273
DAE.NON_PARALLEL(),
7374
Variability.CONTINUOUS,
7475
DAE.OUTPUT(),
75-
DAE.NOT_INNER_OUTER(),
76+
InnerOuter.NOT_INNER_OUTER,
7677
DAE.PUBLIC());
7778

7879
uniontype Component
@@ -83,7 +84,7 @@ uniontype Component
8384
DAE.VarParallelism parallelism;
8485
Variability variability;
8586
DAE.VarDirection direction;
86-
DAE.VarInnerOuter innerOuter;
87+
InnerOuter innerOuter;
8788
DAE.VarVisibility visibility;
8889
end ATTRIBUTES;
8990

@@ -376,7 +377,7 @@ uniontype Component
376377

377378
function isVar
378379
input Component component;
379-
output Boolean isConst = variability(component) == Variability.CONTINUOUS;
380+
output Boolean isVar = variability(component) == Variability.CONTINUOUS;
380381
end isVar;
381382

382383
function visibility
@@ -404,6 +405,54 @@ uniontype Component
404405
end match;
405406
end isPublic;
406407

408+
function isRedeclare
409+
input Component component;
410+
output Boolean isRedeclare;
411+
algorithm
412+
isRedeclare := match component
413+
case COMPONENT_DEF() then SCode.isElementRedeclare(component.definition);
414+
case UNTYPED_COMPONENT() then component.isRedeclare;
415+
else false;
416+
end match;
417+
end isRedeclare;
418+
419+
function innerOuter
420+
input Component component;
421+
output InnerOuter io;
422+
algorithm
423+
io := match component
424+
case UNTYPED_COMPONENT(attributes = Attributes.ATTRIBUTES(innerOuter = io)) then io;
425+
case TYPED_COMPONENT(attributes = Attributes.ATTRIBUTES(innerOuter = io)) then io;
426+
case COMPONENT_DEF()
427+
then Prefixes.innerOuterFromSCode(SCode.prefixesInnerOuter(
428+
SCode.elementPrefixes(component.definition)));
429+
else InnerOuter.NOT_INNER_OUTER;
430+
end match;
431+
end innerOuter;
432+
433+
function isInner
434+
input Component component;
435+
output Boolean isInner;
436+
protected
437+
InnerOuter io = innerOuter(component);
438+
algorithm
439+
isInner := io == InnerOuter.INNER or io == InnerOuter.INNER_OUTER;
440+
end isInner;
441+
442+
function isOuter
443+
input Component component;
444+
output Boolean isOuter;
445+
protected
446+
InnerOuter io = innerOuter(component);
447+
algorithm
448+
isOuter := io == InnerOuter.OUTER or io == InnerOuter.INNER_OUTER;
449+
end isOuter;
450+
451+
function isOnlyOuter
452+
input Component component;
453+
output Boolean isOuter = innerOuter(component) == InnerOuter.OUTER;
454+
end isOnlyOuter;
455+
407456
function isIdentical
408457
input Component comp1;
409458
input Component comp2;
@@ -448,17 +497,6 @@ uniontype Component
448497
end match;
449498
end toString;
450499

451-
function isRedeclare
452-
input Component component;
453-
output Boolean isRedeclare;
454-
algorithm
455-
isRedeclare := match component
456-
case COMPONENT_DEF() then SCode.isElementRedeclare(component.definition);
457-
case UNTYPED_COMPONENT() then component.isRedeclare;
458-
else false;
459-
end match;
460-
end isRedeclare;
461-
462500
function dimensionCount
463501
input Component component;
464502
output Integer count;

Compiler/NFFrontEnd/NFFlatten.mo

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ function flattenComponent
167167

168168
import Origin = NFComponentRef.Origin;
169169
protected
170-
Component c = InstNode.component(component);
170+
Component c;
171171
ComponentRef new_pre;
172172
Type ty;
173173
Option<Expression> binding_exp;
@@ -176,6 +176,19 @@ protected
176176
list<Dimension> dims;
177177
Equation binding_eq;
178178
algorithm
179+
if InstNode.isInnerOuterNode(component) then
180+
// If we get an outer component, flatten it if it's also inner.
181+
if InstNode.isInner(component) then
182+
c := InstNode.component(InstNode.resolveOuter(component));
183+
else
184+
// If it's only outer we skip it since we don't want outer component in the DAE.
185+
return;
186+
end if;
187+
else
188+
// A non-outer component, proceed as normal.
189+
c := InstNode.component(component);
190+
end if;
191+
179192
_ := match c
180193
case Component.TYPED_COMPONENT()
181194
algorithm

Compiler/NFFrontEnd/NFFunction.mo

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import Expression = NFExpression;
3636
import Pointer;
3737
import NFInstNode.InstNode;
3838
import Type = NFType;
39-
import NFPrefixes.Variability;
39+
import NFPrefixes.{Variability, InnerOuter};
4040

4141
protected
4242
import Inst = NFInst;
@@ -769,7 +769,7 @@ protected
769769
output DAE.VarDirection direction;
770770
protected
771771
DAE.ConnectorType cty;
772-
DAE.VarInnerOuter io;
772+
InnerOuter io;
773773
DAE.VarVisibility vis;
774774
algorithm
775775
Component.Attributes.ATTRIBUTES(
@@ -793,16 +793,12 @@ protected
793793
end match;
794794

795795
// Function components may not be inner/outer.
796-
() := match io
797-
case DAE.VarInnerOuter.NOT_INNER_OUTER() then ();
798-
else
799-
algorithm
800-
Error.addSourceMessage(Error.INNER_OUTER_FORMAL_PARAMETER,
801-
{DAEDump.unparseVarInnerOuter(io), InstNode.name(component)},
802-
InstNode.info(component));
803-
then
804-
fail();
805-
end match;
796+
if io <> InnerOuter.NOT_INNER_OUTER then
797+
Error.addSourceMessage(Error.INNER_OUTER_FORMAL_PARAMETER,
798+
{Prefixes.innerOuterString(io), InstNode.name(component)},
799+
InstNode.info(component));
800+
fail();
801+
end if;
806802

807803
// Formal parameters must be public, other function variables must be protected.
808804
() := match (direction, vis)

0 commit comments

Comments
 (0)