Skip to content

Commit

Permalink
An unfinished attempt to fix the multiple class definition bug (http:…
Browse files Browse the repository at this point in the history
…//openmodelica.ida.liu.se:8080/cb/issue/1182). I tried to improve the function  Inst.checkMultiplyDeclared so that it could be used for class definitions, not only for component declarations. Unfortunately, trying to call this function from instElement (when a class definition is processed) makes some files from the testsuite to fail. So I have left the extended checkMultiplyDeclared and comparison functions it calls, but commented out the call in instElement. I.e., the functions are not called, so nothing gets broken, but they are there in case somebody wants to continue the work. It seems to me, though, that the problem is not in comparison functions but in the place they are called from (instElement). But I do not know what the correct place is.

git-svn-id: https://openmodelica.org/svn/OpenModelica/trunk@5413 f25d12d1-65f4-0310-ae8a-bbce733d8d8e
  • Loading branch information
Alexey Lebedev committed Apr 28, 2010
1 parent 5d4ebea commit 27d0b05
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 5 deletions.
31 changes: 31 additions & 0 deletions Compiler/Absyn.mo
Expand Up @@ -4357,4 +4357,35 @@ algorithm
end matchcontinue;
end makeFullyQualified;

public function importEqual "function: importEqual
Compares two import elements. "
input Import im1;
input Import im2;
output Boolean outBoolean;
algorithm
outBoolean:=
matchcontinue (im1,im2)
local
Ident id,id2;
Path p1,p2;
case (NAMED_IMPORT(name = id,path=p1),NAMED_IMPORT(name = id2,path=p2))
equation
equality(id = id2);
true = ModUtil.pathEqual(p1,p2);
then
true;
case (QUAL_IMPORT(path=p1),QUAL_IMPORT(path=p2))
equation
true = ModUtil.pathEqual(p1,p2);
then
true;
case (UNQUAL_IMPORT(path=p1),UNQUAL_IMPORT(path=p2))
equation
true = ModUtil.pathEqual(p1,p2);
then
true;
case (_,_) then false;
end matchcontinue;
end importEqual;

end Absyn;
3 changes: 3 additions & 0 deletions Compiler/Error.mo
Expand Up @@ -212,6 +212,7 @@ public constant ErrorID CIRCULAR_PARAM=124;
public constant ErrorID NESTED_WHEN=125;
public constant ErrorID INVALID_ENUM_LITERAL=126;
public constant ErrorID UNEXCPECTED_FUNCTION_INPUTS_WARNING=127;
public constant ErrorID DUPLICATE_CLASSES_NOT_EQUIVALENT=128;

public constant ErrorID UNBOUND_PARAMETER_WARNING=500;
public constant ErrorID BUILTIN_FUNCTION_SUM_HAS_SCALAR_PARAMETER=501;
Expand Down Expand Up @@ -457,6 +458,8 @@ protected constant list<tuple<Integer, MessageType, Severity, String>> errorTabl
"A break statement not inside a loop"),
(DUPLICATE_ELEMENTS_NOT_IDENTICAL,TRANSLATION(),ERROR(),
"Duplicate elements (due to inherited elements) not identical, first element is: %s, second element is: %s"),
(DUPLICATE_CLASSES_NOT_EQUIVALENT,TRANSLATION(),ERROR(),
"Duplicate class definitions (due to inheritance) not equivalent, first definiton is: %s, second definition is: %s"),
(PACKAGE_VARIABLE_NOT_CONSTANT, TRANSLATION(),ERROR(),"Variable %s in package %s is not constant"),
(RECURSIVE_DEFINITION,TRANSLATION(),ERROR(),"Class %s has a recursive definition, i.e. contains an instance of itself"),
(UNBOUND_PARAMETER_WARNING,TRANSLATION(),WARNING(),
Expand Down
99 changes: 97 additions & 2 deletions Compiler/Inst.mo
Expand Up @@ -5276,9 +5276,11 @@ algorithm
fail();

// Classdefinition without redeclaration
case (cache,env,ih,store,mods,pre,csets,ci_state,(SCode.CLASSDEF(name = n,classDef = c),_),inst_dims,impl,graph)
case (cache,env,ih,store,mods,pre,csets,ci_state,(comp as SCode.CLASSDEF(name = n,classDef = c),cmod),inst_dims,impl,graph)
equation
classmod = Mod.lookupModificationP(mods, Absyn.IDENT(n));
// This was an attempt to fix multiple class definition bug. Unfortunately, it breaks some tests. -- alleb
// _ = checkMultiplyDeclared(cache,env,mods,pre,csets,ci_state,(comp,cmod),inst_dims,impl);
(cache,env_1,ih,dae) =
instClassDecl(cache,env,ih, classmod, pre, csets, c, inst_dims);
then
Expand Down Expand Up @@ -5721,14 +5723,15 @@ algorithm
local
list<Env.Frame> env,env_1,env2,env2_1,cenv,compenv;
DAE.Mod mod;
String n;
String n,n2;
Boolean finalPrefix,repl,prot;
SCode.Element oldElt; DAE.Mod oldMod;
tuple<SCode.Element,DAE.Mod> newComp;
Env.InstStatus instStatus;
SCode.Element oldElt; DAE.Mod oldMod;
tuple<SCode.Element,DAE.Mod> newComp;
Boolean alreadyDeclared;
SCode.Class oldClass,newClass;

case (_,_,_,_,_,_,_,_,_) equation /*print(" dupe check setting ");*/ ErrorExt.setCheckpoint("checkMultiplyDeclared"); then fail();

Expand All @@ -5753,6 +5756,50 @@ algorithm
ErrorExt.rollBack("checkMultiplyDeclared");
then false;


// If a class definition is replaceable, skip check
case (cache,env,mod,prefix,csets,ciState,
(newComp as (SCode.CLASSDEF(replaceablePrefix=true),_)),_,_)
equation
ErrorExt.rollBack("checkMultiplyDeclared");
then false;

// If a class definition is redeclaration, skip check
case (cache,env,mod,prefix,csets,ciState,
(newComp as (SCode.CLASSDEF(replaceablePrefix=_),DAE.REDECL(_,_))),_,_)
equation
ErrorExt.rollBack("checkMultiplyDeclared");
then false;

// If a class definition is a product of InstExtends.instClassExtendsList2, skip check
case (cache,env,mod,prefix,csets,ciState,
(newComp as (SCode.CLASSDEF(name=n,classDef=SCode.CLASS(classDef=SCode.PARTS(elementLst=SCode.EXTENDS(baseClassPath=Absyn.IDENT(n2))::_ ))),_)),_,_)
equation
n=n+&"$parent";
equality(n=n2);
ErrorExt.rollBack("checkMultiplyDeclared");
then false;

// If a class is defined multiple times, the first is used.
// If the two class definitions are not equivalent, an error is given.
//

case (cache,env,mod,prefix,csets,ciState,
(newComp as (SCode.CLASSDEF(name=n, classDef=newClass),_)),_,_)
equation
(oldClass,_) = Lookup.lookupClassLocal(env, n);
checkMultipleClassesEquivalent(oldClass,newClass);
ErrorExt.delCheckpoint("checkMultiplyDeclared");
then true;

// If a class not multiply defined, return.
case (cache,env,mod,prefix,csets,ciState,
(newComp as (SCode.CLASSDEF(name=n, classDef=newClass),_)),_,_)
equation
failure((oldClass,_) = Lookup.lookupClassLocal(env, n));
ErrorExt.rollBack("checkMultiplyDeclared");
then false;

// failure
case (cache,env,mod,prefix,csets,ciState,_,_,_)
equation
Expand Down Expand Up @@ -5814,6 +5861,54 @@ algorithm
end matchcontinue;
end checkMultipleElementsIdentical;

protected function checkMultipleClassesEquivalent
"Checks that the old class definition is equivalent
to the new one. If not, give error message"
input SCode.Class oldClass;
input SCode.Class newClass;
algorithm
_ := matchcontinue(oldClass,newClass)
local
SCode.Class oldCl,newCl;
String s1,s2;
list<String> sl1,sl2;
list<SCode.Enum> enumLst;
list<SCode.Element> elementLst;
list<Boolean> boolList;

// Special cases for checking enumerations which can be represented differently
case(oldCl as SCode.CLASS(classDef=SCode.ENUMERATION(enumLst=enumLst)), newCl as SCode.CLASS(restriction=SCode.R_ENUMERATION(),classDef=SCode.PARTS(elementLst=elementLst)))
equation
sl1=Util.listMap(enumLst,SCode.enumName);
sl2=Util.listMap(elementLst,SCode.elementName);
boolList=Util.listThreadMap(sl1,sl2,stringEqual);
true=Util.boolAndList(boolList);
then ();

case(oldCl as SCode.CLASS(restriction=SCode.R_ENUMERATION(),classDef=SCode.PARTS(elementLst=elementLst)), newCl as SCode.CLASS(classDef=SCode.ENUMERATION(enumLst=enumLst)))
equation
sl1=Util.listMap(enumLst,SCode.enumName);
sl2=Util.listMap(elementLst,SCode.elementName);
boolList=Util.listThreadMap(sl1,sl2,stringEqual);
true=Util.boolAndList(boolList);
then ();

// try equality first!
case(oldCl,newCl)
equation
true = SCode.classEqual(oldCl,newCl);
then ();

case (oldCl,newCl)
equation
s1 = SCode.printClassStr(oldCl);
s2 = SCode.printClassStr(newCl);
Error.addMessage(Error.DUPLICATE_CLASSES_NOT_EQUIVALENT(),{s1,s2});
//print(" *** error message added *** \n");
then fail();
end matchcontinue;
end checkMultipleClassesEquivalent;

protected function removeCrefFromCrefs
"function: removeCrefFromCrefs
Removes a variable from a variable list"
Expand Down
24 changes: 24 additions & 0 deletions Compiler/Lookup.mo
Expand Up @@ -1390,6 +1390,30 @@ algorithm
end matchcontinue;
end lookupIdentLocal;

public function lookupClassLocal "function: lookupClassLocal
Searches for a class definition in the local scope."
input Env.Env inEnv;
input SCode.Ident inIdent;
output SCode.Class outClass;
output Env.Env outEnv;
algorithm
(outCache,outVar,outTplSCodeElementTypesModOption,instStatus,outEnv):=
matchcontinue (inEnv,inIdent)
local
SCode.Class cl;
list<Env.Frame> env;
Option<String> sid;
Env.AvlTree ht;
String id;
Env.Cache cache;
case (env as (Env.FRAME(optName = sid, clsAndVars = ht) :: _),id) /* component environment */
equation
Env.CLASS(cl,env) = Env.avlTreeGet(ht, id);
then
(cl,env);
end matchcontinue;
end lookupClassLocal;

public function lookupAndInstantiate "performs a lookup of a class and then instantiate that class to
return its environment. Helper function used e.g by Inst.mo"
input Env.Cache inCache;
Expand Down
33 changes: 31 additions & 2 deletions Compiler/SCode.mo
Expand Up @@ -1234,6 +1234,15 @@ algorithm
end matchcontinue;
end elementName;

public function enumName ""
input Enum e;
output String s;
algorithm
s := matchcontinue(e)
case(ENUM(literal = s)) then s;
end matchcontinue;
end enumName;

public function componentNamesFromElts
"function: componentNamesFromElts
Helper function to componentNames."
Expand Down Expand Up @@ -1333,6 +1342,10 @@ public function elementEqual
Absyn.InnerOuter io,io2;
Attributes attr1,attr2; Mod mod1,mod2;
Absyn.TypeSpec tp1,tp2;
Absyn.Import im1,im2;
Absyn.Path path1, path2;
Option<String> os1,os2;
Option<Real> or1,or2;
case (CLASSDEF(name1,f1,r1,cl1,_),CLASSDEF(name2,f2,r2,cl2,_))
equation
b1 = stringEqual(name1,name2);
Expand All @@ -1353,6 +1366,22 @@ public function elementEqual
b7 = Absyn.typeSpecEqual(tp1,tp2);
equal = Util.boolAndList({b1,b1a,b2,b3,b4,b5,b6,b7});
then equal;
case (EXTENDS(path1,mod1,_), EXTENDS(path2,mod2,_))
equation
b1 = ModUtil.pathEqual(path1,path2);
b2 = modEqual(mod1,mod2);
equal = Util.boolAndList({b1,b2});
then equal;
case (IMPORT(im1), IMPORT(im2))
equation
equal = Absyn.importEqual(im1,im2);
then equal;
case (DEFINEUNIT(name1,os1,or1), DEFINEUNIT(name2,os2,or2))
equation
b1 = stringEqual(name1,name2);
equality(os1=os2);
equality(or1=or2);
then b1;
case(_,_) then false;
end matchcontinue;
end elementEqual;
Expand All @@ -1378,7 +1407,7 @@ algorithm
end matchcontinue;
end annotationEqual;

protected function classEqual
public function classEqual
"function classEqual
returns true if two classes are equal"
input Class class1;
Expand Down Expand Up @@ -1691,7 +1720,7 @@ algorithm
case(EQ_EQUALS(e11,e12,_),EQ_EQUALS(e21,e22,_))
equation
b1 = Absyn.expEqual(e11,e21);
b2 = Absyn.expEqual(e21,e22);
b2 = Absyn.expEqual(e12,e22);
equal = boolAnd(b1,b2);
then equal;
case(EQ_CONNECT(cr11,cr12,_),EQ_CONNECT(cr21,cr22,_))
Expand Down
31 changes: 30 additions & 1 deletion Compiler/Util.mo
Expand Up @@ -5754,6 +5754,35 @@ algorithm
_ := arrayUpdate(sb,1,b);
end setStatefulBoolean;


public function optionEqual "
Takes two options and a function to compare the type."
input Option<Type_a> inOpt1;
input Option<Type_a> inOpt2;
input CompareFunc inFunc;
output Boolean outBool;

replaceable type Type_a subtypeof Any;
partial function CompareFunc
input Type_a inType_a1;
input Type_a inType_a2;
output Boolean outBool;
end CompareFunc;
algorithm
outBool := matchcontinue(inOpt1,inOpt2,inFunc)
local
Type_a a1,a2;
Boolean b;
CompareFunc fn;

case (NONE(),NONE(),_) then true;
case (SOME(a1),SOME(a2),fn)
equation
b = fn(a1,a2);
then
b;
case (_,_,_) then false;
end matchcontinue;
end optionEqual;

end Util;

0 comments on commit 27d0b05

Please sign in to comment.