Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 68.2% 182 / 0 / 267
Functions: -% 0 / 1 / 1
Branches: 68.1% 126 / 0 / 185

OMCompiler/Compiler/NFFrontEnd/NFSubscript.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 NFSubscript
37 protected
38 import DAE;
39 import List;
40 import SimplifyExp = NFSimplifyExp;
41 import Type = NFType;
42 import RangeIterator = NFRangeIterator;
43 import Dump;
44 import ExpandExp = NFExpandExp;
45 import Prefixes = NFPrefixes;
46 import Ceval = NFCeval;
47 import MetaModelica.Dangerous.listReverseInPlace;
48 import Util;
49 import JSON;
50
51 public
52 import Expression = NFExpression;
53 import Absyn;
54 import AbsynUtil;
55 import BaseModelica;
56 import Dimension = NFDimension;
57 import NFPrefixes.{Variability, Purity};
58 import NFCeval.EvalTarget;
59 import NFInstNode.InstNode;
60 import NFInstNode;
61 import ComponentRef = NFComponentRef;
62
63 import Subscript = NFSubscript;
64
65 record RAW_SUBSCRIPT
66 Absyn.Subscript subscript;
67 end RAW_SUBSCRIPT;
68
69 record UNTYPED
70 Expression exp;
71 end UNTYPED;
72
73 record INDEX
74 Expression index;
75 end INDEX;
76
77 record SLICE
78 Expression slice;
79 end SLICE;
80
81 record EXPANDED_SLICE
82 list<Subscript> indices;
83 end EXPANDED_SLICE;
84
85 record WHOLE end WHOLE;
86
87 // Split proxy and index subscripts are added to modifier array expressions to
88 // indicate where they are split when propagating them down to the array
89 // elements. Proxies are added during the instantiation and then replaced with
90 // split indices during typing once the number of dimensions on elements are known.
91 record SPLIT_PROXY
92 NFInstNode.ScopeRef origin "Weakly: the class tree owns both of these.";
93 NFInstNode.ScopeRef parent;
94 end SPLIT_PROXY;
95
96 record SPLIT_INDEX
97 NFInstNode.ScopeRef node "Weakly: the class tree owns it.";
98 Integer dimIndex;
99 end SPLIT_INDEX;
100
101 function fromExp
102 input Expression exp;
103 output Subscript subscript;
104 algorithm
105 subscript := match exp
106 241197 case Expression.INTEGER() then INDEX(exp);
107 ✗ case Expression.BOOLEAN() then INDEX(exp);
108 1 case Expression.ENUM_LITERAL() then INDEX(exp);
109 26832 else UNTYPED(exp);
110 end match;
111 end fromExp;
112
113 function fromTypedExp
114 input Expression exp;
115 output Subscript subscript;
116 algorithm
117
2/2
✓ Branch 2 taken 3389 times.
✓ Branch 3 taken 190701 times.
194090 subscript := if Type.isArray(Expression.typeOf(exp)) then SLICE(exp) else INDEX(exp);
118 end fromTypedExp;
119
120 function toExp
121 input Subscript subscript;
122 output Expression exp;
123 algorithm
124 exp := match subscript
125 ✗ case UNTYPED() then subscript.exp;
126 151953 case INDEX() then subscript.index;
127 33 case SLICE() then subscript.slice;
128 end match;
129 end toExp;
130
131 function toInteger
132 input Subscript subscript;
133 output Integer int;
134 algorithm
135 int := match subscript
136 256759 case INDEX() then Expression.toInteger(subscript.index);
137 end match;
138 end toInteger;
139
140 function toIntegerOpt
141 input Subscript subscript;
142 output Option<Integer> int;
143 algorithm
144 int := match subscript
145 ✗ case INDEX() then SOME(Expression.toInteger(subscript.index));
146 else NONE();
147 end match;
148 end toIntegerOpt;
149
150 function toIndexList
151 input Subscript subscript;
152 input Integer length;
153 output list<Integer> indices;
154 algorithm
155 indices := match subscript
156 local
157 array<Expression> elems;
158 Integer start, step, stop;
159
160 ✗ case INDEX() then {toInteger(subscript)};
161
162 ✗ case WHOLE() then List.intRange2(1,length);
163
164 case SLICE(slice = Expression.ARRAY(elements = elems))
165 ✗ then list(Expression.toInteger(e) for e in elems);
166
167 case SLICE(slice = Expression.RANGE(
168 start = Expression.INTEGER(start),
169 step = SOME(Expression.INTEGER(step)),
170 stop = Expression.INTEGER(stop)))
171 ✗ then List.intRange3(start, step, stop);
172
173 case SLICE(slice = Expression.RANGE(
174 start = Expression.INTEGER(start),
175 step = NONE(),
176 stop = Expression.INTEGER(stop)))
177 ✗ then List.intRange2(start, stop);
178
179 else algorithm
180 ✗ Error.terminate(getInstanceName() + " got an incorrect subscript type " + toString(subscript) + ".", sourceInfo());
181 ✗ then fail();
182 end match;
183 end toIndexList;
184
185 protected function isValidIndexType
186 input Type ty;
187 output Boolean b = Type.isInteger(ty) or Type.isBoolean(ty) or Type.isEnumeration(ty);
188 end isValidIndexType;
189
190 public
191 function makeIndex
192 input Expression exp;
193 output Subscript subscript;
194 protected
195 Type ty;
196 algorithm
197 357661 ty := Expression.typeOf(exp);
198
1/2
✓ Branch 1 taken 357661 times.
✗ Branch 2 not taken.
357661 if isValidIndexType(ty) then
199 357661 subscript := INDEX(exp);
200 else
201 ✗ Error.terminate(getInstanceName() + " got a non integer type exp to make an index sub", sourceInfo());
202 ✗ fail();
203 end if;
204 end makeIndex;
205
206 function makeSplitIndex
207 input InstNode node;
208 input Integer dimIndex;
209 output Subscript subscript = SPLIT_INDEX(InstNode.scopeRef(node), dimIndex);
210 algorithm
211
1/2
✓ Branch 0 taken 90779 times.
✗ Branch 1 not taken.
90779 if dimIndex < 1 then
212 ✗ Error.terminate(getInstanceName() + " got invalid index " + String(dimIndex), sourceInfo());
213 end if;
214 end makeSplitIndex;
215
216 function isIndex
217 input Subscript sub;
218 output Boolean isIndex;
219 algorithm
220 isIndex := match sub
221 case INDEX() then true;
222 else false;
223 end match;
224 end isIndex;
225
226 function isWhole
227 input Subscript sub;
228 output Boolean isWhole;
229 algorithm
230 isWhole := match sub
231 case WHOLE() then true;
232 else false;
233 end match;
234 end isWhole;
235
236 function isSimple
237 "used for determining if its simple enough to use for an array equation
238 in the case of non scalarization (new backend)"
239 input Subscript sub;
240 output Boolean isSimple = isIndex(sub) or isWhole(sub);
241 end isSimple;
242
243 function isSliced
244 input Subscript sub;
245 output Boolean sliced;
246 algorithm
247 sliced := match sub
248 case SLICE() then true;
249 case WHOLE() then true;
250 else false;
251 end match;
252 end isSliced;
253
254 function isScalar
255 input Subscript sub;
256 output Boolean isScalar;
257 algorithm
258 isScalar := match sub
259 local
260 Type ty;
261
262 case INDEX() algorithm
263 15766 ty := Expression.typeOf(sub.index);
264 15766 then
265 isValidIndexType(ty);
266
267 case SPLIT_INDEX() then true;
268
269 else false;
270 end match;
271 end isScalar;
272
273 function isScalarLiteral
274 input Subscript sub;
275 output Boolean isScalarLiteral;
276 algorithm
277 isScalarLiteral := match sub
278 258775 case INDEX() then Expression.isScalarLiteral(sub.index);
279 else false;
280 end match;
281 end isScalarLiteral;
282
283 function equalsIterator
284 input Subscript sub;
285 input InstNode iterator;
286 output Boolean res;
287 protected
288 ComponentRef cref;
289 algorithm
290 res := match sub
291 case UNTYPED(exp = Expression.CREF(cref = cref))
292 16 then InstNode.refEqual(iterator, ComponentRef.node(cref));
293
294 case INDEX(index = Expression.CREF(cref = cref))
295 3 then InstNode.refEqual(iterator, ComponentRef.node(cref));
296
297 else false;
298 end match;
299 end equalsIterator;
300
301 function isIterator
302 input Subscript sub;
303 output Boolean res;
304 algorithm
305 res := match sub
306 ✗ case UNTYPED() then Expression.isIterator(sub.exp);
307 688 case INDEX() then Expression.isIterator(sub.index);
308 else false;
309 end match;
310 end isIterator;
311
312 function toIterator
313 input Subscript sub;
314 output InstNode iterator;
315 protected
316 ComponentRef cref;
317 algorithm
318 iterator := match sub
319 case UNTYPED(exp = Expression.CREF(cref = cref))
320 guard ComponentRef.isIterator(cref)
321 ✗ then ComponentRef.node(cref);
322
323 case INDEX(index = Expression.CREF(cref = cref))
324 guard ComponentRef.isIterator(cref)
325 29 then ComponentRef.node(cref);
326
327 else InstNode.EMPTY_NODE();
328 end match;
329 end toIterator;
330
331 function isBackendIterator
332 input Subscript sub;
333 output Boolean res;
334 protected
335 ComponentRef cref;
336 algorithm
337 res := match sub
338 case INDEX(index = Expression.CREF(cref = cref))
339 10 then ComponentRef.isIterator(cref);
340
341 else false;
342 end match;
343 end isBackendIterator;
344
345 function isEqual
346 input Subscript subscript1;
347 input Subscript subscript2;
348 output Boolean isEqual;
349 algorithm
350 isEqual := match (subscript1, subscript2)
351 case (RAW_SUBSCRIPT(), RAW_SUBSCRIPT())
352 ✗ then AbsynUtil.subscriptEqual(subscript1.subscript, subscript2.subscript);
353
354 case (UNTYPED(), UNTYPED())
355 ✗ then Expression.isEqual(subscript1.exp, subscript2.exp);
356
357 case (INDEX(), INDEX())
358 102778 then Expression.isEqual(subscript1.index, subscript2.index);
359
360 case (SLICE(), SLICE())
361 56 then Expression.isEqual(subscript1.slice, subscript2.slice);
362
363 case (WHOLE(), WHOLE()) then true;
364
365 case (SPLIT_INDEX(), SPLIT_INDEX())
366
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
3 then subscript1.dimIndex == subscript2.dimIndex and
367 InstNode.refEqual(InstNode.borrow(subscript1.node), InstNode.borrow(subscript2.node));
368
369 else false;
370 end match;
371 end isEqual;
372
373 function isEqualList
374 input list<Subscript> subscripts1;
375 input list<Subscript> subscripts2;
376 output Boolean isEqual;
377 protected
378 Subscript s2;
379 list<Subscript> rest = subscripts2;
380 algorithm
381
2/2
✓ Branch 0 taken 106431 times.
✓ Branch 1 taken 1146551 times.
1252982 for s1 in subscripts1 loop
382
2/2
✓ Branch 0 taken 3579 times.
✓ Branch 1 taken 102852 times.
106431 if listEmpty(rest) then
383 isEqual := false;
384 3579 return;
385 end if;
386
387 102852 s2 :: rest := rest;
388
389
2/2
✓ Branch 1 taken 4467 times.
✓ Branch 2 taken 98385 times.
102852 if not isEqual(s1, s2) then
390 isEqual := false;
391 4467 return;
392 end if;
393 end for;
394
395 1146551 isEqual := listEmpty(rest);
396 end isEqualList;
397
398 function compare
399 input Subscript subscript1;
400 input Subscript subscript2;
401 output Integer comp;
402 algorithm
403
2/2
✓ Branch 0 taken 1260 times.
✓ Branch 1 taken 22253 times.
23513 if referenceEq(subscript1, subscript2) then
404 comp := 0;
405 1260 return;
406 end if;
407
408 22253 comp := Util.intCompare(valueConstructor(subscript1), valueConstructor(subscript2));
409
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22253 times.
22253 if comp <> 0 then
410 ✗ return;
411 end if;
412
413 comp := match subscript1
414 local
415 Expression e;
416 NFInstNode.ScopeRef node;
417 Integer index;
418
419 case UNTYPED()
420 algorithm
421 ✗ UNTYPED(exp = e) := subscript2;
422 ✗ then
423 Expression.compare(subscript1.exp, e);
424
425 case INDEX()
426 algorithm
427
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22219 times.
22219 INDEX(index = e) := subscript2;
428 22219 then
429 Expression.compare(subscript1.index, e);
430
431 case SLICE()
432 algorithm
433
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 34 times.
34 SLICE(slice = e) := subscript2;
434 34 then
435 Expression.compare(subscript1.slice, e);
436
437 case WHOLE() then 0;
438
439 case SPLIT_INDEX()
440 algorithm
441 ✗ SPLIT_INDEX(node = node, dimIndex = index) := subscript2;
442 ✗ comp := InstNode.refCompare(InstNode.borrow(subscript1.node), InstNode.borrow(node));
443 ✗ then
444 if comp == 0 then Util.intCompare(subscript1.dimIndex, index) else comp;
445
446 end match;
447 end compare;
448
449 function compareList
450 input list<Subscript> subscripts1;
451 input list<Subscript> subscripts2;
452 output Integer comp;
453 protected
454 Subscript s2;
455 list<Subscript> rest_s2 = subscripts2;
456 algorithm
457 65733 comp := Util.intCompare(listLength(subscripts1), listLength(subscripts2));
458
459
2/2
✓ Branch 0 taken 65583 times.
✓ Branch 1 taken 150 times.
65733 if comp <> 0 then
460 150 return;
461 end if;
462
463
2/2
✓ Branch 0 taken 23513 times.
✓ Branch 1 taken 51718 times.
75231 for s1 in subscripts1 loop
464
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23513 times.
23513 s2 :: rest_s2 := rest_s2;
465 23513 comp := compare(s1, s2);
466
467
2/2
✓ Branch 0 taken 13865 times.
✓ Branch 1 taken 9648 times.
23513 if comp <> 0 then
468 13865 return;
469 end if;
470 end for;
471
472 comp := 0;
473 end compareList;
474
475 function containsExp
476 input Subscript subscript;
477 input ContainsPred func;
478 output Boolean res;
479
480 partial function ContainsPred
481 input Expression exp;
482 output Boolean res;
483 end ContainsPred;
484 algorithm
485 res := match subscript
486 ✗ case UNTYPED() then Expression.contains(subscript.exp, func);
487 1863486 case INDEX() then Expression.contains(subscript.index, func);
488 617 case SLICE() then Expression.contains(subscript.slice, func);
489 else false;
490 end match;
491 end containsExp;
492
493 function listContainsExp
494 input list<Subscript> subscripts;
495 input ContainsPred func;
496 output Boolean res;
497
498 partial function ContainsPred
499 input Expression exp;
500 output Boolean res;
501 end ContainsPred;
502 algorithm
503
2/2
✓ Branch 0 taken 1865716 times.
✓ Branch 1 taken 5888153 times.
7753869 for s in subscripts loop
504
2/2
✓ Branch 1 taken 533 times.
✓ Branch 2 taken 1865183 times.
1865716 if containsExp(s, func) then
505 res := true;
506 533 return;
507 end if;
508 end for;
509
510 res := false;
511 end listContainsExp;
512
513 function containsExpShallow
514 input Subscript subscript;
515 input ContainsPred func;
516 output Boolean res;
517
518 partial function ContainsPred
519 input Expression exp;
520 output Boolean res;
521 end ContainsPred;
522 algorithm
523 res := match subscript
524
1/2
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
11 case UNTYPED() then func(subscript.exp);
525
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 1996 times.
2024 case INDEX() then func(subscript.index);
526 ✗ case SLICE() then func(subscript.slice);
527 else false;
528 end match;
529 end containsExpShallow;
530
531 function listContainsExpShallow
532 input list<Subscript> subscripts;
533 input ContainsPred func;
534 output Boolean res;
535
536 partial function ContainsPred
537 input Expression exp;
538 output Boolean res;
539 end ContainsPred;
540 algorithm
541
2/2
✓ Branch 0 taken 20416 times.
✓ Branch 1 taken 112372 times.
132788 for s in subscripts loop
542
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20416 times.
20416 if containsExpShallow(s, func) then
543 res := true;
544 ✗ return;
545 end if;
546 end for;
547
548 res := false;
549 end listContainsExpShallow;
550
551 function applyExp
552 input Subscript subscript;
553 input ApplyFunc func;
554
555 partial function ApplyFunc
556 input Expression exp;
557 end ApplyFunc;
558 algorithm
559 () := match subscript
560 1989 case UNTYPED() algorithm Expression.apply(subscript.exp, func); then ();
561 732255 case INDEX() algorithm Expression.apply(subscript.index, func); then ();
562 1458 case SLICE() algorithm Expression.apply(subscript.slice, func); then ();
563 else ();
564 end match;
565 end applyExp;
566
567 function applyExpShallow
568 input Subscript subscript;
569 input ApplyFunc func;
570
571 partial function ApplyFunc
572 input Expression exp;
573 end ApplyFunc;
574 algorithm
575 () := match subscript
576
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 case UNTYPED() algorithm func(subscript.exp); then ();
577
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 548 times.
548 case INDEX() algorithm func(subscript.index); then ();
578 ✗ case SLICE() algorithm func(subscript.slice); then ();
579 else ();
580 end match;
581 end applyExpShallow;
582
583 function mapExp
584 input Subscript subscript;
585 input MapFunc func;
586 output Subscript outSubscript;
587
588 partial function MapFunc
589 input output Expression e;
590 end MapFunc;
591 algorithm
592 outSubscript := match subscript
593 local
594 Expression e1, e2;
595
596 case UNTYPED(exp = e1)
597 algorithm
598 1 e2 := Expression.map(e1, func);
599
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 then
600 if referenceEq(e1, e2) then subscript else UNTYPED(e2);
601
602 case INDEX(index = e1)
603 algorithm
604 2420617 e2 := Expression.map(e1, func);
605
2/2
✓ Branch 0 taken 128469 times.
✓ Branch 1 taken 2292148 times.
2420617 then
606 if referenceEq(e1, e2) then subscript else fromTypedExp(e2);
607
608 case SLICE(slice = e1)
609 algorithm
610 3563 e2 := Expression.map(e1, func);
611
2/2
✓ Branch 0 taken 1294 times.
✓ Branch 1 taken 2269 times.
3563 then
612 if referenceEq(e1, e2) then subscript else fromTypedExp(e2);
613
614 else subscript;
615 end match;
616 end mapExp;
617
618 function mapShallowExp
619 input Subscript subscript;
620 input MapFunc func;
621 output Subscript outSubscript;
622
623 partial function MapFunc
624 input output Expression e;
625 end MapFunc;
626 algorithm
627 outSubscript := match subscript
628 local
629 Expression e1, e2;
630
631 case UNTYPED(exp = e1)
632 algorithm
633 ✗ e2 := func(e1);
634 ✗ then
635 if referenceEq(e1, e2) then subscript else UNTYPED(e2);
636
637 case INDEX(index = e1)
638 algorithm
639
2/2
✓ Branch 0 taken 825442 times.
✓ Branch 1 taken 6350 times.
831792 e2 := func(e1);
640
2/2
✓ Branch 0 taken 51005 times.
✓ Branch 1 taken 780787 times.
831792 then
641 if referenceEq(e1, e2) then subscript else fromTypedExp(e2);
642
643 case SLICE(slice = e1)
644 algorithm
645
1/2
✓ Branch 0 taken 3195 times.
✗ Branch 1 not taken.
3195 e2 := func(e1);
646
2/2
✓ Branch 0 taken 1325 times.
✓ Branch 1 taken 1870 times.
3195 then
647 if referenceEq(e1, e2) then subscript else fromTypedExp(e2);
648
649 else subscript;
650 end match;
651 end mapShallowExp;
652
653 function foldExp<ArgT>
654 input Subscript subscript;
655 input FoldFunc func;
656 input ArgT arg;
657 output ArgT result;
658
659 partial function FoldFunc
660 input Expression exp;
661 input output ArgT arg;
662 end FoldFunc;
663 algorithm
664 result := match subscript
665 16 case UNTYPED() then Expression.fold(subscript.exp, func, arg);
666 837868 case INDEX() then Expression.fold(subscript.index, func, arg);
667 1274 case SLICE() then Expression.fold(subscript.slice, func, arg);
668 else arg;
669 end match;
670 end foldExp;
671
672 function mapFoldExp<ArgT>
673 input Subscript subscript;
674 input MapFunc func;
675 output Subscript outSubscript;
676 input output ArgT arg;
677
678 partial function MapFunc
679 input output Expression e;
680 input output ArgT arg;
681 end MapFunc;
682 algorithm
683 outSubscript := match subscript
684 local
685 Expression exp;
686
687 case UNTYPED()
688 algorithm
689 ✗ (exp, arg) := Expression.mapFold(subscript.exp, func, arg);
690 ✗ then
691 if referenceEq(subscript.exp, exp) then subscript else UNTYPED(exp);
692
693 case INDEX()
694 algorithm
695 21 (exp, arg) := Expression.mapFold(subscript.index, func, arg);
696
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 10 times.
21 then
697 if referenceEq(subscript.index, exp) then subscript else fromTypedExp(exp);
698
699 case SLICE()
700 algorithm
701 ✗ (exp, arg) := Expression.mapFold(subscript.slice, func, arg);
702 ✗ then
703 if referenceEq(subscript.slice, exp) then subscript else fromTypedExp(exp);
704
705 else subscript;
706 end match;
707 end mapFoldExp;
708
709 function mapFoldExpShallow<ArgT>
710 input Subscript subscript;
711 input MapFunc func;
712 output Subscript outSubscript;
713 input output ArgT arg;
714
715 partial function MapFunc
716 input output Expression e;
717 input output ArgT arg;
718 end MapFunc;
719 algorithm
720 outSubscript := match subscript
721 local
722 Expression exp;
723
724 case UNTYPED()
725 algorithm
726 ✗ (exp, arg) := func(subscript.exp, arg);
727 ✗ then
728 if referenceEq(subscript.exp, exp) then subscript else UNTYPED(exp);
729
730 case INDEX()
731 algorithm
732
1/2
✓ Branch 0 taken 430973 times.
✗ Branch 1 not taken.
430973 (exp, arg) := func(subscript.index, arg);
733
2/2
✓ Branch 0 taken 11511 times.
✓ Branch 1 taken 419462 times.
430973 then
734 if referenceEq(subscript.index, exp) then subscript else fromTypedExp(exp);
735
736 case SLICE()
737 algorithm
738
1/2
✓ Branch 0 taken 1435 times.
✗ Branch 1 not taken.
1435 (exp, arg) := func(subscript.slice, arg);
739
2/2
✓ Branch 0 taken 420 times.
✓ Branch 1 taken 1015 times.
1435 then
740 if referenceEq(subscript.slice, exp) then subscript else fromTypedExp(exp);
741
742 else subscript;
743 end match;
744 end mapFoldExpShallow;
745
746 function toAbsyn
747 input Subscript subscript;
748 output Absyn.Subscript asubscript;
749 algorithm
750 asubscript := match subscript
751 ✗ case RAW_SUBSCRIPT() then subscript.subscript;
752 ✗ case UNTYPED() then Absyn.Subscript.SUBSCRIPT(Expression.toAbsyn(subscript.exp));
753 ✗ case INDEX() then Absyn.Subscript.SUBSCRIPT(Expression.toAbsyn(subscript.index));
754 ✗ case SLICE() then Absyn.Subscript.SUBSCRIPT(Expression.toAbsyn(subscript.slice));
755 case WHOLE() then Absyn.Subscript.NOSUB();
756 else
757 algorithm
758 ✗ Error.terminate(getInstanceName() + " failed on unknown subscript", sourceInfo());
759 ✗ then
760 fail();
761 end match;
762 end toAbsyn;
763
764 function toDAE
765 input Subscript subscript;
766 output DAE.Subscript daeSubscript;
767 algorithm
768 daeSubscript := match subscript
769 874092 case INDEX() then DAE.INDEX(Expression.toDAE(subscript.index));
770 145 case SLICE() then DAE.SLICE(Expression.toDAE(subscript.slice));
771 case WHOLE() then DAE.WHOLEDIM();
772 else
773 algorithm
774 ✗ Error.terminate(getInstanceName() + " failed on unknown subscript " + toString(subscript), sourceInfo());
775 ✗ then
776 fail();
777 end match;
778 end toDAE;
779
780 function toString
781 input Subscript subscript;
782 output String string;
783 algorithm
784 string := match subscript
785 ✗ case RAW_SUBSCRIPT() then Dump.printSubscriptStr(subscript.subscript);
786 76 case UNTYPED() then Expression.toString(subscript.exp);
787 66733 case INDEX() then Expression.toString(subscript.index);
788 1943 case SLICE() then Expression.toString(subscript.slice);
789 case EXPANDED_SLICE()
790 ✗ then List.toString(subscript.indices, toString, List.Style.FLAT_CURLY);
791 case WHOLE() then ":";
792 case SPLIT_PROXY()
793 ✗ then "<" + InstNode.name(InstNode.borrow(subscript.origin)) + ", " + InstNode.name(InstNode.borrow(subscript.parent)) + ">";
794 case SPLIT_INDEX()
795 ✗ then "<" + InstNode.name(InstNode.borrow(subscript.node)) + ", " + String(subscript.dimIndex) + ">";
796 end match;
797 end toString;
798
799 function toStringList
800 input list<Subscript> subscripts;
801 output String string;
802 algorithm
803 351722 string := List.toStringCustom(subscripts, toString, "", "[", ", ", "]", false);
804 end toStringList;
805
806 function toFlatString
807 input Subscript subscript;
808 input BaseModelica.OutputFormat format;
809 output String string;
810 algorithm
811 string := match subscript
812 ✗ case RAW_SUBSCRIPT() then Dump.printSubscriptStr(subscript.subscript);
813 ✗ case UNTYPED() then Expression.toFlatString(subscript.exp, format);
814 1618 case INDEX() then Expression.toFlatString(subscript.index, format);
815 1 case SLICE() then Expression.toFlatString(subscript.slice, format);
816 case EXPANDED_SLICE()
817 ✗ then List.toStringCustom(subscript.indices, toString, "", "{", ", ", "}", false);
818 case WHOLE() then ":";
819 case SPLIT_INDEX()
820 ✗ then "<" + InstNode.name(InstNode.borrow(subscript.node)) + ", " + String(subscript.dimIndex) + ">";
821 end match;
822 end toFlatString;
823
824 function toFlatStringList
825 input list<Subscript> subscripts;
826 input BaseModelica.OutputFormat format;
827 input Boolean escapeQuotes;
828 output String string;
829 algorithm
830 1605 string := List.toStringCustom(subscripts, function toFlatString(format = format), "", "[", ",", "]", false);
831
832
2/2
✓ Branch 0 taken 102 times.
✓ Branch 1 taken 1503 times.
1605 if escapeQuotes then
833 1503 string := Util.escapeQuotes(string);
834 end if;
835 end toFlatStringList;
836
837 function toJSON
838 input Subscript subscript;
839 output JSON json;
840 algorithm
841 json := match subscript
842 ✗ case UNTYPED() then Expression.toJSON(subscript.exp);
843 ✗ case INDEX() then Expression.toJSON(subscript.index);
844 ✗ case SLICE() then Expression.toJSON(subscript.slice);
845 ✗ else JSON.makeString(toString(subscript));
846 end match;
847 end toJSON;
848
849 function toJSONList
850 input list<Subscript> subscripts;
851 output JSON json = JSON.makeNull();
852 algorithm
853 ✗ for s in subscripts loop
854 ✗ json := JSON.addElement(toJSON(s), json);
855 end for;
856 end toJSONList;
857
858 function eval
859 input Subscript subscript;
860 input EvalTarget target = NFCeval.noTarget;
861 output Subscript outSubscript;
862 algorithm
863 outSubscript := match subscript
864 29084 case INDEX() then INDEX(Ceval.evalExp(subscript.index, target));
865 16 case SLICE() then SLICE(Ceval.evalExp(subscript.slice, target));
866 else subscript;
867 end match;
868 end eval;
869
870 function simplify
871 input Subscript subscript;
872 input Dimension dimension;
873 output Subscript outSubscript;
874 algorithm
875 outSubscript := match subscript
876 511462 case INDEX() then INDEX(SimplifyExp.simplify(subscript.index));
877 1208 case SLICE() then simplifySlice(subscript.slice, dimension);
878 else subscript;
879 end match;
880 end simplify;
881
882 function simplifySlice
883 input Expression slice;
884 input Dimension dimension;
885 output Subscript outSubscript;
886 protected
887 Expression exp;
888 algorithm
889 1208 exp := SimplifyExp.simplify(slice);
890
891 outSubscript := match exp
892 // If the slice is equivalent to 1:size(dim), replace it with :
893 case Expression.RANGE()
894 guard (isNone(exp.step) or Expression.isOne(Util.getOption(exp.step))) and
895 Dimension.expIsLowerBound(exp.start) and
896 Dimension.expIsUpperBound(exp.stop, dimension)
897 then WHOLE();
898
899 // Otherwise return a new slice with the simplified expression.
900 1153 else SLICE(exp);
901 end match;
902 end simplifySlice;
903
904 function simplifyList
905 input list<Subscript> subscripts;
906 input list<Dimension> dimensions;
907 input Boolean trim = false;
908 output list<Subscript> outSubscripts = {};
909 protected
910 Dimension d;
911 list<Dimension> rest_d = dimensions;
912 algorithm
913
1/2
✓ Branch 0 taken 461767 times.
✗ Branch 1 not taken.
461767 if listEmpty(dimensions) then
914 // If the type of the subscript owner isn't known, for example when dealing
915 // with expandable connector elements, treat the dimensions as unknown.
916 ✗ outSubscripts := list(simplify(s, Dimension.UNKNOWN()) for s in subscripts);
917 else
918
2/2
✓ Branch 0 taken 517610 times.
✓ Branch 1 taken 461767 times.
979377 for s in subscripts loop
919
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 517610 times.
517610 d :: rest_d := rest_d;
920 517610 outSubscripts := simplify(s, d) :: outSubscripts;
921 end for;
922
923
2/2
✓ Branch 0 taken 3075 times.
✓ Branch 1 taken 458692 times.
461767 if trim then
924 3075 outSubscripts := listReverseInPlace(List.trim(outSubscripts, isWhole));
925 else
926 458692 outSubscripts := listReverseInPlace(outSubscripts);
927 end if;
928 end if;
929 end simplifyList;
930
931 function toDimension
932 "Returns a dimension representing the size of the given subscript."
933 input Subscript subscript;
934 output Dimension dimension;
935 algorithm
936 dimension := match subscript
937 ✗ case INDEX() then Dimension.fromInteger(1);
938 7673 case SLICE() then listHead(Type.arrayDims(Expression.typeOf(subscript.slice)));
939 case WHOLE() then Dimension.UNKNOWN();
940 ✗ case SPLIT_INDEX() then Dimension.fromInteger(1);
941 else algorithm
942 ✗ Error.terminate(getInstanceName() + " got wrong subscript " + toString(subscript) + "\n", sourceInfo());
943 ✗ then fail();
944 end match;
945 end toDimension;
946
947 function fromDimension
948 "Returns a slice subscripts that covers the given dimension.
949 Will fail for untyped or unknown dimensions."
950 input Dimension dimension;
951 output Subscript subscript;
952 algorithm
953 subscript := match dimension
954 case Dimension.INTEGER()
955 ✗ then Subscript.SLICE(Expression.makeIntegerRange(1, 1, dimension.size));
956 case Dimension.BOOLEAN()
957 ✗ then Subscript.SLICE(Expression.makeRange(Expression.BOOLEAN(false), NONE(), Expression.BOOLEAN(true)));
958 case Dimension.ENUM()
959 ✗ then Subscript.SLICE(Expression.makeRange(
960 Expression.makeEnumLiteral(dimension.enumType, 1),
961 NONE(),
962 Expression.makeEnumLiteral(dimension.enumType, Type.enumSize(dimension.enumType))));
963 case Dimension.EXP()
964 ✗ then Subscript.SLICE(Expression.makeRange(Expression.INTEGER(1), NONE(), dimension.exp));
965 case Dimension.RESIZABLE()
966 ✗ then Subscript.SLICE(Expression.makeRange(Expression.INTEGER(1), NONE(), dimension.exp));
967 end match;
968 end fromDimension;
969
970 function scalarize
971 input Subscript subscript;
972 input Dimension dimension;
973 input Boolean resize;
974 output list<Subscript> subscripts;
975 algorithm
976 subscripts := match subscript
977 case INDEX() then {subscript};
978 case SLICE()
979
4/4
✓ Branch 2 taken 661 times.
✓ Branch 3 taken 155 times.
✓ Branch 5 taken 661 times.
✓ Branch 6 taken 155 times.
1632 then list(INDEX(e) for e in Expression.arrayElements(ExpandExp.expand(subscript.slice, resize)));
980 case WHOLE()
981 296 then RangeIterator.map(RangeIterator.fromDim(dimension, resize), makeIndex);
982 else {subscript};
983 end match;
984 end scalarize;
985
986 function scalarizeList
987 input list<Subscript> subscripts;
988 input list<Dimension> dimensions;
989 input Boolean resize;
990 output list<list<Subscript>> outSubscripts = {};
991 protected
992 Dimension dim;
993 list<Dimension> rest_dims = dimensions;
994 list<Subscript> subs;
995 algorithm
996
2/2
✓ Branch 0 taken 19746 times.
✓ Branch 1 taken 97852 times.
117598 for s in subscripts loop
997
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19746 times.
19746 dim :: rest_dims := rest_dims;
998 19746 subs := scalarize(s, dim, resize);
999
1000
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19746 times.
19746 if listEmpty(subs) then
1001 outSubscripts := {};
1002 ✗ return;
1003 else
1004 outSubscripts := subs :: outSubscripts;
1005 end if;
1006 end for;
1007
1008
2/2
✓ Branch 0 taken 92524 times.
✓ Branch 1 taken 95452 times.
187976 for d in rest_dims loop
1009 92524 subs := RangeIterator.map(RangeIterator.fromDim(d, resize), makeIndex);
1010
1011
2/2
✓ Branch 0 taken 2400 times.
✓ Branch 1 taken 90124 times.
92524 if listEmpty(subs) then
1012 outSubscripts := {};
1013 2400 return;
1014 else
1015 outSubscripts := subs :: outSubscripts;
1016 end if;
1017 end for;
1018
1019 95452 outSubscripts := listReverse(outSubscripts);
1020 end scalarizeList;
1021
1022 function expand
1023 input Subscript subscript;
1024 input Dimension dimension;
1025 input Boolean resize;
1026 output Subscript outSubscript;
1027 output Boolean expanded;
1028 algorithm
1029 (outSubscript, expanded) := match subscript
1030 local
1031 RangeIterator iter;
1032
1033 756 case SLICE() then expandSlice(subscript, resize);
1034
1035 case WHOLE()
1036 algorithm
1037 2124 iter := RangeIterator.fromDim(dimension, resize);
1038
1039
1/2
✓ Branch 1 taken 2124 times.
✗ Branch 2 not taken.
2124 if RangeIterator.isValid(iter) then
1040 2124 outSubscript := EXPANDED_SLICE(RangeIterator.map(iter, makeIndex));
1041 expanded := true;
1042 else
1043 outSubscript := subscript;
1044 expanded := false;
1045 end if;
1046 2124 then
1047 (outSubscript, expanded);
1048
1049 3837 else (subscript, true);
1050 end match;
1051 end expand;
1052
1053 function expandSlice
1054 input Subscript subscript;
1055 input Boolean resize;
1056 output Subscript outSubscript;
1057 output Boolean expanded;
1058 algorithm
1059 (outSubscript, expanded) := match subscript
1060 local
1061 Expression exp;
1062
1063 case SLICE()
1064 algorithm
1065 // A range with constant but non-literal bounds (`3:end-1` becomes
1066 // `3:5-1`) does not expand until it is simplified.
1067 1029 exp := ExpandExp.expand(SimplifyExp.simplify(subscript.slice), resize);
1068
1069
2/2
✓ Branch 1 taken 1025 times.
✓ Branch 2 taken 4 times.
1029 if Expression.isArray(exp) then
1070
4/4
✓ Branch 1 taken 3331 times.
✓ Branch 2 taken 1025 times.
✓ Branch 4 taken 3331 times.
✓ Branch 5 taken 1025 times.
8712 outSubscript := EXPANDED_SLICE(list(INDEX(e) for e in Expression.arrayElements(exp)));
1071 expanded := true;
1072 else
1073 outSubscript := subscript;
1074 expanded := false;
1075 end if;
1076 then
1077 (outSubscript, expanded);
1078
1079 else (subscript, false);
1080 end match;
1081 end expandSlice;
1082
1083 function expandList
1084 input list<Subscript> subscripts;
1085 input list<Dimension> dimensions;
1086 input Boolean resize;
1087 output list<Subscript> outSubscripts = {};
1088 protected
1089 Dimension dim;
1090 list<Dimension> rest_dims = dimensions;
1091 Subscript sub;
1092 algorithm
1093
2/2
✓ Branch 0 taken 6717 times.
✓ Branch 1 taken 34284 times.
41001 for s in subscripts loop
1094
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6717 times.
6717 dim :: rest_dims := rest_dims;
1095 6717 sub := expand(s, dim, resize);
1096 outSubscripts := sub :: outSubscripts;
1097 end for;
1098
1099
2/2
✓ Branch 0 taken 24649 times.
✓ Branch 1 taken 34284 times.
58933 for d in rest_dims loop
1100 24649 sub := EXPANDED_SLICE(RangeIterator.map(RangeIterator.fromDim(d, resize), makeIndex));
1101 outSubscripts := sub :: outSubscripts;
1102 end for;
1103
1104 34284 outSubscripts := listReverse(outSubscripts);
1105 end expandList;
1106
1107 function variability
1108 input Subscript subscript;
1109 output Variability var;
1110 algorithm
1111 var := match subscript
1112 ✗ case UNTYPED() then Expression.variability(subscript.exp);
1113 4425553 case INDEX() then Expression.variability(subscript.index);
1114 10 case SLICE() then Expression.variability(subscript.slice);
1115 else Variability.CONSTANT;
1116 end match;
1117 end variability;
1118
1119 function variabilityList
1120 input list<Subscript> subscripts;
1121 output Variability var = Variability.CONSTANT;
1122 algorithm
1123
2/2
✓ Branch 0 taken 90058 times.
✓ Branch 1 taken 87685 times.
177743 for s in subscripts loop
1124 90058 var := Prefixes.variabilityMax(var, variability(s));
1125 end for;
1126 end variabilityList;
1127
1128 function purity
1129 input Subscript subscript;
1130 output Purity purity;
1131 algorithm
1132 purity := match subscript
1133 24779 case UNTYPED() then Expression.purity(subscript.exp);
1134 230980 case INDEX() then Expression.purity(subscript.index);
1135 10 case SLICE() then Expression.purity(subscript.slice);
1136 else Purity.IMPURE;
1137 end match;
1138 end purity;
1139
1140 function purityList
1141 input list<Subscript> subscripts;
1142 output Purity pur = Purity.PURE;
1143 algorithm
1144
2/2
✓ Branch 0 taken 90763 times.
✓ Branch 1 taken 88390 times.
179153 for s in subscripts loop
1145 90763 pur := Prefixes.purityMin(pur, purity(s));
1146 end for;
1147 end purityList;
1148
1149 function mergeList
1150 "Merges a list of subscripts with a list of 'existing' subscripts.
1151 This is done by e.g. subscripting existing slice and : subscripts,
1152 such that e.g. mergeList({1, :}, {3:5, 1:3, 4}) => {3, 1:3, 4}.
1153 The function will ensure that the output list contains at most as
1154 many subscripts as the given number of dimensions, and also returns
1155 the list of remaining subscripts that couldn't be added."
1156 input list<Subscript> newSubs "Subscripts to add";
1157 input list<Subscript> oldSubs "Existing subscripts";
1158 input Integer dimensions "The number of dimensions to subscript";
1159 input Boolean backend "if true discards a subscript for scalar if it is exacty 1";
1160 output list<Subscript> outSubs "The merged subscripts, at most 'dimensions' many";
1161 output list<Subscript> remainingSubs "The subscripts that didn't fit";
1162 protected
1163 Integer subs_count;
1164 Subscript new_sub, old_sub;
1165 list<Subscript> rest_old_subs;
1166 Boolean merged = true;
1167 algorithm
1168 // discard an index for backend if it is exactly one for scalars
1169
5/6
✓ Branch 0 taken 13540 times.
✓ Branch 1 taken 366614 times.
✓ Branch 3 taken 8821 times.
✓ Branch 4 taken 4719 times.
✓ Branch 7 taken 8821 times.
✗ Branch 8 not taken.
380154 if backend and listLength(oldSubs) >= dimensions and List.all(List.firstN(oldSubs, dimensions), isBackendIterator) then
1170 8821 (_, remainingSubs) := List.split(newSubs, dimensions);
1171 8821 (outSubs, _) := List.split(oldSubs, dimensions);
1172 8821 return;
1173 end if;
1174
1175 // If there aren't any existing subscripts we just add as many subscripts
1176 // from the list of new subscripts as possible.
1177
2/2
✓ Branch 0 taken 304263 times.
✓ Branch 1 taken 67070 times.
371333 if listEmpty(oldSubs) then
1178
2/2
✓ Branch 1 taken 232439 times.
✓ Branch 2 taken 71824 times.
304263 if listLength(newSubs) <= dimensions then
1179 outSubs := newSubs;
1180 232439 remainingSubs := {};
1181 else
1182 71824 (outSubs, remainingSubs) := List.split(newSubs, dimensions);
1183 end if;
1184
1185 304263 return;
1186 end if;
1187
1188 67070 subs_count := listLength(oldSubs);
1189 67070 remainingSubs := newSubs;
1190 rest_old_subs := oldSubs;
1191 outSubs := {};
1192
1193 // Loop over the remaining subscripts as long as they can be merged.
1194
4/4
✓ Branch 0 taken 1241 times.
✓ Branch 1 taken 132899 times.
✓ Branch 2 taken 65829 times.
✓ Branch 3 taken 67070 times.
134140 while merged and not listEmpty(remainingSubs) loop
1195 67070 new_sub :: remainingSubs := remainingSubs;
1196 merged := false;
1197
1198 // Loop over the old subscripts while this new subscript hasn't been
1199 // merged and there's still old subscript left.
1200
2/2
✓ Branch 0 taken 65829 times.
✓ Branch 1 taken 132671 times.
198500 while not merged loop
1201
2/2
✓ Branch 0 taken 1241 times.
✓ Branch 1 taken 131430 times.
132671 if listEmpty(rest_old_subs) then
1202 1241 remainingSubs := new_sub :: remainingSubs;
1203 1241 break;
1204 else
1205
3/3
✓ Branch 0 taken 1465 times.
✓ Branch 1 taken 64364 times.
✓ Branch 2 taken 65601 times.
131430 old_sub :: rest_old_subs := rest_old_subs;
1206
1207 // Try to replace the old subscript with the new.
1208 (merged, outSubs) := match old_sub
1209 // If the old subscript is a slice, subscript it with the new subscript.
1210 case SLICE()
1211 algorithm
1212 // The old subscript only changes if the new is an index or slice, not :.
1213
1/2
✓ Branch 1 taken 1465 times.
✗ Branch 2 not taken.
1465 if not isWhole(new_sub) then
1214 1465 outSubs := Subscript.INDEX(Expression.applySubscript(new_sub, old_sub.slice)) :: outSubs;
1215 else
1216 outSubs := old_sub :: outSubs;
1217 end if;
1218 then
1219 (true, outSubs);
1220
1221 // If the old subscript is :, replace it with the new subscript.
1222 case WHOLE() then (true, new_sub :: outSubs);
1223 // If the old subscript is a scalar index it can't be replaced.
1224 else (false, old_sub :: outSubs);
1225 end match;
1226 end if;
1227 end while;
1228 end while;
1229
1230 // Append any remaining old subscripts.
1231
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 67070 times.
67086 for s in rest_old_subs loop
1232 outSubs := s :: outSubs;
1233 end for;
1234
1235 // Append any remaining new subscripts to the end of the list as long as
1236 // there are dimensions left to fill.
1237
4/4
✓ Branch 0 taken 1241 times.
✓ Branch 1 taken 66920 times.
✓ Branch 2 taken 1091 times.
✓ Branch 3 taken 150 times.
68161 while not listEmpty(remainingSubs) and subs_count < dimensions loop
1238 1091 new_sub :: remainingSubs := remainingSubs;
1239 outSubs := new_sub :: outSubs;
1240 1091 subs_count := subs_count + 1;
1241 end while;
1242
1243 67070 outSubs := listReverseInPlace(outSubs);
1244 end mergeList;
1245
1246 function nth
1247 input Dimension dim;
1248 input Integer i;
1249 output Subscript sub;
1250 algorithm
1251 sub := match dim
1252 3418 case Dimension.INTEGER() then INDEX(Expression.INTEGER(i));
1253 case Dimension.BOOLEAN() guard(i == 1) then INDEX(Expression.BOOLEAN(false));
1254 case Dimension.BOOLEAN() guard(i == 2) then INDEX(Expression.BOOLEAN(true));
1255 ✗ case Dimension.ENUM() then INDEX(Expression.nthEnumLiteral(dim.enumType, i));
1256 44 case Dimension.RESIZABLE() then INDEX(Expression.INTEGER(i));
1257 else algorithm
1258 ✗ Error.terminate(getInstanceName() + " got an incorrect dimension type " + Dimension.toString(dim) + ".", sourceInfo());
1259 ✗ then fail();
1260 end match;
1261 end nth;
1262
1263 function first
1264 input Dimension dim;
1265 output Subscript sub;
1266 algorithm
1267 sub := match dim
1268 case Dimension.INTEGER() then INDEX(Expression.INTEGER(1));
1269 case Dimension.BOOLEAN() then INDEX(Expression.BOOLEAN(false));
1270 ✗ case Dimension.ENUM() then INDEX(Expression.nthEnumLiteral(dim.enumType, 1));
1271 case Dimension.RESIZABLE() then INDEX(Expression.INTEGER(1));
1272 end match;
1273 end first;
1274
1275 function isFirst
1276 input Subscript sub;
1277 output Boolean b;
1278 algorithm
1279 b := match sub
1280 case INDEX(Expression.INTEGER(1)) then true;
1281 case INDEX(Expression.BOOLEAN(false)) then true;
1282 case INDEX(Expression.ENUM_LITERAL(index = 1)) then true;
1283 else false;
1284 end match;
1285 end isFirst;
1286
1287 function isSplit
1288 input Subscript sub;
1289 output Boolean res;
1290 algorithm
1291 res := match sub
1292 case SPLIT_PROXY() then true;
1293 case SPLIT_INDEX() then true;
1294 else false;
1295 end match;
1296 end isSplit;
1297
1298 function isSplitIndex
1299 input Subscript sub;
1300 output Boolean res;
1301 algorithm
1302 res := match sub
1303 case SPLIT_INDEX() then true;
1304 else false;
1305 end match;
1306 end isSplitIndex;
1307
1308 function isSplitClassProxy
1309 input Subscript sub;
1310 output Boolean res;
1311 algorithm
1312 res := match sub
1313 32 case SPLIT_PROXY() then InstNode.isClass(InstNode.borrow(sub.origin));
1314 else false;
1315 end match;
1316 end isSplitClassProxy;
1317
1318 function isSplitFromOrigin
1319 input Subscript sub;
1320 input InstNode origin;
1321 output Boolean res;
1322 algorithm
1323 res := match sub
1324 25 case SPLIT_PROXY() then InstNode.refEqual(origin, InstNode.borrow(sub.origin));
1325 else false;
1326 end match;
1327 end isSplitFromOrigin;
1328
1329 function expandSplitIndices
1330 input list<Subscript> subs;
1331 input list<InstNode> indicesToKeep = {};
1332 output list<Subscript> outSubs = {};
1333 protected
1334 Boolean changed = false;
1335 algorithm
1336
2/2
✓ Branch 0 taken 116020 times.
✓ Branch 1 taken 298876 times.
414896 for s in subs loop
1337 () := match s
1338 case SPLIT_INDEX()
1339 algorithm
1340
2/2
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 81945 times.
81950 if List.isMemberOnTrue(InstNode.borrow(s.node), indicesToKeep, InstNode.refEqual) then
1341 outSubs := s :: outSubs;
1342 else
1343 outSubs := WHOLE() :: outSubs;
1344 changed := true;
1345 end if;
1346 then
1347 ();
1348
1349 else
1350 algorithm
1351 outSubs := s :: outSubs;
1352 then
1353 ();
1354 end match;
1355 end for;
1356
1357
2/2
✓ Branch 0 taken 79575 times.
✓ Branch 1 taken 219301 times.
298876 if changed then
1358 79575 outSubs := List.trim(outSubs, isWhole);
1359 79575 outSubs := listReverseInPlace(outSubs);
1360 else
1361 outSubs := subs;
1362 end if;
1363 end expandSplitIndices;
1364
1365 function hash
1366 input Subscript sub;
1367 output Integer hash = hashContinue(sub, Util.HASH_SEED);
1368 end hash;
1369
1370 function hashStringContinue
1371 "Same value as stringHashDjb2Continue(toString(sub), hash), but without
1372 rendering the subscript for the integer index case that array subscripts
1373 almost always are. Used where the hash has to stay stable, since it decides
1374 UnorderedSet bucket order and with it the order of the generated code."
1375 input Subscript sub;
1376 input output Integer hash;
1377 algorithm
1378 hash := match sub
1379 local
1380 Integer i;
1381 610764 case INDEX(index = Expression.INTEGER(value = i)) then intHashDjb2Continue(i, hash);
1382 50124 else stringHashDjb2Continue(toString(sub), hash);
1383 end match;
1384 end hashStringContinue;
1385
1386 function hashContinue
1387 input Subscript sub;
1388 input output Integer hash;
1389 algorithm
1390 hash := match sub
1391 ✗ case RAW_SUBSCRIPT() then stringHashDjb2Continue(Dump.printSubscriptStr(sub.subscript), hash);
1392 ✗ case UNTYPED() then Expression.hashContinue(sub.exp, hash);
1393 129 case INDEX() then Expression.hashContinue(sub.index, hash);
1394 ✗ case SLICE() then Expression.hashContinue(sub.slice, hash);
1395
1396 case EXPANDED_SLICE()
1397 algorithm
1398 ✗ hash := stringHashDjb2Continue("{", hash);
1399 ✗ for s in sub.indices loop
1400 ✗ hash := hashContinue(s, hash);
1401 ✗ hash := stringHashDjb2Continue(", ", hash); // trailing comma, don't care...
1402 end for;
1403 ✗ hash := stringHashDjb2Continue("}", hash);
1404 then hash;
1405
1406 ✗ case WHOLE() then stringHashDjb2Continue(":", hash);
1407
1408 case SPLIT_PROXY()
1409 algorithm
1410 ✗ hash := InstNode.hashContinue(InstNode.borrow(sub.origin), hash);
1411 ✗ hash := InstNode.hashContinue(InstNode.borrow(sub.parent), hash);
1412 then hash;
1413
1414 case SPLIT_INDEX()
1415 algorithm
1416 17 hash := InstNode.hashContinue(InstNode.borrow(sub.node), hash);
1417 17 hash := stringHashDjb2Continue(intString(sub.dimIndex), hash);
1418 then hash;
1419
1420 else hash;
1421 end match;
1422 end hashContinue;
1423
1424 function splitIndexDimExp
1425 input Subscript sub;
1426 output Expression exp;
1427 protected
1428 NFInstNode.ScopeRef node;
1429 Integer index;
1430 algorithm
1431
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 SPLIT_INDEX(node = node, dimIndex = index) := sub;
1432 14 exp := Dimension.sizeExp(Type.nthDimension(InstNode.getType(InstNode.borrow(node)), index));
1433 end splitIndexDimExp;
1434
1435 function isLiteral
1436 input Subscript sub;
1437 output Boolean literal;
1438 algorithm
1439 literal := match sub
1440 ✗ case UNTYPED() then Expression.isLiteral(sub.exp);
1441 10111 case INDEX() then Expression.isLiteral(sub.index);
1442 30 case SLICE() then Expression.isLiteral(sub.slice);
1443 case WHOLE() then true;
1444 else false;
1445 end match;
1446 end isLiteral;
1447
1448 function fillWithWholeLeft
1449 input output list<Subscript> subs;
1450 input Integer targetLength;
1451 algorithm
1452 375 subs := listAppend(List.fill(Subscript.WHOLE(), targetLength - listLength(subs)), subs);
1453 end fillWithWholeLeft;
1454
1455 annotation(__OpenModelica_Interface="nf_frontend");
1456 end NFSubscript;
1457