Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 85.9% 244 / 0 / 284
Functions: -% 0 / 1 / 1
Branches: 61.3% 141 / 0 / 230

OMCompiler/Compiler/NFFrontEnd/NFExpandExp.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 NFExpandExp
37 import Expression = NFExpression;
38
39 protected
40 import RangeIterator = NFRangeIterator;
41 import ExpressionIterator = NFExpressionIterator;
42 import Subscript = NFSubscript;
43 import Type = NFType;
44 import Call = NFCall;
45 import NFCallAttributes;
46 import Dimension = NFDimension;
47 import ComponentRef = NFComponentRef;
48 import NFFunction.Function;
49 import Operator = NFOperator;
50 import Ceval = NFCeval;
51 import NFInstNode.InstNode;
52 import SimplifyExp = NFSimplifyExp;
53 import NFPrefixes.{Variability, Purity};
54 import MetaModelica.Dangerous.*;
55 import Absyn;
56 import EvalTarget = NFCeval.EvalTarget;
57 import Array;
58 import Util;
59 import List;
60
61 public
62 function expand
63 input output Expression exp;
64 input Boolean backend = false;
65 input Boolean resize = false;
66 output Boolean expanded;
67 algorithm
68 (exp, expanded) := match exp
69 local
70 array<Expression> arr;
71
72 27411 case Expression.INTEGER() then (exp, true);
73 58787 case Expression.REAL() then (exp, true);
74 7497 case Expression.STRING() then (exp, true);
75 454 case Expression.BOOLEAN() then (exp, true);
76 ✗ case Expression.ENUM_LITERAL() then (exp, true);
77
78 17394 case Expression.CREF(ty = Type.ARRAY()) then expandCref(exp, backend, resize);
79
80 // One-dimensional arrays are already expanded.
81 137155 case Expression.ARRAY() guard Type.isVector(exp.ty) then (exp, true);
82
83 case Expression.ARRAY()
84 algorithm
85 22240 (arr, expanded) := expandArray(exp.elements);
86 22240 exp.elements := arr;
87 22240 then
88 (exp, expanded);
89
90 1 case Expression.TYPENAME() then (expandTypename(exp.ty), true);
91 1677 case Expression.RANGE() then expandRange(exp);
92 7825 case Expression.CALL() then expandCall(exp.call, exp, resize);
93 1 case Expression.SIZE() then expandSize(exp);
94 765622 case Expression.BINARY() then expandBinary(exp, exp.operator, resize);
95 86 case Expression.MULTARY() then expand(SimplifyExp.splitMultary(exp), resize);
96 51365 case Expression.UNARY() then expandUnary(exp);
97 ✗ case Expression.LBINARY() then expandLogicalBinary(exp);
98 ✗ case Expression.LUNARY() then expandLogicalUnary(exp);
99 ✗ case Expression.RELATION() then (exp, true);
100 14 case Expression.CAST() then expandCast(exp);
101 ✗ case Expression.FILENAME() then (exp, true);
102 46397 else expandGeneric(exp, resize);
103 end match;
104 end expand;
105
106 function expandArray
107 "Expands an array of Expressions."
108 input array<Expression> arr;
109 output array<Expression> outArray;
110 output Boolean expanded = true;
111 protected
112 Boolean res;
113 Expression e;
114 algorithm
115 22240 outArray := arrayCopy(arr);
116
117
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22240 times.
57353 for i in 1:arrayLength(outArray) loop
118 35113 (e, res) := expand(arrayGetNoBoundsChecking(outArray, i));
119
120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35113 times.
35113 if not res then
121 expanded := false;
122 ✗ return;
123 end if;
124
125 arrayUpdateNoBoundsChecking(outArray, i, e);
126 end for;
127 end expandArray;
128
129 function expandList
130 "Expands a list of Expressions. If abortOnFailure is true the function will
131 stop if it fails to expand an element and the original list will be
132 returned unchanged. If abortOnFailure is false it will instead continue and
133 try to expand the whole list. In both cases the output 'expanded' indicates
134 whether the whole list could be expanded or not."
135 input list<Expression> expl;
136 input Boolean abortOnFailure = true;
137 output list<Expression> outExpl = {};
138 output Boolean expanded = true;
139 protected
140 Boolean res;
141 algorithm
142
2/2
✓ Branch 0 taken 16099 times.
✓ Branch 1 taken 5671 times.
21770 for exp in expl loop
143 16099 (exp, res) := expand(exp);
144
3/4
✓ Branch 0 taken 16063 times.
✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 16063 times.
16099 expanded := res and expanded;
145
146
3/4
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 16063 times.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
16099 if not res and abortOnFailure then
147 outExpl := expl;
148 36 return;
149 end if;
150
151 outExpl := exp :: outExpl;
152 end for;
153
154 5671 outExpl := listReverseInPlace(outExpl);
155 end expandList;
156
157 function expandCref
158 input Expression crefExp;
159 input Boolean backend = false;
160 input Boolean resize = false;
161 output Expression arrayExp;
162 output Boolean expanded;
163 protected
164 list<list<Subscript>> subs;
165 algorithm
166 (arrayExp, expanded) := match crefExp
167 case Expression.CREF(cref = ComponentRef.CREF())
168 algorithm
169
2/2
✓ Branch 1 taken 454 times.
✓ Branch 2 taken 25768 times.
26222 if Type.hasZeroDimension(crefExp.ty) then
170 454 arrayExp := Expression.makeEmptyArray(crefExp.ty);
171 expanded := true;
172 elseif Type.hasKnownSize(crefExp.ty) then
173 25207 subs := expandCref2(crefExp.cref, backend, resize);
174 25207 arrayExp := expandCref3(subs, crefExp.cref, Type.arrayElementType(crefExp.ty));
175 expanded := true;
176 else
177 arrayExp := crefExp;
178 expanded := false;
179 end if;
180 then
181 (arrayExp, expanded);
182
183 else (crefExp, false);
184 end match;
185 end expandCref;
186
187 function expandCref2
188 input ComponentRef cref;
189 input Boolean backend;
190 input Boolean resize;
191 input output list<list<Subscript>> subs = {};
192 protected
193 list<Subscript> cr_subs = {};
194 list<Dimension> dims;
195
196 import NFComponentRef.Origin;
197 algorithm
198 subs := match cref
199 case ComponentRef.CREF() guard(backend or cref.origin == Origin.CREF)
200 algorithm
201 34284 dims := Type.arrayDims(cref.ty);
202 34284 cr_subs := Subscript.expandList(cref.subscripts, dims, resize);
203
3/4
✓ Branch 0 taken 8791 times.
✓ Branch 1 taken 25493 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8791 times.
68568 then
204 if listEmpty(cr_subs) and not listEmpty(dims) then
205 {} else expandCref2(cref.restCref, backend, resize, cr_subs :: subs);
206
207 else subs;
208 end match;
209 end expandCref2;
210
211 function expandCref3
212 input list<list<Subscript>> subs;
213 input ComponentRef cref;
214 input Type crefType;
215 input list<list<Subscript>> accum = {};
216 output Expression arrayExp;
217 algorithm
218 arrayExp := match subs
219 85346 case {} then Expression.CREF(crefType, ComponentRef.setSubscriptsList(accum, cref));
220 38472 else expandCref4(listHead(subs), {}, accum, listRest(subs), cref, crefType);
221 end match;
222 end expandCref3;
223
224 function expandCref4
225 input list<Subscript> subs;
226 input list<Subscript> comb = {};
227 input list<list<Subscript>> accum = {};
228 input list<list<Subscript>> restSubs;
229 input ComponentRef cref;
230 input Type crefType;
231 output Expression arrayExp;
232 protected
233 array<Expression> expl;
234 Type arr_ty;
235 list<Subscript> slice, rest;
236 Integer i;
237 algorithm
238 arrayExp := match subs
239 197222 case {} then expandCref3(restSubs, cref, crefType, listReverse(comb) :: accum);
240
241 case Subscript.EXPANDED_SLICE(indices = slice) :: rest
242 algorithm
243 31895 expl := arrayCreateNoInit(listLength(slice), Expression.INTEGER(0));
244 i := 1;
245
246
2/2
✓ Branch 1 taken 92034 times.
✓ Branch 2 taken 31895 times.
123929 for idx in slice loop
247 92034 arrayUpdateNoBoundsChecking(expl, i,
248 expandCref4(rest, idx :: comb, accum, restSubs, cref, crefType));
249 92034 i := i + 1;
250 end for;
251
252 63790 arr_ty := Type.liftArrayLeft(Expression.typeOf(arrayGet(expl, 1)), Dimension.fromExpArray(expl));
253 31895 then
254 Expression.makeArray(arr_ty, expl);
255
256 7742 else expandCref4(listRest(subs), listHead(subs) :: comb, accum, restSubs, cref, crefType);
257 end match;
258 end expandCref4;
259
260 function expandTypename
261 input Type ty;
262 output Expression outExp;
263 algorithm
264 outExp := match ty
265 local
266 list<Expression> lits;
267
268 case Type.ARRAY(elementType = Type.BOOLEAN())
269 ✗ then Expression.makeArray(ty, listArray({Expression.BOOLEAN(false), Expression.BOOLEAN(true)}), true);
270
271 case Type.ARRAY(elementType = Type.ENUMERATION())
272 algorithm
273 2 lits := Expression.makeEnumLiterals(ty.elementType);
274 2 then
275 Expression.makeArray(ty, listArray(lits), true);
276
277 else
278 algorithm
279 ✗ Error.addInternalError(getInstanceName() + " got invalid typename", sourceInfo());
280 ✗ then
281 fail();
282 end match;
283 end expandTypename;
284
285 function expandRange
286 input Expression exp;
287 output Expression outExp;
288 output Boolean expanded;
289 protected
290 Type ty;
291 algorithm
292
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1677 times.
1677 Expression.RANGE(ty = ty) := exp;
293 1677 expanded := Expression.isLiteral(exp);
294
295
2/2
✓ Branch 0 taken 1642 times.
✓ Branch 1 taken 35 times.
1677 if expanded then
296 1642 outExp := Ceval.evalExp(exp);
297 else
298 35 (outExp, expanded) := expandNonLiteralRange(exp, ty);
299 end if;
300 end expandRange;
301
302 function expandNonLiteralRange
303 "Expands a numeric range whose bounds are not literals but whose size is
304 known, since the i:th element is start + (i - 1) * step."
305 input Expression exp;
306 input Type ty;
307 output Expression outExp;
308 output Boolean expanded;
309 protected
310 Type ety;
311 Expression start_exp, step_exp, e;
312 Option<Expression> ostep_exp;
313 Integer sz;
314 list<Expression> expl = {};
315 algorithm
316 35 ety := Type.arrayElementType(ty);
317
318
3/6
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 23 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
35 if not (Type.hasKnownSize(ty) and (Type.isInteger(ety) or Type.isReal(ety))) then
319 outExp := exp;
320 expanded := false;
321 23 return;
322 end if;
323
324
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 Expression.RANGE(start = start_exp, step = ostep_exp) := exp;
325 12 step_exp := Util.getOptionOrDefault(ostep_exp, Expression.makeOne(ety));
326 12 sz := Dimension.size(Type.nthDimension(ty, 1));
327
328
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
48 for i in sz:-1:1 loop
329
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 12 times.
36 if i == 1 then
330 e := start_exp;
331 else
332 24 e := Expression.BINARY(makeIndexOffset(i - 1, ety), Operator.makeMul(ety), step_exp);
333 24 e := SimplifyExp.simplify(Expression.BINARY(start_exp, Operator.makeAdd(ety), e));
334 end if;
335
336 expl := e :: expl;
337 end for;
338
339 12 outExp := Expression.makeArray(ty, listArray(expl));
340 expanded := true;
341 end expandNonLiteralRange;
342
343 function makeIndexOffset
344 input Integer offset;
345 input Type ty;
346 output Expression exp = if Type.isReal(ty) then Expression.REAL(intReal(offset)) else Expression.INTEGER(offset);
347 end makeIndexOffset;
348
349 function expandCall
350 input Call call;
351 input Expression exp;
352 input Boolean resize;
353 output Expression outExp;
354 output Boolean expanded;
355 algorithm
356 (outExp, expanded) := matchcontinue call
357 case Call.TYPED_CALL()
358 guard Function.isBuiltin(call.fn) and not Function.isImpure(call.fn)
359 2984 then expandBuiltinCall(call.fn, call.arguments, call, resize);
360
361 case Call.TYPED_ARRAY_CONSTRUCTOR()
362 3009 then expandArrayConstructor(call.exp, call.ty, call.iters);
363
364 3350 else expandGeneric(exp, resize);
365 end matchcontinue;
366 end expandCall;
367
368 function expandBuiltinCall
369 input Function fn;
370 input list<Expression> args;
371 input Call call;
372 input Boolean resize;
373 output Expression outExp;
374 output Boolean expanded;
375 protected
376 Absyn.Path fn_path = Function.nameConsiderBuiltin(fn);
377 algorithm
378 (outExp, expanded) := match AbsynUtil.pathFirstIdent(fn_path)
379 4 case "cat" then expandBuiltinCat(args, call, resize);
380 1380 case "der" then expandBuiltinGeneric(call);
381 1 case "diagonal" then expandBuiltinDiagonal(listHead(args));
382 108 case "fill" then expandBuiltinFill(args);
383 10 case "pre" then expandBuiltinGeneric(call);
384 ✗ case "previous" then expandBuiltinGeneric(call);
385 ✗ case "promote" then expandBuiltinPromote(args);
386 ✗ case "transpose" then expandBuiltinTranspose(listHead(args));
387 end match;
388 end expandBuiltinCall;
389
390 function expandBuiltinCat
391 input list<Expression> args;
392 input Call call;
393 input Boolean resize;
394 output Expression exp;
395 output Boolean expanded;
396 protected
397 list<Expression> expl = {};
398 algorithm
399 5707 (expl, expanded) := expandList(listRest(args));
400
401
2/2
✓ Branch 0 taken 5671 times.
✓ Branch 1 taken 36 times.
5707 if expanded then
402 // This relies on the fact that Ceval.evalBuiltinCat doesn't actually do any
403 // actual constant evaluation, and works on non-constant arrays too as long
404 // as they're expanded.
405 5671 exp := Ceval.evalBuiltinCat(listHead(args), expl, NFCeval.noTarget);
406 else
407 36 exp := expandGeneric(Expression.CALL(call), resize);
408 end if;
409 end expandBuiltinCat;
410
411 function expandBuiltinPromote
412 input list<Expression> args;
413 output Expression exp;
414 output Boolean expanded;
415 protected
416 Integer n;
417 Expression eexp, nexp;
418 algorithm
419 ✗ eexp :: nexp :: {} := args;
420 ✗ Expression.INTEGER(value = n) := nexp;
421 ✗ (eexp, expanded) := expand(eexp);
422 ✗ exp := Expression.promote(eexp, Expression.typeOf(eexp), n);
423 end expandBuiltinPromote;
424
425 function expandBuiltinDiagonal
426 input Expression arg;
427 output Expression outExp;
428 output Boolean expanded;
429 algorithm
430 1 (outExp, expanded) := expand(arg);
431
432
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if expanded then
433 1 outExp := Ceval.evalBuiltinDiagonal(outExp);
434 end if;
435 end expandBuiltinDiagonal;
436
437 function expandBuiltinFill
438 input list<Expression> args;
439 output Expression outExp;
440 output Boolean expanded = true;
441 algorithm
442 108 outExp := Expression.fillArgs(listHead(args), listRest(args));
443 end expandBuiltinFill;
444
445 function expandBuiltinTranspose
446 input Expression arg;
447 output Expression outExp;
448 output Boolean expanded;
449 algorithm
450 ✗ (outExp, expanded) := expand(arg);
451
452 ✗ if expanded then
453 ✗ outExp := Expression.transposeArray(outExp);
454 end if;
455 end expandBuiltinTranspose;
456
457 function expandBuiltinGeneric
458 input Call call;
459 output Expression outExp;
460 output Boolean expanded = true;
461 protected
462 Function fn;
463 Type ty;
464 Variability var;
465 Purity pur;
466 NFCallAttributes attr;
467 Expression arg;
468 algorithm
469
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1390 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1390 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1390 times.
1390 Call.TYPED_CALL(fn, ty, var, pur, {arg}, attr) := call;
470 1390 ty := Type.arrayElementType(ty);
471
472
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1390 times.
1390 (arg, true) := expand(arg);
473 1390 outExp := expandBuiltinGeneric2(arg, fn, ty, var, pur, attr);
474 end expandBuiltinGeneric;
475
476 function expandBuiltinGeneric2
477 input output Expression exp;
478 input Function fn;
479 input Type ty;
480 input Variability var;
481 input Purity pur;
482 input NFCallAttributes attr;
483 algorithm
484 exp := match exp
485 local
486 array<Expression> arr;
487
488 case Expression.ARRAY(literal = true) then exp;
489
490 case Expression.ARRAY()
491 algorithm
492 1380 arr := Array.map(exp.elements,
493 function expandBuiltinGeneric2(fn = fn, ty = ty, var = var, pur = pur, attr = attr));
494 1380 then
495 Expression.makeArray(Type.setArrayElementType(exp.ty, ty), arr);
496
497 3987 else Expression.CALL(Call.TYPED_CALL(fn, ty, var, pur, {exp}, attr));
498 end match;
499 end expandBuiltinGeneric2;
500
501 function expandArrayConstructor
502 input Expression exp;
503 input Type ty;
504 input list<tuple<InstNode, Expression>> iterators;
505 output Expression result;
506 output Boolean expanded = true;
507 protected
508 Expression e = exp, range;
509 InstNode node;
510 list<Expression> ranges = {};
511 Mutable<Expression> iter;
512 list<Mutable<Expression>> iters = {};
513 algorithm
514
4/4
✓ Branch 2 taken 3007 times.
✓ Branch 3 taken 6 times.
✓ Branch 6 taken 617 times.
✓ Branch 7 taken 2390 times.
3013 if Type.hasKnownSize(ty) and not List.any(iterators, function usesIterator(exp = exp)) then
515 2390 result := fillArrayConstructor(expand(SimplifyExp.simplify(exp)), ty, listLength(iterators));
516 2390 return;
517 end if;
518
519
2/2
✓ Branch 0 taken 630 times.
✓ Branch 1 taken 617 times.
1247 for i in iterators loop
520 630 (node, range) := i;
521 630 iter := Mutable.create(Expression.EMPTY(InstNode.getType(node)));
522 630 e := Expression.replaceIterator(e, node, Expression.MUTABLE(iter));
523 iters := iter :: iters;
524
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 624 times.
630 (range, true) := expand(range);
525 ranges := range :: ranges;
526 end for;
527
528 617 result := expandArrayConstructor2(e, ty, ranges, iters);
529 end expandArrayConstructor;
530
531 function usesIterator
532 input tuple<InstNode, Expression> iterator;
533 input Expression exp;
534 output Boolean used = Expression.containsIterator(exp, Util.tuple21(iterator));
535 end usesIterator;
536
537 function fillArrayConstructor
538 "The body does not depend on the iterators: every element is the same expression."
539 input Expression value;
540 input Type ty;
541 input Integer levels;
542 output Expression result;
543 algorithm
544
2/2
✓ Branch 0 taken 2738 times.
✓ Branch 1 taken 2390 times.
5128 result := if levels == 0 then value else
545 Expression.makeArray(ty, arrayCreate(Dimension.size(Type.nthDimension(ty, 1)),
546 fillArrayConstructor(value, Type.unliftArray(ty), levels - 1)));
547 end fillArrayConstructor;
548
549 function expandArrayConstructor2
550 input Expression exp;
551 input Type ty;
552 input list<Expression> ranges;
553 input list<Mutable<Expression>> iterators;
554 output Expression result;
555 protected
556 Expression range;
557 list<Expression> ranges_rest, expl = {};
558 Mutable<Expression> iter;
559 list<Mutable<Expression>> iters_rest;
560 ExpressionIterator range_iter;
561 Expression value;
562 Type el_ty;
563 algorithm
564
2/2
✓ Branch 0 taken 2173 times.
✓ Branch 1 taken 649 times.
2822 if listEmpty(ranges) then
565 // Normally it wouldn't be the expansion's task to simplify expressions,
566 // but we make an exception here since the generated expressions contain
567 // MUTABLE expressions that we need to get rid of. Also, expansion of
568 // array constructors is often done during the scalarization phase, after
569 // the simplification phase, so they wouldn't otherwise be simplified.
570 2173 result := expand(SimplifyExp.simplify(exp));
571 else
572 649 range :: ranges_rest := ranges;
573
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 649 times.
649 iter :: iters_rest := iterators;
574 649 range_iter := ExpressionIterator.fromExp(range);
575 649 el_ty := Type.unliftArray(ty);
576
577
2/2
✓ Branch 1 taken 2205 times.
✓ Branch 2 taken 649 times.
2854 while ExpressionIterator.hasNext(range_iter) loop
578 2205 (range_iter, value) := ExpressionIterator.next(range_iter);
579 2205 Mutable.update(iter, value);
580 2205 expl := expandArrayConstructor2(exp, el_ty, ranges_rest, iters_rest) :: expl;
581 end while;
582
583 649 result := Expression.makeArray(ty, listArray(listReverseInPlace(expl)));
584 end if;
585 end expandArrayConstructor2;
586
587 function expandSize
588 input Expression exp;
589 output Expression outExp;
590 output Boolean expanded = true;
591 algorithm
592 outExp := match exp
593 local
594 Integer dims;
595 Expression e;
596 Type ty;
597 list<Expression> expl;
598
599 case Expression.SIZE(exp = e, dimIndex = NONE())
600 algorithm
601 1 ty := Expression.typeOf(e);
602 1 dims := Type.dimensionCount(ty);
603
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
3 expl := list(Expression.SIZE(e, SOME(Expression.INTEGER(i))) for i in 1:dims);
604 2 then
605 Expression.makeArray(Type.ARRAY(ty, {Dimension.fromInteger(dims)}), listArray(expl));
606
607 // Size with an index is scalar, and thus already maximally expanded.
608 else exp;
609 end match;
610 end expandSize;
611
612 function expandBinary
613 input Expression exp;
614 input Operator op;
615 input Boolean resize;
616 output Expression outExp;
617 output Boolean expanded;
618
619 import NFOperator.Op;
620 algorithm
621 (outExp, expanded) := match op.op
622 4 case Op.ADD_SCALAR_ARRAY then expandBinaryScalarArray(exp, Op.ADD);
623 3 case Op.ADD_ARRAY_SCALAR then expandBinaryArrayScalar(exp, Op.ADD);
624 1 case Op.SUB_SCALAR_ARRAY then expandBinaryScalarArray(exp, Op.SUB);
625 1 case Op.SUB_ARRAY_SCALAR then expandBinaryArrayScalar(exp, Op.SUB);
626 989 case Op.MUL_SCALAR_ARRAY then expandBinaryScalarArray(exp, Op.MUL);
627 887 case Op.MUL_ARRAY_SCALAR then expandBinaryArrayScalar(exp, Op.MUL);
628 3 case Op.MUL_VECTOR_MATRIX then expandBinaryVectorMatrix(exp);
629 2273 case Op.MUL_MATRIX_VECTOR then expandBinaryMatrixVector(exp);
630 1136 case Op.SCALAR_PRODUCT then expandBinaryDotProduct(exp);
631 792 case Op.MATRIX_PRODUCT then expandBinaryMatrixProduct(exp);
632 ✗ case Op.DIV_SCALAR_ARRAY then expandBinaryScalarArray(exp, Op.DIV);
633 714 case Op.DIV_ARRAY_SCALAR then expandBinaryArrayScalar(exp, Op.DIV);
634 2 case Op.POW_SCALAR_ARRAY then expandBinaryScalarArray(exp, Op.POW);
635 47 case Op.POW_ARRAY_SCALAR then expandBinaryArrayScalar(exp, Op.POW);
636 6 case Op.POW_MATRIX then expandBinaryPowMatrix(exp, resize);
637 758764 else expandBinaryElementWise(exp);
638 end match;
639
640
2/2
✓ Branch 0 taken 765290 times.
✓ Branch 1 taken 332 times.
765622 if not expanded then
641 outExp := exp;
642 end if;
643 end expandBinary;
644
645 function expandBinaryElementWise
646 input Expression exp;
647 output Expression outExp;
648 output Boolean expanded;
649 protected
650 Expression exp1, exp2;
651 Operator op;
652 algorithm
653
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 758764 times.
758764 Expression.BINARY(exp1 = exp1, operator = op, exp2 = exp2) := exp;
654
655
2/2
✓ Branch 2 taken 2763 times.
✓ Branch 3 taken 756001 times.
758764 if Type.isArray(Operator.typeOf(op)) then
656 2763 (exp1, expanded) := expand(exp1);
657
658
2/2
✓ Branch 0 taken 2722 times.
✓ Branch 1 taken 41 times.
2763 if expanded then
659 2722 (exp2, expanded) := expand(exp2);
660 end if;
661
662
2/2
✓ Branch 0 taken 2722 times.
✓ Branch 1 taken 41 times.
2763 if expanded then
663 2722 outExp := expandBinaryElementWise2(exp1, Operator.stripEW(op), exp2, SimplifyExp.simplifyBinaryOp);
664 else
665 outExp := exp;
666 end if;
667 else
668 outExp := exp;
669 756001 expanded := true;
670 end if;
671 end expandBinaryElementWise;
672
673 function expandBinaryElementWise2
674 input Expression exp1;
675 input Operator op;
676 input Expression exp2;
677 input MakeFn func;
678 output Expression exp;
679
680 partial function MakeFn
681 input Expression exp1;
682 input Operator op;
683 input Expression exp2;
684 output Expression exp;
685 end MakeFn;
686 protected
687 array<Expression> expl1, expl2, expl;
688 Type ty;
689 Operator eop;
690 algorithm
691 2729 expl1 := Expression.arrayElements(exp1);
692 2729 expl2 := Expression.arrayElements(exp2);
693 2729 ty := Operator.typeOf(op);
694 2729 eop := Operator.setType(Type.unliftArray(ty), op);
695
696
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2726 times.
2729 if Type.dimensionCount(ty) > 1 then
697 3 expl := Array.threadMap(expl1, expl2, function expandBinaryElementWise2(op = eop, func = func));
698 else
699 2726 expl := Array.threadMap(expl1, expl2, function func(op = eop));
700 //expl := list(func(e1, eop, e2) threaded for e1 in expl1, e2 in expl2);
701 end if;
702
703 2729 exp := Expression.makeArray(ty, expl);
704 end expandBinaryElementWise2;
705
706 function expandBinaryScalarArray
707 input Expression exp;
708 input NFOperator.Op scalarOp;
709 output Expression outExp;
710 output Boolean expanded;
711 protected
712 Expression exp1, exp2;
713 Operator op;
714 algorithm
715
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 996 times.
996 Expression.BINARY(exp1 = exp1, operator = op, exp2 = exp2) := exp;
716 996 (exp2, expanded) := expand(exp2);
717
718
2/2
✓ Branch 0 taken 984 times.
✓ Branch 1 taken 12 times.
996 if expanded then
719 984 op := Operator.OPERATOR(Type.arrayElementType(Operator.typeOf(op)), scalarOp);
720 984 outExp := Expression.mapArrayElements(exp2,
721 function SimplifyExp.simplifyBinaryOp(op = op, exp1 = exp1));
722 else
723 outExp := exp;
724 end if;
725 end expandBinaryScalarArray;
726
727 function makeScalarArrayBinary_traverser
728 input Expression exp1;
729 input Operator op;
730 input Expression exp2;
731 output Expression exp;
732 algorithm
733 exp := match exp2
734 case Expression.ARRAY() then exp2;
735 ✗ else SimplifyExp.simplifyBinaryOp(exp1, op, exp2);
736 end match;
737 end makeScalarArrayBinary_traverser;
738
739 function expandBinaryArrayScalar
740 input Expression exp;
741 input NFOperator.Op scalarOp;
742 output Expression outExp;
743 output Boolean expanded;
744 protected
745 Expression exp1, exp2;
746 Operator op;
747 algorithm
748
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1652 times.
1652 Expression.BINARY(exp1 = exp1, operator = op, exp2 = exp2) := exp;
749 1652 (exp1, expanded) := expand(exp1);
750
751
2/2
✓ Branch 0 taken 1449 times.
✓ Branch 1 taken 203 times.
1652 if expanded then
752 1449 op := Operator.OPERATOR(Type.arrayElementType(Operator.typeOf(op)), scalarOp);
753 1449 outExp := Expression.mapArrayElements(exp1,
754 function SimplifyExp.simplifyBinaryOp(op = op, exp2 = exp2));
755 else
756 outExp := exp;
757 end if;
758 end expandBinaryArrayScalar;
759
760 function expandBinaryVectorMatrix
761 "Expands a vector*matrix expression, c[m] = a[n] * b[n, m]."
762 input Expression exp;
763 output Expression outExp;
764 output Boolean expanded;
765 protected
766 Expression exp1, exp2;
767 array<Expression> arr;
768 Type ty;
769 Dimension m;
770 algorithm
771
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 Expression.BINARY(exp1 = exp1, exp2 = exp2) := exp;
772 3 (exp2, expanded) := expand(exp2);
773
774
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if expanded then
775
5/10
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 3 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 3 times.
3 Expression.ARRAY(Type.ARRAY(ty, {m, _}), arr) := Expression.transposeArray(exp2);
776 3 ty := Type.ARRAY(ty, {m});
777
778
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
3 if arrayEmpty(arr) or Type.isEmptyArray(ty) then
779 ✗ outExp := Expression.makeZero(ty);
780 else
781 3 (exp1, expanded) := expand(exp1);
782
783
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if expanded then
784 // c[i] = a * b[:, i] for i in 1:m
785 3 arr := Array.map(arr, function makeScalarProduct(exp1 = exp1));
786 3 outExp := Expression.makeArray(ty, arr);
787 else
788 outExp := exp;
789 end if;
790 end if;
791 else
792 outExp := exp;
793 end if;
794 end expandBinaryVectorMatrix;
795
796 function expandBinaryMatrixVector
797 "Expands a matrix*vector expression, c[n] = a[n, m] * b[m]."
798 input Expression exp;
799 output Expression outExp;
800 output Boolean expanded;
801 protected
802 Expression exp1, exp2;
803 array<Expression> arr;
804 Type ty;
805 Dimension n;
806 algorithm
807
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2273 times.
2273 Expression.BINARY(exp1 = exp1, exp2 = exp2) := exp;
808 2273 (exp1, expanded) := expand(exp1);
809
810
2/2
✓ Branch 0 taken 2270 times.
✓ Branch 1 taken 3 times.
2273 if expanded then
811
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 2270 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2270 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 2270 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 2270 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 2270 times.
2270 Expression.ARRAY(Type.ARRAY(ty, {n, _}), arr) := exp1;
812 2270 ty := Type.ARRAY(ty, {n});
813
814
2/4
✓ Branch 0 taken 2270 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2270 times.
2270 if arrayEmpty(arr) or Type.isEmptyArray(ty) then
815 ✗ outExp := Expression.makeZero(ty);
816 else
817 2270 (exp2, expanded) := expand(exp2);
818
819
1/2
✓ Branch 0 taken 2270 times.
✗ Branch 1 not taken.
2270 if expanded then
820 // c[i] = a[i, :] * b for i in 1:n
821 2270 arr := Array.map(arr, function makeScalarProduct(exp2 = exp2));
822 2270 outExp := Expression.makeArray(ty, arr);
823 else
824 outExp := exp;
825 end if;
826 end if;
827 else
828 outExp := exp;
829 end if;
830 end expandBinaryMatrixVector;
831
832 function expandBinaryDotProduct
833 "Expands a vector*vector expression, c = a[n] * b[n]."
834 input Expression exp;
835 output Expression outExp;
836 output Boolean expanded;
837 protected
838 Expression exp1, exp2;
839 algorithm
840
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1136 times.
1136 Expression.BINARY(exp1 = exp1, exp2 = exp2) := exp;
841 1136 (exp1, expanded) := expand(exp1);
842
843
2/2
✓ Branch 0 taken 1063 times.
✓ Branch 1 taken 73 times.
1136 if expanded then
844 1063 (exp2, expanded) := expand(exp2);
845 end if;
846
847
2/2
✓ Branch 0 taken 1063 times.
✓ Branch 1 taken 73 times.
1136 if expanded then
848 1063 outExp := makeScalarProduct(exp1, exp2);
849 else
850 outExp := exp;
851 end if;
852 end expandBinaryDotProduct;
853
854 function makeScalarProduct
855 input Expression exp1;
856 input Expression exp2;
857 output Expression exp;
858 protected
859 array<Expression> arr1, arr2;
860 Type ty, elem_ty;
861 Operator mul_op, add_op;
862 algorithm
863
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14786 times.
14786 Expression.ARRAY(ty, arr1) := exp1;
864
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14786 times.
14786 Expression.ARRAY( _, arr2) := exp2;
865 14786 elem_ty := Type.unliftArray(ty);
866
867
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 14720 times.
14786 if arrayEmpty(arr1) then
868 // Scalar product of two empty arrays. The result is defined in the spec
869 // by sum, so we return 0 since that's the default value of sum.
870 66 exp := Expression.makeZero(elem_ty);
871 else
872 14720 mul_op := Operator.makeMul(elem_ty);
873 14720 add_op := Operator.makeAdd(elem_ty);
874 14720 arr1 := Array.threadMap(arr1, arr2, function SimplifyExp.simplifyBinaryOp(op = mul_op));
875 14720 exp := Array.reduce(arr1, function SimplifyExp.simplifyBinaryOp(op = add_op));
876 end if;
877 end makeScalarProduct;
878
879 function expandBinaryMatrixProduct
880 "Expands a matrix*matrix expression, c[n, p] = a[n, m] * b[m, p]."
881 input Expression exp;
882 output Expression outExp;
883 output Boolean expanded;
884 protected
885 Expression exp1, exp2;
886 algorithm
887
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 792 times.
792 Expression.BINARY(exp1 = exp1, exp2 = exp2) := exp;
888 792 (exp1, expanded) := expand(exp1);
889
890
1/2
✓ Branch 0 taken 792 times.
✗ Branch 1 not taken.
792 if expanded then
891 792 (exp2, expanded) := expand(exp2);
892 end if;
893
894
1/2
✓ Branch 0 taken 792 times.
✗ Branch 1 not taken.
792 if expanded then
895 792 outExp := makeBinaryMatrixProduct(exp1, exp2);
896 else
897 outExp := exp;
898 end if;
899 end expandBinaryMatrixProduct;
900
901 function makeBinaryMatrixProduct
902 input Expression exp1;
903 input Expression exp2;
904 output Expression exp;
905 protected
906 array<Expression> arr1, arr2, arr;
907 Type ty, row_ty, mat_ty;
908 Dimension n, p;
909 Integer len;
910 Expression e;
911 algorithm
912
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 797 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 797 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 797 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 797 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 797 times.
797 Expression.ARRAY(Type.ARRAY(ty, {n, _}), arr1) := exp1;
913 // Transpose the second matrix. This makes it easier to do the multiplication,
914 // since we can do row-row multiplications instead of row-column.
915
5/10
✗ Branch 1 not taken.
✓ Branch 2 taken 797 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 797 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 797 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 797 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 797 times.
797 Expression.ARRAY(Type.ARRAY(dimensions = {p, _}), arr2) := Expression.transposeArray(exp2);
916 797 mat_ty := Type.ARRAY(ty, {n, p});
917
918
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 797 times.
797 if arrayEmpty(arr2) then
919 // If any of the matrices' dimensions are zero, the result will be a matrix
920 // of zeroes (the default value of sum). Only arr2 needs to be checked here,
921 // the normal case can handle arr1 being empty.
922 ✗ exp := Expression.makeZero(mat_ty);
923 else
924 // c[i, j] = a[i, :] * b[:, j] for i in 1:n, j in 1:p.
925 797 row_ty := Type.ARRAY(ty, {p});
926 len := arrayLength(arr1);
927 797 arr := arrayCreateNoInit(len, exp1);
928
929
1/2
✓ Branch 0 taken 797 times.
✗ Branch 1 not taken.
3174 for i in 1:len loop
930 2377 e := arrayGetNoBoundsChecking(arr1, i);
931 2377 arrayUpdateNoBoundsChecking(arr, i,
932 Expression.makeArray(row_ty, makeBinaryMatrixProduct2(e, arr2)));
933 end for;
934
935 797 exp := Expression.makeArray(mat_ty, arr);
936 end if;
937 end makeBinaryMatrixProduct;
938
939 function makeBinaryMatrixProduct2
940 input Expression row;
941 input array<Expression> matrix;
942 output array<Expression> outRow;
943 algorithm
944 2377 outRow := Array.map(matrix, function makeScalarProduct(exp1 = row));
945 end makeBinaryMatrixProduct2;
946
947 function expandBinaryPowMatrix
948 input Expression exp;
949 input Boolean resize;
950 output Expression outExp = exp;
951 output Boolean expanded;
952 protected
953 Expression exp1, exp2;
954 Operator op;
955 Integer n;
956 algorithm
957
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 Expression.BINARY(exp1 = exp1, operator = op, exp2 = exp2) := exp;
958
959 (outExp, expanded) := match exp2
960 // a ^ 0 = identity(size(a, 1))
961 case Expression.INTEGER(0)
962 algorithm
963 1 n := Dimension.size(listHead(Type.arrayDims(Operator.typeOf(op))));
964 1 then
965 (Expression.makeIdentityMatrix(n, Type.REAL()), true);
966
967 // a ^ n where n is a literal value.
968 case Expression.INTEGER(n)
969 guard n > 0
970 algorithm
971 4 (exp1, expanded) := expand(exp1);
972
973
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if expanded then
974 4 outExp := expandBinaryPowMatrix2(exp1, n);
975 end if;
976 4 then
977 (outExp, expanded);
978
979 // a ^ n where n is unknown, subscript the whole expression.
980 1 else expandGeneric(exp, resize);
981 end match;
982 end expandBinaryPowMatrix;
983
984 function expandBinaryPowMatrix2
985 input Expression matrix;
986 input Integer n;
987 output Expression exp;
988 algorithm
989 exp := match n
990 // A^1 = A
991 case 1 then matrix;
992 // A^2 = A * A
993 3 case 2 then makeBinaryMatrixProduct(matrix, matrix);
994
995 // A^n = A^m * A^m where n = 2*m
996 case _ guard intMod(n, 2) == 0
997 algorithm
998 1 exp := expandBinaryPowMatrix2(matrix, intDiv(n, 2));
999 1 then
1000 makeBinaryMatrixProduct(exp, exp);
1001
1002 // A^n = A * A^(n-1)
1003 else
1004 algorithm
1005 1 exp := expandBinaryPowMatrix2(matrix, n - 1);
1006 1 then
1007 makeBinaryMatrixProduct(matrix, exp);
1008
1009 end match;
1010 end expandBinaryPowMatrix2;
1011
1012 function expandUnary
1013 input Expression exp;
1014 output Expression outExp;
1015 output Boolean expanded;
1016 protected
1017 Expression operand;
1018 Operator op, scalar_op;
1019 algorithm
1020
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51365 times.
51365 Expression.UNARY(op, operand) := exp;
1021 51365 (operand, expanded) := expand(operand);
1022
1023
2/2
✓ Branch 0 taken 51364 times.
✓ Branch 1 taken 1 time.
51365 if expanded then
1024 51364 scalar_op := Operator.scalarize(op);
1025 51364 outExp := Expression.mapArrayElements(operand,
1026 function SimplifyExp.simplifyUnaryOp(op = scalar_op));
1027 else
1028 outExp := exp;
1029 end if;
1030 end expandUnary;
1031
1032 function expandLogicalBinary
1033 input Expression exp;
1034 output Expression outExp;
1035 output Boolean expanded;
1036 protected
1037 Expression exp1, exp2;
1038 Operator op;
1039 algorithm
1040 ✗ Expression.LBINARY(exp1 = exp1, operator = op, exp2 = exp2) := exp;
1041
1042 ✗ if Type.isArray(Operator.typeOf(op)) then
1043 ✗ (exp1, expanded) := expand(exp1);
1044
1045 ✗ if expanded then
1046 ✗ (exp2, expanded) := expand(exp2);
1047 end if;
1048
1049 ✗ if expanded then
1050 ✗ outExp := expandBinaryElementWise2(exp1, op, exp2, makeLBinaryOp);
1051 else
1052 outExp := exp;
1053 end if;
1054 else
1055 outExp := exp;
1056 ✗ expanded := true;
1057 end if;
1058 end expandLogicalBinary;
1059
1060 function makeLBinaryOp
1061 input Expression exp1;
1062 input Operator op;
1063 input Expression exp2;
1064 output Expression exp;
1065 algorithm
1066 ✗ if Expression.isScalarLiteral(exp1) and Expression.isScalarLiteral(exp2) then
1067 ✗ exp := Ceval.evalLogicBinaryOp(exp1, op, exp2);
1068 else
1069 ✗ exp := Expression.LBINARY(exp1, op, exp2);
1070 end if;
1071 end makeLBinaryOp;
1072
1073 function expandLogicalUnary
1074 input Expression exp;
1075 output Expression outExp;
1076 output Boolean expanded;
1077 protected
1078 Expression operand;
1079 Operator op, scalar_op;
1080 algorithm
1081 ✗ Expression.LUNARY(op, operand) := exp;
1082 ✗ (operand, expanded) := expand(operand);
1083
1084 ✗ if expanded then
1085 ✗ scalar_op := Operator.scalarize(op);
1086 ✗ outExp := Expression.mapArrayElements(operand, function makeLogicalUnaryOp(op = scalar_op));
1087 else
1088 outExp := exp;
1089 end if;
1090 end expandLogicalUnary;
1091
1092 function makeLogicalUnaryOp
1093 input Expression exp1;
1094 input Operator op;
1095 output Expression exp = Expression.LUNARY(op, exp1);
1096 end makeLogicalUnaryOp;
1097
1098 function expandCast
1099 input Expression castExp;
1100 output Expression outExp;
1101 output Boolean expanded;
1102 protected
1103 Expression exp;
1104 Type ty;
1105 algorithm
1106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 Expression.CAST(exp = exp, ty = ty) := castExp;
1107 14 (outExp, expanded) := expand(exp);
1108
1109
2/4
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
14 if expanded and not referenceEq(exp, outExp) then
1110 14 outExp := Expression.typeCast(outExp, ty);
1111 else
1112 outExp := castExp;
1113 end if;
1114 end expandCast;
1115
1116 function expandGeneric
1117 input Expression exp;
1118 input Boolean resize;
1119 output Expression outExp;
1120 output Boolean expanded;
1121 protected
1122 Type ty;
1123 list<Dimension> dims;
1124 list<list<Subscript>> subs;
1125 algorithm
1126 49784 ty := Expression.typeOf(exp);
1127
1128
2/2
✓ Branch 1 taken 852 times.
✓ Branch 2 taken 48932 times.
49784 if Type.isArray(ty) then
1129 852 expanded := Type.hasKnownSize(ty);
1130
1131
2/2
✓ Branch 0 taken 776 times.
✓ Branch 1 taken 76 times.
852 if expanded then
1132 776 dims := Type.arrayDims(ty);
1133
8/8
✓ Branch 0 taken 888 times.
✓ Branch 1 taken 776 times.
✓ Branch 2 taken 888 times.
✓ Branch 3 taken 776 times.
✓ Branch 6 taken 2863 times.
✓ Branch 7 taken 888 times.
✓ Branch 8 taken 2863 times.
✓ Branch 9 taken 888 times.
4527 subs := list(list(Subscript.INDEX(e) for e in RangeIterator.toList(RangeIterator.fromDim(d, resize))) for d in dims);
1134 776 outExp := expandGeneric2(subs, exp, ty);
1135 else
1136 outExp := exp;
1137 end if;
1138 else
1139 outExp := exp;
1140 expanded := true;
1141 end if;
1142 end expandGeneric;
1143
1144 function expandGeneric2
1145 input list<list<Subscript>> subs;
1146 input Expression exp;
1147 input Type ty;
1148 input list<Subscript> accum = {};
1149 output Expression outExp;
1150 protected
1151 Type t;
1152 list<Subscript> sub;
1153 array<Expression> expl;
1154 list<list<Subscript>> rest_subs;
1155 Integer i;
1156 algorithm
1157 outExp := match subs
1158 case sub :: rest_subs
1159 algorithm
1160 1139 t := Type.unliftArray(ty);
1161 1139 expl := arrayCreateNoInit(listLength(sub), exp);
1162 i := 1;
1163
1164
2/2
✓ Branch 1 taken 3569 times.
✓ Branch 2 taken 1139 times.
4708 for s in sub loop
1165 3569 arrayUpdateNoBoundsChecking(expl, i,
1166 expandGeneric2(rest_subs, exp, t, s :: accum));
1167 3569 i := i + 1;
1168 end for;
1169 1139 then
1170 Expression.makeArray(ty, expl);
1171
1172 case {}
1173 algorithm
1174 outExp := exp;
1175
2/2
✓ Branch 1 taken 4238 times.
✓ Branch 2 taken 3206 times.
7444 for s in listReverse(accum) loop
1176 4238 outExp := Expression.applySubscript(s, outExp);
1177 end for;
1178 then
1179 outExp;
1180
1181 end match;
1182 end expandGeneric2;
1183
1184 function expandCallArgs
1185 input output Expression exp;
1186 protected
1187 Call call;
1188 algorithm
1189 () := match exp
1190 case Expression.CALL(call = call as Call.TYPED_CALL())
1191 algorithm
1192
4/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1 time.
3 call.arguments := list(expand(arg) for arg in call.arguments);
1193 1 exp.call := call;
1194 then
1195 ();
1196
1197 else ();
1198 end match;
1199 end expandCallArgs;
1200
1201 annotation(__OpenModelica_Interface="nf_frontend");
1202 end NFExpandExp;
1203