Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 65.4% 578 / 0 / 884
Functions: -% 0 / 1 / 1
Branches: 56.4% 288 / 0 / 511

OMCompiler/Compiler/NFFrontEnd/NFCeval.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 NFCeval
37
38 import Binding = NFBinding;
39 import ComponentRef = NFComponentRef;
40 import Error;
41 import Component = NFComponent;
42 import Expression = NFExpression;
43 import NFInstNode.InstNode;
44 import NFInstNode;
45 import Operator = NFOperator;
46 import NFOperator.Op;
47 import Typing = NFTyping;
48 import Call = NFCall;
49 import Dimension = NFDimension;
50 import Type = NFType;
51 import ExpressionBasics;
52 import NFPrefixes.{Variability, Purity};
53 import NFClassTree.ClassTree;
54 import ComplexType = NFComplexType;
55 import Subscript = NFSubscript;
56 import NFTyping.TypingError;
57 import Record = NFRecord;
58 import InstContext = NFInstContext;
59 import Global;
60
61 protected
62 import NFFunction.Function;
63 import EvalFunction = NFEvalFunction;
64 import List;
65 import System;
66 import ExpressionIterator = NFExpressionIterator;
67 import MetaModelica.Dangerous.*;
68 import Class = NFClass;
69 import TypeCheck = NFTypeCheck;
70 import ExpandExp = NFExpandExp;
71 import Prefixes = NFPrefixes;
72 import SimplifyExp = NFSimplifyExp;
73 import UnorderedMap;
74 import Absyn;
75 import ErrorExt;
76 import Array;
77 import Vector;
78
79 public
80 uniontype EvalTarget
81 record EVAL_TARGET
82 SourceInfo info;
83 InstContext.Type context;
84 Option<EvalTargetData> extra;
85 end EVAL_TARGET;
86
87 function new
88 input SourceInfo info;
89 input InstContext.Type context = NFInstContext.NO_CONTEXT;
90 input Option<EvalTargetData> extra = NONE();
91 output EvalTarget target = EVAL_TARGET(info, context, extra);
92 end new;
93
94 function hasInfo
95 input EvalTarget target;
96 output Boolean res = not stringEmpty(target.info.fileName);
97 end hasInfo;
98
99 function getInfo
100 input EvalTarget target;
101 output SourceInfo info = target.info;
102 end getInfo;
103 end EvalTarget;
104
105 constant EvalTarget noTarget = EvalTarget.EVAL_TARGET(Absyn.dummyInfo, NFInstContext.NO_CONTEXT, NONE());
106
107 uniontype EvalTargetData
108 record DIMENSION_DATA
109 InstNode component;
110 Integer index;
111 Expression exp;
112 end DIMENSION_DATA;
113 end EvalTargetData;
114
115 function tryEvalExpResizable
116 input output Expression exp;
117 input EvalTarget target = noTarget;
118 algorithm
119 34650 ErrorExt.setCheckpoint(getInstanceName());
120 try
121 34650 exp := evalExp(exp, target);
122 34647 ErrorExt.delCheckpoint(getInstanceName());
123 else
124 3 exp := tryEvalExpPartial(exp, target);
125
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if Expression.contains(exp, Expression.isResizableCref) then
126 /* evaluation is allowed to fail for resizables */
127 ✗ ErrorExt.rollBack(getInstanceName());
128 else
129 3 ErrorExt.delCheckpoint(getInstanceName());
130 3 fail();
131 end if;
132 end try;
133 end tryEvalExpResizable;
134
135 function tryEvalExp
136 input output Expression exp;
137 input EvalTarget target = noTarget;
138 algorithm
139 79377 ErrorExt.setCheckpoint(getInstanceName());
140
141 try
142 79377 exp := evalExp(exp, target);
143 else
144 end try;
145
146 79377 ErrorExt.rollBack(getInstanceName());
147 end tryEvalExp;
148
149 function evalExp
150 input output Expression exp;
151 input EvalTarget target = noTarget;
152 algorithm
153 exp := match exp
154 local
155 Expression exp1, exp2;
156 Call call;
157 ComponentRef cref;
158
159 case Expression.CREF()
160 93378 then evalCref(exp.cref, exp, target);
161
162 case Expression.TYPENAME()
163 56 then evalTypename(exp.ty, exp, target);
164
165 case Expression.ARRAY()
166
2/2
✓ Branch 0 taken 99448 times.
✓ Branch 1 taken 59121 times.
158569 then if exp.literal then exp
167 else
168 Expression.makeArrayCheckLiteral(exp.ty,
169 Array.map(exp.elements, function evalExp(target = target)));
170
171 10913 case Expression.RANGE() then evalRange(exp, target);
172
173 case Expression.TUPLE()
174 algorithm
175 ✗ exp.elements := list(evalExp(e, target) for e in exp.elements);
176 then
177 exp;
178
179 case Expression.RECORD()
180 algorithm
181
4/4
✓ Branch 0 taken 123424 times.
✓ Branch 1 taken 8837 times.
✓ Branch 2 taken 123424 times.
✓ Branch 3 taken 8837 times.
141098 exp.elements := list(evalExp(e, target) for e in exp.elements);
182 then
183 exp;
184
185 case Expression.CALL()
186 39858 then evalCall(exp.call, target);
187
188 case Expression.SIZE()
189 4162 then evalSize(exp.exp, exp.dimIndex, target);
190
191 case Expression.BINARY()
192 algorithm
193 271501 exp1 := evalExp(exp.exp1, target);
194 271364 exp2 := evalExp(exp.exp2, target);
195 271362 then
196 evalBinaryOp(exp1, exp.operator, exp2, target);
197
198 case Expression.MULTARY()
199 4 then evalExp(SimplifyExp.splitMultary(exp), target);
200
201 case Expression.UNARY()
202 algorithm
203 11209 exp1 := evalExp(exp.exp, target);
204 11209 then
205 evalUnaryOp(exp1, exp.operator);
206
207 case Expression.LBINARY()
208 algorithm
209 5913 exp1 := evalExp(exp.exp1, target);
210
211
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 5912 times.
5913 if Expression.isSplitSubscriptedExp(exp1) then
212 1 exp2 := evalExp(exp.exp2, target);
213 else
214 5912 exp2 := exp.exp2;
215 end if;
216 5913 then
217 evalLogicBinaryOp(exp1, exp.operator, exp2, target);
218
219 case Expression.LUNARY()
220 algorithm
221 2886 exp1 := evalExp(exp.exp, target);
222 2884 then
223 evalLogicUnaryOp(exp1, exp.operator);
224
225 case Expression.RELATION()
226 algorithm
227 26684 exp1 := evalExp(exp.exp1, target);
228 26682 exp2 := evalExp(exp.exp2, target);
229 26682 then
230 evalRelationOp(exp1, exp.operator, exp2);
231
232 10757 case Expression.IF() then evalIfExp(exp, target);
233
234 case Expression.CAST()
235 algorithm
236 19887 exp1 := evalExp(exp.exp, target);
237 19887 then
238 evalCast(exp1, exp.ty);
239
240 ✗ case Expression.BOX() then evalExp(exp.exp, target);
241 ✗ case Expression.UNBOX() then evalExp(exp.exp, target);
242
243 case Expression.SUBSCRIPTED_EXP()
244 96167 then evalSubscriptedExp(exp.exp, exp.subscripts, target);
245
246 case Expression.TUPLE_ELEMENT()
247 algorithm
248 7 exp1 := evalExp(exp.tupleExp, target);
249 7 then
250 Expression.tupleElement(exp1, exp.index);
251
252 case Expression.RECORD_ELEMENT()
253 31 then evalRecordElement(exp, target);
254
255 case Expression.MUTABLE()
256 algorithm
257 329822 exp1 := evalExp(Mutable.access(exp.exp), target);
258 then
259 exp1;
260
261 case Expression.INSTANCE_NAME()
262 6 then evalGetInstanceName(exp.scope);
263
264 else exp;
265 end match;
266 end evalExp;
267
268 function tryEvalExpPartial
269 input output Expression exp;
270 input EvalTarget target = noTarget;
271 algorithm
272 3 ErrorExt.setCheckpoint(getInstanceName());
273
274 try
275 3 exp := evalExpPartial(exp, target);
276 else
277 end try;
278
279 3 ErrorExt.rollBack(getInstanceName());
280 end tryEvalExpPartial;
281
282 function evalExpPartialDefault
283 "Simplied version of evalExpPartial to work around MetaModelica issues with
284 default arguments and multiple return values when used as a function pointer."
285 input output Expression exp;
286 algorithm
287 587 exp := evalExpPartial(exp);
288 end evalExpPartialDefault;
289
290 function evalExpPartial
291 "Evaluates the parts of an expression that are possible to evaluate. This
292 means leaving parts of the expression that contains e.g. iterators or mutable
293 expressions. This can be used to optimize an expression that is expected to
294 be evaluated many times, for example the expression in an array constructor."
295 input Expression exp;
296 input EvalTarget target = noTarget;
297 input Boolean evaluated = true;
298 output Expression outExp;
299 output Boolean outEvaluated "True if the whole expression is evaluated, otherwise false.";
300 protected
301 Expression e;
302 algorithm
303
3/3
✓ Branch 3 taken 1501 times.
✓ Branch 4 taken 134 times.
✓ Branch 5 taken 7903 times.
9539 (e, outEvaluated) :=
304 Expression.mapFoldShallow(exp, function evalExpPartial(target = target), true);
305
306 outExp := match e
307 case Expression.CREF()
308 algorithm
309
2/2
✓ Branch 1 taken 643 times.
✓ Branch 2 taken 858 times.
1501 if ComponentRef.isIterator(e.cref) then
310 // Don't evaluate iterators.
311 outExp := e;
312 outEvaluated := false;
313 else
314 // Crefs can be evaluated even if they have non-evaluated subscripts.
315 643 outExp := evalCref(e.cref, e, target, evalSubscripts = false);
316 640 outEvaluated := Expression.isLiteral(outExp);
317 end if;
318 then
319 outExp;
320
321 // Don't evaluate mutable expressions. While they could technically be
322 // evaluated they're usually used as mutable iterators.
323 case Expression.MUTABLE()
324 algorithm
325 outEvaluated := false;
326 then
327 e;
328
329
2/2
✓ Branch 0 taken 6141 times.
✓ Branch 1 taken 1762 times.
7903 else if outEvaluated then evalExp(e, target) else e;
330 end match;
331
332
2/2
✓ Branch 0 taken 8362 times.
✓ Branch 1 taken 1173 times.
9535 outEvaluated := evaluated and outEvaluated;
333 end evalExpPartial;
334
335 function evalCref
336 input ComponentRef cref;
337 input Expression defaultExp;
338 input EvalTarget target;
339 input Boolean evalSubscripts = true;
340 input Boolean liftExp = true;
341 output Expression exp;
342 protected
343 InstNode c;
344 algorithm
345 exp := match cref
346 case ComponentRef.CREF()
347 guard InstNode.isComponent(ComponentRef.node(cref)) and
348 not ComponentRef.isIterator(cref) and
349 ComponentRef.nodeVariability(cref) <= Variability.NON_STRUCTURAL_PARAMETER
350 179314 then evalComponentBinding(ComponentRef.node(cref), cref, defaultExp, target,
351 evalSubscripts, liftExp);
352
353 else defaultExp;
354 end match;
355 end evalCref;
356
357 function evalComponentBinding
358 input InstNode node;
359 input ComponentRef cref;
360 input Expression defaultExp "The expression returned if the binding couldn't be evaluated";
361 input EvalTarget target;
362 input Boolean evalSubscripts = true;
363 input Boolean liftExp = false "Ensure that the result has the same dimensions as the cref";
364 output Expression exp;
365 protected
366 InstContext.Type exp_context;
367 Component comp;
368 Binding binding;
369 Boolean evaluated;
370 Option<Expression> start_exp;
371 Type cref_ty, exp_ty;
372 Integer dim_diff;
373 list<Integer> errors;
374 algorithm
375 179314 exp_context := InstContext.nodeContext(node, target.context);
376 179314 Typing.typeComponentBinding(node, exp_context, typeChildren = false);
377 179310 comp := InstNode.component(node);
378 179310 binding := Component.getBinding(comp);
379
380
2/2
✓ Branch 1 taken 1738 times.
✓ Branch 2 taken 177572 times.
179310 if Binding.isUnbound(binding) then
381 // In some cases we need to construct a binding for the node, for example when
382 // a record has bindings on the fields but not on the record instance as a whole.
383 1738 binding := makeComponentBinding(comp, node, Expression.toCref(defaultExp), target);
384
385
2/2
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 1714 times.
1738 if Binding.isUnbound(binding) then
386 // If we couldn't construct a binding, try to use the start value instead.
387 24 start_exp := evalComponentStartBinding(node, comp, cref, target, evalSubscripts);
388
389
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 24 times.
24 if isSome(start_exp) then
390 // The component had a valid start value. The value has already been
391 // evaluated by evalComponentStartBinding, so skip the rest of the function.
392 ✗ SOME(exp) := start_exp;
393 ✗ return;
394 end if;
395 end if;
396 end if;
397
398 (exp, evaluated) := match binding
399 case Binding.TYPED_BINDING()
400 algorithm
401 exp := match Mutable.access(binding.evalState)
402 // A not yet evaluated binding.
403 case NFBinding.EvalState.NOT_EVALUATED
404 algorithm
405 // Mark the binding as currently being evaluated, to detect loops due
406 // to mutually dependent constants/parameters.
407 35784 Mutable.update(binding.evalState, NFBinding.EvalState.EVALUATING);
408 35784 ErrorExt.setCheckpoint(getInstanceName());
409
410 // Evaluate the binding expression.
411 try
412 35784 exp := evalExp(binding.bindingExp, target);
413 35774 ErrorExt.delCheckpoint(getInstanceName());
414 else
415 // Reset the flag if the evaluation failed.
416 10 Mutable.update(binding.evalState, NFBinding.EvalState.NOT_EVALUATED);
417 10 errors := ErrorExt.popCheckPoint(getInstanceName());
418 10 Error.addSourceMessage(Error.ERROR_FROM_HERE, {}, binding.info);
419 10 ErrorExt.pushMessages(errors);
420 10 fail();
421 end try;
422
423 // Update the binding expression in the component and mark the
424 // binding as evaluated.
425 35774 binding.bindingExp := exp;
426 35774 comp := Component.setBinding(binding, comp);
427 35774 InstNode.updateComponent(comp, node);
428 35774 Mutable.update(binding.evalState, NFBinding.EvalState.EVALUATED);
429 then
430 exp;
431
432 // An already evaluated binding.
433 141076 case NFBinding.EvalState.EVALUATED then binding.bindingExp;
434
435 // A binding that's being evaluated => evaluation loop.
436 else
437 algorithm
438 3 Error.addSourceMessage(Error.CIRCULAR_PARAM,
439 {InstNode.name(node), Prefixes.variabilityString(Component.variability(comp))},
440 InstNode.info(node));
441 1 then
442 fail();
443 end match;
444 then
445 (exp, true);
446
447 2425 case Binding.CEVAL_BINDING() then (binding.bindingExp, true);
448
449 case Binding.UNBOUND()
450 algorithm
451 24 printUnboundError(comp, target, defaultExp);
452 then
453 (defaultExp, false);
454
455 else
456 algorithm
457 ✗ Error.addInternalError(getInstanceName() + " failed on untyped binding", sourceInfo());
458 ✗ then
459 fail();
460
461 end match;
462
463 // Apply subscripts from the cref to the binding expression as needed.
464
2/2
✓ Branch 0 taken 179275 times.
✓ Branch 1 taken 20 times.
179295 if evaluated then
465 179275 exp := subscriptBinding(exp, cref, evalSubscripts);
466 end if;
467
468
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 179295 times.
✓ Branch 3 taken 53 times.
✓ Branch 4 taken 179242 times.
179295 if liftExp and not Expression.contains(exp, Expression.isSplitSubscriptedExp) then
469 179242 exp_ty := Expression.typeOf(exp);
470 179242 cref_ty := Expression.typeOf(defaultExp);
471 179242 dim_diff := Type.dimensionDiff(cref_ty, exp_ty);
472
473
1/2
✓ Branch 0 taken 179242 times.
✗ Branch 1 not taken.
179242 if dim_diff > 0 then
474 ✗ exp := Expression.liftArrayList(List.firstN(Type.arrayDims(cref_ty), dim_diff), exp);
475 end if;
476 end if;
477 end evalComponentBinding;
478
479 function subscriptBinding
480 input output Expression exp;
481 input ComponentRef cref;
482 input Boolean evalSubscripts;
483 protected
484 list<Subscript> subs;
485 algorithm
486 179275 subs := ComponentRef.getSubscripts(cref);
487
488
2/2
✓ Branch 0 taken 91896 times.
✓ Branch 1 taken 87379 times.
179275 if evalSubscripts then
489
4/4
✓ Branch 0 taken 5390 times.
✓ Branch 1 taken 91896 times.
✓ Branch 2 taken 5390 times.
✓ Branch 3 taken 91896 times.
97286 subs := list(Subscript.eval(s) for s in subs);
490 end if;
491
492 179275 subs := List.trimToLength(subs, Expression.dimensionCount(exp));
493 179275 exp := Expression.applySubscripts(subs, exp);
494 179275 exp := subscriptBinding2(exp, cref, evalSubscripts, NONE());
495 end subscriptBinding;
496
497 function subscriptBinding2
498 input output Expression exp;
499 input ComponentRef cref;
500 input Boolean evalSubscripts;
501 input output Option<UnorderedMap<InstNode, list<Subscript>>> subMap;
502 protected
503 type SubscriptList = list<Subscript>;
504 UnorderedMap<InstNode, list<Subscript>> sub_map;
505 list<Subscript> subs;
506 list<ComponentRef> cref_parts;
507 Expression e;
508 algorithm
509 (exp, subMap) := match exp
510 case Expression.SUBSCRIPTED_EXP(subscripts = subs)
511 algorithm
512
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2298 times.
✓ Branch 2 taken 2298 times.
✗ Branch 3 not taken.
2298 if isSome(subMap) then
513 ✗ SOME(sub_map) := subMap;
514 else
515 // If the cref hasn't been flattened then subscripts that reference
516 // the scope parts of the cref should be kept as they are, so the
517 // scope isn't added to the map in that case.
518 2298 cref_parts := ComponentRef.toListReverse(cref, includeScope = isFlatCref(cref));
519
520 // Create a map that maps each part of the cref to the subscripts on that part.
521 2298 sub_map := UnorderedMap.new<SubscriptList>(InstNode.hash,
522 InstNode.refEqual, Util.nextPrime(listLength(cref_parts)));
523
524
2/2
✓ Branch 0 taken 4610 times.
✓ Branch 1 taken 2298 times.
6908 for cr in cref_parts loop
525 4610 UnorderedMap.addUnique(ComponentRef.node(cr), ComponentRef.getSubscripts(cr), sub_map);
526 end for;
527
528 2298 subMap := SOME(sub_map);
529 end if;
530
531 // Replace the split subscripts with the corresponding subscripts from the cref.
532
4/4
✓ Branch 0 taken 2440 times.
✓ Branch 1 taken 2298 times.
✓ Branch 2 taken 2440 times.
✓ Branch 3 taken 2298 times.
4738 subs := list(subscriptBinding3(s, sub_map) for s in subs);
533
534 // Evaluate the subscripts if it was requested.
535
2/2
✓ Branch 0 taken 189 times.
✓ Branch 1 taken 2109 times.
2298 if evalSubscripts then
536
4/4
✓ Branch 0 taken 190 times.
✓ Branch 1 taken 189 times.
✓ Branch 2 taken 190 times.
✓ Branch 3 taken 189 times.
379 subs := list(Subscript.eval(s) for s in subs);
537 end if;
538
539 2298 (e, subMap) := subscriptBinding2(exp.exp, cref, evalSubscripts, subMap);
540 2298 e := Expression.applySubscripts(subs, e);
541 2298 then
542 (e, subMap);
543
544 13381 case Expression.ARRAY(literal = true) then (exp, subMap);
545
546
2/2
✓ Branch 0 taken 113917 times.
✓ Branch 1 taken 233102 times.
460936 else Expression.mapFoldShallow(exp,
547 function subscriptBinding2(cref = cref, evalSubscripts = evalSubscripts), subMap);
548
549 end match;
550 end subscriptBinding2;
551
552 function isFlatCref
553 input ComponentRef cref;
554 output Boolean flat;
555 algorithm
556 flat := match cref
557 // A cref is considered to be flat if the first part that comes from the
558 // scope and has an array type also has subscripts. A cref with only scalars
559 // in the scope part may technically be flat, but it doesn't matter since
560 // there won't be any subscripts referencing them anyway.
561 case ComponentRef.CREF(origin = NFComponentRef.Origin.SCOPE)
562 guard Type.isArray(cref.ty)
563 504 then not listEmpty(cref.subscripts);
564
565 6063 case ComponentRef.CREF() then isFlatCref(cref.restCref);
566 else false;
567 end match;
568 end isFlatCref;
569
570 function subscriptBinding3
571 input Subscript subscript;
572 input UnorderedMap<InstNode, list<Subscript>> subMap;
573 output Subscript outSubscript;
574 protected
575 Option<list<Subscript>> osubs;
576 list<Subscript> subs;
577 algorithm
578 outSubscript := match subscript
579 case Subscript.SPLIT_INDEX()
580 algorithm
581 526 osubs := UnorderedMap.get(InstNode.borrow(subscript.node), subMap);
582
583
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 526 times.
✓ Branch 2 taken 479 times.
✓ Branch 3 taken 47 times.
526 if isSome(osubs) then
584 479 SOME(subs) := osubs;
585
586
2/2
✓ Branch 1 taken 471 times.
✓ Branch 2 taken 8 times.
479 if subscript.dimIndex > listLength(subs) then
587 outSubscript := Subscript.WHOLE();
588 else
589 471 outSubscript := listGet(subs, subscript.dimIndex);
590 end if;
591 else
592 outSubscript := subscript;
593 end if;
594 then
595 outSubscript;
596
597 else subscript;
598 end match;
599 end subscriptBinding3;
600
601 function evalComponentStartBinding
602 "Tries to evaluate the given component's start value. NONE() is returned if
603 the component isn't a fixed parameter or if it doesn't have a start value.
604 Otherwise the evaluated binding expression is returned if it could be
605 evaluated, or the function will fail if it couldn't be."
606 input InstNode node;
607 input Component comp;
608 input ComponentRef cref;
609 input EvalTarget target;
610 input Boolean evalSubscripts;
611 output Option<Expression> outExp = NONE();
612 protected
613 Variability var;
614 InstNode start_node;
615 Component start_comp;
616 Binding binding;
617 Expression exp;
618 algorithm
619 // Only use the start value if the component is a fixed parameter.
620 24 var := Component.variability(comp);
621
4/4
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 2 times.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 13 times.
24 if (var <> Variability.PARAMETER and var <> Variability.STRUCTURAL_PARAMETER) or
622 not Component.isFixed(comp) then
623 11 return;
624 end if;
625
626 // Look up "start" in the class.
627 try
628 13 start_node := Class.lookupElement("start", InstNode.getClass(node));
629 else
630 ✗ return;
631 end try;
632
633 // Make sure we have an actual start attribute, and didn't just find some
634 // other element named start in the class.
635 13 start_comp := InstNode.component(start_node);
636
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
13 if not Component.isTypeAttribute(start_comp) then
637 ✗ return;
638 end if;
639
640 // Try to evaluate the binding if one exists.
641 13 binding := Component.getBinding(start_comp);
642
643 outExp := match binding
644 case Binding.TYPED_BINDING()
645 algorithm
646 ✗ exp := evalExp(binding.bindingExp, target);
647
648 ✗ if not referenceEq(exp, binding.bindingExp) then
649 ✗ binding.bindingExp := exp;
650 ✗ start_comp := Component.setBinding(binding, start_comp);
651 ✗ InstNode.updateComponent(start_comp, start_node);
652 end if;
653 then
654 SOME(exp);
655
656 13 else outExp;
657 end match;
658 end evalComponentStartBinding;
659
660 function makeComponentBinding
661 input Component component;
662 input InstNode node;
663 input ComponentRef cref;
664 input EvalTarget target;
665 output Binding binding;
666 protected
667 Type ty;
668 NFInstNode.ScopeRef rec_node;
669 Expression exp;
670 algorithm
671 binding := matchcontinue component
672 // A record field without an explicit binding, evaluate the parent's binding
673 // if it has one and fetch the binding from it instead.
674 case _
675 algorithm
676 1738 exp := makeRecordFieldBindingFromParent(cref, target);
677
1/2
✓ Branch 1 taken 1443 times.
✗ Branch 2 not taken.
1443 then
678 if Expression.isEmpty(exp) then NFBinding.EMPTY_BINDING else Binding.CEVAL_BINDING(exp);
679
680 // A record component without an explicit binding, create one from its children.
681 case Component.COMPONENT(ty = Type.COMPLEX(complexTy = ComplexType.RECORD(rec_node)))
682 algorithm
683 269 exp := makeRecordBindingExp(component.classInst, InstNode.borrow(rec_node), component.ty, cref, target);
684 269 binding := Binding.CEVAL_BINDING(exp);
685
686
2/2
✓ Branch 1 taken 268 times.
✓ Branch 2 taken 1 time.
269 if not ComponentRef.hasSubscripts(cref) then
687 268 InstNode.updateComponent(Component.setBinding(binding, component), node);
688 end if;
689 then
690 binding;
691
692 // A record array component without an explicit binding, create one from its children.
693 case Component.COMPONENT(ty = Type.ARRAY(elementType = ty as
694 Type.COMPLEX(complexTy = ComplexType.RECORD(rec_node))))
695 algorithm
696 2 exp := Expression.mapCrefScalars(Expression.fromCref(cref),
697 function makeRecordBindingExp(typeNode = component.classInst,
698 recordNode = InstNode.borrow(rec_node), recordType = ty, target = target));
699
700 2 binding := Binding.CEVAL_BINDING(exp);
701
702
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
2 if not ComponentRef.hasSubscripts(cref) then
703 1 InstNode.updateComponent(Component.setBinding(binding, component), node);
704 end if;
705 then
706 binding;
707
708 else NFBinding.EMPTY_BINDING;
709 end matchcontinue;
710 end makeComponentBinding;
711
712 function makeRecordFieldBindingFromParent
713 input ComponentRef cref;
714 input EvalTarget target;
715 output Expression exp;
716 protected
717 ComponentRef parent_cr;
718 InstNode parent;
719 InstContext.Type exp_context;
720 Binding binding;
721 Component comp;
722 list<Subscript> subs;
723 algorithm
724 2607 parent_cr := ComponentRef.rest(cref);
725 2607 parent := ComponentRef.node(parent_cr);
726 2374 exp_context := InstContext.nodeContext(parent, target.context);
727
728 2374 comp := InstNode.component(parent);
729 2315 binding := Component.getBinding(comp);
730 2315 subs := ComponentRef.getSubscripts(parent_cr);
731
732
2/2
✓ Branch 1 taken 1446 times.
✓ Branch 2 taken 869 times.
2315 if Binding.hasExp(binding) then
733
2/2
✓ Branch 1 taken 64 times.
✓ Branch 2 taken 1382 times.
1446 if not Binding.isTyped(binding) then
734 64 binding := Typing.typeBinding(binding, InstContext.set(exp_context, NFInstContext.BINDING));
735 64 comp := Component.setBinding(binding, comp);
736 64 InstNode.updateComponent(comp, parent);
737 end if;
738
739 1446 exp := Binding.getExp(binding);
740 1446 exp := Expression.applySubscripts(subs, exp);
741 1446 exp := Expression.recordElement(ComponentRef.firstName(cref), exp);
742 1446 exp := evalExp(exp, target);
743
744 1443 exp := Expression.map(exp, function Expression.expandNonListedSplitIndices(
745 indicesToKeep = ComponentRef.nodesIncludingSplitSubs(cref)));
746 else
747 // If the parent didn't have a binding, try the parent's parent.
748 869 exp := makeRecordFieldBindingFromParent(parent_cr, target);
749 1 exp := Expression.applySubscripts(subs, exp);
750 1 exp := Expression.recordElement(ComponentRef.firstName(cref), exp);
751 end if;
752 end makeRecordFieldBindingFromParent;
753
754 function makeRecordBindingExp
755 input InstNode typeNode;
756 input InstNode recordNode;
757 input Type recordType;
758 input ComponentRef cref;
759 input EvalTarget target;
760 output Expression exp;
761 protected
762 ClassTree tree;
763 array<InstNode> comps;
764 list<Expression> args;
765 Type ty;
766 InstNode c;
767 ComponentRef cr;
768 Expression arg;
769 algorithm
770 273 tree := Class.classTree(InstNode.getClass(typeNode));
771 273 comps := ClassTree.getComponents(tree);
772 273 args := {};
773
774 273 ErrorExt.setCheckpoint(getInstanceName());
775
2/2
✓ Branch 0 taken 271 times.
✓ Branch 1 taken 2 times.
5884 for i in arrayLength(comps):-1:1 loop
776 5611 c := comps[i];
777 5611 ty := InstNode.getType(c);
778 5611 cr := ComponentRef.prefixCref(c, ty, {}, cref);
779 5611 arg := Expression.CREF(ty, cr);
780
781
2/2
✓ Branch 2 taken 5610 times.
✓ Branch 3 taken 1 time.
5611 if Component.variability(InstNode.component(c)) <= Variability.PARAMETER then
782 try
783 5610 arg := evalExp(arg, target);
784 else
785 // Ignore components that don't have a binding, it might not be an error
786 // and if it is we can give better error messages in other places.
787 end try;
788 end if;
789
790 args := arg :: args;
791 end for;
792 273 ErrorExt.rollBack(getInstanceName());
793
794 273 exp := Expression.makeRecord(InstNode.fullPath(recordNode), recordType, args);
795 end makeRecordBindingExp;
796
797 function evalTypename
798 input Type ty;
799 input Expression originExp;
800 input EvalTarget target;
801 output Expression exp;
802 algorithm
803 // Only expand the typename into an array if it's used as a range, and keep
804 // them as typenames when used as e.g. dimensions.
805
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 55 times.
56 exp := if InstContext.inIterationRange(target.context) then ExpandExp.expandTypename(ty) else originExp;
806 end evalTypename;
807
808 function evalRange
809 input Expression rangeExp;
810 input EvalTarget target;
811 output Expression result;
812 protected
813 Type ty;
814 Expression start_exp, stop_exp;
815 Option<Expression> step_exp;
816 algorithm
817
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10913 times.
10913 Expression.RANGE(ty = ty, start = start_exp, step = step_exp, stop = stop_exp) := rangeExp;
818 10913 start_exp := evalExp(start_exp, target);
819 10913 step_exp := Util.applyOption(step_exp, function evalExp(target = target));
820 10913 stop_exp := evalExp(stop_exp, target);
821
822
2/2
✓ Branch 1 taken 2298 times.
✓ Branch 2 taken 8603 times.
10901 if InstContext.inIterationRange(target.context) then
823 2298 ty := TypeCheck.getRangeType(start_exp, step_exp, stop_exp,
824 Type.arrayElementType(ty), EvalTarget.getInfo(target));
825 2298 result := Expression.RANGE(ty, start_exp, step_exp, stop_exp);
826 else
827 8603 result := Expression.RANGE(ty, start_exp, step_exp, stop_exp);
828 8603 result := Expression.mapSplitExpressions(result, evalRangeExp);
829 end if;
830 end evalRange;
831
832 function evalRangeExp
833 input Expression rangeExp;
834 output Expression exp;
835 protected
836 Expression start, step, stop;
837 Option<Expression> opt_step;
838 list<Expression> expl;
839 Type ty;
840 list<String> literals;
841 Integer istep;
842 algorithm
843
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 8603 times.
8603 Expression.RANGE(start = start, step = opt_step, stop = stop) := SimplifyExp.simplify(Expression.map(rangeExp, Expression.replaceResizableParameter));
844
845
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8603 times.
✓ Branch 2 taken 8548 times.
✓ Branch 3 taken 55 times.
8603 if isSome(opt_step) then
846 55 SOME(step) := opt_step;
847
848 (ty, expl) := match (start, step, stop)
849 case (Expression.INTEGER(), Expression.INTEGER(istep), Expression.INTEGER())
850 algorithm
851 // The compiler decided to randomly dislike using step.value here, hence istep.
852
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 64 times.
✓ Branch 5 taken 54 times.
✓ Branch 6 taken 10 times.
64 expl := list(Expression.INTEGER(i) for i in start.value:istep:stop.value);
853 then
854 (Type.INTEGER(), expl);
855
856 case (Expression.REAL(), Expression.REAL(), Expression.REAL())
857 algorithm
858 45 expl := evalRangeReal(start.value, step.value, stop.value);
859 then
860 (Type.REAL(), expl);
861
862 else
863 algorithm
864 ✗ printWrongArgsError(getInstanceName(), {start, step, stop}, sourceInfo());
865 ✗ then
866 fail();
867 end match;
868 else
869 (ty, expl) := match (start, stop)
870 case (Expression.INTEGER(), Expression.INTEGER())
871 algorithm
872
2/2
✓ Branch 0 taken 38103 times.
✓ Branch 1 taken 8502 times.
46605 expl := list(Expression.INTEGER(i) for i in start.value:stop.value);
873 then
874 (Type.INTEGER(), expl);
875
876 case (Expression.REAL(), Expression.REAL())
877 algorithm
878 5 expl := evalRangeReal(start.value, 1.0, stop.value);
879 then
880 (Type.REAL(), expl);
881
882 case (Expression.BOOLEAN(), Expression.BOOLEAN())
883 algorithm
884 ✗ expl := list(Expression.BOOLEAN(b) for b in start.value:stop.value);
885 then
886 (Type.BOOLEAN(), expl);
887
888 case (Expression.ENUM_LITERAL(ty = ty as Type.ENUMERATION()), Expression.ENUM_LITERAL())
889 algorithm
890
2/2
✓ Branch 0 taken 345 times.
✓ Branch 1 taken 39 times.
384 expl := list(Expression.ENUM_LITERAL(ty, listGet(ty.literals, i), i) for i in start.index:stop.index);
891 then
892 (ty, expl);
893
894 else
895 algorithm
896 2 printWrongArgsError(getInstanceName(), {start, stop}, sourceInfo());
897 2 then
898 fail();
899 end match;
900 end if;
901
902 17202 exp := Expression.makeArray(Type.ARRAY(ty, {Dimension.fromInteger(listLength(expl))}),
903 listArray(expl), literal = true);
904 end evalRangeExp;
905
906 function evalRangeReal
907 input Real start;
908 input Real step;
909 input Real stop;
910 output list<Expression> result;
911 protected
912 Integer steps;
913 algorithm
914 50 steps := Util.realRangeSize(start, step, stop);
915
916 // Real ranges are tricky, make sure that start and stop are reproduced
917 // exactly if they are part of the range.
918
1/2
✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
50 if steps == 0 then
919 result := {};
920 elseif steps == 1 then
921 ✗ result := {Expression.REAL(start)};
922 else
923 50 result := {Expression.REAL(stop)};
924
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 1 time.
309 for i in steps-2:-1:1 loop
925 259 result := Expression.REAL(start + i * step) :: result;
926 end for;
927 50 result := Expression.REAL(start) :: result;
928 end if;
929 end evalRangeReal;
930
931 function printFailedEvalError
932 input String name;
933 input Expression exp;
934 input SourceInfo info;
935 algorithm
936 254 Error.addInternalError(name + " failed to evaluate ‘" + Expression.toString(exp) + "‘", info);
937 end printFailedEvalError;
938
939 function evalBinaryOp
940 input Expression exp1;
941 input Operator op;
942 input Expression exp2;
943 input EvalTarget target = noTarget;
944 output Expression exp;
945 algorithm
946 303611 exp := Expression.mapSplitExpressions(Expression.BINARY(exp1, op, exp2),
947 function evalBinaryExp(target = target));
948 end evalBinaryOp;
949
950 function evalBinaryExp
951 input Expression binaryExp;
952 input EvalTarget target;
953 output Expression result;
954 protected
955 Expression e1, e2;
956 Operator op;
957 algorithm
958
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 303613 times.
303613 Expression.BINARY(exp1 = e1, operator = op, exp2 = e2) := binaryExp;
959 303613 result := evalBinaryOp_dispatch(e1, op, e2, target);
960 end evalBinaryExp;
961
962 function evalBinaryOp_dispatch
963 input Expression exp1;
964 input Operator op;
965 input Expression exp2;
966 input EvalTarget target = noTarget;
967 output Expression exp;
968 algorithm
969 exp := match op.op
970 69738 case Op.ADD then evalBinaryAdd(exp1, exp2);
971 42428 case Op.SUB then evalBinarySub(exp1, exp2);
972 144641 case Op.MUL then evalBinaryMul(exp1, exp2);
973 27868 case Op.DIV then evalBinaryDiv(exp1, exp2, target);
974 11524 case Op.POW then evalBinaryPow(exp1, exp2, target);
975 ✗ case Op.ADD_EW then evalBinaryAdd(exp1, exp2);
976 ✗ case Op.SUB_EW then evalBinarySub(exp1, exp2);
977 6 case Op.MUL_EW then evalBinaryMul(exp1, exp2);
978 ✗ case Op.ADD_SCALAR_ARRAY then evalBinaryScalarArray(exp1, exp2, evalBinaryAdd);
979 ✗ case Op.ADD_ARRAY_SCALAR then evalBinaryArrayScalar(exp1, exp2, evalBinaryAdd);
980 ✗ case Op.SUB_SCALAR_ARRAY then evalBinaryScalarArray(exp1, exp2, evalBinarySub);
981 ✗ case Op.SUB_ARRAY_SCALAR then evalBinaryArrayScalar(exp1, exp2, evalBinarySub);
982 329 case Op.MUL_SCALAR_ARRAY then evalBinaryScalarArray(exp1, exp2, evalBinaryMul);
983 778 case Op.MUL_ARRAY_SCALAR then evalBinaryArrayScalar(exp1, exp2, evalBinaryMul);
984 ✗ case Op.MUL_VECTOR_MATRIX then evalBinaryMulVectorMatrix(exp1, exp2);
985 37 case Op.MUL_MATRIX_VECTOR then evalBinaryMulMatrixVector(exp1, exp2);
986 4420 case Op.SCALAR_PRODUCT then evalBinaryScalarProduct(exp1, exp2);
987 114 case Op.MATRIX_PRODUCT then evalBinaryMatrixProduct(exp1, exp2);
988 case Op.DIV_SCALAR_ARRAY
989 2 then evalBinaryScalarArray(exp1, exp2, function evalBinaryDiv(target = target));
990 case Op.DIV_ARRAY_SCALAR
991 1719 then evalBinaryArrayScalar(exp1, exp2, function evalBinaryDiv(target = target));
992 ✗ case Op.POW_SCALAR_ARRAY then evalBinaryScalarArray(exp1, exp2, function evalBinaryPow(target = target));
993 ✗ case Op.POW_ARRAY_SCALAR then evalBinaryArrayScalar(exp1, exp2, function evalBinaryPow(target = target));
994 9 case Op.POW_MATRIX then evalBinaryPowMatrix(exp1, exp2);
995 else
996 algorithm
997 ✗ Error.addInternalError(getInstanceName() + ": unimplemented case for " +
998 Expression.toString(Expression.BINARY(exp1, op, exp2)), sourceInfo());
999 ✗ then
1000 fail();
1001 end match;
1002 end evalBinaryOp_dispatch;
1003
1004 function evalBinaryAdd
1005 input Expression exp1;
1006 input Expression exp2;
1007 output Expression exp;
1008 algorithm
1009 exp := match (exp1, exp2)
1010 // while technically not allowed to mix integers and reals, it occurs when solving in the new backend
1011 case (Expression.REAL(), Expression.INTEGER())
1012 4 then Expression.REAL(exp1.value + exp2.value);
1013 case (Expression.INTEGER(), Expression.REAL())
1014 2 then Expression.REAL(exp1.value + exp2.value);
1015
1016 case (Expression.INTEGER(), Expression.INTEGER())
1017 10327 then Expression.INTEGER(exp1.value + exp2.value);
1018
1019 case (Expression.REAL(), Expression.REAL())
1020 80656 then Expression.REAL(exp1.value + exp2.value);
1021
1022 case (Expression.STRING(), Expression.STRING())
1023 2168 then Expression.STRING(exp1.value + exp2.value);
1024
1025 case (Expression.STRING(), Expression.FILENAME())
1026 ✗ then Expression.STRING(exp1.value + exp2.filename);
1027
1028 case (Expression.FILENAME(), Expression.STRING())
1029 ✗ then Expression.STRING(exp1.filename + exp2.value);
1030
1031 case (Expression.FILENAME(), Expression.FILENAME())
1032 ✗ then Expression.STRING(exp1.filename + exp2.filename);
1033
1034 case (Expression.ARRAY(), Expression.ARRAY())
1035 guard arrayLength(exp1.elements) == arrayLength(exp2.elements)
1036 676 then Expression.makeArray(exp1.ty,
1037 Array.threadMap(exp1.elements, exp2.elements, evalBinaryAdd),
1038 literal = true);
1039
1040 // technically the following two are incorrect because they need element wise addition
1041 // but the backend can create these and immediately tries to evaluate them.
1042 // kabdelhak: instead of fixing the operators we will just allow this to be immediately evaluated
1043 case (Expression.ARRAY(), _)
1044 ✗ then Expression.makeArray(exp1.ty,
1045 Array.map(exp1.elements, function evalBinaryAdd(exp2 = exp2)),
1046 literal = exp1.literal);
1047 case (_, Expression.ARRAY())
1048 327 then Expression.makeArray(exp2.ty,
1049 Array.map(exp2.elements, function evalBinaryAdd(exp1 = exp1)),
1050 literal = exp2.literal);
1051
1052 // first element is added to nothing. To make sure the right typing is used
1053 case (Expression.EMPTY(), _) then exp2;
1054 case (_, Expression.EMPTY()) then exp1;
1055
1056 else
1057 algorithm
1058 6 exp := Expression.BINARY(exp1, Operator.makeAdd(Type.UNKNOWN()), exp2);
1059 6 printFailedEvalError(getInstanceName(), exp, sourceInfo());
1060 6 then
1061 fail();
1062 end match;
1063 end evalBinaryAdd;
1064
1065 function evalBinarySub
1066 input Expression exp1;
1067 input Expression exp2;
1068 output Expression exp;
1069 algorithm
1070 exp := match (exp1, exp2)
1071 // while technically not allowed to mix integers and reals, it occurs when solving in the new backend
1072 case (Expression.REAL(), Expression.INTEGER())
1073 2 then Expression.REAL(exp1.value - exp2.value);
1074 case (Expression.INTEGER(), Expression.REAL())
1075 5 then Expression.REAL(exp1.value - exp2.value);
1076
1077 case (Expression.INTEGER(), Expression.INTEGER())
1078 13236 then Expression.INTEGER(exp1.value - exp2.value);
1079
1080 case (Expression.REAL(), Expression.REAL())
1081 42832 then Expression.REAL(exp1.value - exp2.value);
1082
1083 case (Expression.ARRAY(), Expression.ARRAY())
1084 guard arrayLength(exp1.elements) == arrayLength(exp2.elements)
1085 802 then Expression.makeArray(exp1.ty,
1086 Array.threadMap(exp1.elements, exp2.elements, evalBinarySub),
1087 literal = true);
1088
1089 // technically the following two are incorrect because they need element wise addition
1090 // but the backend can create these and immediately tries to evaluate them.
1091 // kabdelhak: instead of fixing the operators we will just allow this to be immediately evaluated
1092 case (Expression.ARRAY(), _)
1093 ✗ then Expression.makeArray(exp1.ty,
1094 Array.map(exp1.elements, function evalBinarySub(exp2 = exp2)),
1095 literal = exp1.literal);
1096 case (_, Expression.ARRAY())
1097 120 then Expression.makeArray(exp2.ty,
1098 Array.map(exp2.elements, function evalBinarySub(exp1 = exp1)),
1099 literal = exp2.literal);
1100
1101 // first element is subtracted from nothing. To make sure the right typing is used
1102 4026 case (Expression.EMPTY(), _) then evalBinarySub(Expression.makeZero(Expression.typeOf(exp2)), exp2);
1103 case (_, Expression.EMPTY()) then exp1;
1104
1105 else
1106 algorithm
1107 22 exp := Expression.BINARY(exp1, Operator.makeSub(Type.UNKNOWN()), exp2);
1108 22 printFailedEvalError(getInstanceName(), exp, sourceInfo());
1109 22 then
1110 fail();
1111 end match;
1112 end evalBinarySub;
1113
1114 function expandLiteralRange
1115 "A range operand can still be unevaluated here, e.g. 1 + (1:2) from an iterator
1116 substituted into a subscript. Turn a literal range into an array."
1117 input output Expression exp;
1118 algorithm
1119 exp := match exp
1120 case Expression.RANGE() guard Expression.isLiteral(exp)
1121 ✗ then Expression.mapSplitExpressions(exp, evalRangeExp);
1122 else exp;
1123 end match;
1124 end expandLiteralRange;
1125
1126 function evalMultaryAddSub
1127 input list<Expression> arguments;
1128 input list<Expression> inv_arguments;
1129 input Type operator_ty;
1130 output Expression exp = Expression.EMPTY(operator_ty);
1131 output Boolean isNeutral;
1132 algorithm
1133 // add up all arguments
1134
2/2
✓ Branch 0 taken 26779 times.
✓ Branch 1 taken 56439 times.
83218 for arg in arguments loop
1135 26779 exp := evalBinaryAdd(exp, expandLiteralRange(arg));
1136 end for;
1137
1138 // subtract all inverse arguments
1139
2/2
✓ Branch 0 taken 11994 times.
✓ Branch 1 taken 56439 times.
68433 for arg in inv_arguments loop
1140 11994 exp := evalBinarySub(exp, expandLiteralRange(arg));
1141 end for;
1142
1143 // return a boolean that is set to true if its the neutral element
1144
4/4
✓ Branch 1 taken 24706 times.
✓ Branch 2 taken 31733 times.
✓ Branch 4 taken 7269 times.
✓ Branch 5 taken 17437 times.
56439 isNeutral := Expression.isEmpty(exp) or Expression.isZero(exp);
1145 end evalMultaryAddSub;
1146
1147 function evalBinaryMul
1148 input Expression exp1;
1149 input Expression exp2;
1150 output Expression exp;
1151 algorithm
1152 exp := match (exp1, exp2)
1153 // while technically not allowed to mix integers and reals, it occurs when solving in the new backend
1154 case (Expression.REAL(), Expression.INTEGER())
1155 3 then Expression.REAL(exp1.value * exp2.value);
1156 case (Expression.INTEGER(), Expression.REAL())
1157 12 then Expression.REAL(exp1.value * exp2.value);
1158
1159 case (Expression.INTEGER(), Expression.INTEGER())
1160 866 then Expression.INTEGER(exp1.value * exp2.value);
1161
1162 case (Expression.REAL(), Expression.REAL())
1163 164501 then Expression.REAL(exp1.value * exp2.value);
1164
1165 case (Expression.ARRAY(), Expression.ARRAY())
1166 guard arrayLength(exp1.elements) == arrayLength(exp2.elements)
1167 10 then Expression.makeArray(exp1.ty,
1168 Array.threadMap(exp1.elements, exp2.elements, evalBinaryMul),
1169 literal = true);
1170
1171 // technically the following two are incorrect because they need element wise addition
1172 // but the backend can create these and immediately tries to evaluate them.
1173 // kabdelhak: instead of fixing the operators we will just allow this to be immediately evaluated
1174 case (Expression.ARRAY(), _)
1175 ✗ then Expression.makeArray(exp1.ty,
1176 Array.map(exp1.elements, function evalBinaryMul(exp2 = exp2)),
1177 literal = exp1.literal);
1178 case (_, Expression.ARRAY())
1179 54 then Expression.makeArray(exp2.ty,
1180 Array.map(exp2.elements, function evalBinaryMul(exp1 = exp1)),
1181 literal = exp2.literal);
1182
1183 // first element is multiplied to nothing. To make sure the right typing is used
1184 case (Expression.EMPTY(), _) then exp2;
1185 case (_, Expression.EMPTY()) then exp1;
1186
1187 else
1188 algorithm
1189 63 exp := Expression.BINARY(exp1, Operator.makeMul(Type.UNKNOWN()), exp2);
1190 63 printFailedEvalError(getInstanceName(), exp, sourceInfo());
1191 63 then
1192 fail();
1193 end match;
1194 end evalBinaryMul;
1195
1196 function evalBinaryDiv
1197 input Expression exp1;
1198 input Expression exp2;
1199 input EvalTarget target;
1200 output Expression exp;
1201 algorithm
1202 exp := match (exp1, exp2)
1203 // Division by zero
1204 case (_, _) guard Expression.isZero(exp2)
1205 algorithm
1206 ✗ if EvalTarget.hasInfo(target) then
1207 ✗ Error.addSourceMessage(Error.DIVISION_BY_ZERO,
1208 {Expression.toString(exp1), Expression.toString(exp2)}, EvalTarget.getInfo(target));
1209 ✗ fail();
1210 else
1211 ✗ exp := Expression.BINARY(exp1, Operator.makeDiv(Type.REAL()), exp2);
1212 end if;
1213 then
1214 exp;
1215
1216 // while technically not allowed to divide integers, it occurs when solving in the new backend
1217 case (_, Expression.INTEGER(1)) then exp1;
1218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 case (Expression.REAL(), Expression.INTEGER()) then Expression.REAL(exp1.value / exp2.value);
1219 ✗ case (Expression.INTEGER(), Expression.REAL()) then Expression.REAL(exp1.value / exp2.value);
1220
1221
5/8
✓ Branch 0 taken 16 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 12 times.
32 case (Expression.INTEGER(), Expression.INTEGER()) then
1222 if intMod(exp1.value, exp2.value) == 0 then Expression.INTEGER(intDiv(exp1.value, exp2.value)) else Expression.REAL(exp1.value / exp2.value);
1223
1224 case (Expression.REAL(), Expression.REAL())
1225
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33276 times.
33276 then Expression.REAL(exp1.value / exp2.value);
1226
1227 case (Expression.ARRAY(), Expression.ARRAY())
1228 guard arrayLength(exp1.elements) == arrayLength(exp2.elements)
1229 ✗ then Expression.makeArray(exp1.ty,
1230 Array.threadMap(exp1.elements, exp2.elements, function evalBinaryDiv(target = target)),
1231 literal = true);
1232
1233 // technically the following two are incorrect because they need element wise addition
1234 // but the backend can create these and immediately tries to evaluate them.
1235 // kabdelhak: instead of fixing the operators we will just allow this to be immediately evaluated
1236 case (Expression.ARRAY(), _)
1237 ✗ then Expression.makeArray(exp1.ty,
1238 Array.map(exp1.elements, function evalBinaryDiv(exp2 = exp2, target = target)),
1239 literal = exp1.literal);
1240 case (_, Expression.ARRAY())
1241 ✗ then Expression.makeArray(exp2.ty,
1242 Array.map(exp2.elements, function evalBinaryDiv(exp1 = exp1, target = target)),
1243 literal = exp2.literal);
1244
1245 // first element is divided from nothing. To make sure the right typing is used
1246 208 case (Expression.EMPTY(), _) then evalBinaryDiv(Expression.makeOne(Expression.typeOf(exp2)), exp2, target);
1247 case (_, Expression.EMPTY()) then exp1;
1248
1249 else
1250 algorithm
1251 28 exp := Expression.BINARY(exp1, Operator.makeDiv(Type.UNKNOWN()), exp2);
1252 28 printFailedEvalError(getInstanceName(), exp, sourceInfo());
1253 28 then
1254 fail();
1255 end match;
1256 end evalBinaryDiv;
1257
1258 function evalMultaryMulDiv
1259 input list<Expression> arguments;
1260 input list<Expression> inv_arguments;
1261 input Type operator_ty;
1262 output Expression exp = Expression.EMPTY(operator_ty);
1263 output Boolean isNeutral;
1264 algorithm
1265 // multiply all arguments
1266
2/2
✓ Branch 0 taken 8317 times.
✓ Branch 1 taken 20545 times.
28862 for arg in arguments loop
1267 8317 exp := evalBinaryMul(exp, expandLiteralRange(arg));
1268 end for;
1269
1270 // divide all inverse arguments
1271
2/2
✓ Branch 0 taken 1255 times.
✓ Branch 1 taken 20545 times.
21800 for arg in inv_arguments loop
1272 1255 exp := evalBinaryDiv(exp, expandLiteralRange(arg), noTarget);
1273 end for;
1274
1275 // return a boolean that is set to true if its the neutral element
1276
4/4
✓ Branch 1 taken 7908 times.
✓ Branch 2 taken 12637 times.
✓ Branch 4 taken 902 times.
✓ Branch 5 taken 7006 times.
20545 isNeutral := Expression.isEmpty(exp) or Expression.isOne(exp);
1277 end evalMultaryMulDiv;
1278
1279 function evalBinaryPow
1280 input Expression exp1;
1281 input Expression exp2;
1282 input EvalTarget target;
1283 output Expression exp;
1284 algorithm
1285 exp := match (exp1, exp2)
1286 case (Expression.REAL(), Expression.REAL())
1287 guard exp1.value < 0 and realInt(exp2.value) <> exp2.value
1288 algorithm
1289 ✗ if EvalTarget.hasInfo(target) then
1290 ✗ Error.addSourceMessage(Error.INVALID_NEGATIVE_POW,
1291 {Expression.toString(exp1), Expression.toString(exp2)}, EvalTarget.getInfo(target));
1292 ✗ fail();
1293 end if;
1294 ✗ then
1295 Expression.BINARY(exp1, Operator.makePow(Type.REAL()), exp2);
1296
1297 case (Expression.REAL(), Expression.REAL())
1298
8/22
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 11506 times.
✓ Branch 2 taken 18 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 18 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 18 times.
✓ Branch 8 taken 18 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✓ Branch 18 taken 11524 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 11524 times.
11524 then Expression.REAL(exp1.value ^ exp2.value);
1299
1300 case (Expression.ARRAY(), Expression.ARRAY())
1301 guard arrayLength(exp1.elements) == arrayLength(exp2.elements)
1302 ✗ then Expression.makeArray(exp1.ty,
1303 Array.threadMap(exp1.elements, exp2.elements, function evalBinaryPow(target = target)),
1304 literal = true);
1305
1306 else
1307 algorithm
1308 ✗ exp := Expression.BINARY(exp1, Operator.makePow(Type.UNKNOWN()), exp2);
1309 ✗ printFailedEvalError(getInstanceName(), exp, sourceInfo());
1310 ✗ then
1311 fail();
1312 end match;
1313 end evalBinaryPow;
1314
1315 function evalBinaryScalarArray
1316 input Expression scalarExp;
1317 input Expression arrayExp;
1318 input FuncT opFunc;
1319 output Expression exp;
1320
1321 partial function FuncT
1322 input Expression exp1;
1323 input Expression exp2;
1324 output Expression exp;
1325 end FuncT;
1326 algorithm
1327 exp := match arrayExp
1328 case Expression.ARRAY()
1329 589 then Expression.makeArray(arrayExp.ty,
1330 Array.map(arrayExp.elements, function evalBinaryScalarArray(scalarExp = scalarExp, opFunc = opFunc)),
1331 literal = true);
1332
1333
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 1531 times.
1549 else opFunc(scalarExp, arrayExp);
1334 end match;
1335 end evalBinaryScalarArray;
1336
1337 function evalBinaryArrayScalar
1338 input Expression arrayExp;
1339 input Expression scalarExp;
1340 input FuncT opFunc;
1341 output Expression exp;
1342
1343 partial function FuncT
1344 input Expression exp1;
1345 input Expression exp2;
1346 output Expression exp;
1347 end FuncT;
1348 algorithm
1349 exp := match arrayExp
1350 case Expression.ARRAY()
1351 2689 then Expression.makeArray(arrayExp.ty,
1352 Array.map(arrayExp.elements, function evalBinaryArrayScalar(scalarExp = scalarExp, opFunc = opFunc)),
1353 literal = true);
1354
1355
2/2
✓ Branch 0 taken 5201 times.
✓ Branch 1 taken 2756 times.
7957 else opFunc(arrayExp, scalarExp);
1356 end match;
1357 end evalBinaryArrayScalar;
1358
1359 function evalBinaryMulVectorMatrix
1360 input Expression vectorExp;
1361 input Expression matrixExp;
1362 output Expression exp;
1363 protected
1364 Dimension m;
1365 Type ty;
1366 array<Expression> arr;
1367 algorithm
1368 exp := match Expression.transposeArray(matrixExp)
1369 case Expression.ARRAY(Type.ARRAY(ty, {m, _}), arr)
1370 algorithm
1371 ✗ arr := Array.map(arr, function evalBinaryScalarProduct(exp1 = vectorExp));
1372 ✗ then
1373 Expression.makeArray(Type.ARRAY(ty, {m}), arr, literal = true);
1374
1375 else
1376 algorithm
1377 ✗ exp := Expression.BINARY(vectorExp, Operator.makeMul(Type.UNKNOWN()), matrixExp);
1378 ✗ printFailedEvalError(getInstanceName(), exp, sourceInfo());
1379 ✗ then
1380 fail();
1381
1382 end match;
1383 end evalBinaryMulVectorMatrix;
1384
1385 function evalBinaryMulMatrixVector
1386 input Expression matrixExp;
1387 input Expression vectorExp;
1388 output Expression exp;
1389 protected
1390 Dimension n;
1391 Type ty;
1392 array<Expression> arr;
1393 algorithm
1394 exp := match matrixExp
1395 case Expression.ARRAY(Type.ARRAY(ty, {n, _}), arr)
1396 algorithm
1397 37 arr := Array.map(arr, function evalBinaryScalarProduct(exp2 = vectorExp));
1398 37 then
1399 Expression.makeArray(Type.ARRAY(ty, {n}), arr, literal = true);
1400
1401 else
1402 algorithm
1403 ✗ exp := Expression.BINARY(matrixExp, Operator.makeMul(Type.UNKNOWN()), vectorExp);
1404 ✗ printFailedEvalError(getInstanceName(), exp, sourceInfo());
1405 ✗ then
1406 fail();
1407
1408 end match;
1409 end evalBinaryMulMatrixVector;
1410
1411 function evalBinaryScalarProduct
1412 input Expression exp1;
1413 input Expression exp2;
1414 output Expression exp;
1415 algorithm
1416 exp := match (exp1, exp2)
1417 local
1418 Type elem_ty;
1419
1420 case (Expression.ARRAY(ty = Type.ARRAY(elem_ty)), Expression.ARRAY())
1421 guard arrayLength(exp1.elements) == arrayLength(exp2.elements)
1422 algorithm
1423 5610 exp := Expression.makeZero(elem_ty);
1424
1425
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5610 times.
✓ Branch 2 taken 5609 times.
✓ Branch 3 taken 1 time.
27087 for i in 1:arrayLength(exp1.elements) loop
1426 15867 exp := evalBinaryAdd(exp,
1427 evalBinaryMul(arrayGetNoBoundsChecking(exp1.elements, i),
1428 arrayGetNoBoundsChecking(exp2.elements, i)));
1429 end for;
1430 then
1431 exp;
1432
1433 else
1434 algorithm
1435 ✗ exp := Expression.BINARY(exp1, Operator.makeMul(Type.UNKNOWN()), exp2);
1436 ✗ printFailedEvalError(getInstanceName(), exp, sourceInfo());
1437 ✗ then
1438 fail();
1439
1440 end match;
1441 end evalBinaryScalarProduct;
1442
1443 function evalBinaryMatrixProduct
1444 input Expression exp1;
1445 input Expression exp2;
1446 output Expression exp;
1447 protected
1448 Expression e2;
1449 Type elem_ty, row_ty, mat_ty;
1450 Dimension n, p;
1451 array<Expression> arr1, arr2, arr;
1452 algorithm
1453 121 e2 := Expression.transposeArray(exp2);
1454
1455 exp := match (exp1, e2)
1456 case (Expression.ARRAY(Type.ARRAY(elem_ty, {n, _}), arr1),
1457 Expression.ARRAY(Type.ARRAY(_, {p, _}), arr2))
1458 algorithm
1459 121 mat_ty := Type.ARRAY(elem_ty, {n, p});
1460
1461
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 121 times.
121 if arrayEmpty(arr2) then
1462 ✗ exp := Expression.makeZero(mat_ty);
1463 else
1464 121 row_ty := Type.ARRAY(elem_ty, {p});
1465 121 arr := arrayCreateNoInit(arrayLength(arr1), exp1);
1466
1467
1/2
✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
482 for i in 1:arrayLength(arr1) loop
1468 361 arrayUpdateNoBoundsChecking(arr, i,
1469 Expression.makeArray(row_ty,
1470 Array.map(arr2, function evalBinaryScalarProduct(exp1 = arrayGetNoBoundsChecking(arr1, i))),
1471 literal = true));
1472 end for;
1473
1474 121 exp := Expression.makeArray(mat_ty, arr, literal = true);
1475 end if;
1476 then
1477 exp;
1478
1479 else
1480 algorithm
1481 ✗ exp := Expression.BINARY(exp1, Operator.makeMul(Type.UNKNOWN()), exp2);
1482 ✗ printFailedEvalError(getInstanceName(), exp, sourceInfo());
1483 ✗ then
1484 fail();
1485
1486 end match;
1487 end evalBinaryMatrixProduct;
1488
1489 function evalBinaryPowMatrix
1490 input Expression matrixExp;
1491 input Expression nExp;
1492 output Expression exp;
1493 protected
1494 Integer n;
1495 algorithm
1496 exp := match nExp
1497 case Expression.INTEGER(value = 0)
1498 algorithm
1499 3 n := Dimension.size(listHead(Type.arrayDims(Expression.typeOf(matrixExp))));
1500 3 then
1501 Expression.makeIdentityMatrix(n, Type.REAL());
1502
1503 case Expression.INTEGER(value = n)
1504 6 then evalBinaryPowMatrix2(matrixExp, n);
1505
1506 else
1507 algorithm
1508 ✗ exp := Expression.BINARY(matrixExp, Operator.makePow(Type.UNKNOWN()), nExp);
1509 ✗ printFailedEvalError(getInstanceName(), exp, sourceInfo());
1510 ✗ then
1511 fail();
1512
1513 end match;
1514 end evalBinaryPowMatrix;
1515
1516 function evalBinaryPowMatrix2
1517 input Expression matrix;
1518 input Integer n;
1519 output Expression exp;
1520 algorithm
1521 exp := match n
1522 // A^1 = A
1523 case 1 then matrix;
1524
1525 // A^2 = A * A
1526 5 case 2 then evalBinaryMatrixProduct(matrix, matrix);
1527
1528 // A^n = A^m * A^m where n = 2*m
1529 case _ guard intMod(n, 2) == 0
1530 algorithm
1531 1 exp := evalBinaryPowMatrix2(matrix, intDiv(n, 2));
1532 1 then
1533 evalBinaryMatrixProduct(exp, exp);
1534
1535 // A^n = A * A^(n-1)
1536 else
1537 algorithm
1538 1 exp := evalBinaryPowMatrix2(matrix, n - 1);
1539 1 then
1540 evalBinaryMatrixProduct(matrix, exp);
1541
1542 end match;
1543 end evalBinaryPowMatrix2;
1544
1545 function evalUnaryOp
1546 input Expression exp1;
1547 input Operator op;
1548 output Expression exp;
1549 algorithm
1550 exp := match op.op
1551 case Op.UMINUS guard(Expression.isZero(exp1)) then exp1;
1552 17867 case Op.UMINUS then Expression.mapSplitExpressions(exp1, evalUnaryMinus);
1553 else
1554 algorithm
1555 ✗ Error.addInternalError(getInstanceName() + ": unimplemented case for " +
1556 Expression.toString(Expression.UNARY(op, exp1)), sourceInfo());
1557 ✗ then
1558 fail();
1559 end match;
1560 end evalUnaryOp;
1561
1562 function evalUnaryMinus
1563 input Expression exp1;
1564 output Expression exp;
1565 algorithm
1566 exp := match exp1
1567 ✗ case Expression.INTEGER() then Expression.INTEGER(-exp1.value);
1568 18013 case Expression.REAL() then Expression.REAL(-exp1.value);
1569
1570 case Expression.ARRAY()
1571 algorithm
1572 73 exp1.elements := Array.map(exp1.elements, evalUnaryMinus);
1573 then
1574 exp1;
1575
1576 else
1577 algorithm
1578 6 exp := Expression.UNARY(Operator.makeUMinus(Type.UNKNOWN()), exp1);
1579 6 printFailedEvalError(getInstanceName(), exp, sourceInfo());
1580 6 then
1581 fail();
1582 end match;
1583 end evalUnaryMinus;
1584
1585 function evalLogicBinaryOp
1586 input Expression exp1;
1587 input Operator op;
1588 input Expression exp2;
1589 input EvalTarget target = noTarget;
1590 output Expression exp;
1591 algorithm
1592 5913 exp := Expression.mapSplitExpressions(Expression.LBINARY(exp1, op, exp2),
1593 function evalLogicBinaryExp(target = target));
1594 end evalLogicBinaryOp;
1595
1596 function evalLogicBinaryExp
1597 input Expression binaryExp;
1598 input EvalTarget target;
1599 output Expression result;
1600 protected
1601 Expression e1, e2;
1602 Operator op;
1603 algorithm
1604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5915 times.
5915 Expression.LBINARY(exp1 = e1, operator = op, exp2 = e2) := binaryExp;
1605 5915 result := evalLogicBinaryOp_dispatch(e1, op, e2, target);
1606 end evalLogicBinaryExp;
1607
1608 function evalLogicBinaryOp_dispatch
1609 input Expression exp1;
1610 input Operator op;
1611 input Expression exp2;
1612 input EvalTarget target;
1613 output Expression exp;
1614 algorithm
1615 exp := match op.op
1616 5278 case Op.AND then evalLogicBinaryAnd(evalExp(exp1, target), exp2, target);
1617 637 case Op.OR then evalLogicBinaryOr(evalExp(exp1, target), exp2, target);
1618 else
1619 algorithm
1620 ✗ Error.addInternalError(getInstanceName() + ": unimplemented case for " +
1621 Expression.toString(Expression.LBINARY(exp1, op, exp2)), sourceInfo());
1622 ✗ then
1623 fail();
1624 end match;
1625 end evalLogicBinaryOp_dispatch;
1626
1627 function evalLogicBinaryAnd
1628 input Expression exp1;
1629 input Expression exp2;
1630 input EvalTarget target;
1631 output Expression exp;
1632 algorithm
1633 exp := matchcontinue exp1
1634 local
1635 array<Expression> arr;
1636
1637 case Expression.BOOLEAN()
1638
2/2
✓ Branch 0 taken 4599 times.
✓ Branch 1 taken 679 times.
5278 then if exp1.value then evalExp(exp2, target) else exp1;
1639
1640 case Expression.ARRAY()
1641 algorithm
1642 ✗ Expression.ARRAY(elements = arr) := evalExp(exp2, target);
1643 ✗ arr := Array.threadMap(exp1.elements, arr, function evalLogicBinaryAnd(target = target));
1644 ✗ then
1645 Expression.makeArray(Type.setArrayElementType(exp1.ty, Type.BOOLEAN()), arr, literal = true);
1646
1647 else
1648 algorithm
1649 ✗ exp := Expression.LBINARY(exp1, Operator.makeAnd(Type.UNKNOWN()), exp2);
1650 ✗ printFailedEvalError(getInstanceName(), exp, sourceInfo());
1651 ✗ then
1652 fail();
1653 end matchcontinue;
1654 end evalLogicBinaryAnd;
1655
1656 function evalLogicBinaryOr
1657 input Expression exp1;
1658 input Expression exp2;
1659 input EvalTarget target;
1660 output Expression exp;
1661 algorithm
1662 exp := match exp1
1663 local
1664 array<Expression> arr;
1665
1666 case Expression.BOOLEAN()
1667
2/2
✓ Branch 0 taken 416 times.
✓ Branch 1 taken 221 times.
637 then if exp1.value then exp1 else evalExp(exp2, target);
1668
1669 case Expression.ARRAY()
1670 algorithm
1671 ✗ Expression.ARRAY(elements = arr) := evalExp(exp2, target);
1672 ✗ arr := Array.threadMap(exp1.elements, arr, function evalLogicBinaryOr(target = target));
1673 ✗ then
1674 Expression.makeArray(Type.setArrayElementType(exp1.ty, Type.BOOLEAN()), arr, literal = true);
1675
1676 else
1677 algorithm
1678 ✗ exp := Expression.LBINARY(exp1, Operator.makeOr(Type.UNKNOWN()), exp2);
1679 ✗ printFailedEvalError(getInstanceName(), exp, sourceInfo());
1680 ✗ then
1681 fail();
1682 end match;
1683 end evalLogicBinaryOr;
1684
1685 function evalLogicUnaryOp
1686 input Expression exp1;
1687 input Operator op;
1688 output Expression exp;
1689 algorithm
1690 exp := match op.op
1691 3685 case Op.NOT then Expression.mapSplitExpressions(exp1, evalLogicUnaryNot);
1692 else
1693 algorithm
1694 ✗ Error.addInternalError(getInstanceName() + ": unimplemented case for " +
1695 Expression.toString(Expression.LUNARY(op, exp1)), sourceInfo());
1696 ✗ then
1697 fail();
1698 end match;
1699 end evalLogicUnaryOp;
1700
1701 function evalLogicUnaryNot
1702 input Expression exp1;
1703 output Expression exp;
1704 algorithm
1705 exp := match exp1
1706
2/2
✓ Branch 0 taken 992 times.
✓ Branch 1 taken 2693 times.
4677 case Expression.BOOLEAN() then Expression.BOOLEAN(not exp1.value);
1707 ✗ case Expression.ARRAY() then Expression.mapArrayElements(exp1, evalLogicUnaryNot);
1708
1709 else
1710 algorithm
1711 ✗ exp := Expression.LUNARY(Operator.makeNot(Type.UNKNOWN()), exp1);
1712 ✗ printFailedEvalError(getInstanceName(), exp, sourceInfo());
1713 ✗ then
1714 fail();
1715 end match;
1716 end evalLogicUnaryNot;
1717
1718 function evalRelationOp
1719 input Expression exp1;
1720 input Operator op;
1721 input Expression exp2;
1722 output Expression exp;
1723 algorithm
1724 31154 exp := Expression.mapSplitExpressions(Expression.RELATION(exp1, op, exp2, -1), evalRelationExp);
1725 end evalRelationOp;
1726
1727 function evalRelationExp
1728 input Expression relationExp;
1729 output Expression result;
1730 protected
1731 Expression e1, e2;
1732 Operator op;
1733 algorithm
1734
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31158 times.
31158 Expression.RELATION(exp1 = e1, operator = op, exp2 = e2) := relationExp;
1735 31158 result := evalRelationOp_dispatch(e1, op, e2);
1736 end evalRelationExp;
1737
1738 function evalRelationOp_dispatch
1739 input Expression exp1;
1740 input Operator op;
1741 input Expression exp2;
1742 output Expression exp;
1743 protected
1744 Boolean res;
1745 algorithm
1746 res := match op.op
1747 1257 case Op.LESS then evalRelationLess(exp1, exp2);
1748 631 case Op.LESSEQ then evalRelationLessEq(exp1, exp2);
1749 13765 case Op.GREATER then evalRelationGreater(exp1, exp2);
1750 1237 case Op.GREATEREQ then evalRelationGreaterEq(exp1, exp2);
1751 10769 case Op.EQUAL then evalRelationEqual(exp1, exp2);
1752 3499 case Op.NEQUAL then evalRelationNotEqual(exp1, exp2);
1753 else
1754 algorithm
1755 ✗ Error.addInternalError(getInstanceName() + ": unimplemented case for " +
1756 Expression.toString(Expression.RELATION(exp1, op, exp2, -1)), sourceInfo());
1757 ✗ then
1758 fail();
1759 end match;
1760
1761
2/2
✓ Branch 0 taken 19135 times.
✓ Branch 1 taken 11961 times.
50231 exp := Expression.BOOLEAN(res);
1762 end evalRelationOp_dispatch;
1763
1764 function evalRelationLess
1765 input Expression exp1;
1766 input Expression exp2;
1767 output Boolean res;
1768 algorithm
1769 res := match (exp1, exp2)
1770 case (Expression.INTEGER(), Expression.INTEGER())
1771 215 then exp1.value < exp2.value;
1772 case (Expression.REAL(), Expression.REAL())
1773 1029 then exp1.value < exp2.value;
1774 case (Expression.BOOLEAN(), Expression.BOOLEAN())
1775
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 then exp1.value < exp2.value;
1776 case (Expression.STRING(), Expression.STRING())
1777 1 then stringCompare(exp1.value, exp2.value) < 0;
1778 case (Expression.STRING(), Expression.FILENAME())
1779 ✗ then stringCompare(exp1.value, exp2.filename) < 0;
1780 case (Expression.FILENAME(), Expression.STRING())
1781 ✗ then stringCompare(exp1.filename, exp2.value) < 0;
1782 case (Expression.FILENAME(), Expression.FILENAME())
1783 ✗ then stringCompare(exp1.filename, exp2.filename) < 0;
1784 case (Expression.ENUM_LITERAL(), Expression.ENUM_LITERAL())
1785 11 then exp1.index < exp2.index;
1786
1787 else
1788 algorithm
1789 ✗ printFailedEvalError(getInstanceName(),
1790 Expression.RELATION(exp1, Operator.makeLess(Type.UNKNOWN()), exp2, -1), sourceInfo());
1791 ✗ then
1792 fail();
1793 end match;
1794 end evalRelationLess;
1795
1796 function evalRelationLessEq
1797 input Expression exp1;
1798 input Expression exp2;
1799 output Boolean res;
1800 algorithm
1801 res := match (exp1, exp2)
1802 case (Expression.INTEGER(), Expression.INTEGER())
1803 233 then exp1.value <= exp2.value;
1804 case (Expression.REAL(), Expression.REAL())
1805 395 then exp1.value <= exp2.value;
1806 case (Expression.BOOLEAN(), Expression.BOOLEAN())
1807
2/4
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
1 then exp1.value <= exp2.value;
1808 case (Expression.STRING(), Expression.STRING())
1809 1 then stringCompare(exp1.value, exp2.value) <= 0;
1810 case (Expression.STRING(), Expression.FILENAME())
1811 ✗ then stringCompare(exp1.value, exp2.filename) <= 0;
1812 case (Expression.FILENAME(), Expression.STRING())
1813 ✗ then stringCompare(exp1.filename, exp2.value) <= 0;
1814 case (Expression.FILENAME(), Expression.FILENAME())
1815 ✗ then stringCompare(exp1.filename, exp2.filename) <= 0;
1816 case (Expression.ENUM_LITERAL(), Expression.ENUM_LITERAL())
1817 1 then exp1.index <= exp2.index;
1818
1819 else
1820 algorithm
1821 ✗ printFailedEvalError(getInstanceName(),
1822 Expression.RELATION(exp1, Operator.makeLessEq(Type.UNKNOWN()), exp2, -1), sourceInfo());
1823 ✗ then
1824 fail();
1825 end match;
1826 end evalRelationLessEq;
1827
1828 function evalRelationGreater
1829 input Expression exp1;
1830 input Expression exp2;
1831 output Boolean res;
1832 algorithm
1833 res := match (exp1, exp2)
1834 case (Expression.INTEGER(), Expression.INTEGER())
1835 2036 then exp1.value > exp2.value;
1836 case (Expression.REAL(), Expression.REAL())
1837 11724 then exp1.value > exp2.value;
1838 case (Expression.BOOLEAN(), Expression.BOOLEAN())
1839
2/4
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
1 then exp1.value > exp2.value;
1840 case (Expression.STRING(), Expression.STRING())
1841 1 then stringCompare(exp1.value, exp2.value) > 0;
1842 case (Expression.STRING(), Expression.FILENAME())
1843 ✗ then stringCompare(exp1.value, exp2.filename) > 0;
1844 case (Expression.FILENAME(), Expression.STRING())
1845 ✗ then stringCompare(exp1.filename, exp2.value) > 0;
1846 case (Expression.FILENAME(), Expression.FILENAME())
1847 ✗ then stringCompare(exp1.filename, exp2.filename) > 0;
1848 case (Expression.ENUM_LITERAL(), Expression.ENUM_LITERAL())
1849 1 then exp1.index > exp2.index;
1850
1851 else
1852 algorithm
1853 2 printFailedEvalError(getInstanceName(),
1854 Expression.RELATION(exp1, Operator.makeGreater(Type.UNKNOWN()), exp2, -1), sourceInfo());
1855 2 then
1856 fail();
1857 end match;
1858 end evalRelationGreater;
1859
1860 function evalRelationGreaterEq
1861 input Expression exp1;
1862 input Expression exp2;
1863 output Boolean res;
1864 algorithm
1865 res := match (exp1, exp2)
1866 case (Expression.INTEGER(), Expression.INTEGER())
1867 22 then exp1.value >= exp2.value;
1868 case (Expression.REAL(), Expression.REAL())
1869 1122 then exp1.value >= exp2.value;
1870 case (Expression.BOOLEAN(), Expression.BOOLEAN())
1871
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1 then exp1.value >= exp2.value;
1872 case (Expression.STRING(), Expression.STRING())
1873 1 then stringCompare(exp1.value, exp2.value) >= 0;
1874 case (Expression.STRING(), Expression.FILENAME())
1875 ✗ then stringCompare(exp1.value, exp2.filename) >= 0;
1876 case (Expression.FILENAME(), Expression.STRING())
1877 ✗ then stringCompare(exp1.filename, exp2.value) >= 0;
1878 case (Expression.FILENAME(), Expression.FILENAME())
1879 ✗ then stringCompare(exp1.filename, exp2.filename) >= 0;
1880 case (Expression.ENUM_LITERAL(), Expression.ENUM_LITERAL())
1881 91 then exp1.index >= exp2.index;
1882
1883 else
1884 algorithm
1885 ✗ printFailedEvalError(getInstanceName(),
1886 Expression.RELATION(exp1, Operator.makeGreaterEq(Type.UNKNOWN()), exp2, -1), sourceInfo());
1887 ✗ then
1888 fail();
1889 end match;
1890 end evalRelationGreaterEq;
1891
1892 function evalRelationEqual
1893 input Expression exp1;
1894 input Expression exp2;
1895 output Boolean res;
1896 algorithm
1897 res := match (exp1, exp2)
1898 case (Expression.INTEGER(), Expression.INTEGER())
1899 6794 then exp1.value == exp2.value;
1900 case (Expression.REAL(), Expression.REAL())
1901 263 then exp1.value == exp2.value;
1902 case (Expression.BOOLEAN(), Expression.BOOLEAN())
1903 21 then exp1.value == exp2.value;
1904 case (Expression.STRING(), Expression.STRING())
1905 194 then stringCompare(exp1.value, exp2.value) == 0;
1906 case (Expression.STRING(), Expression.FILENAME())
1907 ✗ then stringCompare(exp1.value, exp2.filename) == 0;
1908 case (Expression.FILENAME(), Expression.STRING())
1909 ✗ then stringCompare(exp1.filename, exp2.value) == 0;
1910 case (Expression.FILENAME(), Expression.FILENAME())
1911 ✗ then stringCompare(exp1.filename, exp2.filename) == 0;
1912 case (Expression.ENUM_LITERAL(), Expression.ENUM_LITERAL())
1913 3437 then exp1.index == exp2.index;
1914
1915 else
1916 algorithm
1917 60 printFailedEvalError(getInstanceName(),
1918 Expression.RELATION(exp1, Operator.makeEqual(Type.UNKNOWN()), exp2, -1), sourceInfo());
1919 60 then
1920 fail();
1921 end match;
1922 end evalRelationEqual;
1923
1924 function evalRelationNotEqual
1925 input Expression exp1;
1926 input Expression exp2;
1927 output Boolean res;
1928 algorithm
1929 res := match (exp1, exp2)
1930 case (Expression.INTEGER(), Expression.INTEGER())
1931 652 then exp1.value <> exp2.value;
1932 case (Expression.REAL(), Expression.REAL())
1933 2598 then exp1.value <> exp2.value;
1934 case (Expression.BOOLEAN(), Expression.BOOLEAN())
1935 1 then exp1.value <> exp2.value;
1936 case (Expression.STRING(), Expression.STRING())
1937 43 then stringCompare(exp1.value, exp2.value) <> 0;
1938 case (Expression.STRING(), Expression.FILENAME())
1939 ✗ then stringCompare(exp1.value, exp2.filename) <> 0;
1940 case (Expression.FILENAME(), Expression.STRING())
1941 ✗ then stringCompare(exp1.filename, exp2.value) <> 0;
1942 case (Expression.FILENAME(), Expression.FILENAME())
1943 ✗ then stringCompare(exp1.filename, exp2.filename) <> 0;
1944 case (Expression.ENUM_LITERAL(), Expression.ENUM_LITERAL())
1945 205 then exp1.index <> exp2.index;
1946
1947 else
1948 algorithm
1949 ✗ printFailedEvalError(getInstanceName(),
1950 Expression.RELATION(exp1, Operator.makeNotEqual(Type.UNKNOWN()), exp2, -1), sourceInfo());
1951 ✗ then
1952 fail();
1953 end match;
1954 end evalRelationNotEqual;
1955
1956 function evalIfExp
1957 input Expression ifExp;
1958 input EvalTarget target;
1959 output Expression result;
1960 protected
1961 Type ty;
1962 Expression cond, btrue, bfalse;
1963 algorithm
1964
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10757 times.
10757 Expression.IF(ty, cond, btrue, bfalse) := ifExp;
1965 10757 result := Expression.IF(ty, evalExp(cond, target), btrue, bfalse);
1966 10757 result := Expression.mapSplitExpressions(result, function evalIfExp2(target = target));
1967 end evalIfExp;
1968
1969 function evalIfExp2
1970 input Expression ifExp;
1971 input EvalTarget target;
1972 output Expression result;
1973 protected
1974 Type ty;
1975 Expression cond, tb, fb;
1976 algorithm
1977
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10757 times.
10757 Expression.IF(ty = ty, condition = cond, trueBranch = tb, falseBranch = fb) := ifExp;
1978
1979 result := match cond
1980 case Expression.BOOLEAN()
1981 algorithm
1982
3/4
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 10751 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
10757 if Type.isConditionalArray(ty) and not Type.isMatchedBranch(cond.value, ty) then
1983 ✗ (tb, fb) := Util.swap(cond.value, fb, tb);
1984 ✗ Error.addSourceMessage(Error.ARRAY_DIMENSION_MISMATCH,
1985 {Expression.toString(tb), Type.toString(Expression.typeOf(tb)),
1986 Dimension.toStringList(Type.arrayDims(Expression.typeOf(fb)), brackets = false)},
1987 EvalTarget.getInfo(target));
1988 ✗ fail();
1989 end if;
1990
2/2
✓ Branch 0 taken 7873 times.
✓ Branch 1 taken 2884 times.
10757 then
1991 evalExp(if cond.value then tb else fb, target);
1992
1993 else
1994 algorithm
1995 ✗ Error.addInternalError(getInstanceName() + ": unimplemented case for " +
1996 Expression.toString(ifExp), sourceInfo());
1997 ✗ then
1998 fail();
1999 end match;
2000 end evalIfExp2;
2001
2002 function evalCast
2003 input Expression castExp;
2004 input Type castTy;
2005 output Expression exp;
2006 algorithm
2007 19887 exp := Expression.typeCast(castExp, castTy);
2008
2009 // Expression.typeCast will just create a CAST if it can't typecast
2010 // the expression, so make sure we actually got something else back.
2011 () := match exp
2012 case Expression.CAST()
2013 algorithm
2014 67 exp := Expression.CAST(castTy, castExp);
2015 67 printFailedEvalError(getInstanceName(), exp, sourceInfo());
2016 67 then
2017 fail();
2018 else ();
2019 end match;
2020 end evalCast;
2021
2022 function evalCall
2023 input Call call;
2024 input EvalTarget target;
2025 output Expression exp;
2026 protected
2027 Call c = call;
2028 algorithm
2029 exp := match c
2030 local
2031
2032 case Call.TYPED_CALL()
2033 algorithm
2034
4/4
✓ Branch 0 taken 237691 times.
✓ Branch 1 taken 125832 times.
✓ Branch 2 taken 237691 times.
✓ Branch 3 taken 125832 times.
489355 c.arguments := list(evalExp(arg, target) for arg in c.arguments);
2035
2/2
✓ Branch 1 taken 102856 times.
✓ Branch 2 taken 22976 times.
125832 then
2036 if Function.isBuiltin(c.fn) then
2037 Expression.mapSplitExpressions(Expression.CALL(c), function evalBuiltinCallExp(target = target))
2038 else
2039 Expression.mapSplitExpressions(Expression.CALL(c), function evalNormalCallExp(target = target));
2040
2041 case Call.TYPED_ARRAY_CONSTRUCTOR()
2042 algorithm
2043 531 c.exp := evalExpPartial(c.exp);
2044 531 c.iters := Call.mapIteratorsExpShallow(c.iters, evalExpPartialDefault);
2045 531 then
2046 Expression.mapSplitExpressions(Expression.CALL(c), evalArrayConstructor);
2047
2048 case Call.TYPED_REDUCTION()
2049 algorithm
2050 55 c.exp := evalExpPartial(c.exp);
2051 55 c.iters := Call.mapIteratorsExpShallow(c.iters, evalExpPartialDefault);
2052 55 then
2053 Expression.mapSplitExpressions(Expression.CALL(c), evalReduction);
2054
2055 else
2056 algorithm
2057 ✗ Error.addInternalError(getInstanceName() + " got untyped call", sourceInfo());
2058 ✗ then
2059 fail();
2060
2061 end match;
2062 end evalCall;
2063
2064 function evalBuiltinCallExp
2065 input Expression callExp;
2066 input EvalTarget target;
2067 output Expression result;
2068 protected
2069 Function fn;
2070 list<Expression> args;
2071 algorithm
2072
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 102856 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 102856 times.
102856 Expression.CALL(call = Call.TYPED_CALL(fn = fn, arguments = args)) := callExp;
2073 102856 result := evalBuiltinCall(fn, args, target);
2074 end evalBuiltinCallExp;
2075
2076 function evalBuiltinCall
2077 input Function fn;
2078 input list<Expression> args;
2079 input EvalTarget target;
2080 output Expression result;
2081 protected
2082 Absyn.Path fn_path = Function.nameConsiderBuiltin(fn);
2083 algorithm
2084 result := match AbsynUtil.pathFirstIdent(fn_path)
2085 209 case "abs" then evalBuiltinAbs(listHead(args));
2086 5 case "acos" then evalBuiltinAcos(listHead(args), target);
2087 ✗ case "array" then evalBuiltinArray(args);
2088 219 case "asin" then evalBuiltinAsin(listHead(args), target);
2089 1 case "atan2" then evalBuiltinAtan2(args);
2090 2 case "atan" then evalBuiltinAtan(listHead(args));
2091 4123 case "cat" then evalBuiltinCat(listHead(args), listRest(args), target);
2092 16 case "ceil" then evalBuiltinCeil(listHead(args));
2093 1 case "cosh" then evalBuiltinCosh(listHead(args));
2094 789 case "cos" then evalBuiltinCos(listHead(args));
2095 1 case "der" then evalBuiltinDer(listHead(args));
2096 // TODO: Fix typing of diagonal so the argument isn't boxed.
2097 2 case "diagonal" then evalBuiltinDiagonal(Expression.unbox(listHead(args)));
2098 24 case "div" then evalBuiltinDiv(args, target);
2099 6105 case "exp" then evalBuiltinExp(listHead(args));
2100 76878 case "fill" then evalBuiltinFill(args);
2101 9 case "floor" then evalBuiltinFloor(listHead(args));
2102 1108 case "identity" then evalBuiltinIdentity(listHead(args));
2103 128 case "integer" then evalBuiltinInteger(listHead(args));
2104 14 case "Integer" then evalBuiltinIntegerEnum(listHead(args));
2105 6 case "log10" then evalBuiltinLog10(listHead(args), target);
2106 3341 case "log" then evalBuiltinLog(listHead(args), target);
2107 ✗ case "matrix" then evalBuiltinMatrix(listHead(args));
2108 218 case "max" then evalBuiltinMax(args, fn);
2109 529 case "min" then evalBuiltinMin(args, fn);
2110 476 case "mod" then evalBuiltinMod(args, target);
2111 4 case "noEvent" then listHead(args); // No events during ceval, just return the argument.
2112 3 case "nthRoot" then evalBuiltinNthRoot(args, target);
2113 ✗ case "ones" then evalBuiltinOnes(args);
2114 ✗ case "pre" then listHead(args);
2115 5 case "product" then evalBuiltinProduct(listHead(args));
2116 161 case "promote" then evalBuiltinPromote(listGet(args,1),listGet(args,2));
2117 ✗ case "rem" then evalBuiltinRem(args, target);
2118 ✗ case "scalar" then evalBuiltinScalar(listHead(args));
2119 2 case "sign" then evalBuiltinSign(listHead(args));
2120 1 case "sinh" then evalBuiltinSinh(listHead(args));
2121 827 case "sin" then evalBuiltinSin(listHead(args));
2122 ✗ case "skew" then evalBuiltinSkew(listHead(args));
2123 784 case "smooth" then listGet(args, 2);
2124 5855 case "sqrt" then evalBuiltinSqrt(listHead(args));
2125 844 case "String" then evalBuiltinString(args);
2126 95 case "sum" then evalBuiltinSum(listHead(args));
2127 ✗ case "symmetric" then evalBuiltinSymmetric(listHead(args));
2128 2 case "tanh" then evalBuiltinTanh(listHead(args));
2129 1 case "tan" then evalBuiltinTan(listHead(args));
2130 57 case "transpose" then evalBuiltinTranspose(listHead(args));
2131 8 case "vector" then evalBuiltinVector(listHead(args));
2132 ✗ case "zeros" then evalBuiltinZeros(args);
2133 1 case "OpenModelica_uriToFilename" then evalUriToFilename(fn, listHead(args), target);
2134 ✗ case "intBitAnd" then evalIntBitAnd(args);
2135 ✗ case "intBitOr" then evalIntBitOr(args);
2136 ✗ case "intBitXor" then evalIntBitXor(args);
2137 ✗ case "intBitLShift" then evalIntBitLShift(args);
2138 ✗ case "intBitRShift" then evalIntBitRShift(args);
2139 ✗ case "intMaxLit" then Expression.INTEGER(System.intMaxLit());
2140 ✗ case "inferredClock" then evalInferredClock(args);
2141 ✗ case "rationalClock" then evalRationalClock(args);
2142 ✗ case "realClock" then evalRealClock(args);
2143 ✗ case "booleanClock" then evalBooleanClock(args);
2144 ✗ case "solverClock" then evalSolverClock(args);
2145 ✗ case "$OMC$PositiveMax" then evalPositiveMax(listGet(args,1),listGet(args,2));
2146 ✗ case "$OMC$inStreamDiv" then listHead(args);
2147 else
2148 algorithm
2149 2 Error.addInternalError(getInstanceName() + ": unimplemented case for " +
2150 AbsynUtil.pathString(fn_path), sourceInfo());
2151 2 then
2152 fail();
2153 end match;
2154 end evalBuiltinCall;
2155
2156 function evalNormalCallExp
2157 input Expression callExp;
2158 input EvalTarget target;
2159 output Expression result;
2160 protected
2161 Function fn;
2162 list<Expression> args;
2163 algorithm
2164
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 22992 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 22992 times.
22992 Expression.CALL(call = Call.TYPED_CALL(fn = fn, arguments = args)) := callExp;
2165 22992 result := evalNormalCall(fn, args, target);
2166 end evalNormalCallExp;
2167
2168 function evalNormalCall
2169 input Function fn;
2170 input list<Expression> args;
2171 input EvalTarget target;
2172 output Expression result = EvalFunction.evaluate(fn, args, target);
2173 end evalNormalCall;
2174
2175 function evalBuiltinAbs
2176 input Expression arg;
2177 output Expression result;
2178 algorithm
2179 result := match arg
2180 1 case Expression.INTEGER() then Expression.INTEGER(abs(arg.value));
2181 208 case Expression.REAL() then Expression.REAL(abs(arg.value));
2182 ✗ else algorithm printWrongArgsError(getInstanceName(), {arg}, sourceInfo()); then fail();
2183 end match;
2184 end evalBuiltinAbs;
2185
2186 function evalBuiltinAcos
2187 input Expression arg;
2188 input EvalTarget target;
2189 output Expression result;
2190 protected
2191 Real x;
2192 algorithm
2193 result := match arg
2194 case Expression.REAL(value = x)
2195 algorithm
2196
3/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3 times.
5 if x < -1.0 or x > 1.0 then
2197
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
2 if EvalTarget.hasInfo(target) then
2198 2 Error.addSourceMessage(Error.ARGUMENT_OUT_OF_RANGE,
2199 {String(x), "acos", "-1 <= x <= 1"}, EvalTarget.getInfo(target));
2200 end if;
2201
2202 2 fail();
2203 end if;
2204
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 then
2205 Expression.REAL(acos(x));
2206
2207 ✗ else algorithm printWrongArgsError(getInstanceName(), {arg}, sourceInfo()); then fail();
2208 end match;
2209 end evalBuiltinAcos;
2210
2211 function evalBuiltinArray
2212 input list<Expression> args;
2213 output Expression result;
2214 protected
2215 Type ty;
2216 algorithm
2217 ✗ ty := Expression.typeOf(listHead(args));
2218 ✗ ty := Type.liftArrayLeft(ty, Dimension.fromInteger(listLength(args)));
2219 ✗ result := Expression.makeArray(ty, listArray(args), literal = true);
2220 end evalBuiltinArray;
2221
2222 function evalBuiltinAsin
2223 input Expression arg;
2224 input EvalTarget target;
2225 output Expression result;
2226 protected
2227 Real x;
2228 algorithm
2229 result := match arg
2230 case Expression.REAL(value = x)
2231 algorithm
2232
2/4
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 219 times.
219 if x < -1.0 or x > 1.0 then
2233 ✗ if EvalTarget.hasInfo(target) then
2234 ✗ Error.addSourceMessage(Error.ARGUMENT_OUT_OF_RANGE,
2235 {String(x), "asin", "-1 <= x <= 1"}, EvalTarget.getInfo(target));
2236 end if;
2237
2238 ✗ fail();
2239 end if;
2240
2/4
✓ Branch 0 taken 219 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 219 times.
219 then
2241 Expression.REAL(asin(x));
2242
2243 ✗ else algorithm printWrongArgsError(getInstanceName(), {arg}, sourceInfo()); then fail();
2244 end match;
2245 end evalBuiltinAsin;
2246
2247 function evalBuiltinAtan2
2248 input list<Expression> args;
2249 output Expression result;
2250 protected
2251 Real y, x;
2252 algorithm
2253 result := match args
2254 case {Expression.REAL(value = y), Expression.REAL(value = x)}
2255 1 then Expression.REAL(atan2(y, x));
2256
2257 ✗ else algorithm printWrongArgsError(getInstanceName(), args, sourceInfo()); then fail();
2258 end match;
2259 end evalBuiltinAtan2;
2260
2261 function evalBuiltinAtan
2262 input Expression arg;
2263 output Expression result;
2264 algorithm
2265 result := match arg
2266 2 case Expression.REAL() then Expression.REAL(atan(arg.value));
2267 ✗ else algorithm printWrongArgsError(getInstanceName(), {arg}, sourceInfo()); then fail();
2268 end match;
2269 end evalBuiltinAtan;
2270
2271 function evalBuiltinCat
2272 input Expression argN;
2273 input list<Expression> args;
2274 input EvalTarget target;
2275 output Expression result;
2276 protected
2277 Integer n, nd, sz;
2278 Type ty;
2279 list<Expression> es;
2280 list<Integer> dims;
2281 algorithm
2282
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9794 times.
9794 Expression.INTEGER(n) := argN;
2283 9794 ty := Expression.typeOf(listHead(args));
2284 9794 nd := Type.dimensionCount(ty);
2285
2286
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9794 times.
9794 if n > nd or n < 1 then
2287 ✗ if EvalTarget.hasInfo(target) then
2288 ✗ Error.addSourceMessage(Error.ARGUMENT_OUT_OF_RANGE, {String(n), "cat", "1 <= x <= " + String(nd)}, EvalTarget.getInfo(target));
2289 end if;
2290 ✗ fail();
2291 end if;
2292
2293
6/6
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 28762 times.
✓ Branch 3 taken 28773 times.
✓ Branch 4 taken 9794 times.
✓ Branch 5 taken 28762 times.
✓ Branch 6 taken 9794 times.
38567 es := list(e for e guard not Expression.isEmptyArray(e) in args);
2294 9794 sz := listLength(es);
2295
2296
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9794 times.
9794 if sz == 0 then
2297 ✗ result := listHead(args);
2298 elseif sz == 1 then
2299 7 result := listHead(es);
2300 else
2301 9787 (es,dims) := ExpressionBasics.evalCat(n, es, getArrayContents=Expression.arrayElementList, toString=Expression.toString);
2302
4/4
✓ Branch 0 taken 16455 times.
✓ Branch 1 taken 9787 times.
✓ Branch 2 taken 16455 times.
✓ Branch 3 taken 9787 times.
26242 result := Expression.arrayFromList(es, Expression.typeOf(listHead(es)), list(Dimension.fromInteger(d) for d in dims));
2303 end if;
2304 end evalBuiltinCat;
2305
2306 function evalBuiltinCeil
2307 input Expression arg;
2308 output Expression result;
2309 algorithm
2310 result := match arg
2311 16 case Expression.REAL() then Expression.REAL(ceil(arg.value));
2312 ✗ else algorithm printWrongArgsError(getInstanceName(), {arg}, sourceInfo()); then fail();
2313 end match;
2314 end evalBuiltinCeil;
2315
2316 function evalBuiltinCosh
2317 input Expression arg;
2318 output Expression result;
2319 algorithm
2320 result := match arg
2321 1 case Expression.REAL() then Expression.REAL(cosh(arg.value));
2322 ✗ else algorithm printWrongArgsError(getInstanceName(), {arg}, sourceInfo()); then fail();
2323 end match;
2324 end evalBuiltinCosh;
2325
2326 function evalBuiltinCos
2327 input Expression arg;
2328 output Expression result;
2329 algorithm
2330 result := match arg
2331 784 case Expression.REAL() then Expression.REAL(cos(arg.value));
2332 5 else algorithm printWrongArgsError(getInstanceName(), {arg}, sourceInfo()); then fail();
2333 end match;
2334 end evalBuiltinCos;
2335
2336 function evalBuiltinDer
2337 input Expression arg;
2338 output Expression result;
2339 algorithm
2340 1 result := Expression.fillType(Expression.typeOf(arg), Expression.REAL(0.0));
2341 end evalBuiltinDer;
2342
2343 function evalBuiltinDiagonal
2344 input Expression arg;
2345 output Expression result;
2346 protected
2347 Type elem_ty, row_ty;
2348 Expression zero, exp;
2349 Integer n, i = 1;
2350 Boolean e_lit, arg_lit = true;
2351 array<Expression> arr_zero, arr_row, arr_rows;
2352 algorithm
2353 result := match arg
2354 case Expression.ARRAY() guard arrayEmpty(arg.elements) then arg;
2355
2356 case Expression.ARRAY()
2357 algorithm
2358
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 n := arrayLength(arg.elements);
2359 3 elem_ty := Type.unliftArray(arg.ty);
2360 3 row_ty := Type.liftArrayLeft(elem_ty, Dimension.fromInteger(n));
2361 3 zero := Expression.makeZero(elem_ty);
2362 3 arr_zero := arrayCreate(n, zero);
2363 3 arr_rows := arrayCreateNoInit(n, zero);
2364
2365
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
11 for i in 1:n loop
2366 8 arr_row := arrayCopy(arr_zero);
2367 8 exp := arrayGetNoBoundsChecking(arg.elements, i);
2368 8 e_lit := Expression.isLiteral(exp);
2369 8 arg_lit := arg_lit and e_lit;
2370 arrayUpdateNoBoundsChecking(arr_row, i, exp);
2371 8 exp := Expression.makeArray(row_ty, arr_row, e_lit);
2372 arrayUpdateNoBoundsChecking(arr_rows, i, exp);
2373 end for;
2374 3 then
2375 Expression.makeArray(Type.liftArrayLeft(row_ty, Dimension.fromInteger(n)), arr_rows, arg_lit);
2376
2377 ✗ else algorithm printWrongArgsError(getInstanceName(), {arg}, sourceInfo()); then fail();
2378 end match;
2379 end evalBuiltinDiagonal;
2380
2381 function evalBuiltinDiv
2382 input list<Expression> args;
2383 input EvalTarget target;
2384 output Expression result;
2385 protected
2386 Real rx, ry;
2387 Integer ix, iy;
2388 algorithm
2389 result := match args
2390 case {Expression.INTEGER(ix), Expression.INTEGER(iy)}
2391 algorithm
2392
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if iy == 0 then
2393 ✗ if EvalTarget.hasInfo(target) then
2394 ✗ Error.addSourceMessage(Error.DIVISION_BY_ZERO,
2395 {String(ix), String(iy)}, EvalTarget.getInfo(target));
2396 end if;
2397
2398 ✗ fail();
2399 end if;
2400 19 then
2401 Expression.INTEGER(intDiv(ix, iy));
2402
2403 case {Expression.REAL(rx), Expression.REAL(ry)}
2404 algorithm
2405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if ry == 0.0 then
2406 ✗ if EvalTarget.hasInfo(target) then
2407 ✗ Error.addSourceMessage(Error.DIVISION_BY_ZERO,
2408 {String(rx), String(ry)}, EvalTarget.getInfo(target));
2409 end if;
2410
2411 ✗ fail();
2412 end if;
2413
2414 5 rx := rx / ry;
2415
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 4 times.
5 then
2416 Expression.REAL(if rx < 0.0 then ceil(rx) else floor(rx));
2417
2418 ✗ else algorithm printWrongArgsError(getInstanceName(), args, sourceInfo()); then fail();
2419 end match;
2420 end evalBuiltinDiv;
2421
2422 function evalBuiltinExp
2423 input Expression arg;
2424 output Expression result;
2425 algorithm
2426 result := match arg
2427 6105 case Expression.REAL() then Expression.REAL(exp(arg.value));
2428 ✗ else algorithm printWrongArgsError(getInstanceName(), {arg}, sourceInfo()); then fail();
2429 end match;
2430 end evalBuiltinExp;
2431
2432 public
2433 function evalBuiltinFill
2434 input list<Expression> args;
2435 output Expression result;
2436 protected
2437 Expression fill_exp;
2438 list<Expression> dims;
2439 algorithm
2440 try
2441
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 76878 times.
76878 fill_exp :: dims := args;
2442 76878 result := Expression.fillArgs(fill_exp, dims);
2443 else
2444 ✗ printWrongArgsError(getInstanceName(), args, sourceInfo());
2445 ✗ fail();
2446 end try;
2447 end evalBuiltinFill;
2448
2449 protected
2450 function evalBuiltinFloor
2451 input Expression arg;
2452 output Expression result;
2453 algorithm
2454 result := match arg
2455 9 case Expression.REAL() then Expression.REAL(floor(arg.value));
2456 ✗ else algorithm printWrongArgsError(getInstanceName(), {arg}, sourceInfo()); then fail();
2457 end match;
2458 end evalBuiltinFloor;
2459
2460 function evalBuiltinIdentity
2461 input Expression arg;
2462 output Expression result;
2463 algorithm
2464 result := match arg
2465 case Expression.INTEGER()
2466 1108 then Expression.makeIdentityMatrix(arg.value, Type.INTEGER());
2467
2468 ✗ else algorithm printWrongArgsError(getInstanceName(), {arg}, sourceInfo()); then fail();
2469 end match;
2470 end evalBuiltinIdentity;
2471
2472 function evalBuiltinInteger
2473 input Expression arg;
2474 output Expression result;
2475 algorithm
2476 result := match arg
2477 case Expression.INTEGER() then arg;
2478 128 case Expression.REAL() then Expression.INTEGER(realInt(arg.value));
2479 ✗ else algorithm printWrongArgsError(getInstanceName(), {arg}, sourceInfo()); then fail();
2480 end match;
2481 end evalBuiltinInteger;
2482
2483 function evalBuiltinIntegerEnum
2484 input Expression arg;
2485 output Expression result;
2486 algorithm
2487 result := match arg
2488 14 case Expression.ENUM_LITERAL() then Expression.INTEGER(arg.index);
2489 ✗ else algorithm printWrongArgsError(getInstanceName(), {arg}, sourceInfo()); then fail();
2490 end match;
2491 end evalBuiltinIntegerEnum;
2492
2493 function evalBuiltinLog10
2494 input Expression arg;
2495 input EvalTarget target;
2496 output Expression result;
2497 protected
2498 Real x;
2499 algorithm
2500 result := match arg
2501 case Expression.REAL(value = x)
2502 algorithm
2503
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
6 if x <= 0.0 then
2504
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
2 if EvalTarget.hasInfo(target) then
2505 2 Error.addSourceMessage(Error.ARGUMENT_OUT_OF_RANGE,
2506 {String(x), "log10", "x > 0"}, EvalTarget.getInfo(target));
2507 end if;
2508
2509 2 fail();
2510 end if;
2511
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 then
2512 Expression.REAL(log10(x));
2513
2514 ✗ else algorithm printWrongArgsError(getInstanceName(), {arg}, sourceInfo()); then fail();
2515 end match;
2516 end evalBuiltinLog10;
2517
2518 function evalBuiltinLog
2519 input Expression arg;
2520 input EvalTarget target;
2521 output Expression result;
2522 protected
2523 Real x;
2524 algorithm
2525 result := match arg
2526 case Expression.REAL(value = x)
2527 algorithm
2528
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3341 times.
3341 if x <= 0.0 then
2529 ✗ if EvalTarget.hasInfo(target) then
2530 ✗ Error.addSourceMessage(Error.ARGUMENT_OUT_OF_RANGE,
2531 {String(x), "log", "x > 0"}, EvalTarget.getInfo(target));
2532 end if;
2533
2534 ✗ fail();
2535 end if;
2536
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3341 times.
3341 then
2537 Expression.REAL(log(x));
2538
2539 ✗ else algorithm printWrongArgsError(getInstanceName(), {arg}, sourceInfo()); then fail();
2540 end match;
2541 end evalBuiltinLog;
2542
2543 function evalBuiltinMatrix
2544 input Expression arg;
2545 output Expression result;
2546 algorithm
2547 result := match arg
2548 local
2549 Integer dim_count;
2550 Dimension dim1, dim2;
2551 Type ty;
2552 array<Expression> arr;
2553
2554 case Expression.ARRAY(ty = ty)
2555 algorithm
2556 ✗ dim_count := Type.dimensionCount(ty);
2557
2558 ✗ if dim_count < 2 then
2559 ✗ result := Expression.promote(arg, ty, 2);
2560 elseif dim_count == 2 then
2561 result := arg;
2562 else
2563 ✗ dim1 :: dim2 :: _ := Type.arrayDims(ty);
2564 ✗ ty := Type.liftArrayLeft(Type.arrayElementType(ty), dim2);
2565 ✗ arr := Array.map(arg.elements, function evalBuiltinMatrix2(ty = ty));
2566 ✗ ty := Type.liftArrayLeft(ty, dim1);
2567 ✗ result := Expression.makeArray(ty, arr);
2568 end if;
2569 then
2570 result;
2571
2572 else
2573 algorithm
2574 ✗ ty := Expression.typeOf(arg);
2575
2576 ✗ if Type.isScalar(ty) then
2577 ✗ result := Expression.promote(arg, ty, 2);
2578 else
2579 ✗ printWrongArgsError(getInstanceName(), {arg}, sourceInfo());
2580 ✗ fail();
2581 end if;
2582 then
2583 result;
2584
2585 end match;
2586 end evalBuiltinMatrix;
2587
2588 function evalBuiltinMatrix2
2589 input Expression arg;
2590 input Type ty;
2591 output Expression result;
2592 algorithm
2593 result := match arg
2594 case Expression.ARRAY()
2595 ✗ then Expression.makeArray(ty,
2596 Array.map(arg.elements, Expression.toScalar),
2597 arg.literal);
2598
2599 ✗ else algorithm printWrongArgsError(getInstanceName(), {arg}, sourceInfo()); then fail();
2600 end match;
2601 end evalBuiltinMatrix2;
2602
2603 function evalBuiltinMax
2604 input list<Expression> args;
2605 input Function fn;
2606 output Expression result;
2607 protected
2608 Expression e1, e2;
2609 Type ty;
2610 algorithm
2611 result := match args
2612 188 case {e1, e2} then evalBuiltinMax2(e1, e2);
2613
2614 case {e1}
2615 guard Expression.isArray(e1)
2616 algorithm
2617 26 ty := Expression.typeOf(e1);
2618 26 result := Expression.fold(e1, evalBuiltinMax2, Expression.EMPTY(ty));
2619
2620
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
26 if Expression.isEmpty(result) then
2621 ✗ result := Expression.makeMinValue(Type.arrayElementType(ty));
2622 end if;
2623 then
2624 result;
2625
2626 4 else algorithm printWrongArgsError(getInstanceName(), args, sourceInfo()); then fail();
2627 end match;
2628 end evalBuiltinMax;
2629
2630 public
2631 function evalBuiltinMax2
2632 input Expression exp1;
2633 input Expression exp2;
2634 output Expression result;
2635 algorithm
2636 result := match (exp1, exp2)
2637 case (Expression.INTEGER(), Expression.INTEGER())
2638
2/2
✓ Branch 0 taken 178 times.
✓ Branch 1 taken 7 times.
185 then if exp1.value < exp2.value then exp2 else exp1;
2639 case (Expression.REAL(), Expression.REAL())
2640
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 8 times.
60 then if exp1.value < exp2.value then exp2 else exp1;
2641 case (Expression.BOOLEAN(), Expression.BOOLEAN())
2642
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1 time.
4 then if exp1.value < exp2.value then exp2 else exp1;
2643 case (Expression.ENUM_LITERAL(), Expression.ENUM_LITERAL())
2644
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 2 times.
3 then if exp1.index < exp2.index then exp2 else exp1;
2645 case (Expression.ARRAY(), _) then exp2;
2646 case (_, Expression.EMPTY()) then exp1;
2647 ✗ else algorithm printWrongArgsError(getInstanceName(), {exp1, exp2}, sourceInfo()); then fail();
2648 end match;
2649 end evalBuiltinMax2;
2650
2651 protected
2652 function evalPositiveMax
2653 input Expression flow_exp;
2654 input Expression eps;
2655 output Expression result;
2656 algorithm
2657 ✗ result := if Expression.isNonPositive(flow_exp)
2658 then Expression.makeZero(Expression.typeOf(flow_exp))
2659 else evalBuiltinMax2(flow_exp, eps);
2660 end evalPositiveMax;
2661
2662 function evalBuiltinMin
2663 input list<Expression> args;
2664 input Function fn;
2665 output Expression result;
2666 protected
2667 Expression e1, e2;
2668 Type ty;
2669 algorithm
2670 result := match args
2671 517 case {e1, e2} then evalBuiltinMin2(e1, e2);
2672
2673 case {e1}
2674 guard Expression.isArray(e1)
2675 algorithm
2676 12 ty := Expression.typeOf(e1);
2677 12 result := Expression.fold(e1, evalBuiltinMin2, Expression.EMPTY(ty));
2678
2679
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
12 if Expression.isEmpty(result) then
2680 ✗ result := Expression.makeMaxValue(Type.arrayElementType(ty));
2681 end if;
2682 then
2683 result;
2684
2685 ✗ else algorithm printWrongArgsError(getInstanceName(), args, sourceInfo()); then fail();
2686 end match;
2687 end evalBuiltinMin;
2688
2689 public
2690 function evalBuiltinMin2
2691 input Expression exp1;
2692 input Expression exp2;
2693 output Expression result;
2694 algorithm
2695 result := match (exp1, exp2)
2696 case (Expression.INTEGER(), Expression.INTEGER())
2697
2/2
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 31 times.
42 then if exp1.value > exp2.value then exp2 else exp1;
2698 case (Expression.REAL(), Expression.REAL())
2699
2/2
✓ Branch 0 taken 490 times.
✓ Branch 1 taken 15 times.
505 then if exp1.value > exp2.value then exp2 else exp1;
2700 case (Expression.BOOLEAN(), Expression.BOOLEAN())
2701
3/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1 time.
2 then if exp1.value > exp2.value then exp2 else exp1;
2702 case (Expression.ENUM_LITERAL(), Expression.ENUM_LITERAL())
2703
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
3 then if exp1.index > exp2.index then exp2 else exp1;
2704 case (Expression.ARRAY(), _) then exp2;
2705 case (_, Expression.EMPTY()) then exp1;
2706 ✗ else algorithm printWrongArgsError(getInstanceName(), {exp1, exp2}, sourceInfo()); then fail();
2707 end match;
2708 end evalBuiltinMin2;
2709
2710 protected
2711 function evalBuiltinMod
2712 input list<Expression> args;
2713 input EvalTarget target;
2714 output Expression result;
2715 protected
2716 Expression x, y;
2717 algorithm
2718
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 476 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 476 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 476 times.
476 {x, y} := args;
2719
2720 result := match (x, y)
2721 case (Expression.INTEGER(), Expression.INTEGER())
2722 algorithm
2723
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 176 times.
176 if y.value == 0 then
2724 ✗ if EvalTarget.hasInfo(target) then
2725 ✗ Error.addSourceMessage(Error.MODULO_BY_ZERO,
2726 {String(x.value), String(y.value)}, EvalTarget.getInfo(target));
2727 end if;
2728
2729 ✗ fail();
2730 end if;
2731
1/2
✓ Branch 0 taken 176 times.
✗ Branch 1 not taken.
352 then
2732 Expression.INTEGER(mod(x.value, y.value));
2733
2734 case (Expression.REAL(), Expression.REAL())
2735 algorithm
2736
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 288 times.
288 if y.value == 0.0 then
2737 ✗ if EvalTarget.hasInfo(target) then
2738 ✗ Error.addSourceMessage(Error.MODULO_BY_ZERO,
2739 {String(x.value), String(y.value)}, EvalTarget.getInfo(target));
2740 end if;
2741
2742 ✗ fail();
2743 end if;
2744 288 then
2745 Expression.REAL(mod(x.value, y.value));
2746
2747 12 else algorithm printWrongArgsError(getInstanceName(), args, sourceInfo()); then fail();
2748 end match;
2749 end evalBuiltinMod;
2750
2751 function evalBuiltinNthRoot
2752 input list<Expression> args;
2753 input EvalTarget target;
2754 output Expression result;
2755 protected
2756 Real v;
2757 Integer n;
2758 algorithm
2759 result := match args
2760 case {Expression.REAL(v), Expression.INTEGER(n)}
2761 algorithm
2762 // n must be positive.
2763
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
3 if n <= 0 and EvalTarget.hasInfo(target) then
2764 ✗ Error.addSourceMessage(Error.NON_POSITIVE_NTH_ROOT,
2765 {String(v), String(n)}, EvalTarget.getInfo(target));
2766 ✗ fail();
2767 end if;
2768
2769 // If n is even, then v must be non-negative.
2770
3/6
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
3 if intMod(n, 2) == 0 and v < 0 and EvalTarget.hasInfo(target) then
2771 ✗ Error.addSourceMessage(Error.NEGATIVE_NTH_ROOT,
2772 {String(v), String(n)}, EvalTarget.getInfo(target));
2773 ✗ fail();
2774 end if;
2775
11/52
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 time.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 time.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
✓ Branch 26 taken 1 time.
✗ Branch 27 not taken.
✗ Branch 28 not taken.
✓ Branch 29 taken 1 time.
✗ Branch 30 not taken.
✓ Branch 31 taken 2 times.
✗ Branch 32 not taken.
✗ Branch 33 not taken.
✗ Branch 34 not taken.
✗ Branch 35 not taken.
✗ Branch 36 not taken.
✗ Branch 37 not taken.
✗ Branch 38 not taken.
✗ Branch 39 not taken.
✗ Branch 40 not taken.
✗ Branch 41 not taken.
✗ Branch 42 not taken.
✗ Branch 43 not taken.
✗ Branch 44 not taken.
✗ Branch 45 not taken.
✗ Branch 46 not taken.
✗ Branch 47 not taken.
✓ Branch 48 taken 2 times.
✗ Branch 49 not taken.
✗ Branch 50 not taken.
✓ Branch 51 taken 2 times.
3 then
2776 Expression.REAL(if v < 0.0 and intMod(n, 2) <> 0 then -((-v) ^ (1/n)) else v ^ (1/n));
2777
2778 else
2779 algorithm
2780 ✗ printWrongArgsError(getInstanceName(), args, sourceInfo());
2781 ✗ then
2782 fail();
2783
2784 end match;
2785 end evalBuiltinNthRoot;
2786
2787 function evalBuiltinOnes
2788 input list<Expression> args;
2789 output Expression result;
2790 algorithm
2791 ✗ result := evalBuiltinFill(Expression.INTEGER(1) :: args);
2792 end evalBuiltinOnes;
2793
2794 function evalBuiltinProduct
2795 input Expression arg;
2796 output Expression result;
2797 algorithm
2798 result := match arg
2799 case _
2800 guard Expression.isArray(arg)
2801 then match Type.arrayElementType(Expression.typeOf(arg))
2802 4 case Type.INTEGER() then Expression.INTEGER(Expression.fold(arg, evalBuiltinProductInt, 1));
2803 1 case Type.REAL() then Expression.REAL(Expression.fold(arg, evalBuiltinProductReal, 1.0));
2804 ✗ else algorithm printWrongArgsError(getInstanceName(), {arg}, sourceInfo()); then fail();
2805 end match;
2806
2807 ✗ else algorithm printWrongArgsError(getInstanceName(), {arg}, sourceInfo()); then fail();
2808 end match;
2809 end evalBuiltinProduct;
2810
2811 function evalBuiltinProductInt
2812 input Expression exp;
2813 input output Integer result;
2814 algorithm
2815 result := match exp
2816 15 case Expression.INTEGER() then result * exp.value;
2817 case Expression.ARRAY() then result;
2818 else fail();
2819 end match;
2820 end evalBuiltinProductInt;
2821
2822 function evalBuiltinProductReal
2823 input Expression exp;
2824 input output Real result;
2825 algorithm
2826 result := match exp
2827 3 case Expression.REAL() then result * exp.value;
2828 case Expression.ARRAY() then result;
2829 else fail();
2830 end match;
2831 end evalBuiltinProductReal;
2832
2833 function evalBuiltinPromote
2834 input Expression arg, argN;
2835 output Expression result;
2836 protected
2837 Integer n;
2838 algorithm
2839
1/2
✓ Branch 1 taken 161 times.
✗ Branch 2 not taken.
161 if Expression.isInteger(argN) then
2840
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 161 times.
161 Expression.INTEGER(n) := argN;
2841 161 result := Expression.promote(arg, Expression.typeOf(arg), n);
2842 else
2843 ✗ printWrongArgsError(getInstanceName(), {arg, argN}, sourceInfo());
2844 ✗ fail();
2845 end if;
2846 end evalBuiltinPromote;
2847
2848 function evalBuiltinRem
2849 input list<Expression> args;
2850 input EvalTarget target;
2851 output Expression result;
2852 protected
2853 Expression x, y;
2854 algorithm
2855 ✗ {x, y} := args;
2856
2857 result := match (x, y)
2858 case (Expression.INTEGER(), Expression.INTEGER())
2859 algorithm
2860 ✗ if y.value == 0 then
2861 ✗ if EvalTarget.hasInfo(target) then
2862 ✗ Error.addSourceMessage(Error.REM_ARG_ZERO, {String(x.value),
2863 String(y.value)}, EvalTarget.getInfo(target));
2864 end if;
2865
2866 ✗ fail();
2867 end if;
2868 ✗ then
2869 Expression.INTEGER(x.value - (div(x.value, y.value) * y.value));
2870
2871 case (Expression.REAL(), Expression.REAL())
2872 algorithm
2873 ✗ if y.value == 0.0 then
2874 ✗ if EvalTarget.hasInfo(target) then
2875 ✗ Error.addSourceMessage(Error.REM_ARG_ZERO,
2876 {String(x.value), String(y.value)}, EvalTarget.getInfo(target));
2877 end if;
2878
2879 ✗ fail();
2880 end if;
2881 ✗ then
2882 Expression.REAL(x.value - (div(x.value, y.value) * y.value));
2883
2884 ✗ else algorithm printWrongArgsError(getInstanceName(), args, sourceInfo()); then fail();
2885 end match;
2886 end evalBuiltinRem;
2887
2888 function evalBuiltinScalar
2889 input Expression arg;
2890 output Expression result = arg;
2891 algorithm
2892 ✗ while Expression.isArray(result) loop
2893 ✗ result := Expression.arrayScalarElement(result);
2894 end while;
2895 end evalBuiltinScalar;
2896
2897 function evalBuiltinSign
2898 input Expression arg;
2899 output Expression result;
2900 algorithm
2901 result := match arg
2902 case Expression.REAL()
2903
3/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
2 then Expression.INTEGER(if arg.value > 0 then 1 else if arg.value < 0 then -1 else 0);
2904 case Expression.INTEGER()
2905 ✗ then Expression.INTEGER(if arg.value > 0 then 1 else if arg.value < 0 then -1 else 0);
2906 ✗ else algorithm printWrongArgsError(getInstanceName(), {arg}, sourceInfo()); then fail();
2907 end match;
2908 end evalBuiltinSign;
2909
2910 function evalBuiltinSinh
2911 input Expression arg;
2912 output Expression result;
2913 algorithm
2914 result := match arg
2915 1 case Expression.REAL() then Expression.REAL(sinh(arg.value));
2916 ✗ else algorithm printWrongArgsError(getInstanceName(), {arg}, sourceInfo()); then fail();
2917 end match;
2918 end evalBuiltinSinh;
2919
2920 function evalBuiltinSin
2921 input Expression arg;
2922 output Expression result;
2923 algorithm
2924 result := match arg
2925 827 case Expression.REAL() then Expression.REAL(sin(arg.value));
2926 ✗ else algorithm printWrongArgsError(getInstanceName(), {arg}, sourceInfo()); then fail();
2927 end match;
2928 end evalBuiltinSin;
2929
2930 function evalBuiltinSkew
2931 input Expression arg;
2932 output Expression result;
2933 protected
2934 Expression x1, x2, x3, y1, y2, y3;
2935 Type ty;
2936 Expression zero;
2937 Boolean literal;
2938 algorithm
2939 result := match arg
2940 case Expression.ARRAY(ty = ty, literal = literal)
2941 algorithm
2942 ✗ x1 := arrayGet(arg.elements, 1);
2943 x2 := arrayGet(arg.elements, 2);
2944 x3 := arrayGet(arg.elements, 3);
2945 ✗ zero := Expression.makeZero(Type.arrayElementType(ty));
2946 ✗ y1 := Expression.makeArray(ty, listArray({zero, Expression.negate(x3), x2}), literal);
2947 ✗ y2 := Expression.makeArray(ty, listArray({x3, zero, Expression.negate(x1)}), literal);
2948 ✗ y3 := Expression.makeArray(ty, listArray({Expression.negate(x2), x1, zero}), literal);
2949 ✗ ty := Type.liftArrayLeft(ty, Dimension.fromInteger(3));
2950 ✗ then
2951 Expression.makeArray(ty, listArray({y1, y2, y3}), literal);
2952
2953 ✗ else algorithm printWrongArgsError(getInstanceName(), {arg}, sourceInfo()); then fail();
2954 end match;
2955 end evalBuiltinSkew;
2956
2957 function evalBuiltinSqrt
2958 input Expression arg;
2959 output Expression result;
2960 algorithm
2961 result := match arg
2962
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5855 times.
5855 case Expression.REAL() guard arg.value >= 0.0 then Expression.REAL(sqrt(arg.value));
2963 // Left for the generated code's assertion rather than folded to NaN.
2964 ✗ case Expression.REAL() then fail();
2965 ✗ else algorithm printWrongArgsError(getInstanceName(), {arg}, sourceInfo()); then fail();
2966 end match;
2967 end evalBuiltinSqrt;
2968
2969 function evalBuiltinString
2970 input list<Expression> args;
2971 output Expression result;
2972 algorithm
2973 result := match args
2974 local
2975 Expression arg;
2976 Integer min_len, str_len, significant_digits;
2977 Boolean left_justified;
2978 String str, format;
2979 Real r;
2980
2981 case {arg, Expression.INTEGER(min_len), Expression.BOOLEAN(left_justified)}
2982 algorithm
2983 str := match arg
2984 19 case Expression.INTEGER() then intString(arg.value);
2985
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
2 case Expression.BOOLEAN() then boolString(arg.value);
2986 2 case Expression.ENUM_LITERAL() then arg.name;
2987 ✗ else algorithm printWrongArgsError(getInstanceName(), args, sourceInfo()); then fail();
2988 end match;
2989
2990 23 str_len := stringLength(str);
2991
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 21 times.
23 if str_len < min_len then
2992
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
2 if left_justified then
2993 1 str := str + stringAppendList(List.fill(" ", min_len - str_len));
2994 else
2995 1 str := stringAppendList(List.fill(" ", min_len - str_len)) + str;
2996 end if;
2997 end if;
2998 23 then
2999 Expression.STRING(str);
3000
3001 case {Expression.REAL(r), Expression.INTEGER(significant_digits),
3002 Expression.INTEGER(min_len), Expression.BOOLEAN(left_justified)}
3003 algorithm
3004
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 820 times.
820 format := "%" + (if left_justified then "-" else "") +
3005 intString(min_len) + "." + intString(significant_digits) + "g";
3006 820 str := System.sprintff(format, r);
3007 820 then
3008 Expression.STRING(str);
3009
3010 case {Expression.REAL(r), Expression.STRING(format)}
3011 algorithm
3012 1 str := System.sprintff("%" + format, r);
3013 1 then
3014 Expression.STRING(str);
3015
3016 end match;
3017 end evalBuiltinString;
3018
3019 function evalBuiltinSum
3020 input Expression arg;
3021 output Expression result;
3022 algorithm
3023 result := match arg
3024 case _ guard Expression.isArray(arg)
3025 then match Type.arrayElementType(Expression.typeOf(arg))
3026 7 case Type.INTEGER() then Expression.INTEGER(Expression.fold(arg, evalBuiltinSumInt, 0));
3027 88 case Type.REAL() then Expression.REAL(Expression.fold(arg, evalBuiltinSumReal, 0.0));
3028 ✗ else algorithm printWrongArgsError(getInstanceName(), {arg}, sourceInfo()); then fail();
3029 end match;
3030
3031 ✗ else algorithm printWrongArgsError(getInstanceName(), {arg}, sourceInfo()); then fail();
3032 end match;
3033 end evalBuiltinSum;
3034
3035 function evalBuiltinSumInt
3036 input Expression exp;
3037 input output Integer result;
3038 algorithm
3039 result := match exp
3040 33 case Expression.INTEGER() then result + exp.value;
3041 case Expression.ARRAY() then result;
3042 else fail();
3043 end match;
3044 end evalBuiltinSumInt;
3045
3046 function evalBuiltinSumReal
3047 input Expression exp;
3048 input output Real result;
3049 algorithm
3050 result := match exp
3051 311 case Expression.REAL() then result + exp.value;
3052 case Expression.ARRAY() then result;
3053 else fail();
3054 end match;
3055 end evalBuiltinSumReal;
3056
3057 function evalBuiltinSymmetric
3058 input Expression arg;
3059 output Expression result;
3060 protected
3061 array<array<Expression>> mat;
3062 Integer n;
3063 Type ty, row_ty;
3064 array<Expression> arr, accum;
3065 algorithm
3066 ✗ ty := Expression.typeOf(arg);
3067
3068 ✗ if Expression.isArray(arg) and Type.isSquareMatrix(ty) then
3069 ✗ mat := Array.map(Expression.arrayElements(arg), Expression.arrayElements);
3070 n := arrayLength(mat);
3071 ✗ row_ty := Type.unliftArray(Expression.typeOf(arg));
3072 ✗ accum := arrayCreateNoInit(n, arg);
3073
3074 ✗ for i in 1:n loop
3075 ✗ arr := arrayCreateNoInit(n, arg);
3076
3077 ✗ for j in 1:n loop
3078 ✗ arrayUpdateNoBoundsChecking(arr, j,
3079 if i > j then arrayGet(mat[j], i) else arrayGet(mat[i], j));
3080 end for;
3081
3082 ✗ arrayUpdateNoBoundsChecking(accum, i,
3083 Expression.makeArray(row_ty, arr, literal = true));
3084 end for;
3085
3086 ✗ result := Expression.makeArray(ty, accum, literal = true);
3087 else
3088 ✗ printWrongArgsError(getInstanceName(), {arg}, sourceInfo());
3089 ✗ fail();
3090 end if;
3091 end evalBuiltinSymmetric;
3092
3093 function evalBuiltinTanh
3094 input Expression arg;
3095 output Expression result;
3096 algorithm
3097 result := match arg
3098 2 case Expression.REAL() then Expression.REAL(tanh(arg.value));
3099 ✗ else algorithm printWrongArgsError(getInstanceName(), {arg}, sourceInfo()); then fail();
3100 end match;
3101 end evalBuiltinTanh;
3102
3103 function evalBuiltinTan
3104 input Expression arg;
3105 output Expression result;
3106 algorithm
3107 result := match arg
3108 1 case Expression.REAL() then Expression.REAL(tan(arg.value));
3109 ✗ else algorithm printWrongArgsError(getInstanceName(), {arg}, sourceInfo()); then fail();
3110 end match;
3111 end evalBuiltinTan;
3112
3113 function evalBuiltinTranspose
3114 input Expression arg;
3115 output Expression result;
3116 protected
3117 Type ty;
3118 algorithm
3119 57 ty := Expression.typeOf(arg);
3120
3121
2/4
✓ Branch 1 taken 57 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 57 times.
✗ Branch 5 not taken.
57 if Expression.isArray(arg) and Type.dimensionCount(ty) >= 2 then
3122 57 result := Expression.transposeArray(arg);
3123 else
3124 ✗ printWrongArgsError(getInstanceName(), {arg}, sourceInfo());
3125 ✗ fail();
3126 end if;
3127 end evalBuiltinTranspose;
3128
3129 function evalBuiltinVector
3130 input Expression arg;
3131 output Expression result;
3132 protected
3133 list<Expression> expl;
3134 algorithm
3135 8 expl := Expression.arrayScalarElements(arg);
3136 8 result := Expression.makeExpArray(listArray(expl),
3137 Type.arrayElementType(Expression.typeOf(arg)), isLiteral = true);
3138 end evalBuiltinVector;
3139
3140 function evalBuiltinZeros
3141 input list<Expression> args;
3142 output Expression result;
3143 algorithm
3144 ✗ result := evalBuiltinFill(Expression.INTEGER(0) :: args);
3145 end evalBuiltinZeros;
3146
3147 function evalUriToFilename
3148 input Function fn;
3149 input Expression arg;
3150 input EvalTarget target;
3151 output Expression result;
3152 algorithm
3153 result := match arg
3154 case Expression.STRING()
3155 1 then Expression.FILENAME(OpenModelica.Scripting.uriToFilename(arg.value));
3156
3157 case Expression.FILENAME()
3158 ✗ then Expression.FILENAME(OpenModelica.Scripting.uriToFilename(arg.filename));
3159
3160 ✗ else algorithm printWrongArgsError(getInstanceName(), {arg}, sourceInfo()); then fail();
3161 end match;
3162 end evalUriToFilename;
3163
3164 function evalIntBitAnd
3165 input list<Expression> args;
3166 output Expression result;
3167 protected
3168 Integer i1, i2;
3169 algorithm
3170 result := match args
3171 case {Expression.INTEGER(value = i1), Expression.INTEGER(value = i2)}
3172 ✗ then Expression.INTEGER(intBitAnd(i1, i2));
3173
3174 ✗ else algorithm printWrongArgsError(getInstanceName(), args, sourceInfo()); then fail();
3175 end match;
3176 end evalIntBitAnd;
3177
3178 function evalIntBitOr
3179 input list<Expression> args;
3180 output Expression result;
3181 protected
3182 Integer i1, i2;
3183 algorithm
3184 result := match args
3185 case {Expression.INTEGER(value = i1), Expression.INTEGER(value = i2)}
3186 ✗ then Expression.INTEGER(intBitOr(i1, i2));
3187
3188 ✗ else algorithm printWrongArgsError(getInstanceName(), args, sourceInfo()); then fail();
3189 end match;
3190 end evalIntBitOr;
3191
3192 function evalIntBitXor
3193 input list<Expression> args;
3194 output Expression result;
3195 protected
3196 Integer i1, i2;
3197 algorithm
3198 result := match args
3199 case {Expression.INTEGER(value = i1), Expression.INTEGER(value = i2)}
3200 ✗ then Expression.INTEGER(intBitXor(i1, i2));
3201
3202 ✗ else algorithm printWrongArgsError(getInstanceName(), args, sourceInfo()); then fail();
3203 end match;
3204 end evalIntBitXor;
3205
3206 function evalIntBitLShift
3207 input list<Expression> args;
3208 output Expression result;
3209 protected
3210 Integer i1, i2;
3211 algorithm
3212 result := match args
3213 case {Expression.INTEGER(value = i1), Expression.INTEGER(value = i2)}
3214 ✗ then Expression.INTEGER(intBitLShift(i1, i2));
3215
3216 ✗ else algorithm printWrongArgsError(getInstanceName(), args, sourceInfo()); then fail();
3217 end match;
3218 end evalIntBitLShift;
3219
3220 function evalIntBitRShift
3221 input list<Expression> args;
3222 output Expression result;
3223 protected
3224 Integer i1, i2;
3225 algorithm
3226 result := match args
3227 case {Expression.INTEGER(value = i1), Expression.INTEGER(value = i2)}
3228 ✗ then Expression.INTEGER(intBitRShift(i1, i2));
3229
3230 ✗ else algorithm printWrongArgsError(getInstanceName(), args, sourceInfo()); then fail();
3231 end match;
3232 end evalIntBitRShift;
3233
3234 function evalInferredClock
3235 input list<Expression> args;
3236 output Expression result;
3237 algorithm
3238 result := match args
3239 case {}
3240 ✗ then Expression.CLKCONST(Expression.ClockKind.INFERRED_CLOCK(System.tmpTickIndex(Global.inferredClock_index)));
3241
3242 ✗ else algorithm printWrongArgsError(getInstanceName(), args, sourceInfo()); then fail();
3243 end match;
3244 end evalInferredClock;
3245
3246 function evalRationalClock
3247 input list<Expression> args;
3248 output Expression result;
3249 algorithm
3250 result := match args
3251 local
3252 Expression interval, resolution;
3253
3254 case {interval as Expression.INTEGER(), resolution as Expression.INTEGER()}
3255 ✗ then Expression.CLKCONST(Expression.ClockKind.RATIONAL_CLOCK(interval, resolution));
3256
3257 ✗ else algorithm printWrongArgsError(getInstanceName(), args, sourceInfo()); then fail();
3258 end match;
3259 end evalRationalClock;
3260
3261 function evalRealClock
3262 input list<Expression> args;
3263 output Expression result;
3264 algorithm
3265 result := match args
3266 local
3267 Expression interval;
3268
3269 case {interval as Expression.REAL()}
3270 ✗ then Expression.CLKCONST(Expression.ClockKind.REAL_CLOCK(interval));
3271
3272 ✗ else algorithm printWrongArgsError(getInstanceName(), args, sourceInfo()); then fail();
3273 end match;
3274 end evalRealClock;
3275
3276 function evalBooleanClock
3277 input list<Expression> args;
3278 output Expression result;
3279 algorithm
3280 result := match args
3281 local
3282 Expression condition, interval;
3283
3284 case {condition as Expression.BOOLEAN(), interval as Expression.REAL()}
3285 ✗ then Expression.CLKCONST(Expression.ClockKind.EVENT_CLOCK(condition, interval));
3286
3287 ✗ else algorithm printWrongArgsError(getInstanceName(), args, sourceInfo()); then fail();
3288 end match;
3289 end evalBooleanClock;
3290
3291 function evalSolverClock
3292 input list<Expression> args;
3293 output Expression result;
3294 algorithm
3295 result := match args
3296 local
3297 Expression c, solver;
3298
3299 case {c as Expression.CLKCONST(), solver as Expression.STRING()}
3300 ✗ then Expression.CLKCONST(Expression.ClockKind.SOLVER_CLOCK(c, solver));
3301
3302 ✗ else algorithm printWrongArgsError(getInstanceName(), args, sourceInfo()); then fail();
3303 end match;
3304 end evalSolverClock;
3305
3306 public function evalGetInstanceName
3307 input InstNode scope;
3308 output Expression result;
3309 algorithm
3310 // getInstanceName is normally evaluated by the flattening, but we might get
3311 // here when getInstanceName is used in e.g. a package. In that case use the
3312 // scope that was saved during the typing.
3313 7 result := Expression.STRING(AbsynUtil.pathString(InstNode.rootPath(scope)));
3314 end evalGetInstanceName;
3315
3316 protected function evalArrayConstructor
3317 input Expression callExp;
3318 output Expression result;
3319 protected
3320 Expression exp;
3321 list<tuple<InstNode, Expression>> iters;
3322 list<Mutable<Expression>> iter_exps;
3323 list<Expression> ranges;
3324 algorithm
3325
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 531 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 531 times.
531 Expression.CALL(call = Call.TYPED_ARRAY_CONSTRUCTOR(exp = exp, iters = iters)) := callExp;
3326 531 (exp, ranges, iter_exps) := Expression.createIterationRanges(exp, iters);
3327 531 result := evalArrayConstructor2(exp, ranges, iter_exps);
3328 end evalArrayConstructor;
3329
3330 function evalArrayConstructor2
3331 input Expression exp;
3332 input list<Expression> ranges;
3333 input list<Mutable<Expression>> iterators;
3334 output Expression result;
3335 protected
3336 Expression range;
3337 list<Expression> ranges_rest, expl = {};
3338 array<Expression> arr;
3339 Mutable<Expression> iter;
3340 list<Mutable<Expression>> iters_rest;
3341 ExpressionIterator range_iter;
3342 Expression value;
3343 Type ty;
3344 algorithm
3345
2/2
✓ Branch 0 taken 1787 times.
✓ Branch 1 taken 531 times.
2318 if listEmpty(ranges) then
3346 1787 result := evalExp(exp);
3347 else
3348 531 range :: ranges_rest := ranges;
3349 531 range := evalExp(range);
3350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 531 times.
531 iter :: iters_rest := iterators;
3351 531 range_iter := ExpressionIterator.fromExp(range);
3352
3353
2/2
✓ Branch 1 taken 1787 times.
✓ Branch 2 taken 531 times.
2318 while ExpressionIterator.hasNext(range_iter) loop
3354 1787 (range_iter, value) := ExpressionIterator.next(range_iter);
3355 1787 Mutable.update(iter, value);
3356 1787 expl := evalArrayConstructor2(exp, ranges_rest, iters_rest) :: expl;
3357 end while;
3358
3359 531 arr := listArray(listReverseInPlace(expl));
3360
3361
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 529 times.
531 ty := if arrayEmpty(arr) then
3362 Type.liftArrayLeftList(Expression.typeOf(exp), List.mapFlat(ranges_rest, Expression.dimensions)) else
3363 Expression.typeOf(listHead(expl));
3364
3365 531 ty := Type.liftArrayLeft(ty, Dimension.fromInteger(arrayLength(arr)));
3366 531 result := Expression.makeArray(ty, arr, literal = true);
3367 end if;
3368 end evalArrayConstructor2;
3369
3370 partial function ReductionFn
3371 input Expression exp1;
3372 input Expression exp2;
3373 output Expression result;
3374 end ReductionFn;
3375
3376 function evalReduction
3377 input Expression callExp;
3378 output Expression result;
3379 protected
3380 Function fn;
3381 Expression exp, default_exp;
3382 list<tuple<InstNode, Expression>> iters;
3383 Type ty;
3384 ReductionFn red_fn;
3385
3386 function reductionFn
3387 input Expression exp1;
3388 input Expression exp2;
3389 input EvalTarget target;
3390 input ReductionFn fn;
3391 output Expression result = fn(exp1, evalExp(exp2, target));
3392 end reductionFn;
3393 algorithm
3394
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 55 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 55 times.
55 Expression.CALL(call = Call.TYPED_REDUCTION(fn = fn, exp = exp, iters = iters)) := callExp;
3395 55 ty := Expression.typeOf(exp);
3396
3397 (red_fn, default_exp) := match AbsynUtil.pathString(Function.name(fn))
3398 45 case "sum" then (evalBinaryAdd, Expression.makeZero(ty));
3399 2 case "product" then (evalBinaryMul, Expression.makeOne(ty));
3400 4 case "min" then (evalBuiltinMin2, Expression.makeMaxValue(ty));
3401 4 case "max" then (evalBuiltinMax2, Expression.makeMinValue(ty));
3402 else
3403 algorithm
3404 ✗ Error.terminate(getInstanceName() + " got unknown reduction function " +
3405 AbsynUtil.pathString(Function.name(fn)), sourceInfo());
3406 ✗ then
3407 fail();
3408 end match;
3409
3410 55 result := Expression.foldReduction(exp, iters, default_exp,
3411 function evalExp(target = noTarget), red_fn);
3412 end evalReduction;
3413
3414 function evalSize
3415 input Expression exp;
3416 input Option<Expression> optIndex;
3417 input EvalTarget target;
3418 output Expression outExp;
3419 protected
3420 Expression index_exp;
3421 Integer index;
3422 TypingError ty_err;
3423 Dimension dim;
3424 Type ty;
3425 SourceInfo info;
3426 array<Expression> arr;
3427 algorithm
3428 4162 info := EvalTarget.getInfo(target);
3429
3430
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4162 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 4155 times.
4162 if isSome(optIndex) then
3431 // Evaluate the index.
3432 4155 index_exp := evalExp(Util.getOption(optIndex), target);
3433 4155 index := Expression.toInteger(index_exp);
3434
3435 // Get the index'd dimension of the expression.
3436 4155 (dim, _, ty_err) := Typing.typeExpDim(exp, index, NFInstContext.CLASS, info);
3437 4155 Typing.checkSizeTypingError(ty_err, exp, index, info);
3438
3439 // Return the size expression for the found dimension.
3440 4155 outExp := Dimension.sizeExp(dim);
3441 4094 outExp := evalExp(outExp, target);
3442 else
3443 7 (outExp, ty) := Typing.typeExp(exp, NFInstContext.CLASS, info);
3444 7 arr := Array.mapList(Type.arrayDims(ty), Dimension.sizeExp);
3445 7 Array.mapNoCopy(arr, function evalExp(target = target));
3446 7 dim := Dimension.fromInteger(arrayLength(arr), Variability.PARAMETER);
3447 7 outExp := Expression.makeArray(Type.ARRAY(Type.INTEGER(), {dim}), arr);
3448 end if;
3449 end evalSize;
3450
3451 function evalSubscriptedExp
3452 input Expression exp;
3453 input list<Subscript> subscripts;
3454 input EvalTarget target;
3455 output Expression result;
3456 protected
3457 list<Subscript> subs;
3458 algorithm
3459 result := match exp
3460 case Expression.RANGE()
3461 6 then Expression.RANGE(exp.ty,
3462 evalExp(exp.start, target),
3463 Util.applyOption(exp.step, function evalExp(target = target)),
3464 evalExp(exp.stop, target));
3465
3466 96161 else evalExp(exp, target);
3467 end match;
3468
3469
4/4
✓ Branch 0 taken 96753 times.
✓ Branch 1 taken 96167 times.
✓ Branch 2 taken 96753 times.
✓ Branch 3 taken 96167 times.
192920 subs := list(Subscript.mapShallowExp(s, function evalExp(target = target)) for s in subscripts);
3470 96167 result := Expression.applySubscripts(subs, result);
3471 end evalSubscriptedExp;
3472
3473 function evalRecordElement
3474 input Expression exp;
3475 input EvalTarget target;
3476 output Expression result;
3477 protected
3478 Expression e;
3479 Integer index;
3480 algorithm
3481
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 Expression.RECORD_ELEMENT(recordExp = e, index = index) := exp;
3482 31 e := evalExp(e, target);
3483
3484 try
3485 22 result := Expression.mapSplitExpressions(e,
3486 function Expression.nthRecordElement(index = index));
3487 else
3488 6 Error.terminate(getInstanceName() + " could not evaluate " +
3489 Expression.toString(exp), sourceInfo());
3490 end try;
3491 end evalRecordElement;
3492
3493 function evalRecordElement2
3494 input Expression exp;
3495 input Integer index;
3496 output Expression result;
3497 algorithm
3498 result := match exp
3499 case Expression.RECORD()
3500 ✗ then listGet(exp.elements, index);
3501 end match;
3502 end evalRecordElement2;
3503
3504 protected
3505
3506 function printUnboundError
3507 input Component component;
3508 input EvalTarget target;
3509 input Expression exp;
3510 protected
3511 EvalTargetData extra;
3512 algorithm
3513
2/2
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 4 times.
24 if not EvalTarget.hasInfo(target) then
3514 20 return;
3515 end if;
3516
3517 () := match target.extra
3518 case SOME(extra as EvalTargetData.DIMENSION_DATA())
3519 algorithm
3520 6 Error.addSourceMessage(Error.STRUCTURAL_PARAMETER_OR_CONSTANT_WITH_NO_BINDING,
3521 {Expression.toString(extra.exp), InstNode.name(extra.component)}, target.info);
3522 2 then
3523 fail();
3524
3525 case _
3526 guard InstContext.inCondition(target.context)
3527 algorithm
3528 ✗ Error.addSourceMessage(Error.CONDITIONAL_EXP_WITHOUT_VALUE,
3529 {Expression.toString(exp)}, target.info);
3530 ✗ then
3531 fail();
3532
3533 else
3534 algorithm
3535 // check if we have a parameter with (fixed = true), annotation(Evaluate = true) and no binding
3536
3/4
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1 time.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 time.
2 if listMember(Component.variability(component), {Variability.STRUCTURAL_PARAMETER, Variability.PARAMETER}) and
3537 Util.getOptionOrDefault(Component.getEvaluateAnnotation(component), false)
3538 then
3539 // only add an error if fixed = true
3540 ✗ if Component.isFixed(component) then
3541 ✗ Error.addMultiSourceMessage(Error.UNBOUND_PARAMETER_EVALUATE_TRUE,
3542 {Expression.toString(exp) + "(fixed = true)"},
3543 {InstNode.info(ComponentRef.node(Expression.toCref(exp))), EvalTarget.getInfo(target)});
3544 end if;
3545 else // constant with no binding
3546 8 Error.addMultiSourceMessage(Error.UNBOUND_CONSTANT,
3547 {Expression.toString(exp)},
3548 {InstNode.info(ComponentRef.node(Expression.toCref(exp))), EvalTarget.getInfo(target)});
3549 2 fail();
3550 end if;
3551 then
3552 ();
3553
3554 end match;
3555 end printUnboundError;
3556
3557 function printWrongArgsError
3558 input String evalFunc;
3559 input list<Expression> args;
3560 input SourceInfo info;
3561 algorithm
3562 23 Error.addInternalError(evalFunc + " got invalid arguments " +
3563 List.toString(args, Expression.toString, List.Style.FLAT_BRACKETS), info);
3564 end printWrongArgsError;
3565
3566 annotation(__OpenModelica_Interface="nf_frontend");
3567 end NFCeval;
3568