Skip to content

Commit

Permalink
Improve copyClass API (#12120)
Browse files Browse the repository at this point in the history
- Improved `copyClass` so that it updates the paths in the copied class
  to be valid in the new location of the class where possible.
- Changed default `within` argument of `copyClass` from `TopLevel` to
  `__OpenModelica_TopLevel` to make it a bit less likely to conflict
  with user models.
  • Loading branch information
perost committed Mar 19, 2024
1 parent c54136e commit d4be423
Show file tree
Hide file tree
Showing 15 changed files with 883 additions and 6 deletions.
2 changes: 1 addition & 1 deletion OMCompiler/Compiler/FrontEnd/ModelicaBuiltin.mo
Expand Up @@ -2714,7 +2714,7 @@ function copyClass
"Copies a class within the same level"
input TypeName className "the class that should be copied";
input String newClassName "the name for new class";
input TypeName withIn = $TypeName(TopLevel) "the with in path for new class";
input TypeName withIn = $TypeName(__OpenModelica_TopLevel) "the with in path for new class";
output Boolean result;
external "builtin";
annotation(preferredView="text");
Expand Down
68 changes: 68 additions & 0 deletions OMCompiler/Compiler/NFFrontEnd/NFLookup.mo
Expand Up @@ -489,6 +489,74 @@ algorithm
fail();
end lookupSimpleName;

function lookupSimpleNameRootPath
"Returns the qualified path needed to find the given name in the given scope
that's either a root class or a class somewhere inside a root class. If the
name is found outside the root class it's fully qualified, otherwise it's
returned as it is."
input String name;
input InstNode scope;
input InstContext.Type context;
output Absyn.Path path;
protected
InstNode node, cur_scope = scope;
Boolean in_root_class = true;
algorithm
if InstContext.inAnnotation(context) then
try
_ := lookupLocalSimpleName(name, InstNode.annotationScope(scope));
// Name refers to builtin annotation that shouldn't be qualified.
path := Absyn.Path.IDENT(name);
return;
else
end try;
end if;

for i in 1:Global.recursionDepthLimit loop
try
node := Class.lookupElement(name, InstNode.getClass(cur_scope));

if in_root_class then
// If we're still inside the root class, then the name doesn't need to be qualified.
path := Absyn.Path.IDENT(name);
else
// Otherwise, fully qualify the path.
path := AbsynUtil.makeFullyQualified(InstNode.fullPath(node));
end if;

return;
else
if InstNode.isEncapsulated(cur_scope) then
// If the scope is encapsulated then the name can only refer to builtin
// classes, which are already fully qualified.
path := Absyn.Path.IDENT(name);
return;
elseif name == InstNode.name(cur_scope) and InstNode.isClass(cur_scope) then
// The current scope is the class we're looking for.
path := if in_root_class then Absyn.Path.IDENT(name) else
AbsynUtil.makeFullyQualified(InstNode.fullPath(cur_scope));
return;
elseif InstNode.isTopScope(cur_scope) then
// If we reach the top scope then the name is either already fully
// qualified or couldn't be found, in either case return name as it is.
path := Absyn.Path.IDENT(name);
return;
else
if in_root_class and InstNode.isRootClass(cur_scope) then
// The scope was the root class, now we're start to look in the
// enclosing scopes of the root class.
in_root_class := false;
end if;

// Continue in the enclosing scope.
cur_scope := InstNode.parentScope(cur_scope);
end if;
end try;
end for;

fail();
end lookupSimpleNameRootPath;

function lookupNameWithError
input Absyn.Path name;
input InstNode scope;
Expand Down
2 changes: 1 addition & 1 deletion OMCompiler/Compiler/NFFrontEnd/NFModelicaBuiltin.mo
Expand Up @@ -2967,7 +2967,7 @@ function copyClass
"Copies a class within the same level"
input TypeName className "the class that should be copied";
input String newClassName "the name for new class";
input TypeName withIn = $TypeName(TopLevel) "the with in path for new class";
input TypeName withIn = $TypeName(__OpenModelica_TopLevel) "the with in path for new class";
output Boolean result;
external "builtin";
annotation(preferredView="text");
Expand Down
8 changes: 6 additions & 2 deletions OMCompiler/Compiler/Script/CevalScriptBackend.mo
Expand Up @@ -1502,7 +1502,7 @@ algorithm

case ("moveClassToBottom", _) then Values.BOOL(false);

case ("copyClass",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(name), Values.CODE(Absyn.C_TYPENAME(Absyn.IDENT("TopLevel")))})
case ("copyClass",{Values.CODE(Absyn.C_TYPENAME(classpath)), Values.STRING(name), Values.CODE(Absyn.C_TYPENAME(Absyn.IDENT("__OpenModelica_TopLevel")))})
equation
p = SymbolTable.getAbsyn();
absynClass = InteractiveUtil.getPathedClassInProgram(classpath, p);
Expand Down Expand Up @@ -5083,8 +5083,12 @@ algorithm

end match;

// Update the paths in the class to reflect the new location.
cls := NFApi.updateMovedClassPaths(inClass, inClassPath, inWithin);

// Replace the filename of each element with the new path.
cls := moveClassInfo(inClass, dst_path);
cls := moveClassInfo(cls, dst_path);

// Change the name of the class and put it in as a copy in the program.
cls := AbsynUtil.setClassName(cls, inName);
outProg := InteractiveUtil.updateProgram(Absyn.PROGRAM({cls}, inWithin), inProg);
Expand Down

0 comments on commit d4be423

Please sign in to comment.