Skip to content

Commit

Permalink
- Don't enter base classes that the lookup is coming from in SCodeLoo…
Browse files Browse the repository at this point in the history
…kup to

  avoid infinite loops when extending a base class further down in the environment.
- When doing dependency analysis on an extends clause, remove it from the
  environment so that we don't look it up in itself.


git-svn-id: https://openmodelica.org/svn/OpenModelica/trunk@10327 f25d12d1-65f4-0310-ae8a-bbce733d8d8e
  • Loading branch information
perost committed Nov 8, 2011
1 parent 9134616 commit 3c8b349
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 32 deletions.
9 changes: 5 additions & 4 deletions Compiler/FrontEnd/SCodeDependency.mo
Expand Up @@ -690,7 +690,7 @@ algorithm
Option<SCode.ConstrainClass> cc;
SCode.Element cls;
Item ty_item;
Env ty_env;
Env ty_env, env;
SCode.Ident name;
SCode.Prefixes prefixes;

Expand All @@ -703,10 +703,11 @@ algorithm
case (SCode.EXTENDS(baseClassPath = bc, modifications = mods, info = info),
_, _)
equation
true = checkNotExtendsDependent(bc, inEnv, info);
analyseExtends(bc, inEnv, info);
env = SCodeEnv.removeExtendFromLocalScope(bc, inEnv);
true = checkNotExtendsDependent(bc, env, info);
analyseExtends(bc, env, info);
(ty_item, _, ty_env) =
SCodeLookup.lookupBaseClassName(bc, inEnv, info);
SCodeLookup.lookupBaseClassName(bc, env, info);
ty_env = SCodeEnv.mergeItemEnv(ty_item, ty_env);
analyseModifier(mods, inEnv, ty_env, info);
then
Expand Down
34 changes: 34 additions & 0 deletions Compiler/FrontEnd/SCodeEnv.mo
Expand Up @@ -355,6 +355,40 @@ algorithm
outEnv := FRAME(name, ty, tree, exts, imps, is_used) :: rest;
end removeExtendsFromLocalScope;

public function removeExtendFromLocalScope
"Removes a given extends clause from the local scope."
input Absyn.Path inExtend;
input Env inEnv;
output Env outEnv;
protected
Option<String> name;
FrameType ty;
AvlTree tree;
ImportTable imps;
Env rest;
Util.StatefulBoolean iu;
list<Extends> bcl;
list<SCode.Element> re;
Option<SCode.Element> cei;
algorithm
FRAME(name = name, frameType = ty, clsAndVars = tree, extendsTable =
EXTENDS_TABLE(baseClasses = bcl, redeclaredElements = re, classExtendsInfo = cei),
importTable = imps, isUsed = iu) :: rest := inEnv;
(bcl, _) := List.deleteMemberOnTrue(inExtend, bcl, isExtendNamed);
outEnv := FRAME(name, ty, tree, EXTENDS_TABLE(bcl, re, cei), imps, iu) :: rest;
end removeExtendFromLocalScope;

protected function isExtendNamed
input Absyn.Path inName;
input Extends inExtends;
output Boolean outIsNamed;
protected
Absyn.Path bc;
algorithm
EXTENDS(baseClass = bc) := inExtends;
outIsNamed := Absyn.pathEqual(inName, bc);
end isExtendNamed;

public function removeRedeclaresFromLocalScope
input Env inEnv;
output Env outEnv;
Expand Down
93 changes: 65 additions & 28 deletions Compiler/FrontEnd/SCodeLookup.mo
Expand Up @@ -111,49 +111,54 @@ public function lookupSimpleName
output Env outEnv;
algorithm
(SOME(outItem), SOME(outPath), SOME(outEnv)) :=
lookupSimpleName2(inName, inEnv);
lookupSimpleName2(inName, inEnv, {});
end lookupSimpleName;

public function lookupSimpleName2
"Helper function to lookupSimpleName. Looks up a simple identifier in the
environment."
input Absyn.Ident inName;
input Env inEnv;
input list<String> inVisitedScopes;
output Option<Item> outItem;
output Option<Absyn.Path> outPath;
output Option<Env> outEnv;
algorithm
(outItem, outPath, outEnv) := matchcontinue(inName, inEnv)
(outItem, outPath, outEnv) := matchcontinue(inName, inEnv, inVisitedScopes)
local
FrameType frame_type;
Env rest_env;
Option<Item> opt_item;
Option<Absyn.Path> opt_path;
Option<Env> opt_env;
String scope_name;

// Check the local scope.
case (_, _)
case (_, _, _)
equation
(opt_item, opt_path, opt_env) = lookupInLocalScope(inName, inEnv);
(opt_item, opt_path, opt_env) =
lookupInLocalScope(inName, inEnv, inVisitedScopes);
then
(opt_item, opt_path, opt_env);

// If not found in the local scope, check the next frame unless the current
// frame is encapsulated.
case (_, SCodeEnv.FRAME(frameType = frame_type) :: rest_env)
case (_, SCodeEnv.FRAME(name = SOME(scope_name), frameType = frame_type) ::
rest_env, _)
equation
frameNotEncapsulated(frame_type);
(opt_item, opt_path, opt_env) = lookupSimpleName2(inName, rest_env);
(opt_item, opt_path, opt_env) =
lookupSimpleName2(inName, rest_env, scope_name :: inVisitedScopes);
then
(opt_item, opt_path, opt_env);

// If the current frame is encapsulated, check for builtin types and
// functions in the top scope.
case (_, SCodeEnv.FRAME(frameType = SCodeEnv.ENCAPSULATED_SCOPE()) ::
rest_env)
rest_env, _)
equation
rest_env = SCodeEnv.getEnvTopScope(rest_env);
(opt_item, opt_path, opt_env) = lookupSimpleName2(inName, rest_env);
(opt_item, opt_path, opt_env) = lookupSimpleName2(inName, rest_env, {});
checkBuiltinItem(opt_item);
then
(opt_item, opt_path, opt_env);
Expand Down Expand Up @@ -190,11 +195,12 @@ public function lookupInLocalScope
found), or fails if no match is found."
input Absyn.Ident inName;
input Env inEnv;
input list<String> inVisitedScopes;
output Option<Item> outItem;
output Option<Absyn.Path> outPath;
output Option<Env> outEnv;
algorithm
(outItem, outPath, outEnv) := matchcontinue(inName, inEnv)
(outItem, outPath, outEnv) := matchcontinue(inName, inEnv, inVisitedScopes)
local
AvlTree cls_and_vars;
Env rest_env, env;
Expand All @@ -207,24 +213,24 @@ algorithm
Option<Env> opt_env;

// Look among the locally declared components.
case (_, SCodeEnv.FRAME(clsAndVars = cls_and_vars) :: _)
case (_, SCodeEnv.FRAME(clsAndVars = cls_and_vars) :: _, _)
equation
item = SCodeEnv.avlTreeGet(cls_and_vars, inName);
item = SCodeEnv.resolveAlias(item, cls_and_vars);
then
(SOME(item), SOME(Absyn.IDENT(inName)), SOME(inEnv));

// Look among the inherited components.
case (_, _)
case (_, _, _)
equation
(opt_item, opt_path, _, opt_env) =
lookupInBaseClasses(inName, inEnv, INSERT_REDECLARES());
lookupInBaseClasses(inName, inEnv, INSERT_REDECLARES(), inVisitedScopes);
then
(opt_item, opt_path, opt_env);

// Look among the qualified imports.
case (_, SCodeEnv.FRAME(importTable =
SCodeEnv.IMPORT_TABLE(hidden = false, qualifiedImports = imps)) :: _)
SCodeEnv.IMPORT_TABLE(hidden = false, qualifiedImports = imps)) :: _, _)
equation
(opt_item, opt_path, opt_env) =
lookupInQualifiedImports(inName, imps, inEnv);
Expand All @@ -233,7 +239,7 @@ algorithm

// Look among the unqualified imports.
case (_, SCodeEnv.FRAME(importTable =
SCodeEnv.IMPORT_TABLE(hidden = false, unqualifiedImports = imps)) :: _)
SCodeEnv.IMPORT_TABLE(hidden = false, unqualifiedImports = imps)) :: _, _)
equation
(item, path, env) =
lookupInUnqualifiedImports(inName, imps, inEnv);
Expand All @@ -242,9 +248,10 @@ algorithm

// Look in the next scope only if the current scope is an implicit scope
// (for example a for or match/matchcontinue scope).
case (_, SCodeEnv.FRAME(frameType = SCodeEnv.IMPLICIT_SCOPE()) :: rest_env)
case (_, SCodeEnv.FRAME(frameType = SCodeEnv.IMPLICIT_SCOPE()) :: rest_env, _)
equation
(opt_item, opt_path, opt_env) = lookupInLocalScope(inName, rest_env);
(opt_item, opt_path, opt_env) =
lookupInLocalScope(inName, rest_env, inVisitedScopes);
then
(opt_item, opt_path, opt_env);

Expand All @@ -256,6 +263,7 @@ public function lookupInBaseClasses
input Absyn.Ident inName;
input Env inEnv;
input RedeclareReplaceStrategy inReplaceRedeclares;
input list<String> inVisitedScopes;
output Option<Item> outItem;
output Option<Absyn.Path> outPath;
output Absyn.Path outBaseClass;
Expand All @@ -272,7 +280,7 @@ algorithm
env := SCodeEnv.removeExtendsFromLocalScope(inEnv);
env := SCodeEnv.setImportTableHidden(env, false);
(outItem, outPath, outBaseClass, outEnv) :=
lookupInBaseClasses2(inName, bcl, env, inReplaceRedeclares);
lookupInBaseClasses2(inName, bcl, env, inReplaceRedeclares, inVisitedScopes);
end lookupInBaseClasses;

public function lookupInBaseClasses2
Expand All @@ -282,13 +290,14 @@ public function lookupInBaseClasses2
input list<Extends> inBaseClasses;
input Env inEnv;
input RedeclareReplaceStrategy inReplaceRedeclares;
input list<String> inVisitedScopes;
output Option<Item> outItem;
output Option<Absyn.Path> outPath;
output Absyn.Path outBaseClass;
output Option<Env> outEnv;
algorithm
(outItem, outPath, outBaseClass, outEnv) :=
matchcontinue(inName, inBaseClasses, inEnv, inReplaceRedeclares)
matchcontinue(inName, inBaseClasses, inEnv, inReplaceRedeclares, inVisitedScopes)
local
Absyn.Path bc, path;
list<Extends> rest_bc;
Expand All @@ -302,10 +311,11 @@ algorithm

// Look in the first base class.
case (_, SCodeEnv.EXTENDS(baseClass = bc, redeclareModifiers = redecls,
info = info) :: _, _, _)
info = info) :: _, _, _, _)
equation
// Find the base class.
(item, path, env) = lookupBaseClassName(bc, inEnv, info);
true = checkVisitedScopes(inVisitedScopes, inEnv, path);
// Hide the imports to make sure that we don't find the name via them
// (imports are not inherited).
item = SCodeEnv.setImportsInItemHidden(item, true);
Expand All @@ -318,16 +328,43 @@ algorithm
(opt_item, opt_path, bc, opt_env);

// No match, check the rest of the base classes.
case (_, _ :: rest_bc, _, _)
case (_, _ :: rest_bc, _, _, _)
equation
(opt_item, opt_path, bc, opt_env) =
lookupInBaseClasses2(inName, rest_bc, inEnv, inReplaceRedeclares);
lookupInBaseClasses2(inName, rest_bc, inEnv, inReplaceRedeclares, inVisitedScopes);
then
(opt_item, opt_path, bc, opt_env);

end matchcontinue;
end lookupInBaseClasses2;

protected function checkVisitedScopes
"Checks if we are trying to look up a base class that we are coming from when
going up in the environment, to avoid infinite loops."
input list<String> inVisitedScopes;
input Env inEnv;
input Absyn.Path inBaseClass;
output Boolean outRes;
algorithm
outRes := matchcontinue(inVisitedScopes, inEnv, inBaseClass)
local
Absyn.Path env_path, visited_path, bc_path;

case ({}, _, _) then true;

case (_, _, _)
equation
env_path = SCodeEnv.getEnvPath(inEnv);
bc_path = Absyn.removePrefix(env_path, inBaseClass);
visited_path = Absyn.stringListPath(inVisitedScopes);
true = Absyn.pathPrefixOf(visited_path, bc_path);
then
false;

else true;
end matchcontinue;
end checkVisitedScopes;

protected function lookupInBaseClasses3
input Absyn.Path inName;
input Option<Item> inItem;
Expand Down Expand Up @@ -486,7 +523,7 @@ algorithm
// Simple name, look in the local scope.
case (Absyn.IDENT(name = name), _)
equation
(SOME(item), SOME(path), SOME(env)) = lookupInLocalScope(name, inEnv);
(SOME(item), SOME(path), SOME(env)) = lookupInLocalScope(name, inEnv, {});
env = SCodeEnv.setImportTableHidden(env, false);
then
(item, path, env);
Expand All @@ -496,7 +533,7 @@ algorithm
equation
// Look up the name in the local scope.
(SOME(item), SOME(new_path), SOME(env)) =
lookupInLocalScope(name, inEnv);
lookupInLocalScope(name, inEnv, {});
env = SCodeEnv.setImportTableHidden(env, false);
// Look for the rest of the path in the found item.
(item, path, env) = lookupNameInItem(path, item, env);
Expand Down Expand Up @@ -528,7 +565,7 @@ algorithm
// Simple identifier, look in the local scope.
case (Absyn.CREF_IDENT(name = name, subscripts = subs), _)
equation
(SOME(item), SOME(new_path), _) = lookupInLocalScope(name, inEnv);
(SOME(item), SOME(new_path), _) = lookupInLocalScope(name, inEnv, {});
cref = Absyn.pathToCrefWithSubs(new_path, subs);
then
(item, cref);
Expand All @@ -539,7 +576,7 @@ algorithm
equation
// Look in the local scope.
(SOME(item), SOME(new_path), SOME(env)) =
lookupInLocalScope(name, inEnv);
lookupInLocalScope(name, inEnv, {});
// Look for the rest of the reference in the found item.
(item, cref_rest) = lookupCrefInItem(cref_rest, item, env);
cref = Absyn.pathToCrefWithSubs(new_path, subs);
Expand Down Expand Up @@ -656,7 +693,7 @@ public function lookupBaseClass
output Item outItem;
algorithm
(SOME(outItem), _, outBaseClass, _) := lookupInBaseClasses(inClass, inEnv,
INSERT_REDECLARES());
INSERT_REDECLARES(), {});
end lookupBaseClass;

public function lookupRedeclaredClassByItem
Expand All @@ -677,7 +714,7 @@ algorithm
case (SCodeEnv.CLASS(cls = SCode.CLASS(name = name)), _, _)
equation
(SOME(item), _, _, SOME(env)) = lookupInBaseClasses(name, inEnv,
IGNORE_REDECLARES());
IGNORE_REDECLARES(), {});
SCode.PREFIXES(redeclarePrefix = rdp, replaceablePrefix = rpp) =
SCodeEnv.getItemPrefixes(item);
(item, env) = lookupRedeclaredClass2(item, rdp, rpp, env, inInfo);
Expand Down Expand Up @@ -728,7 +765,7 @@ algorithm
SCode.REDECLARE(), SCode.REPLACEABLE(cc = _), _, _)
equation
(SOME(item), _, _, SOME(env)) = lookupInBaseClasses(name, inEnv,
IGNORE_REDECLARES());
IGNORE_REDECLARES(), {});
SCode.PREFIXES(redeclarePrefix = rdp, replaceablePrefix = rpp) =
SCodeEnv.getItemPrefixes(item);
(item, env) = lookupRedeclaredClass2(item, rdp, rpp, env, inInfo);
Expand Down

0 comments on commit 3c8b349

Please sign in to comment.