Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 52.9% 396 / 0 / 748
Functions: -% 0 / 1 / 1
Branches: 33.7% 283 / 0 / 840

OMCompiler/Compiler/FrontEnd/SCodeUtil.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 SCodeUtil
37 " file: SCodeUtil.mo
38 package: SCodeUtil
39 description: Utility functions for the SCodeUtil.intermediate form"
40
41 import SCode;
42
43 protected
44 import Absyn;
45 import AbsynUtil;
46 import Error;
47 import List;
48 import Util;
49
50 public
51
52 replaceable type Argument subtypeof Any;
53 constant SourceInfo dummyInfo = SOURCEINFO("", false, 0, 0, 0, 0, 0.0);
54
55 function stripSubmod
56 "Removes all submodifiers from the Mod."
57 input output SCode.Mod mod;
58 algorithm
59 () := match mod
60 case SCode.MOD()
61 algorithm
62 6 mod.subModLst := {};
63 then
64 ();
65
66 else ();
67 end match;
68 end stripSubmod;
69
70 function filterSubMods
71 "Removes submods from a modifier based on a filter function."
72 input output SCode.Mod mod;
73 input FilterFunc filter;
74
75 partial function FilterFunc
76 input SCode.SubMod submod;
77 output Boolean keep;
78 end FilterFunc;
79 algorithm
80 mod := match mod
81 case SCode.MOD()
82 algorithm
83
8/8
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 4167529 times.
✓ Branch 4 taken 4167583 times.
✓ Branch 5 taken 46 times.
✓ Branch 6 taken 4167629 times.
✓ Branch 7 taken 3070406 times.
✓ Branch 8 taken 46 times.
✓ Branch 9 taken 3070406 times.
10308441 mod.subModLst := list(m for m guard filter(m) in mod.subModLst);
84 then
85 match mod
86 case SCode.MOD(subModLst = {}, binding = NONE()) then SCode.NOMOD();
87 else mod;
88 end match;
89
90 else mod;
91 end match;
92 end filterSubMods;
93
94 function filterGivenSubModNames
95 input SCode.SubMod submod;
96 input list<String> namesToKeep;
97 output Boolean keep;
98 algorithm
99 96 keep := listMember(submod.ident, namesToKeep);
100 end filterGivenSubModNames;
101
102 function removeGivenSubModNames
103 input SCode.SubMod submod;
104 input list<String> namesToRemove;
105 output Boolean keep;
106 algorithm
107 4 keep := not listMember(submod.ident, namesToRemove);
108 end removeGivenSubModNames;
109
110 function getElementNamed
111 "Return the Element with the name given as first argument from the Class."
112 input SCode.Ident inIdent;
113 input SCode.Element inClass;
114 output SCode.Element outElement;
115 algorithm
116 outElement := match (inIdent,inClass)
117 local
118 SCode.Element elt;
119 String id;
120 list<SCode.Element> elts;
121
122 case (id,SCode.CLASS(classDef = SCode.PARTS(elementLst = elts)))
123 algorithm
124 82 elt := getElementNamedFromElts(id, elts);
125 then
126 elt;
127
128 /* adrpo: handle also the case model extends X then X; */
129 case (id,SCode.CLASS(classDef = SCode.CLASS_EXTENDS(composition = SCode.PARTS(elementLst = elts))))
130 algorithm
131 ✗ elt := getElementNamedFromElts(id, elts);
132 then
133 elt;
134 end match;
135 end getElementNamed;
136
137 function getElementNamedFromElts
138 "Helper function to getElementNamed."
139 input SCode.Ident inIdent;
140 input list<SCode.Element> inElementLst;
141 output SCode.Element outElement;
142 algorithm
143 outElement := matchcontinue (inIdent,inElementLst)
144 local
145 SCode.Element elt,comp,cdef;
146 String id2,id1;
147 list<SCode.Element> xs;
148
149 case (id2,((comp as SCode.COMPONENT(name = id1)) :: _))
150 algorithm
151
4/4
✓ Branch 0 taken 154 times.
✓ Branch 1 taken 348 times.
✓ Branch 3 taken 82 times.
✓ Branch 4 taken 72 times.
502 true := stringEq(id1, id2);
152 then
153 comp;
154
155 case (id2,(SCode.COMPONENT(name = id1) :: xs))
156 algorithm
157
3/4
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 348 times.
✓ Branch 3 taken 72 times.
✗ Branch 4 not taken.
420 false := stringEq(id1, id2);
158 420 elt := getElementNamedFromElts(id2, xs);
159 then
160 elt;
161
162 case (id2,(SCode.CLASS(name = id1) :: xs))
163 algorithm
164 ✗ false := stringEq(id1, id2);
165 ✗ elt := getElementNamedFromElts(id2, xs);
166 then
167 elt;
168
169 case (id2,(SCode.EXTENDS() :: xs))
170 algorithm
171 ✗ elt := getElementNamedFromElts(id2, xs);
172 then
173 elt;
174
175 case (id2,((cdef as SCode.CLASS(name = id1)) :: _))
176 algorithm
177 ✗ true := stringEq(id1, id2);
178 then
179 cdef;
180
181 // Try next.
182 case (id2, _:: xs)
183 algorithm
184 ✗ elt := getElementNamedFromElts(id2, xs);
185 then
186 elt;
187 end matchcontinue;
188 end getElementNamedFromElts;
189
190 function isElementExtends "
191 Author BZ, 2009-01
192 check if an element is of type EXTENDS or not."
193 input SCode.Element ele;
194 output Boolean isExtend;
195 algorithm
196 isExtend := match ele
197 case SCode.EXTENDS() then true;
198 else false;
199 end match;
200 end isElementExtends;
201
202 function isElementExtendsOrClassExtends
203 "Check if an element extends another class."
204 input SCode.Element ele;
205 output Boolean isExtend;
206 algorithm
207 isExtend := match ele
208 case SCode.EXTENDS() then true;
209 else false;
210 end match;
211 end isElementExtendsOrClassExtends;
212
213 function isNotElementClassExtends "
214 check if an element is not of type CLASS_EXTENDS."
215 input SCode.Element ele;
216 output Boolean isExtend;
217 algorithm
218 isExtend := match ele
219 case SCode.CLASS(classDef = SCode.CLASS_EXTENDS()) then false;
220 else true;
221 end match;
222 end isNotElementClassExtends;
223
224 function isParameterOrConst
225 "Returns true if Variability indicates a parameter or constant."
226 input SCode.Variability inVariability;
227 output Boolean outBoolean;
228 algorithm
229 outBoolean := match inVariability
230 case SCode.PARAM() then true;
231 case SCode.CONST() then true;
232 else false;
233 end match;
234 end isParameterOrConst;
235
236 function isConstant
237 "Returns true if Variability is constant, otherwise false"
238 input SCode.Variability inVariability;
239 output Boolean outBoolean;
240 algorithm
241 outBoolean := match inVariability
242 case SCode.CONST() then true;
243 else false;
244 end match;
245 end isConstant;
246
247 function countParts
248 "Counts the number of ClassParts of a Class."
249 input SCode.Element inClass;
250 output Integer outInteger;
251 algorithm
252 outInteger := match inClass
253 local
254 Integer res;
255 list<SCode.Element> elts;
256
257 case SCode.CLASS(classDef = SCode.PARTS(elementLst = elts))
258 algorithm
259 ✗ res := listLength(elts);
260 then
261 res;
262
263 /* adrpo: handle also model extends X ... parts ... end X; */
264 case SCode.CLASS(classDef = SCode.CLASS_EXTENDS(composition = SCode.PARTS(elementLst = elts)))
265 algorithm
266 ✗ res := listLength(elts);
267 then
268 res;
269
270 else 0;
271
272 end match;
273 end countParts;
274
275 function componentNames
276 "Return a string list of all component names of a class."
277 input SCode.Element inClass;
278 output list<String> outStringLst;
279 algorithm
280 outStringLst := match inClass
281 local list<String> res; list<SCode.Element> elts;
282
283 case SCode.CLASS(classDef = SCode.PARTS(elementLst = elts))
284 algorithm
285 4395 res := componentNamesFromElts(elts);
286 then
287 res;
288
289 /* adrpo: handle also the case model extends X end X;*/
290 case SCode.CLASS(classDef = SCode.CLASS_EXTENDS(composition = SCode.PARTS(elementLst = elts)))
291 algorithm
292 ✗ res := componentNamesFromElts(elts);
293 then
294 res;
295
296 else {};
297
298 end match;
299 end componentNames;
300
301 function componentNamesFromElts
302 "Helper function to componentNames."
303 input list<SCode.Element> inElements;
304 output list<String> outComponentNames;
305 algorithm
306 4395 outComponentNames := List.filterMap(inElements, componentName);
307 end componentNamesFromElts;
308
309 function componentName
310 input SCode.Element inComponent;
311 output String outName;
312 algorithm
313
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24070 times.
24070 SCode.COMPONENT(name = outName) := inComponent;
314 end componentName;
315
316 function elementInfo "retrieves the element info"
317 input SCode.Element e;
318 output SourceInfo info;
319 algorithm
320 info := match e
321 local
322 SourceInfo i;
323
324 case SCode.COMPONENT(info = i) then i;
325 case SCode.CLASS(info = i) then i;
326 case SCode.EXTENDS(info = i) then i;
327 case SCode.IMPORT(info = i) then i;
328 else Absyn.dummyInfo;
329
330 end match;
331 end elementInfo;
332
333 function setElementName
334 input output SCode.Element e;
335 input String name;
336 algorithm
337 () := match e
338 24 case SCode.CLASS() algorithm e.name := name; then ();
339 ✗ case SCode.COMPONENT() algorithm e.name := name; then ();
340 ✗ case SCode.DEFINEUNIT() algorithm e.name := name; then ();
341 else ();
342 end match;
343 end setElementName;
344
345 function elementName ""
346 input SCode.Element e;
347 output String s;
348 algorithm
349 s := match e
350 case SCode.COMPONENT(name = s) then s;
351 case SCode.CLASS(name = s) then s;
352 end match;
353 end elementName;
354
355 function elementNameInfo
356 input SCode.Element element;
357 output String name;
358 output SourceInfo info;
359 algorithm
360 (name, info) := match element
361 case SCode.COMPONENT(name = name, info = info) then (name, info);
362 case SCode.CLASS(name = name, info = info) then (name, info);
363 end match;
364 end elementNameInfo;
365
366 function elementNames "Gets all elements that have an element name from the list"
367 input list<SCode.Element> elts;
368 output list<String> names;
369 algorithm
370 39619 names := List.fold(elts,elementNamesWork,{});
371 end elementNames;
372
373 protected function elementNamesWork "Gets all elements that have an element name from the list"
374 input SCode.Element e;
375 input list<String> acc;
376 output list<String> out;
377 algorithm
378 out := match e
379 local
380 String s;
381 case SCode.COMPONENT(name = s) then s::acc;
382 case SCode.CLASS(name = s) then s::acc;
383 else acc;
384 end match;
385 end elementNamesWork;
386
387 public function renameElement
388 input output SCode.Element element;
389 input String name;
390 algorithm
391 () := match element
392 ✗ case SCode.CLASS() algorithm element.name := name; then ();
393 ✗ case SCode.COMPONENT() algorithm element.name := name; then ();
394 end match;
395 end renameElement;
396
397 public function elementNameEqual
398 input SCode.Element inElement1;
399 input SCode.Element inElement2;
400 output Boolean outEqual;
401 algorithm
402 outEqual := match (inElement1, inElement2)
403
4/4
✓ Branch 0 taken 610279 times.
✓ Branch 1 taken 12146 times.
✓ Branch 3 taken 393 times.
✓ Branch 4 taken 609886 times.
622425 case (SCode.CLASS(), SCode.CLASS()) then inElement1.name == inElement2.name;
404
4/4
✓ Branch 0 taken 307836 times.
✓ Branch 1 taken 107938 times.
✓ Branch 3 taken 10079 times.
✓ Branch 4 taken 297757 times.
415774 case (SCode.COMPONENT(), SCode.COMPONENT()) then inElement1.name == inElement2.name;
405 ✗ case (SCode.DEFINEUNIT(), SCode.DEFINEUNIT()) then inElement1.name == inElement2.name;
406 case (SCode.EXTENDS(), SCode.EXTENDS())
407 ✗ then AbsynUtil.pathEqual(inElement1.baseClassPath, inElement2.baseClassPath);
408 case (SCode.IMPORT(), SCode.IMPORT())
409 526 then AbsynUtil.importEqual(inElement1.imp, inElement2.imp);
410 else false;
411 end match;
412 end elementNameEqual;
413
414 public function enumName ""
415 input SCode.Enum e;
416 output String s;
417 algorithm
418 s := match e
419 case SCode.ENUM(literal = s) then s;
420 end match;
421 end enumName;
422
423 public function isRecord
424 "Return true if Class is a record."
425 input SCode.Element inClass;
426 output Boolean outBoolean;
427 algorithm
428 outBoolean := match inClass
429 case SCode.CLASS(restriction = SCode.R_RECORD()) then true;
430 else false;
431 end match;
432 end isRecord;
433
434 public function isTypeVar
435 "Return true if Class is a type"
436 input SCode.Element inClass;
437 output Boolean outBoolean;
438 algorithm
439 outBoolean := match inClass
440 case SCode.CLASS(restriction = SCode.R_TYPE()) then true;
441 else false;
442 end match;
443 end isTypeVar;
444
445 public function isPolymorphicTypeVar
446 input SCode.Element cls;
447 output Boolean res;
448 algorithm
449 res := match cls
450 case SCode.CLASS(restriction = SCode.R_TYPE(),
451 classDef = SCode.DERIVED(
452 typeSpec = Absyn.TCOMPLEX(
453 path = Absyn.IDENT(name = "polymorphic")))) then true;
454
455 else false;
456 end match;
457 end isPolymorphicTypeVar;
458
459 public function isOperatorRecord
460 "Return true if Class is a operator record."
461 input SCode.Element inClass;
462 output Boolean outBoolean;
463 algorithm
464 outBoolean := match inClass
465 case SCode.CLASS(restriction = SCode.R_RECORD(true)) then true;
466 else false;
467 end match;
468 end isOperatorRecord;
469
470 public function isFunction
471 "Return true if Class is a function."
472 input SCode.Element inClass;
473 output Boolean outBoolean;
474 algorithm
475 outBoolean := match inClass
476 case SCode.CLASS(restriction = SCode.R_FUNCTION()) then true;
477 else false;
478 end match;
479 end isFunction;
480
481 public function isUniontype
482 "Return true if Class is a uniontype."
483 input SCode.Element inClass;
484 output Boolean outBoolean;
485 algorithm
486 outBoolean := match inClass
487 case SCode.CLASS(restriction = SCode.R_UNIONTYPE()) then true;
488 else false;
489 end match;
490 end isUniontype;
491
492 public function isFunctionRestriction
493 "Return true if restriction is a function."
494 input SCode.Restriction inRestriction;
495 output Boolean outBoolean;
496 algorithm
497 outBoolean := match inRestriction
498 case SCode.R_FUNCTION() then true;
499 else false;
500 end match;
501 end isFunctionRestriction;
502
503 public function isFunctionOrExtFunctionRestriction
504 "restriction is function or external function.
505 Otherwise false is returned."
506 input SCode.Restriction r;
507 output Boolean res;
508 algorithm
509 res := match r
510 case SCode.R_FUNCTION(SCode.FR_NORMAL_FUNCTION()) then true;
511 case SCode.R_FUNCTION(SCode.FR_EXTERNAL_FUNCTION()) then true;
512 else false;
513 end match;
514 end isFunctionOrExtFunctionRestriction;
515
516 public function isOperator
517 "restriction is operator or operator function.
518 Otherwise false is returned."
519 input SCode.Element el;
520 output Boolean res;
521 algorithm
522 res := match el
523 case SCode.CLASS(restriction=SCode.R_OPERATOR()) then true;
524 case SCode.CLASS(restriction=SCode.R_FUNCTION(SCode.FR_OPERATOR_FUNCTION())) then true;
525 else false;
526 end match;
527 end isOperator;
528
529 public function isEnumeration
530 input SCode.Element el;
531 output Boolean res;
532 algorithm
533 res := match el
534 case SCode.CLASS(restriction = SCode.R_ENUMERATION()) then true;
535 else false;
536 end match;
537 end isEnumeration;
538
539 public function className
540 "Returns the class name of a Class."
541 input SCode.Element inClass;
542 output String outName;
543 algorithm
544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 529947 times.
529947 SCode.CLASS(name = outName) := inClass;
545 end className;
546
547 public function classSetPartial
548 "Sets the partial attribute of a class element."
549 input output SCode.Element cls;
550 input SCode.Partial inPartial;
551 algorithm
552 () := match cls
553 case SCode.CLASS()
554 algorithm
555 4210 cls.partialPrefix := inPartial;
556 then
557 ();
558 end match;
559 end classSetPartial;
560
561 public function elementEqual
562 "returns true if two elements are equal,
563 i.e. for a component have the same type,
564 name, and attributes, etc."
565 input SCode.Element element1;
566 input SCode.Element element2;
567 output Boolean equal;
568 algorithm
569 equal := matchcontinue (element1, element2)
570 case (SCode.CLASS(), SCode.CLASS())
571
9/14
✓ Branch 0 taken 3022266 times.
✓ Branch 1 taken 39928962 times.
✓ Branch 3 taken 168 times.
✓ Branch 4 taken 3022098 times.
✓ Branch 6 taken 168 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 168 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 168 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 168 times.
✗ Branch 16 not taken.
✗ Branch 18 not taken.
✓ Branch 19 taken 168 times.
42951228 then stringEq(element1.name, element2.name) and
572 prefixesEqual(element1.prefixes, element2.prefixes) and
573 valueEq(element1.encapsulatedPrefix, element2.encapsulatedPrefix) and
574 valueEq(element1.partialPrefix, element2.partialPrefix) and
575 restrictionEqual(element1.restriction, element2.restriction) and
576 classDefEqual(element1.classDef, element2.classDef);
577
578 case (SCode.COMPONENT(), SCode.COMPONENT())
579
11/14
✓ Branch 0 taken 781922 times.
✓ Branch 1 taken 1310416 times.
✓ Branch 3 taken 463538 times.
✓ Branch 4 taken 318384 times.
✓ Branch 6 taken 463538 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 463537 times.
✓ Branch 10 taken 1 time.
✓ Branch 12 taken 463537 times.
✗ Branch 13 not taken.
✓ Branch 15 taken 463530 times.
✓ Branch 16 taken 7 times.
✗ Branch 18 not taken.
✓ Branch 19 taken 463530 times.
2092338 then stringEq(element1.name, element2.name) and
580 prefixesEqual(element1.prefixes, element2.prefixes) and
581 attributesEqual(element1.attributes, element2.attributes) and
582 modEqual(element1.modifications, element2.modifications) and
583 AbsynUtil.typeSpecEqual(element1.typeSpec, element2.typeSpec) and
584 valueEq(element1.condition, element2.condition);
585
586 case (SCode.EXTENDS(), SCode.EXTENDS())
587
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 2876 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2876 then AbsynUtil.pathEqual(element1.baseClassPath, element2.baseClassPath) and
588 modEqual(element1.modifications, element2.modifications);
589
590 case (SCode.IMPORT(), SCode.IMPORT())
591 153919 then AbsynUtil.importEqual(element1.imp, element2.imp);
592
593 case (SCode.DEFINEUNIT(), SCode.DEFINEUNIT())
594 ✗ then stringEq(element1.name, element2.name) and
595 valueEq(element1.exp, element2.exp) and
596 valueEq(element1.weight, element2.weight);
597
598 // otherwise false
599 else false;
600 end matchcontinue;
601 end elementEqual;
602
603 // stefan
604 public function annotationEqual
605 "returns true if 2 annotations are equal"
606 input SCode.Annotation annotation1;
607 input SCode.Annotation annotation2;
608 output Boolean equal = modEqual(annotation1.modification, annotation2.modification);
609 end annotationEqual;
610
611 public function restrictionEqual "Returns true if two Restriction's are equal."
612 input SCode.Restriction restr1;
613 input SCode.Restriction restr2;
614 output Boolean equal;
615 algorithm
616 equal := match(restr1,restr2)
617 local
618 SCode.FunctionRestriction funcRest1,funcRest2;
619
620 case (SCode.R_CLASS(),SCode.R_CLASS()) then true;
621 case (SCode.R_OPTIMIZATION(),SCode.R_OPTIMIZATION()) then true;
622 case (SCode.R_MODEL(),SCode.R_MODEL()) then true;
623 case (SCode.R_RECORD(true),SCode.R_RECORD(true)) then true; // operator record
624 case (SCode.R_RECORD(false),SCode.R_RECORD(false)) then true;
625 case (SCode.R_BLOCK(),SCode.R_BLOCK()) then true;
626 case (SCode.R_CONNECTOR(true),SCode.R_CONNECTOR(true)) then true; // expandable connectors
627 case (SCode.R_CONNECTOR(false),SCode.R_CONNECTOR(false)) then true; // non expandable connectors
628 case (SCode.R_OPERATOR(),SCode.R_OPERATOR()) then true; // operator
629 case (SCode.R_TYPE(),SCode.R_TYPE()) then true;
630 case (SCode.R_PACKAGE(),SCode.R_PACKAGE()) then true;
631 62 case (SCode.R_FUNCTION(funcRest1),SCode.R_FUNCTION(funcRest2)) then funcRestrictionEqual(funcRest1,funcRest2);
632 case (SCode.R_ENUMERATION(),SCode.R_ENUMERATION()) then true;
633 case (SCode.R_PREDEFINED_INTEGER(),SCode.R_PREDEFINED_INTEGER()) then true;
634 case (SCode.R_PREDEFINED_REAL(),SCode.R_PREDEFINED_REAL()) then true;
635 case (SCode.R_PREDEFINED_STRING(),SCode.R_PREDEFINED_STRING()) then true;
636 case (SCode.R_PREDEFINED_BOOLEAN(),SCode.R_PREDEFINED_BOOLEAN()) then true;
637 // BTH
638 case (SCode.R_PREDEFINED_CLOCK(),SCode.R_PREDEFINED_CLOCK()) then true;
639 case (SCode.R_PREDEFINED_ENUMERATION(),SCode.R_PREDEFINED_ENUMERATION()) then true;
640 ✗ case (SCode.R_UNIONTYPE(),SCode.R_UNIONTYPE()) then min(t1==t2 threaded for t1 in restr1.typeVars, t2 in restr2.typeVars);
641 else false;
642 end match;
643 end restrictionEqual;
644
645 public function funcRestrictionEqual
646 input SCode.FunctionRestriction funcRestr1;
647 input SCode.FunctionRestriction funcRestr2;
648 output Boolean equal;
649 algorithm
650 equal := match(funcRestr1,funcRestr2)
651 case (SCode.FR_NORMAL_FUNCTION(),SCode.FR_NORMAL_FUNCTION())
652 62 then AbsynUtil.purityEqual(funcRestr1.purity, funcRestr2.purity);
653 case (SCode.FR_EXTERNAL_FUNCTION(),SCode.FR_EXTERNAL_FUNCTION())
654 ✗ then AbsynUtil.purityEqual(funcRestr1.purity, funcRestr2.purity);
655 case (SCode.FR_OPERATOR_FUNCTION(),SCode.FR_OPERATOR_FUNCTION()) then true;
656 case (SCode.FR_RECORD_CONSTRUCTOR(),SCode.FR_RECORD_CONSTRUCTOR()) then true;
657 case (SCode.FR_PARALLEL_FUNCTION(),SCode.FR_PARALLEL_FUNCTION()) then true;
658 case (SCode.FR_KERNEL_FUNCTION(),SCode.FR_KERNEL_FUNCTION()) then true;
659 else false;
660 end match;
661 end funcRestrictionEqual;
662
663 function enumEqual
664 input SCode.Enum e1;
665 input SCode.Enum e2;
666 output Boolean isEqual = e1.literal == e2.literal;
667 end enumEqual;
668
669 protected function classDefEqual
670 "Returns true if Two ClassDef's are equal"
671 input SCode.ClassDef cdef1;
672 input SCode.ClassDef cdef2;
673 output Boolean equal;
674 algorithm
675 equal := match(cdef1,cdef2)
676 case (SCode.PARTS(), SCode.PARTS())
677 ✗ then List.isEqualOnTrue(cdef1.elementLst, cdef2.elementLst, elementEqual) and
678 List.isEqualOnTrue(cdef1.normalEquationLst, cdef2.normalEquationLst, equationEqual) and
679 List.isEqualOnTrue(cdef1.initialEquationLst, cdef2.initialEquationLst, equationEqual) and
680 List.isEqualOnTrue(cdef1.normalAlgorithmLst, cdef2.normalAlgorithmLst, algorithmEqual) and
681 List.isEqualOnTrue(cdef1.initialAlgorithmLst, cdef2.initialAlgorithmLst, algorithmEqual);
682
683 case (SCode.DERIVED(), SCode.DERIVED())
684
3/6
✓ Branch 1 taken 167 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 167 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 167 times.
167 then AbsynUtil.typeSpecEqual(cdef1.typeSpec, cdef2.typeSpec) and
685 modEqual(cdef1.modifications, cdef2.modifications) and
686 attributesEqual(cdef1.attributes, cdef2.attributes);
687
688 case (SCode.ENUMERATION(), SCode.ENUMERATION())
689 1 then List.isEqualOnTrue(cdef1.enumLst, cdef2.enumLst, enumEqual);
690
691 case (SCode.CLASS_EXTENDS(), SCode.CLASS_EXTENDS())
692 ✗ then modEqual(cdef1.modifications, cdef2.modifications) and
693 classDefEqual(cdef1.composition, cdef2.composition);
694
695 case (SCode.PDER(), SCode.PDER())
696 ✗ then List.isEqualOnTrue(cdef1.derivedVariables, cdef2.derivedVariables, stringEq);
697
698 else false;
699 end match;
700 end classDefEqual;
701
702 protected function arraydimOptEqual
703 "Returns true if two Option<ArrayDim> are equal"
704 input Option<Absyn.ArrayDim> adopt1;
705 input Option<Absyn.ArrayDim> adopt2;
706 output Boolean equal;
707 algorithm
708 equal := match(adopt1,adopt2)
709 local
710 list<Absyn.Subscript> lst1,lst2;
711 case (NONE(), NONE()) then true;
712 ✗ case (SOME(lst1), SOME(lst2)) then List.isEqualOnTrue(lst1,lst2,subscriptEqual);
713 else false;
714 end match;
715 end arraydimOptEqual;
716
717 protected function subscriptEqual
718 "Returns true if two Absyn.Subscript are equal"
719 input Absyn.Subscript sub1;
720 input Absyn.Subscript sub2;
721 output Boolean equal;
722 algorithm
723 equal := match(sub1,sub2)
724 local
725 Absyn.Exp e1,e2;
726
727 case(Absyn.NOSUB(),Absyn.NOSUB()) then true;
728 case(Absyn.SUBSCRIPT(e1),Absyn.SUBSCRIPT(e2))
729 ✗ then AbsynUtil.expEqual(e1,e2);
730
731 end match;
732 end subscriptEqual;
733
734 protected function algorithmEqual
735 "Returns true if two Algorithm's are equal."
736 input SCode.AlgorithmSection alg1;
737 input SCode.AlgorithmSection alg2;
738 output Boolean equal;
739 algorithm
740 ✗ equal := List.isEqualOnTrue(alg1.statements, alg2.statements, statementEqual);
741 end algorithmEqual;
742
743 protected function statementEqual
744 "Returns true if two Absyn.Algorithm are equal."
745 input SCode.Statement ai1;
746 input SCode.Statement ai2;
747 output Boolean equal;
748 algorithm
749 equal := matchcontinue(ai1,ai2)
750 local
751 Absyn.Algorithm alg1,alg2;
752 SCode.Statement a1,a2;
753 Absyn.ComponentRef cr1,cr2;
754 Absyn.Exp e1,e2,e11,e12,e21,e22;
755 Boolean b1,b2;
756
757 case(SCode.ALG_ASSIGN(assignComponent = Absyn.CREF(cr1), value = e1),
758 SCode.ALG_ASSIGN(assignComponent = Absyn.CREF(cr2), value = e2))
759 algorithm
760 ✗ b1 := AbsynUtil.crefEqual(cr1,cr2);
761 ✗ b2 := AbsynUtil.expEqual(e1,e2);
762 ✗ equal := boolAnd(b1,b2);
763 then equal;
764 case(SCode.ALG_ASSIGN(assignComponent = e11 as Absyn.TUPLE(_), value = e12),SCode.ALG_ASSIGN(assignComponent = e21 as Absyn.TUPLE(_), value = e22))
765 algorithm
766 ✗ b1 := AbsynUtil.expEqual(e11,e21);
767 ✗ b2 := AbsynUtil.expEqual(e12,e22);
768 ✗ equal := boolAnd(b1,b2);
769 then equal;
770 // base it on equality for now as the ones below are not implemented!
771 case(a1, a2)
772 algorithm
773 ✗ Absyn.ALGORITHMITEM(algorithm_ = alg1) := statementToAlgorithmItem(a1);
774 ✗ Absyn.ALGORITHMITEM(algorithm_ = alg2) := statementToAlgorithmItem(a2);
775 // Don't compare comments and line numbers
776 ✗ then valueEq(alg1, alg2);
777 // maybe replace failure/equality with these:
778 //case(Absyn.ALG_IF(_,_,_,_),Absyn.ALG_IF(_,_,_,_)) then false; // TODO: SCode.ALG_IF
779 //case (Absyn.ALG_FOR(_,_),Absyn.ALG_FOR(_,_)) then false; // TODO: SCode.ALG_FOR
780 //case (Absyn.ALG_WHILE(_,_),Absyn.ALG_WHILE(_,_)) then false; // TODO: SCode.ALG_WHILE
781 //case(Absyn.ALG_WHEN_A(_,_,_),Absyn.ALG_WHEN_A(_,_,_)) then false; //TODO: SCode.ALG_WHILE
782 //case (Absyn.ALG_NORETCALL(_,_),Absyn.ALG_NORETCALL(_,_)) then false; //TODO: SCode.ALG_NORETCALL
783 else false;
784 end matchcontinue;
785 end statementEqual;
786
787 protected function equationEqual
788 "Returns true if two equations are equal."
789 input SCode.Equation eq1;
790 input SCode.Equation eq2;
791 output Boolean equal;
792 algorithm
793 equal := matchcontinue(eq1,eq2)
794 local
795 list<list<SCode.Equation>> tb1,tb2;
796 Absyn.Exp cond1,cond2;
797 list<Absyn.Exp> ifcond1,ifcond2;
798 Absyn.Exp e11,e12,e21,e22,exp1,exp2,c1,c2,m1,m2,e1,e2;
799 Absyn.ComponentRef cr11,cr12,cr21,cr22,cr1,cr2;
800 Absyn.Ident id1,id2;
801 list<SCode.Equation> fb1,fb2,eql1,eql2,elst1,elst2;
802
803 case (SCode.EQ_IF(condition = ifcond1, thenBranch = tb1, elseBranch = fb1),SCode.EQ_IF(condition = ifcond2, thenBranch = tb2, elseBranch = fb2))
804 algorithm
805 ✗ true := equationEqual2(tb1,tb2);
806 ✗ true := List.isEqualOnTrue(fb1,fb2,equationEqual);
807 ✗ true := List.isEqualOnTrue(ifcond1,ifcond2,AbsynUtil.expEqual);
808 then
809 true;
810
811 case(SCode.EQ_EQUALS(expLeft = e11, expRight = e12),SCode.EQ_EQUALS(expLeft = e21, expRight = e22))
812 algorithm
813 ✗ true := AbsynUtil.expEqual(e11,e21);
814 ✗ true := AbsynUtil.expEqual(e12,e22);
815 then
816 true;
817
818 case(SCode.EQ_PDE(expLeft = e11, expRight = e12, domain = cr1),SCode.EQ_PDE(expLeft = e21, expRight = e22, domain = cr2))
819 algorithm
820 ✗ true := AbsynUtil.expEqual(e11,e21);
821 ✗ true := AbsynUtil.expEqual(e12,e22);
822 ✗ true := AbsynUtil.crefEqual(cr1,cr2);
823 then
824 true;
825
826 case(SCode.EQ_CONNECT(crefLeft = cr11, crefRight = cr12),SCode.EQ_CONNECT(crefLeft = cr21, crefRight = cr22))
827 algorithm
828 ✗ true := AbsynUtil.crefEqual(cr11,cr21);
829 ✗ true := AbsynUtil.crefEqual(cr12,cr22);
830 then
831 true;
832
833 case (SCode.EQ_FOR(index = id1, range = SOME(exp1), eEquationLst = eql1),SCode.EQ_FOR(index = id2, range = SOME(exp2), eEquationLst = eql2))
834 algorithm
835 ✗ true := List.isEqualOnTrue(eql1,eql2,equationEqual);
836 ✗ true := AbsynUtil.expEqual(exp1,exp2);
837 ✗ true := stringEq(id1,id2);
838 then
839 true;
840
841 case (SCode.EQ_FOR(index = id1, range = NONE(), eEquationLst = eql1),SCode.EQ_FOR(index = id2, range = NONE(), eEquationLst = eql2))
842 algorithm
843 ✗ true := List.isEqualOnTrue(eql1,eql2,equationEqual);
844 ✗ true := stringEq(id1,id2);
845 then
846 true;
847
848 case (SCode.EQ_WHEN(condition = cond1, eEquationLst = elst1),SCode.EQ_WHEN(condition = cond2, eEquationLst = elst2)) // TODO: elsewhen not checked yet.
849 algorithm
850 ✗ true := List.isEqualOnTrue(elst1,elst2,equationEqual);
851 ✗ true := AbsynUtil.expEqual(cond1,cond2);
852 then
853 true;
854
855 case (SCode.EQ_ASSERT(condition = c1, message = m1),SCode.EQ_ASSERT(condition = c2, message = m2))
856 algorithm
857 ✗ true := AbsynUtil.expEqual(c1,c2);
858 ✗ true := AbsynUtil.expEqual(m1,m2);
859 then
860 true;
861
862 case (SCode.EQ_REINIT(), SCode.EQ_REINIT())
863 algorithm
864 ✗ true := AbsynUtil.expEqual(eq1.cref, eq2.cref);
865 ✗ true := AbsynUtil.expEqual(eq1.expReinit, eq2.expReinit);
866 then
867 true;
868
869 case (SCode.EQ_NORETCALL(exp = e1), SCode.EQ_NORETCALL(exp = e2))
870 algorithm
871 ✗ true := AbsynUtil.expEqual(e1,e2);
872 then
873 true;
874
875 // otherwise false
876 else false;
877 end matchcontinue;
878 end equationEqual;
879
880 protected function equationEqual2
881 "Author BZ
882 Helper function for equationEqual2, does compare list<list<equation>> (else ifs in ifequations.)"
883 input list<list<SCode.Equation>> inTb1;
884 input list<list<SCode.Equation>> inTb2;
885 output Boolean bOut;
886 algorithm
887 bOut := matchcontinue(inTb1,inTb2)
888 local
889 list<SCode.Equation> tb_1,tb_2;
890 list<list<SCode.Equation>> tb1,tb2;
891
892 case({},{}) then true;
893 case(_,{}) then false;
894 case({},_) then false;
895 case(tb_1::tb1,tb_2::tb2)
896 algorithm
897 ✗ true := List.isEqualOnTrue(tb_1,tb_2,equationEqual);
898 ✗ true := equationEqual2(tb1,tb2);
899 then
900 true;
901 case(_::_,_::_) then false;
902
903 end matchcontinue;
904 end equationEqual2;
905
906 public function modEqual
907 "Return true if two Mod:s are equal"
908 input SCode.Mod mod1;
909 input SCode.Mod mod2;
910 output Boolean equal;
911 algorithm
912 equal := matchcontinue(mod1,mod2)
913 local
914 SCode.Final f1,f2;
915 SCode.Each each1,each2;
916 list<SCode.SubMod> submodlst1,submodlst2;
917 Absyn.Exp e1,e2;
918 SCode.Element elt1,elt2;
919
920 case (SCode.MOD(f1,each1,submodlst1,SOME(e1),_),SCode.MOD(f2,each2,submodlst2,SOME(e2),_))
921 algorithm
922
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 202458 times.
202458 true := valueEq(f1,f2);
923
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 202458 times.
202458 true := eachEqual(each1,each2);
924
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 202458 times.
202458 true := subModsEqual(submodlst1,submodlst2);
925
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 202458 times.
202458 true := AbsynUtil.expEqual(e1,e2);
926 then
927 true;
928
929 case (SCode.MOD(f1,each1,submodlst1,NONE(),_),SCode.MOD(f2,each2,submodlst2,NONE(),_))
930 algorithm
931
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 28056 times.
28056 true := valueEq(f1,f2);
932
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 28056 times.
28056 true := eachEqual(each1,each2);
933
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 28056 times.
28056 true := subModsEqual(submodlst1,submodlst2);
934 then
935 true;
936
937 case (SCode.NOMOD(),SCode.NOMOD()) then true;
938
939 case (SCode.REDECL(f1,each1,elt1),SCode.REDECL(f2,each2,elt2))
940 algorithm
941
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 179 times.
179 true := valueEq(f1,f2);
942
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 179 times.
179 true := eachEqual(each1,each2);
943
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 179 times.
179 true := elementEqual(elt1, elt2);
944 then
945 true;
946
947 case (SCode.BREAK_COMPONENT(), SCode.BREAK_COMPONENT()) then true;
948
949 case (SCode.BREAK_CONNECT(), SCode.BREAK_CONNECT())
950 ✗ then AbsynUtil.crefEqual(mod1.lhs, mod2.lhs) and AbsynUtil.crefEqual(mod1.rhs, mod2.lhs);
951
952 else false;
953
954 end matchcontinue;
955 end modEqual;
956
957 protected function subModsEqual
958 "Return true if two subModifier lists are equal"
959 input list<SCode.SubMod> inSubModLst1;
960 input list<SCode.SubMod> inSubModLst2;
961 output Boolean equal;
962 algorithm
963 equal := match(inSubModLst1,inSubModLst2)
964 local
965 SCode.Ident id1,id2;
966 SCode.Mod mod1,mod2;
967 list<SCode.SubMod> subModLst1,subModLst2;
968
969 case ({},{}) then true;
970
971 case (SCode.NAMEMOD(id1,mod1)::subModLst1,SCode.NAMEMOD(id2,mod2)::subModLst2) guard stringEq(id1,id2) and modEqual(mod1,mod2) and subModsEqual(subModLst1,subModLst2)
972 then
973 true;
974
975 else false;
976 end match;
977 end subModsEqual;
978
979 protected function subscriptsEqual
980 "Returns true if two subscript lists are equal"
981 input list<SCode.Subscript> inSs1;
982 input list<SCode.Subscript> inSs2;
983 output Boolean equal;
984 algorithm
985 equal := matchcontinue(inSs1,inSs2)
986 local
987 Absyn.Exp e1,e2;
988 list<SCode.Subscript> ss1,ss2;
989
990 case({},{}) then true;
991
992 case(Absyn.NOSUB()::ss1,Absyn.NOSUB()::ss2)
993 ✗ then subscriptsEqual(ss1,ss2);
994
995 case(Absyn.SUBSCRIPT(e1)::ss1,Absyn.SUBSCRIPT(e2)::ss2)
996 algorithm
997 ✗ true := AbsynUtil.expEqual(e1,e2);
998 ✗ true := subscriptsEqual(ss1,ss2);
999 then
1000 true;
1001
1002 else false;
1003 end matchcontinue;
1004 end subscriptsEqual;
1005
1006 public function attributesEqual
1007 "Returns true if two Atributes are equal"
1008 input SCode.Attributes attr1;
1009 input SCode.Attributes attr2;
1010 output Boolean equal;
1011 algorithm
1012
7/12
✓ Branch 1 taken 463709 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 463709 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 463709 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 463707 times.
✓ Branch 11 taken 2 times.
✓ Branch 13 taken 463707 times.
✗ Branch 14 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 463707 times.
463709 equal := arrayDimEqual(attr1.arrayDims, attr2.arrayDims) and
1013 valueEq(attr1.connectorType, attr2.connectorType) and
1014 parallelismEqual(attr1.parallelism, attr2.parallelism) and
1015 variabilityEqual(attr1.variability, attr2.variability) and
1016 AbsynUtil.directionEqual(attr1.direction, attr2.direction) and
1017 AbsynUtil.isFieldEqual(attr1.isField, attr2.isField);
1018 end attributesEqual;
1019
1020 public function parallelismEqual
1021 "Returns true if two Parallelism prefixes are equal"
1022 input SCode.Parallelism prl1;
1023 input SCode.Parallelism prl2;
1024 output Boolean equal;
1025 algorithm
1026 equal := match(prl1,prl2)
1027 case(SCode.PARGLOBAL(),SCode.PARGLOBAL()) then true;
1028 case(SCode.PARLOCAL(),SCode.PARLOCAL()) then true;
1029 case(SCode.NON_PARALLEL(),SCode.NON_PARALLEL()) then true;
1030 else false;
1031 end match;
1032 end parallelismEqual;
1033
1034 public function variabilityEqual
1035 "Returns true if two Variablity prefixes are equal"
1036 input SCode.Variability var1;
1037 input SCode.Variability var2;
1038 output Boolean equal;
1039 algorithm
1040 equal := match(var1,var2)
1041 case(SCode.VAR(),SCode.VAR()) then true;
1042 case(SCode.DISCRETE(),SCode.DISCRETE()) then true;
1043 case(SCode.PARAM(),SCode.PARAM()) then true;
1044 case(SCode.CONST(),SCode.CONST()) then true;
1045 else false;
1046 end match;
1047 end variabilityEqual;
1048
1049 protected function arrayDimEqual
1050 "Return true if two arraydims are equal"
1051 input Absyn.ArrayDim iad1;
1052 input Absyn.ArrayDim iad2;
1053 output Boolean equal;
1054 algorithm
1055 equal := matchcontinue(iad1,iad2)
1056 local
1057 Absyn.Exp e1,e2;
1058 Absyn.ArrayDim ad1,ad2;
1059
1060 case({},{}) then true;
1061
1062 case (Absyn.NOSUB()::ad1, Absyn.NOSUB()::ad2)
1063 algorithm
1064
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6353 times.
6353 true := arrayDimEqual(ad1,ad2);
1065 then
1066 true;
1067
1068 case (Absyn.SUBSCRIPT(e1)::ad1,Absyn.SUBSCRIPT(e2)::ad2)
1069 algorithm
1070
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 56446 times.
56446 true := AbsynUtil.expEqual(e1,e2);
1071
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 56446 times.
56446 true := arrayDimEqual(ad1,ad2);
1072 then
1073 true;
1074
1075 else false;
1076 end matchcontinue;
1077 end arrayDimEqual;
1078
1079 public function setClassRestriction "Sets the restriction of a SCode Class"
1080 input SCode.Restriction r;
1081 input output SCode.Element cl;
1082 algorithm
1083 () := match cl
1084 case SCode.CLASS()
1085 algorithm
1086 ✗ cl.restriction := r;
1087 then
1088 ();
1089 end match;
1090 end setClassRestriction;
1091
1092 public function setClassName "Sets the name of a SCode Class"
1093 input SCode.Ident name;
1094 input output SCode.Element cl;
1095 algorithm
1096 () := match cl
1097 case SCode.CLASS()
1098 algorithm
1099
4/4
✓ Branch 0 taken 1186 times.
✓ Branch 1 taken 23429 times.
✓ Branch 3 taken 98 times.
✓ Branch 4 taken 1088 times.
24615 if name <> cl.name then
1100 23527 cl.name := name;
1101 end if;
1102 then
1103 ();
1104 end match;
1105 end setClassName;
1106
1107 public function makeClassPartial
1108 input SCode.Element inClass;
1109 output SCode.Element outClass = inClass;
1110 algorithm
1111 outClass := match outClass
1112 case SCode.CLASS(partialPrefix = SCode.NOT_PARTIAL())
1113 algorithm
1114 ✗ outClass.partialPrefix := SCode.PARTIAL();
1115 then
1116 outClass;
1117
1118 else outClass;
1119 end match;
1120 end makeClassPartial;
1121
1122 public function setClassPartialPrefix "Sets the partial prefix of a SCode Class"
1123 input SCode.Partial partialPrefix;
1124 input output SCode.Element cl;
1125 algorithm
1126 () := match cl
1127 case SCode.CLASS()
1128 algorithm
1129
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 16356 times.
16362 if not valueEq(partialPrefix, cl.partialPrefix) then
1130 6 cl.partialPrefix := partialPrefix;
1131 end if;
1132 then
1133 ();
1134 end match;
1135 end setClassPartialPrefix;
1136
1137 public function findIteratorIndexedCrefsInEquations
1138 input list<SCode.Equation> inEqs;
1139 input String inIterator;
1140 input list<AbsynUtil.IteratorIndexedCref> inCrefs = {};
1141 output list<AbsynUtil.IteratorIndexedCref> outCrefs;
1142 algorithm
1143 ✗ outCrefs := List.fold1(inEqs, findIteratorIndexedCrefsInEquation, inIterator,
1144 inCrefs);
1145 end findIteratorIndexedCrefsInEquations;
1146
1147 public function findIteratorIndexedCrefsInEquation
1148 input SCode.Equation inEq;
1149 input String inIterator;
1150 input list<AbsynUtil.IteratorIndexedCref> inCrefs = {};
1151 output list<AbsynUtil.IteratorIndexedCref> outCrefs;
1152 algorithm
1153 ✗ outCrefs := foldEquationsExps(inEq,
1154 function AbsynUtil.findIteratorIndexedCrefs(inIterator = inIterator), inCrefs);
1155 end findIteratorIndexedCrefsInEquation;
1156
1157 public function findIteratorIndexedCrefsInStatements
1158 input list<SCode.Statement> inStatements;
1159 input String inIterator;
1160 input list<AbsynUtil.IteratorIndexedCref> inCrefs = {};
1161 output list<AbsynUtil.IteratorIndexedCref> outCrefs;
1162 algorithm
1163 4 outCrefs := List.fold1(inStatements, findIteratorIndexedCrefsInStatement,
1164 inIterator, inCrefs);
1165 end findIteratorIndexedCrefsInStatements;
1166
1167 public function findIteratorIndexedCrefsInStatement
1168 input SCode.Statement inStatement;
1169 input String inIterator;
1170 input list<AbsynUtil.IteratorIndexedCref> inCrefs = {};
1171 output list<AbsynUtil.IteratorIndexedCref> outCrefs;
1172 algorithm
1173 4 outCrefs := foldStatementsExps(inStatement,
1174 function AbsynUtil.findIteratorIndexedCrefs(inIterator = inIterator), inCrefs);
1175 end findIteratorIndexedCrefsInStatement;
1176
1177 protected function filterComponents
1178 "Filters out the components from the given list of elements, as well as their names."
1179 input list<SCode.Element> inElements;
1180 output list<SCode.Element> outComponents;
1181 output list<String> outComponentNames;
1182 algorithm
1183 135 (outComponents, outComponentNames) := List.map_2(inElements, filterComponents2);
1184 end filterComponents;
1185
1186 protected function filterComponents2
1187 input SCode.Element inElement;
1188 output SCode.Element outComponent;
1189 output String outName;
1190 algorithm
1191
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1024 times.
✓ Branch 3 taken 1024 times.
✗ Branch 4 not taken.
1024 SCode.COMPONENT(name = outName) := inElement;
1192 outComponent := inElement;
1193 end filterComponents2;
1194
1195 public function getClassComponents
1196 "This function returns the components from a class"
1197 input SCode.Element cl;
1198 output list<SCode.Element> compElts;
1199 output list<String> compNames;
1200 algorithm
1201 (compElts,compNames) := match cl
1202 local
1203 list<SCode.Element> elts, comps;
1204 list<String> names;
1205
1206 case SCode.CLASS(classDef = SCode.PARTS(elementLst = elts))
1207 algorithm
1208 135 (comps, names) := filterComponents(elts);
1209 then (comps,names);
1210 case SCode.CLASS(classDef = SCode.CLASS_EXTENDS(composition = SCode.PARTS(elementLst = elts)))
1211 algorithm
1212 ✗ (comps, names) := filterComponents(elts);
1213 then (comps,names);
1214 end match;
1215 end getClassComponents;
1216
1217 public function getClassElements
1218 "This function returns the components from a class"
1219 input SCode.Element cl;
1220 output list<SCode.Element> elts;
1221 algorithm
1222 elts := match cl
1223 case SCode.CLASS(classDef = SCode.PARTS(elementLst = elts))
1224 then elts;
1225 case SCode.CLASS(classDef = SCode.CLASS_EXTENDS(composition = SCode.PARTS(elementLst = elts)))
1226 then elts;
1227 else {};
1228 end match;
1229 end getClassElements;
1230
1231 public function makeEnumType
1232 "Creates an EnumType element from an enumeration literal and an optional
1233 comment."
1234 input SCode.Enum inEnum;
1235 input SourceInfo inInfo;
1236 output SCode.Element outEnumType;
1237 protected
1238 String literal;
1239 SCode.Comment comment;
1240 algorithm
1241 898634 SCode.ENUM(literal = literal, comment = comment) := inEnum;
1242 898634 checkValidEnumLiteral(literal, inInfo);
1243 898634 outEnumType := SCode.COMPONENT(literal, SCode.defaultPrefixes, SCode.defaultConstAttr,
1244 Absyn.TPATH(Absyn.IDENT("EnumType"), NONE()),
1245 SCode.NOMOD(), comment, NONE(), inInfo);
1246 end makeEnumType;
1247
1248 public function variabilityOr
1249 "Returns the more constant of two Variabilities
1250 (considers VAR() < DISCRETE() < PARAM() < CONST()),
1251 similarly to Types.constOr."
1252 input SCode.Variability inConst1;
1253 input SCode.Variability inConst2;
1254 output SCode.Variability outConst;
1255 algorithm
1256 outConst := match(inConst1, inConst2)
1257 case (SCode.CONST(),_) then SCode.CONST();
1258 case (_,SCode.CONST()) then SCode.CONST();
1259 case (SCode.PARAM(),_) then SCode.PARAM();
1260 case (_,SCode.PARAM()) then SCode.PARAM();
1261 case (SCode.DISCRETE(),_) then SCode.DISCRETE();
1262 case (_,SCode.DISCRETE()) then SCode.DISCRETE();
1263 else SCode.VAR();
1264 end match;
1265 end variabilityOr;
1266
1267 public function statementToAlgorithmItem
1268 "Transforms SCode.Statement back to Absyn.AlgorithmItem. Discards the comment.
1269 Only to be used to unparse statements again."
1270 input SCode.Statement stmt;
1271 output Absyn.AlgorithmItem algi;
1272 algorithm
1273 algi := match stmt
1274 local
1275 Absyn.ComponentRef functionCall;
1276 Absyn.Exp assignComponent;
1277 Absyn.Exp boolExpr;
1278 Absyn.Exp value;
1279 String iterator;
1280 Option<Absyn.Exp> range;
1281 Absyn.FunctionArgs functionArgs;
1282 SourceInfo info;
1283 list<Absyn.Exp> conditions;
1284 list<list<SCode.Statement>> stmtsList;
1285 list<SCode.Statement> body,trueBranch,elseBranch;
1286 list<tuple<Absyn.Exp, list<SCode.Statement>>> branches;
1287 list<Absyn.AlgorithmItem> algs1,algs2;
1288 list<list<Absyn.AlgorithmItem>> algsLst;
1289 list<tuple<Absyn.Exp,list<Absyn.AlgorithmItem>>> abranches;
1290
1291 case SCode.ALG_ASSIGN(assignComponent,value,_,info)
1292 ✗ then Absyn.ALGORITHMITEM(Absyn.ALG_ASSIGN(assignComponent,value),NONE(),info);
1293
1294 case SCode.ALG_IF(boolExpr,trueBranch,branches,elseBranch,_,info)
1295 algorithm
1296 ✗ algs1 := List.map(trueBranch,statementToAlgorithmItem);
1297
1298 ✗ conditions := List.map(branches, Util.tuple21);
1299 ✗ stmtsList := List.map(branches, Util.tuple22);
1300 ✗ algsLst := List.mapList(stmtsList, statementToAlgorithmItem);
1301 ✗ abranches := List.zip(conditions,algsLst);
1302
1303 ✗ algs2 := List.map(elseBranch,statementToAlgorithmItem);
1304 ✗ then Absyn.ALGORITHMITEM(Absyn.ALG_IF(boolExpr,algs1,abranches,algs2),NONE(),info);
1305
1306 case SCode.ALG_FOR(iterator,range,body,_,info)
1307 algorithm
1308 ✗ algs1 := List.map(body,statementToAlgorithmItem);
1309 ✗ then Absyn.ALGORITHMITEM(Absyn.ALG_FOR({Absyn.ITERATOR(iterator,NONE(),range)},algs1),NONE(),info);
1310
1311 case SCode.ALG_PARFOR(iterator,range,body,_,info)
1312 algorithm
1313 ✗ algs1 := List.map(body,statementToAlgorithmItem);
1314 ✗ then Absyn.ALGORITHMITEM(Absyn.ALG_PARFOR({Absyn.ITERATOR(iterator,NONE(),range)},algs1),NONE(),info);
1315
1316 case SCode.ALG_WHILE(boolExpr,body,_,info)
1317 algorithm
1318 ✗ algs1 := List.map(body,statementToAlgorithmItem);
1319 ✗ then Absyn.ALGORITHMITEM(Absyn.ALG_WHILE(boolExpr,algs1),NONE(),info);
1320
1321 case SCode.ALG_WHEN_A(branches,_,info)
1322 algorithm
1323 ✗ boolExpr::conditions := List.map(branches, Util.tuple21);
1324 ✗ stmtsList := List.map(branches, Util.tuple22);
1325 ✗ algs1::algsLst := List.mapList(stmtsList, statementToAlgorithmItem);
1326 ✗ abranches := List.zip(conditions,algsLst);
1327 ✗ then Absyn.ALGORITHMITEM(Absyn.ALG_WHEN_A(boolExpr,algs1,abranches),NONE(),info);
1328
1329 case SCode.ALG_ASSERT()
1330 ✗ then Absyn.ALGORITHMITEM(Absyn.ALG_NORETCALL(Absyn.CREF_IDENT("assert", {}),
1331 Absyn.FUNCTIONARGS({stmt.condition, stmt.message, stmt.level}, {})), NONE(), stmt.info);
1332
1333 case SCode.ALG_TERMINATE()
1334 ✗ then Absyn.ALGORITHMITEM(Absyn.ALG_NORETCALL(Absyn.CREF_IDENT("terminate", {}),
1335 Absyn.FUNCTIONARGS({stmt.message}, {})), NONE(), stmt.info);
1336
1337 case SCode.ALG_REINIT()
1338 ✗ then Absyn.ALGORITHMITEM(Absyn.ALG_NORETCALL(Absyn.CREF_IDENT("reinit", {}),
1339 Absyn.FUNCTIONARGS({stmt.cref, stmt.newValue}, {})), NONE(), stmt.info);
1340
1341 case SCode.ALG_NORETCALL(Absyn.CALL(function_=functionCall,functionArgs=functionArgs),_,info)
1342 ✗ then Absyn.ALGORITHMITEM(Absyn.ALG_NORETCALL(functionCall,functionArgs),NONE(),info);
1343
1344 case SCode.ALG_RETURN(_,info)
1345 ✗ then Absyn.ALGORITHMITEM(Absyn.ALG_RETURN(),NONE(),info);
1346
1347 case SCode.ALG_BREAK(_,info)
1348 ✗ then Absyn.ALGORITHMITEM(Absyn.ALG_BREAK(),NONE(),info);
1349
1350 case SCode.ALG_CONTINUE(_,info)
1351 ✗ then Absyn.ALGORITHMITEM(Absyn.ALG_CONTINUE(),NONE(),info);
1352
1353 case SCode.ALG_FAILURE(body,_,info)
1354 algorithm
1355 ✗ algs1 := List.map(body,statementToAlgorithmItem);
1356 ✗ then Absyn.ALGORITHMITEM(Absyn.ALG_FAILURE(algs1),NONE(),info);
1357 end match;
1358 end statementToAlgorithmItem;
1359
1360 public function emptyModOrEquality
1361 "Checks if a Mod is empty (or only an equality binding is present)"
1362 input SCode.Mod mod;
1363 output Boolean b;
1364 algorithm
1365 b := match mod
1366 case SCode.NOMOD() then true;
1367 case SCode.MOD(subModLst={}) then true;
1368 else false;
1369 end match;
1370 end emptyModOrEquality;
1371
1372 public function isComponentWithDirection
1373 input SCode.Element elt;
1374 input Absyn.Direction dir1;
1375 output Boolean b;
1376 algorithm
1377 b := match elt
1378 local
1379 Absyn.Direction dir2;
1380
1381 case SCode.COMPONENT(attributes = SCode.ATTR(direction = dir2))
1382 4708 then AbsynUtil.directionEqual(dir1,dir2);
1383
1384 else false;
1385 end match;
1386 end isComponentWithDirection;
1387
1388 public function isComponent
1389 input SCode.Element elt;
1390 output Boolean b;
1391 algorithm
1392 b := match elt
1393 case SCode.COMPONENT() then true;
1394 else false;
1395 end match;
1396 end isComponent;
1397
1398 public function isNotComponent
1399 input SCode.Element elt;
1400 output Boolean b;
1401 algorithm
1402 b := match elt
1403 case SCode.COMPONENT() then false;
1404 else true;
1405 end match;
1406 end isNotComponent;
1407
1408 public function isClassOrComponent
1409 input SCode.Element inElement;
1410 output Boolean outIsClassOrComponent;
1411 algorithm
1412 outIsClassOrComponent := match inElement
1413 case SCode.CLASS() then true;
1414 case SCode.COMPONENT() then true;
1415 end match;
1416 end isClassOrComponent;
1417
1418 public function isClass
1419 input SCode.Element inElement;
1420 output Boolean outIsClass;
1421 algorithm
1422 outIsClass := match inElement
1423 case SCode.CLASS() then true;
1424 else false;
1425 end match;
1426 end isClass;
1427
1428 public function isImport
1429 input SCode.Element element;
1430 output Boolean isImport;
1431 algorithm
1432 isImport := match element
1433 case SCode.IMPORT() then true;
1434 else false;
1435 end match;
1436 end isImport;
1437
1438 public function foldEquations<ArgT>
1439 "Calls the given function on the equation and all its subequations, and
1440 updates the argument for each call."
1441 input SCode.Equation inEquation;
1442 input FoldFunc inFunc;
1443 input ArgT inArg;
1444 output ArgT outArg;
1445
1446 partial function FoldFunc
1447 input SCode.Equation inEquation;
1448 input ArgT inArg;
1449 output ArgT outArg;
1450 end FoldFunc;
1451 algorithm
1452 ✗ outArg := inFunc(inEquation, inArg);
1453
1454 outArg := match inEquation
1455 local
1456 list<SCode.Equation> eql;
1457
1458 case SCode.EQ_IF()
1459 algorithm
1460 ✗ outArg := List.foldList(inEquation.thenBranch, function foldEquations(inFunc = inFunc), outArg);
1461 ✗ then
1462 List.fold1(inEquation.elseBranch, foldEquations, inFunc, outArg);
1463
1464 case SCode.EQ_FOR()
1465 ✗ then List.fold1(inEquation.eEquationLst, foldEquations, inFunc, outArg);
1466
1467 case SCode.EQ_WHEN()
1468 algorithm
1469 ✗ outArg := List.fold1(inEquation.eEquationLst, foldEquations, inFunc, outArg);
1470
1471 ✗ for branch in inEquation.elseBranches loop
1472 ✗ (_, eql) := branch;
1473 ✗ outArg := List.fold1(eql, foldEquations, inFunc, outArg);
1474 end for;
1475 then
1476 outArg;
1477
1478 end match;
1479 end foldEquations;
1480
1481 public function foldEquationsExps<ArgT>
1482 "Calls the given function on all expressions inside the equation, and updates
1483 the argument for each call."
1484 input SCode.Equation inEquation;
1485 input FoldFunc inFunc;
1486 input ArgT inArg;
1487 output ArgT outArg = inArg;
1488
1489 partial function FoldFunc
1490 input Absyn.Exp inExp;
1491 input ArgT inArg;
1492 output ArgT outArg;
1493 end FoldFunc;
1494 algorithm
1495 outArg := match inEquation
1496 local
1497 Absyn.Exp exp;
1498 list<SCode.Equation> eql;
1499
1500 case SCode.EQ_IF()
1501 algorithm
1502 43 outArg := List.fold(inEquation.condition, inFunc, outArg);
1503 43 outArg := List.foldList(inEquation.thenBranch, function foldEquationsExps(inFunc = inFunc), outArg);
1504 43 then
1505 List.fold1(inEquation.elseBranch, foldEquationsExps, inFunc, outArg);
1506
1507 case SCode.EQ_EQUALS()
1508 algorithm
1509
1/2
✓ Branch 0 taken 228 times.
✗ Branch 1 not taken.
228 outArg := inFunc(inEquation.expLeft, outArg);
1510
1/2
✓ Branch 0 taken 228 times.
✗ Branch 1 not taken.
228 outArg := inFunc(inEquation.expRight, outArg);
1511 then
1512 outArg;
1513
1514 case SCode.EQ_PDE()
1515 algorithm
1516 ✗ outArg := inFunc(inEquation.expLeft, outArg);
1517 ✗ outArg := inFunc(inEquation.expRight, outArg);
1518 then
1519 outArg;
1520
1521 case SCode.EQ_CONNECT()
1522 algorithm
1523
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 outArg := inFunc(Absyn.CREF(inEquation.crefLeft), outArg);
1524
1/2
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
14 outArg := inFunc(Absyn.CREF(inEquation.crefRight), outArg);
1525 then
1526 outArg;
1527
1528 case SCode.EQ_FOR()
1529 algorithm
1530
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
18 if isSome(inEquation.range) then
1531 18 SOME(exp) := inEquation.range;
1532
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 outArg := inFunc(exp, outArg);
1533 end if;
1534 18 then
1535 List.fold1(inEquation.eEquationLst, foldEquationsExps, inFunc, outArg);
1536
1537 case SCode.EQ_WHEN()
1538 algorithm
1539 ✗ outArg := inFunc(inEquation.condition, outArg);
1540 ✗ outArg := List.fold1(inEquation.eEquationLst, foldEquationsExps, inFunc, outArg);
1541
1542 ✗ for branch in inEquation.elseBranches loop
1543 ✗ (exp, eql) := branch;
1544 ✗ outArg := inFunc(exp, outArg);
1545 ✗ outArg := List.fold1(eql, foldEquationsExps, inFunc, outArg);
1546 end for;
1547 then
1548 outArg;
1549
1550 case SCode.EQ_ASSERT()
1551 algorithm
1552
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 outArg := inFunc(inEquation.condition, outArg);
1553
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 outArg := inFunc(inEquation.message, outArg);
1554
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 outArg := inFunc(inEquation.level, outArg);
1555 then
1556 outArg;
1557
1558 case SCode.EQ_TERMINATE()
1559 ✗ then inFunc(inEquation.message, outArg);
1560
1561 case SCode.EQ_REINIT()
1562 algorithm
1563 ✗ outArg := inFunc(inEquation.cref, outArg);
1564 ✗ outArg := inFunc(inEquation.expReinit, outArg);
1565 then
1566 outArg;
1567
1568 case SCode.EQ_NORETCALL()
1569
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 then inFunc(inEquation.exp, outArg);
1570
1571 end match;
1572 end foldEquationsExps;
1573
1574 public function foldStatementsExps<ArgT>
1575 "Calls the given function on all expressions inside the statement, and updates
1576 the argument for each call."
1577 input SCode.Statement inStatement;
1578 input FoldFunc inFunc;
1579 input ArgT inArg;
1580 output ArgT outArg = inArg;
1581
1582 partial function FoldFunc
1583 input Absyn.Exp inExp;
1584 input ArgT inArg;
1585 output ArgT outArg;
1586 end FoldFunc;
1587 algorithm
1588 outArg := match inStatement
1589 local
1590 Absyn.Exp exp;
1591 list<SCode.Statement> stmts;
1592
1593 case SCode.ALG_ASSIGN()
1594 algorithm
1595
1/2
✓ Branch 0 taken 259 times.
✗ Branch 1 not taken.
259 outArg := inFunc(inStatement.assignComponent, outArg);
1596
1/2
✓ Branch 0 taken 259 times.
✗ Branch 1 not taken.
259 outArg := inFunc(inStatement.value, outArg);
1597 then
1598 outArg;
1599
1600 case SCode.ALG_IF()
1601 algorithm
1602
1/2
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
35 outArg := inFunc(inStatement.boolExpr, outArg);
1603 35 outArg := List.fold1(inStatement.trueBranch, foldStatementsExps, inFunc, outArg);
1604
1605
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 35 times.
45 for branch in inStatement.elseIfBranch loop
1606 10 (exp, stmts) := branch;
1607
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 outArg := inFunc(exp, outArg);
1608 10 outArg := List.fold1(stmts, foldStatementsExps, inFunc, outArg);
1609 end for;
1610
1611 35 outArg := List.fold1(inStatement.elseBranch, foldStatementsExps, inFunc, outArg);
1612 then
1613 outArg;
1614
1615 case SCode.ALG_FOR()
1616 algorithm
1617
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 1 time.
5 if isSome(inStatement.range) then
1618 4 SOME(exp) := inStatement.range;
1619
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 outArg := inFunc(exp, outArg);
1620 end if;
1621 5 then
1622 List.fold1(inStatement.forBody, foldStatementsExps, inFunc, outArg);
1623
1624 case SCode.ALG_PARFOR()
1625 algorithm
1626 ✗ if isSome(inStatement.range) then
1627 ✗ SOME(exp) := inStatement.range;
1628 ✗ outArg := inFunc(exp, outArg);
1629 end if;
1630 ✗ then
1631 List.fold1(inStatement.parforBody, foldStatementsExps, inFunc, outArg);
1632
1633 case SCode.ALG_WHILE()
1634 algorithm
1635
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 outArg := inFunc(inStatement.boolExpr, outArg);
1636 1 then
1637 List.fold1(inStatement.whileBody, foldStatementsExps, inFunc, outArg);
1638
1639 case SCode.ALG_WHEN_A()
1640 algorithm
1641 ✗ for branch in inStatement.branches loop
1642 ✗ (exp, stmts) := branch;
1643 ✗ outArg := inFunc(exp, outArg);
1644 ✗ outArg := List.fold1(stmts, foldStatementsExps, inFunc, outArg);
1645 end for;
1646 then
1647 outArg;
1648
1649 case SCode.ALG_ASSERT()
1650 algorithm
1651
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 outArg := inFunc(inStatement.condition, outArg);
1652
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 outArg := inFunc(inStatement.message, outArg);
1653
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 outArg := inFunc(inStatement.level, outArg);
1654 then
1655 outArg;
1656
1657 case SCode.ALG_TERMINATE()
1658 ✗ then inFunc(inStatement.message, outArg);
1659
1660 case SCode.ALG_REINIT()
1661 algorithm
1662 ✗ outArg := inFunc(inStatement.cref, outArg);
1663 ✗ then
1664 inFunc(inStatement.newValue, outArg);
1665
1666 case SCode.ALG_NORETCALL()
1667
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 then inFunc(inStatement.exp, outArg);
1668
1669 case SCode.ALG_FAILURE()
1670 ✗ then List.fold1(inStatement.stmts, foldStatementsExps, inFunc, outArg);
1671
1672 case SCode.ALG_TRY()
1673 algorithm
1674 ✗ outArg := List.fold1(inStatement.body, foldStatementsExps, inFunc, outArg);
1675 ✗ then
1676 List.fold1(inStatement.elseBody, foldStatementsExps, inFunc, outArg);
1677
1678 // No else case, to make this function break if a new statement is added to SCode.
1679 case SCode.ALG_RETURN() then outArg;
1680 case SCode.ALG_BREAK() then outArg;
1681 case SCode.ALG_CONTINUE() then outArg;
1682 end match;
1683 end foldStatementsExps;
1684
1685 public function mapFoldEquationsList<ArgT>
1686 "Traverses a list of SCode.Equations, calling mapFoldEquations on each SCode.Equation
1687 in the list."
1688 input output list<SCode.Equation> eql;
1689 input TraverseFunc traverser;
1690 input output ArgT arg;
1691
1692 partial function TraverseFunc
1693 input output SCode.Equation eq;
1694 input output ArgT arg;
1695 end TraverseFunc;
1696 algorithm
1697 3452 (eql, arg) := List.mapFold(eql, function mapFoldEquations(traverser = traverser), arg);
1698 end mapFoldEquationsList;
1699
1700 public function mapFoldEquations<ArgT>
1701 "Traverses an SCode.Equation. For each SCode.Equation it finds it calls the given
1702 function with the SCode.Equation and an extra argument which is passed along."
1703 input output SCode.Equation eq;
1704 input TraverseFunc traverser;
1705 input output ArgT arg;
1706
1707 partial function TraverseFunc
1708 input output SCode.Equation eq;
1709 input output ArgT arg;
1710 end TraverseFunc;
1711 algorithm
1712
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21295 times.
21295 (eq, arg) := traverser(eq, arg);
1713
1714 (eq, arg) := match eq
1715 local
1716 Absyn.Exp e1;
1717 list<Absyn.Exp> expl1;
1718 list<list<SCode.Equation>> then_branch;
1719 list<SCode.Equation> else_branch, eql;
1720 list<tuple<Absyn.Exp, list<SCode.Equation>>> else_when;
1721 SCode.Comment comment;
1722 SourceInfo info;
1723
1724 case SCode.EQ_IF(expl1, then_branch, else_branch, comment, info)
1725 algorithm
1726 1262 (then_branch, arg) := List.mapFold(then_branch,
1727 function mapFoldEquationsList(traverser = traverser), arg);
1728 1262 (else_branch, arg) := mapFoldEquationsList(else_branch, traverser, arg);
1729 1262 then
1730 (SCode.EQ_IF(expl1, then_branch, else_branch, comment, info), arg);
1731
1732 case SCode.EQ_FOR()
1733 algorithm
1734 370 (eql, arg) := mapFoldEquationsList(eq.eEquationLst, traverser, arg);
1735 370 eq.eEquationLst := eql;
1736 370 then
1737 (eq, arg);
1738
1739 case SCode.EQ_WHEN(e1, eql, else_when, comment, info)
1740 algorithm
1741 232 (eql, arg) := mapFoldEquationsList(eql, traverser, arg);
1742 232 (else_when, arg) := List.mapFold(else_when,
1743 function mapFoldElseWhenEquations(traverser = traverser), arg);
1744 232 then
1745 (SCode.EQ_WHEN(e1, eql, else_when, comment, info), arg);
1746
1747 19431 else (eq, arg);
1748 end match;
1749 end mapFoldEquations;
1750
1751 protected function mapFoldElseWhenEquations<ArgT>
1752 "Traverses all SCode.Equations in an else when branch, calling the given function
1753 on each SCode.Equation."
1754 input output tuple<Absyn.Exp, list<SCode.Equation>> elseWhen;
1755 input TraverseFunc traverser;
1756 input output ArgT arg;
1757
1758 partial function TraverseFunc
1759 input output SCode.Equation eq;
1760 input output ArgT arg;
1761 end TraverseFunc;
1762
1763 protected
1764 Absyn.Exp exp;
1765 list<SCode.Equation> eql;
1766 algorithm
1767 2 (exp, eql) := elseWhen;
1768 2 (eql, arg) := mapFoldEquationsList(eql, traverser, arg);
1769 2 elseWhen := (exp, eql);
1770 end mapFoldElseWhenEquations;
1771
1772 public function mapFoldEquationListExps<ArgT>
1773 "Traverses a list of SCode.Equations, calling the given function on each Absyn.Exp
1774 it encounters."
1775 input list<SCode.Equation> inEquations;
1776 input TraverseFunc traverser;
1777 input ArgT inArg;
1778 output list<SCode.Equation> outEquations;
1779 output ArgT outArg;
1780
1781 partial function TraverseFunc
1782 input output Absyn.Exp exp;
1783 input output ArgT arg;
1784 end TraverseFunc;
1785 algorithm
1786 ✗ (outEquations, outArg) := List.map1Fold(inEquations, mapFoldEquationExps, traverser, inArg);
1787 end mapFoldEquationListExps;
1788
1789 public function mapFoldEquationExps<ArgT>
1790 "Traverses an SCode.Equation, calling the given function on each Absyn.Exp it
1791 encounters. This funcion is intended to be used together with
1792 mapFoldEquations, and does NOT descend into sub-Equations."
1793 input output SCode.Equation eq;
1794 input TraverseFunc traverser;
1795 input output ArgT arg;
1796
1797 partial function TraverseFunc
1798 input output Absyn.Exp exp;
1799 input output ArgT arg;
1800 end TraverseFunc;
1801 algorithm
1802 (eq, arg) := match eq
1803 local
1804 Absyn.Exp e1, e2, e3;
1805 list<Absyn.Exp> expl1;
1806 list<list<SCode.Equation>> then_branch;
1807 list<SCode.Equation> else_branch, eql;
1808 list<tuple<Absyn.Exp, list<SCode.Equation>>> else_when;
1809 SCode.Comment comment;
1810 SourceInfo info;
1811 Absyn.ComponentRef cr1, cr2, domain;
1812 SCode.Ident index;
1813
1814 case SCode.EQ_IF(expl1, then_branch, else_branch, comment, info)
1815 algorithm
1816 1262 (expl1, arg) := AbsynUtil.traverseExpList(expl1, traverser, arg);
1817 1262 then
1818 (SCode.EQ_IF(expl1, then_branch, else_branch, comment, info), arg);
1819
1820 case SCode.EQ_EQUALS(e1, e2, comment, info)
1821 algorithm
1822
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13651 times.
13651 (e1, arg) := traverser(e1, arg);
1823
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13651 times.
13651 (e2, arg) := traverser(e2, arg);
1824 13651 then
1825 (SCode.EQ_EQUALS(e1, e2, comment, info), arg);
1826
1827 case SCode.EQ_PDE(e1, e2, domain, comment, info)
1828 algorithm
1829
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 (e1, arg) := traverser(e1, arg);
1830
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 (e2, arg) := traverser(e2, arg);
1831 8 then
1832 (SCode.EQ_PDE(e1, e2, domain, comment, info), arg);
1833
1834 case SCode.EQ_CONNECT(cr1, cr2, comment, info)
1835 algorithm
1836 4906 (cr1, arg) := mapFoldComponentRefExps(cr1, traverser, arg);
1837 4906 (cr2, arg) := mapFoldComponentRefExps(cr2, traverser, arg);
1838 4906 then
1839 (SCode.EQ_CONNECT(cr1, cr2, comment, info), arg);
1840
1841 case SCode.EQ_FOR(index, SOME(e1), eql, comment, info)
1842 algorithm
1843
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 370 times.
370 (e1, arg) := traverser(e1, arg);
1844 370 then
1845 (SCode.EQ_FOR(index, SOME(e1), eql, comment, info), arg);
1846
1847 case SCode.EQ_WHEN(e1, eql, else_when, comment, info)
1848 algorithm
1849
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 232 times.
232 (e1, arg) := traverser(e1, arg);
1850 232 (else_when, arg) := List.map1Fold(else_when, mapFoldElseWhenExps, traverser, arg);
1851 232 then
1852 (SCode.EQ_WHEN(e1, eql, else_when, comment, info), arg);
1853
1854 case SCode.EQ_ASSERT(e1, e2, e3, comment, info)
1855 algorithm
1856
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 564 times.
564 (e1, arg) := traverser(e1, arg);
1857
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 564 times.
564 (e2, arg) := traverser(e2, arg);
1858
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 564 times.
564 (e3, arg) := traverser(e3, arg);
1859 564 then
1860 (SCode.EQ_ASSERT(e1, e2, e3, comment, info), arg);
1861
1862 case SCode.EQ_TERMINATE(e1, comment, info)
1863 algorithm
1864
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 (e1, arg) := traverser(e1, arg);
1865 12 then
1866 (SCode.EQ_TERMINATE(e1, comment, info), arg);
1867
1868 case SCode.EQ_REINIT(e1, e2, comment, info)
1869 algorithm
1870
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 (e1, arg) := traverser(e1, arg);
1871
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 (e2, arg) := traverser(e2, arg);
1872 30 then
1873 (SCode.EQ_REINIT(e1, e2, comment, info), arg);
1874
1875 case SCode.EQ_NORETCALL(e1, comment, info)
1876 algorithm
1877
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 260 times.
260 (e1, arg) := traverser(e1, arg);
1878 260 then
1879 (SCode.EQ_NORETCALL(e1, comment, info), arg);
1880
1881 else (eq, arg);
1882 end match;
1883 end mapFoldEquationExps;
1884
1885 protected function mapFoldComponentRefExps<ArgT>
1886 "Traverses the subscripts of a component reference and calls the given
1887 function on the subscript expressions."
1888 input Absyn.ComponentRef inCref;
1889 input TraverseFunc inFunc;
1890 input ArgT inArg;
1891 output Absyn.ComponentRef outCref;
1892 output ArgT outArg;
1893
1894 partial function TraverseFunc
1895 input output Absyn.Exp exp;
1896 input output ArgT arg;
1897 end TraverseFunc;
1898 algorithm
1899 (outCref, outArg) := match inCref
1900 local
1901 Absyn.Ident name;
1902 list<Absyn.Subscript> subs;
1903 Absyn.ComponentRef cr;
1904 ArgT arg;
1905
1906 case Absyn.CREF_FULLYQUALIFIED(componentRef = cr)
1907 algorithm
1908 ✗ (cr, arg) := mapFoldComponentRefExps(cr, inFunc, inArg);
1909 ✗ then
1910 (AbsynUtil.crefMakeFullyQualified(cr), arg);
1911
1912 case Absyn.CREF_QUAL(name = name, subscripts = subs, componentRef = cr)
1913 algorithm
1914 8592 (cr, arg) := mapFoldComponentRefExps(cr, inFunc, inArg);
1915 8592 (subs, arg) := List.map1Fold(subs, mapFoldSubscriptExps, inFunc, arg);
1916 8592 then
1917 (Absyn.CREF_QUAL(name, subs, cr), arg);
1918
1919 case Absyn.CREF_IDENT(name = name, subscripts = subs)
1920 algorithm
1921 9812 (subs, arg) := List.map1Fold(subs, mapFoldSubscriptExps, inFunc, inArg);
1922 9812 then
1923 (Absyn.CREF_IDENT(name, subs), arg);
1924
1925 case Absyn.WILD() then (inCref, inArg);
1926 end match;
1927 end mapFoldComponentRefExps;
1928
1929 protected function mapFoldSubscriptExps<ArgT>
1930 "Calls the given function on the subscript expression."
1931 input Absyn.Subscript inSubscript;
1932 input TraverseFunc inFunc;
1933 input ArgT inArg;
1934 output Absyn.Subscript outSubscript;
1935 output ArgT outArg;
1936
1937 partial function TraverseFunc
1938 input output Absyn.Exp exp;
1939 input output ArgT arg;
1940 end TraverseFunc;
1941 algorithm
1942 (outSubscript, outArg) := match(inSubscript, inFunc, inArg)
1943 local
1944 Absyn.Exp sub_exp;
1945 TraverseFunc traverser;
1946 ArgT arg;
1947
1948 case (Absyn.SUBSCRIPT(subscript = sub_exp), traverser, arg)
1949 algorithm
1950
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 308 times.
308 (sub_exp, arg) := traverser(sub_exp, arg);
1951 308 then
1952 (Absyn.SUBSCRIPT(sub_exp), arg);
1953
1954 case (Absyn.NOSUB(), _, _) then (inSubscript, inArg);
1955 end match;
1956 end mapFoldSubscriptExps;
1957
1958 protected function mapFoldElseWhenExps<ArgT>
1959 "Traverses the expressions in an else when branch, and calls the given
1960 function on the expressions."
1961 input tuple<Absyn.Exp, list<SCode.Equation>> inElseWhen;
1962 input TraverseFunc traverser;
1963 input ArgT inArg;
1964 output tuple<Absyn.Exp, list<SCode.Equation>> outElseWhen;
1965 output ArgT outArg;
1966
1967 partial function TraverseFunc
1968 input output Absyn.Exp exp;
1969 input output ArgT arg;
1970 end TraverseFunc;
1971 protected
1972 Absyn.Exp exp;
1973 list<SCode.Equation> eql;
1974 algorithm
1975 2 (exp, eql) := inElseWhen;
1976
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 (exp, outArg) := traverser(exp, inArg);
1977 2 outElseWhen := (exp, eql);
1978 end mapFoldElseWhenExps;
1979
1980 protected function mapFoldForIteratorExps<ArgT>
1981 "Calls the given function on the expression associated with a for iterator."
1982 input Absyn.ForIterator inIterator;
1983 input TraverseFunc inFunc;
1984 input ArgT inArg;
1985 output Absyn.ForIterator outIterator;
1986 output ArgT outArg;
1987
1988 partial function TraverseFunc
1989 input output Absyn.Exp exp;
1990 input output ArgT arg;
1991 end TraverseFunc;
1992 algorithm
1993 (outIterator, outArg) := match(inIterator, inFunc, inArg)
1994 local
1995 TraverseFunc traverser;
1996 ArgT arg;
1997 Absyn.Ident ident;
1998 Absyn.Exp guardExp,range;
1999
2000 case (Absyn.ITERATOR(ident, NONE(), NONE()), _, arg)
2001 ✗ then
2002 (Absyn.ITERATOR(ident, NONE(), NONE()), arg);
2003
2004 case (Absyn.ITERATOR(ident, NONE(), SOME(range)), traverser, arg)
2005 algorithm
2006 ✗ (range, arg) := traverser(range, arg);
2007 ✗ then
2008 (Absyn.ITERATOR(ident, NONE(), SOME(range)), arg);
2009
2010 case (Absyn.ITERATOR(ident, SOME(guardExp), SOME(range)), traverser, arg)
2011 algorithm
2012 ✗ (guardExp, arg) := traverser(guardExp, arg);
2013 ✗ (range, arg) := traverser(range, arg);
2014 ✗ then
2015 (Absyn.ITERATOR(ident, SOME(guardExp), SOME(range)), arg);
2016
2017 case (Absyn.ITERATOR(ident, SOME(guardExp), NONE()), traverser, arg)
2018 algorithm
2019 ✗ (guardExp, arg) := traverser(guardExp, arg);
2020 ✗ then
2021 (Absyn.ITERATOR(ident, SOME(guardExp), NONE()), arg);
2022
2023 end match;
2024 end mapFoldForIteratorExps;
2025
2026 public function mapFoldStatementsList<ArgT>
2027 "Calls traverseStatement on each statement in the given list."
2028 input output list<SCode.Statement> statements;
2029 input TraverseFunc traverser;
2030 input output ArgT arg;
2031
2032 partial function TraverseFunc
2033 input output SCode.Statement stmt;
2034 input output ArgT arg;
2035 end TraverseFunc;
2036 algorithm
2037 9012 (statements, arg) :=
2038 List.mapFold(statements, function mapFoldStatements(traverser = traverser), arg);
2039 end mapFoldStatementsList;
2040
2041 public function mapFoldStatements<ArgT>
2042 "Traverses all statements in the given statement in a top-down approach where
2043 the given function is applied to each statement found, beginning with the given
2044 statement."
2045 input output SCode.Statement stmt;
2046 input TraverseFunc traverser;
2047 input output ArgT arg;
2048
2049 partial function TraverseFunc
2050 input output SCode.Statement stmt;
2051 input output ArgT arg;
2052 end TraverseFunc;
2053 algorithm
2054
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61165 times.
61165 (stmt, arg) := traverser(stmt, arg);
2055
2056 (stmt, arg) := match stmt
2057 local
2058 Absyn.Exp e;
2059 list<SCode.Statement> stmts1, stmts2;
2060 list<tuple<Absyn.Exp, list<SCode.Statement>>> branches;
2061 SCode.Comment comment;
2062 SourceInfo info;
2063 String iter;
2064 Option<Absyn.Exp> range;
2065
2066 case SCode.ALG_IF(e, stmts1, branches, stmts2, comment, info)
2067 algorithm
2068 3544 (stmts1, arg) := mapFoldStatementsList(stmts1, traverser, arg);
2069 3544 (branches, arg) := List.mapFold(branches,
2070 function mapFoldBranchStatements(traverser = traverser), arg);
2071 3544 (stmts2, arg) := mapFoldStatementsList(stmts2, traverser, arg);
2072 3544 then
2073 (SCode.ALG_IF(e, stmts1, branches, stmts2, comment, info), arg);
2074
2075 case SCode.ALG_FOR(iter, range, stmts1, comment, info)
2076 algorithm
2077 392 (stmts1, arg) := mapFoldStatementsList(stmts1, traverser, arg);
2078 392 then
2079 (SCode.ALG_FOR(iter, range, stmts1, comment, info), arg);
2080
2081 case SCode.ALG_PARFOR(iter, range, stmts1, comment, info)
2082 algorithm
2083 ✗ (stmts1, arg) := mapFoldStatementsList(stmts1, traverser, arg);
2084 ✗ then
2085 (SCode.ALG_PARFOR(iter, range, stmts1, comment, info), arg);
2086
2087 case SCode.ALG_WHILE(e, stmts1, comment, info)
2088 algorithm
2089 194 (stmts1, arg) := mapFoldStatementsList(stmts1, traverser, arg);
2090 194 then
2091 (SCode.ALG_WHILE(e, stmts1, comment, info), arg);
2092
2093 case SCode.ALG_WHEN_A(branches, comment, info)
2094 algorithm
2095 156 (branches, arg) := List.mapFold(branches,
2096 function mapFoldBranchStatements(traverser = traverser), arg);
2097 156 then
2098 (SCode.ALG_WHEN_A(branches, comment, info), arg);
2099
2100 case SCode.ALG_FAILURE(stmts1, comment, info)
2101 algorithm
2102 ✗ (stmts1, arg) := mapFoldStatementsList(stmts1, traverser, arg);
2103 ✗ then
2104 (SCode.ALG_FAILURE(stmts1, comment, info), arg);
2105
2106 56879 else (stmt, arg);
2107 end match;
2108 end mapFoldStatements;
2109
2110 protected function mapFoldBranchStatements<ArgT>
2111 "Helper function to traverseStatements2. Calls traverseStatement each
2112 statement in a given branch."
2113 input output tuple<Absyn.Exp, list<SCode.Statement>> branch;
2114 input TraverseFunc traverser;
2115 input output ArgT arg;
2116
2117 partial function TraverseFunc
2118 input output SCode.Statement stmt;
2119 input output ArgT arg;
2120 end TraverseFunc;
2121 protected
2122 Absyn.Exp exp;
2123 list<SCode.Statement> stmts;
2124 algorithm
2125 1338 (exp, stmts) := branch;
2126 1338 (stmts, arg) := mapFoldStatementsList(stmts, traverser, arg);
2127 1338 branch := (exp, stmts);
2128 end mapFoldBranchStatements;
2129
2130 public function mapFoldStatementListExps<ArgT>
2131 "Traverses a list of statements and calls the given function on each
2132 expression found."
2133 input list<SCode.Statement> inStatements;
2134 input TraverseFunc inFunc;
2135 input ArgT inArg;
2136 output list<SCode.Statement> outStatements;
2137 output ArgT outArg;
2138
2139 partial function TraverseFunc
2140 input output Absyn.Exp exp;
2141 input output ArgT arg;
2142 end TraverseFunc;
2143 algorithm
2144 ✗ (outStatements, outArg) := List.map1Fold(inStatements, mapFoldStatementExps, inFunc, inArg);
2145 end mapFoldStatementListExps;
2146
2147 public function mapFoldStatementExps<ArgT>
2148 "Applies the given function to each expression in the given statement. This
2149 function is intended to be used together with mapFoldStatements, and does NOT
2150 descend into sub-statements."
2151 input SCode.Statement inStatement;
2152 input TraverseFunc inFunc;
2153 input ArgT inArg;
2154 output SCode.Statement outStatement;
2155 output ArgT outArg;
2156
2157 partial function TraverseFunc
2158 input output Absyn.Exp exp;
2159 input output ArgT arg;
2160 end TraverseFunc;
2161 algorithm
2162 (outStatement, outArg) := match(inStatement, inFunc, inArg)
2163 local
2164 TraverseFunc traverser;
2165 ArgT arg;
2166 String iterator;
2167 Absyn.Exp e1, e2, e3;
2168 list<SCode.Statement> stmts1, stmts2;
2169 list<tuple<Absyn.Exp, list<SCode.Statement>>> branches;
2170 SCode.Comment comment;
2171 SourceInfo info;
2172 Absyn.ComponentRef cref;
2173
2174 case (SCode.ALG_ASSIGN(e1, e2, comment, info), traverser, arg)
2175 algorithm
2176
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 55247 times.
55247 (e1, arg) := traverser(e1, arg);
2177
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 55247 times.
55247 (e2, arg) := traverser(e2, arg);
2178 55247 then
2179 (SCode.ALG_ASSIGN(e1, e2, comment, info), arg);
2180
2181 case (SCode.ALG_IF(e1, stmts1, branches, stmts2, comment, info), traverser, arg)
2182 algorithm
2183
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3544 times.
3544 (e1, arg) := traverser(e1, arg);
2184 3544 (branches, arg) := List.map1Fold(branches, mapFoldBranchExps, traverser, arg);
2185 3544 then
2186 (SCode.ALG_IF(e1, stmts1, branches, stmts2, comment, info), arg);
2187
2188 case (SCode.ALG_FOR(iterator, SOME(e1), stmts1, comment, info), traverser, arg)
2189 algorithm
2190
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 384 times.
384 (e1, arg) := traverser(e1, arg);
2191 384 then
2192 (SCode.ALG_FOR(iterator, SOME(e1), stmts1, comment, info), arg);
2193
2194
2195 case (SCode.ALG_PARFOR(iterator, SOME(e1), stmts1, comment, info), traverser, arg)
2196 algorithm
2197 ✗ (e1, arg) := traverser(e1, arg);
2198 ✗ then
2199 (SCode.ALG_PARFOR(iterator, SOME(e1), stmts1, comment, info), arg);
2200
2201 case (SCode.ALG_WHILE(e1, stmts1, comment, info), traverser, arg)
2202 algorithm
2203
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 194 times.
194 (e1, arg) := traverser(e1, arg);
2204 194 then
2205 (SCode.ALG_WHILE(e1, stmts1, comment, info), arg);
2206
2207 case (SCode.ALG_WHEN_A(branches, comment, info), traverser, arg)
2208 algorithm
2209 156 (branches, arg) := List.map1Fold(branches, mapFoldBranchExps, traverser, arg);
2210 156 then
2211 (SCode.ALG_WHEN_A(branches, comment, info), arg);
2212
2213 case (SCode.ALG_ASSERT(), traverser, arg)
2214 algorithm
2215
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1478 times.
1478 (e1, arg) := traverser(inStatement.condition, arg);
2216
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1478 times.
1478 (e2, arg) := traverser(inStatement.message, arg);
2217
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1478 times.
1478 (e3, arg) := traverser(inStatement.level, arg);
2218 1478 then
2219 (SCode.ALG_ASSERT(e1, e2, e3, inStatement.comment, inStatement.info), arg);
2220
2221 case (SCode.ALG_TERMINATE(), traverser, arg)
2222 algorithm
2223 ✗ (e1, arg) := traverser(inStatement.message, arg);
2224 ✗ then
2225 (SCode.ALG_TERMINATE(e1, inStatement.comment, inStatement.info), arg);
2226
2227 case (SCode.ALG_REINIT(), traverser, arg)
2228 algorithm
2229
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 (e1, arg) := traverser(inStatement.cref, arg);
2230
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 (e2, arg) := traverser(inStatement.newValue, arg);
2231 42 then
2232 (SCode.ALG_REINIT(e1, e2, inStatement.comment, inStatement.info), arg);
2233
2234 case (SCode.ALG_NORETCALL(e1, comment, info), traverser, arg)
2235 algorithm
2236
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 (e1, arg) := traverser(e1, arg);
2237 72 then
2238 (SCode.ALG_NORETCALL(e1, comment, info), arg);
2239
2240 else (inStatement, inArg);
2241 end match;
2242 end mapFoldStatementExps;
2243
2244 protected function mapFoldBranchExps<ArgT>
2245 "Calls the given function on each expression found in an if or when branch."
2246 input tuple<Absyn.Exp, list<SCode.Statement>> inBranch;
2247 input TraverseFunc traverser;
2248 input ArgT inArg;
2249 output tuple<Absyn.Exp, list<SCode.Statement>> outBranch;
2250 output ArgT outArg;
2251
2252 partial function TraverseFunc
2253 input output Absyn.Exp exp;
2254 input output ArgT arg;
2255 end TraverseFunc;
2256 protected
2257 ArgT arg;
2258 Absyn.Exp exp;
2259 list<SCode.Statement> stmts;
2260 algorithm
2261 1338 (exp, stmts) := inBranch;
2262
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1338 times.
1338 (exp, outArg) := traverser(exp, inArg);
2263 1338 outBranch := (exp, stmts);
2264 end mapFoldBranchExps;
2265
2266 public function elementIsClass
2267 input SCode.Element el;
2268 output Boolean b;
2269 algorithm
2270 b := match el
2271 case SCode.CLASS() then true;
2272 else false;
2273 end match;
2274 end elementIsClass;
2275
2276 public function elementIsImport
2277 input SCode.Element inElement;
2278 output Boolean outIsImport;
2279 algorithm
2280 outIsImport := match inElement
2281 case SCode.IMPORT() then true;
2282 else false;
2283 end match;
2284 end elementIsImport;
2285
2286 public function elementIsPublicImport
2287 input SCode.Element el;
2288 output Boolean b;
2289 algorithm
2290 b := match el
2291 case SCode.IMPORT(visibility=SCode.PUBLIC()) then true;
2292 else false;
2293 end match;
2294 end elementIsPublicImport;
2295
2296 public function elementIsProtectedImport
2297 input SCode.Element el;
2298 output Boolean b;
2299 algorithm
2300 b := match el
2301 case SCode.IMPORT(visibility=SCode.PROTECTED()) then true;
2302 else false;
2303 end match;
2304 end elementIsProtectedImport;
2305
2306 public function getElementClass
2307 input SCode.Element el;
2308 output SCode.Element cl;
2309 algorithm
2310 cl := match el
2311 case SCode.CLASS() then el;
2312 else fail();
2313 end match;
2314 end getElementClass;
2315
2316 public constant list<String> knownExternalCFunctions = {"sin","cos","tan","asin","acos","atan","atan2","sinh","cosh","tanh","exp","log","log10","sqrt"};
2317
2318 public function isBuiltinFunction
2319 input SCode.Element cl;
2320 input list<String> inVars;
2321 input list<String> outVars;
2322 output String name;
2323 algorithm
2324 name := match (cl, outVars)
2325 local
2326 String outVar1,outVar2;
2327 list<String> argsStr;
2328 list<Absyn.Exp> args;
2329 case (SCode.CLASS(name=name,restriction=SCode.R_FUNCTION(SCode.FR_EXTERNAL_FUNCTION()),classDef=SCode.PARTS(externalDecl=SOME(SCode.EXTERNALDECL(funcName=NONE(),lang=SOME("builtin"))))), _)
2330 then name;
2331 case (SCode.CLASS(restriction=SCode.R_FUNCTION(SCode.FR_EXTERNAL_FUNCTION()),classDef=SCode.PARTS(externalDecl=SOME(SCode.EXTERNALDECL(funcName=SOME(name),lang=SOME("builtin"))))), _)
2332 then name;
2333 case (SCode.CLASS(name=name,restriction=SCode.R_FUNCTION(SCode.FR_PARALLEL_FUNCTION()),classDef=SCode.PARTS(externalDecl=SOME(SCode.EXTERNALDECL(funcName=NONE(),lang=SOME("builtin"))))), _)
2334 then name;
2335 case (SCode.CLASS(restriction=SCode.R_FUNCTION(SCode.FR_PARALLEL_FUNCTION()),classDef=SCode.PARTS(externalDecl=SOME(SCode.EXTERNALDECL(funcName=SOME(name),lang=SOME("builtin"))))), _)
2336 then name;
2337 case (SCode.CLASS(restriction=SCode.R_FUNCTION(SCode.FR_EXTERNAL_FUNCTION()), classDef=SCode.PARTS(externalDecl=SOME(SCode.EXTERNALDECL(funcName=SOME(name),lang=SOME("C"),output_=SOME(Absyn.CREF_IDENT(outVar2,{})),args=args)))), {outVar1})
2338 algorithm
2339
2/2
✓ Branch 1 taken 1058 times.
✓ Branch 2 taken 31 times.
1089 true := listMember(name,knownExternalCFunctions);
2340
2/4
✓ Branch 0 taken 31 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 31 times.
31 true := outVar2 == outVar1;
2341 31 argsStr := List.mapMap(args, AbsynUtil.expCref, AbsynUtil.crefIdent);
2342
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
31 true := valueEq(argsStr, inVars);
2343 then name;
2344 case (SCode.CLASS(name=name,
2345 restriction=SCode.R_FUNCTION(SCode.FR_EXTERNAL_FUNCTION()),
2346 classDef=SCode.PARTS(externalDecl=SOME(SCode.EXTERNALDECL(funcName=NONE(),lang=SOME("C"))))), _)
2347 algorithm
2348
1/2
✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
25 true := listMember(name,knownExternalCFunctions);
2349 then name;
2350 end match;
2351 end isBuiltinFunction;
2352
2353 public function getEquationInfo
2354 "Extracts the SourceInfo from an SCode.Equation."
2355 input SCode.Equation inEquation;
2356 output SourceInfo info;
2357 algorithm
2358 info := match inEquation
2359 1262 case SCode.EQ_IF() then inEquation.info;
2360 13701 case SCode.EQ_EQUALS() then inEquation.info;
2361 8 case SCode.EQ_PDE() then inEquation.info;
2362 4918 case SCode.EQ_CONNECT() then inEquation.info;
2363 13 case SCode.EQ_FOR() then inEquation.info;
2364 232 case SCode.EQ_WHEN() then inEquation.info;
2365 570 case SCode.EQ_ASSERT() then inEquation.info;
2366 12 case SCode.EQ_TERMINATE() then inEquation.info;
2367 ✗ case SCode.EQ_REINIT() then inEquation.info;
2368 261 case SCode.EQ_NORETCALL() then inEquation.info;
2369 end match;
2370 end getEquationInfo;
2371
2372 public function getStatementInfo
2373 "Extracts the SourceInfo from a Statement."
2374 input SCode.Statement inStatement;
2375 output SourceInfo outInfo;
2376 algorithm
2377 outInfo := match inStatement
2378 55280 case SCode.ALG_ASSIGN() then inStatement.info;
2379 3544 case SCode.ALG_IF() then inStatement.info;
2380 13 case SCode.ALG_FOR() then inStatement.info;
2381 ✗ case SCode.ALG_PARFOR() then inStatement.info;
2382 194 case SCode.ALG_WHILE() then inStatement.info;
2383 156 case SCode.ALG_WHEN_A() then inStatement.info;
2384 1478 case SCode.ALG_ASSERT() then inStatement.info;
2385 ✗ case SCode.ALG_TERMINATE() then inStatement.info;
2386 42 case SCode.ALG_REINIT() then inStatement.info;
2387 72 case SCode.ALG_NORETCALL() then inStatement.info;
2388 6 case SCode.ALG_RETURN() then inStatement.info;
2389 30 case SCode.ALG_BREAK() then inStatement.info;
2390 ✗ case SCode.ALG_FAILURE() then inStatement.info;
2391 2 case SCode.ALG_TRY() then inStatement.info;
2392 2 case SCode.ALG_CONTINUE() then inStatement.info;
2393 else
2394 algorithm
2395 ✗ Error.addInternalError("SCodeUtil.getStatementInfo failed", sourceInfo());
2396 then Absyn.dummyInfo;
2397 end match;
2398 end getStatementInfo;
2399
2400 public function prependSubModToMod
2401 input SCode.SubMod subMod;
2402 input output SCode.Mod mod;
2403 algorithm
2404 mod := match mod
2405 case SCode.NOMOD()
2406 ✗ then SCode.MOD(SCode.NOT_FINAL(), SCode.NOT_EACH(), {subMod}, NONE(), NONE(), Error.dummyInfo);
2407 case SCode.MOD()
2408 algorithm
2409 4 mod.subModLst := subMod :: mod.subModLst;
2410 then mod;
2411 end match;
2412 end prependSubModToMod;
2413
2414 public function addElementToClass
2415 "Adds a given element to a class definition. Only implemented for PARTS."
2416 input SCode.Element inElement;
2417 input SCode.Element inClassDef;
2418 output SCode.Element outClassDef;
2419 protected
2420 SCode.ClassDef cdef;
2421 algorithm
2422
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38782 times.
38782 SCode.CLASS(classDef = cdef) := inClassDef;
2423 38782 cdef := addElementToCompositeClassDef(inElement, cdef);
2424 38782 outClassDef := setClassDef(cdef, inClassDef);
2425 end addElementToClass;
2426
2427 public function addElementToCompositeClassDef
2428 "Adds a given element to a PARTS class definition."
2429 input SCode.Element element;
2430 input output SCode.ClassDef classDef;
2431 algorithm
2432 () := match classDef
2433 case SCode.PARTS()
2434 algorithm
2435 77564 classDef.elementLst := element :: classDef.elementLst;
2436 then
2437 ();
2438 end match;
2439 end addElementToCompositeClassDef;
2440
2441 public function visibilityBool
2442 "returns true for PUBLIC and false for PROTECTED"
2443 input SCode.Visibility inVisibility;
2444 output Boolean bVisibility;
2445 algorithm
2446 bVisibility := match inVisibility
2447 case SCode.PUBLIC() then true;
2448 case SCode.PROTECTED() then false;
2449 end match;
2450 end visibilityBool;
2451
2452 public function boolVisibility
2453 "returns for PUBLIC true and for PROTECTED false"
2454 input Boolean inBoolVisibility;
2455 output SCode.Visibility outVisibility;
2456 algorithm
2457 ✗ outVisibility := match inBoolVisibility
2458 case true then SCode.PUBLIC();
2459 case false then SCode.PROTECTED();
2460 end match;
2461 end boolVisibility;
2462
2463 public function visibilityEqual
2464 input SCode.Visibility inVisibility1;
2465 input SCode.Visibility inVisibility2;
2466 output Boolean outEqual;
2467 algorithm
2468 outEqual := match(inVisibility1, inVisibility2)
2469 case (SCode.PUBLIC(), SCode.PUBLIC()) then true;
2470 case (SCode.PROTECTED(), SCode.PROTECTED()) then true;
2471 else false;
2472 end match;
2473 end visibilityEqual;
2474
2475 public function eachBool
2476 input SCode.Each inEach;
2477 output Boolean bEach;
2478 algorithm
2479 bEach := match inEach
2480 case SCode.EACH() then true;
2481 case SCode.NOT_EACH() then false;
2482 end match;
2483 end eachBool;
2484
2485 public function boolEach
2486 input Boolean inBoolEach;
2487 output SCode.Each outEach;
2488 algorithm
2489 ✗ outEach := match inBoolEach
2490 case true then SCode.EACH();
2491 case false then SCode.NOT_EACH();
2492 end match;
2493 end boolEach;
2494
2495 public function prefixesRedeclare
2496 input SCode.Prefixes inPrefixes;
2497 output SCode.Redeclare outRedeclare;
2498 algorithm
2499 1419018 SCode.PREFIXES(redeclarePrefix = outRedeclare) := inPrefixes;
2500 end prefixesRedeclare;
2501
2502 public function prefixesSetRedeclare
2503 input output SCode.Prefixes prefixes;
2504 input SCode.Redeclare inRedeclare;
2505 algorithm
2506 ✗ prefixes.redeclarePrefix := inRedeclare;
2507 end prefixesSetRedeclare;
2508
2509 public function prefixesSetReplaceable
2510 input output SCode.Prefixes prefixes;
2511 input SCode.Replaceable inReplaceable;
2512 algorithm
2513 ✗ prefixes.replaceablePrefix := inReplaceable;
2514 end prefixesSetReplaceable;
2515
2516 public function redeclareBool
2517 input SCode.Redeclare inRedeclare;
2518 output Boolean bRedeclare;
2519 algorithm
2520 bRedeclare := match inRedeclare
2521 case SCode.REDECLARE() then true;
2522 case SCode.NOT_REDECLARE() then false;
2523 end match;
2524 end redeclareBool;
2525
2526 public function boolRedeclare
2527 input Boolean inBoolRedeclare;
2528 output SCode.Redeclare outRedeclare;
2529 algorithm
2530
2/2
✓ Branch 0 taken 36976482 times.
✓ Branch 1 taken 493040 times.
37469522 outRedeclare := match inBoolRedeclare
2531 case true then SCode.REDECLARE();
2532 case false then SCode.NOT_REDECLARE();
2533 end match;
2534 end boolRedeclare;
2535
2536 public function replaceableBool
2537 input SCode.Replaceable inReplaceable;
2538 output Boolean bReplaceable;
2539 algorithm
2540 bReplaceable := match inReplaceable
2541 case SCode.REPLACEABLE() then true;
2542 case SCode.NOT_REPLACEABLE() then false;
2543 end match;
2544 end replaceableBool;
2545
2546 public function replaceableOptConstraint
2547 input SCode.Replaceable inReplaceable;
2548 output Option<SCode.ConstrainClass> outOptConstrainClass;
2549 algorithm
2550 outOptConstrainClass := match inReplaceable
2551 local Option<SCode.ConstrainClass> cc;
2552 case SCode.REPLACEABLE(cc) then cc;
2553 case SCode.NOT_REPLACEABLE() then NONE();
2554 end match;
2555 end replaceableOptConstraint;
2556
2557 public function boolReplaceable
2558 input Boolean inBoolReplaceable;
2559 input Option<SCode.ConstrainClass> inOptConstrainClass;
2560 output SCode.Replaceable outReplaceable;
2561 algorithm
2562 outReplaceable := match(inBoolReplaceable, inOptConstrainClass)
2563 ✗ case (true, _) then SCode.REPLACEABLE(inOptConstrainClass);
2564 case (false, SOME(_))
2565 algorithm
2566 ✗ print("Ignoring constraint class because replaceable prefix is not present!\n");
2567 then SCode.NOT_REPLACEABLE();
2568 case (false, _) then SCode.NOT_REPLACEABLE();
2569 end match;
2570 end boolReplaceable;
2571
2572 public function encapsulatedBool
2573 input SCode.Encapsulated inEncapsulated;
2574 output Boolean bEncapsulated;
2575 algorithm
2576 bEncapsulated := match inEncapsulated
2577 case SCode.ENCAPSULATED() then true;
2578 case SCode.NOT_ENCAPSULATED() then false;
2579 end match;
2580 end encapsulatedBool;
2581
2582 public function boolEncapsulated
2583 input Boolean inBoolEncapsulated;
2584 output SCode.Encapsulated outEncapsulated;
2585 algorithm
2586
2/2
✓ Branch 0 taken 7732180 times.
✓ Branch 1 taken 38799 times.
7770979 outEncapsulated := match inBoolEncapsulated
2587 case true then SCode.ENCAPSULATED();
2588 case false then SCode.NOT_ENCAPSULATED();
2589 end match;
2590 end boolEncapsulated;
2591
2592 public function partialBool
2593 input SCode.Partial inPartial;
2594 output Boolean bPartial;
2595 algorithm
2596 bPartial := match inPartial
2597 case SCode.PARTIAL() then true;
2598 case SCode.NOT_PARTIAL() then false;
2599 end match;
2600 end partialBool;
2601
2602 public function boolPartial
2603 input Boolean inBoolPartial;
2604 output SCode.Partial outPartial;
2605 algorithm
2606
2/2
✓ Branch 0 taken 7532376 times.
✓ Branch 1 taken 238603 times.
7770979 outPartial := match inBoolPartial
2607 case true then SCode.PARTIAL();
2608 case false then SCode.NOT_PARTIAL();
2609 end match;
2610 end boolPartial;
2611
2612 public function prefixesFinal
2613 input SCode.Prefixes inPrefixes;
2614 output SCode.Final outFinal;
2615 algorithm
2616 1640335 SCode.PREFIXES(finalPrefix = outFinal) := inPrefixes;
2617 end prefixesFinal;
2618
2619 public function finalBool
2620 input SCode.Final inFinal;
2621 output Boolean bFinal;
2622 algorithm
2623 bFinal := match inFinal
2624 case SCode.FINAL() then true;
2625 case SCode.NOT_FINAL() then false;
2626 end match;
2627 end finalBool;
2628
2629 public function finalEqual
2630 input SCode.Final inFinal1;
2631 input SCode.Final inFinal2;
2632 output Boolean bFinal;
2633 algorithm
2634 bFinal := match(inFinal1,inFinal2)
2635 case (SCode.FINAL(),SCode.FINAL()) then true;
2636 case (SCode.NOT_FINAL(),SCode.NOT_FINAL()) then true;
2637 else false;
2638 end match;
2639 end finalEqual;
2640
2641 public function boolFinal
2642 input Boolean inBoolFinal;
2643 output SCode.Final outFinal;
2644 algorithm
2645
2/2
✓ Branch 0 taken 114811798 times.
✓ Branch 1 taken 2921877 times.
117733675 outFinal := if inBoolFinal then SCode.FINAL() else SCode.NOT_FINAL();
2646 end boolFinal;
2647
2648 public function connectorTypeEqual
2649 input SCode.ConnectorType inConnectorType1;
2650 input SCode.ConnectorType inConnectorType2;
2651 output Boolean outEqual;
2652 algorithm
2653 outEqual := match(inConnectorType1, inConnectorType2)
2654 case (SCode.POTENTIAL(), SCode.POTENTIAL()) then true;
2655 case (SCode.FLOW(), SCode.FLOW()) then true;
2656 case (SCode.STREAM(), SCode.STREAM()) then true;
2657 end match;
2658 end connectorTypeEqual;
2659
2660 public function potentialBool
2661 input SCode.ConnectorType inConnectorType;
2662 output Boolean outPotential;
2663 algorithm
2664 outPotential := match inConnectorType
2665 case SCode.POTENTIAL() then true;
2666 else false;
2667 end match;
2668 end potentialBool;
2669
2670 public function flowBool
2671 input SCode.ConnectorType inConnectorType;
2672 output Boolean outFlow;
2673 algorithm
2674 outFlow := match inConnectorType
2675 case SCode.FLOW() then true;
2676 else false;
2677 end match;
2678 end flowBool;
2679
2680 public function boolFlow
2681 input Boolean inBoolFlow;
2682 output SCode.ConnectorType outFlow;
2683 algorithm
2684 ✗ outFlow := match inBoolFlow
2685 case true then SCode.FLOW();
2686 else SCode.POTENTIAL();
2687 end match;
2688 end boolFlow;
2689
2690 public function streamBool
2691 input SCode.ConnectorType inStream;
2692 output Boolean bStream;
2693 algorithm
2694 bStream := match inStream
2695 case SCode.STREAM() then true;
2696 else false;
2697 end match;
2698 end streamBool;
2699
2700 public function boolStream
2701 input Boolean inBoolStream;
2702 output SCode.ConnectorType outStream;
2703 algorithm
2704 ✗ outStream := match inBoolStream
2705 case true then SCode.STREAM();
2706 else SCode.POTENTIAL();
2707 end match;
2708 end boolStream;
2709
2710 public function mergeAttributesFromClass
2711 input SCode.Attributes inAttributes;
2712 input SCode.Element inClass;
2713 output SCode.Attributes outAttributes;
2714 algorithm
2715 outAttributes := match inClass
2716 local
2717 SCode.Attributes cls_attr, attr;
2718
2719 case SCode.CLASS(classDef = SCode.DERIVED(attributes = cls_attr))
2720 algorithm
2721
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 117230 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 117230 times.
117230 SOME(attr) := mergeAttributes(inAttributes, SOME(cls_attr));
2722 then
2723 attr;
2724
2725 else inAttributes;
2726 end match;
2727 end mergeAttributesFromClass;
2728
2729 public function mergeAttributes
2730 "@author: adrpo
2731 Function that is used with Derived classes,
2732 merge the derived Attributes with the optional Attributes returned from ~instClass~."
2733 input SCode.Attributes ele;
2734 input Option<SCode.Attributes> oEle;
2735 output Option<SCode.Attributes> outoEle;
2736 algorithm
2737 outoEle := match(ele, oEle)
2738 local
2739 SCode.Parallelism p1,p2,p;
2740 SCode.Variability v1,v2,v;
2741 Absyn.Direction d1,d2,d;
2742 Absyn.IsField isf1, isf2, isf;
2743 Absyn.ArrayDim ad1,ad;
2744 SCode.ConnectorType ct1, ct2, ct;
2745
2746 case (_,NONE()) then SOME(ele);
2747 case(SCode.ATTR(ad1,ct1,p1,v1,d1,isf1), SOME(SCode.ATTR(_,ct2,p2,v2,d2,isf2)))
2748 algorithm
2749 197493 ct := propagateConnectorType(ct1, ct2);
2750 197493 p := propagateParallelism(p1,p2);
2751 197493 v := propagateVariability(v1,v2);
2752 197493 d := propagateDirection(d1,d2);
2753 197493 isf := propagateIsField(isf1,isf2);
2754 ad := ad1; // TODO! CHECK if ad1 == ad2!
2755 197493 then
2756 SOME(SCode.ATTR(ad,ct,p,v,d,isf));
2757 end match;
2758 end mergeAttributes;
2759
2760 public function prefixesVisibility
2761 input SCode.Prefixes inPrefixes;
2762 output SCode.Visibility outVisibility;
2763 algorithm
2764 538211 SCode.PREFIXES(visibility = outVisibility) := inPrefixes;
2765 end prefixesVisibility;
2766
2767 public function prefixesSetVisibility
2768 input output SCode.Prefixes prefixes;
2769 input SCode.Visibility inVisibility;
2770 algorithm
2771 ✗ prefixes.visibility := inVisibility;
2772 end prefixesSetVisibility;
2773
2774 public function eachEqual "Returns true if two each attributes are equal"
2775 input SCode.Each each1;
2776 input SCode.Each each2;
2777 output Boolean equal;
2778 algorithm
2779 equal := match(each1,each2)
2780 case (SCode.NOT_EACH(), SCode.NOT_EACH()) then true;
2781 case (SCode.EACH(), SCode.EACH()) then true;
2782 else false;
2783 end match;
2784 end eachEqual;
2785
2786 public function replaceableEqual "Returns true if two replaceable attributes are equal"
2787 input SCode.Replaceable r1;
2788 input SCode.Replaceable r2;
2789 output Boolean equal;
2790 algorithm
2791 equal := match(r1,r2)
2792 local
2793 Absyn.Path p1, p2;
2794 SCode.Mod m1, m2;
2795
2796 case(SCode.NOT_REPLACEABLE(),SCode.NOT_REPLACEABLE()) then true;
2797
2798 case(SCode.REPLACEABLE(SOME(SCode.CONSTRAINCLASS(constrainingClass = p1, modifier = m1))),
2799 SCode.REPLACEABLE(SOME(SCode.CONSTRAINCLASS(constrainingClass = p2, modifier = m2)))) guard AbsynUtil.pathEqual(p1, p2) and modEqual(m1, m2)
2800 then
2801 true;
2802
2803 case(SCode.REPLACEABLE(NONE()),SCode.REPLACEABLE(NONE())) then true;
2804
2805 else false;
2806
2807 end match;
2808 end replaceableEqual;
2809
2810 public function prefixesEqual "Returns true if two prefixes are equal"
2811 input SCode.Prefixes prefixes1;
2812 input SCode.Prefixes prefixes2;
2813 output Boolean equal;
2814 algorithm
2815
5/10
✓ Branch 1 taken 463710 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 463710 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 463710 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 463710 times.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✓ Branch 14 taken 463710 times.
463710 equal := valueEq(prefixes1.visibility, prefixes2.visibility) and
2816 valueEq(prefixes1.redeclarePrefix, prefixes2.redeclarePrefix) and
2817 valueEq(prefixes1.finalPrefix, prefixes2.finalPrefix) and
2818 AbsynUtil.innerOuterEqual(prefixes1.innerOuter, prefixes2.innerOuter) and
2819 replaceableEqual(prefixes1.replaceablePrefix, prefixes2.replaceablePrefix);
2820 end prefixesEqual;
2821
2822 public function prefixesReplaceable "Returns the replaceable part"
2823 input SCode.Prefixes prefixes;
2824 output SCode.Replaceable repl;
2825 algorithm
2826 288806 SCode.PREFIXES(replaceablePrefix = repl) := prefixes;
2827 end prefixesReplaceable;
2828
2829 public function elementPrefixes
2830 input SCode.Element inElement;
2831 output SCode.Prefixes outPrefixes;
2832 algorithm
2833 outPrefixes := match inElement
2834 1818135 case SCode.CLASS() then inElement.prefixes;
2835 3631584 case SCode.COMPONENT() then inElement.prefixes;
2836 end match;
2837 end elementPrefixes;
2838
2839 public function setElementPrefixes
2840 input SCode.Prefixes prefixes;
2841 input output SCode.Element element;
2842 algorithm
2843 () := match element
2844 51 case SCode.CLASS() algorithm element.prefixes := prefixes; then ();
2845 ✗ case SCode.COMPONENT() algorithm element.prefixes := prefixes; then ();
2846 end match;
2847 end setElementPrefixes;
2848
2849 public function isElementReplaceable
2850 input SCode.Element inElement;
2851 output Boolean isReplaceable;
2852 protected
2853 SCode.Prefixes pf;
2854 algorithm
2855 147582 pf := elementPrefixes(inElement);
2856 147582 isReplaceable := replaceableBool(prefixesReplaceable(pf));
2857 end isElementReplaceable;
2858
2859 public function isElementRedeclare
2860 input SCode.Element inElement;
2861 output Boolean isRedeclare;
2862 protected
2863 SCode.Prefixes pf;
2864 algorithm
2865 1419018 pf := elementPrefixes(inElement);
2866 1419018 isRedeclare := redeclareBool(prefixesRedeclare(pf));
2867 end isElementRedeclare;
2868
2869 public function prefixesInnerOuter
2870 input SCode.Prefixes inPrefixes;
2871 output Absyn.InnerOuter outInnerOuter;
2872 algorithm
2873 4434027 SCode.PREFIXES(innerOuter = outInnerOuter) := inPrefixes;
2874 end prefixesInnerOuter;
2875
2876 public function prefixesSetInnerOuter
2877 input output SCode.Prefixes prefixes;
2878 input Absyn.InnerOuter innerOuter;
2879 algorithm
2880 4 prefixes.innerOuter := innerOuter;
2881 end prefixesSetInnerOuter;
2882
2883 public function removeAttributeDimensions
2884 input output SCode.Attributes attributes;
2885 algorithm
2886 526574 attributes.arrayDims := {};
2887 end removeAttributeDimensions;
2888
2889 public function setAttributesDirection
2890 input output SCode.Attributes attributes;
2891 input Absyn.Direction direction;
2892 algorithm
2893 425774 attributes.direction := direction;
2894 end setAttributesDirection;
2895
2896 public function attrVariability
2897 "Return the variability attribute from Attributes"
2898 input SCode.Attributes attr;
2899 output SCode.Variability var;
2900 algorithm
2901 var := match attr
2902 local SCode.Variability v;
2903 case SCode.ATTR(variability = v) then v;
2904 end match;
2905 end attrVariability;
2906
2907 public function setAttributesVariability
2908 input output SCode.Attributes attributes;
2909 input SCode.Variability variability;
2910 algorithm
2911 ✗ attributes.variability := variability;
2912 end setAttributesVariability;
2913
2914 public function isDerivedClassDef
2915 input SCode.ClassDef inClassDef;
2916 output Boolean isDerived;
2917 algorithm
2918 isDerived := match inClassDef
2919 case SCode.DERIVED() then true;
2920 else false;
2921 end match;
2922 end isDerivedClassDef;
2923
2924 public function isConnector
2925 input SCode.Restriction inRestriction;
2926 output Boolean isConnector;
2927 algorithm
2928 isConnector := match inRestriction
2929 case SCode.R_CONNECTOR() then true;
2930 else false;
2931 end match;
2932 end isConnector;
2933
2934 public function removeBuiltinsFromTopScope
2935 input SCode.Program inProgram;
2936 output SCode.Program outProgram;
2937 algorithm
2938 5 outProgram := List.filterOnTrue(inProgram, isNotBuiltinClass);
2939 end removeBuiltinsFromTopScope;
2940
2941 protected function isNotBuiltinClass
2942 input SCode.Element inClass;
2943 output Boolean b;
2944 algorithm
2945 b := match inClass
2946 case SCode.CLASS(classDef = SCode.PARTS(externalDecl =
2947 SOME(SCode.EXTERNALDECL(lang = SOME("builtin"))))) then false;
2948 else true;
2949 end match;
2950 end isNotBuiltinClass;
2951
2952 public function getElementAnnotation
2953 input SCode.Element element;
2954 input String name;
2955 output Option<SCode.Annotation> outAnnotation;
2956 algorithm
2957 outAnnotation := match element
2958 ✗ case SCode.EXTENDS() then element.ann;
2959 73219 case SCode.CLASS() then element.cmt.annotation_;
2960 ✗ case SCode.COMPONENT() then element.comment.annotation_;
2961 else NONE();
2962 end match;
2963 end getElementAnnotation;
2964
2965 public function lookupAnnotation
2966 "Returns the modifier with the given name if it can be found in the
2967 annotation, otherwise an empty modifier."
2968 input SCode.Annotation ann;
2969 input String name;
2970 output SCode.Mod mod;
2971 protected
2972 list<SCode.SubMod> submods;
2973 String id;
2974 algorithm
2975 mod := match ann
2976 case SCode.ANNOTATION(modification = SCode.MOD(subModLst = submods))
2977 algorithm
2978
2/2
✓ Branch 0 taken 2478912 times.
✓ Branch 1 taken 1582638 times.
4061550 for sm in submods loop
2979 2478912 SCode.NAMEMOD(id, mod) := sm;
2980
2981
4/4
✓ Branch 0 taken 421260 times.
✓ Branch 1 taken 2057652 times.
✓ Branch 3 taken 366505 times.
✓ Branch 4 taken 54755 times.
2478912 if id == name then
2982 366505 return;
2983 end if;
2984 end for;
2985 then
2986 SCode.NOMOD();
2987
2988 else SCode.NOMOD();
2989 end match;
2990 end lookupAnnotation;
2991
2992 public function lookupAnnotationBinding
2993 input SCode.Annotation ann;
2994 input String name;
2995 output Option<Absyn.Exp> binding;
2996 algorithm
2997 1019117 binding := getModifierBinding(lookupAnnotation(ann, name));
2998 end lookupAnnotationBinding;
2999
3000 public function lookupBooleanAnnotation
3001 input SCode.Annotation ann;
3002 input String name;
3003 output Option<Boolean> value;
3004 protected
3005 Option<Absyn.Exp> binding;
3006 Boolean bval;
3007 algorithm
3008 103951 binding := lookupAnnotationBinding(ann, name);
3009
3010 value := match binding
3011
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 11623 times.
11631 case SOME(Absyn.Exp.BOOL(value = bval)) then SOME(bval);
3012 else NONE();
3013 end match;
3014 end lookupBooleanAnnotation;
3015
3016 public function lookupBooleanAnnotationMod
3017 input SCode.Mod mod;
3018 output Option<Boolean> value;
3019 protected
3020 Option<Absyn.Exp> binding;
3021 Boolean bval;
3022 algorithm
3023 3099 binding := getModifierBinding(mod);
3024
3025 value := match binding
3026
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 case SOME(Absyn.Exp.BOOL(value = bval)) then SOME(bval);
3027 else NONE();
3028 end match;
3029 end lookupBooleanAnnotationMod;
3030
3031 public function lookupAnnotations
3032 "Returns a list of modifiers with the given name found in the annotation."
3033 input SCode.Annotation ann;
3034 input String name;
3035 output list<SCode.Mod> mods = {};
3036 protected
3037 list<SCode.SubMod> submods;
3038 String id;
3039 SCode.Mod mod;
3040 algorithm
3041 mods := match ann
3042 case SCode.ANNOTATION(modification = SCode.MOD(subModLst = submods))
3043 algorithm
3044
2/2
✓ Branch 0 taken 75576 times.
✓ Branch 1 taken 41410 times.
116986 for sm in submods loop
3045 75576 SCode.NAMEMOD(id, mod) := sm;
3046
3047
4/4
✓ Branch 0 taken 2657 times.
✓ Branch 1 taken 72919 times.
✓ Branch 3 taken 1301 times.
✓ Branch 4 taken 1356 times.
75576 if id == name then
3048 mods := mod :: mods;
3049 end if;
3050 end for;
3051 then
3052 mods;
3053
3054 else {};
3055 end match;
3056 end lookupAnnotations;
3057
3058 public function lookupElementAnnotation
3059 "Returns the modifier with the given name if it can be found in the annotation
3060 of the given element, otherwise an empty modifier."
3061 input SCode.Element element;
3062 input String name;
3063 output SCode.Mod mod;
3064 protected
3065 Option<SCode.Annotation> ann;
3066 algorithm
3067 73219 ann := getElementAnnotation(element, name);
3068
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 73219 times.
✓ Branch 2 taken 50635 times.
✓ Branch 3 taken 22584 times.
73219 mod := if isSome(ann) then lookupAnnotation(Util.getOption(ann), name) else SCode.Mod.NOMOD();
3069 end lookupElementAnnotation;
3070
3071 public function lookupElementAnnotationBinding
3072 input SCode.Element element;
3073 input String name;
3074 output Option<Absyn.Exp> binding;
3075 algorithm
3076 18 binding := getModifierBinding(lookupElementAnnotation(element, name));
3077 end lookupElementAnnotationBinding;
3078
3079 public function hasBooleanNamedAnnotationInClass
3080 input SCode.Element inClass;
3081 input String namedAnnotation;
3082 output Boolean hasAnn;
3083 algorithm
3084 hasAnn := match inClass
3085 local
3086 SCode.Annotation ann;
3087 case SCode.CLASS(cmt=SCode.COMMENT(annotation_ = SOME(ann)))
3088 345133 then hasBooleanNamedAnnotation(ann, namedAnnotation);
3089 else false;
3090 end match;
3091 end hasBooleanNamedAnnotationInClass;
3092
3093 public function hasBooleanNamedAnnotationInComponent
3094 input SCode.Element inComponent;
3095 input String namedAnnotation;
3096 output Boolean hasAnn;
3097 algorithm
3098 hasAnn := match inComponent
3099 local
3100 SCode.Annotation ann;
3101 case SCode.COMPONENT(comment = SCode.COMMENT(annotation_ = SOME(ann)))
3102 ✗ then hasBooleanNamedAnnotation(ann, namedAnnotation);
3103 else false;
3104 end match;
3105 end hasBooleanNamedAnnotationInComponent;
3106
3107 public function commentAnnotation
3108 input SCode.Comment cmt;
3109 output Option<SCode.Annotation> ann = cmt.annotation_;
3110 end commentAnnotation;
3111
3112 public function optCommentAnnotation
3113 input Option<SCode.Comment> cmt;
3114 output Option<SCode.Annotation> ann;
3115 algorithm
3116 ann := match cmt
3117 case SOME(SCode.COMMENT(annotation_ = ann)) then ann;
3118 else NONE();
3119 end match;
3120 end optCommentAnnotation;
3121
3122 public function optCommentHasBooleanNamedAnnotation
3123 "check if the named annotation is present and has value true"
3124 input Option<SCode.Comment> comm;
3125 input String annotationName;
3126 output Boolean outB;
3127 algorithm
3128 outB := match comm
3129 local
3130 SCode.Annotation ann;
3131 case SOME(SCode.COMMENT(annotation_=SOME(ann)))
3132 152 then hasBooleanNamedAnnotation(ann,annotationName);
3133 else false;
3134 end match;
3135 end optCommentHasBooleanNamedAnnotation;
3136
3137 public function commentHasBooleanNamedAnnotation
3138 "check if the named annotation is present and has value true"
3139 input SCode.Comment comm;
3140 input String annotationName;
3141 output Boolean outB;
3142 algorithm
3143 outB := match comm
3144 local
3145 SCode.Annotation ann;
3146 case SCode.COMMENT(annotation_=SOME(ann))
3147 236278 then hasBooleanNamedAnnotation(ann,annotationName);
3148 else false;
3149 end match;
3150 end commentHasBooleanNamedAnnotation;
3151
3152 public function hasBooleanNamedAnnotation
3153 "Checks if the given annotation contains an entry with the given name with the
3154 value true."
3155 input SCode.Annotation inAnnotation;
3156 input String inName;
3157 output Boolean outHasEntry;
3158 protected
3159 Option<Absyn.Exp> binding;
3160 algorithm
3161 641388 binding := lookupAnnotationBinding(inAnnotation, inName);
3162
3163 outHasEntry := match binding
3164 case SOME(Absyn.BOOL(value = true)) then true;
3165 else false;
3166 end match;
3167 end hasBooleanNamedAnnotation;
3168
3169 public function optCommentHasBooleanNamedAnnotationFalse
3170 "check if the named annotation is present and has value false"
3171 input Option<SCode.Comment> comm;
3172 input String annotationName;
3173 output Boolean outB;
3174 algorithm
3175 outB := match comm
3176 local
3177 SCode.Annotation ann;
3178 case SOME(SCode.COMMENT(annotation_=SOME(ann)))
3179 118179 then hasBooleanNamedAnnotationFalse(ann, annotationName);
3180 else false;
3181 end match;
3182 end optCommentHasBooleanNamedAnnotationFalse;
3183
3184 public function hasBooleanNamedAnnotationFalse
3185 "Checks if the given annotation contains an entry with the given name with the
3186 value False."
3187 input SCode.Annotation inAnnotation;
3188 input String inName;
3189 output Boolean outHasEntry;
3190 protected
3191 Option<Absyn.Exp> binding;
3192 algorithm
3193 118179 binding := lookupAnnotationBinding(inAnnotation, inName);
3194
3195 outHasEntry := match binding
3196 case SOME(Absyn.BOOL(value = false)) then true;
3197 else false;
3198 end match;
3199 end hasBooleanNamedAnnotationFalse;
3200
3201 public function getEvaluateAnnotation
3202 "Looks up the Evaluate annotation and returns the value if the annotation
3203 exists and has a boolean value, otherwise NONE()."
3204 input SCode.Comment cmt;
3205 output Option<Boolean> value;
3206 protected
3207 SCode.Annotation ann;
3208 algorithm
3209 value := match cmt
3210 case SCode.COMMENT(annotation_ = SOME(ann))
3211 103951 then lookupBooleanAnnotation(ann, "Evaluate");
3212 else NONE();
3213 end match;
3214 end getEvaluateAnnotation;
3215
3216 public function appendAnnotationToCommentOption
3217 input SCode.Annotation inAnnotation;
3218 input Option<SCode.Comment> inComment;
3219 input Boolean check_replace = false;
3220 output Option<SCode.Comment> outComment;
3221 algorithm
3222 outComment := match inComment
3223 local
3224 SCode.Comment comment;
3225 ✗ case SOME(comment) then SOME(appendAnnotationToComment(inAnnotation, comment, check_replace));
3226 ✗ else SOME(SCode.COMMENT(SOME(inAnnotation), NONE()));
3227 end match;
3228 end appendAnnotationToCommentOption;
3229
3230 public function appendAnnotationToComment
3231 input SCode.Annotation inAnnotation;
3232 input SCode.Comment inComment;
3233 input Boolean check_replace = false;
3234 output SCode.Comment outComment;
3235 protected
3236 function isNotElem
3237 input SCode.SubMod mod;
3238 input list<SCode.SubMod> mods;
3239 output Boolean b = true;
3240 algorithm
3241
2/2
✓ Branch 0 taken 8180 times.
✓ Branch 1 taken 3743 times.
11923 for m in mods loop
3242
3/4
✓ Branch 0 taken 4437 times.
✓ Branch 1 taken 3743 times.
✓ Branch 3 taken 4437 times.
✗ Branch 4 not taken.
8180 if (mod.ident == m.ident) then
3243 b := false;
3244 4437 return;
3245 end if;
3246 end for;
3247 end isNotElem;
3248 algorithm
3249 outComment := match(inAnnotation, inComment)
3250 local
3251 Option<String> cmt;
3252 list<SCode.SubMod> mods1;
3253 SCode.Mod mod;
3254
3255 case (_, SCode.COMMENT(NONE(), cmt))
3256 336 then SCode.COMMENT(SOME(inAnnotation), cmt);
3257
3258 case (SCode.ANNOTATION(modification = SCode.MOD(subModLst = mods1)),
3259 SCode.COMMENT(SOME(SCode.ANNOTATION(modification = mod as SCode.MOD())), cmt))
3260 algorithm
3261
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4437 times.
4437 if not check_replace then
3262 ✗ mod.subModLst := listAppend(mods1, mod.subModLst);
3263 else
3264 8874 mod.subModLst := listAppend(mods1, List.filterOnTrue(mod.subModLst, function isNotElem(mods = mods1)));
3265 end if;
3266 8874 then
3267 SCode.COMMENT(SOME(SCode.ANNOTATION(mod)), cmt);
3268
3269 end match;
3270 end appendAnnotationToComment;
3271
3272 public function getModifierInfo
3273 input SCode.Mod inMod;
3274 output SourceInfo outInfo;
3275 algorithm
3276 outInfo := match inMod
3277 local
3278 SourceInfo info;
3279 SCode.Element el;
3280
3281 case SCode.MOD(info = info) then info;
3282 1 case SCode.REDECL(element = el) then elementInfo(el);
3283 10 case SCode.BREAK_COMPONENT() then inMod.info;
3284 ✗ case SCode.BREAK_CONNECT() then inMod.info;
3285 else Absyn.dummyInfo;
3286 end match;
3287 end getModifierInfo;
3288
3289 public function getModifierBinding
3290 input SCode.Mod inMod;
3291 output Option<Absyn.Exp> outBinding;
3292 algorithm
3293 outBinding := match inMod
3294 361238 case SCode.MOD() then inMod.binding;
3295 else NONE();
3296 end match;
3297 end getModifierBinding;
3298
3299 public function setModifierBinding
3300 input Option<Absyn.Exp> binding;
3301 input output SCode.Mod mod;
3302 algorithm
3303 () := match mod
3304 ✗ case SCode.Mod.MOD() algorithm mod.binding := binding; then ();
3305 else ();
3306 end match;
3307 end setModifierBinding;
3308
3309 function getComponentCondition
3310 input SCode.Element element;
3311 output Option<Absyn.Exp> condition;
3312 algorithm
3313 condition := match element
3314 ✗ case SCode.COMPONENT() then element.condition;
3315 else NONE();
3316 end match;
3317 end getComponentCondition;
3318
3319 public function removeComponentCondition
3320 input output SCode.Element element;
3321 algorithm
3322 () := match element
3323 case SCode.COMPONENT()
3324 algorithm
3325 ✗ element.condition := NONE();
3326 then
3327 ();
3328 end match;
3329 end removeComponentCondition;
3330
3331 public function isInnerComponent
3332 "Returns true if the given element is an element with the inner prefix,
3333 otherwise false."
3334 input SCode.Element inElement;
3335 output Boolean outIsInner;
3336 algorithm
3337 outIsInner := match inElement
3338 local
3339 Absyn.InnerOuter io;
3340
3341 case SCode.COMPONENT(prefixes = SCode.PREFIXES(innerOuter = io))
3342 ✗ then AbsynUtil.isInner(io);
3343
3344 else false;
3345
3346 end match;
3347 end isInnerComponent;
3348
3349 public function makeElementProtected
3350 input output SCode.Element element;
3351 protected
3352 SCode.Prefixes prefixes;
3353 algorithm
3354 () := match element
3355 case SCode.COMPONENT(prefixes = prefixes as SCode.PREFIXES(visibility = SCode.PUBLIC()))
3356 algorithm
3357 2 prefixes.visibility := SCode.PROTECTED();
3358 2 element.prefixes := prefixes;
3359 then
3360 ();
3361
3362 case SCode.EXTENDS(visibility = SCode.PUBLIC())
3363 algorithm
3364 ✗ element.visibility := SCode.PROTECTED();
3365 then
3366 ();
3367
3368 else ();
3369 end match;
3370 end makeElementProtected;
3371
3372 public function isElementPublic
3373 input SCode.Element inElement;
3374 output Boolean outIsPublic;
3375 algorithm
3376 ✗ outIsPublic := visibilityBool(elementVisibility(inElement));
3377 end isElementPublic;
3378
3379 public function isElementProtected
3380 input SCode.Element inElement;
3381 output Boolean outIsProtected;
3382 algorithm
3383 591681 outIsProtected := not visibilityBool(elementVisibility(inElement));
3384 end isElementProtected;
3385
3386 public function isElementEncapsulated
3387 input SCode.Element inElement;
3388 output Boolean outIsEncapsulated;
3389 algorithm
3390 outIsEncapsulated := match inElement
3391 case SCode.CLASS(encapsulatedPrefix = SCode.ENCAPSULATED()) then true;
3392 else false;
3393 end match;
3394 end isElementEncapsulated;
3395
3396 public function getElementsFromElement
3397 input SCode.Program inProgram;
3398 input SCode.Element inElement;
3399 output SCode.Program outProgram;
3400 algorithm
3401 outProgram := match inElement
3402 local
3403 SCode.Program els;
3404 SCode.Element e;
3405 Absyn.Path p;
3406
3407 // a class with parts
3408 case SCode.CLASS(classDef = SCode.PARTS(elementLst = els)) then els;
3409 // a class extends
3410 case SCode.CLASS(classDef = SCode.CLASS_EXTENDS(composition = SCode.PARTS(elementLst = els))) then els;
3411 // a derived class
3412 case SCode.CLASS(classDef = SCode.DERIVED(typeSpec = Absyn.TPATH(path = p)))
3413 algorithm
3414 ✗ e := getElementWithPath(inProgram, p);
3415 ✗ els := getElementsFromElement(inProgram, e);
3416 then
3417 els;
3418 end match;
3419 end getElementsFromElement;
3420
3421 protected function getElementWithId
3422 "returns the element from the program having the name as the id.
3423 if the element does not exist it fails"
3424 input SCode.Program inProgram;
3425 input String inId;
3426 output SCode.Element outElement;
3427 algorithm
3428 outElement := match(inProgram, inId)
3429 local
3430 SCode.Program rest;
3431 SCode.Element e;
3432 Absyn.Path p;
3433 Absyn.Ident i, n;
3434
3435 case ((e as SCode.CLASS(name = n))::_, i)
3436 guard stringEq(n, i)
3437 then
3438 e;
3439
3440 case ((e as SCode.COMPONENT(name = n))::_, i)
3441 guard stringEq(n, i)
3442 then
3443 e;
3444
3445 case ((e as SCode.EXTENDS(baseClassPath = p))::_, i)
3446 guard stringEq(AbsynUtil.pathString(p), i)
3447 then
3448 e;
3449
3450 case (_::rest, i)
3451 14 then getElementWithId(rest, i);
3452
3453 end match;
3454 end getElementWithId;
3455
3456 public function getElementWithPath
3457 "returns the element from the program having the name as the id.
3458 if the element does not exist it fails"
3459 input SCode.Program inProgram;
3460 input Absyn.Path inPath;
3461 output SCode.Element outElement;
3462 algorithm
3463 outElement := match inPath
3464 local
3465 SCode.Program sp;
3466 SCode.Element e;
3467 Absyn.Path p;
3468 Absyn.Ident i;
3469
3470 case Absyn.FULLYQUALIFIED(p)
3471 ✗ then getElementWithPath(inProgram, p);
3472
3473 case Absyn.IDENT(i)
3474 algorithm
3475 78 e := getElementWithId(inProgram, i);
3476 then
3477 e;
3478
3479 case Absyn.QUALIFIED(i, p)
3480 algorithm
3481 2 e := getElementWithId(inProgram, i);
3482 2 sp := getElementsFromElement(inProgram, e);
3483 2 e := getElementWithPath(sp, p);
3484 then
3485 e;
3486 end match;
3487 end getElementWithPath;
3488
3489 public function getElementName ""
3490 input SCode.Element e;
3491 output String s;
3492 algorithm
3493 s := match e
3494 local Absyn.Path p;
3495 case SCode.COMPONENT(name = s) then s;
3496 case SCode.CLASS(name = s) then s;
3497 ✗ case SCode.EXTENDS(baseClassPath = p) then AbsynUtil.pathString(p);
3498 end match;
3499 end getElementName;
3500
3501 public function getElementTypePath
3502 input SCode.Element element;
3503 output Absyn.Path path;
3504 algorithm
3505 path := match element
3506 17 case SCode.COMPONENT() then AbsynUtil.typeSpecPath(element.typeSpec);
3507 ✗ case SCode.EXTENDS() then element.baseClassPath;
3508 end match;
3509 end getElementTypePath;
3510
3511 public function setBaseClassPath
3512 "@auhtor: adrpo
3513 set the base class path in extends"
3514 input output SCode.Element element;
3515 input Absyn.Path inBcPath;
3516 algorithm
3517 () := match element
3518 case SCode.EXTENDS()
3519 algorithm
3520 ✗ element.baseClassPath := inBcPath;
3521 then
3522 ();
3523 end match;
3524 end setBaseClassPath;
3525
3526 public function getBaseClassPath
3527 "@auhtor: adrpo
3528 return the base class path in extends"
3529 input SCode.Element inE;
3530 output Absyn.Path outBcPath;
3531 algorithm
3532 ✗ SCode.EXTENDS(baseClassPath = outBcPath) := inE;
3533 end getBaseClassPath;
3534
3535 public function setComponentTypeSpec
3536 "Sets the typespec of a component element."
3537 input output SCode.Element element;
3538 input Absyn.TypeSpec typeSpec;
3539 algorithm
3540 () := match element
3541 case SCode.COMPONENT()
3542 algorithm
3543 ✗ element.typeSpec := typeSpec;
3544 then
3545 ();
3546 end match;
3547 end setComponentTypeSpec;
3548
3549 public function getComponentTypeSpec
3550 "@auhtor: adrpo
3551 get the typespec path in component"
3552 input SCode.Element inE;
3553 output Absyn.TypeSpec outTypeSpec;
3554 protected
3555 algorithm
3556
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 SCode.COMPONENT(typeSpec = outTypeSpec) := inE;
3557 end getComponentTypeSpec;
3558
3559 public function setComponentMod
3560 "Sets the modification in a component element."
3561 input output SCode.Element element;
3562 input SCode.Mod mod;
3563 algorithm
3564 () := match element
3565 case SCode.COMPONENT()
3566 algorithm
3567 50 element.modifications := mod;
3568 then
3569 ();
3570 end match;
3571 end setComponentMod;
3572
3573 public function getComponentMod
3574 "@auhtor: adrpo
3575 get the modification in component"
3576 input SCode.Element inE;
3577 output SCode.Mod outMod;
3578 algorithm
3579 ✗ SCode.COMPONENT(modifications = outMod) := inE;
3580 end getComponentMod;
3581
3582 public function isDerivedClass
3583 input SCode.Element inClass;
3584 output Boolean isDerived;
3585 algorithm
3586 isDerived := match inClass
3587 case SCode.CLASS(classDef = SCode.DERIVED()) then true;
3588 else false;
3589 end match;
3590 end isDerivedClass;
3591
3592 public function isClassExtends
3593 input SCode.Element cls;
3594 output Boolean isCE;
3595 algorithm
3596 isCE := match cls
3597 case SCode.CLASS(classDef = SCode.CLASS_EXTENDS()) then true;
3598 else false;
3599 end match;
3600 end isClassExtends;
3601
3602 public function getDerivedTypeSpec
3603 "@auhtor: adrpo
3604 set the base class path in extends"
3605 input SCode.Element inE;
3606 output Absyn.TypeSpec outTypeSpec;
3607 protected
3608 algorithm
3609 ✗ SCode.CLASS(classDef=SCode.DERIVED(typeSpec = outTypeSpec)) := inE;
3610 end getDerivedTypeSpec;
3611
3612 public function getDerivedMod
3613 "@auhtor: adrpo
3614 set the base class path in extends"
3615 input SCode.Element inE;
3616 output SCode.Mod outMod;
3617 protected
3618 algorithm
3619
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 988 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 988 times.
988 SCode.CLASS(classDef=SCode.DERIVED(modifications = outMod)) := inE;
3620 end getDerivedMod;
3621
3622 public function setClassPrefixes
3623 input SCode.Prefixes prefixes;
3624 input output SCode.Element cl;
3625 algorithm
3626 () := match cl
3627 case SCode.CLASS()
3628 algorithm
3629 ✗ cl.prefixes := prefixes;
3630 then
3631 ();
3632 end match;
3633 end setClassPrefixes;
3634
3635 public function getClassDef
3636 input SCode.Element inClass;
3637 output SCode.ClassDef outCdef;
3638 algorithm
3639 outCdef := match inClass
3640 case SCode.CLASS(classDef = outCdef) then outCdef;
3641 end match;
3642 end getClassDef;
3643
3644 public function setClassDef
3645 input SCode.ClassDef classDef;
3646 input output SCode.Element cls;
3647 algorithm
3648 () := match cls
3649 case SCode.CLASS()
3650 algorithm
3651 56100 cls.classDef := classDef;
3652 then
3653 ();
3654 end match;
3655 end setClassDef;
3656
3657 public function getClassBody
3658 "Returns the body of a class, which for a class extends is the definition it
3659 contains and otherwise just the immediate definition of the class."
3660 input SCode.Element inClass;
3661 output SCode.ClassDef outCdef;
3662 algorithm
3663 119179 outCdef := getClassDef(inClass);
3664
3665 outCdef := match outCdef
3666 1916 case SCode.ClassDef.CLASS_EXTENDS() then outCdef.composition;
3667 else outCdef;
3668 end match;
3669 end getClassBody;
3670
3671 public function equationsContainReinit
3672 "@author:
3673 returns true if equations contains reinit"
3674 input list<SCode.Equation> inEqs;
3675 output Boolean hasReinit;
3676 algorithm
3677 ✗ hasReinit := match inEqs
3678 local Boolean b;
3679 case _
3680 algorithm
3681 b := List.applyAndFold(inEqs, boolOr, equationContainReinit, false);
3682 then
3683 b;
3684 end match;
3685 end equationsContainReinit;
3686
3687 public function equationContainReinit
3688 "@author:
3689 returns true if equation contains reinit"
3690 input SCode.Equation inEq;
3691 output Boolean hasReinit;
3692 algorithm
3693 hasReinit := match inEq
3694 local
3695 Boolean b;
3696 list<SCode.Equation> eqs;
3697 list<list<SCode.Equation>> eqs_lst;
3698 list<tuple<Absyn.Exp, list<SCode.Equation>>> tpl_el;
3699
3700 case SCode.EQ_REINIT() then true;
3701 case SCode.EQ_WHEN(eEquationLst = eqs, elseBranches = tpl_el)
3702 algorithm
3703 ✗ b := equationsContainReinit(eqs);
3704 ✗ eqs_lst := List.map(tpl_el, Util.tuple22);
3705 ✗ b := List.applyAndFold(eqs_lst, boolOr, equationsContainReinit, b);
3706 then
3707 b;
3708
3709 case SCode.EQ_IF(thenBranch = eqs_lst, elseBranch = eqs)
3710 algorithm
3711 ✗ b := equationsContainReinit(eqs);
3712 ✗ b := List.applyAndFold(eqs_lst, boolOr, equationsContainReinit, b);
3713 then
3714 b;
3715
3716 case SCode.EQ_FOR(eEquationLst = eqs)
3717 algorithm
3718 ✗ b := equationsContainReinit(eqs);
3719 then
3720 b;
3721
3722 else false;
3723
3724 end match;
3725 end equationContainReinit;
3726
3727 public function algorithmsContainReinit
3728 "@author:
3729 returns true if statements contains reinit"
3730 input list<SCode.Statement> inAlgs;
3731 output Boolean hasReinit;
3732 algorithm
3733 6 hasReinit := match inAlgs
3734 local Boolean b;
3735 case _
3736 algorithm
3737 b := List.applyAndFold(inAlgs, boolOr, algorithmContainReinit, false);
3738 then
3739 b;
3740 end match;
3741 end algorithmsContainReinit;
3742
3743 public function algorithmContainReinit
3744 "@author:
3745 returns true if statement contains reinit"
3746 input SCode.Statement inAlg;
3747 output Boolean hasReinit;
3748 algorithm
3749 hasReinit := match inAlg
3750 local
3751 Boolean b, b1, b2, b3;
3752 list<SCode.Statement> algs, algs1, algs2;
3753 list<list<SCode.Statement>> algs_lst;
3754 list<tuple<Absyn.Exp, list<SCode.Statement>>> tpl_alg;
3755
3756 case SCode.ALG_REINIT() then true;
3757
3758 case SCode.ALG_WHEN_A(branches = tpl_alg)
3759 algorithm
3760 ✗ algs_lst := List.map(tpl_alg, Util.tuple22);
3761 ✗ b := List.applyAndFold(algs_lst, boolOr, algorithmsContainReinit, false);
3762 then
3763 b;
3764
3765 case SCode.ALG_IF(trueBranch = algs1, elseIfBranch = tpl_alg, elseBranch = algs2)
3766 algorithm
3767 ✗ b1 := algorithmsContainReinit(algs1);
3768 ✗ algs_lst := List.map(tpl_alg, Util.tuple22);
3769 ✗ b2 := List.applyAndFold(algs_lst, boolOr, algorithmsContainReinit, b1);
3770 ✗ b3 := algorithmsContainReinit(algs2);
3771 ✗ b := boolOr(b1, boolOr(b2, b3));
3772 then
3773 b;
3774
3775 case SCode.ALG_FOR(forBody = algs)
3776 algorithm
3777 ✗ b := algorithmsContainReinit(algs);
3778 then
3779 b;
3780
3781 case SCode.ALG_WHILE(whileBody = algs)
3782 algorithm
3783 ✗ b := algorithmsContainReinit(algs);
3784 then
3785 b;
3786
3787 else false;
3788
3789 end match;
3790 end algorithmContainReinit;
3791
3792 public function getClassPartialPrefix
3793 input SCode.Element inElement;
3794 output SCode.Partial outPartial;
3795 algorithm
3796
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42445 times.
42445 SCode.CLASS(partialPrefix = outPartial) := inElement;
3797 end getClassPartialPrefix;
3798
3799 public function getClassRestriction
3800 input SCode.Element inElement;
3801 output SCode.Restriction outRestriction;
3802 algorithm
3803
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4461313 times.
4461313 SCode.CLASS(restriction = outRestriction) := inElement;
3804 end getClassRestriction;
3805
3806 public function isRedeclareSubMod
3807 input SCode.SubMod inSubMod;
3808 output Boolean outIsRedeclare;
3809 algorithm
3810 outIsRedeclare := match inSubMod
3811 case SCode.NAMEMOD(mod = SCode.REDECL()) then true;
3812 else false;
3813 end match;
3814 end isRedeclareSubMod;
3815
3816 public function isBreakSubMod
3817 input SCode.SubMod subMod;
3818 output Boolean isBreak;
3819 algorithm
3820 isBreak := match subMod.mod
3821 case SCode.Mod.BREAK_COMPONENT() then true;
3822 case SCode.Mod.BREAK_CONNECT() then true;
3823 else false;
3824 end match;
3825 end isBreakSubMod;
3826
3827 public function isBreakComponentSubMod
3828 input SCode.SubMod subMod;
3829 output Boolean isBreak;
3830 algorithm
3831 isBreak := match subMod
3832 case SCode.NAMEMOD(mod = SCode.Mod.BREAK_COMPONENT()) then true;
3833 else false;
3834 end match;
3835 end isBreakComponentSubMod;
3836
3837 public function isBreakConnectSubMod
3838 input SCode.SubMod subMod;
3839 output Boolean isBreak;
3840 algorithm
3841 isBreak := match subMod
3842 case SCode.NAMEMOD(mod = SCode.Mod.BREAK_CONNECT()) then true;
3843 else false;
3844 end match;
3845 end isBreakConnectSubMod;
3846
3847 public function componentMod
3848 input SCode.Element inElement;
3849 output SCode.Mod outMod;
3850 algorithm
3851 outMod := match inElement
3852 local
3853 SCode.Mod mod;
3854
3855 case SCode.COMPONENT(modifications = mod) then mod;
3856 else SCode.NOMOD();
3857
3858 end match;
3859 end componentMod;
3860
3861 public function elementMod
3862 input SCode.Element inElement;
3863 output SCode.Mod outMod;
3864 algorithm
3865 outMod := match inElement
3866 local
3867 SCode.Mod mod;
3868
3869 case SCode.COMPONENT(modifications = mod) then mod;
3870 case SCode.CLASS(classDef = SCode.DERIVED(modifications = mod)) then mod;
3871 case SCode.CLASS(classDef = SCode.CLASS_EXTENDS(modifications = mod)) then mod;
3872 case SCode.EXTENDS(modifications = mod) then mod;
3873 else SCode.NOMOD();
3874
3875 end match;
3876 end elementMod;
3877
3878 public function setElementMod
3879 "Sets the modifier of an element, or fails if the element is not capable of
3880 having a modifier."
3881 input output SCode.Element element;
3882 input SCode.Mod mod;
3883 algorithm
3884 () := match element
3885 ✗ case SCode.COMPONENT() algorithm element.modifications := mod; then ();
3886 ✗ case SCode.CLASS() algorithm element.classDef := setClassDefMod(element.classDef, mod); then ();
3887 ✗ case SCode.EXTENDS() algorithm element.modifications := mod; then ();
3888 end match;
3889 end setElementMod;
3890
3891 protected function setClassDefMod
3892 input output SCode.ClassDef classDef;
3893 input SCode.Mod inMod;
3894 algorithm
3895 () := match classDef
3896 ✗ case SCode.DERIVED() algorithm classDef.modifications := inMod; then ();
3897 ✗ case SCode.CLASS_EXTENDS() algorithm classDef.modifications := inMod; then ();
3898 else ();
3899 end match;
3900 end setClassDefMod;
3901
3902 public function isBuiltinElement
3903 input SCode.Element inElement;
3904 output Boolean outIsBuiltin;
3905 algorithm
3906 outIsBuiltin := match inElement
3907 local
3908 SCode.Annotation ann;
3909
3910 case SCode.CLASS(classDef = SCode.PARTS(externalDecl =
3911 SOME(SCode.EXTERNALDECL(lang = SOME("builtin"))))) then true;
3912 case SCode.CLASS(cmt = SCode.COMMENT(annotation_ = SOME(ann)))
3913 ✗ then hasBooleanNamedAnnotation(ann, "__OpenModelica_builtin");
3914 else false;
3915 end match;
3916 end isBuiltinElement;
3917
3918 public function isExternalFunctionRestriction
3919 input SCode.FunctionRestriction inRestr;
3920 output Boolean isExternal;
3921 algorithm
3922 isExternal := match inRestr
3923 case SCode.FR_EXTERNAL_FUNCTION() then true;
3924 else false;
3925 end match;
3926 end isExternalFunctionRestriction;
3927
3928 public function isImpureFunctionRestriction
3929 input SCode.FunctionRestriction inRestr;
3930 output Boolean isExternal;
3931 algorithm
3932 isExternal := match inRestr
3933 case SCode.FR_EXTERNAL_FUNCTION(purity = Absyn.FunctionPurity.IMPURE()) then true;
3934 case SCode.FR_NORMAL_FUNCTION(purity = Absyn.FunctionPurity.IMPURE()) then true;
3935 else false;
3936 end match;
3937 end isImpureFunctionRestriction;
3938
3939 public function isRestrictionImpure
3940 input SCode.Restriction inRestr;
3941 input Boolean hasZeroOutputPreMSL3_2;
3942 output Boolean isImpure;
3943 algorithm
3944 isImpure := match inRestr
3945 // Any function explicitly declared impure is impure.
3946 case SCode.R_FUNCTION(SCode.FR_NORMAL_FUNCTION(purity = Absyn.FunctionPurity.IMPURE())) then true;
3947 case SCode.R_FUNCTION(SCode.FR_EXTERNAL_FUNCTION(purity = Absyn.FunctionPurity.IMPURE())) then true;
3948 // External functions with no pure/impure prefix are impure by default since Modelica 3.3.
3949 case SCode.R_FUNCTION(SCode.FR_EXTERNAL_FUNCTION(purity = Absyn.FunctionPurity.NO_PURITY()))
3950 54938 then not hasZeroOutputPreMSL3_2;
3951 else false;
3952 end match;
3953 end isRestrictionImpure;
3954
3955 public function getFunctionRestrictionPurity
3956 input SCode.FunctionRestriction restr;
3957 output Absyn.FunctionPurity purity;
3958 algorithm
3959 purity := match restr
3960 case SCode.FR_NORMAL_FUNCTION(purity = purity) then purity;
3961 case SCode.FR_EXTERNAL_FUNCTION(purity = purity) then purity;
3962 else Absyn.FunctionPurity.NO_PURITY();
3963 end match;
3964 end getFunctionRestrictionPurity;
3965
3966 public function elementInnerOuter
3967 input SCode.Element element;
3968 output Absyn.InnerOuter io;
3969 algorithm
3970 io := match element
3971 ✗ case SCode.Element.CLASS() then prefixesInnerOuter(element.prefixes);
3972 ✗ case SCode.Element.COMPONENT() then prefixesInnerOuter(element.prefixes);
3973 else Absyn.InnerOuter.NOT_INNER_OUTER();
3974 end match;
3975 end elementInnerOuter;
3976
3977 public function elementVisibility
3978 input SCode.Element element;
3979 output SCode.Visibility visibility;
3980 algorithm
3981 visibility := match element
3982 19 case SCode.Element.IMPORT() then element.visibility;
3983 66017 case SCode.Element.EXTENDS() then element.visibility;
3984 41211 case SCode.Element.CLASS() then prefixesVisibility(element.prefixes);
3985 484434 case SCode.Element.COMPONENT() then prefixesVisibility(element.prefixes);
3986 ✗ case SCode.Element.DEFINEUNIT() then element.visibility;
3987 end match;
3988 end elementVisibility;
3989
3990 public function isClassNamed
3991 "Returns true if the given element is a class with the given name, otherwise false."
3992 input SCode.Ident inName;
3993 input SCode.Element inClass;
3994 output Boolean outIsNamed;
3995 algorithm
3996 outIsNamed := match inClass
3997 local
3998 SCode.Ident name;
3999
4000
4/4
✓ Branch 0 taken 901 times.
✓ Branch 1 taken 487 times.
✓ Branch 3 taken 40 times.
✓ Branch 4 taken 861 times.
1388 case SCode.CLASS(name = name) then stringEq(inName, name);
4001 else false;
4002 end match;
4003 end isClassNamed;
4004
4005 public function isElementNamed
4006 input SCode.Ident name;
4007 input SCode.Element element;
4008 output Boolean res;
4009 algorithm
4010 res := match element
4011
4/4
✓ Branch 0 taken 623 times.
✓ Branch 1 taken 1590 times.
✓ Branch 3 taken 336 times.
✓ Branch 4 taken 287 times.
2213 case SCode.CLASS() then element.name == name;
4012
4/4
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 14 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 14 times.
36 case SCode.COMPONENT() then element.name == name;
4013 else false;
4014 end match;
4015 end isElementNamed;
4016
4017 public function getElementComment
4018 "Returns the comment of an element."
4019 input SCode.Element inElement;
4020 output Option<SCode.Comment> outComment;
4021 algorithm
4022 outComment := match inElement
4023 local
4024 SCode.Comment cmt;
4025
4026 case SCode.COMPONENT(comment = cmt) then SOME(cmt);
4027 case SCode.CLASS(cmt = cmt) then SOME(cmt);
4028 9 case SCode.EXTENDS() then SOME(SCode.Comment.COMMENT(inElement.ann, NONE()));
4029 else NONE();
4030
4031 end match;
4032 end getElementComment;
4033
4034 public function stripAnnotationFromComment
4035 "Removes the annotation from a comment."
4036 input Option<SCode.Comment> inComment;
4037 output Option<SCode.Comment> outComment;
4038 algorithm
4039 outComment := match inComment
4040 local
4041 Option<String> str;
4042
4043 ✗ case SOME(SCode.COMMENT(_, str)) then SOME(SCode.COMMENT(NONE(), str));
4044 else NONE();
4045
4046 end match;
4047 end stripAnnotationFromComment;
4048
4049 public function isOverloadedFunction
4050 input SCode.Element inElement;
4051 output Boolean isOverloaded;
4052 algorithm
4053 isOverloaded := match inElement
4054 case SCode.CLASS(classDef = SCode.OVERLOAD()) then true;
4055 else false;
4056 end match;
4057 end isOverloadedFunction;
4058
4059 public function mergeWithOriginal
4060 "@author: adrpo
4061 this function merges the original declaration with the redeclared declaration, see 7.3.2 in Spec.
4062 - modifiers from the constraining class on derived classes are merged into the new declaration
4063 - modifiers from the original derived classes are merged into the new declaration
4064 - if the original declaration has no constraining type the derived declaration is used
4065 - prefixes and attributes are merged
4066 same with components
4067 TODO! how about non-short class definitions with constrained by with modifications?"
4068 input output SCode.Element newClass;
4069 input SCode.Element oldClass;
4070 algorithm
4071 () := matchcontinue(newClass, oldClass)
4072 local
4073 SCode.Prefixes prefixes1, prefixes2;
4074 SCode.ClassDef cd1,cd2;
4075 SCode.Mod mCCNew, mCCOld;
4076
4077 // for functions return the new one!
4078 case (_, _)
4079 algorithm
4080
2/2
✓ Branch 1 taken 2039 times.
✓ Branch 2 taken 8247 times.
10286 true := isFunction(newClass);
4081 then
4082 ();
4083
4084 case (SCode.CLASS(prefixes = prefixes1, classDef = cd1),
4085 SCode.CLASS(prefixes = prefixes2, classDef = cd2))
4086 algorithm
4087 2039 mCCNew := getConstrainedByModifiers(prefixes1);
4088 2039 mCCOld := getConstrainedByModifiers(prefixes2);
4089 2039 newClass.classDef := mergeClassDef(cd1, cd2, mCCNew, mCCOld);
4090 2021 newClass.prefixes := propagatePrefixes(prefixes1, prefixes2);
4091 then
4092 ();
4093
4094 else ();
4095 end matchcontinue;
4096 end mergeWithOriginal;
4097
4098 public function getConstrainedByModifiers
4099 input SCode.Prefixes inPrefixes;
4100 output SCode.Mod outMod;
4101 algorithm
4102 outMod := match inPrefixes
4103 local SCode.Mod m;
4104 case SCode.PREFIXES(replaceablePrefix = SCode.REPLACEABLE(SOME(SCode.CONSTRAINCLASS(modifier = m))))
4105 then m;
4106 else SCode.NOMOD();
4107 end match;
4108 end getConstrainedByModifiers;
4109
4110 public function mergeClassDef
4111 "@author: adrpo
4112 see mergeWithOriginal"
4113 input SCode.ClassDef inNew;
4114 input SCode.ClassDef inOld;
4115 input SCode.Mod inCCModNew;
4116 input SCode.Mod inCCModOld;
4117 output SCode.ClassDef outNew;
4118 algorithm
4119 outNew := match(inNew, inOld)
4120 local
4121 SCode.ClassDef n;
4122 Absyn.TypeSpec ts1;
4123 SCode.Mod m1, m2;
4124 SCode.Attributes a1, a2;
4125
4126 case (SCode.DERIVED(ts1,m1,a1), SCode.DERIVED(_,m2,a2))
4127 algorithm
4128 2021 m2 := mergeModifiers(m2, inCCModOld);
4129 2021 m1 := mergeModifiers(m1, inCCModNew);
4130 2021 m2 := mergeModifiers(m1, m2);
4131 2021 a2 := propagateAttributes(a2, a1);
4132 2021 n := SCode.DERIVED(ts1,m2,a2);
4133 then
4134 n;
4135
4136 end match;
4137 end mergeClassDef;
4138
4139 public function mergeModifiers
4140 input SCode.Mod inNewMod;
4141 input SCode.Mod inOldMod;
4142 output SCode.Mod outMod;
4143 algorithm
4144 outMod := match(inNewMod, inOldMod)
4145 local
4146 SCode.Final f1, f2;
4147 SCode.Each e1, e2;
4148 list<SCode.SubMod> sl1, sl2, sl;
4149 Option<Absyn.Exp> b1, b2, b;
4150 SourceInfo i1;
4151 SCode.Mod m;
4152 Option<String> cmt;
4153
4154 case (_, SCode.NOMOD()) then inNewMod;
4155 case (SCode.NOMOD(), _) then inOldMod;
4156 case (SCode.REDECL(), _) then inNewMod;
4157
4158 case (SCode.MOD(f1, e1, sl1, b1, cmt, i1),
4159 SCode.MOD(f2, e2, sl2, b2, _))
4160 algorithm
4161
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 23032 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 23032 times.
23032 b := if isSome(b1) then b1 else b2;
4162 23032 sl := mergeSubMods(sl1, sl2);
4163
1/2
✓ Branch 0 taken 23032 times.
✗ Branch 1 not taken.
23032 if referenceEq(b, b1) and referenceEq(sl, sl1) then
4164 m := inNewMod;
4165 elseif referenceEq(b, b2) and referenceEq(sl, sl2) and valueEq(f1, f2) and valueEq(e1, e2) then
4166 m := inOldMod;
4167 else
4168 23032 m := SCode.MOD(f1, e1, sl, b, cmt, i1);
4169 end if;
4170 then
4171 m;
4172
4173 else inNewMod;
4174
4175 end match;
4176 end mergeModifiers;
4177
4178 protected function mergeSubMods
4179 input list<SCode.SubMod> inNew;
4180 input list<SCode.SubMod> inOld;
4181 output list<SCode.SubMod> outSubs;
4182 algorithm
4183 outSubs := matchcontinue inNew
4184 local
4185 list<SCode.SubMod> sl, rest, old;
4186 SCode.SubMod s;
4187
4188 case {} then inOld;
4189
4190 case s::rest
4191 algorithm
4192 45345 old := removeSub(s, inOld);
4193 45345 sl := mergeSubMods(rest, old);
4194 then
4195 s::sl;
4196
4197 else inNew;
4198 end matchcontinue;
4199 end mergeSubMods;
4200
4201 protected function removeSub
4202 input SCode.SubMod inSub;
4203 input list<SCode.SubMod> inOld;
4204 output list<SCode.SubMod> outSubs;
4205 algorithm
4206 outSubs := match(inSub, inOld)
4207 local
4208 list<SCode.SubMod> rest;
4209 SCode.Ident id1, id2;
4210 SCode.SubMod s;
4211
4212 case (_, {}) then inOld;
4213
4214 case (SCode.NAMEMOD(ident = id1), SCode.NAMEMOD(ident = id2)::rest) guard stringEqual(id1, id2)
4215 then
4216 rest;
4217
4218 case (_, s::rest)
4219 algorithm
4220 39485 rest := removeSub(inSub, rest);
4221 then
4222 s::rest;
4223 end match;
4224 end removeSub;
4225
4226 public function mergeComponentModifiers
4227 input output SCode.Element newComp;
4228 input SCode.Element oldComp;
4229 algorithm
4230 () := match (newComp, oldComp)
4231 case (SCode.COMPONENT(), SCode.COMPONENT())
4232 algorithm
4233 ✗ newComp.modifications := mergeModifiers(newComp.modifications, oldComp.modifications);
4234 then
4235 ();
4236 end match;
4237 end mergeComponentModifiers;
4238
4239 public function propagateAttributes
4240 input SCode.Attributes inOriginalAttributes;
4241 input SCode.Attributes inNewAttributes;
4242 input Boolean inNewTypeIsArray = false;
4243 output SCode.Attributes outNewAttributes;
4244 protected
4245 Absyn.ArrayDim dims1, dims2;
4246 SCode.ConnectorType ct1, ct2;
4247 SCode.Parallelism prl1,prl2;
4248 SCode.Variability var1, var2;
4249 Absyn.Direction dir1, dir2;
4250 Absyn.IsField if1, if2;
4251 algorithm
4252 2206 SCode.ATTR(dims1, ct1, prl1, var1, dir1, if1) := inOriginalAttributes;
4253 2206 SCode.ATTR(dims2, ct2, prl2, var2, dir2, if2) := inNewAttributes;
4254
4255 // If the new component has an array type, don't propagate the old dimensions.
4256 // E.g. type Real3 = Real[3];
4257 // replaceable Real x[:];
4258 // comp(redeclare Real3 x) => Real[3] x
4259
2/2
✓ Branch 0 taken 2205 times.
✓ Branch 1 taken 1 time.
2206 if not inNewTypeIsArray then
4260 2205 dims2 := propagateArrayDimensions(dims1, dims2);
4261 end if;
4262
4263 2206 ct2 := propagateConnectorType(ct1, ct2);
4264 2206 prl2 := propagateParallelism(prl1,prl2);
4265 2206 var2 := propagateVariability(var1, var2);
4266 2206 dir2 := propagateDirection(dir1, dir2);
4267 2206 if2 := propagateIsField(if1,if2);
4268 2206 outNewAttributes := SCode.ATTR(dims2, ct2, prl2, var2, dir2, if2);
4269 end propagateAttributes;
4270
4271 public function propagateArrayDimensions
4272 input Absyn.ArrayDim inOriginalDims;
4273 input Absyn.ArrayDim inNewDims;
4274 output Absyn.ArrayDim outNewDims;
4275 algorithm
4276 outNewDims := match inNewDims
4277 case {} then inOriginalDims;
4278 else inNewDims;
4279 end match;
4280 end propagateArrayDimensions;
4281
4282 public function propagateConnectorType
4283 input SCode.ConnectorType inOriginalConnectorType;
4284 input SCode.ConnectorType inNewConnectorType;
4285 output SCode.ConnectorType outNewConnectorType;
4286 algorithm
4287 outNewConnectorType := match inNewConnectorType
4288 case SCode.POTENTIAL() then inOriginalConnectorType;
4289 else inNewConnectorType;
4290 end match;
4291 end propagateConnectorType;
4292
4293 public function propagateParallelism
4294 input SCode.Parallelism inOriginalParallelism;
4295 input SCode.Parallelism inNewParallelism;
4296 output SCode.Parallelism outNewParallelism;
4297 algorithm
4298 outNewParallelism := match inNewParallelism
4299 case SCode.NON_PARALLEL() then inOriginalParallelism;
4300 else inNewParallelism;
4301 end match;
4302 end propagateParallelism;
4303
4304 public function propagateVariability
4305 input SCode.Variability inOriginalVariability;
4306 input SCode.Variability inNewVariability;
4307 output SCode.Variability outNewVariability;
4308 algorithm
4309 outNewVariability := match inNewVariability
4310 case SCode.VAR() then inOriginalVariability;
4311 else inNewVariability;
4312 end match;
4313 end propagateVariability;
4314
4315 public function propagateDirection
4316 input Absyn.Direction inOriginalDirection;
4317 input Absyn.Direction inNewDirection;
4318 output Absyn.Direction outNewDirection;
4319 algorithm
4320 outNewDirection := match inNewDirection
4321 case Absyn.BIDIR() then inOriginalDirection;
4322 else inNewDirection;
4323 end match;
4324 end propagateDirection;
4325
4326 public function propagateIsField
4327 input Absyn.IsField inOriginalIsField;
4328 input Absyn.IsField inNewIsField;
4329 output Absyn.IsField outNewIsField;
4330 algorithm
4331 outNewIsField := match inNewIsField
4332 case Absyn.NONFIELD() then inOriginalIsField;
4333 else inNewIsField;
4334 end match;
4335 end propagateIsField;
4336
4337 public function propagateAttributesVar
4338 input SCode.Element originalVar;
4339 input output SCode.Element newVar;
4340 input Boolean isNewTypeArray;
4341 algorithm
4342 () := match (originalVar, newVar)
4343 case (SCode.COMPONENT(), SCode.COMPONENT())
4344 algorithm
4345 50 newVar.prefixes := propagatePrefixes(originalVar.prefixes, newVar.prefixes);
4346 50 newVar.attributes := propagateAttributes(originalVar.attributes, newVar.attributes, isNewTypeArray);
4347 then
4348 ();
4349 end match;
4350 end propagateAttributesVar;
4351
4352 public function propagateAttributesClass
4353 input SCode.Element originalClass;
4354 input output SCode.Element newClass;
4355 algorithm
4356 () := match (originalClass, newClass)
4357 case (SCode.CLASS(), SCode.CLASS())
4358 algorithm
4359 ✗ newClass.prefixes := propagatePrefixes(originalClass.prefixes, newClass.prefixes);
4360 then
4361 ();
4362 end match;
4363 end propagateAttributesClass;
4364
4365 public function propagatePrefixes
4366 input SCode.Prefixes originalPrefixes;
4367 input output SCode.Prefixes newPrefixes;
4368 algorithm
4369 () := match (originalPrefixes, newPrefixes)
4370 case (SCode.PREFIXES(), SCode.PREFIXES())
4371 algorithm
4372 2394 newPrefixes.innerOuter := propagatePrefixInnerOuter(originalPrefixes.innerOuter, newPrefixes.innerOuter);
4373 then
4374 ();
4375 end match;
4376 end propagatePrefixes;
4377
4378 public function propagatePrefixInnerOuter
4379 input Absyn.InnerOuter inOriginalIO;
4380 input Absyn.InnerOuter inIO;
4381 output Absyn.InnerOuter outIO;
4382 algorithm
4383 outIO := match inIO
4384 case Absyn.NOT_INNER_OUTER() then inOriginalIO;
4385 else inIO;
4386 end match;
4387 end propagatePrefixInnerOuter;
4388
4389 public function isPackage
4390 "Return true if Class is a partial."
4391 input SCode.Element inClass;
4392 output Boolean outBoolean;
4393 algorithm
4394 outBoolean := match inClass
4395 case SCode.CLASS(restriction = SCode.R_PACKAGE()) then true;
4396 else false;
4397 end match;
4398 end isPackage;
4399
4400 public function isPartial
4401 "Return true if Class is a partial."
4402 input SCode.Element inClass;
4403 output Boolean outBoolean;
4404 algorithm
4405 outBoolean := match inClass
4406 case SCode.CLASS(partialPrefix = SCode.PARTIAL()) then true;
4407 else false;
4408 end match;
4409 end isPartial;
4410
4411 public function isValidPackageElement
4412 "Return true if the given element is allowed in a package, i.e. if it's a
4413 constant or non-component element. Otherwise returns false."
4414 input SCode.Element inElement;
4415 output Boolean outIsValid;
4416 algorithm
4417 outIsValid := match inElement
4418 case SCode.COMPONENT(attributes = SCode.ATTR(variability = SCode.CONST())) then true;
4419 case SCode.COMPONENT() then false;
4420 else true;
4421 end match;
4422 end isValidPackageElement;
4423
4424
4425 public function classIsExternalObject
4426 "returns true if a Class fulfills the requirements of an external object"
4427 input SCode.Element cl;
4428 output Boolean res;
4429 algorithm
4430 res := match cl
4431 local
4432 list<SCode.Element> els;
4433
4434 case SCode.CLASS(classDef=SCode.PARTS(elementLst=els))
4435 14454 then isExternalObject(els);
4436
4437 else false;
4438 end match;
4439 end classIsExternalObject;
4440
4441 public function isExternalObject
4442 "Returns true if the element list fulfills the condition of an External Object.
4443 An external object extends the builtinClass ExternalObject, and has two local
4444 functions, destructor and constructor. "
4445 input list<SCode.Element> els;
4446 output Boolean res;
4447 algorithm
4448
6/8
✓ Branch 1 taken 52401 times.
✓ Branch 2 taken 388652 times.
✓ Branch 4 taken 127 times.
✓ Branch 5 taken 52274 times.
✓ Branch 7 taken 127 times.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 127 times.
441053 res := if listLength(els) == 3 then
4449 hasExtendsOfExternalObject(els)
4450 and hasExternalObjectDestructor(els)
4451 and hasExternalObjectConstructor(els)
4452 else
4453 false;
4454 end isExternalObject;
4455
4456 protected function hasExtendsOfExternalObject
4457 "returns true if element list contains 'extends ExternalObject;'"
4458 input list<SCode.Element> inEls;
4459 output Boolean res;
4460 algorithm
4461 res:= match inEls
4462 local
4463 list<SCode.Element> els;
4464 Absyn.Path path;
4465 case {} then false;
4466 case SCode.EXTENDS(baseClassPath = path)::_
4467 guard( AbsynUtil.pathEqual(path, Absyn.IDENT("ExternalObject")) ) then true;
4468 156822 case _::els then hasExtendsOfExternalObject(els);
4469 end match;
4470 end hasExtendsOfExternalObject;
4471
4472 protected function hasExternalObjectDestructor
4473 "returns true if element list contains 'function destructor .. end destructor'"
4474 input list<SCode.Element> inEls;
4475 output Boolean res;
4476 algorithm
4477 res:= match inEls
4478 local list<SCode.Element> els;
4479 case SCode.CLASS(name="destructor")::_ then true;
4480 254 case _::els then hasExternalObjectDestructor(els);
4481 else false;
4482 end match;
4483 end hasExternalObjectDestructor;
4484
4485 protected function hasExternalObjectConstructor
4486 "returns true if element list contains 'function constructor ... end constructor'"
4487 input list<SCode.Element> inEls;
4488 output Boolean res;
4489 algorithm
4490 res:= match inEls
4491 local list<SCode.Element> els;
4492 case SCode.CLASS(name="constructor")::_ then true;
4493 127 case _::els then hasExternalObjectConstructor(els);
4494 else false;
4495 end match;
4496 end hasExternalObjectConstructor;
4497
4498 public function getExternalObjectDestructor
4499 "returns the class 'function destructor .. end destructor' from element list"
4500 input list<SCode.Element> inEls;
4501 output SCode.Element cl;
4502 algorithm
4503 cl:= match inEls
4504 local list<SCode.Element> els;
4505 case (cl as SCode.CLASS(name="destructor"))::_ then cl;
4506 124 case _::els then getExternalObjectDestructor(els);
4507 end match;
4508 end getExternalObjectDestructor;
4509
4510 public function getExternalObjectConstructor
4511 "returns the class 'function constructor ... end constructor' from element list"
4512 input list<SCode.Element> inEls;
4513 output SCode.Element cl;
4514 algorithm
4515 cl:= match inEls
4516 local list<SCode.Element> els;
4517 case (cl as SCode.CLASS(name="constructor"))::_ then cl;
4518 62 case _::els then getExternalObjectConstructor(els);
4519 end match;
4520 end getExternalObjectConstructor;
4521
4522 public function isInstantiableClassRestriction
4523 input SCode.Restriction inRestriction;
4524 output Boolean outIsInstantiable;
4525 algorithm
4526 outIsInstantiable := match inRestriction
4527 case SCode.R_CLASS() then true;
4528 case SCode.R_MODEL() then true;
4529 case SCode.R_RECORD() then true;
4530 case SCode.R_BLOCK() then true;
4531 case SCode.R_CONNECTOR() then true;
4532 case SCode.R_TYPE() then true;
4533 case SCode.R_ENUMERATION() then true;
4534 else false;
4535 end match;
4536 end isInstantiableClassRestriction;
4537
4538 public function isInitial
4539 input SCode.Initial inInitial;
4540 output Boolean isIn;
4541 algorithm
4542 isIn := match inInitial
4543 case SCode.INITIAL() then true;
4544 else false;
4545 end match;
4546 end isInitial;
4547
4548 public function checkSameRestriction
4549 "check if the restrictions are the same for redeclared classes"
4550 input SCode.Restriction inResNew;
4551 input SCode.Restriction inResOrig;
4552 input SourceInfo inInfoNew;
4553 input SourceInfo inInfoOrig;
4554 output SCode.Restriction outRes;
4555 output SourceInfo outInfo;
4556 algorithm
4557 (outRes, outInfo) := match inInfoOrig
4558 case _
4559 algorithm
4560 // todo: check if the restrictions are the same for redeclared classes
4561 then
4562 (inResNew, inInfoNew);
4563 end match;
4564 end checkSameRestriction;
4565
4566 public function setComponentName
4567 "Sets the name of a component element."
4568 input output SCode.Element element;
4569 input SCode.Ident name;
4570 algorithm
4571 () := match element
4572 case SCode.COMPONENT()
4573 algorithm
4574 997 element.name := name;
4575 then
4576 ();
4577 end match;
4578 end setComponentName;
4579
4580 public function isArrayComponent
4581 input SCode.Element inElement;
4582 output Boolean outIsArray;
4583 algorithm
4584 outIsArray := match inElement
4585 case SCode.COMPONENT(attributes = SCode.ATTR(arrayDims = _ :: _)) then true;
4586 else false;
4587 end match;
4588 end isArrayComponent;
4589
4590 public function isEmptyMod
4591 input SCode.Mod mod;
4592 output Boolean isEmpty;
4593 algorithm
4594 isEmpty := match mod
4595 case SCode.NOMOD() then true;
4596 else false;
4597 end match;
4598 end isEmptyMod;
4599
4600 function getConstrainingMod
4601 input SCode.Element element;
4602 output SCode.Mod mod;
4603 algorithm
4604 mod := match element
4605 case SCode.CLASS(prefixes = SCode.Prefixes.PREFIXES(replaceablePrefix =
4606 SCode.Replaceable.REPLACEABLE(cc = SOME(SCode.CONSTRAINCLASS(modifier = mod))))) then mod;
4607 case SCode.CLASS(classDef = SCode.DERIVED(modifications = mod)) then mod;
4608 case SCode.COMPONENT(prefixes = SCode.Prefixes.PREFIXES(replaceablePrefix =
4609 SCode.Replaceable.REPLACEABLE(cc = SOME(SCode.CONSTRAINCLASS(modifier = mod))))) then mod;
4610 case SCode.COMPONENT(modifications = mod) then mod;
4611 else SCode.NOMOD();
4612 end match;
4613 end getConstrainingMod;
4614
4615 function isEmptyClassDef
4616 input SCode.ClassDef cdef;
4617 output Boolean isEmpty;
4618 algorithm
4619 isEmpty := match cdef
4620 case SCode.PARTS()
4621
7/16
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 time.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 time.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 time.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✓ Branch 15 taken 1 time.
1 then listEmpty(cdef.elementLst) and
4622 listEmpty(cdef.normalEquationLst) and
4623 listEmpty(cdef.initialEquationLst) and
4624 listEmpty(cdef.normalAlgorithmLst) and
4625 listEmpty(cdef.initialAlgorithmLst) and
4626 isNone(cdef.externalDecl);
4627
4628 1 case SCode.CLASS_EXTENDS() then isEmptyClassDef(cdef.composition);
4629 ✗ case SCode.ENUMERATION() then listEmpty(cdef.enumLst);
4630 else true;
4631 end match;
4632 end isEmptyClassDef;
4633
4634 function stripCommentsFromProgram
4635 "Strips all annotations and/or comments from a program."
4636 input output SCode.Program program;
4637 input Boolean stripAnnotations;
4638 input Boolean stripComments;
4639 algorithm
4640 ✗ program := list(stripCommentsFromElement(e, stripAnnotations, stripComments) for e in program);
4641 end stripCommentsFromProgram;
4642
4643 function stripCommentsFromElement
4644 input output SCode.Element element;
4645 input Boolean stripAnn;
4646 input Boolean stripCmt;
4647 algorithm
4648 () := match element
4649 case SCode.EXTENDS()
4650 algorithm
4651 ✗ if stripAnn then
4652 ✗ element.ann := NONE();
4653 end if;
4654
4655 ✗ element.modifications := stripCommentsFromMod(element.modifications, stripAnn, stripCmt);
4656 then
4657 ();
4658
4659 case SCode.CLASS()
4660 algorithm
4661 ✗ element.classDef := stripCommentsFromClassDef(element.classDef, stripAnn, stripCmt);
4662 ✗ element.cmt := stripCommentsFromComment(element.cmt, stripAnn, stripCmt);
4663 then
4664 ();
4665
4666 case SCode.COMPONENT()
4667 algorithm
4668 ✗ element.modifications := stripCommentsFromMod(element.modifications, stripAnn, stripCmt);
4669 ✗ element.comment := stripCommentsFromComment(element.comment, stripAnn, stripCmt);
4670 then
4671 ();
4672
4673 else ();
4674 end match;
4675 end stripCommentsFromElement;
4676
4677 function stripCommentsFromMod
4678 input output SCode.Mod mod;
4679 input Boolean stripAnn;
4680 input Boolean stripCmt;
4681 algorithm
4682 () := match mod
4683 case SCode.MOD()
4684 algorithm
4685 ✗ mod.subModLst := list(stripCommentsFromSubMod(m, stripAnn, stripCmt) for m in mod.subModLst);
4686 then
4687 ();
4688
4689 case SCode.REDECL()
4690 algorithm
4691 ✗ mod.element := stripCommentsFromElement(mod.element, stripAnn, stripCmt);
4692 then
4693 ();
4694
4695 else ();
4696 end match;
4697 end stripCommentsFromMod;
4698
4699 function stripCommentsFromSubMod
4700 input output SCode.SubMod submod;
4701 input Boolean stripAnn;
4702 input Boolean stripCmt;
4703 algorithm
4704 ✗ submod.mod := stripCommentsFromMod(submod.mod, stripAnn, stripCmt);
4705 end stripCommentsFromSubMod;
4706
4707 function stripCommentsFromClassDef
4708 input output SCode.ClassDef cdef;
4709 input Boolean stripAnn;
4710 input Boolean stripCmt;
4711 algorithm
4712 cdef := match cdef
4713 local
4714 list<SCode.Element> el;
4715 list<SCode.Equation> eql, ieql;
4716 list<SCode.AlgorithmSection> alg, ialg;
4717 Option<SCode.ExternalDecl> ext;
4718
4719 case SCode.PARTS()
4720 algorithm
4721 ✗ el := list(stripCommentsFromElement(e, stripAnn, stripCmt) for e in cdef.elementLst);
4722 ✗ eql := list(stripCommentsFromEquation(eq, stripAnn, stripCmt) for eq in cdef.normalEquationLst);
4723 ✗ ieql := list(stripCommentsFromEquation(ieq, stripAnn, stripCmt) for ieq in cdef.initialEquationLst);
4724 ✗ alg := list(stripCommentsFromAlgorithm(a, stripAnn, stripCmt) for a in cdef.normalAlgorithmLst);
4725 ✗ ialg := list(stripCommentsFromAlgorithm(ia, stripAnn, stripCmt) for ia in cdef.initialAlgorithmLst);
4726 ✗ ext := stripCommentsFromExternalDecl(cdef.externalDecl, stripAnn, stripCmt);
4727 ✗ then
4728 SCode.PARTS(el, eql, ieql, alg, ialg, cdef.constraintLst, cdef.clsattrs, ext);
4729
4730 case SCode.CLASS_EXTENDS()
4731 algorithm
4732 ✗ cdef.modifications := stripCommentsFromMod(cdef.modifications, stripAnn, stripCmt);
4733 ✗ cdef.composition := stripCommentsFromClassDef(cdef.composition, stripAnn, stripCmt);
4734 then
4735 cdef;
4736
4737 case SCode.DERIVED()
4738 algorithm
4739 ✗ cdef.modifications := stripCommentsFromMod(cdef.modifications, stripAnn, stripCmt);
4740 then
4741 cdef;
4742
4743 case SCode.ENUMERATION()
4744 algorithm
4745 ✗ cdef.enumLst := list(stripCommentsFromEnum(e, stripAnn, stripCmt) for e in cdef.enumLst);
4746 then
4747 cdef;
4748
4749 else cdef;
4750 end match;
4751 end stripCommentsFromClassDef;
4752
4753 function stripCommentsFromEnum
4754 input output SCode.Enum enum;
4755 input Boolean stripAnn;
4756 input Boolean stripCmt;
4757 algorithm
4758 ✗ enum.comment := stripCommentsFromComment(enum.comment, stripAnn, stripCmt);
4759 end stripCommentsFromEnum;
4760
4761 function stripCommentsFromComment
4762 input output SCode.Comment cmt;
4763 input Boolean stripAnn;
4764 input Boolean stripCmt;
4765 algorithm
4766 ✗ if stripAnn then
4767 ✗ cmt.annotation_ := NONE();
4768 end if;
4769
4770 ✗ if stripCmt then
4771 ✗ cmt.comment := NONE();
4772 end if;
4773 end stripCommentsFromComment;
4774
4775 function stripCommentsFromExternalDecl
4776 input output Option<SCode.ExternalDecl> extDecl;
4777 input Boolean stripAnn;
4778 input Boolean stripCmt;
4779 protected
4780 SCode.ExternalDecl ext_decl;
4781 algorithm
4782 ✗ if isSome(extDecl) and stripAnn then
4783 ✗ SOME(ext_decl) := extDecl;
4784 ✗ ext_decl.annotation_ := NONE();
4785 extDecl := SOME(ext_decl);
4786 end if;
4787 end stripCommentsFromExternalDecl;
4788
4789 function stripCommentsFromEquation
4790 input output SCode.Equation eq;
4791 input Boolean stripAnn;
4792 input Boolean stripCmt;
4793 algorithm
4794 () := match eq
4795 case SCode.EQ_IF()
4796 algorithm
4797 ✗ eq.thenBranch := list(
4798 list(stripCommentsFromEquation(e, stripAnn, stripCmt) for e in branch)
4799 for branch in eq.thenBranch);
4800 ✗ eq.elseBranch := list(stripCommentsFromEquation(e, stripAnn, stripCmt) for e in eq.elseBranch);
4801 ✗ eq.comment := stripCommentsFromComment(eq.comment, stripAnn, stripCmt);
4802 then
4803 ();
4804
4805 case SCode.EQ_EQUALS()
4806 algorithm
4807 ✗ eq.comment := stripCommentsFromComment(eq.comment, stripAnn, stripCmt);
4808 then
4809 ();
4810
4811 case SCode.EQ_PDE()
4812 algorithm
4813 ✗ eq.comment := stripCommentsFromComment(eq.comment, stripAnn, stripCmt);
4814 then
4815 ();
4816
4817 case SCode.EQ_CONNECT()
4818 algorithm
4819 ✗ eq.comment := stripCommentsFromComment(eq.comment, stripAnn, stripCmt);
4820 then
4821 ();
4822
4823 case SCode.EQ_FOR()
4824 algorithm
4825 ✗ eq.eEquationLst := list(stripCommentsFromEquation(e, stripAnn, stripCmt) for e in eq.eEquationLst);
4826 ✗ eq.comment := stripCommentsFromComment(eq.comment, stripAnn, stripCmt);
4827 then
4828 ();
4829
4830 case SCode.EQ_WHEN()
4831 algorithm
4832 ✗ eq.eEquationLst := list(stripCommentsFromEquation(e, stripAnn, stripCmt) for e in eq.eEquationLst);
4833 ✗ eq.elseBranches := list(stripCommentsFromWhenEqBranch(b, stripAnn, stripCmt) for b in eq.elseBranches);
4834 ✗ eq.comment := stripCommentsFromComment(eq.comment, stripAnn, stripCmt);
4835 then
4836 ();
4837
4838 case SCode.EQ_ASSERT()
4839 algorithm
4840 ✗ eq.comment := stripCommentsFromComment(eq.comment, stripAnn, stripCmt);
4841 then
4842 ();
4843
4844 case SCode.EQ_TERMINATE()
4845 algorithm
4846 ✗ eq.comment := stripCommentsFromComment(eq.comment, stripAnn, stripCmt);
4847 then
4848 ();
4849
4850 case SCode.EQ_REINIT()
4851 algorithm
4852 ✗ eq.comment := stripCommentsFromComment(eq.comment, stripAnn, stripCmt);
4853 then
4854 ();
4855
4856 case SCode.EQ_NORETCALL()
4857 algorithm
4858 ✗ eq.comment := stripCommentsFromComment(eq.comment, stripAnn, stripCmt);
4859 then
4860 ();
4861
4862 end match;
4863 end stripCommentsFromEquation;
4864
4865 function stripCommentsFromWhenEqBranch
4866 input output tuple<Absyn.Exp, list<SCode.Equation>> branch;
4867 input Boolean stripAnn;
4868 input Boolean stripCmt;
4869 protected
4870 Absyn.Exp cond;
4871 list<SCode.Equation> body;
4872 algorithm
4873 ✗ (cond, body) := branch;
4874 ✗ body := list(stripCommentsFromEquation(e, stripAnn, stripCmt) for e in body);
4875 ✗ branch := (cond, body);
4876 end stripCommentsFromWhenEqBranch;
4877
4878 function stripCommentsFromAlgorithm
4879 input output SCode.AlgorithmSection alg;
4880 input Boolean stripAnn;
4881 input Boolean stripCmt;
4882 algorithm
4883 ✗ alg.statements := list(stripCommentsFromStatement(s, stripAnn, stripCmt) for s in alg.statements);
4884 end stripCommentsFromAlgorithm;
4885
4886 function stripCommentsFromStatement
4887 input output SCode.Statement stmt;
4888 input Boolean stripAnn;
4889 input Boolean stripCmt;
4890 algorithm
4891 () := match stmt
4892 case SCode.ALG_ASSIGN()
4893 algorithm
4894 ✗ stmt.comment := stripCommentsFromComment(stmt.comment, stripAnn, stripCmt);
4895 then
4896 ();
4897
4898 case SCode.ALG_IF()
4899 algorithm
4900 ✗ stmt.trueBranch := list(stripCommentsFromStatement(s, stripAnn, stripCmt) for s in stmt.trueBranch);
4901 ✗ stmt.elseIfBranch := list(stripCommentsFromStatementBranch(b, stripAnn, stripCmt) for b in stmt.elseIfBranch);
4902 ✗ stmt.elseBranch := list(stripCommentsFromStatement(s, stripAnn, stripCmt) for s in stmt.elseBranch);
4903 ✗ stmt.comment := stripCommentsFromComment(stmt.comment, stripAnn, stripCmt);
4904 then
4905 ();
4906
4907 case SCode.ALG_FOR()
4908 algorithm
4909 ✗ stmt.forBody := list(stripCommentsFromStatement(s, stripAnn, stripCmt) for s in stmt.forBody);
4910 ✗ stmt.comment := stripCommentsFromComment(stmt.comment, stripAnn, stripCmt);
4911 then
4912 ();
4913
4914 case SCode.ALG_PARFOR()
4915 algorithm
4916 ✗ stmt.parforBody := list(stripCommentsFromStatement(s, stripAnn, stripCmt) for s in stmt.parforBody);
4917 ✗ stmt.comment := stripCommentsFromComment(stmt.comment, stripAnn, stripCmt);
4918 then
4919 ();
4920
4921 case SCode.ALG_WHILE()
4922 algorithm
4923 ✗ stmt.whileBody := list(stripCommentsFromStatement(s, stripAnn, stripCmt) for s in stmt.whileBody);
4924 ✗ stmt.comment := stripCommentsFromComment(stmt.comment, stripAnn, stripCmt);
4925 then
4926 ();
4927
4928 case SCode.ALG_WHEN_A()
4929 algorithm
4930 ✗ stmt.branches := list(stripCommentsFromStatementBranch(b, stripAnn, stripCmt) for b in stmt.branches);
4931 ✗ stmt.comment := stripCommentsFromComment(stmt.comment, stripAnn, stripCmt);
4932 then
4933 ();
4934
4935 case SCode.Statement.ALG_ASSERT()
4936 algorithm
4937 ✗ stmt.comment := stripCommentsFromComment(stmt.comment, stripAnn, stripCmt);
4938 then
4939 ();
4940
4941 case SCode.ALG_TERMINATE()
4942 algorithm
4943 ✗ stmt.comment := stripCommentsFromComment(stmt.comment, stripAnn, stripCmt);
4944 then
4945 ();
4946
4947 case SCode.ALG_REINIT()
4948 algorithm
4949 ✗ stmt.comment := stripCommentsFromComment(stmt.comment, stripAnn, stripCmt);
4950 then
4951 ();
4952
4953 case SCode.ALG_NORETCALL()
4954 algorithm
4955 ✗ stmt.comment := stripCommentsFromComment(stmt.comment, stripAnn, stripCmt);
4956 then
4957 ();
4958
4959 case SCode.ALG_RETURN()
4960 algorithm
4961 ✗ stmt.comment := stripCommentsFromComment(stmt.comment, stripAnn, stripCmt);
4962 then
4963 ();
4964
4965 case SCode.ALG_BREAK()
4966 algorithm
4967 ✗ stmt.comment := stripCommentsFromComment(stmt.comment, stripAnn, stripCmt);
4968 then
4969 ();
4970
4971 case SCode.ALG_FAILURE()
4972 algorithm
4973 ✗ stmt.comment := stripCommentsFromComment(stmt.comment, stripAnn, stripCmt);
4974 then
4975 ();
4976
4977 case SCode.ALG_TRY()
4978 algorithm
4979 ✗ stmt.body := list(stripCommentsFromStatement(s, stripAnn, stripCmt) for s in stmt.body);
4980 ✗ stmt.elseBody := list(stripCommentsFromStatement(s, stripAnn, stripCmt) for s in stmt.elseBody);
4981 ✗ stmt.comment := stripCommentsFromComment(stmt.comment, stripAnn, stripCmt);
4982 then
4983 ();
4984
4985 case SCode.ALG_CONTINUE()
4986 algorithm
4987 ✗ stmt.comment := stripCommentsFromComment(stmt.comment, stripAnn, stripCmt);
4988 then
4989 ();
4990
4991 end match;
4992 end stripCommentsFromStatement;
4993
4994 function stripCommentsFromStatementBranch
4995 input output tuple<Absyn.Exp, list<SCode.Statement>> branch;
4996 input Boolean stripAnn;
4997 input Boolean stripCmt;
4998 protected
4999 Absyn.Exp cond;
5000 list<SCode.Statement> body;
5001 algorithm
5002 ✗ (cond, body) := branch;
5003 ✗ body := list(stripCommentsFromStatement(s, stripAnn, stripCmt) for s in body);
5004 ✗ branch := (cond, body);
5005 end stripCommentsFromStatementBranch;
5006
5007 function checkValidEnumLiteral
5008 input String inLiteral;
5009 input SourceInfo inInfo;
5010 algorithm
5011
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 898634 times.
898634 if listMember(inLiteral, {"quantity", "min", "max", "start", "fixed"}) then
5012 ✗ Error.addSourceMessage(Error.INVALID_ENUM_LITERAL, {inLiteral}, inInfo);
5013 ✗ fail();
5014 end if;
5015 end checkValidEnumLiteral;
5016
5017 public function isRedeclareElement
5018 "get the redeclare-as-element elements"
5019 input SCode.Element element;
5020 output Boolean isElement;
5021 algorithm
5022 isElement := match element
5023 // redeclare-as-element component
5024 case SCode.COMPONENT(prefixes = SCode.PREFIXES(redeclarePrefix = SCode.REDECLARE()))
5025 then true;
5026 // not redeclare class extends
5027 case SCode.CLASS(classDef = SCode.CLASS_EXTENDS())
5028 then false;
5029 // redeclare-as-element class!, not class extends
5030 case SCode.CLASS(prefixes = SCode.PREFIXES(redeclarePrefix = SCode.REDECLARE()))
5031 then true;
5032 else false;
5033 end match;
5034 end isRedeclareElement;
5035
5036
5037 public function mergeSCodeOptAnn
5038 input Option<SCode.Annotation> inModOuter;
5039 input Option<SCode.Annotation> inModInner;
5040 output Option<SCode.Annotation> outMod;
5041 algorithm
5042 outMod := match (inModOuter, inModInner)
5043 local
5044 SCode.Mod mod1, mod2, mod;
5045
5046 case (NONE(),_) then inModInner;
5047 case (_,NONE()) then inModOuter;
5048 case (SOME(SCode.ANNOTATION(mod1)),SOME(SCode.ANNOTATION(mod2)))
5049 algorithm
5050 ✗ mod := mergeSCodeMods(mod1,mod2);
5051 ✗ then SOME(SCode.ANNOTATION(mod));
5052 end match;
5053 end mergeSCodeOptAnn;
5054
5055 public function mergeSCodeMods
5056 input SCode.Mod inModOuter;
5057 input SCode.Mod inModInner;
5058 output SCode.Mod outMod;
5059 algorithm
5060 outMod := match (inModOuter, inModInner)
5061 local
5062 list<SCode.SubMod> subMods;
5063 Option<Absyn.Exp> binding;
5064
5065 case (SCode.NOMOD(), _) then inModInner;
5066 case (_, SCode.NOMOD()) then inModOuter;
5067
5068 case (SCode.MOD(),
5069 SCode.MOD())
5070 algorithm
5071 405 subMods := listAppend(inModOuter.subModLst, inModInner.subModLst);
5072
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 405 times.
✓ Branch 2 taken 405 times.
✗ Branch 3 not taken.
405 binding := if isSome(inModOuter.binding) then inModOuter.binding else inModInner.binding;
5073 405 then
5074 SCode.MOD(inModOuter.finalPrefix, inModOuter.eachPrefix, subMods,
5075 binding, inModOuter.comment, inModOuter.info);
5076
5077 end match;
5078 end mergeSCodeMods;
5079
5080 function hasNamedExternalCall
5081 input String name;
5082 input SCode.ClassDef def;
5083 output Boolean hasCall;
5084 algorithm
5085 hasCall := match def
5086 local
5087 String fn_name;
5088
5089 case SCode.PARTS(externalDecl = SOME(SCode.EXTERNALDECL(funcName = SOME(fn_name))))
5090
4/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 427 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 11 times.
444 then fn_name == name;
5091 747 case SCode.CLASS_EXTENDS() then hasNamedExternalCall(name, def.composition);
5092 else false;
5093 end match;
5094 end hasNamedExternalCall;
5095
5096 function classDefHasSections
5097 "Returns true if the class definition directly contains any sections,
5098 otherwise false."
5099 input SCode.ClassDef cdef;
5100 input Boolean checkExternal;
5101 output Boolean res;
5102 algorithm
5103 res := match cdef
5104 case SCode.ClassDef.PARTS()
5105
9/14
✓ Branch 0 taken 6854 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6854 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6852 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 6852 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 time.
✓ Branch 9 taken 6851 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 time.
✓ Branch 12 taken 1 time.
✗ Branch 13 not taken.
6854 then not (listEmpty(cdef.normalEquationLst) and
5106 listEmpty(cdef.initialEquationLst) and
5107 listEmpty(cdef.normalAlgorithmLst) and
5108 listEmpty(cdef.initialAlgorithmLst) and
5109 (if checkExternal then isNone(cdef.externalDecl) else true));
5110
5111 case SCode.ClassDef.CLASS_EXTENDS()
5112 ✗ then classDefHasSections(cdef.composition, checkExternal);
5113
5114 else false;
5115 end match;
5116 end classDefHasSections;
5117
5118 function mapElements
5119 "Applies a function to all elements in a list of elements, and recursively to
5120 all elements in those elements."
5121 input output list<SCode.Element> elements;
5122 input Func func;
5123
5124 partial function Func
5125 input output SCode.Element element;
5126 end Func;
5127 algorithm
5128 ✗ elements := list(mapElement(e, func) for e in elements);
5129 end mapElements;
5130
5131 function mapElement
5132 input output SCode.Element element;
5133 input Func func;
5134
5135 partial function Func
5136 input output SCode.Element element;
5137 end Func;
5138 protected
5139 SCode.ClassDef def;
5140 algorithm
5141 () := match element
5142 case SCode.Element.CLASS()
5143 algorithm
5144 ✗ def := mapElementsClassDef(element.classDef, func);
5145
5146 ✗ if not referenceEq(def, element.classDef) then
5147 ✗ element.classDef := def;
5148 end if;
5149 then
5150 ();
5151
5152 else ();
5153 end match;
5154
5155 ✗ element := func(element);
5156 end mapElement;
5157
5158 function mapElementsClassDef
5159 input output SCode.ClassDef classDef;
5160 input Func func;
5161
5162 partial function Func
5163 input output SCode.Element element;
5164 end Func;
5165 protected
5166 SCode.ClassDef def;
5167 algorithm
5168 () := match classDef
5169 case SCode.ClassDef.PARTS()
5170 algorithm
5171 ✗ classDef.elementLst := list(mapElement(e, func) for e in classDef.elementLst);
5172 then
5173 ();
5174
5175 case SCode.ClassDef.CLASS_EXTENDS()
5176 algorithm
5177 ✗ def := mapElementsClassDef(classDef.composition, func);
5178
5179 ✗ if not referenceEq(def, classDef.composition) then
5180 ✗ classDef.composition := def;
5181 end if;
5182 then
5183 ();
5184
5185 else ();
5186 end match;
5187 end mapElementsClassDef;
5188
5189 function mapEquationsList
5190 "Applies a function to all equations in a list of equations, and recursively
5191 to all equations in those equations."
5192 input output list<SCode.Equation> eql;
5193 input Func func;
5194
5195 partial function Func
5196 input output SCode.Equation eq;
5197 end Func;
5198 algorithm
5199
4/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 8 times.
9 eql := list(mapEquations(e, func) for e in eql);
5200 end mapEquationsList;
5201
5202 function mapEquations
5203 input output SCode.Equation eq;
5204 input Func func;
5205
5206 partial function Func
5207 input output SCode.Equation eq;
5208 end Func;
5209 algorithm
5210 () := match eq
5211 case SCode.Equation.EQ_IF()
5212 algorithm
5213 ✗ eq.thenBranch := list(mapEquationsList(b, func) for b in eq.thenBranch);
5214 ✗ eq.elseBranch := mapEquationsList(eq.elseBranch, func);
5215 then
5216 ();
5217
5218 case SCode.Equation.EQ_FOR()
5219 algorithm
5220 ✗ eq.eEquationLst := mapEquationsList(eq.eEquationLst, func);
5221 then
5222 ();
5223
5224 case SCode.Equation.EQ_WHEN()
5225 algorithm
5226 ✗ eq.eEquationLst := mapEquationsList(eq.eEquationLst, func);
5227 ✗ eq.elseBranches := list(
5228 (Util.tuple21(b), mapEquationsList(Util.tuple22(b), func)) for b in eq.elseBranches);
5229 then
5230 ();
5231
5232 else ();
5233 end match;
5234
5235
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 eq := func(eq);
5236 end mapEquations;
5237
5238 function mapEquationExps
5239 input output SCode.Equation eq;
5240 input Func func;
5241
5242 partial function Func
5243 input output Absyn.Exp exp;
5244 end Func;
5245 algorithm
5246 () := match eq
5247 case SCode.Equation.EQ_IF()
5248 algorithm
5249 ✗ eq.condition := list(func(e) for e in eq.condition);
5250 then
5251 ();
5252
5253 case SCode.Equation.EQ_EQUALS()
5254 algorithm
5255
1/2
✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
44 eq.expLeft := func(eq.expLeft);
5256
1/2
✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
44 eq.expRight := func(eq.expRight);
5257 then
5258 ();
5259
5260 case SCode.Equation.EQ_PDE()
5261 algorithm
5262 ✗ eq.expLeft := func(eq.expLeft);
5263 ✗ eq.expRight := func(eq.expRight);
5264 ✗ eq.domain := AbsynUtil.mapCrefExps(eq.domain, func);
5265 then
5266 ();
5267
5268 case SCode.Equation.EQ_CONNECT()
5269 algorithm
5270 ✗ eq.crefLeft := AbsynUtil.mapCrefExps(eq.crefLeft, func);
5271 ✗ eq.crefRight := AbsynUtil.mapCrefExps(eq.crefRight, func);
5272 then
5273 ();
5274
5275 case SCode.Equation.EQ_FOR()
5276 algorithm
5277
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
13 if isSome(eq.range) then
5278
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
26 eq.range := SOME(func(Util.getOption(eq.range)));
5279 end if;
5280 then
5281 ();
5282
5283 case SCode.Equation.EQ_WHEN()
5284 algorithm
5285 ✗ eq.condition := func(eq.condition);
5286 ✗ eq.elseBranches := list(Util.applyTuple21(b, func) for b in eq.elseBranches);
5287 then
5288 ();
5289
5290 case SCode.Equation.EQ_ASSERT()
5291 algorithm
5292
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 eq.condition := func(eq.condition);
5293
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 eq.message := func(eq.message);
5294
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 eq.level := func(eq.level);
5295 then
5296 ();
5297
5298 case SCode.Equation.EQ_TERMINATE()
5299 algorithm
5300 ✗ eq.message := func(eq.message);
5301 then
5302 ();
5303
5304 case SCode.Equation.EQ_REINIT()
5305 algorithm
5306 ✗ eq.cref := func(eq.cref);
5307 ✗ eq.expReinit := func(eq.expReinit);
5308 then
5309 ();
5310
5311 case SCode.Equation.EQ_NORETCALL()
5312 algorithm
5313 ✗ eq.exp := func(eq.exp);
5314 then
5315 ();
5316
5317 end match;
5318 end mapEquationExps;
5319
5320 function mapAlgorithmStatements
5321 "Applies a function to all statements in algorithm section, and recursively
5322 to all statements in those statements."
5323 input output SCode.AlgorithmSection alg;
5324 input Func func;
5325
5326 partial function Func
5327 input output SCode.Statement stmt;
5328 end Func;
5329 algorithm
5330 1 alg.statements := mapStatementsList(alg.statements, func);
5331 end mapAlgorithmStatements;
5332
5333 function mapStatementsList
5334 input output list<SCode.Statement> statements;
5335 input Func func;
5336
5337 partial function Func
5338 input output SCode.Statement stmt;
5339 end Func;
5340 algorithm
5341
4/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1 time.
2 statements := list(mapStatements(s, func) for s in statements);
5342 end mapStatementsList;
5343
5344 function mapStatements
5345 input output SCode.Statement stmt;
5346 input Func func;
5347
5348 partial function Func
5349 input output SCode.Statement stmt;
5350 end Func;
5351 algorithm
5352 () := match stmt
5353 case SCode.Statement.ALG_IF()
5354 algorithm
5355 ✗ stmt.trueBranch := mapStatementsList(stmt.trueBranch, func);
5356 ✗ stmt.elseIfBranch :=
5357 list((Util.tuple21(b), mapStatementsList(Util.tuple22(b), func)) for b in stmt.elseIfBranch);
5358 ✗ stmt.elseBranch := mapStatementsList(stmt.elseBranch, func);
5359 then
5360 ();
5361
5362 case SCode.Statement.ALG_FOR()
5363 algorithm
5364 ✗ stmt.forBody := mapStatementsList(stmt.forBody, func);
5365 then
5366 ();
5367
5368 case SCode.Statement.ALG_PARFOR()
5369 algorithm
5370 ✗ stmt.parforBody := mapStatementsList(stmt.parforBody, func);
5371 then
5372 ();
5373
5374 case SCode.Statement.ALG_WHILE()
5375 algorithm
5376 ✗ stmt.whileBody := mapStatementsList(stmt.whileBody, func);
5377 then
5378 ();
5379
5380 case SCode.Statement.ALG_WHEN_A()
5381 algorithm
5382 ✗ stmt.branches :=
5383 list((Util.tuple21(b), mapStatementsList(Util.tuple22(b), func)) for b in stmt.branches);
5384 then
5385 ();
5386
5387 case SCode.Statement.ALG_FAILURE()
5388 algorithm
5389 ✗ stmt.stmts := mapStatementsList(stmt.stmts, func);
5390 then
5391 ();
5392
5393 case SCode.Statement.ALG_TRY()
5394 algorithm
5395 ✗ stmt.body := mapStatementsList(stmt.body, func);
5396 ✗ stmt.elseBody := mapStatementsList(stmt.body, func);
5397 then
5398 ();
5399
5400 else ();
5401 end match;
5402
5403
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 stmt := func(stmt);
5404 end mapStatements;
5405
5406 function mapStatementExps
5407 "Applies a function to all expressions in a statement."
5408 input output SCode.Statement stmt;
5409 input Func func;
5410
5411 partial function Func
5412 input output Absyn.Exp exp;
5413 end Func;
5414 algorithm
5415 () := match stmt
5416 case SCode.Statement.ALG_ASSIGN()
5417 algorithm
5418
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 stmt.assignComponent := func(stmt.assignComponent);
5419
1/2
✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
32 stmt.value := func(stmt.value);
5420 then
5421 ();
5422
5423 case SCode.Statement.ALG_IF()
5424 algorithm
5425 ✗ stmt.boolExpr := func(stmt.boolExpr);
5426 ✗ stmt.elseIfBranch := list((func(Util.tuple21(b)), Util.tuple22(b)) for b in stmt.elseIfBranch);
5427 then
5428 ();
5429
5430 case SCode.Statement.ALG_FOR()
5431 algorithm
5432
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
13 if isSome(stmt.range) then
5433
1/2
✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
26 stmt.range := SOME(func(Util.getOption(stmt.range)));
5434 end if;
5435 then
5436 ();
5437
5438 case SCode.Statement.ALG_PARFOR()
5439 algorithm
5440 ✗ if isSome(stmt.range) then
5441 ✗ stmt.range := SOME(func(Util.getOption(stmt.range)));
5442 end if;
5443 then
5444 ();
5445
5446 case SCode.Statement.ALG_WHILE()
5447 algorithm
5448 ✗ stmt.boolExpr := func(stmt.boolExpr);
5449 then
5450 ();
5451
5452 case SCode.Statement.ALG_WHEN_A()
5453 algorithm
5454 ✗ stmt.branches := list((func(Util.tuple21(b)), Util.tuple22(b)) for b in stmt.branches);
5455 then
5456 ();
5457
5458 case SCode.Statement.ALG_ASSERT()
5459 algorithm
5460 ✗ stmt.condition := func(stmt.condition);
5461 ✗ stmt.message := func(stmt.message);
5462 ✗ stmt.level := func(stmt.level);
5463 then
5464 ();
5465
5466 case SCode.Statement.ALG_TERMINATE()
5467 algorithm
5468 ✗ stmt.message := func(stmt.message);
5469 then
5470 ();
5471
5472 case SCode.Statement.ALG_REINIT()
5473 algorithm
5474 ✗ stmt.cref := func(stmt.cref);
5475 ✗ stmt.newValue := func(stmt.newValue);
5476 then
5477 ();
5478
5479 case SCode.Statement.ALG_NORETCALL()
5480 algorithm
5481 ✗ stmt.exp := func(stmt.exp);
5482 then
5483 ();
5484
5485 else ();
5486 end match;
5487 end mapStatementExps;
5488
5489 function lookupModInMod
5490 "Looks up a modifier with the given name in the given modifier, or returns
5491 NOMOD() if no modifier is found."
5492 input String name;
5493 input SCode.Mod mod;
5494 output SCode.Mod outMod;
5495 algorithm
5496 outMod := match mod
5497 case SCode.Mod.MOD()
5498 algorithm
5499
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 for m in mod.subModLst loop
5500
3/4
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 28 times.
✓ Branch 4 taken 22 times.
50 if m.ident == name then
5501 28 outMod := m.mod;
5502 28 return;
5503 end if;
5504 end for;
5505 then
5506 SCode.Mod.NOMOD();
5507
5508 else SCode.Mod.NOMOD();
5509 end match;
5510 end lookupModInMod;
5511
5512 function isNonEmptyAlgorithm
5513 input SCode.AlgorithmSection alg;
5514 output Boolean res = not listEmpty(alg.statements);
5515 end isNonEmptyAlgorithm;
5516
5517 function onlyLiteralsInMod
5518 "Checks if the bindings in a modifier only contains literal expressions."
5519 input SCode.Mod mod;
5520 output Boolean onlyLiterals;
5521 algorithm
5522 onlyLiterals := match mod
5523 case SCode.Mod.MOD()
5524 algorithm
5525
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 168 times.
✓ Branch 2 taken 80 times.
✓ Branch 3 taken 88 times.
168 if isSome(mod.binding) then
5526 80 onlyLiterals := AbsynUtil.onlyLiteralsInExp(Util.getOption(mod.binding));
5527 else
5528 onlyLiterals := true;
5529 end if;
5530
5531
2/2
✓ Branch 0 taken 167 times.
✓ Branch 1 taken 1 time.
168 if onlyLiterals then
5532
2/2
✓ Branch 0 taken 138 times.
✓ Branch 1 taken 165 times.
303 for m in mod.subModLst loop
5533 138 onlyLiterals := onlyLiteralsInMod(m.mod);
5534
5535
2/2
✓ Branch 0 taken 136 times.
✓ Branch 1 taken 2 times.
138 if not onlyLiterals then
5536 break;
5537 end if;
5538 end for;
5539 end if;
5540 then
5541 onlyLiterals;
5542
5543 else true;
5544 end match;
5545 end onlyLiteralsInMod;
5546
5547 function transformPathedElementInProgram
5548 input Absyn.Path path;
5549 input Func func;
5550 input output SCode.Program program;
5551 output Boolean success;
5552
5553 partial function Func
5554 input output SCode.Element element;
5555 end Func;
5556 algorithm
5557 978 (program, success) := List.findMap(program,
5558 function transformPathedElementInElement(path = path, func = func));
5559 end transformPathedElementInProgram;
5560
5561 function transformPathedElementInElement
5562 input Absyn.Path path;
5563 input Func func;
5564 input output SCode.Element element;
5565 output Boolean success;
5566
5567 partial function Func
5568 input output SCode.Element element;
5569 end Func;
5570 protected
5571 SCode.ClassDef cdef;
5572 algorithm
5573 948 success := isElementNamed(AbsynUtil.pathFirstIdent(path), element);
5574
5575
2/2
✓ Branch 0 taken 893 times.
✓ Branch 1 taken 55 times.
948 if success then
5576
2/2
✓ Branch 1 taken 51 times.
✓ Branch 2 taken 4 times.
55 if AbsynUtil.pathIsIdent(path) then
5577
1/2
✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
51 element := func(element);
5578 elseif isClass(element) then
5579 4 (cdef, success) := transformPathedElementInClassDef(AbsynUtil.pathRest(path), func, getClassDef(element));
5580
5581
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if success then
5582 4 element := setClassDef(cdef, element);
5583 end if;
5584 end if;
5585 end if;
5586 end transformPathedElementInElement;
5587
5588 function transformPathedElementInClassDef
5589 input Absyn.Path path;
5590 input Func func;
5591 input output SCode.ClassDef cls;
5592 output Boolean success;
5593
5594 partial function Func
5595 input output SCode.Element element;
5596 end Func;
5597 protected
5598 list<SCode.Element> elems;
5599 SCode.ClassDef cdef;
5600 algorithm
5601 success := match cls
5602 case SCode.ClassDef.PARTS()
5603 algorithm
5604 4 (elems, success) := transformPathedElementInProgram(path, func, cls.elementLst);
5605
5606
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if success then
5607 4 cls.elementLst := elems;
5608 end if;
5609 4 then
5610 success;
5611
5612 case SCode.ClassDef.CLASS_EXTENDS()
5613 algorithm
5614 ✗ (cdef, success) := transformPathedElementInClassDef(path, func, cls.composition);
5615
5616 ✗ if success then
5617 ✗ cls.composition := cdef;
5618 end if;
5619 ✗ then
5620 success;
5621
5622 else false;
5623 end match;
5624 end transformPathedElementInClassDef;
5625
5626 public function makeMod
5627 input Boolean isFinal = false;
5628 input Boolean isEach = false;
5629 input list<SCode.SubMod> subMods = {};
5630 input Option<Absyn.Exp> binding = NONE();
5631 input Option<String> comment = NONE();
5632 input SourceInfo info = Absyn.dummyInfo;
5633 output SCode.Mod mod;
5634 algorithm
5635
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
6 mod := SCode.Mod.MOD(
5636 if isFinal then SCode.Final.FINAL() else SCode.Final.NOT_FINAL(),
5637 if isEach then SCode.Each.EACH() else SCode.Each.NOT_EACH(),
5638 subMods,
5639 binding,
5640 comment,
5641 info
5642 );
5643 end makeMod;
5644
5645 public function makeSingleAnnotation
5646 "Creates an annotation(name = value) annotation."
5647 input String name;
5648 input Absyn.Exp value;
5649 output SCode.Annotation ann;
5650 algorithm
5651 128 ann := SCode.Annotation.ANNOTATION(SCode.Mod.MOD(
5652 SCode.Final.NOT_FINAL(),
5653 SCode.Each.NOT_EACH(),
5654 {
5655 SCode.SubMod.NAMEMOD(
5656 name,
5657 SCode.Mod.MOD(
5658 SCode.Final.NOT_FINAL(),
5659 SCode.Each.NOT_EACH(),
5660 {},
5661 SOME(value),
5662 NONE(),
5663 Absyn.dummyInfo
5664 )
5665 )
5666 },
5667 NONE(),
5668 NONE(),
5669 Absyn.dummyInfo
5670 ));
5671 end makeSingleAnnotation;
5672
5673 public function setAnnotationInComment
5674 "Sets the value of an annotation in a comment. If the annotation doesn't already exist it's added."
5675 input String name;
5676 input Absyn.Exp value;
5677 input output SCode.Comment cmt;
5678 input Boolean replace = true "Whether to replace the value of an existing annotation or not";
5679 protected
5680 algorithm
5681
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
✓ Branch 2 taken 64 times.
✓ Branch 3 taken 2 times.
66 if isNone(cmt.annotation_) then
5682 64 cmt.annotation_ := SOME(makeSingleAnnotation(name, value));
5683 64 return;
5684 else
5685 4 cmt.annotation_ := SOME(setAnnotationValue(name, value, Util.getOption(cmt.annotation_), replace));
5686 end if;
5687 end setAnnotationInComment;
5688
5689 public function setAnnotationValue
5690 "Sets the value of an annotation. If the annotation doesn't already exist it's added."
5691 input String name;
5692 input Absyn.Exp value;
5693 input output SCode.Annotation ann;
5694 input Boolean replace = true "Whether to replace the value of an existing annotation or not";
5695 protected
5696 SCode.Mod mod;
5697 list<SCode.SubMod> submods;
5698 Boolean found;
5699
5700 function replace_mod
5701 input String name;
5702 input Absyn.Exp value;
5703 input Boolean replace;
5704 input output SCode.SubMod mod;
5705 output Boolean found;
5706 algorithm
5707
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
2 found := mod.ident == name;
5708
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if found and replace then
5709 ✗ mod.mod := setModifierBinding(SOME(value), mod.mod);
5710 end if;
5711 end replace_mod;
5712 algorithm
5713 () := match ann
5714 case SCode.Annotation.ANNOTATION(modification = mod as SCode.Mod.MOD())
5715 algorithm
5716
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
4 (submods, found) := List.findMap(mod.subModLst,
5717 function replace_mod(name = name, value = value, replace = replace));
5718
5719
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if not found then
5720 2 submods := SCode.SubMod.NAMEMOD(name, makeMod(binding = SOME(value))) :: submods;
5721 end if;
5722
5723 2 mod.subModLst := submods;
5724 2 ann.modification := mod;
5725 then
5726 ();
5727
5728 else ();
5729 end match;
5730 end setAnnotationValue;
5731
5732 annotation(__OpenModelica_Interface="frontend_dump");
5733 end SCodeUtil;
5734