Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 49.9% 516 / 0 / 1034
Functions: -% 0 / 1 / 1
Branches: 44.5% 345 / 0 / 775

OMCompiler/Compiler/Script/InteractiveUtil.mo
Line Branch Exec Source
1 /*
2 * This file is part of OpenModelica.
3 *
4 * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC),
5 * c/o Linköpings universitet, Department of Computer and Information Science,
6 * SE-58183 Linköping, Sweden.
7 *
8 * All rights reserved.
9 *
10 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR
11 * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8.
12 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES
13 * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL
14 * VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
15 *
16 * The OpenModelica software and the OSMC (Open Source Modelica Consortium)
17 * Public License (OSMC-PL) are obtained from OSMC, either from the above
18 * address, from the URLs:
19 * http://www.openmodelica.org or
20 * https://github.com/OpenModelica/ or
21 * http://www.ida.liu.se/projects/OpenModelica,
22 * and in the OpenModelica distribution.
23 *
24 * GNU AGPL version 3 is obtained from:
25 * https://www.gnu.org/licenses/licenses.html#GPL
26 *
27 * This program is distributed WITHOUT ANY WARRANTY; without
28 * even the implied warranty of MERCHANTABILITY or FITNESS
29 * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
30 * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
31 *
32 * See the full OSMC Public License conditions for more details.
33 *
34 */
35
36 encapsulated package InteractiveUtil
37 " file: InteractiveUtil.mo
38 package: InteractiveUtil
39 description: This module contain functionality for model management,
40 expression evaluation, etc. in the interactive environment.
41
42 $Id: InteractiveUtil.mo 25580 2015-04-16 14:04:16Z jansilar $
43
44 This module contains utility functions for Interactive.mo"
45
46 //public imports
47 import Absyn;
48 import ProgramUtil;
49 import AbsynToSCode;
50 import AbsynUtil;
51 import ConnectionGraph;
52 import DAE;
53 import FCore;
54 import Interactive;
55 import Interactive.Access;
56 import SCode;
57 import Values;
58
59 // protected imports
60 protected
61
62 import Ceval;
63 import ClassInf;
64 import Config;
65 import DAE.Connect;
66 import DAEUtil;
67 import DoubleEnded;
68 import Dump;
69 import Error;
70 import ErrorExt;
71 import ExpressionBasics;
72 import ExpressionSimplify;
73 import FBuiltin;
74 import FGraph;
75 import Flags;
76 import FlagsUtil;
77 import InnerOuter;
78 import Inst;
79 import InstTypes;
80 import List;
81 import Lookup;
82 import Mod;
83 import NFApi;
84 import Parser;
85 import Print;
86 import SCodeUtil;
87 import StaticScript;
88 import StringUtil;
89 import SymbolTable;
90 import System;
91 import UnitAbsyn;
92 import UnorderedSet;
93 import UnorderedMap;
94 import Util;
95 import ValuesDump;
96
97 import MetaModelica.Dangerous;
98 import ClassInfUtil;
99
100 public
101 type GraphicEnvCache = Interactive.GraphicEnvCache;
102 type AnnotationType = Interactive.AnnotationType;
103
104 type Visibility = enumeration(PUBLIC, PROTECTED, ANY);
105
106 public function getExtendsElementspecInClass
107 "Retrieve all ElementSpec of a class that are EXTENDS."
108 input Absyn.Class inClass;
109 output list<Absyn.ElementSpec> outAbsynElementSpecLst;
110 algorithm
111 outAbsynElementSpecLst:=
112 match inClass
113 local
114 list<Absyn.ElementSpec> ext;
115 list<Absyn.ClassPart> parts;
116 list<Absyn.ElementArg> eltArg;
117 Absyn.Path tp;
118 /* a class with parts */
119 case Absyn.CLASS(body = Absyn.PARTS(classParts = parts))
120 algorithm
121 11449 ext := getExtendsElementspecInClassparts(parts);
122 then
123 ext;
124 /* adrpo: handle also model extends M end M; */
125 case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts))
126 algorithm
127 155 ext := getExtendsElementspecInClassparts(parts);
128 then
129 ext;
130 /* a derived class */
131 case Absyn.CLASS(body = Absyn.DERIVED(typeSpec=Absyn.TPATH(tp,_), arguments=eltArg))
132 815 then
133 {Absyn.EXTENDS(tp,eltArg,NONE())};
134 // Note: the array dimensions of DERIVED are lost. They must be
135 // queried by another api-function
136 else {};
137 end match;
138 end getExtendsElementspecInClass;
139
140 protected function getExtendsElementspecInClassparts
141 "Helper function to getExtendsElementspecInClass."
142 input list<Absyn.ClassPart> inAbsynClassPartLst;
143 output list<Absyn.ElementSpec> outAbsynElementSpecLst;
144 algorithm
145 outAbsynElementSpecLst:=
146 match inAbsynClassPartLst
147 local
148 list<Absyn.ElementSpec> lst1,lst2,res;
149 list<Absyn.ElementItem> elts;
150 list<Absyn.ClassPart> rest;
151
152 case {} then {};
153
154 case Absyn.PUBLIC(contents = elts) :: rest
155 algorithm
156 11768 lst1 := getExtendsElementspecInClassparts(rest);
157 11768 lst2 := getExtendsElementspecInElementitems(elts);
158 11768 res := listAppend(lst1, lst2);
159 then
160 res;
161
162 case Absyn.PROTECTED(contents = elts) :: rest
163 algorithm
164 1604 lst1 := getExtendsElementspecInClassparts(rest);
165 1604 lst2 := getExtendsElementspecInElementitems(elts);
166 1604 res := listAppend(lst1, lst2);
167 then
168 res;
169
170 case _ :: rest
171 algorithm
172 4790 res := getExtendsElementspecInClassparts(rest);
173 then
174 res;
175
176 end match;
177 end getExtendsElementspecInClassparts;
178
179 protected function getExtendsElementspecInElementitems
180 "Helper function to getExtendsElementspecInClassparts."
181 input list<Absyn.ElementItem> inAbsynElementItemLst;
182 output list<Absyn.ElementSpec> outAbsynElementSpecLst;
183 algorithm
184 outAbsynElementSpecLst:=
185 matchcontinue inAbsynElementItemLst
186 local
187 Absyn.Element el;
188 Absyn.ElementSpec elt;
189 list<Absyn.ElementSpec> res;
190 list<Absyn.ElementItem> rest;
191 case {} then {};
192 case Absyn.ELEMENTITEM(element = el) :: rest
193 algorithm
194 69094 elt := getExtendsElementspecInElement(el) "Bug in MetaModelica Compiler (MMC). If the two premisses below are in swapped order
195 the compiler enters infinite loop (but no stack overflow)" ;
196 6794 res := getExtendsElementspecInElementitems(rest);
197 then
198 (elt :: res);
199 case _ :: rest
200 algorithm
201 64500 res := getExtendsElementspecInElementitems(rest);
202 then
203 res;
204 end matchcontinue;
205 end getExtendsElementspecInElementitems;
206
207 protected function getExtendsElementspecInElement
208 "Helper function to getExtendsElementspecInElementitems."
209 input Absyn.Element inElement;
210 output Absyn.ElementSpec outElementSpec;
211 algorithm
212 outElementSpec:=
213 match inElement
214 local Absyn.ElementSpec ext;
215 case Absyn.ELEMENT(specification = (ext as Absyn.EXTENDS())) then ext;
216 end match;
217 end getExtendsElementspecInElement;
218
219 public function removeElementModifiers
220 "Removes all the modifiers of a component."
221 input Absyn.Path path;
222 input String inComponentName;
223 input Absyn.Program inProgram;
224 input Boolean keepRedeclares;
225 output Absyn.Program outProgram;
226 output Boolean outResult;
227 protected
228 Absyn.Within within_;
229 Absyn.Class cls;
230 algorithm
231 try
232 ✗ within_ := ProgramUtil.buildWithin(path);
233 ✗ cls := ProgramUtil.getPathedClassInProgram(path, inProgram);
234 ✗ cls := clearComponentModifiersInClass(cls, inComponentName, keepRedeclares);
235 ✗ outProgram := ProgramUtil.updateProgram(Absyn.PROGRAM({cls}, within_), inProgram);
236 outResult := true;
237 else
238 outProgram := inProgram;
239 outResult := false;
240 end try;
241 end removeElementModifiers;
242
243 public function clearComponentModifiersInClass
244 input Absyn.Class inClass;
245 input String inComponentName;
246 input Boolean keepRedeclares;
247 output Absyn.Class outClass = inClass;
248 algorithm
249
3/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
3 (outClass, true) := AbsynUtil.traverseClassComponents(inClass,
250 function clearComponentModifiersInCompitems(inComponentName =
251 inComponentName, keepRedeclares = keepRedeclares), false);
252 end clearComponentModifiersInClass;
253
254 protected function clearComponentModifiersInCompitems
255 "Helper function to clearComponentModifiersInClass. Clears the modifiers in a ComponentItem."
256 input list<Absyn.ComponentItem> inComponents;
257 input Boolean inFound;
258 input String inComponentName;
259 input Boolean keepRedeclares = false;
260 output list<Absyn.ComponentItem> outComponents = {};
261 output Boolean outFound;
262 output Boolean outContinue;
263 protected
264 Absyn.ComponentItem item;
265 list<Absyn.ComponentItem> rest_items = inComponents;
266 Absyn.Component comp;
267 algorithm
268 // Try to find the component we're looking for.
269
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 while not listEmpty(rest_items) loop
270 2 item :: rest_items := rest_items;
271
272
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
2 if AbsynUtil.componentName(item) == inComponentName then
273 // Found component, propagate the modifier to it.
274 () := match item
275 case Absyn.COMPONENTITEM(component = comp as Absyn.COMPONENT())
276 algorithm
277
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
2 comp.modification := if not keepRedeclares then NONE() else stripModifiersKeepRedeclares(comp.modification);
278 2 item.component := comp;
279 then
280 ();
281 end match;
282
283 // Reassemble the item list and return.
284 2 outComponents := List.append_reverse(outComponents, item :: rest_items);
285 outFound := true;
286 outContinue := false;
287 2 return;
288 end if;
289 outComponents := item :: outComponents;
290 end while;
291
292 // Component not found, continue looking.
293 outComponents := inComponents;
294 outFound := false;
295 outContinue := true;
296 end clearComponentModifiersInCompitems;
297
298 protected function stripModifiersKeepRedeclares
299 input Option<Absyn.Modification> inMod;
300 output Option<Absyn.Modification> outMod;
301 algorithm
302 outMod := match inMod
303 local
304 Absyn.Modification m;
305 list<Absyn.ElementArg> ea;
306 case NONE() then NONE();
307 case SOME(Absyn.CLASSMOD(ea, _))
308 algorithm
309
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
3 ea := list(e for e guard(match e case Absyn.REDECLARATION() then true; else false; end match) in ea);
310 1 m := Absyn.CLASSMOD(ea, Absyn.NOMOD());
311 then
312 SOME(m);
313 end match;
314 end stripModifiersKeepRedeclares;
315
316 public function setElementModifier
317 "Sets a submodifier of an element."
318 input Absyn.Path inClass;
319 input Absyn.Path inElementName;
320 input Absyn.Modification inMod;
321 input output Absyn.Program program;
322 output Boolean outResult;
323 protected
324 Absyn.Within within_;
325 Absyn.Class cls;
326 algorithm
327 try
328 48 cls := ProgramUtil.getPathedClassInProgram(inClass, program);
329 47 (cls, outResult) := setElementSubmodifierInClass(cls, inElementName, inMod);
330 47 within_ := ProgramUtil.buildWithin(inClass);
331 47 program := ProgramUtil.updateProgram(Absyn.PROGRAM({cls}, within_), program);
332 else
333 1 outResult := false;
334 end try;
335 end setElementModifier;
336
337 public function setExtendsModifier
338 "Sets a submodifier on an extends clause in a class."
339 input Absyn.Path className;
340 input Absyn.Path extendsName;
341 input Absyn.Path elementName;
342 input Absyn.Modification mod;
343 input output Absyn.Program program;
344 output Boolean result;
345 protected
346 Absyn.Within within_;
347 Absyn.Class cls;
348 GraphicEnvCache env;
349 algorithm
350 try
351 10 cls := ProgramUtil.getPathedClassInProgram(className, program);
352 10 env := Interactive.getClassEnv(program, className);
353 10 (cls, result) := setExtendsSubmodifierInClass(cls, extendsName, elementName, mod, env);
354 10 within_ := ProgramUtil.buildWithin(className);
355 10 program := ProgramUtil.updateProgram(Absyn.PROGRAM({cls}, within_), program);
356 else
357 ✗ result := false;
358 end try;
359 end setExtendsModifier;
360
361 protected function setElementSubmodifierInClass
362 " Sets a sub modifier on a component in a class.
363 inputs: (Absyn.Class,
364 Absyn.Ident, /* component name */
365 Absyn.ComponentRef, /* subvariable path */
366 Absyn.Modification)
367 outputs: Absyn.Class"
368 input Absyn.Class inClass;
369 input Absyn.Path inElementName;
370 input Absyn.Modification inMod;
371 output Absyn.Class outClass = inClass;
372 output Boolean found;
373 algorithm
374
1/2
✓ Branch 3 taken 47 times.
✗ Branch 4 not taken.
47 (outClass, found) := AbsynUtil.traverseClassElements(inClass,
375 function setSubmodifierInElement(elementName = inElementName, mod = inMod), false);
376 end setElementSubmodifierInClass;
377
378 protected function setExtendsSubmodifierInClass
379 "Helper function to setExtendsSubmodifierValue."
380 input output Absyn.Class cls;
381 input Absyn.Path extendsPath;
382 input Absyn.Path elementName;
383 input Absyn.Modification mod;
384 input GraphicEnvCache env;
385 output Boolean found;
386 algorithm
387
1/2
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
10 (cls, found) := AbsynUtil.traverseClassElements(cls,
388 function setExtendsSubmodifierInElement(extendsPath = extendsPath,
389 elementName = elementName, mod = mod, env = env), false);
390 end setExtendsSubmodifierInClass;
391
392 protected function setSubmodifierInElement
393 "Helper function to setElementSubmodifierInClass.
394 Sets the modifier in an Element."
395 input output Absyn.Element element;
396 input output Boolean found;
397 input Absyn.Path elementName;
398 input Absyn.Modification mod;
399 output Boolean outContinue = true;
400 algorithm
401
2/2
✓ Branch 2 taken 45 times.
✓ Branch 3 taken 38 times.
83 if AbsynUtil.isElementNamed(AbsynUtil.pathFirstIdent(elementName), element) then
402 try
403 () := match element
404 case Absyn.ELEMENT()
405 algorithm
406 45 element.specification := setSubmodifierInElementSpec(elementName, mod, element.specification);
407 then ();
408 end match;
409 found := true;
410 outContinue := false;
411 else
412 end try;
413 end if;
414 end setSubmodifierInElement;
415
416 protected function setExtendsSubmodifierInElement
417 "Helper function to setExtendsSubmodifierValue."
418 input output Absyn.Element element;
419 input Absyn.Path extendsPath;
420 input Absyn.Path elementName;
421 input Absyn.Modification mod;
422 input GraphicEnvCache env;
423 input output Boolean found;
424 output Boolean outContinue = true;
425 protected
426 Absyn.ElementSpec ext_spec;
427 Absyn.Path full_path;
428 list<Absyn.ElementArg> eargs;
429 Option<Absyn.Modification> opt_mod;
430 algorithm
431 found := matchcontinue element
432 case Absyn.ELEMENT(specification = ext_spec as Absyn.EXTENDS(elementArg = eargs))
433 algorithm
434 10 (_, full_path) := Interactive.mkFullyQual(env, ext_spec.path);
435
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 true := AbsynUtil.pathEqual(extendsPath, full_path);
436
437
3/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 time.
✓ Branch 6 taken 9 times.
10 if AbsynUtil.pathFirstIdent(elementName) == "_" then
438 // If the element name is _, then apply the modifier directly to the
439 // extends clause instead of to a specific element.
440 2 opt_mod := propagateMod(elementName, mod, SOME(Absyn.CLASSMOD(eargs, Absyn.NOMOD())));
441 else
442 18 opt_mod := propagateMod(AbsynUtil.prefixPath("dummy", elementName),
443 mod, SOME(Absyn.CLASSMOD(eargs, Absyn.NOMOD())));
444 end if;
445
446 ext_spec.elementArg := match opt_mod
447 case SOME(Absyn.Modification.CLASSMOD(elementArgLst = eargs)) then eargs;
448 else {};
449 end match;
450
451 10 element.specification := ext_spec;
452 then
453 true;
454
455 else false;
456 end matchcontinue;
457
458
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 outContinue := not found;
459 end setExtendsSubmodifierInElement;
460
461 function setSubmodifierInElementSpec
462 input Absyn.Path elementName;
463 input Absyn.Modification mod;
464 input output Absyn.ElementSpec elSpec;
465 algorithm
466 () := match elSpec
467 case Absyn.CLASSDEF()
468 algorithm
469 ✗ elSpec.class_ := setSubmodifierInClass(elementName, elSpec.class_, mod);
470 then
471 ();
472
473 case Absyn.COMPONENTS()
474 algorithm
475 46 elSpec.components := setComponentSubmodifierInCompitems(elSpec.components, false, elementName, mod);
476 then
477 ();
478 end match;
479 end setSubmodifierInElementSpec;
480
481 function setSubmodifierInClass
482 input Absyn.Path inElementName;
483 input Absyn.Class inClass;
484 input Absyn.Modification inMod;
485 output Absyn.Class outClass;
486 protected
487 Absyn.Class cls = inClass;
488 Absyn.Modification mod;
489 Absyn.ClassDef body;
490 algorithm
491 outClass := match cls
492 case Absyn.CLASS()
493 algorithm
494 ✗ body := cls.body;
495 body := match body
496 case Absyn.DERIVED()
497 algorithm
498 ✗ SOME(mod) := propagateMod(inElementName, inMod, SOME(Absyn.CLASSMOD(body.arguments, Absyn.NOMOD())));
499 ✗ body.arguments := match mod case Absyn.CLASSMOD() then mod.elementArgLst; end match;
500 then body;
501 end match;
502 ✗ cls.body := body;
503 then
504 cls;
505 end match;
506 end setSubmodifierInClass;
507
508 public function setComponentSubmodifierInCompitems
509 "Helper function to setComponentSubmodifierInClass. Sets the modifier in a
510 ComponentItem."
511 input list<Absyn.ComponentItem> inComponents;
512 input Boolean inFound;
513 input Absyn.Path inComponentName;
514 input Absyn.Modification inMod;
515 output list<Absyn.ComponentItem> outComponents = {};
516 output Boolean outFound;
517 output Boolean outContinue;
518 protected
519 Absyn.ComponentItem item;
520 list<Absyn.ComponentItem> rest_items = inComponents;
521 Absyn.Component comp;
522 String comp_id;
523 algorithm
524 46 comp_id := AbsynUtil.pathFirstIdent(inComponentName);
525
526 // Try to find the component we're looking for.
527
1/2
✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
47 while not listEmpty(rest_items) loop
528 47 item :: rest_items := rest_items;
529
530
3/4
✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 46 times.
✓ Branch 6 taken 1 time.
47 if AbsynUtil.componentName(item) == comp_id then
531 // Found component, propagate the modifier to it.
532 () := match item
533 case Absyn.COMPONENTITEM(component = comp as Absyn.COMPONENT())
534 algorithm
535 46 comp.modification := propagateMod(inComponentName, inMod, comp.modification);
536 46 item.component := comp;
537 then
538 ();
539 end match;
540
541 // Reassemble the item list and return.
542 46 outComponents := List.append_reverse(outComponents, item :: rest_items);
543 outFound := true;
544 outContinue := false;
545 46 return;
546 end if;
547 outComponents := item :: outComponents;
548 end while;
549
550 // Component not found, continue looking.
551 outComponents := inComponents;
552 outFound := false;
553 outContinue := true;
554 end setComponentSubmodifierInCompitems;
555
556 public function propagateMod
557 input Absyn.Path inComponentName;
558 input Absyn.Modification inNewMod;
559 input Option<Absyn.Modification> inOldMod;
560 output Option<Absyn.Modification> outMod;
561 protected
562 list<Absyn.ElementArg> new_args, old_args;
563 Absyn.EqMod new_eqmod, old_eqmod;
564 Absyn.Modification mod;
565 algorithm
566
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 88 times.
✓ Branch 2 taken 75 times.
✓ Branch 3 taken 13 times.
88 if isSome(inOldMod) then
567 75 SOME(Absyn.CLASSMOD(elementArgLst = old_args, eqMod = old_eqmod)) := inOldMod;
568 else
569 old_args := {};
570 old_eqmod := Absyn.NOMOD();
571 end if;
572
573
2/2
✓ Branch 1 taken 45 times.
✓ Branch 2 taken 43 times.
88 if AbsynUtil.pathIsIdent(inComponentName) then
574 45 Absyn.CLASSMOD(elementArgLst = new_args, eqMod = new_eqmod) := inNewMod;
575
576 // If we have no eqmod but a list of submods, keep the old eqmod.
577
4/4
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 22 times.
✓ Branch 3 taken 11 times.
✓ Branch 4 taken 12 times.
45 if valueEq(new_eqmod, Absyn.NOMOD()) and not listEmpty(new_args) then
578 new_eqmod := old_eqmod;
579 end if;
580
581 // Merge submodifiers if the new mod isn't empty, otherwise clear them.
582
2/2
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 12 times.
45 if not AbsynUtil.isEmptyMod(inNewMod) then
583 33 new_args := mergeElementArgs(old_args, new_args);
584 end if;
585
586 45 mod := Absyn.CLASSMOD(new_args, new_eqmod);
587 else
588 43 new_args := propagateMod2(inComponentName, old_args, inNewMod);
589 43 mod := Absyn.CLASSMOD(new_args, old_eqmod);
590 end if;
591
592
2/2
✓ Branch 1 taken 71 times.
✓ Branch 2 taken 17 times.
88 outMod := if AbsynUtil.isEmptyMod(mod) then NONE() else SOME(mod);
593 end propagateMod;
594
595 protected function mergeElementArgs
596 input list<Absyn.ElementArg> inOldArgs;
597 input list<Absyn.ElementArg> inNewArgs;
598 output list<Absyn.ElementArg> outArgs = inOldArgs;
599 protected
600 Boolean found;
601 algorithm
602
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 11 times.
33 if listEmpty(inOldArgs) then
603 22 outArgs := removeEmptySubMods(inNewArgs);
604 elseif listEmpty(inNewArgs) then
605 outArgs := inOldArgs;
606 else
607
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 10 times.
22 for narg in inNewArgs loop
608 12 (outArgs, found) := List.replaceOnTrue(narg, outArgs,
609 function AbsynUtil.elementArgEqualName(inArg2 = narg));
610
611
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 9 times.
12 if not found then
612 3 outArgs := List.appendElt(narg, outArgs);
613 end if;
614 end for;
615
616 10 outArgs := removeEmptySubMods(outArgs);
617 end if;
618 end mergeElementArgs;
619
620 function removeEmptySubMods
621 input list<Absyn.ElementArg> subMods;
622 output list<Absyn.ElementArg> outSubMods = {};
623 protected
624 Absyn.Modification mod;
625 algorithm
626
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 53 times.
83 for m in subMods loop
627 () := match m
628 case Absyn.ElementArg.MODIFICATION(modification = SOME(mod))
629 algorithm
630 21 mod.elementArgLst := removeEmptySubMods(mod.elementArgLst);
631
2/2
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 1 time.
41 m.modification := if AbsynUtil.isEmptyMod(mod) then NONE() else SOME(mod);
632 then
633 ();
634
635 else ();
636 end match;
637
638
2/2
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 3 times.
30 if not AbsynUtil.isEmptySubMod(m) then
639 outSubMods := m :: outSubMods;
640 end if;
641 end for;
642
643 53 outSubMods := Dangerous.listReverseInPlace(outSubMods);
644 end removeEmptySubMods;
645
646 protected function propagateMod2
647 input Absyn.Path inComponentName;
648 input list<Absyn.ElementArg> inSubMods;
649 input Absyn.Modification inNewMod;
650 output list<Absyn.ElementArg> outSubMods = {};
651 protected
652 Absyn.ElementArg submod;
653 list<Absyn.ElementArg> rest_submods = inSubMods;
654 Absyn.Path comp_name, comp_rest;
655 algorithm
656 // Search through the submods to see if one matches the component name.
657
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 10 times.
57 while not listEmpty(rest_submods) loop
658 47 submod :: rest_submods := rest_submods;
659 47 comp_name := AbsynUtil.pathRest(inComponentName);
660 comp_rest := comp_name;
661
662 // Try to find the submod whose path matches the best. If we have a
663 // component name a.b.c, then first check a.b.c, then a.b, then a.
664 12 while true loop
665
2/2
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 26 times.
59 if AbsynUtil.pathEqual(comp_name, AbsynUtil.elementArgName(submod)) then
666 // Found matching submod, propagate the modifier to it.
667 () := match submod
668 case Absyn.MODIFICATION()
669 algorithm
670
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 28 times.
32 if not AbsynUtil.pathIsIdent(comp_name) then
671 4 comp_name := AbsynUtil.pathPrefix(comp_name);
672 4 comp_rest := AbsynUtil.removePrefix(comp_name, comp_rest);
673 end if;
674
675 32 submod.modification := propagateMod(comp_rest, inNewMod, submod.modification);
676
677
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 22 times.
✓ Branch 3 taken 10 times.
32 if isSome(submod.modification) then
678 rest_submods := submod :: rest_submods;
679 end if;
680 then
681 ();
682
683 case Absyn.REDECLARATION()
684 algorithm
685 1 submod.elementSpec := setSubmodifierInElementSpec(comp_rest, inNewMod, submod.elementSpec);
686 rest_submods := submod :: rest_submods;
687 then
688 ();
689
690 else ();
691 end match;
692
693 33 outSubMods := List.append_reverse(outSubMods, rest_submods);
694 33 return;
695 end if;
696
697
2/2
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 14 times.
26 if AbsynUtil.pathIsIdent(comp_name) then
698 // Nothing left of the path, break and continue with next submod.
699 break;
700 else
701 // Remove the last part of the component name and see if that matches
702 // instead.
703 12 comp_name := AbsynUtil.pathPrefix(comp_name);
704 end if;
705 end while;
706
707 outSubMods := submod :: outSubMods;
708 end while;
709
710
2/2
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 1 time.
10 if not AbsynUtil.isEmptyMod(inNewMod) then
711 // No matching submod was found, create a new submod and insert it into the list.
712 9 submod := createNestedSubMod(AbsynUtil.pathRest(inComponentName), inNewMod);
713 9 outSubMods := listReverse(submod :: outSubMods);
714 else
715 outSubMods := inSubMods;
716 end if;
717 end propagateMod2;
718
719 protected function createNestedSubMod
720 input Absyn.Path inComponentName;
721 input Absyn.Modification inMod;
722 output Absyn.ElementArg outSubMod;
723 algorithm
724
2/2
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 1 time.
10 if AbsynUtil.pathIsIdent(inComponentName) then
725 9 outSubMod := Absyn.MODIFICATION(false, Absyn.NON_EACH(), inComponentName,
726 SOME(inMod), NONE(), Absyn.dummyInfo);
727 else
728 1 outSubMod := createNestedSubMod(AbsynUtil.pathRest(inComponentName), inMod);
729 2 outSubMod := Absyn.MODIFICATION(false, Absyn.NON_EACH(),
730 AbsynUtil.pathFirstPath(inComponentName),
731 SOME(Absyn.CLASSMOD({outSubMod}, Absyn.NOMOD())), NONE(),
732 Absyn.dummyInfo);
733 end if;
734 end createNestedSubMod;
735
736 public function getElementModifierValue
737 input Absyn.ComponentRef classRef;
738 input Absyn.ComponentRef varRef;
739 input Absyn.ComponentRef subModRef;
740 input Absyn.Program program;
741 output String valueStr;
742 protected
743 Absyn.Path cls_path;
744 String name, elName;
745 Absyn.Class cls;
746 list<Absyn.ElementArg> args = {};
747 list<Absyn.Element> elems;
748 Boolean found = false;
749 list<Absyn.ComponentItem> components;
750 Option<Absyn.Modification> optMod;
751 algorithm
752 try
753 ✗ cls_path := AbsynUtil.crefToPath(classRef);
754 ✗ elName := AbsynUtil.crefIdent(varRef);
755 ✗ cls := ProgramUtil.getPathedClassInProgram(cls_path, program);
756 ✗ elems := getElementsInClass(cls);
757 ✗ for e in elems loop
758 args := match e
759 case Absyn.ELEMENT(specification=Absyn.CLASSDEF(class_ = Absyn.CLASS(name = name, body = Absyn.DERIVED(arguments = args)))) guard stringEq(name, elName)
760 algorithm
761 found := true;
762 then
763 args;
764 case Absyn.ELEMENT(specification=Absyn.COMPONENTS(components = components))
765 algorithm
766 ✗ for c in components loop
767 ✗ Absyn.COMPONENTITEM(Absyn.COMPONENT(name = name, modification = optMod)) := c;
768 ✗ if stringEq(name, elName) then
769 ✗ Absyn.CLASSMOD(elementArgLst = args) := Util.getOptionOrDefault(optMod, Absyn.CLASSMOD({}, Absyn.NOMOD()));
770 found := true;
771 end if;
772 end for;
773 ✗ then
774 args;
775 else {};
776 end match;
777 ✗ if found then
778 break;
779 end if;
780 end for;
781 ✗ if found then
782 ✗ valueStr := getModificationValueStr(args, AbsynUtil.crefToPath(subModRef));
783 else
784 valueStr := "";
785 end if;
786 else
787 valueStr := "";
788 end try;
789 end getElementModifierValue;
790
791 public function getModificationValueStr
792 "Looks up a modifier in a list of element args and returns its binding
793 expression, or fails if no modifier is found."
794 input list<Absyn.ElementArg> args;
795 input Absyn.Path path;
796 output String value = "";
797 protected
798 String name;
799 list<Absyn.ElementArg> rest_args = args;
800 Absyn.ElementArg arg;
801 Boolean found = false;
802 Absyn.ElementSpec elSpec;
803 Absyn.Exp exp;
804 algorithm
805 ✗ while not found loop
806 ✗ arg :: rest_args := rest_args;
807
808 found := match arg
809 case Absyn.MODIFICATION() guard AbsynUtil.pathEqual(arg.path, path)
810 algorithm
811 ✗ SOME(Absyn.CLASSMOD(eqMod = Absyn.EQMOD(exp = exp))) := arg.modification;
812 ✗ value := Dump.printExpStr(exp);
813 then
814 true;
815
816 case Absyn.MODIFICATION(path = Absyn.IDENT(name = name))
817 guard name == AbsynUtil.pathFirstIdent(path)
818 algorithm
819 ✗ SOME(Absyn.CLASSMOD(elementArgLst = rest_args)) := arg.modification;
820 ✗ value := getModificationValueStr(rest_args, AbsynUtil.pathRest(path));
821 then
822 true;
823
824 case Absyn.REDECLARATION(elementSpec = elSpec)
825 guard AbsynUtil.pathFirstIdent(path) == AbsynUtil.elementSpecName(elSpec)
826 algorithm
827 ✗ value := System.escapedString(Dump.unparseElementArgStr(arg), false);
828 then
829 true;
830
831 else false;
832 end match;
833 end while;
834 end getModificationValueStr;
835
836 public function getElementModifierValues
837 input Absyn.ComponentRef inComponentRef1;
838 input Absyn.ComponentRef inComponentRef2;
839 input Absyn.ComponentRef inComponentRef3;
840 input Absyn.Program inProgram4;
841 output String outString;
842 algorithm
843 outString := matchcontinue (inComponentRef1,inComponentRef2,inComponentRef3,inProgram4)
844 local
845 Absyn.Path p_class;
846 String name,res;
847 Absyn.Class cdef;
848 list<Absyn.Element> elems;
849 list<list<Absyn.ComponentItem>> compelts;
850 list<Absyn.ComponentItem> compelts_1;
851 Absyn.Modification mod;
852 Absyn.ComponentRef class_,ident,subident;
853 Absyn.Program p;
854 list<Absyn.ElementArg> elementArgLst;
855
856 case (class_,ident,subident,p)
857 algorithm
858 ✗ p_class := AbsynUtil.crefToPath(class_);
859 ✗ Absyn.IDENT(name) := AbsynUtil.crefToPath(ident);
860 ✗ cdef := ProgramUtil.getPathedClassInProgram(p_class, p);
861 ✗ elems := getElementsInClass(cdef);
862 ✗ compelts := List.map(elems, getComponentitemsInElement);
863 ✗ compelts_1 := List.flatten(compelts);
864 ✗ {Absyn.COMPONENTITEM(component=Absyn.COMPONENT(modification=SOME(Absyn.CLASSMOD(elementArgLst=elementArgLst))))} := List.select1(compelts_1, componentitemNamed, name);
865 ✗ mod := getModificationValues(elementArgLst, AbsynUtil.crefToPath(subident));
866 ✗ res := unparseMods(mod);
867 then
868 res;
869 else "Error";
870 end matchcontinue;
871 end getElementModifierValues;
872
873 public function unparseMods
874 input Absyn.Modification mod;
875 output String s;
876 protected
877 Absyn.ElementArg arg;
878 algorithm
879 s := match mod
880 case Absyn.CLASSMOD(elementArgLst = (arg as Absyn.REDECLARATION())::_)
881 ✗ then System.escapedString(Dump.unparseElementArgStr(arg), false);
882 else
883 ✗ then Dump.unparseModificationStr(mod);
884 end match;
885 end unparseMods;
886
887 protected function getModificationValues
888 "Helper function to getComponentModifierValues
889 Investigates modifications to find submodifier."
890 input list<Absyn.ElementArg> inAbsynElementArgLst;
891 input Absyn.Path inPath;
892 output Absyn.Modification outModification;
893 algorithm
894 outModification:=
895 match (inAbsynElementArgLst,inPath)
896 local
897 Absyn.Path p1,p2;
898 Absyn.Modification mod,res;
899 list<Absyn.ElementArg> rest,args;
900 String name1,name2;
901 Absyn.ElementSpec elSpec;
902 Absyn.ElementArg elArg;
903 case ((Absyn.MODIFICATION(path = p1,modification = SOME(mod)) :: _),p2) guard AbsynUtil.pathEqual(p1, p2)
904 then
905 mod;
906 case ((Absyn.MODIFICATION(path = Absyn.IDENT(name = name1),modification = SOME(Absyn.CLASSMOD(elementArgLst=args))) :: _),Absyn.QUALIFIED(name = name2,path = p2))
907 guard stringEq(name1, name2)
908 algorithm
909 ✗ res := getModificationValues(args, p2);
910 then
911 res;
912 case ((elArg as Absyn.REDECLARATION(elementSpec = elSpec)) :: _, p1) guard AbsynUtil.pathFirstIdent(p1) == AbsynUtil.elementSpecName(elSpec)
913 ✗ then
914 Absyn.CLASSMOD({elArg}, Absyn.NOMOD());
915 case ((_ :: rest),_)
916 algorithm
917 ✗ mod := getModificationValues(rest, inPath);
918 then
919 mod;
920 end match;
921 end getModificationValues;
922
923 public function getElementModifierNames
924 "Return the modifiernames of an element"
925 input Absyn.Path path;
926 input String inElementName;
927 input Absyn.Program inProgram3;
928 output list<String> outList;
929 algorithm
930 outList:=
931 matchcontinue inProgram3
932 local
933 Absyn.Class cdef;
934 list<Absyn.Element> elems;
935 list<String> res;
936 String name;
937 Absyn.Program p;
938 list<Absyn.ElementArg> mod = {}, args = {};
939 list<Absyn.ComponentItem> components;
940 Boolean found = false;
941 Option<Absyn.Modification> optMod;
942 case p
943 algorithm
944 ✗ cdef := ProgramUtil.getPathedClassInProgram(path, p);
945 ✗ elems := getElementsInClass(cdef);
946 ✗ for e in elems loop
947 mod := match e
948 case Absyn.ELEMENT(specification=Absyn.CLASSDEF(class_ = Absyn.CLASS(name = name, body = Absyn.DERIVED(arguments = args)))) guard stringEq(name, inElementName)
949 algorithm
950 found := true;
951 then
952 args;
953 case Absyn.ELEMENT(specification=Absyn.COMPONENTS(components = components))
954 algorithm
955 ✗ for c in components loop
956 ✗ Absyn.COMPONENTITEM(Absyn.COMPONENT(name = name, modification = optMod)) := c;
957 ✗ if stringEq(name, inElementName) then
958 ✗ Absyn.CLASSMOD(elementArgLst = mod) := Util.getOptionOrDefault(optMod, Absyn.CLASSMOD({}, Absyn.NOMOD()));
959 found := true;
960 end if;
961 end for;
962 ✗ then
963 mod;
964 else {};
965 end match;
966 ✗ if found then
967 break;
968 end if;
969 end for;
970 ✗ res := getModificationNames(mod, includeRedeclares = true);
971 then
972 res;
973 else {};
974 end matchcontinue;
975 end getElementModifierNames;
976
977 function getExtendsModifierNames
978 "Return the modifier names of a modification on an extends clause.
979 For instance,
980 model test extends A(p1=3,p2(z=3));end test;
981 getExtendsModifierNames(test,A) => {p1,p2.z}
982 "
983 input Absyn.Path classPath;
984 input Absyn.Path extendsPath;
985 input Boolean useQuotes;
986 input Absyn.Program program;
987 output Values.Value result;
988 protected
989 list<Absyn.ElementArg> extmod;
990 list<String> res;
991 Boolean silent = not Flags.isSet(Flags.NF_API_NOISE);
992 algorithm
993
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 if silent then
994 11 ErrorExt.setCheckpoint(getInstanceName());
995 end if;
996
997 try
998
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 11 times.
11 SOME(Absyn.EXTENDS(elementArg = extmod)) :=
999 getPathedExtendsInProgram(classPath, extendsPath, program);
1000 11 res := getModificationNames(extmod, includeRedeclares = true);
1001
1002
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
11 if useQuotes then
1003 2 res := Interactive.insertQuotesToList(res);
1004 end if;
1005
1006
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 11 times.
27 result := ValuesMake.makeArray(list(ValuesMake.makeCodeTypeName(AbsynUtil.makeIdentPathFromString(s)) for s in res));
1007 else
1008 ✗ result := ValuesMake.makeString("Error");
1009 end try;
1010
1011
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 if silent then
1012 11 ErrorExt.rollBack(getInstanceName());
1013 end if;
1014 end getExtendsModifierNames;
1015
1016 protected function getModificationNames
1017 "Helper function to getElementModifierNames"
1018 input list<Absyn.ElementArg> inAbsynElementArgLst;
1019 input Boolean includeRedeclares = false;
1020 output list<String> outStringLst;
1021 algorithm
1022 outStringLst:=
1023 matchcontinue inAbsynElementArgLst
1024 local
1025 list<String> names,names2,res;
1026 String name;
1027 list<Absyn.ElementArg> rest,args;
1028 Absyn.ElementSpec elSpec;
1029 Absyn.Path p;
1030
1031 case {} then {};
1032
1033 case Absyn.MODIFICATION(path = Absyn.IDENT(name = name),modification = NONE()) :: rest
1034 algorithm
1035 ✗ names := getModificationNames(rest, includeRedeclares);
1036 then
1037 name :: names;
1038
1039 case Absyn.MODIFICATION(path = p,modification = SOME(Absyn.CLASSMOD({},_))) :: rest
1040 algorithm
1041 11 name := AbsynUtil.pathString(p);
1042 11 names := getModificationNames(rest, includeRedeclares);
1043 then
1044 name :: names;
1045
1046 // modifier with submodifiers -and- binding, e.g. m(...)=2, add also m to list
1047 case Absyn.MODIFICATION(path = p,modification = SOME(Absyn.CLASSMOD(args,Absyn.EQMOD()))) :: rest
1048 algorithm
1049 1 name := AbsynUtil.pathString(p);
1050
4/4
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 1 time.
3 names2 := list(stringAppend(stringAppend(name, "."), n) for n in getModificationNames(args, includeRedeclares));
1051 1 names := getModificationNames(rest, includeRedeclares);
1052 1 res := listAppend(names2, names);
1053 then
1054 name :: res;
1055
1056 // modifier with submodifiers, e.g. m(...)
1057 case Absyn.MODIFICATION(path = p,modification = SOME(Absyn.CLASSMOD(args,_))) :: rest
1058 algorithm
1059 3 name := AbsynUtil.pathString(p);
1060
4/4
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 3 times.
6 names2 := list(stringAppend(stringAppend(name, "."), n) for n in getModificationNames(args, includeRedeclares));
1061 3 names := getModificationNames(rest, includeRedeclares);
1062 3 res := listAppend(names2, names);
1063 then
1064 res;
1065
1066 case Absyn.REDECLARATION(elementSpec = elSpec) :: rest guard includeRedeclares
1067 algorithm
1068 4 name := AbsynUtil.elementSpecName(elSpec);
1069 4 names := getModificationNames(rest, includeRedeclares);
1070 then
1071 name :: names;
1072
1073 case _ :: rest
1074 algorithm
1075 ✗ names := getModificationNames(rest, includeRedeclares);
1076 then
1077 names;
1078
1079 end matchcontinue;
1080 end getModificationNames;
1081
1082 public function getElementBinding
1083 " Returns the value of a component in a class.
1084 For example, the component
1085 Real x=1;
1086 returns 1.
1087 This can be used for both parameters, constants and variables."
1088 input Absyn.Path path;
1089 input String parameterName;
1090 input Absyn.Program program;
1091 output String bindingStr;
1092 protected
1093 Absyn.Class cls;
1094 Absyn.ComponentItem component;
1095 algorithm
1096 try
1097 ✗ cls := ProgramUtil.getPathedClassInProgram(path, program);
1098 ✗ component := getComponentInClass(cls, parameterName);
1099 ✗ bindingStr := Dump.printExpStr(getVariableBindingInComponentitem(component));
1100 else
1101 bindingStr := "";
1102 end try;
1103 end getElementBinding;
1104
1105 public function getComponentInClass
1106 "Returns the component with the given name in the given class, or fails if no
1107 such component exists."
1108 input Absyn.Class cls;
1109 input Absyn.Ident componentName;
1110 output Absyn.ComponentItem component;
1111 protected
1112 Absyn.ClassDef body;
1113 list<Absyn.ClassPart> parts;
1114 list<Absyn.ElementItem> elements;
1115 list<Absyn.ComponentItem> components;
1116 algorithm
1117 30 Absyn.CLASS(body = body) := cls;
1118
1119 parts := match body
1120 30 case Absyn.PARTS() then body.classParts;
1121 ✗ case Absyn.CLASS_EXTENDS() then body.parts;
1122 end match;
1123
1124
3/5
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 30 times.
✓ Branch 4 taken 1 time.
31 for part in parts loop
1125 elements := match part
1126 30 case Absyn.PUBLIC() then part.contents;
1127 ✗ case Absyn.PROTECTED() then part.contents;
1128 else {};
1129 end match;
1130
1131
2/2
✓ Branch 0 taken 107 times.
✓ Branch 1 taken 1 time.
108 for e in elements loop
1132 components := match e
1133 case Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification =
1134 Absyn.COMPONENTS(components = components))) then components;
1135 else {};
1136 end match;
1137
1138
2/2
✓ Branch 0 taken 92 times.
✓ Branch 1 taken 78 times.
170 for c in components loop
1139
4/4
✓ Branch 1 taken 89 times.
✓ Branch 2 taken 3 times.
✓ Branch 5 taken 29 times.
✓ Branch 6 taken 60 times.
92 if AbsynUtil.componentName(c) == componentName then
1140 component := c;
1141 29 return;
1142 end if;
1143 end for;
1144 end for;
1145
1146 end for;
1147
1148 1 fail();
1149 end getComponentInClass;
1150
1151 public function getNthComponentInClass
1152 "Returns the n:th component in a class."
1153 input Absyn.Class inClass;
1154 input Integer nth;
1155 output Absyn.Element outElement;
1156 protected
1157 list<Absyn.Element> pub, pro;
1158 Integer n;
1159 algorithm
1160 5 pub := getPublicComponentsInClass(inClass);
1161 5 n := listLength(pub);
1162
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if nth <= n then
1163 5 outElement := listGet(pub, nth);
1164 else
1165 // !TODO, check access annotation
1166 ✗ pro := getProtectedComponentsInClass(inClass);
1167 ✗ outElement := listGet(pro, nth-n);
1168 end if;
1169 end getNthComponentInClass;
1170
1171 public function getComponentsInClass
1172 " Both public and protected lists are searched."
1173 input Absyn.Class inClass;
1174 input Visibility visibility = Visibility.ANY;
1175 output list<Absyn.Element> outAbsynElementLst;
1176 algorithm
1177 outAbsynElementLst:=
1178 match inClass
1179 local
1180 list<Absyn.Element> lst1,res;
1181 list<Absyn.ClassPart> lst;
1182
1183 case Absyn.CLASS(body = Absyn.PARTS(classParts = {})) then {};
1184 case Absyn.CLASS(body = Absyn.PARTS(classParts = lst))
1185 algorithm
1186 res := {};
1187
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 31 times.
79 for elt in lst loop
1188 res := match elt
1189 case Absyn.PUBLIC() guard visibility <> Visibility.PROTECTED
1190 algorithm
1191 25 lst1 := getComponentsInElementitems(elt.contents);
1192 25 then
1193 List.append_reverse(lst1, res);
1194 case Absyn.PROTECTED() guard visibility <> Visibility.PUBLIC
1195 algorithm
1196 2 lst1 := getComponentsInElementitems(elt.contents);
1197 2 then
1198 List.append_reverse(lst1, res);
1199 else res;
1200 end match;
1201 end for;
1202 31 then
1203 Dangerous.listReverseInPlace(res);
1204
1205 // adrpo: handle also the case model extends X end X;
1206 case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = {})) then {};
1207 case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = lst))
1208 algorithm
1209 res := {};
1210 ✗ for elt in lst loop
1211 res := match elt
1212 case Absyn.PUBLIC() guard visibility <> Visibility.PROTECTED
1213 algorithm
1214 ✗ lst1 := getComponentsInElementitems(elt.contents);
1215 ✗ then
1216 List.append_reverse(lst1, res);
1217 case Absyn.PROTECTED() guard visibility <> Visibility.PUBLIC
1218 algorithm
1219 ✗ lst1 := getComponentsInElementitems(elt.contents);
1220 ✗ then
1221 List.append_reverse(lst1, res);
1222 else res;
1223 end match;
1224 end for;
1225 ✗ then
1226 Dangerous.listReverseInPlace(res);
1227
1228 else {};
1229
1230 end match;
1231 end getComponentsInClass;
1232
1233 function getPublicComponentsInClass
1234 input Absyn.Class inClass;
1235 output list<Absyn.Element> components;
1236 algorithm
1237 11 components := getComponentsInClass(inClass, Visibility.PUBLIC);
1238 end getPublicComponentsInClass;
1239
1240 function getProtectedComponentsInClass
1241 input Absyn.Class inClass;
1242 output list<Absyn.Element> components;
1243 algorithm
1244 6 components := getComponentsInClass(inClass, Visibility.PROTECTED);
1245 end getProtectedComponentsInClass;
1246
1247 public function getComponentsInElementitems
1248 "Helper function to getComponentsInClass."
1249 input list<Absyn.ElementItem> inAbsynElementItemLst;
1250 output list<Absyn.Element> outAbsynElementLst = {};
1251 algorithm
1252
2/2
✓ Branch 0 taken 146 times.
✓ Branch 1 taken 27 times.
173 for el in inAbsynElementItemLst loop
1253 () := match el
1254 local
1255 Absyn.Element elt;
1256 case Absyn.ELEMENTITEM(element = elt as Absyn.ELEMENT(specification = Absyn.COMPONENTS()))
1257 algorithm
1258 outAbsynElementLst := elt :: outAbsynElementLst;
1259 then ();
1260
1261 else ();
1262 end match;
1263 end for;
1264 27 outAbsynElementLst := Dangerous.listReverseInPlace(outAbsynElementLst);
1265 end getComponentsInElementitems;
1266
1267 public function getVariableBindingInComponentitem
1268 " Retrieve the variable binding from an ComponentItem"
1269 input Absyn.ComponentItem inComponentItem;
1270 output Absyn.Exp outExp;
1271 algorithm
1272 outExp := match inComponentItem
1273 local Absyn.Exp e;
1274 case Absyn.COMPONENTITEM(component = Absyn.COMPONENT(modification = SOME(Absyn.CLASSMOD(eqMod=Absyn.EQMOD(exp=e))))) then e;
1275 end match;
1276 end getVariableBindingInComponentitem;
1277
1278
1279
1280 public function componentitemNamed
1281 " Returns true if the component item has
1282 the name matching the second argument."
1283 input Absyn.ComponentItem inComponentItem;
1284 input Absyn.Ident inIdent;
1285 output Boolean outBoolean;
1286 algorithm
1287 outBoolean := match (inComponentItem,inIdent)
1288 local String id1,id2;
1289 case (Absyn.COMPONENTITEM(component = Absyn.COMPONENT(name = id1)),id2)
1290 guard
1291 stringEq(id1, id2)
1292 then
1293 true;
1294 else false;
1295 end match;
1296 end componentitemNamed;
1297
1298 public function getComponentitemsInElement
1299 " Retrieves the ComponentItems of a component Element.
1300 If Element is not a component, empty list is returned."
1301 input Absyn.Element inElement;
1302 output list<Absyn.ComponentItem> outAbsynComponentItemLst;
1303 algorithm
1304 outAbsynComponentItemLst := match inElement
1305 local list<Absyn.ComponentItem> l;
1306 case Absyn.ELEMENT(specification = Absyn.COMPONENTS(components = l)) then l;
1307 else {};
1308 end match;
1309 end getComponentitemsInElement;
1310
1311
1312
1313
1314
1315 public function createEnvironment
1316 input Absyn.Program p;
1317 input Option<SCode.Program> os;
1318 input Absyn.Path modelPath;
1319 output Interactive.GraphicEnvCache genv;
1320 protected
1321 FCore.Graph env,env_1,env2;
1322 SCode.Program s;
1323 SCode.Element c;
1324 String id;
1325 SCode.Encapsulated encflag;
1326 SCode.Restriction restr;
1327 ClassInf.State ci_state;
1328 FCore.Cache cache;
1329 Boolean permissive;
1330 algorithm
1331
1/2
✓ Branch 1 taken 12482 times.
✗ Branch 2 not taken.
12482 if Flags.isSet(Flags.NF_API) then
1332 12482 genv := Interactive.GRAPHIC_ENV_FULL_CACHE(p, modelPath, FCore.emptyCache(), FGraph.emptyGraph);
1333 else
1334 ✗ s := Util.getOptionOrDefault(os, AbsynToSCode.translateAbsyn2SCode(p));
1335 ✗ (cache,env) := Inst.makeEnvFromProgram(s);
1336 ✗ (cache,(c as SCode.CLASS(name=id,encapsulatedPrefix=encflag,restriction=restr)),env_1) := Lookup.lookupClass(cache, env, modelPath);
1337 ✗ env2 := FGraph.openScope(env_1, encflag, id, FGraph.restrictionToScopeType(restr));
1338 ✗ ci_state := ClassInfUtil.start(restr, FGraph.getGraphName(env2));
1339 ✗ permissive := Flags.getConfigBool(Flags.PERMISSIVE);
1340 ✗ FlagsUtil.setConfigBool(Flags.PERMISSIVE, true);
1341 try
1342 ✗ (_,env2,_,_,_) :=
1343 Inst.partialInstClassIn(cache, env2, InnerOuter.emptyInstHierarchy, DAE.NOMOD(),
1344 DAE.NOPRE(), ci_state, c, SCode.PUBLIC(), {}, 0);
1345 ✗ FlagsUtil.setConfigBool(Flags.PERMISSIVE, permissive);
1346 else
1347 ✗ FlagsUtil.setConfigBool(Flags.PERMISSIVE, permissive);
1348 ✗ fail();
1349 end try;
1350 ✗ genv := Interactive.GRAPHIC_ENV_FULL_CACHE(SymbolTable.getAbsyn(), modelPath, cache, env2);
1351 end if;
1352 end createEnvironment;
1353
1354 public function getClassCommentInCommentOpt
1355 "Helper function to getComponentComment."
1356 input Option<Absyn.Comment> inComment;
1357 output String outString;
1358 algorithm
1359 outString := match inComment
1360 case SOME(Absyn.COMMENT(comment = SOME(outString))) then outString;
1361 else "";
1362 end match;
1363 end getClassCommentInCommentOpt;
1364
1365
1366
1367
1368
1369
1370
1371 public function getElementAnnotationsFromElts
1372 "Helper function to getElementAnnotations."
1373 input list<Absyn.Element> els;
1374 input Absyn.Class inClass;
1375 input Absyn.Program inFullProgram;
1376 input Absyn.Path inModelPath;
1377 output Values.Value result;
1378 protected
1379 list<SCode.Element> graphicProgramSCode;
1380 FCore.Graph env;
1381 Absyn.Program placementProgram;
1382 GraphicEnvCache cache;
1383 algorithm
1384
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 if not Flags.isSet(Flags.NF_API) then
1385 ✗ placementProgram := modelicaAnnotationProgram(Config.getAnnotationVersion());
1386 ✗ graphicProgramSCode := AbsynToSCode.translateAbsyn2SCode(placementProgram);
1387 ✗ (_,env) := Inst.makeEnvFromProgram(graphicProgramSCode);
1388 else
1389 10 env := FGraph.emptyGraph;
1390 end if;
1391 10 cache := Interactive.GRAPHIC_ENV_NO_CACHE(inFullProgram, inModelPath);
1392 10 result := getElementitemsAnnotations(els, env, inClass, cache);
1393 end getElementAnnotationsFromElts;
1394
1395 protected function getElementitemsAnnotations
1396 "Helper function to getElementAnnotationsFromElts"
1397 input list<Absyn.Element> inElements;
1398 input FCore.Graph inEnv;
1399 input Absyn.Class inClass;
1400 input GraphicEnvCache inCache;
1401 output Values.Value result;
1402 protected
1403 list<Values.Value> res, accum = {};
1404 GraphicEnvCache cache = inCache;
1405 list<Absyn.ComponentItem> items;
1406 Option<Absyn.ConstrainClass> cc;
1407 list<Absyn.ElementArg> annotations;
1408 Option<Absyn.Comment> cmt;
1409 Absyn.Program fullProgram;
1410 Absyn.Path modelPath;
1411 algorithm
1412
1/2
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
10 if Flags.isSet(Flags.NF_API) then
1413 10 (fullProgram, modelPath) := Interactive.cacheProgramAndPath(inCache);
1414 10 result := makeAnnotationArrayValue(NFApi.evaluateAnnotations(fullProgram, modelPath, inElements));
1415 10 return;
1416 end if;
1417
1418 ✗ for e in listReverse(inElements) loop
1419 accum := matchcontinue e
1420 case Absyn.ELEMENT(specification = Absyn.COMPONENTS(components = items), constrainClass = cc)
1421 algorithm
1422 ✗ (res, cache) := getElementitemsAnnotationsFromItems(items,
1423 getAnnotationsFromConstraintClass(cc), inEnv, inClass, cache);
1424 ✗ then
1425 listAppend(res, accum);
1426
1427 case Absyn.ELEMENT(specification = Absyn.CLASSDEF(
1428 class_ = Absyn.CLASS(body = Absyn.DERIVED(comment = cmt))),
1429 constrainClass = cc)
1430 algorithm
1431 annotations := match cmt
1432 case SOME(Absyn.COMMENT(annotation_ = SOME(Absyn.ANNOTATION(annotations))))
1433 then annotations;
1434 else {};
1435 end match;
1436 ✗ (res, cache) := getElementitemsAnnotationsFromElArgs(annotations,
1437 getAnnotationsFromConstraintClass(cc), inEnv, inClass, cache);
1438 ✗ then
1439 ValuesMake.makeArray(res) :: accum;
1440
1441 case Absyn.ELEMENT(specification = Absyn.COMPONENTS())
1442 then Values.Value.ARRAY({}, {0}) :: accum;
1443
1444 case Absyn.ELEMENT(specification = Absyn.CLASSDEF(class_ = Absyn.CLASS(body = Absyn.DERIVED())))
1445 then Values.Value.ARRAY({}, {0}) :: accum;
1446
1447 ✗ else accum;
1448 end matchcontinue;
1449 end for;
1450
1451 ✗ result := ValuesMake.makeArray(accum);
1452 end getElementitemsAnnotations;
1453
1454 protected function getElementitemsAnnotationsFromElArgs
1455 "Helper function to getElementitemsAnnotations."
1456 input list<Absyn.ElementArg> inAnnotations;
1457 input list<Absyn.ElementArg> ccAnnotations;
1458 input FCore.Graph inEnv;
1459 input Absyn.Class inClass;
1460 input GraphicEnvCache inCache;
1461 output list<Values.Value> result;
1462 output GraphicEnvCache outCache = inCache;
1463 protected
1464 list<Absyn.ElementArg> annotations;
1465 list<String> strl;
1466 algorithm
1467 ✗ annotations := listAppend(inAnnotations, ccAnnotations);
1468 ✗ (strl, outCache) := getElementitemsAnnotationsElArgs(annotations, inEnv, inClass, outCache);
1469 ✗ result := list(ValuesMake.makeCodeTypeNameStr(s) for s in strl);
1470 end getElementitemsAnnotationsFromElArgs;
1471
1472 protected function getAnnotationsFromConstraintClass
1473 input Option<Absyn.ConstrainClass> inCC;
1474 output list<Absyn.ElementArg> outElArgLst;
1475 algorithm
1476 outElArgLst := match inCC
1477 local list<Absyn.ElementArg> elementArgs;
1478 case SOME(Absyn.CONSTRAINCLASS(comment = SOME(Absyn.COMMENT(annotation_ = SOME(Absyn.ANNOTATION(elementArgs))))))
1479 then elementArgs;
1480 else {};
1481 end match;
1482 end getAnnotationsFromConstraintClass;
1483
1484 public function getElementitemsAnnotationsElArgs
1485 "Helper function to getElementitemsAnnotationsFromItems."
1486 input list<Absyn.ElementArg> inElementArgs;
1487 input FCore.Graph inEnv;
1488 input Absyn.Class inClass;
1489 input GraphicEnvCache inCache;
1490 input Boolean addAnnotationName = true;
1491 output list<String> outStringLst = {};
1492 output GraphicEnvCache outCache = inCache;
1493 protected
1494 String str, ann_name;
1495 Absyn.Exp eq_aexp, graphic_exp;
1496 DAE.Exp eq_dexp, graphic_dexp;
1497 DAE.Properties prop;
1498 SourceInfo info;
1499 FCore.Cache cache;
1500 FCore.Graph env, env2;
1501 list<Absyn.ElementArg> mod, stripped_mod, graphic_mod;
1502 SCode.Element c;
1503 SCode.Mod smod;
1504 DAE.Mod dmod;
1505 DAE.DAElist dae;
1506 Boolean is_icon, is_diagram;
1507 Absyn.Program graphic_prog;
1508 SCode.Element placement_cls;
1509 algorithm
1510 ✗ for e in listReverse(inElementArgs) loop
1511
1512 ✗ e := AbsynUtil.createChoiceArray(e);
1513
1514 str := matchcontinue e
1515 case Absyn.MODIFICATION(
1516 path = Absyn.IDENT(ann_name),
1517 modification = SOME(Absyn.CLASSMOD({}, Absyn.EQMOD(eq_aexp))),
1518 info = info)
1519 algorithm
1520 ✗ (cache, env, _, outCache) := buildEnvForGraphicProgram(outCache, {});
1521
1522 ✗ (_, eq_dexp, prop) :=
1523 StaticScript.elabGraphicsExp(cache, env, eq_aexp, false, DAE.NOPRE(), info);
1524
1525 ✗ (cache, eq_dexp, prop) := Ceval.cevalIfConstant(cache, env, eq_dexp, prop, false, info);
1526 ✗ eq_dexp := ExpressionSimplify.simplify1(eq_dexp);
1527 ✗ Print.clearErrorBuf() "Clear any error messages generated by the annotations.";
1528
1529 ✗ str := ExpressionBasics.printExpStr(eq_dexp);
1530 ✗ then
1531 stringAppendList({ann_name, "=", str});
1532
1533 case Absyn.MODIFICATION(
1534 path = Absyn.IDENT(ann_name),
1535 modification = SOME(Absyn.CLASSMOD(mod, Absyn.NOMOD())),
1536 info = info)
1537 algorithm
1538 ✗ if not listMember(ann_name, {"Icon", "Diagram", "choices"}) then
1539 ✗ (cache, env, _, outCache) := buildEnvForGraphicProgram(outCache, mod);
1540
1541 ✗ (cache, c, env2) := Lookup.lookupClassIdent(cache, inEnv, ann_name);
1542 ✗ smod := AbsynToSCode.translateMod(SOME(Absyn.CLASSMOD(mod,
1543 Absyn.NOMOD())), SCode.NOT_FINAL(), SCode.NOT_EACH(), NONE(), info);
1544 ✗ (cache, dmod) := Mod.elabMod(cache, env, InnerOuter.emptyInstHierarchy, DAE.NOPRE(),
1545 smod, false, Mod.COMPONENT(ann_name), Absyn.dummyInfo);
1546
1547 ✗ c := SCodeUtil.classSetPartial(c, SCode.NOT_PARTIAL());
1548 ✗ (_, _, _, _, dae) := Inst.instClass(cache, env2, InnerOuter.emptyInstHierarchy,
1549 UnitAbsyn.noStore, dmod, DAE.NOPRE(), c, {}, false,
1550 InstTypes.TOP_CALL(), ConnectionGraph.EMPTY, Connect.emptySet);
1551
1552 ✗ str := DAEUtil.getVariableBindingsStr(DAEUtil.daeElements(dae));
1553 else // icon, diagram or choices
1554 ✗ is_icon := ann_name == "Icon";
1555 ✗ is_diagram := ann_name == "Diagram" or ann_name == "choices";
1556
1557 ✗ (stripped_mod, graphic_mod) := AbsynUtil.stripGraphicsAndInteractionModification(mod);
1558 ✗ ErrorExt.setCheckpoint("buildEnvForGraphicProgram");
1559 // GRAPHIC_ENV_NO_CACHE(inFullProgram, inModelPath)
1560 try
1561 ✗ (cache, env, graphic_prog, _) :=
1562 buildEnvForGraphicProgram(inCache, mod);
1563 ✗ ErrorExt.rollBack("buildEnvForGraphicProgram");
1564 else
1565 ✗ ErrorExt.delCheckpoint("buildEnvForGraphicProgram");
1566 // Fallback to only the graphical primitives left in the program
1567 ✗ (cache, env, graphic_prog, _) := buildEnvForGraphicProgram(inCache, {});
1568 end try;
1569
1570 ✗ smod := AbsynToSCode.translateMod(SOME(Absyn.CLASSMOD(stripped_mod, Absyn.NOMOD())),
1571 SCode.NOT_FINAL(), SCode.NOT_EACH(), NONE(), info);
1572 ✗ (cache, dmod) := Mod.elabMod(cache, env, InnerOuter.emptyInstHierarchy,
1573 DAE.NOPRE(), smod, false, Mod.COMPONENT(ann_name), info);
1574
1575 ✗ placement_cls := AbsynToSCode.translateClass(ProgramUtil.getClassInProgram(ann_name, graphic_prog));
1576 ✗ (cache, _, _, _, dae) :=
1577 Inst.instClass(cache, env, InnerOuter.emptyInstHierarchy, UnitAbsyn.noStore,
1578 dmod, DAE.NOPRE(), placement_cls, {}, false, InstTypes.TOP_CALL(),
1579 ConnectionGraph.EMPTY, Connect.emptySet);
1580 ✗ str := DAEUtil.getVariableBindingsStr(DAEUtil.daeElements(dae));
1581
1582 // Icon and Diagram contain graphic primitives which must be handled
1583 // specially.
1584 ✗ if is_icon or is_diagram then
1585 try
1586 ✗ {Absyn.MODIFICATION(modification = SOME(Absyn.CLASSMOD(eqMod =
1587 Absyn.EQMOD(exp = graphic_exp))))} := graphic_mod;
1588 ✗ (_, graphic_dexp, prop) := StaticScript.elabGraphicsExp(cache, env,
1589 graphic_exp, false, DAE.NOPRE(), info);
1590
1591 ✗ if is_icon then
1592 ✗ ErrorExt.setCheckpoint("getAnnotationString: Icon");
1593 ✗ (cache, graphic_dexp) :=
1594 Ceval.cevalIfConstant(cache, env, graphic_dexp, prop, false, info);
1595 ✗ graphic_dexp := ExpressionSimplify.simplify1(graphic_dexp);
1596 ✗ ErrorExt.rollBack("getAnnotationString: Icon");
1597 end if;
1598
1599 ✗ str := str + "," + ExpressionBasics.printExpStr(graphic_dexp);
1600 else
1601 end try;
1602 end if;
1603
1604 ✗ Print.clearErrorBuf() "This is to clear the error-msg generated by the annotations.";
1605 end if;
1606 ✗ then
1607 if addAnnotationName
1608 then stringAppendList({ann_name, "(", str, ")"})
1609 else str;
1610
1611 case Absyn.MODIFICATION(path = Absyn.IDENT(ann_name), modification = NONE())
1612 algorithm
1613 ✗ (cache, _, _, outCache) := buildEnvForGraphicProgram(outCache, {});
1614
1615 ✗ (cache, c, env) := Lookup.lookupClassIdent(cache, inEnv, ann_name);
1616 ✗ c := SCodeUtil.classSetPartial(c, SCode.NOT_PARTIAL());
1617 ✗ (_, _, _, _, dae) := Inst.instClass(cache, env, InnerOuter.emptyInstHierarchy,
1618 UnitAbsyn.noStore, DAE.NOMOD(), DAE.NOPRE(), c, {}, false,
1619 InstTypes.TOP_CALL(), ConnectionGraph.EMPTY, Connect.emptySet);
1620
1621 ✗ str := DAEUtil.getVariableBindingsStr(DAEUtil.daeElements(dae));
1622 ✗ then
1623 if addAnnotationName
1624 then stringAppendList({ann_name, "(", str, ")"})
1625 else str;
1626
1627 case Absyn.MODIFICATION(
1628 path = Absyn.IDENT(ann_name),
1629 info = info)
1630 algorithm
1631 ✗ str := "error evaluating: annotation(" + Dump.unparseElementArgStr(e) + ")";
1632 ✗ str := Util.escapeQuotes(str);
1633 ✗ then
1634 stringAppendList({ann_name, "(\"", str, "\")"});
1635
1636 end matchcontinue;
1637
1638 outStringLst := str :: outStringLst;
1639 end for;
1640 end getElementitemsAnnotationsElArgs;
1641
1642 protected function getElementitemsAnnotationsFromItems
1643 "Helper function to getElementitemsAnnotations."
1644 input list<Absyn.ComponentItem> inComponentItems;
1645 input list<Absyn.ElementArg> ccAnnotations;
1646 input FCore.Graph inEnv;
1647 input Absyn.Class inClass;
1648 input GraphicEnvCache inCache;
1649 output list<Values.Value> result = {};
1650 output GraphicEnvCache outCache = inCache;
1651 protected
1652 list<Absyn.ElementArg> annotations;
1653 list<String> strl;
1654 algorithm
1655 ✗ for comp in listReverse(inComponentItems) loop
1656 annotations := match comp
1657 case Absyn.COMPONENTITEM(comment = SOME(Absyn.COMMENT(annotation_ =
1658 SOME(Absyn.ANNOTATION(annotations)))))
1659 ✗ then listAppend(annotations, ccAnnotations);
1660 else ccAnnotations;
1661 end match;
1662
1663 ✗ (strl, outCache) := getElementitemsAnnotationsElArgs(annotations, inEnv, inClass, outCache);
1664 ✗ result := makeAnnotationArrayValue(strl) :: result;
1665 end for;
1666 end getElementitemsAnnotationsFromItems;
1667
1668 public function modelicaAnnotationProgram
1669 input String annotationVersion "1.x or 2.x or 3.x";
1670 output Absyn.Program annotationProgram;
1671 protected
1672 String filename;
1673 algorithm
1674 1693 filename := Settings.getInstallationDirectoryPath() +
1675 "/lib/omc/AnnotationsBuiltin_" +
1676 Util.stringReplaceChar(annotationVersion, ".", "_") +
1677 ".mo";
1678 1693 annotationProgram := Parser.parse(filename, "UTF-8");
1679 end modelicaAnnotationProgram;
1680
1681 public function buildEnvForGraphicProgram
1682 "Builds an environment for instantiating graphical annotations. If the
1683 annotation modification only contains literals we only need to make an
1684 environment from the program, otherwise we need to fully instantiate the
1685 class used. To avoid doing this work over and over this function takes and
1686 returns a GraphicEnvCache, which is used to save the state between multiple
1687 calls to this function.
1688
1689 This function is called by getAnnotationString, which expects to get back an
1690 Absyn.Program where the graphical annotation classes have been added. Since
1691 this is only used by getAnnotationString so far, and it always calls this
1692 function with an empty cache, this function returns a dummy program when
1693 called with a non-empty cache. The generated absyn program could easily be
1694 added to the cache if necessary though."
1695 input GraphicEnvCache inCache;
1696 input list<Absyn.ElementArg> inAnnotationMod;
1697 output FCore.Cache outCache;
1698 output FCore.Graph outEnv;
1699 output Absyn.Program outGraphicProgram;
1700 output GraphicEnvCache outGraphicEnvCache;
1701 algorithm
1702 (outCache, outEnv, outGraphicProgram, outGraphicEnvCache) := match inCache
1703 local
1704 SCode.Program scode_program;
1705
1706 // Class already fully instantiated, return cached data.
1707 case Interactive.GRAPHIC_ENV_FULL_CACHE()
1708 ✗ then (inCache.cache, inCache.env, Absyn.dummyProgram, inCache);
1709
1710 // Partial cache, instantiate class to make full cache if needed.
1711 case Interactive.GRAPHIC_ENV_PARTIAL_CACHE()
1712 algorithm
1713 ✗ if AbsynUtil.onlyLiteralsInAnnotationMod(inAnnotationMod) then
1714 ✗ outCache := inCache.cache;
1715 ✗ outEnv := inCache.env;
1716 outGraphicEnvCache := inCache;
1717 ✗ outGraphicProgram := inCache.program;
1718 else
1719 ✗ (outCache, outEnv, outGraphicProgram) :=
1720 buildEnvForGraphicProgramFull(inCache.program, inCache.modelPath);
1721 ✗ outGraphicEnvCache := Interactive.GRAPHIC_ENV_FULL_CACHE(inCache.program, inCache.modelPath, outCache, outEnv);
1722 end if;
1723 ✗ then
1724 (outCache, outEnv, outGraphicProgram, outGraphicEnvCache);
1725
1726 // No cache, make partial or full cache as needed.
1727 case Interactive.GRAPHIC_ENV_NO_CACHE()
1728 algorithm
1729 ✗ if AbsynUtil.onlyLiteralsInAnnotationMod(inAnnotationMod) then
1730 ✗ outGraphicProgram := modelicaAnnotationProgram(Config.getAnnotationVersion());
1731 ✗ scode_program := AbsynToSCode.translateAbsyn2SCode(outGraphicProgram);
1732 ✗ (outCache, outEnv) := Inst.makeEnvFromProgram(scode_program);
1733 ✗ outGraphicEnvCache :=
1734 Interactive.GRAPHIC_ENV_PARTIAL_CACHE(inCache.program, inCache.modelPath, outCache, outEnv);
1735 else
1736 ✗ (outCache, outEnv, outGraphicProgram) :=
1737 buildEnvForGraphicProgramFull(inCache.program, inCache.modelPath);
1738 ✗ outGraphicEnvCache := Interactive.GRAPHIC_ENV_FULL_CACHE(inCache.program, inCache.modelPath, outCache, outEnv);
1739 end if;
1740 ✗ then
1741 (outCache, outEnv, outGraphicProgram, outGraphicEnvCache);
1742
1743 end match;
1744 end buildEnvForGraphicProgram;
1745
1746 protected function buildEnvForGraphicProgramFull
1747 "Helper function to buildEnvForGraphicProgram. Builds an environment by fully
1748 instantiating the currently used class."
1749 input Absyn.Program inProgram;
1750 input Absyn.Path inModelPath;
1751 output FCore.Cache outCache = FCore.emptyCache();
1752 output FCore.Graph outEnv = FGraph.empty();
1753 output Absyn.Program outProgram;
1754 protected
1755 Boolean check_model, eval_param, failed = false, graphics_mode;
1756 Absyn.Program graphic_program;
1757 SCode.Program scode_program;
1758 algorithm
1759 ✗ graphic_program := modelicaAnnotationProgram(Config.getAnnotationVersion());
1760 ✗ outProgram := ProgramUtil.updateProgram(graphic_program, inProgram);
1761 ✗ scode_program := AbsynToSCode.translateAbsyn2SCode(outProgram);
1762
1763 ✗ check_model := Flags.getConfigBool(Flags.CHECK_MODEL);
1764 ✗ eval_param := Config.getEvaluateParametersInAnnotations();
1765 ✗ graphics_mode := Config.getGraphicsExpMode();
1766 ✗ FlagsUtil.setConfigBool(Flags.CHECK_MODEL, true);
1767 ✗ Config.setEvaluateParametersInAnnotations(true);
1768 ✗ Config.setGraphicsExpMode(true);
1769
1770 try
1771 ✗ (outCache, outEnv) := Inst.instantiateClass(FCore.emptyCache(), InnerOuter.emptyInstHierarchy, scode_program, inModelPath);
1772 else
1773 failed := true;
1774 end try;
1775
1776 ✗ Config.setEvaluateParametersInAnnotations(eval_param);
1777 ✗ FlagsUtil.setConfigBool(Flags.CHECK_MODEL, check_model);
1778 ✗ Config.setGraphicsExpMode(graphics_mode);
1779 ✗ if failed then
1780 ✗ fail();
1781 end if;
1782 end buildEnvForGraphicProgramFull;
1783
1784 public function getElementsInClass
1785 " Both public and protected lists are searched."
1786 input Absyn.Class inClass;
1787 output list<Absyn.Element> outAbsynElementLst;
1788 algorithm
1789 outAbsynElementLst:=
1790 match inClass
1791 local
1792 list<Absyn.Element> lst1,res;
1793 list<Absyn.ElementItem> elts;
1794 list<Absyn.ClassPart> lst;
1795
1796 case Absyn.CLASS(body = Absyn.PARTS(classParts = {})) then {};
1797 case Absyn.CLASS(body = Absyn.PARTS(classParts = lst))
1798 algorithm
1799 res := {};
1800 ✗ for elt in lst loop
1801 () := match elt
1802 case Absyn.PUBLIC(contents = elts)
1803 algorithm
1804 ✗ lst1 := getElementsInElementitems(elts);
1805 ✗ res := List.append_reverse(lst1, res);
1806 then ();
1807 case Absyn.PROTECTED(contents = elts)
1808 algorithm
1809 ✗ lst1 := getElementsInElementitems(elts);
1810 ✗ res := List.append_reverse(lst1, res);
1811 then ();
1812 else ();
1813 end match;
1814 end for;
1815 ✗ res := Dangerous.listReverseInPlace(res);
1816 then
1817 res;
1818
1819 // adrpo: handle also the case model extends X end X;
1820 case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = {})) then {};
1821 case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = lst))
1822 algorithm
1823 res := {};
1824 ✗ for elt in lst loop
1825 () := match elt
1826 case Absyn.PUBLIC(contents = elts)
1827 algorithm
1828 ✗ lst1 := getElementsInElementitems(elts);
1829 ✗ res := List.append_reverse(lst1, res);
1830 then ();
1831 case Absyn.PROTECTED(contents = elts)
1832 algorithm
1833 ✗ lst1 := getElementsInElementitems(elts);
1834 ✗ res := List.append_reverse(lst1, res);
1835 then ();
1836 else ();
1837 end match;
1838 end for;
1839 ✗ res := Dangerous.listReverseInPlace(res);
1840 then
1841 res;
1842
1843 else {};
1844
1845 end match;
1846 end getElementsInClass;
1847
1848 public function getPublicElementsInClass
1849 " Public lists are searched."
1850 input Absyn.Class inClass;
1851 output list<Absyn.Element> outAbsynElementLst;
1852 algorithm
1853 outAbsynElementLst:=
1854 match inClass
1855 local
1856 list<Absyn.Element> lst1,res;
1857 list<Absyn.ElementItem> elts;
1858 list<Absyn.ClassPart> lst;
1859
1860 case Absyn.CLASS(body = Absyn.PARTS(classParts = {})) then {};
1861 case Absyn.CLASS(body = Absyn.PARTS(classParts = lst))
1862 algorithm
1863 res := {};
1864
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 24 times.
73 for elt in lst loop
1865 () := match elt
1866 case Absyn.PUBLIC(contents = elts)
1867 algorithm
1868 24 lst1 := getElementsInElementitems(elts);
1869 24 res := List.append_reverse(lst1, res);
1870 then ();
1871 else ();
1872 end match;
1873 end for;
1874 24 res := Dangerous.listReverseInPlace(res);
1875 then
1876 res;
1877
1878 // adrpo: handle also the case model extends X end X;
1879 case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = {})) then {};
1880 case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = lst))
1881 algorithm
1882 res := {};
1883 ✗ for elt in lst loop
1884 () := match elt
1885 case Absyn.PUBLIC(contents = elts)
1886 algorithm
1887 ✗ lst1 := getElementsInElementitems(elts);
1888 ✗ res := List.append_reverse(lst1, res);
1889 then ();
1890 else ();
1891 end match;
1892 end for;
1893 ✗ res := Dangerous.listReverseInPlace(res);
1894 then
1895 res;
1896
1897 else {};
1898 end match;
1899 end getPublicElementsInClass;
1900
1901 public function getProtectedElementsInClass
1902 " Protected lists are searched."
1903 input Absyn.Class inClass;
1904 output list<Absyn.Element> outAbsynElementLst;
1905 algorithm
1906 outAbsynElementLst:=
1907 match inClass
1908 local
1909 list<Absyn.Element> lst1,res;
1910 list<Absyn.ElementItem> elts;
1911 list<Absyn.ClassPart> lst;
1912
1913 case Absyn.CLASS(body = Absyn.PARTS(classParts = {})) then {};
1914 case Absyn.CLASS(body = Absyn.PARTS(classParts = lst))
1915 algorithm
1916 res := {};
1917
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 24 times.
73 for elt in lst loop
1918 () := match elt
1919 case Absyn.PROTECTED(contents = elts)
1920 algorithm
1921 15 lst1 := getElementsInElementitems(elts);
1922 15 res := List.append_reverse(lst1, res);
1923 then ();
1924 else ();
1925 end match;
1926 end for;
1927 24 res := Dangerous.listReverseInPlace(res);
1928 then
1929 res;
1930
1931 // adrpo: handle also the case model extends X end X;
1932 case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = {})) then {};
1933 case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = lst))
1934 algorithm
1935 res := {};
1936 ✗ for elt in lst loop
1937 () := match elt
1938 case Absyn.PROTECTED(contents = elts)
1939 algorithm
1940 ✗ lst1 := getElementsInElementitems(elts);
1941 ✗ res := List.append_reverse(lst1, res);
1942 then ();
1943 else ();
1944 end match;
1945 end for;
1946 ✗ res := Dangerous.listReverseInPlace(res);
1947 then
1948 res;
1949
1950 else {};
1951 end match;
1952 end getProtectedElementsInClass;
1953
1954 protected function getElementsInElementitems
1955 "Helper function to getElementsInClass."
1956 input list<Absyn.ElementItem> inAbsynElementItemLst;
1957 output list<Absyn.Element> outAbsynElementLst = {};
1958 algorithm
1959
2/2
✓ Branch 0 taken 279 times.
✓ Branch 1 taken 39 times.
318 for el in inAbsynElementItemLst loop
1960 () := match el
1961 local
1962 Absyn.Element elt;
1963 case Absyn.ELEMENTITEM(element = elt)
1964 algorithm
1965 outAbsynElementLst := elt :: outAbsynElementLst;
1966 then ();
1967
1968 else ();
1969 end match;
1970 end for;
1971 39 outAbsynElementLst := Dangerous.listReverseInPlace(outAbsynElementLst);
1972 end getElementsInElementitems;
1973
1974 public function dimensionListValues
1975 input list<Absyn.Subscript> dims;
1976 output list<Values.Value> vals;
1977 algorithm
1978
4/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 262 times.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 262 times.
290 vals := list(ValuesMake.makeCodeTypeNameStr(Dump.printSubscriptStr(d)) for d in dims);
1979 end dimensionListValues;
1980
1981 protected function getElementInfo
1982 " This function takes an Element and returns a list of strings
1983 of comma separated values of the type and name and comment,
1984 and attributes of of the component, If Element is not a
1985 component, the empty string is returned.
1986 inputs: (Absyn.Element, string, /* public or protected */, FCore.Graph)
1987 outputs: string list"
1988 input Absyn.Element element;
1989 input Boolean isPublic;
1990 input Boolean quoteNames;
1991 input Boolean onlyComponents;
1992 input GraphicEnvCache env;
1993 input output list<Values.Value> infos = {};
1994 protected
1995 Absyn.ElementAttributes attr;
1996 Absyn.Path ty, cc_path;
1997 list<Absyn.ComponentItem> comps;
1998 String name, cmt;
1999 list<Values.Value> common_info, info;
2000 Absyn.Class cls;
2001 Absyn.Restriction restriction;
2002 Option<Absyn.Comment> opt_cmt;
2003 Option<Absyn.ConstrainClass> opt_cc;
2004 Option<Absyn.ArrayDim> opt_adim;
2005 list<Values.Value> common_dims, dims;
2006 Values.Value dims_val;
2007 algorithm
2008 infos := match element
2009 case Absyn.ELEMENT(specification = Absyn.COMPONENTS(
2010 attributes = attr, typeSpec = Absyn.TPATH(path = ty, arrayDim = opt_adim), components = comps),
2011 constrainClass = opt_cc)
2012 algorithm
2013 common_info := {};
2014 131 ty := qualifyPath(env, ty);
2015 131 common_dims := dimensionListValues(attr.arrayDim);
2016
2017
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 94 times.
131 if not onlyComponents then
2018 37 cc_path := getConstrainClassPath(env, opt_cc);
2019
2020
1/2
✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
37 if quoteNames then
2021 37 common_info := ValuesMake.makeString(AbsynUtil.pathString(cc_path)) :: common_info;
2022 else
2023 ✗ common_info := ValuesMake.makeCodeTypeName(getConstrainClassPath(env, opt_cc)) :: common_info;
2024 end if;
2025 end if;
2026
2027 131 common_info := getElementAttributeValues(element, isPublic, quoteNames, common_info);
2028
2029
2/2
✓ Branch 1 taken 131 times.
✓ Branch 2 taken 131 times.
262 for comp in listReverse(comps) loop
2030 131 name := comp.component.name;
2031 131 cmt := getComponentComment(comp, element);
2032 131 dims := dimensionListValues(comp.component.arrayDim);
2033 131 dims_val := ValuesMake.makeArray(listAppend(dims, common_dims));
2034
2035
2/2
✓ Branch 0 taken 111 times.
✓ Branch 1 taken 20 times.
131 if quoteNames then
2036 111 dims_val := ValuesMake.makeString(ValuesDump.printValStr(dims_val));
2037 end if;
2038
2039 131 info := List.appendElt(dims_val, common_info);
2040 131 info := ValuesMake.makeString(cmt) :: info;
2041
2042
2/2
✓ Branch 0 taken 111 times.
✓ Branch 1 taken 20 times.
131 if quoteNames then
2043 111 info := ValuesMake.makeString(name) :: info;
2044 111 info := ValuesMake.makeString(AbsynUtil.pathString(ty)) :: info;
2045 else
2046 20 info := ValuesMake.makeCodeTypeNameStr(name) :: info;
2047 20 info := ValuesMake.makeCodeTypeName(ty) :: info;
2048 end if;
2049
2050
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 94 times.
131 if not onlyComponents then
2051 74 info := ValuesMake.makeString("co") :: ValuesMake.makeString("-") :: info;
2052 end if;
2053
2054 131 infos := ValuesMake.makeArray(info) :: infos;
2055 end for;
2056 then
2057 infos;
2058
2059 case Absyn.ELEMENT(specification = Absyn.CLASSDEF(class_ = cls as Absyn.CLASS(
2060 name = name, restriction = restriction,
2061 body = Absyn.DERIVED(typeSpec = Absyn.TPATH(ty, opt_adim), attributes = attr, comment = opt_cmt))),
2062 constrainClass = opt_cc)
2063 guard not onlyComponents
2064 algorithm
2065 ✗ ty := qualifyPath(env, ty);
2066
2067 ✗ cmt := getConstrainingClassComment(opt_cc);
2068
2069 ✗ if stringEmpty(cmt) then
2070 ✗ cmt := getClassCommentInCommentOpt(opt_cmt);
2071 end if;
2072
2073 ✗ dims := if isSome(opt_adim) then dimensionListValues(Util.getOption(opt_adim)) else {};
2074 ✗ dims := listAppend(dimensionListValues(attr.arrayDim), dims);
2075 ✗ dims_val := ValuesMake.makeArray(dims);
2076
2077 ✗ if quoteNames then
2078 ✗ dims_val := ValuesMake.makeString(ValuesDump.printValStr(dims_val));
2079 end if;
2080
2081 info := {dims_val};
2082 ✗ info := ValuesMake.makeCodeTypeName(getConstrainClassPath(env, opt_cc)) :: info;
2083 ✗ info := getElementAttributeValues(element, isPublic, quoteNames, info);
2084 ✗ info := ValuesMake.makeString(cmt) :: info;
2085 ✗ info := ValuesMake.makeCodeTypeNameStr(name) :: info;
2086 ✗ info := ValuesMake.makeCodeTypeName(ty) :: info;
2087 ✗ info := ValuesMake.makeString(Dump.unparseRestrictionStr(restriction)) :: info;
2088 ✗ info := ValuesMake.makeString("cl") :: info;
2089
2090 ✗ infos := ValuesMake.makeArray(info) :: infos;
2091 then
2092 infos;
2093
2094 else infos;
2095 end match;
2096 end getElementInfo;
2097
2098 public function getElementAttributeValues
2099 input Absyn.Element element;
2100 input Boolean isPublic;
2101 input Boolean quoteNames;
2102 input output list<Values.Value> attrValues;
2103 protected
2104 Absyn.ElementAttributes attr;
2105 algorithm
2106 attrValues := match element
2107 case Absyn.Element.ELEMENT()
2108 algorithm
2109 attr := match element.specification
2110 case Absyn.ElementSpec.CLASSDEF(class_ = Absyn.Class.CLASS(body = Absyn.ClassDef.DERIVED(attributes = attr))) then attr;
2111 case Absyn.ElementSpec.COMPONENTS(attributes = attr) then attr;
2112 end match;
2113
2114 393 attrValues := ValuesMake.makeString(attrVariabilityStr(attr)) ::
2115 ValuesMake.makeString(innerOuterStr(element.innerOuter)) ::
2116 ValuesMake.makeString(attrDirectionStr(attr)) ::
2117 attrValues;
2118
2119
2/2
✓ Branch 0 taken 111 times.
✓ Branch 1 taken 20 times.
131 if quoteNames then
2120 444 attrValues := ValuesMake.makeString(String(element.finalPrefix)) ::
2121 ValuesMake.makeString(String(attr.flowPrefix)) ::
2122 ValuesMake.makeString(String(attr.streamPrefix)) ::
2123 ValuesMake.makeString(String(AbsynUtil.isElementReplaceable(element))) ::
2124 attrValues;
2125 else
2126 80 attrValues := ValuesMake.makeBoolean(element.finalPrefix) ::
2127 ValuesMake.makeBoolean(attr.flowPrefix) ::
2128 ValuesMake.makeBoolean(attr.streamPrefix) ::
2129 ValuesMake.makeBoolean(AbsynUtil.isElementReplaceable(element)) ::
2130 attrValues;
2131 end if;
2132
2133
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 114 times.
148 attrValues := ValuesMake.makeString(if isPublic then "public" else "protected") :: attrValues;
2134 then
2135 attrValues;
2136 end match;
2137 end getElementAttributeValues;
2138
2139 public function qualifyPath
2140 input GraphicEnvCache inEnv;
2141 input Absyn.Path inPath;
2142 input Boolean failOnError = false;
2143 output Absyn.Path outPath;
2144 algorithm
2145 outPath := match inPath
2146 case Absyn.FULLYQUALIFIED(__) then inPath;
2147 case Absyn.IDENT("Real") then inPath;
2148 case Absyn.IDENT("Integer") then inPath;
2149 case Absyn.IDENT("Boolean") then inPath;
2150 case Absyn.IDENT("String") then inPath;
2151 else
2152 algorithm
2153 try
2154
1/2
✓ Branch 1 taken 7054 times.
✗ Branch 2 not taken.
7054 if Flags.isSet(Flags.NF_API) then
2155 7054 (_, outPath) := Interactive.mkFullyQual(inEnv, inPath, failOnError);
2156 else
2157 ✗ outPath := qualifyType(Interactive.envFromGraphicEnvCache(inEnv), inPath);
2158 end if;
2159 else
2160 ✗ if failOnError then
2161 ✗ fail();
2162 else
2163 ✗ outPath := inPath;
2164 end if;
2165 end try;
2166 7054 then
2167 outPath;
2168 end match;
2169 end qualifyPath;
2170
2171 public function getConstrainClassPath
2172 input GraphicEnvCache inEnv;
2173 input Option<Absyn.ConstrainClass> occ;
2174 output Absyn.Path path;
2175 algorithm
2176 path := matchcontinue occ
2177 case SOME(Absyn.CONSTRAINCLASS(elementSpec = Absyn.EXTENDS(path = path)))
2178 ✗ then qualifyPath(inEnv, path);
2179 else Absyn.Path.IDENT("$Any");
2180 end matchcontinue;
2181 end getConstrainClassPath;
2182
2183 public function qualifyType
2184 input FGraph.Graph inEnv;
2185 input Absyn.Path p;
2186 output Absyn.Path fqp = p;
2187 protected
2188 Option<Absyn.Path> oenv_path;
2189 Absyn.Path env_path, tp_path, pkg_path;
2190 String tp_name;
2191 FGraph.Graph env;
2192 algorithm
2193 ✗ if AbsynUtil.pathIsFullyQualified(p) then
2194 ✗ return;
2195 end if;
2196
2197 fqp := matchcontinue ()
2198 // Look up the full type path.
2199 case ()
2200 algorithm
2201 ✗ (_, _, env) := Lookup.lookupClass(FCore.emptyCache(), inEnv, p);
2202 ✗ oenv_path := FGraph.getScopePath(env);
2203
2204 // If the type was found in a non-top scope, construct the fully
2205 // qualified path of the type. Otherwise the type is already fully
2206 // qualified, and we can use it as it is.
2207 ✗ if isSome(oenv_path) then
2208 ✗ SOME(env_path) := oenv_path;
2209 ✗ tp_name := AbsynUtil.pathLastIdent(p);
2210 ✗ tp_path := AbsynUtil.suffixPath(env_path, tp_name);
2211 else
2212 tp_path := p;
2213 end if;
2214 then
2215 tp_path;
2216
2217 // If the first case fails, i.e. if the type name doesn't reference an
2218 // existing type, try to construct a fully qualified path to where the
2219 // type should be, but isn't.
2220 case ()
2221 algorithm
2222 // Look up the first identifier in the type name.
2223 ✗ pkg_path := AbsynUtil.pathFirstPath(p);
2224 ✗ (_, _, env) := Lookup.lookupClass(FCore.emptyCache(), inEnv, pkg_path);
2225 ✗ oenv_path := FGraph.getScopePath(env);
2226
2227 // Replace the first identifier in the type name with the path to
2228 // the found class. If the class was found at top-scope, i.e. if
2229 // oenv_path is NONE, then the type name is already fully qualified.
2230 ✗ if isSome(oenv_path) then
2231 ✗ SOME(env_path) := oenv_path;
2232 ✗ tp_path := AbsynUtil.joinPaths(env_path, p);
2233 else
2234 tp_path := p;
2235 end if;
2236 then
2237 tp_path;
2238
2239 else p;
2240 end matchcontinue;
2241 end qualifyType;
2242
2243 public function getElementsInfo
2244 input list<Absyn.Element> elements;
2245 input Boolean isPublic;
2246 input Boolean useQuotes;
2247 input Boolean onlyComponents;
2248 input Interactive.GraphicEnvCache env;
2249 input output list<Values.Value> infos = {};
2250 algorithm
2251
2/2
✓ Branch 1 taken 137 times.
✓ Branch 2 taken 44 times.
181 for elem in listReverse(elements) loop
2252 137 infos := getElementInfo(elem, isPublic, useQuotes, onlyComponents, env, infos);
2253 end for;
2254 end getElementsInfo;
2255
2256 public function keywordReplaceable
2257 "Returns true if RedeclareKeywords contains replaceable."
2258 input Option<Absyn.RedeclareKeywords> inAbsynRedeclareKeywordsOption;
2259 output Boolean outBoolean;
2260 algorithm
2261 outBoolean:=
2262 match inAbsynRedeclareKeywordsOption
2263 case SOME(Absyn.REPLACEABLE()) then true;
2264 case SOME(Absyn.REDECLARE_REPLACEABLE()) then true;
2265 else false;
2266 end match;
2267 end keywordReplaceable;
2268
2269 public function innerOuterStr
2270 "Helper function to getElementInfo, retrieve the inner outer string."
2271 input Absyn.InnerOuter inInnerOuter;
2272 output String outString;
2273 algorithm
2274 outString:=
2275 match inInnerOuter
2276 case Absyn.INNER() then "inner";
2277 case Absyn.OUTER() then "outer";
2278 case Absyn.NOT_INNER_OUTER() then "none";
2279 case Absyn.INNER_OUTER() then "innerouter";
2280 end match;
2281 end innerOuterStr;
2282
2283 public function attrFlowStr
2284 "Helper function to get_component_info,
2285 retrieve flow attribite as bool string."
2286 input Absyn.ElementAttributes inElementAttributes;
2287 output String outString;
2288 algorithm
2289 outString:=
2290 match inElementAttributes
2291 local
2292 String res;
2293 Boolean f;
2294 case Absyn.ATTR(flowPrefix = f)
2295 algorithm
2296
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 res := boolString(f);
2297 then
2298 res;
2299 end match;
2300 end attrFlowStr;
2301
2302 public function attrStreamStr
2303 "Helper function to get_component_info,
2304 retrieve stream attribute as bool string."
2305 input Absyn.ElementAttributes inElementAttributes;
2306 output String outString;
2307 algorithm
2308 outString:=
2309 match inElementAttributes
2310 local
2311 String res;
2312 Boolean s;
2313 case Absyn.ATTR(streamPrefix = s)
2314 algorithm
2315
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 res := boolString(s);
2316 then
2317 res;
2318 end match;
2319 end attrStreamStr;
2320
2321 public function attrParallelismStr
2322 "Helper function to get_component_info,
2323 retrieve parallelism as a string."
2324 input Absyn.ElementAttributes inElementAttributes;
2325 output String outString;
2326 algorithm
2327 outString:=
2328 match inElementAttributes
2329 case Absyn.ATTR(parallelism = Absyn.PARGLOBAL()) then "parglobal";
2330 case Absyn.ATTR(parallelism = Absyn.PARLOCAL()) then "parlocal";
2331 case Absyn.ATTR(parallelism = Absyn.NON_PARALLEL()) then "";
2332 end match;
2333 end attrParallelismStr;
2334
2335 public function attrVariabilityStr
2336 "Helper function to get_component_info,
2337 retrieve variability as a string."
2338 input Absyn.ElementAttributes inElementAttributes;
2339 output String outString;
2340 algorithm
2341 outString:=
2342 match inElementAttributes
2343 case Absyn.ATTR(variability = Absyn.VAR()) then "unspecified";
2344 case Absyn.ATTR(variability = Absyn.DISCRETE()) then "discrete";
2345 case Absyn.ATTR(variability = Absyn.PARAM()) then "parameter";
2346 case Absyn.ATTR(variability = Absyn.CONST()) then "constant";
2347 end match;
2348 end attrVariabilityStr;
2349
2350 public function attrDirectionStr
2351 "Helper function to get_component_info,
2352 retrieve direction as a string."
2353 input Absyn.ElementAttributes inElementAttributes;
2354 output String outString;
2355 algorithm
2356 outString:=
2357 match inElementAttributes
2358 case Absyn.ATTR(direction = Absyn.INPUT()) then "input";
2359 case Absyn.ATTR(direction = Absyn.OUTPUT()) then "output";
2360 case Absyn.ATTR(direction = Absyn.BIDIR()) then "unspecified";
2361 end match;
2362 end attrDirectionStr;
2363
2364 public function getConstrainingClassComment
2365 input Option<Absyn.ConstrainClass> constrainingClass;
2366 output String comment;
2367 algorithm
2368 comment := match constrainingClass
2369 case SOME(Absyn.ConstrainClass.CONSTRAINCLASS(
2370 comment = SOME(Absyn.Comment.COMMENT(comment = SOME(comment))))) then comment;
2371 else "";
2372 end match;
2373 end getConstrainingClassComment;
2374
2375 public function getComponentComment
2376 input Absyn.ComponentItem component;
2377 input Absyn.Element element;
2378 output String comment;
2379 algorithm
2380 // The Modelica syntax allows a comment on both the element and the
2381 // constraining clause, but the specification recommends putting it on
2382 // the constraining clause. So check the constraining clause first.
2383 138 comment := getConstrainingClassComment(AbsynUtil.getElementConstrainingClass(element));
2384
2385
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
138 if stringEmpty(comment) then
2386 138 comment := getClassCommentInCommentOpt(component.comment);
2387 end if;
2388 end getComponentComment;
2389
2390 public function getComponentItemsNameAndComment
2391 " separated list of all component names and comments (if any)."
2392 input list<Absyn.ComponentItem> inComponents;
2393 input Absyn.Element inElement;
2394 output list<list<String>> outStrings = {};
2395 protected
2396 String name, cmt_str;
2397 algorithm
2398
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 5 times.
10 for comp in listReverse(inComponents) loop
2399 () := match comp
2400 case Absyn.COMPONENTITEM(component = Absyn.COMPONENT(name = name))
2401 algorithm
2402 5 cmt_str := getComponentComment(comp, inElement);
2403 5 cmt_str := StringUtil.quote(cmt_str);
2404
2405 outStrings := {name, cmt_str} :: outStrings;
2406 then
2407 ();
2408
2409 else ();
2410 end match;
2411 end for;
2412 end getComponentItemsNameAndComment;
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438 public function replaceEquationList "
2439 This function replaces the `EquationItem\' list in the `ClassPart\' list,
2440 and returns the updated list.
2441 "
2442 input list<Absyn.ClassPart> inAbsynClassPartLst;
2443 input list<Absyn.EquationItem> inAbsynEquationItemLst;
2444 output list<Absyn.ClassPart> outAbsynClassPartLst;
2445 algorithm
2446 outAbsynClassPartLst:=
2447 match (inAbsynClassPartLst,inAbsynEquationItemLst)
2448 local
2449 Absyn.ClassPart x;
2450 list<Absyn.ClassPart> rest,ys,xs;
2451 list<Absyn.EquationItem> newequationlst,new;
2452 13 case (((Absyn.EQUATIONS()) :: rest),newequationlst) then (Absyn.EQUATIONS(newequationlst) :: rest);
2453 case ((x :: xs),new)
2454 algorithm
2455 16 ys := replaceEquationList(xs, new);
2456 then
2457 (x :: ys);
2458 case ({},_) then {};
2459 end match;
2460 end replaceEquationList;
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470 public function getEquationList "This function takes a ClassPart List and returns the first EquationItem
2471 list of the class."
2472 input list<Absyn.ClassPart> inAbsynClassPartLst;
2473 output list<Absyn.EquationItem> outAbsynEquationItemLst;
2474 algorithm
2475 outAbsynEquationItemLst := match inAbsynClassPartLst
2476 local
2477 list<Absyn.EquationItem> lst,ys;
2478 list<Absyn.ClassPart> xs;
2479 case Absyn.EQUATIONS(contents = lst) :: _ then lst;
2480 case _ :: xs
2481 algorithm
2482 22 ys := getEquationList(xs);
2483 then
2484 ys;
2485 else fail();
2486 end match;
2487 end getEquationList;
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503 public function annotationListToAbsyn
2504 "This function takes a list of NamedArg and returns an Absyn.Annotation.
2505 for instance {annotation = Placement( ...) } is converted to ANNOTATION(Placement(...))"
2506 input list<Absyn.NamedArg> inAbsynNamedArgLst;
2507 output Absyn.Annotation outAnnotation;
2508 protected
2509 list<Absyn.ElementArg> args={};
2510 algorithm
2511
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 13 times.
26 for arg in inAbsynNamedArgLst loop
2512 args := match arg
2513 local
2514 Absyn.ElementArg eltarg;
2515 Absyn.Exp e;
2516 case Absyn.NAMEDARG(argName = "annotate",argValue = e)
2517 algorithm
2518 13 eltarg := recordConstructorToModification(e);
2519 then eltarg::args;
2520 case Absyn.NAMEDARG(argName = "comment") then args;
2521 else args;
2522 end match;
2523 end for;
2524 13 outAnnotation := Absyn.ANNOTATION(Dangerous.listReverseInPlace(args));
2525 end annotationListToAbsyn;
2526
2527 protected function recordConstructorToModification
2528 " This function takes a record constructor expression and translates
2529 it into a ElementArg. Since modifications must be named, only named
2530 arguments are treated in the record constructor."
2531 input Absyn.Exp inExp;
2532 output Absyn.ElementArg outElementArg;
2533 algorithm
2534 outElementArg:=
2535 matchcontinue inExp
2536 local
2537 list<Absyn.ElementArg> eltarglst;
2538 Absyn.ElementArg res,emod;
2539 Absyn.ComponentRef cr;
2540 list<Absyn.NamedArg> nargs;
2541 Absyn.Exp e;
2542 Absyn.Path p;
2543
2544 /* Covers the case annotate=Diagram(SOMETHING(x=1,y=2)) */
2545 case Absyn.CALL(function_ = cr,functionArgs = Absyn.FUNCTIONARGS(args = {(e as Absyn.CALL())},argNames = nargs))
2546 algorithm
2547 1 eltarglst := List.map(nargs, namedargToModification);
2548 1 emod := recordConstructorToModification(e);
2549 1 p := AbsynUtil.crefToPath(cr);
2550 2 res := Absyn.MODIFICATION(false,Absyn.NON_EACH(),p,SOME(Absyn.CLASSMOD((emod :: eltarglst),Absyn.NOMOD())),NONE(),Absyn.dummyInfo);
2551 then
2552 res;
2553 /* Covers the case annotate=Diagram(x=1,y=2) */
2554 case Absyn.CALL(function_ = cr,functionArgs = Absyn.FUNCTIONARGS(args = {},argNames = nargs))
2555 algorithm
2556 20 eltarglst := List.map(nargs, namedargToModification);
2557 20 p := AbsynUtil.crefToPath(cr);
2558 40 res := Absyn.MODIFICATION(false,Absyn.NON_EACH(),p,SOME(Absyn.CLASSMOD(eltarglst,Absyn.NOMOD())),NONE(),Absyn.dummyInfo);
2559 then
2560 res;
2561 /* Covers the case annotate=Diagram(1) */
2562 case Absyn.CALL(function_ = cr,functionArgs = Absyn.FUNCTIONARGS(args = {e}, argNames = {}))
2563 algorithm
2564 ✗ p := AbsynUtil.crefToPath(cr);
2565 ✗ res := Absyn.MODIFICATION(false,Absyn.NON_EACH(),p,SOME(Absyn.CLASSMOD({},Absyn.EQMOD(e,Absyn.dummyInfo))),NONE(),Absyn.dummyInfo);
2566 then
2567 res;
2568 else
2569 algorithm
2570 ✗ Print.printBuf("InteractiveUtil.recordConstructorToModification failed, exp=");
2571 ✗ Print.printBuf(Dump.printExpStr(inExp));
2572 ✗ Print.printBuf("\n");
2573 ✗ then
2574 fail();
2575 end matchcontinue;
2576 end recordConstructorToModification;
2577
2578 protected function namedargToModification
2579 "This function takes a NamedArg and translates it into a ElementArg."
2580 input Absyn.NamedArg inNamedArg;
2581 output Absyn.ElementArg outElementArg;
2582 algorithm
2583 outElementArg:=
2584 matchcontinue inNamedArg
2585 local
2586 list<Absyn.ElementArg> elts;
2587 Absyn.ElementArg res;
2588 String id;
2589 Absyn.Exp c,e;
2590 case Absyn.NAMEDARG(argName = id,argValue = (c as Absyn.CALL(functionArgs = Absyn.FUNCTIONARGS(args = {}))))
2591 algorithm
2592
5/10
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
3 Absyn.MODIFICATION(modification = SOME(Absyn.CLASSMOD(elts,_)), comment = NONE()) := recordConstructorToModification(c);
2593 6 res := Absyn.MODIFICATION(false,Absyn.NON_EACH(),Absyn.IDENT(id),SOME(Absyn.CLASSMOD(elts,Absyn.NOMOD())),NONE(),Absyn.dummyInfo);
2594 then
2595 res;
2596 case Absyn.NAMEDARG(argName = id,argValue = e)
2597 algorithm
2598 72 res := Absyn.MODIFICATION(false,Absyn.NON_EACH(),Absyn.IDENT(id),SOME(Absyn.CLASSMOD({},Absyn.EQMOD(e,Absyn.dummyInfo /*Bad*/))),NONE(),Absyn.dummyInfo);
2599 then
2600 res;
2601 else
2602 algorithm
2603 ✗ Print.printBuf("- InteractiveUtil.namedargToModification failed\n");
2604 ✗ then
2605 fail();
2606 end matchcontinue;
2607 end namedargToModification;
2608
2609
2610
2611
2612
2613
2614
2615 public function getAllInheritedClasses
2616 input Absyn.Path inClassName;
2617 input Absyn.Program inProgram;
2618 output list<Absyn.Path> outBaseClassNames;
2619 protected
2620 GraphicEnvCache genv;
2621 algorithm
2622 outBaseClassNames :=
2623 matchcontinue (inClassName,inProgram)
2624 local
2625 Absyn.Path p_class;
2626 list<Absyn.Path> paths, fqpaths, allPaths = {};
2627 Absyn.Class cdef;
2628 list<Absyn.ElementSpec> exts;
2629 Absyn.Program p;
2630
2631 case (p_class,p)
2632 algorithm
2633 13087 cdef := ProgramUtil.getPathedClassInProgram(p_class, p);
2634 12452 exts := getExtendsElementspecInClass(cdef);
2635 12452 paths := List.map(exts, getBaseClassNameFromExtends);
2636 fqpaths := {};
2637 try
2638 12452 genv := createEnvironment(p, NONE(), p_class);
2639
2/2
✓ Branch 0 taken 7579 times.
✓ Branch 1 taken 12452 times.
20031 for pt in paths loop
2640 7579 fqpaths := qualifyPath(genv, pt) :: fqpaths;
2641 end for;
2642 12452 fqpaths := listReverse(fqpaths);
2643 else
2644 // print("Bummer: " + AbsynUtil.pathString(p_class) + "\n");
2645 ✗ fqpaths := paths;
2646 end try;
2647 allPaths := {};
2648
2/2
✓ Branch 0 taken 7579 times.
✓ Branch 1 taken 12452 times.
20031 for pt in fqpaths loop
2649 7579 allPaths := List.append_reverse(getAllInheritedClasses(pt, p), allPaths);
2650 end for;
2651 12452 allPaths := Dangerous.listReverseInPlace(List.unique(allPaths));
2652 12452 then
2653 listAppend(fqpaths, allPaths);
2654
2655 else {};
2656 end matchcontinue;
2657 end getAllInheritedClasses;
2658
2659 public function getBaseClassNameFromExtends
2660 "function: getBaseClassNameFromExtends"
2661 input Absyn.ElementSpec inElementSpec;
2662 output Absyn.Path outBaseClassPath;
2663 algorithm
2664 outBaseClassPath := match inElementSpec
2665 local
2666 Absyn.Path path;
2667
2668 case Absyn.EXTENDS(path = path) then path;
2669 end match;
2670 end getBaseClassNameFromExtends;
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680 uniontype ClassEntry
2681 record CLASS_ENTRY
2682 Absyn.Path path;
2683 Absyn.Class cls;
2684 end CLASS_ENTRY;
2685
2686 function getPath
2687 input ClassEntry entry;
2688 output Absyn.Path path = entry.path;
2689 end getPath;
2690
2691 function greaterEq
2692 input ClassEntry entry1;
2693 input ClassEntry entry2;
2694 output Boolean res = AbsynUtil.pathGe(entry1.path, entry2.path);
2695 end greaterEq;
2696
2697 function equal
2698 input ClassEntry entry1;
2699 input ClassEntry entry2;
2700 output Boolean res = referenceEq(entry1.cls, entry2.cls);
2701 end equal;
2702 end ClassEntry;
2703
2704 public function getAllSubtypeOf
2705 input Absyn.Path baseClass;
2706 input Absyn.Path parentClass;
2707 input Absyn.Program program;
2708 input Boolean includePartial;
2709 input Boolean sort;
2710 output list<Absyn.Path> paths;
2711 protected
2712 list<ClassEntry> classes;
2713 algorithm
2714 5 classes := getAllSubtypeOf2(baseClass, parentClass, program, includePartial, sort);
2715
4/4
✓ Branch 0 taken 85 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 85 times.
✓ Branch 3 taken 5 times.
90 paths := list(ClassEntry.getPath(c) for c in classes);
2716 end getAllSubtypeOf;
2717
2718 public function getReplaceableChoices
2719 input Absyn.Path baseClass;
2720 input Absyn.Path parentClass;
2721 input Absyn.Program program;
2722 input Boolean includePartial;
2723 input Boolean sort;
2724 output Values.Value res;
2725 protected
2726 list<ClassEntry> classes;
2727 list<Values.Value> vals = {};
2728 Values.Value name_val, cmt_val;
2729 algorithm
2730 1 classes := getAllSubtypeOf2(baseClass, parentClass, program, includePartial, sort);
2731
2732
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1 time.
5 for entry in classes loop
2733 4 name_val := ValuesMake.makeString(AbsynUtil.pathString(entry.path));
2734 4 cmt_val := ValuesMake.makeString(AbsynUtil.classDefStringComment(entry.cls.body));
2735 4 vals := ValuesMake.makeArray({name_val, cmt_val}) :: vals;
2736 end for;
2737
2738 1 res := ValuesMake.makeArray(Dangerous.listReverseInPlace(vals));
2739 end getReplaceableChoices;
2740
2741 protected function getAllSubtypeOfCandidates
2742 "Returns a list of all classes that needs to be considered by getAllSubtypeOf"
2743 input Absyn.Path path;
2744 input Absyn.Path parentClass;
2745 input Absyn.Program program;
2746 input Boolean includePartial;
2747 input output list<ClassEntry> candidates;
2748 protected
2749 Absyn.Class cdef;
2750 list<String> names;
2751 list<Absyn.Path> paths;
2752 Boolean is_parent;
2753 algorithm
2754 try
2755 5503 cdef := ProgramUtil.getPathedClassInProgram(path, program);
2756 else
2757 ✗ return;
2758 end try;
2759
2760 // Only add non-partial classes if includePartial = false.
2761
4/4
✓ Branch 0 taken 5495 times.
✓ Branch 1 taken 8 times.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 5494 times.
5503 if includePartial or AbsynUtil.isNotPartial(cdef) then
2762 5502 candidates := ClassEntry.CLASS_ENTRY(path, cdef) :: candidates;
2763
2764 // Only recurse into packages, unless it's the parent class in which case we
2765 // also want to include local classes.
2766 5502 is_parent := AbsynUtil.pathEqual(path, parentClass);
2767
4/4
✓ Branch 1 taken 4735 times.
✓ Branch 2 taken 767 times.
✓ Branch 3 taken 4731 times.
✓ Branch 4 taken 4 times.
5502 if AbsynUtil.isPackageRestriction(cdef.restriction) or is_parent then
2768 771 names := getClassnamesInClassListNoPartial(path, program, cdef, is_parent, false);
2769
4/4
✓ Branch 0 taken 5481 times.
✓ Branch 1 taken 771 times.
✓ Branch 2 taken 5481 times.
✓ Branch 3 taken 771 times.
6252 paths := list(AbsynUtil.suffixPath(path, n) for n in names);
2770
1/2
✓ Branch 0 taken 771 times.
✗ Branch 1 not taken.
1542 candidates := List.fold(paths,
2771 function getAllSubtypeOfCandidates(program = program, parentClass = parentClass, includePartial = includePartial), candidates);
2772 end if;
2773 end if;
2774 end getAllSubtypeOfCandidates;
2775
2776 public function getAllSubtypeOf2
2777 "Returns the list of all classes that extend from class_ given a parentClass where the lookup for class_ should start"
2778 input Absyn.Path baseClass;
2779 input Absyn.Path parentClass;
2780 input Absyn.Program program;
2781 input Boolean includePartial;
2782 input Boolean sort;
2783 output list<ClassEntry> entries;
2784 protected
2785 list<String> strlst;
2786 Absyn.Path p, parent, base_class;
2787 Absyn.Class cls;
2788 ClassEntry base_entry;
2789 list<Absyn.Class> classes;
2790 list<Absyn.Path> result_path_lst;
2791 list<ClassEntry> acc, locals;
2792 list<tuple<Absyn.Path, list<ClassEntry>>> candidates = {};
2793 GraphicEnvCache genv;
2794 Option<Absyn.Path> opt_path;
2795 algorithm
2796 // Collect candidates inherited by the parent class. Do this first so they
2797 // end up after the local ones but before all the rest in the result list.
2798
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 6 times.
8 for ext in getAllInheritedClasses(parentClass, program) loop
2799 2 acc := getAllSubtypeOfCandidates(ext, ext, program, includePartial, {});
2800 2 candidates := (ext, acc) :: candidates;
2801 end for;
2802
2803 // Collect candidates in the rest of the program.
2804 6 Absyn.PROGRAM(classes=classes) := program;
2805
2806
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 if not includePartial then
2807
6/6
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 15 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 12 times.
✓ Branch 6 taken 4 times.
19 classes := list(c for c guard AbsynUtil.isNotPartial(c) in classes);
2808 end if;
2809
2810 6 strlst := List.map(classes, AbsynUtil.getClassName);
2811
4/4
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 6 times.
26 result_path_lst := list(AbsynUtil.makeIdentPathFromString(str) for str in strlst);
2812
2813 acc := {};
2814
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 6 times.
26 for p in result_path_lst loop
2815 20 acc := getAllSubtypeOfCandidates(p, parentClass, program, includePartial, acc);
2816 end for;
2817 6 candidates := (parentClass, acc) :: candidates;
2818
2819 // Fully qualify the base class we're looking for.
2820 try
2821 6 genv := createEnvironment(program, NONE(), parentClass);
2822 6 base_class := qualifyPath(genv, baseClass, failOnError = true);
2823 else
2824 entries := {};
2825 ✗ return;
2826 end try;
2827
2828 // Go through all the candidates and find which ones extend from the base class.
2829 entries := {};
2830 locals := {};
2831
2832
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 6 times.
14 for tup in candidates loop
2833 8 (parent, acc) := tup;
2834
2835
2/2
✓ Branch 0 taken 5502 times.
✓ Branch 1 taken 8 times.
5510 for entry in acc loop
2836
2/2
✓ Branch 1 taken 86 times.
✓ Branch 2 taken 5416 times.
5502 if isSubtypeOf(entry.path, base_class, program) then
2837 // Put classes declared locally in the parent class first in the list and
2838 // remove the parent prefix from their name, since they're usually meant
2839 // to be the default option.
2840 86 opt_path := AbsynUtil.removePrefixOpt(parent, entry.path);
2841
2842
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 86 times.
✓ Branch 2 taken 83 times.
✓ Branch 3 taken 3 times.
86 if isSome(opt_path) then
2843 3 entry.path := Util.getOption(opt_path);
2844 locals := entry :: locals;
2845 else
2846 entries := entry :: entries;
2847 end if;
2848 end if;
2849 end for;
2850 end for;
2851
2852 // Also add the base class itself if it's a candidate.
2853 6 cls := ProgramUtil.getPathedClassInProgram(base_class, program);
2854 6 base_entry := ClassEntry.CLASS_ENTRY(base_class, cls);
2855
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3 times.
11 for tup in candidates loop
2856 8 (_, acc) := tup;
2857
2858
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 5 times.
8 if List.contains(acc, base_entry, ClassEntry.equal) then
2859 entries := base_entry :: entries;
2860 break;
2861 end if;
2862 end for;
2863
2864 6 entries := listAppend(locals, entries);
2865 6 entries := List.uniqueOnTrue(entries, ClassEntry.equal);
2866
2867
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 time.
6 if sort then
2868 1 entries := List.sort(entries, ClassEntry.greaterEq);
2869 end if;
2870 end getAllSubtypeOf2;
2871
2872 protected function isSubtypeOf
2873 input Absyn.Path classPath;
2874 input Absyn.Path baseClassPath;
2875 input Absyn.Program program;
2876 output Boolean res;
2877 protected
2878 list<Absyn.Path> base_classes;
2879 algorithm
2880 5502 base_classes := getAllInheritedClasses(classPath, program);
2881 5502 res := List.contains(base_classes, baseClassPath, AbsynUtil.pathSuffixOfr);
2882 end isSubtypeOf;
2883
2884 public function updateConnectionAnnotation
2885 "Updates a connection annotation in a model."
2886 input Absyn.ComponentRef inClass;
2887 input String inFrom;
2888 input String inTo;
2889 input list<Absyn.NamedArg> inAnnotation;
2890 input Absyn.Program inProgram;
2891 output Absyn.Program outProgram;
2892 protected
2893 Absyn.Path class_path;
2894 Absyn.Class cls;
2895 Absyn.Within class_within;
2896 algorithm
2897 1 class_path := AbsynUtil.crefToPath(inClass);
2898 1 cls := ProgramUtil.getPathedClassInProgram(class_path, inProgram);
2899 1 cls := updateConnectionAnnotationInClass(cls, inFrom, inTo, annotationListToAbsyn(inAnnotation));
2900
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 class_within := if AbsynUtil.pathIsIdent(class_path) then
2901 Absyn.TOP() else Absyn.WITHIN(AbsynUtil.stripLast(class_path));
2902 1 outProgram := ProgramUtil.updateProgram(Absyn.PROGRAM({cls}, class_within), inProgram);
2903 end updateConnectionAnnotation;
2904
2905 public function updateConnectionAnnotationInClass
2906 "Helper function to updateConnectionAnnotation."
2907 input Absyn.Class inClass1;
2908 input String inFrom;
2909 input String inTo;
2910 input Absyn.Annotation inAnnotation;
2911 output Absyn.Class outClass;
2912 algorithm
2913 outClass:=
2914 match (inClass1, inFrom, inTo, inAnnotation)
2915 local
2916 list<Absyn.EquationItem> eqlst,eqlst_1;
2917 list<Absyn.ClassPart> parts2,parts;
2918 String bcname;
2919 Option<String> cmt;
2920 list<Absyn.ElementArg> modif;
2921 list<String> typeVars;
2922 list<Absyn.NamedArg> classAttrs;
2923 list<Absyn.Annotation> ann;
2924 String from, to;
2925 Absyn.Annotation annotation_;
2926 /* a class with parts */
2927 case (outClass as Absyn.CLASS(body = Absyn.PARTS(typeVars = typeVars,classAttrs = classAttrs,classParts = parts,ann=ann,comment = cmt)),from,to,annotation_)
2928 algorithm
2929 3 eqlst := getEquationList(parts);
2930 3 eqlst_1 := updateConnectionAnnotationInEqList(eqlst, from, to, annotation_);
2931 3 parts2 := replaceEquationList(parts, eqlst_1);
2932 6 outClass.body := Absyn.PARTS(typeVars,classAttrs,parts2,ann,cmt);
2933 then
2934 outClass;
2935 /* an extended class with parts: model extends M end M; */
2936 case (outClass as Absyn.CLASS(body = Absyn.CLASS_EXTENDS(baseClassName = bcname,modifications=modif,parts = parts,ann = ann,comment = cmt)),from,to,annotation_)
2937 algorithm
2938 ✗ eqlst := getEquationList(parts);
2939 ✗ eqlst_1 := updateConnectionAnnotationInEqList(eqlst, from, to, annotation_);
2940 ✗ parts2 := replaceEquationList(parts, eqlst_1);
2941 ✗ outClass.body := Absyn.CLASS_EXTENDS(bcname,modif,cmt,parts2,ann);
2942 then
2943 outClass;
2944 end match;
2945 end updateConnectionAnnotationInClass;
2946
2947 protected function updateConnectionAnnotationInEqList
2948 "Helper function to updateConnectionAnnotation."
2949 input list<Absyn.EquationItem> equations;
2950 input String from;
2951 input String to;
2952 input Absyn.Annotation ann;
2953 output list<Absyn.EquationItem> outEquations = {};
2954 protected
2955 Absyn.ComponentRef c1, c2;
2956 String c1_str, c2_str;
2957 Boolean found = false;
2958 algorithm
2959
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 for eq in equations loop
2960
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if not found then
2961 eq := match eq
2962 case Absyn.EQUATIONITEM(equation_ = Absyn.EQ_CONNECT(connector1 = c1, connector2 = c2))
2963 algorithm
2964 3 c1_str := AbsynUtil.crefString(c1);
2965 3 c2_str := AbsynUtil.crefString(c2);
2966
2967
4/8
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
3 if (c1_str == from and c2_str == to) then
2968 found := true;
2969 end if;
2970 if not found then
2971 ✗ found := (c1_str == to and c2_str == from);
2972 end if;
2973 if found then
2974 6 eq.comment := SOME(Absyn.COMMENT(SOME(ann), NONE()));
2975 end if;
2976 then
2977 eq;
2978
2979 else eq;
2980 end match;
2981 end if;
2982
2983 outEquations := eq :: outEquations;
2984 end for;
2985
2986 3 outEquations := Dangerous.listReverseInPlace(outEquations);
2987 end updateConnectionAnnotationInEqList;
2988
2989 public function updateConnectionNames
2990 "Updates a connection connector names in a model."
2991 input Absyn.Path inPath;
2992 input String inFrom;
2993 input String inTo;
2994 input String inFromNew;
2995 input String inToNew;
2996 input Absyn.Program inProgram;
2997 output Boolean outResult;
2998 output Absyn.Program outProgram;
2999 algorithm
3000 (outResult, outProgram) := matchcontinue (inPath, inFrom, inTo, inFromNew, inToNew, inProgram)
3001 local
3002 Absyn.Path path, modelwithin;
3003 String from, to, fromNew, toNew;
3004 Absyn.Class cdef, newcdef;
3005 Absyn.Program newp, p;
3006
3007 case (path, from, to, fromNew, toNew, (p as Absyn.PROGRAM()))
3008 algorithm
3009 ✗ modelwithin := AbsynUtil.stripLast(path);
3010 ✗ cdef := ProgramUtil.getPathedClassInProgram(path, p);
3011 ✗ newcdef := updateConnectionNamesInClass(cdef, from, to, fromNew, toNew);
3012 ✗ newp := ProgramUtil.updateProgram(Absyn.PROGRAM({newcdef},Absyn.WITHIN(modelwithin)), p);
3013 then
3014 (true, newp);
3015
3016 case (path, from, to, fromNew, toNew, (p as Absyn.PROGRAM()))
3017 algorithm
3018 ✗ cdef := ProgramUtil.getPathedClassInProgram(path, p);
3019 ✗ newcdef := updateConnectionNamesInClass(cdef, from, to, fromNew, toNew);
3020 ✗ newp := ProgramUtil.updateProgram(Absyn.PROGRAM({newcdef},Absyn.TOP()), p);
3021 then
3022 (true, newp);
3023
3024 case (_, _, _, _, _, (p as Absyn.PROGRAM())) then (false, p);
3025 end matchcontinue;
3026 end updateConnectionNames;
3027
3028 protected function updateConnectionNamesInClass
3029 "Helper function to updateConnectionNames."
3030 input Absyn.Class inClass1;
3031 input String inFrom;
3032 input String inTo;
3033 input String inFromNew;
3034 input String inToNew;
3035 output Absyn.Class outClass;
3036 algorithm
3037 outClass:=
3038 match (inClass1, inFrom, inTo, inFromNew, inToNew)
3039 local
3040 list<Absyn.EquationItem> eqlst,eqlst_1;
3041 list<Absyn.ClassPart> parts2,parts;
3042 String bcname;
3043 Option<String> cmt;
3044 list<Absyn.ElementArg> modif;
3045 list<String> typeVars;
3046 list<Absyn.NamedArg> classAttrs;
3047 list<Absyn.Annotation> ann;
3048 String from, to, fromNew, toNew;
3049 /* a class with parts */
3050 case (outClass as Absyn.CLASS(body = Absyn.PARTS(typeVars = typeVars,classAttrs = classAttrs,classParts = parts,ann=ann,comment = cmt)),from,to,fromNew,toNew)
3051 algorithm
3052 ✗ eqlst := getEquationList(parts);
3053 ✗ eqlst_1 := updateConnectionNamesInEqList(eqlst, from, to, fromNew, toNew);
3054 ✗ parts2 := replaceEquationList(parts, eqlst_1);
3055 ✗ outClass.body := Absyn.PARTS(typeVars,classAttrs,parts2,ann,cmt);
3056 then
3057 outClass;
3058 /* an extended class with parts: model extends M end M; */
3059 case (outClass as Absyn.CLASS(body = Absyn.CLASS_EXTENDS(baseClassName = bcname,modifications=modif,parts = parts,ann = ann,comment = cmt)),from,to,fromNew,toNew)
3060 algorithm
3061 ✗ eqlst := getEquationList(parts);
3062 ✗ eqlst_1 := updateConnectionNamesInEqList(eqlst, from, to, fromNew, toNew);
3063 ✗ parts2 := replaceEquationList(parts, eqlst_1);
3064 ✗ outClass.body := Absyn.CLASS_EXTENDS(bcname,modif,cmt,parts2,ann);
3065 then
3066 outClass;
3067 end match;
3068 end updateConnectionNamesInClass;
3069
3070 protected function updateConnectionNamesInEqList
3071 "Helper function to updateConnectionNames."
3072 input list<Absyn.EquationItem> equations;
3073 input String from;
3074 input String to;
3075 input String fromNew;
3076 input String toNew;
3077 output list<Absyn.EquationItem> outEquations = {};
3078 protected
3079 Absyn.ComponentRef c1, c2;
3080 String c1_str, c2_str;
3081 Boolean found = false;
3082
3083 algorithm
3084 ✗ for eq in equations loop
3085 ✗ if not found then
3086 eq := match eq
3087 case Absyn.EQUATIONITEM(equation_ = Absyn.EQ_CONNECT(connector1 = c1, connector2 = c2))
3088 algorithm
3089 ✗ c1_str := AbsynUtil.crefString(c1);
3090 ✗ c2_str := AbsynUtil.crefString(c2);
3091
3092 ✗ found := if (c1_str == from and c2_str == to) then true else (c1_str == to and c2_str == from);
3093 if found then
3094 ✗ eq.equation_ := Absyn.EQ_CONNECT(Parser.stringCref(fromNew), Parser.stringCref(toNew));
3095 end if;
3096 then
3097 eq;
3098
3099 else eq;
3100 end match;
3101 end if;
3102
3103 outEquations := eq :: outEquations;
3104 end for;
3105
3106 ✗ outEquations := Dangerous.listReverseInPlace(outEquations);
3107 end updateConnectionNamesInEqList;
3108
3109 protected function getClassnamesInClassListNoPartial
3110 input Absyn.Path inPath;
3111 input Absyn.Program inProgram;
3112 input Absyn.Class inClass;
3113 input Boolean inShowProtected;
3114 input Boolean includeConstants;
3115 output list<String> outString;
3116 algorithm
3117
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 771 times.
771 if AbsynUtil.isPartial(inClass) then
3118 outString := {};
3119 ✗ return;
3120 end if;
3121
3122 outString:=
3123 match (inClass, inShowProtected, includeConstants)
3124 local
3125 list<String> strlist;
3126 list<Absyn.ClassPart> parts;
3127 Boolean b,c;
3128
3129 case (Absyn.CLASS(body = Absyn.PARTS(classParts = parts)), b, c)
3130 algorithm
3131 765 strlist := getClassnamesInPartsNoPartial(parts,b,c);
3132 then
3133 strlist;
3134
3135 case (Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)), b, c)
3136 algorithm
3137 ✗ strlist := getClassnamesInPartsNoPartial(parts,b,c);
3138 then strlist;
3139
3140 case (Absyn.CLASS(body = Absyn.DERIVED(typeSpec=Absyn.TPATH())), _, _)
3141 algorithm
3142 //(cdef,newpath) = lookupClassdef(path, inmodel, p);
3143 //res = getClassnamesInClassListNoPartial(newpath, p, cdef);
3144 then
3145 {};//res;
3146
3147 case (Absyn.CLASS(body = Absyn.OVERLOAD()), _, _)
3148 algorithm
3149 then {};
3150
3151 case (Absyn.CLASS(body = Absyn.ENUMERATION()), _, _)
3152 algorithm
3153 then {};
3154
3155 case (Absyn.CLASS(body = Absyn.PDER()), _, _)
3156 algorithm
3157 then {};
3158
3159 end match;
3160 end getClassnamesInClassListNoPartial;
3161
3162 public function getClassnamesInPartsNoPartial
3163 "Helper function to ProgramUtil.getClassnamesInClass."
3164 input list<Absyn.ClassPart> inAbsynClassPartLst;
3165 input Boolean inShowProtected;
3166 input Boolean includeConstants;
3167 output list<String> outStringLst;
3168 algorithm
3169 outStringLst:=
3170 matchcontinue (inAbsynClassPartLst,inShowProtected,includeConstants)
3171 local
3172 list<String> l1,l2,res;
3173 list<Absyn.ElementItem> elts;
3174 list<Absyn.ClassPart> rest;
3175 Boolean b,c;
3176
3177 case ({},_,_) then {};
3178
3179 case ((Absyn.PUBLIC(contents = elts) :: rest),b,c)
3180 algorithm
3181 771 l1 := getClassnamesInEltsNoPartial(elts,c);
3182 771 l2 := getClassnamesInPartsNoPartial(rest,b,c);
3183 771 res := listAppend(l1, l2);
3184 then
3185 res;
3186
3187 // adeas31 2012-01-25: Also check the protected sections.
3188 case ((Absyn.PROTECTED(contents = elts) :: rest), true, c)
3189 algorithm
3190 ✗ l1 := getClassnamesInEltsNoPartial(elts,c);
3191 ✗ l2 := getClassnamesInPartsNoPartial(rest,true,c);
3192 ✗ res := listAppend(l1, l2);
3193 then
3194 res;
3195
3196 case ((_ :: rest),b,c)
3197 algorithm
3198 6 res := getClassnamesInPartsNoPartial(rest,b,c);
3199 then
3200 res;
3201
3202 end matchcontinue;
3203 end getClassnamesInPartsNoPartial;
3204
3205 public function getClassnamesInEltsNoPartial
3206 "Helper function to getClassnamesInPartsNoPartial."
3207 input list<Absyn.ElementItem> inAbsynElementItemLst;
3208 input Boolean includeConstants;
3209 output list<String> outStringLst;
3210 protected
3211 DoubleEnded.MutableList<String> delst;
3212 algorithm
3213 771 delst := DoubleEnded.fromList({});
3214
2/2
✓ Branch 0 taken 8359 times.
✓ Branch 1 taken 771 times.
9130 for elt in inAbsynElementItemLst loop
3215 () := match elt
3216 local
3217 String id;
3218 list<Absyn.ComponentItem> lst;
3219
3220 case Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = Absyn.CLASSDEF(class_ =
3221 Absyn.CLASS(partialPrefix=false, body = Absyn.CLASS_EXTENDS(baseClassName = id)))))
3222 algorithm
3223 152 DoubleEnded.push_back(delst, id);
3224 then ();
3225
3226 case Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = Absyn.CLASSDEF(class_ =
3227 Absyn.CLASS(partialPrefix=false, name = id))))
3228 algorithm
3229 5329 DoubleEnded.push_back(delst, id);
3230 then ();
3231
3232 case Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = Absyn.COMPONENTS(attributes = Absyn.ATTR(variability = Absyn.CONST()),
3233 components = lst))) guard includeConstants
3234 algorithm
3235 ✗ DoubleEnded.push_list_back(delst, ProgramUtil.getComponentItemsName(lst,false));
3236 then ();
3237
3238 else ();
3239 end match;
3240 end for;
3241 771 outStringLst := DoubleEnded.toListAndClear(delst);
3242 end getClassnamesInEltsNoPartial;
3243
3244 public function removeInnerClass "
3245 This function takes two class definitions. The first one is the local
3246 class that should be removed from the second one.
3247 "
3248 input Absyn.Class inClass1;
3249 input Absyn.Class inClass2;
3250 output Absyn.Class outClass;
3251 algorithm
3252 outClass:=
3253 matchcontinue (inClass1,inClass2)
3254 local
3255 list<Absyn.ElementItem> publst,publst2,prolst,prolst2;
3256 list<Absyn.ClassPart> parts2,parts;
3257 Absyn.Class c1;
3258 String a,bcname,n;
3259 Option<String> cmt;
3260 SourceInfo file_info;
3261 list<Absyn.ElementArg> modif;
3262 list<String> typeVars;
3263 list<Absyn.NamedArg> classAttrs;
3264 list<Absyn.Annotation> ann;
3265
3266 // a class with parts - class found in public
3267 case (c1,outClass as Absyn.CLASS(
3268 body = Absyn.PARTS(typeVars = typeVars, classAttrs = classAttrs, classParts = parts,ann = ann, comment = cmt)))
3269 algorithm
3270 1 publst := ProgramUtil.getPublicList(parts);
3271 1 publst2 := removeClassInElementitemlist(publst, c1);
3272 1 parts2 := ProgramUtil.replacePublicList(parts, publst2);
3273 2 outClass.body := Absyn.PARTS(typeVars,classAttrs,parts2,ann,cmt);
3274 then
3275 outClass;
3276
3277 // a class with parts - class found in protected
3278 case (c1,outClass as Absyn.CLASS(
3279 body = Absyn.PARTS(typeVars = typeVars, classAttrs = classAttrs, classParts = parts,ann = ann, comment = cmt)))
3280 algorithm
3281 ✗ prolst := ProgramUtil.getProtectedList(parts);
3282 ✗ prolst2 := removeClassInElementitemlist(prolst, c1);
3283 ✗ parts2 := ProgramUtil.replaceProtectedList(parts, prolst2);
3284 ✗ outClass.body := Absyn.PARTS(typeVars,classAttrs,parts2,ann,cmt);
3285 then
3286 outClass;
3287
3288 // an extended class with parts: model extends M end M; - class found in public
3289 case (c1,outClass as Absyn.CLASS(
3290 body = Absyn.CLASS_EXTENDS(baseClassName=bcname,modifications=modif,parts = parts,comment = cmt,ann = ann)))
3291 algorithm
3292 ✗ publst := ProgramUtil.getPublicList(parts);
3293 ✗ publst2 := removeClassInElementitemlist(publst, c1);
3294 ✗ parts2 := ProgramUtil.replacePublicList(parts, publst2);
3295 ✗ outClass.body := Absyn.CLASS_EXTENDS(bcname,modif,cmt,parts2,ann);
3296 then
3297 outClass;
3298
3299 // an extended class with parts: model extends M end M; - class found in protected
3300 case (c1,outClass as Absyn.CLASS(
3301 body = Absyn.CLASS_EXTENDS(baseClassName=bcname,modifications=modif,parts = parts,comment = cmt,ann = ann)))
3302 algorithm
3303 ✗ prolst := ProgramUtil.getProtectedList(parts);
3304 ✗ prolst2 := removeClassInElementitemlist(prolst, c1);
3305 ✗ parts2 := ProgramUtil.replaceProtectedList(parts, prolst2);
3306 ✗ outClass.body := Absyn.CLASS_EXTENDS(bcname,modif,cmt,parts2,ann);
3307 then
3308 outClass;
3309
3310 // class not found anywhere!
3311 case (Absyn.CLASS(name = n),Absyn.CLASS(name = a, info = file_info))
3312 algorithm
3313 ✗ Error.addSourceMessage(Error.CLASS_NOT_FOUND, {n, a}, file_info);
3314 ✗ then
3315 fail();
3316
3317 end matchcontinue;
3318 end removeInnerClass;
3319
3320 protected function removeClassInElementitemlist
3321 " This function takes an Element list and a Class and returns a modified
3322 element list where the class definition of the class is removed."
3323 input list<Absyn.ElementItem> inElements;
3324 input Absyn.Class inClass;
3325 output list<Absyn.ElementItem> outElements;
3326 protected
3327 String name;
3328 algorithm
3329 1 Absyn.CLASS(name = name) := inClass;
3330 1 outElements := List.deleteMemberOnTrue(name, inElements, ProgramUtil.classElementItemIsNamed);
3331 end removeClassInElementitemlist;
3332
3333 public function getPathedElementInProgram
3334 "Looks up an element in the program using the given path."
3335 input Absyn.Path path;
3336 input Absyn.Program program;
3337 output Absyn.Element element;
3338 protected
3339 Absyn.Class cls;
3340 algorithm
3341 try
3342 9 cls := ProgramUtil.getClassInProgram(AbsynUtil.pathFirstIdent(path), program);
3343 else
3344 1 cls := ProgramUtil.getClassInProgram(AbsynUtil.pathFirstIdent(path), FBuiltin.getInitialFunctions());
3345 end try;
3346
3347
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 6 times.
9 if AbsynUtil.pathIsIdent(path) then
3348 // Since the program only stores classes instead of elements we have to
3349 // create a dummy element if we find a top-level class.
3350 3 element := Absyn.Element.ELEMENT(false, NONE(), Absyn.InnerOuter.NOT_INNER_OUTER(),
3351 Absyn.ElementSpec.CLASSDEF(false, cls), cls.info, NONE());
3352 else
3353
2/4
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
6 SOME(element) := getPathedElementInClass(AbsynUtil.pathRest(path), cls);
3354 end if;
3355 end getPathedElementInProgram;
3356
3357 protected function getPathedElementInClass
3358 input Absyn.Path path;
3359 input Absyn.Class cls;
3360 output Option<Absyn.Element> element = NONE();
3361 algorithm
3362
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 for part in AbsynUtil.getClassPartsInClass(cls) loop
3363 7 element := getPathedElementInClassPart(path, part);
3364
3365
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
7 if isSome(element) then
3366 break;
3367 end if;
3368 end for;
3369 end getPathedElementInClass;
3370
3371 protected function getPathedElementInClassPart
3372 input Absyn.Path path;
3373 input Absyn.ClassPart part;
3374 output Option<Absyn.Element> element = NONE();
3375 protected
3376 Absyn.Element e;
3377 algorithm
3378
1/2
✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
13 for item in AbsynUtil.getElementItemsInClassPart(part) loop
3379
2/2
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 6 times.
13 if AbsynUtil.isElementItemNamed(AbsynUtil.pathFirstIdent(path), item) then
3380
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 Absyn.ElementItem.ELEMENTITEM(element = e) := item;
3381
3382
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 1 time.
7 if AbsynUtil.pathIsIdent(path) then
3383 element := SOME(e);
3384 else
3385 1 element := getPathedElementInElement(AbsynUtil.pathRest(path), e);
3386 end if;
3387
3388 break;
3389 end if;
3390 end for;
3391 end getPathedElementInClassPart;
3392
3393 protected function getPathedElementInElement
3394 input Absyn.Path path;
3395 input Absyn.Element element;
3396 output Option<Absyn.Element> outElement;
3397 protected
3398 Absyn.Class cls;
3399 algorithm
3400 outElement := match element
3401 case Absyn.Element.ELEMENT(specification = Absyn.ElementSpec.CLASSDEF(class_ = cls))
3402 1 then getPathedElementInClass(path, cls);
3403 else NONE();
3404 end match;
3405 end getPathedElementInElement;
3406
3407 public function getPathedExtendsInProgram
3408 "Returns the extends clause that matches the fully qualified extends path in
3409 the given class."
3410 input Absyn.Path classPath;
3411 input Absyn.Path extendsPath;
3412 input Absyn.Program program;
3413 output Option<Absyn.ElementSpec> extendsSpec;
3414 protected
3415 Absyn.Class cls;
3416 GraphicEnvCache env;
3417 algorithm
3418 try
3419 27 cls := ProgramUtil.getPathedClassInProgram(classPath, program);
3420 27 env := Interactive.getClassEnv(program, classPath);
3421
3422
1/2
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
54 for ext in getExtendsElementspecInClass(cls) loop
3423 27 ext := Interactive.makeExtendsFullyQualified(ext, env);
3424
3425
1/2
✓ Branch 2 taken 27 times.
✗ Branch 3 not taken.
27 if AbsynUtil.pathEqual(extendsPath, AbsynUtil.elementSpecToPath(ext)) then
3426 extendsSpec := SOME(ext);
3427 27 return;
3428 end if;
3429 end for;
3430 else
3431 end try;
3432
3433 extendsSpec := NONE();
3434 end getPathedExtendsInProgram;
3435
3436 public function transformPathedElementInList<T>
3437 input list<T> inList;
3438 input FuncType inFunc;
3439 output list<T> outList = {};
3440 output Option<Absyn.Element> outElement = NONE();
3441 output Boolean outFound = false;
3442
3443 partial function FuncType
3444 input output T t;
3445 output Option<Absyn.Element> outElement;
3446 output Boolean outFound;
3447 end FuncType;
3448 protected
3449 T e;
3450 list<T> rest = inList;
3451 algorithm
3452
4/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 2 times.
22 while not listEmpty(rest) and not outFound loop
3453 11 e :: rest := rest;
3454
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 (e, outElement, outFound) := inFunc(e);
3455 outList := e :: outList;
3456 end while;
3457
3458 11 outList := List.append_reverse(outList, rest);
3459 end transformPathedElementInList;
3460
3461 public function transformPathedElementInProgram
3462 input Absyn.Path path;
3463 input Func func;
3464 input output Absyn.Program program;
3465 output Option<Absyn.Element> element;
3466 output Boolean success;
3467
3468 partial function Func
3469 input output Absyn.Element element;
3470 end Func;
3471 protected
3472 list<Absyn.Class> clss;
3473
3474 function transform_class
3475 input Absyn.Path path;
3476 input Func func;
3477 input output Absyn.Class cls;
3478 output Option<Absyn.Element> outElement;
3479 output Boolean found;
3480 protected
3481 Absyn.Element elem;
3482 algorithm
3483 // Is this the class we're looking for?
3484
2/4
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
5 found := AbsynUtil.pathFirstIdent(path) == cls.name;
3485
3486
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if found then
3487
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 3 times.
5 if AbsynUtil.pathIsIdent(path) then
3488 // The path points to a top-level class, temporarily transform it to an
3489 // element and call the function on it.
3490 2 elem := Absyn.Element.ELEMENT(false, NONE(), Absyn.InnerOuter.NOT_INNER_OUTER(),
3491 Absyn.ElementSpec.CLASSDEF(false, cls), cls.info, NONE());
3492
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 elem := func(elem);
3493 2 outElement := SOME(elem);
3494
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 Absyn.Element.ELEMENT(specification = Absyn.ElementSpec.CLASSDEF(class_ = cls)) := elem;
3495 else
3496 // The path points to an element inside the class.
3497 3 (cls, outElement, found) := transformPathedElementInClass(AbsynUtil.pathRest(path), func, cls);
3498 end if;
3499 else
3500 ✗ outElement := NONE();
3501 end if;
3502 end transform_class;
3503 algorithm
3504 5 (clss, element, success) := transformPathedElementInList(program.classes, function transform_class(path = path, func = func));
3505
3506
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if success then
3507 5 program.classes := clss;
3508 end if;
3509 end transformPathedElementInProgram;
3510
3511 protected function transformPathedElementInClass
3512 input Absyn.Path path;
3513 input Func func;
3514 input output Absyn.Class cls;
3515 output Option<Absyn.Element> element;
3516 output Boolean success;
3517
3518 partial function Func
3519 input output Absyn.Element element;
3520 end Func;
3521 protected
3522 Absyn.ClassDef def;
3523 algorithm
3524 3 (def, element, success) := transformPathedElementInClassDef(path, func, cls.body);
3525
3526
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if success then
3527 3 cls.body := def;
3528 end if;
3529 end transformPathedElementInClass;
3530
3531 protected function transformPathedElementInClassDef
3532 input Absyn.Path path;
3533 input Func func;
3534 input output Absyn.ClassDef def;
3535 output Option<Absyn.Element> element = NONE();
3536 output Boolean success;
3537
3538 partial function Func
3539 input output Absyn.Element element;
3540 end Func;
3541 protected
3542 list<Absyn.ClassPart> parts;
3543 algorithm
3544 success := match def
3545 case Absyn.ClassDef.PARTS()
3546 algorithm
3547 3 (parts, element, success) := transformPathedElementInList(def.classParts,
3548 function transformPathedElementInClassPart(path = path, func = func));
3549
3550
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if success then
3551 3 def.classParts := parts;
3552 end if;
3553 3 then
3554 success;
3555
3556 case Absyn.ClassDef.CLASS_EXTENDS()
3557 algorithm
3558 ✗ (parts, element, success) := transformPathedElementInList(def.parts,
3559 function transformPathedElementInClassPart(path = path, func = func));
3560
3561 ✗ if success then
3562 ✗ def.parts := parts;
3563 end if;
3564 ✗ then
3565 success;
3566
3567 else false;
3568 end match;
3569 end transformPathedElementInClassDef;
3570
3571 protected function transformPathedElementInClassPart
3572 input Absyn.Path path;
3573 input Func func;
3574 input output Absyn.ClassPart part;
3575 output Option<Absyn.Element> element = NONE();
3576 output Boolean success;
3577
3578 partial function Func
3579 input output Absyn.Element element;
3580 end Func;
3581 protected
3582 list<Absyn.ElementItem> items;
3583 algorithm
3584 success := match part
3585 case Absyn.ClassPart.PUBLIC()
3586 algorithm
3587 3 (items, element, success) := transformPathedElementInList(part.contents,
3588 function transformPathedElementInElementItem(path = path, func = func));
3589
3590
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if success then
3591 3 part.contents := items;
3592 end if;
3593 3 then
3594 success;
3595
3596 case Absyn.ClassPart.PROTECTED()
3597 algorithm
3598 ✗ (items, element, success) := transformPathedElementInList(part.contents,
3599 function transformPathedElementInElementItem(path = path, func = func));
3600
3601 ✗ if success then
3602 ✗ part.contents := items;
3603 end if;
3604 ✗ then
3605 success;
3606
3607 else false;
3608 end match;
3609 end transformPathedElementInClassPart;
3610
3611 protected function transformPathedElementInElementItem
3612 input Absyn.Path path;
3613 input Func func;
3614 input output Absyn.ElementItem item;
3615 output Option<Absyn.Element> outElement = NONE();
3616 output Boolean success;
3617
3618 partial function Func
3619 input output Absyn.Element element;
3620 end Func;
3621 protected
3622 Absyn.Element element;
3623 algorithm
3624 success := match item
3625 case Absyn.ElementItem.ELEMENTITEM()
3626 guard AbsynUtil.isElementItemNamed(AbsynUtil.pathFirstIdent(path), item)
3627 algorithm
3628
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 if AbsynUtil.pathIsIdent(path) then
3629
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 item.element := func(item.element);
3630 3 outElement := SOME(item.element);
3631 3 success := true;
3632 else
3633 ✗ (element, outElement, success) := transformPathedElementInElement(AbsynUtil.pathRest(path), func, item.element);
3634
3635 ✗ if success then
3636 ✗ item.element := element;
3637 end if;
3638 end if;
3639 3 then
3640 success;
3641
3642 else false;
3643 end match;
3644 end transformPathedElementInElementItem;
3645
3646 protected function transformPathedElementInElement
3647 input Absyn.Path path;
3648 input Func func;
3649 input output Absyn.Element element;
3650 output Option<Absyn.Element> outElement = NONE();
3651 output Boolean success;
3652
3653 partial function Func
3654 input output Absyn.Element element;
3655 end Func;
3656 protected
3657 Absyn.ElementSpec spec;
3658 algorithm
3659 success := match element
3660 case Absyn.Element.ELEMENT()
3661 algorithm
3662 ✗ (spec, outElement, success) := transformPathedElementInElementSpec(path, func, element.specification);
3663
3664 ✗ if success then
3665 ✗ element.specification := spec;
3666 end if;
3667 then
3668 success;
3669
3670 else false;
3671 end match;
3672 end transformPathedElementInElement;
3673
3674 protected function transformPathedElementInElementSpec
3675 input Absyn.Path path;
3676 input Func func;
3677 input output Absyn.ElementSpec spec;
3678 output Option<Absyn.Element> element = NONE();
3679 output Boolean success;
3680
3681 partial function Func
3682 input output Absyn.Element element;
3683 end Func;
3684 protected
3685 Absyn.Class cls;
3686 algorithm
3687 success := match spec
3688 case Absyn.ElementSpec.CLASSDEF()
3689 algorithm
3690 ✗ (cls, element, success) := transformPathedElementInClass(path, func, spec.class_);
3691
3692 ✗ if success then
3693 ✗ spec.class_ := cls;
3694 end if;
3695 then
3696 success;
3697
3698 else false;
3699 end match;
3700 end transformPathedElementInElementSpec;
3701
3702 public function getPathedClassRestriction
3703 input Absyn.Path path;
3704 input Absyn.Program program;
3705 output Absyn.Restriction restriction;
3706 algorithm
3707 try
3708 ✗ Absyn.CLASS(restriction = restriction) := ProgramUtil.getPathedClassInProgram(path, program);
3709 else
3710 restriction := Absyn.Restriction.R_UNKNOWN();
3711 end try;
3712 end getPathedClassRestriction;
3713
3714 public function getPathedSCodeElementInProgram
3715 input Absyn.Path path;
3716 input SCode.Program program;
3717 output SCode.Element element;
3718 protected
3719 String name;
3720 algorithm
3721 248 name := AbsynUtil.pathFirstIdent(path);
3722 248 element := List.find(program, function SCodeUtil.isElementNamed(name = name));
3723
3724
2/2
✓ Branch 1 taken 149 times.
✓ Branch 2 taken 94 times.
243 if not AbsynUtil.pathIsIdent(path) then
3725 149 element := getPathedSCodeElementInProgram(AbsynUtil.pathRest(path), SCodeUtil.getClassElements(element));
3726 end if;
3727 end getPathedSCodeElementInProgram;
3728
3729 public function getElementAnnotation
3730 input Absyn.Path elementPath;
3731 input Absyn.Program program;
3732 output String annotationString;
3733 protected
3734 Absyn.Element elem;
3735 Option<Absyn.Annotation> ann;
3736 list<Absyn.ElementArg> eargs;
3737 algorithm
3738 try
3739 4 elem := getPathedElementInProgram(elementPath, program);
3740 4 ann := AbsynUtil.getElementAnnotation(elem, AbsynUtil.pathLastIdent(elementPath));
3741
3742
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 if isSome(ann) then
3743 4 SOME(Absyn.Annotation.ANNOTATION(elementArgs = eargs)) := ann;
3744 4 annotationString := List.toString(eargs, Dump.unparseElementArgStr, List.Style.FLAT_BRACKETS);
3745 else
3746 annotationString := "()";
3747 end if;
3748 else
3749 annotationString := "";
3750 end try;
3751 end getElementAnnotation;
3752
3753 public function setElementAnnotation
3754 input Absyn.Path elementPath;
3755 input Absyn.Modification annotationMod;
3756 input output Absyn.Program program;
3757 output Boolean success = true;
3758 protected
3759 Option<Absyn.Annotation> ann;
3760 String name;
3761 Option<Absyn.Element> elem_opt;
3762 algorithm
3763 try
3764 ✗ if listEmpty(annotationMod.elementArgLst) then
3765 ann := NONE();
3766 else
3767 ✗ ann := SOME(Absyn.Annotation.ANNOTATION(annotationMod.elementArgLst));
3768 end if;
3769
3770 ✗ name := AbsynUtil.pathLastIdent(elementPath);
3771 ✗ (program, elem_opt, success) := transformPathedElementInProgram(elementPath,
3772 function AbsynUtil.setElementAnnotation(name = name, inAnnotation = ann), program);
3773
3774 ✗ if success then
3775 ✗ SymbolTable.setAbsynElement(program, Util.getOption(elem_opt), elementPath);
3776 end if;
3777 else
3778 ✗ success := false;
3779 end try;
3780 end setElementAnnotation;
3781
3782 public function loadClassContentString
3783 input String content;
3784 input Absyn.Path classPath;
3785 input Integer offsetX;
3786 input Integer offsetY;
3787 input output Absyn.Program program;
3788 output Boolean success = true;
3789 protected
3790 Absyn.ClassDef parsed_body;
3791 algorithm
3792 try
3793
2/4
✗ Branch 5 not taken.
✓ Branch 6 taken 1 time.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 time.
1 Absyn.Program.PROGRAM(classes = {Absyn.Class.CLASS(body = parsed_body)}) :=
3794 Parser.parsestring(stringAppendList({"model dummy\n", content, "end dummy;\n"}));
3795
3796 1 parsed_body := offsetAnnotationsInClassDef(parsed_body, offsetX, offsetY);
3797 1 (program, _, success) := transformPathedElementInProgram(classPath,
3798 function mergeClassContents(newContent = parsed_body), program);
3799 else
3800 ✗ success := false;
3801 end try;
3802 end loadClassContentString;
3803
3804 public function mergeClassContents
3805 input output Absyn.Element element;
3806 input Absyn.ClassDef newContent;
3807 protected
3808 Absyn.ElementSpec spec;
3809 Absyn.Class cls;
3810 Absyn.ClassDef old_content, new_content;
3811 algorithm
3812 1 new_content := resolveMergeContentsConflicts(element, newContent);
3813
3814 () := match element
3815 case Absyn.Element.ELEMENT(specification = spec as
3816 Absyn.ElementSpec.CLASSDEF(class_ = cls as
3817 Absyn.Class.CLASS(body = old_content)))
3818 algorithm
3819 () := match (old_content, new_content)
3820 case (Absyn.ClassDef.PARTS(), Absyn.ClassDef.PARTS())
3821 algorithm
3822 1 old_content.classParts := mergeClassParts(new_content.classParts, old_content.classParts);
3823 1 old_content.ann := mergeAnnotationLists(new_content.ann, old_content.ann);
3824 then
3825 ();
3826
3827 case (Absyn.ClassDef.CLASS_EXTENDS(), Absyn.ClassDef.PARTS())
3828 algorithm
3829 ✗ old_content.parts := mergeClassParts(new_content.classParts, old_content.parts);
3830 ✗ old_content.ann := mergeAnnotationLists(new_content.ann, old_content.ann);
3831 then
3832 ();
3833
3834 end match;
3835
3836 1 cls.body := old_content;
3837 1 spec.class_ := cls;
3838 1 element.specification := spec;
3839 then
3840 ();
3841 end match;
3842 end mergeClassContents;
3843
3844 protected function mergeClassParts
3845 "Merges a list of new class parts with a list of old parts."
3846 input list<Absyn.ClassPart> newParts;
3847 input list<Absyn.ClassPart> oldParts;
3848 output list<Absyn.ClassPart> outParts;
3849 protected
3850 Vector<Absyn.ClassPart> parts;
3851 Option<Absyn.ClassPart> op;
3852 Absyn.ClassPart p;
3853 Integer index;
3854 algorithm
3855 1 parts := Vector.fromList(oldParts);
3856
3857
6/8
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 time.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 1 time.
5 for part in newParts loop
3858 () := match part
3859 case Absyn.ClassPart.PUBLIC()
3860 algorithm
3861 // Try to find the last public/protected element section.
3862 1 (op, index) := Vector.findLast(parts, AbsynUtil.isElementSection);
3863
3864 () := match op
3865 // Compatible public section, append the new elements to the old.
3866 case SOME(p as Absyn.ClassPart.PUBLIC())
3867 algorithm
3868 ✗ part.contents := listAppend(p.contents, part.contents);
3869 ✗ Vector.updateNoBounds(parts, index, part);
3870 then
3871 ();
3872
3873 // Otherwise insert the section after any existing element sections.
3874 else
3875 algorithm
3876 1 Vector.insert(parts, part, max(index + 1, 1));
3877 then
3878 ();
3879
3880 end match;
3881 then
3882 ();
3883
3884 case Absyn.ClassPart.PROTECTED()
3885 algorithm
3886 // Try to find the last public/protected element section.
3887 1 (op, index) := Vector.findLast(parts, AbsynUtil.isElementSection);
3888
3889 () := match op
3890 // Compatible protected section, append the new elements to the old.
3891 case SOME(p as Absyn.ClassPart.PROTECTED())
3892 algorithm
3893 ✗ part.contents := listAppend(p.contents, part.contents);
3894 ✗ Vector.updateNoBounds(parts, index, part);
3895 then
3896 ();
3897
3898 // Otherwise insert the section after any existing element sections.
3899 else
3900 algorithm
3901 1 Vector.insert(parts, part, max(index + 1, 1));
3902 then
3903 ();
3904
3905 end match;
3906 then
3907 ();
3908
3909 case Absyn.ClassPart.EQUATIONS()
3910 algorithm
3911 // Try to find the last normal/initial equation section.
3912 1 (op, index) := Vector.findLast(parts, AbsynUtil.isEquationSection);
3913
3914 () := match op
3915 // Compatible normal equation section, append the new contents to the old.
3916 case SOME(p as Absyn.ClassPart.EQUATIONS())
3917 algorithm
3918 1 part.contents := listAppend(p.contents, part.contents);
3919 1 Vector.updateNoBounds(parts, index, part);
3920 then
3921 ();
3922
3923 // Otherwise insert the new section after any existing element and equation sections.
3924 else
3925 algorithm
3926 ✗ if index == -1 then
3927 ✗ (_, index) := Vector.findLast(parts, AbsynUtil.isElementSection);
3928 end if;
3929 ✗ Vector.insert(parts, part, max(index + 1, 1));
3930 then
3931 ();
3932
3933 end match;
3934 then
3935 ();
3936
3937 case Absyn.ClassPart.INITIALEQUATIONS()
3938 algorithm
3939 // Try to find the last normal/initial equation section.
3940 ✗ (op, index) := Vector.findLast(parts, AbsynUtil.isEquationSection);
3941
3942 () := match op
3943 // Compatible initial equation section, append the new contents to the old.
3944 case SOME(p as Absyn.ClassPart.INITIALEQUATIONS())
3945 algorithm
3946 ✗ part.contents := listAppend(p.contents, part.contents);
3947 ✗ Vector.updateNoBounds(parts, index, part);
3948 then
3949 ();
3950
3951 // Otherwise insert the new section after any existing element and equation sections.
3952 else
3953 algorithm
3954 ✗ if index == -1 then
3955 ✗ (_, index) := Vector.findLast(parts, AbsynUtil.isElementSection);
3956 end if;
3957 ✗ Vector.insert(parts, part, max(index + 1, 1));
3958 then
3959 ();
3960
3961 end match;
3962 then
3963 ();
3964
3965 // external section, replace the existing one or add it at the end of the
3966 // class if none exists.
3967 case Absyn.ClassPart.EXTERNAL()
3968 algorithm
3969 ✗ (_, index) := Vector.findLast(parts, AbsynUtil.isExternalPart);
3970
3971 ✗ if index <> -1 then
3972 ✗ Vector.updateNoBounds(parts, index, part);
3973 else
3974 ✗ Vector.push(parts, part);
3975 end if;
3976 then
3977 ();
3978
3979 // Anything else, add to the end of the class without merging.
3980 else
3981 algorithm
3982 1 Vector.push(parts, part);
3983 then
3984 ();
3985 end match;
3986 end for;
3987
3988 1 outParts := Vector.toList(parts);
3989 end mergeClassParts;
3990
3991 function mergeAnnotationLists
3992 input list<Absyn.Annotation> newAnnotations;
3993 input list<Absyn.Annotation> oldAnnotations;
3994 output list<Absyn.Annotation> outAnnotations;
3995 protected
3996 Absyn.Annotation old_ann;
3997 algorithm
3998
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if listEmpty(oldAnnotations) then
3999 outAnnotations := newAnnotations;
4000 else
4001 ✗ old_ann := listHead(oldAnnotations);
4002 ✗ for new_ann in newAnnotations loop
4003 ✗ old_ann := AbsynUtil.mergeAnnotations(old_ann, new_ann, mergeSubMods = true, mergeEqMods = true);
4004 end for;
4005 ✗ outAnnotations := old_ann :: listRest(oldAnnotations);
4006 end if;
4007 end mergeAnnotationLists;
4008
4009 function resolveMergeContentsConflicts
4010 input Absyn.Element oldElement;
4011 input output Absyn.ClassDef newContent;
4012 protected
4013 UnorderedSet<String> old_names;
4014 UnorderedMap<String, String> rename_map;
4015 String new_name;
4016 Integer index;
4017 list<String> conflicting_names = {};
4018 algorithm
4019 // Collect the existing names in a hash set.
4020 1 old_names := UnorderedSet.new(stringHashDjb2, stringEq);
4021
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 1 time.
7 for e in AbsynUtil.getElementItemsInElement(oldElement) loop
4022
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 6 times.
12 for name in AbsynUtil.elementItemNames(e) loop
4023 6 UnorderedSet.add(name, old_names);
4024 end for;
4025 end for;
4026
4027 // Go through the names in the new content.
4028 1 rename_map := UnorderedMap.new<String>(stringHashDjb2, stringEq);
4029
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 1 time.
7 for e in AbsynUtil.getElementItemsInClassDef(newContent) loop
4030
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 6 times.
12 for name in AbsynUtil.elementItemNames(e) loop
4031
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
6 if UnorderedSet.contains(name, old_names) then
4032 // If the name conflicts with an existing name, save it for later.
4033 conflicting_names := name :: conflicting_names;
4034 else
4035 // If the name doesn't conflict, add it to the set of existing names to
4036 // take it into account when generating new names for conflicting names.
4037 3 UnorderedSet.add(name, old_names);
4038 end if;
4039 end for;
4040 end for;
4041
4042
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if listEmpty(conflicting_names) then
4043 ✗ return;
4044 end if;
4045
4046 // Go through the conflicting names and find a non-conflicting name for them.
4047
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 time.
4 for name in listReverse(conflicting_names) loop
4048 // Try name1, name2, etc. until a non-conflicting name is found.
4049 index := 1;
4050 3 new_name := name + String(index);
4051
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 3 times.
4 while UnorderedSet.contains(new_name, old_names) loop
4052 1 index := index + 1;
4053 1 new_name := name + String(index);
4054 end while;
4055
4056 // Save the mapping for name->new_name to apply to the class.
4057 3 UnorderedMap.add(name, new_name, rename_map);
4058
4059 // Add the new name to the set of existing names.
4060 3 UnorderedSet.add(new_name, old_names);
4061 end for;
4062
4063 // Apply the new names to the class definition.
4064
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 if not UnorderedMap.isEmpty(rename_map) then
4065 1 newContent := renameElementsInClassDef(newContent, rename_map);
4066 end if;
4067 end resolveMergeContentsConflicts;
4068
4069 function renameElementsInElement
4070 input output Absyn.Element element;
4071 input UnorderedMap<String, String> nameMap;
4072 algorithm
4073 () := match element
4074 case Absyn.Element.ELEMENT()
4075 algorithm
4076 7 element.specification := renameElementsInElementSpec(element.specification, nameMap, renameElement = true);
4077 7 element.constrainClass := renameElementsInConstrainClassOpt(element.constrainClass, nameMap);
4078 then
4079 ();
4080
4081 else ();
4082 end match;
4083 end renameElementsInElement;
4084
4085 function renameElementsInElementSpec
4086 input output Absyn.ElementSpec spec;
4087 input UnorderedMap<String, String> nameMap;
4088 input Boolean renameElement;
4089 algorithm
4090 () := match spec
4091 case Absyn.ElementSpec.CLASSDEF()
4092 algorithm
4093 1 spec.class_ := renameElementsInClass(spec.class_, nameMap, renameElement);
4094 then
4095 ();
4096
4097 case Absyn.ElementSpec.EXTENDS()
4098 algorithm
4099 ✗ spec.elementArg := list(renameElementsInElementArg(a, nameMap) for a in spec.elementArg);
4100 ✗ spec.annotationOpt := renameElementsInAnnotationOpt(spec.annotationOpt, nameMap);
4101 then
4102 ();
4103
4104 case Absyn.ElementSpec.COMPONENTS()
4105 algorithm
4106 6 spec.attributes := renameElementsInAttributes(spec.attributes, nameMap);
4107 6 spec.typeSpec := renameElementsInTypeSpec(spec.typeSpec, nameMap);
4108
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6 times.
18 spec.components := list(renameElementsInComponentItem(c, nameMap, renameElement) for c in spec.components);
4109 then
4110 ();
4111
4112 else ();
4113 end match;
4114 end renameElementsInElementSpec;
4115
4116 function renameElementsInClass
4117 input output Absyn.Class cls;
4118 input UnorderedMap<String, String> nameMap;
4119 input Boolean renameElement;
4120 algorithm
4121
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if renameElement then
4122 1 cls.name := renameElementsInIdent(cls.name, nameMap);
4123 end if;
4124
4125 1 cls.body := renameElementsInClassDef(cls.body, nameMap);
4126 end renameElementsInClass;
4127
4128 function renameElementsInClassDef
4129 input output Absyn.ClassDef classDef;
4130 input UnorderedMap<String, String> nameMap;
4131 algorithm
4132 () := match classDef
4133 case Absyn.ClassDef.PARTS()
4134 algorithm
4135
4/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 2 times.
9 classDef.classParts := list(renameElementsInClassPart(p, nameMap) for p in classDef.classParts);
4136
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
4 classDef.ann := list(renameElementsInAnnotation(a, nameMap) for a in classDef.ann);
4137 then
4138 ();
4139
4140 case Absyn.ClassDef.DERIVED()
4141 algorithm
4142 ✗ classDef.typeSpec := renameElementsInTypeSpec(classDef.typeSpec, nameMap);
4143 ✗ classDef.attributes := renameElementsInAttributes(classDef.attributes, nameMap);
4144 ✗ classDef.arguments := list(renameElementsInElementArg(a, nameMap) for a in classDef.arguments);
4145 ✗ classDef.comment := renameElementsInCommentOpt(classDef.comment, nameMap);
4146 then
4147 ();
4148
4149 case Absyn.ClassDef.CLASS_EXTENDS()
4150 algorithm
4151 ✗ classDef.modifications := list(renameElementsInElementArg(a, nameMap) for a in classDef.modifications);
4152 ✗ classDef.parts := list(renameElementsInClassPart(p, nameMap) for p in classDef.parts);
4153 ✗ classDef.ann := list(renameElementsInAnnotation(a, nameMap) for a in classDef.ann);
4154 then
4155 ();
4156
4157 else ();
4158 end match;
4159 end renameElementsInClassDef;
4160
4161 function renameElementsInClassPart
4162 input output Absyn.ClassPart part;
4163 input UnorderedMap<String, String> nameMap;
4164 algorithm
4165 () := match part
4166 case Absyn.ClassPart.PUBLIC()
4167 algorithm
4168
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 2 times.
10 part.contents := list(renameElementsInElementItem(i, nameMap) for i in part.contents);
4169 then
4170 ();
4171
4172 case Absyn.ClassPart.PROTECTED()
4173 algorithm
4174
4/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1 time.
3 part.contents := list(renameElementsInElementItem(i, nameMap) for i in part.contents);
4175 then
4176 ();
4177
4178 case Absyn.ClassPart.CONSTRAINTS()
4179 algorithm
4180 ✗ part.contents := list(renameElementsInExp(e, nameMap) for e in part.contents);
4181 then
4182 ();
4183
4184 case Absyn.ClassPart.EQUATIONS()
4185 algorithm
4186 1 part.contents := renameElementsInEquationItems(part.contents, nameMap);
4187 then
4188 ();
4189
4190 case Absyn.ClassPart.INITIALEQUATIONS()
4191 algorithm
4192 ✗ part.contents := renameElementsInEquationItems(part.contents, nameMap);
4193 then
4194 ();
4195
4196 case Absyn.ClassPart.ALGORITHMS()
4197 algorithm
4198 1 part.contents := renameElementsInAlgorithmItems(part.contents, nameMap);
4199 then
4200 ();
4201
4202 case Absyn.ClassPart.INITIALALGORITHMS()
4203 algorithm
4204 ✗ part.contents := renameElementsInAlgorithmItems(part.contents, nameMap);
4205 then
4206 ();
4207
4208 case Absyn.ClassPart.EXTERNAL()
4209 algorithm
4210 ✗ part.externalDecl := renameElementsInExternalDecl(part.externalDecl, nameMap);
4211 ✗ part.annotation_ := renameElementsInAnnotationOpt(part.annotation_, nameMap);
4212 then
4213 ();
4214
4215 else ();
4216 end match;
4217 end renameElementsInClassPart;
4218
4219 function renameElementsInElementItem
4220 input output Absyn.ElementItem item;
4221 input UnorderedMap<String, String> nameMap;
4222 algorithm
4223 () := match item
4224 case Absyn.ElementItem.ELEMENTITEM()
4225 algorithm
4226 7 item.element := renameElementsInElement(item.element, nameMap);
4227 then
4228 ();
4229
4230 else ();
4231 end match;
4232 end renameElementsInElementItem;
4233
4234 function renameElementsInEquationItems
4235 input output list<Absyn.EquationItem> items;
4236 input UnorderedMap<String, String> nameMap;
4237 algorithm
4238
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 time.
3 items := list(renameElementsInEquationItem(i, nameMap) for i in items);
4239 end renameElementsInEquationItems;
4240
4241 function renameElementsInEquationItem
4242 input output Absyn.EquationItem item;
4243 input UnorderedMap<String, String> nameMap;
4244 algorithm
4245 () := match item
4246 case Absyn.EquationItem.EQUATIONITEM()
4247 algorithm
4248 2 item.equation_ := renameElementsInEquation(item.equation_, nameMap);
4249 2 item.comment := renameElementsInCommentOpt(item.comment, nameMap);
4250 then
4251 ();
4252
4253 else ();
4254 end match;
4255 end renameElementsInEquationItem;
4256
4257 function renameElementsInEquation
4258 input output Absyn.Equation eq;
4259 input UnorderedMap<String, String> nameMap;
4260 algorithm
4261 () := match eq
4262 case Absyn.Equation.EQ_IF()
4263 algorithm
4264 ✗ eq.ifExp := AbsynUtil.traverseExp(eq.ifExp, renameElementsInExp, nameMap);
4265 ✗ eq.equationTrueItems := renameElementsInEquationItems(eq.equationTrueItems, nameMap);
4266 ✗ eq.elseIfBranches := list(renameElementsInEquationBranch(b, nameMap) for b in eq.elseIfBranches);
4267 ✗ eq.equationElseItems := renameElementsInEquationItems(eq.equationElseItems, nameMap);
4268 then
4269 ();
4270
4271 case Absyn.Equation.EQ_EQUALS()
4272 algorithm
4273 1 eq.leftSide := AbsynUtil.traverseExp(eq.leftSide, renameElementsInExp, nameMap);
4274 1 eq.rightSide := AbsynUtil.traverseExp(eq.rightSide, renameElementsInExp, nameMap);
4275 then
4276 ();
4277
4278 case Absyn.Equation.EQ_PDE()
4279 algorithm
4280 ✗ eq.leftSide := AbsynUtil.traverseExp(eq.leftSide, renameElementsInExp, nameMap);
4281 ✗ eq.rightSide := AbsynUtil.traverseExp(eq.rightSide, renameElementsInExp, nameMap);
4282 then
4283 ();
4284
4285 case Absyn.Equation.EQ_CONNECT()
4286 algorithm
4287 1 eq.connector1 := renameElementsInCref(eq.connector1, nameMap);
4288 1 eq.connector2 := renameElementsInCref(eq.connector2, nameMap);
4289 then
4290 ();
4291
4292 case Absyn.Equation.EQ_FOR()
4293 algorithm
4294 ✗ eq.iterators := list(renameElementsInIterator(i, nameMap) for i in eq.iterators);
4295 ✗ eq.forEquations := renameElementsInEquationItems(eq.forEquations, nameMap);
4296 then
4297 ();
4298
4299 case Absyn.Equation.EQ_WHEN_E()
4300 algorithm
4301 ✗ eq.whenExp := AbsynUtil.traverseExp(eq.whenExp, renameElementsInExp, nameMap);
4302 ✗ eq.whenEquations := renameElementsInEquationItems(eq.whenEquations, nameMap);
4303 ✗ eq.elseWhenEquations := list(renameElementsInEquationBranch(b, nameMap) for b in eq.elseWhenEquations);
4304 then
4305 ();
4306
4307 case Absyn.Equation.EQ_NORETCALL()
4308 algorithm
4309 ✗ eq.functionName := renameElementsInCref(eq.functionName, nameMap);
4310 ✗ eq.functionArgs := AbsynUtil.traverseExpBidirFunctionArgs(eq.functionArgs, renameElementsInExp,
4311 AbsynUtil.dummyTraverseExp, nameMap);
4312 then
4313 ();
4314
4315 case Absyn.Equation.EQ_FAILURE()
4316 algorithm
4317 ✗ eq.equ := renameElementsInEquationItem(eq.equ, nameMap);
4318 then
4319 ();
4320
4321 else ();
4322 end match;
4323 end renameElementsInEquation;
4324
4325 function renameElementsInEquationBranch
4326 input output tuple<Absyn.Exp, list<Absyn.EquationItem>> branch;
4327 input UnorderedMap<String, String> nameMap;
4328 protected
4329 Absyn.Exp cond;
4330 list<Absyn.EquationItem> body;
4331 algorithm
4332 ✗ (cond, body) := branch;
4333 ✗ cond := AbsynUtil.traverseExp(cond, renameElementsInExp, nameMap);
4334 ✗ body := renameElementsInEquationItems(body, nameMap);
4335 ✗ branch := (cond, body);
4336 end renameElementsInEquationBranch;
4337
4338 function renameElementsInIterator
4339 input output Absyn.ForIterator iter;
4340 input UnorderedMap<String, String> nameMap;
4341 algorithm
4342 ✗ if isSome(iter.range) then
4343 ✗ iter.range := SOME(AbsynUtil.traverseExp(Util.getOption(iter.range), renameElementsInExp, nameMap));
4344 end if;
4345 end renameElementsInIterator;
4346
4347 function renameElementsInAlgorithmItems
4348 input output list<Absyn.AlgorithmItem> items;
4349 input UnorderedMap<String, String> nameMap;
4350 algorithm
4351
4/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1 time.
2 items := list(renameElementsInAlgorithmItem(i, nameMap) for i in items);
4352 end renameElementsInAlgorithmItems;
4353
4354 function renameElementsInAlgorithmItem
4355 input output Absyn.AlgorithmItem item;
4356 input UnorderedMap<String, String> nameMap;
4357 algorithm
4358 () := match item
4359 case Absyn.AlgorithmItem.ALGORITHMITEM()
4360 algorithm
4361 1 item.algorithm_ := renameElementsInAlgorithm(item.algorithm_, nameMap);
4362 1 item.comment := renameElementsInCommentOpt(item.comment, nameMap);
4363 then
4364 ();
4365
4366 else ();
4367 end match;
4368 end renameElementsInAlgorithmItem;
4369
4370 function renameElementsInAlgorithm
4371 input output Absyn.Algorithm alg;
4372 input UnorderedMap<String, String> nameMap;
4373 algorithm
4374 () := match alg
4375 case Absyn.Algorithm.ALG_ASSIGN()
4376 algorithm
4377 1 alg.assignComponent := AbsynUtil.traverseExp(alg.assignComponent, renameElementsInExp, nameMap);
4378 1 alg.value := AbsynUtil.traverseExp(alg.value, renameElementsInExp, nameMap);
4379 then
4380 ();
4381
4382 case Absyn.Algorithm.ALG_IF()
4383 algorithm
4384 ✗ alg.ifExp := AbsynUtil.traverseExp(alg.ifExp, renameElementsInExp, nameMap);
4385 ✗ alg.trueBranch := renameElementsInAlgorithmItems(alg.trueBranch, nameMap);
4386 ✗ alg.elseIfAlgorithmBranch := list(renameElementsInAlgorithmBranch(b, nameMap) for b in alg.elseIfAlgorithmBranch);
4387 ✗ alg.elseBranch := renameElementsInAlgorithmItems(alg.elseBranch, nameMap);
4388 then
4389 ();
4390
4391 case Absyn.Algorithm.ALG_FOR()
4392 algorithm
4393 ✗ alg.iterators := list(renameElementsInIterator(i, nameMap) for i in alg.iterators);
4394 ✗ alg.forBody := renameElementsInAlgorithmItems(alg.forBody, nameMap);
4395 then
4396 ();
4397
4398 case Absyn.Algorithm.ALG_PARFOR()
4399 algorithm
4400 ✗ alg.iterators := list(renameElementsInIterator(i, nameMap) for i in alg.iterators);
4401 ✗ alg.parforBody := renameElementsInAlgorithmItems(alg.parforBody, nameMap);
4402 then
4403 ();
4404
4405 case Absyn.Algorithm.ALG_WHILE()
4406 algorithm
4407 ✗ alg.boolExpr := AbsynUtil.traverseExp(alg.boolExpr, renameElementsInExp, nameMap);
4408 ✗ alg.whileBody := renameElementsInAlgorithmItems(alg.whileBody, nameMap);
4409 then
4410 ();
4411
4412 case Absyn.Algorithm.ALG_WHEN_A()
4413 algorithm
4414 ✗ alg.boolExpr := AbsynUtil.traverseExp(alg.boolExpr, renameElementsInExp, nameMap);
4415 ✗ alg.whenBody := renameElementsInAlgorithmItems(alg.whenBody, nameMap);
4416 ✗ alg.elseWhenAlgorithmBranch := list(renameElementsInAlgorithmBranch(b, nameMap) for b in alg.elseWhenAlgorithmBranch);
4417 then
4418 ();
4419
4420 case Absyn.Algorithm.ALG_NORETCALL()
4421 algorithm
4422 ✗ alg.functionCall := renameElementsInCref(alg.functionCall, nameMap);
4423 ✗ alg.functionArgs := AbsynUtil.traverseExpBidirFunctionArgs(alg.functionArgs, renameElementsInExp,
4424 AbsynUtil.dummyTraverseExp, nameMap);
4425 then
4426 ();
4427
4428 else ();
4429 end match;
4430 end renameElementsInAlgorithm;
4431
4432 function renameElementsInAlgorithmBranch
4433 input output tuple<Absyn.Exp, list<Absyn.AlgorithmItem>> branch;
4434 input UnorderedMap<String, String> nameMap;
4435 protected
4436 Absyn.Exp cond;
4437 list<Absyn.AlgorithmItem> body;
4438 algorithm
4439 ✗ (cond, body) := branch;
4440 ✗ cond := AbsynUtil.traverseExp(cond, renameElementsInExp, nameMap);
4441 ✗ body := renameElementsInAlgorithmItems(body, nameMap);
4442 ✗ branch := (cond, body);
4443 end renameElementsInAlgorithmBranch;
4444
4445 function renameElementsInElementArg
4446 input output Absyn.ElementArg arg;
4447 input UnorderedMap<String, String> nameMap;
4448 algorithm
4449 () := match arg
4450 case Absyn.ElementArg.MODIFICATION()
4451 algorithm
4452 ✗ arg.modification := renameElementsInModificationOpt(arg.modification, nameMap);
4453 then
4454 ();
4455
4456 case Absyn.ElementArg.REDECLARATION()
4457 algorithm
4458 ✗ arg.elementSpec := renameElementsInElementSpec(arg.elementSpec, nameMap, renameElement = false);
4459 ✗ arg.constrainClass := renameElementsInConstrainClassOpt(arg.constrainClass, nameMap);
4460 then
4461 ();
4462
4463 else ();
4464 end match;
4465 end renameElementsInElementArg;
4466
4467 function renameElementsInConstrainClassOpt
4468 input output Option<Absyn.ConstrainClass> cc;
4469 input UnorderedMap<String, String> nameMap;
4470 algorithm
4471 7 cc := Util.applyOption(cc, function renameElementsInConstrainClass(nameMap = nameMap));
4472 end renameElementsInConstrainClassOpt;
4473
4474 function renameElementsInConstrainClass
4475 input output Absyn.ConstrainClass cc;
4476 input UnorderedMap<String, String> nameMap;
4477 algorithm
4478 ✗ cc.elementSpec := renameElementsInElementSpec(cc.elementSpec, nameMap, renameElement = true);
4479 cc.comment := renameElementsInCommentOpt(cc.comment, nameMap);
4480 end renameElementsInConstrainClass;
4481
4482 function renameElementsInCommentOpt
4483 input output Option<Absyn.Comment> comment;
4484 input UnorderedMap<String, String> nameMap;
4485 algorithm
4486 9 comment := Util.applyOption(comment, function renameElementsInComment(nameMap = nameMap));
4487 end renameElementsInCommentOpt;
4488
4489 function renameElementsInComment
4490 input output Absyn.Comment comment;
4491 input UnorderedMap<String, String> nameMap;
4492 algorithm
4493 ✗ comment.annotation_ := Util.applyOption(comment.annotation_, function renameElementsInAnnotation(nameMap = nameMap));
4494 end renameElementsInComment;
4495
4496 function renameElementsInAnnotationOpt
4497 input output Option<Absyn.Annotation> ann;
4498 input UnorderedMap<String, String> nameMap;
4499 algorithm
4500 ✗ ann := Util.applyOption(ann, function renameElementsInAnnotation(nameMap = nameMap));
4501 end renameElementsInAnnotationOpt;
4502
4503 function renameElementsInAnnotation
4504 input output Absyn.Annotation ann;
4505 input UnorderedMap<String, String> nameMap;
4506 algorithm
4507 ✗ ann.elementArgs := list(renameElementsInElementArg(a, nameMap) for a in ann.elementArgs);
4508 end renameElementsInAnnotation;
4509
4510 function renameElementsInModificationOpt
4511 input output Option<Absyn.Modification> mod;
4512 input UnorderedMap<String, String> nameMap;
4513 algorithm
4514 6 mod := Util.applyOption(mod, function renameElementsInModification(nameMap = nameMap));
4515 end renameElementsInModificationOpt;
4516
4517 function renameElementsInModification
4518 input output Absyn.Modification mod;
4519 input UnorderedMap<String, String> nameMap;
4520 algorithm
4521 ✗ mod.elementArgLst := list(renameElementsInElementArg(a, nameMap) for a in mod.elementArgLst);
4522 mod.eqMod := renameElementsInEqMod(mod.eqMod, nameMap);
4523 end renameElementsInModification;
4524
4525 function renameElementsInEqMod
4526 input output Absyn.EqMod eqMod;
4527 input UnorderedMap<String, String> nameMap;
4528 algorithm
4529 () := match eqMod
4530 case Absyn.EqMod.EQMOD()
4531 algorithm
4532 ✗ eqMod.exp := AbsynUtil.traverseExp(eqMod.exp, renameElementsInExp, nameMap);
4533 then
4534 ();
4535
4536 else ();
4537 end match;
4538 end renameElementsInEqMod;
4539
4540 function renameElementsInExp
4541 input output Absyn.Exp exp;
4542 input output UnorderedMap<String, String> nameMap;
4543 algorithm
4544 () := match exp
4545 case Absyn.Exp.CREF()
4546 algorithm
4547 4 exp.componentRef := renameElementsInCref(exp.componentRef, nameMap);
4548 then
4549 ();
4550
4551 case Absyn.Exp.CALL()
4552 algorithm
4553 ✗ exp.function_ := renameElementsInCref(exp.function_, nameMap);
4554 then
4555 ();
4556
4557 case Absyn.Exp.PARTEVALFUNCTION()
4558 algorithm
4559 ✗ exp.function_ := renameElementsInCref(exp.function_, nameMap);
4560 then
4561 ();
4562
4563 else ();
4564 end match;
4565 end renameElementsInExp;
4566
4567 function renameElementsInCref
4568 input output Absyn.ComponentRef cref;
4569 input UnorderedMap<String, String> nameMap;
4570 input Boolean onlySubs = false;
4571 algorithm
4572 () := match cref
4573 case Absyn.ComponentRef.CREF_QUAL()
4574 algorithm
4575 ✗ if not onlySubs then
4576 ✗ cref.name := renameElementsInIdent(cref.name, nameMap);
4577 end if;
4578
4579 ✗ cref.subscripts := list(renameElementsInSubscript(s, nameMap) for s in cref.subscripts);
4580 ✗ cref.componentRef := renameElementsInCref(cref.componentRef, nameMap, onlySubs = true);
4581 then
4582 ();
4583
4584 case Absyn.ComponentRef.CREF_IDENT()
4585 algorithm
4586
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if not onlySubs then
4587 6 cref.name := renameElementsInIdent(cref.name, nameMap);
4588 end if;
4589
4590
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
12 cref.subscripts := list(renameElementsInSubscript(s, nameMap) for s in cref.subscripts);
4591 then
4592 ();
4593
4594 else ();
4595 end match;
4596 end renameElementsInCref;
4597
4598 function renameElementsInPath
4599 input output Absyn.Path path;
4600 input UnorderedMap<String, String> nameMap;
4601 algorithm
4602 () := match path
4603 case Absyn.Path.QUALIFIED()
4604 algorithm
4605 ✗ path.name := renameElementsInIdent(path.name, nameMap);
4606 then
4607 ();
4608
4609 case Absyn.Path.IDENT()
4610 algorithm
4611 6 path.name := renameElementsInIdent(path.name, nameMap);
4612 then
4613 ();
4614
4615 else ();
4616 end match;
4617 end renameElementsInPath;
4618
4619 function renameElementsInIdent
4620 input output String ident;
4621 input UnorderedMap<String, String> nameMap;
4622 algorithm
4623 19 ident := UnorderedMap.getOrDefault(ident, nameMap, ident);
4624 end renameElementsInIdent;
4625
4626 function renameElementsInSubscripts
4627 input output list<Absyn.Subscript> subs;
4628 input UnorderedMap<String, String> nameMap;
4629 algorithm
4630
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 subs := list(renameElementsInSubscript(s, nameMap) for s in subs);
4631 end renameElementsInSubscripts;
4632
4633 function renameElementsInSubscript
4634 input output Absyn.Subscript sub;
4635 input UnorderedMap<String, String> nameMap;
4636 algorithm
4637 () := match sub
4638 case Absyn.Subscript.SUBSCRIPT()
4639 algorithm
4640 ✗ sub.subscript := AbsynUtil.traverseExp(sub.subscript, renameElementsInExp, nameMap);
4641 then
4642 ();
4643
4644 else ();
4645 end match;
4646 end renameElementsInSubscript;
4647
4648 function renameElementsInExternalDecl
4649 input output Absyn.ExternalDecl extDecl;
4650 input UnorderedMap<String, String> nameMap;
4651 algorithm
4652 ✗ extDecl.args := list(renameElementsInExp(a, nameMap) for a in extDecl.args);
4653 extDecl.annotation_ := renameElementsInAnnotationOpt(extDecl.annotation_, nameMap);
4654 end renameElementsInExternalDecl;
4655
4656 function renameElementsInTypeSpec
4657 input output Absyn.TypeSpec spec;
4658 input UnorderedMap<String, String> nameMap;
4659 algorithm
4660 () := match spec
4661 case Absyn.TypeSpec.TPATH()
4662 algorithm
4663 6 spec.path := renameElementsInPath(spec.path, nameMap);
4664 12 spec.arrayDim := Util.applyOption(spec.arrayDim, function renameElementsInSubscripts(nameMap = nameMap));
4665 then
4666 ();
4667
4668 case Absyn.TypeSpec.TCOMPLEX()
4669 algorithm
4670 ✗ spec.path := renameElementsInPath(spec.path, nameMap);
4671 ✗ spec.arrayDim := Util.applyOption(spec.arrayDim, function renameElementsInSubscripts(nameMap = nameMap));
4672 then
4673 ();
4674 end match;
4675 end renameElementsInTypeSpec;
4676
4677 function renameElementsInAttributes
4678 input output Absyn.ElementAttributes attrs;
4679 input UnorderedMap<String, String> nameMap;
4680 algorithm
4681 6 attrs.arrayDim := renameElementsInSubscripts(attrs.arrayDim, nameMap);
4682 end renameElementsInAttributes;
4683
4684 function renameElementsInComponentItem
4685 input output Absyn.ComponentItem component;
4686 input UnorderedMap<String, String> nameMap;
4687 input Boolean renameElement;
4688 protected
4689 Absyn.Exp exp;
4690 algorithm
4691 6 component.component := renameElementsInComponent(component.component, nameMap, renameElement);
4692
4693
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
6 if isSome(component.condition) then
4694 ✗ SOME(exp) := component.condition;
4695 ✗ exp := AbsynUtil.traverseExp(exp, renameElementsInExp, nameMap);
4696 ✗ component.condition := SOME(exp);
4697 end if;
4698
4699 6 component.comment := renameElementsInCommentOpt(component.comment, nameMap);
4700 end renameElementsInComponentItem;
4701
4702 function renameElementsInComponent
4703 input output Absyn.Component component;
4704 input UnorderedMap<String, String> nameMap;
4705 input Boolean renameElement;
4706 algorithm
4707
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if renameElement then
4708 6 component.name := renameElementsInIdent(component.name, nameMap);
4709 end if;
4710
4711 6 component.arrayDim := renameElementsInSubscripts(component.arrayDim, nameMap);
4712 component.modification := renameElementsInModificationOpt(component.modification, nameMap);
4713 end renameElementsInComponent;
4714
4715 public function getInheritedAnnotation
4716 "Returns the modification for a specific annotation in a class, while also
4717 recursively looking up and merging annotations inherited from extends.
4718 If there are multiple non-identical inherited annotation only the first one
4719 is used, and a warning message is optionally emitted."
4720 input Absyn.Path modelPath;
4721 input String annotationName;
4722 input Absyn.Program program;
4723 input Boolean printConflictWarning = true "Prints a warning if inherited annotations conflict.";
4724 output Option<Absyn.Modification> outAnnotation = NONE();
4725 protected
4726 Absyn.Class cls;
4727 list<Absyn.Path> extends_paths;
4728 list<Option<Absyn.Modification>> extends_oannl;
4729 Absyn.Modification extends_ann, extends_ann2;
4730 Absyn.Path extends_path;
4731 algorithm
4732 // Look up the annotation in the given model.
4733 3059 cls := ProgramUtil.getPathedClassInProgram(modelPath, program);
4734 3058 outAnnotation := AbsynUtil.lookupClassAnnotation(cls, annotationName);
4735
4736 // Fetch the named annotation from all inherited classes.
4737 3058 ErrorExt.setCheckpoint(getInstanceName());
4738 try
4739 3058 extends_paths := NFApi.getInheritedClasses(modelPath, program);
4740 else
4741 extends_paths := {};
4742 end try;
4743 3058 ErrorExt.rollBack(getInstanceName());
4744
4745
2/2
✓ Branch 0 taken 2675 times.
✓ Branch 1 taken 383 times.
3058 if listEmpty(extends_paths) then
4746 // No extends.
4747 2675 return;
4748 end if;
4749
4750
4/4
✓ Branch 0 taken 411 times.
✓ Branch 1 taken 382 times.
✓ Branch 2 taken 411 times.
✓ Branch 3 taken 382 times.
793 extends_oannl := list(getInheritedAnnotation(ep, annotationName, program) for ep in extends_paths);
4751
4752
2/2
✓ Branch 0 taken 409 times.
✓ Branch 1 taken 358 times.
767 while not listEmpty(extends_oannl) loop
4753
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 409 times.
✓ Branch 5 taken 385 times.
✓ Branch 6 taken 24 times.
409 if isSome(listHead(extends_oannl)) then
4754 // Found an inherited annotation, merge it with the class' annotation if
4755 // it has one or just return it as it is.
4756 24 extends_ann := Util.getOption(listHead(extends_oannl));
4757
4758
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 5 times.
24 if isSome(outAnnotation) then
4759 19 outAnnotation := SOME(AbsynUtil.mergeModifiers(Util.getOption(outAnnotation), extends_ann));
4760 else
4761 outAnnotation := SOME(extends_ann);
4762 end if;
4763
4764
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 if printConflictWarning then
4765 // Check if we have any more inherited annotations.
4766
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 extends_path :: extends_paths := extends_paths;
4767
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 24 times.
49 for a in listRest(extends_oannl) loop
4768
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
1 if isSome(a) then
4769 ✗ SOME(extends_ann2) := a;
4770 ✗ if not valueEq(extends_ann, extends_ann2) then
4771 // Found an inherited annotation that's not equal to the first one, print a warning.
4772 ✗ Error.addMessage(Error.CONFLICTING_INHERITED_ANNOTATIONS,
4773 {annotationName, AbsynUtil.pathString(modelPath),
4774 Dump.unparseModificationStr(extends_ann), AbsynUtil.pathString(extends_path),
4775 Dump.unparseModificationStr(extends_ann2), AbsynUtil.pathString(listHead(extends_paths))});
4776 break;
4777 end if;
4778
4779 ✗ extends_paths := listRest(extends_paths);
4780 end if;
4781 end for;
4782 end if;
4783
4784 // Return the merged annotation.
4785 24 return;
4786 end if;
4787
4788 385 extends_oannl := listRest(extends_oannl);
4789 385 extends_paths := listRest(extends_paths);
4790 end while;
4791 end getInheritedAnnotation;
4792
4793 public function setElementType
4794 input Absyn.Path elementPath;
4795 input Absyn.ComponentRef className;
4796 input output Absyn.Program program;
4797 output Boolean success = true;
4798 protected
4799 Option<Absyn.Element> elem_opt;
4800 Absyn.TypeSpec ty;
4801 algorithm
4802 try
4803 ✗ ty := AbsynUtil.crefToTypeSpec(className);
4804 ✗ (program, elem_opt, success) := transformPathedElementInProgram(elementPath,
4805 function AbsynUtil.setElementType(typeSpec = ty, allowMultipleComponents = false), program);
4806
4807 ✗ if success then
4808 ✗ SymbolTable.setAbsynElement(program, Util.getOption(elem_opt), elementPath);
4809 end if;
4810 else
4811 ✗ success := false;
4812 end try;
4813 end setElementType;
4814
4815 function makeCommentFromArgs
4816 input Absyn.Exp commentExp;
4817 input Absyn.Exp annotationExp;
4818 input Option<Absyn.Comment> oldComment = NONE();
4819 output Option<Absyn.Comment> comment;
4820 protected
4821 Option<Absyn.Annotation> ann;
4822 Option<String> cmt;
4823 algorithm
4824 cmt := match commentExp
4825 case Absyn.Exp.TUPLE(expressions = {}) then NONE();
4826 2 case Absyn.Exp.STRING() then SOME(commentExp.value);
4827 end match;
4828
4829 ann := match annotationExp
4830 case Absyn.Exp.TUPLE(expressions = {}) then NONE();
4831 8 else SOME(Absyn.Annotation.ANNOTATION({recordConstructorToModification(annotationExp)}));
4832 end match;
4833
4834
6/8
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 27 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 23 times.
29 if isSome(cmt) or isSome(ann) then
4835
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
6 cmt := if isSome(cmt) then cmt else AbsynUtil.getCommentOptComment(oldComment);
4836
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 4 times.
6 ann := if isSome(ann) then ann else AbsynUtil.getCommentOptAnnotation(oldComment);
4837 12 comment := SOME(Absyn.Comment.COMMENT(ann, cmt));
4838 else
4839 comment := oldComment;
4840 end if;
4841 end makeCommentFromArgs;
4842
4843 function makeModifierFromArgs
4844 input Absyn.Exp bindingExp;
4845 input Absyn.Modification modifier;
4846 input SourceInfo info;
4847 input Option<Absyn.Modification> oldModifier = NONE();
4848 output Option<Absyn.Modification> outModifier;
4849 algorithm
4850 outModifier := match (bindingExp, modifier)
4851 // No binding, no modifier.
4852 case (Absyn.Exp.TUPLE(expressions = {}), Absyn.Modification.CLASSMOD(elementArgLst = {})) then oldModifier;
4853 // Only modifier.
4854 case (Absyn.Exp.TUPLE(expressions = {}), _) then SOME(modifier);
4855 // Binding, maybe modifier.
4856 case (_, Absyn.Modification.CLASSMOD())
4857 2 then SOME(Absyn.Modification.CLASSMOD(modifier.elementArgLst,
4858 Absyn.EqMod.EQMOD(bindingExp, info)));
4859 end match;
4860 end makeModifierFromArgs;
4861
4862 public function accessClass
4863 "Looks up a class and calls the given function on it, while also handling
4864 Access annotations and the nfAPINoise flag."
4865 input Absyn.Path classPath;
4866 input Absyn.Program program;
4867 input Fn fn;
4868 input Boolean evaluateParams = false;
4869 input Boolean graphicsExpMode = false;
4870 input Access accessLevel = Access.icon;
4871 output Values.Value result;
4872
4873 partial function Fn
4874 input Absyn.Path classPath;
4875 input Absyn.Program program;
4876 input Access accessLevel;
4877 output Values.Value result;
4878 end Fn;
4879 protected
4880 Access access;
4881 Boolean silent = false, eval_params, graphics_exp_mode;
4882 algorithm
4883 35 eval_params := Config.getEvaluateParametersInAnnotations();
4884 35 graphics_exp_mode := Config.getGraphicsExpMode();
4885
4886 try
4887 35 access := Interactive.checkAccessAnnotationAndEncryption(classPath, program);
4888
4889
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 if access < accessLevel then
4890 ✗ Error.addMessage(Error.ACCESS_ENCRYPTED_PROTECTED_CONTENTS, {});
4891 ✗ result := ValuesMake.makeBoolean(false);
4892 ✗ return;
4893 end if;
4894
4895 35 silent := not Flags.isSet(Flags.NF_API_NOISE);
4896
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 if silent then
4897 35 ErrorExt.setCheckpoint(getInstanceName());
4898 end if;
4899
4900 35 Config.setEvaluateParametersInAnnotations(evaluateParams);
4901 35 Config.setGraphicsExpMode(graphicsExpMode);
4902
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 29 times.
35 result := fn(classPath, program, access);
4903 else
4904 ✗ result := ValuesMake.makeBoolean(false);
4905 end try;
4906
4907
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 if silent then
4908 35 ErrorExt.rollBack(getInstanceName());
4909 end if;
4910
4911 35 Config.setGraphicsExpMode(graphics_exp_mode);
4912 35 Config.setEvaluateParametersInAnnotations(eval_params);
4913 end accessClass;
4914
4915 function makeAnnotationArrayValue
4916 "Some of the old functions that handle annotations just dumps the annotations
4917 to strings, but the new API functions need to return Values. Until those
4918 functions have been rewritten to create Values instead we can abuse TypeName
4919 expressions to get the correct output.
4920 TODO: Rewrite old functions that return strings instead of Values and get
4921 rid of this hack."
4922 input list<String> annotations;
4923 output Values.Value arr;
4924 algorithm
4925
4/4
✓ Branch 0 taken 193 times.
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 193 times.
✓ Branch 3 taken 32 times.
225 arr := ValuesMake.makeArray(list(ValuesMake.makeCodeTypeNameStr(s) for s in annotations));
4926 end makeAnnotationArrayValue;
4927
4928 function parseWithinPath
4929 input Absyn.Path path;
4930 output Absyn.Within outWithin;
4931 algorithm
4932 outWithin := match path
4933 case Absyn.Path.IDENT("__OpenModelica_TopLevel") then Absyn.Within.TOP();
4934 4 else Absyn.Within.WITHIN(path);
4935 end match;
4936 end parseWithinPath;
4937
4938 function offsetAnnotationsInClassDef
4939 input output Absyn.ClassDef cdef;
4940 input Integer x;
4941 input Integer y;
4942 algorithm
4943
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if x == 0 and y == 0 then
4944 1 return;
4945 end if;
4946
4947 () := match cdef
4948 case Absyn.ClassDef.PARTS()
4949 algorithm
4950 ✗ cdef.classParts := list(offsetAnnotationsInClassPart(p, x, y) for p in cdef.classParts);
4951 ✗ cdef.ann := list(offsetDiagramAnnotation(a, x, y) for a in cdef.ann);
4952 then
4953 ();
4954
4955 case Absyn.ClassDef.DERIVED()
4956 algorithm
4957 ✗ cdef.comment := offsetDiagramAnnotationInOptComment(cdef.comment, x, y);
4958 then
4959 ();
4960
4961 case Absyn.ClassDef.ENUMERATION()
4962 algorithm
4963 ✗ cdef.comment := offsetDiagramAnnotationInOptComment(cdef.comment, x, y);
4964 then
4965 ();
4966
4967 case Absyn.ClassDef.OVERLOAD()
4968 algorithm
4969 ✗ cdef.comment := offsetDiagramAnnotationInOptComment(cdef.comment, x, y);
4970 then
4971 ();
4972
4973 case Absyn.ClassDef.CLASS_EXTENDS()
4974 algorithm
4975 ✗ cdef.parts := list(offsetAnnotationsInClassPart(p, x, y) for p in cdef.parts);
4976 ✗ cdef.ann := list(offsetDiagramAnnotation(a, x, y) for a in cdef.ann);
4977 then
4978 ();
4979
4980 case Absyn.ClassDef.PDER()
4981 algorithm
4982 ✗ cdef.comment := offsetDiagramAnnotationInOptComment(cdef.comment, x, y);
4983 then
4984 ();
4985
4986 end match;
4987 end offsetAnnotationsInClassDef;
4988
4989 function offsetAnnotationsInClassPart
4990 input output Absyn.ClassPart part;
4991 input Integer x;
4992 input Integer y;
4993 algorithm
4994 () := match part
4995 case Absyn.ClassPart.PUBLIC()
4996 algorithm
4997 ✗ part.contents := list(offsetAnnotationsInElementItem(i, x, y) for i in part.contents);
4998 then
4999 ();
5000
5001 case Absyn.ClassPart.PROTECTED()
5002 algorithm
5003 ✗ part.contents := list(offsetAnnotationsInElementItem(i, x, y) for i in part.contents);
5004 then
5005 ();
5006
5007 case Absyn.ClassPart.EQUATIONS()
5008 algorithm
5009 ✗ part.contents := list(offsetAnnotationsInEquationItem(e, x, y) for e in part.contents);
5010 then
5011 ();
5012
5013 else ();
5014 end match;
5015 end offsetAnnotationsInClassPart;
5016
5017 function offsetAnnotationsInElementItem
5018 input output Absyn.ElementItem item;
5019 input Integer x;
5020 input Integer y;
5021 algorithm
5022 () := match item
5023 case Absyn.ElementItem.ELEMENTITEM()
5024 algorithm
5025 ✗ item.element := offsetAnnotationsInElement(item.element, x, y);
5026 then
5027 ();
5028
5029 else ();
5030 end match;
5031 end offsetAnnotationsInElementItem;
5032
5033 function offsetAnnotationsInElement
5034 input output Absyn.Element element;
5035 input Integer x;
5036 input Integer y;
5037 algorithm
5038 () := match element
5039 case Absyn.Element.ELEMENT()
5040 algorithm
5041 ✗ element.specification := offsetAnnotationsInElementSpec(element.specification, x, y);
5042 then
5043 ();
5044
5045 else ();
5046 end match;
5047 end offsetAnnotationsInElement;
5048
5049 function offsetAnnotationsInElementSpec
5050 input output Absyn.ElementSpec spec;
5051 input Integer x;
5052 input Integer y;
5053 algorithm
5054 () := match spec
5055 case Absyn.ElementSpec.COMPONENTS()
5056 algorithm
5057 ✗ spec.components := list(offsetAnnotationsInComponentItem(c, x, y) for c in spec.components);
5058 then
5059 ();
5060
5061 else ();
5062 end match;
5063 end offsetAnnotationsInElementSpec;
5064
5065 constant Absyn.Path PLACEMENT_ORIGIN_PATH =
5066 Absyn.Path.QUALIFIED("Placement", Absyn.Path.QUALIFIED("transformation", Absyn.Path.IDENT("origin")));
5067 constant Absyn.Path PLACEMENT_ICON_TRANSFORMATION_PATH =
5068 Absyn.Path.QUALIFIED("Placement", Absyn.Path.IDENT("iconTransformation"));
5069 constant Absyn.Path LINE_POINTS_PATH = Absyn.Path.QUALIFIED("Line", Absyn.Path.IDENT("points"));
5070 constant Absyn.Path DIAGRAM_GRAPHICS_PATH = Absyn.Path.QUALIFIED("Diagram", Absyn.Path.IDENT("graphics"));
5071
5072 function offsetAnnotationsInComponentItem
5073 input output Absyn.ComponentItem item;
5074 input Integer x;
5075 input Integer y;
5076 protected
5077 Option<Absyn.Annotation> oann;
5078 Absyn.Annotation ann;
5079 algorithm
5080 ✗ oann := AbsynUtil.getCommentOptAnnotation(item.comment);
5081 ✗ ann := if isSome(oann) then Util.getOption(oann) else Absyn.Annotation.ANNOTATION({});
5082 ✗ ann := AbsynUtil.transformAnnotationArg(ann, PLACEMENT_ORIGIN_PATH, function offsetOriginAnnotation(x = x, y = y));
5083 ✗ ann := offsetIconTransformationAnnotation(ann, x, y);
5084 ✗ item := AbsynUtil.setComponentItemAnnotation(item, SOME(ann));
5085 end offsetAnnotationsInComponentItem;
5086
5087 function offsetIconTransformationAnnotation
5088 input output Absyn.Annotation ann;
5089 input Integer x;
5090 input Integer y;
5091 protected
5092 function impl
5093 input output Absyn.ElementArg arg;
5094 input Integer x;
5095 input Integer y;
5096 protected
5097 Absyn.Modification mod;
5098 algorithm
5099 () := match arg
5100 case Absyn.ElementArg.MODIFICATION(modification = SOME(mod))
5101 algorithm
5102 ✗ mod.elementArgLst := AbsynUtil.transformAnnotationInArgs(mod.elementArgLst, Absyn.IDENT("origin"),
5103 function offsetOriginAnnotation(x = x, y = y));
5104 ✗ arg.modification := SOME(mod);
5105 then
5106 ();
5107 end match;
5108 end impl;
5109 algorithm
5110 try
5111 ✗ ann := AbsynUtil.transformAnnotationArg(ann, PLACEMENT_ICON_TRANSFORMATION_PATH,
5112 function impl(x = x, y = y), insert = false);
5113 else
5114 end try;
5115 end offsetIconTransformationAnnotation;
5116
5117 function offsetOriginAnnotation
5118 input output Absyn.ElementArg arg;
5119 input Integer x;
5120 input Integer y;
5121 protected
5122 Absyn.Modification mod;
5123 Absyn.EqMod eq_mod;
5124 algorithm
5125 () := match arg
5126 case Absyn.ElementArg.MODIFICATION()
5127 algorithm
5128 ✗ if isSome(arg.modification) then
5129 ✗ SOME(mod) := arg.modification;
5130 else
5131 mod := Absyn.Modification.CLASSMOD({}, Absyn.EqMod.NOMOD());
5132 end if;
5133
5134 ✗ eq_mod := mod.eqMod;
5135 mod.eqMod := match eq_mod
5136 case Absyn.EqMod.EQMOD()
5137 algorithm
5138 ✗ eq_mod.exp := offsetPointExpression(eq_mod.exp, x, y);
5139 then
5140 eq_mod;
5141
5142 ✗ else Absyn.EqMod.EQMOD(makeOrigin(x, y), Absyn.dummyInfo);
5143 end match;
5144
5145 ✗ arg.modification := SOME(mod);
5146 then
5147 ();
5148 end match;
5149 end offsetOriginAnnotation;
5150
5151 function makeOrigin
5152 input Integer x;
5153 input Integer y;
5154 output Absyn.Exp origin = Absyn.Exp.ARRAY({Absyn.Exp.INTEGER(x), Absyn.Exp.INTEGER(y)});
5155 end makeOrigin;
5156
5157 function offsetPointExpression
5158 input output Absyn.Exp point;
5159 input Integer x;
5160 input Integer y;
5161 protected
5162 Absyn.Exp e1, e2;
5163 algorithm
5164 point := match point
5165 case Absyn.Exp.ARRAY(arrayExp = {e1, e2})
5166 ✗ then Absyn.Exp.ARRAY({offsetIntegerExpression(e1, x), offsetIntegerExpression(e2, y)});
5167 ✗ else Absyn.Exp.BINARY(point, Absyn.Operator.ADD(), makeOrigin(x, y));
5168 end match;
5169 end offsetPointExpression;
5170
5171 function offsetIntegerExpression
5172 input output Absyn.Exp exp;
5173 input Integer offset;
5174 protected
5175 Integer v;
5176 algorithm
5177 exp := match exp
5178 ✗ case Absyn.Exp.INTEGER() then Absyn.Exp.INTEGER(exp.value + offset);
5179 ✗ case Absyn.Exp.UNARY(op = Absyn.Operator.UPLUS(), exp = Absyn.Exp.INTEGER(v)) then Absyn.Exp.INTEGER(v + offset);
5180 ✗ case Absyn.Exp.UNARY(op = Absyn.Operator.UMINUS(), exp = Absyn.Exp.INTEGER(v)) then Absyn.Exp.INTEGER(-v + offset);
5181 ✗ else if offset > 0 then Absyn.Exp.BINARY(exp, Absyn.Operator.ADD(), Absyn.Exp.INTEGER(offset))
5182 elseif offset < 0 then Absyn.Exp.BINARY(exp, Absyn.Operator.SUB(), Absyn.Exp.INTEGER(-offset))
5183 else exp;
5184 end match;
5185 end offsetIntegerExpression;
5186
5187 function offsetLineExpression
5188 input output Absyn.Exp line;
5189 input Integer x;
5190 input Integer y;
5191 algorithm
5192 () := match line
5193 case Absyn.Exp.ARRAY()
5194 algorithm
5195 ✗ line.arrayExp := list(offsetPointExpression(p, x, y) for p in line.arrayExp);
5196 then
5197 ();
5198
5199 else ();
5200 end match;
5201 end offsetLineExpression;
5202
5203 function offsetAnnotationsInEquationItem
5204 input output Absyn.EquationItem item;
5205 input Integer x;
5206 input Integer y;
5207 protected
5208 Absyn.Comment cmt;
5209 Absyn.Annotation ann;
5210 algorithm
5211 () := matchcontinue item
5212 case Absyn.EquationItem.EQUATIONITEM(comment = SOME(cmt as Absyn.COMMENT(annotation_ = SOME(ann))))
5213 algorithm
5214 ✗ ann := AbsynUtil.transformAnnotationArg(ann, LINE_POINTS_PATH,
5215 function offsetConnectionLineAnnotation(x = x, y = y), insert = false);
5216 ✗ cmt.annotation_ := SOME(ann);
5217 ✗ item.comment := SOME(cmt);
5218 then
5219 ();
5220
5221 else ();
5222 end matchcontinue;
5223 end offsetAnnotationsInEquationItem;
5224
5225 function offsetConnectionLineAnnotation
5226 input output Absyn.ElementArg arg;
5227 input Integer x;
5228 input Integer y;
5229 protected
5230 Absyn.EqMod eq_mod;
5231 algorithm
5232 () := match arg
5233 case Absyn.ElementArg.MODIFICATION(modification = SOME(Absyn.Modification.CLASSMOD(eqMod = eq_mod as Absyn.EqMod.EQMOD())))
5234 algorithm
5235 ✗ eq_mod.exp := offsetLineExpression(eq_mod.exp, x, y);
5236 ✗ arg.modification := SOME(Absyn.Modification.CLASSMOD({}, eq_mod));
5237 then
5238 ();
5239
5240 else ();
5241 end match;
5242 end offsetConnectionLineAnnotation;
5243
5244 function offsetDiagramAnnotationInOptComment
5245 input output Option<Absyn.Comment> cmt;
5246 input Integer x;
5247 input Integer y;
5248 protected
5249 Option<String> cmt_str;
5250 Absyn.Annotation ann;
5251 algorithm
5252 () := match cmt
5253 case SOME(Absyn.Comment.COMMENT(SOME(ann), cmt_str))
5254 algorithm
5255 ✗ ann := offsetDiagramAnnotation(ann, x, y);
5256 ✗ cmt := SOME(Absyn.Comment.COMMENT(SOME(ann), cmt_str));
5257 then
5258 ();
5259
5260 else ();
5261 end match;
5262 end offsetDiagramAnnotationInOptComment;
5263
5264 function offsetDiagramAnnotation
5265 input output Absyn.Annotation ann;
5266 input Integer x;
5267 input Integer y;
5268 algorithm
5269 ✗ ann := AbsynUtil.transformAnnotationArg(ann, DIAGRAM_GRAPHICS_PATH,
5270 function offsetGraphicsAnnotation(x = x, y = y));
5271 end offsetDiagramAnnotation;
5272
5273 function offsetGraphicsAnnotation
5274 input output Absyn.ElementArg arg;
5275 input Integer x;
5276 input Integer y;
5277 protected
5278 Absyn.EqMod eq_mod;
5279 algorithm
5280 () := match arg
5281 case Absyn.ElementArg.MODIFICATION(modification = SOME(Absyn.Modification.CLASSMOD(eqMod = eq_mod as Absyn.EqMod.EQMOD())))
5282 algorithm
5283 ✗ eq_mod.exp := offsetGraphicsExpression(eq_mod.exp, x, y);
5284 ✗ arg.modification := SOME(Absyn.Modification.CLASSMOD({}, eq_mod));
5285 then
5286 ();
5287
5288 else ();
5289 end match;
5290 end offsetGraphicsAnnotation;
5291
5292 function offsetGraphicsExpression
5293 input output Absyn.Exp graphics;
5294 input Integer x;
5295 input Integer y;
5296 algorithm
5297 () := match graphics
5298 case Absyn.Exp.ARRAY()
5299 algorithm
5300 ✗ graphics.arrayExp := list(offsetGraphicsItemExpression(p, x, y) for p in graphics.arrayExp);
5301 then
5302 ();
5303
5304 else ();
5305 end match;
5306 end offsetGraphicsExpression;
5307
5308 function offsetGraphicsItemExpression
5309 input output Absyn.Exp item;
5310 input Integer x;
5311 input Integer y;
5312 protected
5313 Absyn.FunctionArgs args;
5314 list<Absyn.NamedArg> named_args;
5315 Boolean found;
5316 Absyn.Exp visible, origin;
5317 list<Absyn.Exp> rest;
5318
5319 function offset_named_origin
5320 input output Absyn.NamedArg arg;
5321 input Integer x;
5322 input Integer y;
5323 output Boolean found;
5324 algorithm
5325 ✗ found := arg.argName == "origin";
5326
5327 if found then
5328 ✗ arg.argValue := offsetPointExpression(arg.argValue, x, y);
5329 end if;
5330 end offset_named_origin;
5331 algorithm
5332 () := match item
5333 case Absyn.Exp.CALL(functionArgs = args as Absyn.FunctionArgs.FUNCTIONARGS())
5334 algorithm
5335 ✗ if listLength(args.args) >= 2 then
5336 // If there are two or more positional argument then origin is the second one.
5337 ✗ visible :: origin :: rest := args.args;
5338 ✗ origin := offsetPointExpression(origin, x, y);
5339 ✗ args.args := visible :: origin :: rest;
5340 else
5341 // Otherwise try to find and update a named origin argument.
5342 ✗ (named_args, found) := List.findMap(args.argNames, function offset_named_origin(x = x, y = y));
5343
5344 ✗ if found then
5345 ✗ args.argNames := named_args;
5346 else
5347 // No origin was found, add it.
5348 ✗ args.argNames := Absyn.NamedArg.NAMEDARG("origin", makeOrigin(x, y)) :: args.argNames;
5349 end if;
5350 end if;
5351
5352 ✗ item.functionArgs := args;
5353 then
5354 ();
5355
5356 else ();
5357 end match;
5358 end offsetGraphicsItemExpression;
5359
5360 public function addToPublic
5361 "This function takes a Class definition and adds an
5362 ElementItem to the first public section in the class.
5363 If no public section is available in the class one is created."
5364 input output Absyn.Class cls;
5365 input Absyn.ElementItem element;
5366 protected
5367 list<Absyn.ElementItem> elems;
5368 Absyn.ClassDef cdef;
5369 algorithm
5370 () := matchcontinue cls
5371 case Absyn.CLASS(body = cdef as Absyn.PARTS())
5372 algorithm
5373 18 elems := ProgramUtil.getPublicList(cdef.classParts);
5374 18 elems := List.appendElt(element, elems);
5375 18 cdef.classParts := ProgramUtil.replacePublicList(cdef.classParts, elems);
5376 18 cls.body := cdef;
5377 then
5378 ();
5379
5380 case Absyn.CLASS(body = cdef as Absyn.PARTS())
5381 algorithm
5382 ✗ cdef.classParts := Absyn.PUBLIC({element}) :: cdef.classParts;
5383 ✗ cls.body := cdef;
5384 then
5385 ();
5386
5387 // adrpo: handle also the case model extends X end X;
5388 case Absyn.CLASS(body = cdef as Absyn.CLASS_EXTENDS())
5389 algorithm
5390 ✗ elems := ProgramUtil.getPublicList(cdef.parts);
5391 ✗ elems := List.appendElt(element, elems);
5392 ✗ cdef.parts := ProgramUtil.replacePublicList(cdef.parts, elems);
5393 ✗ cls.body := cdef;
5394 then
5395 ();
5396
5397 // adrpo: handle also the case model extends X end X;
5398 case Absyn.CLASS(body = cdef as Absyn.CLASS_EXTENDS())
5399 algorithm
5400 ✗ cdef.parts := Absyn.PUBLIC({element}) :: cdef.parts;
5401 ✗ cls.body := cdef;
5402 then
5403 ();
5404
5405 end matchcontinue;
5406 end addToPublic;
5407
5408 public function addToProtected
5409 "This function takes a Class definition and adds an
5410 ElementItem to the first protected section in the class.
5411 If no protected section is available in the class one is created."
5412 input output Absyn.Class cls;
5413 input Absyn.ElementItem element;
5414 protected
5415 list<Absyn.ElementItem> elems;
5416 Absyn.ClassDef cdef;
5417 algorithm
5418 () := matchcontinue cls
5419 case Absyn.CLASS(body = cdef as Absyn.PARTS())
5420 algorithm
5421 ✗ elems := ProgramUtil.getProtectedList(cdef.classParts);
5422 ✗ elems := List.appendElt(element, elems);
5423 ✗ cdef.classParts := ProgramUtil.replaceProtectedList(cdef.classParts, elems);
5424 ✗ cls.body := cdef;
5425 then
5426 ();
5427
5428 case Absyn.CLASS(body = cdef as Absyn.PARTS())
5429 algorithm
5430 ✗ cdef.classParts := Absyn.PROTECTED({element}) :: cdef.classParts;
5431 ✗ cls.body := cdef;
5432 then
5433 ();
5434
5435 // adrpo: handle also the case model extends X end X;
5436 case Absyn.CLASS(body = cdef as Absyn.CLASS_EXTENDS())
5437 algorithm
5438 ✗ elems := ProgramUtil.getProtectedList(cdef.parts);
5439 ✗ elems := List.appendElt(element, elems);
5440 ✗ cdef.parts := ProgramUtil.replaceProtectedList(cdef.parts, elems);
5441 ✗ cls.body := cdef;
5442 then
5443 ();
5444
5445 // adrpo: handle also the case model extends X end X;
5446 case Absyn.CLASS(body = cdef as Absyn.CLASS_EXTENDS())
5447 algorithm
5448 ✗ cdef.parts := Absyn.PROTECTED({element}) :: cdef.parts;
5449 ✗ cls.body := cdef;
5450 then
5451 ();
5452
5453 end matchcontinue;
5454 end addToProtected;
5455
5456 public function addToEquation
5457 "This function takes a Class definition and adds an
5458 EquationItem to the first equation section in the class.
5459 If no equation section is available in the class one is created."
5460 input output Absyn.Class cls;
5461 input Absyn.EquationItem eq;
5462 protected
5463 list<Absyn.EquationItem> eqlst;
5464 Absyn.ClassDef cdef;
5465 algorithm
5466 () := matchcontinue cls
5467 case Absyn.CLASS(body = cdef as Absyn.PARTS())
5468 algorithm
5469 10 eqlst := InteractiveUtil.getEquationList(cdef.classParts);
5470 6 eqlst := List.appendElt(eq, eqlst);
5471 6 cdef.classParts := InteractiveUtil.replaceEquationList(cdef.classParts, eqlst);
5472 6 cls.body := cdef;
5473 then
5474 ();
5475
5476 case Absyn.CLASS(body = cdef as Absyn.PARTS())
5477 algorithm
5478 8 cdef.classParts := List.appendElt(Absyn.EQUATIONS({eq}), cdef.classParts) "Add the equations last, to make nicer output if public section present" ;
5479 4 cls.body := cdef;
5480 then
5481 ();
5482
5483 /* adrpo: handle also the case model extends X end X; */
5484 case Absyn.CLASS(body = cdef as Absyn.CLASS_EXTENDS())
5485 algorithm
5486 ✗ eqlst := InteractiveUtil.getEquationList(cdef.parts);
5487 ✗ eqlst := List.appendElt(eq, eqlst);
5488 ✗ cdef.parts := InteractiveUtil.replaceEquationList(cdef.parts, eqlst);
5489 ✗ cls.body := cdef;
5490 then
5491 ();
5492
5493 /* adrpo: handle also the case model extends X end X; */
5494 case Absyn.CLASS(body = cdef as Absyn.CLASS_EXTENDS())
5495 algorithm
5496 ✗ cdef.parts := List.appendElt(Absyn.EQUATIONS({eq}), cdef.parts) "Add the equations last, to make nicer output if public section present" ;
5497 ✗ cls.body := cdef;
5498 then
5499 ();
5500
5501 end matchcontinue;
5502 end addToEquation;
5503
5504 annotation(__OpenModelica_Interface="backend_main");
5505 end InteractiveUtil;
5506