Skip to content

Commit

Permalink
Fixed bug with infinite recursion in lookup. See packages2.mo in test…
Browse files Browse the repository at this point in the history
…suite.

Cleaned up lookup code a bit.



git-svn-id: https://openmodelica.org/svn/OpenModelica/trunk@2436 f25d12d1-65f4-0310-ae8a-bbce733d8d8e
  • Loading branch information
Peter Aronsson committed Jun 29, 2006
1 parent a4539e4 commit 5c92983
Show file tree
Hide file tree
Showing 6 changed files with 272 additions and 64 deletions.
108 changes: 108 additions & 0 deletions Compiler/Absyn.mo
Expand Up @@ -894,6 +894,8 @@ protected import OpenModelica.Compiler.Util;

protected import OpenModelica.Compiler.Print;

protected import OpenModelica.Compiler.ModUtil;

public function elementSpecName "adrpo -- not used
with \"Dump.rml\"

Expand Down Expand Up @@ -1011,6 +1013,96 @@ algorithm
end matchcontinue;
end pathFirstIdent;

public function pathSuffixOf "returns true if suffix_path is a suffix of path"
input Path suffix_path;
input Path path;
output Boolean res;
algorithm
res := matchcontinue(suffix_path,path)
local Path p;
case(suffix_path,path)
equation
true = ModUtil.pathEqual(suffix_path,path);
then true;
case(suffix_path,QUALIFIED(name=_,path = p))
then pathSuffixOf(suffix_path,p);
case(_,_) then false;
end matchcontinue;
end pathSuffixOf;


public function pathPrefixOf "returns true if prefix_path is a prefix of path"
input Path prefix_path;
input Path path;
output Boolean res;
algorithm
res := matchcontinue(prefix_path,path)
local Path p;
case(prefix_path,path)
equation
true = ModUtil.pathEqual(prefix_path,path);
then true;
case(prefix_path,path)
then pathPrefixOf(prefix_path,stripLast(path));
case(_,_) then false;
end matchcontinue;
end pathPrefixOf;


public function removePrefix "removes the prefix_path from path, and returns the rest of path"
input Path prefix_path;
input Path path;
output Path newPath;
algorithm
newPath := matchcontinue(prefix_path,path)
local Path p,p2; Ident id1,id2;
case (QUALIFIED(name=id1,path=p),QUALIFIED(name=id2,path=p2)) equation
equality(id1=id2);
then removePrefix(p,p2);
case(IDENT(id1),QUALIFIED(name=id2,path=p2)) equation
equality(id1=id2);
then p2;
end matchcontinue;
end removePrefix;

public function pathContainedIn "This function checks if subPath is contained in path.
If it is the complete path is returned. Otherwise the function fails.
For example,
pathContainedIn( C.D, A.B.C) => A.B.C.D
pathContainedIn(C.D, A.B.C.D) => A.B.C.D
pathContainedIn(A.B.C.D, A.B.C.D) => A.B.C.D
pathContainedIn(B.C,A.B) => A.B.C
"
input Path subPath;
input Path path;
output Path completePath;
algorithm
completePath := matchcontinue(subPath,path)
// A suffix, e.g. C.D in A.B.C.D
case (subPath,path)
equation
true=pathSuffixOf(subPath,path);
then path;
// strip last ident of path and recursively check if suffix.
case (subPath,path)
local Ident ident; Path newPath;
equation
ident = pathLastIdent(path);
newPath = stripLast(path);
newPath=pathContainedIn(subPath,newPath);
then joinPaths(newPath,IDENT(ident));

// strip last ident of subpath and recursively check if suffix.
case (subPath,path)
local Ident ident; Path newSubPath;
equation
ident = pathLastIdent(subPath);
newSubPath = stripLast(subPath);
newSubPath=pathContainedIn(newSubPath,path);
then joinPaths(newSubPath,IDENT(ident));
end matchcontinue;
end pathContainedIn;

public function getCrefFromExp "function: getCrefFromExp
Returns a flattened list of the component references
Expand Down Expand Up @@ -1236,6 +1328,22 @@ algorithm
end matchcontinue;
end stripLast;

public function stripFirst "function: stripFirst
Returns the path given as argument to the function
minus the first ident.
"
input Path inPath;
output Path outPath;
algorithm
outPath:=
matchcontinue (inPath)
local
Path p;
case (QUALIFIED(name = _,path = p)) then p;
end matchcontinue;
end stripFirst;

public function crefToPath "function: crefToPath
This function converts a `ComponentRef\' to a `Path\', if possible.
Expand Down
23 changes: 19 additions & 4 deletions Compiler/Env.mo
Expand Up @@ -276,6 +276,7 @@ protected function nameScope "function: nameScope
flattening of the inheritance hiergearchy. The reason for this is that types
of inherited components needs to be expanded such that the types can be
looked up from the environment of the base class.
See also openScope, getScopeName.
"
input Env inEnv;
input Ident inIdent;
Expand All @@ -294,6 +295,19 @@ algorithm
end matchcontinue;
end nameScope;

public function getScopeName "function: getScopeName
Returns the name of a scope, if no name exist, the function fails.
"
input Env inEnv;
output Ident name;
algorithm
name:=
matchcontinue (inEnv)
case ((FRAME(class_1 = SOME(name))::_)) then (name);
end matchcontinue;
end getScopeName;


public function extendFrameC "function: extendFrameC
This function adds a class definition to the environment.
Expand Down Expand Up @@ -719,7 +733,7 @@ algorithm
s4 = printEnvStr(bcframes);
res = Util.stringAppendList(
{"FRAME: ",sid," (enc=",encflag_str,
") \nclasses and vars:\n=============\n",s1," Types:\n======\n",s2," Imports:\n=======\n",s3,"\n"});
") \nclasses and vars:\n=============\n",s1," Types:\n======\n",s2," Imports:\n=======\n",s3,"baseclass:\n======\n",s4,"end baseclass\n"});
then
res;
case FRAME(class_1 = NONE,list_2 = ht,list_3 = httypes,list_4 = imps,list_5 = bcframes,current6 = crs,encapsulated_7 = encflag)
Expand All @@ -731,7 +745,7 @@ algorithm
encflag_str = Util.boolString(encflag);
res = Util.stringAppendList(
{"FRAME: unnamed (enc=",encflag_str,
") \nclasses and vars:\n=============\n",s1," Types:\n======\n",s2," Imports:\n=======\n",s3,"\n"});
") \nclasses and vars:\n=============\n",s1," Types:\n======\n",s2," Imports:\n=======\n",s3,"baseclass:\n======\n",s4,"end baseclass\n"});
then
res;
end matchcontinue;
Expand Down Expand Up @@ -1223,7 +1237,7 @@ algorithm
equation

env = cacheGetEnv(scope,path,tree);
// print("got cached env for ");print(Absyn.pathString(path)); print("\n");
//print("got cached env for ");print(Absyn.pathString(path)); print("\n");
then env;
case (_,_,_) then fail();
end matchcontinue;
Expand Down Expand Up @@ -1273,7 +1287,8 @@ algorithm
case (path2,path,tree)
equation
env = cacheGetEnv2(path2,path,tree);
//print("found ");print(Absyn.pathString(path));print(" in cache\n");
//print("found ");print(Absyn.pathString(path));print(" in cache at scope");
//print(Absyn.pathString(path2));print("\n");
then env;

// Go up one level. Only if we search for e.g. M.C.E and in scope M
Expand Down
60 changes: 44 additions & 16 deletions Compiler/Inst.mo
Expand Up @@ -920,6 +920,7 @@ algorithm
ci_state = ClassInf.start(r, n);
(cache,dae1,env_3,(csets_1 as Connect.SETS(_,crs)),ci_state_1,tys,bc_ty)
= instClassIn(cache,env_1, mod, pre, csets, ci_state, c, false, inst_dims, impl) ;
//print("makeFullyQualified926\n");
(cache,fq_class) = makeFullyQualified(cache,env, Absyn.IDENT(n));

//str = Absyn.pathString(fq_class); print("------------------- CLASS makeFullyQualified instClass-----------------\n");print(n); print(" ");print(str);print("\n===============================================\n");
Expand All @@ -929,6 +930,7 @@ algorithm
dae2 = Connect.equations(csets_1);
(cache,dae3) = Connect.unconnectedFlowEquations(cache,csets_1, dae1, env_3, callscope_1);
dae = Util.listFlatten({dae1_1,dae2,dae3});
//print("makeFullyQualified936\n");
(cache,typename) = makeFullyQualified(cache,env, Absyn.IDENT(n));
ty = mktype(typename, ci_state_1, tys, bc_ty) ;
then
Expand Down Expand Up @@ -999,13 +1001,15 @@ algorithm
c_1 = SCode.classSetPartial(c, false);
(cache,dae1,env_3,(csets_1 as Connect.SETS(_,crs)),ci_state_1,tys,bc_ty)
= instClassIn(cache,env_1, mod, pre, csets, ci_state, c_1, false, inst_dims, impl) ;
(cache,fq_class) = makeFullyQualified(cache,env, Absyn.IDENT(n));
//print("makeFullyQualified1007\n");
(cache,fq_class) = makeFullyQualified(cache,env_3, Absyn.IDENT(n));
dae1_1 = DAE.setComponentType(dae1, fq_class);
callscope_1 = isTopCall(callscope);
dae2 = Connect.equations(csets_1);
(cache,dae3) = Connect.unconnectedFlowEquations(cache,csets_1, dae1, env_3, callscope_1);
dae = Util.listFlatten({dae1_1,dae2,dae3});
(cache,typename) = makeFullyQualified(cache,env, Absyn.IDENT(n));
//print("makeFullyQualified1014\n");
(cache,typename) = makeFullyQualified(cache,env_3, Absyn.IDENT(n));
ty = mktypeWithArrays(typename, ci_state_1, tys, bc_ty);
then
(cache,dae,env_3,Connect.SETS({},crs),ty,ci_state_1);
Expand Down Expand Up @@ -1752,7 +1756,7 @@ algorithm
(cache,m_1) = Mod.elabMod(cache,env, Prefix.NOPRE(), mod, true) "impl" ;
m_2 = Mod.merge(mods, m_1, env, Prefix.NOPRE());
(cache,cdef,cenv) = Lookup.lookupClass(cache,env, path, true);
(cache,dae,env_1,_,ty,st) = instClassBasictype(cache,env, m_2, Prefix.NOPRE(), Connect.emptySet, cdef,
(cache,dae,env_1,_,ty,st) = instClassBasictype(cache,cenv, m_2, Prefix.NOPRE(), Connect.emptySet, cdef,
inst_dims, false, INNER_CALL()) "impl" ;
b1 = Types.basicType(ty);
b2 = Types.arrayType(ty);
Expand Down Expand Up @@ -1929,6 +1933,7 @@ algorithm
env3 = addComponentsToEnv(env2, mods, pre, csets, ci_state, constantEls, constantEls,
{}, inst_dims, false);
(cache,_,env3,_,ci_state2,_) = instElementList(cache,env3, mods, pre, csets, ci_state1, constantEls, inst_dims, true) "instantiate constants";

then
(cache,env3,ci_state2);
case (cache,env,mods,pre,csets,ci_state,SCode.DERIVED(short = cn,absynArrayDimOption = ad,mod = mod),re,prot,inst_dims) /* This rule describes how to instantiate a derived class definition */
Expand All @@ -1940,6 +1945,7 @@ algorithm
new_ci_state = ClassInf.start(r, cn2);
mods_1 = Mod.merge(mods, m, cenv_2, pre);
mods_2 = Mod.merge(mods_1, mod_1, cenv_2, pre);
print("partialInstClassIn1948\n");
(cache,env_2,new_ci_state_1) = partialInstClassIn(cache,cenv_2, mods_2, pre, csets, new_ci_state, c, prot,
inst_dims);
then
Expand Down Expand Up @@ -2088,7 +2094,7 @@ algorithm
SCode.Mod emod;
SCode.Element elt;
Env.Cache cache;
case (cache,env,mod,(SCode.EXTENDS(path = tp,mod = emod) :: rest),ci_state,impl) /* inherited initial equations inherited algorithms inherited initial algorithms */
case (cache,env,mod,(SCode.EXTENDS(path = tp,mod = emod) :: rest),ci_state,impl)
equation
(cache,(c as SCode.CLASS(cn,_,encf,r,_)),cenv) = Lookup.lookupClass(cache,env, tp, true);
outermod = Mod.lookupModificationP(mod, Absyn.IDENT(cn));
Expand Down Expand Up @@ -2126,8 +2132,7 @@ algorithm
fail();
case (cache,env,mod,(SCode.EXTENDS(path = tp,mod = emod) :: rest),ci_state,impl)
equation
//Debug.fprint("failtrace", "Failed inst_extends_list on EXTENDS\n env:");
Env.printEnv(env);
//print("instExtendsList failed on extends ");print(Absyn.pathString(tp));print("\n");
then
fail();
case (cache,env,mod,(elt :: rest),ci_state,impl) /* Components that are not EXTENDS */
Expand Down Expand Up @@ -3264,19 +3269,31 @@ algorithm
Env.BinTree cl,tps;
list<Env.Item> imps;
list<Exp.ComponentRef> crs;
Absyn.Path tp;
Absyn.Path tp,envpath;
Env.Cache cache;
case (cache,env,NONE) then (cache,env);
case (cache,(env as (Env.FRAME(class_1 = id,list_2 = cl,list_3 = tps,list_4 = imps,current6 = crs,encapsulated_7 = enc) :: fs)),SOME(tp)) /* Base classes are fully qualified names, search from top scope This is needed since the environment can be encapsulated, but
inherited classes are not affected by this and therefore should
search from top scope directly. */

/* Special case to avoid infinite recursion.
If in scope A.B and searching for A.B.C.D, look for C.D directly in the scope. Otherwise, A.B
will be instantiated over and over again, see testcase packages2.mo
*/
case (cache,(env as (Env.FRAME(class_1 = id,list_2 = cl,list_3 = tps,list_4 = imps,current6 = crs,encapsulated_7 = enc) :: fs)),SOME(tp))
local Absyn.Path newTp;
equation
SOME(envpath) = Env.getEnvPath(env);
true = Absyn.pathPrefixOf(envpath,tp);
newTp = Absyn.removePrefix(envpath,tp);
(cache,env_2) = Lookup.lookupAndInstantiate(cache,env,newTp,true);
then
(cache,Env.FRAME(id,cl,tps,imps,env_2,crs,enc) :: fs);

/* Base classes are fully qualified names, search from top scope.
This is needed since the environment can be encapsulated, but inherited classes are not affected
by this and therefore should search from top scope directly. */
case (cache,(env as (Env.FRAME(class_1 = id,list_2 = cl,list_3 = tps,list_4 = imps,current6 = crs,encapsulated_7 = enc) :: fs)),SOME(tp))
equation
top_frame = Env.topFrame(env);
(cache,(c as SCode.CLASS(cn2,_,enc2,r,_)),cenv) = Lookup.lookupClass(cache,{top_frame}, tp, true);
cenv_2 = Env.openScope(cenv, enc2, SOME(cn2));
new_ci_state = ClassInf.start(r, cn2);
(cache,env_2,new_ci_state_1) = partialInstClassIn(cache,cenv_2, Types.NOMOD(), Prefix.NOPRE(), Connect.emptySet,
new_ci_state, c, false, {});
(cache,env_2) = Lookup.lookupAndInstantiate(cache,{top_frame},tp,true);
then
(cache,Env.FRAME(id,cl,tps,imps,env_2,crs,enc) :: fs);
case (_,_,_)
Expand Down Expand Up @@ -5185,6 +5202,15 @@ algorithm
NONE = Env.getEnvPath(env);
then
(cache,path);

/* case (cache,env,path)
local Absyn.Path envpath,newPath;
equation
SOME(envpath) = Env.getEnvPath(env);
newPath = Absyn.pathContainedIn(path,envpath);
//print("makeFullyQualified( contained =");print(Absyn.pathString(newPath));print("\n");
then (cache,newPath);*/

case (cache,env,path) /* To make a class fully qualified, the class path
is looked up in the environment.
The FQ path consist of the simple class name
Expand Down Expand Up @@ -5245,6 +5271,7 @@ algorithm
equation
(cache,dae,cenv,csets_1,ty,st) = instClass(cache,env, mod, pre, csets, c, inst_dims, true, INNER_CALL());
env_1 = Env.extendFrameC(env,c);
//print("makeFullyQualified5275\n");
(cache,fpath) = makeFullyQualified(cache,env_1, Absyn.IDENT(n));
ty1 = setFullyQualifiedTypename(ty,fpath);
env_1 = Env.extendFrameT(env_1, n, ty1);
Expand All @@ -5256,7 +5283,8 @@ algorithm
case (cache,env,mod,pre,csets,(c as SCode.CLASS(name = n,restricion = (restr as SCode.R_EXT_FUNCTION()),parts = (parts as SCode.PARTS(elementLst = els)))),inst_dims)
equation
(cache,dae,cenv,csets_1,ty,st) = instClass(cache,env, mod, pre, csets, c, inst_dims, true, INNER_CALL());
env_1 = Env.extendFrameC(env,c);
env_1 = Env.extendFrameC(env,c);
//print("makeFullyQualified5288\n");
(cache,fpath) = makeFullyQualified(cache,env_1, Absyn.IDENT(n));
ty1 = setFullyQualifiedTypename(ty,fpath);
env_1 = Env.extendFrameT(env_1, n, ty1);
Expand Down

0 comments on commit 5c92983

Please sign in to comment.