Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 94.7% 54 / 0 / 57
Functions: -% 0 / 1 / 1
Branches: 75.8% 47 / 0 / 62

OMCompiler/Compiler/NFFrontEnd/NFStructural.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 package NFStructural
37 "Contains utility functions for handling structural parameters."
38
39 import Attributes = NFAttributes;
40 import Binding = NFBinding;
41 import Call = NFCall;
42 import Component = NFComponent;
43 import ComponentRef = NFComponentRef;
44 import Dimension = NFDimension;
45 import Expression = NFExpression;
46 import InstContext = NFInstContext;
47 import NFInstNode.InstNode;
48 import NFPrefixes.Variability;
49 import Subscript = NFSubscript;
50
51 protected
52 import Util;
53
54 public
55 function isStructuralComponent
56 input Component component;
57 input Attributes compAttrs;
58 input Binding compBinding;
59 input InstNode compNode;
60 input Boolean compEval "If the component has an Evaluate=true annotation";
61 input Boolean parentEval "If any parent has an Evaluate=true annotation";
62 input InstContext.Type context;
63 output Boolean isStructural;
64 protected
65 Binding binding;
66 algorithm
67
2/2
✓ Branch 0 taken 110276 times.
✓ Branch 1 taken 172491 times.
282767 if compAttrs.variability <> Variability.PARAMETER then
68 // Only parameters can be structural.
69 isStructural := false;
70 elseif compEval or parentEval then
71
2/2
✓ Branch 1 taken 25144 times.
✓ Branch 2 taken 11056 times.
36200 binding := if Binding.isBound(compBinding) then
72 compBinding else Component.getTypeAttributeBinding(component, "start");
73
74 // If the component or any of its parents has an Evaluate=true annotation
75 // we should probably evaluate the parameter, which we do by marking it as
76 // structural.
77
2/2
✓ Branch 1 taken 36199 times.
✓ Branch 2 taken 1 time.
36200 if not Component.isFixed(component) then
78 // Except non-fixed parameters.
79 isStructural := false;
80 elseif Component.isExternalObject(component) then
81 // Except external objects.
82 isStructural := false;
83 elseif not (Binding.isBound(binding) or InstNode.hasBinding(compNode)) then
84 // Except parameters with no bindings.
85
2/4
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
1 if not parentEval and not InstContext.inRelaxed(context) then
86 // Print a warning if a parameter has an Evaluate=true annotation but no binding.
87 ✗ Error.addSourceMessage(Error.UNBOUND_PARAMETER_EVALUATE_TRUE,
88 {InstNode.name(compNode)}, InstNode.info(compNode));
89 end if;
90
91 isStructural := false;
92 elseif isBindingNotFixed(binding, requireFinal = false) then
93 // Except parameters that depend on non-fixed parameters.
94 isStructural := false;
95 else
96 // All other parameters are considered structural in this case.
97 isStructural := true;
98 end if;
99 //elseif Component.isFinal(component) and Component.isFixed(component) then
100 // // If a parameter is fixed and final we might also want to evaluate it,
101 // // since its binding can't be modified. But only if all parameters it
102 // // depends on are also fixed and final.
103 // if Binding.isUnbound(binding) or isBindingNotFixed(binding, requireFinal = true) then
104 // isStructural := false;
105 // else
106 // isStructural := true;
107 // end if;
108 else
109 isStructural := false;
110 end if;
111 end isStructuralComponent;
112
113 function isBindingNotFixed
114 input Binding binding;
115 input Boolean requireFinal;
116 input Integer maxDepth = 4;
117 output Boolean isNotFixed;
118 algorithm
119
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 42345 times.
42432 if maxDepth == 0 then
120 isNotFixed := true;
121 87 return;
122 end if;
123
124
2/2
✓ Branch 1 taken 29851 times.
✓ Branch 2 taken 12494 times.
42345 if Binding.hasExp(binding) then
125 29851 isNotFixed := isExpressionNotFixed(Binding.getExp(binding), requireFinal, maxDepth);
126 else
127 isNotFixed := true;
128 end if;
129 end isBindingNotFixed;
130
131 function isComponentBindingNotFixed
132 input Component component;
133 input InstNode node;
134 input Boolean requireFinal;
135 input Integer maxDepth;
136 input Boolean isRecord = false;
137 output Boolean isNotFixed;
138 protected
139 Binding binding;
140 InstNode parent;
141 algorithm
142 6511 binding := Component.getBinding(component);
143
144
2/2
✓ Branch 1 taken 279 times.
✓ Branch 2 taken 6232 times.
6511 if Binding.isUnbound(binding) then
145
4/4
✓ Branch 0 taken 278 times.
✓ Branch 1 taken 1 time.
✓ Branch 3 taken 100 times.
✓ Branch 4 taken 178 times.
279 if isRecord or InstNode.isRecord(node) then
146 // TODO: Check whether the record fields have bindings or not.
147 isNotFixed := false;
148 else
149 100 parent := InstNode.parent(node);
150
151
3/4
✓ Branch 1 taken 98 times.
✓ Branch 2 taken 2 times.
✓ Branch 4 taken 98 times.
✗ Branch 5 not taken.
100 if InstNode.isComponent(parent) and InstNode.isRecord(parent) then
152 98 isNotFixed := isComponentBindingNotFixed(InstNode.component(parent), parent, requireFinal, maxDepth, true);
153 else
154 2 binding := Component.getTypeAttributeBinding(component, "start");
155 2 isNotFixed := isBindingNotFixed(binding, requireFinal, maxDepth);
156 end if;
157 end if;
158 else
159 6232 isNotFixed := isBindingNotFixed(binding, requireFinal, maxDepth);
160 end if;
161 end isComponentBindingNotFixed;
162
163 function isExpressionNotFixed
164 input Expression exp;
165 input Boolean requireFinal = false;
166 input Integer maxDepth = 4;
167 output Boolean isNotFixed;
168 algorithm
169 isNotFixed := match exp
170 local
171 InstNode node;
172 Component c;
173 Variability var;
174
175 case Expression.CREF()
176 guard ComponentRef.isCref(exp.cref) and not ComponentRef.isIterator(exp.cref)
177 algorithm
178 23896 node := ComponentRef.node(exp.cref);
179
180
1/2
✓ Branch 1 taken 23896 times.
✗ Branch 2 not taken.
23896 if InstNode.isComponent(node) then
181 23896 c := InstNode.component(node);
182 23896 var := Component.variability(c);
183
184
4/4
✓ Branch 0 taken 7504 times.
✓ Branch 1 taken 16392 times.
✓ Branch 3 taken 7485 times.
✓ Branch 4 taken 19 times.
23896 if var <= Variability.STRUCTURAL_PARAMETER or ComponentRef.isResizable(exp.cref) then
185 // resizable parameters are evaluated when needed for structural decisions
186 isNotFixed := false;
187 elseif var == Variability.PARAMETER and
188 (not requireFinal or Component.isFinal(c)) and
189 not Component.isExternalObject(c) and
190 Component.isFixed(c) then
191 6413 isNotFixed := isComponentBindingNotFixed(c, node, requireFinal, maxDepth - 1);
192 else
193 isNotFixed := true;
194 end if;
195 else
196 isNotFixed := true;
197 end if;
198
4/6
✓ Branch 0 taken 23896 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 22470 times.
✓ Branch 4 taken 1426 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 22470 times.
47792 then
199 isNotFixed or
200 Expression.containsShallow(exp,
201 function isExpressionNotFixed(requireFinal = requireFinal, maxDepth = maxDepth));
202
203 case Expression.SIZE()
204 algorithm
205
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 if isSome(exp.dimIndex) then
206 3 isNotFixed := isExpressionNotFixed(Util.getOption(exp.dimIndex), requireFinal, maxDepth);
207 else
208 isNotFixed := false;
209 end if;
210 then
211 isNotFixed;
212
213 case Expression.CALL()
214 algorithm
215
3/4
✓ Branch 1 taken 2580 times.
✓ Branch 2 taken 2 times.
✓ Branch 4 taken 2580 times.
✗ Branch 5 not taken.
2582 if Call.isImpure(exp.call) or Call.isExternal(exp.call) then
216 isNotFixed := true;
217 else
218
1/2
✓ Branch 0 taken 2580 times.
✗ Branch 1 not taken.
5160 isNotFixed := Expression.containsShallow(exp,
219 function isExpressionNotFixed(requireFinal = requireFinal, maxDepth = maxDepth));
220 end if;
221 then
222 isNotFixed;
223
224
1/2
✓ Branch 0 taken 76292 times.
✗ Branch 1 not taken.
152584 else Expression.containsShallow(exp,
225 function isExpressionNotFixed(requireFinal = requireFinal, maxDepth = maxDepth));
226 end match;
227 end isExpressionNotFixed;
228
229 function markDimension
230 input Dimension dimension;
231 algorithm
232 () := match dimension
233 case Dimension.UNTYPED()
234 algorithm
235 65403 markExp(dimension.dimension);
236 then
237 ();
238
239 case Dimension.EXP()
240 algorithm
241 ✗ markExp(dimension.exp);
242 then
243 ();
244
245 else ();
246 end match;
247 end markDimension;
248
249 function markExp
250 input Expression exp;
251 import NFComponentRef.Origin;
252 algorithm
253 () := match exp
254 local
255 InstNode node;
256 Component comp;
257 Expression e;
258
259 case Expression.CREF(cref = ComponentRef.CREF(origin = Origin.CREF))
260 algorithm
261 62459 node := ComponentRef.node(exp.cref);
262
263
1/2
✓ Branch 1 taken 62459 times.
✗ Branch 2 not taken.
62459 if InstNode.isComponent(node) then
264 62459 comp := InstNode.component(node);
265
266
2/2
✓ Branch 1 taken 10163 times.
✓ Branch 2 taken 52296 times.
62459 if Component.variability(comp) == Variability.PARAMETER then
267 10163 markComponent(comp, node);
268 end if;
269 end if;
270
271 62459 Expression.applyShallow(exp, markExp);
272 then
273 ();
274
275 case Expression.SIZE()
276 algorithm
277 // The expression in the size expression should not be marked as
278 // structural, since only the type of it matters to determine the size.
279 // Subscripts in the expression should be marked as structural though.
280 2388 markSubscriptsInExp(exp.exp);
281
282 // The optional index should be marked as structural.
283
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2388 times.
✓ Branch 2 taken 2388 times.
✗ Branch 3 not taken.
2388 if isSome(exp.dimIndex) then
284 2388 SOME(e) := exp.dimIndex;
285 markExp(e);
286 end if;
287 then
288 ();
289
290 else
291 algorithm
292 185585 Expression.applyShallow(exp, markExp);
293 then
294 ();
295 end match;
296 end markExp;
297
298 function markSubscriptsInExp
299 input Expression exp;
300 algorithm
301 () := match exp
302 case Expression.CREF()
303 algorithm
304 33567 ComponentRef.applySubscripts(exp.cref, markSubscript);
305 then
306 ();
307
308 else
309 algorithm
310 4228 Expression.applyShallow(exp, markSubscriptsInExp);
311 then
312 ();
313 end match;
314 end markSubscriptsInExp;
315
316 function markComponent
317 input Component component;
318 input InstNode node;
319 protected
320 Component comp;
321 Option<Expression> binding;
322 algorithm
323 33767 comp := Component.setVariability(Variability.STRUCTURAL_PARAMETER, component);
324 33767 comp := Component.setFinal(comp, true);
325 33767 InstNode.updateComponent(comp, node);
326
327 33767 binding := Binding.getExpOpt(Component.getBinding(comp));
328
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 33767 times.
✓ Branch 2 taken 20927 times.
✓ Branch 3 taken 12840 times.
33767 if isSome(binding) then
329 20927 markExp(Util.getOption(binding));
330 end if;
331 end markComponent;
332
333 function markExpSize
334 input Expression exp;
335 algorithm
336 108661 Expression.apply(exp, markExpSize_traverser);
337 end markExpSize;
338
339 function markExpSize_traverser
340 input Expression exp;
341 algorithm
342 () := match exp
343 local
344 list<tuple<InstNode, Expression>> iters;
345
346 case Expression.CALL(call = Call.UNTYPED_ARRAY_CONSTRUCTOR(iters = iters))
347 algorithm
348
2/2
✓ Branch 0 taken 896 times.
✓ Branch 1 taken 896 times.
1792 for iter in iters loop
349 896 markExp(Util.tuple22(iter));
350 end for;
351 then
352 ();
353
354 else ();
355 end match;
356 end markExpSize_traverser;
357
358 function markSubscripts
359 input Expression exp;
360 algorithm
361 () := match exp
362 case Expression.CREF()
363 algorithm
364 ✗ ComponentRef.applySubscripts(exp.cref, markSubscript);
365 then
366 ();
367
368 else ();
369 end match;
370 end markSubscripts;
371
372 function markSubscript
373 input Subscript sub;
374 algorithm
375 () := match sub
376 329 case Subscript.UNTYPED() algorithm markExp(sub.exp); then ();
377 1269 case Subscript.INDEX() algorithm markExp(sub.index); then ();
378 7 case Subscript.SLICE() algorithm markExp(sub.slice); then ();
379 else ();
380 end match;
381 end markSubscript;
382
383 annotation(__OpenModelica_Interface="nf_frontend");
384 end NFStructural;
385