Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 74.4% 1402 / 0 / 1885
Functions: -% 0 / 1 / 1
Branches: 62.4% 1038 / 0 / 1663

OMCompiler/Compiler/NFFrontEnd/NFExpression.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 uniontype NFExpression
37 protected
38 import Array;
39 import Util;
40 import Absyn;
41 import AbsynUtil;
42 import List;
43 import System;
44 import Flags;
45
46 import NFBackendExtension.{BackendInfo, VariableKind};
47 import Builtin = NFBuiltin;
48 import BuiltinCall = NFBuiltinCall;
49 import Ceval = NFCeval;
50 import ComplexType = NFComplexType;
51 import ExpandExp = NFExpandExp;
52 import Expression = NFExpression;
53 import Function = NFFunction;
54 import JSON;
55 import MetaModelica.Dangerous.*;
56 import NFPrefixes.{Variability, Purity};
57 import Prefixes = NFPrefixes;
58 import RangeIterator = NFRangeIterator;
59 import SimplifyExp = NFSimplifyExp;
60 import TypeCheck = NFTypeCheck;
61 import UnorderedSet;
62 import ValuesMake;
63 import Variable = NFVariable;
64
65 public
66 import Absyn.Path;
67 import BaseModelica;
68 import DAE;
69 import NFInstNode.InstNode;
70 import Operator = NFOperator;
71 import Subscript = NFSubscript;
72 import Dimension = NFDimension;
73 import Type = NFType;
74 import ComponentRef = NFComponentRef;
75 import Call = NFCall;
76 import Binding = NFBinding;
77 import NFClassTree.ClassTree;
78 import Class = NFClass;
79 import NFComponentRef.Origin;
80 import Values;
81 import Record = NFRecord;
82 import ClockKind = NFClockKind;
83 import ExpressionIterator = NFExpressionIterator;
84 import InstContext = NFInstContext;
85 import UnorderedMap;
86
87 record INTEGER
88 Integer value;
89 end INTEGER;
90
91 record REAL
92 Real value;
93 end REAL;
94
95 record STRING
96 String value;
97 end STRING;
98
99 record BOOLEAN
100 Boolean value;
101 end BOOLEAN;
102
103 record ENUM_LITERAL
104 Type ty;
105 String name;
106 Integer index;
107 end ENUM_LITERAL;
108
109 record CLKCONST "Clock constructors"
110 ClockKind clk "Clock kinds";
111 end CLKCONST;
112
113 record CREF
114 Type ty;
115 ComponentRef cref;
116 end CREF;
117
118 record TYPENAME "Represents a type used as a range, e.g. Boolean."
119 Type ty;
120 end TYPENAME;
121
122 record ARRAY
123 Type ty;
124 array<Expression> elements;
125 Boolean literal "True if the array is known to only contain literal expressions.";
126 end ARRAY;
127
128 record MATRIX "The array concatentation operator [a,b; c,d]; this should be removed during type-checking"
129 // Does not have a type since we only keep this operator before type-checking
130 list<list<Expression>> elements;
131 end MATRIX;
132
133 record RANGE
134 Type ty;
135 Expression start;
136 Option<Expression> step;
137 Expression stop;
138 end RANGE;
139
140 record TUPLE
141 Type ty;
142 list<Expression> elements;
143 end TUPLE;
144
145 record RECORD
146 Path path; // Maybe not needed since the type contains the name. Prefix?
147 Type ty;
148 list<Expression> elements;
149 end RECORD;
150
151 record CALL
152 Call call;
153 end CALL;
154
155 record SIZE
156 Expression exp;
157 Option<Expression> dimIndex;
158 end SIZE;
159
160 record END
161 end END;
162
163 record BINARY "Binary operations, e.g. a+4"
164 Expression exp1;
165 Operator operator;
166 Expression exp2;
167 end BINARY;
168
169 record UNARY "Unary operations, -(4x)"
170 Operator operator;
171 Expression exp;
172 end UNARY;
173
174 record LBINARY "Logical binary operations: and, or"
175 Expression exp1;
176 Operator operator;
177 Expression exp2;
178 end LBINARY;
179
180 record LUNARY "Logical unary operations: not"
181 Operator operator;
182 Expression exp;
183 end LUNARY;
184
185 record RELATION "Relation, e.g. a <= 0"
186 Expression exp1;
187 Operator operator;
188 Expression exp2;
189 Integer index "index for event codegen"; // TODO: remove me :)
190 end RELATION;
191
192 record MULTARY
193 "Multary expressions with the same operator, e.g. a+b+c
194 An empty list has to be interpreted as the neutral element of the operator space"
195 list<Expression> arguments "arguments that are chained with the operator (+, *)";
196 list<Expression> inv_arguments "arguments that are chained with the inverse operator (-, :)";
197 Operator operator "Can only be + or * (commutative)";
198 end MULTARY;
199
200 record IF
201 Type ty;
202 Expression condition;
203 Expression trueBranch;
204 Expression falseBranch;
205 end IF;
206
207 record CAST
208 Type ty;
209 Expression exp;
210 end CAST;
211
212 record BOX "MetaModelica boxed value"
213 Expression exp;
214 end BOX;
215
216 record UNBOX "MetaModelica value unboxing (similar to a cast)"
217 Expression exp;
218 Type ty;
219 end UNBOX;
220
221 record SUBSCRIPTED_EXP
222 Expression exp;
223 list<Subscript> subscripts;
224 Type ty;
225 Boolean split;
226 end SUBSCRIPTED_EXP;
227
228 record TUPLE_ELEMENT
229 Expression tupleExp;
230 Integer index;
231 Type ty;
232 end TUPLE_ELEMENT;
233
234 record RECORD_ELEMENT
235 Expression recordExp;
236 Integer index;
237 String fieldName;
238 Type ty;
239 end RECORD_ELEMENT;
240
241 record MUTABLE
242 Mutable<Expression> exp;
243 end MUTABLE;
244
245 record EMPTY
246 Type ty;
247 end EMPTY;
248
249 record PARTIAL_FUNCTION_APPLICATION
250 ComponentRef fn;
251 list<Expression> args;
252 list<String> argNames;
253 Type ty;
254 end PARTIAL_FUNCTION_APPLICATION;
255
256 record FILENAME
257 String filename;
258 end FILENAME;
259
260 record SHARED_LITERAL
261 "Before code generation, we make a pass that replaces constant literals
262 with a SHARED_LITERAL expression. Any immutable type can be shared:
263 basic MetaModelica types and Modelica strings are fine. There is no point
264 to share Real, Integer, Boolean or Enum though."
265 Integer index "A unique indexing that can be used to point to a single shared literal in generated code";
266 Expression exp "For printing strings, code generators that do not support this kind of literal, or for getting the type in case the code generator needs that";
267 end SHARED_LITERAL;
268
269 record INSTANCE_NAME
270 InstNode scope;
271 end INSTANCE_NAME;
272
273 function isArray
274 input Expression exp;
275 output Boolean isArray;
276 algorithm
277 isArray := match exp
278 case ARRAY() then true;
279 else false;
280 end match;
281 end isArray;
282
283 function isEmptyArray
284 input Expression exp;
285 output Boolean emptyArray;
286 algorithm
287 emptyArray := match exp
288
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 157906 times.
315812 case ARRAY() then arrayEmpty(exp.elements);
289 else false;
290 end match;
291 end isEmptyArray;
292
293 function isVector
294 input Expression exp;
295 output Boolean res;
296 algorithm
297 res := match exp
298 106427 case ARRAY() then Type.isVector(exp.ty);
299 else false;
300 end match;
301 end isVector;
302
303 function isCref
304 input Expression exp;
305 output Boolean isCref;
306 algorithm
307 isCref := match exp
308 case CREF() then true;
309 else false;
310 end match;
311 end isCref;
312
313 function isFunctionInputCref
314 input Expression exp;
315 output Boolean res;
316 algorithm
317 res := match exp
318 294 case CREF() then ComponentRef.isInput(ComponentRef.last(exp.cref));
319 else false;
320 end match;
321 end isFunctionInputCref;
322
323 function isWildCref
324 input Expression exp;
325 output Boolean wild;
326 algorithm
327 wild := match exp
328 case CREF(cref = ComponentRef.WILD()) then true;
329 else false;
330 end match;
331 end isWildCref;
332
333 function isCall
334 input Expression exp;
335 output Boolean isCall;
336 algorithm
337 isCall := match exp
338 case CALL() then true;
339 else false;
340 end match;
341 end isCall;
342
343 function isImpureCall
344 input Expression exp;
345 output Boolean isImpure;
346 algorithm
347 isImpure := match exp
348 35201 case CALL() then Call.isImpure(exp.call);
349 else false;
350 end match;
351 end isImpureCall;
352
353 function isExternalCall
354 input Expression exp;
355 output Boolean res;
356 algorithm
357 res := match exp
358 28522 case CALL() then Call.isExternal(exp.call);
359 else false;
360 end match;
361 end isExternalCall;
362
363 function isCallNamed
364 input Expression exp;
365 input String name;
366 output Boolean res;
367 algorithm
368 res := match exp
369 14666 case CALL() then Call.isNamed(exp.call, name);
370 else false;
371 end match;
372 end isCallNamed;
373
374 function isConnectionCall
375 input Expression exp;
376 output Boolean isConnection;
377 algorithm
378 isConnection := match exp
379 case CALL()
380
6/6
✓ Branch 1 taken 486 times.
✓ Branch 2 taken 15 times.
✓ Branch 4 taken 480 times.
✓ Branch 5 taken 6 times.
✓ Branch 7 taken 5 times.
✓ Branch 8 taken 475 times.
501 then Call.isConnectionsOperator(exp.call) or
381 Call.isStreamOperator(exp.call) or
382 Call.isCardinality(exp.call);
383 else false;
384 end match;
385 end isConnectionCall;
386
387 function isTrue
388 input Expression exp;
389 output Boolean isTrue;
390 algorithm
391 isTrue := match exp
392 case BOOLEAN(true) then true;
393 else false;
394 end match;
395 end isTrue;
396
397 function isAllTrue
398 input Expression exp;
399 output Boolean isTrue;
400 algorithm
401 isTrue := match exp
402 local
403 Expression e;
404 case BOOLEAN(true) then true;
405 45 case ARRAY() then Array.all(exp.elements, isAllTrue);
406 825 case CALL(call = Call.TYPED_ARRAY_CONSTRUCTOR(exp = e)) then isAllTrue(e);
407 else false;
408 end match;
409 end isAllTrue;
410
411 function isFalse
412 input Expression exp;
413 output Boolean isTrue;
414 algorithm
415 isTrue := match exp
416 case BOOLEAN(false) then true;
417 else false;
418 end match;
419 end isFalse;
420
421 function isTrivialCref
422 input Expression exp;
423 output Boolean b;
424 algorithm
425 b := match exp
426 case CREF() then true;
427 case UNARY(exp = CREF()) then true;
428 case LUNARY(exp = CREF()) then true;
429 else false;
430 end match;
431 end isTrivialCref;
432
433 function hash
434 input Expression exp;
435 output Integer hash = hashContinue(exp, Util.HASH_SEED);
436 end hash;
437
438 function hashContinue
439 input Expression exp;
440 input output Integer hash;
441 algorithm
442 hash := match exp
443 local
444 Absyn.Path path;
445
446 967 case INTEGER() then intHashDjb2Continue(exp.value, hash);
447 8229 case REAL() then stringHashDjb2Continue(realString(exp.value), hash);
448 4266 case STRING() then stringHashDjb2Continue(exp.value, hash);
449 ✗ case BOOLEAN() then stringHashDjb2Continue(boolString(exp.value), hash);
450
451 case ENUM_LITERAL(ty = Type.ENUMERATION(typePath = path))
452 algorithm
453 ✗ hash := AbsynUtil.pathHashContinue(path, hash);
454 ✗ hash := stringHashDjb2Continue(".", hash);
455 ✗ hash := stringHashDjb2Continue(exp.name, hash);
456 then hash;
457
458 ✗ case CLKCONST() then ClockKind.hashContinue(exp.clk, hash);
459 56795 case CREF() then ComponentRef.hashContinue(exp.cref, false, hash);
460 ✗ case TYPENAME() then Type.hashContinue(Type.arrayElementType(exp.ty), hash);
461
462 case ARRAY()
463 algorithm
464 859 hash := stringHashDjb2Continue("{", hash);
465
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 859 times.
✓ Branch 3 taken 4058 times.
✓ Branch 4 taken 859 times.
5776 for e in exp.elements loop
466 4058 hash := hashContinue(e, hash);
467 4058 hash := stringHashDjb2Continue(", ", hash); // trailing comma, don't care...
468 end for;
469 859 hash := stringHashDjb2Continue("}", hash);
470 then hash;
471
472 case MATRIX()
473 algorithm
474 ✗ hash := stringHashDjb2Continue("[", hash);
475 ✗ for el in exp.elements loop
476 ✗ for e in el loop
477 ✗ hash := hashContinue(e, hash);
478 ✗ hash := stringHashDjb2Continue(", ", hash); // trailing comma, don't care...
479 end for;
480 ✗ hash := stringHashDjb2Continue("; ", hash); // trailing semicolon, don't care...
481 end for;
482 ✗ hash := stringHashDjb2Continue("]", hash);
483 then hash;
484
485 case RANGE()
486 algorithm
487 ✗ hash := hashContinue(exp.start, hash);
488 ✗ hash := stringHashDjb2Continue(":", hash);
489 ✗ if isSome(exp.step) then
490 ✗ hash := hashContinue(Util.getOption(exp.step), hash);
491 ✗ hash := stringHashDjb2Continue(":", hash);
492 end if;
493 ✗ hash := hashContinue(exp.stop, hash);
494 then hash;
495
496 case TUPLE()
497 algorithm
498 4 hash := stringHashDjb2Continue("(", hash);
499
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
20 for e in exp.elements loop
500 16 hash := hashContinue(e, hash);
501 16 hash := stringHashDjb2Continue(", ", hash); // trailing comma, don't care...
502 end for;
503 4 hash := stringHashDjb2Continue(")", hash);
504 then hash;
505
506 case RECORD()
507 algorithm
508 62 hash := AbsynUtil.pathHashContinue(exp.path, hash);
509 62 hash := stringHashDjb2Continue("(", hash);
510
2/2
✓ Branch 0 taken 604 times.
✓ Branch 1 taken 62 times.
666 for e in exp.elements loop
511 604 hash := hashContinue(e, hash);
512 604 hash := stringHashDjb2Continue(", ", hash); // trailing comma, don't care...
513 end for;
514 62 hash := stringHashDjb2Continue(")", hash);
515 then hash;
516
517 3757 case CALL() then stringHashDjb2Continue(Call.toString(exp.call), hash); // TODO use Call.hashContinue
518
519 case SIZE()
520 algorithm
521 ✗ hash := stringHashDjb2Continue("size(", hash);
522 ✗ hash := hashContinue(exp.exp, hash);
523 ✗ if isSome(exp.dimIndex) then
524 ✗ hash := stringHashDjb2Continue(", ", hash);
525 ✗ hash := hashContinue(Util.getOption(exp.dimIndex), hash);
526 end if;
527 ✗ hash := stringHashDjb2Continue(")", hash);
528 then hash;
529
530 ✗ case END() then stringHashDjb2Continue("end", hash);
531
532 case BINARY()
533 algorithm
534 6236 hash := hashContinue(exp.exp1, hash);
535 6236 hash := stringHashDjb2Continue(Operator.symbol(exp.operator), hash);
536 6236 hash := hashContinue(exp.exp2, hash);
537 then hash;
538
539 case UNARY()
540 algorithm
541 204 hash := stringHashDjb2Continue(Operator.symbol(exp.operator, ""), hash);
542 204 hash := hashContinue(exp.exp, hash);
543 then hash;
544
545 case LBINARY()
546 algorithm
547 ✗ hash := hashContinue(exp.exp1, hash);
548 ✗ hash := stringHashDjb2Continue(Operator.symbol(exp.operator), hash);
549 ✗ hash := hashContinue(exp.exp2, hash);
550 then hash;
551
552 case LUNARY()
553 algorithm
554 ✗ hash := stringHashDjb2Continue(Operator.symbol(exp.operator, ""), hash);
555 ✗ hash := stringHashDjb2Continue(" ", hash);
556 ✗ hash := hashContinue(exp.exp, hash);
557 then hash;
558
559 case RELATION()
560 algorithm
561 317 hash := hashContinue(exp.exp1, hash);
562 317 hash := stringHashDjb2Continue(Operator.symbol(exp.operator), hash);
563 317 hash := hashContinue(exp.exp2, hash);
564 then hash;
565
566 case MULTARY()
567 algorithm
568 11906 hash := stringHashDjb2Continue("(", hash);
569
2/2
✓ Branch 0 taken 21779 times.
✓ Branch 1 taken 11906 times.
33685 for e in exp.arguments loop
570 21779 hash := stringHashDjb2Continue(Operator.symbol(exp.operator), hash);
571 21779 hash := hashContinue(e, hash);
572 end for;
573 11906 hash := stringHashDjb2Continue(")", hash);
574 11906 hash := stringHashDjb2Continue(Operator.symbol(Operator.invert(exp.operator)), hash);
575 11906 hash := stringHashDjb2Continue("(", hash);
576
2/2
✓ Branch 0 taken 2594 times.
✓ Branch 1 taken 11906 times.
14500 for e in exp.inv_arguments loop
577 2594 hash := stringHashDjb2Continue(Operator.symbol(exp.operator), hash);
578 2594 hash := hashContinue(e, hash);
579 end for;
580 11906 hash := stringHashDjb2Continue(")", hash);
581 then hash;
582
583 case IF()
584 algorithm
585 329 hash := stringHashDjb2Continue("if ", hash);
586 329 hash := hashContinue(exp.condition, hash);
587 329 hash := stringHashDjb2Continue(" then ", hash);
588 329 hash := hashContinue(exp.trueBranch, hash);
589 329 hash := stringHashDjb2Continue(" else ", hash);
590 329 hash := hashContinue(exp.falseBranch, hash);
591 then hash;
592
593 case CAST()
594 algorithm
595 183 hash := stringHashDjb2Continue("CAST(", hash);
596 183 hash := Type.hashContinue(exp.ty, hash);
597 183 hash := stringHashDjb2Continue(", ", hash);
598 183 hash := hashContinue(exp.exp, hash);
599 183 hash := stringHashDjb2Continue(")", hash);
600 then hash;
601
602 case BOX()
603 algorithm
604 ✗ hash := stringHashDjb2Continue("BOX(", hash);
605 ✗ hash := hashContinue(exp.exp, hash);
606 ✗ hash := stringHashDjb2Continue(")", hash);
607 then hash;
608
609 case UNBOX()
610 algorithm
611 ✗ hash := stringHashDjb2Continue("UNBOX(", hash);
612 ✗ hash := hashContinue(exp.exp, hash);
613 ✗ hash := stringHashDjb2Continue(")", hash);
614 then hash;
615
616 case SUBSCRIPTED_EXP()
617 algorithm
618 129 hash := stringHashDjb2Continue("(", hash);
619 129 hash := hashContinue(exp.exp, hash);
620 129 hash := stringHashDjb2Continue(")[", hash);
621
2/2
✓ Branch 0 taken 129 times.
✓ Branch 1 taken 129 times.
258 for sub in exp.subscripts loop
622 129 hash := Subscript.hashContinue(sub, hash);
623 129 hash := stringHashDjb2Continue(", ", hash); // trailing comma, don't care...
624 end for;
625 129 hash := stringHashDjb2Continue("]", hash);
626 then hash;
627
628 case TUPLE_ELEMENT()
629 algorithm
630 ✗ hash := hashContinue(exp.tupleExp, hash);
631 ✗ hash := stringHashDjb2Continue("[", hash);
632 ✗ hash := stringHashDjb2Continue(intString(exp.index), hash);
633 ✗ hash := stringHashDjb2Continue("]", hash);
634 then hash;
635
636 case RECORD_ELEMENT()
637 algorithm
638 59 hash := stringHashDjb2Continue("(", hash);
639 59 hash := hashContinue(exp.recordExp, hash);
640 59 hash := stringHashDjb2Continue(").", hash);
641 59 hash := stringHashDjb2Continue(exp.fieldName, hash);
642 then hash;
643
644 ✗ case MUTABLE() then hashContinue(Mutable.access(exp.exp), hash);
645 ✗ case EMPTY() then stringHashDjb2Continue("#EMPTY#", hash);
646
647 case PARTIAL_FUNCTION_APPLICATION()
648 algorithm
649 ✗ hash := stringHashDjb2Continue("function ", hash);
650 ✗ hash := ComponentRef.hashContinue(exp.fn, false, hash);
651 ✗ hash := stringHashDjb2Continue("(", hash);
652 //list(n + " = " + toString(a) threaded for a in exp.args, n in exp.argNames)
653 ✗ for n in exp.argNames loop
654 ✗ hash := stringHashDjb2Continue(n, hash);
655 ✗ hash := stringHashDjb2Continue(", ", hash); // trailing comma, don't care...
656 end for;
657 ✗ hash := stringHashDjb2Continue(" = ", hash);
658 ✗ for a in exp.args loop
659 ✗ hash := hashContinue(a, hash);
660 ✗ hash := stringHashDjb2Continue(", ", hash); // trailing comma, don't care...
661 end for;
662 ✗ hash := stringHashDjb2Continue(")", hash);
663 then hash;
664
665 ✗ case FILENAME() then stringHashDjb2Continue(exp.filename, hash);
666
667 case SHARED_LITERAL()
668 algorithm
669 346 hash := stringHashDjb2Continue("LITERAL(", hash);
670 346 hash := stringHashDjb2Continue(intString(exp.index), hash);
671 346 hash := stringHashDjb2Continue(", ", hash);
672 346 hash := hashContinue(exp.exp, hash);
673 346 hash := stringHashDjb2Continue(")", hash);
674 then hash;
675
676 ✗ case INSTANCE_NAME() then stringHashDjb2Continue("getInstanceName()", hash);
677 else hash;
678 end match;
679 end hashContinue;
680
681 function isEqual
682 "Returns true if the two expressions are equal, otherwise false."
683 input Expression exp1;
684 input Expression exp2;
685 output Boolean isEqual;
686 algorithm
687 313055 isEqual := 0 == compare(exp1, exp2);
688 end isEqual;
689
690 function compare
691 "Checks whether two expressions are equal, and returns 0 if they are.
692 If the first expression is 'less' than the second it returns an integer
693 less than 0, otherwise an integer greater than 0."
694 input Expression exp1;
695 input Expression exp2;
696 output Integer comp;
697 algorithm
698 // Check if the expressions are the same object.
699
2/2
✓ Branch 0 taken 18073 times.
✓ Branch 1 taken 373145 times.
391218 if referenceEq(exp1, exp2) then
700 comp := 0;
701 18073 return;
702 end if;
703
704 // Return false if the expressions are of different kinds.
705 373145 comp := Util.intCompare(valueConstructor(exp1), valueConstructor(exp2));
706
2/2
✓ Branch 0 taken 128448 times.
✓ Branch 1 taken 244697 times.
373145 if comp <> 0 then
707 128448 return;
708 end if;
709
710 comp := match exp1
711 local
712 Integer i;
713 Real r;
714 String s;
715 Boolean b;
716 ComponentRef cr;
717 Type ty;
718 list<Expression> expl, inv_expl;
719 Expression e1, e2, e3;
720 Option<Expression> oe;
721 Path p;
722 Operator op;
723 Call c;
724 list<Subscript> subs;
725 ClockKind clk;
726 Mutable<Expression> me;
727 list<list<Expression>> mat;
728 array<Expression> arr;
729 InstNode node;
730
731 case INTEGER()
732 algorithm
733
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 112920 times.
112920 INTEGER(value = i) := exp2;
734 112920 then
735 Util.intCompare(exp1.value, i);
736
737 case REAL()
738 algorithm
739
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4358 times.
4358 REAL(value = r) := exp2;
740 4358 then
741 Util.realCompare(exp1.value, r);
742
743 case STRING()
744 algorithm
745
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3503 times.
3503 STRING(value = s) := exp2;
746 3503 then
747 stringCompare(exp1.value, s);
748
749 case BOOLEAN()
750 algorithm
751
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 BOOLEAN(value = b) := exp2;
752 52 then
753 Util.boolCompare(exp1.value, b);
754
755 case ENUM_LITERAL()
756 algorithm
757
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 231 times.
231 ENUM_LITERAL(ty = ty, index = i) := exp2;
758 231 comp := AbsynUtil.pathCompare(Type.enumName(exp1.ty), Type.enumName(ty));
759
760
1/2
✓ Branch 0 taken 231 times.
✗ Branch 1 not taken.
231 if comp == 0 then
761 231 comp := Util.intCompare(exp1.index, i);
762 end if;
763 then
764 comp;
765
766 case CLKCONST()
767 algorithm
768 ✗ CLKCONST(clk) := exp2;
769 ✗ then
770 ClockKind.compare(exp1.clk, clk);
771
772 case CREF()
773 algorithm
774
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 67245 times.
67245 CREF(cref = cr) := exp2;
775 67245 then
776 ComponentRef.compare(exp1.cref, cr);
777
778 case TYPENAME()
779 algorithm
780 ✗ TYPENAME(ty = ty) := exp2;
781 ✗ then
782 valueCompare(exp1.ty, ty);
783
784 case ARRAY()
785 algorithm
786
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1167 times.
1167 ARRAY(ty = ty, elements = arr) := exp2;
787 1167 comp := valueCompare(ty, exp1.ty);
788
2/2
✓ Branch 0 taken 1161 times.
✓ Branch 1 taken 6 times.
1167 then
789 if comp == 0 then Array.compare(exp1.elements, arr, compare) else comp;
790
791 case MATRIX()
792 algorithm
793 ✗ MATRIX(elements = mat) := exp2;
794 ✗ then
795 List.compare(exp1.elements, mat, function List.compare(compareFn = compare));
796
797 case RANGE()
798 algorithm
799
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 338 times.
338 RANGE(start = e1, step = oe, stop = e2) := exp2;
800 338 comp := compare(exp1.start, e1);
801
2/2
✓ Branch 0 taken 325 times.
✓ Branch 1 taken 13 times.
338 if comp == 0 then
802 325 comp := compare(exp1.stop, e2);
803
2/2
✓ Branch 0 taken 321 times.
✓ Branch 1 taken 4 times.
325 if comp == 0 then
804 321 comp := compareOpt(exp1.step, oe);
805 end if;
806 end if;
807 then
808 comp;
809
810 case TUPLE()
811 algorithm
812
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 TUPLE(elements = expl) := exp2;
813 3 then
814 List.compare(exp1.elements, expl, compare);
815
816 case RECORD()
817 algorithm
818
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
73 RECORD(path = p, elements = expl) := exp2;
819 73 comp := AbsynUtil.pathCompare(exp1.path, p);
820
1/2
✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
73 then
821 if comp == 0 then List.compare(exp1.elements, expl, compare) else comp;
822
823 case CALL()
824 algorithm
825
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2194 times.
2194 CALL(call = c) := exp2;
826 2194 then
827 Call.compare(exp1.call, c);
828
829 case SIZE()
830 algorithm
831
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 125 times.
125 SIZE(exp = e1, dimIndex = oe) := exp2;
832 125 comp := compareOpt(exp1.dimIndex, oe);
833
2/2
✓ Branch 0 taken 124 times.
✓ Branch 1 taken 1 time.
125 then
834 if comp == 0 then compare(exp1.exp, e1) else comp;
835
836 case END() then 0;
837
838 case MULTARY()
839 algorithm
840
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7113 times.
7113 MULTARY(arguments = expl, inv_arguments = inv_expl, operator = op) := exp2;
841 7113 comp := Operator.compare(exp1.operator, op);
842
2/2
✓ Branch 0 taken 7077 times.
✓ Branch 1 taken 36 times.
7113 if comp == 0 then
843 7077 comp := compareList(exp1.arguments, expl);
844 end if;
845
2/2
✓ Branch 0 taken 6910 times.
✓ Branch 1 taken 203 times.
7113 if comp == 0 then
846 6910 comp := compareList(exp1.inv_arguments, inv_expl);
847 end if;
848 then
849 comp;
850
851 case BINARY()
852 algorithm
853
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43774 times.
43774 BINARY(exp1 = e1, operator = op, exp2 = e2) := exp2;
854 43774 comp := Operator.compare(exp1.operator, op);
855
2/2
✓ Branch 0 taken 29569 times.
✓ Branch 1 taken 14205 times.
43774 if comp == 0 then
856 29569 comp := compare(exp1.exp1, e1);
857
2/2
✓ Branch 0 taken 1509 times.
✓ Branch 1 taken 28060 times.
29569 if comp == 0 then
858 1509 comp := compare(exp1.exp2, e2);
859 end if;
860 end if;
861 then
862 comp;
863
864 case UNARY()
865 algorithm
866
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 568 times.
568 UNARY(operator = op, exp = e1) := exp2;
867 568 comp := Operator.compare(exp1.operator, op);
868
1/2
✓ Branch 0 taken 568 times.
✗ Branch 1 not taken.
568 then
869 if comp == 0 then compare(exp1.exp, e1) else comp;
870
871 case LBINARY()
872 algorithm
873
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
64 LBINARY(exp1 = e1, operator = op, exp2 = e2) := exp2;
874 64 comp := Operator.compare(exp1.operator, op);
875
1/2
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
64 if comp == 0 then
876 64 comp := compare(exp1.exp1, e1);
877
1/2
✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
64 if comp == 0 then
878 64 comp := compare(exp1.exp2, e2);
879 end if;
880 end if;
881 then
882 comp;
883
884 case LUNARY()
885 algorithm
886
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 LUNARY(operator = op, exp = e1) := exp2;
887 21 comp := Operator.compare(exp1.operator, op);
888
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 then
889 if comp == 0 then compare(exp1.exp, e1) else comp;
890
891 case RELATION()
892 algorithm
893
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 246 times.
246 RELATION(exp1 = e1, operator = op, exp2 = e2) := exp2;
894 246 comp := Operator.compare(exp1.operator, op);
895
2/2
✓ Branch 0 taken 223 times.
✓ Branch 1 taken 23 times.
246 if comp == 0 then
896 223 comp := compare(exp1.exp1, e1);
897
2/2
✓ Branch 0 taken 221 times.
✓ Branch 1 taken 2 times.
223 if comp == 0 then
898 221 comp := compare(exp1.exp2, e2);
899 end if;
900 end if;
901 then
902 comp;
903
904 case IF()
905 algorithm
906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 157 times.
157 IF(condition = e1, trueBranch = e2, falseBranch = e3) := exp2;
907 157 comp := compare(exp1.condition, e1);
908
2/2
✓ Branch 0 taken 130 times.
✓ Branch 1 taken 27 times.
157 if comp == 0 then
909 130 comp := compare(exp1.trueBranch, e2);
910
1/2
✓ Branch 0 taken 130 times.
✗ Branch 1 not taken.
130 if comp == 0 then
911 130 comp := compare(exp1.falseBranch, e3);
912 end if;
913 end if;
914 then
915 comp;
916
917 case CAST()
918 algorithm
919 e1 := match exp2
920 case CAST(exp = e1) then e1;
921 case e1 then e1;
922 end match;
923 150 then
924 compare(exp1.exp, e1);
925
926 case BOX()
927 algorithm
928
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 BOX(exp = e2) := exp2;
929 65 then
930 compare(exp1.exp, e2);
931
932 case UNBOX()
933 algorithm
934 ✗ UNBOX(exp = e1) := exp2;
935 ✗ then
936 compare(exp1.exp, e1);
937
938 case SUBSCRIPTED_EXP()
939 algorithm
940
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 89 times.
89 SUBSCRIPTED_EXP(exp = e1, subscripts = subs) := exp2;
941 89 comp := compare(exp1.exp, e1);
942
943
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 43 times.
89 if comp == 0 then
944 46 comp := Subscript.compareList(exp1.subscripts, subs);
945 end if;
946 then
947 comp;
948
949 case TUPLE_ELEMENT()
950 algorithm
951 ✗ TUPLE_ELEMENT(tupleExp = e1, index = i) := exp2;
952 ✗ comp := Util.intCompare(exp1.index, i);
953
954 ✗ if comp == 0 then
955 ✗ comp := compare(exp1.tupleExp, e1);
956 end if;
957 then
958 comp;
959
960 case RECORD_ELEMENT()
961 algorithm
962
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 RECORD_ELEMENT(recordExp = e1, index = i) := exp2;
963 60 comp := Util.intCompare(exp1.index, i);
964
965
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 if comp == 0 then
966 60 comp := compare(exp1.recordExp, e1);
967 end if;
968 then
969 comp;
970
971 case MUTABLE()
972 algorithm
973 ✗ MUTABLE(exp = me) := exp2;
974 ✗ then
975 compare(Mutable.access(exp1.exp), Mutable.access(me));
976
977 case SHARED_LITERAL()
978 algorithm
979
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 158 times.
158 SHARED_LITERAL(exp = e1) := exp2;
980 158 then
981 compare(exp1.exp, e1);
982
983 case EMPTY()
984 algorithm
985 ✗ EMPTY(ty = ty) := exp2;
986 ✗ then
987 valueCompare(exp1.ty, ty);
988
989 case PARTIAL_FUNCTION_APPLICATION()
990 algorithm
991
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 PARTIAL_FUNCTION_APPLICATION(fn = cr, args = expl) := exp2;
992 23 comp := ComponentRef.compare(exp1.fn, cr);
993
994
1/2
✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
23 if comp == 0 then
995 23 comp := List.compare(exp1.args, expl, compare);
996 end if;
997 then
998 comp;
999
1000 case FILENAME()
1001 algorithm
1002 ✗ FILENAME(filename = s) := exp2;
1003 ✗ then
1004 stringCompare(exp1.filename, s);
1005
1006 case INSTANCE_NAME()
1007 algorithm
1008 ✗ INSTANCE_NAME(scope = node) := exp2;
1009 ✗ then
1010 InstNode.refCompare(exp1.scope, node);
1011
1012 else
1013 algorithm
1014 ✗ Error.terminate(getInstanceName() + " got unknown expression.", sourceInfo());
1015 ✗ then
1016 fail();
1017
1018 end match;
1019 end compare;
1020
1021 function compareOpt
1022 input Option<Expression> expl1;
1023 input Option<Expression> expl2;
1024 output Integer comp;
1025 protected
1026 Expression e1, e2;
1027 algorithm
1028 comp := match(expl1, expl2)
1029 case (NONE(), NONE()) then 0;
1030 case (NONE(), _) then -1;
1031 case (_, NONE()) then 1;
1032 144 case (SOME(e1), SOME(e2)) then compare(e1, e2);
1033 end match;
1034 end compareOpt;
1035
1036 function compareList
1037 input list<Expression> expl1;
1038 input list<Expression> expl2;
1039 output Integer comp = List.compare(expl1, expl2, compare);
1040 end compareList;
1041
1042 function typeOf
1043 input Expression exp;
1044 output Type ty;
1045 algorithm
1046 ty := match exp
1047 case INTEGER() then Type.INTEGER();
1048 case REAL() then Type.REAL();
1049 case STRING() then Type.STRING();
1050 case BOOLEAN() then Type.BOOLEAN();
1051 86975 case ENUM_LITERAL() then exp.ty;
1052 case CLKCONST() then Type.CLOCK();
1053 2672183 case CREF() then exp.ty;
1054 5 case TYPENAME() then exp.ty;
1055 669297 case ARRAY() then exp.ty;
1056 38893 case RANGE() then exp.ty;
1057 1221 case TUPLE() then exp.ty;
1058 25852 case RECORD() then exp.ty;
1059 745815 case CALL() then Call.typeOf(exp.call);
1060
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 18761 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 18755 times.
18761 case SIZE() then if isSome(exp.dimIndex) then
1061 Type.INTEGER() else Type.sizeType(typeOf(exp.exp));
1062 case END() then Type.INTEGER();
1063 105865 case MULTARY() then Operator.typeOf(exp.operator);
1064 1367733 case BINARY() then Operator.typeOf(exp.operator);
1065 111833 case UNARY() then Operator.typeOf(exp.operator);
1066 15071 case LBINARY() then Operator.typeOf(exp.operator);
1067 5274 case LUNARY() then Operator.typeOf(exp.operator);
1068 63503 case RELATION() then Type.copyDims(Operator.typeOf(exp.operator), Type.BOOLEAN());
1069 33072 case IF() then exp.ty;
1070 31145 case CAST() then exp.ty;
1071 116 case BOX() then Type.METABOXED(typeOf(exp.exp));
1072 67 case UNBOX() then exp.ty;
1073 22651 case SUBSCRIPTED_EXP() then exp.ty;
1074 170 case TUPLE_ELEMENT() then exp.ty;
1075 318 case RECORD_ELEMENT() then exp.ty;
1076 97472 case MUTABLE() then typeOf(Mutable.access(exp.exp));
1077 9 case SHARED_LITERAL() then typeOf(exp.exp);
1078 47449 case EMPTY() then exp.ty;
1079 123 case PARTIAL_FUNCTION_APPLICATION() then exp.ty;
1080 case FILENAME() then Type.STRING();
1081 case INSTANCE_NAME() then Type.STRING();
1082 else Type.UNKNOWN();
1083 end match;
1084 end typeOf;
1085
1086 function sizeOf
1087 "this can fail for certain untyped expressions"
1088 input Expression exp;
1089 output Integer sz = Type.sizeOf(typeOf(exp));
1090 end sizeOf;
1091
1092 function callOf
1093 input Expression exp;
1094 output Call call;
1095 algorithm
1096
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 CALL(call = call) := exp;
1097 end callOf;
1098
1099 function sizeZero
1100 "returns true if its a constructor that is definitely of size zero;"
1101 input Expression exp;
1102 output Boolean b;
1103 algorithm
1104 try
1105 528 b := 0 == sizeOf(exp);
1106 else
1107 // fill(x, ..., 0, ...) is empty even if its dimension is not known as an integer
1108 b := false;
1109
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 3 times.
4 if isCallNamed(exp, "fill") then
1110
2/2
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 1 time.
3 for arg in listRest(Call.arguments(callOf(exp))) loop
1111
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 if isZero(arg) then
1112 b := true;
1113 end if;
1114 end for;
1115 end if;
1116 end try;
1117 end sizeZero;
1118
1119 function setType
1120 input Type ty;
1121 input output Expression exp;
1122 algorithm
1123 exp := match exp
1124 ✗ case ENUM_LITERAL() algorithm exp.ty := ty; then exp;
1125 200921 case CREF() algorithm exp.ty := ty; then exp;
1126 4 case TYPENAME() algorithm exp.ty := ty; then exp;
1127 496445 case ARRAY() algorithm exp.ty := ty; then exp;
1128 18980 case RANGE() algorithm exp.ty := ty; then exp;
1129 ✗ case TUPLE() algorithm exp.ty := ty; then exp;
1130 ✗ case RECORD() algorithm exp.ty := ty; then exp;
1131 320790 case CALL() algorithm exp.call := Call.setType(exp.call, ty); then exp;
1132 37077 case BINARY() algorithm exp.operator := Operator.setType(ty, exp.operator); then exp;
1133 2164 case UNARY() algorithm exp.operator := Operator.setType(ty, exp.operator); then exp;
1134 4 case LBINARY() algorithm exp.operator := Operator.setType(ty, exp.operator); then exp;
1135 1 case LUNARY() algorithm exp.operator := Operator.setType(ty, exp.operator); then exp;
1136 ✗ case RELATION() algorithm exp.operator := Operator.setType(ty, exp.operator); then exp;
1137 8993 case IF() algorithm exp.ty := ty; then exp;
1138 16519 case CAST() algorithm exp.ty := ty; then exp;
1139 ✗ case UNBOX() algorithm exp.ty := ty; then exp;
1140 20 case SUBSCRIPTED_EXP() algorithm exp.ty := ty; then exp;
1141 27 case TUPLE_ELEMENT() algorithm exp.ty := ty; then exp;
1142 8 case RECORD_ELEMENT() algorithm exp.ty := ty; then exp;
1143 ✗ case PARTIAL_FUNCTION_APPLICATION() algorithm exp.ty := ty; then exp;
1144 else exp;
1145 end match;
1146 end setType;
1147
1148 function applyToType
1149 input output Expression exp;
1150 input typeFunc func;
1151 partial function typeFunc
1152 input output Type ty;
1153 end typeFunc;
1154 algorithm
1155 exp := match exp
1156 local
1157 Operator o;
1158
1/2
✓ Branch 0 taken 1658 times.
✗ Branch 1 not taken.
1658 case ENUM_LITERAL() algorithm exp.ty := func(exp.ty); then exp;
1159
1/2
✓ Branch 0 taken 112173 times.
✗ Branch 1 not taken.
224346 case CREF() algorithm exp.ty := func(exp.ty); exp.cref := ComponentRef.applyToType(exp.cref, func); then exp;
1160 ✗ case TYPENAME() algorithm exp.ty := func(exp.ty); then exp;
1161
1/2
✓ Branch 0 taken 2870 times.
✗ Branch 1 not taken.
2870 case ARRAY() algorithm exp.ty := func(exp.ty); then exp;
1162
1/2
✓ Branch 0 taken 5360 times.
✗ Branch 1 not taken.
5360 case RANGE() algorithm exp.ty := func(exp.ty); then exp;
1163
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 case TUPLE() algorithm exp.ty := func(exp.ty); then exp;
1164
1/2
✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
45 case RECORD() algorithm exp.ty := func(exp.ty); then exp;
1165
1/2
✓ Branch 0 taken 12352 times.
✗ Branch 1 not taken.
12352 case CALL() algorithm exp.call := Call.setType(exp.call, func(Call.typeOf(exp.call))); then exp;
1166 ✗ case SIZE() algorithm exp.exp := applyToType(exp.exp, func); then exp;
1167
1/2
✓ Branch 0 taken 35707 times.
✗ Branch 1 not taken.
71414 case MULTARY(operator = o) algorithm o.ty := func(o.ty); exp.operator := o; then exp;
1168
1/2
✓ Branch 0 taken 5034 times.
✗ Branch 1 not taken.
10068 case BINARY(operator = o) algorithm o.ty := func(o.ty); exp.operator := o; then exp;
1169
1/2
✓ Branch 0 taken 2063 times.
✗ Branch 1 not taken.
4126 case UNARY(operator = o) algorithm o.ty := func(o.ty); exp.operator := o; then exp;
1170
1/2
✓ Branch 0 taken 645 times.
✗ Branch 1 not taken.
1290 case LBINARY(operator = o) algorithm o.ty := func(o.ty); exp.operator := o; then exp;
1171
1/2
✓ Branch 0 taken 425 times.
✗ Branch 1 not taken.
850 case LUNARY(operator = o) algorithm o.ty := func(o.ty); exp.operator := o; then exp;
1172
1/2
✓ Branch 0 taken 3036 times.
✗ Branch 1 not taken.
6072 case RELATION(operator = o) algorithm o.ty := func(o.ty); exp.operator := o; then exp;
1173
1/2
✓ Branch 0 taken 723 times.
✗ Branch 1 not taken.
723 case IF() algorithm exp.ty := func(exp.ty); then exp;
1174
1/2
✓ Branch 0 taken 533 times.
✗ Branch 1 not taken.
533 case CAST() algorithm exp.ty := func(exp.ty); then exp;
1175 294 case BOX() algorithm exp.exp := applyToType(exp.exp, func); then exp;
1176 ✗ case UNBOX() algorithm exp.ty := func(exp.ty); then exp;
1177
1/2
✓ Branch 0 taken 368 times.
✗ Branch 1 not taken.
368 case SUBSCRIPTED_EXP() algorithm exp.ty := func(exp.ty); then exp;
1178 ✗ case TUPLE_ELEMENT() algorithm exp.ty := func(exp.ty); then exp;
1179
1/2
✓ Branch 0 taken 239 times.
✗ Branch 1 not taken.
239 case RECORD_ELEMENT() algorithm exp.ty := func(exp.ty); then exp;
1180 ✗ case MUTABLE() algorithm Mutable.update(exp.exp, applyToType(Mutable.access(exp.exp), func)); then exp;
1181 ✗ case SHARED_LITERAL() algorithm exp.exp := applyToType(exp.exp, func); then exp;
1182 ✗ case EMPTY() algorithm exp.ty := func(exp.ty); then exp;
1183
1/2
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
70 case PARTIAL_FUNCTION_APPLICATION() algorithm exp.ty := func(exp.ty); then exp;
1184 else exp;
1185 end match;
1186 end applyToType;
1187
1188
1189 function typeCastOpt
1190 input Option<Expression> exp;
1191 input Type ty;
1192 output Option<Expression> outExp = Util.applyOption(exp, function typeCast(ty = ty));
1193 end typeCastOpt;
1194
1195 function typeCast
1196 "Converts an expression to the given type. Dimensions of array types can be
1197 omitted, and are ignored by this function, since arrays can't be cast to a
1198 different size. Only the element type of the type is used, so for example:
1199 typeCast({1, 2, 3}, Type.REAL()) => {1.0, 2.0, 3.0}
1200
1201 The function does not check that the cast is valid, and expressions that
1202 can't be converted outright will be wrapped as a CAST expression."
1203 input output Expression exp;
1204 input Type ty;
1205 protected
1206 Type t, ety;
1207 Expression e1, e2;
1208 array<Expression> arr;
1209 algorithm
1210 276953 ety := Type.arrayElementType(ty);
1211
1212 exp := match exp
1213 // Integer can be cast to Real.
1214 case INTEGER()
1215
1/6
✓ Branch 1 taken 223708 times.
✗ Branch 2 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
223708 then if Type.isReal(ety) then REAL(intReal(exp.value))
1216 elseif Type.isEnumeration(ety) and Flags.isConfigFlagSet(Flags.ALLOW_NON_STANDARD_MODELICA, "nonStdIntegersAsEnumeration") // Integer can be cast to Enumeration with non-standard Modelica
1217 then ENUM_LITERAL(ety, Type.nthEnumLiteral(ety, exp.value), exp.value)
1218 else typeCastGeneric(exp, ety);
1219
1220 // Enumeration can be cast to Integer with non-standard Modelica
1221 case ENUM_LITERAL() guard Flags.isConfigFlagSet(Flags.ALLOW_NON_STANDARD_MODELICA, "nonStdEnumerationAsIntegers")
1222 ✗ then if Type.isInteger(ety) then INTEGER(toInteger(exp)) else typeCastGeneric(exp, ety);
1223
1224 // Boolean can be cast to Real (only if -d=nfAPI is on)
1225 // as there are annotations having expressions such as Boolean x > 0.5
1226 case BOOLEAN()
1227 ✗ then if Type.isReal(ety) and Flags.isSet(Flags.NF_API) then
1228 REAL(if exp.value then 1.0 else 0.0) else typeCastGeneric(exp, ety);
1229
1230 // Real doesn't need to be cast to Real, since we convert e.g. array with
1231 // a mix of Integers and Reals to only Reals.
1232 case REAL()
1233
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 486 times.
486 then if Type.isReal(ety) then exp else typeCastGeneric(exp, ety);
1234
1235 // For arrays we typecast each element and update the type of the array.
1236 case ARRAY(ty = t, elements = arr)
1237 algorithm
1238 22757 arr := Array.map(arr, function typeCast(ty = ety));
1239 22757 t := Type.setArrayElementType(t, ety);
1240 22757 then
1241 makeArray(t, arr, exp.literal);
1242
1243 case RANGE(ty = t)
1244 algorithm
1245 34 t := Type.setArrayElementType(t, ety);
1246 34 then
1247 RANGE(t, typeCast(exp.start, ety), typeCastOpt(exp.step, ety), typeCast(exp.stop, ety));
1248
1249 // Unary operators (i.e. -) are handled by casting the operand.
1250 case UNARY()
1251 algorithm
1252 148 t := Type.setArrayElementType(Operator.typeOf(exp.operator), ety);
1253 148 then
1254 UNARY(Operator.setType(t, exp.operator), typeCast(exp.exp, ety));
1255
1256 // Integer arithmetic is cast by casting the operands, so that a result
1257 // that does not fit in an Integer is still the exact Real one.
1258 case BINARY()
1259 guard Type.isReal(ety) and isCastableIntegerArithmetic(exp.operator)
1260 algorithm
1261 1329 t := Type.setArrayElementType(Operator.typeOf(exp.operator), ety);
1262 1329 then
1263 BINARY(typeCast(exp.exp1, ety), Operator.setType(t, exp.operator), typeCast(exp.exp2, ety));
1264
1265 // If-expressions are handled by casting each of the branches.
1266 case IF()
1267 algorithm
1268 1274 e1 := typeCast(exp.trueBranch, ety);
1269 1274 e2 := typeCast(exp.falseBranch, ety);
1270
2/2
✓ Branch 1 taken 51 times.
✓ Branch 2 taken 1223 times.
1274 t := if Type.isConditionalArray(ty) then
1271 Type.setConditionalArrayTypes(ty, typeOf(e1), typeOf(e2)) else typeOf(e1);
1272 1274 then
1273 IF(t, exp.condition, e1, e2);
1274
1275 // Calls are handled by Call.typeCast, which has special rules for some functions.
1276 case CALL()
1277 11492 then Call.typeCast(exp, ety);
1278
1279 // Casting a cast expression overrides its current cast type.
1280 ✗ case CAST() then typeCast(exp.exp, ty);
1281
1282 case SUBSCRIPTED_EXP()
1283 algorithm
1284 6075 e1 := typeCast(exp.exp, ety);
1285 6075 t := Type.setArrayElementType(exp.ty, ety);
1286 6075 then
1287 SUBSCRIPTED_EXP(e1, exp.subscripts, t, exp.split);
1288
1289 // Other expressions are handled by making a CAST expression.
1290 9650 else typeCastGeneric(exp, ety);
1291 end match;
1292 end typeCast;
1293
1294 function isCastableIntegerArithmetic
1295 "Whether an Integer operation gives the same value on the operands cast to
1296 Real: addition, subtraction and multiplication, but not division or ^."
1297 input Operator op;
1298 output Boolean res;
1299 protected
1300 import NFOperator.Op;
1301 algorithm
1302 res := Type.isInteger(Type.arrayElementType(Operator.typeOf(op))) and
1303 (match op.op
1304 case Op.ADD then true;
1305 case Op.SUB then true;
1306 case Op.MUL then true;
1307 case Op.ADD_EW then true;
1308 case Op.SUB_EW then true;
1309 case Op.MUL_EW then true;
1310 case Op.ADD_SCALAR_ARRAY then true;
1311 case Op.ADD_ARRAY_SCALAR then true;
1312 case Op.SUB_SCALAR_ARRAY then true;
1313 case Op.SUB_ARRAY_SCALAR then true;
1314 case Op.MUL_SCALAR_ARRAY then true;
1315 case Op.MUL_ARRAY_SCALAR then true;
1316 case Op.MUL_VECTOR_MATRIX then true;
1317 case Op.MUL_MATRIX_VECTOR then true;
1318 case Op.SCALAR_PRODUCT then true;
1319 case Op.MATRIX_PRODUCT then true;
1320 else false;
1321 end match);
1322 end isCastableIntegerArithmetic;
1323
1324 function typeCastGeneric
1325 input output Expression exp;
1326 input Type ty;
1327 protected
1328 Type exp_ty = typeOf(exp);
1329 algorithm
1330
2/2
✓ Branch 2 taken 641 times.
✓ Branch 3 taken 9086 times.
9727 if not Type.isEqual(ty, Type.arrayElementType(exp_ty)) then
1331 9086 exp := CAST(Type.setArrayElementType(exp_ty, ty), exp);
1332 end if;
1333 end typeCastGeneric;
1334
1335 function realValue
1336 input Expression exp;
1337 output Real value;
1338 algorithm
1339 value := match exp
1340 3361 case REAL() then exp.value;
1341 26 case INTEGER() then intReal(exp.value);
1342 end match;
1343 end realValue;
1344
1345 function makeReal
1346 input Real value;
1347 output Expression exp = REAL(value);
1348 end makeReal;
1349
1350 function integerValue
1351 input Expression exp;
1352 output Integer value;
1353 algorithm
1354 try
1355
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 506 times.
506 INTEGER(value=value) := exp;
1356 else
1357 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because expression is not an integer:\n"
1358 + toString(exp)});
1359 ✗ fail();
1360 end try;
1361 end integerValue;
1362
1363 function integerValueOrDefault
1364 input Expression exp;
1365 input output Integer value = 0;
1366 algorithm
1367 value := match exp
1368 166 case INTEGER() then exp.value;
1369 else value;
1370 end match;
1371 end integerValueOrDefault;
1372
1373 function makeInteger
1374 input Integer value;
1375 output Expression exp = INTEGER(value);
1376 end makeInteger;
1377
1378 function stringValue
1379 input Expression exp;
1380 output String value;
1381 algorithm
1382 value := match exp
1383 7061 case STRING() then exp.value;
1384 ✗ case FILENAME() then exp.filename;
1385 else "";
1386 end match;
1387 end stringValue;
1388
1389 function booleanValue
1390 input Expression exp;
1391 output Boolean value;
1392 algorithm
1393 try
1394 ✗ BOOLEAN(value=value) := exp;
1395 else
1396 value := false;
1397 end try;
1398 end booleanValue;
1399
1400 function makeArray
1401 input Type ty;
1402 input array<Expression> expl;
1403 input Boolean literal = false;
1404 output Expression outExp;
1405 algorithm
1406
2/2
✓ Branch 0 taken 835130 times.
✓ Branch 1 taken 124442 times.
1794702 outExp := ARRAY(ty, expl, literal);
1407 annotation(__OpenModelica_EarlyInline = true);
1408 end makeArray;
1409
1410 function makeArrayCheckLiteral
1411 input Type ty;
1412 input array<Expression> expl;
1413 output Expression outExp;
1414 algorithm
1415
2/2
✓ Branch 1 taken 37373 times.
✓ Branch 2 taken 218354 times.
293100 outExp := ARRAY(ty, expl, Array.all(expl, isLiteral));
1416 annotation(__OpenModelica_EarlyInline = true);
1417 end makeArrayCheckLiteral;
1418
1419 function makeEmptyArray
1420 "Creates an array from a type where at least one of the dimensions is zero."
1421 input Type ty;
1422 output Expression outExp;
1423 protected
1424 list<Dimension> dims, non_empty_dims = {};
1425 Type arr_ty;
1426 algorithm
1427 // Split the dimensions on the first zero dimension.
1428 482 dims := Type.arrayDims(ty);
1429
1430
2/2
✓ Branch 2 taken 34 times.
✓ Branch 3 taken 476 times.
516 while not Dimension.isZero(listHead(dims)) loop
1431 34 non_empty_dims := listHead(dims) :: non_empty_dims;
1432 34 dims := listRest(dims);
1433 end while;
1434
1435 // Create an empty array with the zero dimension and the dimensions after.
1436 476 arr_ty := Type.ARRAY(Type.arrayElementType(ty), dims);
1437 476 outExp := ARRAY(arr_ty, listArray({}), true);
1438 // Lift the empty array with the dimensions preceeding the zero dimension.
1439 476 outExp := liftArrayList(non_empty_dims, outExp);
1440 end makeEmptyArray;
1441
1442 function makeIntegerArray
1443 input list<Integer> values;
1444 output Expression exp;
1445 algorithm
1446 14 exp := makeArray(Type.ARRAY(Type.INTEGER(), {Dimension.fromInteger(listLength(values))}),
1447 Array.mapList(values, makeInteger),
1448 literal = true);
1449 end makeIntegerArray;
1450
1451 function makeRealArray
1452 input list<Real> values;
1453 output Expression exp;
1454 algorithm
1455 14 exp := makeArray(Type.ARRAY(Type.REAL(), {Dimension.fromInteger(listLength(values))}),
1456 Array.mapList(values, makeReal),
1457 literal = true);
1458 end makeRealArray;
1459
1460 function makeRealMatrix
1461 input list<list<Real>> values;
1462 output Expression exp;
1463 protected
1464 Type ty;
1465 list<Expression> expl;
1466 algorithm
1467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if listEmpty(values) then
1468 ✗ ty := Type.ARRAY(Type.REAL(), {Dimension.fromInteger(0), Dimension.UNKNOWN()});
1469 ✗ exp := makeEmptyArray(ty);
1470 else
1471 28 ty := Type.ARRAY(Type.REAL(), {Dimension.fromInteger(listLength(listHead(values)))});
1472
8/8
✓ Branch 0 taken 126 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 126 times.
✓ Branch 3 taken 14 times.
✓ Branch 4 taken 252 times.
✓ Branch 5 taken 126 times.
✓ Branch 6 taken 252 times.
✓ Branch 7 taken 126 times.
392 expl := list(makeArray(ty, listArray(list(REAL(v) for v in row)), literal = true) for row in values);
1473 14 ty := Type.liftArrayLeft(ty, Dimension.fromInteger(listLength(expl)));
1474 14 exp := makeArray(ty, listArray(expl), literal = true);
1475 end if;
1476 end makeRealMatrix;
1477
1478 function makeExpArray
1479 input array<Expression> elements;
1480 input Type elementType;
1481 input Boolean isLiteral = false;
1482 output Expression exp;
1483 protected
1484 Type ty;
1485 algorithm
1486 2027 ty := Type.liftArrayLeft(elementType, Dimension.fromInteger(arrayLength(elements)));
1487 2027 exp := makeArray(ty, elements, isLiteral);
1488 end makeExpArray;
1489
1490 function makeRecord
1491 input Absyn.Path recordName;
1492 input Type recordType;
1493 input list<Expression> fields;
1494 output Expression exp;
1495 algorithm
1496 10566 exp := RECORD(recordName, recordType, fields);
1497 end makeRecord;
1498
1499 function makeRange
1500 input Expression start;
1501 input Option<Expression> step;
1502 input Expression stop;
1503 output Expression rangeExp;
1504 algorithm
1505 2173 rangeExp := RANGE(
1506 TypeCheck.getRangeType(start, step, stop, typeOf(start), Absyn.dummyInfo),
1507 start, step, stop
1508 );
1509 end makeRange;
1510
1511 function makeIntegerRange
1512 input Integer start;
1513 input Integer step;
1514 input Integer stop;
1515 output Expression rangeExp;
1516 protected
1517 Expression start_exp, stop_exp;
1518 Option<Expression> step_exp;
1519 algorithm
1520 11 start_exp := INTEGER(start);
1521 11 stop_exp := INTEGER(stop);
1522
1523
2/6
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
11 if start == stop or
1524 step == 1 and start <= stop or
1525 step == -1 and start >= stop then
1526 step_exp := NONE();
1527 else
1528 ✗ step_exp := SOME(INTEGER(step));
1529 end if;
1530
1531 11 rangeExp := makeRange(start_exp, step_exp, stop_exp);
1532 end makeIntegerRange;
1533
1534 function getIntegerRange
1535 input Expression range "has to be RANGE()!";
1536 input Boolean resize;
1537 output Integer start;
1538 output Integer step;
1539 output Integer stop;
1540 algorithm
1541 (start, step, stop) := match range
1542 case RANGE() algorithm
1543 try
1544 1180 start := getInteger(range.start, resize);
1545 1180 stop := getInteger(range.stop, resize);
1546
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1180 times.
✓ Branch 2 taken 1176 times.
✓ Branch 3 taken 4 times.
1180 if isSome(range.step) then
1547 4 step := getInteger(Util.getOption(range.step), resize);
1548 else
1549
1/2
✓ Branch 0 taken 1176 times.
✗ Branch 1 not taken.
1176 step := if start > stop then -1 else 1;
1550 end if;
1551 else
1552 ✗ Error.terminate(getInstanceName() + " range could not be parsed to integer values: " + toString(range), sourceInfo());
1553 ✗ fail();
1554 end try;
1555 then (start, step, stop);
1556 else algorithm
1557 ✗ Error.terminate(getInstanceName() + " expression not RANGE(): " + toString(range), sourceInfo());
1558 ✗ then fail();
1559 end match;
1560 end getIntegerRange;
1561
1562 function getInteger
1563 input Expression exp;
1564 input Boolean resize;
1565 output Integer i;
1566 protected
1567 Expression e;
1568 algorithm
1569
2/2
✓ Branch 0 taken 1850 times.
✓ Branch 1 taken 1966 times.
3816 if resize then
1570 1850 e := Expression.map(exp, Expression.replaceResizableParameter);
1571 else
1572 1966 e := Expression.map(exp, Expression.replaceResizableParameterWithOriginal);
1573 end if;
1574 i := match SimplifyExp.simplify(e)
1575 case INTEGER(i) then i;
1576 else algorithm
1577 ✗ Error.terminate(getInstanceName() + " cannot be parsed to an integer: " + toString(exp), sourceInfo());
1578 ✗ then fail();
1579 end match;
1580 end getInteger;
1581
1582 function makeTuple
1583 input list<Expression> expl;
1584 output Expression tupleExp;
1585 protected
1586 list<Type> tyl;
1587 algorithm
1588
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 17 times.
22 if listLength(expl) == 1 then
1589 5 tupleExp := listHead(expl);
1590 else
1591
4/4
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 34 times.
✓ Branch 3 taken 17 times.
51 tyl := list(typeOf(e) for e in expl);
1592 17 tupleExp := TUPLE(Type.TUPLE(tyl, NONE()), expl);
1593 end if;
1594 end makeTuple;
1595
1596 function emptyRange
1597 "returns true if the range is size 0 or less and not resizable"
1598 input Expression range "has to be RANGE()!";
1599 output Boolean b = (not contains(range, isResizableCref)) and 0 >= Dimension.size(Type.nthDimension(typeOf(range), 1), false);
1600 end emptyRange;
1601
1602 function rangeSize
1603 input Expression range "has to be RANGE()!";
1604 input Boolean resize = false;
1605 output Integer size = Dimension.size(Type.nthDimension(typeOf(range), 1), resize);
1606 end rangeSize;
1607
1608 function rangeSizeExp
1609 input Expression range "has to be RANGE()!";
1610 output Expression size = Dimension.sizeExp(Type.nthDimension(typeOf(range), 1));
1611 end rangeSizeExp;
1612
1613 function applySubscripts
1614 "Subscripts an expression with the given list of subscripts."
1615 input list<Subscript> subscripts;
1616 input Expression exp;
1617 input Boolean applyToScope = false;
1618 output Expression outExp;
1619 algorithm
1620
2/2
✓ Branch 0 taken 400527 times.
✓ Branch 1 taken 904423 times.
1304950 if listEmpty(subscripts) then
1621 outExp := exp;
1622 else
1623 400527 outExp := applySubscript(listHead(subscripts), exp, listRest(subscripts), applyToScope);
1624 end if;
1625 end applySubscripts;
1626
1627 function applySubscript
1628 "Subscripts an expression with the given subscript, and then applies the
1629 optional list of subscripts to each element of the subscripted expression."
1630 input Subscript subscript;
1631 input Expression exp;
1632 input list<Subscript> restSubscripts = {};
1633 input Boolean applyToScope = false;
1634 output Expression outExp;
1635 algorithm
1636 outExp := match exp
1637 99329 case CREF() then applySubscriptCref(subscript, exp.cref, restSubscripts, applyToScope);
1638
1639 case TYPENAME() guard listEmpty(restSubscripts)
1640 ✗ then applySubscriptTypename(subscript, exp.ty);
1641
1642 127104 case ARRAY() then applySubscriptArray(subscript, exp, restSubscripts, applyToScope);
1643
1644 case RANGE() guard listEmpty(restSubscripts)
1645 1269 then applySubscriptRange(subscript, exp);
1646
1647 case CALL()
1648 90303 then applySubscriptCall(subscript, exp, restSubscripts, applyToScope);
1649
1650 265 case IF() then applySubscriptIf(subscript, exp, restSubscripts, applyToScope);
1651
1652 case BINARY() guard List.all(subscript :: restSubscripts, isCheapSubscript)
1653 4157 then applySubscriptBinary(subscript, exp, restSubscripts, applyToScope);
1654
1655 case UNARY() guard Type.isArray(Operator.typeOf(exp.operator)) and
1656 List.all(subscript :: restSubscripts, isCheapSubscript)
1657 algorithm
1658 26 outExp := applySubscript(subscript, exp.exp, restSubscripts, applyToScope);
1659 26 then
1660 UNARY(Operator.setType(typeOf(outExp), exp.operator), outExp);
1661
1662 case UNBOX()
1663 algorithm
1664 ✗ outExp := applySubscript(subscript, exp.exp, restSubscripts, applyToScope);
1665 ✗ then
1666 unbox(outExp);
1667
1668 ✗ case BOX() then box(applySubscript(subscript, exp.exp, restSubscripts, applyToScope));
1669
1670 case CAST()
1671 algorithm
1672 5 outExp := applySubscript(subscript, exp.exp, restSubscripts, applyToScope);
1673 5 then
1674 CAST(Type.copyElementType(typeOf(outExp), exp.ty), outExp);
1675
1676 94144 else makeSubscriptedExp(subscript :: restSubscripts, exp);
1677 end match;
1678 end applySubscript;
1679
1680 function applySubscriptCref
1681 input Subscript subscript;
1682 input ComponentRef cref;
1683 input list<Subscript> restSubscripts;
1684 input Boolean applyToScope;
1685 output Expression outExp;
1686 protected
1687 ComponentRef cr;
1688 Type ty;
1689 algorithm
1690 99329 cr := ComponentRef.mergeSubscripts(subscript :: restSubscripts, cref, applyToScope);
1691 99329 ty := ComponentRef.getSubscriptedType(cr);
1692 99329 outExp := CREF(ty, cr);
1693 end applySubscriptCref;
1694
1695 function applySubscriptTypename
1696 input Subscript subscript;
1697 input Type ty;
1698 output Expression outExp;
1699 protected
1700 Subscript sub;
1701 array<Expression> expl;
1702 algorithm
1703 ✗ sub := Subscript.expandSlice(subscript, false);
1704
1705 outExp := match sub
1706 ✗ case Subscript.INDEX() then applyIndexSubscriptTypename(ty, sub);
1707
1708 case Subscript.SLICE()
1709 ✗ then SUBSCRIPTED_EXP(TYPENAME(ty), {subscript}, Type.ARRAY(ty, {Subscript.toDimension(sub)}), false);
1710
1711 case Subscript.WHOLE()
1712 ✗ then TYPENAME(ty);
1713
1714 case Subscript.EXPANDED_SLICE()
1715 algorithm
1716 ✗ expl := Array.mapList(sub.indices, function applyIndexSubscriptTypename(ty = ty));
1717 ✗ then
1718 makeArray(Type.liftArrayLeft(ty, Dimension.fromInteger(arrayLength(expl))), expl, literal = true);
1719
1720 end match;
1721 end applySubscriptTypename;
1722
1723 function applyIndexSubscriptTypename
1724 input Type ty;
1725 input Subscript index;
1726 output Expression subscriptedExp;
1727 protected
1728 Expression idx_exp;
1729 Integer idx;
1730 algorithm
1731 ✗ idx_exp := Subscript.toExp(index);
1732
1733 ✗ if isScalarLiteral(idx_exp) then
1734 ✗ idx := toInteger(idx_exp);
1735
1736 subscriptedExp := match ty
1737 case Type.BOOLEAN() guard idx <= 2
1738 ✗ then if idx == 1 then BOOLEAN(false) else BOOLEAN(true);
1739
1740 ✗ case Type.ENUMERATION() then nthEnumLiteral(ty, idx);
1741 end match;
1742 else
1743 ✗ subscriptedExp := SUBSCRIPTED_EXP(TYPENAME(ty), {index}, ty, false);
1744 end if;
1745 end applyIndexSubscriptTypename;
1746
1747 function applySubscriptArray
1748 input Subscript subscript;
1749 input Expression exp;
1750 input list<Subscript> restSubscripts;
1751 input Boolean applyToScope;
1752 output Expression outExp;
1753 protected
1754 Subscript sub, s;
1755 list<Subscript> rest_subs;
1756 array<Expression> expl;
1757 Type ty;
1758 Boolean literal;
1759 algorithm
1760
2/2
✓ Branch 1 taken 114 times.
✓ Branch 2 taken 126990 times.
127104 if isEmptyArray(exp) then
1761 114 outExp := makeSubscriptedExp(subscript :: restSubscripts, exp);
1762 114 return;
1763 end if;
1764
1765 126990 sub := Subscript.expandSlice(subscript, false);
1766
1767 outExp := match sub
1768 122707 case Subscript.INDEX() then applyIndexSubscriptArray(exp, sub, restSubscripts);
1769 4 case Subscript.SLICE() then makeSubscriptedExp(subscript :: restSubscripts, exp);
1770 case Subscript.WHOLE()
1771 algorithm
1772
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 129 times.
139 if listEmpty(restSubscripts) then
1773 outExp := exp;
1774 else
1775
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 ARRAY(ty = ty, elements = expl, literal = literal) := exp;
1776 10 s :: rest_subs := restSubscripts;
1777
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
20 expl := Array.map(expl, function applySubscript(subscript = s, restSubscripts = rest_subs, applyToScope = applyToScope));
1778 10 (ty, literal) := typeSubscriptedArray(expl, restSubscripts, ty, literal);
1779 10 outExp := makeArray(ty, expl, literal);
1780 end if;
1781 then
1782 outExp;
1783
1784 case Subscript.EXPANDED_SLICE()
1785 algorithm
1786
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 269 times.
269 ARRAY(ty = ty, literal = literal) := exp;
1787 269 expl := Array.mapList(sub.indices,
1788 function applyIndexSubscriptArray(exp = exp, restSubscripts = restSubscripts));
1789 269 (ty, literal) := typeSubscriptedArray(expl, restSubscripts, ty, literal);
1790 269 then
1791 makeArray(ty, expl, literal);
1792
1793 3870 case Subscript.SPLIT_INDEX() then makeSubscriptedExp(subscript :: restSubscripts, exp);
1794
1795 end match;
1796 end applySubscriptArray;
1797
1798 function typeSubscriptedArray
1799 input array<Expression> elements;
1800 input list<Subscript> subscripts;
1801 input output Type ty;
1802 input output Boolean literal;
1803 protected
1804 Integer count;
1805 Expression e;
1806 algorithm
1807 count := arrayLength(elements);
1808
1809
2/2
✓ Branch 0 taken 122 times.
✓ Branch 1 taken 157 times.
279 if count > 0 then
1810 // If the array isn't empty, use the type of the first element.
1811 e := elements[1];
1812 122 ty := typeOf(e);
1813 // Non-literal subscripts might change an array from literal to non-literal.
1814
3/4
✓ Branch 0 taken 112 times.
✓ Branch 1 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 112 times.
122 literal := literal and isLiteral(e);
1815 else
1816 // If the array is empty, use the slower method of subscripting the type.
1817 157 ty := Type.subscript(Type.unliftArray(ty), subscripts);
1818 end if;
1819
1820 279 ty := Type.liftArrayLeft(ty, Dimension.fromInteger(count));
1821 end typeSubscriptedArray;
1822
1823 function applyIndexSubscriptArray
1824 input Expression exp;
1825 input Subscript index;
1826 input list<Subscript> restSubscripts;
1827 output Expression outExp;
1828 algorithm
1829 123122 outExp := applyIndexExpArray(exp, Subscript.toExp(index), restSubscripts);
1830 end applyIndexSubscriptArray;
1831
1832 function applyIndexExpArray
1833 input Expression exp;
1834 input Expression index;
1835 input list<Subscript> restSubscripts;
1836 output Expression outExp;
1837 protected
1838 array<Expression> expl;
1839 Integer idx;
1840 algorithm
1841 // Try to subscript the array if the index is known.
1842
2/2
✓ Branch 1 taken 116158 times.
✓ Branch 2 taken 6964 times.
123122 if isScalarLiteral(index) then
1843
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 116158 times.
116158 ARRAY(elements = expl) := exp;
1844 116158 idx := toInteger(index);
1845
1846 // Check that the index is in bounds. We don't want to fail here if it's
1847 // out of bounds, that's someone else's problem and might be fine.
1848
3/4
✓ Branch 0 taken 116158 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 116155 times.
✓ Branch 3 taken 3 times.
232316 if idx > 0 and idx <= arrayLength(expl) then
1849 116155 outExp := applySubscripts(restSubscripts, expl[idx]);
1850 116155 return;
1851 end if;
1852 end if;
1853
1854 // Otherwise create a subscript expression.
1855 13934 outExp := makeSubscriptedExp(Subscript.INDEX(index) :: restSubscripts, exp);
1856 end applyIndexExpArray;
1857
1858 function applySubscriptRange
1859 input Subscript subscript;
1860 input Expression exp;
1861 output Expression outExp;
1862 protected
1863 Subscript sub;
1864 Type ty;
1865 array<Expression> expl;
1866 algorithm
1867 1269 sub := Subscript.expandSlice(subscript, false);
1868
1869 outExp := match sub
1870 1122 case Subscript.INDEX() then applyIndexSubscriptRange(exp, sub);
1871
1872 case Subscript.SLICE()
1873 algorithm
1874 ✗ RANGE(ty = ty) := exp;
1875 ✗ ty := Type.ARRAY(Type.unliftArray(ty), {Subscript.toDimension(sub)});
1876 ✗ then
1877 SUBSCRIPTED_EXP(exp, {subscript}, ty, false);
1878
1879 case Subscript.WHOLE() then exp;
1880
1881 case Subscript.EXPANDED_SLICE()
1882 algorithm
1883 ✗ expl := Array.mapList(sub.indices, function applyIndexSubscriptRange(rangeExp = exp));
1884 ✗ RANGE(ty = ty) := exp;
1885 ✗ then
1886 makeArray(Type.liftArrayLeft(ty, Dimension.fromInteger(arrayLength(expl))), expl);
1887
1888 case Subscript.SPLIT_INDEX()
1889 algorithm
1890
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 147 times.
147 RANGE(ty = ty) := exp;
1891 147 ty := Type.unliftArray(ty);
1892 147 then
1893 SUBSCRIPTED_EXP(exp, {sub}, ty, true);
1894
1895 else
1896 algorithm
1897 ✗ Error.terminate(getInstanceName() + " got unknown subscript '" + Subscript.toString(sub) + "'", sourceInfo());
1898 ✗ then
1899 fail();
1900
1901 end match;
1902 end applySubscriptRange;
1903
1904 function applyIndexSubscriptRange
1905 input Expression rangeExp;
1906 input Subscript index;
1907 output Expression outExp;
1908 protected
1909 Expression index_exp, start_exp, stop_exp;
1910 Option<Expression> step_exp;
1911 Type ty;
1912 list<Subscript> subs;
1913 Integer step, offset;
1914 algorithm
1915
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1122 times.
1122 Subscript.INDEX(index = index_exp) := index;
1916
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1122 times.
1122 RANGE(ty = ty, start = start_exp, step = step_exp, stop = stop_exp) := rangeExp;
1917
1918
4/6
✓ Branch 1 taken 628 times.
✓ Branch 2 taken 494 times.
✓ Branch 4 taken 628 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 628 times.
✗ Branch 8 not taken.
1122 if isScalarLiteral(index_exp) and isScalarLiteral(start_exp) and
1919 Util.applyOptionOrDefault(step_exp, isScalarLiteral, true) then
1920 628 outExp := applyIndexSubscriptRange2(start_exp, step_exp, stop_exp, toInteger(index_exp));
1921 elseif isScalarLiteral(index_exp) and toInteger(index_exp) == 1 then
1922 outExp := start_exp;
1923 elseif Type.isInteger(Type.arrayElementType(ty)) and isScalarLiteral(start_exp) and
1924 Util.applyOptionOrDefault(step_exp, isScalarLiteral, true) then
1925 // (start:step:stop)[i] = step*i + (start - step), e.g. (1:n)[i] = i
1926 492 step := Util.applyOptionOrDefault(step_exp, toInteger, 1);
1927 492 offset := toInteger(start_exp) - step;
1928 outExp := index_exp;
1929
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 492 times.
492 if step <> 1 then
1930 ✗ outExp := BINARY(INTEGER(step), Operator.makeMul(Type.INTEGER()), outExp);
1931 end if;
1932
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 392 times.
492 if offset <> 0 then
1933 100 outExp := BINARY(outExp, Operator.makeAdd(Type.INTEGER()), INTEGER(offset));
1934 end if;
1935 else
1936 subs := {index};
1937 2 ty := Type.subscript(ty, subs);
1938 2 outExp := SUBSCRIPTED_EXP(rangeExp, subs, ty, false);
1939 end if;
1940 end applyIndexSubscriptRange;
1941
1942 function applyIndexSubscriptRange2
1943 input Expression startExp;
1944 input Option<Expression> stepExp;
1945 input Expression stopExp;
1946 input Integer index;
1947 output Expression subscriptedExp;
1948 protected
1949 Integer iidx;
1950 Real ridx;
1951 algorithm
1952 subscriptedExp := match (startExp, stepExp)
1953 case (INTEGER(), SOME(INTEGER(iidx)))
1954 ✗ then INTEGER(startExp.value + (index - 1) * iidx);
1955
1956 case (INTEGER(), _)
1957 628 then INTEGER(startExp.value + index - 1);
1958
1959 case (REAL(), SOME(REAL(ridx)))
1960 ✗ then REAL(startExp.value + (index - 1) * ridx);
1961
1962 case (REAL(), _)
1963 ✗ then REAL(startExp.value + index - 1.0);
1964
1965 case (BOOLEAN(), _)
1966 ✗ then if index == 1 then startExp else stopExp;
1967
1968 case (ENUM_LITERAL(index = iidx), _)
1969 algorithm
1970 ✗ iidx := iidx + index - 1;
1971 ✗ then
1972 nthEnumLiteral(startExp.ty, iidx);
1973
1974 end match;
1975 end applyIndexSubscriptRange2;
1976
1977 function applySubscriptCall
1978 input Subscript subscript;
1979 input Expression exp;
1980 input list<Subscript> restSubscripts;
1981 input Boolean applyToScope;
1982 output Expression outExp;
1983 protected
1984 Call call;
1985 algorithm
1986
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90303 times.
90303 CALL(call = call) := exp;
1987
1988 outExp := match call
1989 local
1990 Expression arg;
1991 Type ty;
1992
1993 case Call.TYPED_CALL(arguments = {arg})
1994 guard Function.Function.isSubscriptableBuiltin(call.fn)
1995 algorithm
1996 12 arg := applySubscript(subscript, arg, restSubscripts, applyToScope);
1997 12 ty := Type.copyDims(typeOf(arg), call.ty);
1998 12 then
1999 CALL(Call.TYPED_CALL(call.fn, ty, call.var, call.purity, {arg}, call.attributes));
2000
2001 case Call.TYPED_ARRAY_CONSTRUCTOR()
2002 2254 then applySubscriptArrayConstructor(subscript, call, restSubscripts);
2003
2004 88037 else makeSubscriptedExp(subscript :: restSubscripts, exp);
2005 end match;
2006 end applySubscriptCall;
2007
2008 function applySubscriptArrayConstructor
2009 input Subscript subscript;
2010 input Call call;
2011 input list<Subscript> restSubscripts;
2012 output Expression outExp;
2013 algorithm
2014
3/4
✓ Branch 1 taken 1675 times.
✓ Branch 2 taken 579 times.
✓ Branch 3 taken 1675 times.
✗ Branch 4 not taken.
2254 if Subscript.isIndex(subscript) and listEmpty(restSubscripts) then
2015 1675 outExp := applyIndexSubscriptArrayConstructor(call, subscript);
2016 else
2017 // TODO: Handle slicing and multiple subscripts better.
2018 579 outExp := makeSubscriptedExp(subscript :: restSubscripts, CALL(call));
2019 end if;
2020 end applySubscriptArrayConstructor;
2021
2022 function applyIndexSubscriptArrayConstructor
2023 input Call call;
2024 input Subscript index;
2025 output Expression subscriptedExp;
2026 protected
2027 Type ty;
2028 Variability var;
2029 Purity pur;
2030 Expression exp, iter_exp;
2031 list<tuple<InstNode, Expression>> iters;
2032 InstNode iter;
2033 algorithm
2034
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1675 times.
1675 Call.TYPED_ARRAY_CONSTRUCTOR(ty, var, pur, exp, iters) := call;
2035 1675 ((iter, iter_exp), iters) := List.splitLast(iters);
2036 1675 iter_exp := applySubscript(index, iter_exp);
2037 1675 subscriptedExp := replaceIterator(exp, iter, iter_exp);
2038
2039
1/2
✓ Branch 0 taken 1675 times.
✗ Branch 1 not taken.
1675 if not listEmpty(iters) then
2040 ✗ subscriptedExp := CALL(Call.TYPED_ARRAY_CONSTRUCTOR(Type.unliftArray(ty), var, pur, subscriptedExp, iters));
2041 end if;
2042 end applyIndexSubscriptArrayConstructor;
2043
2044 function applySubscriptIf
2045 input Subscript subscript;
2046 input Expression exp;
2047 input list<Subscript> restSubscripts;
2048 input Boolean applyToScope;
2049 output Expression outExp;
2050 protected
2051 Expression cond, tb, fb;
2052 Type ty;
2053 algorithm
2054
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 265 times.
265 IF(ty, cond, tb, fb) := exp;
2055
2056
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 263 times.
265 if Type.isConditionalArray(ty) then
2057 // Subscripting both branches of a conditional array might not be possible
2058 // since they have different dimensions. If it fails just subscript the
2059 // whole if-expression instead.
2060 try
2061 2 tb := applySubscript(subscript, tb, restSubscripts, applyToScope);
2062 2 fb := applySubscript(subscript, fb, restSubscripts, applyToScope);
2063 2 ty := Type.setConditionalArrayTypes(ty, typeOf(tb), typeOf(fb));
2064 2 outExp := IF(ty, cond, tb, fb);
2065 else
2066 ✗ outExp := makeSubscriptedExp(subscript :: restSubscripts, exp);
2067 end try;
2068 else
2069 263 tb := applySubscript(subscript, tb, restSubscripts, applyToScope);
2070 263 fb := applySubscript(subscript, fb, restSubscripts, applyToScope);
2071 263 ty := typeOf(tb);
2072 263 outExp := IF(ty, cond, tb, fb);
2073 end if;
2074 end applySubscriptIf;
2075
2076 function isCheapSubscript
2077 "Whether the subscript can be duplicated into the operands of an operator."
2078 input Subscript subscript;
2079 output Boolean cheap;
2080 algorithm
2081 cheap := match subscript
2082
3/4
✓ Branch 1 taken 1662 times.
✓ Branch 2 taken 2521 times.
✓ Branch 4 taken 1662 times.
✗ Branch 5 not taken.
4183 case Subscript.INDEX() then isCref(subscript.index) or isScalarLiteral(subscript.index);
2083 case Subscript.WHOLE() then true;
2084 else false;
2085 end match;
2086 end isCheapSubscript;
2087
2088 function applySubscriptBinary
2089 "Moves the subscripts into the operands of an element-wise operator:
2090 (a .* b)[i] = a[i] * b[i], (a * s)[i] = a[i] * s."
2091 input Subscript subscript;
2092 input Expression exp;
2093 input list<Subscript> restSubscripts;
2094 input Boolean applyToScope;
2095 output Expression outExp;
2096 protected
2097 import NFOperator.Op;
2098 Expression e1, e2;
2099 Operator op;
2100 Op scalar_op;
2101 Boolean sub1, sub2;
2102 algorithm
2103
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4157 times.
4157 BINARY(e1, op, e2) := exp;
2104
2105 (sub1, sub2, scalar_op) := match op.op
2106 case Op.ADD guard Type.isArray(op.ty) then (true, true, Op.ADD);
2107 case Op.SUB guard Type.isArray(op.ty) then (true, true, Op.SUB);
2108 case Op.ADD_EW then (true, true, Op.ADD);
2109 case Op.SUB_EW then (true, true, Op.SUB);
2110 case Op.MUL_EW then (true, true, Op.MUL);
2111 case Op.DIV_EW then (true, true, Op.DIV);
2112 case Op.POW_EW then (true, true, Op.POW);
2113 case Op.ADD_ARRAY_SCALAR then (true, false, Op.ADD);
2114 case Op.SUB_ARRAY_SCALAR then (true, false, Op.SUB);
2115 case Op.MUL_ARRAY_SCALAR then (true, false, Op.MUL);
2116 case Op.DIV_ARRAY_SCALAR then (true, false, Op.DIV);
2117 case Op.POW_ARRAY_SCALAR then (true, false, Op.POW);
2118 case Op.ADD_SCALAR_ARRAY then (false, true, Op.ADD);
2119 case Op.SUB_SCALAR_ARRAY then (false, true, Op.SUB);
2120 case Op.MUL_SCALAR_ARRAY then (false, true, Op.MUL);
2121 case Op.DIV_SCALAR_ARRAY then (false, true, Op.DIV);
2122 case Op.POW_SCALAR_ARRAY then (false, true, Op.POW);
2123 1354 else (false, false, op.op);
2124 end match;
2125
2126
2/2
✓ Branch 0 taken 1354 times.
✓ Branch 1 taken 2803 times.
4157 if not (sub1 or sub2) then
2127 1354 outExp := makeSubscriptedExp(subscript :: restSubscripts, exp);
2128 1354 return;
2129 end if;
2130
2131
2/2
✓ Branch 0 taken 2281 times.
✓ Branch 1 taken 522 times.
2803 if sub1 then
2132 2281 e1 := applySubscript(subscript, e1, restSubscripts, applyToScope);
2133 end if;
2134
2135
2/2
✓ Branch 0 taken 1705 times.
✓ Branch 1 taken 1098 times.
2803 if sub2 then
2136 1705 e2 := applySubscript(subscript, e2, restSubscripts, applyToScope);
2137 end if;
2138
2139
2/2
✓ Branch 0 taken 522 times.
✓ Branch 1 taken 2281 times.
3325 op.ty := typeOf(if sub1 then e1 else e2);
2140
2141
2/2
✓ Branch 1 taken 2790 times.
✓ Branch 2 taken 13 times.
2803 if Type.isScalar(op.ty) then
2142 2790 op.op := scalar_op;
2143 end if;
2144
2145 2803 outExp := BINARY(e1, op, e2);
2146 end applySubscriptBinary;
2147
2148 function makeSubscriptedExp
2149 input list<Subscript> subscripts;
2150 input Expression exp;
2151 input Boolean backend = false;
2152 output Expression outExp;
2153 protected
2154 Expression e;
2155 list<Subscript> subs, extra_subs;
2156 Type ty;
2157 Integer dim_count;
2158 Boolean split;
2159 algorithm
2160 // If the expression is already a SUBSCRIPTED_EXP we need to concatenate the
2161 // old subscripts with the new. Otherwise we just create a new SUBSCRIPTED_EXP.
2162 (e, subs, ty, split) := match exp
2163 940 case SUBSCRIPTED_EXP() then (exp.exp, exp.subscripts, typeOf(exp.exp), exp.split);
2164 194130 else (exp, {}, typeOf(exp), false);
2165 end match;
2166
2167
2/2
✓ Branch 0 taken 195068 times.
✓ Branch 1 taken 2 times.
195070 if not split then
2168 195068 split := List.any(subscripts, Subscript.isSplitIndex);
2169 end if;
2170
2171 195070 dim_count := Type.dimensionCount(ty);
2172 195070 (subs, extra_subs) := Subscript.mergeList(subscripts, subs, dim_count, backend);
2173
2174 // Check that the expression has enough dimensions to be subscripted.
2175
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 195070 times.
195070 if not listEmpty(extra_subs) then
2176 ✗ Error.terminate(getInstanceName() + ": too few dimensions in " +
2177 toString(exp) + " to apply subscripts " + Subscript.toStringList(subscripts), sourceInfo());
2178 end if;
2179
2180 195070 ty := Type.subscript(ty, subs);
2181
2/2
✓ Branch 0 taken 108666 times.
✓ Branch 1 taken 86404 times.
303736 outExp := SUBSCRIPTED_EXP(e, subs, ty, split);
2182 end makeSubscriptedExp;
2183
2184 function replaceIterator
2185 "Replaces the given iterator with the given value in an expression."
2186 input output Expression exp;
2187 input InstNode iterator;
2188 input Expression iteratorValue;
2189 algorithm
2190 32148 exp := map(exp, function replaceIterator2(iterator = iterator, iteratorValue = iteratorValue));
2191 end replaceIterator;
2192
2193 function replaceIterator2
2194 input Expression exp;
2195 input InstNode iterator;
2196 input Expression iteratorValue;
2197 output Expression outExp;
2198 algorithm
2199 outExp := match exp
2200 local
2201 InstNode node;
2202 ComponentRef cref;
2203 list<String> fields;
2204
2205 // Cref is simple identifier, i
2206 case CREF(cref = ComponentRef.CREF())
2207 guard ComponentRef.isSimple(exp.cref)
2208
2/2
✓ Branch 2 taken 31166 times.
✓ Branch 3 taken 61693 times.
92859 then if InstNode.refEqual(iterator, ComponentRef.node(exp.cref)) then iteratorValue else exp;
2209
2210 // Cref is qualified identifier, i.x
2211 case CREF(cref = ComponentRef.CREF())
2212 algorithm
2213 // Only the first (last in stored order) part of a cref can be an iterator.
2214 50870 node := ComponentRef.node(ComponentRef.last(exp.cref));
2215
2216
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 50869 times.
50870 if InstNode.refEqual(iterator, node) then
2217 // Start with the given value.
2218 outExp := iteratorValue;
2219
2220 // Go down into the record fields using the rest of the cref.
2221
4/4
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 1 time.
2 fields := list(InstNode.name(n) for n in listRest(ComponentRef.nodes(exp.cref)));
2222
2223
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
2 for f in fields loop
2224 1 outExp := recordElement(f, outExp);
2225 end for;
2226 else
2227 outExp := exp;
2228 end if;
2229 then
2230 outExp;
2231
2232 else exp;
2233 end match;
2234 end replaceIterator2;
2235
2236 function containsIterator
2237 input Expression exp;
2238 input InstNode iterator;
2239 output Boolean res;
2240 protected
2241 function containsIterator2
2242 input Expression exp;
2243 input InstNode iterator;
2244 output Boolean res;
2245 algorithm
2246 res := match exp
2247 // Only the first (last in stored order) part of a cref can be an iterator: `i.x`.
2248 case CREF() guard ComponentRef.isIterator(exp.cref)
2249 621 then InstNode.refEqual(ComponentRef.node(ComponentRef.last(exp.cref)), iterator);
2250 else false;
2251 end match;
2252 end containsIterator2;
2253 algorithm
2254 3356 res := contains(exp, function containsIterator2(iterator = iterator));
2255 end containsIterator;
2256
2257 function arrayFromList
2258 input list<Expression> inExps;
2259 input Type elemTy;
2260 input list<Dimension> inDims;
2261 output Expression outExp;
2262 algorithm
2263 9787 outExp := arrayFromList_impl(inExps, elemTy, listReverse(inDims));
2264 end arrayFromList;
2265
2266 function arrayFromList_impl
2267 input list<Expression> inExps;
2268 input Type elemTy;
2269 input list<Dimension> inDims;
2270 output Expression outExp;
2271 protected
2272 Dimension ldim;
2273 list<Dimension> restdims;
2274 Type ty;
2275 list<Expression> newlst;
2276 list<list<Expression>> partexps;
2277 Integer dimsize;
2278 algorithm
2279 16455 Error.assertion(not listEmpty(inDims), "Empty dimension list given in arrayFromList.", sourceInfo());
2280
2281
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16455 times.
16455 ldim::restdims := inDims;
2282 16455 dimsize := Dimension.size(ldim);
2283 16455 ty := Type.liftArrayLeft(elemTy, ldim);
2284
2285
2/2
✓ Branch 1 taken 9787 times.
✓ Branch 2 taken 6668 times.
16455 if List.hasOneElement(inDims) then
2286 9787 Error.assertion(dimsize == listLength(inExps), "Length mismatch in arrayFromList.", sourceInfo());
2287 9787 outExp := makeArray(ty, listArray(inExps));
2288 9787 return;
2289 end if;
2290
2291 6668 partexps := List.partition(inExps, dimsize);
2292
2293 newlst := {};
2294
2/2
✓ Branch 0 taken 6975 times.
✓ Branch 1 taken 6668 times.
13643 for arrexp in partexps loop
2295 6975 newlst := makeArray(ty, listArray(arrexp))::newlst;
2296 end for;
2297
2298 6668 newlst := listReverse(newlst);
2299 6668 outExp := arrayFromList_impl(newlst, ty, restdims);
2300 end arrayFromList_impl;
2301
2302 function makeEnumLiteral
2303 input Type enumType;
2304 input Integer index;
2305 output Expression literal;
2306 protected
2307 list<String> literals;
2308 algorithm
2309
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 Type.ENUMERATION(literals = literals) := enumType;
2310 3 literal := ENUM_LITERAL(enumType, listGet(literals, index), index);
2311 end makeEnumLiteral;
2312
2313 function makeEnumLiterals
2314 input Type enumType;
2315 output list<Expression> literals;
2316 protected
2317 list<String> lits;
2318 algorithm
2319
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 Type.ENUMERATION(literals = lits) := enumType;
2320
7/8
✓ Branch 1 taken 178 times.
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 178 times.
✓ Branch 4 taken 27 times.
✓ Branch 5 taken 178 times.
✓ Branch 6 taken 27 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 27 times.
205 literals := list(ENUM_LITERAL(enumType, l, i)
2321 threaded for l in lits, i in 1:listLength(lits));
2322 end makeEnumLiterals;
2323
2324 function isIntegerValue
2325 "Returns true if the expression is an Integer expression with the given
2326 value, otherwise false."
2327 input Expression exp;
2328 input Integer value;
2329 output Boolean result;
2330 algorithm
2331 result := match exp
2332 4 case INTEGER() then exp.value == value;
2333 else false;
2334 end match;
2335 end isIntegerValue;
2336
2337 function toInteger
2338 input Expression exp;
2339 output Integer i;
2340 algorithm
2341 i := match exp
2342 497097 case INTEGER() then exp.value;
2343
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 case BOOLEAN() then if exp.value then 2 else 1;
2344 8 case ENUM_LITERAL() then exp.index;
2345 end match;
2346 end toInteger;
2347
2348 function toStringTyped
2349 input Expression exp;
2350 output String str;
2351 algorithm
2352 ✗ str := "/*" + Type.toString(typeOf(exp)) + "*/ " + toString(exp);
2353 end toStringTyped;
2354
2355 function toString
2356 input Expression exp;
2357 output String str;
2358 protected
2359 Type t;
2360 algorithm
2361 str := match exp
2362 39652 case INTEGER() then intString(exp.value);
2363 10365 case REAL() then realString(exp.value);
2364 269 case STRING() then "\"" + System.escapedString(exp.value, false) + "\"";
2365
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 169 times.
198 case BOOLEAN() then boolString(exp.value);
2366
2367 case ENUM_LITERAL(ty = t as Type.ENUMERATION())
2368 443 then AbsynUtil.pathString(t.typePath) + "." + exp.name;
2369
2370 2 case CLKCONST() then ClockKind.toString(exp.clk);
2371 111397 case CREF() then ComponentRef.toString(exp.cref);
2372 ✗ case TYPENAME() then Type.typenameString(Type.arrayElementType(exp.ty));
2373
4/4
✓ Branch 0 taken 12795 times.
✓ Branch 1 taken 3607 times.
✓ Branch 3 taken 12795 times.
✓ Branch 4 taken 3607 times.
32804 case ARRAY() then "{" + stringDelimitList(list(toString(e) for e in exp.elements), ", ") + "}";
2374 ✗ case MATRIX() then "[" + stringDelimitList(list(stringDelimitList(list(toString(e) for e in el), ", ") for el in exp.elements), "; ") + "]";
2375
2376
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1839 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 1826 times.
1839 case RANGE() then operandString(exp.start, exp, false) +
2377 (
2378 if isSome(exp.step)
2379 then ":" + operandString(Util.getOption(exp.step), exp, false)
2380 else ""
2381 ) + ":" + operandString(exp.stop, exp, false);
2382
2383
4/4
✓ Branch 0 taken 233 times.
✓ Branch 1 taken 79 times.
✓ Branch 2 taken 233 times.
✓ Branch 3 taken 79 times.
312 case TUPLE() then "(" + stringDelimitList(list(toString(e) for e in exp.elements), ", ") + ")";
2384 158 case RECORD() then List.toStringCustom(exp.elements, toString, AbsynUtil.pathString(exp.path), "(", ", ", ")", true);
2385 4691 case CALL() then Call.toString(exp.call);
2386
2/4
✗ Branch 2 not taken.
✓ Branch 3 taken 35 times.
✓ Branch 4 taken 35 times.
✗ Branch 5 not taken.
35 case SIZE() then "size(" + toString(exp.exp) +
2387 (
2388 if isSome(exp.dimIndex)
2389 then ", " + toString(Util.getOption(exp.dimIndex))
2390 else ""
2391 ) + ")";
2392 case END() then "end";
2393
2394 7154 case MULTARY() guard(listEmpty(exp.inv_arguments)) then multaryString(exp.arguments, exp, exp.operator, false);
2395
2396 case MULTARY() guard(listEmpty(exp.arguments) and Operator.isDashClassification(Operator.getMathClassification(exp.operator)))
2397 7 then "-" + multaryString(exp.inv_arguments, exp, exp.operator);
2398
2399 71 case MULTARY() guard(listEmpty(exp.arguments)) then "1/" + multaryString(exp.inv_arguments, exp, exp.operator);
2400
2401 2179 case MULTARY() then multaryString(exp.arguments, exp, exp.operator) +
2402 Operator.symbol(Operator.invert(exp.operator)) +
2403 multaryString(exp.inv_arguments, exp, exp.operator);
2404
2405 11087 case BINARY() then operandString(exp.exp1, exp, true) +
2406 Operator.symbol(exp.operator) +
2407 operandString(exp.exp2, exp, false);
2408
2409 2407 case UNARY() then Operator.symbol(exp.operator, "") +
2410 operandString(exp.exp, exp, false);
2411
2412 96 case LBINARY() then operandString(exp.exp1, exp, true) +
2413 Operator.symbol(exp.operator) +
2414 operandString(exp.exp2, exp, false);
2415
2416 17 case LUNARY() then Operator.symbol(exp.operator, "") + " " +
2417 operandString(exp.exp, exp, false);
2418
2419 613 case RELATION() then operandString(exp.exp1, exp, true) +
2420 Operator.symbol(exp.operator) +
2421 operandString(exp.exp2, exp, false);
2422
2423 135 case IF() then "if " + toString(exp.condition) + " then " + toString(exp.trueBranch) + " else " + toString(exp.falseBranch);
2424
2425
2/2
✓ Branch 1 taken 45 times.
✓ Branch 2 taken 414 times.
459 case CAST() then if Flags.isSet(Flags.NF_API) then
2426 toString(exp.exp)
2427 else
2428 "CAST(" + Type.toString(exp.ty) + ", " + toString(exp.exp) + ")";
2429
2430 3 case BOX() then "BOX(" + toString(exp.exp) + ")";
2431 ✗ case UNBOX() then "UNBOX(" + toString(exp.exp) + ")";
2432 69 case SUBSCRIPTED_EXP() then "(" + toString(exp.exp) + ")" + Subscript.toStringList(exp.subscripts);
2433 30 case TUPLE_ELEMENT() then toString(exp.tupleExp) + "[" + intString(exp.index) + "]";
2434 10 case RECORD_ELEMENT() then "(" + toString(exp.recordExp) + ")." + exp.fieldName;
2435 ✗ case MUTABLE() then toString(Mutable.access(exp.exp));
2436 ✗ case SHARED_LITERAL() then "LITERAL(" + intString(exp.index) + ", " + toString(exp.exp) + ")";
2437 case EMPTY() then "#EMPTY#";
2438 case PARTIAL_FUNCTION_APPLICATION()
2439
7/8
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 3 times.
✓ Branch 8 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
6 then "function " + ComponentRef.toString(exp.fn) + "(" + stringDelimitList(
2440 list(n + " = " + toString(a) threaded for a in exp.args, n in exp.argNames), ", ") + ")";
2441
2442 ✗ case FILENAME() then "\"" + System.escapedString(exp.filename, false) + "\"";
2443 case INSTANCE_NAME() then "getInstanceName()";
2444 ✗ else anyString(exp);
2445 end match;
2446 end toString;
2447
2448 function toFlatString
2449 input Expression exp;
2450 input BaseModelica.OutputFormat format;
2451 output String str;
2452 protected
2453 Type t;
2454 algorithm
2455 str := match exp
2456 1703 case INTEGER() then intString(exp.value);
2457 1467 case REAL() then realString(exp.value);
2458 3 case STRING() then "\"" + Util.escapeModelicaStringToCString(exp.value) + "\"";
2459
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 12 times.
15 case BOOLEAN() then boolString(exp.value);
2460
2461 case ENUM_LITERAL(ty = t as Type.ENUMERATION())
2462
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 then if Type.isBuiltinEnumeration(t) then
2463 AbsynUtil.pathString(t.typePath) + "." + exp.name
2464 else
2465 Util.makeQuotedIdentifier(AbsynUtil.pathString(t.typePath)) + "." + Util.makeQuotedIdentifier(exp.name);
2466
2467 ✗ case CLKCONST() then ClockKind.toFlatString(exp.clk, format);
2468
2469 672 case CREF() then ComponentRef.toFlatString(exp.cref, format);
2470 ✗ case TYPENAME() then Type.typenameString(Type.arrayElementType(exp.ty));
2471
2472 case ARRAY()
2473
6/8
✗ Branch 0 not taken.
✓ Branch 1 taken 337 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 337 times.
✓ Branch 12 taken 988 times.
✓ Branch 13 taken 337 times.
✓ Branch 15 taken 988 times.
✓ Branch 16 taken 337 times.
2987 then if arrayEmpty(exp.elements) then
2474 "fill("+toFlatString(makeDefaultValue(Type.elementType(exp.ty)), format)+", " + Type.dimensionsToFlatString(exp.ty, format) + ")"
2475 else
2476 "{" + stringDelimitList(list(toFlatString(e, format) for e in exp.elements), ", ") + "}";
2477
2478 ✗ case MATRIX() then "[" + stringDelimitList(list(stringDelimitList(list(toFlatString(e, format) for e in el), ", ") for el in exp.elements), "; ") + "]";
2479
2480
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 19 times.
19 case RANGE() then operandFlatString(exp.start, exp, false, format) +
2481 (
2482 if isSome(exp.step)
2483 then ":" + operandFlatString(Util.getOption(exp.step), exp, false, format)
2484 else ""
2485 ) + ":" + operandFlatString(exp.stop, exp, false, format);
2486
2487 ✗ case TUPLE() then "(" + stringDelimitList(list(toFlatString(e, format) for e in exp.elements), ", ") + ")";
2488 137 case RECORD() then List.toStringCustom(exp.elements, function toFlatString(format = format), Type.toFlatString(exp.ty, format), "(", ", ", ")", true);
2489 106 case CALL() then Call.toFlatString(exp.call, format);
2490 ✗ case SIZE() then "size(" + toFlatString(exp.exp, format) +
2491 (
2492 if isSome(exp.dimIndex)
2493 then ", " + toFlatString(Util.getOption(exp.dimIndex), format)
2494 else ""
2495 ) + ")";
2496 case END() then "end";
2497
2498 4 case MULTARY() guard(listEmpty(exp.inv_arguments)) then multaryFlatString(exp.arguments, exp, exp.operator, format, false);
2499
2500 case MULTARY() guard(listEmpty(exp.arguments) and Operator.isDashClassification(Operator.getMathClassification(exp.operator)))
2501 1 then "-" + multaryFlatString(exp.inv_arguments, exp, exp.operator, format);
2502
2503 ✗ case MULTARY() guard(listEmpty(exp.arguments)) then "1/" + multaryFlatString(exp.inv_arguments, exp, exp.operator, format);
2504
2505 4 case MULTARY() then multaryFlatString(exp.arguments, exp, exp.operator, format) +
2506 Operator.symbol(Operator.invert(exp.operator)) +
2507 multaryFlatString(exp.inv_arguments, exp, exp.operator, format);
2508
2509 155 case BINARY() then operandFlatString(exp.exp1, exp, true, format) +
2510 Operator.symbol(exp.operator) +
2511 operandFlatString(exp.exp2, exp, false, format);
2512
2513 15 case UNARY() then Operator.symbol(exp.operator, "") +
2514 operandFlatString(exp.exp, exp, false, format);
2515
2516 ✗ case LBINARY() then operandFlatString(exp.exp1, exp, true, format) +
2517 Operator.symbol(exp.operator) +
2518 operandFlatString(exp.exp2, exp, false, format);
2519
2520 ✗ case LUNARY() then Operator.symbol(exp.operator, "") + " " +
2521 operandFlatString(exp.exp, exp, false, format);
2522
2523 18 case RELATION() then operandFlatString(exp.exp1, exp, true, format) +
2524 Operator.symbol(exp.operator) +
2525 operandFlatString(exp.exp2, exp, false, format);
2526
2527 16 case IF() then "if " + toFlatString(exp.condition, format) + " then " + toFlatString(exp.trueBranch, format) + " else " + toFlatString(exp.falseBranch, format);
2528
2529 1 case CAST() then toFlatString(exp.exp, format);
2530 ✗ case UNBOX() then toFlatString(exp.exp, format);
2531 ✗ case BOX() then toFlatString(exp.exp, format);
2532
2533 8 case SUBSCRIPTED_EXP() then "(" + toFlatString(exp.exp, format) + ")" + Subscript.toFlatStringList(exp.subscripts, format, escapeQuotes = false);
2534 1 case TUPLE_ELEMENT() then toFlatString(exp.tupleExp, format);
2535 ✗ case RECORD_ELEMENT() then "(" + toFlatString(exp.recordExp, format) + ")." + exp.fieldName;
2536 ✗ case MUTABLE() then toFlatString(Mutable.access(exp.exp), format);
2537 ✗ case SHARED_LITERAL() then "[literal: " + intString(exp.index) + ", " + toString(exp.exp) + "]";
2538 case EMPTY() then "#EMPTY#";
2539 case PARTIAL_FUNCTION_APPLICATION()
2540 ✗ then "function " + ComponentRef.toFlatString(exp.fn, format) + "(" + stringDelimitList(
2541 list(n + " = " + toFlatString(a, format) threaded for a in exp.args, n in exp.argNames), ", ") + ")";
2542
2543 ✗ case FILENAME() then "\"" + Util.escapeModelicaStringToCString(exp.filename) + "\"";
2544 case INSTANCE_NAME() then "getInstanceName()";
2545 ✗ else anyString(exp);
2546 end match;
2547 end toFlatString;
2548
2549 function operandString
2550 "Helper function to toString, prints an operator and adds parentheses as needed."
2551 input Expression operand;
2552 input Expression operator;
2553 input Boolean lhs;
2554 output String str;
2555 protected
2556 Integer operand_prio, operator_prio;
2557 Boolean parenthesize = false;
2558 algorithm
2559 48898 str := toString(operand);
2560 48898 operand_prio := priority(operand, lhs);
2561
2562
2/2
✓ Branch 0 taken 46604 times.
✓ Branch 1 taken 2294 times.
48898 if operand_prio == 4 then
2563 parenthesize := true;
2564 else
2565 46604 operator_prio := priority(operator, lhs);
2566
2567
2/2
✓ Branch 0 taken 44413 times.
✓ Branch 1 taken 2191 times.
46604 if operand_prio > operator_prio then
2568 parenthesize := true;
2569 elseif operand_prio == operator_prio then
2570
2/2
✓ Branch 0 taken 2157 times.
✓ Branch 1 taken 809 times.
2966 parenthesize := if lhs then isNonAssociativeExp(operand) else not
2571 isAssociativeExp(operand);
2572 end if;
2573 end if;
2574
2575
2/2
✓ Branch 0 taken 2246 times.
✓ Branch 1 taken 720 times.
2966 if parenthesize then
2576 5205 str := "(" + str + ")";
2577 end if;
2578 end operandString;
2579
2580 function operandFlatString
2581 "Helper function to toString, prints an operator and adds parentheses as needed."
2582 input Expression operand;
2583 input Expression operator;
2584 input Boolean lhs;
2585 input BaseModelica.OutputFormat format;
2586 output String str;
2587 protected
2588 Integer operand_prio, operator_prio;
2589 Boolean parenthesize = false;
2590 algorithm
2591 424 str := toFlatString(operand, format);
2592 424 operand_prio := priority(operand, lhs);
2593
2594
1/2
✓ Branch 0 taken 424 times.
✗ Branch 1 not taken.
424 if operand_prio == 4 then
2595 parenthesize := true;
2596 else
2597 424 operator_prio := priority(operator, lhs);
2598
2599
2/2
✓ Branch 0 taken 398 times.
✓ Branch 1 taken 26 times.
424 if operand_prio > operator_prio then
2600 parenthesize := true;
2601 elseif operand_prio == operator_prio then
2602
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 4 times.
31 parenthesize := if lhs then isNonAssociativeExp(operand)
2603 else not isAssociativeExp(operand);
2604 end if;
2605 end if;
2606
2607
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 2 times.
31 if parenthesize then
2608 28 str := "(" + str + ")";
2609 end if;
2610 end operandFlatString;
2611
2612 function multaryString
2613 input list<Expression> arguments;
2614 input Expression exp;
2615 input Operator operator;
2616 input Boolean parenthesize = true;
2617 output String str;
2618 algorithm
2619
4/4
✓ Branch 0 taken 19191 times.
✓ Branch 1 taken 11590 times.
✓ Branch 2 taken 19191 times.
✓ Branch 3 taken 11590 times.
30781 str := stringDelimitList(list(operandString(e, exp, false) for e in arguments), Operator.symbol(operator));
2620
4/4
✓ Branch 0 taken 7154 times.
✓ Branch 1 taken 4436 times.
✓ Branch 3 taken 4347 times.
✓ Branch 4 taken 89 times.
11590 if parenthesize and listLength(arguments) > 1 then
2621 89 str := "(" + str + ")";
2622 end if;
2623 end multaryString;
2624
2625 function multaryFlatString
2626 input list<Expression> arguments;
2627 input Expression exp;
2628 input Operator operator;
2629 input BaseModelica.OutputFormat format;
2630 input Boolean parenthesize = true;
2631 output String str;
2632 algorithm
2633
4/4
✓ Branch 0 taken 25 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 13 times.
38 str := stringDelimitList(list(operandFlatString(e, exp, false, format) for e in arguments), Operator.symbol(operator));
2634
4/4
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 9 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 5 times.
13 if parenthesize and listLength(arguments) > 1 then
2635 5 str := "(" + str + ")";
2636 end if;
2637 end multaryFlatString;
2638
2639 function priority
2640 input Expression exp;
2641 input Boolean lhs;
2642 output Integer priority;
2643 algorithm
2644 priority := match exp
2645 12972 case INTEGER() then if exp.value < 0 then 4 else 0;
2646
2/2
✓ Branch 0 taken 3148 times.
✓ Branch 1 taken 211 times.
3359 case REAL() then if exp.value < 0.0 then 4 else 0;
2647 20274 case MULTARY() then Operator.priority(exp.operator, lhs);
2648 28059 case BINARY() then Operator.priority(exp.operator, lhs);
2649 case UNARY() then 4;
2650 221 case LBINARY() then Operator.priority(exp.operator, lhs);
2651 case LUNARY() then 7;
2652 case RELATION() then 6;
2653 case RANGE() then 10;
2654 case IF() then 11;
2655 387 case CAST() then priority(exp.exp, lhs);
2656 ✗ case BOX() then priority(exp.exp, lhs);
2657 ✗ case UNBOX() then priority(exp.exp, lhs);
2658 else 0;
2659 end match;
2660 end priority;
2661
2662 function isAssociativeExp
2663 input Expression exp;
2664 output Boolean isAssociative;
2665 algorithm
2666 isAssociative := match exp
2667 182 case BINARY() then Operator.isAssociative(exp.operator);
2668 case LBINARY() then true;
2669 else false;
2670 end match;
2671 end isAssociativeExp;
2672
2673 function isNonAssociativeExp
2674 input Expression exp;
2675 output Boolean isAssociative;
2676 algorithm
2677 isAssociative := match exp
2678 2174 case BINARY() then Operator.isNonAssociative(exp.operator);
2679 case LBINARY() then true;
2680 else false;
2681 end match;
2682 end isNonAssociativeExp;
2683
2684 function getName
2685 "Returns the 'name' of an Expression, for example the function name of a
2686 call or the record class name of a record expression."
2687 input Expression exp;
2688 output String name;
2689 algorithm
2690 name := match exp
2691 ✗ case RECORD() then AbsynUtil.pathString(exp.path);
2692 18 case CALL() then AbsynUtil.pathString(Call.functionName(exp.call));
2693 ✗ case CAST() then getName(exp.exp);
2694 ✗ case BOX() then getName(exp.exp);
2695 ✗ case UNBOX() then getName(exp.exp);
2696 ✗ case MUTABLE() then getName(Mutable.access(exp.exp));
2697 ✗ case SHARED_LITERAL() then getName(exp.exp);
2698 ✗ case PARTIAL_FUNCTION_APPLICATION() then ComponentRef.toString(exp.fn);
2699 case INSTANCE_NAME() then "getInstanceName";
2700 ✗ else toString(exp);
2701 end match;
2702 end getName;
2703
2704 function enumLiteralPath
2705 input Expression exp;
2706 output Absyn.Path path;
2707 protected
2708 String name;
2709 Absyn.Path ty_path;
2710 algorithm
2711
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 20546 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20546 times.
20546 ENUM_LITERAL(name = name, ty = Type.ENUMERATION(typePath = ty_path)) := exp;
2712 20546 path := AbsynUtil.suffixPath(ty_path, name);
2713 end enumLiteralPath;
2714
2715 function getNominal
2716 input output Expression exp;
2717 algorithm
2718 54 exp := Expression.map(exp, computeNominal);
2719 54 exp := SimplifyExp.simplify(exp);
2720 end getNominal;
2721
2722 function computeNominal
2723 "Replaces variable crefs with their nominal values and normalizes by removing all negations.
2724 Needs to be mapped with Expression.map()"
2725 input output Expression exp;
2726 algorithm
2727 exp := match exp
2728 local
2729 PointerWeak<Variable> varPointer;
2730 Option<Expression> nominal;
2731 Operator operator;
2732 Operator.SizeClassification sizeClass;
2733
2734 // replace variables with their nominal values
2735 case CREF(cref = ComponentRef.CREF())
2736 guard InstNode.isVar(ComponentRef.node(exp.cref))
2737 algorithm
2738
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 InstNode.VAR_NODE(varPointer = varPointer) := ComponentRef.node(exp.cref);
2739 4 nominal := Variable.getNominal(Pointer.access(PointerWeak.upgrade(varPointer)));
2740 4 then Util.getOptionOrDefault(nominal, exp);
2741
2742 // remove negation
2743 18 case INTEGER() then INTEGER(abs(exp.value));
2744 79 case REAL() then REAL(abs(exp.value));
2745 1 case UNARY() then exp.exp;
2746
2747 // replace binary - with +
2748 case BINARY(operator = operator) guard(Operator.getMathClassification(operator) == NFOperator.MathClassification.SUBTRACTION) algorithm
2749 ✗ (_, sizeClass) := Operator.classify(operator);
2750 ✗ exp.operator := Operator.fromClassification((NFOperator.MathClassification.ADDITION, sizeClass), operator.ty);
2751 then exp;
2752
2753 // replace multary - with +
2754 case MULTARY(operator = operator) guard(Operator.getMathClassification(operator) == NFOperator.MathClassification.ADDITION) algorithm
2755 11 exp.arguments := listAppend(exp.arguments, exp.inv_arguments);
2756 11 exp.inv_arguments := {};
2757 then exp;
2758
2759 else exp;
2760 end match;
2761 end computeNominal;
2762
2763 function toAbsyn
2764 input Expression exp;
2765 output Absyn.Exp aexp;
2766 algorithm
2767 aexp := match exp
2768 local
2769 Type ty;
2770
2771 ✗ case INTEGER() then Absyn.Exp.INTEGER(exp.value);
2772 ✗ case REAL() then Absyn.Exp.REAL(String(exp.value));
2773 ✗ case STRING() then Absyn.Exp.STRING(exp.value);
2774 4773 case BOOLEAN() then Absyn.Exp.BOOL(exp.value);
2775 case ENUM_LITERAL(ty=Type.ENUMERATION())
2776 ✗ then Absyn.Exp.CREF(AbsynUtil.pathToCref(enumLiteralPath(exp)));
2777 ✗ case CLKCONST() then ClockKind.toAbsyn(exp.clk);
2778 ✗ case CREF() then Absyn.Exp.CREF(ComponentRef.toAbsyn(exp.cref));
2779 ✗ case TYPENAME() then Absyn.Exp.CREF(Absyn.ComponentRef.CREF_IDENT(Type.toString(exp.ty), {}));
2780 ✗ case ARRAY() then Absyn.Exp.ARRAY(list(toAbsyn(e) for e in exp.elements));
2781 ✗ case MATRIX() then Absyn.Exp.MATRIX(list(list(toAbsyn(e) for e in l) for l in exp.elements));
2782 ✗ case RANGE() then Absyn.Exp.RANGE(toAbsyn(exp.start), Util.applyOption(exp.step, toAbsyn), toAbsyn(exp.stop));
2783 ✗ case TUPLE() then Absyn.Exp.TUPLE(list(toAbsyn(e) for e in exp.elements));
2784 ✗ case RECORD() then AbsynUtil.makeCall(AbsynUtil.pathToCref(exp.path), list(toAbsyn(e) for e in exp.elements));
2785 ✗ case CALL() then Call.toAbsyn(exp.call);
2786 ✗ case SIZE() then AbsynUtil.makeCall(Absyn.ComponentRef.CREF_IDENT("size", {}),
2787 if isSome(exp.dimIndex) then {toAbsyn(Util.getOption(exp.dimIndex))} else {});
2788 case END() then Absyn.Exp.END();
2789 ✗ case BINARY() then Absyn.Exp.BINARY(toAbsyn(exp.exp1), Operator.toAbsyn(exp.operator), toAbsyn(exp.exp2));
2790 ✗ case UNARY() then Absyn.Exp.UNARY(Operator.toAbsyn(exp.operator), toAbsyn(exp.exp));
2791 ✗ case LBINARY() then Absyn.Exp.LBINARY(toAbsyn(exp.exp1), Operator.toAbsyn(exp.operator), toAbsyn(exp.exp2));
2792 ✗ case LUNARY() then Absyn.Exp.LUNARY(Operator.toAbsyn(exp.operator), toAbsyn(exp.exp));
2793 ✗ case RELATION() then Absyn.Exp.RELATION(toAbsyn(exp.exp1), Operator.toAbsyn(exp.operator), toAbsyn(exp.exp2));
2794 ✗ case IF() then Absyn.Exp.IFEXP(toAbsyn(exp.condition), toAbsyn(exp.trueBranch), toAbsyn(exp.falseBranch), {});
2795 ✗ case CAST() then toAbsyn(exp.exp);
2796 ✗ case BOX() then toAbsyn(exp.exp);
2797 ✗ case UNBOX() then toAbsyn(exp.exp);
2798 ✗ case MUTABLE() then toAbsyn(Mutable.access(exp.exp));
2799 ✗ case SHARED_LITERAL() then toAbsyn(exp.exp);
2800 case PARTIAL_FUNCTION_APPLICATION()
2801 ✗ then Absyn.Exp.PARTEVALFUNCTION(ComponentRef.toAbsyn(exp.fn),
2802 Absyn.FunctionArgs.FUNCTIONARGS(list(toAbsyn(e) for e in exp.args), {}));
2803 ✗ case FILENAME() then Absyn.Exp.STRING(exp.filename);
2804 ✗ case INSTANCE_NAME() then AbsynUtil.makeCall(Absyn.ComponentRef.CREF_IDENT("getInstanceName", {}), {});
2805
2806 else
2807 algorithm
2808 ✗ Error.terminate(getInstanceName() + " got unknown expression '" + toString(exp) + "'", sourceInfo());
2809 ✗ then
2810 fail();
2811
2812 end match;
2813 end toAbsyn;
2814
2815 function toDAE
2816 input Expression exp;
2817 input Boolean allowEmpty = false "Whether to allow conversion of EMPTY or not";
2818 output DAE.Exp dexp;
2819 algorithm
2820 dexp := match exp
2821 local
2822 DAE.Operator daeOp;
2823 Boolean swap, negate;
2824 DAE.Exp dae1, dae2;
2825 Function.Function fn;
2826 DAE.Type dty;
2827
2828 934927 case INTEGER() then DAE.ICONST(exp.value);
2829 657928 case REAL() then DAE.RCONST(exp.value);
2830 518698 case STRING() then DAE.SCONST(exp.value);
2831 33636 case BOOLEAN() then DAE.BCONST(exp.value);
2832 20546 case ENUM_LITERAL() then DAE.ENUM_LITERAL(enumLiteralPath(exp), exp.index);
2833
2834 case CLKCONST()
2835 76 then DAE.CLKCONST(ClockKind.toDAE(exp.clk));
2836
2837 case CREF()
2838 966752 then DAE.CREF(ComponentRef.toDAE(exp.cref), Type.toDAE(exp.ty));
2839
2840 case TYPENAME()
2841 ✗ then toDAE(ExpandExp.expandTypename(exp.ty));
2842
2843 case ARRAY()
2844
6/6
✓ Branch 0 taken 160263 times.
✓ Branch 1 taken 37335 times.
✓ Branch 3 taken 160263 times.
✓ Branch 4 taken 37335 times.
✓ Branch 7 taken 2701 times.
✓ Branch 8 taken 34634 times.
397897 then DAE.ARRAY(Type.toDAE(exp.ty), Type.isVector(exp.ty),
2845 list(toDAE(e) for e in exp.elements));
2846
2847 2454 case RECORD() then toDAERecord(exp.ty, exp.path, exp.elements);
2848
2849 case RANGE()
2850
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1299 times.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 1287 times.
1311 then DAE.RANGE(
2851 Type.toDAE(exp.ty),
2852 toDAE(exp.start),
2853 if isSome(exp.step)
2854 then SOME(toDAE(Util.getOption(exp.step)))
2855 else NONE(),
2856 toDAE(exp.stop));
2857
2858
4/4
✓ Branch 0 taken 345 times.
✓ Branch 1 taken 161 times.
✓ Branch 2 taken 345 times.
✓ Branch 3 taken 161 times.
506 case TUPLE() then DAE.TUPLE(list(toDAE(e) for e in exp.elements));
2859 73055 case CALL() then Call.toDAE(exp.call);
2860
2861 case SIZE()
2862
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4756 times.
✓ Branch 2 taken 4753 times.
✓ Branch 3 taken 3 times.
9509 then DAE.SIZE(toDAE(exp.exp),
2863 if isSome(exp.dimIndex)
2864 then SOME(toDAE(Util.getOption(exp.dimIndex)))
2865 else NONE());
2866
2867 // END() doesn't have a DAE representation.
2868
2869 // convert to binaries by splitting then use toDAE on result
2870 35991 case MULTARY() then toDAE(SimplifyExp.splitMultary(exp));
2871
2872 case BINARY()
2873 algorithm
2874 709747 (daeOp, swap, negate) := Operator.toDAE(exp.operator);
2875 709747 dae1 := toDAE(exp.exp1);
2876
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 709746 times.
709747 dae2 := toDAE(if negate then negate(exp.exp2) else exp.exp2);
2877
4/4
✓ Branch 0 taken 709401 times.
✓ Branch 1 taken 346 times.
✓ Branch 2 taken 709401 times.
✓ Branch 3 taken 346 times.
2128549 then
2878 DAE.BINARY(if swap then dae2 else dae1, daeOp, if swap then dae1 else dae2);
2879
2880 27443 case UNARY() then DAE.UNARY(Operator.toDAE(exp.operator), toDAE(exp.exp));
2881 3802 case LBINARY() then DAE.LBINARY(toDAE(exp.exp1), Operator.toDAE(exp.operator), toDAE(exp.exp2));
2882 920 case LUNARY() then DAE.LUNARY(Operator.toDAE(exp.operator), toDAE(exp.exp));
2883 19565 case RELATION() then DAE.RELATION(toDAE(exp.exp1), Operator.toDAE(exp.operator), toDAE(exp.exp2), exp.index, NONE());
2884 6383 case IF() then DAE.IFEXP(toDAE(exp.condition), toDAE(exp.trueBranch), toDAE(exp.falseBranch));
2885 4333 case CAST() then DAE.CAST(Type.toDAE(exp.ty), toDAE(exp.exp));
2886 195 case BOX() then DAE.BOX(toDAE(exp.exp));
2887 65 case UNBOX() then DAE.UNBOX(toDAE(exp.exp), Type.toDAE(exp.ty));
2888
2889 case SUBSCRIPTED_EXP()
2890
4/4
✓ Branch 0 taken 2529 times.
✓ Branch 1 taken 2390 times.
✓ Branch 2 taken 2529 times.
✓ Branch 3 taken 2390 times.
4919 then DAE.ASUB(toDAE(exp.exp), list(Subscript.toDAE(s) for s in exp.subscripts));
2891
2892 case TUPLE_ELEMENT()
2893 108 then DAE.TSUB(toDAE(exp.tupleExp), exp.index, Type.toDAE(exp.ty));
2894
2895 case RECORD_ELEMENT()
2896 113 then DAE.RSUB(toDAE(exp.recordExp), -1, exp.fieldName, Type.toDAE(exp.ty));
2897
2898 case PARTIAL_FUNCTION_APPLICATION()
2899 algorithm
2900
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
33 fn :: _ := Function.Function.typeRefCache(exp.fn);
2901
4/4
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 106 times.
✓ Branch 3 taken 33 times.
139 then
2902 DAE.PARTEVALFUNCTION(Function.Function.nameConsiderBuiltin(fn),
2903 list(toDAE(arg) for arg in exp.args),
2904 Type.toDAE(exp.ty),
2905 Type.toDAE(Type.FUNCTION(fn, NFType.FunctionType.FUNCTIONAL_VARIABLE)));
2906
2907 ✗ case MUTABLE() then toDAE(Mutable.access(exp.exp));
2908
2909 // EMPTY expressions can be a sign of something having gone wrong, but we want to allow them in
2910 // some cases such as in records, so only allow them if the caller requests it.
2911 case EMPTY()
2912 guard allowEmpty
2913 algorithm
2914 ✗ dty := Type.toDAE(exp.ty);
2915 ✗ then
2916 DAE.EMPTY("", DAE.CREF_IDENT("$dummy", dty, {}), dty, Type.toString(exp.ty));
2917
2918 2723 case SHARED_LITERAL() then DAE.SHARED_LITERAL(exp.index, toDAE(exp.exp));
2919 case FILENAME()
2920
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 then if Flags.getConfigBool(Flags.BUILDING_FMU) then
2921 DAE.CALL(Absyn.Path.IDENT("OpenModelica_fmuLoadResource"),
2922 {DAE.SCONST(exp.filename)}, DAE.callAttrBuiltinImpureString)
2923 else
2924 DAE.SCONST(exp.filename);
2925 case INSTANCE_NAME() then DAE.CALL(Absyn.Path.IDENT("getInstanceName"), {}, DAE.callAttrBuiltinString);
2926
2927 else
2928 algorithm
2929 ✗ Error.terminate(getInstanceName() + " got unknown expression '" + toString(exp) + "'", sourceInfo());
2930 ✗ then
2931 fail();
2932
2933 end match;
2934 end toDAE;
2935
2936 function toDAERecord
2937 input Type ty;
2938 input Absyn.Path path;
2939 input list<Expression> args;
2940 output DAE.Exp exp;
2941 protected
2942 list<String> field_names = {};
2943 Expression arg;
2944 list<Expression> rest_args = args;
2945 list<DAE.Exp> dargs = {};
2946 algorithm
2947
2/2
✓ Branch 2 taken 27115 times.
✓ Branch 3 taken 2454 times.
29569 for field in Type.recordFields(Type.unbox(ty)) loop
2948
3/5
✗ Branch 0 not taken.
✓ Branch 1 taken 27115 times.
✓ Branch 3 taken 27113 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
27115 arg :: rest_args := rest_args;
2949
2950 () := match field
2951 case Record.Field.INPUT()
2952 algorithm
2953 27113 field_names := field.name :: field_names;
2954 27113 dargs := toDAE(arg, allowEmpty = true) :: dargs;
2955 then
2956 ();
2957
2958 // TODO: Constants/parameters shouldn't be added to record expressions
2959 // since that causes issues with the backend, but removing them
2960 // currently causes even worse issues.
2961 case Record.Field.LOCAL()
2962 algorithm
2963 2 field_names := field.name :: field_names;
2964 2 dargs := toDAE(arg, allowEmpty = true) :: dargs;
2965 then
2966 ();
2967
2968 else ();
2969 end match;
2970 end for;
2971
2972 2454 field_names := listReverseInPlace(field_names);
2973 2454 dargs := listReverseInPlace(dargs);
2974
2975
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2451 times.
2454 exp := if Type.isBoxed(ty) then
2976 DAE.METARECORDCALL(path, dargs, field_names, -1, {})
2977 else
2978 DAE.RECORD(path, dargs, field_names, Type.toDAE(ty));
2979 end toDAERecord;
2980
2981 function toDAEValue
2982 input Expression exp;
2983 output Values.Value value;
2984 algorithm
2985 value := match exp
2986 local
2987 Type ty;
2988
2989 3 case INTEGER() then Values.INTEGER(exp.value);
2990 47 case REAL() then Values.REAL(exp.value);
2991 ✗ case STRING() then Values.STRING(exp.value);
2992 ✗ case BOOLEAN() then Values.BOOL(exp.value);
2993 case ENUM_LITERAL(ty = ty as Type.ENUMERATION())
2994 ✗ then Values.ENUM_LITERAL(AbsynUtil.suffixPath(ty.typePath, exp.name), exp.index);
2995 ✗ case ARRAY() then ValuesMake.makeArray(list(toDAEValue(e) for e in exp.elements));
2996 1 case RECORD() then toDAEValueRecord(exp.ty, exp.path, exp.elements);
2997 ✗ case FILENAME() then Values.STRING(exp.filename);
2998
2999 else
3000 algorithm
3001 ✗ Error.terminate(getInstanceName() + " got unhandled expression " + toString(exp), sourceInfo());
3002 ✗ then
3003 fail();
3004 end match;
3005 end toDAEValue;
3006
3007 function toDAEValueRecord
3008 input Type ty;
3009 input Absyn.Path path;
3010 input list<Expression> args;
3011 output Values.Value value;
3012 protected
3013 list<String> field_names = {};
3014 Expression arg;
3015 list<Expression> rest_args = args;
3016 list<Values.Value> values = {};
3017 algorithm
3018
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 time.
3 for field in Type.recordFields(ty) loop
3019
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 arg :: rest_args := rest_args;
3020
3021 () := match field
3022 case Record.Field.INPUT()
3023 algorithm
3024 2 field_names := field.name :: field_names;
3025 2 values := toDAEValue(arg) :: values;
3026 then
3027 ();
3028
3029 else ();
3030 end match;
3031 end for;
3032
3033 1 field_names := listReverseInPlace(field_names);
3034 1 values := listReverseInPlace(values);
3035 1 value := Values.RECORD(path, values, field_names, -1);
3036 end toDAEValueRecord;
3037
3038 function dimensionCount
3039 input Expression exp;
3040 input Boolean isDim = false;
3041 output Integer dimCount;
3042 algorithm
3043 dimCount := match exp
3044 // Typenames expand to arrays when used as e.g. iteration ranges, but when used as a
3045 // dimension they work the same as an Integer and are treated as scalars.
3046 53 case TYPENAME() then if isDim then 0 else 1;
3047 case ARRAY(ty = Type.UNKNOWN())
3048 ✗ then 1 + dimensionCount(arrayGet(exp.elements, 1));
3049 case MATRIX() then 2;
3050
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 664 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 664 times.
664 case SIZE() then if isNone(exp.dimIndex) then dimensionCount(exp.exp) else 0;
3051 265374 else Type.dimensionCount(typeOf(exp));
3052 end match;
3053 end dimensionCount;
3054
3055 function dimensions
3056 input Expression exp;
3057 output list<Dimension> dims;
3058 algorithm
3059 ✗ dims := Type.arrayDims(typeOf(exp));
3060 end dimensions;
3061
3062 function map
3063 "Applies a function recursively (depth-first, post-order) to an expression
3064 and creates a new expression from the returned values.
3065 NOTE: For performance reasons this function does not recurse into arrays
3066 marked as literal."
3067 input Expression exp;
3068 input MapFunc func;
3069 output Expression outExp;
3070
3071 partial function MapFunc
3072 input output Expression e;
3073 end MapFunc;
3074 algorithm
3075 outExp := match exp
3076 local
3077 Expression e1, e2, e3, e4;
3078
3079 525 case CLKCONST() then CLKCONST(ClockKind.mapExp(exp.clk, func));
3080 4381439 case CREF() then CREF(exp.ty, ComponentRef.mapExp(exp.cref, func));
3081 574203 case ARRAY() guard not exp.literal then makeArray(exp.ty, Array.map(exp.elements, function map(func = func)), exp.literal);
3082
8/8
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 16 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 16 times.
✓ Branch 7 taken 8 times.
26 case MATRIX() then MATRIX(list(list(map(e, func) for e in row) for row in exp.elements));
3083
3084 case RANGE(step = SOME(e2))
3085 algorithm
3086 292 e1 := map(exp.start, func);
3087 292 e4 := map(e2, func);
3088 292 e3 := map(exp.stop, func);
3089
5/6
✓ Branch 0 taken 273 times.
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 273 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 267 times.
317 then
3090 if referenceEq(exp.start, e1) and referenceEq(e2, e4) and
3091 referenceEq(exp.stop, e3) then exp else RANGE(exp.ty, e1, SOME(e4), e3);
3092
3093 case RANGE()
3094 algorithm
3095 36050 e1 := map(exp.start, func);
3096 36050 e3 := map(exp.stop, func);
3097
4/4
✓ Branch 0 taken 35810 times.
✓ Branch 1 taken 240 times.
✓ Branch 2 taken 4638 times.
✓ Branch 3 taken 31172 times.
36050 then
3098 if referenceEq(exp.start, e1) and referenceEq(exp.stop, e3)
3099 then exp else RANGE(exp.ty, e1, NONE(), e3);
3100
3101
4/4
✓ Branch 0 taken 6415 times.
✓ Branch 1 taken 2519 times.
✓ Branch 2 taken 6415 times.
✓ Branch 3 taken 2519 times.
8934 case TUPLE() then TUPLE(exp.ty, list(map(e, func) for e in exp.elements));
3102
3103 case RECORD()
3104
4/4
✓ Branch 0 taken 406599 times.
✓ Branch 1 taken 28416 times.
✓ Branch 2 taken 406599 times.
✓ Branch 3 taken 28416 times.
435015 then RECORD(exp.path, exp.ty, list(map(e, func) for e in exp.elements));
3105
3106 719210 case CALL() then CALL(Call.mapExp(exp.call, func));
3107
3108 case SIZE(dimIndex = SOME(e2))
3109 algorithm
3110 15996 e1 := map(exp.exp, func);
3111 15996 e3 := map(e2, func);
3112
3/4
✓ Branch 0 taken 108 times.
✓ Branch 1 taken 15888 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 108 times.
31884 then
3113 if referenceEq(exp.exp, e1) and referenceEq(e2, e3) then exp else SIZE(e1, SOME(e3));
3114
3115 case SIZE()
3116 algorithm
3117 11 e1 := map(exp.exp, func);
3118
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 then
3119 if referenceEq(exp.exp, e1) then exp else SIZE(e1, NONE());
3120
3121 case BINARY()
3122 algorithm
3123 2368335 e1 := map(exp.exp1, func);
3124 2368335 e2 := map(exp.exp2, func);
3125
4/4
✓ Branch 0 taken 407342 times.
✓ Branch 1 taken 1960993 times.
✓ Branch 2 taken 399832 times.
✓ Branch 3 taken 7510 times.
2368335 then
3126 if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2)
3127 then exp else BINARY(e1, exp.operator, e2);
3128
3129 case MULTARY()
3130 algorithm
3131 // ToDo: referenceEq ?
3132
4/4
✓ Branch 0 taken 421507 times.
✓ Branch 1 taken 232112 times.
✓ Branch 2 taken 421507 times.
✓ Branch 3 taken 232112 times.
885731 exp.arguments := list(map(arg, func) for arg in exp.arguments);
3133
4/4
✓ Branch 0 taken 73326 times.
✓ Branch 1 taken 232112 times.
✓ Branch 2 taken 73326 times.
✓ Branch 3 taken 232112 times.
537550 exp.inv_arguments := list(map(arg, func) for arg in exp.inv_arguments);
3134 then exp;
3135
3136 case UNARY()
3137 algorithm
3138 108485 e1 := map(exp.exp, func);
3139
2/2
✓ Branch 0 taken 108444 times.
✓ Branch 1 taken 41 times.
108485 then
3140 if referenceEq(exp.exp, e1) then exp else UNARY(exp.operator, e1);
3141
3142 case LBINARY()
3143 algorithm
3144 19129 e1 := map(exp.exp1, func);
3145 19129 e2 := map(exp.exp2, func);
3146
4/4
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 19077 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 28 times.
19129 then
3147 if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2)
3148 then exp else LBINARY(e1, exp.operator, e2);
3149
3150 case LUNARY()
3151 algorithm
3152 6275 e1 := map(exp.exp, func);
3153
2/2
✓ Branch 0 taken 6247 times.
✓ Branch 1 taken 28 times.
6275 then
3154 if referenceEq(exp.exp, e1) then exp else LUNARY(exp.operator, e1);
3155
3156 case RELATION()
3157 algorithm
3158 198022 e1 := map(exp.exp1, func);
3159 198022 e2 := map(exp.exp2, func);
3160
4/4
✓ Branch 0 taken 5073 times.
✓ Branch 1 taken 192949 times.
✓ Branch 2 taken 151 times.
✓ Branch 3 taken 4922 times.
198022 then
3161 if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2)
3162 then exp else RELATION(e1, exp.operator, e2, exp.index);
3163
3164 case IF()
3165 algorithm
3166 139884 e1 := map(exp.condition, func);
3167 139884 e2 := map(exp.trueBranch, func);
3168 139884 e3 := map(exp.falseBranch, func);
3169
6/6
✓ Branch 0 taken 4875 times.
✓ Branch 1 taken 135009 times.
✓ Branch 2 taken 4114 times.
✓ Branch 3 taken 761 times.
✓ Branch 4 taken 3873 times.
✓ Branch 5 taken 241 times.
139884 then
3170 if referenceEq(exp.condition, e1) and referenceEq(exp.trueBranch, e2) and
3171 referenceEq(exp.falseBranch, e3) then exp else IF(exp.ty, e1, e2, e3);
3172
3173 case CAST()
3174 algorithm
3175 45275 e1 := map(exp.exp, func);
3176
2/2
✓ Branch 0 taken 44886 times.
✓ Branch 1 taken 389 times.
45275 then
3177 if referenceEq(exp.exp, e1) then exp else CAST(exp.ty, e1);
3178
3179 case BOX()
3180 algorithm
3181 2219 e1 := map(exp.exp, func);
3182
2/2
✓ Branch 0 taken 1148 times.
✓ Branch 1 taken 1071 times.
2219 then
3183 if referenceEq(exp.exp, e1) then exp else box(e1);
3184
3185 case UNBOX()
3186 algorithm
3187 117 e1 := map(exp.exp, func);
3188
1/2
✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
117 then
3189 if referenceEq(exp.exp, e1) then exp else unbox(e1);
3190
3191 case SUBSCRIPTED_EXP()
3192
4/4
✓ Branch 0 taken 190551 times.
✓ Branch 1 taken 189760 times.
✓ Branch 2 taken 190551 times.
✓ Branch 3 taken 189760 times.
380311 then SUBSCRIPTED_EXP(map(exp.exp, func),
3193 list(Subscript.mapExp(s, func) for s in exp.subscripts), exp.ty, exp.split);
3194
3195 case TUPLE_ELEMENT()
3196 algorithm
3197 210 e1 := map(exp.tupleExp, func);
3198
1/2
✓ Branch 0 taken 210 times.
✗ Branch 1 not taken.
210 then
3199 if referenceEq(exp.tupleExp, e1) then exp else TUPLE_ELEMENT(e1, exp.index, exp.ty);
3200
3201 case RECORD_ELEMENT()
3202 algorithm
3203 1508 e1 := map(exp.recordExp, func);
3204
1/2
✓ Branch 0 taken 1508 times.
✗ Branch 1 not taken.
1508 then
3205 if referenceEq(exp.recordExp, e1) then exp else RECORD_ELEMENT(e1, exp.index, exp.fieldName, exp.ty);
3206
3207 case MUTABLE()
3208 algorithm
3209 659721 Mutable.update(exp.exp, map(Mutable.access(exp.exp), func));
3210 then
3211 exp;
3212
3213 case SHARED_LITERAL()
3214 algorithm
3215 20 exp.exp := map(exp.exp, func);
3216 then
3217 exp;
3218
3219 case PARTIAL_FUNCTION_APPLICATION()
3220 algorithm
3221
4/4
✓ Branch 0 taken 2054 times.
✓ Branch 1 taken 509 times.
✓ Branch 2 taken 2054 times.
✓ Branch 3 taken 509 times.
3072 exp.args := list(map(e, func) for e in exp.args);
3222 then
3223 exp;
3224
3225 else exp;
3226 end match;
3227
3228
2/2
✓ Branch 0 taken 11487387 times.
✓ Branch 1 taken 8300136 times.
19787523 outExp := func(outExp);
3229 end map;
3230
3231 function fakeMap
3232 "has an interface like map but just applies the function directly.
3233 used for functions that map itself but need to use mapping interfaces"
3234 input Expression exp;
3235 input MapFunc func;
3236 output Expression outExp = func(exp);
3237
3238 partial function MapFunc
3239 input output Expression e;
3240 end MapFunc;
3241 end fakeMap;
3242
3243 function mapOpt
3244 input Option<Expression> exp;
3245 input MapFunc func;
3246 output Option<Expression> outExp;
3247
3248 partial function MapFunc
3249 input output Expression e;
3250 end MapFunc;
3251 protected
3252 Expression e;
3253 algorithm
3254 outExp := match exp
3255 438 case SOME(e) then SOME(map(e, func));
3256 else exp;
3257 end match;
3258 end mapOpt;
3259
3260 function mapReverse
3261 "Applies a function recursively (depth-first, pre-order) to an expression
3262 and creates a new expression from the returned values.
3263 NOTE: For performance reasons this function does not recurse into arrays
3264 marked as literal."
3265 input output Expression exp;
3266 input MapFunc func;
3267
3268 partial function MapFunc
3269 input output Expression e;
3270 end MapFunc;
3271 algorithm
3272
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 17611 times.
17615 exp := func(exp);
3273 exp := match exp
3274 local
3275 Expression e1, e2, e3, e4;
3276
3277 ✗ case CLKCONST() then CLKCONST(ClockKind.mapExp(exp.clk, func));
3278 8889 case CREF() then CREF(exp.ty, ComponentRef.mapExp(exp.cref, func));
3279 45 case ARRAY() guard not exp.literal then makeArray(exp.ty, Array.map(exp.elements, function mapReverse(func = func)), exp.literal);
3280 ✗ case MATRIX() then MATRIX(list(list(mapReverse(e, func) for e in row) for row in exp.elements));
3281
3282 case RANGE(step = SOME(e2))
3283 algorithm
3284 4 e1 := mapReverse(exp.start, func);
3285 4 e4 := mapReverse(e2, func);
3286 4 e3 := mapReverse(exp.stop, func);
3287
3/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
4 then
3288 if referenceEq(exp.start, e1) and referenceEq(e2, e4) and
3289 referenceEq(exp.stop, e3) then exp else RANGE(exp.ty, e1, SOME(e4), e3);
3290
3291 case RANGE()
3292 algorithm
3293 338 e1 := mapReverse(exp.start, func);
3294 338 e3 := mapReverse(exp.stop, func);
3295
3/4
✓ Branch 0 taken 338 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 63 times.
✓ Branch 3 taken 275 times.
338 then
3296 if referenceEq(exp.start, e1) and referenceEq(exp.stop, e3)
3297 then exp else RANGE(exp.ty, e1, NONE(), e3);
3298
3299
4/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 3 times.
13 case TUPLE() then TUPLE(exp.ty, list(mapReverse(e, func) for e in exp.elements));
3300
3301 case RECORD()
3302 ✗ then RECORD(exp.path, exp.ty, list(mapReverse(e, func) for e in exp.elements));
3303
3304 1293 case CALL() then CALL(Call.mapExp(exp.call, func));
3305
3306 case SIZE(dimIndex = SOME(e2))
3307 algorithm
3308 ✗ e1 := mapReverse(exp.exp, func);
3309 ✗ e3 := mapReverse(e2, func);
3310 ✗ then
3311 if referenceEq(exp.exp, e1) and referenceEq(e2, e3) then exp else SIZE(e1, SOME(e3));
3312
3313 case SIZE()
3314 algorithm
3315 ✗ e1 := mapReverse(exp.exp, func);
3316 ✗ then
3317 if referenceEq(exp.exp, e1) then exp else SIZE(e1, NONE());
3318
3319 case BINARY()
3320 algorithm
3321 439 e1 := mapReverse(exp.exp1, func);
3322 439 e2 := mapReverse(exp.exp2, func);
3323
3/4
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 369 times.
✓ Branch 2 taken 70 times.
✗ Branch 3 not taken.
439 then
3324 if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2)
3325 then exp else BINARY(e1, exp.operator, e2);
3326
3327 case MULTARY()
3328 algorithm
3329 // ToDo: referenceEq ?
3330
4/4
✓ Branch 0 taken 5764 times.
✓ Branch 1 taken 3205 times.
✓ Branch 2 taken 5764 times.
✓ Branch 3 taken 3205 times.
12174 exp.arguments := list(mapReverse(arg, func) for arg in exp.arguments);
3331
4/4
✓ Branch 0 taken 901 times.
✓ Branch 1 taken 3205 times.
✓ Branch 2 taken 901 times.
✓ Branch 3 taken 3205 times.
7311 exp.inv_arguments := list(mapReverse(arg, func) for arg in exp.inv_arguments);
3332 then exp;
3333
3334 case UNARY()
3335 algorithm
3336 56 e1 := mapReverse(exp.exp, func);
3337
1/2
✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
56 then
3338 if referenceEq(exp.exp, e1) then exp else UNARY(exp.operator, e1);
3339
3340 case LBINARY()
3341 algorithm
3342 79 e1 := mapReverse(exp.exp1, func);
3343 79 e2 := mapReverse(exp.exp2, func);
3344
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
79 then
3345 if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2)
3346 then exp else LBINARY(e1, exp.operator, e2);
3347
3348 case LUNARY()
3349 algorithm
3350 55 e1 := mapReverse(exp.exp, func);
3351
1/2
✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
55 then
3352 if referenceEq(exp.exp, e1) then exp else LUNARY(exp.operator, e1);
3353
3354 case RELATION()
3355 algorithm
3356 189 e1 := mapReverse(exp.exp1, func);
3357 189 e2 := mapReverse(exp.exp2, func);
3358
3/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 188 times.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
189 then
3359 if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2)
3360 then exp else RELATION(e1, exp.operator, e2, exp.index);
3361
3362 case IF()
3363 algorithm
3364 58 e1 := mapReverse(exp.condition, func);
3365 58 e2 := mapReverse(exp.trueBranch, func);
3366 58 e3 := mapReverse(exp.falseBranch, func);
3367
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
58 then
3368 if referenceEq(exp.condition, e1) and referenceEq(exp.trueBranch, e2) and
3369 referenceEq(exp.falseBranch, e3) then exp else IF(exp.ty, e1, e2, e3);
3370
3371 case CAST()
3372 algorithm
3373 50 e1 := mapReverse(exp.exp, func);
3374
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 then
3375 if referenceEq(exp.exp, e1) then exp else CAST(exp.ty, e1);
3376
3377 case BOX()
3378 algorithm
3379 ✗ e1 := mapReverse(exp.exp, func);
3380 ✗ then
3381 if referenceEq(exp.exp, e1) then exp else box(e1);
3382
3383 case UNBOX()
3384 algorithm
3385 ✗ e1 := mapReverse(exp.exp, func);
3386 ✗ then
3387 if referenceEq(exp.exp, e1) then exp else unbox(e1);
3388
3389 case SUBSCRIPTED_EXP()
3390
4/4
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 40 times.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 40 times.
80 then SUBSCRIPTED_EXP(mapReverse(exp.exp, func),
3391 list(Subscript.mapExp(s, func) for s in exp.subscripts), exp.ty, exp.split);
3392
3393 case TUPLE_ELEMENT()
3394 algorithm
3395 ✗ e1 := mapReverse(exp.tupleExp, func);
3396 ✗ then
3397 if referenceEq(exp.tupleExp, e1) then exp else TUPLE_ELEMENT(e1, exp.index, exp.ty);
3398
3399 case RECORD_ELEMENT()
3400 algorithm
3401 ✗ e1 := mapReverse(exp.recordExp, func);
3402 ✗ then
3403 if referenceEq(exp.recordExp, e1) then exp else RECORD_ELEMENT(e1, exp.index, exp.fieldName, exp.ty);
3404
3405 case MUTABLE()
3406 algorithm
3407 ✗ Mutable.update(exp.exp, mapReverse(Mutable.access(exp.exp), func));
3408 then
3409 exp;
3410
3411 case SHARED_LITERAL()
3412 algorithm
3413 ✗ exp.exp := mapReverse(exp.exp, func);
3414 then
3415 exp;
3416
3417 case PARTIAL_FUNCTION_APPLICATION()
3418 algorithm
3419 ✗ exp.args := list(mapReverse(e, func) for e in exp.args);
3420 then
3421 exp;
3422
3423 else exp;
3424 end match;
3425 end mapReverse;
3426
3427 function mapShallow
3428 "Applies a function recursively to each subexpression in an expression,
3429 without recursion, and creates a new expression from the returned values.
3430 NOTE: For performance reasons this function does not recurse into arrays
3431 marked as literal."
3432 input Expression exp;
3433 input MapFunc func;
3434 output Expression outExp;
3435
3436 partial function MapFunc
3437 input output Expression e;
3438 end MapFunc;
3439 algorithm
3440 outExp := match exp
3441 local
3442 Expression e1, e2, e3, e4;
3443
3444 154 case CLKCONST() then CLKCONST(ClockKind.mapExpShallow(exp.clk, func));
3445 1221707 case CREF() then CREF(exp.ty, ComponentRef.mapExpShallow(exp.cref, func));
3446 84963 case ARRAY() guard not exp.literal then makeArray(exp.ty, Array.map(exp.elements, func), exp.literal);
3447 ✗ case MATRIX() then MATRIX(list(list(func(e) for e in row) for row in exp.elements));
3448
3449 case RANGE(step = SOME(e2))
3450 algorithm
3451
2/2
✓ Branch 0 taken 135 times.
✓ Branch 1 taken 6 times.
141 e1 := func(exp.start);
3452
2/2
✓ Branch 0 taken 135 times.
✓ Branch 1 taken 6 times.
141 e4 := func(e2);
3453
2/2
✓ Branch 0 taken 135 times.
✓ Branch 1 taken 6 times.
141 e3 := func(exp.stop);
3454
5/6
✓ Branch 0 taken 129 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 129 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 121 times.
161 then
3455 if referenceEq(exp.start, e1) and referenceEq(e2, e4) and
3456 referenceEq(exp.stop, e3) then exp else RANGE(exp.ty, e1, SOME(e4), e3);
3457
3458 case RANGE()
3459 algorithm
3460
2/2
✓ Branch 0 taken 17346 times.
✓ Branch 1 taken 10 times.
17356 e1 := func(exp.start);
3461
2/2
✓ Branch 0 taken 17346 times.
✓ Branch 1 taken 10 times.
17356 e3 := func(exp.stop);
3462
4/4
✓ Branch 0 taken 17331 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 2752 times.
✓ Branch 3 taken 14579 times.
17356 then
3463 if referenceEq(exp.start, e1) and referenceEq(exp.stop, e3)
3464 then exp else RANGE(exp.ty, e1, NONE(), e3);
3465
3466
5/6
✓ Branch 0 taken 604 times.
✓ Branch 1 taken 259 times.
✓ Branch 2 taken 604 times.
✓ Branch 3 taken 259 times.
✓ Branch 4 taken 604 times.
✗ Branch 5 not taken.
863 case TUPLE() then TUPLE(exp.ty, list(func(e) for e in exp.elements));
3467
3468 case RECORD()
3469
6/6
✓ Branch 0 taken 101121 times.
✓ Branch 1 taken 6953 times.
✓ Branch 2 taken 101121 times.
✓ Branch 3 taken 6953 times.
✓ Branch 4 taken 100696 times.
✓ Branch 5 taken 425 times.
108074 then RECORD(exp.path, exp.ty, list(func(e) for e in exp.elements));
3470
3471 317611 case CALL() then CALL(Call.mapExpShallow(exp.call, func));
3472
3473 case SIZE(dimIndex = SOME(e2))
3474 algorithm
3475
2/2
✓ Branch 0 taken 407 times.
✓ Branch 1 taken 36 times.
443 e1 := func(exp.exp);
3476
2/2
✓ Branch 0 taken 407 times.
✓ Branch 1 taken 36 times.
443 e3 := func(e2);
3477
3/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 434 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
877 then
3478 if referenceEq(exp.exp, e1) and referenceEq(e2, e3) then exp else SIZE(e1, SOME(e3));
3479
3480 case SIZE()
3481 algorithm
3482
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 e1 := func(exp.exp);
3483
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 then
3484 if referenceEq(exp.exp, e1) then exp else SIZE(e1, NONE());
3485
3486 case BINARY()
3487 algorithm
3488
2/2
✓ Branch 0 taken 985489 times.
✓ Branch 1 taken 6365 times.
991854 e1 := func(exp.exp1);
3489
2/2
✓ Branch 0 taken 985489 times.
✓ Branch 1 taken 6365 times.
991854 e2 := func(exp.exp2);
3490
4/4
✓ Branch 0 taken 149266 times.
✓ Branch 1 taken 842588 times.
✓ Branch 2 taken 127481 times.
✓ Branch 3 taken 21785 times.
991854 then
3491 if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2)
3492 then exp else BINARY(e1, exp.operator, e2);
3493
3494 case MULTARY()
3495 algorithm
3496 // ToDo: referenceEq ?
3497
6/6
✓ Branch 0 taken 93048 times.
✓ Branch 1 taken 47877 times.
✓ Branch 2 taken 93048 times.
✓ Branch 3 taken 47877 times.
✓ Branch 4 taken 91067 times.
✓ Branch 5 taken 1981 times.
188802 exp.arguments := list(func(arg) for arg in exp.arguments);
3498
6/6
✓ Branch 0 taken 10063 times.
✓ Branch 1 taken 47877 times.
✓ Branch 2 taken 10063 times.
✓ Branch 3 taken 47877 times.
✓ Branch 4 taken 9826 times.
✓ Branch 5 taken 237 times.
105817 exp.inv_arguments := list(func(arg) for arg in exp.inv_arguments);
3499 then exp;
3500
3501 case UNARY()
3502 algorithm
3503
2/2
✓ Branch 0 taken 53204 times.
✓ Branch 1 taken 368 times.
53572 e1 := func(exp.exp);
3504
2/2
✓ Branch 0 taken 52169 times.
✓ Branch 1 taken 1403 times.
53572 then
3505 if referenceEq(exp.exp, e1) then exp else UNARY(exp.operator, e1);
3506
3507 case LBINARY()
3508 algorithm
3509
1/2
✓ Branch 0 taken 9673 times.
✗ Branch 1 not taken.
9673 e1 := func(exp.exp1);
3510
1/2
✓ Branch 0 taken 9673 times.
✗ Branch 1 not taken.
9673 e2 := func(exp.exp2);
3511
4/4
✓ Branch 0 taken 272 times.
✓ Branch 1 taken 9401 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 259 times.
9673 then
3512 if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2)
3513 then exp else LBINARY(e1, exp.operator, e2);
3514
3515 case LUNARY()
3516 algorithm
3517
1/2
✓ Branch 0 taken 4022 times.
✗ Branch 1 not taken.
4022 e1 := func(exp.exp);
3518
2/2
✓ Branch 0 taken 3637 times.
✓ Branch 1 taken 385 times.
4022 then
3519 if referenceEq(exp.exp, e1) then exp else LUNARY(exp.operator, e1);
3520
3521 case RELATION()
3522 algorithm
3523
2/2
✓ Branch 0 taken 29213 times.
✓ Branch 1 taken 921 times.
30134 e1 := func(exp.exp1);
3524
2/2
✓ Branch 0 taken 29213 times.
✓ Branch 1 taken 921 times.
30134 e2 := func(exp.exp2);
3525
4/4
✓ Branch 0 taken 1110 times.
✓ Branch 1 taken 29024 times.
✓ Branch 2 taken 113 times.
✓ Branch 3 taken 997 times.
30134 then
3526 if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2)
3527 then exp else RELATION(e1, exp.operator, e2, exp.index);
3528
3529 case IF()
3530 algorithm
3531
2/2
✓ Branch 0 taken 18403 times.
✓ Branch 1 taken 926 times.
19329 e1 := func(exp.condition);
3532
2/2
✓ Branch 0 taken 18403 times.
✓ Branch 1 taken 926 times.
19329 e2 := func(exp.trueBranch);
3533
2/2
✓ Branch 0 taken 18403 times.
✓ Branch 1 taken 926 times.
19329 e3 := func(exp.falseBranch);
3534
6/6
✓ Branch 0 taken 551 times.
✓ Branch 1 taken 18778 times.
✓ Branch 2 taken 414 times.
✓ Branch 3 taken 137 times.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 401 times.
19329 then
3535 if referenceEq(exp.condition, e1) and referenceEq(exp.trueBranch, e2) and
3536 referenceEq(exp.falseBranch, e3) then exp else IF(exp.ty, e1, e2, e3);
3537
3538 case CAST()
3539 algorithm
3540
2/2
✓ Branch 0 taken 15307 times.
✓ Branch 1 taken 18 times.
15325 e1 := func(exp.exp);
3541
2/2
✓ Branch 0 taken 14671 times.
✓ Branch 1 taken 654 times.
15325 then
3542 if referenceEq(exp.exp, e1) then exp else CAST(exp.ty, e1);
3543
3544 case BOX()
3545 algorithm
3546
2/2
✓ Branch 0 taken 522 times.
✓ Branch 1 taken 72 times.
594 e1 := func(exp.exp);
3547
2/2
✓ Branch 0 taken 247 times.
✓ Branch 1 taken 347 times.
594 then
3548 if referenceEq(exp.exp, e1) then exp else box(e1);
3549
3550 case UNBOX()
3551 algorithm
3552
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 e1 := func(exp.exp);
3553
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 then
3554 if referenceEq(exp.exp, e1) then exp else unbox(e1);
3555
3556 case SUBSCRIPTED_EXP()
3557
6/6
✓ Branch 0 taken 10418 times.
✓ Branch 1 taken 10136 times.
✓ Branch 2 taken 10418 times.
✓ Branch 3 taken 10136 times.
✓ Branch 5 taken 10125 times.
✓ Branch 6 taken 11 times.
20554 then SUBSCRIPTED_EXP(func(exp.exp),
3558 list(Subscript.mapShallowExp(e, func) for e in exp.subscripts), exp.ty, exp.split);
3559
3560 case TUPLE_ELEMENT()
3561 algorithm
3562
1/2
✓ Branch 0 taken 134 times.
✗ Branch 1 not taken.
134 e1 := func(exp.tupleExp);
3563
1/2
✓ Branch 0 taken 134 times.
✗ Branch 1 not taken.
134 then
3564 if referenceEq(exp.tupleExp, e1) then exp else TUPLE_ELEMENT(e1, exp.index, exp.ty);
3565
3566 case RECORD_ELEMENT()
3567 algorithm
3568
2/2
✓ Branch 0 taken 119 times.
✓ Branch 1 taken 37 times.
156 e1 := func(exp.recordExp);
3569
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 110 times.
156 then
3570 if referenceEq(exp.recordExp, e1) then exp else RECORD_ELEMENT(e1, exp.index, exp.fieldName, exp.ty);
3571
3572 case MUTABLE()
3573 algorithm
3574 ✗ Mutable.update(exp.exp, func(Mutable.access(exp.exp)));
3575 then
3576 exp;
3577
3578 case SHARED_LITERAL()
3579 algorithm
3580
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
8 exp.exp := func(exp.exp);
3581 then
3582 exp;
3583
3584 case PARTIAL_FUNCTION_APPLICATION()
3585 algorithm
3586
6/6
✓ Branch 0 taken 461 times.
✓ Branch 1 taken 122 times.
✓ Branch 2 taken 461 times.
✓ Branch 3 taken 122 times.
✓ Branch 4 taken 389 times.
✓ Branch 5 taken 72 times.
705 exp.args := list(func(e) for e in exp.args);
3587 then
3588 exp;
3589
3590 else exp;
3591 end match;
3592 end mapShallow;
3593
3594 function mapShallowOpt
3595 input Option<Expression> exp;
3596 input MapFunc func;
3597 output Option<Expression> outExp;
3598
3599 partial function MapFunc
3600 input output Expression e;
3601 end MapFunc;
3602 protected
3603 Expression e;
3604 algorithm
3605 outExp := match exp
3606
2/2
✓ Branch 0 taken 229 times.
✓ Branch 1 taken 6 times.
235 case SOME(e) then SOME(func(e));
3607 else exp;
3608 end match;
3609 end mapShallowOpt;
3610
3611 function mapArrayElements
3612 "Applies the given function to each scalar elements of an array."
3613 input Expression exp;
3614 input MapFunc func;
3615 output Expression outExp;
3616
3617 partial function MapFunc
3618 input output Expression e;
3619 end MapFunc;
3620 algorithm
3621 outExp := match exp
3622 case ARRAY()
3623 algorithm
3624 8758 exp.elements := Array.map(exp.elements, function mapArrayElements(func = func));
3625
2/2
✓ Branch 1 taken 4180 times.
✓ Branch 2 taken 199 times.
8559 exp.literal := Array.all(exp.elements, isLiteral);
3626 then
3627 exp;
3628
3629
1/2
✓ Branch 0 taken 60931 times.
✗ Branch 1 not taken.
60931 else func(exp);
3630 end match;
3631 end mapArrayElements;
3632
3633 function foldArray<ArgT>
3634 input array<Expression> expl;
3635 input FoldFunc func;
3636 input ArgT arg;
3637 output ArgT result = arg;
3638
3639 partial function FoldFunc
3640 input Expression exp;
3641 input output ArgT arg;
3642 end FoldFunc;
3643 algorithm
3644
2/2
✓ Branch 1 taken 797550 times.
✓ Branch 2 taken 208054 times.
1005604 for e in expl loop
3645 797550 result := fold(e, func, result);
3646 end for;
3647 end foldArray;
3648
3649 function foldList<ArgT>
3650 input list<Expression> expl;
3651 input FoldFunc func;
3652 input ArgT arg;
3653 output ArgT result = arg;
3654
3655 partial function FoldFunc
3656 input Expression exp;
3657 input output ArgT arg;
3658 end FoldFunc;
3659 algorithm
3660
2/2
✓ Branch 0 taken 318239 times.
✓ Branch 1 taken 154719 times.
472958 for e in expl loop
3661 318239 result := fold(e, func, result);
3662 end for;
3663 end foldList;
3664
3665 function foldOpt<ArgT>
3666 input Option<Expression> exp;
3667 input FoldFunc func;
3668 input ArgT arg;
3669 output ArgT result;
3670
3671 partial function FoldFunc
3672 input Expression exp;
3673 input output ArgT arg;
3674 end FoldFunc;
3675 algorithm
3676 result := match exp
3677 local
3678 Expression e;
3679
3680
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 227 times.
289 case SOME(e) then func(e, arg);
3681 else arg;
3682 end match;
3683 end foldOpt;
3684
3685 function fold<ArgT>
3686 input Expression exp;
3687 input FoldFunc func;
3688 input ArgT arg;
3689 output ArgT result;
3690
3691 partial function FoldFunc
3692 input Expression exp;
3693 input output ArgT arg;
3694 end FoldFunc;
3695 algorithm
3696 result := match exp
3697 local
3698 Expression e;
3699
3700 179 case CLKCONST() then ClockKind.foldExp(exp.clk, func, arg);
3701 1682779 case CREF() then ComponentRef.foldExp(exp.cref, func, arg);
3702 208054 case ARRAY() then foldArray(exp.elements, func, arg);
3703
3704 case MATRIX()
3705 algorithm
3706 result := arg;
3707 ✗ for row in exp.elements loop
3708 ✗ result := foldList(row, func, result);
3709 end for;
3710 then
3711 result;
3712
3713 case RANGE()
3714 algorithm
3715 3680 result := fold(exp.start, func, arg);
3716 3680 result := foldOpt(exp.step, func, result);
3717 3680 then
3718 fold(exp.stop, func, result);
3719
3720 967 case TUPLE() then foldList(exp.elements, func, arg);
3721 5183 case RECORD() then foldList(exp.elements, func, arg);
3722 150754 case CALL() then Call.foldExp(exp.call, func, arg);
3723
3724 case SIZE(dimIndex = SOME(e))
3725 algorithm
3726 7929 result := fold(exp.exp, func, arg);
3727 7929 then
3728 fold(e, func, result);
3729
3730 5 case SIZE() then fold(exp.exp, func, arg);
3731
3732 case BINARY()
3733 algorithm
3734 910172 result := fold(exp.exp1, func, arg);
3735 910172 then
3736 fold(exp.exp2, func, result);
3737
3738 case MULTARY()
3739 algorithm
3740 result := arg;
3741
2/2
✓ Branch 0 taken 72778 times.
✓ Branch 1 taken 38868 times.
111646 for argument in exp.arguments loop
3742 72778 result := fold(argument, func, result);
3743 end for;
3744
2/2
✓ Branch 0 taken 20329 times.
✓ Branch 1 taken 38868 times.
59197 for argument in exp.inv_arguments loop
3745 20329 result := fold(argument, func, result);
3746 end for;
3747 then
3748 result;
3749
3750 35083 case UNARY() then fold(exp.exp, func, arg);
3751
3752 case LBINARY()
3753 algorithm
3754 7247 result := fold(exp.exp1, func, arg);
3755 7247 then
3756 fold(exp.exp2, func, result);
3757
3758 1678 case LUNARY() then fold(exp.exp, func, arg);
3759
3760 case RELATION()
3761 algorithm
3762 33830 result := fold(exp.exp1, func, arg);
3763 33830 then
3764 fold(exp.exp2, func, result);
3765
3766 case IF()
3767 algorithm
3768 12417 result := fold(exp.condition, func, arg);
3769 12417 result := fold(exp.trueBranch, func, result);
3770 12417 then
3771 fold(exp.falseBranch, func, result);
3772
3773 6730 case CAST() then fold(exp.exp, func, arg);
3774 355 case BOX() then fold(exp.exp, func, arg);
3775 131 case UNBOX() then fold(exp.exp, func, arg);
3776
3777 case SUBSCRIPTED_EXP()
3778 algorithm
3779 21451 result := fold(exp.exp, func, arg);
3780 21451 then
3781 List.fold(exp.subscripts, function Subscript.foldExp(func = func), result);
3782
3783 144 case TUPLE_ELEMENT() then fold(exp.tupleExp, func, arg);
3784 49 case RECORD_ELEMENT() then fold(exp.recordExp, func, arg);
3785 ✗ case MUTABLE() then fold(Mutable.access(exp.exp), func, arg);
3786 4401 case SHARED_LITERAL() then fold(exp.exp, func, arg);
3787 58 case PARTIAL_FUNCTION_APPLICATION() then foldList(exp.args, func, arg);
3788 else arg;
3789 end match;
3790
3791
2/2
✓ Branch 0 taken 642132 times.
✓ Branch 1 taken 5697938 times.
6340070 result := func(exp, result);
3792 end fold;
3793
3794 function applyArray
3795 input array<Expression> expl;
3796 input ApplyFunc func;
3797
3798 partial function ApplyFunc
3799 input Expression exp;
3800 end ApplyFunc;
3801 algorithm
3802
2/2
✓ Branch 1 taken 240103 times.
✓ Branch 2 taken 106020 times.
346123 for e in expl loop
3803 240103 apply(e, func);
3804 end for;
3805 end applyArray;
3806
3807 function applyList
3808 input list<Expression> expl;
3809 input ApplyFunc func;
3810
3811 partial function ApplyFunc
3812 input Expression exp;
3813 end ApplyFunc;
3814 algorithm
3815
2/2
✓ Branch 0 taken 438567 times.
✓ Branch 1 taken 220372 times.
658939 for e in expl loop
3816 438567 apply(e, func);
3817 end for;
3818 end applyList;
3819
3820 function applyOpt
3821 input Option<Expression> exp;
3822 input ApplyFunc func;
3823
3824 partial function ApplyFunc
3825 input Expression exp;
3826 end ApplyFunc;
3827 protected
3828 Expression e;
3829 algorithm
3830
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 7871 times.
✓ Branch 2 taken 864 times.
✓ Branch 3 taken 7007 times.
7871 if isSome(exp) then
3831 864 SOME(e) := exp;
3832 864 apply(e, func);
3833 end if;
3834 end applyOpt;
3835
3836 function apply
3837 input Expression exp;
3838 input ApplyFunc func;
3839
3840 partial function ApplyFunc
3841 input Expression exp;
3842 end ApplyFunc;
3843 algorithm
3844 () := match exp
3845 local
3846
3847 164 case CLKCONST() algorithm ClockKind.applyExp(exp.clk, func); then ();
3848 1539213 case CREF() algorithm ComponentRef.applyExp(exp.cref, func); then ();
3849 106020 case ARRAY() algorithm applyArray(exp.elements, func); then ();
3850
3851 case MATRIX()
3852 algorithm
3853
2/2
✓ Branch 0 taken 3306 times.
✓ Branch 1 taken 1266 times.
4572 for row in exp.elements loop
3854 3306 applyList(row, func);
3855 end for;
3856 then
3857 ();
3858
3859 case RANGE()
3860 algorithm
3861 7108 apply(exp.start, func);
3862 7108 applyOpt(exp.step, func);
3863 7108 apply(exp.stop, func);
3864 then
3865 ();
3866
3867 371 case TUPLE() algorithm applyList(exp.elements, func); then ();
3868 2581 case RECORD() algorithm applyList(exp.elements, func); then ();
3869 218926 case CALL() algorithm Call.applyExp(exp.call, func); then ();
3870
3871 case SIZE()
3872 algorithm
3873 621 apply(exp.exp, func);
3874 621 applyOpt(exp.dimIndex, func);
3875 then
3876 ();
3877
3878 case BINARY()
3879 algorithm
3880 808571 apply(exp.exp1, func);
3881 808571 apply(exp.exp2, func);
3882 then
3883 ();
3884
3885 case MULTARY()
3886 algorithm
3887
2/2
✓ Branch 0 taken 78647 times.
✓ Branch 1 taken 38060 times.
116707 for arg in exp.arguments loop
3888 78647 apply(arg, func);
3889 end for;
3890
2/2
✓ Branch 0 taken 11092 times.
✓ Branch 1 taken 38060 times.
49152 for arg in exp.inv_arguments loop
3891 11092 apply(arg, func);
3892 end for;
3893 then ();
3894
3895 51497 case UNARY() algorithm apply(exp.exp, func); then ();
3896
3897 case LBINARY()
3898 algorithm
3899 9304 apply(exp.exp1, func);
3900 9304 apply(exp.exp2, func);
3901 then
3902 ();
3903
3904 2564 case LUNARY() algorithm apply(exp.exp, func); then ();
3905
3906 case RELATION()
3907 algorithm
3908 33102 apply(exp.exp1, func);
3909 33102 apply(exp.exp2, func);
3910 then
3911 ();
3912
3913 case IF()
3914 algorithm
3915 17326 apply(exp.condition, func);
3916 17326 apply(exp.trueBranch, func);
3917 17326 apply(exp.falseBranch, func);
3918 then
3919 ();
3920
3921 12068 case CAST() algorithm apply(exp.exp, func); then ();
3922 161 case BOX() algorithm apply(exp.exp, func); then ();
3923 66 case UNBOX() algorithm apply(exp.exp, func); then ();
3924
3925 case SUBSCRIPTED_EXP()
3926 algorithm
3927 57657 apply(exp.exp, func);
3928
3929
2/2
✓ Branch 0 taken 58034 times.
✓ Branch 1 taken 57657 times.
115691 for s in exp.subscripts loop
3930 58034 Subscript.applyExp(s, func);
3931 end for;
3932 then
3933 ();
3934
3935 134 case TUPLE_ELEMENT() algorithm apply(exp.tupleExp, func); then ();
3936 1 case RECORD_ELEMENT() algorithm apply(exp.recordExp, func); then ();
3937 ✗ case MUTABLE() algorithm apply(Mutable.access(exp.exp), func); then ();
3938 ✗ case SHARED_LITERAL() algorithm apply(exp.exp, func); then ();
3939 25 case PARTIAL_FUNCTION_APPLICATION() algorithm applyList(exp.args, func); then ();
3940 else ();
3941 end match;
3942
3943
2/2
✓ Branch 0 taken 5324673 times.
✓ Branch 1 taken 301852 times.
5626525 func(exp);
3944 end apply;
3945
3946 function applyArrayShallow
3947 input array<Expression> expl;
3948 input ApplyFunc func;
3949
3950 partial function ApplyFunc
3951 input Expression exp;
3952 end ApplyFunc;
3953 algorithm
3954
2/2
✓ Branch 1 taken 7476 times.
✓ Branch 2 taken 2499 times.
9975 for e in expl loop
3955
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7476 times.
7476 func(e);
3956 end for;
3957 end applyArrayShallow;
3958
3959 function applyListShallow
3960 input list<Expression> expl;
3961 input ApplyFunc func;
3962
3963 partial function ApplyFunc
3964 input Expression exp;
3965 end ApplyFunc;
3966 algorithm
3967
2/2
✓ Branch 0 taken 4419 times.
✓ Branch 1 taken 2013 times.
6432 for e in expl loop
3968
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4419 times.
4419 func(e);
3969 end for;
3970 end applyListShallow;
3971
3972 function applyShallow
3973 input Expression exp;
3974 input ApplyFunc func;
3975
3976 partial function ApplyFunc
3977 input Expression exp;
3978 end ApplyFunc;
3979 algorithm
3980 () := match exp
3981 local
3982
3983 ✗ case CLKCONST() algorithm ClockKind.applyExpShallow(exp.clk, func); then ();
3984 62769 case CREF() algorithm ComponentRef.applyExpShallow(exp.cref, func); then ();
3985 2499 case ARRAY() algorithm applyArrayShallow(exp.elements, func); then ();
3986
3987 case MATRIX()
3988 algorithm
3989
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 23 times.
81 for row in exp.elements loop
3990 58 applyListShallow(row, func);
3991 end for;
3992 then
3993 ();
3994
3995 case RANGE()
3996 algorithm
3997
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16427 times.
16427 func(exp.start);
3998 16427 applyShallowOpt(exp.step, func);
3999
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16427 times.
16427 func(exp.stop);
4000 then
4001 ();
4002
4003 6 case TUPLE() algorithm applyListShallow(exp.elements, func); then ();
4004 ✗ case RECORD() algorithm applyListShallow(exp.elements, func); then ();
4005 1959 case CALL() algorithm Call.applyExpShallow(exp.call, func); then ();
4006
4007 case SIZE()
4008 algorithm
4009 ✗ func(exp.exp);
4010 ✗ applyShallowOpt(exp.dimIndex, func);
4011 then
4012 ();
4013
4014 case BINARY()
4015 algorithm
4016
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11892 times.
11892 func(exp.exp1);
4017
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11892 times.
11892 func(exp.exp2);
4018 then
4019 ();
4020
4021 case MULTARY()
4022 algorithm
4023 ✗ for arg in exp.arguments loop
4024 ✗ func(arg);
4025 end for;
4026 ✗ for arg in exp.inv_arguments loop
4027 ✗ func(arg);
4028 end for;
4029 then ();
4030
4031
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 case UNARY() algorithm func(exp.exp); then ();
4032
4033 case LBINARY()
4034 algorithm
4035
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4894 times.
4894 func(exp.exp1);
4036
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4894 times.
4894 func(exp.exp2);
4037 then
4038 ();
4039
4040
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2484 times.
2484 case LUNARY() algorithm func(exp.exp); then ();
4041
4042 case RELATION()
4043 algorithm
4044
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4808 times.
4808 func(exp.exp1);
4045
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4808 times.
4808 func(exp.exp2);
4046 then
4047 ();
4048
4049 case IF()
4050 algorithm
4051
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3271 times.
3271 func(exp.condition);
4052
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3271 times.
3271 func(exp.trueBranch);
4053
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3271 times.
3271 func(exp.falseBranch);
4054 then
4055 ();
4056
4057
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 114 times.
114 case CAST() algorithm func(exp.exp); then ();
4058 ✗ case BOX() algorithm func(exp.exp); then ();
4059 ✗ case UNBOX() algorithm func(exp.exp); then ();
4060
4061 case SUBSCRIPTED_EXP()
4062 algorithm
4063
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11188 times.
11188 func(exp.exp);
4064
4065
2/2
✓ Branch 0 taken 13738 times.
✓ Branch 1 taken 11188 times.
24926 for s in exp.subscripts loop
4066 13738 Subscript.applyExpShallow(s, func);
4067 end for;
4068 then
4069 ();
4070
4071 ✗ case TUPLE_ELEMENT() algorithm func(exp.tupleExp); then ();
4072 ✗ case RECORD_ELEMENT() algorithm func(exp.recordExp); then ();
4073 ✗ case MUTABLE() algorithm func(Mutable.access(exp.exp)); then ();
4074 ✗ case SHARED_LITERAL() algorithm func(exp.exp); then ();
4075 ✗ case PARTIAL_FUNCTION_APPLICATION() algorithm applyListShallow(exp.args, func); then ();
4076 else ();
4077 end match;
4078 end applyShallow;
4079
4080 function applyShallowOpt
4081 input Option<Expression> exp;
4082 input ApplyFunc func;
4083
4084 partial function ApplyFunc
4085 input Expression exp;
4086 end ApplyFunc;
4087 protected
4088 Expression e;
4089 algorithm
4090
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 16427 times.
✓ Branch 2 taken 84 times.
✓ Branch 3 taken 16343 times.
16427 if isSome(exp) then
4091 84 SOME(e) := exp;
4092
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 func(e);
4093 end if;
4094 end applyShallowOpt;
4095
4096 function mapFold<ArgT>
4097 input Expression exp;
4098 input MapFunc func;
4099 output Expression outExp;
4100 input output ArgT arg;
4101
4102 partial function MapFunc
4103 input output Expression e;
4104 input output ArgT arg;
4105 end MapFunc;
4106 algorithm
4107 outExp := match exp
4108 local
4109 Expression e1, e2, e3, e4;
4110 ComponentRef cr;
4111 list<Expression> expl;
4112 Call call;
4113 list<Subscript> subs;
4114 ClockKind ck;
4115 list<list<Expression>> mat;
4116 array<Expression> arr;
4117
4118 case CLKCONST()
4119 algorithm
4120 ✗ (ck, arg) := ClockKind.mapFoldExp(exp.clk, func, arg);
4121 ✗ then
4122 if referenceEq(exp.clk, ck) then exp else CLKCONST(ck);
4123
4124 case CREF()
4125 algorithm
4126 1998 (cr, arg) := ComponentRef.mapFoldExp(exp.cref, func, arg);
4127
1/2
✓ Branch 0 taken 1998 times.
✗ Branch 1 not taken.
1998 then
4128 if referenceEq(exp.cref, cr) then exp else CREF(exp.ty, cr);
4129
4130 case ARRAY()
4131 algorithm
4132 19 (arr, arg) := Array.mapFold(exp.elements, function mapFold(func = func), arg);
4133 19 then
4134 makeArray(exp.ty, arr, exp.literal);
4135
4136 case MATRIX()
4137 algorithm
4138 ✗ (mat, arg) := List.mapFoldList(exp.elements, function mapFold(func = func), arg);
4139 ✗ then
4140 MATRIX(mat);
4141
4142 case RANGE(step = SOME(e2))
4143 algorithm
4144 ✗ (e1, arg) := mapFold(exp.start, func, arg);
4145 ✗ (e4, arg) := mapFold(e2, func, arg);
4146 ✗ (e3, arg) := mapFold(exp.stop, func, arg);
4147 ✗ then
4148 if referenceEq(exp.start, e1) and referenceEq(e2, e4) and
4149 referenceEq(exp.stop, e3) then exp else RANGE(exp.ty, e1, SOME(e4), e3);
4150
4151 case RANGE()
4152 algorithm
4153 ✗ (e1, arg) := mapFold(exp.start, func, arg);
4154 ✗ (e3, arg) := mapFold(exp.stop, func, arg);
4155 ✗ then
4156 if referenceEq(exp.start, e1) and referenceEq(exp.stop, e3)
4157 then exp else RANGE(exp.ty, e1, NONE(), e3);
4158
4159 case TUPLE()
4160 algorithm
4161 ✗ (expl, arg) := List.map1Fold(exp.elements, mapFold, func, arg);
4162 ✗ then
4163 TUPLE(exp.ty, expl);
4164
4165 case RECORD()
4166 algorithm
4167 18 (expl, arg) := List.map1Fold(exp.elements, mapFold, func, arg);
4168 18 then
4169 RECORD(exp.path, exp.ty, expl);
4170
4171 case CALL()
4172 algorithm
4173 28 (call, arg) := Call.mapFoldExp(exp.call, func, arg);
4174
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 then
4175 if referenceEq(exp.call, call) then exp else CALL(call);
4176
4177 case SIZE(dimIndex = SOME(e2))
4178 algorithm
4179 ✗ (e1, arg) := mapFold(exp.exp, func, arg);
4180 ✗ (e3, arg) := mapFold(e2, func, arg);
4181 ✗ then
4182 if referenceEq(exp.exp, e1) and referenceEq(e2, e3) then exp else SIZE(e1, SOME(e3));
4183
4184 case SIZE()
4185 algorithm
4186 ✗ (e1, arg) := mapFold(exp.exp, func, arg);
4187 ✗ then
4188 if referenceEq(exp.exp, e1) then exp else SIZE(e1, NONE());
4189
4190 case BINARY()
4191 algorithm
4192 8 (e1, arg) := mapFold(exp.exp1, func, arg);
4193 8 (e2, arg) := mapFold(exp.exp2, func, arg);
4194
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
8 then
4195 if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2)
4196 then exp else BINARY(e1, exp.operator, e2);
4197
4198 case MULTARY()
4199 algorithm
4200 // ToDo: referenceEq ?
4201 expl := {};
4202
2/2
✓ Branch 0 taken 282 times.
✓ Branch 1 taken 143 times.
425 for argument in exp.arguments loop
4203 282 (e1, arg) := mapFold(argument, func, arg);
4204 expl := e1 :: expl;
4205 end for;
4206 143 exp.arguments := listReverse(expl);
4207 expl := {};
4208
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 143 times.
147 for argument in exp.inv_arguments loop
4209 4 (e1, arg) := mapFold(argument, func, arg);
4210 expl := e1 :: expl;
4211 end for;
4212 143 exp.inv_arguments := listReverse(expl);
4213 then exp;
4214
4215 case UNARY()
4216 algorithm
4217 230 (e1, arg) := mapFold(exp.exp, func, arg);
4218
1/2
✓ Branch 0 taken 230 times.
✗ Branch 1 not taken.
230 then
4219 if referenceEq(exp.exp, e1) then exp else UNARY(exp.operator, e1);
4220
4221 case LBINARY()
4222 algorithm
4223 25 (e1, arg) := mapFold(exp.exp1, func, arg);
4224 25 (e2, arg) := mapFold(exp.exp2, func, arg);
4225
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
25 then
4226 if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2)
4227 then exp else LBINARY(e1, exp.operator, e2);
4228
4229 case LUNARY()
4230 algorithm
4231 21 (e1, arg) := mapFold(exp.exp, func, arg);
4232
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 then
4233 if referenceEq(exp.exp, e1) then exp else LUNARY(exp.operator, e1);
4234
4235 case RELATION()
4236 algorithm
4237 114 (e1, arg) := mapFold(exp.exp1, func, arg);
4238 114 (e2, arg) := mapFold(exp.exp2, func, arg);
4239
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
114 then
4240 if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2)
4241 then exp else RELATION(e1, exp.operator, e2, exp.index);
4242
4243 case IF()
4244 algorithm
4245 ✗ (e1, arg) := mapFold(exp.condition, func, arg);
4246 ✗ (e2, arg) := mapFold(exp.trueBranch, func, arg);
4247 ✗ (e3, arg) := mapFold(exp.falseBranch, func, arg);
4248 ✗ then
4249 if referenceEq(exp.condition, e1) and referenceEq(exp.trueBranch, e2) and
4250 referenceEq(exp.falseBranch, e3) then exp else IF(exp.ty, e1, e2, e3);
4251
4252 case CAST()
4253 algorithm
4254 11 (e1, arg) := mapFold(exp.exp, func, arg);
4255
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 then
4256 if referenceEq(exp.exp, e1) then exp else CAST(exp.ty, e1);
4257
4258 case BOX()
4259 algorithm
4260 ✗ (e1, arg) := mapFold(exp.exp, func, arg);
4261 ✗ then
4262 if referenceEq(exp.exp, e1) then exp else box(e1);
4263
4264 case UNBOX()
4265 algorithm
4266 ✗ (e1, arg) := mapFold(exp.exp, func, arg);
4267 ✗ then
4268 if referenceEq(exp.exp, e1) then exp else unbox(e1);
4269
4270 case SUBSCRIPTED_EXP()
4271 algorithm
4272 17 (e1, arg) := mapFold(exp.exp, func, arg);
4273 17 (subs, arg) := List.mapFold(exp.subscripts, function Subscript.mapFoldExp(func = func), arg);
4274 17 then
4275 SUBSCRIPTED_EXP(e1, subs, exp.ty, exp.split);
4276
4277 case TUPLE_ELEMENT()
4278 algorithm
4279 ✗ (e1, arg) := mapFold(exp.tupleExp, func, arg);
4280 ✗ then
4281 if referenceEq(exp.tupleExp, e1) then exp else TUPLE_ELEMENT(e1, exp.index, exp.ty);
4282
4283 case RECORD_ELEMENT()
4284 algorithm
4285 ✗ (e1, arg) := mapFold(exp.recordExp, func, arg);
4286 ✗ then
4287 if referenceEq(exp.recordExp, e1) then exp else RECORD_ELEMENT(e1, exp.index, exp.fieldName, exp.ty);
4288
4289 case MUTABLE()
4290 algorithm
4291 ✗ (e1, arg) := mapFold(Mutable.access(exp.exp), func, arg);
4292 ✗ Mutable.update(exp.exp, e1);
4293 then
4294 exp;
4295
4296 case SHARED_LITERAL()
4297 algorithm
4298 ✗ (e1, arg) := mapFold(exp.exp, func, arg);
4299 ✗ exp.exp := e1;
4300 then
4301 exp;
4302
4303 case PARTIAL_FUNCTION_APPLICATION()
4304 algorithm
4305 ✗ (expl, arg) := List.map1Fold(exp.args, mapFold, func, arg);
4306 ✗ exp.args := expl;
4307 then
4308 exp;
4309
4310 else exp;
4311 end match;
4312
4313
2/2
✓ Branch 0 taken 3409 times.
✓ Branch 1 taken 147 times.
3556 (outExp, arg) := func(outExp, arg);
4314 end mapFold;
4315
4316 function mapFoldOpt<ArgT>
4317 input Option<Expression> exp;
4318 input MapFunc func;
4319 output Option<Expression> outExp;
4320 input output ArgT arg;
4321
4322 partial function MapFunc
4323 input output Expression e;
4324 input output ArgT arg;
4325 end MapFunc;
4326 protected
4327 Expression e;
4328 algorithm
4329 outExp := match exp
4330 case SOME(e)
4331 algorithm
4332 ✗ (e, arg) := mapFold(e, func, arg);
4333 then
4334 SOME(e);
4335
4336 else exp;
4337 end match;
4338 end mapFoldOpt;
4339
4340 function mapFoldShallow<ArgT>
4341 input Expression exp;
4342 input MapFunc func;
4343 output Expression outExp;
4344 input output ArgT arg;
4345
4346 partial function MapFunc
4347 input output Expression e;
4348 input output ArgT arg;
4349 end MapFunc;
4350 algorithm
4351 outExp := match exp
4352 local
4353 Expression e1, e2, e3;
4354 Option<Expression> oe;
4355 ComponentRef cr;
4356 list<Expression> expl;
4357 Call call;
4358 list<Subscript> subs;
4359 ClockKind ck;
4360 list<list<Expression>> mat;
4361 array<Expression> arr;
4362
4363 case CLKCONST()
4364 algorithm
4365 87 (ck, arg) := ClockKind.mapFoldExpShallow(exp.clk, func, arg);
4366
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 55 times.
87 then
4367 if referenceEq(exp.clk, ck) then exp else CLKCONST(ck);
4368
4369 case CREF()
4370 algorithm
4371 1181884 (cr, arg) := ComponentRef.mapFoldExpShallow(exp.cref, func, arg);
4372
2/2
✓ Branch 0 taken 1181881 times.
✓ Branch 1 taken 3 times.
1181884 then
4373 if referenceEq(exp.cref, cr) then exp else CREF(exp.ty, cr);
4374
4375 case ARRAY()
4376 algorithm
4377 55553 (arr, arg) := Array.mapFold(exp.elements, func, arg);
4378 55553 then
4379 makeArray(exp.ty, arr, exp.literal);
4380
4381 case MATRIX()
4382 algorithm
4383 ✗ (mat, arg) := List.mapFoldList(exp.elements, func, arg);
4384 ✗ then
4385 MATRIX(mat);
4386
4387 case RANGE(step = oe)
4388 algorithm
4389
1/2
✓ Branch 0 taken 3985 times.
✗ Branch 1 not taken.
3985 (e1, arg) := func(exp.start, arg);
4390 3985 (oe, arg) := mapFoldOptShallow(exp.step, func, arg);
4391
1/2
✓ Branch 0 taken 3985 times.
✗ Branch 1 not taken.
3985 (e3, arg) := func(exp.stop, arg);
4392
5/6
✓ Branch 0 taken 3968 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 3968 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1026 times.
✓ Branch 5 taken 2942 times.
3985 then
4393 if referenceEq(e1, exp.start) and referenceEq(oe, exp.step) and referenceEq(e3, exp.stop) then
4394 exp else RANGE(exp.ty, e1, oe, e3);
4395
4396 case TUPLE()
4397 algorithm
4398 817 (expl, arg) := List.mapFold(exp.elements, func, arg);
4399 817 then
4400 TUPLE(exp.ty, expl);
4401
4402 case RECORD()
4403 algorithm
4404 6542 (expl, arg) := List.mapFold(exp.elements, func, arg);
4405 6542 then
4406 RECORD(exp.path, exp.ty, expl);
4407
4408 case CALL()
4409 algorithm
4410 167306 (call, arg) := Call.mapFoldExpShallow(exp.call, func, arg);
4411
1/2
✓ Branch 0 taken 167306 times.
✗ Branch 1 not taken.
167306 then
4412 if referenceEq(exp.call, call) then exp else CALL(call);
4413
4414 case SIZE()
4415 algorithm
4416
1/2
✓ Branch 0 taken 1944 times.
✗ Branch 1 not taken.
1944 (e1, arg) := func(exp.exp, arg);
4417 1944 (oe, arg) := mapFoldOptShallow(exp.dimIndex, func, arg);
4418
3/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1943 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
1944 then
4419 if referenceEq(exp.exp, e1) and referenceEq(exp.dimIndex, oe) then
4420 exp else SIZE(e1, oe);
4421
4422 case BINARY()
4423 algorithm
4424
1/2
✓ Branch 0 taken 708444 times.
✗ Branch 1 not taken.
708444 (e1, arg) := func(exp.exp1, arg);
4425
1/2
✓ Branch 0 taken 708442 times.
✗ Branch 1 not taken.
708442 (e2, arg) := func(exp.exp2, arg);
4426
4/4
✓ Branch 0 taken 146743 times.
✓ Branch 1 taken 561699 times.
✓ Branch 2 taken 136258 times.
✓ Branch 3 taken 10485 times.
708442 then
4427 if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2)
4428 then exp else BINARY(e1, exp.operator, e2);
4429
4430 case MULTARY()
4431 algorithm
4432 // ToDo: referenceEq ?
4433 expl := {};
4434
2/2
✓ Branch 0 taken 37432 times.
✓ Branch 1 taken 15785 times.
53217 for argument in exp.arguments loop
4435
1/2
✓ Branch 0 taken 37432 times.
✗ Branch 1 not taken.
37432 (e1, arg) := func(argument, arg);
4436 expl := e1 :: expl;
4437 end for;
4438 15785 exp.arguments := listReverse(expl);
4439 expl := {};
4440
2/2
✓ Branch 0 taken 158 times.
✓ Branch 1 taken 15785 times.
15943 for argument in exp.inv_arguments loop
4441
1/2
✓ Branch 0 taken 158 times.
✗ Branch 1 not taken.
158 (e1, arg) := func(argument, arg);
4442 expl := e1 :: expl;
4443 end for;
4444 15785 exp.inv_arguments := listReverse(expl);
4445 then exp;
4446
4447 case UNARY()
4448 algorithm
4449
1/2
✓ Branch 0 taken 48098 times.
✗ Branch 1 not taken.
48098 (e1, arg) := func(exp.exp, arg);
4450
2/2
✓ Branch 0 taken 47965 times.
✓ Branch 1 taken 133 times.
48098 then
4451 if referenceEq(exp.exp, e1) then exp else UNARY(exp.operator, e1);
4452
4453 case LBINARY()
4454 algorithm
4455
1/2
✓ Branch 0 taken 5829 times.
✗ Branch 1 not taken.
5829 (e1, arg) := func(exp.exp1, arg);
4456
1/2
✓ Branch 0 taken 5829 times.
✗ Branch 1 not taken.
5829 (e2, arg) := func(exp.exp2, arg);
4457
4/4
✓ Branch 0 taken 514 times.
✓ Branch 1 taken 5315 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 510 times.
5829 then
4458 if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2)
4459 then exp else LBINARY(e1, exp.operator, e2);
4460
4461 case LUNARY()
4462 algorithm
4463
1/2
✓ Branch 0 taken 1725 times.
✗ Branch 1 not taken.
1725 (e1, arg) := func(exp.exp, arg);
4464
2/2
✓ Branch 0 taken 1510 times.
✓ Branch 1 taken 215 times.
1725 then
4465 if referenceEq(exp.exp, e1) then exp else LUNARY(exp.operator, e1);
4466
4467 case RELATION()
4468 algorithm
4469
1/2
✓ Branch 0 taken 24235 times.
✗ Branch 1 not taken.
24235 (e1, arg) := func(exp.exp1, arg);
4470
1/2
✓ Branch 0 taken 24235 times.
✗ Branch 1 not taken.
24235 (e2, arg) := func(exp.exp2, arg);
4471
4/4
✓ Branch 0 taken 2622 times.
✓ Branch 1 taken 21613 times.
✓ Branch 2 taken 94 times.
✓ Branch 3 taken 2528 times.
24235 then
4472 if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2)
4473 then exp else RELATION(e1, exp.operator, e2, exp.index);
4474
4475 case IF()
4476 algorithm
4477
1/2
✓ Branch 0 taken 2807 times.
✗ Branch 1 not taken.
2807 (e1, arg) := func(exp.condition, arg);
4478
1/2
✓ Branch 0 taken 2807 times.
✗ Branch 1 not taken.
2807 (e2, arg) := func(exp.trueBranch, arg);
4479
1/2
✓ Branch 0 taken 2807 times.
✗ Branch 1 not taken.
2807 (e3, arg) := func(exp.falseBranch, arg);
4480
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 2807 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
2807 then
4481 if referenceEq(exp.condition, e1) and referenceEq(exp.trueBranch, e2) and
4482 referenceEq(exp.falseBranch, e3) then exp else IF(exp.ty, e1, e2, e3);
4483
4484 case CAST()
4485 algorithm
4486
1/2
✓ Branch 0 taken 9517 times.
✗ Branch 1 not taken.
9517 (e1, arg) := func(exp.exp, arg);
4487
2/2
✓ Branch 0 taken 9107 times.
✓ Branch 1 taken 410 times.
9517 then
4488 if referenceEq(exp.exp, e1) then exp else CAST(exp.ty, e1);
4489
4490 case BOX()
4491 algorithm
4492
1/2
✓ Branch 0 taken 137 times.
✗ Branch 1 not taken.
137 (e1, arg) := func(exp.exp, arg);
4493
1/2
✓ Branch 0 taken 137 times.
✗ Branch 1 not taken.
137 then
4494 if referenceEq(exp.exp, e1) then exp else box(e1);
4495
4496 case UNBOX()
4497 algorithm
4498
1/2
✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
65 (e1, arg) := func(exp.exp, arg);
4499
1/2
✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
65 then
4500 if referenceEq(exp.exp, e1) then exp else unbox(e1);
4501
4502 case SUBSCRIPTED_EXP()
4503 algorithm
4504
1/2
✓ Branch 0 taken 4787 times.
✗ Branch 1 not taken.
4787 (e1, arg) := func(exp.exp, arg);
4505 4787 (subs, arg) := List.mapFold(exp.subscripts, function Subscript.mapFoldExpShallow(func = func), arg);
4506 4787 then
4507 SUBSCRIPTED_EXP(e1, subs, exp.ty, exp.split);
4508
4509 case TUPLE_ELEMENT()
4510 algorithm
4511
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
95 (e1, arg) := func(exp.tupleExp, arg);
4512
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
95 then
4513 if referenceEq(exp.tupleExp, e1) then exp else TUPLE_ELEMENT(e1, exp.index, exp.ty);
4514
4515 case RECORD_ELEMENT()
4516 algorithm
4517
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 (e1, arg) := func(exp.recordExp, arg);
4518
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 then
4519 if referenceEq(exp.recordExp, e1) then exp else RECORD_ELEMENT(e1, exp.index, exp.fieldName, exp.ty);
4520
4521 case MUTABLE()
4522 algorithm
4523
1/2
✓ Branch 0 taken 134 times.
✗ Branch 1 not taken.
134 (e1, arg) := func(Mutable.access(exp.exp), arg);
4524 134 Mutable.update(exp.exp, e1);
4525 then
4526 exp;
4527
4528 case SHARED_LITERAL()
4529 algorithm
4530 ✗ (e1, arg) := func(exp.exp, arg);
4531 ✗ exp.exp := e1;
4532 then
4533 exp;
4534
4535 case PARTIAL_FUNCTION_APPLICATION()
4536 algorithm
4537 25 (expl, arg) := List.mapFold(exp.args, func, arg);
4538 25 exp.args := expl;
4539 then
4540 exp;
4541
4542 else exp;
4543 end match;
4544 end mapFoldShallow;
4545
4546 function mapFoldOptShallow<ArgT>
4547 input Option<Expression> exp;
4548 input MapFunc func;
4549 output Option<Expression> outExp;
4550 input output ArgT arg;
4551
4552 partial function MapFunc
4553 input output Expression e;
4554 input output ArgT arg;
4555 end MapFunc;
4556 protected
4557 Expression e1, e2;
4558 algorithm
4559 outExp := match exp
4560 case SOME(e1)
4561 algorithm
4562
1/2
✓ Branch 0 taken 2545 times.
✗ Branch 1 not taken.
2545 (e2, arg) := func(e1, arg);
4563
2/2
✓ Branch 0 taken 279 times.
✓ Branch 1 taken 2266 times.
2545 then
4564 if referenceEq(e1, e2) then exp else SOME(e2);
4565
4566 else exp;
4567 end match;
4568 end mapFoldOptShallow;
4569
4570 function containsOpt
4571 input Option<Expression> exp;
4572 input ContainsPred func;
4573 output Boolean res;
4574
4575 partial function ContainsPred
4576 input Expression exp;
4577 output Boolean res;
4578 end ContainsPred;
4579 protected
4580 Expression e;
4581 algorithm
4582 res := match exp
4583 4336 case SOME(e) then contains(e, func);
4584 else false;
4585 end match;
4586 end containsOpt;
4587
4588 function contains
4589 input Expression exp;
4590 input ContainsPred func;
4591 output Boolean res;
4592
4593 partial function ContainsPred
4594 input Expression exp;
4595 output Boolean res;
4596 end ContainsPred;
4597 algorithm
4598
4/4
✓ Branch 0 taken 140377 times.
✓ Branch 1 taken 14145449 times.
✓ Branch 4 taken 125184 times.
✓ Branch 5 taken 14160642 times.
14285826 if func(exp) then
4599 res := true;
4600 125184 return;
4601 end if;
4602
4603 res := match exp
4604 local
4605
4606 3 case CLKCONST() then ClockKind.containsExp(exp.clk, func);
4607 4249875 case CREF() then ComponentRef.containsExp(exp.cref, func);
4608 77357 case ARRAY() then arrayContains(exp.elements, func);
4609
4610 case MATRIX()
4611 algorithm
4612 res := false;
4613
4614 ✗ for row in exp.elements loop
4615 ✗ if listContains(row, func) then
4616 res := true;
4617 break;
4618 end if;
4619 end for;
4620 then
4621 res;
4622
4623 case RANGE()
4624
4/6
✓ Branch 1 taken 6027 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6027 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 60 times.
✓ Branch 8 taken 5967 times.
6027 then contains(exp.start, func) or
4625 containsOpt(exp.step, func) or
4626 contains(exp.stop, func);
4627
4628 6 case TUPLE() then listContains(exp.elements, func);
4629 6603 case RECORD() then listContains(exp.elements, func);
4630 61374 case CALL() then Call.containsExp(exp.call, func);
4631
4632 case SIZE()
4633
3/4
✓ Branch 1 taken 4323 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 50 times.
✓ Branch 5 taken 4273 times.
4323 then containsOpt(exp.dimIndex, func) or
4634 contains(exp.exp, func);
4635
4636
4/4
✓ Branch 1 taken 5204022 times.
✓ Branch 2 taken 3877 times.
✓ Branch 4 taken 5745 times.
✓ Branch 5 taken 5198277 times.
5207899 case BINARY() then contains(exp.exp1, func) or contains(exp.exp2, func);
4637 case MULTARY()
4638 algorithm
4639 res := false;
4640
2/2
✓ Branch 0 taken 4483 times.
✓ Branch 1 taken 1783 times.
6266 for arg in exp.arguments loop
4641
2/2
✓ Branch 0 taken 4465 times.
✓ Branch 1 taken 18 times.
4483 if res then break; end if;
4642 4465 res := contains(arg, func);
4643 end for;
4644
2/2
✓ Branch 0 taken 341 times.
✓ Branch 1 taken 1770 times.
2111 for arg in exp.inv_arguments loop
4645
2/2
✓ Branch 0 taken 310 times.
✓ Branch 1 taken 31 times.
341 if res then break; end if;
4646 310 res := contains(arg, func);
4647 end for;
4648 then res;
4649 177041 case UNARY() then contains(exp.exp, func);
4650
2/4
✓ Branch 1 taken 449 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 449 times.
449 case LBINARY() then contains(exp.exp1, func) or contains(exp.exp2, func);
4651 344 case LUNARY() then contains(exp.exp, func);
4652
4/4
✓ Branch 1 taken 5146 times.
✓ Branch 2 taken 6 times.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 5145 times.
5152 case RELATION() then contains(exp.exp1, func) or contains(exp.exp2, func);
4653
4654 case IF()
4655
6/6
✓ Branch 1 taken 6309 times.
✓ Branch 2 taken 3 times.
✓ Branch 4 taken 6282 times.
✓ Branch 5 taken 27 times.
✓ Branch 7 taken 9 times.
✓ Branch 8 taken 6273 times.
6312 then contains(exp.condition, func) or
4656 contains(exp.trueBranch, func) or
4657 contains(exp.falseBranch, func);
4658
4659 6463 case CAST() then contains(exp.exp, func);
4660 20 case BOX() then contains(exp.exp, func);
4661 18 case UNBOX() then contains(exp.exp, func);
4662
4663 case SUBSCRIPTED_EXP()
4664
4/4
✓ Branch 1 taken 9585 times.
✓ Branch 2 taken 1389 times.
✓ Branch 4 taken 438 times.
✓ Branch 5 taken 9147 times.
10974 then contains(exp.exp, func) or Subscript.listContainsExp(exp.subscripts, func);
4665
4666 36 case TUPLE_ELEMENT() then contains(exp.tupleExp, func);
4667 ✗ case RECORD_ELEMENT() then contains(exp.recordExp, func);
4668 6880 case MUTABLE() then contains(Mutable.access(exp.exp), func);
4669 ✗ case SHARED_LITERAL() then contains(exp.exp, func);
4670 1 case PARTIAL_FUNCTION_APPLICATION() then listContains(exp.args, func);
4671 else false;
4672 end match;
4673 end contains;
4674
4675 function arrayContains
4676 input array<Expression> expl;
4677 input ContainsPred func;
4678 output Boolean res;
4679
4680 partial function ContainsPred
4681 input Expression exp;
4682 output Boolean res;
4683 end ContainsPred;
4684 algorithm
4685
2/2
✓ Branch 1 taken 231966 times.
✓ Branch 2 taken 69946 times.
301912 for e in expl loop
4686
2/2
✓ Branch 1 taken 7411 times.
✓ Branch 2 taken 224555 times.
231966 if contains(e, func) then
4687 res := true;
4688 7411 return;
4689 end if;
4690 end for;
4691
4692 res := false;
4693 end arrayContains;
4694
4695 function listContains
4696 input list<Expression> expl;
4697 input ContainsPred func;
4698 output Boolean res;
4699
4700 partial function ContainsPred
4701 input Expression exp;
4702 output Boolean res;
4703 end ContainsPred;
4704 algorithm
4705
2/2
✓ Branch 0 taken 281539 times.
✓ Branch 1 taken 66984 times.
348523 for e in expl loop
4706
2/2
✓ Branch 1 taken 698 times.
✓ Branch 2 taken 280841 times.
281539 if contains(e, func) then
4707 res := true;
4708 698 return;
4709 end if;
4710 end for;
4711
4712 res := false;
4713 end listContains;
4714
4715 function containsShallow
4716 input Expression exp;
4717 input ContainsPred func;
4718 output Boolean res;
4719
4720 partial function ContainsPred
4721 input Expression exp;
4722 output Boolean res;
4723 end ContainsPred;
4724 algorithm
4725 res := match exp
4726 24 case CLKCONST() then ClockKind.containsExpShallow(exp.clk, func);
4727 31963 case CREF() then ComponentRef.containsExpShallow(exp.cref, func);
4728 8244 case ARRAY() then Array.any(exp.elements, func);
4729
4730 case MATRIX()
4731 algorithm
4732 res := false;
4733
4734 ✗ for row in exp.elements loop
4735 ✗ if List.any(row, func) then
4736 res := true;
4737 break;
4738 end if;
4739 end for;
4740 then
4741 res;
4742
4743 case RANGE()
4744
9/14
✓ Branch 0 taken 1550 times.
✓ Branch 1 taken 8704 times.
✓ Branch 3 taken 1550 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 8704 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 10254 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1550 times.
✓ Branch 12 taken 8704 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1550 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 8704 times.
10254 then func(exp.start) or
4745 Util.applyOptionOrDefault(exp.step, func, false) or
4746 func(exp.stop);
4747
4748 ✗ case TUPLE() then List.any(exp.elements, func);
4749 4962 case RECORD() then List.any(exp.elements, func);
4750 133692 case CALL() then Call.containsExpShallow(exp.call, func);
4751
4752 case SIZE()
4753
3/8
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 18 times.
18 then Util.applyOptionOrDefault(exp.dimIndex, func, false) or
4754 func(exp.exp);
4755
4756
11/12
✓ Branch 0 taken 1696 times.
✓ Branch 1 taken 307938 times.
✓ Branch 3 taken 1644 times.
✓ Branch 4 taken 52 times.
✓ Branch 6 taken 307938 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1644 times.
✓ Branch 9 taken 307938 times.
✓ Branch 11 taken 36 times.
✓ Branch 12 taken 1608 times.
✓ Branch 14 taken 1 time.
✓ Branch 15 taken 307937 times.
309634 case BINARY() then func(exp.exp1) or func(exp.exp2);
4757 case MULTARY()
4758 algorithm
4759 res := false;
4760 ✗ for arg in exp.arguments loop
4761 ✗ if res then break; end if;
4762 ✗ res := func(arg);
4763 end for;
4764 ✗ for arg in exp.inv_arguments loop
4765 ✗ if res then break; end if;
4766 ✗ res := func(arg);
4767 end for;
4768 then res;
4769
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 880 times.
929 case UNARY() then func(exp.exp);
4770
10/12
✓ Branch 0 taken 1194 times.
✓ Branch 1 taken 6126 times.
✓ Branch 3 taken 1089 times.
✓ Branch 4 taken 105 times.
✓ Branch 6 taken 6125 times.
✓ Branch 7 taken 1 time.
✓ Branch 8 taken 1089 times.
✓ Branch 9 taken 6125 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1089 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 6125 times.
7320 case LBINARY() then func(exp.exp1) or func(exp.exp2);
4771
2/2
✓ Branch 0 taken 2244 times.
✓ Branch 1 taken 494 times.
2738 case LUNARY() then func(exp.exp);
4772
10/12
✓ Branch 0 taken 5041 times.
✓ Branch 1 taken 34213 times.
✓ Branch 3 taken 4544 times.
✓ Branch 4 taken 497 times.
✓ Branch 6 taken 34210 times.
✓ Branch 7 taken 3 times.
✓ Branch 8 taken 4544 times.
✓ Branch 9 taken 34210 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 4544 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 34210 times.
39254 case RELATION() then func(exp.exp1) or func(exp.exp2);
4773
14/18
✓ Branch 0 taken 259 times.
✓ Branch 1 taken 11310 times.
✓ Branch 3 taken 259 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 11310 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 259 times.
✓ Branch 9 taken 11310 times.
✓ Branch 11 taken 154 times.
✓ Branch 12 taken 105 times.
✓ Branch 14 taken 11310 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 154 times.
✓ Branch 17 taken 11310 times.
✓ Branch 19 taken 57 times.
✓ Branch 20 taken 97 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 11310 times.
11569 case IF() then func(exp.condition) or func(exp.trueBranch) or func(exp.falseBranch);
4774
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 401 times.
413 case CAST() then func(exp.exp);
4775
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 case BOX() then func(exp.exp);
4776 ✗ case UNBOX() then func(exp.exp);
4777
4778 case SUBSCRIPTED_EXP()
4779
6/8
✓ Branch 0 taken 18430 times.
✓ Branch 1 taken 876 times.
✓ Branch 3 taken 18326 times.
✓ Branch 4 taken 104 times.
✓ Branch 6 taken 876 times.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 19202 times.
19306 then func(exp.exp) or Subscript.listContainsExpShallow(exp.subscripts, func);
4780
4781 ✗ case TUPLE_ELEMENT() then func(exp.tupleExp);
4782 ✗ case RECORD_ELEMENT() then func(exp.recordExp);
4783
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2625 times.
2625 case MUTABLE() then func(Mutable.access(exp.exp));
4784 ✗ case SHARED_LITERAL() then func(exp.exp);
4785 1 case PARTIAL_FUNCTION_APPLICATION() then listContains(exp.args, func);
4786 else false;
4787 end match;
4788 end containsShallow;
4789
4790 function arrayFirstScalar
4791 "Returns the first scalar element of an array. Fails if the array is empty."
4792 input Expression arrayExp;
4793 output Expression exp;
4794 algorithm
4795 exp := match arrayExp
4796
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
44 case ARRAY() then arrayFirstScalar(arrayGet(arrayExp.elements, 1));
4797 else arrayExp;
4798 end match;
4799 end arrayFirstScalar;
4800
4801 function arrayAllEqual
4802 "Checks if all scalar elements in an array are equal to each other."
4803 input Expression arrayExp;
4804 output Boolean allEqual;
4805 algorithm
4806 allEqual := matchcontinue arrayExp
4807 17 case ARRAY() then arrayAllEqual2(arrayExp, arrayFirstScalar(arrayExp));
4808 else true;
4809 end matchcontinue;
4810 end arrayAllEqual;
4811
4812 function arrayAllEqual2
4813 input Expression arrayExp;
4814 input Expression element;
4815 output Boolean allEqual;
4816 algorithm
4817 allEqual := match arrayExp
4818 case ARRAY()
4819 guard not arrayEmpty(arrayExp.elements) and isArray(arrayGet(arrayExp.elements, 1))
4820 1 then Array.all(arrayExp.elements, function arrayAllEqual2(element = element));
4821 case ARRAY()
4822 17 then Array.all(arrayExp.elements, function isEqual(exp2 = element));
4823 else true;
4824 end match;
4825 end arrayAllEqual2;
4826
4827 function fromCref
4828 input ComponentRef cref;
4829 input Boolean includeScope = false;
4830 output Expression exp;
4831 algorithm
4832 259030 exp := CREF(ComponentRef.getSubscriptedType(cref, includeScope), cref);
4833 end fromCref;
4834
4835 function fromTypedCref
4836 input ComponentRef cref;
4837 input Type ty;
4838 output Expression exp = CREF(ty, cref);
4839 end fromTypedCref;
4840
4841 function toCref
4842 input Expression exp;
4843 output ComponentRef cref;
4844 algorithm
4845
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2886 times.
2886 CREF(cref = cref) := exp;
4846 end toCref;
4847
4848 function extractCrefs
4849 input Expression exp;
4850 output UnorderedSet<ComponentRef> crefs = fold(exp, extractCref, UnorderedSet.new(ComponentRef.hash, ComponentRef.isEqual));
4851 end extractCrefs;
4852
4853 function extractCref
4854 input Expression exp;
4855 input output UnorderedSet<ComponentRef> crefs;
4856 algorithm
4857 crefs := match exp
4858 case CREF() algorithm
4859 5545 UnorderedSet.add(exp.cref, crefs);
4860 then crefs;
4861 else crefs;
4862 end match;
4863 end extractCref;
4864
4865 function isResizableCref
4866 input Expression exp;
4867 output Boolean b;
4868 algorithm
4869 b := match exp
4870 13925 case CREF() then ComponentRef.isResizable(exp.cref);
4871 else false;
4872 end match;
4873 end isResizableCref;
4874
4875 function isIterator
4876 input Expression exp;
4877 output Boolean isIterator;
4878 algorithm
4879 isIterator := match exp
4880 1004 case CREF() then ComponentRef.isIterator(exp.cref);
4881 else false;
4882 end match;
4883 end isIterator;
4884
4885 function containsAnyIterator
4886 input Expression exp;
4887 input InstContext.Type context;
4888 output Boolean iter;
4889 algorithm
4890 ✗ if InstContext.inFor(context) then
4891 ✗ iter := contains(exp, isIterator);
4892 else
4893 iter := false;
4894 end if;
4895 end containsAnyIterator;
4896
4897 function isTime
4898 input Expression exp;
4899 output Boolean b;
4900 algorithm
4901 b := match exp
4902 35 case CREF() then ComponentRef.isTime(exp.cref);
4903 else false;
4904 end match;
4905 end isTime;
4906
4907 function isSubstitute
4908 input Expression exp;
4909 output Boolean b;
4910 algorithm
4911 b := match exp
4912 2850 case CREF() then ComponentRef.isSubstitute(exp.cref);
4913 else false;
4914 end match;
4915 end isSubstitute;
4916
4917 function isZero
4918 input Expression exp;
4919 output Boolean b;
4920 algorithm
4921 b := match exp
4922 55437 case INTEGER() then exp.value == 0;
4923 228386 case REAL() then exp.value == 0.0;
4924 1250 case CAST() then isZero(exp.exp);
4925 16083 case UNARY() then isZero(exp.exp);
4926 2821 case ARRAY() then Array.all(exp.elements, isZero);
4927 else false;
4928 end match;
4929 end isZero;
4930
4931 function isNonZero
4932 input Expression exp;
4933 output Boolean res = isPositive(exp) or isNegative(exp);
4934 end isNonZero;
4935
4936 function isOne
4937 input Expression exp;
4938 output Boolean b;
4939 algorithm
4940 b := match exp
4941 1509 case INTEGER() then exp.value == 1;
4942 26843 case REAL() then exp.value == 1.0;
4943 600 case CAST() then isOne(exp.exp);
4944 104 case UNARY() then isMinusOne(exp.exp);
4945 55 case ARRAY() then Array.all(exp.elements, isOne);
4946 else false;
4947 end match;
4948 end isOne;
4949
4950 function isMinusOne
4951 input Expression exp;
4952 output Boolean isOne;
4953 algorithm
4954 isOne := match exp
4955 ✗ case INTEGER() then exp.value == -1;
4956 8296 case REAL() then exp.value == -1.0;
4957 445 case CAST() then isMinusOne(exp.exp);
4958 99 case UNARY() then isOne(exp.exp);
4959 else false;
4960 end match;
4961 end isMinusOne;
4962
4963 function isNaN
4964 input Expression nan;
4965 output Boolean b;
4966 algorithm
4967 b := match nan
4968
2/6
✓ Branch 1 taken 198 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 198 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
198 case BINARY() then Operator.getMathClassification(nan.operator) == NFOperator.MathClassification.DIVISION and isZero(nan.exp1) and isZero(nan.exp2);
4969 else false;
4970 end match;
4971 end isNaN;
4972
4973 function isPositive
4974 input Expression exp;
4975 output Boolean positive "true if exp is known to be > 0, otherwise false";
4976 algorithm
4977 positive := match exp
4978 387 case INTEGER() then exp.value > 0;
4979 12 case REAL() then exp.value > 0.0;
4980 ✗ case CAST() then isPositive(exp.exp);
4981 3 case UNARY() then isNegative(exp.exp);
4982 57 case CREF() then Util.applyOptionOrDefault(ComponentRef.lookupVarAttr(exp.cref, "min"), isPositive, false);
4983 4 case CALL() then Call.isPositive(exp.call);
4984 else false;
4985 end match;
4986 end isPositive;
4987
4988 function isNegative
4989 input Expression exp;
4990 output Boolean negative "true if exp is known to be < 0, otherwise false";
4991 algorithm
4992 negative := match exp
4993 352 case INTEGER() then exp.value < 0;
4994 415 case REAL() then exp.value < 0.0;
4995 ✗ case CAST() then isNegative(exp.exp);
4996 3 case UNARY() then isPositive(exp.exp);
4997 59 case CREF() then Util.applyOptionOrDefault(ComponentRef.lookupVarAttr(exp.cref, "max"), isNegative, false);
4998 ✗ case CALL() then Call.isNegative(exp.call);
4999 else false;
5000 end match;
5001 end isNegative;
5002
5003 function isNonPositive
5004 input Expression exp;
5005 output Boolean res "true if exp is known to be <= 0, otherwise false";
5006 algorithm
5007 res := match exp
5008 224 case INTEGER() then exp.value <= 0;
5009 437 case REAL() then exp.value <= 0.0;
5010 ✗ case CAST() then isNonPositive(exp.exp);
5011 1442 case UNARY() then isNonNegative(exp.exp);
5012 146 case CREF() then Util.applyOptionOrDefault(ComponentRef.lookupVarAttr(exp.cref, "max"), isNonPositive, false);
5013 ✗ case CALL() then Call.isNonPositive(exp.call);
5014 4 case ARRAY() then Array.all(exp.elements, isNonPositive);
5015 else false;
5016 end match;
5017 end isNonPositive;
5018
5019 function isNonNegative
5020 input Expression exp;
5021 output Boolean res "true if exp is known to be >= 0, otherwise false";
5022 algorithm
5023 res := match exp
5024 2 case INTEGER() then exp.value >= 0;
5025 1240 case REAL() then exp.value >= 0.0;
5026 ✗ case CAST() then isNonNegative(exp.exp);
5027 ✗ case UNARY() then isNonPositive(exp.exp);
5028 1442 case CREF() then Util.applyOptionOrDefault(ComponentRef.lookupVarAttr(exp.cref, "min"), isNonNegative, false);
5029 ✗ case CALL() then Call.isNonNegative(exp.call);
5030 else false;
5031 end match;
5032 end isNonNegative;
5033
5034 function isEven
5035 input Expression exp;
5036 output Boolean even;
5037 algorithm
5038 even := match exp
5039
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
10 case INTEGER() then intMod(exp.value, 2) == 0;
5040 ✗ case REAL() then realMod(exp.value, 2.0) == 0.0;
5041 ✗ case CAST() then isEven(exp.exp);
5042 else false;
5043 end match;
5044 end isEven;
5045
5046 function isGreaterOrEqual
5047 input Expression lhs;
5048 input Expression rhs;
5049 output Boolean res "true if we know that lhs >= rhs, otherwise false";
5050 algorithm
5051 res := match (lhs, rhs)
5052 ✗ case (REAL(), REAL()) then lhs.value >= rhs.value;
5053 146 case (CREF(), _) then Util.applyOptionOrDefault(ComponentRef.lookupVarAttr(lhs.cref, "min"), function isGreaterOrEqual(rhs=rhs), false);
5054 1442 case (_, CREF()) then Util.applyOptionOrDefault(ComponentRef.lookupVarAttr(rhs.cref, "max"), function isGreaterOrEqual(lhs=lhs), false);
5055 1442 case (UNARY(exp = CREF()), _) then isGreaterOrEqual(negate(rhs), lhs.exp);
5056 ✗ case (_, UNARY(exp = CREF())) then isGreaterOrEqual(rhs.exp, negate(lhs));
5057 else false;
5058 end match;
5059 end isGreaterOrEqual;
5060
5061 function hasArrayType
5062 input Expression exp;
5063 output Boolean b = Type.isArray(typeOf(exp));
5064 end hasArrayType;
5065
5066 function isScalar
5067 input Expression exp;
5068 output Boolean scalar = Type.isScalar(typeOf(exp));
5069 end isScalar;
5070
5071 function isScalarLiteral
5072 input Expression exp;
5073 output Boolean literal;
5074 algorithm
5075 literal := match exp
5076 case INTEGER() then true;
5077 case REAL() then true;
5078 case STRING() then true;
5079 case BOOLEAN() then true;
5080 case ENUM_LITERAL() then true;
5081 case FILENAME() then true;
5082 else false;
5083 end match;
5084 end isScalarLiteral;
5085
5086 function isLiteral
5087 input Expression exp;
5088 output Boolean literal;
5089 algorithm
5090 literal := match exp
5091 case INTEGER() then true;
5092 case REAL() then true;
5093 case STRING() then true;
5094 case BOOLEAN() then true;
5095 case ENUM_LITERAL() then true;
5096
4/4
✓ Branch 0 taken 48759 times.
✓ Branch 1 taken 36515 times.
✓ Branch 3 taken 25721 times.
✓ Branch 4 taken 23038 times.
85274 case ARRAY() then exp.literal or Array.all(exp.elements, isLiteral);
5097 2265 case RECORD() then List.all(exp.elements, isLiteral);
5098
5/6
✓ Branch 1 taken 4228 times.
✓ Branch 2 taken 1 time.
✓ Branch 4 taken 4123 times.
✓ Branch 5 taken 105 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 4123 times.
4229 case RANGE() then isLiteral(exp.start) and isLiteral(exp.stop) and
5099 Util.applyOptionOrDefault(exp.step, isLiteral, true);
5100 case FILENAME() then true;
5101 else false;
5102 end match;
5103 end isLiteral;
5104
5105 function isLiteralXML
5106 "allows for expressions additionally for init_xml"
5107 input Expression exp;
5108 output Boolean literal;
5109 algorithm
5110 literal := match exp
5111 local
5112 Expression call_exp;
5113 case INTEGER() then true;
5114 case REAL() then true;
5115 case STRING() then true;
5116 case BOOLEAN() then true;
5117 case ENUM_LITERAL() then true;
5118 313 case ARRAY() then Array.all(exp.elements, isLiteralXML);
5119 24 case RECORD() then List.all(exp.elements, isLiteralXML);
5120
3/6
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 5 times.
5 case RANGE() then isLiteralXML(exp.start) and isLiteralXML(exp.stop) and
5121 Util.applyOptionOrDefault(exp.step, isLiteralXML, true);
5122 case FILENAME() then true;
5123 149 case CALL(call = Call.TYPED_ARRAY_CONSTRUCTOR(exp = call_exp)) then isLiteralXML(call_exp);
5124 else false;
5125 end match;
5126 end isLiteralXML;
5127
5128 function isLiteralReplace
5129 input Expression exp;
5130 output Boolean b;
5131 algorithm
5132 b := match exp
5133 case STRING() then true;
5134 case BOX(STRING()) then true;
5135 73 case RECORD() then isLiteral(exp);
5136 409 case ARRAY() then isLiteral(exp);
5137 else false;
5138 end match;
5139 end isLiteralReplace;
5140
5141 function isKnownSizeFill
5142 input Expression exp;
5143 output Boolean literal;
5144 algorithm
5145 literal := match exp
5146 502 case CALL() then Call.isKnownSizeFill(exp.call);
5147 else false;
5148 end match;
5149 end isKnownSizeFill;
5150
5151 function isInteger
5152 input Expression exp;
5153 output Boolean isInteger;
5154 algorithm
5155 isInteger := match exp
5156 case INTEGER() then true;
5157 else false;
5158 end match;
5159 end isInteger;
5160
5161 function isReal
5162 input Expression exp;
5163 output Boolean isReal;
5164 algorithm
5165 isReal := match exp
5166 case REAL() then true;
5167 else false;
5168 end match;
5169 end isReal;
5170
5171 function isConstNumber
5172 input Expression exp;
5173 output Boolean b;
5174 algorithm
5175 b := match exp
5176 case INTEGER() then true;
5177 case REAL() then true;
5178 ✗ case CAST() then isConstNumber(exp.exp);
5179 232 case UNARY() then isConstNumber(exp.exp);
5180 else false;
5181 end match;
5182 end isConstNumber;
5183
5184 function isBoolean
5185 input Expression exp;
5186 output Boolean isBool;
5187 algorithm
5188 isBool := match exp
5189 case BOOLEAN() then true;
5190 else false;
5191 end match;
5192 end isBoolean;
5193
5194 function isRecord
5195 input Expression exp;
5196 output Boolean isRecord;
5197 algorithm
5198 isRecord := match exp
5199 case RECORD() then true;
5200 else false;
5201 end match;
5202 end isRecord;
5203
5204 function isRecordOrRecordArray
5205 input Expression exp;
5206 output Boolean isRecord;
5207 algorithm
5208 isRecord := match exp
5209 case RECORD() then true;
5210 154 case ARRAY() then Array.all(exp.elements, isRecordOrRecordArray);
5211 else false;
5212 end match;
5213 end isRecordOrRecordArray;
5214
5215 function fillType
5216 "Creates an array with the given type, filling it with the given scalar
5217 expression."
5218 input Type ty;
5219 input Expression fillExp;
5220 output Expression exp = fillExp;
5221 protected
5222 list<Dimension> dims = Type.arrayDims(ty);
5223 Type arr_ty = Type.arrayElementType(ty);
5224 Boolean is_literal = isLiteral(exp);
5225 algorithm
5226
2/2
✓ Branch 1 taken 8027 times.
✓ Branch 2 taken 6413 times.
14440 for dim in listReverse(dims) loop
5227 8027 (exp, arr_ty) := fillArray_impl(Dimension.size(dim), exp, arr_ty, is_literal);
5228 end for;
5229 end fillType;
5230
5231 function fillArgs
5232 "Creates an array from the given fill expression and list of dimensions,
5233 similar to fill(fillExp, dims...). Fails if not all dimensions can be
5234 converted to Integer values."
5235 input Expression fillExp;
5236 input list<Expression> dims;
5237 output Expression result = fillExp;
5238 protected
5239 Type arr_ty = typeOf(result);
5240 Boolean is_literal = isLiteral(fillExp);
5241 Expression d_resizable;
5242 algorithm
5243
2/2
✓ Branch 1 taken 79955 times.
✓ Branch 2 taken 77462 times.
157417 for d in listReverse(dims) loop
5244 79955 d_resizable := map(d, function replaceResizableParameter());
5245 79955 (result, arr_ty) := fillArray_impl(toInteger(d_resizable), result, arr_ty, is_literal);
5246 end for;
5247 end fillArgs;
5248
5249 function fillArray
5250 input Integer n;
5251 input Expression fillExp;
5252 output Expression result;
5253 algorithm
5254 ✗ result := fillArray_impl(n, fillExp, typeOf(fillExp), isLiteral(fillExp));
5255 end fillArray;
5256
5257 function fillArray_impl
5258 input Integer n;
5259 input Expression fillExp;
5260 input Type ty;
5261 input Boolean isLiteral;
5262 output Expression result;
5263 output Type resultType;
5264 protected
5265 array<Expression> arr;
5266 algorithm
5267 87978 arr := Array.generate(n, function clone(exp = fillExp));
5268 87978 resultType := Type.liftArrayLeft(ty, Dimension.fromInteger(n));
5269 87978 result := makeArray(resultType, arr, isLiteral);
5270 end fillArray_impl;
5271
5272 function liftArray
5273 "Creates an array with the given dimension, where each element is the given
5274 expression. Example: liftArray([3], 1) => {1, 1, 1}"
5275 input Dimension dim;
5276 input output Expression exp;
5277 output Type arrayType = typeOf(exp);
5278 algorithm
5279 ✗ (exp, arrayType) := fillArray_impl(Dimension.size(dim), exp, arrayType, isLiteral(exp));
5280 end liftArray;
5281
5282 function liftArrayList
5283 "Creates an array from the given list of dimensions, where each element is
5284 the given expression. Example:
5285 liftArrayList([2, 3], 1) => {{1, 1, 1}, {1, 1, 1}}"
5286 input list<Dimension> dims;
5287 input output Expression exp;
5288 output Type arrayType = typeOf(exp);
5289 protected
5290 Boolean is_literal = isLiteral(exp);
5291 algorithm
5292
2/2
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 476 times.
504 for dim in listReverse(dims) loop
5293 28 (exp, arrayType) := fillArray_impl(Dimension.size(dim), exp, arrayType, is_literal);
5294 end for;
5295 end liftArrayList;
5296
5297 function makeZero
5298 input Type ty;
5299 output Expression zeroExp;
5300 algorithm
5301 zeroExp := match ty
5302 case Type.REAL() then REAL(0.0);
5303 case Type.INTEGER() then INTEGER(0);
5304 case Type.BOOLEAN() then BOOLEAN(false);
5305 426 case Type.ARRAY() then fillType(ty, makeZero(Type.arrayElementType(ty)));
5306 2 case Type.COMPLEX() then makeOperatorRecordZero(Type.complexNode(ty));
5307 else algorithm
5308 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for: " + Type.toString(ty)});
5309 ✗ then fail();
5310 end match;
5311 end makeZero;
5312
5313 function makeOperatorRecordZero
5314 input InstNode recordNode;
5315 output Expression zeroExp;
5316 protected
5317 InstNode op_node;
5318 Function.Function fn;
5319 algorithm
5320 try
5321 2 op_node := Class.lookupElement("'0'", InstNode.getClass(recordNode));
5322 2 Function.Function.instFunctionNode(op_node, NFInstContext.NO_CONTEXT, InstNode.info(InstNode.parent(op_node)));
5323
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 {fn} := Function.Function.typeNodeCache(op_node);
5324 2 zeroExp := CALL(Call.makeTypedCall(fn, {}, Variability.CONSTANT, Purity.PURE));
5325 2 zeroExp := Ceval.evalExp(zeroExp);
5326 else
5327 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for: " + InstNode.toString(recordNode)});
5328 ✗ fail();
5329 end try;
5330 end makeOperatorRecordZero;
5331
5332 function makeOne
5333 input Type ty;
5334 output Expression oneExp;
5335 algorithm
5336 oneExp := match ty
5337 case Type.REAL() then REAL(1.0);
5338 case Type.INTEGER() then INTEGER(1);
5339 165 case Type.ARRAY() then fillType(ty, makeOne(Type.arrayElementType(ty)));
5340 else algorithm
5341 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for: " + Type.toString(ty)});
5342 ✗ then fail();
5343 end match;
5344 end makeOne;
5345
5346 function makeMinusOne
5347 input Type ty;
5348 output Expression oneExp;
5349 algorithm
5350 oneExp := match ty
5351 case Type.REAL() then REAL(-1.0);
5352 case Type.INTEGER() then INTEGER(-1);
5353 ✗ case Type.ARRAY() then fillType(ty, makeMinusOne(Type.arrayElementType(ty)));
5354 else algorithm
5355 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for: " + Type.toString(ty)});
5356 ✗ then fail();
5357 end match;
5358 end makeMinusOne;
5359
5360 function makeNaN
5361 input Type ty;
5362 output Expression nan;
5363 protected
5364 Expression zero = Expression.makeZero(ty);
5365 algorithm
5366 ✗ nan := BINARY(zero, Operator.makeDiv(ty), zero);
5367 end makeNaN;
5368
5369 function makeMaxValue
5370 input Type ty;
5371 output Expression exp;
5372 algorithm
5373 exp := match ty
5374 22 case Type.REAL() then REAL(System.realMaxLit());
5375 4 case Type.INTEGER() then INTEGER(System.intMaxLit());
5376 case Type.BOOLEAN() then BOOLEAN(true);
5377 4 case Type.ENUMERATION() then ENUM_LITERAL(ty, List.last(ty.literals), listLength(ty.literals));
5378 ✗ case Type.ARRAY() then fillType(ty, makeMaxValue(Type.arrayElementType(ty)));
5379 ✗ else REAL(System.realMaxLit()); // backup case just for backend;
5380 end match;
5381 end makeMaxValue;
5382
5383 function makeMinValue
5384 input Type ty;
5385 output Expression exp;
5386 algorithm
5387 exp := match ty
5388 7 case Type.REAL() then REAL(-System.realMaxLit());
5389 4 case Type.INTEGER() then INTEGER(-System.intMaxLit());
5390 case Type.BOOLEAN() then BOOLEAN(false);
5391 4 case Type.ENUMERATION() then ENUM_LITERAL(ty, listHead(ty.literals), 1);
5392 ✗ case Type.ARRAY() then fillType(ty, makeMinValue(Type.arrayElementType(ty)));
5393 ✗ else REAL(-System.realMaxLit()); // backup case just for backend;
5394 end match;
5395 end makeMinValue;
5396
5397 function makeDefaultValue
5398 input Type ty;
5399 input Option<Expression> min = NONE();
5400 input Option<Expression> max = NONE();
5401 output Expression exp;
5402 algorithm
5403 exp := match ty
5404 case Type.INTEGER()
5405 algorithm
5406
5/6
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 time.
✓ Branch 6 taken 1 time.
✓ Branch 7 taken 1 time.
3 if isSome(min) and isNonNegative(Util.getOption(min)) then
5407 // default = min if min >= 0
5408
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
1 SOME(exp) := min;
5409 elseif isSome(max) and isNonPositive(Util.getOption(max)) then
5410 // default = max if max <= 0
5411
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
1 SOME(exp) := max;
5412 else
5413 exp := INTEGER(0);
5414 end if;
5415 then
5416 exp;
5417
5418 case Type.REAL()
5419 algorithm
5420
5/6
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 time.
✓ Branch 6 taken 1 time.
✓ Branch 7 taken 1 time.
3 if isSome(min) and isNonNegative(Util.getOption(min)) then
5421 // default = min if min >= 0.0
5422
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
1 SOME(exp) := min;
5423 elseif isSome(max) and isNonPositive(Util.getOption(max)) then
5424 // default = max if max <= 0.0
5425
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
1 SOME(exp) := max;
5426 else
5427 exp := REAL(0.0);
5428 end if;
5429 then
5430 exp;
5431
5432 case Type.STRING() then STRING("");
5433 case Type.BOOLEAN() then BOOLEAN(false);
5434
5435 case Type.ENUMERATION()
5436 algorithm
5437
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1 time.
2 if isSome(min) then
5438 1 SOME(exp) := min;
5439 else
5440 1 exp := ENUM_LITERAL(ty, listHead(ty.literals), 1);
5441 end if;
5442 then
5443 exp;
5444
5445 ✗ case Type.ARRAY() then fillType(ty, makeDefaultValue(Type.arrayElementType(ty)));
5446 ✗ case Type.TUPLE() then TUPLE(ty, list(makeDefaultValue(t) for t in ty.types));
5447 end match;
5448 end makeDefaultValue;
5449
5450 function box
5451 input Expression exp;
5452 output Expression boxedExp;
5453 algorithm
5454 boxedExp := match exp
5455 case STRING() then exp;
5456 case RECORD()
5457
4/4
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 3 times.
33 then RECORD(exp.path, Type.box(exp.ty), list(box(e) for e in exp.elements));
5458 case BOX() then exp;
5459 case FILENAME() then exp;
5460 1775 else BOX(exp);
5461 end match;
5462 end box;
5463
5464 function unbox
5465 input Expression boxedExp;
5466 output Expression exp;
5467 algorithm
5468 exp := match boxedExp
5469 local
5470 Type ty;
5471
5472 15 case BOX() then boxedExp.exp;
5473
5474 else
5475 algorithm
5476 462 ty := typeOf(boxedExp);
5477
2/2
✓ Branch 1 taken 319 times.
✓ Branch 2 taken 143 times.
462 then
5478 if Type.isBoxed(ty) then UNBOX(boxedExp, Type.unbox(ty)) else boxedExp;
5479
5480 end match;
5481 end unbox;
5482
5483 function isNegated
5484 input Expression exp;
5485 output Boolean negated;
5486 algorithm
5487 negated := match exp
5488 63009 case INTEGER() then exp.value < 0;
5489 160979 case REAL() then exp.value < 0;
5490 2215 case CAST() then isNegated(exp.exp);
5491 case UNARY() then true;
5492 else false;
5493 end match;
5494 end isNegated;
5495
5496 function negate
5497 "Returns '-exp'"
5498 input output Expression exp;
5499 algorithm
5500 exp := match exp
5501 10222 case INTEGER() then INTEGER(-exp.value);
5502 384267 case REAL() then REAL(-exp.value);
5503 2 case CAST() then CAST(exp.ty, negate(exp.exp));
5504 25508 case UNARY() then exp.exp;
5505 147215 else UNARY(Operator.makeUMinus(typeOf(exp)), exp);
5506 end match;
5507 end negate;
5508
5509 function logicNegate
5510 "Returns 'not exp'"
5511 input Expression exp;
5512 output Expression outExp;
5513 algorithm
5514 outExp := match exp
5515 ✗ case BOOLEAN() then BOOLEAN(not exp.value);
5516 33 case LUNARY() then exp.exp;
5517 189 else LUNARY(Operator.makeNot(typeOf(exp)), exp);
5518 end match;
5519 end logicNegate;
5520
5521 function revertRange
5522 "reverts the direction of a range"
5523 input output Expression range;
5524 algorithm
5525 range := match range
5526 local
5527 Expression step;
5528 ✗ case RANGE(step = SOME(step)) then RANGE(range.ty, range.stop, SOME(negate(step)), range.start);
5529 1 case RANGE() then RANGE(range.ty, range.stop, SOME(INTEGER(-1)), range.start);
5530 else algorithm
5531 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because expression is not a range:\n"
5532 + toString(range)});
5533 ✗ then fail();
5534 end match;
5535 end revertRange;
5536
5537 function sliceRange
5538 "slices the range with a given zero-based start and one-based step"
5539 input output Expression range;
5540 input tuple<Integer, Integer, Integer> slice "start step stop";
5541 algorithm
5542 range := match (range, slice)
5543 local
5544 Integer start, step, stop;
5545 Integer slice_start, slice_step, slice_stop;
5546
5547 case (RANGE(), (slice_start, slice_step, slice_stop)) algorithm
5548 ✗ step := Util.applyOptionOrDefault(range.step, integerValue, 1);
5549 ✗ start := integerValue(range.start);
5550 // shift start and stop accordingly, multiply step
5551 ✗ stop := start + slice_stop * step;
5552 ✗ start := start + slice_start * step;
5553 ✗ step := slice_step * step;
5554 ✗ range := RANGE(range.ty, INTEGER(start), SOME(INTEGER(step)), INTEGER(stop));
5555 ✗ then retype(range);
5556
5557 else algorithm
5558 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because expression is not a range:\n"
5559 + toString(range)});
5560 ✗ then fail();
5561 end match;
5562 end sliceRange;
5563
5564 function arrayElements
5565 input Expression array;
5566 output array<Expression> elements;
5567 algorithm
5568
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 121251 times.
121251 ARRAY(elements = elements) := array;
5569 end arrayElements;
5570
5571 function arrayElementList
5572 input Expression array;
5573 output list<Expression> elements;
5574 algorithm
5575 elements := match array
5576 49677 case ARRAY() then arrayList(array.elements);
5577 end match;
5578 end arrayElementList;
5579
5580 function arrayScalarElements
5581 input Expression exp;
5582 output list<Expression> elements;
5583 algorithm
5584 1437 elements := listReverseInPlace(arrayScalarElements_impl(exp, {}));
5585 end arrayScalarElements;
5586
5587 function arrayScalarElements_impl
5588 input Expression exp;
5589 input output list<Expression> elements;
5590 algorithm
5591 elements := match exp
5592 case ARRAY()
5593 algorithm
5594
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4446 times.
✓ Branch 3 taken 7694 times.
✓ Branch 4 taken 4446 times.
16586 for e in exp.elements loop
5595 7694 elements := arrayScalarElements_impl(e, elements);
5596 end for;
5597 then
5598 elements;
5599
5600 else exp :: elements;
5601 end match;
5602 end arrayScalarElements_impl;
5603
5604 function arrayScalarElement
5605 input Expression arrayExp;
5606 output Expression scalarExp;
5607 algorithm
5608 scalarExp := match arrayExp
5609 case ARRAY()
5610 guard arrayLength(arrayExp.elements) == 1
5611 then arrayGet(arrayExp.elements, 1);
5612 end match;
5613 end arrayScalarElement;
5614
5615 function hasArrayCall
5616 "Returns true if the given expression contains a function call that returns
5617 an array, otherwise false."
5618 input Expression exp;
5619 output Boolean hasArrayCall;
5620 algorithm
5621 841425 hasArrayCall := contains(exp, hasArrayCall2);
5622 end hasArrayCall;
5623
5624 function hasArrayCall2
5625 input Expression exp;
5626 output Boolean hasArrayCall;
5627 protected
5628 Call call;
5629 Type ty;
5630 algorithm
5631 hasArrayCall := match exp
5632 case CALL(call = call)
5633 algorithm
5634 52950 ty := Call.typeOf(call);
5635
4/4
✓ Branch 1 taken 8444 times.
✓ Branch 2 taken 44506 times.
✓ Branch 4 taken 1399 times.
✓ Branch 5 taken 7045 times.
52950 then
5636 Type.isArray(ty) and Call.isVectorizeable(call);
5637
5638 case TUPLE_ELEMENT(tupleExp = CALL(call = call))
5639 algorithm
5640 11 ty := Type.nthTupleType(Call.typeOf(call), exp.index);
5641
3/4
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
11 then
5642 Type.isArray(ty) and Call.isVectorizeable(call);
5643
5644 else false;
5645 end match;
5646 end hasArrayCall2;
5647
5648 function transposeArray
5649 input Expression arrayExp;
5650 output Expression outExp;
5651 protected
5652 Dimension dim1, dim2;
5653 list<Dimension> rest_dims;
5654 Type ty, row_ty;
5655 Boolean literal;
5656 array<Expression> arr;
5657 array<array<Expression>> matrix_arr;
5658 algorithm
5659 outExp := match arrayExp
5660 case ARRAY(Type.ARRAY(ty, dim1 :: dim2 :: rest_dims), arr, literal)
5661 algorithm
5662
1/2
✓ Branch 0 taken 1246 times.
✗ Branch 1 not taken.
1246 if not arrayEmpty(arr) then
5663 1246 row_ty := Type.ARRAY(ty, dim1 :: rest_dims);
5664 1246 matrix_arr := Array.map(arr, arrayElements);
5665 1246 matrix_arr := Array.transpose(matrix_arr);
5666
2/2
✓ Branch 0 taken 1220 times.
✓ Branch 1 taken 26 times.
2466 arr := Array.map(matrix_arr, function makeArray(ty = row_ty, literal = literal));
5667 end if;
5668 1246 then
5669 makeArray(Type.ARRAY(ty, dim2 :: dim1 :: rest_dims), arr, literal);
5670 end match;
5671 end transposeArray;
5672
5673 function makeIdentityMatrix
5674 input Integer n;
5675 input Type elementType;
5676 output Expression matrix;
5677 protected
5678 array<Expression> row, rows;
5679 Expression zero, one;
5680 Type row_ty;
5681 algorithm
5682 1112 zero := makeZero(elementType);
5683 1112 one := makeOne(elementType);
5684
5685 1112 rows := arrayCreateNoInit(n, zero);
5686 2224 row_ty := Type.ARRAY(elementType, {Dimension.fromInteger(n)});
5687
5688
1/2
✓ Branch 0 taken 1112 times.
✗ Branch 1 not taken.
4446 for i in 1:n loop
5689 3334 row := arrayCreateNoInit(n, zero);
5690
5691 10000 for j in 1:n loop
5692
2/2
✓ Branch 0 taken 6666 times.
✓ Branch 1 taken 3334 times.
10000 arrayUpdateNoBoundsChecking(row, j, if i == j then one else zero);
5693 end for;
5694
5695 3334 arrayUpdateNoBoundsChecking(rows, i, makeArray(row_ty, row, true));
5696 end for;
5697
5698 1112 matrix := makeExpArray(rows, row_ty, true);
5699 end makeIdentityMatrix;
5700
5701
5702 // Upper-triangular mask (including diagonal) as a literal matrix.
5703 // Mask U[i,j] = 1 if i <= j else 0
5704 function makeTriuMask
5705 input Integer n;
5706 input Type elTy;
5707 output Expression mask;
5708 protected
5709 array<Expression> row, rows;
5710 Expression zero, one;
5711 Type row_ty;
5712 Integer i, j;
5713 algorithm
5714 ✗ zero := Expression.makeZero(elTy);
5715 ✗ one := Expression.makeOne(elTy);
5716
5717 ✗ rows := arrayCreateNoInit(n, zero);
5718 ✗ row_ty := Type.ARRAY(elTy, {Dimension.fromInteger(n)});
5719
5720 ✗ for i in 1:n loop
5721 ✗ row := arrayCreateNoInit(n, zero);
5722
5723 ✗ for j in 1:n loop
5724 ✗ arrayUpdateNoBoundsChecking(row, j, if i <= j then one else zero);
5725 end for;
5726
5727 ✗ arrayUpdateNoBoundsChecking(rows, i, Expression.makeArray(row_ty, row, true));
5728 end for;
5729
5730 ✗ mask := Expression.makeExpArray(rows, row_ty, true);
5731 end makeTriuMask;
5732
5733 function promote
5734 input output Expression e;
5735 input output Type ty;
5736 input Integer n;
5737 protected
5738 list<Dimension> dims;
5739 Type ety;
5740 list<Type> tys = {};
5741 Boolean is_array;
5742 algorithm
5743 // Construct the dimensions that needs to be added.
5744
2/2
✓ Branch 2 taken 36310 times.
✓ Branch 3 taken 24325 times.
60635 dims := list(Dimension.fromInteger(1) for i in Type.dimensionCount(ty):n-1);
5745
5746
2/2
✓ Branch 0 taken 5652 times.
✓ Branch 1 taken 18673 times.
24325 if not listEmpty(dims) then
5747 // Concatenate the existing dimensions and the added ones.
5748 18673 dims := listAppend(Type.arrayDims(ty), dims);
5749
5750 // Construct the result type.
5751 18673 is_array := Type.isArray(ty);
5752 18673 ety := Type.arrayElementType(ty);
5753 18673 ty := Type.liftArrayLeftList(ety, dims);
5754
5755 // Construct the expression types, to avoid having to create a new type
5756 // for each subexpression that will be created.
5757
2/2
✓ Branch 0 taken 37346 times.
✓ Branch 1 taken 18673 times.
56019 while not listEmpty(dims) loop
5758 37346 tys := Type.liftArrayLeftList(ety, dims) :: tys;
5759 37346 dims := listRest(dims);
5760 end while;
5761
5762 18673 e := promote2(e, is_array, n, listReverse(tys));
5763 end if;
5764 end promote;
5765
5766 function promote2
5767 input Expression exp;
5768 input Boolean isArray;
5769 input Integer dims;
5770 input list<Type> types;
5771 output Expression outExp = exp;
5772 algorithm
5773 outExp := match (exp, types)
5774 local
5775 Type ty;
5776 list<Type> rest_ty;
5777 Boolean expanded;
5778
5779 // No types left, we're done!
5780 case (_, {}) then exp;
5781
5782 // An array, promote each element in the array.
5783 case (ARRAY(), ty :: rest_ty)
5784 845 then makeArray(ty, Array.map(exp.elements,
5785 function promote2(isArray = false, dims = dims, types = rest_ty)));
5786
5787 // An expression with array type, but which is not an array expression.
5788 // Such an expression can't be promoted here, so we create a promote call instead.
5789 case (_, _) guard isArray
5790 algorithm
5791
3/4
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 859 times.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
867 if Flags.getConfigBool(Flags.NEW_BACKEND) and not Expression.isLiteral(exp) then
5792 8 expanded := false;
5793 else
5794 859 (outExp, expanded) := ExpandExp.expand(exp);
5795 end if;
5796
5797 // The ARRAY case above is what consumes the expansion; recursing on
5798 // anything else would not terminate.
5799
3/4
✓ Branch 0 taken 676 times.
✓ Branch 1 taken 191 times.
✓ Branch 3 taken 676 times.
✗ Branch 4 not taken.
867 if expanded and isArray(outExp) then
5800 676 outExp := promote2(outExp, true, dims, types);
5801 else
5802 382 outExp := CALL(Call.makeTypedCall(
5803 NFBuiltinFuncs.PROMOTE, {exp, INTEGER(dims)}, variability(exp), purity(exp), listHead(types)));
5804 end if;
5805 then
5806 outExp;
5807
5808 // A scalar expression, promote it as many times as the number of types given.
5809 else
5810 algorithm
5811 outExp := exp;
5812
2/2
✓ Branch 1 taken 38250 times.
✓ Branch 2 taken 20613 times.
58863 for ty in listReverse(types) loop
5813 38250 outExp := makeArray(ty, arrayCreate(1, outExp));
5814 end for;
5815 then
5816 outExp;
5817
5818 end match;
5819 end promote2;
5820
5821 function variability
5822 input Expression exp;
5823 output Variability var;
5824 algorithm
5825 var := match exp
5826 case INTEGER() then Variability.CONSTANT;
5827 case REAL() then Variability.CONSTANT;
5828 case STRING() then Variability.CONSTANT;
5829 case BOOLEAN() then Variability.CONSTANT;
5830 case ENUM_LITERAL() then Variability.CONSTANT;
5831 case CLKCONST() then Variability.DISCRETE;
5832 6088175 case CREF() then ComponentRef.variability(exp.cref);
5833 case TYPENAME() then Variability.CONSTANT;
5834 289 case ARRAY() then variabilityArray(exp.elements);
5835 ✗ case MATRIX() then List.fold(exp.elements, variabilityList, Variability.CONSTANT);
5836
5837 case RANGE()
5838 algorithm
5839 5 var := variability(exp.start);
5840 5 var := Prefixes.variabilityMax(var, variability(exp.stop));
5841
5842
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3 times.
5 if isSome(exp.step) then
5843 2 var := Prefixes.variabilityMax(var, variability(Util.getOption(exp.step)));
5844 end if;
5845 then
5846 var;
5847
5848 ✗ case TUPLE() then variabilityList(exp.elements);
5849 76 case RECORD() then variabilityList(exp.elements);
5850 7306 case CALL() then Call.variability(exp.call);
5851 case SIZE()
5852 algorithm
5853
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2019 times.
✓ Branch 2 taken 2019 times.
✗ Branch 3 not taken.
2019 if isSome(exp.dimIndex) then
5854 2019 var := Prefixes.variabilityMax(Variability.PARAMETER,
5855 variability(Util.getOption(exp.dimIndex)));
5856 else
5857 var := Variability.PARAMETER;
5858 end if;
5859 then
5860 var;
5861
5862 case END() then Variability.PARAMETER;
5863 1409717 case MULTARY() then Prefixes.variabilityMax(variabilityList(exp.arguments), variabilityList(exp.arguments));
5864 6278522 case BINARY() then Prefixes.variabilityMax(variability(exp.exp1), variability(exp.exp2));
5865 1135 case UNARY() then variability(exp.exp);
5866 495 case LBINARY() then Prefixes.variabilityMax(variability(exp.exp1), variability(exp.exp2));
5867 75 case LUNARY() then variability(exp.exp);
5868 case RELATION()
5869 5898 then Prefixes.variabilityMin(
5870 Prefixes.variabilityMax(variability(exp.exp1), variability(exp.exp2)),
5871 Variability.DISCRETE);
5872
5873 case IF()
5874 949 then Prefixes.variabilityMax(variability(exp.condition),
5875 Prefixes.variabilityMax(variability(exp.trueBranch), variability(exp.falseBranch)));
5876
5877 23 case CAST() then variability(exp.exp);
5878 ✗ case BOX() then variability(exp.exp);
5879 ✗ case UNBOX() then variability(exp.exp);
5880 case SUBSCRIPTED_EXP()
5881 204 then Prefixes.variabilityMax(variability(exp.exp), Subscript.variabilityList(exp.subscripts));
5882 6 case TUPLE_ELEMENT() then variability(exp.tupleExp);
5883 114 case RECORD_ELEMENT() then variability(exp.recordExp);
5884 ✗ case MUTABLE() then variability(Mutable.access(exp.exp));
5885 ✗ case SHARED_LITERAL() then variability(exp.exp);
5886 case EMPTY() then Variability.CONSTANT;
5887 case PARTIAL_FUNCTION_APPLICATION() then Variability.CONTINUOUS;
5888 case FILENAME() then Variability.CONSTANT;
5889 case INSTANCE_NAME() then Variability.CONSTANT;
5890 else
5891 algorithm
5892 ✗ Error.terminate(getInstanceName() + " got unknown expression.", sourceInfo());
5893 ✗ then
5894 fail();
5895 end match;
5896 end variability;
5897
5898 function variabilityArray
5899 input array<Expression> expl;
5900 input output Variability var = Variability.CONSTANT;
5901 algorithm
5902
2/2
✓ Branch 1 taken 3291 times.
✓ Branch 2 taken 289 times.
3580 for e in expl loop
5903 3291 var := Prefixes.variabilityMax(var, variability(e));
5904 end for;
5905 end variabilityArray;
5906
5907 function variabilityList
5908 input list<Expression> expl;
5909 input output Variability var = Variability.CONSTANT;
5910 algorithm
5911
2/2
✓ Branch 0 taken 5620712 times.
✓ Branch 1 taken 2819510 times.
8440222 for e in expl loop
5912 5620712 var := Prefixes.variabilityMax(var, variability(e));
5913 end for;
5914 end variabilityList;
5915
5916 function purity
5917 input Expression exp;
5918 output Purity pur;
5919 algorithm
5920 pur := match exp
5921 case INTEGER() then Purity.PURE;
5922 case REAL() then Purity.PURE;
5923 case STRING() then Purity.PURE;
5924 case BOOLEAN() then Purity.PURE;
5925 case ENUM_LITERAL() then Purity.PURE;
5926 case CLKCONST() then Purity.PURE;
5927 29552 case CREF() then ComponentRef.purity(exp.cref);
5928 case TYPENAME() then Purity.PURE;
5929 25 case ARRAY() then purityArray(exp.elements);
5930 ✗ case MATRIX() then List.fold(exp.elements, purityList, Purity.PURE);
5931
5932 case RANGE()
5933 algorithm
5934 5882 pur := purity(exp.start);
5935 5882 pur := Prefixes.purityMin(pur, purity(exp.stop));
5936
5937
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5882 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 5880 times.
5882 if isSome(exp.step) then
5938 2 pur := Prefixes.purityMin(pur, purity(Util.getOption(exp.step)));
5939 end if;
5940 then
5941 pur;
5942
5943 ✗ case TUPLE() then purityList(exp.elements);
5944 75 case RECORD() then purityList(exp.elements);
5945 158 case CALL() then Call.purity(exp.call);
5946 case SIZE()
5947
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
✓ Branch 2 taken 63 times.
✗ Branch 3 not taken.
63 then if isSome(exp.dimIndex) then purity(Util.getOption(exp.dimIndex)) else Purity.PURE;
5948
5949 case END() then Purity.PURE;
5950 6766 case BINARY() then Prefixes.purityMin(purity(exp.exp1), purity(exp.exp2));
5951 233 case UNARY() then purity(exp.exp);
5952 ✗ case LBINARY() then Prefixes.purityMin(purity(exp.exp1), purity(exp.exp2));
5953 15 case LUNARY() then purity(exp.exp);
5954 68 case RELATION() then Prefixes.purityMin(purity(exp.exp1), purity(exp.exp2));
5955 89 case MULTARY() then Prefixes.purityMin(purityList(exp.arguments), purityList(exp.inv_arguments));
5956 71 case IF() then Prefixes.purityMin(purity(exp.condition),
5957 Prefixes.purityMin(purity(exp.trueBranch), purity(exp.falseBranch)));
5958 16 case CAST() then purity(exp.exp);
5959 ✗ case BOX() then purity(exp.exp);
5960 ✗ case UNBOX() then purity(exp.exp);
5961 case SUBSCRIPTED_EXP()
5962 183 then Prefixes.purityMin(purity(exp.exp), Subscript.purityList(exp.subscripts));
5963 ✗ case TUPLE_ELEMENT() then purity(exp.tupleExp);
5964 60 case RECORD_ELEMENT() then purity(exp.recordExp);
5965 ✗ case MUTABLE() then purity(Mutable.access(exp.exp));
5966 ✗ case SHARED_LITERAL() then purity(exp.exp);
5967 case EMPTY() then Purity.PURE;
5968 case PARTIAL_FUNCTION_APPLICATION() then Purity.PURE;
5969 case FILENAME() then Purity.PURE;
5970 case INSTANCE_NAME() then Purity.PURE;
5971 else
5972 algorithm
5973 ✗ Error.terminate(getInstanceName() + " got unknown expression.", sourceInfo());
5974 ✗ then
5975 fail();
5976 end match;
5977 end purity;
5978
5979 function purityArray
5980 input array<Expression> expl;
5981 input output Purity pur = Purity.PURE;
5982 algorithm
5983
2/2
✓ Branch 1 taken 77 times.
✓ Branch 2 taken 25 times.
102 for e in expl loop
5984 77 pur := Prefixes.purityMin(pur, purity(e));
5985 end for;
5986 end purityArray;
5987
5988 function purityList
5989 input list<Expression> expl;
5990 input output Purity pur = Purity.PURE;
5991 algorithm
5992
2/2
✓ Branch 0 taken 548 times.
✓ Branch 1 taken 253 times.
801 for e in expl loop
5993 548 pur := Prefixes.purityMin(pur, purity(e));
5994 end for;
5995 end purityList;
5996
5997 function makeMutable
5998 input Expression exp;
5999 output Expression outExp;
6000 algorithm
6001 134325 outExp := MUTABLE(Mutable.create(exp));
6002 end makeMutable;
6003
6004 function makeImmutable
6005 input Expression exp;
6006 output Expression outExp;
6007 algorithm
6008 outExp := match exp
6009 117371 case MUTABLE() then Mutable.access(exp.exp);
6010 else exp;
6011 end match;
6012 end makeImmutable;
6013
6014 function isMutable
6015 input Expression exp;
6016 output Boolean isMutable;
6017 algorithm
6018 isMutable := match exp
6019 case MUTABLE() then true;
6020 else false;
6021 end match;
6022 end isMutable;
6023
6024 function updateMutable
6025 input Expression mutableExp;
6026 input Expression value;
6027 protected
6028 Mutable<Expression> exp_ptr;
6029 algorithm
6030
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 MUTABLE(exp = exp_ptr) := mutableExp;
6031 38 Mutable.update(exp_ptr, value);
6032 end updateMutable;
6033
6034 function applyMutable
6035 input Expression mutableExp;
6036 input FuncType func;
6037
6038 partial function FuncType
6039 input output Expression exp;
6040 end FuncType;
6041 protected
6042 Mutable<Expression> exp_ptr;
6043 algorithm
6044
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 133747 times.
133747 MUTABLE(exp = exp_ptr) := mutableExp;
6045
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 133747 times.
133747 Mutable.update(exp_ptr, func(Mutable.access(exp_ptr)));
6046 end applyMutable;
6047
6048 function isEmpty
6049 input Expression exp;
6050 output Boolean empty;
6051 algorithm
6052 empty := match exp
6053 case EMPTY() then true;
6054 else false;
6055 end match;
6056 end isEmpty;
6057
6058 function isEnd
6059 input Expression exp;
6060 output Boolean isend;
6061 algorithm
6062 isend := match exp
6063 case END() then true;
6064 else false;
6065 end match;
6066 end isEnd;
6067
6068 function enumIndexExp
6069 input Expression enumExp;
6070 output Expression indexExp;
6071 algorithm
6072 indexExp := match enumExp
6073 ✗ case ENUM_LITERAL() then INTEGER(enumExp.index);
6074 ✗ else CALL(Call.makeTypedCall(
6075 NFBuiltinFuncs.INTEGER_ENUM, {enumExp}, variability(enumExp), Purity.PURE));
6076 end match;
6077 end enumIndexExp;
6078
6079 function toScalar
6080 input Expression exp;
6081 output Expression outExp;
6082 algorithm
6083 outExp := match exp
6084 case ARRAY()
6085 guard arrayLength(exp.elements) == 1
6086 ✗ then toScalar(arrayGet(exp.elements, 1));
6087 else exp;
6088 end match;
6089 end toScalar;
6090
6091 function tupleElement
6092 input Expression exp;
6093 input Integer index;
6094 output Expression tupleElem;
6095 algorithm
6096 tupleElem := match exp
6097 7 case TUPLE() then listGet(exp.elements, index);
6098
6099 case ARRAY()
6100 algorithm
6101 ✗ exp.elements := Array.map(exp.elements, function tupleElement(index = index));
6102 then
6103 exp;
6104
6105 case SUBSCRIPTED_EXP(split = true)
6106 ✗ then mapSplitExpressions(exp, function tupleElement(index = index));
6107
6108 1853 else TUPLE_ELEMENT(exp, index, Type.nthTupleType(typeOf(exp), index));
6109 end match;
6110 end tupleElement;
6111
6112 function recordElement
6113 "Returns the field with the given name in a record expression. If the
6114 expression is an array it will return the equivalent of calling the
6115 function on each element of the array."
6116 input String elementName;
6117 input Expression recordExp;
6118 output Expression outExp;
6119 algorithm
6120 outExp := match recordExp
6121 local
6122 InstNode node;
6123 Class cls;
6124 ClassTree cls_tree;
6125 Type ty;
6126 Integer index;
6127 ComponentRef cref;
6128 array<Expression> arr;
6129
6130 case RECORD(ty = Type.COMPLEX())
6131 algorithm
6132 174271 node := Type.complexNode(recordExp.ty);
6133 174271 cls := InstNode.getClass(node);
6134 174271 index := Class.lookupComponentIndex(elementName, cls);
6135 174271 then
6136 listGet(recordExp.elements, index);
6137
6138 case CREF()
6139 algorithm
6140 1129 node := Type.complexNode(Type.arrayElementType(recordExp.ty));
6141 1129 cls_tree := Class.classTree(InstNode.getClass(node));
6142
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1129 times.
1129 (node, false) := ClassTree.lookupElement(elementName, cls_tree);
6143 1129 ty := InstNode.getType(node);
6144 1129 cref := ComponentRef.prefixCref(node, ty, {}, recordExp.cref);
6145 1129 ty := Type.liftArrayLeftList(ty, Type.arrayDims(recordExp.ty));
6146 1129 then
6147 CREF(ty, cref);
6148
6149 case ARRAY(ty = Type.ARRAY(elementType = Type.COMPLEX()))
6150 guard arrayEmpty(recordExp.elements)
6151 algorithm
6152 ✗ node := Type.complexNode(Type.arrayElementType(recordExp.ty));
6153 ✗ cls := InstNode.getClass(node);
6154 ✗ index := Class.lookupComponentIndex(elementName, cls);
6155 ✗ ty := InstNode.getType(Class.nthComponent(index, cls));
6156 ✗ ty := Type.liftArrayLeftList(ty, Type.arrayDims(recordExp.ty));
6157 ✗ then
6158 makeEmptyArray(ty);
6159
6160 case ARRAY(ty = Type.ARRAY(elementType = Type.COMPLEX()))
6161 algorithm
6162 366 node := Type.complexNode(Type.arrayElementType(recordExp.ty));
6163 366 index := Class.lookupComponentIndex(elementName, InstNode.getClass(node));
6164 366 arr := Array.map(recordExp.elements, function nthRecordElement(index = index));
6165 732 ty := Type.liftArrayLeft(typeOf(arrayGet(arr, 1)),
6166 Dimension.fromInteger(arrayLength(arr)));
6167 366 then
6168 makeArray(ty, arr, recordExp.literal);
6169
6170 case SUBSCRIPTED_EXP()
6171 algorithm
6172 305 outExp := recordElement(elementName, recordExp.exp);
6173 305 ty := Type.subscript(typeOf(outExp), recordExp.subscripts);
6174 305 then
6175 SUBSCRIPTED_EXP(outExp, recordExp.subscripts, ty, recordExp.split);
6176
6177 ✗ case EMPTY() then fail();
6178
6179 else
6180 algorithm
6181 1192 ty := typeOf(recordExp);
6182 1192 node := Type.complexNode(Type.arrayElementType(ty));
6183 1192 cls := InstNode.getClass(node);
6184 1192 index := Class.lookupComponentIndex(elementName, cls);
6185 1192 ty := Type.liftArrayLeftList(
6186 InstNode.getType(Class.nthComponent(index, cls)),
6187 Type.arrayDims(ty));
6188 1192 then
6189 RECORD_ELEMENT(recordExp, index, elementName, ty);
6190
6191 end match;
6192 end recordElement;
6193
6194 function nthRecordElement
6195 "Returns the nth field of a record expression. If the expression is an array
6196 it will return an array with the nth field in each array element."
6197 input Integer index;
6198 input Expression recordExp;
6199 output Expression outExp;
6200 algorithm
6201 outExp := match recordExp
6202 local
6203 InstNode node;
6204 Type ty;
6205 array<Expression> arr;
6206 Expression trueBranch, falseBranch;
6207
6208 241 case RECORD() then listGet(recordExp.elements, index);
6209
6210 case CREF()
6211 algorithm
6212 2187 node := Type.complexNode(Type.arrayElementType(typeOf(recordExp)));
6213 2187 node := Class.nthComponent(index, InstNode.getClass(node));
6214 2187 then
6215 fromCref(ComponentRef.prefixCref(node, InstNode.getType(node), {}, recordExp.cref));
6216
6217 case ARRAY(ty = Type.ARRAY(elementType = Type.COMPLEX()))
6218 guard arrayEmpty(recordExp.elements)
6219 6 then makeEmptyArray(InstNode.getType(Class.nthComponent(index,
6220 InstNode.getClass(Type.complexNode(Type.arrayElementType(recordExp.ty))))));
6221
6222 case ARRAY()
6223 algorithm
6224 35 arr := Array.map(recordExp.elements, function nthRecordElement(index = index));
6225 70 ty := Type.liftArrayLeft(typeOf(arrayGet(arr, 1)), listHead(Type.arrayDims(recordExp.ty)));
6226 35 then
6227 makeArray(ty, arr);
6228
6229 case RECORD_ELEMENT(ty = Type.ARRAY(elementType = Type.COMPLEX()))
6230 algorithm
6231 ✗ node := Type.complexNode(Type.arrayElementType(recordExp.ty));
6232 ✗ node := Class.nthComponent(index, InstNode.getClass(node));
6233 ✗ then
6234 RECORD_ELEMENT(recordExp, index, InstNode.name(node),
6235 Type.liftArrayLeftList(InstNode.getType(node), Type.arrayDims(recordExp.ty)));
6236
6237 case SUBSCRIPTED_EXP()
6238 algorithm
6239 ✗ outExp := nthRecordElement(index, recordExp.exp);
6240 ✗ ty := Type.subscript(typeOf(outExp), recordExp.subscripts);
6241 ✗ then
6242 SUBSCRIPTED_EXP(outExp, recordExp.subscripts, ty, recordExp.split);
6243
6244 case IF()
6245 algorithm
6246 ✗ trueBranch := nthRecordElement(index, recordExp.trueBranch);
6247 ✗ falseBranch := nthRecordElement(index, recordExp.falseBranch);
6248 ✗ then
6249 IF(typeOf(trueBranch), recordExp.condition, trueBranch, falseBranch);
6250
6251 else
6252 algorithm
6253 199 node := Type.complexNode(typeOf(recordExp));
6254 199 node := Class.nthComponent(index, InstNode.getClass(node));
6255 199 then
6256 RECORD_ELEMENT(recordExp, index, InstNode.name(node), InstNode.getType(node));
6257
6258 end match;
6259 end nthRecordElement;
6260
6261 function getRecordElements
6262 input Expression exp;
6263 output list<Expression> elements = {};
6264 protected
6265 Type ty = Type.arrayElementType(typeOf(exp));
6266 algorithm
6267 elements := match ty
6268 local
6269 ComplexType complexTy;
6270
6271 case Type.COMPLEX(complexTy = complexTy as ComplexType.RECORD()) algorithm
6272
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
✓ Branch 2 taken 96 times.
✗ Branch 3 not taken.
1311 for i in arrayLength(complexTy.fields):-1:1 loop
6273 1119 elements := recordElement(Record.Field.name(complexTy.fields[i]), exp) :: elements;
6274 end for;
6275 then elements;
6276 else elements;
6277 end match;
6278 end getRecordElements;
6279
6280 function retype
6281 input output Expression exp;
6282 algorithm
6283 () := match exp
6284 local
6285 Type ty;
6286
6287 case RANGE()
6288 algorithm
6289 608 exp.ty := TypeCheck.keepRangeSize(
6290 TypeCheck.getRangeType(exp.start, exp.step, exp.stop,
6291 typeOf(exp.start), Absyn.dummyInfo), exp.ty);
6292 then
6293 ();
6294
6295 case CALL(call = Call.TYPED_ARRAY_CONSTRUCTOR())
6296 algorithm
6297 19 exp.call := Call.retype(exp.call);
6298 then
6299 ();
6300
6301 else
6302 algorithm
6303 22127 ty := typeOf(exp);
6304
6305
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 22127 times.
22127 if Type.isConditionalArray(ty) then
6306 ✗ ty := Type.simplifyConditionalArray(ty);
6307 ✗ exp := setType(ty, exp);
6308 end if;
6309 then
6310 ();
6311
6312 end match;
6313 end retype;
6314
6315 function nthEnumLiteral
6316 input Type ty;
6317 input Integer n;
6318 output Expression exp;
6319 algorithm
6320 ✗ exp := ENUM_LITERAL(ty, Type.nthEnumLiteral(ty, n), n);
6321 end nthEnumLiteral;
6322
6323 function createIterationRanges
6324 input output Expression exp;
6325 input list<tuple<InstNode, Expression>> iterators;
6326 output list<Expression> ranges = {};
6327 output list<Mutable<Expression>> iters = {};
6328 protected
6329 InstNode node;
6330 Expression range;
6331 Mutable<Expression> iter;
6332 algorithm
6333
2/2
✓ Branch 0 taken 806 times.
✓ Branch 1 taken 805 times.
1611 for i in iterators loop
6334 806 (node, range) := i;
6335 806 iter := Mutable.create(INTEGER(0));
6336
4/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 806 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 806 times.
807 ranges := list(replaceIterator(r, node, MUTABLE(iter)) for r in ranges);
6337 806 exp := replaceIterator(exp, node, MUTABLE(iter));
6338 iters := iter :: iters;
6339 ranges := range :: ranges;
6340 end for;
6341 end createIterationRanges;
6342
6343 function foldReduction
6344 input Expression exp;
6345 input list<tuple<InstNode, Expression>> iterators;
6346 input Expression foldExp;
6347 input MapFn mapFn;
6348 input FoldFn foldFn;
6349 output Expression result;
6350
6351 partial function MapFn
6352 input output Expression exp;
6353 end MapFn;
6354
6355 partial function FoldFn
6356 input Expression exp1;
6357 input Expression exp2;
6358 output Expression result;
6359 end FoldFn;
6360 protected
6361 Expression e;
6362 list<Expression> ranges = {};
6363 list<Mutable<Expression>> iters = {};
6364 algorithm
6365 274 (e, ranges, iters) := createIterationRanges(exp, iterators);
6366 274 result := foldReduction2(e, ranges, iters, foldExp, mapFn, foldFn);
6367 end foldReduction;
6368
6369 function foldReduction2
6370 input Expression exp;
6371 input list<Expression> ranges;
6372 input list<Mutable<Expression>> iterators;
6373 input Expression foldExp;
6374 input MapFn mapFn;
6375 input FoldFn foldFn;
6376 output Expression result;
6377
6378 partial function MapFn
6379 input output Expression exp;
6380 end MapFn;
6381
6382 partial function FoldFn
6383 input Expression exp1;
6384 input Expression exp2;
6385 output Expression result;
6386 end FoldFn;
6387 protected
6388 Expression range, value;
6389 list<Expression> ranges_rest;
6390 Mutable<Expression> iter;
6391 list<Mutable<Expression>> iters_rest;
6392 ExpressionIterator range_iter;
6393 algorithm
6394
2/2
✓ Branch 0 taken 6692 times.
✓ Branch 1 taken 281 times.
6973 if listEmpty(ranges) then
6395
4/6
✓ Branch 0 taken 6362 times.
✓ Branch 1 taken 330 times.
✓ Branch 2 taken 6362 times.
✗ Branch 3 not taken.
✓ Branch 7 taken 330 times.
✗ Branch 8 not taken.
6692 result := foldFn(foldExp, mapFn(exp));
6396 else
6397 281 range :: ranges_rest := ranges;
6398 281 range := Ceval.evalExp(range);
6399
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 281 times.
281 iter :: iters_rest := iterators;
6400 281 range_iter := ExpressionIterator.fromExp(range);
6401 result := foldExp;
6402
6403
2/2
✓ Branch 1 taken 6699 times.
✓ Branch 2 taken 281 times.
6980 while ExpressionIterator.hasNext(range_iter) loop
6404 6699 (range_iter, value) := ExpressionIterator.next(range_iter);
6405 6699 Mutable.update(iter, value);
6406 6699 result := foldReduction2(exp, ranges_rest, iters_rest, result, mapFn, foldFn);
6407 end while;
6408 end if;
6409 end foldReduction2;
6410
6411 function isPure
6412 input Expression exp;
6413 output Boolean isPure;
6414 algorithm
6415 isPure := match exp
6416 3199 case CREF() then not ComponentRef.isIterator(exp.cref);
6417 case CALL()
6418 then match AbsynUtil.pathFirstIdent(Call.functionName(exp.call))
6419 case "Connections" then false;
6420 case "cardinality" then false;
6421 3 else not Call.isImpure(exp.call);
6422 end match;
6423 else true;
6424 end match;
6425 end isPure;
6426
6427 function containsCref
6428 "returns true if the expression contains the cref"
6429 input Expression exp;
6430 input ComponentRef cref;
6431 output Boolean b;
6432 algorithm
6433 7180 b := fold(exp, function isCrefEqual(cref = cref), false);
6434 end containsCref;
6435
6436 function isCrefEqual
6437 input Expression exp;
6438 input output Boolean b;
6439 input ComponentRef cref;
6440 algorithm
6441 b := match (b, exp)
6442 11062 case (false, CREF()) then ComponentRef.isEqual(exp.cref, cref);
6443 else b;
6444 end match;
6445 end isCrefEqual;
6446
6447 function containsCrefSet
6448 "returns true if the expression contains any crefs in the set"
6449 input Expression exp;
6450 input UnorderedSet<ComponentRef> set;
6451 output Boolean b;
6452 algorithm
6453 ✗ b := fold(exp, function isCrefEqualSet(set = set), false);
6454 end containsCrefSet;
6455
6456 function isCrefEqualSet
6457 input Expression exp;
6458 input output Boolean b;
6459 input UnorderedSet<ComponentRef> set;
6460 algorithm
6461 b := match (b, exp)
6462 ✗ case (false, CREF()) then UnorderedSet.contains(exp.cref, set);
6463 else b;
6464 end match;
6465 end isCrefEqualSet;
6466
6467 function filterSplitIndices
6468 input output Expression exp;
6469 input InstNode node;
6470 protected
6471 list<Subscript> subs;
6472 algorithm
6473 exp := match exp
6474 case SUBSCRIPTED_EXP(exp = _, subscripts = subs)
6475 algorithm
6476
6/6
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 1 time.
✓ Branch 6 taken 1 time.
3 subs := list(s for s guard not filterSplitIndices2(s, node) in subs);
6477
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✓ Branch 3 taken 1 time.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 time.
1 then
6478 if listEmpty(subs) then
6479 exp.exp
6480 elseif Type.isUnknown(exp.ty) then
6481 SUBSCRIPTED_EXP(exp.exp, subs, exp.ty, List.any(subs, Subscript.isSplit))
6482 else
6483 applySubscripts(subs, exp.exp);
6484
6485 else exp;
6486 end match;
6487 end filterSplitIndices;
6488
6489 function filterSplitIndices2
6490 input Subscript sub;
6491 input InstNode node;
6492 output Boolean matching;
6493 algorithm
6494 matching := match sub
6495 ✗ case Subscript.SPLIT_INDEX() then InstNode.refEqual(InstNode.borrow(sub.node), node);
6496 2 case Subscript.SPLIT_PROXY() then InstNode.refEqual(InstNode.borrow(sub.parent), node);
6497 else false;
6498 end match;
6499 end filterSplitIndices2;
6500
6501 function expandSplitIndices
6502 "Replaces split indices in a subscripted expression with : subscripts."
6503 input Expression exp;
6504 output Expression outExp;
6505 algorithm
6506 outExp := match exp
6507 case SUBSCRIPTED_EXP()
6508 4814 then applySubscripts(Subscript.expandSplitIndices(exp.subscripts, {}), exp.exp);
6509
6510 case CREF()
6511 algorithm
6512 101955 exp.cref := ComponentRef.expandSplitSubscripts(exp.cref);
6513 then
6514 exp;
6515
6516 else exp;
6517 end match;
6518 end expandSplitIndices;
6519
6520 function expandNonListedSplitIndices
6521 "Replaces split indices in a subscripted expression with : subscripts,
6522 except for indices that reference nodes in the given list."
6523 input Expression exp;
6524 input list<InstNode> indicesToKeep;
6525 output Expression outExp;
6526 algorithm
6527 outExp := match exp
6528 case SUBSCRIPTED_EXP(split = true)
6529 5 then applySubscripts(Subscript.expandSplitIndices(exp.subscripts, indicesToKeep), exp.exp);
6530 else exp;
6531 end match;
6532 end expandNonListedSplitIndices;
6533
6534 function isSplitSubscriptedExp
6535 input Expression exp;
6536 output Boolean split;
6537 algorithm
6538 split := match exp
6539 case SUBSCRIPTED_EXP(split = split) then split;
6540 else false;
6541 end match;
6542 end isSplitSubscriptedExp;
6543
6544 function mapSplitExpressions
6545 input Expression exp;
6546 input Func func;
6547 output Expression outExp;
6548
6549 partial function Func
6550 input output Expression exp;
6551 end Func;
6552 protected
6553 Option<UnorderedMap<Subscript, Expression>> osub_repls;
6554 UnorderedMap<Subscript, Expression> sub_repls;
6555 list<Subscript> subs;
6556 list<Expression> sub_exps, dim_sizes;
6557 algorithm
6558
2/2
✓ Branch 1 taken 508016 times.
✓ Branch 2 taken 14 times.
508030 if not containsSplitSubscriptedExp(exp) then
6559
2/2
✓ Branch 0 taken 446125 times.
✓ Branch 1 taken 61891 times.
508016 outExp := func(exp);
6560 507748 return;
6561 end if;
6562
6563 14 (outExp, osub_repls) := mapFold(exp, replaceSplitSubscripts, NONE());
6564
6565
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
14 if isNone(osub_repls) then
6566 ✗ outExp := func(exp);
6567 else
6568 14 SOME(sub_repls) := osub_repls;
6569 14 subs := UnorderedMap.keyList(sub_repls);
6570 14 sub_exps := UnorderedMap.valueList(sub_repls);
6571
4/4
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 14 times.
28 dim_sizes := list(Subscript.splitIndexDimExp(s) for s in subs);
6572
4/4
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 14 times.
42 dim_sizes := list(replaceSplitSubscripts(d, SOME(sub_repls)) for d in dim_sizes);
6573 14 outExp := mapSplitExpressions2(outExp, dim_sizes, sub_exps, func);
6574 14 outExp := applySubscripts(subs, outExp);
6575 end if;
6576 end mapSplitExpressions;
6577
6578 function containsSplitSubscriptedExp
6579 "Like contains(exp, isSplitSubscriptedExp), but also looks into iterator
6580 ranges like mapFold does. Literal arrays are skipped, like in
6581 Ceval.subscriptBinding2."
6582 input Expression exp;
6583 output Boolean res;
6584 algorithm
6585 res := match exp
6586 case SUBSCRIPTED_EXP(split = true) then true;
6587 case ARRAY(literal = true) then false;
6588 case CALL()
6589
7/8
✓ Branch 1 taken 683 times.
✓ Branch 2 taken 130973 times.
✓ Branch 3 taken 683 times.
✓ Branch 4 taken 130973 times.
✓ Branch 7 taken 130964 times.
✓ Branch 8 taken 9 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 130964 times.
131656 then containsShallow(exp, containsSplitSubscriptedExp) or
6590 List.any(list(Util.tuple22(i) for i in Call.iterators(exp.call)), containsSplitSubscriptedExp);
6591 1477717 else containsShallow(exp, containsSplitSubscriptedExp);
6592 end match;
6593 end containsSplitSubscriptedExp;
6594
6595 function replaceSplitSubscripts
6596 input output Expression exp;
6597 input output Option<UnorderedMap<Subscript, Expression>> subRepls;
6598 algorithm
6599 exp := match exp
6600 local
6601 list<Subscript> subs;
6602
6603 case SUBSCRIPTED_EXP(split = true)
6604 algorithm
6605 17 (subs, subRepls) := List.mapFold(exp.subscripts, replaceSplitSubscripts2, subRepls);
6606 17 then
6607 applySubscripts(subs, exp.exp);
6608
6609 else exp;
6610 end match;
6611 end replaceSplitSubscripts;
6612
6613 function replaceSplitSubscripts2
6614 input output Subscript subscript;
6615 input output Option<UnorderedMap<Subscript, Expression>> subRepls;
6616 protected
6617 Expression sub_exp;
6618 UnorderedMap<Subscript, Expression> sub_repls;
6619 algorithm
6620 subscript := match subscript
6621 case Subscript.SPLIT_INDEX()
6622 algorithm
6623
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 3 times.
17 if isSome(subRepls) then
6624 3 SOME(sub_repls) := subRepls;
6625 else
6626 14 sub_repls := UnorderedMap.new<Expression>(Subscript.hash, Subscript.isEqual);
6627 subRepls := SOME(sub_repls);
6628 end if;
6629
6630 17 sub_exp := makeMutable(INTEGER(0));
6631 17 sub_exp := UnorderedMap.tryAdd(subscript, sub_exp, sub_repls);
6632 17 then
6633 Subscript.INDEX(sub_exp);
6634
6635 else subscript;
6636 end match;
6637 end replaceSplitSubscripts2;
6638
6639 function mapSplitExpressions2
6640 input Expression exp;
6641 input list<Expression> dimSizes;
6642 input list<Expression> subExps;
6643 input Func func;
6644 output Expression outExp;
6645
6646 partial function Func
6647 input output Expression exp;
6648 end Func;
6649 protected
6650 Expression dim_size;
6651 list<Expression> rest_dims;
6652 Integer dim_size_int;
6653 Expression sub_exp;
6654 list<Expression> rest_subs;
6655 array<Expression> expl;
6656 Type ty;
6657 algorithm
6658
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 14 times.
52 if listEmpty(dimSizes) then
6659 38 outExp := map(exp, mapSplitExpressions3);
6660
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 8 times.
38 outExp := func(outExp);
6661 else
6662 14 dim_size :: rest_dims := dimSizes;
6663 14 dim_size_int := toInteger(Ceval.evalExp(dim_size));
6664
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 sub_exp :: rest_subs := subExps;
6665 14 expl := arrayCreateNoInit(dim_size_int, exp);
6666
6667
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
52 for i in 1:dim_size_int loop
6668 38 updateMutable(sub_exp, INTEGER(i));
6669 38 arrayUpdateNoBoundsChecking(expl, i,
6670 mapSplitExpressions2(exp, rest_dims, rest_subs, func));
6671 end for;
6672
6673
1/2
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
28 ty := typeOf(if arrayEmpty(expl) then exp else arrayGet(expl, 1));
6674 14 outExp := makeExpArray(expl, ty, Array.all(expl, isLiteral));
6675 end if;
6676 end mapSplitExpressions2;
6677
6678 function mapSplitExpressions3
6679 input output Expression exp;
6680 protected
6681 list<Subscript> subs;
6682 algorithm
6683 exp := match exp
6684 47 case MUTABLE() then Mutable.access(exp.exp);
6685
6686 case SUBSCRIPTED_EXP(subscripts = subs)
6687 47 then applySubscripts(subs, exp.exp);
6688
6689 else exp;
6690 end match;
6691 end mapSplitExpressions3;
6692
6693 function mapCrefScalars
6694 "Takes a cref expression and applies a function to each scalar cref,
6695 creating a new expression with the same dimensions as the given cref.
6696 Ex: mapCrefScalars(/*Real[2, 2]*/ x, ComponentRef.toString) =>
6697 {{'x[1, 1]', 'x[1, 2]'}, {'x[2, 1]', 'x[2, 2]'}}"
6698 input Expression crefExp;
6699 input MapFn mapFn;
6700 output Expression outExp;
6701
6702 partial function MapFn
6703 input ComponentRef cref;
6704 output Expression exp;
6705 end MapFn;
6706 algorithm
6707 2 outExp := ExpandExp.expand(crefExp);
6708 2 outExp := mapCrefScalars2(outExp, mapFn);
6709 end mapCrefScalars;
6710
6711 function mapCrefScalars2
6712 input Expression exp;
6713 input MapFn mapFn;
6714 output Expression outExp;
6715
6716 partial function MapFn
6717 input ComponentRef cref;
6718 output Expression exp;
6719 end MapFn;
6720 protected
6721 Type ty;
6722 Boolean literal;
6723 ComponentRef cref;
6724 array<Expression> arr;
6725 algorithm
6726 outExp := match exp
6727 case ARRAY()
6728 guard not arrayEmpty(exp.elements)
6729 algorithm
6730 1 arr := Array.map(exp.elements, function mapCrefScalars2(mapFn = mapFn));
6731 1 ty := typeOf(arrayGet(arr, 1));
6732 1 literal := Array.all(arr, isLiteral);
6733 1 then
6734 makeExpArray(arr, ty, literal);
6735
6736
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 case CREF() then mapFn(exp.cref);
6737 else exp;
6738 end match;
6739 end mapCrefScalars2;
6740
6741 function isFunctionPointer
6742 input Expression exp;
6743 output Boolean res;
6744 algorithm
6745 res := match exp
6746 case CREF(ty = Type.FUNCTION()) then true;
6747 case PARTIAL_FUNCTION_APPLICATION() then true;
6748 else false;
6749 end match;
6750 end isFunctionPointer;
6751
6752 function isClockOrSampleFunction
6753 "returns true if the expression is any form of clock sampling function"
6754 input Expression exp;
6755 output Boolean b;
6756 algorithm
6757 b := match exp
6758 local
6759 Call call;
6760 Expression arg;
6761 case CALL(call = call as Call.TYPED_CALL(arguments = arg :: _))
6762 then match AbsynUtil.pathString(Function.Function.nameConsiderBuiltin(call.fn))
6763 61 case "sample" then not isLiteral(arg); // sample has a non clocked meaning as well
6764 case "subSample" then true;
6765 case "superSample" then true;
6766 case "shiftSample" then true;
6767 case "backSample" then true;
6768 else false;
6769 end match;
6770 case Expression.CLKCONST() then true;
6771 else false;
6772 end match;
6773 end isClockOrSampleFunction;
6774
6775 function isConnector
6776 "Returns true if the expression is a component reference that refers to a
6777 connector, otherwise false."
6778 input Expression exp;
6779 output Boolean res;
6780 protected
6781 InstNode node;
6782 algorithm
6783 res := match exp
6784 case CREF()
6785 algorithm
6786 2354 node := ComponentRef.node(exp.cref);
6787
2/4
✓ Branch 1 taken 2354 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2354 times.
2354 then
6788 InstNode.isComponent(node) and InstNode.isConnector(node);
6789
6790 else false;
6791 end match;
6792 end isConnector;
6793
6794 function isComponentExpression
6795 "Returns true if the expression is a component reference that refers to an
6796 actual component (and not e.g. a function), otherwise false"
6797 input Expression exp;
6798 output Boolean res;
6799 algorithm
6800 res := match exp
6801 case CREF()
6802
2/4
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 44 times.
44 then ComponentRef.isCref(exp.cref) and
6803 InstNode.isComponent(ComponentRef.node(exp.cref));
6804
6805 else false;
6806 end match;
6807 end isComponentExpression;
6808
6809 function clone
6810 "Clones an expression to make it and any expression it contains unique,
6811 such that e.g. arrays don't share their internal arrays."
6812 input output Expression exp;
6813 algorithm
6814 exp := match exp
6815 case ARRAY()
6816 algorithm
6817 16714 exp.elements := Array.map(exp.elements, clone);
6818 then
6819 exp;
6820
6821 336232 else mapShallow(exp, clone);
6822 end match;
6823 end clone;
6824
6825 function toJSON
6826 input Expression exp;
6827 output JSON json;
6828 protected
6829 function dump_arg
6830 input String name;
6831 input Expression arg;
6832 output JSON json = JSON.emptyListObject();
6833 algorithm
6834 ✗ json := JSON.addPair("name", JSON.makeString(name), json);
6835 ✗ json := JSON.addPair("value", toJSON(arg), json);
6836 end dump_arg;
6837 algorithm
6838 json := match exp
6839 429 case INTEGER() then JSON.makeInteger(exp.value);
6840 389 case REAL() then JSON.makeNumber(exp.value);
6841 24 case STRING() then JSON.makeString(exp.value);
6842 42 case BOOLEAN() then JSON.makeBoolean(exp.value);
6843 case ENUM_LITERAL()
6844 algorithm
6845 115 json := JSON.emptyListObject();
6846 115 json := JSON.addPair("$kind", JSON.STRING("enum"), json);
6847 115 json := JSON.addPair("name", JSON.makeString(toString(exp)), json);
6848 115 json := JSON.addPair("index", JSON.makeInteger(exp.index), json);
6849 then
6850 json;
6851
6852 case CLKCONST()
6853 ✗ then ClockKind.toJSON(exp.clk);
6854
6855 26 case CREF() then ComponentRef.toJSON(exp.cref);
6856
6857 case TYPENAME()
6858 algorithm
6859 ✗ json := JSON.emptyListObject();
6860 ✗ json := JSON.addPair("$kind", JSON.STRING("typename"), json);
6861 ✗ json := JSON.addPair("name", JSON.makeString(Type.typenameString(Type.arrayElementType(exp.ty))), json);
6862 then
6863 json;
6864
6865 case ARRAY()
6866
4/4
✓ Branch 0 taken 672 times.
✓ Branch 1 taken 300 times.
✓ Branch 3 taken 672 times.
✓ Branch 4 taken 300 times.
1944 then JSON.makeList(list(toJSON(e) for e in exp.elements));
6867
6868 case RANGE()
6869 algorithm
6870 1 json := JSON.emptyListObject();
6871 1 json := JSON.addPair("$kind", JSON.STRING("range"), json);
6872 1 json := JSON.addPair("start", toJSON(exp.start), json);
6873
6874
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
1 if isSome(exp.step) then
6875 ✗ json := JSON.addPair("step", toJSON(Util.getOption(exp.step)), json);
6876 end if;
6877
6878 1 json := JSON.addPair("stop", toJSON(exp.stop), json);
6879 then
6880 json;
6881
6882 case TUPLE()
6883 algorithm
6884 ✗ json := JSON.emptyListObject();
6885 ✗ json := JSON.addPair("$kind", JSON.STRING("tuple"), json);
6886 ✗ json := JSON.addPair("elements",
6887 JSON.makeList(list(toJSON(e) for e in exp.elements)), json);
6888 then
6889 json;
6890
6891 case RECORD()
6892 algorithm
6893 47 json := JSON.emptyListObject();
6894 47 json := JSON.addPair("$kind", JSON.STRING("record"), json);
6895 47 json := JSON.addPair("name", JSON.makeString(AbsynUtil.pathString(exp.path)), json);
6896
4/4
✓ Branch 0 taken 463 times.
✓ Branch 1 taken 47 times.
✓ Branch 2 taken 463 times.
✓ Branch 3 taken 47 times.
510 json := JSON.addPair("elements",
6897 JSON.makeList(list(toJSON(e) for e in exp.elements)), json);
6898 then
6899 json;
6900
6901 case CALL()
6902 5 then Call.toJSON(exp.call);
6903
6904 case SIZE()
6905 algorithm
6906 ✗ json := JSON.emptyListObject();
6907 ✗ json := JSON.addPair("$kind", JSON.STRING("call"), json);
6908 ✗ json := JSON.addPair("name", JSON.STRING("size"), json);
6909
6910 ✗ if isSome(exp.dimIndex) then
6911 ✗ json := JSON.addPair("arguments",
6912 JSON.makeList({toJSON(exp.exp), toJSON(Util.getOption(exp.dimIndex))}), json);
6913 else
6914 ✗ json := JSON.addPair("arguments", JSON.makeArray({toJSON(exp.exp)}), json);
6915 end if;
6916 then
6917 json;
6918
6919 case BINARY()
6920 algorithm
6921 2 json := JSON.emptyListObject();
6922 2 json := JSON.addPair("$kind", JSON.STRING("binary_op"), json);
6923 2 json := JSON.addPair("lhs", toJSON(exp.exp1), json);
6924 2 json := JSON.addPair("op", Operator.toJSON(exp.operator), json);
6925 2 json := JSON.addPair("rhs", toJSON(exp.exp2), json);
6926 then
6927 json;
6928
6929 case UNARY()
6930 algorithm
6931 ✗ json := JSON.emptyListObject();
6932 ✗ json := JSON.addPair("$kind", JSON.STRING("unary_op"), json);
6933 ✗ json := JSON.addPair("op", Operator.toJSON(exp.operator), json);
6934 ✗ json := JSON.addPair("exp", toJSON(exp.exp), json);
6935 then
6936 json;
6937
6938 case LBINARY()
6939 algorithm
6940 ✗ json := JSON.emptyListObject();
6941 ✗ json := JSON.addPair("$kind", JSON.STRING("binary_op"), json);
6942 ✗ json := JSON.addPair("lhs", toJSON(exp.exp1), json);
6943 ✗ json := JSON.addPair("op", Operator.toJSON(exp.operator), json);
6944 ✗ json := JSON.addPair("rhs", toJSON(exp.exp2), json);
6945 then
6946 json;
6947
6948 case LUNARY()
6949 algorithm
6950 ✗ json := JSON.emptyListObject();
6951 ✗ json := JSON.addPair("$kind", JSON.STRING("unary_op"), json);
6952 ✗ json := JSON.addPair("op", Operator.toJSON(exp.operator), json);
6953 ✗ json := JSON.addPair("exp", toJSON(exp.exp), json);
6954 then
6955 json;
6956
6957 case RELATION()
6958 algorithm
6959 1 json := JSON.emptyListObject();
6960 1 json := JSON.addPair("$kind", JSON.STRING("binary_op"), json);
6961 1 json := JSON.addPair("lhs", toJSON(exp.exp1), json);
6962 1 json := JSON.addPair("op", Operator.toJSON(exp.operator), json);
6963 1 json := JSON.addPair("rhs", toJSON(exp.exp2), json);
6964 then
6965 json;
6966
6967 case MULTARY()
6968 algorithm
6969 ✗ json := JSON.emptyListObject();
6970 ✗ json := JSON.addPair("$kind", JSON.STRING("multary_op"), json);
6971 ✗ json := JSON.addPair("args",
6972 JSON.makeArray(list(toJSON(a) for a in exp.arguments)), json);
6973 ✗ json := JSON.addPair("inv_args",
6974 JSON.makeArray(list(toJSON(a) for a in exp.inv_arguments)), json);
6975 ✗ json := JSON.addPair("op", Operator.toJSON(exp.operator), json);
6976 then
6977 json;
6978
6979 case IF()
6980 algorithm
6981 1 json := JSON.emptyListObject();
6982 1 json := JSON.addPair("$kind", JSON.STRING("if"), json);
6983 1 json := JSON.addPair("condition", toJSON(exp.condition), json);
6984 1 json := JSON.addPair("true", toJSON(exp.trueBranch), json);
6985 1 json := JSON.addPair("false", toJSON(exp.falseBranch), json);
6986 then
6987 json;
6988
6989 1 case CAST() then toJSON(exp.exp);
6990 ✗ case BOX() then toJSON(exp.exp);
6991 ✗ case UNBOX() then toJSON(exp.exp);
6992
6993 case SUBSCRIPTED_EXP()
6994 algorithm
6995 ✗ json := JSON.emptyListObject();
6996 ✗ json := JSON.addPair("$kind", JSON.STRING("sub"), json);
6997 ✗ json := JSON.addPair("exp", toJSON(exp.exp), json);
6998 ✗ json := JSON.addPair("subscripts", Subscript.toJSONList(exp.subscripts), json);
6999 then
7000 json;
7001
7002 case TUPLE_ELEMENT()
7003 algorithm
7004 ✗ json := JSON.emptyListObject();
7005 ✗ json := JSON.addPair("$kind", JSON.STRING("tuple_element"), json);
7006 ✗ json := JSON.addPair("exp", toJSON(exp.tupleExp), json);
7007 ✗ json := JSON.addPair("index", JSON.makeInteger(exp.index), json);
7008 then
7009 json;
7010
7011 case RECORD_ELEMENT()
7012 algorithm
7013 ✗ json := JSON.emptyListObject();
7014 ✗ json := JSON.addPair("$kind", JSON.STRING("record_element"), json);
7015 ✗ json := JSON.addPair("exp", toJSON(exp.recordExp), json);
7016 ✗ json := JSON.addPair("index", JSON.makeInteger(exp.index), json);
7017 ✗ json := JSON.addPair("field", JSON.makeString(exp.fieldName), json);
7018 then
7019 json;
7020
7021 case PARTIAL_FUNCTION_APPLICATION()
7022 algorithm
7023 ✗ json := JSON.emptyListObject();
7024 ✗ json := JSON.addPair("$kind", JSON.STRING("function"), json);
7025 ✗ json := JSON.addPair("name", JSON.makeString(ComponentRef.toString(exp.fn)), json);
7026 ✗ json := JSON.addPair("arguments", JSON.makeList(
7027 list(dump_arg(name, arg) threaded for arg in exp.args, name in exp.argNames)), json);
7028 then
7029 json;
7030
7031 ✗ case FILENAME() then JSON.makeString(exp.filename);
7032
7033 ✗ else JSON.makeString(toString(exp));
7034 end match;
7035 end toJSON;
7036
7037 function tupleElements
7038 input Expression exp;
7039 output list<Expression> expl;
7040 algorithm
7041 expl := match exp
7042 32 case TUPLE() then exp.elements;
7043 else {exp};
7044 end match;
7045 end tupleElements;
7046
7047 function wrapCall
7048 "wrapper function to apply a Call function"
7049 input output Expression exp;
7050 input callFun fun;
7051 partial function callFun
7052 input output Call call;
7053 end callFun;
7054 algorithm
7055 exp := match exp
7056 case CALL() algorithm
7057
1/2
✓ Branch 0 taken 2732 times.
✗ Branch 1 not taken.
2732 exp.call := fun(exp.call);
7058 then exp;
7059 else exp;
7060 end match;
7061 end wrapCall;
7062
7063 function repairOperator
7064 input output Expression exp;
7065 algorithm
7066 exp := match exp
7067 case BINARY() algorithm
7068 22 exp.operator := Operator.repairBinary(exp.operator, typeOf(exp.exp1), typeOf(exp.exp2));
7069 then exp;
7070
7071 case MULTARY() algorithm
7072
4/4
✓ Branch 1 taken 425 times.
✓ Branch 2 taken 211 times.
✓ Branch 3 taken 425 times.
✓ Branch 4 taken 211 times.
847 exp.operator := Operator.repairMultary(exp.operator, list(typeOf(e) for e in listAppend(exp.arguments, exp.inv_arguments)));
7073 then exp;
7074
7075 else exp;
7076 end match;
7077 end repairOperator;
7078
7079 function makeUnary
7080 input Operator op;
7081 input Expression exp;
7082 output Expression unaryExp;
7083 algorithm
7084
2/2
✓ Branch 0 taken 396610 times.
✓ Branch 1 taken 739 times.
397349 if op.op == NFOperator.Op.ADD then
7085 unaryExp := exp;
7086 elseif op.op == NFOperator.Op.UMINUS then
7087 396610 unaryExp := negate(exp);
7088 else
7089 ✗ unaryExp := UNARY(op, exp);
7090 end if;
7091 end makeUnary;
7092
7093 function replaceLiteral
7094 "use with fake map because it maps itself"
7095 input output Expression exp;
7096 input UnorderedMap<Expression, Integer> map;
7097 input Pointer<Integer> idx_ptr;
7098 protected
7099 function replace
7100 input output Expression exp;
7101 input UnorderedMap<Expression, Integer> map;
7102 input Pointer<Integer> idx_ptr;
7103 protected
7104 Integer idx;
7105 Option<Integer> idx_opt;
7106 algorithm
7107 4177 idx_opt := UnorderedMap.get(exp, map);
7108
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4177 times.
✓ Branch 2 taken 454 times.
✓ Branch 3 taken 3723 times.
4177 if isSome(idx_opt) then
7109 // this literal already exists
7110 3723 idx := Util.getOption(idx_opt);
7111 else
7112 // new literal found
7113 454 idx := Pointer.access(idx_ptr);
7114 454 Pointer.update(idx_ptr, idx + 1);
7115 454 UnorderedMap.add(exp, idx, map);
7116 end if;
7117 4177 exp := SHARED_LITERAL(idx, exp);
7118 end replace;
7119 algorithm
7120 exp := match exp
7121 // do nothing on shared literal
7122 case Expression.SHARED_LITERAL() then exp;
7123
7124 // replace literal array expressions that are not trivial
7125 299 case ARRAY() guard(isLiteralReplace(exp)) then replace(replaceLiteralArrayElements(exp, map, idx_ptr), map, idx_ptr);
7126
7127 case RECORD() guard(isLiteralReplace(exp)) algorithm
7128
4/4
✓ Branch 0 taken 382 times.
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 382 times.
✓ Branch 3 taken 39 times.
460 exp.elements := list(replaceLiteral(elem, map, idx_ptr) for elem in exp.elements);
7129 39 then replace(exp, map, idx_ptr);
7130
7131 // replace literal expressions that are not trivial
7132 3839 case _ guard(isLiteralReplace(exp)) then replace(exp, map, idx_ptr);
7133
7134 // map down for other expressions
7135 38193 else Expression.mapShallow(exp, function replaceLiteral(map = map, idx_ptr = idx_ptr));
7136 end match;
7137 end replaceLiteral;
7138
7139 function replaceLiteralArrayElements
7140 input output Expression exp;
7141 input UnorderedMap<Expression, Integer> map;
7142 input Pointer<Integer> idx_ptr;
7143 algorithm
7144 exp := match exp
7145 case ARRAY() algorithm
7146 636 exp.elements := Array.map(exp.elements, function replaceLiteralArrayElements(map = map, idx_ptr = idx_ptr));
7147 then exp;
7148 1407 else replaceLiteral(exp, map, idx_ptr);
7149 end match;
7150 end replaceLiteralArrayElements;
7151
7152 function replaceCrefWithBinding
7153 input ComponentRef cref;
7154 input output Expression exp;
7155 input recurse func;
7156 partial function recurse
7157 input output Expression exp;
7158 end recurse;
7159 protected
7160 Expression e;
7161 algorithm
7162 exp := match InstNode.getBindingExpOpt(ComponentRef.node(cref))
7163 case SOME(e as Expression.INTEGER()) then e;
7164 27 case SOME(e as Expression.CREF()) then replaceCrefWithBinding(e.cref, e, func);
7165 case SOME(Expression.SUBSCRIPTED_EXP(exp = e as Expression.INTEGER())) then e;
7166 6 case SOME(Expression.SUBSCRIPTED_EXP(exp = e as Expression.CREF())) then replaceCrefWithBinding(e.cref, e, func);
7167 case SOME(e) algorithm
7168 ✗ e := Expression.map(e, func);
7169 then e;
7170 else exp;
7171 end match;
7172 end replaceCrefWithBinding;
7173
7174 function replaceResizableParameterWithOriginal
7175 input output Expression exp;
7176 algorithm
7177 exp := match exp
7178 // frontend replacement
7179 case Expression.CREF() guard(ComponentRef.isResizable(exp.cref)) algorithm
7180 1346 then replaceCrefWithBinding(exp.cref, exp, replaceResizableParameterWithOriginal);
7181 else exp;
7182 end match;
7183 end replaceResizableParameterWithOriginal;
7184
7185 function replaceResizableParameter
7186 input output Expression exp;
7187 algorithm
7188 exp := match exp
7189 local
7190 PointerWeak<Variable> var;
7191 Integer v;
7192
7193 // backend replacement
7194 case Expression.CREF(cref = ComponentRef.CREF())
7195 guard InstNode.isVar(ComponentRef.node(exp.cref)) and ComponentRef.isResizable(exp.cref)
7196 then match Pointer.access(PointerWeak.upgrade(
7197 InstNode.varPointer(ComponentRef.node(exp.cref))))
7198 // optimal value has already been determined
7199 case Variable.VARIABLE(backendinfo = BackendInfo.BACKEND_INFO(varKind = VariableKind.PARAMETER(resize_value = SOME(v))))
7200 707 then Expression.INTEGER(v);
7201
7202 // optimal value not yet computed
7203 143 else replaceCrefWithBinding(exp.cref, exp, replaceResizableParameter);
7204 end match;
7205
7206 // frontend replacement
7207 case Expression.CREF() guard(ComponentRef.isResizable(exp.cref))
7208 557 then replaceCrefWithBinding(exp.cref, exp, replaceResizableParameter);
7209
7210 else exp;
7211 end match;
7212 end replaceResizableParameter;
7213
7214 // Helper: compute multiplication result type from operand types.
7215 function mulResultType
7216 input Type tl;
7217 input Type tr;
7218 output Type tres;
7219 algorithm
7220
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 60 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
60 if Type.isArray(tl) and Type.isArray(tr) then
7221 // Both arrays: keep (left) array type (sizes should already match semantically)
7222 tres := tl;
7223 elseif Type.isArray(tl) then
7224 tres := tl; // array * scalar
7225 elseif Type.isArray(tr) then
7226 tres := tr; // scalar * array
7227 else
7228 // both scalar -> promote numeric type (use left for now; scalar promotion elsewhere already handled)
7229 tres := tl;
7230 end if;
7231 end mulResultType;
7232
7233 // Helper: binary multiply with simple scalar/array size classification.
7234 function mmul
7235 input Expression lhs;
7236 input Expression rhs;
7237 input Operator baseOp;
7238 output Expression prod;
7239 protected
7240 Type tl = typeOf(lhs);
7241 Type tr = typeOf(rhs);
7242 Boolean lArr = Type.isArray(tl);
7243 Boolean rArr = Type.isArray(tr);
7244 Operator.SizeClassification sizeClass;
7245 Type resTy;
7246 Operator op;
7247 algorithm
7248
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 if not lArr and not rArr then
7249 sizeClass := NFOperator.SizeClassification.SCALAR;
7250 elseif not lArr and rArr then
7251 sizeClass := NFOperator.SizeClassification.SCALAR_ARRAY;
7252 elseif lArr and not rArr then
7253 sizeClass := NFOperator.SizeClassification.ARRAY_SCALAR;
7254 else
7255 sizeClass := NFOperator.SizeClassification.ELEMENT_WISE;
7256 end if;
7257
7258 60 resTy := mulResultType(tl, tr);
7259 60 op := Operator.fromClassification((NFOperator.MathClassification.MULTIPLICATION, sizeClass), resTy);
7260 60 prod := BINARY(lhs, op, rhs);
7261 end mmul;
7262
7263 function productOfListExceptSelf
7264 "prod(f_k | k <> i) for each i.
7265 For arguments = {f1, f2, ..., fn} returns list:
7266 { Π_{k≠1} fk, Π_{k≠2} fk, ..., Π_{k≠n} fk }.
7267 Uses a prefix/suffix O(n) algorithm (no repeated full products).
7268 https://leetcode.com/problems/product-of-array-except-self/solutions/65622/simple-java-solution-in-o-n-without-extra-space/
7269 If n = 0 -> {}, if n = 1 -> {1} (multiplicative identity of operator.ty)."
7270 input list<Expression> arguments;
7271 input Operator mulOp "Base multiplication operator (will be repaired per pair)";
7272 output list<Expression> products;
7273 protected
7274 Integer n = listLength(arguments);
7275 array<Expression> argsArr;
7276 array<Expression> pref;
7277 array<Expression> res;
7278 Integer i;
7279 Expression rightProd;
7280 Type baseTy = mulOp.ty;
7281 Type elTy;
7282 algorithm
7283
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if n == 0 then
7284 products := {};
7285 ✗ return;
7286 end if;
7287
7288 // Determine element (scalar) type to build multiplicative identity
7289
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
12 elTy := if Type.isArray(baseTy) then Type.arrayElementType(baseTy) else baseTy;
7290 // Load arguments into array for indexed access
7291 12 argsArr := arrayCreate(n, Expression.makeOne(elTy));
7292 i := 1;
7293
2/2
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 12 times.
36 for a in arguments loop
7294 24 argsArr[i] := a;
7295 24 i := i + 1;
7296 end for;
7297
7298 // Allocate prefix array & result
7299 12 pref := arrayCreate(n, Expression.makeOne(elTy)); // pref[i] = product of args before i with pref[1] = 1.
7300 12 res := arrayCreate(n, Expression.makeOne(elTy));
7301
7302 // Build prefix products: pref[i] = f1 * f2 * ... * f_{i-1}
7303
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
24 for i in 2:n loop
7304 12 pref[i] := mmul(pref[i-1], argsArr[i-1], mulOp);
7305 end for;
7306
7307 // Suffix accumulation
7308 12 rightProd := Expression.makeOne(elTy);
7309
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
36 for i in n:-1:1 loop
7310 // res[i] = (product of left side) * (product of right side)
7311 24 res[i] := mmul(pref[i], rightProd, mulOp);
7312 // update rightProd *= argsArr[i]
7313 24 rightProd := mmul(rightProd, argsArr[i], mulOp);
7314 end for;
7315
7316 // Collect back to list (in order)
7317 products := {};
7318
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
36 for i in n:-1:1 loop
7319 //res[i] := map(res[i], repairOperator);
7320 24 products := SimplifyExp.simplify(res[i]) :: products;
7321 end for;
7322 end productOfListExceptSelf;
7323 annotation(__OpenModelica_Interface="nf_frontend");
7324 end NFExpression;
7325