Skip to content

Commit 645a6be

Browse files
adrpoOpenModelica-Hudson
authored andcommitted
partial implementation of class extends
- the class extends changes are not applied to the baseclass, only the local scope - check if this is the correct way to implement this, or we actually need to replace in the base class
1 parent 0ec2a21 commit 645a6be

File tree

3 files changed

+186
-1
lines changed

3 files changed

+186
-1
lines changed

Compiler/Global/Global.mo

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ constant Integer fgraph_nextId = 22;
7676
constant Integer backendDAE_cseIndex = 23;
7777
// strong component index
7878
constant Integer strongComponent_index = 24;
79+
// class extends
80+
constant Integer classExtends_index = 25;
7981

8082
// ----------------------
8183

Compiler/NFFrontEnd/NFInst.mo

Lines changed: 182 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,14 @@ protected
5959
import Array;
6060
import Error;
6161
import Flatten = NFFlatten;
62+
import Global;
6263
import InstUtil = NFInstUtil;
6364
import List;
6465
import Lookup = NFLookup;
6566
import MetaModelica.Dangerous;
6667
import Typing = NFTyping;
6768
import ExecStat.{execStat,execStatReset};
69+
import System;
6870

6971
public
7072
function instClassInProgram
@@ -431,6 +433,13 @@ algorithm
431433
then
432434
node;
433435

436+
case SCode.CLASS(classDef = cdef as SCode.CLASS_EXTENDS())
437+
algorithm
438+
// get the already existing classes with the same name
439+
print("Got class extends: " + def.name + "\n");
440+
then
441+
fail();
442+
434443
else
435444
algorithm
436445
assert(false, getInstanceName() + " got unknown class");
@@ -732,9 +741,31 @@ function addInheritedElements2
732741
input ClassTree.Tree inScope;
733742
input Integer nodeIndex;
734743
output ClassTree.Tree scope;
744+
protected
745+
SCode.Element c;
746+
ClassTree.Entry idExisting;
747+
InstNode nodeExisting;
735748
algorithm
736749
scope := match id
737-
case ClassTree.Entry.CLASS() then ClassTree.add(inScope, name, id);
750+
case ClassTree.Entry.CLASS()
751+
algorithm
752+
// check if class exists!
753+
try
754+
(idExisting as ClassTree.Entry.CLASS(nodeExisting)) := ClassTree.get(inScope, name);
755+
c := InstNode.definition(nodeExisting);
756+
scope := match c
757+
// is it a class extends?
758+
case SCode.CLASS(classDef = SCode.CLASS_EXTENDS())
759+
then adaptClassExtendsChain(name, idExisting, id, inScope);
760+
// TODO! FIXME! this seems to be a duplicate class definition, add an error
761+
else
762+
then ClassTree.add(inScope, name, id);
763+
end match;
764+
else
765+
scope := ClassTree.add(inScope, name, id);
766+
end try;
767+
then
768+
scope;
738769
case ClassTree.Entry.COMPONENT(node = 0)
739770
then ClassTree.add(inScope, name, ClassTree.Entry.COMPONENT(nodeIndex, id.index));
740771
else inScope;
@@ -1388,5 +1419,155 @@ algorithm
13881419
end match;
13891420
end instStatement;
13901421

1422+
function adaptClassExtendsChain
1423+
"@author: adrpo
1424+
handle class extends
1425+
1. see if we already have a class with the same name
1426+
2. patch the existing class with a new name Model_$ce$number
1427+
3. patch the current class extends with an extends to the Model_$extends_number and change it to a normal class"
1428+
input String name;
1429+
input ClassTree.Entry idExisting "the class extends";
1430+
input ClassTree.Entry id "the base class";
1431+
input ClassTree.Tree inScope;
1432+
output ClassTree.Tree scope;
1433+
protected
1434+
SCode.Element new, existing;
1435+
InstNode newNode, nodeExisting;
1436+
String newName;
1437+
Integer ceTick = System.tmpTickIndex(Global.classExtends_index);
1438+
algorithm
1439+
scope := match id
1440+
case ClassTree.Entry.CLASS()
1441+
algorithm
1442+
// get the class extends class
1443+
newNode := id.node;
1444+
new := InstNode.definition(id.node);
1445+
/* this doen't seem to work to check for the baseclass
1446+
as WE HAVE the baseclass and we are searching for the
1447+
class extends. Somehow this needs to be handled the
1448+
other way, from class extends to the base class!
1449+
// get the existing base class
1450+
try
1451+
idExisting := ClassTree.get(inScope, name);
1452+
else
1453+
// report that the target of class extends does not exist!
1454+
Error.addSourceMessageAndFail(Error.CLASS_EXTENDS_TARGET_NOT_FOUND, {name}, SCode.elementInfo(new));
1455+
end try;*/
1456+
ClassTree.Entry.CLASS(nodeExisting) := idExisting;
1457+
// get the existing class in the environment
1458+
existing := InstNode.definition(nodeExisting);
1459+
// TODO! FIXME! check if the base class (id) is replaceable and add an error if not
1460+
// Error.NON_REPLACEABLE_CLASS_EXTENDS
1461+
newName := name + "$ce$" + String(ceTick);
1462+
// patch the base class and the class extends!
1463+
(new, existing) := patchBaseClassAndClassExtends(newName, name, new, existing);
1464+
// update nodes!
1465+
newNode := InstNode.rename(newNode, newName);
1466+
newNode := InstNode.setDefinition(new, newNode);
1467+
nodeExisting := InstNode.setDefinition(existing, nodeExisting);
1468+
1469+
// do partial instantiation again TODO! FIXME! is this needed??!!
1470+
newNode := partialInstClass(newNode);
1471+
nodeExisting := partialInstClass(nodeExisting);
1472+
1473+
// replace the class extends with the new definition
1474+
scope := ClassTree.add(inScope, name, ClassTree.Entry.CLASS(nodeExisting), ClassTree.addConflictReplace);
1475+
1476+
// add the base class with the new name to the scope
1477+
scope := ClassTree.add(scope, newName, ClassTree.Entry.CLASS(newNode));
1478+
then
1479+
scope;
1480+
1481+
else inScope;
1482+
end match;
1483+
end adaptClassExtendsChain;
1484+
1485+
protected function patchBaseClassAndClassExtends
1486+
input String inBaseEltName;
1487+
input String inClassExtendsEltName;
1488+
input SCode.Element inBaseElt;
1489+
input SCode.Element inClassExtendsElt;
1490+
output SCode.Element outBaseElt;
1491+
output SCode.Element outClassExtendsElt;
1492+
algorithm
1493+
(outBaseElt,outClassExtendsElt) := matchcontinue (inBaseElt,inClassExtendsElt)
1494+
local
1495+
SCode.Element elt,compelt,classExtendsElt;
1496+
SCode.Element cl;
1497+
SCode.ClassDef classDef,classExtendsCdef;
1498+
SCode.Partial partialPrefix1,partialPrefix2;
1499+
SCode.Encapsulated encapsulatedPrefix1,encapsulatedPrefix2;
1500+
SCode.Restriction restriction1,restriction2;
1501+
SCode.Prefixes prefixes1,prefixes2;
1502+
SCode.Visibility vis2;
1503+
String name1,name2,env_path;
1504+
Option<SCode.ExternalDecl> externalDecl1,externalDecl2;
1505+
list<SCode.Annotation> annotationLst1,annotationLst2;
1506+
SCode.Comment comment1,comment2;
1507+
Option<SCode.Annotation> ann1,ann2;
1508+
list<SCode.Element> els1,els2;
1509+
list<SCode.Equation> nEqn1,nEqn2,inEqn1,inEqn2;
1510+
list<SCode.AlgorithmSection> nAlg1,nAlg2,inAlg1,inAlg2;
1511+
list<SCode.ConstraintSection> inCons1, inCons2;
1512+
list<Absyn.NamedArg> clats;
1513+
list<tuple<SCode.Element, DAE.Mod, Boolean>> rest;
1514+
tuple<SCode.Element, DAE.Mod, Boolean> first;
1515+
SCode.Mod mods, derivedMod;
1516+
DAE.Mod mod1,emod;
1517+
SourceInfo info1, info2;
1518+
Boolean b;
1519+
SCode.Attributes attrs;
1520+
Absyn.TypeSpec derivedTySpec;
1521+
1522+
// found the base class with parts
1523+
case (cl as SCode.CLASS(name = name2, classDef = SCode.PARTS()), classExtendsElt)
1524+
equation
1525+
name1 = inClassExtendsEltName;
1526+
name2 = inBaseEltName;
1527+
1528+
SCode.CLASS(_,prefixes2,encapsulatedPrefix2,partialPrefix2,restriction2,SCode.PARTS(els2,nEqn2,inEqn2,nAlg2,inAlg2,inCons2,clats,externalDecl2),comment2,info2) = cl;
1529+
1530+
SCode.CLASS(_, prefixes1, encapsulatedPrefix1, partialPrefix1, restriction1, classExtendsCdef, comment1, info1) = classExtendsElt;
1531+
SCode.CLASS_EXTENDS(_,mods,SCode.PARTS(els1,nEqn1,inEqn1,nAlg1,inAlg1,inCons1,_,externalDecl1)) = classExtendsCdef;
1532+
1533+
classDef = SCode.PARTS(els2,nEqn2,inEqn2,nAlg2,inAlg2,inCons2,clats,externalDecl2);
1534+
compelt = SCode.CLASS(name2,prefixes2,encapsulatedPrefix2,partialPrefix2,restriction2,classDef,comment2,info2);
1535+
vis2 = SCode.prefixesVisibility(prefixes2);
1536+
elt = SCode.EXTENDS(Absyn.IDENT(name2),vis2,mods,NONE(),info1);
1537+
classDef = SCode.PARTS(elt::els1,nEqn1,inEqn1,nAlg1,inAlg1,inCons1,clats,externalDecl1);
1538+
elt = SCode.CLASS(name1, prefixes1, encapsulatedPrefix1, partialPrefix1, restriction1, classDef, comment1, info1);
1539+
then
1540+
(compelt, elt);
1541+
1542+
// found the base class which is derived
1543+
case (cl as SCode.CLASS(name = name2, classDef = SCode.DERIVED()), classExtendsElt)
1544+
equation
1545+
name1 = inClassExtendsEltName;
1546+
name2 = inBaseEltName;
1547+
1548+
SCode.CLASS(_,prefixes2,encapsulatedPrefix2,partialPrefix2,restriction2,SCode.DERIVED(derivedTySpec, derivedMod, attrs),comment2,info2) = cl;
1549+
1550+
SCode.CLASS(_, prefixes1, encapsulatedPrefix1, partialPrefix1, restriction1, classExtendsCdef, comment1, info1) = classExtendsElt;
1551+
SCode.CLASS_EXTENDS(_,mods,SCode.PARTS(els1,nEqn1,inEqn1,nAlg1,inAlg1,inCons1,_,externalDecl1)) = classExtendsCdef;
1552+
1553+
classDef = SCode.DERIVED(derivedTySpec, derivedMod, attrs);
1554+
compelt = SCode.CLASS(name2,prefixes2,encapsulatedPrefix2,partialPrefix2,restriction2,classDef,comment2,info2);
1555+
vis2 = SCode.prefixesVisibility(prefixes2);
1556+
elt = SCode.EXTENDS(Absyn.IDENT(name2),vis2,mods,NONE(),info1);
1557+
classDef = SCode.PARTS(elt::els1,nEqn1,inEqn1,nAlg1,inAlg1,inCons1,{},externalDecl1);
1558+
elt = SCode.CLASS(name1, prefixes1, encapsulatedPrefix1, partialPrefix1, restriction1, classDef, comment1, info1);
1559+
then
1560+
(compelt, elt);
1561+
1562+
// something went wrong!
1563+
else
1564+
equation
1565+
assert(false, getInstanceName() + " could not rename class extends base class to: " + inBaseEltName);
1566+
then
1567+
fail();
1568+
1569+
end matchcontinue;
1570+
end patchBaseClassAndClassExtends;
1571+
13911572
annotation(__OpenModelica_Interface="frontend");
13921573
end NFInst;

Compiler/Util/Error.mo

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,8 @@ public constant Message USER_DEFINED_TEARING_ERROR = MESSAGE(577, SYMBOLIC(), ER
864864
Util.gettext("Wrong usage of user defined tearing: %s Make sure you use user defined tearing as stated in the flag description."));
865865
public constant Message USER_TEARING_VARS = MESSAGE(578, SYMBOLIC(), NOTIFICATION(),
866866
Util.gettext("Following iteration variables are selected by the user for strong component %s (DAE kind: %s):\n%s"));
867+
public constant Message CLASS_EXTENDS_TARGET_NOT_FOUND = MESSAGE(579, TRANSLATION(), ERROR(),
868+
Util.gettext("Base class targeted by class extends %s not found in the inherited classes."));
867869

868870
public constant Message MATCH_SHADOWING = MESSAGE(5001, TRANSLATION(), ERROR(),
869871
Util.gettext("Local variable '%s' shadows another variable."));

0 commit comments

Comments
 (0)