Skip to content

Commit

Permalink
Improve annotation API performance (#11906)
Browse files Browse the repository at this point in the history
- Add `SymbolTable.setAbsynElement/Class` to make it possible to update
  a single element/class without invalidating the cached SCode.
- Change `InteractiveUtil.transformPathedElementInProgram` to return the
  transformed element to allow it to be used with the new SymbolTable
  functions.
- Update `setElementAnnotation` and `updateConnectionAnnotation` to use
  the new SymbolTable functions.
  • Loading branch information
perost committed Jan 30, 2024
1 parent ae41030 commit aa78119
Show file tree
Hide file tree
Showing 4 changed files with 254 additions and 14 deletions.
103 changes: 103 additions & 0 deletions OMCompiler/Compiler/FrontEnd/SCodeUtil.mo
Original file line number Diff line number Diff line change
Expand Up @@ -3086,6 +3086,16 @@ algorithm
end match;
end elementPrefixes;

public function setElementPrefixes
input SCode.Prefixes prefixes;
input output SCode.Element element;
algorithm
() := match element
case SCode.CLASS() algorithm element.prefixes := prefixes; then ();
case SCode.COMPONENT() algorithm element.prefixes := prefixes; then ();
end match;
end setElementPrefixes;

public function isElementReplaceable
input SCode.Element inElement;
output Boolean isReplaceable;
Expand Down Expand Up @@ -4062,6 +4072,19 @@ algorithm
end match;
end getClassDef;

public function setClassDef
input SCode.ClassDef classDef;
input output SCode.Element cls;
algorithm
() := match cls
case SCode.CLASS()
algorithm
cls.classDef := classDef;
then
();
end match;
end setClassDef;

public function getClassBody
"Returns the body of a class, which for a class extends is the definition it
contains and otherwise just the immediate definition of the class."
Expand Down Expand Up @@ -6146,5 +6169,85 @@ algorithm
end match;
end onlyLiteralsInMod;

function transformPathedElementInProgram
input Absyn.Path path;
input Func func;
input output SCode.Program program;
output Boolean success;

partial function Func
input output SCode.Element element;
end Func;
algorithm
(program, success) := List.findMap(program,
function transformPathedElementInElement(path = path, func = func));
end transformPathedElementInProgram;

function transformPathedElementInElement
input Absyn.Path path;
input Func func;
input output SCode.Element element;
output Boolean success;

partial function Func
input output SCode.Element element;
end Func;
protected
SCode.ClassDef cdef;
algorithm
success := isElementNamed(AbsynUtil.pathFirstIdent(path), element);

if success then
if AbsynUtil.pathIsIdent(path) then
element := func(element);
elseif isClass(element) then
(cdef, success) := transformPathedElementInClassDef(AbsynUtil.pathRest(path), func, getClassDef(element));

if success then
element := setClassDef(cdef, element);
end if;
end if;
end if;
end transformPathedElementInElement;

function transformPathedElementInClassDef
input Absyn.Path path;
input Func func;
input output SCode.ClassDef cls;
output Boolean success;

partial function Func
input output SCode.Element element;
end Func;
protected
list<SCode.Element> elems;
SCode.ClassDef cdef;
algorithm
success := match cls
case SCode.ClassDef.PARTS()
algorithm
(elems, success) := transformPathedElementInProgram(path, func, cls.elementLst);

if success then
cls.elementLst := elems;
end if;
then
success;

case SCode.ClassDef.CLASS_EXTENDS()
algorithm
(cdef, success) := transformPathedElementInClassDef(path, func, cls.composition);

if success then
cls.composition := cdef;
end if;
then
success;

else false;
end match;
end transformPathedElementInClassDef;


annotation(__OpenModelica_Interface="frontend");
end SCodeUtil;
3 changes: 1 addition & 2 deletions OMCompiler/Compiler/Script/CevalScriptBackend.mo
Original file line number Diff line number Diff line change
Expand Up @@ -2713,7 +2713,7 @@ algorithm
absynClass := InteractiveUtil.getPathedClassInProgram(classpath, p);
absynClass := InteractiveUtil.updateConnectionAnnotationInClass(absynClass, str1, str2, Absyn.ANNOTATION(annlst));
p := InteractiveUtil.updateProgram(Absyn.PROGRAM({absynClass}, if AbsynUtil.pathIsIdent(classpath) then Absyn.TOP() else Absyn.WITHIN(AbsynUtil.stripLast(classpath))), p);
SymbolTable.setAbsyn(p);
SymbolTable.setAbsynClass(p, absynClass, classpath);
then
Values.BOOL(true);

Expand Down Expand Up @@ -3084,7 +3084,6 @@ algorithm
Values.CODE(Absyn.C_MODIFICATION(modification = mod))})
algorithm
(p, b) := InteractiveUtil.setElementAnnotation(path, mod, SymbolTable.getAbsyn());
SymbolTable.setAbsyn(p);
then
Values.BOOL(b);
Expand Down
66 changes: 54 additions & 12 deletions OMCompiler/Compiler/Script/InteractiveUtil.mo
Original file line number Diff line number Diff line change
Expand Up @@ -4727,10 +4727,36 @@ algorithm
end match;
end getPathedElementInElement;

public function transformPathedElementInList<T>
input list<T> inList;
input FuncType inFunc;
output list<T> outList = {};
output Option<Absyn.Element> outElement = NONE();
output Boolean outFound = false;

partial function FuncType
input output T t;
output Option<Absyn.Element> outElement;
output Boolean outFound;
end FuncType;
protected
T e;
list<T> rest = inList;
algorithm
while not listEmpty(rest) and not outFound loop
e :: rest := rest;
(e, outElement, outFound) := inFunc(e);
outList := e :: outList;
end while;

outList := List.append_reverse(outList, rest);
end transformPathedElementInList;

public function transformPathedElementInProgram
input Absyn.Path path;
input Func func;
input output Absyn.Program program;
output Option<Absyn.Element> element;
output Boolean success;

partial function Func
Expand All @@ -4743,6 +4769,7 @@ protected
input Absyn.Path path;
input Func func;
input output Absyn.Class cls;
output Option<Absyn.Element> outElement;
output Boolean found;
protected
Absyn.Element elem;
Expand All @@ -4757,15 +4784,18 @@ protected
elem := Absyn.Element.ELEMENT(false, NONE(), Absyn.InnerOuter.NOT_INNER_OUTER(),
Absyn.ElementSpec.CLASSDEF(false, cls), cls.info, NONE());
elem := func(elem);
outElement := SOME(elem);
Absyn.Element.ELEMENT(specification = Absyn.ElementSpec.CLASSDEF(class_ = cls)) := elem;
else
// The path points to an element inside the class.
(cls, found) := transformPathedElementInClass(AbsynUtil.pathRest(path), func, cls);
(cls, outElement, found) := transformPathedElementInClass(AbsynUtil.pathRest(path), func, cls);
end if;
else
outElement := NONE();
end if;
end transform_class;
algorithm
(clss, success) := List.findMap(program.classes, function transform_class(path = path, func = func));
(clss, element, success) := transformPathedElementInList(program.classes, function transform_class(path = path, func = func));

if success then
program.classes := clss;
Expand All @@ -4776,6 +4806,7 @@ protected function transformPathedElementInClass
input Absyn.Path path;
input Func func;
input output Absyn.Class cls;
output Option<Absyn.Element> element;
output Boolean success;

partial function Func
Expand All @@ -4784,7 +4815,7 @@ protected function transformPathedElementInClass
protected
Absyn.ClassDef def;
algorithm
(def, success) := transformPathedElementInClassDef(path, func, cls.body);
(def, element, success) := transformPathedElementInClassDef(path, func, cls.body);

if success then
cls.body := def;
Expand All @@ -4795,6 +4826,7 @@ protected function transformPathedElementInClassDef
input Absyn.Path path;
input Func func;
input output Absyn.ClassDef def;
output Option<Absyn.Element> element;
output Boolean success;

partial function Func
Expand All @@ -4806,7 +4838,7 @@ algorithm
success := match def
case Absyn.ClassDef.PARTS()
algorithm
(parts, success) := List.findMap(def.classParts,
(parts, element, success) := transformPathedElementInList(def.classParts,
function transformPathedElementInClassPart(path = path, func = func));

if success then
Expand All @@ -4817,7 +4849,7 @@ algorithm

case Absyn.ClassDef.CLASS_EXTENDS()
algorithm
(parts, success) := List.findMap(def.parts,
(parts, element, success) := transformPathedElementInList(def.parts,
function transformPathedElementInClassPart(path = path, func = func));

if success then
Expand All @@ -4834,6 +4866,7 @@ protected function transformPathedElementInClassPart
input Absyn.Path path;
input Func func;
input output Absyn.ClassPart part;
output Option<Absyn.Element> element;
output Boolean success;

partial function Func
Expand All @@ -4845,7 +4878,7 @@ algorithm
success := match part
case Absyn.ClassPart.PUBLIC()
algorithm
(items, success) := List.findMap(part.contents,
(items, element, success) := transformPathedElementInList(part.contents,
function transformPathedElementInElementItem(path = path, func = func));

if success then
Expand All @@ -4856,7 +4889,7 @@ algorithm

case Absyn.ClassPart.PROTECTED()
algorithm
(items, success) := List.findMap(part.contents,
(items, element, success) := transformPathedElementInList(part.contents,
function transformPathedElementInElementItem(path = path, func = func));

if success then
Expand All @@ -4873,6 +4906,7 @@ protected function transformPathedElementInElementItem
input Absyn.Path path;
input Func func;
input output Absyn.ElementItem item;
output Option<Absyn.Element> outElement;
output Boolean success;

partial function Func
Expand All @@ -4887,9 +4921,10 @@ algorithm
algorithm
if AbsynUtil.pathIsIdent(path) then
item.element := func(item.element);
outElement := SOME(item.element);
success := true;
else
(element, success) := transformPathedElementInElement(AbsynUtil.pathRest(path), func, item.element);
(element, outElement, success) := transformPathedElementInElement(AbsynUtil.pathRest(path), func, item.element);

if success then
item.element := element;
Expand All @@ -4906,6 +4941,7 @@ protected function transformPathedElementInElement
input Absyn.Path path;
input Func func;
input output Absyn.Element element;
output Option<Absyn.Element> outElement;
output Boolean success;

partial function Func
Expand All @@ -4917,7 +4953,7 @@ algorithm
success := match element
case Absyn.Element.ELEMENT()
algorithm
(spec, success) := transformPathedElementInElementSpec(path, func, element.specification);
(spec, outElement, success) := transformPathedElementInElementSpec(path, func, element.specification);

if success then
element.specification := spec;
Expand All @@ -4933,6 +4969,7 @@ protected function transformPathedElementInElementSpec
input Absyn.Path path;
input Func func;
input output Absyn.ElementSpec spec;
output Option<Absyn.Element> element;
output Boolean success;

partial function Func
Expand All @@ -4944,7 +4981,7 @@ algorithm
success := match spec
case Absyn.ElementSpec.CLASSDEF()
algorithm
(cls, success) := transformPathedElementInClass(path, func, spec.class_);
(cls, element, success) := transformPathedElementInClass(path, func, spec.class_);

if success then
spec.class_ := cls;
Expand Down Expand Up @@ -5016,6 +5053,7 @@ public function setElementAnnotation
protected
Option<Absyn.Annotation> ann;
String name;
Option<Absyn.Element> elem_opt;
algorithm
try
if listEmpty(annotationMod.elementArgLst) then
Expand All @@ -5025,8 +5063,12 @@ algorithm
end if;

name := AbsynUtil.pathLastIdent(elementPath);
(program, success) := transformPathedElementInProgram(elementPath,
(program, elem_opt, success) := transformPathedElementInProgram(elementPath,
function AbsynUtil.setElementAnnotation(name = name, inAnnotation = ann), program);

if success then
SymbolTable.setAbsynElement(program, Util.getOption(elem_opt), elementPath);
end if;
else
success := false;
end try;
Expand All @@ -5044,7 +5086,7 @@ algorithm
Absyn.Program.PROGRAM(classes = {Absyn.Class.CLASS(body = parsed_body)}) :=
Parser.parsestring(stringAppendList({"model dummy\n", content, "end dummy;\n"}));

(program, success) := transformPathedElementInProgram(classPath,
(program, _, success) := transformPathedElementInProgram(classPath,
function mergeClassContents(newContent = parsed_body), program);
else
success := false;
Expand Down

0 comments on commit aa78119

Please sign in to comment.