@@ -59,12 +59,14 @@ protected
5959import Array ;
6060import Error ;
6161import Flatten = NFFlatten ;
62+ import Global ;
6263import InstUtil = NFInstUtil ;
6364import List ;
6465import Lookup = NFLookup ;
6566import MetaModelica.Dangerous ;
6667import Typing = NFTyping ;
6768import ExecStat . {execStat,execStatReset};
69+ import System ;
6870
6971public
7072function 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;
735748algorithm
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;
13891420end 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+
13911572annotation(__OpenModelica_Interface= "frontend" );
13921573end NFInst ;
0 commit comments