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

Commit

Permalink
partial implementation of class extends
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
adrpo authored and OpenModelica-Hudson committed Jan 26, 2017
1 parent 0ec2a21 commit 645a6be
Show file tree
Hide file tree
Showing 3 changed files with 186 additions and 1 deletion.
2 changes: 2 additions & 0 deletions Compiler/Global/Global.mo
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ constant Integer fgraph_nextId = 22;
constant Integer backendDAE_cseIndex = 23;
// strong component index
constant Integer strongComponent_index = 24;
// class extends
constant Integer classExtends_index = 25;

// ----------------------

Expand Down
183 changes: 182 additions & 1 deletion Compiler/NFFrontEnd/NFInst.mo
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,14 @@ protected
import Array;
import Error;
import Flatten = NFFlatten;
import Global;
import InstUtil = NFInstUtil;
import List;
import Lookup = NFLookup;
import MetaModelica.Dangerous;
import Typing = NFTyping;
import ExecStat.{execStat,execStatReset};
import System;

public
function instClassInProgram
Expand Down Expand Up @@ -431,6 +433,13 @@ algorithm
then
node;

case SCode.CLASS(classDef = cdef as SCode.CLASS_EXTENDS())
algorithm
// get the already existing classes with the same name
print("Got class extends: " + def.name + "\n");
then
fail();

else
algorithm
assert(false, getInstanceName() + " got unknown class");
Expand Down Expand Up @@ -732,9 +741,31 @@ function addInheritedElements2
input ClassTree.Tree inScope;
input Integer nodeIndex;
output ClassTree.Tree scope;
protected
SCode.Element c;
ClassTree.Entry idExisting;
InstNode nodeExisting;
algorithm
scope := match id
case ClassTree.Entry.CLASS() then ClassTree.add(inScope, name, id);
case ClassTree.Entry.CLASS()
algorithm
// check if class exists!
try
(idExisting as ClassTree.Entry.CLASS(nodeExisting)) := ClassTree.get(inScope, name);
c := InstNode.definition(nodeExisting);
scope := match c
// is it a class extends?
case SCode.CLASS(classDef = SCode.CLASS_EXTENDS())
then adaptClassExtendsChain(name, idExisting, id, inScope);
// TODO! FIXME! this seems to be a duplicate class definition, add an error
else
then ClassTree.add(inScope, name, id);
end match;
else
scope := ClassTree.add(inScope, name, id);
end try;
then
scope;
case ClassTree.Entry.COMPONENT(node = 0)
then ClassTree.add(inScope, name, ClassTree.Entry.COMPONENT(nodeIndex, id.index));
else inScope;
Expand Down Expand Up @@ -1388,5 +1419,155 @@ algorithm
end match;
end instStatement;

function adaptClassExtendsChain
"@author: adrpo
handle class extends
1. see if we already have a class with the same name
2. patch the existing class with a new name Model_$ce$number
3. patch the current class extends with an extends to the Model_$extends_number and change it to a normal class"
input String name;
input ClassTree.Entry idExisting "the class extends";
input ClassTree.Entry id "the base class";
input ClassTree.Tree inScope;
output ClassTree.Tree scope;
protected
SCode.Element new, existing;
InstNode newNode, nodeExisting;
String newName;
Integer ceTick = System.tmpTickIndex(Global.classExtends_index);
algorithm
scope := match id
case ClassTree.Entry.CLASS()
algorithm
// get the class extends class
newNode := id.node;
new := InstNode.definition(id.node);
/* this doen't seem to work to check for the baseclass
as WE HAVE the baseclass and we are searching for the
class extends. Somehow this needs to be handled the
other way, from class extends to the base class!
// get the existing base class
try
idExisting := ClassTree.get(inScope, name);
else
// report that the target of class extends does not exist!
Error.addSourceMessageAndFail(Error.CLASS_EXTENDS_TARGET_NOT_FOUND, {name}, SCode.elementInfo(new));
end try;*/
ClassTree.Entry.CLASS(nodeExisting) := idExisting;
// get the existing class in the environment
existing := InstNode.definition(nodeExisting);
// TODO! FIXME! check if the base class (id) is replaceable and add an error if not
// Error.NON_REPLACEABLE_CLASS_EXTENDS
newName := name + "$ce$" + String(ceTick);
// patch the base class and the class extends!
(new, existing) := patchBaseClassAndClassExtends(newName, name, new, existing);
// update nodes!
newNode := InstNode.rename(newNode, newName);
newNode := InstNode.setDefinition(new, newNode);
nodeExisting := InstNode.setDefinition(existing, nodeExisting);

// do partial instantiation again TODO! FIXME! is this needed??!!
newNode := partialInstClass(newNode);
nodeExisting := partialInstClass(nodeExisting);

// replace the class extends with the new definition
scope := ClassTree.add(inScope, name, ClassTree.Entry.CLASS(nodeExisting), ClassTree.addConflictReplace);

// add the base class with the new name to the scope
scope := ClassTree.add(scope, newName, ClassTree.Entry.CLASS(newNode));
then
scope;

else inScope;
end match;
end adaptClassExtendsChain;

protected function patchBaseClassAndClassExtends
input String inBaseEltName;
input String inClassExtendsEltName;
input SCode.Element inBaseElt;
input SCode.Element inClassExtendsElt;
output SCode.Element outBaseElt;
output SCode.Element outClassExtendsElt;
algorithm
(outBaseElt,outClassExtendsElt) := matchcontinue (inBaseElt,inClassExtendsElt)
local
SCode.Element elt,compelt,classExtendsElt;
SCode.Element cl;
SCode.ClassDef classDef,classExtendsCdef;
SCode.Partial partialPrefix1,partialPrefix2;
SCode.Encapsulated encapsulatedPrefix1,encapsulatedPrefix2;
SCode.Restriction restriction1,restriction2;
SCode.Prefixes prefixes1,prefixes2;
SCode.Visibility vis2;
String name1,name2,env_path;
Option<SCode.ExternalDecl> externalDecl1,externalDecl2;
list<SCode.Annotation> annotationLst1,annotationLst2;
SCode.Comment comment1,comment2;
Option<SCode.Annotation> ann1,ann2;
list<SCode.Element> els1,els2;
list<SCode.Equation> nEqn1,nEqn2,inEqn1,inEqn2;
list<SCode.AlgorithmSection> nAlg1,nAlg2,inAlg1,inAlg2;
list<SCode.ConstraintSection> inCons1, inCons2;
list<Absyn.NamedArg> clats;
list<tuple<SCode.Element, DAE.Mod, Boolean>> rest;
tuple<SCode.Element, DAE.Mod, Boolean> first;
SCode.Mod mods, derivedMod;
DAE.Mod mod1,emod;
SourceInfo info1, info2;
Boolean b;
SCode.Attributes attrs;
Absyn.TypeSpec derivedTySpec;

// found the base class with parts
case (cl as SCode.CLASS(name = name2, classDef = SCode.PARTS()), classExtendsElt)
equation
name1 = inClassExtendsEltName;
name2 = inBaseEltName;

SCode.CLASS(_,prefixes2,encapsulatedPrefix2,partialPrefix2,restriction2,SCode.PARTS(els2,nEqn2,inEqn2,nAlg2,inAlg2,inCons2,clats,externalDecl2),comment2,info2) = cl;

SCode.CLASS(_, prefixes1, encapsulatedPrefix1, partialPrefix1, restriction1, classExtendsCdef, comment1, info1) = classExtendsElt;
SCode.CLASS_EXTENDS(_,mods,SCode.PARTS(els1,nEqn1,inEqn1,nAlg1,inAlg1,inCons1,_,externalDecl1)) = classExtendsCdef;

classDef = SCode.PARTS(els2,nEqn2,inEqn2,nAlg2,inAlg2,inCons2,clats,externalDecl2);
compelt = SCode.CLASS(name2,prefixes2,encapsulatedPrefix2,partialPrefix2,restriction2,classDef,comment2,info2);
vis2 = SCode.prefixesVisibility(prefixes2);
elt = SCode.EXTENDS(Absyn.IDENT(name2),vis2,mods,NONE(),info1);
classDef = SCode.PARTS(elt::els1,nEqn1,inEqn1,nAlg1,inAlg1,inCons1,clats,externalDecl1);
elt = SCode.CLASS(name1, prefixes1, encapsulatedPrefix1, partialPrefix1, restriction1, classDef, comment1, info1);
then
(compelt, elt);

// found the base class which is derived
case (cl as SCode.CLASS(name = name2, classDef = SCode.DERIVED()), classExtendsElt)
equation
name1 = inClassExtendsEltName;
name2 = inBaseEltName;

SCode.CLASS(_,prefixes2,encapsulatedPrefix2,partialPrefix2,restriction2,SCode.DERIVED(derivedTySpec, derivedMod, attrs),comment2,info2) = cl;

SCode.CLASS(_, prefixes1, encapsulatedPrefix1, partialPrefix1, restriction1, classExtendsCdef, comment1, info1) = classExtendsElt;
SCode.CLASS_EXTENDS(_,mods,SCode.PARTS(els1,nEqn1,inEqn1,nAlg1,inAlg1,inCons1,_,externalDecl1)) = classExtendsCdef;

classDef = SCode.DERIVED(derivedTySpec, derivedMod, attrs);
compelt = SCode.CLASS(name2,prefixes2,encapsulatedPrefix2,partialPrefix2,restriction2,classDef,comment2,info2);
vis2 = SCode.prefixesVisibility(prefixes2);
elt = SCode.EXTENDS(Absyn.IDENT(name2),vis2,mods,NONE(),info1);
classDef = SCode.PARTS(elt::els1,nEqn1,inEqn1,nAlg1,inAlg1,inCons1,{},externalDecl1);
elt = SCode.CLASS(name1, prefixes1, encapsulatedPrefix1, partialPrefix1, restriction1, classDef, comment1, info1);
then
(compelt, elt);

// something went wrong!
else
equation
assert(false, getInstanceName() + " could not rename class extends base class to: " + inBaseEltName);
then
fail();

end matchcontinue;
end patchBaseClassAndClassExtends;

annotation(__OpenModelica_Interface="frontend");
end NFInst;
2 changes: 2 additions & 0 deletions Compiler/Util/Error.mo
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,8 @@ public constant Message USER_DEFINED_TEARING_ERROR = MESSAGE(577, SYMBOLIC(), ER
Util.gettext("Wrong usage of user defined tearing: %s Make sure you use user defined tearing as stated in the flag description."));
public constant Message USER_TEARING_VARS = MESSAGE(578, SYMBOLIC(), NOTIFICATION(),
Util.gettext("Following iteration variables are selected by the user for strong component %s (DAE kind: %s):\n%s"));
public constant Message CLASS_EXTENDS_TARGET_NOT_FOUND = MESSAGE(579, TRANSLATION(), ERROR(),
Util.gettext("Base class targeted by class extends %s not found in the inherited classes."));

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

0 comments on commit 645a6be

Please sign in to comment.