Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 81.5% 44 / 0 / 54
Functions: -% 0 / 1 / 1
Branches: 76.1% 35 / 0 / 46

OMCompiler/Compiler/NFFrontEnd/NFExpressionIterator.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 NFExpressionIterator
37 protected
38 import ExpressionIterator = NFExpressionIterator;
39 import ComponentRef = NFComponentRef;
40 import NFInstNode.InstNode;
41 import ExpandExp = NFExpandExp;
42 import SimplifyExp = NFSimplifyExp;
43 import MetaModelica.Dangerous.listReverseInPlace;
44 import Array;
45
46 public
47 import Expression = NFExpression;
48 import Binding = NFBinding;
49 import Util;
50
51 record ARRAY_ITERATOR
52 array<Expression> arr;
53 Integer index;
54 list<array<Expression>> arrays;
55 end ARRAY_ITERATOR;
56
57 record SCALAR_ITERATOR
58 Expression exp;
59 end SCALAR_ITERATOR;
60
61 record EACH_ITERATOR
62 Expression exp;
63 end EACH_ITERATOR;
64
65 record NONE_ITERATOR
66 end NONE_ITERATOR;
67
68 function toString
69 input ExpressionIterator iter;
70 output String str;
71 algorithm
72 str := match iter
73 case ARRAY_ITERATOR()
74 ✗ then List.toStringCustom(iter.arrays, function Array.toString(
75 inPrintFunc = Expression.toString,
76 inNameStr = "",
77 inBeginStr = "{",
78 inDelimitStr = ", ",
79 inEndStr = "}",
80 inPrintEmpty = false,
81 maxLength = 0), "[ARRY] array iterator:\n", "", "\n", "");
82
83 ✗ case SCALAR_ITERATOR() then "[SCAL] scalar iterator: " + Expression.toString(iter.exp) + "\n";
84 ✗ case EACH_ITERATOR() then "[EACH] each iterator: " + Expression.toString(iter.exp) + "\n";
85 case NONE_ITERATOR() then "[NONE] no iterator.\n";
86 end match;
87 end toString;
88
89
90 function fromExp
91 input Expression exp;
92 input Boolean backend = false;
93 input Boolean resize = false;
94 output ExpressionIterator iterator;
95 algorithm
96 iterator := match exp
97 local
98 Expression e;
99 Boolean expanded;
100
101 case Expression.ARRAY()
102 algorithm
103 96428 (e, expanded) := ExpandExp.expand(exp, backend, resize);
104
105
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96428 times.
96428 if not expanded then
106 ✗ Error.terminate(getInstanceName() + " got unexpandable expression `" +
107 Expression.toString(exp) + "`", sourceInfo());
108 end if;
109 96428 then
110 makeArrayIterator(e);
111
112 case Expression.CREF()
113 algorithm
114 8825 e := ExpandExp.expandCref(exp, backend);
115
116 iterator := match e
117 8825 case Expression.ARRAY() then fromExp(e, backend, resize);
118 ✗ else SCALAR_ITERATOR(e);
119 end match;
120 then
121 iterator;
122
123 else
124 algorithm
125 5273 (e, expanded) := ExpandExp.expand(exp, backend, resize);
126
3/4
✓ Branch 0 taken 5273 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 102 times.
✓ Branch 4 taken 5171 times.
5273 then
127 if expanded then
128 (if Expression.isEqual(e, exp) then SCALAR_ITERATOR(exp) else fromExp(e, backend, resize)) else
129 NONE_ITERATOR();
130
131 end match;
132 end fromExp;
133
134 function fromExpOpt
135 input Option<Expression> optExp;
136 output ExpressionIterator iterator;
137 algorithm
138 iterator := match optExp
139 local
140 Expression exp;
141
142 2640 case SOME(exp) then fromExp(exp);
143 else NONE_ITERATOR();
144 end match;
145 end fromExpOpt;
146
147 function fromBinding
148 input Binding binding;
149 output ExpressionIterator iterator;
150 algorithm
151 iterator := match binding
152 local
153
154 case Binding.TYPED_BINDING(eachType = NFBinding.EachType.EACH)
155 9945 then EACH_ITERATOR(binding.bindingExp);
156
157 case Binding.TYPED_BINDING()
158 68254 then fromExp(binding.bindingExp);
159
160 case Binding.FLAT_BINDING()
161 105 then EACH_ITERATOR(binding.bindingExp);
162 end match;
163 end fromBinding;
164
165 function isUniform
166 "Whether every element the iterator yields is the same expression object,
167 so one element stands for all of them."
168 input ExpressionIterator iterator;
169 output Boolean uniform;
170 algorithm
171 uniform := match iterator
172 1961 case ARRAY_ITERATOR() then isUniformArrays(iterator.arr :: iterator.arrays);
173 case EACH_ITERATOR() then true;
174 case NONE_ITERATOR() then true;
175 else false;
176 end match;
177 end isUniform;
178
179 function isUniformArrays
180 input list<array<Expression>> arrays;
181 output Boolean uniform = true;
182 protected
183 Option<Expression> first = NONE();
184 algorithm
185
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2296 times.
✓ Branch 2 taken 2296 times.
✓ Branch 3 taken 1744 times.
4040 for arr in arrays loop
186
2/2
✓ Branch 1 taken 8314 times.
✓ Branch 2 taken 2079 times.
10393 for e in arr loop
187
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8314 times.
✓ Branch 2 taken 1961 times.
✓ Branch 3 taken 6353 times.
8314 if isNone(first) then
188 first := SOME(e);
189 elseif not referenceEq(e, Util.getOption(first)) then
190 uniform := false;
191 217 return;
192 end if;
193 end for;
194 end for;
195 end isUniformArrays;
196
197 function hasNext
198 input ExpressionIterator iterator;
199 output Boolean hasNext;
200 algorithm
201 hasNext := match iterator
202
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72522 times.
145044 case ARRAY_ITERATOR() then iterator.index <= arrayLength(iterator.arr);
203 case SCALAR_ITERATOR() then true;
204 case EACH_ITERATOR() then true;
205 case NONE_ITERATOR() then false;
206 end match;
207 end hasNext;
208
209 function next
210 input output ExpressionIterator iterator;
211 output Expression nextExp;
212 algorithm
213 (iterator, nextExp) := match iterator
214 local
215 list<Expression> rest, arr;
216 Expression next;
217 list<array<Expression>> arrs;
218
219 case ARRAY_ITERATOR()
220 algorithm
221 316378 next := arrayGet(iterator.arr, iterator.index);
222
223
2/2
✓ Branch 0 taken 100700 times.
✓ Branch 1 taken 215678 times.
316378 if iterator.index >= arrayLength(iterator.arr) then
224 100700 arrs := iterator.arrays;
225
3/4
✓ Branch 0 taken 6002 times.
✓ Branch 1 taken 94698 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6002 times.
106702 while not listEmpty(arrs) and arrayEmpty(listHead(arrs)) loop
226 ✗ arrs := listRest(arrs);
227 end while;
228
229
2/2
✓ Branch 0 taken 94698 times.
✓ Branch 1 taken 6002 times.
100700 if listEmpty(arrs) then
230 94698 iterator := ARRAY_ITERATOR(listArray({}), 1, {});
231 else
232 6002 iterator := ARRAY_ITERATOR(listHead(arrs), 1, listRest(arrs));
233 end if;
234 else
235 215678 iterator.index := iterator.index + 1;
236 end if;
237 then
238 (iterator, next);
239
240 case SCALAR_ITERATOR()
241 102 then (NONE_ITERATOR(), iterator.exp);
242
243 37597 case EACH_ITERATOR() then (iterator, iterator.exp);
244 end match;
245 end next;
246
247 function nextOpt
248 input output ExpressionIterator iterator;
249 output Option<Expression> nextExp;
250 protected
251 Expression exp;
252 algorithm
253
2/2
✓ Branch 1 taken 9775 times.
✓ Branch 2 taken 31786 times.
41561 if hasNext(iterator) then
254 9775 (iterator, exp) := next(iterator);
255 9775 nextExp := SOME(exp);
256 else
257 nextExp := NONE();
258 end if;
259 end nextOpt;
260
261 function toList
262 // TODO: Implement this function more efficiently, using the internal
263 // structure of the iterators instead of hasNext and next.
264 input ExpressionIterator iterator;
265 output list<Expression> expl = {};
266 protected
267 ExpressionIterator iter;
268 Expression exp;
269 algorithm
270 iter := iterator;
271
272 ✗ while hasNext(iter) loop
273 ✗ (iter, exp) := next(iter);
274 ✗ expl := exp :: expl;
275 end while;
276
277 ✗ expl := listReverse(expl);
278 end toList;
279
280 function isSubscriptedArrayCall
281 "only checks first slice for a subscripted call and assumes it holds for all of them"
282 input ExpressionIterator iterator;
283 input Boolean trySimplify = true;
284 output Boolean b;
285 protected
286 function is_sub_call
287 input Expression exp;
288 input Boolean trySimplify;
289 output Boolean res;
290 algorithm
291 res := match exp
292 case Expression.SUBSCRIPTED_EXP(exp = Expression.CALL())
293
2/4
✓ Branch 0 taken 322 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 322 times.
✗ Branch 5 not taken.
322 then not trySimplify or Expression.isCall(SimplifyExp.simplify(exp.exp));
294 else false;
295 end match;
296 end is_sub_call;
297 algorithm
298 b := match iterator
299
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8610 times.
17220 case ARRAY_ITERATOR() then is_sub_call(arrayGet(iterator.arr, 1), trySimplify);
300 else false;
301 end match;
302 end isSubscriptedArrayCall;
303
304 protected
305 function makeArrayIterator
306 input Expression exp;
307 output ExpressionIterator iterator;
308 protected
309 list<array<Expression>> arrays;
310 algorithm
311 96428 arrays := flattenArray(exp, {});
312
313
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 96423 times.
96428 if listEmpty(arrays) then
314 5 iterator := ARRAY_ITERATOR(listArray({}), 1, arrays);
315 else
316 96423 iterator := ARRAY_ITERATOR(listHead(arrays), 1, listRest(arrays));
317 end if;
318 end makeArrayIterator;
319
320 function flattenArray
321 input Expression exp;
322 input output list<array<Expression>> arrays;
323 algorithm
324 96428 arrays := flattenArray_impl(exp, {});
325 96428 arrays := listReverseInPlace(arrays);
326
327
4/4
✓ Branch 0 taken 96428 times.
✓ Branch 1 taken 5 times.
✓ Branch 3 taken 96423 times.
✓ Branch 4 taken 5 times.
192861 while not listEmpty(arrays) and arrayEmpty(listHead(arrays)) loop
328 5 arrays := listRest(arrays);
329 end while;
330 end flattenArray;
331
332 function flattenArray_impl
333 input Expression exp;
334 input output list<array<Expression>> arrays;
335 algorithm
336
2/2
✓ Branch 1 taken 102940 times.
✓ Branch 2 taken 3487 times.
106427 if Expression.isVector(exp) then
337 102940 arrays := Expression.arrayElements(exp) :: arrays;
338 else
339
2/2
✓ Branch 2 taken 9999 times.
✓ Branch 3 taken 3487 times.
16973 for e in Expression.arrayElements(exp) loop
340 9999 arrays := flattenArray_impl(e, arrays);
341 end for;
342 end if;
343 end flattenArray_impl;
344
345 annotation(__OpenModelica_Interface="nf_frontend");
346 end NFExpressionIterator;
347