Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 50.4% 135 / 0 / 268
Functions: -% 0 / 1 / 1
Branches: 63.4% 121 / 0 / 191

OMCompiler/Compiler/NFFrontEnd/NFType.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 NFType
37 protected
38 import Type = NFType;
39 import Array;
40 import Absyn;
41 import Class = NFClass;
42 import DAE;
43 import IOStream;
44 import List;
45 import StringUtil;
46 import Util;
47 import NFClassTree.ClassTree;
48
49 public
50 import BaseModelica;
51 import Dimension = NFDimension;
52 import NFInstNode.InstNode;
53 import NFInstNode;
54 import Subscript = NFSubscript;
55 import ComplexType = NFComplexType;
56 import NFFunction.Function;
57 import Record = NFRecord;
58 import UnorderedMap;
59
60 type FunctionType = enumeration(
61 FUNCTIONAL_PARAMETER "Function parameter of function type.",
62 FUNCTION_REFERENCE "Function name used to reference a function.",
63 FUNCTIONAL_VARIABLE "A variable that contains a function reference."
64 );
65
66 type Branch = enumeration(
67 NONE,
68 TRUE,
69 FALSE
70 );
71
72 record INTEGER
73 end INTEGER;
74
75 record REAL
76 end REAL;
77
78 record STRING
79 end STRING;
80
81 record BOOLEAN
82 end BOOLEAN;
83
84 record CLOCK
85 end CLOCK;
86
87 record ENUMERATION
88 Absyn.Path typePath;
89 list<String> literals;
90 end ENUMERATION;
91
92 // TODO: Remove this, which requires updating the bootstrapping sources to
93 // avoid breaking the ffi interface.
94 record __ENUMERATION_ANY_NOT_USED__
95 end __ENUMERATION_ANY_NOT_USED__;
96
97 record ARRAY
98 Type elementType;
99 list<Dimension> dimensions;
100 end ARRAY;
101
102 record TUPLE
103 list<Type> types;
104 Option<list<String>> names;
105 end TUPLE;
106
107 record NORETCALL
108 end NORETCALL;
109
110 record UNKNOWN
111 end UNKNOWN;
112
113 record COMPLEX
114 NFInstNode.ScopeRef cls "The class this type names, weakly:
115 a class's own type names it back, and that is a cycle. Owned by whatever
116 the class hangs off -- a component's `classInst`, a `Function`, a cref.";
117 ComplexType complexTy;
118 end COMPLEX;
119
120 record FUNCTION
121 Function fn;
122 FunctionType fnType;
123 end FUNCTION;
124
125 record METABOXED "Used for MetaModelica generic types"
126 Type ty;
127 end METABOXED;
128
129 record POLYMORPHIC
130 String name;
131 end POLYMORPHIC;
132
133 record ANY
134 end ANY;
135
136 record CONDITIONAL_ARRAY
137 "A type that might be one of two types depending on a condition.
138 The two types are assumed to be array types with equal number of dimensions."
139 Type trueType;
140 Type falseType;
141 Branch matchedBranch;
142 end CONDITIONAL_ARRAY;
143
144 record UNTYPED
145 "Used by untyped components to store type information needed during typing."
146 InstNode typeNode;
147 array<Dimension> dimensions;
148 end UNTYPED;
149
150 // TODO: Fix constants in uniontypes and use these wherever applicable to
151 // speed up comparisons using referenceEq.
152 //constant Type INTEGER_DEFAULT = NFType.INTEGER();
153 //constant Type REAL_DEFAULT = NFType.REAL();
154 //constant Type STRING_DEFAULT = NFType.STRING();
155 //constant Type BOOLEAN_DEFAULT = NFType.BOOLEAN();
156
157 function liftArrayLeft
158 "Adds an array dimension to a type on the left side, e.g.
159 listArrayLeft(Real[2, 3], [4]) => Real[4, 2, 3]."
160 input output Type ty;
161 input Dimension dim;
162 algorithm
163 ty := match ty
164 18228 case ARRAY() then ARRAY(ty.elementType, dim :: ty.dimensions);
165 ✗ case CONDITIONAL_ARRAY() then CONDITIONAL_ARRAY(liftArrayLeft(ty.trueType, dim),
166 liftArrayLeft(ty.falseType, dim),
167 ty.matchedBranch);
168 148966 else ARRAY(ty, {dim});
169 end match;
170 end liftArrayLeft;
171
172 function liftArrayLeftList
173 "Adds array dimensions to a type on the left side, e.g.
174 listArrayLeft(Real[2, 3], [4, 5]) => Real[4, 5, 2, 3]."
175 input output Type ty;
176 input list<Dimension> dims;
177 algorithm
178
2/2
✓ Branch 0 taken 3068380 times.
✓ Branch 1 taken 458324 times.
3526704 if listEmpty(dims) then
179 3068380 return;
180 end if;
181
182 ty := match ty
183 2051 case ARRAY() then ARRAY(ty.elementType, listAppend(dims, ty.dimensions));
184 ✗ case CONDITIONAL_ARRAY() then CONDITIONAL_ARRAY(liftArrayLeftList(ty.trueType, dims),
185 liftArrayLeftList(ty.falseType, dims),
186 ty.matchedBranch);
187 456273 else ARRAY(ty, dims);
188 end match;
189 end liftArrayLeftList;
190
191 function liftArrayRightList
192 "Adds array dimensions to a type on the left side, e.g.
193 listArrayLeft(Real[2, 3], [4, 5]) => Real[2, 3, 4, 5]."
194 input output Type ty;
195 input list<Dimension> dims;
196 algorithm
197
2/2
✓ Branch 0 taken 27177 times.
✓ Branch 1 taken 600 times.
27777 if listEmpty(dims) then
198 27177 return;
199 end if;
200
201 ty := match ty
202 68 case ARRAY() then ARRAY(ty.elementType, listAppend(ty.dimensions, dims));
203 ✗ case CONDITIONAL_ARRAY() then CONDITIONAL_ARRAY(liftArrayRightList(ty.trueType, dims),
204 liftArrayRightList(ty.falseType, dims),
205 ty.matchedBranch);
206 532 else ARRAY(ty, dims);
207 end match;
208 end liftArrayRightList;
209
210 function unliftArray
211 input output Type ty;
212 algorithm
213 ty := match ty
214 local
215 list<Dimension> dims;
216 Type tty, fty;
217
218 case ARRAY(dimensions = _ :: dims)
219
2/2
✓ Branch 0 taken 22905 times.
✓ Branch 1 taken 529 times.
23434 then if listEmpty(dims) then ty.elementType else ARRAY(ty.elementType, dims);
220
221 case CONDITIONAL_ARRAY()
222 algorithm
223 ✗ tty := unliftArray(ty.trueType);
224 ✗ fty := unliftArray(ty.falseType);
225 ✗ then
226 if isEqual(tty, fty) then tty else CONDITIONAL_ARRAY(tty, fty, ty.matchedBranch);
227
228 end match;
229 end unliftArray;
230
231 function unliftArrayN
232 input Integer N;
233 input output Type ty;
234 algorithm
235
2/2
✓ Branch 0 taken 1786 times.
✓ Branch 1 taken 109 times.
1895 if N == 0 then
236 1786 return;
237 end if;
238
239 ty := match ty
240 local
241 list<Dimension> dims;
242 Type tty, fty;
243
244 case ARRAY(dimensions = dims)
245 algorithm
246
1/2
✓ Branch 0 taken 109 times.
✗ Branch 1 not taken.
218 for i in 1:N loop
247 109 dims := listRest(dims);
248 end for;
249
1/2
✓ Branch 0 taken 109 times.
✗ Branch 1 not taken.
109 then
250 if listEmpty(dims) then ty.elementType else ARRAY(ty.elementType, dims);
251
252 case CONDITIONAL_ARRAY()
253 algorithm
254 ✗ tty := unliftArrayN(N, ty.trueType);
255 ✗ fty := unliftArrayN(N, ty.falseType);
256 ✗ then
257 if isEqual(tty, fty) then tty else CONDITIONAL_ARRAY(tty, fty, ty.matchedBranch);
258
259 end match;
260 end unliftArrayN;
261
262 function isInteger
263 input Type ty;
264 output Boolean isInteger;
265 algorithm
266 isInteger := match ty
267 case INTEGER() then true;
268 ✗ case METABOXED() then isInteger(ty.ty);
269 else false;
270 end match;
271 end isInteger;
272
273 function isReal
274 input Type ty;
275 output Boolean isReal;
276 algorithm
277 isReal := match ty
278 case REAL() then true;
279 ✗ case METABOXED() then isReal(ty.ty);
280 else false;
281 end match;
282 end isReal;
283
284 function isBoolean
285 input Type ty;
286 output Boolean isBool;
287 algorithm
288 isBool := match ty
289 case BOOLEAN() then true;
290 ✗ case METABOXED() then isBoolean(ty.ty);
291 else false;
292 end match;
293 end isBoolean;
294
295 function isString
296 input Type ty;
297 output Boolean isString;
298 algorithm
299 isString := match ty
300 case STRING() then true;
301 ✗ case METABOXED() then isString(ty.ty);
302 else false;
303 end match;
304 end isString;
305
306 function isClock
307 input Type ty;
308 output Boolean isClock;
309 algorithm
310 isClock := match ty
311 case CLOCK() then true;
312 ✗ case METABOXED() then isClock(ty.ty);
313 else false;
314 end match;
315 end isClock;
316
317 function isContinuous
318 input Type ty;
319 output Boolean b;
320 algorithm
321 b := match ty
322 local
323 ComplexType ct;
324
325 // check if all fields are continuous
326 case COMPLEX(complexTy = ct as ComplexType.RECORD())
327
4/4
✓ Branch 0 taken 127 times.
✓ Branch 1 taken 52 times.
✓ Branch 3 taken 127 times.
✓ Branch 4 taken 52 times.
358 then List.all(list(lookupRecordFieldType(Record.Field.name(field), ty) for field in ct.fields), isContinuous);
328
329 2452 else isReal(elementType(ty));
330 end match;
331 end isContinuous;
332
333 function isScalar
334 input Type ty;
335 output Boolean isScalar;
336 algorithm
337 isScalar := match ty
338 case ARRAY() then false;
339 case CONDITIONAL_ARRAY() then false;
340 else true;
341 end match;
342 end isScalar;
343
344 function isArray
345 input Type ty;
346 output Boolean isArray;
347 algorithm
348 isArray := match ty
349 case ARRAY() then true;
350 case CONDITIONAL_ARRAY() then true;
351 else false;
352 end match;
353 end isArray;
354
355 function isConditionalArray
356 input Type ty;
357 output Boolean isConditionalArray;
358 algorithm
359 isConditionalArray := match ty
360 case CONDITIONAL_ARRAY() then true;
361 else false;
362 end match;
363 end isConditionalArray;
364
365 function isResizable
366 input Type ty;
367 output Boolean b = List.any(arrayDims(ty), Dimension.isResizable);
368 end isResizable;
369
370 function sizeKnown
371 input Type ty;
372 output Boolean b = not List.any(arrayDims(ty), Dimension.isUnknown);
373 end sizeKnown;
374
375 function isAny
376 input Type ty;
377 output Boolean b;
378 algorithm
379 b := match ty
380 case Type.ANY() then true;
381 else false;
382 end match;
383 end isAny;
384
385 function setConditionalArrayTypes
386 input Type condType;
387 input Type trueType;
388 input Type falseType;
389 output Type outType;
390 protected
391 Branch matched_branch;
392 algorithm
393
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 53 times.
53 CONDITIONAL_ARRAY(matchedBranch = matched_branch) := condType;
394 53 outType := CONDITIONAL_ARRAY(trueType, falseType, matched_branch);
395 end setConditionalArrayTypes;
396
397 function removeSizeOneArraysAndRecords
398 "only to be used for backend. removes size one arrays from type"
399 input output Type ty;
400 algorithm
401 ty := match ty
402 local
403 array<Record.Field> fields;
404
405 // remove size one arrays
406 case ARRAY() algorithm
407
8/8
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 298 times.
✓ Branch 3 taken 299 times.
✓ Branch 4 taken 283 times.
✓ Branch 5 taken 298 times.
✓ Branch 6 taken 283 times.
✓ Branch 8 taken 1 time.
✓ Branch 9 taken 282 times.
865 ty.dimensions := list(dim for dim guard(not Dimension.isOne(dim)) in ty.dimensions);
408
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 282 times.
283 then if listEmpty(ty.dimensions) then removeSizeOneArraysAndRecords(ty.elementType) else ty;
409
410 // remove one-element records
411 case COMPLEX(complexTy = ComplexType.RECORD(fields = fields)) guard(arrayLength(fields) == 1)
412 1 then removeSizeOneArraysAndRecords(lookupRecordFieldType(Record.Field.name(fields[1]), ty));
413
414 else ty;
415 end match;
416 end removeSizeOneArraysAndRecords;
417
418 function isMatchedBranch
419 input Boolean condition;
420 input Type condType;
421 output Boolean isMatched = true;
422 protected
423 Branch matched_branch;
424 algorithm
425
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 CONDITIONAL_ARRAY(matchedBranch = matched_branch) := condType;
426
427
2/4
✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
✗ Branch 3 not taken.
57 if condition and matched_branch == Branch.FALSE or
428 not condition and matched_branch == Branch.TRUE then
429 isMatched := false;
430 end if;
431 end isMatchedBranch;
432
433 function matchedConditionalArrayType
434 input Type ty;
435 output Type outType;
436 algorithm
437 outType := match ty
438 case CONDITIONAL_ARRAY()
439 then match ty.matchedBranch
440 ✗ case Branch.TRUE then ty.trueType;
441 ✗ case Branch.FALSE then ty.falseType;
442 end match;
443 end match;
444 end matchedConditionalArrayType;
445
446 function simplifyConditionalArray
447 input Type ty;
448 output Type outType;
449 algorithm
450 outType := match ty
451 case CONDITIONAL_ARRAY()
452 then match ty.matchedBranch
453 ✗ case Branch.TRUE then ty.trueType;
454 ✗ case Branch.FALSE then ty.falseType;
455 else ty;
456 end match;
457
458 else ty;
459 end match;
460 end simplifyConditionalArray;
461
462 function unifyArrays
463 "Unifies two array types into a single type, with unknown dimensions where
464 the dimensions of the two types disagree. The types are assumed to be
465 array types with the same number of dimensions."
466 input Type ty1;
467 input Type ty2;
468 output Type outType;
469 protected
470 list<Dimension> dims;
471
472 function unify_dims
473 input Dimension dim1;
474 input Dimension dim2;
475 output Dimension dim;
476 algorithm
477
2/2
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 3 times.
13 if Dimension.isSame(dim1, dim2) then
478 dim := dim1;
479 else
480 dim := Dimension.UNKNOWN();
481 end if;
482 end unify_dims;
483 algorithm
484
7/8
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 10 times.
✓ Branch 6 taken 13 times.
✓ Branch 7 taken 10 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 10 times.
23 dims := list(unify_dims(d1, d2) threaded for d1 in arrayDims(ty1), d2 in arrayDims(ty2));
485 10 outType := ARRAY(elementType(ty1), dims);
486 end unifyArrays;
487
488 function isVector
489 "Return whether the type is a vector type or not, i.e. a 1-dimensional array."
490 input Type ty;
491 output Boolean isVector;
492 algorithm
493 isVector := match ty
494 case ARRAY(dimensions = {_}) then true;
495 ✗ case CONDITIONAL_ARRAY() then isVector(ty.trueType);
496 else false;
497 end match;
498 end isVector;
499
500 function isMatrix
501 input Type ty;
502 output Boolean isMatrix;
503 algorithm
504 isMatrix := match ty
505 case ARRAY(dimensions = {_, _}) then true;
506 ✗ case CONDITIONAL_ARRAY() then isMatrix(ty.trueType);
507 else false;
508 end match;
509 end isMatrix;
510
511 function isSquareMatrix
512 input Type ty;
513 output Boolean isSquareMatrix;
514 algorithm
515 isSquareMatrix := match ty
516 local
517 Dimension d1, d2;
518
519 26 case ARRAY(dimensions = {d1, d2}) then Dimension.isEqualKnown(d1, d2);
520 ✗ case CONDITIONAL_ARRAY() then isSquareMatrix(ty.trueType);
521 else false;
522 end match;
523 end isSquareMatrix;
524
525 function isEmptyArray
526 input Type ty;
527 output Boolean isEmpty;
528 algorithm
529 isEmpty := match ty
530 339529 case ARRAY() then List.any(ty.dimensions, Dimension.isZero);
531 ✗ case CONDITIONAL_ARRAY() then isEmptyArray(ty.trueType);
532 else false;
533 end match;
534 end isEmptyArray;
535
536 function isSingleElementArray
537 input Type ty;
538 output Boolean isSingleElement;
539 algorithm
540 isSingleElement := match ty
541 local
542 Dimension d;
543
544 case ARRAY(dimensions = {d})
545
4/4
✓ Branch 1 taken 94 times.
✓ Branch 2 taken 16 times.
✓ Branch 4 taken 42 times.
✓ Branch 5 taken 52 times.
110 then Dimension.isKnown(d) and Dimension.size(d) == 1;
546
547 else false;
548 end match;
549 end isSingleElementArray;
550
551 function isEnumeration
552 input Type ty;
553 output Boolean isEnum;
554 algorithm
555 isEnum := match ty
556 case ENUMERATION() then true;
557 else false;
558 end match;
559 end isEnumeration;
560
561 function isBuiltinEnumeration
562 input Type ty;
563 output Boolean isBuiltin;
564 protected
565 String name;
566 algorithm
567 isBuiltin := match ty
568 case ENUMERATION(typePath = Absyn.Path.IDENT(name))
569 then match name
570 case "StateSelect" then true;
571 case "AssertionLevel" then true;
572 else false;
573 end match;
574
575 else false;
576 end match;
577 end isBuiltinEnumeration;
578
579 function isUnspecifiedEnumeration
580 input Type ty;
581 output Boolean res;
582 algorithm
583 res := match ty
584 case ENUMERATION(literals = {}) then true;
585 else false;
586 end match;
587 end isUnspecifiedEnumeration;
588
589 function isComplex
590 input Type ty;
591 output Boolean isComplex;
592 algorithm
593 isComplex := match ty
594 case COMPLEX() then true;
595 else false;
596 end match;
597 end isComplex;
598
599 function isComplexArray
600 input Type ty;
601 output Boolean isComplex;
602 algorithm
603 isComplex := match ty
604 ✗ case ARRAY() then isComplex(ty.elementType);
605 else false;
606 end match;
607 end isComplexArray;
608
609 function complexNode
610 input Type ty;
611 output InstNode node;
612 protected
613 NFInstNode.ScopeRef cell;
614 algorithm
615
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2910631 times.
2910631 COMPLEX(cls = cell) := ty;
616 2910631 node := InstNode.borrow(cell);
617 end complexNode;
618
619 function complexComponents
620 input Type ty;
621 output array<InstNode> comps;
622 algorithm
623 10 comps := ClassTree.getComponents(Class.classTree(InstNode.getClass(complexNode(ty))));
624 end complexComponents;
625
626 function isConnector
627 input Type ty;
628 output Boolean isConnector;
629 algorithm
630 isConnector := match ty
631 case COMPLEX(complexTy = ComplexType.CONNECTOR()) then true;
632 else false;
633 end match;
634 end isConnector;
635
636 function isStreamConnector
637 input Type ty;
638 output Boolean isStreamConnector;
639 algorithm
640 isStreamConnector := match ty
641 case COMPLEX(complexTy = ComplexType.CONNECTOR(streams = _ :: _)) then true;
642 else false;
643 end match;
644 end isStreamConnector;
645
646 function isExpandableConnector
647 input Type ty;
648 output Boolean isExpandable;
649 algorithm
650 isExpandable := match ty
651 case COMPLEX(complexTy = ComplexType.EXPANDABLE_CONNECTOR()) then true;
652 else false;
653 end match;
654 end isExpandableConnector;
655
656 function isExternalObject
657 input Type ty;
658 output Boolean isEO;
659 algorithm
660 isEO := match ty
661 case COMPLEX(complexTy = ComplexType.EXTERNAL_OBJECT()) then true;
662 else false;
663 end match;
664 end isExternalObject;
665
666 function isRecord
667 input Type ty;
668 output Boolean isRecord;
669 algorithm
670 isRecord := match ty
671 case COMPLEX(complexTy = ComplexType.RECORD()) then true;
672 else false;
673 end match;
674 end isRecord;
675
676 function isBasic
677 input Type ty;
678 output Boolean isNumeric;
679 algorithm
680 isNumeric := match ty
681 case REAL() then true;
682 case INTEGER() then true;
683 case BOOLEAN() then true;
684 case STRING() then true;
685 case ENUMERATION() then true;
686 case CLOCK() then true;
687 ✗ case FUNCTION() then isBasic(Function.returnType(ty.fn));
688 else false;
689 end match;
690 end isBasic;
691
692 function isBasicNumeric
693 input Type ty;
694 output Boolean isNumeric;
695 algorithm
696 isNumeric := match ty
697 case REAL() then true;
698 case INTEGER() then true;
699 else false;
700 end match;
701 end isBasicNumeric;
702
703 function isNumeric
704 input Type ty;
705 output Boolean isNumeric;
706 algorithm
707 isNumeric := match ty
708 1063 case ARRAY() then isBasicNumeric(ty.elementType);
709 ✗ case CONDITIONAL_ARRAY() then isNumeric(ty.trueType);
710 34202 else isBasicNumeric(ty);
711 end match;
712 end isNumeric;
713
714 function isScalarBuiltin
715 "Returns true for all the builtin scalar types such as Integer, Real, etc."
716 input Type ty;
717 output Boolean isScalarBuiltin;
718 algorithm
719 isScalarBuiltin := match ty
720 case INTEGER() then true;
721 case REAL() then true;
722 case STRING() then true;
723 case BOOLEAN() then true;
724 case CLOCK() then true;
725 case ENUMERATION() then true;
726 ✗ case FUNCTION() then isScalarBuiltin(Function.returnType(ty.fn));
727 else false;
728 end match;
729 end isScalarBuiltin;
730
731 function isTuple
732 input Type ty;
733 output Boolean isTuple;
734 algorithm
735 isTuple := match ty
736 case TUPLE() then true;
737 else false;
738 end match;
739 end isTuple;
740
741 function isUnknown
742 input Type ty;
743 output Boolean isUnknown;
744 algorithm
745 isUnknown := match ty
746 case UNKNOWN() then true;
747 else false;
748 end match;
749 end isUnknown;
750
751 function isKnown
752 input Type ty;
753 output Boolean isKnown;
754 algorithm
755 isKnown := match ty
756 case UNKNOWN() then false;
757 case UNTYPED() then false;
758 else true;
759 end match;
760 end isKnown;
761
762 function isPolymorphic
763 input Type ty;
764 output Boolean isPolymorphic;
765 algorithm
766 isPolymorphic := match ty
767 case POLYMORPHIC() then true;
768 else false;
769 end match;
770 end isPolymorphic;
771
772 function isPolymorphicNamed
773 input Type ty;
774 input String name;
775 output Boolean res;
776 algorithm
777 res := match ty
778
3/4
✓ Branch 0 taken 1895 times.
✓ Branch 1 taken 1706 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1895 times.
3601 case POLYMORPHIC() then name == ty.name;
779 else false;
780 end match;
781 end isPolymorphicNamed;
782
783 function firstTupleType
784 input Type ty;
785 output Type outTy;
786 algorithm
787 outTy := match ty
788 65 case TUPLE() then listHead(ty.types);
789 ✗ case ARRAY() then Type.ARRAY(firstTupleType(ty.elementType), ty.dimensions);
790 else ty;
791 end match;
792 end firstTupleType;
793
794 function nthTupleType
795 input Type ty;
796 input Integer n;
797 output Type outTy;
798 algorithm
799 outTy := match ty
800 1864 case TUPLE() then listGet(ty.types, n);
801 ✗ case ARRAY() then Type.ARRAY(nthTupleType(ty.elementType, n), ty.dimensions);
802 else ty;
803 end match;
804 end nthTupleType;
805
806 function arrayElementType
807 "Returns the common type of the elements in an array, or just the type
808 itself if it's not an array type."
809 input Type ty;
810 output Type elementTy;
811 algorithm
812 elementTy := match ty
813 1601436 case ARRAY() then ty.elementType;
814 51 case CONDITIONAL_ARRAY() then arrayElementType(ty.trueType);
815 4 case UNTYPED() guard not arrayEmpty(ty.dimensions) then UNTYPED(ty.typeNode, listArray({}));
816 else ty;
817 end match;
818 end arrayElementType;
819
820 function setArrayElementType
821 "Sets the common type of the elements in an array, if the type is an array
822 type. Otherwise it just returns the given element type."
823 input Type arrayTy;
824 input Type elementTy;
825 output Type ty;
826 algorithm
827 ty := match arrayTy
828 82636 case ARRAY() then liftArrayLeftList(elementTy, arrayTy.dimensions);
829 case CONDITIONAL_ARRAY()
830 ✗ then CONDITIONAL_ARRAY(setArrayElementType(arrayTy.trueType, elementTy),
831 setArrayElementType(arrayTy.falseType, elementTy),
832 arrayTy.matchedBranch);
833 else elementTy;
834 end match;
835 end setArrayElementType;
836
837 function elementType
838 input Type ty;
839 output Type elementTy;
840 algorithm
841 elementTy := match ty
842 299 case ARRAY() then ty.elementType;
843 ✗ case CONDITIONAL_ARRAY() then elementType(ty.trueType);
844 ✗ case FUNCTION() then elementType(Function.returnType(ty.fn));
845 else ty;
846 end match;
847 end elementType;
848
849 function copyElementType
850 "Sets the element type of the destination type to the element type of the
851 source type."
852 input Type dstType;
853 input Type srcType;
854 output Type ty;
855 algorithm
856 171 ty := setArrayElementType(dstType, arrayElementType(srcType));
857 end copyElementType;
858
859 function arrayDims
860 input Type ty;
861 output list<Dimension> dims;
862 algorithm
863 dims := match ty
864 1266565 case ARRAY() then ty.dimensions;
865 2 case FUNCTION() then arrayDims(Function.returnType(ty.fn));
866 1 case METABOXED() then arrayDims(ty.ty);
867 ✗ case CONDITIONAL_ARRAY() then List.fill(Dimension.UNKNOWN(), dimensionCount(ty.trueType));
868 282774 case UNTYPED() then arrayList(ty.dimensions);
869 else {};
870 end match;
871 end arrayDims;
872
873 function copyDims
874 "Copies array dimensions from one type to another, discarding the existing
875 dimensions of the destination type but keeping its element type."
876 input Type srcType;
877 input Type dstType;
878 output Type ty;
879 algorithm
880
2/2
✓ Branch 1 taken 75341 times.
✓ Branch 2 taken 1631 times.
76972 if listEmpty(arrayDims(srcType)) then
881 75341 ty := arrayElementType(dstType);
882 else
883 ty := match dstType
884 case ARRAY()
885 441 then ARRAY(dstType.elementType, arrayDims(srcType));
886
887 1190 else ARRAY(dstType, arrayDims(srcType));
888 end match;
889 end if;
890 end copyDims;
891
892 function applyToDims
893 input output Type ty;
894 input dimFunc func;
895 partial function dimFunc
896 input output Dimension dim;
897 end dimFunc;
898 algorithm
899 ty := match ty
900 local
901 Function fn;
902
6/6
✓ Branch 0 taken 64603 times.
✓ Branch 1 taken 57403 times.
✓ Branch 2 taken 64603 times.
✓ Branch 3 taken 57403 times.
✓ Branch 4 taken 64015 times.
✓ Branch 5 taken 588 times.
179409 case ARRAY() algorithm ty.dimensions := list(func(d) for d in ty.dimensions); then ty;
903 140 case FUNCTION(fn = fn) algorithm fn.returnType := applyToDims(fn.returnType, func); ty.fn := fn; then ty;
904 ✗ case METABOXED() algorithm ty.ty := applyToDims(ty.ty, func); then ty;
905 ✗ case CONDITIONAL_ARRAY() algorithm ty.trueType := applyToDims(ty.trueType, func); then ty;
906 case UNTYPED() algorithm
907 ✗ for i in 1:arrayLength(ty.dimensions) loop
908 ✗ arrayUpdate(ty.dimensions, i, func(ty.dimensions[i]));
909 end for;
910 then ty;
911 else ty;
912 end match;
913 end applyToDims;
914
915 function nthDimension
916 input Type ty;
917 input Integer index;
918 output Dimension dim;
919 algorithm
920 dim := match ty
921 114666 case ARRAY() then listGet(ty.dimensions, index);
922 ✗ case CONDITIONAL_ARRAY() then nthDimension(matchedConditionalArrayType(ty), index);
923 ✗ case FUNCTION() then nthDimension(Function.returnType(ty.fn), index);
924 ✗ case METABOXED() then nthDimension(ty.ty, index);
925 end match;
926 end nthDimension;
927
928 function dimensionCount
929 input Type ty;
930 output Integer dimCount;
931 algorithm
932 dimCount := match ty
933 1049337 case ARRAY() then listLength(ty.dimensions);
934 ✗ case CONDITIONAL_ARRAY() then dimensionCount(ty.trueType);
935 ✗ case FUNCTION() then dimensionCount(Function.returnType(ty.fn));
936 ✗ case METABOXED() then dimensionCount(ty.ty);
937
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5559 times.
5559 case UNTYPED() then arrayLength(ty.dimensions);
938 else 0;
939 end match;
940 end dimensionCount;
941
942 function dimensionDiff
943 input Type ty1;
944 input Type ty2;
945 output Integer diff = dimensionCount(ty1) - dimensionCount(ty2);
946 end dimensionDiff;
947
948 function hasKnownSize
949 input Type ty;
950 output Boolean isKnown;
951 algorithm
952 isKnown := match ty
953 119900 case ARRAY() then List.all(ty.dimensions, function Dimension.isKnown(allowExp = false));
954 case CONDITIONAL_ARRAY() then false;
955 ✗ case FUNCTION() then hasKnownSize(Function.returnType(ty.fn));
956 else true;
957 end match;
958 end hasKnownSize;
959
960 function hasZeroDimension
961 input Type ty;
962 output Boolean hasZero;
963 algorithm
964 hasZero := match ty
965 26219 case ARRAY() then List.any(ty.dimensions, Dimension.isZero);
966 ✗ case CONDITIONAL_ARRAY() then hasZeroDimension(ty.trueType) and hasZeroDimension(ty.falseType);
967 else false;
968 end match;
969 end hasZeroDimension;
970
971 function mapDims
972 input output Type ty;
973 input FuncT func;
974
975 partial function FuncT
976 input output Dimension dim;
977 end FuncT;
978 algorithm
979 () := match ty
980 local
981 Function fn;
982
983 case ARRAY()
984 algorithm
985
6/6
✓ Branch 0 taken 1245951 times.
✓ Branch 1 taken 1010032 times.
✓ Branch 2 taken 1245951 times.
✓ Branch 3 taken 1010032 times.
✓ Branch 4 taken 1200251 times.
✓ Branch 5 taken 45700 times.
3266015 ty.dimensions := list(func(d) for d in ty.dimensions);
986 then
987 ();
988
989 case TUPLE()
990 algorithm
991
4/4
✓ Branch 0 taken 2640 times.
✓ Branch 1 taken 1182 times.
✓ Branch 2 taken 2640 times.
✓ Branch 3 taken 1182 times.
5004 ty.types := list(mapDims(t, func) for t in ty.types);
992 then
993 ();
994
995 case FUNCTION(fn = fn)
996 algorithm
997 156 ty.fn := Function.setReturnType(mapDims(Function.returnType(fn), func), fn);
998 then
999 ();
1000
1001 case METABOXED()
1002 algorithm
1003 248 ty.ty := mapDims(ty.ty, func);
1004 then
1005 ();
1006
1007 case CONDITIONAL_ARRAY()
1008 algorithm
1009 48 ty.trueType := mapDims(ty.trueType, func);
1010 48 ty.falseType := mapDims(ty.falseType, func);
1011 then
1012 ();
1013
1014 else ();
1015 end match;
1016 end mapDims;
1017
1018 function foldDims<ArgT>
1019 input Type ty;
1020 input FuncT func;
1021 input output ArgT arg;
1022
1023 partial function FuncT
1024 input Dimension dim;
1025 input output ArgT arg;
1026 end FuncT;
1027 algorithm
1028 arg := match ty
1029 38410 case ARRAY() then List.fold(ty.dimensions, func, arg);
1030 ✗ case TUPLE() then List.fold(ty.types, function foldDims(func = func), arg);
1031 56 case FUNCTION() then foldDims(Function.returnType(ty.fn), func, arg);
1032 112 case METABOXED() then foldDims(ty.ty, func, arg);
1033 else arg;
1034 end match;
1035 end foldDims;
1036
1037 function nthEnumLiteral
1038 input Type ty;
1039 input Integer index;
1040 output String literal;
1041 protected
1042 list<String> literals;
1043 algorithm
1044 ✗ ENUMERATION(literals = literals) := ty;
1045 ✗ literal := listGet(literals, index);
1046 end nthEnumLiteral;
1047
1048 function toString
1049 input Type ty;
1050 output String str;
1051 algorithm
1052 str := match ty
1053 case Type.INTEGER() then "Integer";
1054 case Type.REAL() then "Real";
1055 case Type.STRING() then "String";
1056 case Type.BOOLEAN() then "Boolean";
1057 case Type.CLOCK() then "Clock";
1058
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 4161 times.
4198 case Type.ENUMERATION() then if listEmpty(ty.literals) then "enumeration(:)" else "enumeration " + AbsynUtil.pathString(ty.typePath) +
1059 "(" + stringDelimitList(ty.literals, ", ") + ")";
1060 2201 case Type.ARRAY() then List.toStringCustom(ty.dimensions, Dimension.toString, toString(ty.elementType), "[", ", ", "]", false);
1061 70 case Type.TUPLE() then "(" + stringDelimitList(List.map(ty.types, toString), ", ") + ")";
1062 case Type.NORETCALL() then "()";
1063 case Type.UNKNOWN() then "unknown()";
1064 2097 case Type.COMPLEX() then AbsynUtil.pathString(InstNode.scopePath(complexNode(ty)));
1065 2 case Type.FUNCTION() then Function.typeString(ty.fn);
1066 2 case Type.METABOXED() then toString(ty.ty);
1067 case Type.POLYMORPHIC()
1068 ✗ then if StringUtil.startsWith(ty.name, "__") then
1069 substring(ty.name, 3, stringLength(ty.name)) else "<" + ty.name + ">";
1070
1071 case Type.ANY() then "$ANY$";
1072 ✗ case Type.CONDITIONAL_ARRAY() then toString(ty.trueType) + "|" + toString(ty.falseType);
1073 ✗ case Type.UNTYPED() then Array.toString(ty.dimensions, Dimension.toString, InstNode.name(ty.typeNode), "[", ", ", "]", false);
1074 else
1075 algorithm
1076 ✗ Error.terminate(getInstanceName() + " got unknown type: " + anyString(ty), sourceInfo());
1077 ✗ then
1078 fail();
1079 end match;
1080 end toString;
1081
1082 function toFlatString
1083 input Type ty;
1084 input BaseModelica.OutputFormat format;
1085 output String str;
1086 algorithm
1087 str := match ty
1088 case Type.INTEGER() then "Integer";
1089 case Type.REAL() then "Real";
1090 case Type.STRING() then "String";
1091 case Type.BOOLEAN() then "Boolean";
1092 case Type.CLOCK() then "Clock";
1093 case Type.ENUMERATION()
1094
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 then if listEmpty(ty.literals) then "enumeration(:)"
1095 elseif Type.isBuiltinEnumeration(ty) then AbsynUtil.pathString(ty.typePath)
1096 else Util.makeQuotedIdentifier(AbsynUtil.pathString(ty.typePath));
1097 ✗ case Type.ARRAY() then Dimension.toFlatStringList(ty.dimensions, format, toFlatString(ty.elementType, format));
1098 ✗ case Type.TUPLE() then "(" + stringDelimitList(List.map(ty.types, function toFlatString(format = format)), ", ") + ")";
1099 case Type.NORETCALL() then "()";
1100 case Type.UNKNOWN() then "unknown()";
1101 272 case Type.COMPLEX() then Util.makeQuotedIdentifier(AbsynUtil.pathString(InstNode.scopePath(complexNode(ty))));
1102 ✗ case Type.FUNCTION() then Util.makeQuotedIdentifier(AbsynUtil.pathString(InstNode.scopePath(InstNode.fromHandle(ty.fn.node))));
1103 ✗ case Type.METABOXED() then toFlatString(ty.ty, format);
1104 ✗ case Type.POLYMORPHIC() then "<" + ty.name + ">";
1105 case Type.ANY() then "$ANY$";
1106 ✗ case Type.CONDITIONAL_ARRAY() then toFlatString(ty.trueType, format) + "|" + toFlatString(ty.falseType, format);
1107 ✗ case Type.UNTYPED() then Array.toString(ty.dimensions, function Dimension.toFlatString(format = format), InstNode.name(ty.typeNode), "[", ", ", "]", false);
1108 else
1109 algorithm
1110 ✗ Error.terminate(getInstanceName() + " got unknown type: " + anyString(ty), sourceInfo());
1111 ✗ then
1112 fail();
1113 end match;
1114 end toFlatString;
1115
1116 function dimensionsToFlatString
1117 input Type ty;
1118 input BaseModelica.OutputFormat format;
1119 output String str;
1120 algorithm
1121 str := match ty
1122 ✗ case Type.ARRAY() then stringDelimitList(List.map(ty.dimensions, function Dimension.toFlatString(format = format)), ", ");
1123 else
1124 algorithm
1125 ✗ Error.terminate(getInstanceName() + " got unknown or not array type: " + anyString(ty), sourceInfo());
1126 ✗ then
1127 fail();
1128 end match;
1129 end dimensionsToFlatString;
1130
1131 function toFlatDeclarationStream
1132 input Type ty;
1133 input BaseModelica.OutputFormat format;
1134 input String indent;
1135 input output IOStream.IOStream s;
1136 protected
1137 String name;
1138 ComplexType complexTy;
1139 Absyn.Path path;
1140 InstNode constructor, destructor;
1141 Function f;
1142 algorithm
1143 s := match ty
1144 case ENUMERATION()
1145 algorithm
1146 2 s := IOStream.append(s, indent);
1147 2 s := IOStream.append(s, "type ");
1148 2 s := IOStream.append(s, Util.makeQuotedIdentifier(AbsynUtil.pathString(ty.typePath)));
1149 2 s := IOStream.append(s, " = enumeration(");
1150
4/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 2 times.
8 s := IOStream.append(s, stringDelimitList(list(Util.makeQuotedIdentifier(l) for l in ty.literals), ", "));
1151 2 s := IOStream.append(s, ")");
1152 then
1153 s;
1154
1155 case COMPLEX(complexTy = ComplexType.RECORD())
1156 26 then Record.toFlatDeclarationStream(complexNode(ty), format, indent, s);
1157
1158 case COMPLEX(complexTy = complexTy as ComplexType.EXTERNAL_OBJECT())
1159 algorithm
1160 ✗ path := InstNode.scopePath(complexNode(ty));
1161 ✗ name := Util.makeQuotedIdentifier(AbsynUtil.pathString(path));
1162 ✗ s := IOStream.append(s, indent);
1163 ✗ s := IOStream.append(s, "class ");
1164 ✗ s := IOStream.append(s, name);
1165 ✗ s := IOStream.append(s, "\n extends ExternalObject;\n\n");
1166 ✗ {f} := Function.typeNodeCache(InstNode.borrow(complexTy.constructor));
1167 ✗ s := Function.toFlatStream(f, format, indent + " ", s, overrideName="constructor");
1168 ✗ s := IOStream.append(s, ";\n\n");
1169 ✗ {f} := Function.typeNodeCache(InstNode.borrow(complexTy.destructor));
1170 ✗ s := Function.toFlatStream(f, format, indent + " ", s, overrideName="destructor");
1171 ✗ s := IOStream.append(s, ";\n\nend ");
1172 ✗ s := IOStream.append(s, name);
1173 then s;
1174
1175 case FUNCTION()
1176 ✗ then Function.toFlatStream(ty.fn, format, indent, s,
1177 overrideName = Util.makeQuotedIdentifier(AbsynUtil.pathString(InstNode.scopePath(InstNode.fromHandle(ty.fn.node)))));
1178
1179 else s;
1180 end match;
1181 end toFlatDeclarationStream;
1182
1183 function typenameString
1184 input Type ty;
1185 output String str;
1186 algorithm
1187 str := match ty
1188 1 case Type.ENUMERATION() then AbsynUtil.pathString(ty.typePath);
1189 ✗ else toString(ty);
1190 end match;
1191 end typenameString;
1192
1193 function toDAE
1194 input Type ty;
1195 input Boolean makeTypeVars = true;
1196 output DAE.Type daeTy;
1197 algorithm
1198 daeTy := match ty
1199 case Type.INTEGER() then DAE.T_INTEGER_DEFAULT;
1200 case Type.REAL() then DAE.T_REAL_DEFAULT;
1201 case Type.STRING() then DAE.T_STRING_DEFAULT;
1202 case Type.BOOLEAN() then DAE.T_BOOL_DEFAULT;
1203 13849 case Type.ENUMERATION() then DAE.T_ENUMERATION(NONE(), ty.typePath, ty.literals, {}, {});
1204 case Type.CLOCK() then DAE.T_CLOCK_DEFAULT;
1205 case Type.ARRAY()
1206
4/4
✓ Branch 0 taken 1064468 times.
✓ Branch 1 taken 900827 times.
✓ Branch 2 taken 1064468 times.
✓ Branch 3 taken 900827 times.
1965295 then DAE.T_ARRAY(toDAE(ty.elementType, makeTypeVars),
1207 list(Dimension.toDAE(d) for d in ty.dimensions));
1208 case Type.TUPLE()
1209
4/4
✓ Branch 0 taken 3871 times.
✓ Branch 1 taken 1744 times.
✓ Branch 2 taken 3871 times.
✓ Branch 3 taken 1744 times.
5615 then DAE.T_TUPLE(list(toDAE(t) for t in ty.types), ty.names);
1210 case Type.FUNCTION()
1211 then match ty.fnType
1212 case FunctionType.FUNCTIONAL_PARAMETER
1213 78 then Function.makeDAEType(ty.fn);
1214 case FunctionType.FUNCTION_REFERENCE
1215
1/2
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
48 then DAE.T_FUNCTION_REFERENCE_FUNC(Function.isBuiltin(ty.fn), Function.makeDAEType(ty.fn));
1216 case FunctionType.FUNCTIONAL_VARIABLE
1217 66 then DAE.T_FUNCTION_REFERENCE_VAR(Function.makeDAEType(ty.fn, true));
1218 end match;
1219 case Type.NORETCALL() then DAE.T_NORETCALL_DEFAULT;
1220 case Type.UNKNOWN() then DAE.T_UNKNOWN_DEFAULT;
1221 case Type.COMPLEX()
1222
2/2
✓ Branch 0 taken 71081 times.
✓ Branch 1 taken 2492650 times.
2563731 then if makeTypeVars then InstNode.toFullDAEType(complexNode(ty)) else InstNode.toPartialDAEType(complexNode(ty));
1223 459 case Type.METABOXED() then DAE.T_METABOXED(toDAE(ty.ty));
1224 ✗ case Type.POLYMORPHIC() then DAE.T_METAPOLYMORPHIC(ty.name);
1225 case Type.ANY() then DAE.T_ANYTYPE(NONE());
1226 else
1227 algorithm
1228 ✗ Error.terminate(getInstanceName() + " got unknown type: " + anyString(ty), sourceInfo());
1229 ✗ then
1230 fail();
1231 end match;
1232 end toDAE;
1233
1234 function subscript
1235 "Reduces a type's dimensions based on the given list of subscripts."
1236 input output Type ty;
1237 input list<Subscript> subs;
1238 input Boolean failOnError = true;
1239 protected
1240 Dimension dim;
1241 list<Dimension> dims, subbed_dims = {};
1242 Type el_ty;
1243 algorithm
1244
2/2
✓ Branch 0 taken 3562957 times.
✓ Branch 1 taken 1167224 times.
4730181 if listEmpty(subs) then
1245 3562957 return;
1246 end if;
1247
1248 ty := match ty
1249 case ARRAY(dimensions = dims)
1250 guard not failOnError and listLength(subs) > listLength(dims)
1251 then Type.UNKNOWN();
1252
1253 case ARRAY(dimensions = dims)
1254 algorithm
1255
2/2
✓ Branch 0 taken 1373871 times.
✓ Branch 1 taken 1167219 times.
2541090 for sub in subs loop
1256
5/7
✗ Branch 0 not taken.
✓ Branch 1 taken 1373871 times.
✓ Branch 2 taken 1141351 times.
✓ Branch 3 taken 7673 times.
✓ Branch 4 taken 43275 times.
✓ Branch 5 taken 181572 times.
✗ Branch 6 not taken.
1373871 dim :: dims := dims;
1257
1258 subbed_dims := match sub
1259 case Subscript.INDEX() then subbed_dims;
1260 7673 case Subscript.SLICE() then Subscript.toDimension(sub) :: subbed_dims;
1261 case Subscript.WHOLE() then dim :: subbed_dims;
1262 case Subscript.SPLIT_INDEX() then subbed_dims;
1263 else algorithm
1264 ✗ Error.terminate(getInstanceName() + " got wrong subscript " + Subscript.toString(sub) + "\n", sourceInfo());
1265 ✗ then fail();
1266 end match;
1267 end for;
1268
1269 1167219 el_ty := arrayElementType(ty);
1270
4/4
✓ Branch 0 taken 1116307 times.
✓ Branch 1 taken 50912 times.
✓ Branch 2 taken 2648 times.
✓ Branch 3 taken 1113659 times.
1167219 then
1271 if not (listEmpty(subbed_dims) and listEmpty(dims)) then
1272 ARRAY(el_ty, listAppend(listReverse(subbed_dims), dims))
1273 else
1274 el_ty;
1275
1276 case CONDITIONAL_ARRAY()
1277 2 then CONDITIONAL_ARRAY(subscript(ty.trueType, subs),
1278 subscript(ty.falseType, subs),
1279 ty.matchedBranch);
1280
1281 ✗ case METABOXED() then METABOXED(subscript(ty.ty, subs));
1282 case UNKNOWN() then ty;
1283
1284 else
1285 algorithm
1286
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if failOnError then
1287 ✗ Error.terminate(getInstanceName() +
1288 " got unsubscriptable type " + toString(ty) + "\n", sourceInfo());
1289 ✗ fail();
1290 end if;
1291 then
1292 Type.UNKNOWN();
1293
1294 end match;
1295 end subscript;
1296
1297 function isEqual
1298 input Type ty1;
1299 input Type ty2;
1300 output Boolean equal;
1301 algorithm
1302
2/2
✓ Branch 0 taken 32065 times.
✓ Branch 1 taken 56291 times.
88356 if referenceEq(ty1, ty2) then
1303 equal := true;
1304 32065 return;
1305 end if;
1306
1307
2/2
✓ Branch 0 taken 55080 times.
✓ Branch 1 taken 1211 times.
56291 if valueConstructor(ty1) <> valueConstructor(ty2) then
1308 equal := false;
1309 55080 return;
1310 end if;
1311
1312 equal := match (ty1, ty2)
1313 local
1314 list<String> names1, names2;
1315
1316 case (ENUMERATION(), ENUMERATION())
1317 ✗ then List.isEqualOnTrue(ty1.literals, ty2.literals, stringEq);
1318
1319 case (ARRAY(), ARRAY())
1320
3/4
✓ Branch 1 taken 139 times.
✓ Branch 2 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 139 times.
143 then isEqual(ty1.elementType, ty2.elementType) and
1321 List.isEqualOnTrue(ty1.dimensions, ty2.dimensions, Dimension.isEqualKnown);
1322
1323 case (CONDITIONAL_ARRAY(), CONDITIONAL_ARRAY())
1324 ✗ then isEqual(ty1.trueType, ty2.trueType) and isEqual(ty1.falseType, ty2.falseType);
1325
1326 case (TUPLE(names = SOME(names1)), TUPLE(names = SOME(names2)))
1327 ✗ then List.isEqualOnTrue(names1, names2, stringEq) and
1328 List.isEqualOnTrue(ty1.types, ty2.types, isEqual);
1329
1330 case (TUPLE(names = NONE()), TUPLE(names = NONE()))
1331 ✗ then List.isEqualOnTrue(ty1.types, ty2.types, isEqual);
1332
1333 case (TUPLE(), TUPLE()) then false;
1334 1065 case (COMPLEX(), COMPLEX()) then InstNode.isSame(complexNode(ty1), complexNode(ty2));
1335
1336 case (UNTYPED(), UNTYPED())
1337
2/4
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
3 then InstNode.isSame(ty1.typeNode, ty2.typeNode) and
1338 Array.isEqualOnTrue(ty1.dimensions, ty2.dimensions, Dimension.isEqualKnown);
1339
1340 else true;
1341 end match;
1342 end isEqual;
1343
1344 function hashContinue
1345 input Type ty;
1346 input output Integer hash;
1347 algorithm
1348 hash := match ty
1349 ✗ case Type.INTEGER() then stringHashDjb2Continue("Integer", hash);
1350 183 case Type.REAL() then stringHashDjb2Continue("Real", hash);
1351 ✗ case Type.STRING() then stringHashDjb2Continue("String", hash);
1352 ✗ case Type.BOOLEAN() then stringHashDjb2Continue("Boolean", hash);
1353 ✗ case Type.CLOCK() then stringHashDjb2Continue("Clock", hash);
1354
1355 case Type.ENUMERATION()
1356 algorithm
1357 ✗ if listEmpty(ty.literals) then
1358 ✗ hash := stringHashDjb2Continue("enumeration(:)", hash);
1359 else
1360 ✗ hash := stringHashDjb2Continue("enumeration", hash);
1361 ✗ hash := AbsynUtil.pathHashContinue(ty.typePath, hash);
1362 ✗ hash := stringHashDjb2Continue("(", hash);
1363 ✗ for lit in ty.literals loop
1364 ✗ hash := stringHashDjb2Continue(lit, hash);
1365 ✗ hash := stringHashDjb2Continue(", ", hash); // trailing comma, don't care...
1366 end for;
1367 ✗ hash := stringHashDjb2Continue(")", hash);
1368 end if;
1369 then hash;
1370
1371 case Type.ARRAY()
1372 algorithm
1373 8 hash := hashContinue(ty.elementType, hash);
1374 8 hash := stringHashDjb2Continue("[", hash);
1375
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
16 for dim in ty.dimensions loop
1376 8 hash := stringHashDjb2Continue(Dimension.toString(dim), hash); // TODO use Dimension.hashContinue
1377 8 hash := stringHashDjb2Continue(", ", hash); // trailing comma, don't care...
1378 end for;
1379 8 hash := stringHashDjb2Continue("]", hash);
1380 then hash;
1381
1382 case Type.TUPLE()
1383 algorithm
1384 ✗ hash := stringHashDjb2Continue("(", hash);
1385 ✗ for t in ty.types loop
1386 ✗ hash := hashContinue(t, hash);
1387 ✗ hash := stringHashDjb2Continue(", ", hash); // trailing comma, don't care...
1388 end for;
1389 ✗ hash := stringHashDjb2Continue(")", hash);
1390 then hash;
1391
1392 ✗ case Type.NORETCALL() then stringHashDjb2Continue("()", hash);
1393 ✗ case Type.UNKNOWN() then stringHashDjb2Continue("unknown()", hash);
1394 ✗ case Type.COMPLEX() then AbsynUtil.pathHashContinue(InstNode.scopePath(complexNode(ty)), hash);
1395 ✗ case Type.FUNCTION() then stringHashDjb2Continue(Function.typeString(ty.fn), hash); // TODO use Functino.hashContinue
1396 ✗ case Type.METABOXED() then hashContinue(ty.ty, hash);
1397 ✗ case Type.POLYMORPHIC() then stringHashDjb2Continue(ty.name, hash);
1398 ✗ case Type.ANY() then stringHashDjb2Continue("$ANY$", hash);
1399
1400 case Type.CONDITIONAL_ARRAY()
1401 algorithm
1402 ✗ hash := hashContinue(ty.trueType, hash);
1403 ✗ hash := hashContinue(ty.falseType, hash);
1404 then hash;
1405
1406 case Type.UNTYPED()
1407 algorithm
1408 ✗ hash := InstNode.hashContinue(ty.typeNode, hash);
1409 ✗ hash := stringHashDjb2Continue("[", hash);
1410 ✗ for dim in ty.dimensions loop
1411 ✗ hash := stringHashDjb2Continue(Dimension.toString(dim), hash); // TODO use Dimension.hashContinue
1412 ✗ hash := stringHashDjb2Continue(", ", hash); // trailing comma, don't care...
1413 end for;
1414 ✗ hash := stringHashDjb2Continue("]", hash);
1415 then hash;
1416
1417 else hash;
1418 end match;
1419 end hashContinue;
1420
1421 function isDiscrete
1422 input Type ty;
1423 output Boolean isDiscrete;
1424 algorithm
1425 isDiscrete := match ty
1426 case INTEGER() then true;
1427 case STRING() then true;
1428 case BOOLEAN() then true;
1429 case ENUMERATION() then true;
1430 17669 case ARRAY() then isDiscrete(ty.elementType);
1431 ✗ case CONDITIONAL_ARRAY() then isDiscrete(ty.trueType);
1432 ✗ case FUNCTION() then isDiscrete(Function.returnType(ty.fn));
1433 else false;
1434 end match;
1435 end isDiscrete;
1436
1437 function lookupRecordFieldType
1438 input String name;
1439 input Type recordType;
1440 output Type fieldType;
1441 algorithm
1442 fieldType := match recordType
1443 case COMPLEX()
1444 128 then InstNode.getType(Class.lookupElement(name, InstNode.getClass(complexNode(recordType))));
1445 case ARRAY()
1446 ✗ then liftArrayLeftList(lookupRecordFieldType(name, recordType.elementType), recordType.dimensions);
1447 case CONDITIONAL_ARRAY()
1448 ✗ then CONDITIONAL_ARRAY(lookupRecordFieldType(name, recordType.trueType),
1449 lookupRecordFieldType(name, recordType.falseType),
1450 recordType.matchedBranch);
1451 end match;
1452 end lookupRecordFieldType;
1453
1454 function recordFieldCount
1455 input Type recordType;
1456 output Integer fieldCount;
1457 protected
1458 array<Record.Field> fields;
1459 algorithm
1460 fieldCount := match recordType
1461 case COMPLEX(complexTy = ComplexType.RECORD(fields = fields)) then arrayLength(fields);
1462 else 0;
1463 end match;
1464 end recordFieldCount;
1465
1466 function recordFields
1467 input Type recordType;
1468 output list<Record.Field> field_lst;
1469 algorithm
1470 field_lst := match recordType
1471 local
1472 array<Record.Field> fields;
1473 8603 case COMPLEX(complexTy = ComplexType.RECORD(fields = fields)) then arrayList(fields);
1474 else {};
1475 end match;
1476 end recordFields;
1477
1478 function setRecordFields
1479 input list<Record.Field> field_lst;
1480 input output Type recordType;
1481 algorithm
1482 recordType := match recordType
1483 local
1484 NFInstNode.ScopeRef rec_node;
1485 UnorderedMap<String, Integer> indexMap;
1486 array<Record.Field> fields = listArray(field_lst);
1487
1488 case COMPLEX(complexTy = ComplexType.RECORD(constructor = rec_node)) algorithm
1489 ✗ indexMap := UnorderedMap.new<Integer>(stringHashDjb2, stringEq, arrayLength(fields));
1490 ✗ updateRecordFieldsIndexMap(fields, indexMap);
1491 ✗ then COMPLEX(recordType.cls, ComplexType.RECORD(rec_node, fields, indexMap));
1492
1493 else recordType;
1494 end match;
1495 end setRecordFields;
1496
1497 function updateRecordFieldsIndexMap
1498 input array<Record.Field> fields;
1499 input UnorderedMap<String, Integer> indexMap;
1500 algorithm
1501
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 28910 times.
224981 for i in 1:arrayLength(fields) loop
1502 196063 UnorderedMap.add(Record.Field.name(fields[i]), i, indexMap);
1503 end for;
1504 end updateRecordFieldsIndexMap;
1505
1506 function tupleFieldCount
1507 input Type tupleType;
1508 output Integer fieldCount;
1509 algorithm
1510 fieldCount := match tupleType
1511 1 case TUPLE() then listLength(tupleType.types);
1512 else 0;
1513 end match;
1514 end tupleFieldCount;
1515
1516 function enumName
1517 input Type ty;
1518 output Absyn.Path name;
1519 algorithm
1520
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 462 times.
462 ENUMERATION(typePath = name) := ty;
1521 end enumName;
1522
1523 function enumSize
1524 input Type ty;
1525 output Integer size;
1526 protected
1527 list<String> literals;
1528 algorithm
1529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 ENUMERATION(literals = literals) := ty;
1530 11 size := listLength(literals);
1531 end enumSize;
1532
1533 function box
1534 input Type ty;
1535 output Type boxedType;
1536 algorithm
1537 boxedType := match ty
1538 case STRING() then ty;
1539 ✗ case TUPLE() then TUPLE(list(box(t) for t in ty.types), ty.names);
1540 case FUNCTION() then ty;
1541 case METABOXED() then ty;
1542 case POLYMORPHIC() then ty;
1543 case ANY() then ty;
1544 case CONDITIONAL_ARRAY()
1545 ✗ then CONDITIONAL_ARRAY(box(ty.trueType), box(ty.falseType), ty.matchedBranch);
1546 366 else METABOXED(ty);
1547 end match;
1548 end box;
1549
1550 function unbox
1551 input Type ty;
1552 output Type unboxedType;
1553 algorithm
1554 unboxedType := match ty
1555 539 case METABOXED() then ty.ty;
1556 else ty;
1557 end match;
1558 end unbox;
1559
1560 function isBoxed
1561 input Type ty;
1562 output Boolean isBoxed;
1563 algorithm
1564 isBoxed := match ty
1565 case METABOXED() then true;
1566 else false;
1567 end match;
1568 end isBoxed;
1569
1570 function sizeType
1571 input Type arrayTy;
1572 output Type sizeTy;
1573 algorithm
1574
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 if Type.isUnknown(arrayTy) then
1575 // Return unknown type if the type is unknown, to avoid returning Array[0]
1576 // for untyped expressions.
1577 sizeTy := Type.UNKNOWN();
1578 else
1579 24 sizeTy := Type.ARRAY(Type.INTEGER(), {Dimension.fromInteger(dimensionCount(arrayTy))});
1580 end if;
1581 end sizeType;
1582
1583 function simplify
1584 input output Type ty;
1585 algorithm
1586 () := match ty
1587 case ARRAY()
1588 algorithm
1589
4/4
✓ Branch 0 taken 356812 times.
✓ Branch 1 taken 307861 times.
✓ Branch 2 taken 356812 times.
✓ Branch 3 taken 307861 times.
972534 ty.dimensions := list(Dimension.simplify(d) for d in ty.dimensions);
1590 then
1591 ();
1592
1593 else ();
1594 end match;
1595 end simplify;
1596
1597 function sizeOf
1598 input Type ty;
1599 input Boolean resize = false;
1600 output Integer sz;
1601 function fold_comp_size
1602 input InstNode comp;
1603 input Integer sz;
1604 output Integer outSize = sz + sizeOf(InstNode.getType(comp));
1605 end fold_comp_size;
1606 algorithm
1607 sz := match ty
1608 case INTEGER() then 1;
1609 case REAL() then 1;
1610 case STRING() then 1;
1611 case BOOLEAN() then 1;
1612 case CLOCK() then 1;
1613 case ENUMERATION() then 1;
1614 44800 case ARRAY() then sizeOf(ty.elementType) * Dimension.sizesProduct(ty.dimensions, resize);
1615
4/4
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 14 times.
42 case TUPLE() then sum(sizeOf(t) for t in ty.types);
1616 case COMPLEX(complexTy = ComplexType.EXTERNAL_OBJECT()) then 1;
1617 case COMPLEX(complexTy = ComplexType.RECORD())
1618 14152 then ClassTree.foldComponents(Class.classTree(InstNode.getClass(complexNode(ty))), fold_comp_size, 0);
1619 case COMPLEX() then 1;
1620 else 0;
1621 end match;
1622 end sizeOf;
1623
1624 function complexSize
1625 "Returns the size of complex part of the type as an option.
1626 Arrays of complex will only return the size of the contained complex type.
1627 Non-complex types will return NONE()."
1628 input Type ty;
1629 input Boolean resize = false;
1630 output Option<Integer> sz;
1631 algorithm
1632 sz := match ty
1633 36473 case ARRAY() then complexSize(ty.elementType, resize);
1634 12832 case COMPLEX(complexTy = ComplexType.RECORD()) then SOME(sizeOf(ty, resize));
1635 else NONE();
1636 end match;
1637 end complexSize;
1638
1639 annotation(__OpenModelica_Interface="nf_frontend");
1640 end NFType;
1641