Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 84.3% 321 / 0 / 381
Functions: -% 0 / 1 / 1
Branches: 77.4% 291 / 0 / 376

OMCompiler/Compiler/NFFrontEnd/NFComponentRef.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 NFComponentRef
37 import BaseModelica;
38
39 protected
40 import Component = NFComponent;
41 import Absyn;
42 import DAE;
43 import Subscript = NFSubscript;
44 import Type = NFType;
45 import NFInstNode.InstNode;
46 import NFInstNode;
47 import NFInstNode.InstNodeType;
48 import Dimension = NFDimension;
49 import Expression = NFExpression;
50 import NFPrefixes.{Variability, Purity, Visibility};
51 import Class = NFClass;
52 import NFClassTree.ClassTree;
53 import List;
54 import Prefixes = NFPrefixes;
55 import MetaModelica.Dangerous.*;
56 import JSON;
57 import Variable = NFVariable;
58 import Binding = NFBinding;
59 import NFBackendExtension.{BackendInfo, Annotations};
60
61 import ComponentRef = NFComponentRef;
62
63 public
64 type Origin = enumeration(
65 CREF "From an Absyn cref.",
66 SCOPE "From prefixing the cref with its scope.",
67 ITERATOR "From an iterator."
68 );
69
70 record CREF
71 InstNode node "The node this cref names. The Rust port stores a weak
72 handle here instead -- see NFComponentRef.rust.mo -- because the class
73 tree owns the node and its class holds the equation the cref sits in.";
74 list<Subscript> subscripts;
75 Type ty "The type of the node, without taking subscripts into account.";
76 Origin origin;
77 ComponentRef restCref;
78 end CREF;
79
80 record EMPTY end EMPTY;
81 record WILD end WILD;
82
83 function fromNode
84 input InstNode node;
85 input Type ty;
86 input list<Subscript> subs = {};
87 input Origin origin = Origin.CREF;
88 output ComponentRef cref = CREF(node, subs, ty, origin, EMPTY());
89 end fromNode;
90
91 function fromOwnedNode
92 "For a synthetic node the cref itself owns. A backend `$fDER` node is in no
93 class tree, so a weak handle would have no other owner and the cref would
94 read back whatever was published for the node it was copied from."
95 input InstNode node;
96 input Type ty;
97 output ComponentRef cref = CREF(node, {}, ty, Origin.CREF, EMPTY());
98 end fromOwnedNode;
99
100 function storeNode
101 "What CREF stores for a node. Identity here; see NFComponentRef.rust.mo."
102 input InstNode node;
103 input Boolean update = false "The same node again, not a different one.";
104 output InstNode stored = node;
105 end storeNode;
106
107 function prefixCref
108 input InstNode node;
109 input Type ty;
110 input list<Subscript> subs;
111 input ComponentRef restCref;
112 output ComponentRef cref = CREF(node, subs, ty, Origin.CREF, restCref);
113 end prefixCref;
114
115 function prefixScope
116 input InstNode node;
117 input Type ty;
118 input list<Subscript> subs;
119 input ComponentRef restCref;
120 output ComponentRef cref = CREF(node, subs, ty, Origin.SCOPE, restCref);
121 end prefixScope;
122
123 function fromAbsyn
124 input InstNode node;
125 input list<Absyn.Subscript> subs;
126 input ComponentRef restCref = EMPTY();
127 input Boolean isIterator = false;
128 output ComponentRef cref;
129 protected
130 list<Subscript> sl;
131 algorithm
132
4/4
✓ Branch 0 taken 307936 times.
✓ Branch 1 taken 1765544 times.
✓ Branch 2 taken 307936 times.
✓ Branch 3 taken 1765544 times.
2073480 sl := list(Subscript.RAW_SUBSCRIPT(s) for s in subs);
133
2/2
✓ Branch 0 taken 1748150 times.
✓ Branch 1 taken 17394 times.
3513694 cref := CREF(node, sl, Type.UNKNOWN(), if isIterator then Origin.ITERATOR else Origin.CREF, restCref);
134 end fromAbsyn;
135
136 function fromAbsynCref
137 input Absyn.ComponentRef acref;
138 input ComponentRef restCref = EMPTY();
139 output ComponentRef cref;
140 algorithm
141 cref := match acref
142 case Absyn.ComponentRef.CREF_IDENT()
143 58 then fromAbsyn(InstNode.NAME_NODE(acref.name), acref.subscripts, restCref);
144
145 case Absyn.ComponentRef.CREF_QUAL()
146 ✗ then fromAbsynCref(acref.componentRef,
147 fromAbsyn(InstNode.NAME_NODE(acref.name), acref.subscripts, restCref));
148
149 case Absyn.ComponentRef.CREF_FULLYQUALIFIED()
150 ✗ then fromAbsynCref(acref.componentRef);
151
152 case Absyn.ComponentRef.WILD() then WILD();
153 case Absyn.ComponentRef.ALLWILD() then WILD();
154 end match;
155 end fromAbsynCref;
156
157 function fromBuiltin
158 input InstNode node;
159 input Type ty;
160 output ComponentRef cref = CREF(node, {}, ty, Origin.SCOPE, EMPTY());
161 end fromBuiltin;
162
163 function makeIterator
164 input InstNode node;
165 input Type ty = InstNode.getType(node);
166 output ComponentRef cref = CREF(node, {}, ty, Origin.ITERATOR, EMPTY());
167 end makeIterator;
168
169 function isWild
170 input ComponentRef cref;
171 output Boolean isWild;
172 algorithm
173 isWild := match cref
174 case WILD() then true;
175 else false;
176 end match;
177 end isWild;
178
179 function isEmpty
180 input ComponentRef cref;
181 output Boolean isEmpty;
182 algorithm
183 isEmpty := match cref
184 case EMPTY() then true;
185 else false;
186 end match;
187 end isEmpty;
188
189 function isSimple
190 input ComponentRef cref;
191 output Boolean isSimple;
192 algorithm
193 isSimple := match cref
194 case CREF(restCref = EMPTY()) then true;
195 else false;
196 end match;
197 end isSimple;
198
199 function isQualified
200 input ComponentRef cref;
201 output Boolean qualified;
202 algorithm
203 qualified := match cref
204 case CREF(restCref = CREF()) then true;
205 else false;
206 end match;
207 end isQualified;
208
209 function isTopLevel
210 input ComponentRef cref;
211 output Boolean b;
212 protected
213 function isTopLevelRecord
214 input ComponentRef cref;
215 output Boolean b;
216 algorithm
217 b := match cref
218
4/4
✓ Branch 1 taken 340 times.
✓ Branch 2 taken 10414 times.
✓ Branch 4 taken 187 times.
✓ Branch 5 taken 153 times.
10754 case CREF() then Type.isRecord(cref.ty) and isTopLevelRecord(cref.restCref);
219 case EMPTY() then true;
220 else false;
221 end match;
222 end isTopLevelRecord;
223 algorithm
224 b := match cref
225 case CREF(restCref = EMPTY()) then true;
226 10565 case CREF() then isTopLevelRecord(cref.restCref);
227 else false;
228 end match;
229 end isTopLevel;
230
231 function isFlow
232 input ComponentRef cref;
233 output Boolean isFlow;
234 protected
235 Component comp;
236 algorithm
237 isFlow := match cref
238 case CREF()
239 guard InstNode.isComponent(node(cref))
240 78 then Component.isFlow(InstNode.component(InstNode.resolveInner(node(cref))));
241
242 else false;
243 end match;
244 end isFlow;
245
246 function isCref
247 input ComponentRef cref;
248 output Boolean isCref;
249 algorithm
250 isCref := match cref
251 case CREF() then true;
252 else false;
253 end match;
254 end isCref;
255
256 function isIterator
257 input ComponentRef cref;
258 output Boolean isIterator;
259 algorithm
260 isIterator := match cref
261 case CREF(origin = Origin.ITERATOR) then true;
262 else false;
263 end match;
264 end isIterator;
265
266 function isInput
267 input ComponentRef cref;
268 output Boolean res;
269 algorithm
270 res := match cref
271 305 case CREF() then InstNode.isInput(node(cref));
272 else false;
273 end match;
274 end isInput;
275
276 function isOutput
277 input ComponentRef cref;
278 output Boolean res;
279 algorithm
280 res := match cref
281 7 case CREF() then InstNode.isOutput(node(cref));
282 else false;
283 end match;
284 end isOutput;
285
286 function isComponent
287 "Returns true if the first part of the cref refers to a component."
288 input ComponentRef cref;
289 output Boolean res;
290 algorithm
291 res := match cref
292 282 case CREF() then InstNode.isComponent(node(cref));
293 else false;
294 end match;
295 end isComponent;
296
297 function stripClassScope
298 "Removes the class parts of the scope from a cref, e.g. M.cell.obj => cell.obj."
299 input ComponentRef cref;
300 output ComponentRef outCref;
301 algorithm
302 outCref := match cref
303 case CREF() guard InstNode.isClass(node(cref)) then EMPTY();
304 case CREF()
305 algorithm
306 567 cref.restCref := stripClassScope(cref.restCref);
307 then
308 cref;
309 else cref;
310 end match;
311 end stripClassScope;
312
313 function isNameNode
314 input ComponentRef cref;
315 output Boolean res;
316 algorithm
317 res := match cref
318 112580 case CREF() then InstNode.isName(node(cref));
319 else false;
320 end match;
321 end isNameNode;
322
323 function isEqualRecordChild
324 "R.x and R can be considered equal in certain cases if x is the only attribute of R"
325 input ComponentRef child;
326 input ComponentRef recd;
327 output Boolean b = ComponentRef.size(child, true) == ComponentRef.size(recd, true);
328 algorithm
329
2/2
✓ Branch 0 taken 8129 times.
✓ Branch 1 taken 13774 times.
21903 if b then
330 13774 b := isRecordChild(child, recd);
331 end if;
332 end isEqualRecordChild;
333
334 function isRecordChild
335 input ComponentRef child;
336 input ComponentRef recd;
337 output Boolean b;
338 algorithm
339 b := match recd
340
2/4
✓ Branch 1 taken 30563 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 30563 times.
30563 case CREF() then ComponentRef.isEqual(child, recd) or isRecordChild(child, recd.restCref);
341 else false;
342 end match;
343 end isRecordChild;
344
345 function node
346 input ComponentRef cref;
347 output InstNode node;
348 algorithm
349
2/2
✓ Branch 0 taken 233 times.
✓ Branch 1 taken 50476013 times.
50476246 CREF(node = node) := cref;
350 end node;
351
352 function nodeName
353 "The name of the node this cref names, without necessarily resolving the
354 node. Identical to `InstNode.name(node(cref))` here; in the Rust port the
355 name is cached in the handle, which is what keeps `isEqual` and
356 `hashContinue` off the weak-read path."
357 input ComponentRef cref;
358 output String name = InstNode.name(node(cref));
359 end nodeName;
360
361 function nodes
362 input ComponentRef cref;
363 input list<InstNode> accum = {};
364 output list<InstNode> nodes;
365 algorithm
366 nodes := match cref
367 11988 case CREF() then nodes(cref.restCref, node(cref) :: accum);
368 else accum;
369 end match;
370 end nodes;
371
372 function nodesIncludingSplitSubs
373 input ComponentRef cref;
374 input list<InstNode> accum = {};
375 output list<InstNode> nodes = accum;
376 protected
377 NFInstNode.ScopeRef node;
378 algorithm
379 nodes := match cref
380 case CREF()
381 algorithm
382
2/2
✓ Branch 0 taken 550 times.
✓ Branch 1 taken 5663 times.
6213 for s in cref.subscripts loop
383
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 548 times.
550 if Subscript.isSplitIndex(s) then
384
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 Subscript.SPLIT_INDEX(node = node) := s;
385 2 nodes := InstNode.borrow(node) :: nodes;
386 end if;
387 end for;
388 11326 then
389 nodesIncludingSplitSubs(cref.restCref, node(cref) :: nodes);
390
391 else nodes;
392 end match;
393 end nodesIncludingSplitSubs;
394
395 function containsNode
396 input ComponentRef cref;
397 input InstNode node;
398 output Boolean res;
399 algorithm
400 res := match cref
401 case CREF()
402
4/4
✓ Branch 2 taken 215438 times.
✓ Branch 3 taken 20794 times.
✓ Branch 5 taken 2340 times.
✓ Branch 6 taken 213098 times.
236232 then InstNode.refEqual(node(cref), node) or containsNode(cref.restCref, node);
403 else false;
404 end match;
405 end containsNode;
406
407 function nodeType
408 input ComponentRef cref;
409 output Type ty;
410 algorithm
411
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7814 times.
7814 CREF(ty = ty) := cref;
412 end nodeType;
413
414 function setNodeType
415 input Type ty;
416 input output ComponentRef cref;
417 algorithm
418 () := match cref
419 case CREF()
420 algorithm
421 1 cref.ty := ty;
422 then
423 ();
424
425 else ();
426 end match;
427 end setNodeType;
428
429 function updateNodeType
430 input output ComponentRef cref;
431 algorithm
432 () := match cref
433 case CREF() guard InstNode.isComponent(node(cref))
434 algorithm
435 20 cref.ty := InstNode.getType(node(cref));
436 then
437 ();
438
439 else ();
440 end match;
441 end updateNodeType;
442
443 function scalarType
444 input ComponentRef cref;
445 output Type ty;
446 algorithm
447
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5399 times.
5399 CREF(ty = ty) := cref;
448 5399 ty := Type.arrayElementType(ty);
449 end scalarType;
450
451 function applyToType
452 input output ComponentRef cref;
453 input typeFunc func;
454 partial function typeFunc
455 input output Type ty;
456 end typeFunc;
457 algorithm
458 cref := match cref
459 case CREF() algorithm
460
1/2
✓ Branch 0 taken 256317 times.
✗ Branch 1 not taken.
256317 cref.ty := func(cref.ty);
461 256317 cref.restCref := applyToType(cref.restCref, func);
462 then cref;
463 else cref;
464 end match;
465 end applyToType;
466
467 function firstName
468 input ComponentRef cref;
469 input Boolean baseModelica = false;
470 output String name;
471 algorithm
472 name := match cref
473 958546 case CREF() then nodeName(cref);
474
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 case WILD() then if baseModelica then "" else "_";
475 else "";
476 end match;
477 end firstName;
478
479 function first
480 input output ComponentRef cref;
481 algorithm
482 () := match cref
483 case CREF()
484 algorithm
485 22994 cref.restCref := EMPTY();
486 then
487 ();
488
489 else ();
490 end match;
491 end first;
492
493 function rest
494 input ComponentRef cref;
495 output ComponentRef restCref;
496 algorithm
497
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3270530 times.
3270530 CREF(restCref = restCref) := cref;
498 end rest;
499
500 function last
501 input ComponentRef cref;
502 output ComponentRef lastCref;
503 algorithm
504 lastCref := match cref
505 203659 case CREF(restCref = CREF()) then last(cref.restCref);
506 else cref;
507 end match;
508 end last;
509
510 function firstNonScope
511 input ComponentRef cref;
512 output ComponentRef first;
513 protected
514 ComponentRef rest_cr = rest(cref);
515 algorithm
516 first := match rest_cr
517 case CREF(origin = Origin.SCOPE) then cref;
518 case EMPTY() then cref;
519 61331 else firstNonScope(rest_cr);
520 end match;
521 end firstNonScope;
522
523 function append
524 input output ComponentRef cref;
525 input ComponentRef restCref;
526 algorithm
527 cref := match cref
528 case CREF()
529 algorithm
530 883186 cref.restCref := append(cref.restCref, restCref);
531 then
532 cref;
533
534 case EMPTY() then restCref;
535 end match;
536 end append;
537
538 function appendScope
539 "Appends the instance scope of the given node to a component reference, as
540 defined by InstNode.scopeList."
541 input InstNode scope;
542 input output ComponentRef cref;
543 input Boolean includeRoot = false "Whether to include the root class name or not.";
544 protected
545 ComponentRef prefix;
546 algorithm
547 1132014 prefix := fromNodeList(InstNode.scopeList(scope, includeRoot));
548
549
2/2
✓ Branch 1 taken 698018 times.
✓ Branch 2 taken 433996 times.
1132014 if not ComponentRef.isEmpty(prefix) then
550 433996 cref := append(cref, prefix);
551 433996 cref := removeOuterCrefPrefix(cref);
552 end if;
553 end appendScope;
554
555 function prepend
556 input ComponentRef restCref;
557 input output ComponentRef cref;
558 algorithm
559 cref := match cref
560 case CREF()
561 algorithm
562 23816 cref.restCref := restCref;
563 then
564 cref;
565
566 case EMPTY() then restCref;
567 end match;
568 end prepend;
569
570 function getComponentType
571 "Returns the type of the component the given cref refers to, without taking
572 subscripts into account."
573 input ComponentRef cref;
574 output Type ty;
575 algorithm
576 ty := match cref
577 34003 case CREF() then cref.ty;
578 else Type.UNKNOWN();
579 end match;
580 end getComponentType;
581
582 function getSubscriptedType
583 "Returns the type of a cref, with the subscripts taken into account."
584 input ComponentRef cref;
585 input Boolean includeScope = false;
586 output Type ty;
587 algorithm
588 ty := match cref
589 case CREF()
590 2894987 then getSubscriptedType2(cref.restCref, Type.subscript(cref.ty, cref.subscripts), includeScope);
591 else Type.UNKNOWN();
592 end match;
593 end getSubscriptedType;
594
595 function getSubscriptedType2
596 input ComponentRef restCref;
597 input Type accumTy;
598 input Boolean includeScope;
599 output Type ty;
600 algorithm
601 ty := match restCref
602 case CREF()
603 guard restCref.origin == Origin.CREF or includeScope
604 algorithm
605 1546268 ty := Type.liftArrayLeftList(accumTy,
606 Type.arrayDims(Type.subscript(restCref.ty, restCref.subscripts)));
607 1546268 then
608 getSubscriptedType2(restCref.restCref, ty, includeScope);
609
610 else accumTy;
611 end match;
612 end getSubscriptedType2;
613
614 function lookupVarAttr
615 input ComponentRef cref;
616 input String attr_name;
617 output Option<Expression> attrValue;
618 algorithm
619 attrValue := match cref
620 case CREF()
621 then match node(cref)
622 local PointerWeak<Variable> v;
623 case InstNode.VAR_NODE(varPointer = v)
624 1410 then Binding.typedExp(Variable.lookupTypeAttribute(attr_name, Pointer.access(PointerWeak.upgrade(v))));
625 else NONE();
626 end match;
627 else NONE();
628 end match;
629 end lookupVarAttr;
630
631 function nodeVariability
632 "Returns the variability of the component node the cref refers to."
633 input ComponentRef cref;
634 output Variability var;
635 algorithm
636 var := match cref
637 case CREF()
638 then match node(cref)
639 local
640 InstNode n;
641 PointerWeak<Variable> v;
642 9575737 case n as InstNode.COMPONENT_NODE() then Component.variability(InstNode.component(n));
643 case InstNode.CLASS_NODE() then Variability.CONSTANT;
644 5791 case InstNode.VAR_NODE(varPointer = v) then Variable.variability(Pointer.access(PointerWeak.upgrade(v)));
645 else Variability.CONTINUOUS;
646 end match;
647 else Variability.CONTINUOUS;
648 end match;
649 end nodeVariability;
650
651 function isResizable
652 "Returns true if the cref refers to a resizable component (frontend) or variable (backend)."
653 input ComponentRef cref;
654 output Boolean b;
655 algorithm
656 b := match cref
657 case CREF()
658 then match node(cref)
659 local
660 InstNode n;
661 PointerWeak<Variable> v;
662
663 // frontend check
664 48793 case n as InstNode.COMPONENT_NODE() then Component.isResizable(InstNode.component(n));
665
666 // backend check
667 case InstNode.VAR_NODE(varPointer = v) then match Pointer.access(PointerWeak.upgrade(v))
668 case Variable.VARIABLE(backendinfo = BackendInfo.BACKEND_INFO(annotations = Annotations.ANNOTATIONS(resizable = b))) then b;
669 else false;
670 end match;
671
672 // default
673 else false;
674 end match;
675 else false;
676 end match;
677 end isResizable;
678
679 function subscriptsVariability
680 input ComponentRef cref;
681 input output Variability var = Variability.CONSTANT;
682 algorithm
683 () := match cref
684 case CREF(origin = Origin.CREF)
685 algorithm
686
2/2
✓ Branch 0 taken 4425318 times.
✓ Branch 1 taken 6115598 times.
10540916 for sub in cref.subscripts loop
687 4425318 var := Prefixes.variabilityMax(var, Subscript.variability(sub));
688 end for;
689 then
690 ();
691
692 else ();
693 end match;
694 end subscriptsVariability;
695
696 function variability
697 "Returns the variability of the cref, with the variability of the subscripts
698 taken into account."
699 input ComponentRef cref;
700 output Variability var = Prefixes.variabilityMax(nodeVariability(cref),
701 subscriptsVariability(cref));
702 end variability;
703
704 function purity
705 input ComponentRef cref;
706 output Purity pur;
707 protected
708 function sub_purity
709 input Subscript sub;
710 input output Purity pur;
711 algorithm
712 295481 pur := Prefixes.purityMin(pur, Subscript.purity(sub));
713 end sub_purity;
714 algorithm
715 pur := match cref
716 case CREF(origin = Origin.ITERATOR) then Purity.IMPURE;
717 1050995 case CREF() then foldSubscripts(cref, sub_purity, Purity.PURE);
718 else Purity.IMPURE;
719 end match;
720 end purity;
721
722 function visibility
723 input ComponentRef cref;
724 output Visibility vis;
725 algorithm
726 vis := match cref
727 ✗ case CREF() then
728 if InstNode.isProtected(node(cref)) then
729 Visibility.PROTECTED else visibility(cref.restCref);
730
731 else Visibility.PUBLIC;
732 end match;
733 end visibility;
734
735 function rename
736 input String name;
737 input output ComponentRef cref;
738 algorithm
739 cref := match cref
740 case CREF()
741 algorithm
742 311 cref.node := InstNode.rename(name, node(cref));
743 then
744 cref;
745
746 else cref;
747 end match;
748 end rename;
749
750 function addSubscript
751 input Subscript subscript;
752 input output ComponentRef cref;
753 algorithm
754 () := match cref
755 case CREF()
756 algorithm
757 ✗ cref.subscripts := listAppend(cref.subscripts, {subscript});
758 then
759 ();
760 end match;
761 end addSubscript;
762
763 function mergeSubscripts
764 "merges subscripts to a cref while respecting the dimension
765 sizes of the types and previous subscripts.
766 if backend = true it discards one subscript for scalars if
767 it is exactly INTEGER(1). (needed for slicing)"
768 input list<Subscript> subscripts;
769 input output ComponentRef cref;
770 input Boolean applyToScope = false;
771 input Boolean backend = false;
772 input Boolean reverse = false;
773 protected
774 ComponentRef old_cref = cref;
775 list<Subscript> new_subscripts;
776 algorithm
777 111519 (new_subscripts, cref) := mergeSubscripts2(subscripts, cref, applyToScope, backend, reverse);
778
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 111519 times.
111519 if not listEmpty(new_subscripts) then
779 ✗ Error.terminate(getInstanceName() + " failed because the subscripts "
780 + List.toString(subscripts, Subscript.toString) + " could not be fully merged onto "
781 + ComponentRef.toString(old_cref) + ".\nResult: " + ComponentRef.toString(cref)
782 + " with leftover: " + List.toString(new_subscripts, Subscript.toString) + ".", sourceInfo());
783 ✗ fail();
784 end if;
785 end mergeSubscripts;
786
787 function mergeSubscripts2
788 input output list<Subscript> subscripts;
789 input output ComponentRef cref;
790 input Boolean applyToScope;
791 input Boolean backend;
792 input Boolean reverse;
793 algorithm
794 (subscripts, cref) := match cref
795 local
796 ComponentRef rest_cref = EMPTY();
797 list<Subscript> cref_subs;
798
799 case CREF(subscripts = cref_subs)
800 guard applyToScope or cref.origin == Origin.CREF
801 algorithm
802
2/2
✓ Branch 0 taken 202607 times.
✓ Branch 1 taken 671 times.
203278 if not reverse then
803 202607 (subscripts, rest_cref) := mergeSubscripts2(subscripts, cref.restCref, applyToScope, backend, reverse);
804 end if;
805
806
2/2
✓ Branch 0 taken 185084 times.
✓ Branch 1 taken 18194 times.
203278 if not listEmpty(subscripts) then
807 185084 (cref_subs, subscripts) :=
808 Subscript.mergeList(subscripts, cref_subs, Type.dimensionCount(cref.ty), backend);
809 end if;
810
811
2/2
✓ Branch 0 taken 671 times.
✓ Branch 1 taken 202607 times.
203278 if reverse then
812 671 cref_subs := listReverse(cref_subs);
813 671 (subscripts, rest_cref) := mergeSubscripts2(subscripts, cref.restCref, applyToScope, backend, reverse);
814 end if;
815 203278 then
816 (subscripts, CREF(cref.node, cref_subs, cref.ty, cref.origin, rest_cref));
817
818 111519 else (subscripts, cref);
819 end match;
820 end mergeSubscripts2;
821
822 function mergeSubscriptsMapped
823 "merges subscripts to a cref while respecting a map that defines the type to subscript mapping.
824 To be used in the backend when the subscripts have to be added to a very specific dimension space
825 Note: due to technical reasons the mapping is done in two steps"
826 input output ComponentRef cref;
827 input UnorderedMap<list<Dimension>, list<ComponentRef>> dims_map;
828 input UnorderedMap<ComponentRef, Subscript> iter_map;
829 protected
830 function checkLocalDimensions
831 "checks if the current dimension configuration results in new subscripts for the cref"
832 input output ComponentRef cref;
833 input list<Dimension> dims;
834 input UnorderedMap<list<Dimension>, list<ComponentRef>> dims_map;
835 input UnorderedMap<ComponentRef, Subscript> iter_map;
836 protected
837 Option<list<ComponentRef>> iter_crefs;
838 list<Subscript> new_subs;
839 algorithm
840 48 iter_crefs := UnorderedMap.get(dims, dims_map);
841
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
✓ Branch 2 taken 44 times.
✓ Branch 3 taken 4 times.
48 if isSome(iter_crefs) then
842 // dimension configuration was found, map to subscripts and apply in reverse
843
4/4
✓ Branch 1 taken 51 times.
✓ Branch 2 taken 44 times.
✓ Branch 3 taken 51 times.
✓ Branch 4 taken 44 times.
95 new_subs := list(UnorderedMap.getSafe(iter_name, iter_map, sourceInfo()) for iter_name in Util.getOption(iter_crefs));
844 44 cref := mergeSubscripts(new_subs, cref, true, true, true);
845 end if;
846 end checkLocalDimensions;
847 algorithm
848 cref := match cref
849 local
850 list<Dimension> dims;
851 ComponentRef new_cref;
852 Type ty = getSubscriptedType(cref);
853 Integer num_local_dims;
854
855 // local array type -> try to find the current dimension configuration in the map and add subscripts
856 case CREF() guard(Type.isArray(ty)) algorithm
857 // get dimensions and check in map
858 61 dims := Type.arrayDims(ty);
859 61 num_local_dims := listLength(Type.arrayDims(cref.ty));
860
861 // check if the dimension configuration exists in the map
862 // and iteratively remove one dimension to check all local configurations
863 new_cref := cref;
864
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 61 times.
109 while num_local_dims > 0 loop
865 48 new_cref := checkLocalDimensions(new_cref, dims, dims_map, iter_map);
866 48 dims := List.stripLast(dims);
867 48 num_local_dims := num_local_dims - 1;
868 end while;
869
870 // apply to restCref afterwards such that the outermost dimensions are handled first
871 // this is important because the full dimension list is considered when checking in the map
872 new_cref := match new_cref
873 case CREF() algorithm
874 61 new_cref.restCref := mergeSubscriptsMapped(new_cref.restCref, dims_map, iter_map);
875 then new_cref;
876 else new_cref;
877 end match;
878 then new_cref;
879
880 // local scalar type -> only apply to
881 case CREF() algorithm
882 // apply to restCref
883 43 cref.restCref := mergeSubscriptsMapped(cref.restCref, dims_map, iter_map);
884 then cref;
885
886 else cref;
887 end match;
888 end mergeSubscriptsMapped;
889
890 function hasSubscripts
891 input ComponentRef cref;
892 output Boolean hasSubscripts;
893 algorithm
894 hasSubscripts := match cref
895 case CREF()
896
4/4
✓ Branch 0 taken 132531 times.
✓ Branch 1 taken 5112 times.
✓ Branch 3 taken 826 times.
✓ Branch 4 taken 131705 times.
137643 then not listEmpty(cref.subscripts) or hasSubscripts(cref.restCref);
897
898 else false;
899 end match;
900 end hasSubscripts;
901
902 function hasNonModelSubscripts
903 input ComponentRef cref;
904 output Boolean hasSubscripts;
905 algorithm
906 hasSubscripts := match cref
907 case CREF() guard(InstNode.isModel(node(cref)))
908 ✗ then hasNonModelSubscripts(cref.restCref);
909 case CREF()
910 ✗ then not listEmpty(cref.subscripts) or hasNonModelSubscripts(cref.restCref);
911 else false;
912 end match;
913 end hasNonModelSubscripts;
914
915 function hasSplitSubscripts
916 input ComponentRef cref;
917 output Boolean res;
918 algorithm
919 res := match cref
920 case CREF(origin = Origin.CREF)
921
4/4
✓ Branch 1 taken 538602 times.
✓ Branch 2 taken 3073 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 538597 times.
541675 then List.any(cref.subscripts, Subscript.isSplitIndex) or
922 hasSplitSubscripts(cref.restCref);
923
924 else false;
925 end match;
926 end hasSplitSubscripts;
927
928 function expandSplitSubscripts
929 input output ComponentRef cref;
930 algorithm
931 () := match cref
932 case CREF(origin = Origin.CREF)
933 algorithm
934 219300 cref.subscripts := Subscript.expandSplitIndices(cref.subscripts, {});
935 219300 cref.restCref := expandSplitSubscripts(cref.restCref);
936 then
937 ();
938
939 else ();
940 end match;
941 end expandSplitSubscripts;
942
943 function getSubscripts
944 input ComponentRef cref;
945 output list<Subscript> subscripts;
946 algorithm
947 subscripts := match cref
948 1115555 case CREF() then cref.subscripts;
949 else {};
950 end match;
951 end getSubscripts;
952
953 function outermostIntegerSubscript
954 "Returns the integer value of the outermost (root-side) INDEX(INTEGER(n))
955 subscript in the cref chain. Returns 0 if none."
956 input ComponentRef cref;
957 output Integer value = 0;
958 algorithm
959 () := match cref
960 case CREF()
961 algorithm
962 1985 value := outermostIntegerSubscript(cref.restCref);
963
2/2
✓ Branch 0 taken 1745 times.
✓ Branch 1 taken 240 times.
1985 if value == 0 then
964
2/2
✓ Branch 0 taken 775 times.
✓ Branch 1 taken 970 times.
1745 for s in cref.subscripts loop
965 () := match s
966 local Integer v;
967 case Subscript.INDEX(index = Expression.INTEGER(v))
968 algorithm value := v;
969 then ();
970 else ();
971 end match;
972
1/2
✓ Branch 0 taken 775 times.
✗ Branch 1 not taken.
775 if value <> 0 then return; end if;
973 end for;
974 end if;
975 then ();
976 else ();
977 end match;
978 end outermostIntegerSubscript;
979
980 function setSubscripts
981 "Sets the subscripts of the first part of a cref."
982 input list<Subscript> subscripts;
983 input output ComponentRef cref;
984 algorithm
985 () := match cref
986 case CREF()
987 algorithm
988 350289 cref.subscripts := subscripts;
989 then
990 ();
991 end match;
992 end setSubscripts;
993
994 function setSubscriptsList
995 "Sets the subscripts of each part of a cref to the corresponding list of subscripts."
996 input list<list<Subscript>> subscripts;
997 input output ComponentRef cref;
998 algorithm
999 cref := match (subscripts, cref)
1000 local
1001 list<Subscript> subs;
1002 list<list<Subscript>> rest_subs;
1003 ComponentRef rest_cref;
1004
1005 case (subs :: rest_subs, CREF())
1006 algorithm
1007 116641 rest_cref := setSubscriptsList(rest_subs, cref.restCref);
1008 116641 then
1009 CREF(cref.node, subs, cref.ty, cref.origin, rest_cref);
1010
1011 case ({}, _) then cref;
1012 end match;
1013 end setSubscriptsList;
1014
1015 function copySubscripts
1016 "merges the subscritps of origin to the target.
1017 Note: does not remove subscripts already on target!"
1018 input ComponentRef origin;
1019 input output ComponentRef target;
1020 protected
1021 list<Subscript> subs = ComponentRef.subscriptsAllFlat(origin);
1022 algorithm
1023
2/2
✓ Branch 0 taken 3230 times.
✓ Branch 1 taken 1989 times.
5219 if not listEmpty(subs) then
1024 1989 target := ComponentRef.mergeSubscripts(subs, target, true, true);
1025 end if;
1026 end copySubscripts;
1027
1028 function subscriptsAllWithWhole
1029 "Returns all subscripts of a cref in reverse order while not omitting whole dimensions.
1030 Ex: a[1, 2].b[4].c[6, 3] => {{6,3}, {4}, {1,2}}"
1031 input ComponentRef cref;
1032 input list<list<Subscript>> accumSubs = {};
1033 output list<list<Subscript>> subscripts;
1034 algorithm
1035 subscripts := match cref
1036 local
1037 list<Subscript> subs;
1038
1039 case CREF(subscripts = {}) algorithm
1040 // one slice per array dimension of this node, so that the subscripts
1041 // stay aligned with the dimensions
1042 subs := {};
1043
2/2
✓ Branch 2 taken 166 times.
✓ Branch 3 taken 2144 times.
2310 for dim in listReverse(Type.arrayDims(cref.ty)) loop
1044 166 subs := Subscript.SLICE(Expression.makeRange(Expression.INTEGER(1), NONE(), Dimension.sizeExp(dim))) :: subs;
1045 end for;
1046 2144 then subscriptsAllWithWhole(cref.restCref, subs :: accumSubs);
1047
1048 1428 case CREF() then subscriptsAllWithWhole(cref.restCref, cref.subscripts :: accumSubs);
1049
1050 else accumSubs;
1051 end match;
1052 end subscriptsAllWithWhole;
1053
1054 function subscriptsAllWithWholeFlat
1055 "Returns all subscripts of a cref as a flat list in the correct order while not omitting whole dimensions.
1056 Ex: a[1, 2].b[4].c[6, 3] => {1, 2, 4, 6, 3}"
1057 input ComponentRef cref;
1058 output list<Subscript> subscripts = List.flatten(subscriptsAllWithWhole(cref));
1059 end subscriptsAllWithWholeFlat;
1060
1061 function subscriptsAll
1062 "Returns all subscripts of a cref.
1063 Ex: a[1, 2].b[4].c[6, 3] => {{1,2}, {4}, {6,3}}"
1064 input ComponentRef cref;
1065 output list<list<Subscript>> subscripts = listReverseInPlace(subscriptsAllReverse(cref));
1066 end subscriptsAll;
1067
1068 function subscriptsAllReverse
1069 "Returns all subscripts of a cref in reverse order.
1070 Ex: a[1, 2].b[4].c[6, 3] => {{6,3}, {4}, {1,2}}"
1071 input ComponentRef cref;
1072 input list<list<Subscript>> accumSubs = {};
1073 output list<list<Subscript>> subscripts;
1074 algorithm
1075 subscripts := match cref
1076 407240 case CREF() then subscriptsAllReverse(cref.restCref, cref.subscripts :: accumSubs);
1077 else accumSubs;
1078 end match;
1079 end subscriptsAllReverse;
1080
1081 function subscriptsAllFlat
1082 "Returns all subscripts of a cref as a flat list in the correct order.
1083 Ex: a[1, 2].b[4].c[6, 3] => {1, 2, 4, 6, 3}"
1084 input ComponentRef cref;
1085 output list<Subscript> subscripts = List.flattenReverse(subscriptsAll(cref));
1086 end subscriptsAllFlat;
1087
1088 function subscriptsExceptModel
1089 "Returns all subscripts of a cref leaving out model subs.
1090 Ex: a[1, 2].b[4].c[6, 3] => {{1,2}, {4}, {6,3}}"
1091 input ComponentRef cref;
1092 input list<list<Subscript>> accumSubs = {};
1093 output list<list<Subscript>> subscripts;
1094 algorithm
1095 subscripts := match cref
1096 ✗ case CREF() guard(InstNode.isModel(node(cref))) then subscriptsExceptModel(cref.restCref, {} :: accumSubs);
1097 ✗ case CREF() then subscriptsExceptModel(cref.restCref, cref.subscripts :: accumSubs);
1098 else accumSubs;
1099 end match;
1100 end subscriptsExceptModel;
1101
1102 function subscriptsN
1103 "Returns the subscripts of the N first parts of a cref in reverse order."
1104 input ComponentRef cref;
1105 input Integer n;
1106 output list<list<Subscript>> subscripts = {};
1107 protected
1108 list<Subscript> subs;
1109 ComponentRef rest = cref;
1110 algorithm
1111 ✗ for i in 1:n loop
1112 ✗ if isEmpty(rest) then
1113 break;
1114 end if;
1115
1116 ✗ CREF(subscripts = subs, restCref = rest) := rest;
1117 subscripts := subs :: subscripts;
1118 end for;
1119 end subscriptsN;
1120
1121 function transferSubscripts
1122 "Copies subscripts from one cref to another, overwriting any subscripts on
1123 the destination cref."
1124 input ComponentRef srcCref;
1125 input ComponentRef dstCref;
1126 output ComponentRef cref;
1127 protected
1128 list<Subscript> subs;
1129 algorithm
1130 cref := match (srcCref, dstCref)
1131 case (EMPTY(), _) then dstCref;
1132 case (_, EMPTY()) then dstCref;
1133 case (_, WILD()) then dstCref;
1134 case (_, CREF(origin = Origin.ITERATOR)) then dstCref;
1135
1136 case (CREF(), CREF(origin = Origin.CREF))
1137 algorithm
1138 487774 dstCref.restCref := transferSubscripts(srcCref, dstCref.restCref);
1139 then
1140 dstCref;
1141
1142 case (CREF(), CREF()) guard InstNode.refEqual(node(srcCref), node(dstCref))
1143 algorithm
1144 684420 cref := transferSubscripts(srcCref.restCref, dstCref.restCref);
1145 // Don't remove subscripts unless there's something to replace them with.
1146 // This avoids loosing subscripts when flattening an already flattened cref with
1147 // a prefix without subscripts, which can happen in the non-scalarized path.
1148
2/2
✓ Branch 0 taken 662425 times.
✓ Branch 1 taken 21995 times.
684420 subs := if listEmpty(srcCref.subscripts) then dstCref.subscripts else srcCref.subscripts;
1149 684420 then
1150 CREF(dstCref.node, subs, dstCref.ty, dstCref.origin, cref);
1151
1152 case (CREF(), CREF())
1153 93798 then transferSubscripts(srcCref.restCref, dstCref);
1154
1155 else
1156 algorithm
1157 ✗ Error.terminate(getInstanceName() + " failed", sourceInfo());
1158 ✗ then
1159 fail();
1160 end match;
1161 end transferSubscripts;
1162
1163 function applySubscripts
1164 input ComponentRef cref;
1165 input FuncT func;
1166 input Boolean applyToScope = false;
1167
1168 partial function FuncT
1169 input Subscript subscript;
1170 end FuncT;
1171 algorithm
1172 () := match cref
1173 case CREF() guard applyToScope or cref.origin == Origin.CREF
1174 algorithm
1175
2/2
✓ Branch 0 taken 1588 times.
✓ Branch 1 taken 53307 times.
54895 for sub in cref.subscripts loop
1176
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1588 times.
1588 func(sub);
1177 end for;
1178
1179 53307 applySubscripts(cref.restCref, func, applyToScope);
1180 then
1181 ();
1182
1183 else ();
1184 end match;
1185 end applySubscripts;
1186
1187 function foldSubscripts<ArgT>
1188 input ComponentRef cref;
1189 input FuncT func;
1190 input output ArgT arg;
1191 input Boolean applyToScope = false;
1192
1193 partial function FuncT
1194 input Subscript subscript;
1195 input output ArgT arg;
1196 end FuncT;
1197 algorithm
1198 arg := match cref
1199 case CREF() guard applyToScope or cref.origin == Origin.CREF
1200 algorithm
1201
2/2
✓ Branch 0 taken 295481 times.
✓ Branch 1 taken 1366258 times.
1661739 for sub in cref.subscripts loop
1202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 295481 times.
295481 arg := func(sub, arg);
1203 end for;
1204 1366258 then
1205 foldSubscripts(cref.restCref, func, arg, applyToScope);
1206
1207 else arg;
1208 end match;
1209 end foldSubscripts;
1210
1211 function mapSubscripts
1212 input output ComponentRef cref;
1213 input FuncT func;
1214 input Boolean applyToScope = false;
1215
1216 partial function FuncT
1217 input output Subscript subscript;
1218 end FuncT;
1219 algorithm
1220 cref := match cref
1221 case CREF() guard applyToScope or cref.origin == Origin.CREF
1222 algorithm
1223
2/2
✓ Branch 0 taken 25749 times.
✓ Branch 1 taken 133832 times.
159581 if not listEmpty(cref.subscripts) then
1224
5/6
✓ Branch 0 taken 28841 times.
✓ Branch 1 taken 25749 times.
✓ Branch 2 taken 28841 times.
✓ Branch 3 taken 25749 times.
✓ Branch 4 taken 28841 times.
✗ Branch 5 not taken.
80339 cref.subscripts := list(func(s) for s in cref.subscripts);
1225 end if;
1226
1227 159581 cref.restCref := mapSubscripts(cref.restCref, func, applyToScope);
1228 then
1229 cref;
1230
1231 else cref;
1232 end match;
1233 end mapSubscripts;
1234
1235 function fillSubscripts
1236 "Fills in any unsubscripted dimensions in the cref with : subscripts,
1237 appending them at the end to preserve subscript order.
1238 E.g. a[i] for Real[10,2] becomes a[i,:]."
1239 input output ComponentRef cref;
1240 algorithm
1241 () := match cref
1242 local
1243 list<Dimension> dims;
1244 Integer dim_count, sub_count;
1245
1246 case CREF()
1247 algorithm
1248 8953 dims := Type.arrayDims(cref.ty);
1249 8953 dim_count := listLength(dims);
1250 8953 sub_count := listLength(cref.subscripts);
1251
1252
2/2
✓ Branch 0 taken 88 times.
✓ Branch 1 taken 8865 times.
8953 if sub_count < dim_count then
1253 88 cref.subscripts := listAppend(cref.subscripts, List.fill(Subscript.WHOLE(), dim_count - sub_count));
1254 end if;
1255
1256 8953 cref.restCref := fillSubscripts(cref.restCref);
1257 then
1258 ();
1259
1260 else ();
1261 end match;
1262 end fillSubscripts;
1263
1264 function replaceWholeSubscripts
1265 "Replaces any : subscripts with slice subscripts for the corresponding dimension."
1266 input output ComponentRef cref;
1267 algorithm
1268 () := match cref
1269 local
1270 list<Dimension> dims;
1271 list<Subscript> subs;
1272
1273 case CREF()
1274 algorithm
1275
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 126 times.
126 if List.any(cref.subscripts, Subscript.isWhole) then
1276 ✗ dims := Type.arrayDims(cref.ty);
1277 subs := {};
1278
1279 ✗ for s in cref.subscripts loop
1280 ✗ if Subscript.isWhole(s) then
1281 ✗ s := Subscript.fromDimension(listHead(dims));
1282 end if;
1283
1284 subs := s :: subs;
1285 ✗ dims := listRest(dims);
1286 end for;
1287
1288 ✗ cref.subscripts := listReverseInPlace(subs);
1289 end if;
1290
1291 126 cref.restCref := replaceWholeSubscripts(cref.restCref);
1292 then
1293 ();
1294
1295 else ();
1296 end match;
1297 end replaceWholeSubscripts;
1298
1299 function combineSubscripts
1300 "Moves all subscripts to the end of the cref.
1301 Ex: a[1, 2].b[4] => a.b[1, 2, 4]"
1302 input output ComponentRef cref;
1303 protected
1304 list<Subscript> subs;
1305 algorithm
1306 // Fill in : subscripts where needed so the cref is fully subscripted.
1307 58 cref := fillSubscripts(cref);
1308 // Fetch all the subscripts.
1309 58 subs := List.flatten(subscriptsAllReverse(cref));
1310
1311
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 35 times.
58 if listEmpty(subs) then
1312 23 return;
1313 end if;
1314
1315 // Replace the cref's subscripts.
1316 35 cref := setSubscripts(subs, stripSubscriptsAll(cref));
1317 end combineSubscripts;
1318
1319 function compare
1320 input ComponentRef cref1;
1321 input ComponentRef cref2;
1322 output Integer comp;
1323 algorithm
1324 comp := match (cref1, cref2)
1325 case (CREF(), CREF())
1326 algorithm
1327 98099 comp := stringCompare(InstNode.name(node(cref1)), InstNode.name(node(cref2)));
1328
1329
2/2
✓ Branch 0 taken 32412 times.
✓ Branch 1 taken 65687 times.
98099 if comp <> 0 then
1330 32412 return;
1331 end if;
1332
1333 65687 comp := Subscript.compareList(cref1.subscripts, cref2.subscripts);
1334
1335
2/2
✓ Branch 0 taken 14015 times.
✓ Branch 1 taken 51672 times.
65687 if comp <> 0 then
1336 14015 return;
1337 end if;
1338 51672 then
1339 compare(cref1.restCref, cref2.restCref);
1340
1341 case (EMPTY(), EMPTY()) then 0;
1342 case (WILD(), WILD()) then 0;
1343 case (_, EMPTY()) then 1;
1344 case (_, WILD()) then 1;
1345 case (EMPTY(), _) then -1;
1346 case (WILD(), _) then -1;
1347 else algorithm
1348 ✗ Error.terminate(getInstanceName() + " failed", sourceInfo());
1349 ✗ then fail();
1350 end match;
1351 end compare;
1352
1353 function isEqual
1354 input ComponentRef cref1;
1355 input ComponentRef cref2;
1356 output Boolean b;
1357 algorithm
1358
2/2
✓ Branch 0 taken 453400 times.
✓ Branch 1 taken 1587284 times.
2040684 if referenceEq(cref1, cref2) then
1359 b := true;
1360 453400 return;
1361 end if;
1362
1363 b := match (cref1, cref2)
1364 case (CREF(), CREF()) algorithm
1365
8/8
✓ Branch 2 taken 1212254 times.
✓ Branch 3 taken 219893 times.
✓ Branch 7 taken 1154588 times.
✓ Branch 8 taken 57666 times.
✓ Branch 10 taken 1145373 times.
✓ Branch 11 taken 9215 times.
✓ Branch 13 taken 49067 times.
✓ Branch 14 taken 1096306 times.
1432147 then nodeName(cref1) == nodeName(cref2) and
1366 Subscript.isEqualList(cref1.subscripts, cref2.subscripts) and
1367 isEqual(cref1.restCref, cref2.restCref);
1368 case (EMPTY(), EMPTY()) then true;
1369 case (WILD(), WILD()) then true;
1370 else false;
1371 end match;
1372 end isEqual;
1373
1374 function isEqualStrip
1375 "strips the subscripts before comparing. Used for non expandend variables"
1376 input ComponentRef cref1;
1377 input ComponentRef cref2;
1378 output Boolean b;
1379 algorithm
1380
2/2
✓ Branch 0 taken 132725 times.
✓ Branch 1 taken 1113126 times.
1245851 if referenceEq(cref1, cref2) then
1381 b := true;
1382 132725 return;
1383 end if;
1384
1385 b := match (cref1, cref2)
1386 case (CREF(), CREF()) algorithm
1387
6/6
✓ Branch 2 taken 866294 times.
✓ Branch 3 taken 90 times.
✓ Branch 7 taken 866270 times.
✓ Branch 8 taken 24 times.
✓ Branch 10 taken 84 times.
✓ Branch 11 taken 866186 times.
866384 then nodeName(cref1) == nodeName(cref2) and
1388 isEqualStrip(cref1.restCref, cref2.restCref);
1389 case (EMPTY(), EMPTY()) then true;
1390 case (WILD(), WILD()) then true;
1391 else false;
1392 end match;
1393 end isEqualStrip;
1394
1395 function isLess
1396 input ComponentRef cref1;
1397 input ComponentRef cref2;
1398 output Boolean isLess = compare(cref1, cref2) < 0;
1399 end isLess;
1400
1401 function isGreater
1402 input ComponentRef cref1;
1403 input ComponentRef cref2;
1404 output Boolean isGreater = compare(cref1, cref2) > 0;
1405 end isGreater;
1406
1407 function rebaseScope
1408 "Gives the scope part of the cref that refers to the same components as the
1409 given prefix, or one of its ancestors, the origins of the prefix, e.g.
1410 cell.obj.k where cell and obj are part of the scope and the prefix
1411 cell.obj.sub where obj was written in the source gives cell.obj.k where obj
1412 has the origin CREF. The nodes, subscripts and types of the cref are kept."
1413 input ComponentRef cref;
1414 input ComponentRef prefix;
1415 output ComponentRef outCref;
1416 protected
1417 Option<ComponentRef> ancestor;
1418 algorithm
1419 outCref := match cref
1420 case CREF(origin = Origin.SCOPE)
1421 algorithm
1422 1049 ancestor := findEqualAncestor(prefix, cref);
1423 then
1424 match ancestor
1425 local
1426 ComponentRef a;
1427 1049 case SOME(a) then copyOrigins(cref, a);
1428 ✗ else setRestCref(cref, rebaseScope(cref.restCref, prefix));
1429 end match;
1430
1431 case CREF()
1432 1051 then setRestCref(cref, rebaseScope(cref.restCref, prefix));
1433
1434 else cref;
1435 end match;
1436 end rebaseScope;
1437
1438 function hasUnmatchedScopePart
1439 "Returns true if the cref refers to a component via the scope that isn't
1440 one of the components in the given prefix, see rebaseScope."
1441 input ComponentRef cref;
1442 input ComponentRef prefix;
1443 output Boolean res;
1444 algorithm
1445 res := match cref
1446 case CREF(origin = Origin.SCOPE)
1447 guard InstNode.isComponent(node(cref)) and isNone(findEqualAncestor(prefix, cref))
1448 then true;
1449
1450 2109 case CREF() then hasUnmatchedScopePart(cref.restCref, prefix);
1451 else false;
1452 end match;
1453 end hasUnmatchedScopePart;
1454
1455 function findEqualAncestor
1456 "Returns the prefix or the first of its ancestors that refers to the same
1457 components as the given cref, ignoring subscripts."
1458 input ComponentRef prefix;
1459 input ComponentRef cref;
1460 output Option<ComponentRef> ancestor;
1461 algorithm
1462 ancestor := match prefix
1463 case CREF()
1464
2/2
✓ Branch 1 taken 1159 times.
✓ Branch 2 taken 21 times.
1180 then
1465 if isEqualStrip(prefix, cref)
1466 then SOME(prefix) else findEqualAncestor(prefix.restCref, cref);
1467
1468 else NONE();
1469 end match;
1470 end findEqualAncestor;
1471
1472 function setRestCref
1473 input output ComponentRef cref;
1474 input ComponentRef restCref;
1475 algorithm
1476 cref := match cref
1477 case CREF()
1478 algorithm
1479
2/2
✓ Branch 0 taken 1049 times.
✓ Branch 1 taken 2 times.
1051 if not referenceEq(cref.restCref, restCref) then
1480 1049 cref.restCref := restCref;
1481 end if;
1482 then
1483 cref;
1484
1485 else cref;
1486 end match;
1487 end setRestCref;
1488
1489 function copyOrigins
1490 input output ComponentRef cref;
1491 input ComponentRef source;
1492 algorithm
1493 cref := match (cref, source)
1494 case (CREF(), CREF())
1495 algorithm
1496 1058 cref.origin := source.origin;
1497 1058 cref.restCref := copyOrigins(cref.restCref, source.restCref);
1498 then
1499 cref;
1500
1501 else cref;
1502 end match;
1503 end copyOrigins;
1504
1505 function isPrefix
1506 input ComponentRef cref1;
1507 input ComponentRef cref2;
1508 output Boolean isPrefix;
1509 algorithm
1510
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27620 times.
27620 if referenceEq(cref1, cref2) then
1511 isPrefix := true;
1512 ✗ return;
1513 end if;
1514
1515 isPrefix := match (cref1, cref2)
1516 case (CREF(), CREF())
1517
8/8
✓ Branch 4 taken 826 times.
✓ Branch 5 taken 26794 times.
✓ Branch 11 taken 8 times.
✓ Branch 12 taken 818 times.
✓ Branch 14 taken 4 times.
✓ Branch 15 taken 4 times.
✓ Branch 17 taken 176 times.
✓ Branch 18 taken 27440 times.
27620 then
1518 InstNode.name(node(cref1)) == InstNode.name(node(cref2)) and isEqual(cref1.restCref, cref2.restCref) or
1519 isEqual(cref1, cref2.restCref);
1520 else false;
1521 end match;
1522 end isPrefix;
1523
1524 function toAbsyn
1525 input ComponentRef cref;
1526 output Absyn.ComponentRef acref;
1527 algorithm
1528 acref := match cref
1529 case CREF()
1530 algorithm
1531 ✗ acref := Absyn.ComponentRef.CREF_IDENT(nodeName(cref),
1532 list(Subscript.toAbsyn(s) for s in cref.subscripts));
1533 ✗ then
1534 toAbsyn_impl(cref.restCref, acref);
1535
1536 case WILD() then Absyn.ComponentRef.WILD();
1537 end match;
1538 end toAbsyn;
1539
1540 function toAbsyn_impl
1541 input ComponentRef cref;
1542 input Absyn.ComponentRef accumCref;
1543 output Absyn.ComponentRef acref;
1544 algorithm
1545 acref := match cref
1546 case EMPTY() then accumCref;
1547
1548 case CREF()
1549 algorithm
1550 ✗ acref := Absyn.ComponentRef.CREF_QUAL(nodeName(cref),
1551 list(Subscript.toAbsyn(s) for s in cref.subscripts), accumCref);
1552 ✗ then
1553 toAbsyn_impl(cref.restCref, acref);
1554
1555 end match;
1556 end toAbsyn_impl;
1557
1558 function toDAE
1559 input ComponentRef cref;
1560 output DAE.ComponentRef dcref;
1561 algorithm
1562 dcref := match cref
1563 case CREF()
1564 algorithm
1565
4/4
✓ Branch 0 taken 773344 times.
✓ Branch 1 taken 1576464 times.
✓ Branch 2 taken 773344 times.
✓ Branch 3 taken 1576464 times.
2349808 dcref := DAE.ComponentRef.CREF_IDENT(nodeName(cref), Type.toDAE(cref.ty),
1566 list(Subscript.toDAE(s) for s in cref.subscripts));
1567 1576464 then
1568 toDAE_impl(cref.restCref, dcref);
1569
1570 case WILD() then DAE.ComponentRef.WILD();
1571 end match;
1572 end toDAE;
1573
1574 function toDAE_impl
1575 input ComponentRef cref;
1576 input DAE.ComponentRef accumCref;
1577 output DAE.ComponentRef dcref;
1578 algorithm
1579 dcref := match cref
1580 local
1581 Type ty;
1582 DAE.Type dty;
1583
1584 case EMPTY() then accumCref;
1585 case CREF()
1586 algorithm
1587 // If the type is unknown here it's likely because the cref part is
1588 // from a scope prefix, which the typing doesn't bother typing since
1589 // that introduces cycles in the typing. We could patch the crefs
1590 // after the typing, but the new frontend doesn't use these types anyway.
1591 // So instead we just fetch the type of the node if the type is unknown.
1592
2/2
✓ Branch 1 taken 299 times.
✓ Branch 2 taken 2534458 times.
2534757 ty := if Type.isUnknown(cref.ty) then InstNode.getType(node(cref)) else cref.ty;
1593 2534757 dty := Type.toDAE(ty, makeTypeVars = false);
1594
4/4
✓ Branch 0 taken 98846 times.
✓ Branch 1 taken 2534757 times.
✓ Branch 2 taken 98846 times.
✓ Branch 3 taken 2534757 times.
2633603 dcref := DAE.ComponentRef.CREF_QUAL(nodeName(cref), dty,
1595 list(Subscript.toDAE(s) for s in cref.subscripts), accumCref);
1596 2534757 then
1597 toDAE_impl(cref.restCref, dcref);
1598 end match;
1599 end toDAE_impl;
1600
1601 function toString
1602 input ComponentRef cref;
1603 output String str;
1604 algorithm
1605 168071 str := stringDelimitList(toString_impl(cref, {}), ".");
1606 end toString;
1607
1608 function toString_impl
1609 input ComponentRef cref;
1610 input output list<String> strl;
1611 algorithm
1612 strl := match cref
1613 local
1614 String str;
1615
1616 case CREF()
1617 algorithm
1618 346008 str := nodeName(cref) + Subscript.toStringList(cref.subscripts);
1619 346008 then
1620 toString_impl(cref.restCref, str :: strl);
1621
1622 case WILD() then "_" :: strl;
1623 else strl;
1624 end match;
1625 end toString_impl;
1626
1627 function toFlatString
1628 input ComponentRef cref;
1629 input BaseModelica.OutputFormat format;
1630 output String str;
1631 protected
1632 list<String> strl;
1633 list<ComponentRef> crefs;
1634 list<Subscript> subs;
1635 ComponentRef cr;
1636 Boolean escapeQuotes;
1637 algorithm
1638 1519 str := firstName(cref, baseModelica = true);
1639
1640
5/8
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 1488 times.
✓ Branch 3 taken 18 times.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1506 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
1519 if str == "time" or str == "" then
1641 13 return;
1642 end if;
1643
1644 1506 crefs := toListReverse(cref);
1645 strl := {"'"};
1646 subs := {};
1647
1648
2/2
✓ Branch 0 taken 1381 times.
✓ Branch 1 taken 125 times.
1506 if format.scalarizeMode == BaseModelica.ScalarizeMode.NOT_SCALARIZED then
1649
2/2
✓ Branch 0 taken 277 times.
✓ Branch 1 taken 125 times.
402 while not listEmpty(crefs) loop
1650 277 cr :: crefs := crefs;
1651 277 strl := Util.escapeQuotes(firstName(cr, baseModelica = true)) :: strl;
1652 277 subs := listAppend(getSubscripts(cr), subs);
1653
1654
6/8
✓ Branch 0 taken 277 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 277 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 89 times.
✓ Branch 8 taken 188 times.
✓ Branch 9 taken 58 times.
✓ Branch 10 taken 31 times.
277 if format.recordMode == BaseModelica.RecordMode.WITH_RECORDS and isCref(cr) and
1655 Type.isRecord(scalarType(cr)) and not listEmpty(crefs) then
1656 strl := "'" :: strl;
1657
1658
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 26 times.
58 if not listEmpty(subs) then
1659 32 strl := Subscript.toFlatStringList(subs, format, escapeQuotes = false) :: strl;
1660 subs := {};
1661 end if;
1662
1663
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
58 if not listEmpty(crefs) then
1664 strl := ".'" :: strl;
1665 end if;
1666 elseif not listEmpty(crefs) then
1667 strl := "." :: strl;
1668 end if;
1669 end while;
1670 else
1671
2/2
✓ Branch 0 taken 3962 times.
✓ Branch 1 taken 1381 times.
5343 while not listEmpty(crefs) loop
1672 3962 cr :: crefs := crefs;
1673 3962 strl := Util.escapeQuotes(firstName(cr, baseModelica = true)) :: strl;
1674 3962 subs := getSubscripts(cr);
1675
1676
6/6
✓ Branch 0 taken 1534 times.
✓ Branch 1 taken 2428 times.
✓ Branch 2 taken 739 times.
✓ Branch 3 taken 795 times.
✓ Branch 4 taken 708 times.
✓ Branch 5 taken 31 times.
3962 if not listEmpty(subs) and
1677 not (format.scalarizeMode == BaseModelica.ScalarizeMode.PARTIALLY_SCALARIZED and listEmpty(crefs)) then
1678 1503 strl := Subscript.toFlatStringList(subs, format, escapeQuotes = true) :: strl;
1679 end if;
1680
1681
2/2
✓ Branch 0 taken 1381 times.
✓ Branch 1 taken 2581 times.
3962 if not listEmpty(crefs) then
1682
5/6
✓ Branch 0 taken 2533 times.
✓ Branch 1 taken 48 times.
✓ Branch 3 taken 2533 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 1201 times.
✓ Branch 8 taken 1332 times.
2581 if format.recordMode == BaseModelica.RecordMode.WITH_RECORDS and isCref(cr) and
1683 Type.isRecord(scalarType(cr)) then
1684 1201 strl := "'.'" :: strl;
1685 else
1686 strl := "." :: strl;
1687 end if;
1688 end if;
1689 end while;
1690
1691
2/2
✓ Branch 0 taken 924 times.
✓ Branch 1 taken 457 times.
1381 if format.scalarizeMode == BaseModelica.ScalarizeMode.PARTIALLY_SCALARIZED then
1692 924 subs := getSubscripts(cref);
1693 else
1694 subs := {};
1695 end if;
1696 end if;
1697
1698 strl := "'" :: strl;
1699
1700
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 1444 times.
1506 if not listEmpty(subs) then
1701 62 strl := Subscript.toFlatStringList(subs, format,
1702 escapeQuotes = format.scalarizeMode == BaseModelica.ScalarizeMode.SCALARIZED) :: strl;
1703 end if;
1704
1705 1506 str := stringAppendList(listReverse(strl));
1706 end toFlatString;
1707
1708 function listToString
1709 input list<ComponentRef> crs;
1710 output String str;
1711 algorithm
1712 ✗ str := "{" + stringDelimitList(List.map(crs, toString), ",") + "}";
1713 end listToString;
1714
1715 function toJSON
1716 input ComponentRef cref;
1717 output JSON json;
1718 algorithm
1719 json := match cref
1720 case CREF()
1721 algorithm
1722 26 json := JSON.emptyListObject();
1723 26 json := JSON.addPair("$kind", JSON.makeString("cref"), json);
1724 26 json := JSON.addPair("parts", JSON.makeList(toJSON_impl(cref)), json);
1725 then
1726 json;
1727
1728 ✗ case EMPTY() then JSON.makeNull();
1729
1730 case WILD()
1731 algorithm
1732 ✗ json := JSON.emptyListObject();
1733 ✗ json := JSON.addPair("$kind", JSON.makeString("cref"), json);
1734 ✗ json := JSON.addPair("parts", JSON.makeList(
1735 {JSON.fromPair("name", JSON.makeString("_"))}), json);
1736 then
1737 json;
1738
1739 ✗ else JSON.makeString(toString(cref));
1740 end match;
1741 end toJSON;
1742
1743 function toJSON_impl
1744 input ComponentRef cref;
1745 input list<JSON> accum = {};
1746 output list<JSON> objs;
1747 protected
1748 JSON obj;
1749 algorithm
1750 objs := match cref
1751 case CREF()
1752 algorithm
1753 37 obj := JSON.emptyListObject();
1754 37 obj := JSON.addPair("name", JSON.makeString(nodeName(cref)), obj);
1755
1756
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 if not listEmpty(cref.subscripts) then
1757 ✗ obj := JSON.addPair("subscripts", Subscript.toJSONList(cref.subscripts), obj);
1758 end if;
1759
2/2
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 11 times.
74 then
1760 if isEmpty(cref.restCref) then toJSON_context(node(cref), obj :: accum) else
1761 toJSON_impl(cref.restCref, obj :: accum);
1762
1763 else accum;
1764 end match;
1765 end toJSON_impl;
1766
1767 function toJSON_context
1768 input InstNode node;
1769 input output list<JSON> accum;
1770 protected
1771 Option<Absyn.Path> opt_context;
1772 algorithm
1773 26 opt_context := InstNode.rootClassContext(InstNode.instanceParent(node));
1774
1775
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 24 times.
26 if isSome(opt_context) then
1776
2/2
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2 times.
6 for name in AbsynUtil.pathToStringListReverse(Util.getOption(opt_context)) loop
1777 4 accum := JSON.addPair("name", JSON.makeString(name), JSON.emptyListObject()) :: accum;
1778 end for;
1779 end if;
1780 end toJSON_context;
1781
1782 function hash
1783 input ComponentRef cref;
1784 output Integer hash = hashContinue(cref, false, Util.HASH_SEED);
1785 end hash;
1786
1787 function hashStrip
1788 "hashes the cref without subscripts. used for non expanded variables"
1789 input ComponentRef cref;
1790 output Integer hash = hashContinue(cref, true, Util.HASH_SEED);
1791 end hashStrip;
1792
1793 function hashContinue
1794 input ComponentRef cref;
1795 input Boolean strip;
1796 input output Integer hash;
1797 algorithm
1798 hash := match cref
1799 case CREF()
1800 algorithm
1801 7345200 hash := stringHashDjb2Continue(nodeName(cref), hash);
1802
1803
2/2
✓ Branch 0 taken 5792357 times.
✓ Branch 1 taken 1552843 times.
7345200 if not strip then
1804
2/2
✓ Branch 0 taken 660888 times.
✓ Branch 1 taken 5792357 times.
6453245 for s in cref.subscripts loop
1805 660888 hash := Subscript.hashStringContinue(s, hash);
1806 end for;
1807 end if;
1808 7345200 then
1809 hashContinue(cref.restCref, strip, hash);
1810
1811 ✗ case WILD() then stringHashDjb2Continue("_", hash);
1812 else hash;
1813 end match;
1814 end hashContinue;
1815
1816 function toPath
1817 input ComponentRef cref;
1818 output Absyn.Path path;
1819 algorithm
1820 path := match cref
1821 case CREF()
1822 21435 then toPath_impl(cref.restCref, Absyn.IDENT(nodeName(cref)));
1823 end match;
1824 end toPath;
1825
1826 function toPath_impl
1827 input ComponentRef cref;
1828 input Absyn.Path accumPath;
1829 output Absyn.Path path;
1830 algorithm
1831 path := match cref
1832 case CREF()
1833 63761 then toPath_impl(cref.restCref,
1834 Absyn.QUALIFIED(nodeName(cref), accumPath));
1835 else accumPath;
1836 end match;
1837 end toPath_impl;
1838
1839 function fromNodeList
1840 input list<InstNode> nodes;
1841 output ComponentRef cref = ComponentRef.EMPTY();
1842 algorithm
1843
2/2
✓ Branch 0 taken 1153730 times.
✓ Branch 1 taken 1243923 times.
2397653 for n in nodes loop
1844 1153730 cref := CREF(n, {}, InstNode.getType(n), Origin.SCOPE, cref);
1845 end for;
1846 end fromNodeList;
1847
1848 function scalarize
1849 input ComponentRef cref;
1850 input Boolean resize;
1851 output list<ComponentRef> crefs;
1852 algorithm
1853 crefs := match cref
1854 local
1855 list<Dimension> dims;
1856 list<list<Subscript>> subs;
1857
1858 case CREF(ty = Type.ARRAY())
1859 algorithm
1860 97852 dims := Type.arrayDims(cref.ty);
1861 97852 subs := Subscript.scalarizeList(cref.subscripts, dims, resize);
1862 97852 subs := List.combination(subs);
1863
4/4
✓ Branch 0 taken 335609 times.
✓ Branch 1 taken 97852 times.
✓ Branch 2 taken 335609 times.
✓ Branch 3 taken 97852 times.
433461 then
1864 list(setSubscripts(s, cref) for s in subs);
1865
1866 else {cref};
1867 end match;
1868 end scalarize;
1869
1870 function scalarizeAll
1871 "output list is in reverse order.
1872 cref: b.A (Real[2, 3])
1873 crefs: {b[2].A[3], b[2].A[2], b[2].A[1], b[1].A[3], b[1].A[2], b[1].A[1]}"
1874 input ComponentRef cref;
1875 input Boolean resize;
1876 output list<ComponentRef> crefs;
1877 protected
1878 ComponentRef next = cref;
1879 list<list<ComponentRef>> nested_crefs = {};
1880 algorithm
1881
2/2
✓ Branch 1 taken 343841 times.
✓ Branch 2 taken 91568 times.
435409 while not isEmpty(next) loop
1882 343841 nested_crefs := scalarize(next, resize) :: nested_crefs;
1883
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 343841 times.
343841 CREF(restCref = next) := next;
1884 end while;
1885 91568 crefs := scalarizeAll_Nesting(nested_crefs);
1886 end scalarizeAll;
1887
1888 function scalarizeAll_Nesting
1889 input list<list<ComponentRef>> nested_crefs;
1890 input ComponentRef cref = EMPTY();
1891 input output list<ComponentRef> crefs = {};
1892 algorithm
1893 crefs := match nested_crefs
1894 local
1895 list<ComponentRef> head;
1896 list<list<ComponentRef>> tail;
1897 Boolean empty;
1898
1899 case head :: tail algorithm
1900 351462 empty := listEmpty(tail);
1901
2/2
✓ Branch 0 taken 447861 times.
✓ Branch 1 taken 351462 times.
799323 for head_cref in head loop
1902 crefs := match head_cref
1903 case CREF() algorithm
1904
2/2
✓ Branch 0 taken 187967 times.
✓ Branch 1 taken 259894 times.
447861 head_cref.restCref := cref;
1905
2/2
✓ Branch 0 taken 187967 times.
✓ Branch 1 taken 259894 times.
447861 if empty then
1906 crefs := head_cref :: crefs;
1907 else
1908 259894 crefs := scalarizeAll_Nesting(tail, head_cref, crefs);
1909 end if;
1910 then crefs;
1911 end match;
1912 end for;
1913 then crefs;
1914 end match;
1915 end scalarizeAll_Nesting;
1916
1917 function scalarizeSlice
1918 input ComponentRef cref;
1919 input list<Integer> slice = {} "optional slice, empty list means all";
1920 input Boolean resize;
1921 output list<ComponentRef> crefs;
1922 protected
1923 ComponentRef next = cref;
1924 list<list<ComponentRef>> nested_crefs = {};
1925 algorithm
1926 ✗ while not isEmpty(next) loop
1927 ✗ nested_crefs := scalarize(next, resize) :: nested_crefs;
1928 ✗ CREF(restCref = next) := next;
1929 end while;
1930 ✗ crefs := scalarizeAll_Nesting(nested_crefs);
1931
1932 // TODO: Only generate crefs that are needed by slice instead of filtering
1933 // them here at the end. Is this even possible for unsorted indices?
1934 ✗ if not listEmpty(slice) then
1935 ✗ crefs := List.getAtIndexLst(crefs, slice, true);
1936 end if;
1937 end scalarizeSlice;
1938
1939 function isPackageConstant
1940 input ComponentRef cref;
1941 output Boolean isPkgConst;
1942 algorithm
1943 // TODO: This should really be CONSTANT and not PARAMETER, but that breaks
1944 // some models since we get some redeclared parameters that look like
1945 // package constants due to redeclare issues, and which need to e.g.
1946 // be collected by Package.collectConstants.
1947
4/4
✓ Branch 1 taken 96855 times.
✓ Branch 2 taken 1007228 times.
✓ Branch 4 taken 85591 times.
✓ Branch 5 taken 11264 times.
1104083 isPkgConst := nodeVariability(cref) <= Variability.PARAMETER and isPackageConstant2(cref);
1948 end isPackageConstant;
1949
1950 function isPackageConstant2
1951 input ComponentRef cref;
1952 output Boolean isPkgConst;
1953 algorithm
1954 isPkgConst := match cref
1955 case CREF() guard InstNode.isClass(node(cref))
1956 11279 then InstNode.isUserdefinedClass(node(cref));
1957 102687 case CREF(origin = Origin.CREF) then isPackageConstant2(cref.restCref);
1958 else false;
1959 end match;
1960 end isPackageConstant2;
1961
1962 function stripSubscripts
1963 "Strips the subscripts from the last name in a cref, e.g. a[2].b[3] => a[2].b"
1964 input ComponentRef cref;
1965 output ComponentRef strippedCref;
1966 output list<Subscript> subs;
1967 algorithm
1968 (strippedCref, subs) := match cref
1969 case CREF()
1970 2141075 then (CREF(cref.node, {}, cref.ty, cref.origin, cref.restCref), cref.subscripts);
1971 else (cref, {});
1972 end match;
1973 end stripSubscripts;
1974
1975 function stripSubscriptsAll
1976 "Strips all subscripts from a cref."
1977 input ComponentRef cref;
1978 output ComponentRef strippedCref;
1979 algorithm
1980 strippedCref := match cref
1981 case CREF()
1982 792117 then CREF(cref.node, {}, cref.ty, cref.origin, stripSubscriptsAll(cref.restCref));
1983 else cref;
1984 end match;
1985 end stripSubscriptsAll;
1986
1987 function stripSubscriptsExceptModel
1988 "Removes all subscript of a componentref expcept for model subscripts"
1989 input output ComponentRef cref;
1990 algorithm
1991 cref := match cref
1992 local
1993 InstNode node;
1994 ComponentRef restCref;
1995
1996 case CREF(restCref = restCref) guard InstNode.isModel(node(cref))
1997 ✗ then CREF(cref.node, cref.subscripts, cref.ty, cref.origin, stripSubscriptsExceptModel(restCref));
1998
1999 case CREF(restCref = restCref)
2000 ✗ then CREF(cref.node, {}, cref.ty, cref.origin, stripSubscriptsExceptModel(restCref));
2001
2002 else cref;
2003 end match;
2004 end stripSubscriptsExceptModel;
2005
2006 function stripIteratorSubscripts
2007 input output ComponentRef cref;
2008 protected
2009 list<Subscript> subs;
2010 algorithm
2011 () := match cref
2012 case CREF()
2013 algorithm
2014
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1477 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1477 if not listEmpty(cref.subscripts) and Subscript.isIterator(List.last(cref.subscripts)) then
2015 ✗ subs := listReverse(cref.subscripts);
2016 ✗ subs := List.trim(subs, Subscript.isIterator);
2017 ✗ cref.subscripts := listReverseInPlace(subs);
2018 end if;
2019
2020 1477 cref.restCref := stripIteratorSubscripts(cref.restCref);
2021 then
2022 ();
2023
2024 else ();
2025 end match;
2026 end stripIteratorSubscripts;
2027
2028 function simplifySubscripts
2029 input output ComponentRef cref;
2030 input Boolean trim = false;
2031 protected
2032 list<Subscript> subs;
2033 ComponentRef rest_cref;
2034 Boolean dirty = false;
2035 algorithm
2036 cref := match cref
2037 case CREF(subscripts = subs)
2038 algorithm
2039
2/2
✓ Branch 0 taken 454119 times.
✓ Branch 1 taken 2582033 times.
3036152 if not listEmpty(subs) then
2040 454119 subs := Subscript.simplifyList(cref.subscripts, Type.arrayDims(cref.ty), trim);
2041 dirty := true;
2042 end if;
2043
2044 3036152 rest_cref := simplifySubscripts(cref.restCref, trim);
2045
4/4
✓ Branch 0 taken 2582033 times.
✓ Branch 1 taken 454119 times.
✓ Branch 2 taken 75636 times.
✓ Branch 3 taken 2506397 times.
3036152 dirty := dirty or not referenceEq(rest_cref, cref.restCref);
2046 529755 then
2047 if dirty then CREF(cref.node, subs, cref.ty, cref.origin, rest_cref) else cref;
2048
2049 else cref;
2050 end match;
2051 end simplifySubscripts;
2052
2053 function evaluateSubscripts
2054 input output ComponentRef cref;
2055 algorithm
2056 cref := match cref
2057 local
2058 list<Subscript> subs;
2059
2060 case CREF(subscripts = {}, origin = Origin.CREF)
2061 algorithm
2062 46224 cref.restCref := evaluateSubscripts(cref.restCref);
2063 then
2064 cref;
2065
2066 case CREF(origin = Origin.CREF)
2067 algorithm
2068
4/4
✓ Branch 0 taken 1687 times.
✓ Branch 1 taken 1687 times.
✓ Branch 2 taken 1687 times.
✓ Branch 3 taken 1687 times.
3374 subs := list(Subscript.eval(s) for s in cref.subscripts);
2069 1687 then
2070 CREF(cref.node, subs, cref.ty, cref.origin, evaluateSubscripts(cref.restCref));
2071
2072 else cref;
2073 end match;
2074 end evaluateSubscripts;
2075
2076 function isDeleted
2077 input ComponentRef cref;
2078 output Boolean isDeleted;
2079 algorithm
2080 isDeleted := match cref
2081 local
2082 InstNode node;
2083
2084 case CREF(origin = Origin.CREF)
2085 algorithm
2086 243308 node := node(cref);
2087
6/6
✓ Branch 1 taken 243250 times.
✓ Branch 2 taken 58 times.
✓ Branch 5 taken 241768 times.
✓ Branch 6 taken 1482 times.
✓ Branch 8 taken 613 times.
✓ Branch 9 taken 241213 times.
243308 then (InstNode.isComponent(node) and Component.isDeleted(InstNode.component(node))) or
2088 isDeleted(cref.restCref);
2089
2090 else false;
2091 end match;
2092 end isDeleted;
2093
2094 function isFromCref
2095 input ComponentRef cref;
2096 output Boolean fromCref;
2097 algorithm
2098 fromCref := match cref
2099 case CREF(origin = Origin.CREF) then true;
2100 case WILD() then true;
2101 else false;
2102 end match;
2103 end isFromCref;
2104
2105 function toListReverse
2106 input ComponentRef cref;
2107 input Boolean includeScope = true;
2108 input list<ComponentRef> accum = {};
2109 output list<ComponentRef> crefs;
2110 algorithm
2111 crefs := match cref
2112 case CREF() guard includeScope
2113 1171664 then toListReverse(cref.restCref, includeScope, cref :: accum);
2114 case CREF(origin = Origin.CREF)
2115 4863 then toListReverse(cref.restCref, includeScope, cref :: accum);
2116 else accum;
2117 end match;
2118 end toListReverse;
2119
2120 function depth
2121 input ComponentRef cref;
2122 output Integer d = 0;
2123 algorithm
2124 d := match cref
2125 case CREF(restCref = EMPTY())
2126 then d + 1;
2127
2128 case CREF()
2129 algorithm
2130 2981 d := 1 + depth(cref.restCref);
2131 then d;
2132
2133 case WILD() then 0;
2134 else /* EMPTY_CREF */ then 0;
2135 end match;
2136 end depth;
2137
2138 function size
2139 "Note: does not take subscripts into account"
2140 input ComponentRef cref;
2141 input Boolean withComplex;
2142 input Boolean resize = false;
2143 output Integer s = product(i for i in sizes(cref, withComplex, resize));
2144 end size;
2145
2146 function sizes
2147 "Note: does not take subscripts into account"
2148 input ComponentRef cref;
2149 input Boolean withComplex;
2150 input Boolean resize = false;
2151 input output list<Integer> s_lst = {};
2152 algorithm
2153 s_lst := match cref
2154 local
2155 list<Integer> local_lst = {};
2156 77146 case EMPTY() then listReverse(s_lst);
2157 case CREF() algorithm
2158 195429 local_lst := sizes_local(cref, withComplex, resize);
2159 195429 s_lst := listAppend(local_lst, s_lst);
2160 195429 then sizes(cref.restCref, withComplex, resize, s_lst);
2161 case WILD() then {0};
2162 end match;
2163 end sizes;
2164
2165 function sizes_local
2166 "Note: does not take subscripts into account"
2167 input ComponentRef cref;
2168 input Boolean withComplex;
2169 input Boolean resize = false;
2170 output list<Integer> s_lst = {};
2171 protected
2172 Option<Integer> complex_size;
2173 algorithm
2174 s_lst := match cref
2175 case CREF() algorithm
2176 195429 complex_size := Type.complexSize(cref.ty);
2177
4/4
✓ Branch 1 taken 44358 times.
✓ Branch 2 taken 195429 times.
✓ Branch 3 taken 44358 times.
✓ Branch 4 taken 195429 times.
239787 s_lst := list(Dimension.size(dim, resize) for dim in Type.arrayDims(cref.ty));
2178
5/6
✓ Branch 0 taken 101211 times.
✓ Branch 1 taken 94218 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 101211 times.
✓ Branch 4 taken 8013 times.
✓ Branch 5 taken 93198 times.
195429 if withComplex and isSome(complex_size) then
2179 8013 s_lst := Util.getOption(complex_size) :: s_lst;
2180 end if;
2181
2/2
✓ Branch 0 taken 151307 times.
✓ Branch 1 taken 44122 times.
195429 s_lst := if listEmpty(s_lst) then {1} else s_lst;
2182 then s_lst;
2183 else {};
2184 end match;
2185 end sizes_local;
2186
2187 function sizes_local_exp
2188 input ComponentRef cref;
2189 input Boolean withComplex;
2190 output list<Expression> s_lst = {};
2191 protected
2192 Option<Integer> complex_size;
2193 algorithm
2194 s_lst := match cref
2195 case CREF() algorithm
2196 ✗ s_lst := list(Dimension.sizeExp(dim) for dim in Type.arrayDims(cref.ty));
2197 // the size of a record can not be determined if it has members with unknown dimensions
2198 ✗ if withComplex then
2199 ✗ complex_size := Type.complexSize(cref.ty);
2200 ✗ if isSome(complex_size) then
2201 ✗ s_lst := Expression.INTEGER(Util.getOption(complex_size)) :: s_lst;
2202 end if;
2203 end if;
2204 ✗ s_lst := if listEmpty(s_lst) then {Expression.INTEGER(1)} else s_lst;
2205 then s_lst;
2206 else {};
2207 end match;
2208 end sizes_local_exp;
2209
2210 function sizeKnown
2211 input ComponentRef cref;
2212 output Boolean b;
2213 algorithm
2214 b := match cref
2215 627 case CREF() then Type.sizeKnown(cref.ty);
2216 else true; // size of WILD() and EMPTY() is known
2217 end match;
2218 end sizeKnown;
2219
2220 function subscriptsToInteger
2221 input ComponentRef cref;
2222 output list<Integer> s_lst = {};
2223 algorithm
2224
2/2
✓ Branch 1 taken 420 times.
✓ Branch 2 taken 233 times.
653 for subs_tmp in subscriptsAllReverse(cref) loop
2225
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 354 times.
420 if listEmpty(subs_tmp) then
2226 s_lst := 1 :: s_lst;
2227 else
2228
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 66 times.
132 for sub in subs_tmp loop
2229 66 s_lst := Expression.integerValueOrDefault(Subscript.toExp(sub), 1) :: s_lst;
2230 end for;
2231 end if;
2232 end for;
2233 end subscriptsToInteger;
2234
2235 function subscriptsToExpression
2236 input ComponentRef cref;
2237 input Boolean addScalar;
2238 // reversed, matching the order of sizes()
2239 output list<Expression> e_lst = listReverse(subscriptsToExpression2(cref, addScalar, {}));
2240 end subscriptsToExpression;
2241
2242 function subscriptsToExpression2
2243 input ComponentRef cref;
2244 input Boolean addScalar;
2245 input list<Expression> accum;
2246 output list<Expression> e_lst;
2247 protected
2248 list<Dimension> dims;
2249 list<Expression> local_lst;
2250 Expression exp;
2251 Dimension whole_dim;
2252 algorithm
2253 e_lst := match cref
2254 case CREF() algorithm
2255
3/4
✓ Branch 0 taken 92652 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20631 times.
✓ Branch 3 taken 72021 times.
92652 if addScalar and listEmpty(cref.subscripts) then
2256 local_lst := {Expression.INTEGER(1)};
2257 else
2258 // a whole subscript is the range over the corresponding dimension of the node
2259 20631 dims := Type.arrayDims(cref.ty);
2260 local_lst := {};
2261
2/2
✓ Branch 0 taken 27678 times.
✓ Branch 1 taken 20631 times.
48309 for sub in cref.subscripts loop
2262 exp := match (sub, dims)
2263 case (Subscript.WHOLE(), whole_dim :: _)
2264 ✗ then Expression.makeRange(Expression.INTEGER(1), NONE(), Dimension.sizeExp(whole_dim));
2265 27678 else Subscript.toExp(sub);
2266 end match;
2267 local_lst := exp :: local_lst;
2268
1/2
✓ Branch 0 taken 27678 times.
✗ Branch 1 not taken.
27678 dims := if listEmpty(dims) then dims else listRest(dims);
2269 end for;
2270 20631 local_lst := listReverse(local_lst);
2271 end if;
2272 92652 then subscriptsToExpression2(cref.restCref, addScalar, listAppend(local_lst, accum));
2273
2274 else accum;
2275 end match;
2276 end subscriptsToExpression2;
2277
2278 function isEmptyArray
2279 "Returns whether any node in the cref has a dimension that's 0."
2280 input ComponentRef cref;
2281 output Boolean isEmpty;
2282 algorithm
2283 isEmpty := match cref
2284 case CREF()
2285
3/4
✓ Branch 1 taken 1654591 times.
✓ Branch 2 taken 20 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1654591 times.
1654611 then Type.isEmptyArray(cref.ty) or isEmptyArray(cref.restCref);
2286 else false;
2287 end match;
2288 end isEmptyArray;
2289
2290 function isComplexArray
2291 input ComponentRef cref;
2292 output Boolean complexArray;
2293 algorithm
2294 complexArray := match cref
2295 41622 case CREF() then isComplexArray2(cref.restCref);
2296 else false;
2297 end match;
2298 end isComplexArray;
2299
2300 function isComplexArray2
2301 input ComponentRef cref;
2302 output Boolean complexArray;
2303 algorithm
2304 complexArray := match cref
2305 case CREF(ty = Type.ARRAY())
2306 guard Type.isArray(Type.subscript(cref.ty, cref.subscripts))
2307 then true;
2308
2309 95949 case CREF() then isComplexArray2(cref.restCref);
2310 else false;
2311 end match;
2312 end isComplexArray2;
2313
2314 function containsExp
2315 input ComponentRef cref;
2316 input ContainsPred func;
2317 output Boolean res;
2318
2319 partial function ContainsPred
2320 input Expression exp;
2321 output Boolean res;
2322 end ContainsPred;
2323 algorithm
2324 res := match cref
2325 case CREF()
2326
4/4
✓ Branch 1 taken 5879006 times.
✓ Branch 2 taken 95 times.
✓ Branch 4 taken 29 times.
✓ Branch 5 taken 5878977 times.
5879101 then Subscript.listContainsExp(cref.subscripts, func) or
2327 containsExp(cref.restCref, func);
2328
2329 else false;
2330 end match;
2331 end containsExp;
2332
2333 function containsExpShallow
2334 input ComponentRef cref;
2335 input ContainsPred func;
2336 output Boolean res;
2337
2338 partial function ContainsPred
2339 input Expression exp;
2340 output Boolean res;
2341 end ContainsPred;
2342 algorithm
2343 res := match cref
2344 case ComponentRef.CREF()
2345
2/4
✓ Branch 1 taken 93170 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 93170 times.
93170 then Subscript.listContainsExpShallow(cref.subscripts, func) or
2346 containsExpShallow(cref.restCref, func);
2347
2348 else false;
2349 end match;
2350 end containsExpShallow;
2351
2352 function applyExp
2353 input ComponentRef cref;
2354 input ApplyFunc func;
2355
2356 partial function ApplyFunc
2357 input Expression exp;
2358 end ApplyFunc;
2359 algorithm
2360 () := match cref
2361 case CREF()
2362 algorithm
2363
2/2
✓ Branch 0 taken 735303 times.
✓ Branch 1 taken 4202361 times.
4937664 for s in cref.subscripts loop
2364 735303 Subscript.applyExp(s, func);
2365 end for;
2366
2367 4202361 applyExp(cref.restCref, func);
2368 then
2369 ();
2370
2371 else ();
2372 end match;
2373 end applyExp;
2374
2375 function applyExpShallow
2376 input ComponentRef cref;
2377 input ApplyFunc func;
2378
2379 partial function ApplyFunc
2380 input Expression exp;
2381 end ApplyFunc;
2382 algorithm
2383 () := match cref
2384 case CREF()
2385 algorithm
2386
2/2
✓ Branch 0 taken 561 times.
✓ Branch 1 taken 175656 times.
176217 for s in cref.subscripts loop
2387 561 Subscript.applyExpShallow(s, func);
2388 end for;
2389
2390 175656 applyExpShallow(cref.restCref, func);
2391 then
2392 ();
2393
2394 else ();
2395 end match;
2396 end applyExpShallow;
2397
2398 function mapExp
2399 input ComponentRef cref;
2400 input MapFunc func;
2401 output ComponentRef outCref;
2402
2403 partial function MapFunc
2404 input output Expression e;
2405 end MapFunc;
2406 algorithm
2407 outCref := match cref
2408 local
2409 list<Subscript> subs;
2410 ComponentRef rest;
2411
2412 case CREF()
2413 algorithm
2414
4/4
✓ Branch 0 taken 2222417 times.
✓ Branch 1 taken 10074985 times.
✓ Branch 2 taken 2222417 times.
✓ Branch 3 taken 10074985 times.
12297402 subs := list(Subscript.mapExp(s, func) for s in cref.subscripts);
2415 10074985 rest := mapExp(cref.restCref, func);
2416 10074985 then
2417 CREF(cref.node, subs, cref.ty, cref.origin, rest);
2418
2419 else cref;
2420 end match;
2421 end mapExp;
2422
2423 function mapExpShallow
2424 input ComponentRef cref;
2425 input MapFunc func;
2426 output ComponentRef outCref;
2427
2428 partial function MapFunc
2429 input output Expression e;
2430 end MapFunc;
2431 algorithm
2432 outCref := match cref
2433 local
2434 list<Subscript> subs;
2435 ComponentRef rest;
2436
2437 case CREF()
2438 algorithm
2439
4/4
✓ Branch 0 taken 701335 times.
✓ Branch 1 taken 4027823 times.
✓ Branch 2 taken 701335 times.
✓ Branch 3 taken 4027823 times.
4729158 subs := list(Subscript.mapShallowExp(s, func) for s in cref.subscripts);
2440 4027823 rest := mapExpShallow(cref.restCref, func);
2441 4027823 then
2442 CREF(cref.node, subs, cref.ty, cref.origin, rest);
2443
2444 else cref;
2445 end match;
2446 end mapExpShallow;
2447
2448 function foldExp<ArgT>
2449 input ComponentRef cref;
2450 input FoldFunc func;
2451 input output ArgT arg;
2452
2453 partial function FoldFunc
2454 input Expression exp;
2455 input output ArgT arg;
2456 end FoldFunc;
2457 algorithm
2458 () := match cref
2459 case CREF()
2460 algorithm
2461 4166292 arg := List.fold(cref.subscripts, function Subscript.foldExp(func = func), arg);
2462 4166292 arg := foldExp(cref.restCref, func, arg);
2463 then
2464 ();
2465
2466 else ();
2467 end match;
2468 end foldExp;
2469
2470 function mapFoldExp<ArgT>
2471 input ComponentRef cref;
2472 input MapFunc func;
2473 output ComponentRef outCref;
2474 input output ArgT arg;
2475
2476 partial function MapFunc
2477 input output Expression e;
2478 input output ArgT arg;
2479 end MapFunc;
2480 algorithm
2481 outCref := match cref
2482 local
2483 list<Subscript> subs;
2484 ComponentRef rest;
2485
2486 case CREF()
2487 algorithm
2488 4401 (subs, arg) := List.map1Fold(cref.subscripts, Subscript.mapFoldExp, func, arg);
2489 4401 (rest, arg) := mapFoldExp(cref.restCref, func, arg);
2490 4401 then
2491 CREF(cref.node, subs, cref.ty, cref.origin, rest);
2492
2493 else cref;
2494 end match;
2495 end mapFoldExp;
2496
2497 function mapFoldExpShallow<ArgT>
2498 input ComponentRef cref;
2499 input MapFunc func;
2500 output ComponentRef outCref;
2501 input output ArgT arg;
2502
2503 partial function MapFunc
2504 input output Expression e;
2505 input output ArgT arg;
2506 end MapFunc;
2507 algorithm
2508 outCref := match cref
2509 local
2510 list<Subscript> subs;
2511 ComponentRef rest;
2512
2513 case CREF()
2514 algorithm
2515 2634155 (subs, arg) := List.map1Fold(cref.subscripts, Subscript.mapFoldExpShallow, func, arg);
2516 2634155 (rest, arg) := mapFoldExpShallow(cref.restCref, func, arg);
2517 2634155 then
2518 CREF(cref.node, subs, cref.ty, cref.origin, rest);
2519
2520 else cref;
2521 end match;
2522 end mapFoldExpShallow;
2523
2524 function isTime
2525 input ComponentRef cref;
2526 output Boolean b = firstName(cref) == "time";
2527 end isTime;
2528
2529 function isSubstitute
2530 input ComponentRef cref;
2531 output Boolean b = firstName(cref) == "$SUBST_CREF";
2532 end isSubstitute;
2533
2534 /* ========================================
2535 Backend Extension functions
2536 ========================================= */
2537
2538 function isDiscrete
2539 "kabdelhak: Returns true if component reference has a discrete type.
2540 Used to analyze algorithm outputs."
2541 input ComponentRef cref;
2542 output Boolean result = Type.isDiscrete(nodeType(cref));
2543 end isDiscrete;
2544
2545 function removeOuterCrefPrefix
2546 input output ComponentRef cref;
2547 algorithm
2548 () := match cref
2549 case ComponentRef.CREF()
2550 algorithm
2551
2/2
✓ Branch 2 taken 438 times.
✓ Branch 3 taken 1605657 times.
1606095 if InstNode.isGeneratedInner(node(cref)) then
2552 438 cref.restCref := EMPTY();
2553 else
2554 1605657 cref.restCref := removeOuterCrefPrefix(cref.restCref);
2555 end if;
2556 then
2557 ();
2558
2559 else ();
2560 end match;
2561 end removeOuterCrefPrefix;
2562
2563 function mapTypes
2564 input ComponentRef cref;
2565 input MapFunc func;
2566 output ComponentRef outCref;
2567
2568 partial function MapFunc
2569 input output Type e;
2570 end MapFunc;
2571 algorithm
2572 outCref := match cref
2573 local
2574 ComponentRef rest;
2575 Type ty;
2576
2577 case CREF()
2578 algorithm
2579
1/2
✓ Branch 0 taken 1327062 times.
✗ Branch 1 not taken.
1327062 ty := func(cref.ty);
2580 1327062 rest := mapTypes(cref.restCref, func);
2581 1327062 then
2582 CREF(cref.node, cref.subscripts, ty, cref.origin, rest);
2583
2584 else cref;
2585 end match;
2586 end mapTypes;
2587
2588 function mapNodes
2589 input ComponentRef cref;
2590 input MapFunc func;
2591 output ComponentRef outCref;
2592
2593 partial function MapFunc
2594 input output InstNode n;
2595 end MapFunc;
2596 algorithm
2597 outCref := match cref
2598 local
2599 ComponentRef rest;
2600 InstNode node;
2601
2602 case CREF()
2603 algorithm
2604 ✗ node := func(node(cref));
2605 ✗ rest := mapNodes(cref.restCref, func);
2606 ✗ then
2607 CREF(node, cref.subscripts, cref.ty, cref.origin, rest);
2608
2609 else cref;
2610 end match;
2611 end mapNodes;
2612
2613 function getArrayCrefOpt
2614 input ComponentRef scal;
2615 output Option<ComponentRef> arr;
2616 protected
2617 list<Subscript> subs;
2618 algorithm
2619
2/2
✓ Branch 1 taken 20861 times.
✓ Branch 2 taken 573 times.
21434 if Flags.getConfigBool(Flags.SIM_CODE_SCALARIZE) then
2620 20861 subs := subscriptsAllFlat(scal);
2621
2/2
✓ Branch 0 taken 12333 times.
✓ Branch 1 taken 8528 times.
20861 if listEmpty(subs) then
2622 // do not do it for scalar variables
2623 arr := NONE();
2624 elseif List.all(subs, Subscript.isFirst) then
2625 // if it is the first element, save the array var
2626 1403 arr := SOME(stripSubscriptsAll(scal));
2627 else
2628 // not first element
2629 arr := NONE();
2630 end if;
2631 else
2632
2/2
✓ Branch 2 taken 346 times.
✓ Branch 3 taken 227 times.
573 arr := if Type.isArray(getSubscriptedType(scal)) then SOME(stripSubscriptsAll(scal)) else NONE();
2633 end if;
2634 end getArrayCrefOpt;
2635
2636 function isSliced
2637 input ComponentRef cref;
2638 output Boolean sliced;
2639 protected
2640 function is_sliced_impl
2641 input ComponentRef cref;
2642 output Boolean sliced;
2643 algorithm
2644 sliced := match cref
2645 case CREF(origin = Origin.CREF)
2646 algorithm
2647
3/4
✓ Branch 2 taken 250210 times.
✓ Branch 3 taken 1 time.
✓ Branch 5 taken 250210 times.
✗ Branch 6 not taken.
250211 sliced := Type.dimensionCount(cref.ty) > listLength(cref.subscripts) or
2648 List.any(cref.subscripts, Subscript.isSliced);
2649
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 250210 times.
250210 then
2650 sliced or is_sliced_impl(cref.restCref);
2651
2652 else false;
2653 end match;
2654 end is_sliced_impl;
2655 algorithm
2656 sliced := match cref
2657 737855 case CREF() then is_sliced_impl(cref.restCref);
2658 else false;
2659 end match;
2660 end isSliced;
2661
2662 function hasImplicitTrailingIndex
2663 "Returns true if the outermost cref component has fewer subscripts than
2664 dimensions.
2665 E.g. a[i] where a : Real[10,2] returns true, because
2666 one scalar index is given but a second dimension is left implicit (:)."
2667 input ComponentRef cref;
2668 output Boolean res;
2669 algorithm
2670 res := match cref
2671 case CREF(origin = Origin.CREF)
2672
4/4
✓ Branch 0 taken 560469 times.
✓ Branch 1 taken 1261188 times.
✓ Branch 4 taken 560455 times.
✓ Branch 5 taken 14 times.
1821657 then not listEmpty(cref.subscripts) and
2673 listLength(cref.subscripts) < Type.dimensionCount(cref.ty);
2674 else false;
2675 end match;
2676 end hasImplicitTrailingIndex;
2677
2678 function iterate
2679 input output ComponentRef cref;
2680 output list<tuple<InstNode, Expression>> iterators;
2681 protected
2682 ComponentRef rest_cref;
2683
2684 function iterate_impl
2685 "Replaces any slice subscripts (including implicit :) with an iterator,
2686 and returns a list of all iterators with the corresponding ranges."
2687 input output ComponentRef cref;
2688 input output list<tuple<InstNode, Expression>> iterators = {};
2689 protected
2690 ComponentRef rest_cref;
2691 Dimension dim;
2692 list<Dimension> dims;
2693 Integer dim_count, sub_count;
2694 list<Subscript> subs, isubs;
2695 Integer dim_index;
2696 InstNode iterator;
2697 Expression range;
2698 algorithm
2699 () := match cref
2700 case CREF(origin = Origin.CREF)
2701 algorithm
2702 3 dims := listReverse(Type.arrayDims(cref.ty));
2703 3 dim_count := listLength(dims);
2704 3 sub_count := listLength(cref.subscripts);
2705 3 subs := List.consN(dim_count - sub_count, Subscript.WHOLE(), cref.subscripts);
2706 isubs := {};
2707 dim_index := dim_count;
2708
2709
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
6 for s in listReverse(subs) loop
2710
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 dim :: dims := dims;
2711
2712
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 if not Subscript.isIndex(s) then
2713 range := match s
2714 // Slices like 1:3 are used directly.
2715 ✗ case Subscript.SLICE() then s.slice;
2716 // : are turned into 1:size(x, dim).
2717 case Subscript.WHOLE()
2718 3 then Expression.makeRange(Dimension.lowerBoundExp(dim),
2719 NONE(),
2720 Dimension.endExp(dim, Expression.CREF(cref.ty, cref), dim_index));
2721 end match;
2722
2723 3 iterator := InstNode.newUniqueIterator();
2724 3 iterators := (iterator, range) :: iterators;
2725 3 dim_index := dim_index - 1;
2726
2727 3 s := Subscript.INDEX(Expression.fromCref(ComponentRef.makeIterator(iterator, Type.INTEGER())));
2728 end if;
2729
2730 isubs := s :: isubs;
2731 end for;
2732
2733 3 cref.subscripts := isubs;
2734 3 (rest_cref, iterators) := iterate_impl(cref.restCref, iterators);
2735 3 cref.restCref := rest_cref;
2736 then
2737 ();
2738
2739 else ();
2740 end match;
2741 end iterate_impl;
2742 algorithm
2743 iterators := match cref
2744 case CREF()
2745 algorithm
2746 1 (rest_cref, iterators) := iterate_impl(cref.restCref);
2747
2748
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if not listEmpty(iterators) then
2749 1 cref.restCref := rest_cref;
2750 1 iterators := listReverseInPlace(iterators);
2751 end if;
2752 1 then
2753 iterators;
2754
2755 else {};
2756 end match;
2757 end iterate;
2758
2759 function getRecordChildren
2760 input ComponentRef cref;
2761 output list<ComponentRef> children = {};
2762 protected
2763 Type ty = Type.arrayElementType(getComponentType(cref));
2764 array<InstNode> children_nodes = listArray({});
2765 algorithm
2766
2/2
✓ Branch 1 taken 194 times.
✓ Branch 2 taken 1450 times.
1644 if Type.isComplex(ty) then
2767 children_nodes := match cref
2768 194 case CREF() then ClassTree.getComponents(Class.classTree(InstNode.getClass(Component.classInstance(InstNode.component(node(cref))))));
2769 ✗ else listArray({});
2770 end match;
2771 end if;
2772
2773
2/2
✓ Branch 0 taken 1450 times.
✓ Branch 1 taken 194 times.
1644 if not arrayEmpty(children_nodes) then
2774
4/4
✓ Branch 0 taken 780 times.
✓ Branch 1 taken 194 times.
✓ Branch 3 taken 780 times.
✓ Branch 4 taken 194 times.
1948 children := list(prefixCref(node, InstNode.getType(node), {}, cref) for node in children_nodes);
2775 end if;
2776 end getRecordChildren;
2777
2778 annotation(__OpenModelica_Interface="nf_frontend");
2779 end NFComponentRef;
2780