Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 70.4% 238 / 0 / 338
Functions: -% 0 / 1 / 1
Branches: 70.7% 130 / 0 / 184

OMCompiler/Compiler/NFFrontEnd/NFBackendExtension.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 NFBackendExtension
37 " ==========================================================================
38 kabdelhak: The following structures are used only in the backend to avoid a
39 forward dependency of the frontend to the backend. All functions for these
40 structures are defined in NBVariable.mo
41 ========================================================================== "
42
43 protected
44 // OF imports
45 import Absyn;
46 import AbsynUtil;
47 import DAE;
48 import Dump;
49 import SCode;
50 import SCodeUtil;
51
52 //NF imports
53 import Attributes = NFAttributes;
54 import NFBinding.Binding;
55 import NFBinding.Source;
56 import Call = NFCall;
57 import Ceval = NFCeval;
58 import ComplexType = NFComplexType;
59 import NFComponent.Component;
60 import ComponentRef = NFComponentRef;
61 import Dimension = NFDimension;
62 import Expression = NFExpression;
63 import ExpressionIterator = NFExpressionIterator;
64 import NFFunction.Function;
65 import NFPrefixes.{Direction, Variability};
66 import NFInstNode.InstNode;
67 import Type = NFType;
68 import Variable = NFVariable;
69
70 // Util imports
71 import Pointer;
72 import PointerWeak;
73 import UnorderedMap;
74 import MetaModelica.Dangerous.listReverseInPlace;
75
76 public
77 uniontype BackendInfo
78 record BACKEND_INFO
79 VariableKind varKind "Structural kind: state, algebraic...";
80 VariableAttributes attributes "values on built-in attributes";
81 Annotations annotations "values on annotations (vendor specific)";
82 Option<PointerWeak<Variable>> var_pre "Pointer (var -> pre) or (pre -> var) if existent.";
83 Option<PointerWeak<Variable>> var_seed "Pointer (var -> seed) or (seed -> var) if existent.";
84 Option<PointerWeak<Variable>> var_pder_res "Pointer (var -> pder, result var in Jacobian) or (pder -> var) if existent.";
85 Option<PointerWeak<Variable>> var_pder_tmp "Pointer (var -> pder, tmp var in Jacobian) or (pder -> var) if existent.";
86 Option<PointerWeak<Variable>> var_start "Pointer (var -> start) or (start -> var) if existent.";
87 Option<PointerWeak<Variable>> parent "record parent if it is part of a record.";
88 end BACKEND_INFO;
89
90 function toString
91 input BackendInfo backendInfo;
92 output String str;
93 algorithm
94 ✗ str := VariableAttributes.toString(backendInfo.attributes);
95 ✗ str := VariableKind.toString(backendInfo.varKind) + (if str == "" then "" else " " + str);
96 end toString;
97
98 function map
99 input output BackendInfo binfo;
100 input expFunc func;
101 partial function expFunc
102 input output Expression exp;
103 end expFunc;
104 algorithm
105 28789 binfo.attributes := VariableAttributes.map(binfo.attributes, func);
106 end map;
107
108 function getVarKind
109 input BackendInfo binfo;
110 output VariableKind varKind = binfo.varKind;
111 end getVarKind;
112
113 function setVarKind
114 input output BackendInfo binfo;
115 input VariableKind varKind;
116 algorithm
117 16067 binfo.varKind := varKind;
118 end setVarKind;
119
120 function setStateSelect
121 input output BackendInfo info;
122 input StateSelect stateSelect_val;
123 input Boolean overwrite = false;
124 algorithm
125 110 info.attributes := VariableAttributes.setStateSelect(info.attributes, stateSelect_val, overwrite);
126 end setStateSelect;
127
128 function setParent
129 input output BackendInfo binfo;
130 input Pointer<Variable> parent;
131 algorithm
132 804 binfo.parent := SOME(PointerWeak.downgrade(parent));
133 end setParent;
134
135 function weaken
136 "A partner edge owns nothing: the variable is in `VariablePointers`."
137 input Option<Pointer<Variable>> strong;
138 output Option<PointerWeak<Variable>> weak;
139 algorithm
140 weak := match strong
141 local Pointer<Variable> p;
142 4683 case SOME(p) then SOME(PointerWeak.downgrade(p));
143 else NONE();
144 end match;
145 end weaken;
146
147 function strengthen
148 "NONE() if the partner is gone, which the callers already handle."
149 input Option<PointerWeak<Variable>> weak;
150 output Option<Pointer<Variable>> strong;
151 algorithm
152 strong := matchcontinue weak
153 local PointerWeak<Variable> w;
154 4100 case SOME(w) then SOME(PointerWeak.upgrade(w));
155 else NONE();
156 end matchcontinue;
157 end strengthen;
158
159 partial function setPartner
160 input output BackendInfo binfo;
161 input Option<Pointer<Variable>> var_ptr;
162 end setPartner;
163
164 function setVarPre extends setPartner;
165 algorithm
166 162 binfo.var_pre := weaken(var_ptr);
167 end setVarPre;
168
169 function setVarSeed extends setPartner;
170 algorithm
171 1492 binfo.var_seed := weaken(var_ptr);
172 end setVarSeed;
173
174 function setVarPDer extends setPartner;
175 input Boolean isTmp;
176 algorithm
177
2/2
✓ Branch 0 taken 684 times.
✓ Branch 1 taken 1694 times.
2378 if isTmp then
178 684 binfo.var_pder_tmp := weaken(var_ptr);
179 else
180 1694 binfo.var_pder_res := weaken(var_ptr);
181 end if;
182 end setVarPDer;
183
184 function setVarStart extends setPartner;
185 algorithm
186 406 binfo.var_start := weaken(var_ptr);
187 end setVarStart;
188
189 function setAttributes
190 input output BackendInfo binfo;
191 input VariableAttributes attributes;
192 input Annotations annotations;
193 algorithm
194 5554 binfo.attributes := attributes;
195 binfo.annotations := annotations;
196 end setAttributes;
197
198 function setHideResult
199 input output BackendInfo binfo;
200 input Boolean hideResult;
201 algorithm
202 binfo := match binfo
203 local
204 Annotations anno;
205 case BACKEND_INFO(annotations = anno as ANNOTATIONS()) algorithm
206
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 967 times.
967 anno.hideResult := hideResult;
207 967 binfo.annotations := anno;
208 then binfo;
209 else binfo;
210 end match;
211 end setHideResult;
212
213 function scalarize
214 input BackendInfo binfo;
215 input Integer length;
216 output list<BackendInfo> binfo_list;
217 algorithm
218 binfo_list := match binfo.varKind
219 local
220 list<VariableAttributes> scalar_attributes;
221 Boolean uniform;
222 47468 case VariableKind.FRONTEND_DUMMY() then List.fill(binfo, length);
223 else algorithm
224 1483 (scalar_attributes, uniform) := VariableAttributes.scalarize(binfo.attributes, length);
225
2/2
✓ Branch 0 taken 1008 times.
✓ Branch 1 taken 475 times.
1483 if uniform then
226 1008 binfo.attributes := listHead(scalar_attributes);
227 end if;
228
6/6
✓ Branch 0 taken 1008 times.
✓ Branch 1 taken 475 times.
✓ Branch 3 taken 3651 times.
✓ Branch 4 taken 475 times.
✓ Branch 5 taken 3651 times.
✓ Branch 6 taken 475 times.
5134 then if uniform then List.fill(binfo, length) else
229 list(BACKEND_INFO(binfo.varKind, attr, binfo.annotations, binfo.var_pre, binfo.var_seed, binfo.var_pder_res, binfo.var_pder_tmp, binfo.var_start, binfo.parent) for attr in scalar_attributes);
230 end match;
231 end scalarize;
232 end BackendInfo;
233
234 constant BackendInfo DUMMY_BACKEND_INFO = BackendInfo.BACKEND_INFO(VariableKind.FRONTEND_DUMMY(), EMPTY_VAR_ATTR_REAL, EMPTY_ANNOTATIONS, NONE(), NONE(), NONE(), NONE(), NONE(), NONE());
235
236 uniontype VariableKind
237 record TIME end TIME;
238 record ALGEBRAIC end ALGEBRAIC;
239 record STATE
240 Integer index "how often this states was differentiated";
241 Option<PointerWeak<Variable>> derivative "pointer to the derivative";
242 Boolean natural "false if it was forced by StateSelect.always or StateSelect.prefer or generated by index reduction";
243 end STATE;
244 record STATE_DER
245 PointerWeak<Variable> state "Original state";
246 Option<Pointer<Expression>> alias "Optional alias state expression. Result of differentiating the state if existant!";
247 end STATE_DER;
248 record DUMMY_DER
249 PointerWeak<Variable> dummy_state "corresponding dummy state";
250 end DUMMY_DER;
251 record DUMMY_STATE
252 PointerWeak<Variable> dummy_der "corresponding dummy derivative";
253 end DUMMY_STATE; // ToDo: maybe dynamic state for dynamic state selection in index reduction
254 record DISCRETE end DISCRETE;
255 record DISCRETE_STATE end DISCRETE_STATE;
256 record PREVIOUS end PREVIOUS;
257 record CLOCK end CLOCK;
258 record CLOCKED end CLOCKED;
259 record PARAMETER
260 Option<Integer> resize_value "if the parameter is resizable, this is the computed optimal size";
261 end PARAMETER;
262 record CONSTANT end CONSTANT;
263 record ITERATOR end ITERATOR;
264 record RECORD
265 list<PointerWeak<Variable>> children;
266 Variability min_var;
267 Variability max_var;
268 end RECORD;
269 record START
270 PointerWeak<Variable> original "Pointer to the corresponding original variable.";
271 end START;
272 record EXTOBJ
273 Absyn.Path fullClassName;
274 end EXTOBJ;
275 record JAC_VAR end JAC_VAR;
276 record JAC_TMP_VAR end JAC_TMP_VAR;
277 record SEED_VAR end SEED_VAR;
278 record OPT_CONSTR end OPT_CONSTR;
279 record OPT_FCONSTR end OPT_FCONSTR;
280 record OPT_INPUT_WITH_DER end OPT_INPUT_WITH_DER;
281 record OPT_INPUT_DER end OPT_INPUT_DER;
282 record OPT_TGRID end OPT_TGRID;
283 record OPT_LOOP_INPUT
284 ComponentRef replaceCref;
285 end OPT_LOOP_INPUT;
286 // ToDo maybe deprecated:
287 record ALG_STATE "algebraic state used by inline solver" end ALG_STATE;
288 record ALG_STATE_OLD "algebraic state old value used by inline solver" end ALG_STATE_OLD;
289 record RESIDUAL_VAR end RESIDUAL_VAR;
290 record DAE_AUX_VAR "auxiliary variable used for DAEmode" end DAE_AUX_VAR;
291 record LOOP_ITERATION "used in SIMCODE, iteration variables in algebraic loops" end LOOP_ITERATION;
292 record LOOP_SOLVED "used in SIMCODE, inner variables of a torn algebraic loop" end LOOP_SOLVED;
293 record FRONTEND_DUMMY "Undefined variable type. Only to be used during frontend phase." end FRONTEND_DUMMY;
294
295 function toString
296 input VariableKind varKind;
297 output String str;
298 algorithm
299 str := match varKind
300 case TIME() then "[TIME]";
301 case ALGEBRAIC() then "[ALGB]";
302 case STATE() then "[STAT]";
303 case STATE_DER() then "[DER-]";
304 case DUMMY_DER() then "[DDER]";
305 case DUMMY_STATE() then "[DSTA]";
306 case DISCRETE() then "[DISC]";
307 case DISCRETE_STATE() then "[DISS]";
308 case PREVIOUS() then "[PRE-]";
309 case CLOCK() then "[CLCK]";
310 case CLOCKED() then "[CLKD]";
311 case PARAMETER() then "[PRMT]";
312 case CONSTANT() then "[CNST]";
313 case ITERATOR() then "[ITER]";
314 case RECORD() then "[RECD]";
315 case START() then "[STRT]";
316 case EXTOBJ() then "[EXTO]";
317 case JAC_VAR() then "[JVAR]";
318 case JAC_TMP_VAR() then "[JTMP]";
319 case SEED_VAR() then "[SEED]";
320 case OPT_CONSTR() then "[OPT][CONS]";
321 case OPT_FCONSTR() then "[OPT][FCON]";
322 case OPT_INPUT_WITH_DER() then "[OPT][INWD]";
323 case OPT_INPUT_DER() then "[OPT][INPD]";
324 case OPT_TGRID() then "[OPT][TGRD]";
325 case OPT_LOOP_INPUT() then "[OPT][LOOP]";
326 case ALG_STATE() then "[ASTA]";
327 case RESIDUAL_VAR() then "[RES-]";
328 case DAE_AUX_VAR() then "[AUX-]";
329 case LOOP_ITERATION() then "[LOOP]";
330 case LOOP_SOLVED() then "[INNR]";
331 case FRONTEND_DUMMY() then "[DMMY]";
332 else "[FAIL] " + getInstanceName() + " failed.";
333 end match;
334 end toString;
335
336 function isTimeDependent
337 input VariableKind varKind;
338 output Boolean b;
339 algorithm
340 // ToDo: check other types!
341 b := match varKind
342 case PARAMETER() then false;
343 case CONSTANT() then false;
344 case ITERATOR() then false;
345 case START() then false;
346 else true;
347 end match;
348 end isTimeDependent;
349
350 function fromType
351 "only creates record, parameter, discrete or algebraic kind"
352 input Type ty;
353 input Boolean makeParam;
354 output VariableKind varKind;
355 protected
356 Variability variability;
357 algorithm
358
2/2
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 777 times.
825 if Type.isRecord(Type.arrayElementType(ty)) then
359
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 2 times.
48 variability := if makeParam then NFPrefixes.Variability.PARAMETER else NFPrefixes.Variability.CONTINUOUS;
360 48 varKind := RECORD({}, variability, variability); // ToDo: children!
361 elseif makeParam then
362 varKind := PARAMETER(NONE());
363 elseif Type.isDiscrete(ty) then
364 varKind := DISCRETE();
365 else
366 varKind := ALGEBRAIC();
367 end if;
368 end fromType;
369 end VariableKind;
370
371 uniontype VariableAttributes
372 record VAR_ATTR_REAL
373 Option<Binding> quantity "quantity";
374 Option<Binding> unit "SI Unit for actual computation value";
375 Option<Binding> displayUnit "SI Unit only for displaying";
376 Option<Binding> min "Lower boundry";
377 Option<Binding> max "Upper boundry";
378 Option<Binding> start "start value";
379 Option<Binding> fixed "fixed - true: default for parameter/constant, false - default for other variables";
380 Option<Binding> nominal "nominal";
381 Option<StateSelect> stateSelect "Priority to be selected as a state during index reduction";
382 Option<TearingSelect> tearingSelect "Priority to be selected as an iteration variable during tearing";
383 Option<Uncertainty> uncertainty "Attributes from data reconcilliation";
384 Option<Distribution> distribution "ToDo: ???";
385 Option<Binding> binding "A binding expression for certain types. E.G. parameters";
386 Option<Boolean> isProtected "Defined in protected scope";
387 Option<Boolean> finalPrefix "Defined as final";
388 end VAR_ATTR_REAL;
389
390 record VAR_ATTR_INT
391 Option<Binding> quantity "quantity";
392 Option<Binding> min "Lower boundry";
393 Option<Binding> max "Upper boundry";
394 Option<Binding> start "start value";
395 Option<Binding> fixed "fixed - true: default for parameter/constant, false - default for other variables";
396 Option<Uncertainty> uncertainty "Attributes from data reconcilliation";
397 Option<Distribution> distribution "ToDo: ???";
398 Option<Binding> binding "A binding expression for certain types. E.G. parameters";
399 Option<Boolean> isProtected "Defined in protected scope";
400 Option<Boolean> finalPrefix "Defined as final";
401 end VAR_ATTR_INT;
402
403 record VAR_ATTR_BOOL
404 Option<Binding> quantity "quantity";
405 Option<Binding> start "start value";
406 Option<Binding> fixed "fixed - true: default for parameter/constant, false - default for other variables";
407 Option<Binding> binding "A binding expression for certain types. E.G. parameters";
408 Option<Boolean> isProtected "Defined in protected scope";
409 Option<Boolean> finalPrefix "Defined as final";
410 end VAR_ATTR_BOOL;
411
412 record VAR_ATTR_CLOCK
413 Option<Boolean> isProtected "Defined in protected scope";
414 Option<Boolean> finalPrefix "Defined as final";
415 end VAR_ATTR_CLOCK;
416
417 record VAR_ATTR_STRING
418 "kabdelhak: why does string have quantity/start/fixed?"
419 Option<Binding> quantity "quantity";
420 Option<Binding> start "start value";
421 Option<Binding> fixed "fixed - true: default for parameter/constant, false - default for other variables";
422 Option<Binding> binding "A binding expression for certain types. E.G. parameters";
423 Option<Boolean> isProtected "Defined in protected scope";
424 Option<Boolean> finalPrefix "Defined as final";
425 end VAR_ATTR_STRING;
426
427 record VAR_ATTR_ENUMERATION
428 Option<Binding> quantity "quantity";
429 Option<Binding> min "Lower boundry";
430 Option<Binding> max "Upper boundry";
431 Option<Binding> start "start value";
432 Option<Binding> fixed "fixed - true: default for parameter/constant, false - default for other variables";
433 Option<Binding> binding "A binding expression for certain types. E.G. parameters";
434 Option<Boolean> isProtected "Defined in protected scope";
435 Option<Boolean> finalPrefix "Defined as final";
436 end VAR_ATTR_ENUMERATION;
437
438 record VAR_ATTR_RECORD
439 UnorderedMap<String, Integer> indexMap;
440 array<VariableAttributes> childrenAttr;
441 end VAR_ATTR_RECORD;
442
443 type VarType = enumeration(ENUMERATION, CLOCK, STRING);
444
445 function toString
446 input VariableAttributes attr;
447 output String str = "";
448 algorithm
449 str := match attr
450 case VAR_ATTR_REAL()
451 1944 then attributesToString({
452 ("fixed", Util.applyOption(attr.fixed, Binding.getTypedExp)),
453 ("start", Util.applyOption(attr.start, Binding.getTypedExp)),
454 ("min", Util.applyOption(attr.min, Binding.getTypedExp)),
455 ("max", Util.applyOption(attr.max, Binding.getTypedExp)),
456 ("nominal", Util.applyOption(attr.nominal, Binding.getTypedExp))
457 }, attr.stateSelect, attr.tearingSelect);
458
459 case VAR_ATTR_INT()
460 192 then attributesToString({
461 ("fixed", Util.applyOption(attr.fixed, Binding.getTypedExp)),
462 ("start", Util.applyOption(attr.start, Binding.getTypedExp)),
463 ("min", Util.applyOption(attr.min, Binding.getTypedExp)),
464 ("max", Util.applyOption(attr.max, Binding.getTypedExp))
465 }, NONE(), NONE());
466
467 case VAR_ATTR_BOOL()
468 ✗ then attributesToString({
469 ("fixed", Util.applyOption(attr.fixed, Binding.getTypedExp)),
470 ("start", Util.applyOption(attr.start, Binding.getTypedExp))
471 }, NONE(), NONE());
472
473 case VAR_ATTR_CLOCK()
474 then "";
475
476 case VAR_ATTR_STRING()
477 ✗ then attributesToString({
478 ("fixed", Util.applyOption(attr.fixed, Binding.getTypedExp)),
479 ("start", Util.applyOption(attr.start, Binding.getTypedExp))
480 }, NONE(), NONE());
481
482 case VAR_ATTR_ENUMERATION()
483 ✗ then attributesToString({
484 ("fixed", Util.applyOption(attr.fixed, Binding.getTypedExp)),
485 ("start", Util.applyOption(attr.start, Binding.getTypedExp)),
486 ("min", Util.applyOption(attr.min, Binding.getTypedExp)),
487 ("max", Util.applyOption(attr.max, Binding.getTypedExp))
488 }, NONE(), NONE());
489
490 case VAR_ATTR_RECORD()
491 ✗ then List.toString(UnorderedMap.toList(attr.indexMap), function recordString(childrenAttr = attr.childrenAttr), List.Style.FLAT);
492
493 else getInstanceName() + " failed. Attribute string could not be created.";
494 end match;
495 // put the string in parentheses only if it is not empty
496
3/4
✓ Branch 0 taken 1053 times.
✓ Branch 1 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1053 times.
1068 str := if "" == str then "" else "(" + str + ")";
497 end toString;
498
499 function recordString
500 input tuple<String, Integer> attr_tpl;
501 input array<VariableAttributes> childrenAttr;
502 output String str;
503 protected
504 String name;
505 Integer index;
506 algorithm
507 ✗ (name, index) := attr_tpl;
508 ✗ str := name + toString(childrenAttr[index]);
509 end recordString;
510
511 function create
512 input list<tuple<String, Binding>> attrs;
513 input Type ty;
514 input Attributes compAttrs;
515 input list<Variable> children;
516 input SCode.Comment comment;
517 output VariableAttributes attributes;
518 protected
519 Boolean is_final;
520 ComplexType complexTy;
521 algorithm
522
4/4
✓ Branch 0 taken 13435 times.
✓ Branch 1 taken 975 times.
✓ Branch 2 taken 13373 times.
✓ Branch 3 taken 62 times.
14410 is_final := compAttrs.isFinal or
523 compAttrs.variability == Variability.STRUCTURAL_PARAMETER;
524
525 attributes := match Type.arrayElementType(ty)
526 7637 case Type.REAL() then createReal(attrs, is_final, comment);
527 5830 case Type.INTEGER() then createInt(attrs, is_final);
528 645 case Type.BOOLEAN() then createBool(attrs, is_final);
529 30 case Type.STRING() then createString(attrs, is_final);
530 70 case Type.ENUMERATION() then createEnum(attrs, is_final);
531 39 case Type.CLOCK() then createClock(is_final);
532 case Type.COMPLEX(complexTy = complexTy as ComplexType.RECORD())
533 156 then createRecord(attrs, complexTy.indexMap, children, is_final);
534
535 3 else createReal(attrs, is_final, comment);
536 end match;
537 end create;
538
539 function map
540 input output VariableAttributes attributes;
541 input expFunc func;
542 partial function expFunc
543 input output Expression exp;
544 end expFunc;
545 algorithm
546 attributes := match attributes
547 case VAR_ATTR_REAL() algorithm
548 53266 attributes.quantity := Util.applyOption(attributes.quantity, function Binding.mapExp(mapFn = func));
549 53266 attributes.unit := Util.applyOption(attributes.unit, function Binding.mapExp(mapFn = func));
550 53266 attributes.displayUnit := Util.applyOption(attributes.displayUnit, function Binding.mapExp(mapFn = func));
551 53266 attributes.min := Util.applyOption(attributes.min, function Binding.mapExp(mapFn = func));
552 53266 attributes.max := Util.applyOption(attributes.max, function Binding.mapExp(mapFn = func));
553 53266 attributes.start := Util.applyOption(attributes.start, function Binding.mapExp(mapFn = func));
554 53266 attributes.fixed := Util.applyOption(attributes.fixed, function Binding.mapExp(mapFn = func));
555 53266 attributes.nominal := Util.applyOption(attributes.nominal, function Binding.mapExp(mapFn = func));
556 53266 attributes.binding := Util.applyOption(attributes.binding, function Binding.mapExp(mapFn = func));
557 then attributes;
558
559 case VAR_ATTR_INT() algorithm
560 2024 attributes.quantity := Util.applyOption(attributes.quantity, function Binding.mapExp(mapFn = func));
561 2024 attributes.min := Util.applyOption(attributes.min, function Binding.mapExp(mapFn = func));
562 2024 attributes.max := Util.applyOption(attributes.max, function Binding.mapExp(mapFn = func));
563 2024 attributes.start := Util.applyOption(attributes.start, function Binding.mapExp(mapFn = func));
564 2024 attributes.fixed := Util.applyOption(attributes.fixed, function Binding.mapExp(mapFn = func));
565 2024 attributes.binding := Util.applyOption(attributes.binding, function Binding.mapExp(mapFn = func));
566 then attributes;
567
568 case VAR_ATTR_BOOL() algorithm
569 2580 attributes.quantity := Util.applyOption(attributes.quantity, function Binding.mapExp(mapFn = func));
570 2580 attributes.start := Util.applyOption(attributes.start, function Binding.mapExp(mapFn = func));
571 2580 attributes.fixed := Util.applyOption(attributes.fixed, function Binding.mapExp(mapFn = func));
572 2580 attributes.binding := Util.applyOption(attributes.binding, function Binding.mapExp(mapFn = func));
573 then attributes;
574
575 case VAR_ATTR_STRING() algorithm
576 120 attributes.quantity := Util.applyOption(attributes.quantity, function Binding.mapExp(mapFn = func));
577 120 attributes.start := Util.applyOption(attributes.start, function Binding.mapExp(mapFn = func));
578 120 attributes.fixed := Util.applyOption(attributes.fixed, function Binding.mapExp(mapFn = func));
579 120 attributes.binding := Util.applyOption(attributes.binding, function Binding.mapExp(mapFn = func));
580 then attributes;
581
582 case VAR_ATTR_ENUMERATION() algorithm
583 272 attributes.quantity := Util.applyOption(attributes.quantity, function Binding.mapExp(mapFn = func));
584 272 attributes.min := Util.applyOption(attributes.min, function Binding.mapExp(mapFn = func));
585 272 attributes.max := Util.applyOption(attributes.max, function Binding.mapExp(mapFn = func));
586 272 attributes.start := Util.applyOption(attributes.start, function Binding.mapExp(mapFn = func));
587 272 attributes.fixed := Util.applyOption(attributes.fixed, function Binding.mapExp(mapFn = func));
588 272 attributes.binding := Util.applyOption(attributes.binding, function Binding.mapExp(mapFn = func));
589 then attributes;
590
591 case VAR_ATTR_RECORD() algorithm
592
4/4
✓ Branch 0 taken 682 times.
✓ Branch 1 taken 312 times.
✓ Branch 3 taken 682 times.
✓ Branch 4 taken 312 times.
2300 attributes.childrenAttr := listArray(list(map(attr, func) for attr in attributes.childrenAttr));
593 then attributes;
594
595 else attributes;
596 end match;
597 end map;
598
599 function setFixed
600 input output VariableAttributes attributes;
601 input Type ty;
602 input Boolean b = true;
603 input Boolean overwrite = false;
604 protected
605 list<Integer> sizes;
606 Expression start, iter_range, fixedExp = Expression.BOOLEAN(b);
607 Option<Expression> step;
608 InstNode iter_name;
609 list<tuple<InstNode, Expression>> iterators = {};
610 Binding fixedBinding;
611 algorithm
612 // make array constructor if it is an array
613
2/2
✓ Branch 1 taken 439 times.
✓ Branch 2 taken 3003 times.
3442 if Type.isArray(ty) then
614
4/4
✓ Branch 1 taken 633 times.
✓ Branch 2 taken 439 times.
✓ Branch 3 taken 633 times.
✓ Branch 4 taken 439 times.
1072 sizes := list(Dimension.size(dim) for dim in Type.arrayDims(ty));
615 start := Expression.INTEGER(1);
616 step := NONE();
617
2/2
✓ Branch 0 taken 633 times.
✓ Branch 1 taken 439 times.
1072 for stop in sizes loop
618 633 iter_name := InstNode.newUniqueIterator();
619 633 iter_range := Expression.RANGE(Type.INTEGER(), start, step, Expression.INTEGER(stop));
620 633 iterators := (iter_name, iter_range) :: iterators;
621 end for;
622 439 fixedExp := Expression.CALL(Call.TYPED_ARRAY_CONSTRUCTOR(ty, Expression.variability(fixedExp), NFPrefixes.Purity.PURE, fixedExp, listReverse(iterators)));
623 end if;
624 3442 fixedBinding := Binding.makeFlat(fixedExp, Variability.CONSTANT, Source.GENERATED);
625
626 attributes := match attributes
627 case VAR_ATTR_REAL() guard(overwrite or isNone(attributes.fixed)) algorithm
628 2657 attributes.fixed := SOME(fixedBinding);
629 then attributes;
630
631 case VAR_ATTR_INT() guard(overwrite or isNone(attributes.fixed)) algorithm
632 175 attributes.fixed := SOME(fixedBinding);
633 then attributes;
634
635 case VAR_ATTR_BOOL() guard(overwrite or isNone(attributes.fixed)) algorithm
636 486 attributes.fixed := SOME(fixedBinding);
637 then attributes;
638
639 case VAR_ATTR_STRING() guard(overwrite or isNone(attributes.fixed)) algorithm
640 30 attributes.fixed := SOME(fixedBinding);
641 then attributes;
642
643 case VAR_ATTR_ENUMERATION() guard(overwrite or isNone(attributes.fixed)) algorithm
644 67 attributes.fixed := SOME(fixedBinding);
645 then attributes;
646
647 else attributes;
648 end match;
649 end setFixed;
650
651 function isFixed
652 input VariableAttributes attributes;
653 output Boolean fixed;
654 algorithm
655 fixed := match attributes
656 local
657 Binding b;
658 ✗ case VAR_ATTR_REAL(fixed = SOME(b)) then Expression.isAllTrue(Binding.getTypedExp(b));
659 ✗ case VAR_ATTR_INT(fixed = SOME(b)) then Expression.isAllTrue(Binding.getTypedExp(b));
660 ✗ case VAR_ATTR_BOOL(fixed = SOME(b)) then Expression.isAllTrue(Binding.getTypedExp(b));
661 ✗ case VAR_ATTR_STRING(fixed = SOME(b)) then Expression.isAllTrue(Binding.getTypedExp(b));
662 ✗ case VAR_ATTR_ENUMERATION(fixed = SOME(b)) then Expression.isAllTrue(Binding.getTypedExp(b));
663 else false;
664 end match;
665 end isFixed;
666
667 function setStartAttribute
668 input output VariableAttributes attributes;
669 input Expression start;
670 input Boolean overwrite = false;
671 protected
672 Binding startBinding;
673 algorithm
674 2981 startBinding := Binding.makeFlat(start, Expression.variability(start), Source.GENERATED);
675 attributes := match attributes
676 case VAR_ATTR_REAL() guard(overwrite or isNone(attributes.start)) algorithm
677 1937 attributes.start := SOME(startBinding);
678 then attributes;
679
680 case VAR_ATTR_INT() guard(overwrite or isNone(attributes.start)) algorithm
681 176 attributes.start := SOME(startBinding);
682 then attributes;
683
684 case VAR_ATTR_BOOL() guard(overwrite or isNone(attributes.start)) algorithm
685 497 attributes.start := SOME(startBinding);
686 then attributes;
687
688 case VAR_ATTR_STRING() guard(overwrite or isNone(attributes.start)) algorithm
689 27 attributes.start := SOME(startBinding);
690 then attributes;
691
692 case VAR_ATTR_ENUMERATION() guard(overwrite or isNone(attributes.start)) algorithm
693 67 attributes.start := SOME(startBinding);
694 then attributes;
695
696 else attributes;
697 end match;
698 end setStartAttribute;
699
700 function getStartAttribute
701 input VariableAttributes attributes;
702 output Option<Expression> start;
703 algorithm
704 start := match attributes
705 7050 case VAR_ATTR_REAL() then Util.applyOption(attributes.start, Binding.getTypedExp);
706 254 case VAR_ATTR_INT() then Util.applyOption(attributes.start, Binding.getTypedExp);
707 547 case VAR_ATTR_BOOL() then Util.applyOption(attributes.start, Binding.getTypedExp);
708 30 case VAR_ATTR_STRING() then Util.applyOption(attributes.start, Binding.getTypedExp);
709 68 case VAR_ATTR_ENUMERATION() then Util.applyOption(attributes.start, Binding.getTypedExp);
710 else NONE();
711 end match;
712 end getStartAttribute;
713
714 function setMin
715 input output VariableAttributes attributes;
716 input Option<Expression> min_val;
717 input Boolean overwrite = false;
718 protected
719 Option<Binding> min_binding = Util.applyOption(min_val, expToGeneratedBinding);
720 algorithm
721 attributes := match attributes
722
723 case VAR_ATTR_REAL() guard(overwrite or isNone(attributes.min)) algorithm
724 78 attributes.min := min_binding;
725 then attributes;
726
727 case VAR_ATTR_INT() guard(overwrite or isNone(attributes.min)) algorithm
728 10 attributes.min := min_binding;
729 then attributes;
730
731 case VAR_ATTR_ENUMERATION() guard(overwrite or isNone(attributes.min)) algorithm
732 ✗ attributes.min := min_binding;
733 then attributes;
734
735 else attributes;
736 end match;
737 end setMin;
738
739 function setMax
740 input output VariableAttributes attributes;
741 input Option<Expression> max_val;
742 input Boolean overwrite = false;
743 protected
744 Option<Binding> max_binding = Util.applyOption(max_val, expToGeneratedBinding);
745 algorithm
746 attributes := match attributes
747
748 case VAR_ATTR_REAL() guard(overwrite or isNone(attributes.max)) algorithm
749 67 attributes.max := max_binding;
750 then attributes;
751
752 case VAR_ATTR_INT() guard(overwrite or isNone(attributes.max)) algorithm
753 10 attributes.max := max_binding;
754 then attributes;
755
756 case VAR_ATTR_ENUMERATION() guard(overwrite or isNone(attributes.max)) algorithm
757 ✗ attributes.max := max_binding;
758 then attributes;
759
760 else attributes;
761 end match;
762 end setMax;
763
764 function merge
765 "Merges the attributes from src into dst. Used by inlining to carry the
766 attributes declared on a function input/output (src) onto the model
767 variable (dst) that is bound to it, so they are not lost when the call is
768 replaced by the function body (see #15947). The model variable wins for
769 any scalar attribute that is already set; for min/max the tightest bound
770 wins."
771 input output VariableAttributes dst;
772 input VariableAttributes src;
773 algorithm
774 dst := match (dst, src)
775 case (VAR_ATTR_REAL(), VAR_ATTR_REAL()) algorithm
776 1674 dst.quantity := mergeOpt(dst.quantity, src.quantity);
777 1674 dst.unit := mergeOpt(dst.unit, src.unit);
778 1674 dst.displayUnit := mergeOpt(dst.displayUnit, src.displayUnit);
779 1674 dst.min := tightestBound(dst.min, src.min, true);
780 1674 dst.max := tightestBound(dst.max, src.max, false);
781 1674 dst.start := mergeOpt(dst.start, src.start);
782 1674 dst.fixed := mergeOpt(dst.fixed, src.fixed);
783 1674 dst.nominal := mergeOpt(dst.nominal, src.nominal);
784 then dst;
785
786 case (VAR_ATTR_INT(), VAR_ATTR_INT()) algorithm
787 8 dst.quantity := mergeOpt(dst.quantity, src.quantity);
788 8 dst.min := tightestBound(dst.min, src.min, true);
789 8 dst.max := tightestBound(dst.max, src.max, false);
790 8 dst.start := mergeOpt(dst.start, src.start);
791 8 dst.fixed := mergeOpt(dst.fixed, src.fixed);
792 then dst;
793
794 case (VAR_ATTR_BOOL(), VAR_ATTR_BOOL()) algorithm
795 ✗ dst.quantity := mergeOpt(dst.quantity, src.quantity);
796 ✗ dst.start := mergeOpt(dst.start, src.start);
797 ✗ dst.fixed := mergeOpt(dst.fixed, src.fixed);
798 then dst;
799
800 case (VAR_ATTR_STRING(), VAR_ATTR_STRING()) algorithm
801 ✗ dst.quantity := mergeOpt(dst.quantity, src.quantity);
802 ✗ dst.start := mergeOpt(dst.start, src.start);
803 ✗ dst.fixed := mergeOpt(dst.fixed, src.fixed);
804 then dst;
805
806 case (VAR_ATTR_ENUMERATION(), VAR_ATTR_ENUMERATION()) algorithm
807 ✗ dst.quantity := mergeOpt(dst.quantity, src.quantity);
808 ✗ dst.min := mergeOpt(dst.min, src.min);
809 ✗ dst.max := mergeOpt(dst.max, src.max);
810 ✗ dst.start := mergeOpt(dst.start, src.start);
811 ✗ dst.fixed := mergeOpt(dst.fixed, src.fixed);
812 then dst;
813
814 else dst;
815 end match;
816 end merge;
817
818 function mergeOpt
819 "Keeps dst if it is already set, otherwise takes src."
820 input output Option<Binding> dst;
821 input Option<Binding> src;
822 algorithm
823
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 10068 times.
✓ Branch 2 taken 5463 times.
✓ Branch 3 taken 4605 times.
10068 dst := if isSome(dst) then dst else src;
824 end mergeOpt;
825
826 function tightestBound
827 "Picks the tighter of two bounds when both are constant numbers, otherwise
828 keeps the already present (dst) bound. isMin = true for lower bounds
829 (the larger value is tighter), false for upper bounds (the smaller value
830 is tighter)."
831 input Option<Binding> dst;
832 input Option<Binding> src;
833 input Boolean isMin;
834 output Option<Binding> res;
835 protected
836 Binding db, sb;
837 Expression de, se;
838 Real dv, sv;
839 algorithm
840
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3364 times.
✓ Branch 2 taken 2042 times.
✓ Branch 3 taken 1322 times.
3364 if isNone(dst) then
841 res := src;
842 elseif isNone(src) then
843 res := dst;
844 else
845 1779 SOME(db) := dst;
846 1779 SOME(sb) := src;
847 1779 de := Binding.getTypedExp(db);
848 1779 se := Binding.getTypedExp(sb);
849 // both bounds must be constant numbers to be able to compare them
850
3/4
✓ Branch 1 taken 1523 times.
✓ Branch 2 taken 256 times.
✓ Branch 4 taken 1523 times.
✗ Branch 5 not taken.
1779 if Expression.isConstNumber(de) and Expression.isConstNumber(se) then
851 1523 dv := Expression.realValue(de);
852 1523 sv := Expression.realValue(se);
853
2/2
✓ Branch 0 taken 823 times.
✓ Branch 1 taken 700 times.
1523 if isMin then
854
2/2
✓ Branch 0 taken 818 times.
✓ Branch 1 taken 5 times.
823 res := if sv > dv then src else dst;
855 else
856
1/2
✓ Branch 0 taken 700 times.
✗ Branch 1 not taken.
700 res := if sv < dv then src else dst;
857 end if;
858 else
859 res := dst;
860 end if;
861 end if;
862 end tightestBound;
863
864 function setStateSelect
865 input output VariableAttributes attributes;
866 input StateSelect stateSelect_val;
867 input Boolean overwrite = false;
868 algorithm
869 attributes := match attributes
870
871 case VAR_ATTR_REAL() guard(overwrite or isNone(attributes.stateSelect)) algorithm
872 125 attributes.stateSelect := SOME(stateSelect_val);
873 then attributes;
874
875 else attributes;
876 end match;
877 end setStateSelect;
878
879 function getStateSelect
880 input VariableAttributes attributes;
881 output StateSelect stateSelect;
882 algorithm
883 stateSelect := match attributes
884 case VAR_ATTR_REAL(stateSelect = SOME(stateSelect)) then stateSelect;
885 else StateSelect.DEFAULT;
886 end match;
887 end getStateSelect;
888
889 function setTearingSelect
890 input output VariableAttributes attributes;
891 input TearingSelect tearingSelect_val;
892 input Boolean overwrite = false;
893 algorithm
894 attributes := match attributes
895
896 case VAR_ATTR_REAL() guard(overwrite or isNone(attributes.tearingSelect)) algorithm
897 ✗ attributes.tearingSelect := SOME(tearingSelect_val);
898 then attributes;
899
900 else attributes;
901 end match;
902 end setTearingSelect;
903
904 function getTearingSelect
905 input VariableAttributes attributes;
906 output TearingSelect tearingSelect;
907 algorithm
908 tearingSelect := match attributes
909 case VAR_ATTR_REAL(tearingSelect = SOME(tearingSelect)) then tearingSelect;
910 else TearingSelect.DEFAULT;
911 end match;
912 end getTearingSelect;
913
914 function getMin
915 input VariableAttributes attr;
916 output Option<Expression> min;
917 algorithm
918 min := match attr
919 1947 case VAR_ATTR_REAL() then Util.applyOption(attr.min, Binding.getTypedExp);
920 20 case VAR_ATTR_INT() then Util.applyOption(attr.min, Binding.getTypedExp);
921 1 case VAR_ATTR_ENUMERATION() then Util.applyOption(attr.min, Binding.getTypedExp);
922 else NONE();
923 end match;
924 end getMin;
925
926 function getMax
927 input VariableAttributes attr;
928 output Option<Expression> max;
929 algorithm
930 max := match attr
931 1947 case VAR_ATTR_REAL() then Util.applyOption(attr.max, Binding.getTypedExp);
932 20 case VAR_ATTR_INT() then Util.applyOption(attr.max, Binding.getTypedExp);
933 1 case VAR_ATTR_ENUMERATION() then Util.applyOption(attr.max, Binding.getTypedExp);
934 else NONE();
935 end match;
936 end getMax;
937
938 function getNominal
939 input VariableAttributes attr;
940 output Option<Expression> nominal;
941 algorithm
942 nominal := match attr
943 1951 case VAR_ATTR_REAL() then Util.applyOption(attr.nominal, Binding.getTypedExp);
944 else NONE();
945 end match;
946 end getNominal;
947
948 function scalarizeReal
949 input ExpressionIterator quantity_iter "quantity";
950 input ExpressionIterator unit_iter "SI Unit for actual computation value";
951 input ExpressionIterator displayUnit_iter "SI Unit only for displaying";
952 input ExpressionIterator min_iter "Lower boundry";
953 input ExpressionIterator max_iter "Upper boundry";
954 input ExpressionIterator start_iter "start value";
955 input ExpressionIterator fixed_iter "fixed - true: default for parameter/constant, false - default for other variables";
956 input ExpressionIterator nominal_iter "nominal";
957 input Option<StateSelect> stateSelect "Priority to be selected as a state during index reduction";
958 input Option<TearingSelect> tearingSelect "Priority to be selected as an iteration variable during tearing";
959 input Option<Uncertainty> uncertainty "Attributes from data reconcilliation";
960 input Option<Distribution> distribution "ToDo: ???";
961 input ExpressionIterator binding_iter "A binding expression for certain types. E.G. parameters";
962 input Option<Boolean> isProtected "Defined in protected scope";
963 input Option<Boolean> finalPrefix "Defined as final";
964 input Integer length "length of result";
965 output list<VariableAttributes> scalar_attributes = {};
966 output Boolean uniform;
967 protected
968 Option<Expression> quantity_e, unit_e, displayUnit_e, min_e, max_e, start_e, fixed_e, nominal_e, binding_e;
969 ExpressionIterator quantity_loc = quantity_iter, unit_loc = unit_iter, displayUnit_loc = displayUnit_iter, min_loc = min_iter, max_loc = max_iter, start_loc = start_iter, fixed_loc = fixed_iter, nominal_loc = nominal_iter, binding_loc = binding_iter;
970 algorithm
971
4/4
✓ Branch 0 taken 1159 times.
✓ Branch 1 taken 245 times.
✓ Branch 3 taken 200 times.
✓ Branch 4 taken 959 times.
1404 uniform := length > 1 and List.all({quantity_iter, unit_iter, displayUnit_iter, min_iter, max_iter, start_iter, fixed_iter, nominal_iter, binding_iter}, ExpressionIterator.isUniform);
972
2/2
✓ Branch 0 taken 444 times.
✓ Branch 1 taken 1 time.
5951 for i in 1:(if uniform then 1 else length) loop
973 4547 (quantity_loc, quantity_e) := ExpressionIterator.nextOpt(quantity_loc);
974 4547 (unit_loc, unit_e) := ExpressionIterator.nextOpt(unit_loc);
975 4547 (displayUnit_loc, displayUnit_e) := ExpressionIterator.nextOpt(displayUnit_loc);
976 4547 (min_loc, min_e) := ExpressionIterator.nextOpt(min_loc);
977 4547 (max_loc, max_e) := ExpressionIterator.nextOpt(max_loc);
978 4547 (start_loc, start_e) := ExpressionIterator.nextOpt(start_loc);
979 4547 (fixed_loc, fixed_e) := ExpressionIterator.nextOpt(fixed_loc);
980 4547 (nominal_loc, nominal_e) := ExpressionIterator.nextOpt(nominal_loc);
981 4547 (binding_loc, binding_e) := ExpressionIterator.nextOpt(binding_loc);
982 4547 scalar_attributes := VAR_ATTR_REAL(
983 Util.applyOption(quantity_e, expToGeneratedBinding),
984 Util.applyOption(unit_e, expToGeneratedBinding),
985 Util.applyOption(displayUnit_e, expToGeneratedBinding),
986 Util.applyOption(min_e, expToGeneratedBinding),
987 Util.applyOption(max_e, expToGeneratedBinding),
988 Util.applyOption(start_e, expToGeneratedBinding),
989 Util.applyOption(fixed_e, expToGeneratedBinding),
990 Util.applyOption(nominal_e, expToGeneratedBinding),
991 stateSelect, tearingSelect, uncertainty, distribution,
992 Util.applyOption(binding_e, expToGeneratedBinding),
993 isProtected, finalPrefix) :: scalar_attributes;
994 end for;
995
2/2
✓ Branch 0 taken 959 times.
✓ Branch 1 taken 445 times.
1404 scalar_attributes := if uniform then List.fill(listHead(scalar_attributes), length) else listReverseInPlace(scalar_attributes);
996 end scalarizeReal;
997
998 function scalarizeInt
999 input ExpressionIterator quantity_iter "quantity";
1000 input ExpressionIterator min_iter "Lower boundry";
1001 input ExpressionIterator max_iter "Upper boundry";
1002 input ExpressionIterator start_iter "start value";
1003 input ExpressionIterator fixed_iter "fixed - true: default for parameter/constant, false - default for other variables";
1004 input Option<Uncertainty> uncertainty "Attributes from data reconcilliation";
1005 input Option<Distribution> distribution "ToDo: ???";
1006 input ExpressionIterator binding_iter "A binding expression for certain types. E.G. parameters";
1007 input Option<Boolean> isProtected "Defined in protected scope";
1008 input Option<Boolean> finalPrefix "Defined as final";
1009 input Integer length "length of result";
1010 output list<VariableAttributes> scalar_attributes = {};
1011 output Boolean uniform;
1012 protected
1013 Option<Expression> quantity_e, min_e, max_e, start_e, fixed_e, binding_e;
1014 ExpressionIterator quantity_loc = quantity_iter, min_loc = min_iter, max_loc = max_iter, start_loc = start_iter, fixed_loc = fixed_iter, binding_loc = binding_iter;
1015 algorithm
1016
4/4
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 9 times.
✓ Branch 3 taken 17 times.
✓ Branch 4 taken 36 times.
62 uniform := length > 1 and List.all({quantity_iter, min_iter, max_iter, start_iter, fixed_iter, binding_iter}, ExpressionIterator.isUniform);
1017
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
157 for i in 1:(if uniform then 1 else length) loop
1018 95 (quantity_loc, quantity_e) := ExpressionIterator.nextOpt(quantity_loc);
1019 95 (min_loc, min_e) := ExpressionIterator.nextOpt(min_loc);
1020 95 (max_loc, max_e) := ExpressionIterator.nextOpt(max_loc);
1021 95 (start_loc, start_e) := ExpressionIterator.nextOpt(start_loc);
1022 95 (fixed_loc, fixed_e) := ExpressionIterator.nextOpt(fixed_loc);
1023 95 (binding_loc, binding_e) := ExpressionIterator.nextOpt(binding_loc);
1024 95 scalar_attributes := VAR_ATTR_INT(
1025 Util.applyOption(quantity_e, expToGeneratedBinding),
1026 Util.applyOption(min_e, expToGeneratedBinding),
1027 Util.applyOption(max_e, expToGeneratedBinding),
1028 Util.applyOption(start_e, expToGeneratedBinding),
1029 Util.applyOption(fixed_e, expToGeneratedBinding),
1030 uncertainty, distribution,
1031 Util.applyOption(binding_e, expToGeneratedBinding),
1032 isProtected, finalPrefix) :: scalar_attributes;
1033 end for;
1034
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 26 times.
62 scalar_attributes := if uniform then List.fill(listHead(scalar_attributes), length) else listReverseInPlace(scalar_attributes);
1035 end scalarizeInt;
1036
1037 function scalarizeBool
1038 input ExpressionIterator quantity_iter "quantity";
1039 input ExpressionIterator start_iter "start value";
1040 input ExpressionIterator fixed_iter "fixed - true: default for parameter/constant, false - default for other variables";
1041 input ExpressionIterator binding_iter "A binding expression for certain types. E.G. parameters";
1042 input Option<Boolean> isProtected "Defined in protected scope";
1043 input Option<Boolean> finalPrefix "Defined as final";
1044 input Integer length "length of result";
1045 output list<VariableAttributes> scalar_attributes = {};
1046 output Boolean uniform;
1047 protected
1048 Option<Expression> quantity_e, start_e, fixed_e, binding_e;
1049 ExpressionIterator quantity_loc = quantity_iter, start_loc = start_iter, fixed_loc = fixed_iter, binding_loc = binding_iter;
1050 algorithm
1051
3/4
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
17 uniform := length > 1 and List.all({quantity_iter, start_iter, fixed_iter, binding_iter}, ExpressionIterator.isUniform);
1052
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
34 for i in 1:(if uniform then 1 else length) loop
1053 17 (quantity_loc, quantity_e) := ExpressionIterator.nextOpt(quantity_loc);
1054 17 (start_loc, start_e) := ExpressionIterator.nextOpt(start_loc);
1055 17 (fixed_loc, fixed_e) := ExpressionIterator.nextOpt(fixed_loc);
1056 17 (binding_loc, binding_e) := ExpressionIterator.nextOpt(binding_loc);
1057 17 scalar_attributes := VAR_ATTR_BOOL(
1058 Util.applyOption(quantity_e, expToGeneratedBinding),
1059 Util.applyOption(start_e, expToGeneratedBinding),
1060 Util.applyOption(fixed_e, expToGeneratedBinding),
1061 Util.applyOption(binding_e, expToGeneratedBinding),
1062 isProtected, finalPrefix) :: scalar_attributes;
1063 end for;
1064
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 4 times.
17 scalar_attributes := if uniform then List.fill(listHead(scalar_attributes), length) else listReverseInPlace(scalar_attributes);
1065 end scalarizeBool;
1066
1067 function scalarizeClock
1068 input Option<Boolean> isProtected "Defined in protected scope";
1069 input Option<Boolean> finalPrefix "Defined as final";
1070 input Integer length "length of result";
1071 output list<VariableAttributes> scalar_attributes = List.fill(VAR_ATTR_CLOCK(isProtected, finalPrefix), length);
1072 output Boolean uniform = true;
1073 end scalarizeClock;
1074
1075 function scalarizeString
1076 input ExpressionIterator quantity_iter "quantity";
1077 input ExpressionIterator start_iter "start value";
1078 input ExpressionIterator fixed_iter "fixed - true: default for parameter/constant, false - default for other variables";
1079 input ExpressionIterator binding_iter "A binding expression for certain types. E.G. parameters";
1080 input Option<Boolean> isProtected "Defined in protected scope";
1081 input Option<Boolean> finalPrefix "Defined as final";
1082 input Integer length "length of result";
1083 output list<VariableAttributes> scalar_attributes = {};
1084 output Boolean uniform;
1085 protected
1086 Option<Expression> quantity_e, start_e, fixed_e, binding_e;
1087 ExpressionIterator quantity_loc = quantity_iter, start_loc = start_iter, fixed_loc = fixed_iter, binding_loc = binding_iter;
1088 algorithm
1089 ✗ uniform := length > 1 and List.all({quantity_iter, start_iter, fixed_iter, binding_iter}, ExpressionIterator.isUniform);
1090 ✗ for i in 1:(if uniform then 1 else length) loop
1091 ✗ (quantity_loc, quantity_e) := ExpressionIterator.nextOpt(quantity_loc);
1092 ✗ (start_loc, start_e) := ExpressionIterator.nextOpt(start_loc);
1093 ✗ (fixed_loc, fixed_e) := ExpressionIterator.nextOpt(fixed_loc);
1094 ✗ (binding_loc, binding_e) := ExpressionIterator.nextOpt(binding_loc);
1095 ✗ scalar_attributes := VAR_ATTR_STRING(
1096 Util.applyOption(quantity_e, expToGeneratedBinding),
1097 Util.applyOption(start_e, expToGeneratedBinding),
1098 Util.applyOption(fixed_e, expToGeneratedBinding),
1099 Util.applyOption(binding_e, expToGeneratedBinding),
1100 isProtected, finalPrefix) :: scalar_attributes;
1101 end for;
1102 ✗ scalar_attributes := if uniform then List.fill(listHead(scalar_attributes), length) else listReverseInPlace(scalar_attributes);
1103 end scalarizeString;
1104
1105 function scalarizeEnumeration
1106 input ExpressionIterator quantity_iter "quantity";
1107 input ExpressionIterator min_iter "Lower boundry";
1108 input ExpressionIterator max_iter "Upper boundry";
1109 input ExpressionIterator start_iter "start value";
1110 input ExpressionIterator fixed_iter "fixed - true: default for parameter/constant, false - default for other variables";
1111 input ExpressionIterator binding_iter "A binding expression for certain types. E.G. parameters";
1112 input Option<Boolean> isProtected "Defined in protected scope";
1113 input Option<Boolean> finalPrefix "Defined as final";
1114 input Integer length "length of result";
1115 output list<VariableAttributes> scalar_attributes = {};
1116 output Boolean uniform;
1117 protected
1118 Option<Expression> quantity_e, min_e, max_e, start_e, fixed_e, binding_e;
1119 ExpressionIterator quantity_loc = quantity_iter, min_loc = min_iter, max_loc = max_iter, start_loc = start_iter, fixed_loc = fixed_iter, binding_loc = binding_iter;
1120 algorithm
1121 ✗ uniform := length > 1 and List.all({quantity_iter, min_iter, max_iter, start_iter, fixed_iter, binding_iter}, ExpressionIterator.isUniform);
1122 ✗ for i in 1:(if uniform then 1 else length) loop
1123 ✗ (quantity_loc, quantity_e) := ExpressionIterator.nextOpt(quantity_loc);
1124 ✗ (min_loc, min_e) := ExpressionIterator.nextOpt(min_loc);
1125 ✗ (max_loc, max_e) := ExpressionIterator.nextOpt(max_loc);
1126 ✗ (start_loc, start_e) := ExpressionIterator.nextOpt(start_loc);
1127 ✗ (fixed_loc, fixed_e) := ExpressionIterator.nextOpt(fixed_loc);
1128 ✗ (binding_loc, binding_e) := ExpressionIterator.nextOpt(binding_loc);
1129 ✗ scalar_attributes := VAR_ATTR_ENUMERATION(
1130 Util.applyOption(quantity_e, expToGeneratedBinding),
1131 Util.applyOption(min_e, expToGeneratedBinding),
1132 Util.applyOption(max_e, expToGeneratedBinding),
1133 Util.applyOption(start_e, expToGeneratedBinding),
1134 Util.applyOption(fixed_e, expToGeneratedBinding),
1135 Util.applyOption(binding_e, expToGeneratedBinding),
1136 isProtected, finalPrefix) :: scalar_attributes;
1137 end for;
1138 ✗ scalar_attributes := if uniform then List.fill(listHead(scalar_attributes), length) else listReverseInPlace(scalar_attributes);
1139 end scalarizeEnumeration;
1140
1141 function scalarize
1142 input VariableAttributes attributes;
1143 input Integer length;
1144 output list<VariableAttributes> scalar_attributes = {};
1145 output Boolean uniform "every element got the same attribute record";
1146 algorithm
1147 (scalar_attributes, uniform) := match attributes
1148 1404 case VAR_ATTR_REAL() then scalarizeReal(
1149 quantity_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.quantity, Binding.getTypedExp)),
1150 unit_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.unit, Binding.getTypedExp)),
1151 displayUnit_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.displayUnit, Binding.getTypedExp)),
1152 min_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.min, Binding.getTypedExp)),
1153 max_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.max, Binding.getTypedExp)),
1154 start_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.start, Binding.getTypedExp)),
1155 fixed_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.fixed, Binding.getTypedExp)),
1156 nominal_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.nominal, Binding.getTypedExp)),
1157 stateSelect = attributes.stateSelect,
1158 tearingSelect = attributes.tearingSelect,
1159 uncertainty = attributes.uncertainty,
1160 distribution = attributes.distribution,
1161 binding_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.binding, Binding.getTypedExp)),
1162 isProtected = attributes.isProtected,
1163 finalPrefix = attributes.finalPrefix,
1164 length = length
1165 );
1166
1167 62 case VAR_ATTR_INT() then scalarizeInt(
1168 quantity_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.quantity, Binding.getTypedExp)),
1169 min_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.min, Binding.getTypedExp)),
1170 max_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.max, Binding.getTypedExp)),
1171 start_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.start, Binding.getTypedExp)),
1172 fixed_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.fixed, Binding.getTypedExp)),
1173 uncertainty = attributes.uncertainty,
1174 distribution = attributes.distribution,
1175 binding_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.binding, Binding.getTypedExp)),
1176 isProtected = attributes.isProtected,
1177 finalPrefix = attributes.finalPrefix,
1178 length = length
1179 );
1180
1181 17 case VAR_ATTR_BOOL() then scalarizeBool(
1182 quantity_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.quantity, Binding.getTypedExp)),
1183 start_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.start, Binding.getTypedExp)),
1184 fixed_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.fixed, Binding.getTypedExp)),
1185 binding_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.binding, Binding.getTypedExp)),
1186 isProtected = attributes.isProtected,
1187 finalPrefix = attributes.finalPrefix,
1188 length = length
1189 );
1190
1191 ✗ case VAR_ATTR_CLOCK() then scalarizeClock(
1192 isProtected = attributes.isProtected,
1193 finalPrefix = attributes.finalPrefix,
1194 length = length
1195 );
1196
1197 ✗ case VAR_ATTR_STRING() then scalarizeString(
1198 quantity_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.quantity, Binding.getTypedExp)),
1199 start_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.start, Binding.getTypedExp)),
1200 fixed_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.fixed, Binding.getTypedExp)),
1201 binding_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.binding, Binding.getTypedExp)),
1202 isProtected = attributes.isProtected,
1203 finalPrefix = attributes.finalPrefix,
1204 length = length
1205 );
1206
1207 ✗ case VAR_ATTR_ENUMERATION() then scalarizeEnumeration(
1208 quantity_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.quantity, Binding.getTypedExp)),
1209 min_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.min, Binding.getTypedExp)),
1210 max_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.max, Binding.getTypedExp)),
1211 start_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.start, Binding.getTypedExp)),
1212 fixed_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.fixed, Binding.getTypedExp)),
1213 binding_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.binding, Binding.getTypedExp)),
1214 isProtected = attributes.isProtected,
1215 finalPrefix = attributes.finalPrefix,
1216 length = length
1217 );
1218
1219 // kabdelhak: ToDo: need to discuss this case
1220 ✗ case VAR_ATTR_RECORD() then ({attributes}, false);
1221
1222 else algorithm
1223 ✗ Error.terminate(getInstanceName() + "failed. Not yet handled: " + toString(attributes), sourceInfo());
1224 ✗ then fail();
1225 end match;
1226 end scalarize;
1227
1228 function elemType
1229 input VariableAttributes attr;
1230 output Type ty;
1231 algorithm
1232 ty := match attr
1233 case VAR_ATTR_REAL() then Type.REAL();
1234 case VAR_ATTR_INT() then Type.INTEGER();
1235 case VAR_ATTR_BOOL() then Type.BOOLEAN();
1236 case VAR_ATTR_CLOCK() then Type.CLOCK();
1237 case VAR_ATTR_STRING() then Type.STRING();
1238 // should probably add enumeration but currently the needed info is not stored here
1239 else algorithm
1240 ✗ Error.terminate(getInstanceName() + " cannot create type from attributes: " + toString(attr), sourceInfo());
1241 ✗ then fail();
1242 end match;
1243 end elemType;
1244
1245 //protected
1246 function attributesToString
1247 input list<tuple<String, Option<Expression>>> tpl_list;
1248 input Option<StateSelect> stateSelect;
1249 input Option<TearingSelect> tearingSelect;
1250 output String str = "";
1251 protected
1252 list<String> buffer = {};
1253 String name;
1254 algorithm
1255
2/2
✓ Branch 0 taken 5244 times.
✓ Branch 1 taken 1068 times.
6312 for tpl in tpl_list loop
1256 5244 buffer := attributeToString(tpl, buffer);
1257 end for;
1258
1259 1068 buffer := stateSelectStringBuffer(stateSelect, buffer);
1260 1068 buffer := tearingSelectStringBuffer(tearingSelect, buffer);
1261
1262 1068 buffer := listReverse(buffer);
1263
1264
2/2
✓ Branch 0 taken 1053 times.
✓ Branch 1 taken 15 times.
1068 if not listEmpty(buffer) then
1265 15 name :: buffer := buffer;
1266 15 str := str + name;
1267
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 15 times.
18 for name in buffer loop
1268 3 str := str + ", " + name;
1269 end for;
1270 end if;
1271 end attributesToString;
1272
1273 function attributeToString
1274 "Creates an optional string for an optional attribute."
1275 input tuple<String, Option<Expression>> tpl;
1276 input output list<String> buffer;
1277 protected
1278 String name;
1279 Option<Expression> optAttr;
1280 Expression attr;
1281 algorithm
1282 5244 (name, optAttr) := tpl;
1283
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5244 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 5239 times.
5244 if isSome(optAttr) then
1284 5 SOME(attr) := optAttr;
1285 5 buffer := name + " = " + Expression.toString(attr) :: buffer;
1286 end if;
1287 end attributeToString;
1288
1289 function stateSelectString
1290 input StateSelect stateSelect;
1291 output String str;
1292 algorithm
1293 str := match stateSelect
1294 case StateSelect.NEVER then "StateSelect = never";
1295 case StateSelect.AVOID then "StateSelect = avoid";
1296 case StateSelect.DEFAULT then "StateSelect = default";
1297 case StateSelect.PREFER then "StateSelect = prefer";
1298 case StateSelect.ALWAYS then "StateSelect = always";
1299 end match;
1300 end stateSelectString;
1301
1302 function tearingSelectString
1303 input TearingSelect tearingSelect;
1304 output String str;
1305 algorithm
1306 str := match tearingSelect
1307 case TearingSelect.NEVER then "TearingSelect = never";
1308 case TearingSelect.AVOID then "TearingSelect = avoid";
1309 case TearingSelect.DEFAULT then "TearingSelect = default";
1310 case TearingSelect.PREFER then "TearingSelect = prefer";
1311 case TearingSelect.ALWAYS then "TearingSelect = always";
1312 end match;
1313 end tearingSelectString;
1314
1315 function stateSelectStringBuffer
1316 input Option<StateSelect> optStateSelect;
1317 input output list<String> buffer;
1318 protected
1319 StateSelect stateSelect;
1320 algorithm
1321
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1068 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 1055 times.
1068 if isSome(optStateSelect) then
1322 13 SOME(stateSelect) := optStateSelect;
1323 13 buffer := stateSelectString(stateSelect) :: buffer;
1324 end if;
1325 end stateSelectStringBuffer;
1326
1327 function tearingSelectStringBuffer
1328 input Option<TearingSelect> optTearingSelect;
1329 input output list<String> buffer;
1330 protected
1331 TearingSelect tearingSelect;
1332 algorithm
1333
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1068 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1068 times.
1068 if isSome(optTearingSelect) then
1334 ✗ SOME(tearingSelect) := optTearingSelect;
1335 ✗ buffer := tearingSelectString(tearingSelect) :: buffer;
1336 end if;
1337 end tearingSelectStringBuffer;
1338
1339 protected
1340 function createReal
1341 input list<tuple<String, Binding>> attrs;
1342 input Boolean isFinal;
1343 input SCode.Comment comment;
1344 output VariableAttributes attributes;
1345 protected
1346 String name;
1347 Binding b;
1348 Option<Binding> quantity = NONE(), unit = NONE(), displayUnit = NONE();
1349 Option<Binding> min = NONE(), max = NONE(), start = NONE(), fixed = NONE(), nominal = NONE();
1350 Option<StateSelect> state_select = NONE();
1351 Option<TearingSelect> tearing_select = NONE();
1352 algorithm
1353
2/2
✓ Branch 0 taken 21842 times.
✓ Branch 1 taken 7640 times.
29482 for attr in attrs loop
1354 21842 (name, b) := attr;
1355 () := match name
1356 1893 case "displayUnit" algorithm displayUnit := createAttribute(b); then ();
1357 124 case "fixed" algorithm fixed := createAttribute(b); then ();
1358 1370 case "max" algorithm max := createAttribute(b); then ();
1359 2440 case "min" algorithm min := createAttribute(b); then ();
1360 2146 case "nominal" algorithm nominal := createAttribute(b); then ();
1361 5630 case "quantity" algorithm quantity := createAttribute(b); then ();
1362 2392 case "start" algorithm start := createAttribute(b); then ();
1363 72 case "stateSelect" algorithm state_select := createStateSelect(b); then ();
1364 // TODO: VAR_ATTR_REAL has no field for unbounded (which should be named unbound).
1365 case "unbounded" then ();
1366 5775 case "unit" algorithm unit := createAttribute(b); then ();
1367
1368 // The attributes should already be type checked, so we shouldn't get any
1369 // unknown attributes here.
1370 else
1371 algorithm
1372 ✗ Error.terminate(getInstanceName() + " got unknown type attribute " + name, sourceInfo());
1373 ✗ then
1374 fail();
1375 end match;
1376 end for;
1377 7640 tearing_select := createTearingSelect(comment);
1378
1379
2/2
✓ Branch 0 taken 7274 times.
✓ Branch 1 taken 366 times.
15280 attributes := VariableAttributes.VAR_ATTR_REAL(
1380 quantity, unit, displayUnit, min, max, start, fixed, nominal,
1381 state_select, tearing_select, NONE(), NONE(), NONE(), NONE(), SOME(isFinal));
1382 end createReal;
1383
1384 function createInt
1385 input list<tuple<String, Binding>> attrs;
1386 input Boolean isFinal;
1387 output VariableAttributes attributes;
1388 protected
1389 String name;
1390 Binding b;
1391 Option<Binding> quantity = NONE(), min = NONE(), max = NONE();
1392 Option<Binding> start = NONE(), fixed = NONE();
1393 algorithm
1394
4/4
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 5749 times.
✓ Branch 2 taken 87 times.
✓ Branch 3 taken 5662 times.
5830 if listEmpty(attrs) and not isFinal then
1395 attributes := EMPTY_VAR_ATTR_INT;
1396 else
1397
2/2
✓ Branch 0 taken 143 times.
✓ Branch 1 taken 168 times.
311 for attr in attrs loop
1398 143 (name, b) := attr;
1399
1400 () := match name
1401 ✗ case "quantity" algorithm quantity := createAttribute(b); then ();
1402 66 case "min" algorithm min := createAttribute(b); then ();
1403 55 case "max" algorithm max := createAttribute(b); then ();
1404 14 case "start" algorithm start := createAttribute(b); then ();
1405 8 case "fixed" algorithm fixed := createAttribute(b); then ();
1406
1407 // The attributes should already be type checked, so we shouldn't get any
1408 // unknown attributes here.
1409 else
1410 algorithm
1411 ✗ Error.terminate(getInstanceName() + " got unknown type attribute " + name, sourceInfo());
1412 ✗ then
1413 fail();
1414 end match;
1415 end for;
1416
1417
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 111 times.
336 attributes := VariableAttributes.VAR_ATTR_INT(
1418 quantity, min, max, start, fixed,
1419 NONE(), NONE(), NONE(), NONE(), SOME(isFinal));
1420 end if;
1421 end createInt;
1422
1423 function createBool
1424 input list<tuple<String, Binding>> attrs;
1425 input Boolean isFinal;
1426 output VariableAttributes attributes;
1427 protected
1428 String name;
1429 Binding b;
1430 Option<Binding> quantity = NONE(), start = NONE(), fixed = NONE();
1431 algorithm
1432
4/4
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 628 times.
✓ Branch 2 taken 469 times.
✓ Branch 3 taken 159 times.
645 if listEmpty(attrs) and not isFinal then
1433 attributes := EMPTY_VAR_ATTR_BOOL;
1434 else
1435
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 486 times.
509 for attr in attrs loop
1436 23 (name, b) := attr;
1437
1438 () := match name
1439 ✗ case "quantity" algorithm quantity := createAttribute(b); then ();
1440 17 case "start" algorithm start := createAttribute(b); then ();
1441 6 case "fixed" algorithm fixed := createAttribute(b); then ();
1442
1443 // The attributes should already be type checked, so we shouldn't get any
1444 // unknown attributes here.
1445 else
1446 algorithm
1447 ✗ Error.terminate(getInstanceName() + " got unknown type attribute " + name, sourceInfo());
1448 ✗ then
1449 fail();
1450 end match;
1451 end for;
1452
1453
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 469 times.
972 attributes := VariableAttributes.VAR_ATTR_BOOL(
1454 quantity, start, fixed, NONE(), NONE(), SOME(isFinal));
1455 end if;
1456 end createBool;
1457
1458 function createString
1459 input list<tuple<String, Binding>> attrs;
1460 input Boolean isFinal;
1461 output VariableAttributes attributes;
1462 protected
1463 String name;
1464 Binding b;
1465 Option<Binding> quantity = NONE(), start = NONE(), fixed = NONE();
1466 algorithm
1467
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 25 times.
30 if listEmpty(attrs) and not isFinal then
1468 attributes := EMPTY_VAR_ATTR_STRING;
1469 else
1470
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 for attr in attrs loop
1471 ✗ (name, b) := attr;
1472
1473 () := match name
1474 ✗ case "quantity" algorithm quantity := createAttribute(b); then ();
1475 ✗ case "start" algorithm start := createAttribute(b); then ();
1476 ✗ case "fixed" algorithm fixed := createAttribute(b); then ();
1477
1478 // The attributes should already be type checked, so we shouldn't get any
1479 // unknown attributes here.
1480 else
1481 algorithm
1482 ✗ Error.terminate(getInstanceName() + " got unknown type attribute " + name, sourceInfo());
1483 ✗ then
1484 fail();
1485 end match;
1486 end for;
1487
1488
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
10 attributes := VariableAttributes.VAR_ATTR_STRING(
1489 quantity, start, fixed, NONE(), NONE(), SOME(isFinal));
1490 end if;
1491 end createString;
1492
1493 function createEnum
1494 input list<tuple<String, Binding>> attrs;
1495 input Boolean isFinal;
1496 output VariableAttributes attributes;
1497 protected
1498 String name;
1499 Binding b;
1500 Option<Binding> quantity = NONE(), min = NONE(), max = NONE();
1501 Option<Binding> start = NONE(), fixed = NONE();
1502 algorithm
1503
4/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 69 times.
✓ Branch 2 taken 67 times.
✓ Branch 3 taken 2 times.
70 if listEmpty(attrs) and not isFinal then
1504 attributes := EMPTY_VAR_ATTR_REAL;
1505 else
1506
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 68 times.
70 for attr in attrs loop
1507 2 (name, b) := attr;
1508
1509 () := match name
1510 1 case "fixed" algorithm fixed := createAttribute(b); then ();
1511 ✗ case "max" algorithm max := createAttribute(b); then ();
1512 ✗ case "min" algorithm min := createAttribute(b); then ();
1513 ✗ case "quantity" algorithm quantity := createAttribute(b); then ();
1514 1 case "start" algorithm start := createAttribute(b); then ();
1515
1516 // The attributes should already be type checked, so we shouldn't get any
1517 // unknown attributes here.
1518 else
1519 algorithm
1520 ✗ Error.terminate(getInstanceName() + " got unknown type attribute " + name, sourceInfo());
1521 ✗ then
1522 fail();
1523 end match;
1524 end for;
1525
1526
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 67 times.
136 attributes := VariableAttributes.VAR_ATTR_ENUMERATION(
1527 quantity, min, max, start, fixed, NONE(), NONE(), SOME(isFinal));
1528 end if;
1529 end createEnum;
1530
1531 function createClock
1532 input Boolean isFinal;
1533 output VariableAttributes attributes = VAR_ATTR_CLOCK(NONE(), SOME(isFinal));
1534 end createClock;
1535
1536 function createRecord
1537 input list<tuple<String, Binding>> attrs;
1538 input UnorderedMap<String, Integer> indexMap;
1539 input list<Variable> children;
1540 input Boolean isFinal;
1541 output VariableAttributes attributes;
1542 protected
1543 array<VariableAttributes> childrenAttr = arrayCreate(listLength(children), EMPTY_VAR_ATTR_REAL);
1544 Integer index;
1545 algorithm
1546
2/2
✓ Branch 1 taken 341 times.
✓ Branch 2 taken 156 times.
497 for var in children loop
1547 () := match UnorderedMap.get(ComponentRef.firstName(var.name), indexMap)
1548 case SOME(index) algorithm
1549 341 childrenAttr[index] := create(var.typeAttributes, var.ty, var.attributes, var.children, var.comment);
1550 then ();
1551 else ();
1552 end match;
1553 end for;
1554 156 attributes := VAR_ATTR_RECORD(indexMap, childrenAttr);
1555 end createRecord;
1556
1557 function createAttribute
1558 input Binding binding;
1559 output Option<Binding> attribute = SOME(binding);
1560 end createAttribute;
1561
1562 function createStateSelect
1563 input Binding binding;
1564 output Option<StateSelect> stateSelect;
1565 protected
1566 Expression exp = Binding.getTypedExp(binding);
1567 String name;
1568 algorithm
1569 72 name := getStateSelectName(exp);
1570 72 stateSelect := SOME(lookupStateSelectMember(name));
1571 end createStateSelect;
1572
1573 function getStateSelectName
1574 input Expression exp;
1575 output String name;
1576 protected
1577 Expression arg;
1578 InstNode node;
1579 Call call;
1580 list<Expression> rest;
1581 algorithm
1582 name := match exp
1583 72 case Expression.ENUM_LITERAL() then exp.name;
1584 ✗ case Expression.CREF(cref = ComponentRef.CREF()) then ComponentRef.nodeName(exp.cref);
1585 43 case Expression.CALL(call = call as Call.TYPED_ARRAY_CONSTRUCTOR()) then getStateSelectName(call.exp);
1586 case Expression.CALL(call = call as Call.TYPED_CALL(arguments = arg::_))
1587 guard(AbsynUtil.pathString(Function.nameConsiderBuiltin(call.fn)) == "fill")
1588 ✗ then getStateSelectName(arg);
1589 case Expression.ARRAY() algorithm
1590 ✗ arg :: rest := arrayList(exp.elements);
1591 ✗ if not (listEmpty(rest) or List.all(rest, function Expression.isEqual(exp2=arg))) then
1592 ✗ Error.terminate(getInstanceName() +
1593 " cannot handle array StateSelect with different values yet:" + Expression.toString(exp), sourceInfo());
1594 ✗ fail();
1595 end if;
1596 ✗ then getStateSelectName(arg);
1597 else algorithm
1598 ✗ Error.terminate(getInstanceName() +
1599 " got invalid StateSelect expression " + Expression.toString(exp), sourceInfo());
1600 ✗ then fail();
1601 end match;
1602 end getStateSelectName;
1603
1604 function lookupStateSelectMember
1605 input String name;
1606 output StateSelect stateSelect;
1607 algorithm
1608 stateSelect := match name
1609 case "never" then StateSelect.NEVER;
1610 case "avoid" then StateSelect.AVOID;
1611 case "default" then StateSelect.DEFAULT;
1612 case "prefer" then StateSelect.PREFER;
1613 case "always" then StateSelect.ALWAYS;
1614 else
1615 algorithm
1616 ✗ Error.terminate(getInstanceName() + " got unknown StateSelect literal " + name, sourceInfo());
1617 ✗ then
1618 fail();
1619 end match;
1620 end lookupStateSelectMember;
1621
1622 function createTearingSelect
1623 "__OpenModelica_tearingSelect is an annotation and has to be extracted from the comment."
1624 input SCode.Comment cmt;
1625 output Option<TearingSelect> tearingSelect = NONE();
1626 protected
1627 Option<SCode.Annotation> opt_anno;
1628 SCode.Annotation anno;
1629 SCode.Mod mod;
1630 Option<Absyn.Exp> opt_val;
1631 Absyn.Exp val;
1632 String name;
1633 SourceInfo info;
1634 algorithm
1635 7640 opt_anno := SCodeUtil.commentAnnotation(cmt);
1636
1637
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 7640 times.
✓ Branch 2 taken 5244 times.
✓ Branch 3 taken 2396 times.
7640 if isNone(opt_anno) then
1638 // No annotation.
1639 5244 return;
1640 end if;
1641
1642 2396 SOME(anno) := opt_anno;
1643 2396 mod := SCodeUtil.lookupAnnotation(anno, "__OpenModelica_tearingSelect");
1644
1645
1/2
✓ Branch 1 taken 2396 times.
✗ Branch 2 not taken.
2396 if SCodeUtil.isEmptyMod(mod) then
1646 2396 mod := SCodeUtil.lookupAnnotation(anno, "tearingSelect");
1647
1648
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2396 times.
2396 if not SCodeUtil.isEmptyMod(mod) then
1649 ✗ Error.addSourceMessage(Error.DEPRECATED_EXPRESSION,
1650 {"tearingSelect", "__OpenModelica_tearingSelect"}, SCodeUtil.getModifierInfo(mod));
1651 end if;
1652 end if;
1653
1654 2396 opt_val := SCodeUtil.getModifierBinding(mod);
1655
1656
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2396 times.
✓ Branch 2 taken 2396 times.
✗ Branch 3 not taken.
2396 if isNone(opt_val) then
1657 // Annotation exists but has no value.
1658 2396 return;
1659 end if;
1660
1661 ✗ SOME(val) := opt_val;
1662 ✗ info := SCodeUtil.getModifierInfo(mod);
1663 ✗ name := getTearingSelectName(val, info);
1664 ✗ tearingSelect := lookupTearingSelectMember(name);
1665
1666 ✗ if isNone(tearingSelect) then
1667 ✗ Error.addSourceMessage(Error.UNKNOWN_ANNOTATION_VALUE, {Dump.printExpStr(val), "__OpenModelica_tearingSelect"}, info);
1668 end if;
1669 end createTearingSelect;
1670
1671 function getTearingSelectName
1672 input Absyn.Exp exp;
1673 input SourceInfo info;
1674 output String name;
1675 algorithm
1676 name := match exp
1677 // TearingSelect.name
1678 case Absyn.Exp.CREF(componentRef =
1679 Absyn.ComponentRef.CREF_QUAL(name = "TearingSelect", subscripts = {}, componentRef =
1680 Absyn.ComponentRef.CREF_IDENT(name = name, subscripts = {})))
1681 then name;
1682
1683 // Single name without the TearingSelect prefix is deprecated and no longer accepted.
1684 case Absyn.Exp.CREF(componentRef = Absyn.ComponentRef.CREF_IDENT(name = name, subscripts = {}))
1685 algorithm
1686 ✗ Error.addSourceMessage(Error.DEPRECATED_EXPRESSION, {name, "TearingSelect." + name}, info);
1687 then
1688 "";
1689
1690 else "";
1691 end match;
1692 end getTearingSelectName;
1693
1694 function lookupTearingSelectMember
1695 input String name;
1696 output Option<TearingSelect> tearingSelect;
1697 algorithm
1698 tearingSelect := match name
1699 case "never" then SOME(TearingSelect.NEVER);
1700 case "avoid" then SOME(TearingSelect.AVOID);
1701 case "default" then SOME(TearingSelect.DEFAULT);
1702 case "prefer" then SOME(TearingSelect.PREFER);
1703 case "always" then SOME(TearingSelect.ALWAYS);
1704 else NONE();
1705 end match;
1706 end lookupTearingSelectMember;
1707
1708 function expToGeneratedBinding
1709 input Expression exp;
1710 output Binding binding = Binding.makeFlat(exp, Variability.CONSTANT, Source.GENERATED);
1711 end expToGeneratedBinding;
1712 end VariableAttributes;
1713
1714 constant VariableAttributes EMPTY_VAR_ATTR_REAL = VAR_ATTR_REAL(NONE(),NONE(),NONE(), NONE(), NONE(),NONE(),NONE(),NONE(),NONE(),NONE(),NONE(),NONE(),NONE(),NONE(),NONE());
1715 constant VariableAttributes EMPTY_VAR_ATTR_INT = VAR_ATTR_INT(NONE(),NONE(),NONE(),NONE(),NONE(),NONE(),NONE(),NONE(),NONE(),NONE());
1716 constant VariableAttributes EMPTY_VAR_ATTR_BOOL = VAR_ATTR_BOOL(NONE(),NONE(),NONE(),NONE(),NONE(),NONE());
1717 constant VariableAttributes EMPTY_VAR_ATTR_CLOCK = VAR_ATTR_CLOCK(NONE(),NONE());
1718 constant VariableAttributes EMPTY_VAR_ATTR_STRING = VAR_ATTR_STRING(NONE(),NONE(),NONE(),NONE(),NONE(),NONE());
1719 constant VariableAttributes EMPTY_VAR_ATTR_ENUMERATION = VAR_ATTR_ENUMERATION(NONE(),NONE(),NONE(),NONE(),NONE(),NONE(),NONE(),NONE());
1720
1721 type StateSelect = enumeration(NEVER, AVOID, DEFAULT, PREFER, ALWAYS);
1722 type TearingSelect = enumeration(NEVER, AVOID, DEFAULT, PREFER, ALWAYS);
1723 type Uncertainty = enumeration(GIVEN, SOUGHT, REFINE, PROPAGATE);
1724
1725 uniontype Distribution
1726 record DISTRIBUTION
1727 Expression name;
1728 Expression params;
1729 Expression paramNames;
1730 end DISTRIBUTION;
1731 end Distribution;
1732
1733 uniontype Annotations
1734 record ANNOTATIONS
1735 "all annotations that are vendor specific
1736 note: doesn't include __OpenModelica_tearingSelect, this is considered a first class attribute"
1737 Boolean hideResult;
1738 Boolean resizable;
1739 Boolean optimizable;
1740 Option<OptimizerExpression> optimizerExpression;
1741 end ANNOTATIONS;
1742
1743 function create
1744 input SCode.Comment comment;
1745 input Attributes attributes;
1746 output Annotations annotations = EMPTY_ANNOTATIONS;
1747 protected
1748 SCode.Mod mod;
1749 Boolean b;
1750 algorithm
1751 // set if it was set globally
1752
2/2
✓ Branch 0 taken 19 times.
✓ Branch 1 taken 12368 times.
12387 if attributes.isResizable then
1753 19 annotations.resizable := true;
1754 end if;
1755
1756 () := match comment
1757 case SCode.COMMENT(annotation_=SOME(SCode.ANNOTATION(modification=mod as SCode.MOD()))) algorithm
1758
2/2
✓ Branch 0 taken 3538 times.
✓ Branch 1 taken 2796 times.
6334 for submod in mod.subModLst loop
1759 () := match submod
1760 case SCode.NAMEMOD(ident = "HideResult", mod = SCode.MOD(binding = SOME(Absyn.BOOL(true)))) algorithm
1761 262 annotations.hideResult := true;
1762 then ();
1763 case SCode.NAMEMOD(ident = "__OpenModelica_resizable", mod = SCode.MOD(binding = SOME(Absyn.BOOL(b)))) algorithm
1764
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 annotations.resizable := b;
1765 then ();
1766 case SCode.NAMEMOD(ident = "optimizable", mod = SCode.MOD(binding = SOME(Absyn.BOOL(b)))) algorithm
1767 ✗ annotations.optimizable := b;
1768 then ();
1769
1770 // TODO: check for conflicting annotations?
1771 case SCode.NAMEMOD(ident = "isMayer", mod = SCode.MOD(binding = SOME(Absyn.BOOL(b)))) algorithm
1772 ✗ annotations.optimizerExpression := SOME(OptimizerExpression.MAYER);
1773 then ();
1774 case SCode.NAMEMOD(ident = "isLagrange", mod = SCode.MOD(binding = SOME(Absyn.BOOL(b)))) algorithm
1775 1 annotations.optimizerExpression := SOME(OptimizerExpression.LAGRANGE);
1776 then ();
1777 case SCode.NAMEMOD(ident = "isConstraint", mod = SCode.MOD(binding = SOME(Absyn.BOOL(b)))) algorithm
1778 ✗ annotations.optimizerExpression := SOME(OptimizerExpression.PATH_CONSTRAINT);
1779 then ();
1780 case SCode.NAMEMOD(ident = "isInitialConstraint", mod = SCode.MOD(binding = SOME(Absyn.BOOL(b)))) algorithm
1781 ✗ annotations.optimizerExpression := SOME(OptimizerExpression.INITIAL_CONSTRAINT);
1782 then ();
1783 case SCode.NAMEMOD(ident = "isFinalConstraint", mod = SCode.MOD(binding = SOME(Absyn.BOOL(b)))) algorithm
1784 ✗ annotations.optimizerExpression := SOME(OptimizerExpression.FINAL_CONSTRAINT);
1785 then ();
1786 case SCode.NAMEMOD(ident = "isInitialTime", mod = SCode.MOD(binding = SOME(Absyn.BOOL(b)))) algorithm
1787 ✗ annotations.optimizerExpression := SOME(OptimizerExpression.INITIAL_TIME);
1788 then ();
1789 case SCode.NAMEMOD(ident = "isFinalTime", mod = SCode.MOD(binding = SOME(Absyn.BOOL(b)))) algorithm
1790 ✗ annotations.optimizerExpression := SOME(OptimizerExpression.FINAL_TIME);
1791 then ();
1792 else ();
1793 end match;
1794 end for;
1795 then ();
1796 else ();
1797 end match;
1798 end create;
1799 end Annotations;
1800
1801 // TODO: how to use Initial or Final state? - better state-pair Real x_0 = x (initialState = true); -> binding only for initial time / optimizer?
1802 type OptimizerExpression = enumeration(MAYER, LAGRANGE, PATH_CONSTRAINT, INITIAL_CONSTRAINT, FINAL_CONSTRAINT, INITIAL_TIME, FINAL_TIME);
1803
1804 constant Annotations EMPTY_ANNOTATIONS = ANNOTATIONS(false, false, false, NONE());
1805
1806 annotation(__OpenModelica_Interface="nf_frontend");
1807 end NFBackendExtension;
1808