Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 50.9% 27 / 0 / 53
Functions: -% 0 / 1 / 1
Branches: 39.3% 11 / 0 / 28

OMCompiler/Compiler/NFFrontEnd/NFRangeIterator.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 NFRangeIterator
37 protected
38 import RangeIterator = NFRangeIterator;
39 import Type = NFType;
40 import Util;
41
42 public
43 import Expression = NFExpression;
44 import Dimension = NFDimension;
45
46 record INT_RANGE
47 Integer current;
48 Integer last;
49 end INT_RANGE;
50
51 record INT_STEP_RANGE
52 Integer current;
53 Integer stepsize;
54 Integer last;
55 end INT_STEP_RANGE;
56
57 record REAL_RANGE
58 Real start;
59 Real stepsize;
60 Integer current;
61 Integer steps;
62 end REAL_RANGE;
63
64 record ARRAY_RANGE
65 array<Expression> values;
66 Integer index;
67 end ARRAY_RANGE;
68
69 record INVALID_RANGE
70 Expression exp;
71 end INVALID_RANGE;
72
73 function isValid
74 input RangeIterator iterator;
75 output Boolean isValid;
76 algorithm
77 isValid := match iterator
78 case INVALID_RANGE() then false;
79 else true;
80 end match;
81 end isValid;
82
83 function fromExp
84 "Returns a RangeIterator created from the given expression. If the
85 expression isn't an expression that can be expanded into elements an
86 invalid range will be returned that will trigger an assertion when used.
87 The valididity of the returned iterator can be checked with isValid."
88 input Expression exp;
89 output RangeIterator iterator;
90 algorithm
91 iterator := match exp
92 local
93 Integer istart, istep, istop;
94 Real rstart, rstep, rstop;
95 Boolean bstart, bstop;
96 Type ty;
97 list<String> literals;
98 list<Expression> values;
99
100 701 case Expression.ARRAY() then ARRAY_RANGE(exp.elements, 1);
101
102 case Expression.RANGE(start = Expression.INTEGER(istart),
103 step = SOME(Expression.INTEGER(istep)),
104 stop = Expression.INTEGER(istop))
105 ✗ then INT_STEP_RANGE(istart, istep, istop);
106
107 case Expression.RANGE(start = Expression.INTEGER(istart),
108 step = NONE(),
109 stop = Expression.INTEGER(istop))
110 1342 then INT_RANGE(istart, istop);
111
112 case Expression.RANGE(start = Expression.REAL(rstart),
113 step = SOME(Expression.REAL(rstep)),
114 stop = Expression.REAL(rstop))
115 ✗ then REAL_RANGE(rstart, rstep, 0, Util.realRangeSize(rstart, rstep, rstop));
116
117 case Expression.RANGE(start = Expression.REAL(rstart),
118 step = NONE(),
119 stop = Expression.REAL(rstop))
120 ✗ then REAL_RANGE(rstart, 1.0, 0, Util.realRangeSize(rstart, 1.0, rstop));
121
122 case Expression.RANGE(start = Expression.BOOLEAN(bstart),
123 stop = Expression.BOOLEAN(bstop))
124 ✗ then ARRAY_RANGE(listArray(list(Expression.BOOLEAN(b) for b in bstart:bstop)), 1);
125
126 case Expression.RANGE(start = Expression.ENUM_LITERAL(ty = ty, index = istart),
127 step = NONE(),
128 stop = Expression.ENUM_LITERAL(index = istop))
129 algorithm
130
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 Type.ENUMERATION(literals = literals) := ty;
131 values := {};
132
133
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if istart <= istop then
134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 for i in 2:istart loop
135 ✗ literals := listRest(literals);
136 end for;
137
138 4 for i in istart:istop loop
139 3 values := Expression.ENUM_LITERAL(ty, listHead(literals), i) :: values;
140 3 literals := listRest(literals);
141 end for;
142
143 1 values := listReverse(values);
144 end if;
145 1 then
146 ARRAY_RANGE(listArray(values), 1);
147
148 // enumeration type based range
149 case Expression.TYPENAME(ty = Type.ARRAY(elementType = ty as Type.ENUMERATION(literals = literals)))
150 algorithm
151 values := {};
152 istep := 0;
153
154 ✗ for l in literals loop
155 ✗ istep := istep + 1;
156 ✗ values := Expression.ENUM_LITERAL(ty, l, istep) :: values;
157 end for;
158 ✗ then
159 ARRAY_RANGE(listArray(values), 1);
160
161 ✗ else INVALID_RANGE(exp);
162
163 end match;
164 end fromExp;
165
166 function fromDim
167 input Dimension dim;
168 input Boolean resizable;
169 output RangeIterator iterator;
170 algorithm
171 iterator := match dim
172 local
173 Type ty;
174
175 122447 case Dimension.INTEGER() then INT_RANGE(1, dim.size);
176
177 case Dimension.BOOLEAN()
178 2 then ARRAY_RANGE(listArray({Expression.BOOLEAN(false), Expression.BOOLEAN(true)}), 1);
179
180 case Dimension.ENUM(enumType = ty as Type.ENUMERATION())
181 25 then ARRAY_RANGE(listArray(Expression.makeEnumLiterals(ty)), 1);
182
183 ✗ case Dimension.EXP() then fromExp(dim.exp);
184
185
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 21 times.
31 case Dimension.RESIZABLE() then INT_RANGE(1, if resizable then Util.getOptionOrDefault(dim.opt_size, dim.size) else dim.size);
186
187 else
188 algorithm
189 ✗ Error.terminate(getInstanceName() + " got unknown dim", sourceInfo());
190 ✗ then
191 fail();
192
193 end match;
194 end fromDim;
195
196 function next
197 input output RangeIterator iterator;
198 output Expression nextExp;
199 algorithm
200 nextExp := match iterator
201 case INT_RANGE()
202 algorithm
203 372338 nextExp := Expression.INTEGER(iterator.current);
204 372338 iterator.current := iterator.current + 1;
205 then
206 nextExp;
207
208 case INT_STEP_RANGE()
209 algorithm
210 ✗ nextExp := Expression.INTEGER(iterator.current);
211 ✗ iterator.current := iterator.current + iterator.stepsize;
212 then
213 nextExp;
214
215 case REAL_RANGE()
216 algorithm
217 ✗ nextExp := Expression.REAL(iterator.start + iterator.stepsize * iterator.current);
218 ✗ iterator.current := iterator.current + 1;
219 then
220 nextExp;
221
222 case ARRAY_RANGE()
223 algorithm
224 7497 nextExp := arrayGet(iterator.values, iterator.index);
225 7497 iterator.index := iterator.index + 1;
226 then
227 nextExp;
228
229 case INVALID_RANGE()
230 algorithm
231 ✗ Error.terminate(getInstanceName() + " got invalid range " +
232 Expression.toString(iterator.exp), sourceInfo());
233 ✗ then
234 fail();
235 end match;
236 end next;
237
238 function hasNext
239 input RangeIterator iterator;
240 output Boolean hasNext;
241 algorithm
242 hasNext := match iterator
243 496158 case INT_RANGE() then iterator.current <= iterator.last;
244 ✗ case INT_STEP_RANGE() then if iterator.stepsize > 0 then iterator.current <= iterator.last
245 else iterator.current >= iterator.last;
246 ✗ case REAL_RANGE() then iterator.current < iterator.steps;
247
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8925 times.
17850 case ARRAY_RANGE() then iterator.index <= arrayLength(iterator.values);
248 case INVALID_RANGE()
249 algorithm
250 ✗ Error.terminate(getInstanceName() + " got invalid range " +
251 Expression.toString(iterator.exp), sourceInfo());
252 ✗ then
253 fail();
254 end match;
255 end hasNext;
256
257 function toList
258 input RangeIterator iterator;
259 output list<Expression> expl = listReverse(toListReverse(iterator));
260 end toList;
261
262 function toListReverse
263 input RangeIterator iterator;
264 output list<Expression> expl = {};
265 protected
266 RangeIterator iter = iterator;
267 Expression exp;
268 algorithm
269
2/2
✓ Branch 1 taken 2863 times.
✓ Branch 2 taken 888 times.
3751 while hasNext(iter) loop
270 2863 (iter, exp) := next(iter);
271 2863 expl := exp :: expl;
272 end while;
273 end toListReverse;
274
275 function map<T>
276 input RangeIterator iterator;
277 input FuncT func;
278 output list<T> lst = {};
279
280 partial function FuncT
281 input Expression exp;
282 output T res;
283 end FuncT;
284 protected
285 RangeIterator iter = iterator;
286 Expression exp;
287 algorithm
288
2/2
✓ Branch 1 taken 356576 times.
✓ Branch 2 taken 119593 times.
476169 while hasNext(iter) loop
289 356576 (iter, exp) := next(iter);
290
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 356576 times.
356576 lst := func(exp) :: lst;
291 end while;
292
293 119593 lst := listReverse(lst);
294 end map;
295
296 function fold<ArgT>
297 input RangeIterator iterator;
298 input FuncT func;
299 input output ArgT arg;
300
301 partial function FuncT
302 input Expression exp;
303 input output ArgT arg;
304 end FuncT;
305 protected
306 RangeIterator iter = iterator;
307 Expression exp;
308 algorithm
309 ✗ while hasNext(iter) loop
310 ✗ (iter, exp) := next(iter);
311 ✗ arg := func(exp, arg);
312 end while;
313 end fold;
314
315 annotation(__OpenModelica_Interface="nf_frontend");
316 end NFRangeIterator;
317