Skip to content

Commit 481e92c

Browse files
authored
Improve annotation API performance (#11906) (#11922)
- 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.
1 parent ce2ba6b commit 481e92c

File tree

4 files changed

+254
-15
lines changed

4 files changed

+254
-15
lines changed

OMCompiler/Compiler/FrontEnd/SCodeUtil.mo

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3086,6 +3086,16 @@ algorithm
30863086
end match;
30873087
end elementPrefixes;
30883088

3089+
public function setElementPrefixes
3090+
input SCode.Prefixes prefixes;
3091+
input output SCode.Element element;
3092+
algorithm
3093+
() := match element
3094+
case SCode.CLASS() algorithm element.prefixes := prefixes; then ();
3095+
case SCode.COMPONENT() algorithm element.prefixes := prefixes; then ();
3096+
end match;
3097+
end setElementPrefixes;
3098+
30893099
public function isElementReplaceable
30903100
input SCode.Element inElement;
30913101
output Boolean isReplaceable;
@@ -4062,6 +4072,19 @@ algorithm
40624072
end match;
40634073
end getClassDef;
40644074

4075+
public function setClassDef
4076+
input SCode.ClassDef classDef;
4077+
input output SCode.Element cls;
4078+
algorithm
4079+
() := match cls
4080+
case SCode.CLASS()
4081+
algorithm
4082+
cls.classDef := classDef;
4083+
then
4084+
();
4085+
end match;
4086+
end setClassDef;
4087+
40654088
public function getClassBody
40664089
"Returns the body of a class, which for a class extends is the definition it
40674090
contains and otherwise just the immediate definition of the class."
@@ -6146,5 +6169,85 @@ algorithm
61466169
end match;
61476170
end onlyLiteralsInMod;
61486171

6172+
function transformPathedElementInProgram
6173+
input Absyn.Path path;
6174+
input Func func;
6175+
input output SCode.Program program;
6176+
output Boolean success;
6177+
6178+
partial function Func
6179+
input output SCode.Element element;
6180+
end Func;
6181+
algorithm
6182+
(program, success) := List.findMap(program,
6183+
function transformPathedElementInElement(path = path, func = func));
6184+
end transformPathedElementInProgram;
6185+
6186+
function transformPathedElementInElement
6187+
input Absyn.Path path;
6188+
input Func func;
6189+
input output SCode.Element element;
6190+
output Boolean success;
6191+
6192+
partial function Func
6193+
input output SCode.Element element;
6194+
end Func;
6195+
protected
6196+
SCode.ClassDef cdef;
6197+
algorithm
6198+
success := isElementNamed(AbsynUtil.pathFirstIdent(path), element);
6199+
6200+
if success then
6201+
if AbsynUtil.pathIsIdent(path) then
6202+
element := func(element);
6203+
elseif isClass(element) then
6204+
(cdef, success) := transformPathedElementInClassDef(AbsynUtil.pathRest(path), func, getClassDef(element));
6205+
6206+
if success then
6207+
element := setClassDef(cdef, element);
6208+
end if;
6209+
end if;
6210+
end if;
6211+
end transformPathedElementInElement;
6212+
6213+
function transformPathedElementInClassDef
6214+
input Absyn.Path path;
6215+
input Func func;
6216+
input output SCode.ClassDef cls;
6217+
output Boolean success;
6218+
6219+
partial function Func
6220+
input output SCode.Element element;
6221+
end Func;
6222+
protected
6223+
list<SCode.Element> elems;
6224+
SCode.ClassDef cdef;
6225+
algorithm
6226+
success := match cls
6227+
case SCode.ClassDef.PARTS()
6228+
algorithm
6229+
(elems, success) := transformPathedElementInProgram(path, func, cls.elementLst);
6230+
6231+
if success then
6232+
cls.elementLst := elems;
6233+
end if;
6234+
then
6235+
success;
6236+
6237+
case SCode.ClassDef.CLASS_EXTENDS()
6238+
algorithm
6239+
(cdef, success) := transformPathedElementInClassDef(path, func, cls.composition);
6240+
6241+
if success then
6242+
cls.composition := cdef;
6243+
end if;
6244+
then
6245+
success;
6246+
6247+
else false;
6248+
end match;
6249+
end transformPathedElementInClassDef;
6250+
6251+
61496252
annotation(__OpenModelica_Interface="frontend");
61506253
end SCodeUtil;

OMCompiler/Compiler/Script/CevalScriptBackend.mo

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2770,7 +2770,7 @@ algorithm
27702770
absynClass := InteractiveUtil.getPathedClassInProgram(classpath, p);
27712771
absynClass := InteractiveUtil.updateConnectionAnnotationInClass(absynClass, str1, str2, Absyn.ANNOTATION(annlst));
27722772
p := InteractiveUtil.updateProgram(Absyn.PROGRAM({absynClass}, if AbsynUtil.pathIsIdent(classpath) then Absyn.TOP() else Absyn.WITHIN(AbsynUtil.stripLast(classpath))), p);
2773-
SymbolTable.setAbsyn(p);
2773+
SymbolTable.setAbsynClass(p, absynClass, classpath);
27742774
then
27752775
Values.BOOL(true);
27762776

@@ -3141,7 +3141,6 @@ algorithm
31413141
Values.CODE(Absyn.C_MODIFICATION(modification = mod))})
31423142
algorithm
31433143
(p, b) := InteractiveUtil.setElementAnnotation(path, mod, SymbolTable.getAbsyn());
3144-
SymbolTable.setAbsyn(p);
31453144
then
31463145
Values.BOOL(b);
31473146

OMCompiler/Compiler/Script/InteractiveUtil.mo

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4727,10 +4727,36 @@ algorithm
47274727
end match;
47284728
end getPathedElementInElement;
47294729

4730+
public function transformPathedElementInList<T>
4731+
input list<T> inList;
4732+
input FuncType inFunc;
4733+
output list<T> outList = {};
4734+
output Option<Absyn.Element> outElement = NONE();
4735+
output Boolean outFound = false;
4736+
4737+
partial function FuncType
4738+
input output T t;
4739+
output Option<Absyn.Element> outElement;
4740+
output Boolean outFound;
4741+
end FuncType;
4742+
protected
4743+
T e;
4744+
list<T> rest = inList;
4745+
algorithm
4746+
while not listEmpty(rest) and not outFound loop
4747+
e :: rest := rest;
4748+
(e, outElement, outFound) := inFunc(e);
4749+
outList := e :: outList;
4750+
end while;
4751+
4752+
outList := List.append_reverse(outList, rest);
4753+
end transformPathedElementInList;
4754+
47304755
public function transformPathedElementInProgram
47314756
input Absyn.Path path;
47324757
input Func func;
47334758
input output Absyn.Program program;
4759+
output Option<Absyn.Element> element;
47344760
output Boolean success;
47354761

47364762
partial function Func
@@ -4745,6 +4771,7 @@ protected
47454771
input Absyn.Path path;
47464772
input Func func;
47474773
input output Absyn.Class cls;
4774+
output Option<Absyn.Element> outElement;
47484775
output Boolean found;
47494776
protected
47504777
Absyn.Element elem;
@@ -4759,16 +4786,18 @@ protected
47594786
elem := Absyn.Element.ELEMENT(false, NONE(), Absyn.InnerOuter.NOT_INNER_OUTER(),
47604787
Absyn.ElementSpec.CLASSDEF(false, cls), cls.info, NONE());
47614788
elem := func(elem);
4789+
outElement := SOME(elem);
47624790
Absyn.Element.ELEMENT(specification = Absyn.ElementSpec.CLASSDEF(class_ = cls)) := elem;
47634791
else
47644792
// The path points to an element inside the class.
4765-
(cls, found) := transformPathedElementInClass(AbsynUtil.pathRest(path), func, cls);
4793+
(cls, outElement, found) := transformPathedElementInClass(AbsynUtil.pathRest(path), func, cls);
47664794
end if;
4795+
else
4796+
outElement := NONE();
47674797
end if;
47684798
end transform_class;
47694799
algorithm
4770-
name := AbsynUtil.pathFirstIdent(path);
4771-
(clss, success) := List.findMap(program.classes, function transform_class(path = path, func = func));
4800+
(clss, element, success) := transformPathedElementInList(program.classes, function transform_class(path = path, func = func));
47724801

47734802
if success then
47744803
program.classes := clss;
@@ -4779,6 +4808,7 @@ protected function transformPathedElementInClass
47794808
input Absyn.Path path;
47804809
input Func func;
47814810
input output Absyn.Class cls;
4811+
output Option<Absyn.Element> element;
47824812
output Boolean success;
47834813

47844814
partial function Func
@@ -4787,7 +4817,7 @@ protected function transformPathedElementInClass
47874817
protected
47884818
Absyn.ClassDef def;
47894819
algorithm
4790-
(def, success) := transformPathedElementInClassDef(path, func, cls.body);
4820+
(def, element, success) := transformPathedElementInClassDef(path, func, cls.body);
47914821

47924822
if success then
47934823
cls.body := def;
@@ -4798,6 +4828,7 @@ protected function transformPathedElementInClassDef
47984828
input Absyn.Path path;
47994829
input Func func;
48004830
input output Absyn.ClassDef def;
4831+
output Option<Absyn.Element> element;
48014832
output Boolean success;
48024833

48034834
partial function Func
@@ -4809,7 +4840,7 @@ algorithm
48094840
success := match def
48104841
case Absyn.ClassDef.PARTS()
48114842
algorithm
4812-
(parts, success) := List.findMap(def.classParts,
4843+
(parts, element, success) := transformPathedElementInList(def.classParts,
48134844
function transformPathedElementInClassPart(path = path, func = func));
48144845

48154846
if success then
@@ -4820,7 +4851,7 @@ algorithm
48204851

48214852
case Absyn.ClassDef.CLASS_EXTENDS()
48224853
algorithm
4823-
(parts, success) := List.findMap(def.parts,
4854+
(parts, element, success) := transformPathedElementInList(def.parts,
48244855
function transformPathedElementInClassPart(path = path, func = func));
48254856

48264857
if success then
@@ -4837,6 +4868,7 @@ protected function transformPathedElementInClassPart
48374868
input Absyn.Path path;
48384869
input Func func;
48394870
input output Absyn.ClassPart part;
4871+
output Option<Absyn.Element> element;
48404872
output Boolean success;
48414873

48424874
partial function Func
@@ -4848,7 +4880,7 @@ algorithm
48484880
success := match part
48494881
case Absyn.ClassPart.PUBLIC()
48504882
algorithm
4851-
(items, success) := List.findMap(part.contents,
4883+
(items, element, success) := transformPathedElementInList(part.contents,
48524884
function transformPathedElementInElementItem(path = path, func = func));
48534885

48544886
if success then
@@ -4859,7 +4891,7 @@ algorithm
48594891

48604892
case Absyn.ClassPart.PROTECTED()
48614893
algorithm
4862-
(items, success) := List.findMap(part.contents,
4894+
(items, element, success) := transformPathedElementInList(part.contents,
48634895
function transformPathedElementInElementItem(path = path, func = func));
48644896

48654897
if success then
@@ -4876,6 +4908,7 @@ protected function transformPathedElementInElementItem
48764908
input Absyn.Path path;
48774909
input Func func;
48784910
input output Absyn.ElementItem item;
4911+
output Option<Absyn.Element> outElement;
48794912
output Boolean success;
48804913

48814914
partial function Func
@@ -4890,9 +4923,10 @@ algorithm
48904923
algorithm
48914924
if AbsynUtil.pathIsIdent(path) then
48924925
item.element := func(item.element);
4926+
outElement := SOME(item.element);
48934927
success := true;
48944928
else
4895-
(element, success) := transformPathedElementInElement(AbsynUtil.pathRest(path), func, item.element);
4929+
(element, outElement, success) := transformPathedElementInElement(AbsynUtil.pathRest(path), func, item.element);
48964930

48974931
if success then
48984932
item.element := element;
@@ -4909,6 +4943,7 @@ protected function transformPathedElementInElement
49094943
input Absyn.Path path;
49104944
input Func func;
49114945
input output Absyn.Element element;
4946+
output Option<Absyn.Element> outElement;
49124947
output Boolean success;
49134948

49144949
partial function Func
@@ -4920,7 +4955,7 @@ algorithm
49204955
success := match element
49214956
case Absyn.Element.ELEMENT()
49224957
algorithm
4923-
(spec, success) := transformPathedElementInElementSpec(path, func, element.specification);
4958+
(spec, outElement, success) := transformPathedElementInElementSpec(path, func, element.specification);
49244959

49254960
if success then
49264961
element.specification := spec;
@@ -4936,6 +4971,7 @@ protected function transformPathedElementInElementSpec
49364971
input Absyn.Path path;
49374972
input Func func;
49384973
input output Absyn.ElementSpec spec;
4974+
output Option<Absyn.Element> element;
49394975
output Boolean success;
49404976

49414977
partial function Func
@@ -4947,7 +4983,7 @@ algorithm
49474983
success := match spec
49484984
case Absyn.ElementSpec.CLASSDEF()
49494985
algorithm
4950-
(cls, success) := transformPathedElementInClass(path, func, spec.class_);
4986+
(cls, element, success) := transformPathedElementInClass(path, func, spec.class_);
49514987

49524988
if success then
49534989
spec.class_ := cls;
@@ -5019,6 +5055,7 @@ public function setElementAnnotation
50195055
protected
50205056
Option<Absyn.Annotation> ann;
50215057
String name;
5058+
Option<Absyn.Element> elem_opt;
50225059
algorithm
50235060
try
50245061
if listEmpty(annotationMod.elementArgLst) then
@@ -5028,8 +5065,12 @@ algorithm
50285065
end if;
50295066

50305067
name := AbsynUtil.pathLastIdent(elementPath);
5031-
(program, success) := transformPathedElementInProgram(elementPath,
5068+
(program, elem_opt, success) := transformPathedElementInProgram(elementPath,
50325069
function AbsynUtil.setElementAnnotation(name = name, inAnnotation = ann), program);
5070+
5071+
if success then
5072+
SymbolTable.setAbsynElement(program, Util.getOption(elem_opt), elementPath);
5073+
end if;
50335074
else
50345075
success := false;
50355076
end try;
@@ -5047,7 +5088,7 @@ algorithm
50475088
Absyn.Program.PROGRAM(classes = {Absyn.Class.CLASS(body = parsed_body)}) :=
50485089
Parser.parsestring(stringAppendList({"model dummy\n", content, "end dummy;\n"}));
50495090

5050-
(program, success) := transformPathedElementInProgram(classPath,
5091+
(program, _, success) := transformPathedElementInProgram(classPath,
50515092
function mergeClassContents(newContent = parsed_body), program);
50525093
else
50535094
success := false;

0 commit comments

Comments
 (0)