Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 61.4% 1397 / 0 / 2276
Functions: -% 0 / 1 / 1
Branches: 58.6% 738 / 0 / 1259

OMCompiler/Compiler/FrontEnd/Expression.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 Expression
37 " file: Expression.mo
38 package: Expression
39 description: Expressions
40
41
42 This file contains the module `Expression\', which contains data types for
43 describing expressions, after they have been examined by the
44 static analyzer in the module `StaticExp\'. There are of course
45 great similarities with the expression types in the `Absyn\'
46 module, but there are also several important differences.
47
48 No overloading of operators occur, and subscripts have been
49 checked to see if they are slices. All expressions are also type
50 consistent, and all implicit type conversions in the AST are made
51 explicit here."
52
53 // public imports
54 public import Absyn;
55 public import AbsynUtil;
56 public import DAE;
57
58 protected
59 type ComponentRef = DAE.ComponentRef;
60 type Exp = DAE.Exp;
61 type Operator = DAE.Operator;
62 type Type = DAE.Type;
63 type Subscript = DAE.Subscript;
64 type Var = DAE.Var;
65
66 // protected imports
67 protected import Array;
68 protected import ClassInf;
69 protected import ComponentReference;
70 protected import ComponentReferenceBasics;
71 protected import Config;
72 protected import DAEUtil;
73 protected import Debug;
74 protected import DoubleEnded;
75 protected import Error;
76 protected import ExpressionDump;
77 protected import ExpressionBasics.printExpStr;
78 protected import ExpressionBasics;
79 protected import ExpressionSimplify;
80 protected import Dump;
81 protected import Flags;
82 protected import List;
83 protected import System; // stringReal
84 protected import Types;
85 protected import Util;
86
87 public constant Integer MAX_SUM_CHAIN = 32
88 "Longer sums are balanced. Shorter ones keep the chain, whose association
89 fixes the summation rounding and is read by the tearing and alias
90 heuristics. NFSimplifyExp.MAX_CHAIN_TERMS is the same limit for MULTARY.";
91
92 /***************************************************/
93 /* transform to other types */
94 /***************************************************/
95
96 public function intSubscript
97 "Converts an integer into an index subscript."
98 input Integer inInteger;
99 output DAE.Subscript outSubscript;
100 algorithm
101 8129 outSubscript := DAE.INDEX(DAE.ICONST(inInteger));
102 end intSubscript;
103
104 public function intSubscripts
105 "Converts a list of integers into index subscripts."
106 input list<Integer> inIntegers;
107 output list<DAE.Subscript> outSubscripts;
108 algorithm
109 ✗ outSubscripts := List.map(inIntegers, intSubscript);
110 end intSubscripts;
111
112 public function dimensionIsZero
113 input DAE.Dimension inDimension;
114 output Boolean outIsZero;
115 algorithm
116 3867 outIsZero := 0 == dimensionSize(inDimension);
117 end dimensionIsZero;
118
119 public function unelabExp
120 "Transform an DAE.Exp into Absyn.Expression.
121 Note: This function currently only works for
122 constants and component references."
123 input DAE.Exp inExp;
124 output Absyn.Exp outExp;
125 algorithm
126 outExp := matchcontinue inExp
127 local
128 Integer i;
129 Real r;
130 String s;
131 Boolean b;
132 Absyn.ComponentRef cr_1;
133 ComponentRef cr;
134 list<Absyn.Exp> expl_1,aexpl;
135 list<DAE.Exp> expl;
136 DAE.Exp e1,e2,e3;
137 Operator op;
138 Absyn.Exp ae1,ae2,ae3;
139 Absyn.Operator aop;
140 list<list<DAE.Exp>> mexpl2;
141 list<list<Absyn.Exp>> amexpl;
142 Absyn.ComponentRef acref;
143 Absyn.Path path;
144 Absyn.CodeNode code;
145 DAE.ReductionIterators riters;
146 Absyn.ForIterators aiters;
147 DAE.Type ty;
148 DAE.Dimensions dims;
149 Absyn.ReductionIterType iterType;
150
151 32086 case DAE.ICONST(integer = i) then Absyn.INTEGER(i);
152 case DAE.RCONST(real = r)
153 algorithm
154 69666 s := realString(r);
155 69666 then Absyn.REAL(s);
156 16209 case DAE.SCONST(string = s) then Absyn.STRING(s);
157
2/2
✓ Branch 0 taken 17731 times.
✓ Branch 1 taken 9019 times.
44481 case DAE.BCONST(bool = b) then Absyn.BOOL(b);
158 case DAE.ENUM_LITERAL(name = path)
159 algorithm
160 490 cr_1 := AbsynUtil.pathToCref(path);
161 490 then Absyn.CREF(cr_1);
162
163 case DAE.CREF(componentRef = cr)
164 algorithm
165 ✗ cr_1 := ComponentReference.unelabCref(cr);
166 ✗ then
167 Absyn.CREF(cr_1);
168
169 case DAE.BINARY(e1,op,e2) algorithm
170 ✗ aop := unelabOperator(op);
171 ✗ ae1 := unelabExp(e1);
172 ✗ ae2 := unelabExp(e2);
173 ✗ then Absyn.BINARY(ae1,aop,ae2);
174
175 case DAE.UNARY(op,e1) algorithm
176 ✗ aop := unelabOperator(op);
177 ✗ ae1 := unelabExp(e1);
178 ✗ then Absyn.UNARY(aop,ae1);
179
180 case DAE.LBINARY(e1,op,e2) algorithm
181 ✗ aop := unelabOperator(op);
182 ✗ ae1 := unelabExp(e1);
183 ✗ ae2 := unelabExp(e2);
184 ✗ then Absyn.LBINARY(ae1,aop,ae2);
185
186 case DAE.LUNARY(op,e1) algorithm
187 ✗ aop := unelabOperator(op);
188 ✗ ae1 := unelabExp(e1);
189 ✗ then Absyn.LUNARY(aop,ae1);
190
191 case DAE.RELATION(exp1=e1,operator=op,exp2=e2) algorithm
192 ✗ aop := unelabOperator(op);
193 ✗ ae1 := unelabExp(e1);
194 ✗ ae2 := unelabExp(e2);
195 ✗ then Absyn.RELATION(ae1,aop,ae2);
196
197 case DAE.IFEXP(e1,e2,e3) algorithm
198 ✗ ae1 := unelabExp(e1);
199 ✗ ae2 := unelabExp(e2);
200 ✗ ae3 := unelabExp(e3);
201 ✗ then Absyn.IFEXP(ae1,ae2,ae3,{});
202
203 case DAE.CALL(path,expl,_)
204 algorithm
205 ✗ aexpl := List.map(expl,unelabExp);
206 ✗ acref := AbsynUtil.pathToCref(path);
207 ✗ then Absyn.CALL(acref,Absyn.FUNCTIONARGS(aexpl,{}),{});
208
209 case DAE.RECORD(path = path,exps = expl)
210 algorithm
211 4 aexpl := List.map(expl,unelabExp);
212 3 acref := AbsynUtil.pathToCref(path);
213 3 then Absyn.CALL(acref,Absyn.FUNCTIONARGS(aexpl,{}),{});
214
215 case DAE.PARTEVALFUNCTION(path,expl,_,_)
216 algorithm
217 ✗ aexpl := List.map(expl,unelabExp);
218 ✗ acref := AbsynUtil.pathToCref(path);
219 ✗ then
220 Absyn.PARTEVALFUNCTION(acref,Absyn.FUNCTIONARGS(aexpl,{}));
221
222 case DAE.ARRAY(array = {}, ty = ty)
223 algorithm
224 36 (ty, dims) := TypesDump.flattenArrayType(ty);
225 36 ae1 := unleabZeroExpFromType(ty);
226 36 expl_1 := List.map(dims, unelabDimensionToFillExp);
227 36 then
228 Absyn.CALL(Absyn.CREF_IDENT("fill",{}),Absyn.FUNCTIONARGS(ae1::expl_1,{}),{});
229
230 case DAE.ARRAY(array = expl)
231 algorithm
232 5864 expl_1 := List.map(expl, unelabExp);
233 5864 then
234 Absyn.ARRAY(expl_1);
235
236 case DAE.MATRIX(matrix = mexpl2)
237 algorithm
238 994 amexpl := List.mapList(mexpl2,unelabExp);
239 994 then (Absyn.MATRIX(amexpl));
240
241 case DAE.RANGE(_,e1,SOME(e2),e3) algorithm
242 ✗ ae1 := unelabExp(e1);
243 ✗ ae2 := unelabExp(e2);
244 ✗ ae3 := unelabExp(e3);
245 ✗ then Absyn.RANGE(ae1,SOME(ae2),ae3);
246
247 case DAE.RANGE(_,e1,NONE(),e3) algorithm
248 ✗ ae1 := unelabExp(e1);
249 ✗ ae3 := unelabExp(e3);
250 ✗ then Absyn.RANGE(ae1,NONE(),ae3);
251
252 case DAE.TUPLE(expl)
253 algorithm
254 ✗ expl_1 := List.map(expl, unelabExp);
255 ✗ then
256 Absyn.TUPLE(expl_1);
257
258 case DAE.CAST(_,e1) algorithm
259 ✗ ae1 := unelabExp(e1);
260 then ae1;
261
262 // ASUB can not be unelabed since it has no representation in Absyn.
263 case DAE.ASUB(_,_) algorithm
264 ✗ print("Internal Error, can not unelab ASUB\n");
265 ✗ then fail();
266
267 // TSUB(expression) => expression
268 case DAE.TSUB(e1,_,_) algorithm
269 ✗ ae1 := unelabExp(e1);
270 then ae1;
271
272 case DAE.SIZE(e1,SOME(e2)) algorithm
273 ✗ ae1 := unelabExp(e1);
274 ✗ ae2 := unelabExp(e2);
275 ✗ then Absyn.CALL(Absyn.CREF_IDENT("size",{}),Absyn.FUNCTIONARGS({ae1,ae2},{}),{});
276
277 /* WHAT? exactly the same case as above???!!!
278 case(DAE.SIZE(e1,SOME(e2))) equation
279 ae1 = unelabExp(e1);
280 ae2 = unelabExp(e2);
281 then Absyn.CALL(Absyn.CREF_IDENT("size",{}),Absyn.FUNCTIONARGS({ae1,ae2},{}));
282 */
283
284 ✗ case DAE.CODE(code,_) then Absyn.CODE(code);
285
286 case DAE.REDUCTION(reductionInfo=DAE.REDUCTIONINFO(iterType=iterType,path=path),expr=e1,iterators=riters)
287 algorithm
288 //print("unelab of reduction not impl. yet");
289 ✗ acref := AbsynUtil.pathToCref(path);
290 ✗ ae1 := unelabExp(e1);
291 ✗ aiters := List.map(riters, unelabReductionIterator);
292 ✗ then Absyn.CALL(acref, Absyn.FOR_ITER_FARG(ae1, iterType, aiters),{});
293
294 else
295 algorithm
296
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 true := Flags.isSet(Flags.FAILTRACE);
297 ✗ print("Expression.unelabExp failed on: " + ExpressionBasics.printExpStr(inExp) + "\n");
298 ✗ then
299 fail();
300 end matchcontinue;
301 end unelabExp;
302
303 public function unelabDimension
304 "Transform an DAE.Dimension into Absyn.Subscript, if possible"
305 input DAE.Dimension inDim;
306 output Absyn.Subscript outDim;
307 algorithm
308 outDim := match inDim
309 local
310 Integer i;
311 Absyn.Path p;
312 Absyn.ComponentRef c;
313 DAE.Exp e;
314 Absyn.Exp ae;
315
316 2 case DAE.DIM_INTEGER(i) then Absyn.SUBSCRIPT(Absyn.INTEGER(i));
317
318 case DAE.DIM_BOOLEAN() then Absyn.SUBSCRIPT(Absyn.CREF(Absyn.CREF_IDENT("Boolean", {})));
319
320 case DAE.DIM_ENUM(enumTypeName = p)
321 algorithm
322 ✗ c := AbsynUtil.pathToCref(p);
323 ✗ then
324 Absyn.SUBSCRIPT(Absyn.CREF(c));
325
326 case DAE.DIM_EXP(e)
327 algorithm
328 ✗ ae := unelabExp(e);
329 ✗ then
330 Absyn.SUBSCRIPT(ae);
331
332 case DAE.DIM_UNKNOWN() then Absyn.NOSUB();
333
334 end match;
335 end unelabDimension;
336
337 protected function unleabZeroExpFromType
338 input DAE.Type ty;
339 output Absyn.Exp outExp;
340 algorithm
341 outExp := match ty
342 case DAE.T_BOOL() then Absyn.BOOL(false);
343 case DAE.T_STRING() then Absyn.STRING("");
344 case DAE.T_INTEGER() then Absyn.INTEGER(0);
345 case DAE.T_REAL() then Absyn.REAL("0.0");
346 case DAE.T_UNKNOWN() then Absyn.REAL("0.0"); /* Look at the crap unelabMod needs... */
347 end match;
348 end unleabZeroExpFromType;
349
350 protected function unelabDimensionToFillExp
351 "Transform an DAE.Dimension into Absyn.Exp, if possible"
352 input DAE.Dimension inDim;
353 output Absyn.Exp outExp;
354 algorithm
355 outExp := match inDim
356 local
357 Integer i;
358 DAE.Exp e;
359
360 36 case DAE.DIM_INTEGER(i) then Absyn.INTEGER(i);
361
362 ✗ case DAE.DIM_EXP(e) then unelabExp(e);
363
364 else Absyn.INTEGER(1); /* Probably bad, but only used with zero-length arrays */
365
366 end match;
367 end unelabDimensionToFillExp;
368
369 protected function unelabReductionIterator
370 input DAE.ReductionIterator riter;
371 output Absyn.ForIterator aiter;
372 algorithm
373 aiter := match riter
374 local
375 String id;
376 DAE.Exp exp;
377 Option<DAE.Exp> gexp;
378 Absyn.Exp aexp;
379 Option<Absyn.Exp> agexp;
380 case DAE.REDUCTIONITER(id=id,exp=exp,guardExp=gexp)
381 algorithm
382 ✗ aexp := unelabExp(exp);
383 ✗ agexp := Util.applyOption(gexp, unelabExp);
384 ✗ then Absyn.ITERATOR(id,agexp,SOME(aexp));
385 end match;
386 end unelabReductionIterator;
387
388 protected function unelabOperator "help function to unelabExpression."
389 input DAE.Operator op;
390 output Absyn.Operator aop;
391 algorithm
392 aop := match op
393 case DAE.ADD(_) then Absyn.ADD();
394 case DAE.SUB(_) then Absyn.SUB();
395 case DAE.MUL(_) then Absyn.MUL();
396 case DAE.DIV(_) then Absyn.DIV();
397 case DAE.POW(_) then Absyn.POW();
398 case DAE.UMINUS(_) then Absyn.UMINUS();
399 case DAE.UMINUS_ARR(_) then Absyn.UMINUS();
400 case DAE.ADD_ARR(_) then Absyn.ADD();
401 case DAE.SUB_ARR(_) then Absyn.SUB();
402 case DAE.MUL_ARR(_) then Absyn.MUL();
403 case DAE.DIV_ARR(_) then Absyn.DIV();
404 case DAE.MUL_ARRAY_SCALAR(_) then Absyn.MUL();
405 case DAE.ADD_ARRAY_SCALAR(_) then Absyn.ADD();
406 case DAE.SUB_SCALAR_ARRAY(_) then Absyn.SUB();
407 case DAE.MUL_SCALAR_PRODUCT(_) then Absyn.MUL();
408 case DAE.MUL_MATRIX_PRODUCT(_) then Absyn.MUL();
409 case DAE.DIV_SCALAR_ARRAY(_) then Absyn.DIV();
410 case DAE.DIV_ARRAY_SCALAR(_) then Absyn.DIV();
411 case DAE.POW_SCALAR_ARRAY(_) then Absyn.POW();
412 case DAE.POW_ARRAY_SCALAR(_) then Absyn.POW();
413 case DAE.POW_ARR(_) then Absyn.POW();
414 case DAE.POW_ARR2(_) then Absyn.POW();
415 case DAE.AND(_) then Absyn.AND();
416 case DAE.OR(_) then Absyn.OR();
417 case DAE.NOT(_) then Absyn.NOT();
418 case DAE.LESS(_) then Absyn.LESS();
419 case DAE.LESSEQ(_) then Absyn.LESSEQ();
420 case DAE.GREATER(_) then Absyn.GREATER();
421 case DAE.GREATEREQ(_) then Absyn.GREATEREQ();
422 case DAE.EQUAL(_) then Absyn.EQUAL();
423 case DAE.NEQUAL(_) then Absyn.NEQUAL();
424 end match;
425 end unelabOperator;
426
427 public function stringifyCrefs
428 "This function takes an expression and transforms all component
429 reference names contained in the expression to a simpler form.
430 For instance DAE.CREF_QUAL(a,{}, DAE.CREF_IDENT(b,{})) becomes
431 DAE.CREF_IDENT(a.b,{})
432
433 NOTE: This function should not be used in OMC, since the OMC backend no longer
434 uses stringified components. It is still used by MathCore though."
435 input DAE.Exp inExp;
436 output DAE.Exp outExp;
437 algorithm
438 ✗ outExp := traverseExpDummy(inExp, traversingstringifyCrefFinder);
439 end stringifyCrefs;
440
441 public function traversingstringifyCrefFinder "
442 helper for stringifyCrefs"
443 input DAE.Exp inExp;
444 output DAE.Exp outExp;
445 algorithm
446 outExp := match inExp
447 local
448 ComponentRef cr,crs;
449 Type ty;
450
451 case DAE.CREF(ty = DAE.T_FUNCTION_REFERENCE_VAR())
452 then inExp;
453
454 case DAE.CREF(ty = DAE.T_FUNCTION_REFERENCE_FUNC())
455 then inExp;
456
457 case DAE.CREF(cr,ty)
458 algorithm
459 ✗ crs := ComponentReference.stringifyComponentRef(cr);
460 ✗ then makeCrefExp(crs,ty);
461
462 else inExp;
463
464 end match;
465 end traversingstringifyCrefFinder;
466
467 public function realToIntIfPossible
468 "converts to ICONST if possible. If it does
469 not fit, a RCONST is returned instead."
470 input Real inVal;
471 output DAE.Exp outVal;
472 algorithm
473 try
474 43249 outVal := DAE.ICONST(realInt(inVal));
475 else
476 ✗ outVal := DAE.RCONST(inVal);
477 end try;
478 end realToIntIfPossible;
479
480 public function liftArrayR "
481 function liftArrayR
482 Converts a type into an array type with dimension n as first dim"
483 input DAE.Type tp;
484 input DAE.Dimension n;
485 output DAE.Type outTp;
486 algorithm
487 outTp := match tp
488 local
489 Type elt_tp;
490 list<DAE.Dimension> dims;
491
492 case DAE.T_ARRAY(elt_tp,dims)
493 algorithm
494 dims := n::dims;
495 14268 then
496 DAE.T_ARRAY(elt_tp,dims);
497
498 285995 else DAE.T_ARRAY(tp,{n});
499
500 end match;
501 end liftArrayR;
502
503 public function dimensionSizeConstantExp
504 "Converts (extracts) a dimension to an expression.
505 This function will fail if dimension is unknown or an expression (in case the dimension is from a different scope).
506 If you want to(kind of) handle unknown dims use dimensionSizeExpHandleUnkown."
507 input DAE.Dimension dim;
508 output DAE.Exp exp;
509 algorithm
510 exp := match dim
511 local
512 Integer i;
513
514 1569 case DAE.DIM_INTEGER(integer = i) then DAE.ICONST(i);
515 1 case DAE.DIM_ENUM(size = i) then DAE.ICONST(i);
516 case DAE.DIM_BOOLEAN() then DAE.ICONST(2);
517 end match;
518 end dimensionSizeConstantExp;
519
520 public function dimensionSizeExp
521 "Converts (extracts) a dimension to an expression.
522 This function will fail if dimension is unknown. i.e. DIM_UNKNOWN.
523 If you want to(kind of) handle unknown dims use dimensionSizeExpHandleUnkown."
524 input DAE.Dimension dim;
525 output DAE.Exp exp;
526 algorithm
527 exp := match dim
528 local
529 Integer i;
530 DAE.Exp e;
531
532 852129 case DAE.DIM_INTEGER(integer = i) then DAE.ICONST(i);
533 576 case DAE.DIM_ENUM(size = i) then DAE.ICONST(i);
534 case DAE.DIM_BOOLEAN() then DAE.ICONST(2);
535 case DAE.DIM_EXP(exp = e) then e;
536 end match;
537 end dimensionSizeExp;
538
539 public function dimensionSizeExpHandleUnkown
540 "Converts (extracts) a dimension to an expression.
541 This function will change unknown dims to DAE.ICONST(-1).
542 we use it to handle unknown dims in code generation. unknown dims
543 are okay if the variable is a function input (it's just holds the slot
544 and will not be generated). Otherwise it's an error
545 since it shouldn't have reached there."
546 input DAE.Dimension dim;
547 output DAE.Exp exp;
548 algorithm
549 exp := match dim
550 case DAE.DIM_UNKNOWN() then DAE.ICONST(-1);
551 520 else dimensionSizeExp(dim);
552 end match;
553 end dimensionSizeExpHandleUnkown;
554
555 public function intDimension
556 "Converts an integer to an array dimension."
557 input Integer value;
558 output DAE.Dimension dim;
559 annotation(__OpenModelica_EarlyInline = true);
560 algorithm
561 19591 dim := DAE.DIM_INTEGER(value);
562 end intDimension;
563
564 public function dimensionSubscript
565 "Converts an array dimension to a subscript."
566 input DAE.Dimension dim;
567 output DAE.Subscript sub;
568 algorithm
569 sub := match dim
570 local
571 Integer i;
572
573 ✗ case DAE.DIM_INTEGER(integer = i) then DAE.INDEX(DAE.ICONST(i));
574 ✗ case DAE.DIM_ENUM(size = i) then DAE.INDEX(DAE.ICONST(i));
575 case DAE.DIM_BOOLEAN() then DAE.INDEX(DAE.ICONST(2));
576 case DAE.DIM_UNKNOWN() then DAE.WHOLEDIM();
577 end match;
578 end dimensionSubscript;
579
580 /***************************************************/
581 /* Change */
582 /***************************************************/
583
584 public function negate
585 "author: PA
586 Negates an expression."
587 input DAE.Exp inExp;
588 output DAE.Exp outExp;
589 algorithm
590 outExp := match inExp
591 local
592 Type t;
593 Operator op;
594 Boolean b,b_1;
595 Real r,r_1;
596 Integer i,i_1;
597 DAE.Exp e,e1,e2;
598
599 // to avoid un-necessary --e
600 case DAE.UNARY(DAE.UMINUS(_),e) then e;
601 case DAE.UNARY(DAE.UMINUS_ARR(_),e) then e;
602 case DAE.LUNARY(DAE.NOT(_),e) then e;
603
604 // -(a*b) = (-a)*b
605 // -(a/b) = (-a)/b
606 case DAE.BINARY(e1,op,e2) guard(isMulOrDiv(op))
607 497778 then DAE.BINARY(negate(e1),op,e2);
608
609 // -(a-b) = b-a
610 case DAE.BINARY(e1,op,e2) guard(isSub(op))
611 13897 then DAE.BINARY(e2,op,e1);
612
613 case e // -0 = 0
614 guard isZero(e)
615 then e;
616
617 case DAE.ICONST(i)
618 algorithm
619 9212 i_1 := 0 - i;
620 9212 then DAE.ICONST(i_1);
621 case DAE.RCONST(r)
622 algorithm
623 488440 r_1 := 0.0 - r;
624 488440 then DAE.RCONST(r_1);
625 case DAE.BCONST(b)
626 algorithm
627 b_1 := not b;
628
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 38 times.
64 then DAE.BCONST(b_1);
629
630 case e
631 algorithm
632 1942437 t := typeof(e);
633 outExp := match t
634 case DAE.T_BOOL() // not e
635 7240 then DAE.LUNARY(DAE.NOT(t),e);
636 else
637 algorithm
638 1935197 b := DAEUtil.expTypeArray(t);
639
2/2
✓ Branch 0 taken 131 times.
✓ Branch 1 taken 1935066 times.
1935197 op := if b then DAE.UMINUS_ARR(t) else DAE.UMINUS(t);
640 1935197 then DAE.UNARY(op,e);
641 end match;
642 then
643 outExp;
644
645 end match;
646 end negate;
647
648 public function negateReal
649 input DAE.Exp inReal;
650 output DAE.Exp outNegatedReal;
651 algorithm
652 2584 outNegatedReal := DAE.UNARY(DAE.UMINUS(DAE.T_REAL_DEFAULT), inReal);
653 end negateReal;
654
655 public function expand "expands products
656 For example
657 a *(b+c) => a*b + a*c"
658 input DAE.Exp e;
659 output DAE.Exp outE;
660 algorithm
661 outE := match e
662 local
663 DAE.Type tp;
664 DAE.Operator op;
665 DAE.Exp e1,e2,e21,e22;
666
667 case DAE.BINARY(e1,DAE.MUL(tp),e2 as DAE.BINARY(e21,op,e22)) guard isAddOrSub(op)
668 algorithm
669 ✗ DAE.BINARY(e21,op,e22) := expand(e2);
670 ✗ then
671 DAE.BINARY(DAE.BINARY(e1,DAE.MUL(tp),e21),op,DAE.BINARY(e1,DAE.MUL(tp),e22));
672
673 else e;
674 end match;
675 end expand;
676
677 public function expDer
678 "author: Frenkel TUD 2012-11
679 exp -> der(exp)"
680 input DAE.Exp inExp;
681 output DAE.Exp outExp;
682 algorithm
683 7253 outExp := DAE.CALL(Absyn.IDENT("der"),{inExp},DAE.callAttrBuiltinReal);
684 end expDer;
685
686 public function expAbs
687 "author: PA
688 Makes the expression absolute. i.e. non-negative."
689 input DAE.Exp inExp;
690 output DAE.Exp outExp;
691 algorithm
692 outExp := match inExp
693 local
694 Integer i2,i;
695 Real r2,r;
696 DAE.Exp e_1,e,e1_1,e2_1,e1,e2;
697 Operator op;
698
699 case DAE.ICONST(integer = i)
700 algorithm
701 ✗ i2 := intAbs(i);
702 ✗ then
703 DAE.ICONST(i2);
704
705 case DAE.RCONST(real = r)
706 algorithm
707 ✗ r2 := realAbs(r);
708 ✗ then
709 DAE.RCONST(r2);
710
711 case DAE.UNARY(operator = DAE.UMINUS(),exp = e)
712 algorithm
713 ✗ e_1 := expAbs(e);
714 then
715 e_1;
716
717 case DAE.BINARY(exp1 = e1,operator = op,exp2 = e2)
718 algorithm
719 ✗ e1_1 := expAbs(e1);
720 ✗ e2_1 := expAbs(e2);
721 ✗ then
722 DAE.BINARY(e1_1,op,e2_1);
723
724 else inExp;
725 end match;
726 end expAbs;
727
728 public function stripNoEvent
729 "Function that strips all noEvent() calls in an expression"
730 input DAE.Exp e;
731 output DAE.Exp outE;
732 algorithm
733 8539 outE := traverseExpDummy(e,stripNoEventExp);
734 end stripNoEvent;
735
736 protected function stripNoEventExp "
737 traversal function for stripNoEvent"
738 input DAE.Exp e;
739 output DAE.Exp outExp;
740 algorithm
741 outExp := match e
742 case DAE.CALL(path=Absyn.IDENT("noEvent"),expLst={outExp}) then outExp;
743 else e;
744 end match;
745 end stripNoEventExp;
746
747 public function addNoEventToRelations
748 "Function that adds a noEvent() call to all relations in an expression"
749 input DAE.Exp e;
750 output DAE.Exp outE;
751 algorithm
752 9406 outE := traverseExpDummy(e,addNoEventToRelationExp);
753 end addNoEventToRelations;
754
755 protected function addNoEventToRelationExp "
756 traversal function for addNoEventToRelations"
757 input DAE.Exp e;
758 output DAE.Exp outExp;
759 algorithm
760 outExp := match e
761 4746 case DAE.RELATION() then makeNoEvent(e);
762 else e;
763 end match;
764 end addNoEventToRelationExp;
765
766 public function addNoEventToRelationsAndConds
767 "Function that adds a noEvent() call to all relations in an expression"
768 input DAE.Exp e;
769 output DAE.Exp outE;
770 algorithm
771 62534 outE := traverseExpDummy(e,addNoEventToRelationandCondExp);
772 end addNoEventToRelationsAndConds;
773
774 protected function addNoEventToRelationandCondExp "
775 traversal function for addNoEventToRelationsAndConds"
776 input DAE.Exp e;
777 output DAE.Exp outExp;
778 algorithm
779 outExp := match e
780 local
781 DAE.Exp e1,e2,e3;
782 4044 case DAE.RELATION() then makeNoEvent(e);
783 3948 case DAE.IFEXP(e1,e2,e3) then DAE.IFEXP(makeNoEvent(e1),e2,e3);
784 else e;
785 end match;
786 end addNoEventToRelationandCondExp;
787
788 public function addNoEventToEventTriggeringFunctions
789 " Function that adds a noEvent() call to all event triggering functions in an expression"
790 input DAE.Exp e;
791 output DAE.Exp outE;
792 algorithm
793 8833 outE := traverseExpDummy(e,addNoEventToEventTriggeringFunctionsExp);
794 end addNoEventToEventTriggeringFunctions;
795
796 protected function addNoEventToEventTriggeringFunctionsExp "
797 traversal function for addNoEventToEventTriggeringFunctions"
798 input DAE.Exp e;
799 output DAE.Exp outExp;
800 algorithm
801 outExp := match e
802 case DAE.CALL()
803 guard
804 isEventTriggeringFunctionExp(e)
805 ✗ then makeNoEvent(e);
806 else e;
807 end match;
808 end addNoEventToEventTriggeringFunctionsExp;
809
810 public function expStripLastSubs
811 "Strips the last subscripts of a Exp"
812 input DAE.Exp inExp;
813 output DAE.Exp outExp;
814 algorithm
815 outExp := match inExp
816 local
817 ComponentRef cr,cr_1;
818 Type ty;
819 Operator op1;
820 DAE.Exp e,e_1;
821 Boolean b;
822
823 case DAE.CREF(componentRef=cr)
824 algorithm
825 114 ty := ComponentReference.crefLastType(cr);
826 114 cr_1 := ComponentReferenceBasics.crefStripLastSubs(cr);
827 114 e := makeCrefExp(cr_1, ty);
828 then
829 e;
830
831 case DAE.UNARY(exp=e)
832 algorithm
833 4 e_1 := expStripLastSubs(e);
834 4 ty := typeof(e_1);
835 4 b := DAEUtil.expTypeArray(ty);
836
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 time.
4 op1 := if b then DAE.UMINUS_ARR(ty) else DAE.UMINUS(ty);
837 4 then
838 DAE.UNARY(op1,e_1);
839 end match;
840 end expStripLastSubs;
841
842 public function expStripLastIdent
843 "Strips the last identifier of a cref Exp"
844 input DAE.Exp inExp;
845 output DAE.Exp outExp;
846 algorithm
847 outExp:=
848 match inExp
849 local
850 ComponentRef cr,cr_1;
851 Type ty;
852 Operator op1;
853 DAE.Exp e,e_1;
854 Boolean b;
855
856 case DAE.CREF(componentRef=cr)
857 algorithm
858 ✗ cr_1 := ComponentReference.crefStripLastIdent(cr);
859 ✗ ty := ComponentReference.crefLastType(cr_1);
860 ✗ e := makeCrefExp(cr_1, ty);
861 then
862 e;
863
864 case DAE.UNARY(exp=e)
865 algorithm
866 ✗ e_1 := expStripLastIdent(e);
867 ✗ ty := typeof(e_1);
868 ✗ b := DAEUtil.expTypeArray(ty);
869 ✗ op1 := if b then DAE.UMINUS_ARR(ty) else DAE.UMINUS(ty);
870 ✗ then
871 DAE.UNARY(op1,e_1);
872 end match;
873 end expStripLastIdent;
874
875 public function prependSubscriptExp
876 "Prepends a subscript to a CREF expression
877 For instance a.b[1,2] with subscript 'i' becomes a.b[i,1,2]."
878 input DAE.Exp exp;
879 input DAE.Subscript subscr;
880 output DAE.Exp outExp;
881 algorithm
882 outExp := match exp
883 local
884 Type t;
885 ComponentRef cr, cr1, cr2;
886 list<DAE.Subscript> subs;
887 DAE.Exp e;
888
889 case DAE.CREF(cr,t)
890 algorithm
891 ✗ cr1 := ComponentReferenceBasics.crefStripLastSubs(cr);
892 ✗ subs := ComponentReference.crefLastSubs(cr);
893 ✗ cr2 := ComponentReference.subscriptCref(cr1,subscr::subs);
894 ✗ e := makeCrefExp(cr2, t);
895 then
896 e;
897 end match;
898 end prependSubscriptExp;
899
900 public function applyExpSubscripts
901 "@mahge
902 Takes an expression and a list of subscripts and subscripts
903 the given expression.
904 If a component reference is given the subs are applied to it.
905 If an array(DAE.ARRAY) is given the element at the specified
906 subscripts is returned. Otherwise and ASUB is built and returned.
907 e.g. subscriptExp on ({{1,2},{3,4}}) with sub [2,1] gives 3
908 subscriptExp on (a) with sub [2,1] gives a[2,1]
909
910 "
911 input output DAE.Exp exp;
912 input list<DAE.Subscript> inSubs;
913 protected
914 String str;
915 algorithm
916 try
917 440549 exp := applyExpSubscripts2(exp, inSubs);
918 else
919 ✗ str := "Expression.applyExpSubscripts failed applying subs: [" + ExpressionDump.printSubscriptLstStr(inSubs)
920 + "] on expression:" + ExpressionBasics.printExpStr(exp) + "\n";
921 ✗ Error.addMessage(Error.INTERNAL_ERROR, {str});
922 end try;
923
924 end applyExpSubscripts;
925
926
927 public function applyExpSubscriptsFoldCheckSimplify "
928 author: PA
929 Takes an arbitrary expression and applies subscripts to it. This is done by creating asub
930 expressions given the original expression and then simplify them.
931 Note: The subscripts must be INDEX
932
933 alternative names: subsriptExp (but already taken), subscriptToAsub
934
935 This version of the function also returns a boolean stating if simplify
936 improved anything (can be used as a heuristic if you want to apply
937 the subscript when scalarizing)
938
939 Note: mahge. Uses of this function should be replaced by applyExpSubscripts. I have not
940 replaced them because I could not make sense of the usage in Backend/RemoveSimpleEquations.
941 It uses the checkSimplify arg and I am not sure what it expects or is supposed to do with the result."
942 input output DAE.Exp exp;
943 input list<DAE.Subscript> inSubs;
944 input output Boolean checkSimplify = false;
945 protected
946 Boolean b;
947 DAE.Exp s;
948 algorithm
949
2/2
✓ Branch 0 taken 453863 times.
✓ Branch 1 taken 279108 times.
732971 for sub in inSubs loop
950 // Apply one subscript at a time, so simplify works fine on it.
951 //s := subscriptIndexExp(sub);
952 try
953 453863 s := getSubscriptExp(sub);
954 453825 (exp,b) := ExpressionSimplify.simplify(makeASUB(exp,{s}));
955 453825 checkSimplify := b or checkSimplify;
956 else
957 // skipped DAE.WHOLEDIM
958 end try;
959 end for;
960 end applyExpSubscriptsFoldCheckSimplify;
961
962 public function applyExpSubscripts2
963 "@mahge
964 Takes an expression and a list of subscripts and subscripts
965 the given expression.
966 If a component reference is given the subs are applied to it.
967 If an array(DAE.ARRAY) is given the element at the specified
968 subscripts is returned. Otherwise and ASUB is built and returned.
969 e.g. subscriptExp on ({{1,2},{3,4}}) with sub [2,1] gives 3
970 subscriptExp on (a) with sub [2,1] gives a[2,1]
971
972 "
973 input DAE.Exp inExp;
974 input list<DAE.Subscript> inSubs;
975 output DAE.Exp outArg;
976 algorithm
977 outArg := match(inExp, inSubs)
978 local
979 DAE.ComponentRef cref;
980 DAE.Type ty;
981 DAE.Exp exp;
982
983 case(_, {}) then inExp;
984
985 case(DAE.CREF(cref, ty), _)
986 algorithm
987 try
988 99240 cref := ComponentReference.subscriptCref(cref, inSubs);
989 99240 ty := ComponentReference.crefTypeFull(cref);
990 99240 exp := DAE.CREF(cref, ty);
991 else
992 ✗ exp := applyExpSubscriptsFoldCheckSimplify(inExp, inSubs);
993 end try;
994 then
995 exp;
996
997 // This is the default operation for exps not handled explicitly. It is unfortunate
998 // we have to build ASUBs. But we can improve this step by step to exclude more exps.
999 // Note getSubscriptExp does not work on WHOLE_DIM subs. So this will fail if one of the
1000 // subs is WHOLE_DIM. DAE.ASUB should have been able to have list<DAE.Subscript> instead
1001 // of just list<DAE.Exp> represneting subs.
1002 else algorithm
1003 257420 exp := applyExpSubscriptsFoldCheckSimplify(inExp, inSubs);
1004 then exp;
1005
1006 end match;
1007 end applyExpSubscripts2;
1008
1009
1010 public function unliftArray
1011 "Converts an array type into its element type
1012 See also Types.unliftArray.
1013 ."
1014 input DAE.Type inType;
1015 output DAE.Type outType;
1016 algorithm
1017 outType := match inType
1018 local
1019 Type tp;
1020 DAE.Dimensions ds;
1021
1022 case DAE.T_ARRAY(ty = tp,dims = {_})
1023 then tp;
1024 case DAE.T_ARRAY(ty = tp,dims = (_ :: ds))
1025 490855 then DAE.T_ARRAY(tp,ds);
1026 case DAE.T_METATYPE(ty = tp)
1027 214 then Types.simplifyType(unliftArray(tp));
1028 case DAE.T_METAARRAY(ty = tp)
1029 then tp;
1030 else inType;
1031 end match;
1032 end unliftArray;
1033
1034 public function unliftArrayIgnoreFirst
1035 input A a;
1036 input DAE.Type inType;
1037 output DAE.Type outType;
1038 replaceable type A subtypeof Any;
1039 algorithm
1040 15 outType := unliftArray(inType);
1041 end unliftArrayIgnoreFirst;
1042
1043 public function unliftExp
1044 input DAE.Exp inExp;
1045 output DAE.Exp outExp;
1046 algorithm
1047 outExp := match inExp
1048 local
1049 Type ty;
1050 DAE.ComponentRef cr;
1051 Boolean s;
1052 list<DAE.Exp> a;
1053 Integer i;
1054 list<list<DAE.Exp>> mat;
1055 DAE.Exp expCref;
1056
1057 case DAE.CREF(componentRef = cr, ty = ty)
1058 algorithm
1059 ✗ ty := unliftArray(ty);
1060 ✗ expCref := makeCrefExp(cr, ty);
1061 then
1062 expCref;
1063
1064 case DAE.ARRAY(ty = ty, scalar = s, array = a)
1065 algorithm
1066 ✗ ty := unliftArray(ty);
1067 ✗ then
1068 DAE.ARRAY(ty, s, a);
1069
1070 case DAE.MATRIX(ty = ty, integer = i, matrix = mat)
1071 algorithm
1072 ✗ ty := unliftArray(ty);
1073 ✗ then
1074 DAE.MATRIX(ty, i, mat);
1075
1076 else inExp;
1077
1078 end match;
1079 end unliftExp;
1080
1081 public function liftExp
1082 input DAE.Exp inExp;
1083 input DAE.Dimension inDimension;
1084 output DAE.Exp outExp;
1085 algorithm
1086 2 outExp := DAE.ARRAY(Types.liftArray(typeof(inExp), inDimension),
1087 false, List.fill(inExp, dimensionSize(inDimension)));
1088 end liftExp;
1089
1090 public function liftExpList
1091 input DAE.Exp inExp;
1092 input list<DAE.Dimension> inDimensions;
1093 output DAE.Exp outExp = inExp;
1094 algorithm
1095
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 time.
3 for dim in listReverse(inDimensions) loop
1096 2 outExp := liftExp(outExp, dim);
1097 end for;
1098 end liftExpList;
1099
1100 public function liftArrayRight "
1101 This function adds an array dimension to a type on the right side, i.e.
1102 liftArrayRigth(Real[2,3],SOME(4)) => Real[2,3,4].
1103 This function has the same functionality as Types.liftArrayType but for DAE.Type.'"
1104 input DAE.Type inType;
1105 input DAE.Dimension inDimension;
1106 output DAE.Type outType;
1107 algorithm
1108 outType := match(inType,inDimension)
1109 local
1110 Type ty_1,ty;
1111 DAE.Dimensions dims;
1112 DAE.Dimension dim;
1113
1114 case (DAE.T_ARRAY(ty,dims),dim)
1115 algorithm
1116 ✗ ty_1 := liftArrayRight(ty, dim);
1117 ✗ then
1118 DAE.T_ARRAY(ty_1,dims);
1119
1120 ✗ else DAE.T_ARRAY(inType,{inDimension});
1121
1122 end match;
1123 end liftArrayRight;
1124
1125 public function liftArrayLeft "
1126 author: PA
1127 This function adds an array dimension to a type on the left side, i.e.
1128 liftArrayRigth(Real[2,3],SOME(4)) => Real[4,2,3]"
1129 input DAE.Type inType;
1130 input DAE.Dimension inDimension;
1131 output DAE.Type outType;
1132 algorithm
1133 outType := match(inType,inDimension)
1134 local
1135 Type ty;
1136 DAE.Dimensions dims;
1137 DAE.Dimension dim;
1138
1139 4080 case (DAE.T_ARRAY(ty,dims),dim) then DAE.T_ARRAY(ty,dim::dims);
1140
1141 23 else DAE.T_ARRAY(inType,{inDimension});
1142
1143 end match;
1144 end liftArrayLeft;
1145
1146 public function liftArrayLeftList
1147 input DAE.Type inType;
1148 input list<DAE.Dimension> inDimensions;
1149 output DAE.Type outType;
1150 algorithm
1151 outType := match(inType, inDimensions)
1152 local
1153 Type ty;
1154 DAE.Dimensions dims;
1155
1156 case (_, {}) then inType;
1157
1158 case (DAE.T_ARRAY(ty, dims), _)
1159 algorithm
1160 2 dims := listAppend(inDimensions, dims);
1161 2 then
1162 DAE.T_ARRAY(ty, dims);
1163
1164 677464 else DAE.T_ARRAY(inType, inDimensions);
1165
1166 end match;
1167 end liftArrayLeftList;
1168
1169 public function setOpType
1170 "Sets the type of an operator."
1171 input DAE.Operator inOp;
1172 input DAE.Type inType;
1173 output DAE.Operator outOp;
1174 algorithm
1175 outOp := match inOp
1176 51919 case DAE.ADD() then DAE.ADD(inType);
1177 24801 case DAE.SUB() then DAE.SUB(inType);
1178 75765 case DAE.MUL() then DAE.MUL(inType);
1179 16420 case DAE.DIV() then DAE.DIV(inType);
1180 8069 case DAE.POW() then DAE.POW(inType);
1181 94571 case DAE.UMINUS() then DAE.UMINUS(inType);
1182 1208 case DAE.UMINUS_ARR() then DAE.UMINUS_ARR(inType);
1183 2931 case DAE.ADD_ARR() then DAE.ADD_ARR(inType);
1184 1690 case DAE.SUB_ARR() then DAE.SUB_ARR(inType);
1185 27 case DAE.MUL_ARR() then DAE.MUL_ARR(inType);
1186 29 case DAE.DIV_ARR() then DAE.DIV_ARR(inType);
1187 1668 case DAE.MUL_ARRAY_SCALAR() then DAE.MUL_ARRAY_SCALAR(inType);
1188 6 case DAE.ADD_ARRAY_SCALAR() then DAE.ADD_ARRAY_SCALAR(inType);
1189 3 case DAE.SUB_SCALAR_ARRAY() then DAE.SUB_SCALAR_ARRAY(inType);
1190 638 case DAE.MUL_SCALAR_PRODUCT() then DAE.MUL_SCALAR_PRODUCT(inType);
1191 607 case DAE.MUL_MATRIX_PRODUCT() then DAE.MUL_MATRIX_PRODUCT(inType);
1192 540 case DAE.DIV_ARRAY_SCALAR() then DAE.DIV_ARRAY_SCALAR(inType);
1193 1 case DAE.DIV_SCALAR_ARRAY() then DAE.DIV_SCALAR_ARRAY(inType);
1194 2 case DAE.POW_ARRAY_SCALAR() then DAE.POW_ARRAY_SCALAR(inType);
1195 1 case DAE.POW_SCALAR_ARRAY() then DAE.POW_SCALAR_ARRAY(inType);
1196 5 case DAE.POW_ARR() then DAE.POW_ARR(inType);
1197 4 case DAE.POW_ARR2() then DAE.POW_ARR2(inType);
1198 3255 case DAE.AND() then DAE.AND(inType);
1199 1768 case DAE.OR() then DAE.OR(inType);
1200 1743 case DAE.NOT() then DAE.NOT(inType);
1201 case DAE.LESS() then inOp;
1202 case DAE.LESSEQ() then inOp;
1203 case DAE.GREATER() then inOp;
1204 case DAE.GREATEREQ() then inOp;
1205 case DAE.EQUAL() then inOp;
1206 case DAE.NEQUAL() then inOp;
1207 case DAE.USERDEFINED() then inOp;
1208 else
1209 algorithm
1210 ✗ true := Flags.isSet(Flags.FAILTRACE);
1211 ✗ Debug.traceln("- Expression.setOpType failed on unknown operator");
1212 ✗ then
1213 fail();
1214 end match;
1215 end setOpType;
1216
1217 public function unliftOperator
1218 "Unlifts the type of an operator by removing one dimension from the operator
1219 type. The operator is changed to the scalar version if the type becomes a
1220 scalar type."
1221 input DAE.Operator inOperator;
1222 output DAE.Operator outOperator;
1223 protected
1224 Type ty;
1225 algorithm
1226 9077 ty := typeofOp(inOperator);
1227 9077 ty := unliftArray(ty);
1228 9077 outOperator := unliftOperator2(inOperator, ty);
1229 end unliftOperator;
1230
1231 public function unliftOperatorX
1232 "Unlifts the type of an operator by removing X dimensions from the operator
1233 type. The operator is changed to the scalar version if the type becomes a
1234 scalar type."
1235 input DAE.Operator inOperator;
1236 input Integer inX;
1237 output DAE.Operator outOperator;
1238 protected
1239 Type ty;
1240 algorithm
1241 154 ty := typeofOp(inOperator);
1242 154 ty := unliftArrayX(ty, inX);
1243 154 outOperator := unliftOperator2(inOperator, ty);
1244 end unliftOperatorX;
1245
1246 protected function unliftOperator2
1247 "Helper function to unliftOperator. Sets the type of the given operator, and
1248 changes the operator to the scalar version if the type is scalar."
1249 input DAE.Operator inOperator;
1250 input DAE.Type inType;
1251 output DAE.Operator outOperator;
1252 algorithm
1253 outOperator := match inType
1254 147 case DAE.T_ARRAY() then setOpType(inOperator, inType);
1255 9084 else makeScalarOpFromArrayOp(inOperator, inType);
1256 end match;
1257 end unliftOperator2;
1258
1259 protected function makeScalarOpFromArrayOp
1260 "Helper function to makeScalarOpFromArrayOp. Returns the scalar version of a
1261 given array operator."
1262 input DAE.Operator inOperator;
1263 input DAE.Type inType;
1264 output DAE.Operator outOperator;
1265 algorithm
1266 outOperator := match inOperator
1267 7879 case DAE.MUL_ARRAY_SCALAR() then DAE.MUL(inType);
1268 8 case DAE.ADD_ARRAY_SCALAR() then DAE.ADD(inType);
1269 6 case DAE.SUB_SCALAR_ARRAY() then DAE.SUB(inType);
1270 1058 case DAE.DIV_ARRAY_SCALAR() then DAE.DIV(inType);
1271 1 case DAE.DIV_SCALAR_ARRAY() then DAE.DIV(inType);
1272 131 case DAE.POW_ARRAY_SCALAR() then DAE.POW(inType);
1273 1 case DAE.POW_SCALAR_ARRAY() then DAE.POW(inType);
1274 ✗ case DAE.UMINUS_ARR() then DAE.UMINUS(inType);
1275 ✗ case DAE.ADD_ARR() then DAE.ADD(inType);
1276 ✗ case DAE.SUB_ARR() then DAE.SUB(inType);
1277 ✗ case DAE.MUL_ARR() then DAE.MUL(inType);
1278 ✗ case DAE.DIV_ARR() then DAE.DIV(inType);
1279 else inOperator;
1280 end match;
1281 end makeScalarOpFromArrayOp;
1282
1283 public function isScalarArrayOp
1284 "Returns true if the operator takes a scalar and an array as arguments."
1285 input DAE.Operator inOperator;
1286 output Boolean outIsScalarArrayOp;
1287 algorithm
1288 outIsScalarArrayOp := match inOperator
1289 case DAE.SUB_SCALAR_ARRAY() then true;
1290 case DAE.DIV_SCALAR_ARRAY() then true;
1291 case DAE.POW_SCALAR_ARRAY() then true;
1292 else false;
1293 end match;
1294 end isScalarArrayOp;
1295
1296 public function isArrayScalarOp
1297 "Returns true if the operator takes an array and a scalar as arguments."
1298 input DAE.Operator inOperator;
1299 output Boolean outIsArrayScalarOp;
1300 algorithm
1301 outIsArrayScalarOp := match inOperator
1302 case DAE.MUL_ARRAY_SCALAR() then true;
1303 case DAE.ADD_ARRAY_SCALAR() then true;
1304 case DAE.DIV_ARRAY_SCALAR() then true;
1305 case DAE.POW_ARRAY_SCALAR() then true;
1306 else false;
1307 end match;
1308 end isArrayScalarOp;
1309
1310 public function subscriptsAppend
1311 "This function takes a subscript list and adds a new subscript.
1312 But there are a few special cases. When the last existing
1313 subscript is a slice, it is replaced by the slice indexed by
1314 the new subscript."
1315 input list<DAE.Subscript> inSubscriptLst;
1316 input DAE.Exp inSubscript;
1317 output list<DAE.Subscript> outSubscriptLst;
1318 algorithm
1319 outSubscriptLst := match inSubscriptLst
1320 local
1321 DAE.Exp e_1,e;
1322 Subscript s;
1323 list<DAE.Subscript> ss_1,ss;
1324
1325 26718 case {} then {DAE.INDEX(inSubscript)};
1326 96 case DAE.WHOLEDIM() :: ss then DAE.INDEX(inSubscript) :: ss;
1327
1328 case {DAE.SLICE(exp = e)}
1329 algorithm
1330 4 (e_1,_) := ExpressionSimplify.simplify1(makeASUB(e,{inSubscript}));
1331 4 then
1332 {DAE.INDEX(e_1)};
1333
1334 26343 case {(s as DAE.INDEX())} then {s,DAE.INDEX(inSubscript)};
1335
1336 case s :: ss
1337 algorithm
1338 103 ss_1 := subscriptsAppend(ss, inSubscript);
1339 then
1340 (s :: ss_1);
1341 end match;
1342 end subscriptsAppend;
1343
1344 public function subscriptsReplaceSlice
1345 "Replaces the first slice subscript in the given list with the given subscript."
1346 input list<DAE.Subscript> inSubscripts;
1347 input DAE.Subscript inSubscript;
1348 output list<DAE.Subscript> outSubscripts;
1349 algorithm
1350 outSubscripts := match inSubscripts
1351 local
1352 list<DAE.Subscript> rest_subs;
1353 DAE.Subscript sub;
1354
1355 case DAE.WHOLEDIM() :: rest_subs then inSubscript :: rest_subs;
1356 case DAE.SLICE() :: rest_subs then inSubscript :: rest_subs;
1357 case sub :: rest_subs
1358 algorithm
1359 8656 rest_subs := subscriptsReplaceSlice(rest_subs, inSubscript);
1360 then
1361 sub :: rest_subs;
1362
1363 end match;
1364 end subscriptsReplaceSlice;
1365
1366 public function unliftArrayTypeWithSubs "
1367 helper function for renameVarsToUnderlineVar2 unlifts array type as much as we have subscripts"
1368 input list<DAE.Subscript> subs;
1369 input DAE.Type ity;
1370 output DAE.Type oty;
1371 algorithm
1372 oty := match(subs,ity)
1373 local
1374 list<DAE.Subscript> rest;
1375 Type ty;
1376
1377 case({},ty) then ty;
1378
1379 case(_::rest, ty)
1380 algorithm
1381 1419525 ty := unliftArray(ty);
1382 1419525 ty := unliftArrayTypeWithSubs(rest,ty);
1383 then
1384 ty;
1385 end match;
1386 end unliftArrayTypeWithSubs;
1387
1388 public function unliftArrayX "Function: unliftArrayX
1389 Unlifts a type with X dimensions..."
1390 input DAE.Type inType;
1391 input Integer x;
1392 output DAE.Type outType;
1393 algorithm
1394 outType := match x
1395 local Type ty;
1396
1397 case 0 then inType;
1398 else
1399 algorithm
1400 82866 ty := unliftArray(inType);
1401 82866 then
1402 unliftArrayX(ty,x-1);
1403 end match;
1404 end unliftArrayX;
1405
1406 public function arrayAppend
1407 "Appends a new element to a DAE.ARRAY."
1408 input DAE.Exp head;
1409 input DAE.Exp rest;
1410 output DAE.Exp array;
1411 algorithm
1412 array := match rest
1413 local
1414 DAE.Type ty;
1415 Boolean scalar;
1416 list<DAE.Exp> expl;
1417 Integer dim;
1418 DAE.Dimensions dims;
1419
1420 case DAE.ARRAY(
1421 DAE.T_ARRAY(ty = ty, dims = DAE.DIM_INTEGER(dim) :: dims),
1422 scalar,
1423 expl)
1424 algorithm
1425 ✗ dim := dim + 1;
1426 ✗ dims := DAE.DIM_INTEGER(dim) :: dims;
1427 ✗ then
1428 DAE.ARRAY(DAE.T_ARRAY(ty, dims), scalar, head :: expl);
1429
1430 else
1431 algorithm
1432 ✗ true := Flags.isSet(Flags.FAILTRACE);
1433 ✗ Debug.traceln("- Expression.arrayAppend failed.");
1434 ✗ then
1435 fail();
1436 end match;
1437 end arrayAppend;
1438
1439
1440 public function arrayDimensionSetFirst
1441 "Updates the first dimension of an array type."
1442 input DAE.Type inArrayType;
1443 input DAE.Dimension dimension;
1444 output DAE.Type outArrayType;
1445 algorithm
1446 outArrayType := match inArrayType
1447 local
1448 DAE.Type ty;
1449 DAE.Dimensions rest_dims;
1450
1451 case DAE.T_ARRAY(ty = ty, dims = _ :: rest_dims)
1452 26145 then DAE.T_ARRAY(ty, dimension :: rest_dims);
1453 end match;
1454 end arrayDimensionSetFirst;
1455
1456 /***************************************************/
1457 /* Getter */
1458 /***************************************************/
1459
1460 public function toReal
1461 "Returns the value of a constant Real expression."
1462 input DAE.Exp inExp;
1463 output Real outReal;
1464 algorithm
1465 outReal := match inExp
1466 95052 case DAE.RCONST() then inExp.real;
1467 17124 case DAE.ICONST() then intReal(inExp.integer);
1468 2 case DAE.CAST() then toReal(inExp.exp);
1469 2340 case DAE.ENUM_LITERAL() then intReal(inExp.index);
1470 end match;
1471 end toReal;
1472
1473 public function toBool
1474 "Returns the value of a constant Boolean expression."
1475 input DAE.Exp inExp;
1476 output Boolean outBool;
1477 algorithm
1478
2/2
✓ Branch 0 taken 33762 times.
✓ Branch 1 taken 3905 times.
37667 DAE.BCONST(outBool) := inExp;
1479 end toBool;
1480
1481 public function realExpIntLit "returns the int value if expression is constant Real that can be represented by an Integer"
1482 input DAE.Exp exp;
1483 output Option<Integer> oi;
1484 algorithm
1485 oi := match exp
1486 local
1487 Real r;
1488 Integer i;
1489 Option<Integer> op;
1490 case DAE.RCONST(real = r)
1491 algorithm
1492 158671 i := realInt(r);
1493
2/2
✓ Branch 0 taken 156970 times.
✓ Branch 1 taken 1701 times.
158671 op := if realEq(r,intReal(i)) then SOME(i) else NONE();
1494 then op;
1495 else NONE();
1496 end match;
1497 end realExpIntLit;
1498
1499 public function expInt "returns the int value if expression is constant Integer"
1500 input DAE.Exp exp;
1501 output Integer i;
1502 algorithm
1503 i := match exp
1504 1828550 case DAE.ICONST() then exp.integer;
1505 7258 case DAE.ENUM_LITERAL() then exp.index;
1506
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 6 times.
15 case DAE.BCONST() then if exp.bool then 1 else 0;
1507 end match;
1508 end expInt;
1509
1510 public function getClockInterval
1511 "Returns a real interval expression for any clock kind; 0.0 if unknown."
1512 input DAE.ClockKind inClk;
1513 output DAE.Exp outIntvl;
1514 protected
1515 DAE.Exp e, e2;
1516 algorithm
1517 outIntvl := match inClk
1518 case DAE.REAL_CLOCK(e)
1519 then e;
1520 case DAE.RATIONAL_CLOCK(e, e2)
1521 3 then DAE.BINARY(
1522 DAE.CAST(DAE.T_REAL_DEFAULT, e),
1523 DAE.DIV(DAE.T_REAL_DEFAULT),
1524 DAE.CAST(DAE.T_REAL_DEFAULT, e2));
1525 case DAE.EVENT_CLOCK(e, e2)
1526 then e2; // startInterval
1527 else
1528 then DAE.RCONST(0.0);
1529 end match;
1530 end getClockInterval;
1531
1532 public function sconstEnumNameString
1533 input DAE.Exp exp;
1534 output String str;
1535 algorithm
1536 str := match exp
1537 local
1538 String s;
1539 Absyn.Path name;
1540 case DAE.SCONST(s) then s;
1541 558 case DAE.ENUM_LITERAL(name) then AbsynUtil.pathString(name);
1542 end match;
1543 end sconstEnumNameString;
1544
1545 public function varName "Returns the name of a Var"
1546 input DAE.Var v;
1547 output String name;
1548 algorithm
1549 name := match v
1550 case DAE.TYPES_VAR(name = name) then name;
1551 end match;
1552 end varName;
1553
1554 public function varType "Returns the type of a Var"
1555 input DAE.Var v;
1556 output DAE.Type tp;
1557 algorithm
1558 tp := match v
1559 case DAE.TYPES_VAR(ty = tp) then tp;
1560 end match;
1561 end varType;
1562
1563 public function expOrDerCref
1564 "Returns the componentref if DAE.Exp is a CREF or DER(CREF)"
1565 input DAE.Exp inExp;
1566 output DAE.ComponentRef outComponentRef;
1567 output Boolean isDer;
1568 algorithm
1569 (outComponentRef, isDer) :=
1570 match inExp
1571 local ComponentRef cr;
1572 case DAE.CREF(componentRef = cr) then (cr, false);
1573 case DAE.CALL(path = Absyn.IDENT(name = "der"),expLst={DAE.CREF(cr,_)}) then (cr, true);
1574 end match;
1575 end expOrDerCref;
1576
1577 public function expCref
1578 "Returns the componentref if DAE.Exp is a CREF,"
1579 input DAE.Exp inExp;
1580 output DAE.ComponentRef outComponentRef;
1581 algorithm
1582 outComponentRef:=
1583 match inExp
1584 local ComponentRef cr;
1585 case DAE.CREF(componentRef = cr) then cr;
1586 end match;
1587 end expCref;
1588
1589 public function expCrefNegCref
1590 "Returns the componentref if DAE.Exp is a CREF or -CREF"
1591 input DAE.Exp inExp;
1592 output DAE.ComponentRef outComponentRef;
1593 algorithm
1594 outComponentRef:=
1595 match inExp
1596 local ComponentRef cr;
1597 case DAE.CREF(componentRef = cr) then cr;
1598 case DAE.UNARY(DAE.UMINUS(_),DAE.CREF(componentRef = cr)) then cr;
1599 case DAE.UNARY(DAE.UMINUS_ARR(_),DAE.CREF(componentRef = cr)) then cr;
1600 end match;
1601 end expCrefNegCref;
1602
1603 public function expCrefTuple
1604 "Returns the componentref if the expression in inTuple is a CREF."
1605 input tuple<DAE.Exp, Boolean> inTuple;
1606 output DAE.ComponentRef outComponentRef;
1607 algorithm
1608 outComponentRef:=
1609 match inTuple
1610 local ComponentRef cr;
1611 case (DAE.CREF(componentRef = cr),_) then cr;
1612 end match;
1613 end expCrefTuple;
1614
1615 public function expCrefInclIfExpFactors
1616 "Returns the componentref if DAE.Exp is a CREF, or the factors of CREF if expression is an if expression.
1617 This is used in e.g. the tearing algorithm to detect potential division by zero in
1618 expressions like 1/(if b then 1.0 else x) which could lead to division by zero if b is false and x is 0; "
1619 input DAE.Exp inExp;
1620 output list<DAE.ComponentRef> outComponentRefs;
1621 algorithm
1622 outComponentRefs:=
1623 match inExp
1624 local ComponentRef cr; DAE.Exp tb,fb;
1625 list<DAE.Exp> f;
1626 list<DAE.ComponentRef> crefs;
1627 case DAE.CREF(componentRef = cr) then {cr};
1628 case DAE.IFEXP(_,tb,fb) algorithm
1629 ✗ f := List.select(listAppend(factors(tb),factors(fb)),isCref);
1630 ✗ crefs := List.map(f,expCref);
1631 then crefs;
1632 end match;
1633 end expCrefInclIfExpFactors;
1634
1635 public function getArrayContents "returns the list of expressions in the array"
1636 input DAE.Exp e;
1637 output list<DAE.Exp> es;
1638 algorithm
1639
2/2
✓ Branch 0 taken 8031 times.
✓ Branch 1 taken 169 times.
8200 DAE.ARRAY(array=es) := e;
1640 end getArrayContents;
1641
1642 public function getArrayOrMatrixContents
1643 "Returns the contents of an array or matrix as a list of expressions."
1644 input DAE.Exp inExp;
1645 output list<DAE.Exp> outContents;
1646 algorithm
1647 outContents := match inExp
1648 local
1649 list<DAE.Exp> expl;
1650 list<list<DAE.Exp>> mat;
1651 DAE.Type ty, el_ty;
1652 DAE.Dimensions dims;
1653 Boolean sc;
1654
1655 case DAE.ARRAY(array = expl) then expl;
1656 case DAE.MATRIX(ty = DAE.T_ARRAY(el_ty, _ :: dims), matrix = mat)
1657 algorithm
1658 107 ty := DAE.T_ARRAY(el_ty, dims);
1659 107 sc := Types.basicType(el_ty);
1660
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
107 then
1661 List.map2(mat, makeArray, ty, sc);
1662
1663 end match;
1664 end getArrayOrMatrixContents;
1665
1666 public function expandArray
1667 input DAE.Exp exp;
1668 output list<DAE.Exp> contents;
1669 algorithm
1670 contents := match exp
1671
4/4
✓ Branch 1 taken 327 times.
✓ Branch 2 taken 110 times.
✓ Branch 3 taken 327 times.
✓ Branch 4 taken 110 times.
437 case DAE.ARRAY() then listAppend(expandArray(e) for e in listReverse(exp.array));
1672 ✗ case DAE.MATRIX() then getArrayOrMatrixContents(exp);
1673 else {exp};
1674 end match;
1675 end expandArray;
1676
1677 protected function makeASUBsForDimension"makes all asubs for the complete dimension of the exp."
1678 input DAE.Exp eIn;
1679 output list<DAE.Exp> eLstOut={};
1680 protected
1681 Integer size;
1682 DAE.Dimensions dims;
1683 algorithm
1684 3 dims := expDimensions(eIn);
1685 try
1686 ✗ {DAE.DIM_INTEGER(integer=size)} := dims;
1687 ✗ for i in size:-1:1 loop
1688 ✗ eLstOut := makeASUBSingleSub(eIn,DAE.ICONST(i))::eLstOut;
1689 end for;
1690 else
1691 eLstOut := {};
1692 end try;
1693 end makeASUBsForDimension;
1694
1695 public function getComplexContents "returns the list of expressions from a complex structure like array,record,call,tuple...
1696 author:Waurich TUD 2014-04"
1697 input DAE.Exp e;
1698 output list<DAE.Exp> es;
1699 algorithm
1700 es := matchcontinue e
1701 local
1702 Boolean noArr;
1703 DAE.Exp exp, exp1, exp2;
1704 DAE.Type ty;
1705 list<DAE.Exp> expLst, expLst1, expLst2;
1706 list<list<DAE.Exp>> expLstLst;
1707 case DAE.CREF()
1708 algorithm
1709 418401 expLst := arrayElements(e);
1710 418401 noArr := listLength(expLst)==1;
1711 418401 exp := listHead(expLst);
1712
4/4
✓ Branch 0 taken 417224 times.
✓ Branch 1 taken 1117 times.
✓ Branch 3 taken 417201 times.
✓ Branch 4 taken 23 times.
418341 noArr := noArr and ExpressionBasics.expEqual(exp,e);
1713 expLst := if noArr then {} else expLst;
1714 then
1715 expLst;
1716
1717 case DAE.BINARY(exp1=exp1,operator=DAE.ADD_ARR(),exp2=exp2)
1718 algorithm
1719
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if isArray(exp1) then
1720 ✗ expLst1 := getComplexContents(exp1);
1721 else
1722 3 expLst1 := makeASUBsForDimension(exp1);
1723 end if;
1724 ✗ if isArray(exp2) then
1725 ✗ expLst2 := getComplexContents(exp2);
1726 else
1727 ✗ expLst2 := makeASUBsForDimension(exp2);
1728 end if;
1729 //print("complexed expLst1:\n"+ExpressionDump.printExpListStr(expLst1)+"\n");
1730 //print("complexed expLst2:\n"+ExpressionDump.printExpListStr(expLst2)+"\n");
1731 ✗ ty := typeof(listHead(expLst1));
1732 ✗ expLst := List.threadMap(expLst1,expLst2,function makeBinaryExp(inOp=DAE.ADD(ty)));
1733 then
1734 expLst;
1735
1736 case DAE.CALL(expLst=expLst)
1737 algorithm
1738 22068 expLstLst := List.map(expLst,getComplexContentsInCall);
1739 22068 expLst := List.flatten(expLstLst);
1740 then
1741 expLst;
1742 case DAE.RECORD(exps=expLst)
1743 algorithm
1744 4262 expLstLst := List.map(expLst,getComplexContentsInCall);
1745 4262 expLst := List.flatten(expLstLst);
1746 then
1747 expLst;
1748 case DAE.ARRAY()
1749 algorithm
1750 2887 expLst := arrayElements(e);
1751 then
1752 expLst;
1753 case DAE.MATRIX(matrix=expLstLst)
1754 algorithm
1755 833 expLst := List.flatten(expLstLst);
1756 then
1757 expLst;
1758 case DAE.TUPLE(PR=expLst)
1759 then
1760 expLst;
1761 case DAE.CAST(exp=exp)
1762 algorithm
1763 14 expLst := getComplexContents(exp);
1764 then
1765 expLst;
1766 case DAE.ASUB(exp=exp)
1767 algorithm
1768 ✗ expLst := getComplexContents(exp);
1769 then
1770 expLst;
1771 else {};
1772 end matchcontinue;
1773 end getComplexContents;
1774
1775 protected function getComplexContentsInCall"gets the scalars for the complex expressions inside a function call"
1776 input DAE.Exp expIn;
1777 output list<DAE.Exp> expsOut;
1778 protected
1779 list<DAE.Exp> expLst;
1780 algorithm
1781 87290 expLst := getComplexContents(expIn);
1782
2/2
✓ Branch 0 taken 83595 times.
✓ Branch 1 taken 3695 times.
87290 expsOut := if listEmpty(expLst) then {expIn} else expLst;
1783 end getComplexContentsInCall;
1784
1785 public function getArrayOrRangeContents "returns the list of expressions in the array"
1786 input DAE.Exp e;
1787 output list<DAE.Exp> es;
1788 algorithm
1789 es := match e
1790 local
1791 Boolean bstart,bstop;
1792 Integer istart,istep,istop;
1793 Real rstart,rstep,rstop;
1794 list<list<DAE.Exp>> matrix;
1795 DAE.Type ty;
1796 case DAE.ARRAY(array=es) then es;
1797 case DAE.MATRIX(matrix=matrix,ty=ty)
1798 algorithm
1799 ✗ ty := Types.unliftArray(ty);
1800 ✗ es := List.map2(matrix,makeArray,ty,not Types.arrayType(ty));
1801 then es;
1802 case DAE.CREF(ty=DAE.T_ARRAY(dims=DAE.DIM_INTEGER(istop)::_))
1803 algorithm
1804 30 es := List.map(ExpressionSimplify.simplifyRange(1,1,istop), makeIntegerExp);
1805 30 es := List.map1r(es, makeASUBSingleSub, e);
1806 then es;
1807 case DAE.RANGE(start = DAE.BCONST(bstart), step = NONE(), stop = DAE.BCONST(bstop))
1808 ✗ then List.map(ExpressionSimplify.simplifyRangeBool(bstart, bstop), makeBoolExp);
1809
1810 case DAE.RANGE(start = DAE.ICONST(istart), step = NONE(), stop = DAE.ICONST(istop))
1811 392 then List.map(ExpressionSimplify.simplifyRange(istart,1,istop), makeIntegerExp);
1812
1813 case DAE.RANGE(start = DAE.ICONST(istart), step = SOME(DAE.ICONST(istep)), stop = DAE.ICONST(istop))
1814 ✗ then List.map(ExpressionSimplify.simplifyRange(istart,istep,istop), makeIntegerExp);
1815
1816 case DAE.RANGE(start = DAE.RCONST(rstart), step = NONE(), stop = DAE.RCONST(rstop))
1817 ✗ then List.map(ExpressionSimplify.simplifyRangeReal(rstart,1.0,rstop), makeRealExp);
1818
1819 case DAE.RANGE(start = DAE.RCONST(rstart), step = SOME(DAE.RCONST(rstep)), stop = DAE.RCONST(rstop))
1820 ✗ then List.map(ExpressionSimplify.simplifyRangeReal(rstart,rstep,rstop), makeRealExp);
1821 end match;
1822 end getArrayOrRangeContents;
1823
1824 public function get2dArrayOrMatrixContent "returns the list of expressions in the array"
1825 input DAE.Exp e;
1826 output list<list<DAE.Exp>> outExps;
1827 algorithm
1828 outExps := match e
1829 local
1830 list<DAE.Exp> es;
1831 list<list<DAE.Exp>> ess;
1832 8076 case DAE.ARRAY(array=es) then List.map(es,getArrayContents);
1833 case DAE.MATRIX(matrix=ess) then ess;
1834 end match;
1835 end get2dArrayOrMatrixContent;
1836
1837 // stefan
1838 public function unboxExpType
1839 "takes a type, and if it is boxed, unbox it
1840 otherwise return the given type"
1841 input DAE.Type inType;
1842 output DAE.Type outType;
1843 algorithm
1844 outType := match inType
1845 local
1846 Type ty;
1847 case DAE.T_METABOXED(ty = ty) then ty;
1848 else inType;
1849 end match;
1850 end unboxExpType;
1851
1852 public function unboxExp
1853 "takes an expression and unboxes it if it is boxed"
1854 input DAE.Exp ie;
1855 output DAE.Exp outExp;
1856 algorithm
1857 outExp := match ie
1858 local
1859 DAE.Exp e;
1860 97 case DAE.BOX(e) then unboxExp(e);
1861 else ie;
1862 end match;
1863 end unboxExp;
1864
1865 public function boxExp
1866 "takes an expression and boxes it"
1867 input DAE.Exp e;
1868 output DAE.Exp outExp;
1869 algorithm
1870 outExp := match e
1871 case DAE.BOX(_) then e;
1872 36346 else DAE.BOX(e);
1873 end match;
1874 end boxExp;
1875
1876 public function getSubscriptExp
1877 "Returns the subscript expression, or fails on DAE.WHOLEDIM."
1878 input DAE.Subscript inSubscript;
1879 output DAE.Exp outExp;
1880 algorithm
1881 outExp := match inSubscript
1882 local DAE.Exp e;
1883
1884 case DAE.SLICE(exp = e) then e;
1885 case DAE.INDEX(exp = e) then e;
1886 case DAE.WHOLE_NONEXP(exp = e) then e;
1887 end match;
1888 end getSubscriptExp;
1889
1890 public function subscriptNonExpandedExp
1891 "Returns the expression in a subscript representing non-expanded array.
1892 If the subscript is not WHOLE_NONEXP the function fails."
1893 input DAE.Subscript inSubscript;
1894 output DAE.Exp outExp;
1895 algorithm
1896 outExp:=
1897 match inSubscript
1898 local DAE.Exp e;
1899 case DAE.WHOLE_NONEXP(exp = e) then e;
1900 end match;
1901 end subscriptNonExpandedExp;
1902
1903 public function subscriptIsFirst
1904 "Returns true if the given subscript is the first index for a dimension, i.e.
1905 1, false or the first enumeration literal in an enumeration."
1906 input DAE.Subscript inSubscript;
1907 output Boolean outIsFirst;
1908 algorithm
1909 outIsFirst := match inSubscript
1910 case DAE.INDEX(exp=DAE.ICONST(1)) then true;
1911 case DAE.INDEX(exp=DAE.BCONST(false)) then true;
1912 case DAE.INDEX(exp=DAE.ENUM_LITERAL(index=1)) then true;
1913 end match;
1914 end subscriptIsFirst;
1915
1916 public function nthArrayExp "author: PA
1917 Returns the nth expression of an array expression."
1918 input DAE.Exp inExp;
1919 input Integer inInteger;
1920 output DAE.Exp outExp;
1921 algorithm
1922 outExp := matchcontinue inExp
1923 local
1924 DAE.Exp e1, e2, e_1, e_2;
1925 list<DAE.Exp> expl;
1926 Operator op;
1927 Type ty;
1928
1929 case DAE.BINARY(operator=op, exp1=e1, exp2=e2) algorithm
1930 216 ty := typeofOp(op);
1931
2/2
✓ Branch 1 taken 84 times.
✓ Branch 2 taken 132 times.
216 true := Types.isArray(ty);
1932 132 e_1 := nthArrayExp(e1, inInteger);
1933 132 e_2 := nthArrayExp(e2, inInteger);
1934 132 then DAE.BINARY(e_1, op, e_2);
1935
1936 case DAE.ARRAY(array=expl) algorithm
1937 576 e1 := listGet(expl, inInteger);
1938 then e1;
1939
1940 else inExp;
1941 end matchcontinue;
1942 end nthArrayExp;
1943
1944 public function expLastSubs
1945 "Return the last subscripts of a Exp"
1946 input DAE.Exp inExp;
1947 output list<DAE.Subscript> outSubscriptLst;
1948 algorithm
1949 outSubscriptLst:=
1950 match inExp
1951 local
1952 ComponentRef cr;
1953 list<DAE.Subscript> subs;
1954 DAE.Exp e;
1955
1956 case DAE.CREF(componentRef=cr)
1957 algorithm
1958 ✗ subs := ComponentReference.crefLastSubs(cr);
1959 then subs;
1960
1961 case DAE.UNARY(exp=e)
1962 algorithm
1963 ✗ subs := expLastSubs(e);
1964 then subs;
1965 end match;
1966 end expLastSubs;
1967
1968 public function expDimensions
1969 "Tries to return the dimensions from an expression, typically an array."
1970 input DAE.Exp inExp;
1971 output DAE.Dimensions outDims;
1972 algorithm
1973 outDims := match inExp
1974 local
1975 DAE.Type tp;
1976 Exp e;
1977
1978 9 case DAE.ARRAY(ty = tp) then arrayDimension(tp);
1979 ✗ case DAE.MATRIX(ty = tp) then arrayDimension(tp);
1980 ✗ case DAE.LUNARY(exp = e) then expDimensions(e);
1981 ✗ case DAE.LBINARY(exp1 = e) then expDimensions(e);
1982 ✗ case DAE.CALL(attr=DAE.CALL_ATTR(ty = tp)) then arrayDimension(tp);
1983
1984 end match;
1985 end expDimensions;
1986
1987 public function arrayDimension "
1988 Author BZ
1989 Get dimension of array.
1990 "
1991 input DAE.Type tp;
1992 output DAE.Dimensions dims;
1993 algorithm
1994 dims := match tp
1995 case DAE.T_ARRAY(dims = dims) then dims;
1996 else {};
1997 end match;
1998 end arrayDimension;
1999
2000 public function arrayTypeDimensions
2001 "Return the array dimensions of a type."
2002 input DAE.Type tp;
2003 output DAE.Dimensions dims;
2004 algorithm
2005 dims := match tp
2006 case DAE.T_ARRAY(dims = dims) then dims;
2007 end match;
2008 end arrayTypeDimensions;
2009
2010 public function subscriptDimensions
2011 "Converts a list of subscript to a list of dimensions."
2012 input list<DAE.Subscript> inSubscripts;
2013 output DAE.Dimensions outDimensions;
2014 algorithm
2015 40 outDimensions := List.map(inSubscripts, subscriptDimension);
2016 end subscriptDimensions;
2017
2018 public function subscriptDimension
2019 "Converts a subscript to a dimension by interpreting the subscript as a
2020 dimension."
2021 input DAE.Subscript inSubscript;
2022 output DAE.Dimension outDimension;
2023 algorithm
2024 outDimension := match inSubscript
2025 local
2026 Integer x;
2027 DAE.Exp e;
2028 String sub_str;
2029
2030 ✗ case DAE.INDEX(exp = DAE.ICONST(x)) then DAE.DIM_INTEGER(x);
2031 4 case DAE.INDEX(exp = e) then DAE.DIM_EXP(e);
2032 case DAE.WHOLEDIM() then DAE.DIM_UNKNOWN();
2033
2034 // Special cases for non-expanded arrays
2035 case DAE.WHOLE_NONEXP(exp = DAE.ICONST(x))
2036 guard not Config.splitArrays()
2037 ✗ then
2038 DAE.DIM_INTEGER(x);
2039
2040 case DAE.WHOLE_NONEXP(exp=e)
2041 guard not Config.splitArrays()
2042 ✗ then
2043 DAE.DIM_EXP(e);
2044
2045 else
2046 algorithm
2047 ✗ true := Flags.isSet(Flags.FAILTRACE);
2048 ✗ sub_str := ExpressionDump.subscriptString(inSubscript);
2049 ✗ Debug.traceln("- Expression.subscriptDimension failed on " + sub_str);
2050 ✗ then
2051 fail();
2052
2053 end match;
2054 end subscriptDimension;
2055
2056 public function arrayEltType
2057 " Returns the element type of an array expression."
2058 input DAE.Type inType;
2059 output DAE.Type outType;
2060 algorithm
2061 outType := match inType
2062 local Type t;
2063 40697 case DAE.T_ARRAY(ty = t) then arrayEltType(t);
2064 else inType;
2065 end match;
2066 end arrayEltType;
2067
2068 public function sizeOf
2069 "Returns the size of a type."
2070 input DAE.Type inType;
2071 output Integer i;
2072 algorithm
2073 i := matchcontinue inType
2074 // count the variables in array
2075 case DAE.T_ARRAY()
2076
4/4
✓ Branch 0 taken 24796 times.
✓ Branch 1 taken 21014 times.
✓ Branch 2 taken 24796 times.
✓ Branch 3 taken 21014 times.
45810 then sizeOf(inType.ty) * product(dimensionSize(d) for d in inType.dims);
2077
2078 case DAE.T_COMPLEX(complexClassType = ClassInf.EXTERNAL_OBJ()) then 0;
2079
2080 // count the variables in record
2081
4/4
✓ Branch 0 taken 36018 times.
✓ Branch 1 taken 4566 times.
✓ Branch 2 taken 36018 times.
✓ Branch 3 taken 4566 times.
40584 case DAE.T_COMPLEX() then sum(sizeOf(varType(v)) for v in inType.varLst);
2082
4/4
✓ Branch 0 taken 12368 times.
✓ Branch 1 taken 2414 times.
✓ Branch 2 taken 12368 times.
✓ Branch 3 taken 2414 times.
14782 case DAE.T_TUPLE() then sum(sizeOf(ty) for ty in inType.types);
2083 ✗ case DAE.T_FUNCTION() then sizeOf(inType.funcResultType);
2084 ✗ case DAE.T_METATYPE() then sizeOf(inType.ty);
2085
2086 // 0 for T_UNKNOWN as it can only appear in tuples for WILD()??!!
2087 case DAE.T_UNKNOWN() then 0;
2088
2089 // for all other consider it just 1 variable
2090 else 1;
2091 end matchcontinue;
2092 end sizeOf;
2093
2094 public function dimensionSize
2095 "Extracts an integer from an array dimension"
2096 input DAE.Dimension dim;
2097 output Integer value;
2098 algorithm
2099 value := match dim
2100 local
2101 Integer i;
2102 case DAE.DIM_INTEGER(integer = i) then i;
2103 case DAE.DIM_ENUM(size = i) then i;
2104 case DAE.DIM_BOOLEAN() then 2;
2105 case DAE.DIM_EXP(exp = DAE.ICONST(integer = i)) then i;
2106 case DAE.DIM_EXP(exp = DAE.ENUM_LITERAL(index = i)) then i;
2107 // else algorithm
2108 // Error.addInternalError("Function dimensionSize failed to extract size from dimension. Make sure
2109 // you have dimension that is evaluated if you want to use this function.", sourceInfo());
2110 // then fail();
2111 end match;
2112 end dimensionSize;
2113
2114 public function addDimensions
2115 input DAE.Dimension dim1;
2116 input DAE.Dimension dim2;
2117 output DAE.Dimension dim;
2118 algorithm
2119 dim := matchcontinue dim2
2120 local
2121 Integer i;
2122 case _
2123 algorithm
2124 1700 i := dimensionSize(dim1)+dimensionSize(dim2);
2125 1700 then DAE.DIM_INTEGER(i);
2126 else DAE.DIM_UNKNOWN();
2127 end matchcontinue;
2128 end addDimensions;
2129
2130 public function dimensionSizeAll
2131 "Extracts an integer from an array dimension. Also handles DIM_EXP and
2132 DIM_UNKNOWN if checkModel is used."
2133 input DAE.Dimension dim;
2134 output Integer value;
2135 algorithm
2136 value := matchcontinue dim
2137 local
2138 Integer i;
2139 DAE.Exp e;
2140 case DAE.DIM_INTEGER(integer = i) then i;
2141 case DAE.DIM_ENUM(size = i) then i;
2142 case DAE.DIM_BOOLEAN() then 2;
2143 64 case DAE.DIM_EXP(exp = e) then expInt(e);
2144 case DAE.DIM_EXP()
2145 algorithm
2146
1/2
✓ Branch 1 taken 64 times.
✗ Branch 2 not taken.
64 true := Flags.getConfigBool(Flags.CHECK_MODEL);
2147 then
2148 0;
2149 case DAE.DIM_UNKNOWN()
2150 algorithm
2151 ✗ true := Flags.getConfigBool(Flags.CHECK_MODEL);
2152 then
2153 0;
2154 end matchcontinue;
2155 end dimensionSizeAll;
2156
2157 public function dimensionsSizes
2158 "Extracts a list of integers from a list of array dimensions"
2159 input DAE.Dimensions inDims;
2160 output list<Integer> outValues;
2161 algorithm
2162 26401 outValues := List.map(inDims, dimensionSizeAll);
2163 end dimensionsSizes;
2164
2165 public function typeof "Retrieves the Type of the Expression"
2166 input DAE.Exp inExp;
2167 output DAE.Type outType;
2168 algorithm
2169 outType := matchcontinue inExp
2170 local
2171 Type tp;
2172 Operator op;
2173 DAE.Exp e2,e,iterExp,operExp;
2174 list<DAE.Exp> explist,exps;
2175 Absyn.Path p;
2176 String msg;
2177 DAE.Type ty, iterTp, operTp;
2178 list<DAE.Type> tys, typeVars;
2179 Integer i;
2180 DAE.Dimension dim;
2181 DAE.Dimensions iterdims;
2182 list<DAE.Subscript> subs;
2183
2184 case DAE.ICONST() then DAE.T_INTEGER_DEFAULT;
2185 case DAE.RCONST() then DAE.T_REAL_DEFAULT;
2186 case DAE.SCONST() then DAE.T_STRING_DEFAULT;
2187 case DAE.BCONST() then DAE.T_BOOL_DEFAULT;
2188 case DAE.CLKCONST() then DAE.T_CLOCK_DEFAULT;
2189 19641 case DAE.ENUM_LITERAL(name = p, index=i) then DAE.T_ENUMERATION(SOME(i), p, {}, {}, {});
2190 case DAE.CREF(ty = tp) then tp;
2191 14304982 case DAE.BINARY(operator = op) then typeofOp(op);
2192 1397419 case DAE.UNARY(operator = op) then typeofOp(op);
2193 23486 case DAE.LBINARY(operator = op) then typeofOp(op);
2194 3505 case DAE.LUNARY(operator = op) then typeofOp(op);
2195 51670 case DAE.RELATION(operator = op) then typeofRelation(typeofOp(op));
2196 119292 case DAE.IFEXP(expThen = e2) then typeof(e2);
2197 case DAE.CALL(attr = DAE.CALL_ATTR(ty=tp)) then tp;
2198 case DAE.RECORD(ty=tp) then tp;
2199 case DAE.PARTEVALFUNCTION(ty=tp) then tp;
2200 case DAE.ARRAY(ty = tp) then tp;
2201 case DAE.MATRIX(ty = tp) then tp;
2202 case DAE.RANGE(ty = tp) then tp;
2203 case DAE.CAST(ty = tp) then tp;
2204 case DAE.ASUB(exp = e,sub=subs)
2205 algorithm
2206 // Count the number of scalar subscripts, and remove as many dimensions.
2207 // adrpo: for some reason we need to handle this differenlty for MetaModelica grammar
2208 // as if not we get errors such as:
2209 // [Types.mo:8694:9-8694:125:writable] Error: Internal error Types.getMetaRecordFields
2210 // called on a non-singleton uniontype: array<BackendDAE.SubPartition>
2211
2/2
✓ Branch 1 taken 214 times.
✓ Branch 2 taken 70048 times.
70262 if Config.acceptMetaModelicaGrammar() then
2212
4/4
✓ Branch 0 taken 214 times.
✓ Branch 1 taken 214 times.
✓ Branch 2 taken 214 times.
✓ Branch 3 taken 214 times.
428 explist := list(Expression.getSubscriptExp(sub) for sub in subs);
2213
5/6
✗ Branch 1 not taken.
✓ Branch 2 taken 214 times.
✓ Branch 3 taken 214 times.
✓ Branch 4 taken 214 times.
✓ Branch 5 taken 214 times.
✓ Branch 6 taken 214 times.
428 i := sum(1 for e guard(isScalar(e)) in explist);
2214 else
2215
6/6
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 78906 times.
✓ Branch 3 taken 78909 times.
✓ Branch 4 taken 70048 times.
✓ Branch 5 taken 78906 times.
✓ Branch 6 taken 70048 times.
148957 i := sum(1 for sub guard(isScalarSubscript(sub)) in subs);
2216 end if;
2217 70262 tp := unliftArrayX(typeof(e), i);
2218 then
2219 tp;
2220 case DAE.TSUB(ty = tp) then tp;
2221 15200 case DAE.RSUB() then inExp.ty;
2222 case DAE.CODE(ty = tp) then tp;
2223 /* array reduction with known size */
2224 case DAE.REDUCTION(iterators={DAE.REDUCTIONITER(exp=iterExp,guardExp=NONE())},expr = operExp, reductionInfo=DAE.REDUCTIONINFO(exprType=DAE.T_ARRAY(dims=dim::_),path = Absyn.IDENT("array")))
2225 algorithm
2226
2/2
✓ Branch 1 taken 72 times.
✓ Branch 2 taken 143 times.
215 false := dimensionKnown(dim);
2227 143 iterTp := typeof(iterExp);
2228 143 operTp := typeof(operExp);
2229
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 139 times.
143 DAE.T_ARRAY(dims=iterdims) := iterTp;
2230 139 tp := Types.liftTypeWithDims(operTp, iterdims);
2231 then tp;
2232 case DAE.REDUCTION(reductionInfo=DAE.REDUCTIONINFO(exprType=ty))
2233 488 then Types.simplifyType(ty);
2234 case DAE.SIZE(_,NONE()) then DAE.T_ARRAY(DAE.T_INTEGER_DEFAULT,{DAE.DIM_UNKNOWN()});
2235 case DAE.SIZE(_,SOME(_)) then DAE.T_INTEGER_DEFAULT;
2236
2237 // MetaModelica extension
2238 case DAE.LIST() then DAE.T_METATYPE(DAE.T_METALIST_DEFAULT);
2239 case DAE.CONS() then DAE.T_METATYPE(DAE.T_METALIST_DEFAULT);
2240 case DAE.META_TUPLE(exps)
2241 algorithm
2242 99 tys := List.map(exps, typeof);
2243 99 then
2244 DAE.T_METATYPE(DAE.T_METATUPLE(tys));
2245 case DAE.TUPLE(exps)
2246 algorithm
2247 8074 tys := List.map(exps, typeof);
2248 8074 then DAE.T_TUPLE(tys, NONE());
2249 case DAE.META_OPTION() then DAE.T_METATYPE(DAE.T_NONE_DEFAULT);
2250 case DAE.METARECORDCALL(path=p, index = i, typeVars=typeVars)
2251 14662 then DAE.T_METATYPE(DAE.T_METARECORD(p, AbsynUtil.stripLast(p), typeVars, i, {}, false));
2252 case DAE.BOX(e)
2253 90 then DAE.T_METATYPE(DAE.T_METABOXED(typeof(e)));
2254 case DAE.MATCHEXPRESSION(et=tp)
2255 then tp;
2256 case DAE.UNBOX(ty = tp) then tp;
2257 1769 case DAE.SHARED_LITERAL(exp = e) then typeof(e);
2258 // A little crazy, but sometimes we call typeof on things that will not be used in the end...
2259 case DAE.EMPTY(ty = tp) then tp;
2260
2261 case e
2262 algorithm
2263 ✗ msg := "- Expression.typeof failed for " + ExpressionBasics.printExpStr(e);
2264 ✗ Error.addMessage(Error.INTERNAL_ERROR, {msg});
2265 ✗ then fail();
2266 end matchcontinue;
2267 end typeof;
2268
2269 protected function typeofRelation
2270 "Boolean or array of boolean"
2271 input DAE.Type inType;
2272 output DAE.Type outType;
2273 algorithm
2274 outType := match inType
2275 local
2276 Type ty;
2277 DAE.Dimensions dims;
2278 case DAE.T_ARRAY(ty=ty,dims=dims)
2279 algorithm
2280 ✗ typeofRelation(ty);
2281 ✗ then
2282 DAE.T_ARRAY(ty,dims);
2283 else DAE.T_BOOL_DEFAULT;
2284 end match;
2285 end typeofRelation;
2286
2287 public function typeofOp
2288 "Helper function to typeof"
2289 input DAE.Operator inOperator;
2290 output DAE.Type outType;
2291 algorithm
2292 outType := match inOperator
2293 local Type t;
2294
2295 case DAE.ADD(ty = t) then t;
2296 case DAE.SUB(ty = t) then t;
2297 case DAE.MUL(ty = t) then t;
2298 case DAE.DIV(ty = t) then t;
2299 case DAE.POW(ty = t) then t;
2300 case DAE.UMINUS(ty = t) then t;
2301 case DAE.UMINUS_ARR(ty = t) then t;
2302 case DAE.ADD_ARR(ty = t) then t;
2303 case DAE.SUB_ARR(ty = t) then t;
2304 case DAE.MUL_ARR(ty = t) then t;
2305 case DAE.DIV_ARR(ty = t) then t;
2306 case DAE.MUL_ARRAY_SCALAR(ty = t) then t;
2307 case DAE.ADD_ARRAY_SCALAR(ty = t) then t;
2308 case DAE.SUB_SCALAR_ARRAY(ty = t) then t;
2309 case DAE.MUL_SCALAR_PRODUCT(ty = t) then t;
2310 case DAE.MUL_MATRIX_PRODUCT(ty = t) then t;
2311 case DAE.DIV_ARRAY_SCALAR(ty = t) then t;
2312 case DAE.DIV_SCALAR_ARRAY(ty = t) then t;
2313 case DAE.POW_ARRAY_SCALAR(ty = t) then t;
2314 case DAE.POW_SCALAR_ARRAY(ty = t) then t;
2315 case DAE.POW_ARR(ty = t) then t;
2316 case DAE.POW_ARR2(ty = t) then t;
2317 case DAE.AND(ty = t) then t;
2318 case DAE.OR(ty = t) then t;
2319 case DAE.NOT(ty = t) then t;
2320 case DAE.LESS(ty = t) then t;
2321 case DAE.LESSEQ(ty = t) then t;
2322 case DAE.GREATER(ty = t) then t;
2323 case DAE.GREATEREQ(ty = t) then t;
2324 case DAE.EQUAL(ty = t) then t;
2325 case DAE.NEQUAL(ty = t) then t;
2326 case DAE.USERDEFINED() then DAE.T_UNKNOWN_DEFAULT;
2327 end match;
2328 end typeofOp;
2329
2330 public function getRelations
2331 "Retrieve all function sub expressions in an expression."
2332 input DAE.Exp inExp;
2333 output list<DAE.Exp> outExpLst;
2334 algorithm
2335 outExpLst := match inExp
2336 local
2337 DAE.Exp e,e1,e2,cond,tb,fb;
2338 list<DAE.Exp> rellst1,rellst2,rellst,rellst3,rellst4,xs;
2339 Type t;
2340 Boolean sc;
2341
2342 case e as DAE.RELATION() then {e};
2343
2344 case DAE.LBINARY(exp1 = e1,exp2 = e2)
2345 algorithm
2346 ✗ rellst1 := getRelations(e1);
2347 ✗ rellst2 := getRelations(e2);
2348 ✗ rellst := listAppend(rellst1, rellst2);
2349 then
2350 rellst;
2351
2352 case DAE.LUNARY(exp = e)
2353 algorithm
2354 ✗ rellst := getRelations(e);
2355 then
2356 rellst;
2357
2358 case DAE.BINARY(exp1 = e1,exp2 = e2)
2359 algorithm
2360 ✗ rellst1 := getRelations(e1);
2361 ✗ rellst2 := getRelations(e2);
2362 ✗ rellst := listAppend(rellst1, rellst2);
2363 then
2364 rellst;
2365
2366 case DAE.IFEXP(expCond = cond,expThen = tb,expElse = fb)
2367 algorithm
2368 ✗ rellst1 := getRelations(cond);
2369 ✗ rellst2 := getRelations(tb);
2370 ✗ rellst3 := getRelations(fb);
2371 ✗ rellst4 := listAppend(rellst1, rellst2);
2372 ✗ rellst := listAppend(rellst3, rellst4);
2373 then
2374 rellst;
2375
2376 case DAE.ARRAY(array = {e})
2377 algorithm
2378 ✗ rellst := getRelations(e);
2379 then
2380 rellst;
2381
2382 case DAE.ARRAY(ty = t,scalar = sc,array = (e :: xs))
2383 algorithm
2384 ✗ rellst1 := getRelations(DAE.ARRAY(t,sc,xs));
2385 ✗ rellst2 := getRelations(e);
2386 ✗ rellst := listAppend(rellst1, rellst2);
2387 then
2388 rellst;
2389
2390 case DAE.UNARY(exp = e)
2391 algorithm
2392 ✗ rellst := getRelations(e);
2393 then
2394 rellst;
2395
2396 else {};
2397 end match;
2398 end getRelations;
2399
2400 public function getAllCrefs "author: lochel
2401 This function extracts all crefs from the input expression, except 'time'."
2402 input DAE.Exp inExp;
2403 output list<DAE.ComponentRef> outCrefs;
2404 algorithm
2405 145829 (_, outCrefs) := traverseExpBottomUp(inExp, getAllCrefs2, {});
2406 end getAllCrefs;
2407
2408 protected function getAllCrefs2
2409 input DAE.Exp inExp;
2410 input list<DAE.ComponentRef> inCrefList;
2411 output DAE.Exp outExp = inExp;
2412 output list<DAE.ComponentRef> outCrefList = inCrefList;
2413 protected
2414 DAE.ComponentRef cr;
2415 algorithm
2416
2/2
✓ Branch 1 taken 328376 times.
✓ Branch 2 taken 96844 times.
425220 if isCref(inExp) then
2417
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96844 times.
96844 DAE.CREF(componentRef=cr) := inExp;
2418
4/4
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 96836 times.
✓ Branch 4 taken 2588 times.
✓ Branch 5 taken 94248 times.
96844 if not ComponentReferenceBasics.crefEqual(cr, DAE.crefTime) and not listMember(cr, inCrefList) then
2419 outCrefList := cr::outCrefList;
2420 end if;
2421 end if;
2422 end getAllCrefs2;
2423
2424 public function allTerms
2425 "similar to terms, but also performs expansion of
2426 multiplications to reveal more terms, like for instance:
2427 allTerms((a+b)*(b+c)) => {a*b,a*c,b*b,b*c}"
2428 input DAE.Exp inExp;
2429 output list<DAE.Exp> outExpLst;
2430 algorithm
2431 outExpLst := matchcontinue inExp
2432 local
2433 list<DAE.Exp> f1,f2,res,f2_1;
2434 DAE.Exp e1,e2;
2435 list<DAE.Subscript> subs;
2436
2437 case DAE.BINARY(exp1 = e1,operator = DAE.ADD(),exp2 = e2)
2438 algorithm
2439 ✗ f1 := allTerms(e1);
2440 ✗ f2 := allTerms(e2);
2441 ✗ res := listAppend(f1, f2);
2442 then
2443 res;
2444
2445 case DAE.BINARY(exp1 = e1,operator = DAE.SUB(),exp2 = e2)
2446 algorithm
2447 ✗ f1 := allTerms(e1);
2448 ✗ f2 := allTerms(e2);
2449 ✗ f2_1 := List.map(f2, negate);
2450 ✗ res := listAppend(f1, f2_1);
2451 then
2452 res;
2453
2454 case DAE.BINARY(exp1 = e1,operator = DAE.ADD_ARR(),exp2 = e2)
2455 algorithm
2456 ✗ f1 := allTerms(e1);
2457 ✗ f2 := allTerms(e2);
2458 ✗ res := listAppend(f1, f2);
2459 then
2460 res;
2461
2462 case DAE.BINARY(exp1 = e1,operator = DAE.SUB_ARR(),exp2 = e2)
2463 algorithm
2464 ✗ f1 := allTerms(e1);
2465 ✗ f2 := allTerms(e2);
2466 ✗ f2_1 := List.map(f2, negate);
2467 ✗ res := listAppend(f1, f2_1);
2468 then
2469 res;
2470
2471 // terms( a*(b+c)) => {a*b, c*b}
2472 case DAE.BINARY(e1,DAE.MUL(_),e2)
2473 algorithm
2474 ✗ f1 as _::_::_ := allTerms(e2);
2475 ✗ f1 := List.map1(f1,makeProduct,e1);
2476 ✗ f1 := List.flatten(List.map(f1,allTerms));
2477 then
2478 f1;
2479
2480 case DAE.BINARY(e1,DAE.MUL_ARR(_),e2)
2481 algorithm
2482 ✗ f1 as _::_::_ := allTerms(e2);
2483 ✗ f1 := List.map1(f1,makeProduct,e1);
2484 ✗ f1 := List.flatten(List.map(f1,allTerms));
2485 then
2486 f1;
2487
2488 case DAE.BINARY(e1,DAE.MUL_ARRAY_SCALAR(_),e2)
2489 algorithm
2490 ✗ f1 as _::_::_ := allTerms(e2);
2491 ✗ f1 := List.map1(f1,makeProduct,e1);
2492 ✗ f1 := List.flatten(List.map(f1,allTerms));
2493 then
2494 f1;
2495
2496 // terms( (b+c)*a) => {b*a, c*a}
2497 case DAE.BINARY(e1,DAE.MUL(_),e2)
2498 algorithm
2499 ✗ f1 as _::_::_ := allTerms(e1);
2500 ✗ f1 := List.map1(f1,makeProduct,e2);
2501 ✗ f1 := List.flatten(List.map(f1,allTerms));
2502 then
2503 f1;
2504
2505 case DAE.BINARY(e1,DAE.MUL_ARR(_),e2)
2506 algorithm
2507 ✗ f1 as _::_::_ := allTerms(e1);
2508 ✗ f1 := List.map1(f1,makeProduct,e2);
2509 ✗ f1 := List.flatten(List.map(f1,allTerms));
2510 then
2511 f1;
2512
2513 case DAE.BINARY(e1,DAE.MUL_ARRAY_SCALAR(_),e2)
2514 algorithm
2515 ✗ f1 as _::_::_ := allTerms(e1);
2516 ✗ f1 := List.map1(f1,makeProduct,e2);
2517 ✗ f1 := List.flatten(List.map(f1,allTerms));
2518 then
2519 f1;
2520
2521 // terms( (b+c)/a) => {b/a, c/a}
2522 case DAE.BINARY(e1,DAE.DIV(_),e2)
2523 algorithm
2524 ✗ f1 as _::_::_ := allTerms(e1);
2525 ✗ f1 := List.map1(f1,expDiv,e2);
2526 ✗ f1 := List.flatten(List.map(f1,allTerms));
2527 then
2528 f1;
2529
2530 case DAE.BINARY(e1,DAE.DIV_ARR(_),e2)
2531 algorithm
2532 ✗ f1 as _::_::_ := allTerms(e1);
2533 ✗ f1 := List.map1(f1,expDiv,e2);
2534 ✗ f1 := List.flatten(List.map(f1,allTerms));
2535 then
2536 f1;
2537
2538 case DAE.BINARY(e1,DAE.DIV_ARRAY_SCALAR(_),e2)
2539 algorithm
2540 ✗ f1 as _::_::_ := allTerms(e1);
2541 ✗ f1 := List.map1(f1,expDiv,e2);
2542 ✗ f1 := List.flatten(List.map(f1,allTerms));
2543 then
2544 f1;
2545
2546 case DAE.BINARY(e1,DAE.DIV_SCALAR_ARRAY(_),e2)
2547 algorithm
2548 ✗ f1 as _::_::_ := allTerms(e1);
2549 ✗ f1 := List.map1(f1,expDiv,e2);
2550 ✗ f1 := List.flatten(List.map(f1,allTerms));
2551 then
2552 f1;
2553
2554 case DAE.UNARY(operator = DAE.UMINUS(),exp=e1)
2555 algorithm
2556 ✗ f1 := allTerms(e1);
2557 ✗ f1 := List.map(f1,negate);
2558 then
2559 f1;
2560
2561 case DAE.UNARY(operator = DAE.UMINUS_ARR(),exp=e1)
2562 algorithm
2563 ✗ f1 := allTerms(e1);
2564 ✗ f1 := List.map(f1,negate);
2565 then
2566 f1;
2567
2568 case DAE.LUNARY(operator = DAE.NOT(), exp = e1)
2569 algorithm
2570 ✗ f1 := allTerms(e1);
2571 ✗ f1 := List.map(f1,negate);
2572 then
2573 f1;
2574
2575 case DAE.ASUB(exp = e1,sub=subs)
2576 algorithm
2577 ✗ f2 := list(Expression.getSubscriptExp(sub) for sub in subs);
2578 ✗ f1 := allTerms(e1);
2579 ✗ f1 := List.map1(f1,makeASUB,f2);
2580 then
2581 f1;
2582 /*
2583 case (e as DAE.BINARY(operator = DAE.MUL())) then {e};
2584 case (e as DAE.BINARY(operator = DAE.MUL_ARR())) then {e};
2585 case (e as DAE.BINARY(operator = DAE.MUL_ARRAY_SCALAR())) then {e};
2586 case (e as DAE.BINARY(operator = DAE.DIV())) then {e};
2587 case (e as DAE.BINARY(operator = DAE.DIV_ARR())) then {e};
2588 case (e as DAE.BINARY(operator = DAE.DIV_ARRAY_SCALAR())) then {e};
2589 case (e as DAE.BINARY(operator = DAE.DIV_SCALAR_ARRAY())) then {e};
2590 case (e as DAE.BINARY(operator = DAE.POW())) then {e};
2591 case (e as DAE.BINARY(operator = DAE.POW_ARR())) then {e};
2592 case (e as DAE.BINARY(operator = DAE.POW_ARR2())) then {e};
2593 case (e as DAE.BINARY(operator = DAE.POW_ARRAY_SCALAR())) then {e};
2594 case (e as DAE.BINARY(operator = DAE.POW_SCALAR_ARRAY())) then {e};
2595 case (e as DAE.CREF()) then {e};
2596 case (e as DAE.ICONST()) then {e};
2597 case (e as DAE.RCONST()) then {e};
2598 case (e as DAE.SCONST()) then {e};
2599 case ((e as DAE.ENUM_LITERAL())) then {e};
2600 case (e as DAE.UNARY()) then {e};
2601 case (e as DAE.IFEXP()) then {e};
2602 case (e as DAE.CALL()) then {e};
2603 case (e as DAE.RECORD()) then {e};
2604 case (e as DAE.PARTEVALFUNCTION()) then {e};
2605 case (e as DAE.ARRAY()) then {e};
2606 case (e as DAE.MATRIX()) then {e};
2607 case (e as DAE.RANGE()) then {e};
2608 case (e as DAE.CAST()) then {e};
2609 case (e as DAE.ASUB()) then {e};
2610 case (e as DAE.SIZE()) then {e};
2611 case (e as DAE.REDUCTION()) then {e};
2612 */
2613 else {inExp};
2614 end matchcontinue;
2615 end allTerms;
2616
2617 public function allTermsForCref
2618 "simliar to terms, but also perform expansion of
2619 multiplications to reveal more terms, like for instance:
2620 allTerms((a(x)+b(x))*(c+d)) => {a(x)*(c+d),b(x)*(c+d)}"
2621 input DAE.Exp inExp;
2622 input DAE.ComponentRef cr "x";
2623 input MapFunc inFunc;
2624 output list<DAE.Exp> outExpLstWithX;
2625 output list<DAE.Exp> outExpLstWithoutX;
2626
2627 partial function MapFunc
2628 input DAE.Exp inElement;
2629 input DAE.ComponentRef inCr;
2630 output Boolean outElement;
2631 end MapFunc;
2632
2633 algorithm
2634 (outExpLstWithX,outExpLstWithoutX) := matchcontinue inExp
2635 local
2636 list<DAE.Exp> f1,f2,fx1,fx2,res,resx;
2637 DAE.Exp e1,e2,e;
2638
2639 case DAE.BINARY(exp1 = e1,operator = DAE.ADD(),exp2 = e2)
2640 algorithm
2641 34686 (fx1,f1) := allTermsForCref(e1, cr, inFunc);
2642 34686 (fx2,f2) := allTermsForCref(e2, cr, inFunc);
2643 34686 res := listAppend(f1, f2);
2644 34686 resx := listAppend(fx1, fx2);
2645 then
2646 (resx, res);
2647
2648 case DAE.BINARY(exp1 = e1,operator = DAE.SUB(),exp2 = e2)
2649 algorithm
2650 24722 (fx1,f1) := allTermsForCref(e1, cr, inFunc);
2651 24722 (fx2,f2) := allTermsForCref(e2, cr, inFunc);
2652 24722 f2 := List.map(f2, negate);
2653 24722 fx2 := List.map(fx2, negate);
2654 24722 res := listAppend(f1, f2);
2655 24722 resx := listAppend(fx1, fx2);
2656 then
2657 (resx,res);
2658
2659 case DAE.BINARY(exp1 = e1,operator = DAE.ADD_ARR(),exp2 = e2)
2660 algorithm
2661 ✗ (fx1,f1) := allTermsForCref(e1, cr, inFunc);
2662 ✗ (fx2,f2) := allTermsForCref(e2, cr, inFunc);
2663 ✗ res := listAppend(f1, f2);
2664 ✗ resx := listAppend(fx1, fx2);
2665 then
2666 (resx, res);
2667
2668 case DAE.BINARY(exp1 = e1,operator = DAE.SUB_ARR(),exp2 = e2)
2669 algorithm
2670 ✗ (fx1,f1) := allTermsForCref(e1, cr, inFunc);
2671 ✗ (fx2,f2) := allTermsForCref(e2, cr, inFunc);
2672 ✗ f2 := List.map(f2, negate);
2673 ✗ fx2 := List.map(fx2, negate);
2674 ✗ res := listAppend(f1, f2);
2675 ✗ resx := listAppend(fx1, fx2);
2676 then
2677 (resx,res);
2678
2679 // terms( a*(b+c)) => {a*b, c*b}
2680 case DAE.BINARY(e1,DAE.MUL(_),e2)
2681 guard inFunc(e2,cr)
2682 algorithm
2683 14953 (fx1, f1) := allTermsForCref(e2, cr, inFunc);
2684 14953 (fx1, f2) := List.split1OnTrue(fx1, inFunc, cr);
2685 14953 res := listAppend(f1, f2);
2686 14953 e := makeSum1(res);
2687 14953 e := expMul(e, e1);
2688 14953 fx1 := List.map1(fx1,expMul,e1);
2689
2/2
✓ Branch 1 taken 3834 times.
✓ Branch 2 taken 11119 times.
14953 if not isZero(e) then
2690
2/2
✓ Branch 1 taken 119 times.
✓ Branch 2 taken 3715 times.
3834 if expHasCrefNoPreOrStart(e1,cr) then
2691 fx1 := e :: fx1;
2692 119 f1 := {};
2693 else
2694 3715 f1 := {e};
2695 end if;
2696 end if;
2697 //f1 = List.flatten(List.map1(fx1,allTermsForCref, cr));
2698 14953 then
2699 (fx1, f1);
2700
2701 // terms( (b+c)*a) => {b*a, c*a}
2702 case DAE.BINARY(e1,DAE.MUL(_),e2)
2703 guard inFunc(e1,cr)
2704 algorithm
2705 2285 (fx1, f1) := allTermsForCref(e1, cr, inFunc);
2706 2285 (fx1, f2) := List.split1OnTrue(fx1, inFunc, cr);
2707 2285 res := listAppend(f1, f2);
2708 2285 e := makeSum1(res);
2709 2285 e := expMul(e, e2);
2710 2285 fx1 := List.map1(fx1,expMul,e2);
2711
2/2
✓ Branch 1 taken 1018 times.
✓ Branch 2 taken 1267 times.
2285 if not isZero(e) then
2712
1/2
✓ Branch 1 taken 1018 times.
✗ Branch 2 not taken.
1018 if expHasCrefNoPreOrStart(e1,cr) then
2713 fx1 := e :: fx1;
2714 1018 f1 := {};
2715 else
2716 ✗ f1 := {e};
2717 end if;
2718 end if;
2719 //fx1 = List.flatten(List.map1(fx1,allTermsForCref, cr));
2720 2285 then
2721 (fx1, f1);
2722
2723 // terms( (b+c)/a) => {b/a, c/a}
2724 case DAE.BINARY(e1,DAE.DIV(_),e2)
2725 guard inFunc(e1,cr)
2726 algorithm
2727 2554 (fx1, f1) := allTermsForCref(e1, cr, inFunc);
2728 2554 (fx1, f2) := List.split1OnTrue(fx1, inFunc, cr);
2729 2554 res := listAppend(f1, f2);
2730 2554 e := makeSum1(res);
2731 2554 e := makeDiv(e, e2);
2732 2554 fx1 := List.map1(fx1,makeDiv,e2);
2733
2/2
✓ Branch 1 taken 1333 times.
✓ Branch 2 taken 1221 times.
2554 if not isZero(e) then
2734
1/2
✓ Branch 1 taken 1333 times.
✗ Branch 2 not taken.
1333 if expHasCrefNoPreOrStart(e1,cr) then
2735 fx1 := e :: fx1;
2736 1333 f1 := {};
2737 else
2738 ✗ f1 := {e};
2739 end if;
2740 end if;
2741 //fx1 = List.flatten(List.map1(fx1,allTermsForCref, cr));
2742 2554 then
2743 (fx1, f1);
2744
2745 // -()
2746 case DAE.UNARY(operator = DAE.UMINUS(),exp=e1)
2747 algorithm
2748 8083 (fx1,f1) := allTermsForCref(e1, cr, inFunc);
2749 8083 f1 := List.map(f1,negate);
2750 8083 fx1 := List.map(fx1,negate);
2751 8083 then
2752 (fx1, f1);
2753
2754 else
2755 algorithm
2756
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 239575 times.
✓ Branch 4 taken 181808 times.
✓ Branch 5 taken 57767 times.
239575 if inFunc(inExp,cr) then
2757 res := {};
2758 resx := {inExp};
2759 else
2760 resx := {};
2761 res := {inExp};
2762 end if;
2763 then (resx, res);
2764 end matchcontinue;
2765 end allTermsForCref;
2766
2767
2768 public function termsExpandUnary
2769 "Returns the terms of the expression if any as a list of expressions"
2770 input DAE.Exp inExp;
2771 output list<DAE.Exp> outExpLst;
2772 algorithm
2773 outExpLst := match inExp
2774 local DAE.Exp e;
2775 2172 case DAE.UNARY(operator = DAE.UMINUS(),exp=e) then List.map(terms(e), negate);
2776 57144 else terms(inExp);
2777 end match;
2778 end termsExpandUnary;
2779
2780 public function terms
2781 "Returns the terms of the expression if any as a list of expressions"
2782 input DAE.Exp inExp;
2783 output list<DAE.Exp> outExpLst;
2784 algorithm
2785 4253423 outExpLst := terms2(inExp,{},false);
2786 end terms;
2787
2788 protected function terms2
2789 "Returns the terms of the expression if any as a list of expressions"
2790 input DAE.Exp inExp;
2791 input list<DAE.Exp> inAcc;
2792 input Boolean neg;
2793 output list<DAE.Exp> outExpLst;
2794 algorithm
2795 outExpLst := match (inExp,inAcc,neg)
2796 local
2797 DAE.Exp e1,e2,e;
2798 list<DAE.Exp> acc;
2799
2800 case (DAE.BINARY(exp1 = e1,operator = DAE.ADD(),exp2 = e2),acc,_)
2801 algorithm
2802 2709930 acc := terms2(e2,acc,neg);
2803 2709930 acc := terms2(e1,acc,neg);
2804 then acc;
2805
2806 case (DAE.BINARY(exp1 = e1,operator = DAE.SUB(),exp2 = e2),acc,_)
2807 algorithm
2808 1034540 acc := terms2(e2,acc,not neg);
2809 1034540 acc := terms2(e1,acc,neg);
2810 then acc;
2811
2812 case (e,acc,true)
2813 algorithm
2814 1025379 e := negate(e);
2815 then e::acc;
2816 case (e,acc,_) then e::acc;
2817 end match;
2818 end terms2;
2819
2820 public function quotient
2821 "author: PA
2822 Returns the quotient of an expression.
2823 For instance e = p/q returns (p,q) for numerator p and denominator q."
2824 input DAE.Exp inExp;
2825 output DAE.Exp num;
2826 output DAE.Exp denom;
2827 algorithm
2828 (num,denom):=
2829 matchcontinue inExp
2830 local
2831 DAE.Exp e1,e2,p,q;
2832 Type tp;
2833 case DAE.BINARY(exp1 = e1,operator = DAE.DIV(),exp2 = e2) then (e1,e2); /* (numerator,denominator) */
2834 case DAE.BINARY(exp1 = e1,operator = DAE.MUL(),exp2 = e2)
2835 algorithm
2836 ✗ (p,q) := quotient(e1);
2837 ✗ tp := typeof(p);
2838 ✗ then
2839 (DAE.BINARY(e2,DAE.MUL(tp),p),q);
2840 case DAE.BINARY(exp1 = e1,operator = DAE.MUL(),exp2 = e2)
2841 algorithm
2842 ✗ (p,q) := quotient(e2);
2843 ✗ tp := typeof(p);
2844 ✗ then
2845 (DAE.BINARY(e1,DAE.MUL(tp),p),q);
2846 end matchcontinue;
2847 end quotient;
2848
2849 public function factors
2850 "Returns the factors of the expression if any as a list of expressions"
2851 input DAE.Exp inExp;
2852 output list<DAE.Exp> outExpLst;
2853 algorithm
2854 // TODO: Remove this listReverse as it is pointless.
2855 // It transforms a*b to b*a, but the testsuite expects this :(
2856 8620897 outExpLst := listReverse(factorsWork(inExp,{},false));
2857 end factors;
2858
2859 protected function factorsWork
2860 "Returns the factors of the expression if any as a list of expressions"
2861 input DAE.Exp inExp;
2862 input output list<DAE.Exp> acc;
2863 input Boolean doInverseFactors "Decides if a factor e should be 1/e instead";
2864 algorithm
2865 acc := match inExp
2866 local
2867 DAE.Exp e1,e2;
2868
2869 case DAE.BINARY(exp1 = e1,operator = DAE.MUL(),exp2 = e2)
2870 algorithm
2871 7073460 acc := factorsWork(e1,acc,doInverseFactors);
2872 7073460 acc := factorsWork(e2,acc,doInverseFactors);
2873 then acc;
2874 case DAE.BINARY(exp1 = e1,operator = DAE.DIV(ty = DAE.T_REAL()),exp2 = e2)
2875 algorithm
2876 363311 acc := factorsWork(e1,acc,doInverseFactors);
2877 363311 acc := factorsWork(e2,acc,not doInverseFactors);
2878 then acc;
2879 case DAE.ICONST(integer = 1)
2880 then acc;
2881 case DAE.RCONST(real = 1.0)
2882 then acc;
2883 // case DAE.UNARY() // factor(-(x*y)) is -(x*y) ??
2884
2/2
✓ Branch 0 taken 459692 times.
✓ Branch 1 taken 16203876 times.
16663568 else (if doInverseFactors then inverseFactors(inExp) else inExp) :: acc;
2885 end match;
2886 end factorsWork;
2887
2888 public function inverseFactors
2889 "each expression in the list inversed.
2890 For example: inverseFactors {a, 3+b} => {1/a, 1/3+b}"
2891 input DAE.Exp inExp;
2892 output DAE.Exp outExp;
2893 algorithm
2894 outExp := matchcontinue inExp
2895 local
2896 Type tp2,tp;
2897 DAE.Exp e1,e2,e;
2898 DAE.Operator op;
2899
2900 // e1^e2 =>e1^(-e2)
2901 case DAE.BINARY(exp1 = e1,operator = DAE.POW(ty = tp),exp2 = e2)
2902 algorithm
2903 48806 tp2 := typeof(e2);
2904 48806 then
2905 DAE.BINARY(e1,DAE.POW(tp),DAE.UNARY(DAE.UMINUS(tp2),e2));
2906
2907 // e1 / e2 = e2 / e1
2908 case DAE.BINARY(exp1 = e1,operator = op as DAE.DIV(),exp2 = e2)
2909 algorithm
2910 ✗ false := isZero(e1);
2911 ✗ then
2912 DAE.BINARY(e2,op,e1);
2913
2914 case e
2915 algorithm
2916
2/2
✓ Branch 1 taken 975 times.
✓ Branch 2 taken 570581 times.
571556 false := isZero(e);
2917 570581 tp := typeof(e);
2918 e := match tp
2919 570581 case DAE.T_REAL() then DAE.BINARY(DAE.RCONST(1.0),DAE.DIV(DAE.T_REAL_DEFAULT),e);
2920 ✗ case DAE.T_INTEGER() then DAE.BINARY(DAE.ICONST(1),DAE.DIV(DAE.T_INTEGER_DEFAULT),e);
2921 end match;
2922 then
2923 e;
2924 end matchcontinue;
2925 end inverseFactors;
2926
2927 public function expandFactors
2928 "
2929 Returns the factors of the expression if any as a list of expressions.
2930 e.g.
2931 -(x*(x*y)^n) -> {-1,x,x^n,x^n}
2932 "
2933 input DAE.Exp inExp;
2934 output list<DAE.Exp> outExpLst;
2935 algorithm
2936 // TODO: Remove this listReverse as it is pointless.
2937 // It transforms a*b to b*a, but the testsuite expects this :(
2938 // issue with ExpressionBasics.expEqual(a*b,b*a) return false
2939 771344 outExpLst := listReverse(expandFactorsWork(inExp,{},false));
2940 end expandFactors;
2941
2942 protected function expandFactorsWork
2943 "Returns the factors of the expression if any as a list of expressions"
2944 input DAE.Exp inExp;
2945 input output list<DAE.Exp> acc;
2946 input Boolean doInverseFactors "Decides if a factor e should be 1/e instead";
2947 algorithm
2948
2949 acc := match inExp
2950 local
2951 DAE.Exp e1,e2,e3,e;
2952 Type tp;
2953 list<DAE.Exp> pow_acc, pow_acc2;
2954 Operator op;
2955
2956 // (x*y)^n = x^n*y^n
2957 case DAE.BINARY(DAE.BINARY(e1,DAE.MUL(),e2), DAE.POW(), e3)
2958 algorithm
2959 702 pow_acc := expandFactorsWork(e1,{},doInverseFactors);
2960 702 pow_acc := expPowLst(pow_acc, e3);
2961
2962 702 pow_acc2 := expandFactorsWork(e2,{},doInverseFactors);
2963 702 pow_acc2 := expPowLst(pow_acc2, e3);
2964
2965 702 acc := listAppend(pow_acc, acc);
2966 702 acc := listAppend(pow_acc2, acc);
2967 then acc;
2968 // (x/y)^n = x^n*y^(-n)
2969 case DAE.BINARY(DAE.BINARY(e1,DAE.DIV(),e2), DAE.POW(), e3)
2970 algorithm
2971 ✗ pow_acc := expandFactorsWork(e1,{},doInverseFactors);
2972 ✗ pow_acc := expPowLst(pow_acc, e3);
2973
2974 ✗ pow_acc2 := expandFactorsWork(e2,{},doInverseFactors);
2975 ✗ pow_acc2 := expPowLst(pow_acc2, negate(e3));
2976
2977 ✗ acc := listAppend(pow_acc, acc);
2978 ✗ acc := listAppend(pow_acc2, acc);
2979 then acc;
2980 // (x^n)^m = x^(n*m)
2981 case DAE.BINARY(DAE.BINARY(e1,DAE.POW(),e2), DAE.POW(), e3)
2982 algorithm
2983 ✗ e := expMul(e2,e3);
2984 ✗ pow_acc := expandFactorsWork(e1,{},doInverseFactors);
2985 ✗ pow_acc := expPowLst(pow_acc, e);
2986
2987 ✗ acc := listAppend(pow_acc, acc);
2988 then acc;
2989 // ToDo
2990 // exp(x + y) = exp(x)*exp(y)
2991 // exp(x - y) = exp(x)/exp(y)
2992 // abs(x*y) = abs(x)*abs(y)
2993 // abs(x/y) = abs(x)/abs(y);
2994
2995 // x/0 = x * 1/0
2996 case DAE.BINARY(e1, op as DAE.DIV(tp), e2)
2997 guard isZero(e2)
2998 algorithm
2999
1/2
✓ Branch 0 taken 552 times.
✗ Branch 1 not taken.
552 if doInverseFactors then
3000 e := e2;
3001 else
3002 552 e := DAE.BINARY(makeConstOne(tp), op, e2);
3003 end if;
3004 552 acc := expandFactorsWork(e1,acc,doInverseFactors);
3005 then e::acc;
3006
3007 // -(x) = -1*x
3008 case DAE.UNARY(DAE.UMINUS(tp),e1)
3009 algorithm
3010 25780 e := makeConstOne(tp);
3011 25780 acc := expandFactorsWork(e1,acc,doInverseFactors);
3012 25780 e := negate(e);
3013 then e::acc;
3014 case DAE.UNARY(DAE.UMINUS_ARR(tp),e1)
3015 algorithm
3016 ✗ e := makeConstOne(tp);
3017 ✗ acc := expandFactorsWork(e1,acc,doInverseFactors);
3018 ✗ e := negate(e);
3019 then e::acc;
3020
3021 else
3022 algorithm
3023 786206 acc := expandFactorsWork3(inExp,acc,doInverseFactors);
3024 786206 then expandFactorsWork2(acc,doInverseFactors);
3025
3026 end match;
3027
3028 end expandFactorsWork;
3029
3030 protected function expandFactorsWork3
3031 input DAE.Exp inExp;
3032 input output list<DAE.Exp> acc;
3033 input Boolean doInverseFactors "Decides if a factor e should be 1/e instead";
3034 protected
3035 DAE.Exp e1,e2, e;
3036 Operator op;
3037 algorithm
3038 acc := matchcontinue inExp
3039 case _
3040 786206 then factorsWork(inExp,acc,doInverseFactors);
3041 case DAE.BINARY(e1, DAE.MUL(), e2)
3042 algorithm
3043 ✗ acc := expandFactorsWork(e1, acc, doInverseFactors);
3044 ✗ acc := expandFactorsWork(e2, acc, doInverseFactors);
3045 then
3046 acc;
3047 case DAE.BINARY(DAE.BINARY(e, op as DAE.DIV(), e1), DAE.DIV(), e2)
3048 algorithm
3049 ✗ e := DAE.BINARY(e, op , expMul(e1, e2));
3050 ✗ acc := expandFactorsWork(e, acc, doInverseFactors);
3051 then
3052 acc;
3053 case DAE.BINARY(DAE.BINARY(e, DAE.MUL(), e1), op as DAE.DIV(), e2)
3054 algorithm
3055 ✗ acc := expandFactorsWork(e, acc, doInverseFactors);
3056 ✗ acc := expandFactorsWork(DAE.BINARY(e1, op, e2), acc, doInverseFactors);
3057 then
3058 acc;
3059 case _
3060 //equation
3061 // print("\ninExp*: ");print(ExpressionBasics.printExpStr(inExp));
3062 then inExp :: acc;
3063 end matchcontinue;
3064
3065
3066 end expandFactorsWork3;
3067
3068
3069 protected function expandFactorsWork2
3070 input list<DAE.Exp> inAcc;
3071 input Boolean doInverseFactors "Decides if a factor e should be 1/e instead";
3072 output list<DAE.Exp> outExpLst = {};
3073 protected
3074 list<DAE.Exp> tmpExpLst;
3075 algorithm
3076
3077
2/2
✓ Branch 0 taken 871363 times.
✓ Branch 1 taken 786206 times.
1657569 for elem in inAcc loop
3078 tmpExpLst := match elem
3079 ✗ case DAE.BINARY(DAE.BINARY(_,DAE.DIV(),_), DAE.POW(), _) then expandFactorsWork(elem,{},doInverseFactors);
3080 546 case DAE.BINARY(DAE.BINARY(_,DAE.MUL(),_), DAE.POW(), _) then expandFactorsWork(elem,{},doInverseFactors);
3081 ✗ case DAE.BINARY(DAE.BINARY(_,DAE.POW(),_), DAE.POW(), _) then expandFactorsWork(elem,{},doInverseFactors);
3082 13614 case DAE.UNARY(DAE.UMINUS(),_) then expandFactorsWork(elem,{},doInverseFactors);
3083 ✗ case DAE.UNARY(DAE.UMINUS_ARR(),_) then expandFactorsWork(elem,{},doInverseFactors);
3084 else {elem};
3085 end match;
3086 871363 outExpLst := listAppend(tmpExpLst, outExpLst);
3087 end for;
3088
3089 end expandFactorsWork2;
3090
3091
3092 public function getTermsContainingX
3093 "Retrieves all terms of an expression containing a variable,
3094 given as second argument (in the form of an Exp)"
3095 input DAE.Exp inExp1;
3096 input DAE.Exp inExp2;
3097 output DAE.Exp outExp1;
3098 output DAE.Exp outExp2;
3099 algorithm
3100 (outExp1,outExp2) := matchcontinue (inExp1,inExp2)
3101 local
3102 DAE.Exp xt1,nonxt1,xt2,nonxt2,xt,nonxt,e1,e2,cr,e,zero;
3103 Type ty;
3104 Boolean res;
3105 case (DAE.BINARY(exp1 = e1,operator = DAE.ADD(ty = ty),exp2 = e2),(cr as DAE.CREF()))
3106 algorithm
3107 ✗ (xt1,nonxt1) := getTermsContainingX(e1, cr);
3108 ✗ (xt2,nonxt2) := getTermsContainingX(e2, cr);
3109 ✗ xt := DAE.BINARY(xt1,DAE.ADD(ty),xt2);
3110 ✗ nonxt := DAE.BINARY(nonxt1,DAE.ADD(ty),nonxt2);
3111 then
3112 (xt,nonxt);
3113 case (DAE.BINARY(exp1 = e1,operator = DAE.SUB(ty = ty),exp2 = e2),(cr as DAE.CREF()))
3114 algorithm
3115 ✗ (xt1,nonxt1) := getTermsContainingX(e1, cr);
3116 ✗ (xt2,nonxt2) := getTermsContainingX(e2, cr);
3117 ✗ xt := DAE.BINARY(xt1,DAE.SUB(ty),xt2);
3118 ✗ nonxt := DAE.BINARY(nonxt1,DAE.SUB(ty),nonxt2);
3119 then
3120 (xt,nonxt);
3121 case (DAE.UNARY(operator = DAE.UMINUS(ty = ty),exp = e),(cr as DAE.CREF()))
3122 algorithm
3123 ✗ (xt1,nonxt1) := getTermsContainingX(e, cr);
3124 ✗ xt := DAE.UNARY(DAE.UMINUS(ty),xt1);
3125 ✗ nonxt := DAE.UNARY(DAE.UMINUS(ty),nonxt1);
3126 then
3127 (xt,nonxt);
3128 case (DAE.BINARY(exp1 = e1,operator = DAE.ADD_ARR(ty = ty),exp2 = e2),(cr as DAE.CREF()))
3129 algorithm
3130 ✗ (xt1,nonxt1) := getTermsContainingX(e1, cr);
3131 ✗ (xt2,nonxt2) := getTermsContainingX(e2, cr);
3132 ✗ xt := DAE.BINARY(xt1,DAE.ADD_ARR(ty),xt2);
3133 ✗ nonxt := DAE.BINARY(nonxt1,DAE.ADD_ARR(ty),nonxt2);
3134 then
3135 (xt,nonxt);
3136 case (DAE.BINARY(exp1 = e1,operator = DAE.SUB_ARR(ty = ty),exp2 = e2),(cr as DAE.CREF()))
3137 algorithm
3138 ✗ (xt1,nonxt1) := getTermsContainingX(e1, cr);
3139 ✗ (xt2,nonxt2) := getTermsContainingX(e2, cr);
3140 ✗ xt := DAE.BINARY(xt1,DAE.SUB_ARR(ty),xt2);
3141 ✗ nonxt := DAE.BINARY(nonxt1,DAE.SUB_ARR(ty),nonxt2);
3142 then
3143 (xt,nonxt);
3144 case (DAE.UNARY(operator = DAE.UMINUS_ARR(ty = ty),exp = e),(cr as DAE.CREF()))
3145 algorithm
3146 ✗ (xt1,nonxt1) := getTermsContainingX(e, cr);
3147 ✗ xt := DAE.UNARY(DAE.UMINUS_ARR(ty),xt1);
3148 ✗ nonxt := DAE.UNARY(DAE.UMINUS_ARR(ty),nonxt1);
3149 then
3150 (xt,nonxt);
3151 case (e,(cr as DAE.CREF(ty = ty)))
3152 algorithm
3153 ✗ res := expContains(e, cr);
3154 ✗ (zero,_) := makeZeroExpression(arrayDimension(ty));
3155 ✗ xt := if res then e else zero;
3156 ✗ nonxt := if res then zero else e;
3157 then
3158 (xt,nonxt);
3159 else
3160 algorithm
3161 /*Print.printBuf("Expression.getTerms_containingX failed: ");
3162 ExpressionDump.printExp(e);
3163 Print.printBuf("\nsolving for: ");
3164 ExpressionDump.printExp(cr);
3165 Print.printBuf("\n");*/
3166 then
3167 fail();
3168 end matchcontinue;
3169 end getTermsContainingX;
3170
3171 public function flattenArrayExpToList "returns all non-array expressions of an array expression as a long list
3172 E.g. {[1,2;3,4],[4,5;6,7]} => {1,2,3,4,4,5,6,7}"
3173 input DAE.Exp e;
3174 output list<DAE.Exp> expLst;
3175 algorithm
3176 expLst := matchcontinue e
3177 local
3178 list<DAE.Exp> expl;
3179 list<list<DAE.Exp>> mexpl;
3180 case DAE.UNARY(operator=DAE.UMINUS_ARR(),exp=DAE.ARRAY(array=expl))
3181 algorithm
3182 ✗ expl := List.flatten(List.map(expl,flattenArrayExpToList));
3183 ✗ expLst := List.map(expl,negate);
3184 then expLst;
3185 case DAE.ARRAY(array=expl)
3186 algorithm
3187 50521 expLst := List.flatten(List.map(expl,flattenArrayExpToList));
3188 then expLst;
3189 case DAE.UNARY(operator=DAE.UMINUS_ARR(),exp=DAE.MATRIX(matrix=mexpl))
3190 algorithm
3191 ✗ expl := List.flatten(List.map(List.flatten(mexpl),flattenArrayExpToList));
3192 ✗ expLst := List.map(expl,negate);
3193 then expLst;
3194 case DAE.MATRIX(matrix=mexpl)
3195 algorithm
3196 2733 expLst := List.flatten(List.map(List.flatten(mexpl),flattenArrayExpToList));
3197 then expLst;
3198 else {e};
3199 end matchcontinue;
3200 end flattenArrayExpToList;
3201
3202 /***************************************************/
3203 /* generate */
3204 /***************************************************/
3205
3206 public function makeNoEvent " adds a noEvent call around an expression"
3207 input DAE.Exp e1;
3208 output DAE.Exp res;
3209 algorithm
3210 12860 res := Expression.makePureBuiltinCall("noEvent", {e1}, DAE.T_BOOL_DEFAULT);
3211 end makeNoEvent;
3212
3213 public function makeAbs ""
3214 input DAE.Exp e1;
3215 output DAE.Exp res;
3216 algorithm
3217 404 res := Expression.makePureBuiltinCall("abs", {e1}, DAE.T_REAL_DEFAULT);
3218 end makeAbs;
3219
3220 public function makeSign ""
3221 input DAE.Exp e1;
3222 output DAE.Exp res;
3223 algorithm
3224 20 res := Expression.makePureBuiltinCall("sign", {e1}, DAE.T_REAL_DEFAULT);
3225 end makeSign;
3226
3227
3228 public function makeNestedIf "creates a nested if expression given a list of conditions and
3229 guarded expressions and a default value (the else branch)"
3230 input list<DAE.Exp> inConds "conditions";
3231 input list<DAE.Exp> inTbExps " guarded expressions, for each condition";
3232 input DAE.Exp fExp "default value, else branch";
3233 output DAE.Exp ifExp;
3234 algorithm
3235 ifExp := match(inConds, inTbExps)
3236 local DAE.Exp c,tbExp; list<DAE.Exp> conds, tbExps;
3237 case({c}, {tbExp})
3238 58 then DAE.IFEXP(c,tbExp,fExp);
3239 case(c::conds, tbExp::tbExps)
3240 algorithm
3241 32 ifExp := makeNestedIf(conds,tbExps,fExp);
3242 32 then DAE.IFEXP(c,tbExp,ifExp);
3243 end match;
3244 end makeNestedIf;
3245
3246 public function makeCrefExp
3247 "Makes an expression of a component reference, given also a type"
3248 input DAE.ComponentRef inCref;
3249 input DAE.Type inExpType;
3250 output DAE.Exp outExp;
3251 algorithm
3252 outExp := match(inCref, inExpType)
3253 local
3254 ComponentRef cref;
3255 Type tGiven, tExisting;
3256
3257 case (cref, tGiven)
3258 algorithm
3259
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3224798 times.
3224798 if Flags.isSet(Flags.CHECK_DAE_CREF_TYPE)
3260 then // check type
3261 ✗ tExisting := ComponentReference.crefLastType(cref);
3262 ✗ if not valueEq(tGiven, tExisting)
3263 then // type not the same
3264 ✗ Debug.traceln("Warning: Expression.makeCrefExp: cref " + ComponentReferenceBasics.printComponentRefStr(cref) + " was given type DAE.CREF.ty: " +
3265 TypesDump.unparseType(tGiven) +
3266 " is different from existing DAE.CREF.componentRef.ty: " +
3267 TypesDump.unparseType(tExisting));
3268 end if;
3269 end if;
3270 3224798 then
3271 DAE.CREF(cref, tGiven);
3272
3273 end match;
3274 end makeCrefExp;
3275
3276
3277 public function crefToExp
3278 " mahge:
3279 creates a DAE.Exp from a cref by exrtacting the type from the types of the cref (if qualified) and
3280 considering the dimensions and subscripts that exist in the cref.
3281 "
3282 input DAE.ComponentRef cr;
3283 output DAE.Exp cref;
3284 algorithm
3285 633086 cref := DAE.CREF(cr,ComponentReference.crefTypeFull(cr));
3286 end crefToExp;
3287
3288
3289
3290
3291 public function crefExp
3292 " ***deprecated.
3293 mahge: use crefToExp(). This is not correct. We need to consider more than just the last subs.
3294
3295 Author: BZ, 2008-08
3296 generate an DAE.CREF(ComponentRef, Type) from a ComponenRef, make array type correct from subs"
3297 input DAE.ComponentRef cr;
3298 output DAE.Exp cref;
3299 algorithm
3300 cref := match cr
3301 local
3302 Type ty1,ty2;
3303 list<DAE.Subscript> subs;
3304
3305 2 case DAE.WILD() then DAE.CREF(cr, DAE.T_UNKNOWN());
3306
3307 case _
3308 algorithm
3309 2475841 ty1 := ComponentReference.crefLastType(cr);
3310 cref := match ty1
3311 case DAE.T_ARRAY()
3312 algorithm
3313 1092858 subs := ComponentReference.crefLastSubs(cr);
3314 1092858 ty2 := unliftArrayTypeWithSubs(subs,ty1);
3315 1092858 then DAE.CREF(cr,ty2);
3316 1382983 else DAE.CREF(cr,ty1);
3317 end match;
3318 then
3319 cref;
3320
3321 end match;
3322 end crefExp;
3323
3324 public function makeASUB
3325 "@author: adrpo
3326 Creates an ASUB given an expression and a list of expression indexes.
3327 If flag -d=checkASUB is ON we give a warning that the given exp is
3328 not a component reference."
3329 input DAE.Exp inExp;
3330 input list<DAE.Exp> inSubs;
3331 output DAE.Exp outExp;
3332 protected
3333 list<Subscript> inSubs_ = list(makeIndexSubscript(s) for s in inSubs);
3334 algorithm
3335 outExp := match(inExp,inSubs_)
3336 local
3337 DAE.Exp exp;
3338 list<Subscript> subs,subs1,subs2;
3339
3340 // We need to be careful when constructing ASUB's. All subscripts should be in a list.
3341 case (DAE.ASUB(exp,subs1),subs2)
3342 algorithm
3343 7556 subs := listAppend(subs1,subs2);
3344 7556 exp := DAE.ASUB(exp,subs);
3345 then
3346 exp;
3347
3348 case(_, _)
3349 algorithm
3350
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 885475 times.
885475 if Flags.isSet(Flags.CHECK_ASUB) // check the DAE.ASUB
3351 then
3352 () := match inExp // check the DAE.ASUB so that the given expression is NOT a cref
3353 case DAE.CREF()
3354 algorithm
3355 ✗ Debug.traceln("Warning: makeASUB: given expression: " +
3356 ExpressionBasics.printExpStr(inExp) +
3357 " contains a component reference!\n" +
3358 " Subscripts exps: [" + stringDelimitList(List.map(inSubs, ExpressionBasics.printExpStr), ",")+ "]\n" +
3359 "DAE.ASUB should not be used for component references, instead the subscripts should be added directly to the component reference!");
3360 then ();
3361 else (); // check the DAE.ASUB -> was not a cref
3362 end match;
3363 end if;
3364 885475 exp := DAE.ASUB(inExp,inSubs_);
3365 then
3366 exp;
3367
3368 end match;
3369 end makeASUB;
3370
3371 public function makeASUBSingleSub
3372 input DAE.Exp exp;
3373 input DAE.Exp sub;
3374 output DAE.Exp outExp;
3375 algorithm
3376 94 outExp := makeASUB(exp,{sub});
3377 end makeASUBSingleSub;
3378
3379 public function makeTuple
3380 input list<DAE.Exp> inExps;
3381 output DAE.Exp outExp;
3382 algorithm
3383
2/2
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 61866 times.
61893 outExp := if listLength(inExps) > 1 then DAE.TUPLE(inExps) else listHead(inExps);
3384 end makeTuple;
3385
3386
3387 public function generateCrefsExpFromExpVar "
3388 Author: Frenkel TUD 2010-05"
3389 input DAE.Var inVar;
3390 input DAE.ComponentRef inCrefPrefix;
3391 output DAE.Exp outCrefExp;
3392 algorithm outCrefExp := match inVar
3393 local
3394 String name;
3395 DAE.Type ty;
3396 DAE.ComponentRef cr;
3397 DAE.Exp e;
3398
3399 case DAE.TYPES_VAR(name=name,ty=ty)
3400 algorithm
3401 35197 cr := ComponentReference.crefPrependIdent(inCrefPrefix,name,{},ty);
3402 35197 e := makeCrefExp(cr, ty);
3403 then
3404 e;
3405
3406 end match;
3407 end generateCrefsExpFromExpVar;
3408
3409 public function generateCrefsFromExpVar "
3410 Author: Frenkel TUD 2010-05"
3411 input DAE.Var inVar;
3412 input DAE.ComponentRef inCrefPrefix;
3413 output DAE.ComponentRef outCref;
3414 algorithm outCref := match inVar
3415 local
3416 String name;
3417 DAE.Type ty;
3418 DAE.ComponentRef cr;
3419
3420 case DAE.TYPES_VAR(name=name,ty=ty)
3421 algorithm
3422 ✗ cr := ComponentReference.crefPrependIdent(inCrefPrefix,name,{},ty);
3423 then
3424 cr;
3425 end match;
3426 end generateCrefsFromExpVar;
3427
3428 public function generateCrefsExpFromExp
3429 input DAE.Exp inExp;
3430 input DAE.ComponentRef inCrefPrefix;
3431 output DAE.Exp outCrefExp;
3432 algorithm
3433 outCrefExp := match inExp
3434 local
3435 String name;
3436 DAE.Type ty;
3437 DAE.ComponentRef cr;
3438 DAE.Exp e;
3439 Absyn.Path p1,p2;
3440 list<DAE.Exp> explst;
3441 Boolean b;
3442 DAE.CallAttributes attr;
3443 list<String> fields;
3444
3445 case DAE.CREF(componentRef=DAE.WILD()) then inExp;
3446
3447 case DAE.ARRAY(ty=ty, scalar=b, array=explst)
3448 algorithm
3449 ✗ explst := List.map1(explst, generateCrefsExpFromExp, inCrefPrefix);
3450 ✗ then DAE.ARRAY(ty, b, explst);
3451
3452 case DAE.CALL(path=p1,expLst=explst,attr=attr as DAE.CALL_ATTR(ty=DAE.T_COMPLEX(complexClassType=ClassInf.RECORD(p2))))
3453 algorithm
3454 ✗ true := AbsynUtil.pathEqual(p1,p2) "is record constructor";
3455 ✗ explst := List.map1(explst, generateCrefsExpFromExp, inCrefPrefix);
3456 ✗ then
3457 DAE.CALL(p1,explst,attr);
3458
3459 case DAE.RECORD(p1, explst, fields, ty)
3460 algorithm
3461 ✗ explst := List.map1(explst, generateCrefsExpFromExp, inCrefPrefix);
3462 ✗ then
3463 DAE.RECORD(p1, explst, fields, ty);
3464
3465 case DAE.CREF(componentRef=cr,ty=ty)
3466 algorithm
3467 ✗ name := ComponentReference.crefModelicaStr(cr);
3468 ✗ cr := ComponentReference.crefPrependIdent(inCrefPrefix,name,{},ty);
3469 ✗ e := makeCrefExp(cr, ty);
3470 then
3471 e;
3472 case DAE.UNARY(exp=e)
3473 ✗ then negate(generateCrefsExpFromExp(e, inCrefPrefix)); /*ToDo: check*/
3474 else
3475 algorithm
3476 ✗ print("Expression.generateCrefsExpFromExp: fail for" + ExpressionBasics.printExpStr(inExp) + "\n");
3477 ✗ then fail();
3478 end match;
3479 end generateCrefsExpFromExp;
3480
3481 public function generateCrefsExpLstFromExp
3482 input DAE.Exp inExp;
3483 input Option<DAE.ComponentRef> inCrefPrefix;
3484 output list<DAE.Exp> outCrefExpList;
3485 algorithm
3486 outCrefExpList := match(inExp,inCrefPrefix)
3487 local
3488 String name;
3489 DAE.Type ty;
3490 DAE.ComponentRef cr, incref;
3491 DAE.Exp e;
3492 Absyn.Path p1,p2;
3493 list<DAE.Exp> explst;
3494
3495 case (DAE.TUPLE(PR=explst), _)
3496 algorithm
3497 ✗ explst := List.flatten(List.map1(explst, generateCrefsExpLstFromExp, inCrefPrefix));
3498 then explst;
3499
3500 case (DAE.ARRAY( array=explst), _)
3501 algorithm
3502 ✗ explst := List.flatten(List.map1(explst, generateCrefsExpLstFromExp, inCrefPrefix));
3503 then explst;
3504
3505 case (DAE.CALL(path=p1,expLst=explst,attr=DAE.CALL_ATTR(ty=DAE.T_COMPLEX(complexClassType=ClassInf.RECORD(p2)))),_)
3506 guard AbsynUtil.pathEqual(p1,p2) // is record constructor
3507 ✗ then List.flatten(List.map1(explst, generateCrefsExpLstFromExp, inCrefPrefix));
3508
3509 case (DAE.RECORD(exps=explst),_)
3510 120 then List.flatten(List.map1(explst, generateCrefsExpLstFromExp, inCrefPrefix));
3511
3512 case(DAE.CALL(path = Absyn.IDENT("der"),expLst = {DAE.CREF(componentRef = incref)}), _)
3513 algorithm
3514 ✗ cr := ComponentReference.crefPrefixDer(incref);
3515 ✗ e := Expression.crefExp(cr);
3516 ✗ then generateCrefsExpLstFromExp(e, inCrefPrefix);
3517
3518 case (DAE.CREF(componentRef=cr,ty=ty),SOME(incref))
3519 algorithm
3520 ✗ name := ComponentReference.crefModelicaStr(cr);
3521 ✗ cr := ComponentReference.crefPrependIdent(incref,name,{},ty);
3522 ✗ e := makeCrefExp(cr, ty);
3523 then
3524 {e};
3525
3526 case (DAE.CREF(),NONE()) then {inExp};
3527
3528 case (DAE.UNARY(exp=e),_)
3529 ✗ then generateCrefsExpLstFromExp(e, inCrefPrefix);/*ToDo: check*/
3530
3531 else
3532 algorithm
3533 ✗ print("Expression.generateCrefsExpLstFromExp: fail for " + ExpressionBasics.printExpStr(inExp) + "\n");
3534 ✗ then fail();
3535
3536 end match;
3537 end generateCrefsExpLstFromExp;
3538
3539 public function makeArray
3540 input list<DAE.Exp> inElements;
3541 input DAE.Type inType;
3542 input Boolean inScalar;
3543 output DAE.Exp outArray;
3544 algorithm
3545
2/2
✓ Branch 0 taken 5360 times.
✓ Branch 1 taken 20842 times.
31562 outArray := DAE.ARRAY(inType, inScalar, inElements);
3546 end makeArray;
3547
3548 public function makeArrayFromList
3549 input list<DAE.Exp> inElements;
3550 output DAE.Exp outArray;
3551 protected
3552 DAE.Type ty;
3553 algorithm
3554 26 ty := typeof(listHead(inElements));
3555
1/2
✗ Branch 4 not taken.
✓ Branch 5 taken 26 times.
52 outArray := DAE.ARRAY(DAE.T_ARRAY(ty,{DAE.DIM_INTEGER(listLength(inElements))}), not Types.isArray(ty), inElements);
3556 end makeArrayFromList;
3557
3558 public function makeScalarArray
3559 "Constructs an array of the given scalar type."
3560 input list<DAE.Exp> inExpLst;
3561 input DAE.Type et;
3562 output DAE.Exp outExp;
3563 protected
3564 Integer i;
3565 algorithm
3566 1571 i := listLength(inExpLst);
3567 3142 outExp := DAE.ARRAY(DAE.T_ARRAY(et, {DAE.DIM_INTEGER(i)}), true, inExpLst);
3568 end makeScalarArray;
3569
3570 public function makeRealArray
3571 "Construct an array node of an DAE.Exp list of type REAL."
3572 input list<DAE.Exp> expl;
3573 output DAE.Exp outExp;
3574 algorithm
3575 806 outExp := makeScalarArray(expl,DAE.T_REAL_DEFAULT);
3576 end makeRealArray;
3577
3578 public function makeRealAdd
3579 "Construct an add node of the two expressions of type REAL."
3580 input DAE.Exp inExp1;
3581 input DAE.Exp inExp2;
3582 output DAE.Exp outExp;
3583 algorithm
3584 6655 outExp := DAE.BINARY(inExp1, DAE.ADD(DAE.T_REAL_DEFAULT), inExp2);
3585 end makeRealAdd;
3586
3587 public function expAdd
3588 "author: PA
3589 Adds two scalar expressions."
3590 input DAE.Exp e1;
3591 input DAE.Exp e2;
3592 output DAE.Exp outExp;
3593 algorithm
3594 outExp := match(e1,e2)
3595 local
3596 Type tp;
3597 Boolean b;
3598 Operator op;
3599 Real r1,r2;
3600 Integer i1,i2;
3601 DAE.Exp e, x, y;
3602
3603 case(_,_) guard isZero(e1) then e2;
3604 case(_,_) guard isZero(e2) then e1;
3605 2799 case(DAE.RCONST(r1),DAE.RCONST(r2)) then DAE.RCONST(r1 + r2);
3606 ✗ case(DAE.ICONST(i1),DAE.ICONST(i2)) then DAE.ICONST(i1 + i2);
3607
3608 /* a + (-b) = a - b */
3609 case (_,DAE.UNARY(operator=DAE.UMINUS(),exp=e))
3610 96413 then
3611 expSub(e1,e);
3612 case (_,DAE.UNARY(operator=DAE.UMINUS_ARR(),exp=e))
3613 ✗ then
3614 expSub(e1,e);
3615 // x +(-y)*z
3616 case (_,DAE.BINARY(DAE.UNARY(DAE.UMINUS(),x),op as DAE.MUL(),y))
3617 8941 then
3618 expSub(e1,DAE.BINARY(x,op,y));
3619 case (_,DAE.BINARY(DAE.UNARY(DAE.UMINUS_ARR(),x), op as DAE.MUL_ARR(),y))
3620 ✗ then
3621 expSub(e1,DAE.BINARY(x,op,y));
3622 // x +(-y)/z
3623 case (_,DAE.BINARY(DAE.UNARY(DAE.UMINUS(),x),op as DAE.DIV(),y))
3624 3603 then
3625 expSub(e1,DAE.BINARY(x,op,y));
3626 case (_,DAE.BINARY(DAE.UNARY(DAE.UMINUS_ARR(),x), op as DAE.DIV_ARR(),y))
3627 ✗ then
3628 expSub(e1,DAE.BINARY(x,op,y));
3629 /* -b + a = a - b */
3630 case (DAE.UNARY(operator=DAE.UMINUS(),exp=e),_)
3631 17103 then
3632 expSub(e2,e);
3633 case (DAE.UNARY(operator=DAE.UMINUS_ARR(),exp=e),_)
3634 ✗ then
3635 expSub(e2,e);
3636 // (-y)*z+x
3637 case (DAE.BINARY(DAE.UNARY(DAE.UMINUS(),x),op as DAE.MUL(),y),_)
3638 4657 then
3639 expSub(e2,DAE.BINARY(x,op,y));
3640 case (DAE.BINARY(DAE.UNARY(DAE.UMINUS_ARR(),x), op as DAE.MUL_ARR(),y),_)
3641 ✗ then
3642 expSub(e2,DAE.BINARY(x,op,y));
3643 // (-y)/z + x
3644 case (DAE.BINARY(DAE.UNARY(DAE.UMINUS(),x),op as DAE.DIV(),y),_)
3645 65 then
3646 expSub(e2,DAE.BINARY(x,op,y));
3647 case (DAE.BINARY(DAE.UNARY(DAE.UMINUS_ARR(),x), op as DAE.DIV_ARR(),y),_)
3648 ✗ then
3649 expSub(e2,DAE.BINARY(x,op,y));
3650
3651 case (_,_) guard Types.isIntegerOrRealOrSubTypeOfEither(typeof(e1))
3652 algorithm
3653 1498688 tp := typeof(e1);
3654 1498688 b := DAEUtil.expTypeArray(tp) " array_elt_type(tp) => tp\'" ;
3655
2/2
✓ Branch 0 taken 193 times.
✓ Branch 1 taken 1498495 times.
1498688 op := if b then DAE.ADD_ARR(tp) else DAE.ADD(tp);
3656 1498688 then
3657 DAE.BINARY(e1,op,e2);
3658 case (_,_) guard Types.isEnumeration(typeof(e1))
3659 ✗ then
3660 DAE.BINARY(e1,DAE.ADD(typeof(e1)),e2);
3661 end match;
3662 end expAdd;
3663
3664 public function expSub
3665 "author: PA
3666 Subtracts two scalar expressions."
3667 input DAE.Exp e1;
3668 input DAE.Exp e2;
3669 output DAE.Exp outExp;
3670 algorithm
3671 outExp := match(e1,e2)
3672 local
3673 Type tp;
3674 Boolean b;
3675 Operator op;
3676 Real r1,r2;
3677 Integer i1,i2;
3678 DAE.Exp e, x,y;
3679 114919 case(_,_) guard isZero(e1) then negate(e2);
3680 case(_,_) guard isZero(e2) then e1;
3681 674 case(DAE.RCONST(r1),DAE.RCONST(r2)) then DAE.RCONST(r1-r2);
3682 ✗ case(DAE.ICONST(i1),DAE.ICONST(i2)) then DAE.ICONST(i1-i2);
3683
3684 /* a - (-b) = a + b */
3685 case (_,DAE.UNARY(operator=DAE.UMINUS(),exp=e))
3686 1808 then
3687 expAdd(e1,e);
3688 case (_,DAE.UNARY(operator=DAE.UMINUS_ARR(),exp=e))
3689 174 then
3690 expAdd(e1,e);
3691 // x -(-y)*z
3692 case (_,DAE.BINARY(DAE.UNARY(DAE.UMINUS(),x),op as DAE.MUL(),y))
3693 2181 then
3694 expAdd(e1,DAE.BINARY(x,op,y));
3695 case (_,DAE.BINARY(DAE.UNARY(DAE.UMINUS_ARR(),x), op as DAE.MUL_ARR(),y))
3696 ✗ then
3697 expAdd(e1,DAE.BINARY(x,op,y));
3698 // x -(-y)/z
3699 case (_,DAE.BINARY(DAE.UNARY(DAE.UMINUS(),x),op as DAE.DIV(),y))
3700 243 then
3701 expAdd(e1,DAE.BINARY(x,op,y));
3702 case (_,DAE.BINARY(DAE.UNARY(DAE.UMINUS_ARR(),x), op as DAE.DIV_ARR(),y))
3703 ✗ then
3704 expAdd(e1,DAE.BINARY(x,op,y));
3705 /* - a - b = -(a + b) */
3706 case (DAE.UNARY(operator=DAE.UMINUS(),exp=e),_)
3707 algorithm
3708 17198 e := expAdd(e,e2);
3709 17198 then
3710 negate(e);
3711 case (DAE.UNARY(operator=DAE.UMINUS_ARR(),exp=e),_)
3712 algorithm
3713 ✗ e := expAdd(e,e2);
3714 ✗ then
3715 negate(e);
3716
3717 case (_,_) guard Types.isIntegerOrRealOrSubTypeOfEither(typeof(e1))
3718 algorithm
3719 636456 tp := typeof(e1);
3720 636456 b := DAEUtil.expTypeArray(tp) " array_elt_type(tp) => tp\'" ;
3721
2/2
✓ Branch 0 taken 3667 times.
✓ Branch 1 taken 632789 times.
636456 op := if b then DAE.SUB_ARR(tp) else DAE.SUB(tp);
3722 636456 then
3723 DAE.BINARY(e1,op,e2);
3724 case (_,_) guard Types.isEnumeration(typeof(e1))
3725 9069 then
3726 DAE.BINARY(e1,DAE.SUB(typeof(e1)),e2);
3727 end match;
3728 end expSub;
3729
3730 public function makeLBinary
3731 "Makes a binary logical expression of all elements in the list."
3732 input list<DAE.Exp> inExpLst;
3733 input DAE.Operator op;
3734 output DAE.Exp outExp;
3735 algorithm
3736 outExp := match (inExpLst,op)
3737 local
3738 DAE.Exp e1,e2,res;
3739 list<DAE.Exp> rest;
3740 String str;
3741 case ({},DAE.AND(_)) then DAE.BCONST(true);
3742 case ({},DAE.OR(_)) then DAE.BCONST(false);
3743 case ({e1},_) then e1;
3744 8 case ({e1, e2},_) then DAE.LBINARY(e1,op,e2);
3745 case ((e1 :: rest),_)
3746 algorithm
3747 8 res := makeLBinary(rest,op);
3748 8 res := DAE.LBINARY(e1,op,res);
3749 then res;
3750 else
3751 algorithm
3752 ✗ str := "Expression.makeLBinary failed for operator " + ExpressionDump.lbinopSymbol(op);
3753 ✗ Error.addMessage(Error.INTERNAL_ERROR, {str});
3754 ✗ then fail();
3755 end match;
3756 end makeLBinary;
3757
3758 public function makeSum1
3759 "Takes a list of expressions an makes a sum
3760 expression sorting adding all elements in the list.
3761
3762 Note:
3763 makeSum1 => (a + b) + c
3764 makeSum => a + (b + c)
3765 "
3766
3767
3768 input list<DAE.Exp> inExpLst;
3769 input Boolean simplify = false;
3770 output DAE.Exp outExp;
3771 protected
3772 DAE.Exp e1,e2;
3773 algorithm
3774 outExp := matchcontinue inExpLst
3775 case {} then DAE.RCONST(0.0);
3776 case {e1} then e1;
3777 183424 case {e1,e2} then expAdd(e1,e2);
3778 24817 case _ then makeSumWork(inExpLst, simplify);
3779 else
3780 algorithm
3781 ✗ if Flags.isSet(Flags.FAILTRACE) then
3782 ✗ Debug.trace("-Expression.makeSum1 failed, DAE.Exp lst:");
3783 ✗ Debug.trace(ExpressionDump.printExpListStr(inExpLst));
3784 end if;
3785 ✗ then fail();
3786 end matchcontinue;
3787
3788 end makeSum1;
3789
3790 protected function makeSumWork
3791 "Takes a list of expressions an makes a sum expression adding all elements in
3792 the list. Zero terms are dropped."
3793 input list<DAE.Exp> inExpLst;
3794 input Boolean simplify = false;
3795 output DAE.Exp outExp;
3796 protected
3797 list<DAE.Exp> terms, rest;
3798 algorithm
3799
6/6
✓ Branch 1 taken 7506 times.
✓ Branch 2 taken 94501 times.
✓ Branch 3 taken 102007 times.
✓ Branch 4 taken 24817 times.
✓ Branch 5 taken 94501 times.
✓ Branch 6 taken 24817 times.
126824 terms := list(e for e guard(not isZero(e)) in inExpLst);
3800
3801
2/2
✓ Branch 0 taken 561 times.
✓ Branch 1 taken 24256 times.
24817 if listEmpty(terms) then
3802 561 outExp := listHead(inExpLst);
3803 elseif listLength(terms) > MAX_SUM_CHAIN then
3804 ✗ outExp := balancedSum(terms, simplify);
3805 else
3806
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24256 times.
24256 outExp :: rest := terms;
3807
3808
2/2
✓ Branch 0 taken 70245 times.
✓ Branch 1 taken 24256 times.
94501 for e in rest loop
3809 70245 outExp := DAE.BINARY(outExp, addOperator(outExp, e), e);
3810
3811
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 70165 times.
70245 if simplify then
3812 80 outExp := ExpressionSimplify.simplify1(outExp);
3813 end if;
3814 end for;
3815 end if;
3816 end makeSumWork;
3817
3818 public function makeSum
3819 "Takes a list of expressions an makes a sum expression adding all elements in
3820 the list. Zero terms are dropped."
3821 input list<DAE.Exp> inExpLst;
3822 output DAE.Exp outExp;
3823 protected
3824 list<DAE.Exp> terms;
3825 algorithm
3826
6/6
✓ Branch 1 taken 1667 times.
✓ Branch 2 taken 2621253 times.
✓ Branch 3 taken 2622920 times.
✓ Branch 4 taken 1227050 times.
✓ Branch 5 taken 2621253 times.
✓ Branch 6 taken 1227050 times.
3849970 terms := list(e for e guard(not isZero(e)) in inExpLst);
3827
3828
2/2
✓ Branch 0 taken 1361 times.
✓ Branch 1 taken 1225689 times.
1227050 if listEmpty(terms) then
3829
1/2
✓ Branch 0 taken 1361 times.
✗ Branch 1 not taken.
1361 outExp := if listEmpty(inExpLst) then DAE.RCONST(0.0) else List.last(inExpLst);
3830 elseif listLength(terms) > MAX_SUM_CHAIN then
3831 ✗ outExp := balancedSum(terms);
3832 else
3833 1225689 terms := listReverse(terms);
3834
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1225689 times.
1225689 outExp :: terms := terms;
3835
3836
2/2
✓ Branch 0 taken 1395564 times.
✓ Branch 1 taken 1225689 times.
2621253 for e in terms loop
3837 1395564 outExp := DAE.BINARY(e, addOperator(e, outExp), outExp);
3838 end for;
3839 end if;
3840 end makeSum;
3841
3842 protected function addOperator
3843 "The addition operator for two summands, array-valued if either of them is."
3844 input DAE.Exp e1;
3845 input DAE.Exp e2;
3846 output DAE.Operator op;
3847 protected
3848 Type tp = typeof(e1);
3849 algorithm
3850
1/2
✓ Branch 1 taken 1465809 times.
✗ Branch 2 not taken.
1465809 if not DAEUtil.expTypeArray(tp) then
3851 1465809 tp := typeof(e2);
3852 end if;
3853
3854
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1465809 times.
1465809 op := if DAEUtil.expTypeArray(tp) then DAE.ADD_ARR(tp) else DAE.ADD(tp);
3855 end addOperator;
3856
3857 protected function balancedSum
3858 "Adds the expressions pairwise, level by level, keeping their order. Used for
3859 sums too long to leave as a chain, see MAX_SUM_CHAIN."
3860 input list<DAE.Exp> inExpLst;
3861 input Boolean simplify = false;
3862 output DAE.Exp outExp;
3863 protected
3864 list<DAE.Exp> level = inExpLst, next;
3865 DAE.Exp e1, e2;
3866 algorithm
3867 ✗ while not listEmpty(listRest(level)) loop
3868 next := {};
3869
3870 ✗ while not listEmpty(level) loop
3871 ✗ e1 :: level := level;
3872
3873 ✗ if listEmpty(level) then
3874 next := e1 :: next;
3875 else
3876 ✗ e2 :: level := level;
3877 ✗ outExp := DAE.BINARY(e1, addOperator(e1, e2), e2);
3878 ✗ next := (if simplify then ExpressionSimplify.simplify1(outExp) else outExp) :: next;
3879 end if;
3880 end while;
3881
3882 ✗ level := MetaModelica.Dangerous.listReverseInPlace(next);
3883 end while;
3884
3885 ✗ outExp := listHead(level);
3886 end balancedSum;
3887
3888 public function expMul
3889 "author: PA
3890 Multiplies two scalar expressions."
3891 input DAE.Exp e1;
3892 input DAE.Exp e2;
3893 output DAE.Exp outExp;
3894 algorithm
3895 outExp := matchcontinue(e1,e2)
3896 local
3897 Type tp;
3898 Boolean b1,b2;
3899 Operator op;
3900 Real r1,r2;
3901 Integer i1,i2;
3902 DAE.Exp e1_1,e2_1;
3903 case(_,_)
3904 algorithm
3905
2/2
✓ Branch 1 taken 2402788 times.
✓ Branch 2 taken 375766 times.
2778554 true := isZero(e1);
3906 then e1;
3907 case(_,_)
3908 algorithm
3909
2/2
✓ Branch 1 taken 2037354 times.
✓ Branch 2 taken 365434 times.
2402788 true := isZero(e2);
3910 then e2;
3911 case(DAE.RCONST(real = 1.0),_)
3912 then e2;
3913 case(_,DAE.RCONST(real = 1.0))
3914 then e1;
3915 case(DAE.ICONST(1),_)
3916 then e2;
3917 case(_,DAE.ICONST(1))
3918 then e1;
3919 case(DAE.RCONST(r1),DAE.RCONST(r2))
3920 algorithm
3921 8854 r1 := realMul(r1,r2);
3922 8854 then
3923 DAE.RCONST(r1);
3924 case(DAE.ICONST(i1),DAE.ICONST(i2))
3925 algorithm
3926 ✗ i1 := intMul(i1,i2);
3927 ✗ then
3928 DAE.ICONST(i1);
3929 else
3930 algorithm
3931 1252705 tp := typeof(e1);
3932
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1252705 times.
1252705 true := Types.isIntegerOrRealOrSubTypeOfEither(tp);
3933 1252705 b1 := DAEUtil.expTypeArray(tp);
3934 1252705 tp := typeof(e2);
3935
2/2
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 1252691 times.
1252705 true := Types.isIntegerOrRealOrSubTypeOfEither(tp);
3936 1252691 b2 := DAEUtil.expTypeArray(tp);
3937 /* swap e1 and e2 if we have scalar mul array */
3938 1252691 (e1_1,e2_1) := Util.swap((not b1) and b2, e1, e2);
3939 /* Create all kinds of multiplication with scalars or arrays */
3940
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1252689 times.
✓ Branch 3 taken 1252497 times.
✓ Branch 4 taken 192 times.
1252691 op := if b1 and b2 then DAE.MUL_ARR(tp) else (if b1==b2 then DAE.MUL(tp) else DAE.MUL_ARRAY_SCALAR(tp));
3941 1252691 then
3942 DAE.BINARY(e1_1,op,e2_1);
3943 end matchcontinue;
3944 end expMul;
3945
3946 public function expPow "author: vitalij"
3947 input DAE.Exp e1;
3948 input DAE.Exp e2;
3949 output DAE.Exp outExp;
3950
3951 algorithm
3952 outExp := match(e1,e2)
3953 local
3954 Type tp;
3955 DAE.Exp e,e3,e4,e5;
3956 Boolean b;
3957 Operator op;
3958
3959 // e1^1 = e1
3960 case(_,_) guard(isOne(e2))
3961 then e1;
3962
3963 // e1^0 = 1
3964 case(_,_) guard(isZero(e2))
3965 2 then makeConstOne(typeof(e1));
3966
3967 // 1^e2 = 1
3968 case (_,_) guard(isConstOne(e1))
3969 then e1;
3970
3971 // 0^e2 = 0
3972 case (_,_) guard(isZero(e1) and isPositive(e2))
3973 14 then makeConstZero(typeof(e1));
3974
3975 // (-e)^r = e^r if r is even
3976 case (DAE.UNARY(DAE.UMINUS(),e), _) guard(isEven(e2))
3977 ✗ then expPow(e, e2);
3978
3979 // (x/y)^(-z) = (y/x)^z
3980 case (DAE.BINARY(e3, DAE.DIV(), e4), DAE.UNARY(DAE.UMINUS(),e5))
3981 algorithm
3982 ✗ e := makeDiv(e4,e3);
3983 ✗ e := expPow(e,e5);
3984 then e;
3985
3986 // (e1/e2)^(-r) = (e2/e1)^r
3987 case (DAE.BINARY(e3, DAE.DIV(), e4) , _) guard(isNegativeOrZero(e2))
3988 ✗ then expPow(makeDiv(e4,e3), negate(e2));
3989
3990 // x^0.5 => sqrt(x)
3991 case (_, _) guard(isHalf(e2) and isPositiveOrZero(e1))
3992 ✗ then Expression.makePureBuiltinCall("sqrt",{e1},DAE.T_REAL_DEFAULT);
3993
3994 else algorithm
3995 2204 tp := typeof(e1);
3996 2204 b := DAEUtil.expTypeArray(tp);
3997
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2204 times.
2204 op := if b then DAE.POW_ARR(tp) else DAE.POW(tp);
3998 2204 then DAE.BINARY(e1,op,e2);
3999
4000 end match;
4001 end expPow;
4002
4003 public function expPowLst
4004 "
4005 {a,b}^n -> {a^n, b^n}
4006 author: vitalij"
4007 input list<DAE.Exp> expLst;
4008 input DAE.Exp n;
4009 output list<DAE.Exp> outExp = List.map1(expLst, expPow, n);
4010 end expPowLst;
4011
4012 public function expMaxScalar "author: Frenkel TUD 2011-04
4013 returns max(e1,e2)."
4014 input DAE.Exp e1;
4015 input DAE.Exp e2;
4016 output DAE.Exp outExp;
4017 protected
4018 Type tp;
4019 algorithm
4020 15036 tp := typeof(e1);
4021 15036 outExp := DAE.CALL(Absyn.IDENT("max"),{e1,e2},DAE.CALL_ATTR(tp,false,true,false,false,DAE.NO_INLINE(),DAE.NO_TAIL(),DAE.NoReturn.RETURNS));
4022 end expMaxScalar;
4023
4024 public function expOptMaxScalar
4025 input Option<DAE.Exp> e1;
4026 input Option<DAE.Exp> e2;
4027 output Option<DAE.Exp> outExp;
4028 protected
4029 algorithm
4030 outExp := match(e1,e2)
4031 local DAE.Exp e11, e22;
4032 case(_, NONE()) then e1;
4033 case(NONE(), ) then e2;
4034 15030 case(SOME(e11), SOME(e22)) then SOME(expMaxScalar(e11, e22));
4035 end match;
4036 end expOptMaxScalar;
4037
4038
4039 public function expMinScalar "author: Frenkel TUD 2011-04
4040 returns min(e1,e2)."
4041 input DAE.Exp e1;
4042 input DAE.Exp e2;
4043 output DAE.Exp outExp;
4044 protected
4045 Type tp;
4046 algorithm
4047 9186 tp := typeof(e1);
4048 9186 outExp := DAE.CALL(Absyn.IDENT("min"),{e1,e2},DAE.CALL_ATTR(tp, false, true, false, false, DAE.NO_INLINE(), DAE.NO_TAIL(), DAE.NoReturn.RETURNS));
4049 end expMinScalar;
4050
4051 public function expOptMinScalar
4052 input Option<DAE.Exp> e1;
4053 input Option<DAE.Exp> e2;
4054 output Option<DAE.Exp> outExp;
4055 protected
4056 algorithm
4057 outExp := match(e1,e2)
4058 local DAE.Exp e11, e22;
4059 case(_, NONE()) then e1;
4060 case(NONE(), ) then e2;
4061 9180 case(SOME(e11), SOME(e22)) then SOME(expMinScalar(e11, e22));
4062 end match;
4063 end expOptMinScalar;
4064
4065
4066 public function makeProductVector "takes and expression e1 and a list of expressisions {v1,v2,...,vn} and returns
4067 {e1*v1,e1*v2,...,e1*vn}"
4068 input DAE.Exp e1;
4069 input list<DAE.Exp> v;
4070 output list<DAE.Exp> res;
4071 algorithm
4072 ✗ res := List.map1(v,makeProduct,e1);
4073 end makeProductVector;
4074
4075 public function makeScalarProduct
4076 "calculate a scalr product <v,w>"
4077 input array<DAE.Exp> v;
4078 input array<DAE.Exp> w;
4079 output DAE.Exp s = DAE.RCONST(0.0);
4080 protected
4081 Integer size1=arrayLength(v), size2= arrayLength(w);
4082 algorithm
4083
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 231 times.
231 if size1 <> size2 then
4084 ✗ print("makeScalarProduct faili.\n");
4085 ✗ return ;
4086 end if;
4087
4088
2/2
✓ Branch 0 taken 4566 times.
✓ Branch 1 taken 231 times.
4797 s := makeSum1(list( expMul(arrayGet(v,i), arrayGet(w,i)) for i in 1:size1 ));
4089 231 (s,_) := ExpressionSimplify.simplify(s);
4090
4091 end makeScalarProduct;
4092
4093 public function lenVec
4094 input array<DAE.Exp> v;
4095 output DAE.Exp len = makeScalarProduct(v,v);
4096 algorithm
4097 20 len := Expression.makePureBuiltinCall("sqrt",{len},DAE.T_REAL_DEFAULT);
4098 end lenVec;
4099
4100 public function subVec
4101 input array<DAE.Exp> v;
4102 input array<DAE.Exp> w;
4103 output array<DAE.Exp> y;
4104
4105 protected
4106 Integer size1=arrayLength(v), size2= arrayLength(w);
4107 algorithm
4108 ✗ if size1 <> size2 then
4109 ✗ print("subVec fail.\n");
4110 ✗ fail();
4111 end if;
4112 ✗ y := arrayCreate(size1, DAE.RCONST(0.0));
4113 ✗ for i in 1:size1 loop
4114 ✗ arrayUpdate(y,i,expSub(arrayGet(v,i), arrayGet(w,i)));
4115 end for;
4116 end subVec;
4117
4118
4119 public function makeProduct
4120 "Makes a product of two expressions"
4121 input DAE.Exp e1;
4122 input DAE.Exp e2;
4123 output DAE.Exp product;
4124 algorithm
4125 15522 product := makeProductLst({e1,e2});
4126 end makeProduct;
4127
4128 public function makeProductLst
4129 "Takes a list of expressions an makes a product
4130 expression multiplying all elements in the list."
4131 input list<DAE.Exp> inExpLst;
4132 output DAE.Exp outExp;
4133 algorithm
4134 outExp:=
4135 matchcontinue inExpLst
4136 local
4137 DAE.Exp e1,res,e,e2,p1;
4138 list<DAE.Exp> es,rest,lst;
4139 Type tp;
4140 list<String> explst;
4141 String str;
4142 Boolean b_isZero,b1,b2;
4143 case {} then DAE.RCONST(1.0);
4144 case {e1} then e1;
4145 case e :: es /* to prevent infinite recursion, disregard constant 1. */
4146 algorithm
4147
2/2
✓ Branch 1 taken 3627362 times.
✓ Branch 2 taken 124 times.
3627486 true := isConstOne(e);
4148 124 res := makeProductLst(es);
4149 then
4150 res;
4151 // e1/e*e2 for e = 0 => fail
4152 case DAE.BINARY(operator = DAE.DIV(),exp2 = e)::_
4153 algorithm
4154 85909 true := isZero(e);
4155 85909 then
4156 fail();
4157
4158 // e2*e1/e for e = 0 => fail
4159 case {_,DAE.BINARY(operator = DAE.DIV(),exp2 = e)}
4160 algorithm
4161 145426 true := isZero(e);
4162 then
4163 fail();
4164 case e :: _ /* to prevent infinite recursion, disregard constant 0. */
4165 algorithm
4166
2/2
✓ Branch 1 taken 3626610 times.
✓ Branch 2 taken 752 times.
3627362 true := isZero(e);
4167 then e;
4168 case {DAE.BINARY(exp1 = e1,operator = DAE.DIV(ty = tp),exp2 = e),e2}
4169 algorithm
4170
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 58482 times.
58482 true := isConstOne(e1);
4171 58482 then
4172 DAE.BINARY(e2,DAE.DIV(tp),e);
4173 case {e2,DAE.BINARY(exp1 = e1,operator = DAE.DIV(ty = tp),exp2 = e)}
4174 algorithm
4175
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 100686 times.
100686 true := isConstOne(e1);
4176 100686 then
4177 DAE.BINARY(e2,DAE.DIV(tp),e);
4178 case DAE.BINARY(exp1 = e1,operator = DAE.DIV(ty = tp),exp2 = e) :: es
4179 algorithm
4180
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 27427 times.
27427 true := isConstOne(e1);
4181 27427 p1 := makeProductLst(es);
4182 27427 res := DAE.BINARY(p1,DAE.DIV(tp),e);
4183 27427 b_isZero := isZero(p1);
4184
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27427 times.
27427 res := if b_isZero then makeConstZero(typeof(e)) else res;
4185 then
4186 res;
4187 case {e1,e2}
4188 algorithm
4189
1/2
✓ Branch 1 taken 2968982 times.
✗ Branch 2 not taken.
2968982 true := isConstOne(e2);
4190 then
4191 e1;
4192 case {e1,e2}
4193 algorithm
4194 2968982 b1 := isZero(e1);
4195 2968982 b2 := isZero(e2);
4196 2968982 b_isZero := boolOr(b1,b2);
4197 2968982 tp := typeof(e1) "Take type info from e1, ok since type checking already performed." ;
4198 2968982 tp := checkIfOther(tp);
4199 2968982 res := DAE.BINARY(e1,DAE.MUL(tp),e2);
4200
2/2
✓ Branch 0 taken 834 times.
✓ Branch 1 taken 2968148 times.
2968982 res := if b_isZero then makeConstZero(tp) else res;
4201 then
4202 res;
4203 case e1 :: rest
4204 algorithm
4205 471033 e2 := makeProductLst(rest);
4206 471033 tp := typeof(e1);
4207 471033 tp := checkIfOther(tp);
4208 471033 res := DAE.BINARY(e1,DAE.MUL(tp),e2);
4209 471033 b1 := isZero(e1);
4210 471033 b2 := isZero(e2);
4211 471033 b_isZero := boolOr(b1,b2);
4212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 471033 times.
471033 res := if b_isZero then makeConstZero(typeof(e1)) else res;
4213 then
4214 res;
4215 case lst
4216 algorithm
4217 ✗ true := Flags.isSet(Flags.FAILTRACE);
4218 ✗ Debug.trace("-Expression.makeProductLst failed, DAE.Exp lst:");
4219 ✗ explst := List.map(lst, ExpressionBasics.printExpStr);
4220 ✗ str := stringDelimitList(explst, ", ");
4221 ✗ Debug.traceln(str);
4222 ✗ then
4223 fail();
4224 end matchcontinue;
4225 end makeProductLst;
4226
4227 protected function checkIfOther
4228 "Checks if a type is OTHER and in that case returns REAL instead.
4229 This is used to make proper transformations in case OTHER is
4230 retrieved from subexpression where it should instead be REAL or INT"
4231 input DAE.Type inTp;
4232 output DAE.Type outTp;
4233 algorithm
4234 outTp := match inTp
4235 case DAE.T_UNKNOWN() then DAE.T_REAL_DEFAULT;
4236 else inTp;
4237 end match;
4238 end checkIfOther;
4239
4240 public function expDiv "
4241 function expDiv
4242 author: PA
4243 Divides two scalar expressions."
4244 input DAE.Exp e1;
4245 input DAE.Exp e2;
4246 output DAE.Exp outExp;
4247 protected
4248 Type tp;
4249 Boolean b;
4250 Operator op;
4251 algorithm
4252 24059 tp := typeof(e1);
4253
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 24059 times.
24059 true := Types.isIntegerOrRealOrSubTypeOfEither(tp);
4254 24059 b := DAEUtil.expTypeArray(tp);
4255
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 24058 times.
24059 op := if b then DAE.DIV_ARR(tp) else DAE.DIV(tp);
4256 24059 outExp := DAE.BINARY(e1,op,e2);
4257 end expDiv;
4258
4259 public function makeDiv "Takes two expressions and create a division"
4260 input DAE.Exp e1;
4261 input DAE.Exp e2;
4262 output DAE.Exp res;
4263 algorithm
4264 res := match e2
4265 case _ guard(isZero(e1) and not isZero(e2))
4266 then e1;
4267 case _ guard(isOne(e2))
4268 then e1;
4269 23372 else expDiv(e1,e2);
4270 end match;
4271 end makeDiv;
4272
4273 public function makeDivVector "takes and expression e1 and a list of expressisions {v1,v2,...,vn} and returns
4274 {v1/e1,v2/e1,...,vn/e1}"
4275 input list<DAE.Exp> v;
4276 input DAE.Exp e1;
4277 output list<DAE.Exp> res;
4278 algorithm
4279 ✗ res := List.map1(v,makeDiv,e1);
4280 end makeDivVector;
4281
4282 public function makeAsubAddIndex "creates an ASUB given an expression and an index"
4283 input DAE.Exp e;
4284 input Integer indx;
4285 output DAE.Exp outExp = e;
4286 algorithm
4287 outExp := match outExp
4288 case DAE.ASUB()
4289 algorithm
4290 ✗ outExp.sub := listAppend(outExp.sub, {DAE.INDEX(DAE.ICONST(indx))});
4291 then
4292 outExp;
4293
4294 ✗ else makeASUB(e, {DAE.ICONST(indx)});
4295 end match;
4296 end makeAsubAddIndex;
4297
4298 public function makeIntegerExp
4299 "Creates an integer constant expression given the integer input."
4300 input Integer i;
4301 output DAE.Exp e;
4302 annotation(__OpenModelica_EarlyInline = true);
4303 algorithm
4304 2317 e := DAE.ICONST(i);
4305 end makeIntegerExp;
4306
4307 public function makeRealExp
4308 "Creates an integer constant expression given the integer input."
4309 input Real r;
4310 output DAE.Exp e;
4311 annotation(__OpenModelica_EarlyInline = true);
4312 algorithm
4313 ✗ e := DAE.RCONST(r);
4314 end makeRealExp;
4315
4316 public function makeBoolExp
4317 "Creates an integer constant expression given the integer input."
4318 input Boolean b;
4319 output DAE.Exp e;
4320 annotation(__OpenModelica_EarlyInline = true);
4321 algorithm
4322 ✗ e := DAE.BCONST(b);
4323 end makeBoolExp;
4324
4325 public function makeConstOne
4326 "author: PA
4327 Create the constant value one, given a type that is INT or REAL"
4328 input DAE.Type inType;
4329 output DAE.Exp outExp;
4330 algorithm
4331 outExp := match inType
4332 case DAE.T_INTEGER() then DAE.ICONST(1);
4333 case DAE.T_REAL() then DAE.RCONST(1.0);
4334 else DAE.RCONST(1.0);
4335 end match;
4336 end makeConstOne;
4337
4338 public function makeConstZero
4339 "Generates a zero constant"
4340 input DAE.Type inType;
4341 output DAE.Exp const;
4342 algorithm
4343 const := match inType
4344 case DAE.T_REAL() then DAE.RCONST(0.0);
4345 case DAE.T_INTEGER() then DAE.ICONST(0);
4346 else DAE.RCONST(0.0);
4347 end match;
4348 end makeConstZero;
4349
4350 function makeConstNumber
4351 input DAE.Type ty;
4352 input Integer n;
4353 output DAE.Exp exp;
4354 algorithm
4355 exp := match ty
4356 ✗ case DAE.T_INTEGER() then DAE.ICONST(n);
4357 528 else DAE.RCONST(n);
4358 end match;
4359 end makeConstNumber;
4360
4361 public function makeConstZeroE
4362 "Generates a zero constant, using type from inExp"
4363 input DAE.Exp iExp;
4364 output DAE.Exp const;
4365 protected
4366 DAE.Type tp = typeof(iExp);
4367 algorithm
4368 16 const := makeConstZero(tp);
4369 end makeConstZeroE;
4370
4371
4372 public function makeListOfZeros
4373 input Integer inDimension;
4374 output list<DAE.Exp> outList = {};
4375 algorithm
4376
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 806 times.
806 if (inDimension > 0) then
4377 2418 for i in 1:inDimension loop
4378 outList := DAE.RCONST(0.0) :: outList;
4379 end for;
4380 end if;
4381 end makeListOfZeros;
4382
4383 public function makeRealArrayOfZeros
4384 input Integer inDimension;
4385 output DAE.Exp outExp;
4386 protected
4387 list<DAE.Exp> l;
4388 algorithm
4389 806 l := makeListOfZeros(inDimension);
4390 806 outExp := makeRealArray(l);
4391 end makeRealArrayOfZeros;
4392
4393 public function createZeroExpression
4394 input DAE.Type inType;
4395 output DAE.Exp outExp;
4396 algorithm
4397 outExp := match inType
4398 local
4399 DAE.Exp e;
4400 list<DAE.Type> typeLst;
4401 list<DAE.Exp> expLst;
4402 DAE.Dimensions dims;
4403 Absyn.Path path;
4404 list<DAE.Var> varLst;
4405 list<String> varNames;
4406
4407 // real and integer
4408 1857 case _ guard(isIntegerOrReal(inType)) then makeConstZero(inType);
4409
4410 case DAE.T_TUPLE(types=typeLst) algorithm
4411 ✗ expLst := List.map(typeLst, createZeroExpression);
4412 ✗ e := DAE.TUPLE(expLst);
4413 then e;
4414
4415 case DAE.T_ARRAY(dims=dims) algorithm
4416 ✗ (e, _) := makeZeroExpression(dims);
4417 then e;
4418
4419 // record type
4420 case DAE.T_COMPLEX(varLst=varLst,complexClassType=ClassInf.RECORD(path)) algorithm
4421 ✗ typeLst := list(v.ty for v in varLst);
4422 ✗ expLst := List.map(typeLst, createZeroExpression);
4423 ✗ varNames := List.map(varLst, varName);
4424 ✗ true := listLength(varNames) == listLength(expLst);
4425 ✗ e := DAE.RECORD(path, expLst, varNames, inType);
4426 then e;
4427
4428 // all other are failing cases
4429 else fail();
4430 end match;
4431 end createZeroExpression;
4432
4433
4434 public function makeZeroExpression
4435 " creates a Real or array<Real> zero expression with given dimensions, also returns its type"
4436 input DAE.Dimensions inDims;
4437 output DAE.Exp outExp;
4438 output DAE.Type outType;
4439 algorithm
4440 (outExp,outType) := match inDims
4441 local
4442 Integer i;
4443 DAE.Dimension d;
4444 DAE.Dimensions dims;
4445 DAE.Exp e;
4446 list<DAE.Exp> eLst;
4447 DAE.Type ty;
4448 Boolean scalar;
4449
4450 case {} then (DAE.RCONST(0.0), DAE.T_REAL_DEFAULT);
4451
4452 case d::dims
4453 algorithm
4454 16809 i := dimensionSize(d);
4455 16791 (e, ty) := makeZeroExpression(dims);
4456 16791 eLst := List.fill(e,i);
4457 16791 scalar := listEmpty(dims);
4458
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 16783 times.
33590 then
4459 (DAE.ARRAY(DAE.T_ARRAY(DAE.T_REAL_DEFAULT,d::dims),scalar,eLst),
4460 DAE.T_ARRAY(ty,{d}));
4461 end match;
4462 end makeZeroExpression;
4463
4464 public function makeOneExpression
4465 " creates a Real or array<Real> one expression with given dimensions, also returns its type"
4466 input DAE.Dimensions inDims;
4467 output DAE.Exp outExp;
4468 output DAE.Type outType;
4469 algorithm
4470 (outExp,outType) := match inDims
4471 local
4472 Integer i;
4473 DAE.Dimension d;
4474 DAE.Dimensions dims;
4475 DAE.Exp e;
4476 list<DAE.Exp> eLst;
4477 DAE.Type ty;
4478 Boolean scalar;
4479
4480 case {} then (DAE.RCONST(1.0), DAE.T_REAL_DEFAULT);
4481
4482 case d::dims
4483 algorithm
4484 28 i := dimensionSize(d);
4485 28 (e, ty) := makeOneExpression(dims);
4486 28 eLst := List.fill(e,i);
4487 28 scalar := listEmpty(dims);
4488
2/2
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 16 times.
68 then
4489 (DAE.ARRAY(DAE.T_ARRAY(DAE.T_REAL_DEFAULT,d::dims),scalar,eLst),
4490 DAE.T_ARRAY(ty,{d}));
4491 end match;
4492 end makeOneExpression;
4493
4494 public function listToArray
4495 " @mahge:
4496 creates an array from a list of expressions and
4497 dimensions. e.g.
4498 listToArray({1,2,3,4,5,6}, {3,2}) -> {{1,2}, {3,4}, {5,6}}
4499 "
4500 input list<DAE.Exp> inList;
4501 input DAE.Dimensions dims;
4502 output DAE.Exp oExp;
4503 algorithm
4504 oExp := matchcontinue(inList, dims)
4505 local
4506 DAE.Type ty;
4507 DAE.Exp exp;
4508
4509 case(_, {})
4510 algorithm
4511 ✗ Error.addMessage(Error.INTERNAL_ERROR, {"Expression.listToArray called with empty dimension list."});
4512 ✗ then fail();
4513
4514 case({}, _)
4515 algorithm
4516 ✗ Error.addMessage(Error.INTERNAL_ERROR, {"Expression.listToArray called with empty list."});
4517 ✗ then fail();
4518
4519 // Here we assume that all the elements of the list
4520 // have the same type.
4521 case(exp::_, _)
4522 algorithm
4523 78 ty := typeof(exp);
4524 78 oExp := listToArray2(inList,dims,ty);
4525 then
4526 oExp;
4527 end matchcontinue;
4528
4529 end listToArray;
4530
4531
4532 protected function listToArray2
4533 input list<DAE.Exp> inList;
4534 input DAE.Dimensions iDims;
4535 input DAE.Type inType;
4536 output DAE.Exp oExp;
4537 algorithm
4538 () := match iDims
4539 local
4540 Integer i;
4541 DAE.Dimension d;
4542 list<DAE.Exp> explst;
4543 DAE.Dimensions dims;
4544 Boolean is_scalar;
4545 DAE.Type ty;
4546
4547 case {d}
4548 algorithm
4549 78 is_scalar := not Types.isArray(inType);
4550
1/2
✓ Branch 1 taken 78 times.
✗ Branch 2 not taken.
78 if dimensionKnown(d) then
4551 78 i := dimensionSize(d);
4552
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 78 times.
78 if i <> listLength(inList) then
4553 ✗ Error.addMessage(Error.INTERNAL_ERROR, {"Expression.listToArray2: Number of elements in the list does not match the dimension size."});
4554 ✗ fail();
4555 else
4556 78 ty := liftArrayR(inType, DAE.DIM_INTEGER(listLength(inList)));
4557
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 71 times.
85 oExp := DAE.ARRAY(ty, is_scalar, inList);
4558 end if;
4559 // We do not know the dimension size but we have only one dimension.
4560 // WE just create a one dimensional array and hope for the best. This is needed for
4561 // codegen when we have to expand an array crefexp to an array expression. Sometimes
4562 // we get an unevaluated dimension for a model variable all the way down in codegen :(
4563 else
4564 ✗ ty := liftArrayR(inType, d);
4565 ✗ oExp := DAE.ARRAY(ty, is_scalar, inList);
4566 end if;
4567 then ();
4568
4569 case _ :: _
4570 algorithm
4571 7 (d, dims) := List.splitLast(iDims);
4572 7 explst := listToArray3(inList,d);
4573 7 ty := liftArrayR(inType, DAE.DIM_INTEGER(listLength(explst)));
4574 7 oExp := listToArray2(explst,dims,ty);
4575 then
4576 ();
4577
4578 end match;
4579 end listToArray2;
4580
4581
4582 protected function listToArray3
4583 input list<DAE.Exp> inList;
4584 input DAE.Dimension iDim;
4585 output list<DAE.Exp> oExps;
4586 algorithm
4587 oExps := match(inList, iDim)
4588 local
4589 Integer i;
4590 DAE.Dimension d;
4591 list<DAE.Exp> explst, restexps, restarr;
4592 DAE.Exp arrexp;
4593
4594 case({}, _) then {};
4595
4596 case(_, d)
4597 algorithm
4598 26 i := dimensionSize(d);
4599
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
26 if (i > listLength(inList)) then
4600 ✗ Error.addMessage(Error.INTERNAL_ERROR, {"Expression.listToArray3: Not enough elements left in list to fit dimension."});
4601 ✗ fail();
4602 else
4603 26 (explst, restexps) := List.split(inList,i);
4604 26 arrexp := makeArrayFromList(explst);
4605 26 restarr := listToArray3(restexps,d);
4606 end if;
4607 then
4608 arrexp::restarr;
4609
4610 end match;
4611 end listToArray3;
4612
4613
4614 public function arrayFill
4615 input DAE.Dimensions dims;
4616 input DAE.Exp inExp;
4617 output DAE.Exp oExp;
4618 algorithm
4619 oExp := match dims
4620
4621 case {} then inExp;
4622
4623 else
4624 algorithm
4625 4 oExp := arrayFill2(dims,inExp);
4626 then
4627 oExp;
4628
4629 end match;
4630 end arrayFill;
4631
4632 protected function arrayFill2
4633 input DAE.Dimensions iDims;
4634 input DAE.Exp inExp;
4635 output DAE.Exp oExp;
4636 algorithm
4637 oExp := match iDims
4638 local
4639 Integer i;
4640 DAE.Dimension d;
4641 Type ty;
4642 list<DAE.Exp> expl;
4643 DAE.Exp arrexp;
4644 DAE.Dimensions dims;
4645
4646 case {d}
4647 algorithm
4648 5 ty := typeof(inExp);
4649 5 i := dimensionSize(d);
4650 5 expl := List.fill(inExp, i);
4651 10 then
4652 DAE.ARRAY(DAE.T_ARRAY(ty,{DAE.DIM_INTEGER(i)}),true,expl);
4653
4654 case d::dims
4655 algorithm
4656 1 arrexp := arrayFill2({d},inExp);
4657 1 arrexp := arrayFill2(dims,arrexp);
4658 then
4659 arrexp;
4660
4661 end match;
4662 end arrayFill2;
4663
4664 public function makeIndexSubscript
4665 "Creates a Subscript INDEX from an Expression."
4666 input DAE.Exp exp;
4667 output DAE.Subscript subscript;
4668 annotation(__OpenModelica_EarlyInline = true);
4669 algorithm
4670 2294 subscript := DAE.INDEX(exp);
4671 end makeIndexSubscript;
4672
4673 public function makeVar "Creates a Var given a name and Type"
4674 input String name;
4675 input DAE.Type tp;
4676 output DAE.Var v;
4677 annotation(__OpenModelica_EarlyInline = true);
4678 algorithm
4679 79673 v := DAE.TYPES_VAR(name, DAE.dummyAttrVar, tp, DAE.UNBOUND(), false, NONE());
4680 end makeVar;
4681
4682 public function dimensionsAdd
4683 "Adds two dimensions."
4684 input DAE.Dimension dim1;
4685 input DAE.Dimension dim2;
4686 output DAE.Dimension res;
4687 algorithm
4688 try
4689 9738 res := intDimension(dimensionSize(dim1) + dimensionSize(dim2));
4690 else
4691 res := DAE.DIM_UNKNOWN();
4692 end try;
4693 end dimensionsAdd;
4694
4695 public function concatArrayType
4696 "Concatenates two array types, so that the resulting type is correct."
4697 input DAE.Type arrayType1;
4698 input DAE.Type arrayType2;
4699 output DAE.Type concatType;
4700 algorithm
4701 concatType := match(arrayType1, arrayType2)
4702 local
4703 DAE.Type et;
4704 DAE.Dimension dim1, dim2;
4705 DAE.Dimensions dims1;
4706
4707 case (DAE.T_ARRAY(ty = et, dims = dim1 :: dims1), DAE.T_ARRAY(dims = dim2 :: _))
4708 algorithm
4709 3783 dim1 := dimensionsAdd(dim1, dim2);
4710 3783 then
4711 DAE.T_ARRAY(et, dim1 :: dims1);
4712 end match;
4713 end concatArrayType;
4714
4715 public function replaceExpTpl
4716 "Help function to e.g. detectImplicitDiscreteAlgsStatemensFor"
4717 input DAE.Exp inExp;
4718 input tuple<DAE.Exp, DAE.Exp> tpl;
4719 output DAE.Exp outExp;
4720 output tuple<DAE.Exp, DAE.Exp> outTpl;
4721 algorithm
4722 (outExp,outTpl) := match(inExp,tpl)
4723 local
4724 DAE.Exp e, e1, s, t;
4725
4726 case (e, (s, t))
4727 algorithm
4728 268 (e1, _) := replaceExp(e, s, t);
4729 then (e1, tpl);
4730
4731 end match;
4732 end replaceExpTpl;
4733
4734 public function replaceExp
4735 "Helper function to replaceExpList."
4736 input DAE.Exp inExp;
4737 input DAE.Exp inSourceExp;
4738 input DAE.Exp inTargetExp;
4739 output DAE.Exp exp;
4740 output Integer i;
4741 algorithm
4742
2/2
✓ Branch 2 taken 106 times.
✓ Branch 3 taken 1880 times.
1986 (exp,(_,_,i)) := traverseExpTopDown(inExp,replaceExpWork,(inSourceExp,inTargetExp,0));
4743 end replaceExp;
4744
4745 protected function replaceExpWork
4746 input DAE.Exp inExp;
4747 input tuple<DAE.Exp,DAE.Exp,Integer> inTpl;
4748 output DAE.Exp outExp;
4749 output Boolean cont;
4750 output tuple<DAE.Exp,DAE.Exp,Integer> otpl;
4751 algorithm
4752 (outExp,cont,otpl) := match inTpl
4753 local
4754 DAE.Exp source,target;
4755 Integer c;
4756 case (source,target,c)
4757 guard ExpressionBasics.expEqual(inExp, source)
4758 2151 then (target,false,(source,target,c+1));
4759
4760 else (inExp,true,inTpl);
4761 end match;
4762 end replaceExpWork;
4763
4764 public function replaceExpNoEvent
4765 "Like replaceExp, but does not descend into noEvent() or smooth() calls.
4766 Relations inside such operators are evaluated continuously (without state
4767 events), so replacing them by an (event-based, discrete) variable would
4768 change the model semantics. Replacing a whole noEvent()/smooth() expression
4769 is still possible, since the equality check happens before the descent stop."
4770 input DAE.Exp inExp;
4771 input DAE.Exp inSourceExp;
4772 input DAE.Exp inTargetExp;
4773 output DAE.Exp exp;
4774 output Integer i;
4775 algorithm
4776
1/2
✓ Branch 2 taken 159513 times.
✗ Branch 3 not taken.
159513 (exp,(_,_,i)) := traverseExpTopDown(inExp,replaceExpWorkNoEvent,(inSourceExp,inTargetExp,0));
4777 end replaceExpNoEvent;
4778
4779 protected function replaceExpWorkNoEvent
4780 input DAE.Exp inExp;
4781 input tuple<DAE.Exp,DAE.Exp,Integer> inTpl;
4782 output DAE.Exp outExp;
4783 output Boolean cont;
4784 output tuple<DAE.Exp,DAE.Exp,Integer> otpl;
4785 algorithm
4786 (outExp,cont,otpl) := match (inExp, inTpl)
4787 local
4788 DAE.Exp source,target;
4789 Integer c;
4790 case (_, (source,target,c))
4791 guard ExpressionBasics.expEqual(inExp, source)
4792 2352 then (target,false,(source,target,c+1));
4793
4794 // do not replace inside noEvent()/smooth(): expressions there are
4795 // continuous, substituting them by an event-based variable is unsound
4796 case (DAE.CALL(path=Absyn.IDENT(name="noEvent")), _)
4797 then (inExp,false,inTpl);
4798
4799 case (DAE.CALL(path=Absyn.IDENT(name="smooth")), _)
4800 then (inExp,false,inTpl);
4801
4802 else (inExp,true,inTpl);
4803 end match;
4804 end replaceExpWorkNoEvent;
4805
4806 public function expressionCollector
4807 input DAE.Exp exp;
4808 input list<DAE.Exp> acc;
4809 output DAE.Exp outExp;
4810 output list<DAE.Exp> outExps;
4811 algorithm
4812 outExp := exp;
4813 outExps := exp::acc;
4814 end expressionCollector;
4815
4816
4817 public function replaceCrefBottomUp
4818 input DAE.Exp inExp;
4819 input DAE.ComponentRef inSourceExp;
4820 input DAE.Exp inTargetExp;
4821 output DAE.Exp exp;
4822 algorithm
4823 32 (exp,_) := traverseExpBottomUp(inExp,replaceCref,(inSourceExp,inTargetExp));
4824 end replaceCrefBottomUp;
4825
4826 public function replaceCref
4827 "Replace a componentref with a expression"
4828 input DAE.Exp inExp;
4829 input tuple<DAE.ComponentRef,DAE.Exp> inTpl;
4830 output DAE.Exp outExp;
4831 output tuple<DAE.ComponentRef,DAE.Exp> otpl;
4832 algorithm
4833 (outExp,otpl) := match (inExp,inTpl)
4834 local
4835 DAE.Exp target;
4836 DAE.ComponentRef cr,cr1;
4837 case (DAE.CREF(componentRef=cr),(cr1,target))
4838 guard ComponentReferenceBasics.crefEqualNoStringCompare(cr, cr1)
4839 then
4840 (target,inTpl);
4841 else (inExp,inTpl);
4842 end match;
4843 end replaceCref;
4844
4845 public function containsInitialCall "public function containsInitialCall
4846 author: lochel
4847 Spec33 p. 90:
4848 [...] The equations of a when-clause are active during initialization, if
4849 and only if they are explicitly enabled with the initial() operator; and
4850 only in one of the two forms when initial() then or when {…,initial(),…}
4851 then. [...]"
4852 input DAE.Exp condition; // expression of a when-clause
4853 output Boolean res;
4854 algorithm
4855 res := match condition
4856 local
4857 list<Exp> array;
4858
4859 case DAE.CALL(path = Absyn.IDENT(name = "initial"))
4860 then true;
4861
4862 case DAE.ARRAY(array=array)
4863 189 then List.any(array, containsInitialCall);
4864
4865 else false;
4866 end match;
4867 end containsInitialCall;
4868
4869 /***************************************************/
4870 /* traverse DAE.Exp */
4871 /***************************************************/
4872
4873 public function traverseExpBottomUp<T>
4874 "Traverses all subexpressions of an expression.
4875 Takes a function and an extra argument passed through the traversal.
4876 The function can potentially change the expression. In such cases,
4877 the changes are made bottom-up, i.e. a subexpression is traversed
4878 and changed before the complete expression is traversed.
4879
4880 NOTE: The user-provided function is not allowed to fail! If you want to
4881 detect a failure, return NONE() in your user-provided datatype."
4882 input DAE.Exp inExp;
4883 input FuncExpType inFunc;
4884 input T inExtArg;
4885 output DAE.Exp outExp;
4886 output T outExtArg;
4887
4888 partial function FuncExpType
4889 input DAE.Exp inExp;
4890 input T inExtArg;
4891 output DAE.Exp outExp;
4892 output T outExtArg;
4893 end FuncExpType;
4894 algorithm
4895 (outExp, outExtArg) := match inExp
4896 local
4897 DAE.Exp e1_1, e, e1, e2_1, e2, e3_1, e3;
4898 T ext_arg;
4899 Operator op;
4900 list<DAE.Exp> expl_1, expl;
4901 Absyn.Path fn;
4902 Boolean scalar;
4903 Type tp, t;
4904 Integer i;
4905 list<list<DAE.Exp>> lstexpl_1, lstexpl;
4906 Integer dim;
4907 String str;
4908 list<DAE.Element> localDecls;
4909 list<String> fieldNames;
4910 DAE.CallAttributes attr;
4911 list<DAE.MatchCase> cases, cases_1;
4912 DAE.MatchType matchTy;
4913 Integer index_;
4914 Option<tuple<DAE.Exp, Integer, Integer>> isExpisASUB;
4915 DAE.ReductionInfo reductionInfo;
4916 DAE.ReductionIterators riters, riters_1;
4917 DAE.ComponentRef cr, cr_1;
4918 list<list<String>> aliases;
4919 DAE.ClockKind clk, clk1;
4920 list<DAE.Type> typeVars;
4921 list<DAE.Subscript> subs;
4922
4923 case DAE.EMPTY() algorithm
4924
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 (e, ext_arg) := inFunc(inExp, inExtArg);
4925 then (e, ext_arg);
4926
4927 case DAE.ICONST() algorithm
4928
2/2
✓ Branch 0 taken 18547957 times.
✓ Branch 1 taken 49558377 times.
68106334 (e, ext_arg) := inFunc(inExp, inExtArg);
4929 then (e, ext_arg);
4930
4931 case DAE.RCONST() algorithm
4932
2/2
✓ Branch 0 taken 9765578 times.
✓ Branch 1 taken 56322051 times.
66087629 (e, ext_arg) := inFunc(inExp, inExtArg);
4933 then (e, ext_arg);
4934
4935 case DAE.SCONST() algorithm
4936
2/2
✓ Branch 0 taken 1708485 times.
✓ Branch 1 taken 6693753 times.
8402238 (e, ext_arg) := inFunc(inExp, inExtArg);
4937 then (e, ext_arg);
4938
4939 case DAE.BCONST() algorithm
4940
2/2
✓ Branch 0 taken 497226 times.
✓ Branch 1 taken 1582041 times.
2079267 (e, ext_arg) := inFunc(inExp, inExtArg);
4941 then (e, ext_arg);
4942
4943 case DAE.CLKCONST(clk) algorithm
4944 1717 (clk1, ext_arg) := traverseExpClk(clk, inFunc, inExtArg);
4945
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1711 times.
1717 e := if referenceEq(clk1, clk) then inExp else DAE.CLKCONST(clk1);
4946
2/2
✓ Branch 0 taken 739 times.
✓ Branch 1 taken 978 times.
1717 (e, ext_arg) := inFunc(e, ext_arg);
4947 then (e, ext_arg);
4948
4949 case DAE.ENUM_LITERAL() algorithm
4950
2/2
✓ Branch 0 taken 586392 times.
✓ Branch 1 taken 644789 times.
1231181 (e, ext_arg) := inFunc(inExp, inExtArg);
4951 then (e, ext_arg);
4952
4953 case DAE.CREF(cr, tp) algorithm
4954
2/2
✓ Branch 1 taken 28092729 times.
✓ Branch 2 taken 49053853 times.
77146582 if ComponentReferenceBasics.crefHasNoSubscripts(cr) then
4955
2/2
✓ Branch 0 taken 8375938 times.
✓ Branch 1 taken 19716791 times.
28092729 (e, ext_arg) := inFunc(inExp, inExtArg);
4956 else
4957 49053853 (cr_1, ext_arg) := traverseExpCref(cr, inFunc, inExtArg);
4958
2/2
✓ Branch 0 taken 38667 times.
✓ Branch 1 taken 49015186 times.
49053853 e := if referenceEq(cr, cr_1) then inExp else DAE.CREF(cr_1, tp);
4959
2/2
✓ Branch 0 taken 13677750 times.
✓ Branch 1 taken 35376103 times.
49053853 (e, ext_arg) := inFunc(e, ext_arg);
4960 end if;
4961 77146582 then (e, ext_arg);
4962
4963 // unary
4964 case DAE.UNARY(operator=op, exp=e1) algorithm
4965 3293278 (e1_1, ext_arg) := traverseExpBottomUp(e1, inFunc, inExtArg);
4966
2/2
✓ Branch 0 taken 327637 times.
✓ Branch 1 taken 2965641 times.
3293278 e := if referenceEq(e1, e1_1) then inExp else DAE.UNARY(op, e1_1);
4967
2/2
✓ Branch 0 taken 641444 times.
✓ Branch 1 taken 2651834 times.
3293278 (e, ext_arg) := inFunc(e, ext_arg);
4968 then (e, ext_arg);
4969
4970 // binary
4971 case DAE.BINARY(exp1=e1, operator=op, exp2=e2) algorithm
4972 62476541 (e1_1, ext_arg) := traverseExpBottomUp(e1, inFunc, inExtArg);
4973 62476541 (e2_1, ext_arg) := traverseExpBottomUp(e2, inFunc, ext_arg);
4974
2/2
✓ Branch 0 taken 7490506 times.
✓ Branch 1 taken 54986035 times.
62476541 e := if referenceEq(e1, e1_1) and referenceEq(e2, e2_1) then inExp else DAE.BINARY(e1_1, op, e2_1);
4975
2/2
✓ Branch 0 taken 13651086 times.
✓ Branch 1 taken 48825455 times.
62476541 (e, ext_arg) := inFunc(e, ext_arg);
4976 then (e, ext_arg);
4977
4978 // logical unary
4979 case DAE.LUNARY(operator=op, exp=e1) algorithm
4980 93789 (e1_1, ext_arg) := traverseExpBottomUp(e1, inFunc, inExtArg);
4981
2/2
✓ Branch 0 taken 2527 times.
✓ Branch 1 taken 91262 times.
93789 e := if referenceEq(e1, e1_1) then inExp else DAE.LUNARY(op, e1_1);
4982
2/2
✓ Branch 0 taken 38222 times.
✓ Branch 1 taken 55567 times.
93789 (e, ext_arg) := inFunc(e, ext_arg);
4983 then (e, ext_arg);
4984
4985 // logical binary
4986 case DAE.LBINARY(exp1=e1, operator=op, exp2=e2) algorithm
4987 558755 (e1_1, ext_arg) := traverseExpBottomUp(e1, inFunc, inExtArg);
4988 558755 (e2_1, ext_arg) := traverseExpBottomUp(e2, inFunc, ext_arg);
4989
2/2
✓ Branch 0 taken 17613 times.
✓ Branch 1 taken 541142 times.
558755 e := if referenceEq(e1, e1_1) and referenceEq(e2, e2_1) then inExp else DAE.LBINARY(e1_1, op, e2_1);
4990
2/2
✓ Branch 0 taken 242363 times.
✓ Branch 1 taken 316392 times.
558755 (e, ext_arg) := inFunc(e, ext_arg);
4991 then (e, ext_arg);
4992
4993 // relation
4994 case DAE.RELATION(exp1=e1, operator=op, exp2=e2, index=index_, optionExpisASUB=isExpisASUB) algorithm
4995 1537068 (e1_1, ext_arg) := traverseExpBottomUp(e1, inFunc, inExtArg);
4996 1537068 (e2_1, ext_arg) := traverseExpBottomUp(e2, inFunc, ext_arg);
4997
2/2
✓ Branch 0 taken 40876 times.
✓ Branch 1 taken 1496192 times.
1537068 e := if referenceEq(e1, e1_1) and referenceEq(e2, e2_1) then inExp else DAE.RELATION(e1_1, op, e2_1, index_, isExpisASUB);
4998
2/2
✓ Branch 0 taken 576565 times.
✓ Branch 1 taken 960503 times.
1537068 (e, ext_arg) := inFunc(e, ext_arg);
4999 then (e, ext_arg);
5000
5001 // if expressions
5002 case DAE.IFEXP(expCond=e1, expThen=e2, expElse=e3) algorithm
5003 808107 (e1_1, ext_arg) := traverseExpBottomUp(e1, inFunc, inExtArg);
5004 808107 (e2_1, ext_arg) := traverseExpBottomUp(e2, inFunc, ext_arg);
5005 808107 (e3_1, ext_arg) := traverseExpBottomUp(e3, inFunc, ext_arg);
5006
4/4
✓ Branch 0 taken 765274 times.
✓ Branch 1 taken 42833 times.
✓ Branch 2 taken 11977 times.
✓ Branch 3 taken 753297 times.
808107 e := if referenceEq(e1, e1_1) and referenceEq(e2, e2_1) and referenceEq(e3, e3_1) then inExp else DAE.IFEXP(e1_1, e2_1, e3_1);
5007
2/2
✓ Branch 0 taken 328437 times.
✓ Branch 1 taken 479670 times.
808107 (e, ext_arg) := inFunc(e, ext_arg);
5008 then (e, ext_arg);
5009
5010 case DAE.CALL(path=fn, expLst=expl, attr=attr) algorithm
5011 6036062 (expl_1, ext_arg) := traverseExpList(expl, inFunc, inExtArg);
5012
2/2
✓ Branch 0 taken 180124 times.
✓ Branch 1 taken 5855938 times.
6036062 e := if referenceEq(expl, expl_1) then inExp else DAE.CALL(fn, expl_1, attr);
5013
2/2
✓ Branch 0 taken 1994133 times.
✓ Branch 1 taken 4041929 times.
6036062 (e, ext_arg) := inFunc(e, ext_arg);
5014 then (e, ext_arg);
5015
5016 case DAE.RECORD(path=fn, exps=expl, comp=fieldNames, ty=tp) algorithm
5017 437412 (expl_1, ext_arg) := traverseExpList(expl, inFunc, inExtArg);
5018
2/2
✓ Branch 0 taken 12866 times.
✓ Branch 1 taken 424546 times.
437412 e := if referenceEq(expl, expl_1) then inExp else DAE.RECORD(fn, expl_1, fieldNames, tp);
5019
2/2
✓ Branch 0 taken 164298 times.
✓ Branch 1 taken 273114 times.
437412 (e, ext_arg) := inFunc(e, ext_arg);
5020 then (e, ext_arg);
5021
5022 case DAE.PARTEVALFUNCTION(fn, expl, tp, t) algorithm
5023 9054 (expl_1, ext_arg) := traverseExpList(expl, inFunc, inExtArg);
5024
2/2
✓ Branch 0 taken 463 times.
✓ Branch 1 taken 8591 times.
9054 e := if referenceEq(expl, expl_1) then inExp else DAE.PARTEVALFUNCTION(fn, expl_1, tp, t);
5025
2/2
✓ Branch 0 taken 4622 times.
✓ Branch 1 taken 4432 times.
9054 (e, ext_arg) := inFunc(e, ext_arg);
5026 then (e, ext_arg);
5027
5028 case DAE.ARRAY(ty=tp, scalar=scalar, array=expl) algorithm
5029 8038838 (expl_1, ext_arg) := traverseExpList(expl, inFunc, inExtArg);
5030
4/4
✓ Branch 0 taken 97680 times.
✓ Branch 1 taken 7941158 times.
✓ Branch 2 taken 4771 times.
✓ Branch 3 taken 92909 times.
8043609 e := if referenceEq(expl, expl_1) then inExp else DAE.ARRAY(tp, scalar, expl_1);
5031
2/2
✓ Branch 0 taken 694434 times.
✓ Branch 1 taken 7344404 times.
8038838 (e, ext_arg) := inFunc(e, ext_arg);
5032 then (e, ext_arg);
5033
5034 case DAE.MATRIX(ty=tp, integer=dim, matrix=lstexpl) algorithm
5035 394783 (lstexpl_1, ext_arg) := traverseExpMatrix(lstexpl, inFunc, inExtArg);
5036
2/2
✓ Branch 0 taken 2618 times.
✓ Branch 1 taken 392165 times.
394783 e := if referenceEq(lstexpl, lstexpl_1) then inExp else DAE.MATRIX(tp, dim, lstexpl_1);
5037
2/2
✓ Branch 0 taken 54966 times.
✓ Branch 1 taken 339817 times.
394783 (e, ext_arg) := inFunc(e, ext_arg);
5038 then (e, ext_arg);
5039
5040 case DAE.RANGE(ty=tp, start=e1, step=NONE(), stop=e2) algorithm
5041 15117 (e1_1, ext_arg) := traverseExpBottomUp(e1, inFunc, inExtArg);
5042 15117 (e2_1, ext_arg) := traverseExpBottomUp(e2, inFunc, ext_arg);
5043
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 15055 times.
15117 e := if referenceEq(e1, e1_1) and referenceEq(e2, e2_1) then inExp else DAE.RANGE(tp, e1_1, NONE(), e2_1);
5044
2/2
✓ Branch 0 taken 6974 times.
✓ Branch 1 taken 8143 times.
15117 (e, ext_arg) := inFunc(e, ext_arg);
5045 then (e, ext_arg);
5046
5047 case DAE.RANGE(ty=tp, start=e1, step=SOME(e2), stop=e3) algorithm
5048 224 (e1_1, ext_arg) := traverseExpBottomUp(e1, inFunc, inExtArg);
5049 224 (e2_1, ext_arg) := traverseExpBottomUp(e2, inFunc, ext_arg);
5050 224 (e3_1, ext_arg) := traverseExpBottomUp(e3, inFunc, ext_arg);
5051
3/4
✓ Branch 0 taken 222 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 222 times.
226 e := if referenceEq(e1, e1_1) and referenceEq(e2, e2_1) and referenceEq(e3, e3_1) then inExp else DAE.RANGE(tp, e1_1, SOME(e2_1), e3_1);
5052
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 166 times.
224 (e, ext_arg) := inFunc(e, ext_arg);
5053 then (e, ext_arg);
5054
5055 case DAE.TUPLE(PR=expl) algorithm
5056 38549 (expl_1, ext_arg) := traverseExpList(expl, inFunc, inExtArg);
5057
2/2
✓ Branch 0 taken 1873 times.
✓ Branch 1 taken 36676 times.
38549 e := if referenceEq(expl, expl_1) then inExp else DAE.TUPLE(expl_1);
5058
2/2
✓ Branch 0 taken 15232 times.
✓ Branch 1 taken 23317 times.
38549 (e, ext_arg) := inFunc(e, ext_arg);
5059 then (e, ext_arg);
5060
5061 case DAE.CAST(ty=tp, exp=e1) algorithm
5062 757299 (e1_1, ext_arg) := traverseExpBottomUp(e1, inFunc, inExtArg);
5063
2/2
✓ Branch 0 taken 11945 times.
✓ Branch 1 taken 745354 times.
757299 e := if referenceEq(e1, e1_1) then inExp else DAE.CAST(tp, e1_1);
5064
2/2
✓ Branch 0 taken 77104 times.
✓ Branch 1 taken 680195 times.
757299 (e, ext_arg) := inFunc(e, ext_arg);
5065 then (e, ext_arg);
5066
5067 case DAE.ASUB(exp=e1, sub=subs) algorithm
5068
4/4
✓ Branch 0 taken 1043549 times.
✓ Branch 1 taken 1009951 times.
✓ Branch 2 taken 1043549 times.
✓ Branch 3 taken 1009951 times.
2053500 expl := list(Expression.getSubscriptExp(sub) for sub in subs);
5069 1009951 (e1_1, ext_arg) := traverseExpBottomUp(e1, inFunc, inExtArg);
5070 1009951 (expl_1, ext_arg) := traverseExpList(expl, inFunc, ext_arg);
5071
2/2
✓ Branch 0 taken 47900 times.
✓ Branch 1 taken 962051 times.
1009951 e := if referenceEq(e1, e1_1) and referenceEq(expl, expl_1) then inExp else makeASUB(e1_1, expl_1);
5072
2/2
✓ Branch 0 taken 69742 times.
✓ Branch 1 taken 940209 times.
1009951 (e, ext_arg) := inFunc(e, ext_arg);
5073 then (e, ext_arg);
5074
5075 case DAE.TSUB(e1, i, tp) algorithm
5076 3328 (e1_1, ext_arg) := traverseExpBottomUp(e1, inFunc, inExtArg);
5077
2/2
✓ Branch 0 taken 133 times.
✓ Branch 1 taken 3195 times.
3328 e := if referenceEq(e1, e1_1) then inExp else DAE.TSUB(e1_1, i, tp);
5078
2/2
✓ Branch 0 taken 1117 times.
✓ Branch 1 taken 2211 times.
3328 (e, ext_arg) := inFunc(e, ext_arg);
5079 then (e, ext_arg);
5080
5081 case e1 as DAE.RSUB()
5082 algorithm
5083 367964 (e1_1, ext_arg) := traverseExpBottomUp(e1.exp, inFunc, inExtArg);
5084
2/2
✓ Branch 0 taken 5121 times.
✓ Branch 1 taken 362843 times.
367964 if not referenceEq(e1.exp, e1_1) then
5085 5121 e1.exp := e1_1;
5086 end if;
5087
2/2
✓ Branch 0 taken 145911 times.
✓ Branch 1 taken 222053 times.
367964 (e1, ext_arg) := inFunc(e1, ext_arg);
5088 then (e1, ext_arg);
5089
5090 case DAE.SIZE(exp=e1, sz=NONE()) algorithm
5091 12 (e1_1, ext_arg) := traverseExpBottomUp(e1, inFunc, inExtArg);
5092
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 e := if referenceEq(e1, e1_1) then inExp else DAE.SIZE(e1_1, NONE());
5093
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
12 (e, ext_arg) := inFunc(e, ext_arg);
5094 then (e, ext_arg);
5095
5096 case DAE.SIZE(exp=e1, sz=SOME(e2)) algorithm
5097 20909 (e1_1, ext_arg) := traverseExpBottomUp(e1, inFunc, inExtArg);
5098 20909 (e2_1, ext_arg) := traverseExpBottomUp(e2, inFunc, ext_arg);
5099
2/2
✓ Branch 0 taken 789 times.
✓ Branch 1 taken 20120 times.
21698 e := if referenceEq(e1, e1_1) and referenceEq(e2, e2_1) then inExp else DAE.SIZE(e1_1, SOME(e2_1));
5100
2/2
✓ Branch 0 taken 7694 times.
✓ Branch 1 taken 13215 times.
20909 (e, ext_arg) := inFunc(e, ext_arg);
5101 then (e, ext_arg);
5102
5103 case DAE.REDUCTION(reductionInfo=reductionInfo, expr=e1, iterators=riters) algorithm
5104 3688 (e1_1, ext_arg) := traverseExpBottomUp(e1, inFunc, inExtArg);
5105 3688 (riters_1, ext_arg) := traverseReductionIterators(riters, inFunc, ext_arg);
5106
2/2
✓ Branch 0 taken 213 times.
✓ Branch 1 taken 3475 times.
3688 e := if referenceEq(e1, e1_1) and referenceEq(riters, riters_1) then inExp else DAE.REDUCTION(reductionInfo, e1_1, riters_1);
5107
2/2
✓ Branch 0 taken 519 times.
✓ Branch 1 taken 3169 times.
3688 (e, ext_arg) := inFunc(e, ext_arg);
5108 then (e, ext_arg);
5109
5110 // MetaModelica list
5111 case DAE.CONS(e1, e2) algorithm
5112 4708 (e1_1, ext_arg) := traverseExpBottomUp(e1, inFunc, inExtArg);
5113 4708 (e2_1, ext_arg) := traverseExpBottomUp(e2, inFunc, ext_arg);
5114
2/2
✓ Branch 0 taken 1144 times.
✓ Branch 1 taken 3564 times.
4708 e := if referenceEq(e1, e1_1) and referenceEq(e2, e2_1) then inExp else DAE.CONS(e1_1, e2_1);
5115
2/2
✓ Branch 0 taken 351 times.
✓ Branch 1 taken 4357 times.
4708 (e, ext_arg) := inFunc(e, ext_arg);
5116 then (e, ext_arg);
5117
5118 case DAE.LIST(expl) algorithm
5119 50539 (expl_1, ext_arg) := traverseExpList(expl, inFunc, inExtArg);
5120
2/2
✓ Branch 0 taken 326 times.
✓ Branch 1 taken 50213 times.
50539 e := if referenceEq(expl, expl_1) then inExp else DAE.LIST(expl_1);
5121
2/2
✓ Branch 0 taken 4936 times.
✓ Branch 1 taken 45603 times.
50539 (e, ext_arg) := inFunc(e, ext_arg);
5122 then (e, ext_arg);
5123
5124 case DAE.META_TUPLE(expl) algorithm
5125 15142 (expl_1, ext_arg) := traverseExpList(expl, inFunc, inExtArg);
5126
2/2
✓ Branch 0 taken 1085 times.
✓ Branch 1 taken 14057 times.
15142 e := if referenceEq(expl, expl_1) then inExp else DAE.META_TUPLE(expl_1);
5127
2/2
✓ Branch 0 taken 1777 times.
✓ Branch 1 taken 13365 times.
15142 (e, ext_arg) := inFunc(e, ext_arg);
5128 then (e, ext_arg);
5129
5130 case DAE.META_OPTION(NONE()) algorithm
5131
2/2
✓ Branch 0 taken 2213 times.
✓ Branch 1 taken 38036 times.
40249 (e, ext_arg) := inFunc(inExp, inExtArg);
5132 then (e, ext_arg);
5133
5134 case DAE.META_OPTION(SOME(e1)) algorithm
5135 15672 (e1_1, ext_arg) := traverseExpBottomUp(e1, inFunc, inExtArg);
5136
2/2
✓ Branch 0 taken 372 times.
✓ Branch 1 taken 15300 times.
16044 e := if referenceEq(e1, e1_1) then inExp else DAE.META_OPTION(SOME(e1_1));
5137
2/2
✓ Branch 0 taken 675 times.
✓ Branch 1 taken 14997 times.
15672 (e, ext_arg) := inFunc(e, ext_arg);
5138 then (e, ext_arg);
5139
5140 case DAE.BOX(e1) algorithm
5141 147956 (e1_1, ext_arg) := traverseExpBottomUp(e1, inFunc, inExtArg);
5142
2/2
✓ Branch 0 taken 1162 times.
✓ Branch 1 taken 146794 times.
147956 e := if referenceEq(e1, e1_1) then inExp else DAE.BOX(e1_1);
5143
2/2
✓ Branch 0 taken 21780 times.
✓ Branch 1 taken 126176 times.
147956 (e, ext_arg) := inFunc(e, ext_arg);
5144 then (e, ext_arg);
5145
5146 case DAE.UNBOX(e1, tp) algorithm
5147 5726 (e1_1, ext_arg) := traverseExpBottomUp(e1, inFunc, inExtArg);
5148
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 5639 times.
5726 e := if referenceEq(e1, e1_1) then inExp else DAE.UNBOX(e1_1, tp);
5149
2/2
✓ Branch 0 taken 1090 times.
✓ Branch 1 taken 4636 times.
5726 (e, ext_arg) := inFunc(e, ext_arg);
5150 then (e, ext_arg);
5151
5152 case DAE.METARECORDCALL(fn, expl, fieldNames, i, typeVars) algorithm
5153 191067 (expl_1, ext_arg) := traverseExpList(expl, inFunc, inExtArg);
5154
2/2
✓ Branch 0 taken 4424 times.
✓ Branch 1 taken 186643 times.
191067 e := if referenceEq(expl, expl_1) then inExp else DAE.METARECORDCALL(fn, expl_1, fieldNames, i, typeVars);
5155
2/2
✓ Branch 0 taken 13822 times.
✓ Branch 1 taken 177245 times.
191067 (e, ext_arg) := inFunc(e, ext_arg);
5156 then (e, ext_arg);
5157 // ---------------------
5158
5159 case DAE.MATCHEXPRESSION(matchTy, expl, aliases, localDecls, cases, tp) algorithm
5160 // Don't traverse the local declarations; we don't store bindings there (yet)
5161 9880 (expl_1, ext_arg) := traverseExpList(expl, inFunc, inExtArg);
5162 9880 (cases_1, ext_arg) := traverseMatchCases(cases, inFunc, ext_arg);
5163
2/2
✓ Branch 0 taken 3293 times.
✓ Branch 1 taken 6587 times.
9880 e := if referenceEq(expl, expl_1) and referenceEq(cases, cases_1) then inExp else DAE.MATCHEXPRESSION(matchTy, expl_1, aliases, localDecls, cases_1, tp);
5164
2/2
✓ Branch 0 taken 1174 times.
✓ Branch 1 taken 8706 times.
9880 (e, ext_arg) := inFunc(e, ext_arg);
5165 then (e, ext_arg);
5166
5167 case DAE.SHARED_LITERAL() algorithm
5168
2/2
✓ Branch 0 taken 2649 times.
✓ Branch 1 taken 5498 times.
8147 (e, ext_arg) := inFunc(inExp, inExtArg);
5169 then (e, ext_arg);
5170
5171 case DAE.PATTERN() algorithm
5172
2/2
✓ Branch 0 taken 660 times.
✓ Branch 1 taken 5660 times.
6320 (e, ext_arg) := inFunc(inExp, inExtArg);
5173 then (e, ext_arg);
5174
5175 // Why don't we call inFunc() for these expressions?
5176 20806 case DAE.CODE() then (inExp, inExtArg);
5177
5178 else algorithm
5179 ✗ str := ExpressionBasics.printExpStr(inExp);
5180 ✗ str := "Expression.traverseExpBottomUp or one of the user-defined functions using it is not implemented correctly: " + str;
5181 ✗ Error.addInternalError(str, sourceInfo());
5182 ✗ then fail();
5183 end match;
5184 end traverseExpBottomUp;
5185
5186 public function traverseExpDummy "Like traverseExpBottomUp but passes a default 0 argument"
5187 replaceable type Type_a subtypeof Any;
5188 input DAE.Exp inExp;
5189 input FuncExpType func;
5190 output DAE.Exp outExp;
5191 partial function FuncExpType
5192 input DAE.Exp inExp;
5193 output DAE.Exp outExp;
5194 end FuncExpType;
5195 algorithm
5196 197992 (outExp,_) := traverseExpBottomUp(inExp,traverseExpDummyHelper,func);
5197 end traverseExpDummy;
5198
5199 public function traverseExpDummyHelper "Like traverseExpBottomUp but does not use an extra argument"
5200 replaceable type Type_a subtypeof Any;
5201 input DAE.Exp inExp;
5202 input FuncExpType func;
5203 output DAE.Exp outExp;
5204 output FuncExpType outFunc;
5205 partial function FuncExpType
5206 input DAE.Exp inExp;
5207 output DAE.Exp outExp;
5208 end FuncExpType;
5209 algorithm
5210
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6558244 times.
6558244 outExp := func(inExp);
5211 outFunc := func;
5212 end traverseExpDummyHelper;
5213
5214 public function traverseSubexpressionsHelper
5215 "This function is used as input to a traverse function that does not traverse all subexpressions.
5216 The extra argument is a tuple of the actul function to call on each subexpression and the extra argument."
5217 replaceable type Type_a subtypeof Any;
5218 input DAE.Exp inExp;
5219 input tuple<FuncExpType,Type_a> itpl;
5220 output DAE.Exp outExp;
5221 output tuple<FuncExpType,Type_a> otpl;
5222 partial function FuncExpType
5223 input DAE.Exp inExp;
5224 input Type_a inTypeA;
5225 output DAE.Exp outExp;
5226 output Type_a outA;
5227 end FuncExpType;
5228 protected
5229 FuncExpType rel;
5230 Type_a ext_arg, ext_arg2;
5231 algorithm
5232 8023292 (rel,ext_arg) := itpl;
5233 8023292 (outExp,ext_arg2) := traverseExpBottomUp(inExp,rel,ext_arg);
5234
2/2
✓ Branch 0 taken 36147 times.
✓ Branch 1 taken 7987145 times.
8023292 otpl := if referenceEq(ext_arg, ext_arg2) then itpl else (rel,ext_arg2);
5235 end traverseSubexpressionsHelper;
5236
5237 public function traverseSubexpressions
5238 "This function is used as input to a traverse function that does not traverse all subexpressions.
5239 The extra argument is a tuple of the actul function to call on each subexpression and the extra argument."
5240 replaceable type Type_a subtypeof Any;
5241 input output DAE.Exp e;
5242 input output Type_a arg;
5243 input FuncExpType func;
5244 partial function FuncExpType
5245 input DAE.Exp inExp;
5246 input Type_a inTypeA;
5247 output DAE.Exp outExp;
5248 output Type_a outA;
5249 end FuncExpType;
5250 algorithm
5251 49328 (e, arg) := traverseExpBottomUp(e, func, arg);
5252 end traverseSubexpressions;
5253
5254 public function traverseSubexpressionsDummyHelper
5255 "This function is used as input to a traverse function that does not traverse all subexpressions.
5256 The extra argument is a tuple of the actul function to call on each subexpression and the extra argument.
5257 "
5258 replaceable type Type_a subtypeof Any;
5259 input DAE.Exp inExp;
5260 input FuncExpType inFunc;
5261 output DAE.Exp outExp;
5262 output FuncExpType outFunc;
5263 partial function FuncExpType
5264 input DAE.Exp inExp;
5265 output DAE.Exp outExp;
5266 end FuncExpType;
5267 algorithm
5268 118183 (outExp,outFunc) := traverseExpBottomUp(inExp,traverseExpDummyHelper,inFunc);
5269 end traverseSubexpressionsDummyHelper;
5270
5271 public function traverseSubexpressionsTopDownHelper
5272 "This function is used as input to a traverse function that does not traverse all subexpressions.
5273 The extra argument is a tuple of the actual function to call on each subexpression and the extra argument."
5274 replaceable type Type_a subtypeof Any;
5275 input DAE.Exp inExp;
5276 input tuple<FuncExpType2,Type_a> itpl;
5277 output DAE.Exp outExp;
5278 output tuple<FuncExpType2,Type_a> otpl;
5279 partial function FuncExpType2
5280 input DAE.Exp inExp;
5281 input Type_a inTypeA;
5282 output DAE.Exp outExp;
5283 output Boolean cont;
5284 output Type_a outA;
5285 end FuncExpType2;
5286 protected
5287 FuncExpType2 rel;
5288 Type_a ext_arg, ext_arg2;
5289 algorithm
5290 797502 (rel,ext_arg) := itpl;
5291 797502 (outExp,ext_arg2) := traverseExpTopDown(inExp,rel,ext_arg);
5292
2/2
✓ Branch 0 taken 3864 times.
✓ Branch 1 taken 793638 times.
797502 otpl := if referenceEq(ext_arg, ext_arg2) then itpl else (rel,ext_arg2);
5293 end traverseSubexpressionsTopDownHelper;
5294
5295 protected function traverseExpMatrix
5296 "author: PA
5297 Helper function to traverseExpBottomUp, traverses matrix expressions."
5298 replaceable type Type_a subtypeof Any;
5299 input list<list<DAE.Exp>> inMatrix;
5300 input FuncExpType func;
5301 input Type_a inTypeA;
5302 output list<list<DAE.Exp>> outMatrix = {};
5303 output Type_a outTypeA = inTypeA;
5304 partial function FuncExpType
5305 input DAE.Exp inExp;
5306 input Type_a inTypeA;
5307 output DAE.Exp outExp;
5308 output Type_a outA;
5309 end FuncExpType;
5310 protected
5311 list<DAE.Exp> row_1;
5312 Boolean same = true;
5313 algorithm
5314
2/2
✓ Branch 0 taken 1183036 times.
✓ Branch 1 taken 394783 times.
1577819 for row in inMatrix loop
5315 1183036 (row_1,outTypeA) := traverseExpList(row, func, outTypeA);
5316
2/2
✓ Branch 0 taken 1176288 times.
✓ Branch 1 taken 6748 times.
1183036 same := if referenceEq(row,row_1) then same else false;
5317 outMatrix := row_1::outMatrix;
5318 end for;
5319
2/2
✓ Branch 0 taken 2618 times.
✓ Branch 1 taken 392165 times.
394783 if same then
5320 outMatrix := inMatrix;
5321 else
5322 2618 outMatrix := MetaModelica.Dangerous.listReverseInPlace(outMatrix);
5323 end if;
5324 end traverseExpMatrix;
5325
5326 public function traverseExpList<ArgT> "Calls traverseExpBottomUp for each element of list."
5327 input list<DAE.Exp> inExpl;
5328 input FuncExpType rel;
5329 input ArgT iext_arg;
5330 output list<DAE.Exp> expl;
5331 output ArgT ext_arg = iext_arg;
5332 partial function FuncExpType
5333 input DAE.Exp inExp;
5334 input ArgT inTypeA;
5335 output DAE.Exp outExp;
5336 output ArgT outA;
5337 end FuncExpType;
5338 protected
5339 DAE.Exp e1;
5340 DoubleEnded.MutableList<DAE.Exp> delst;
5341 list<DAE.Exp> rest = inExpl;
5342 Integer nEq=0;
5343 algorithm
5344 // Preserve reference equality without any allocation if nothing changed.
5345 expl := inExpl;
5346
2/2
✓ Branch 0 taken 57385188 times.
✓ Branch 1 taken 16724489 times.
74109677 while not listEmpty(rest) loop
5347 57385188 (e1, ext_arg) := traverseExpBottomUp(listHead(rest), rel, ext_arg);
5348
2/2
✓ Branch 1 taken 307299 times.
✓ Branch 2 taken 57077889 times.
57385188 if not referenceEq(listHead(rest), e1) then
5349 // First change: switch to building a new list with a DoubleEnded list.
5350 307299 delst := DoubleEnded.empty(e1);
5351
1/2
✓ Branch 0 taken 399575 times.
✗ Branch 1 not taken.
399575 for elt in inExpl loop
5352
2/2
✓ Branch 0 taken 92276 times.
✓ Branch 1 taken 307299 times.
399575 if nEq < 1 then
5353 break;
5354 end if;
5355 92276 DoubleEnded.push_back(delst, elt);
5356 92276 nEq := nEq-1;
5357 end for;
5358 307299 DoubleEnded.push_back(delst, e1);
5359
2/2
✓ Branch 1 taken 348926 times.
✓ Branch 2 taken 307299 times.
656225 for e in listRest(rest) loop
5360 348926 (e1, ext_arg) := traverseExpBottomUp(e, rel, ext_arg);
5361 348926 DoubleEnded.push_back(delst, e1);
5362 end for;
5363 307299 expl := DoubleEnded.toListAndClear(delst);
5364 307299 return;
5365 end if;
5366 57077889 nEq := nEq + 1;
5367 57077889 rest := listRest(rest);
5368 end while;
5369 end traverseExpList;
5370
5371 public function traverseExpTopDown
5372 "Traverses all subexpressions of an expression.
5373 Takes a function and an extra argument passed through the traversal.
5374 The function can potentially change the expression. In such cases,
5375 the changes are made top-down, i.e. a subexpression is traversed
5376 and changed after the complete expression is traversed."
5377 replaceable type Type_a subtypeof Any;
5378 input DAE.Exp inExp;
5379 input FuncExpType func;
5380 input Type_a ext_arg;
5381 output DAE.Exp outExp;
5382 output Type_a outArg;
5383 partial function FuncExpType
5384 input DAE.Exp exp;
5385 input Type_a arg;
5386 output DAE.Exp outExp;
5387 output Boolean cont;
5388 output Type_a outArg;
5389 end FuncExpType;
5390 protected
5391 Boolean cont;
5392 algorithm
5393
2/2
✓ Branch 0 taken 39498619 times.
✓ Branch 1 taken 42931892 times.
82430511 (outExp,cont,outArg) := func(inExp,ext_arg);
5394 82430511 (outExp,outArg) := traverseExpTopDown1(cont,outExp,func,outArg);
5395 end traverseExpTopDown;
5396
5397 protected function traverseExpClk
5398 replaceable type Type_a subtypeof Any;
5399 input DAE.ClockKind inClk;
5400 input FuncExpType func;
5401 input Type_a inArg;
5402 output DAE.ClockKind outClk;
5403 output Type_a outArg;
5404 partial function FuncExpType
5405 input DAE.Exp exp;
5406 input Type_a arg;
5407 output DAE.Exp outExp;
5408 output Type_a outArg;
5409 end FuncExpType;
5410 algorithm
5411 (outClk, outArg) := match inClk
5412 local
5413 DAE.Exp e, e1, e2, ea, eb;
5414 Type_a arg;
5415 DAE.ClockKind clk;
5416 case DAE.RATIONAL_CLOCK(e1, e2)
5417 algorithm
5418 233 (ea, arg) := traverseExpBottomUp(e1, func, inArg);
5419 233 (eb, arg) := traverseExpBottomUp(e2, func, inArg);
5420
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 233 times.
233 clk := if referenceEq(ea, e1) and referenceEq(eb, e2)
5421 then inClk else DAE.RATIONAL_CLOCK(ea, eb);
5422 233 then (clk, arg);
5423 case DAE.REAL_CLOCK(e)
5424 algorithm
5425 290 (e1, arg) := traverseExpBottomUp(e, func, inArg);
5426
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 290 times.
290 clk := if referenceEq(e1, e) then inClk else DAE.REAL_CLOCK(e1);
5427 290 then (clk, arg);
5428 case DAE.EVENT_CLOCK(e1, e2)
5429 algorithm
5430 127 (ea, arg) := traverseExpBottomUp(e1, func, inArg);
5431 127 (eb, arg) := traverseExpBottomUp(e2, func, inArg);
5432
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 123 times.
127 clk := if referenceEq(ea, e1) and referenceEq(eb, e2)
5433 then inClk else DAE.EVENT_CLOCK(ea, eb);
5434 127 then (clk, arg);
5435 case DAE.SOLVER_CLOCK(e1, e2)
5436 algorithm
5437 31 (ea, arg) := traverseExpBottomUp(e1, func, inArg);
5438 31 (eb, arg) := traverseExpBottomUp(e2, func, inArg);
5439
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 29 times.
31 clk := if referenceEq(ea, e1) and referenceEq(eb, e2)
5440 then inClk else DAE.SOLVER_CLOCK(ea, eb);
5441 31 then (clk, arg);
5442 else (inClk, inArg);
5443 end match;
5444 end traverseExpClk;
5445
5446 protected function traverseExpTopDownClockHelper
5447 replaceable type Type_a subtypeof Any;
5448 input DAE.ClockKind inClk;
5449 input FuncExpType func;
5450 input Type_a inArg;
5451 output DAE.ClockKind outClk;
5452 output Type_a outArg;
5453 partial function FuncExpType
5454 input DAE.Exp exp;
5455 input Type_a arg;
5456 output DAE.Exp outExp;
5457 output Boolean cont;
5458 output Type_a outArg;
5459 end FuncExpType;
5460 algorithm
5461 (outClk, outArg) := match inClk
5462 local
5463 DAE.Exp e, e1, e2, ea, eb;
5464 Type_a arg;
5465 DAE.ClockKind clk;
5466
5467 case DAE.RATIONAL_CLOCK(e1, e2)
5468 algorithm
5469 110 (ea, arg) := traverseExpTopDown(e1, func, inArg);
5470 110 (eb, arg) := traverseExpTopDown(e2, func, inArg);
5471
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 110 times.
110 clk := if referenceEq(ea, e1) and referenceEq(eb, e2)
5472 then inClk else DAE.RATIONAL_CLOCK(ea, eb);
5473 110 then (clk, arg);
5474 case DAE.REAL_CLOCK(e)
5475 algorithm
5476 96 (e1, arg) := traverseExpTopDown(e, func, inArg);
5477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
96 clk := if referenceEq(e1, e) then inClk else DAE.REAL_CLOCK(e1);
5478 96 then (clk, arg);
5479 case DAE.EVENT_CLOCK(e1, e2)
5480 algorithm
5481 51 (ea, arg) := traverseExpTopDown(e1, func, inArg);
5482 51 (eb, arg) := traverseExpTopDown(e2, func, inArg);
5483
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 43 times.
51 clk := if referenceEq(ea, e1) and referenceEq(eb, e2)
5484 then inClk else DAE.EVENT_CLOCK(ea, eb);
5485 51 then (clk, arg);
5486 case DAE.SOLVER_CLOCK(e1, e2)
5487 algorithm
5488 8 (ea, arg) := traverseExpTopDown(e1, func, inArg);
5489 8 (eb, arg) := traverseExpTopDown(e2, func, inArg);
5490
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 clk := if referenceEq(ea, e1) and referenceEq(eb, e2)
5491 then inClk else DAE.SOLVER_CLOCK(ea, eb);
5492 8 then (clk, arg);
5493 else (inClk, inArg);
5494 end match;
5495 end traverseExpTopDownClockHelper;
5496
5497 protected function traverseExpTopDown1
5498 "Helper for traverseExpTopDown."
5499 replaceable type Type_a subtypeof Any;
5500 input Boolean cont;
5501 input DAE.Exp inExp;
5502 input FuncExpType func;
5503 input Type_a inArg;
5504 output DAE.Exp outExp;
5505 output Type_a outArg;
5506 partial function FuncExpType
5507 input DAE.Exp exp;
5508 input Type_a arg;
5509 output DAE.Exp outExp;
5510 output Boolean cont;
5511 output Type_a outArg;
5512 end FuncExpType;
5513 algorithm
5514 (outExp,outArg) := match (cont,inExp,inArg)
5515 local
5516 DAE.Exp e1_1,e,e1,e2_1,e2,e3_1,e3;
5517 Type_a ext_arg_1,ext_arg_2,ext_arg,ext_arg_3;
5518 Operator op;
5519 list<DAE.Exp> expl_1,expl;
5520 Absyn.Path fn;
5521 Boolean scalar;
5522 Type tp,et,t;
5523 Integer i;
5524 String str;
5525 list<String> fieldNames;
5526 list<list<DAE.Exp>> lstexpl_1,lstexpl;
5527 Integer dim;
5528 Integer index_;
5529 Option<tuple<DAE.Exp,Integer,Integer>> isExpisASUB;
5530 Option<DAE.Exp> oe1;
5531 DAE.ReductionInfo reductionInfo;
5532 DAE.ReductionIterators riters;
5533 DAE.CallAttributes attr;
5534 list<DAE.Element> localDecls;
5535 DAE.MatchType matchType;
5536 list<DAE.MatchCase> cases;
5537 ComponentRef cr,cr_1;
5538 list<list<String>> aliases;
5539 DAE.ClockKind clk, clk1;
5540 list<DAE.Type> typeVars;
5541 list<DAE.Subscript> subs;
5542
5543 case (false,_,_) then (inExp,inArg);
5544 case (_,DAE.ICONST(_),ext_arg) then (inExp,ext_arg);
5545 case (_,DAE.RCONST(_),ext_arg) then (inExp,ext_arg);
5546 case (_,DAE.SCONST(_),ext_arg) then (inExp,ext_arg);
5547 case (_,DAE.BCONST(_),ext_arg) then (inExp,ext_arg);
5548 case (_,DAE.CLKCONST(clk),ext_arg)
5549 algorithm
5550 626 (clk1, ext_arg) := traverseExpTopDownClockHelper(clk,func,ext_arg);
5551
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 618 times.
626 e := if referenceEq(clk1,clk) then inExp else DAE.CLKCONST(clk1);
5552 626 then (e, ext_arg);
5553 case (_,DAE.ENUM_LITERAL(),ext_arg) then (inExp,ext_arg);
5554 case (_,DAE.CREF(componentRef = cr),ext_arg)
5555 guard ComponentReferenceBasics.crefHasNoSubscripts(cr)
5556 9245157 then (inExp,ext_arg);
5557 case (_,DAE.CREF(cr,tp),ext_arg)
5558 algorithm
5559 14921790 (cr_1,ext_arg_1) := traverseExpTopDownCrefHelper(cr,func,ext_arg);
5560
2/2
✓ Branch 0 taken 566 times.
✓ Branch 1 taken 14921224 times.
14921790 then (if referenceEq(cr,cr_1) then inExp else DAE.CREF(cr_1,tp),ext_arg_1);
5561 // unary
5562 case (_,DAE.UNARY(operator = op,exp = e1),ext_arg)
5563 algorithm
5564 942173 (e1_1,ext_arg_1) := traverseExpTopDown(e1, func, ext_arg);
5565
2/2
✓ Branch 0 taken 74358 times.
✓ Branch 1 taken 867815 times.
942173 then
5566 (if referenceEq(e1, e1_1) then inExp else DAE.UNARY(op,e1_1),ext_arg_1);
5567
5568 // binary
5569 case (_,DAE.BINARY(exp1 = e1,operator = op,exp2 = e2),ext_arg)
5570 algorithm
5571 16533272 (e1_1,ext_arg_1) := traverseExpTopDown(e1, func, ext_arg);
5572 16533272 (e2_1,ext_arg_2) := traverseExpTopDown(e2, func, ext_arg_1);
5573
2/2
✓ Branch 0 taken 1693730 times.
✓ Branch 1 taken 14839542 times.
16533272 then (if referenceEq(e1, e1_1) and referenceEq(e2, e2_1) then inExp else DAE.BINARY(e1_1,op,e2_1),ext_arg_2);
5574
5575 // logical unary
5576 case (_,DAE.LUNARY(operator = op,exp = e1),ext_arg)
5577 algorithm
5578 44984 (e1_1,ext_arg_1) := traverseExpTopDown(e1, func, ext_arg);
5579
2/2
✓ Branch 0 taken 2129 times.
✓ Branch 1 taken 42855 times.
44984 then (if referenceEq(e1, e1_1) then inExp else DAE.LUNARY(op,e1_1),ext_arg_1);
5580
5581 // logical binary
5582 case (_,DAE.LBINARY(exp1 = e1,operator = op,exp2 = e2),ext_arg)
5583 algorithm
5584 270888 (e1_1,ext_arg_1) := traverseExpTopDown(e1, func, ext_arg);
5585 270888 (e2_1,ext_arg_2) := traverseExpTopDown(e2, func, ext_arg_1);
5586
2/2
✓ Branch 0 taken 170001 times.
✓ Branch 1 taken 100887 times.
270888 then (if referenceEq(e1, e1_1) and referenceEq(e2, e2_1) then inExp else DAE.LBINARY(e1_1,op,e2_1),ext_arg_2);
5587
5588 // relation
5589 case (_,DAE.RELATION(exp1 = e1,operator = op,exp2 = e2, index=index_, optionExpisASUB= isExpisASUB),ext_arg)
5590 algorithm
5591 582410 (e1_1,ext_arg_1) := traverseExpTopDown(e1, func, ext_arg);
5592 582410 (e2_1,ext_arg_2) := traverseExpTopDown(e2, func, ext_arg_1);
5593
2/2
✓ Branch 0 taken 44991 times.
✓ Branch 1 taken 537419 times.
582410 then (if referenceEq(e1, e1_1) and referenceEq(e2, e2_1) then inExp else DAE.RELATION(e1_1,op,e2_1,index_,isExpisASUB),ext_arg_2);
5594
5595 // if expressions
5596 case (_,(DAE.IFEXP(expCond = e1,expThen = e2,expElse = e3)),ext_arg)
5597 algorithm
5598 194096 (e1_1,ext_arg_1) := traverseExpTopDown(e1, func, ext_arg);
5599 194096 (e2_1,ext_arg_2) := traverseExpTopDown(e2, func, ext_arg_1);
5600 194096 (e3_1,ext_arg_3) := traverseExpTopDown(e3, func, ext_arg_2);
5601
4/4
✓ Branch 0 taken 99332 times.
✓ Branch 1 taken 94764 times.
✓ Branch 2 taken 13070 times.
✓ Branch 3 taken 86262 times.
194096 then (if referenceEq(e1, e1_1) and referenceEq(e2, e2_1) and referenceEq(e3, e3_1) then inExp else DAE.IFEXP(e1_1,e2_1,e3_1),ext_arg_3);
5602
5603 // call
5604 case (_,(DAE.CALL(path = fn,expLst = expl,attr = attr)),ext_arg)
5605 algorithm
5606 2020479 (expl_1,ext_arg_1) := traverseExpListTopDown(expl, func, ext_arg);
5607 2020479 then (DAE.CALL(fn,expl_1,attr),ext_arg_1);
5608
5609 case (_,(DAE.RECORD(path = fn,exps = expl,comp = fieldNames,ty = tp)),ext_arg)
5610 algorithm
5611 237392 (expl_1,ext_arg_1) := traverseExpListTopDown(expl, func, ext_arg);
5612 237392 then (DAE.RECORD(fn,expl_1,fieldNames,tp),ext_arg_1);
5613
5614 case (_,(DAE.PARTEVALFUNCTION(fn, expl, tp, t)),ext_arg)
5615 algorithm
5616 5857 (expl_1,ext_arg_1) := traverseExpListTopDown(expl, func, ext_arg);
5617 5857 then (DAE.PARTEVALFUNCTION(fn,expl_1,tp,t),ext_arg_1);
5618
5619 case (_,(DAE.ARRAY(ty = tp,scalar = scalar,array = expl)),ext_arg)
5620 algorithm
5621 486965 (expl_1,ext_arg_1) := traverseExpListTopDown(expl, func, ext_arg);
5622
2/2
✓ Branch 0 taken 12858 times.
✓ Branch 1 taken 474107 times.
499823 then (DAE.ARRAY(tp,scalar,expl_1),ext_arg_1);
5623
5624 case (_,(DAE.MATRIX(ty = tp,integer = dim,matrix = lstexpl)),ext_arg)
5625 algorithm
5626 67927 (lstexpl_1,ext_arg_1) := traverseExpMatrixTopDown(lstexpl, func, ext_arg);
5627 67927 then (DAE.MATRIX(tp,dim,lstexpl_1),ext_arg_1);
5628
5629 case (_,(DAE.RANGE(ty = tp,start = e1,step = NONE(),stop = e2)),ext_arg)
5630 algorithm
5631 13578 (e1_1,ext_arg_1) := traverseExpTopDown(e1, func, ext_arg);
5632 13578 (e2_1,ext_arg_2) := traverseExpTopDown(e2, func, ext_arg_1);
5633
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 13546 times.
13578 then (if referenceEq(e1, e1_1) and referenceEq(e2, e2_1) then inExp else DAE.RANGE(tp,e1_1,NONE(),e2_1),ext_arg_2);
5634
5635 case (_,(DAE.RANGE(ty = tp,start = e1,step = SOME(e2),stop = e3)),ext_arg)
5636 algorithm
5637 66 (e1_1,ext_arg_1) := traverseExpTopDown(e1, func, ext_arg);
5638 66 (e2_1,ext_arg_2) := traverseExpTopDown(e2, func, ext_arg_1);
5639 66 (e3_1,ext_arg_3) := traverseExpTopDown(e3, func, ext_arg_2);
5640
2/4
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 66 times.
66 then (if referenceEq(e1, e1_1) and referenceEq(e2, e2_1) and referenceEq(e3, e3_1) then inExp else DAE.RANGE(tp,e1_1,SOME(e2_1),e3_1),ext_arg_3);
5641
5642 case (_,(DAE.TUPLE(PR = expl)),ext_arg)
5643 algorithm
5644 17154 (expl_1,ext_arg_1) := traverseExpListTopDown(expl, func, ext_arg);
5645 17154 then (DAE.TUPLE(expl_1),ext_arg_1);
5646
5647 case (_,(DAE.CAST(ty = tp,exp = e1)),ext_arg)
5648 algorithm
5649 99352 (e1_1,ext_arg_1) := traverseExpTopDown(e1, func, ext_arg);
5650 99352 then (DAE.CAST(tp,e1_1),ext_arg_1);
5651
5652 case (_,(DAE.ASUB(exp = e1,sub = subs)),ext_arg)
5653 algorithm
5654
4/4
✓ Branch 0 taken 85025 times.
✓ Branch 1 taken 75675 times.
✓ Branch 2 taken 85025 times.
✓ Branch 3 taken 75675 times.
160700 expl_1 := list(Expression.getSubscriptExp(sub) for sub in subs);
5655 75675 (e1_1,ext_arg_1) := traverseExpTopDown(e1, func, ext_arg);
5656 75675 (expl_1,ext_arg_2) := traverseExpListTopDown(expl_1, func, ext_arg_1);
5657 75675 then (makeASUB(e1_1,expl_1),ext_arg_2);
5658
5659 case (_,(DAE.TSUB(e1,i,tp)),ext_arg)
5660 algorithm
5661 873 (e1_1,ext_arg_1) := traverseExpTopDown(e1, func, ext_arg);
5662 873 then (DAE.TSUB(e1_1,i,tp),ext_arg_1);
5663
5664 case (_,e1 as DAE.RSUB(),ext_arg)
5665 algorithm
5666 167653 (e1_1,ext_arg_1) := traverseExpTopDown(e1.exp, func, ext_arg);
5667
2/2
✓ Branch 0 taken 135711 times.
✓ Branch 1 taken 31942 times.
167653 if not referenceEq(e1.exp, e1_1) then
5668 135711 e1.exp := e1_1;
5669 end if;
5670 167653 then (e1,ext_arg_1);
5671
5672 case (_,(DAE.SIZE(exp = e1,sz = NONE())),ext_arg)
5673 algorithm
5674 3 (e1_1,ext_arg_1) := traverseExpTopDown(e1, func, ext_arg);
5675 3 then (DAE.SIZE(e1_1,NONE()),ext_arg_1);
5676
5677 case (_,(DAE.SIZE(exp = e1,sz = SOME(e2))),ext_arg)
5678 algorithm
5679 1528 (e1_1,ext_arg_1) := traverseExpTopDown(e1, func, ext_arg);
5680 1528 (e2_1,ext_arg_2) := traverseExpTopDown(e2, func, ext_arg_1);
5681
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1528 times.
1528 then (if referenceEq(e1, e1_1) and referenceEq(e2, e2_1) then inExp else DAE.SIZE(e1_1,SOME(e2_1)),ext_arg_2);
5682
5683 case (_,DAE.CODE(),ext_arg) then (inExp,ext_arg);
5684
5685 case (_,DAE.REDUCTION(reductionInfo = reductionInfo, expr = e1, iterators = riters),ext_arg)
5686 algorithm
5687 243 (e1,ext_arg) := traverseExpTopDown(e1, func, ext_arg);
5688 243 (riters,ext_arg) := traverseReductionIteratorsTopDown(riters, func, ext_arg);
5689 243 then (DAE.REDUCTION(reductionInfo,e1,riters),ext_arg);
5690
5691 case (_, DAE.EMPTY(), _)
5692 then (inExp, inArg);
5693
5694 // MetaModelica list
5695 case (_,DAE.CONS(e1,e2),ext_arg)
5696 algorithm
5697 598 (e1_1,ext_arg_1) := traverseExpTopDown(e1, func, ext_arg);
5698 598 (e2_1,ext_arg_2) := traverseExpTopDown(e2, func, ext_arg_1);
5699
2/2
✓ Branch 0 taken 209 times.
✓ Branch 1 taken 389 times.
598 then (if referenceEq(e1, e1_1) and referenceEq(e2, e2_1) then inExp else DAE.CONS(e1_1,e2_1),ext_arg_2);
5700
5701 case (_,DAE.LIST(expl),ext_arg)
5702 algorithm
5703 4034 (expl_1,ext_arg_1) := traverseExpListTopDown(expl, func, ext_arg);
5704 4034 then (DAE.LIST(expl_1),ext_arg_1);
5705
5706 case (_,DAE.META_TUPLE(expl),ext_arg)
5707 algorithm
5708 1274 (expl_1,ext_arg_1) := traverseExpListTopDown(expl, func, ext_arg);
5709 1274 then (DAE.META_TUPLE(expl_1),ext_arg_1);
5710
5711 case (_,DAE.META_OPTION(oe1),ext_arg)
5712 algorithm
5713 12418 (oe1,ext_arg) := traverseExpOptTopDown(oe1, func, ext_arg);
5714 12418 then (DAE.META_OPTION(oe1),ext_arg);
5715
5716 case (_,DAE.MATCHEXPRESSION(matchType,expl,aliases,localDecls,cases,et),ext_arg)
5717 algorithm
5718 1171 (expl,ext_arg) := traverseExpListTopDown(expl,func,ext_arg);
5719 1171 (cases, ext_arg) := traverseMatchCasesTopDown(cases, func, ext_arg);
5720 1171 then (DAE.MATCHEXPRESSION(matchType,expl,aliases,localDecls,cases,et),ext_arg);
5721
5722 case (_,DAE.METARECORDCALL(fn,expl,fieldNames,i,typeVars),ext_arg)
5723 algorithm
5724 9619 (expl_1,ext_arg_1) := traverseExpListTopDown(expl, func, ext_arg);
5725 9619 then (DAE.METARECORDCALL(fn,expl_1,fieldNames,i,typeVars),ext_arg_1);
5726
5727 case (_,DAE.UNBOX(e1,tp),ext_arg)
5728 algorithm
5729 597 (e1_1,ext_arg_1) := traverseExpTopDown(e1, func, ext_arg);
5730 597 then (DAE.UNBOX(e1_1,tp),ext_arg_1);
5731
5732 case (_,DAE.BOX(e1),ext_arg)
5733 algorithm
5734 21838 (e1_1,ext_arg_1) := traverseExpTopDown(e1, func, ext_arg);
5735 21838 then (DAE.BOX(e1_1),ext_arg_1);
5736
5737 case (_,DAE.PATTERN(),ext_arg)
5738 then (inExp,ext_arg);
5739
5740 case (_,DAE.SHARED_LITERAL(),ext_arg)
5741 then (inExp,ext_arg);
5742
5743 else
5744 algorithm
5745 ✗ str := ExpressionBasics.printExpStr(inExp);
5746 ✗ str := getInstanceName() + " or " + System.dladdr(func) + "not implemented correctly: " + str;
5747 ✗ Error.addMessage(Error.INTERNAL_ERROR, {str});
5748 ✗ then fail();
5749 end match;
5750 end traverseExpTopDown1;
5751
5752 protected function traverseExpMatrixTopDown
5753 "author: PA
5754 Helper function to traverseExpTopDown, traverses matrix expressions."
5755 replaceable type Type_a subtypeof Any;
5756 input list<list<DAE.Exp>> inMatrix;
5757 input FuncExpType func;
5758 input Type_a inTypeA;
5759 output list<list<DAE.Exp>> outMatrix = {};
5760 output Type_a outTypeA = inTypeA;
5761 partial function FuncExpType
5762 input DAE.Exp exp;
5763 input Type_a arg;
5764 output DAE.Exp outExp;
5765 output Boolean cont;
5766 output Type_a outArg;
5767 end FuncExpType;
5768 protected
5769 list<DAE.Exp> row_1;
5770 Boolean same = true;
5771 algorithm
5772
2/2
✓ Branch 0 taken 203184 times.
✓ Branch 1 taken 67927 times.
271111 for row in inMatrix loop
5773 203184 (row_1,outTypeA) := traverseExpListTopDown(row, func, outTypeA);
5774
2/2
✓ Branch 0 taken 201410 times.
✓ Branch 1 taken 1774 times.
203184 same := if referenceEq(row,row_1) then same else false;
5775 outMatrix := row_1::outMatrix;
5776 end for;
5777
2/2
✓ Branch 0 taken 654 times.
✓ Branch 1 taken 67273 times.
67927 if same then
5778 outMatrix := inMatrix;
5779 else
5780 654 outMatrix := MetaModelica.Dangerous.listReverseInPlace(outMatrix);
5781 end if;
5782 end traverseExpMatrixTopDown;
5783
5784 public function traverseExpListTopDown
5785 " author PA:
5786 Calls traverseExpListTopDown for each element of list."
5787 replaceable type Type_a subtypeof Any;
5788 input list<DAE.Exp> inExpl;
5789 input FuncExpType rel;
5790 input Type_a inExt_arg;
5791 output list<DAE.Exp> outExpl = {};
5792 output Type_a outA = inExt_arg;
5793 partial function FuncExpType
5794 input DAE.Exp exp;
5795 input Type_a arg;
5796 output DAE.Exp outExp;
5797 output Boolean cont;
5798 output Type_a outArg;
5799 end FuncExpType;
5800 protected
5801 DAE.Exp e_1;
5802 list<DAE.Exp> rest = inExpl, acc;
5803 Integer nEq = 0;
5804 algorithm
5805 // Allocates only once an element changes, like traverseExpList.
5806 outExpl := inExpl;
5807
2/2
✓ Branch 0 taken 8975288 times.
✓ Branch 1 taken 2526627 times.
11501915 while not listEmpty(rest) loop
5808 8975288 (e_1, outA) := traverseExpTopDown(listHead(rest), rel, outA);
5809
2/2
✓ Branch 1 taken 536553 times.
✓ Branch 2 taken 8438735 times.
8975288 if not referenceEq(listHead(rest), e_1) then
5810 acc := {};
5811
1/2
✓ Branch 0 taken 821700 times.
✗ Branch 1 not taken.
821700 for e in inExpl loop
5812
2/2
✓ Branch 0 taken 285147 times.
✓ Branch 1 taken 536553 times.
821700 if nEq < 1 then
5813 break;
5814 end if;
5815 acc := e :: acc;
5816 285147 nEq := nEq - 1;
5817 end for;
5818 acc := e_1 :: acc;
5819
2/2
✓ Branch 1 taken 567167 times.
✓ Branch 2 taken 536553 times.
1103720 for e in listRest(rest) loop
5820 567167 (e_1, outA) := traverseExpTopDown(e, rel, outA);
5821 acc := e_1 :: acc;
5822 end for;
5823 536553 outExpl := MetaModelica.Dangerous.listReverseInPlace(acc);
5824 536553 return;
5825 end if;
5826 8438735 nEq := nEq + 1;
5827 8438735 rest := listRest(rest);
5828 end while;
5829 end traverseExpListTopDown;
5830
5831 public function traverseExpOpt "Calls traverseExpBottomUp for SOME(exp) and does nothing for NONE"
5832 input Option<DAE.Exp> inExp;
5833 input FuncExpType func;
5834 input Type_a inTypeA;
5835 output Option<DAE.Exp> outExp;
5836 output Type_a outTypeA;
5837 partial function FuncExpType
5838 input DAE.Exp inExp;
5839 input Type_a inTypeA;
5840 output DAE.Exp outExp;
5841 output Type_a outA;
5842 end FuncExpType;
5843 replaceable type Type_a subtypeof Any;
5844 algorithm
5845 (outExp,outTypeA) := match (inExp, inTypeA)
5846 local
5847 DAE.Exp e,e1;
5848 Type_a a;
5849 Option<DAE.Exp> oe;
5850 case (NONE(), a) then (inExp/*In case external functions create a copy of NONE()*/,a);
5851 case(oe as SOME(e), a) algorithm
5852 6632807 (e1,a) := traverseExpBottomUp(e,func,a);
5853
2/2
✓ Branch 0 taken 5210 times.
✓ Branch 1 taken 6627597 times.
6632807 oe := if referenceEq(e,e1) then oe else SOME(e1);
5854 6632807 then (oe,a);
5855 end match;
5856 end traverseExpOpt;
5857
5858 public function traverseExpOptTopDown "Calls traverseExpTopDown for SOME(exp) and does nothing for NONE"
5859 input Option<DAE.Exp> inExp;
5860 input FuncExpType func;
5861 input Type_a inTypeA;
5862 output Option<DAE.Exp> outExp;
5863 output Type_a outA;
5864 partial function FuncExpType
5865 input DAE.Exp inExp;
5866 input Type_a inTypeA;
5867 output DAE.Exp outExp;
5868 output Boolean cont;
5869 output Type_a outA;
5870 end FuncExpType;
5871 replaceable type Type_a subtypeof Any;
5872 algorithm
5873 (outExp,outA) := match (inExp, inTypeA)
5874 local DAE.Exp e,e1; Type_a a;
5875 case(NONE(), a) then (NONE(),a);
5876 case(SOME(e), a)
5877 algorithm
5878 10902 (e1,a) := traverseExpTopDown(e,func,a);
5879
2/2
✓ Branch 0 taken 7377 times.
✓ Branch 1 taken 3525 times.
18279 then (if referenceEq(e,e1) then inExp else SOME(e1),a);
5880 end match;
5881 end traverseExpOptTopDown;
5882
5883 public function traverseExpCrefDims<ArgT>
5884 input DAE.ComponentRef inCref;
5885 input FuncType inFunc;
5886 input ArgT inArg;
5887 output DAE.ComponentRef outCref;
5888 output ArgT outArg;
5889
5890 partial function FuncType
5891 input DAE.Exp inExp;
5892 input ArgT inArg;
5893 output DAE.Exp outExp;
5894 output ArgT outArg;
5895 end FuncType;
5896 algorithm
5897 (outCref, outArg) := match inCref
5898 local
5899 DAE.Ident id;
5900 DAE.Type ty, new_ty;
5901 list<DAE.Subscript> subs;
5902 DAE.ComponentRef cr, new_cr;
5903 ArgT arg;
5904
5905 case DAE.CREF_QUAL(id, ty, subs, cr)
5906 algorithm
5907 2084004 (new_cr, arg) := traverseExpCrefDims(cr, inFunc, inArg);
5908 2084004 (new_ty, arg) := traverseExpTypeDims(ty, inFunc, inArg);
5909
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2084004 times.
2084004 cr := if referenceEq(new_cr, cr) and referenceEq(new_ty, ty)
5910 then inCref else DAE.CREF_QUAL(id, new_ty, subs, new_cr);
5911 2084004 then
5912 (cr, arg);
5913
5914 case DAE.CREF_IDENT(id, ty, subs)
5915 algorithm
5916 1385159 (new_ty, arg) := traverseExpTypeDims(ty, inFunc, inArg);
5917
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1385159 times.
1385159 cr := if referenceEq(new_ty, ty)
5918 then inCref else DAE.CREF_IDENT(id, new_ty, subs);
5919 1385159 then
5920 (cr, arg);
5921
5922 else (inCref, inArg);
5923 end match;
5924 end traverseExpCrefDims;
5925
5926 public function traverseExpTypeDims<ArgT>
5927 input DAE.Type inType;
5928 input FuncType inFunc;
5929 input ArgT inArg;
5930 output DAE.Type outType;
5931 output ArgT outArg;
5932
5933 partial function FuncType
5934 input DAE.Exp inExp;
5935 input ArgT inArg;
5936 output DAE.Exp outExp;
5937 output ArgT outArg;
5938 end FuncType;
5939 algorithm
5940 (outType, outArg) := match inType
5941 local
5942 DAE.Type ty, new_ty;
5943 list<DAE.Dimension> dims;
5944 ArgT arg;
5945 Boolean changed;
5946 ClassInf.State state;
5947 list<DAE.Var> vars;
5948 DAE.EqualityConstraint ec;
5949
5950 case DAE.T_ARRAY(ty, dims)
5951 algorithm
5952 778757 (_, arg, changed) := traverseExpTypeDims2(dims, inFunc, inArg);
5953
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 778757 times.
778757 ty := if changed then DAE.T_ARRAY(ty, dims) else inType;
5954 778757 then
5955 (ty, arg);
5956
5957 case DAE.T_SUBTYPE_BASIC(state, vars, ty, ec)
5958 algorithm
5959 ✗ (new_ty, arg) := traverseExpTypeDims(ty, inFunc, inArg);
5960 ✗ ty := if referenceEq(new_ty, ty) then inType else DAE.T_SUBTYPE_BASIC(state, vars, ty, ec);
5961 ✗ then
5962 (ty, arg);
5963
5964 else (inType, inArg);
5965 end match;
5966 end traverseExpTypeDims;
5967
5968 protected function traverseExpTypeDims2<ArgT>
5969 input list<DAE.Dimension> inDims;
5970 input FuncType inFunc;
5971 input ArgT inArg;
5972 output list<DAE.Dimension> outDims = {};
5973 output ArgT outArg = inArg;
5974 output Boolean outChanged = false;
5975
5976 partial function FuncType
5977 input DAE.Exp inExp;
5978 input ArgT inArg;
5979 output DAE.Exp outExp;
5980 output ArgT outArg;
5981 end FuncType;
5982 protected
5983 Boolean changed;
5984 DAE.Exp exp, new_exp;
5985 algorithm
5986
2/2
✓ Branch 0 taken 906469 times.
✓ Branch 1 taken 778757 times.
1685226 for dim in inDims loop
5987 dim := match dim
5988 case DAE.DIM_EXP(exp)
5989 algorithm
5990
1/2
✓ Branch 0 taken 2426 times.
✗ Branch 1 not taken.
2426 (new_exp, outArg) := inFunc(exp, outArg);
5991 2426 changed := not referenceEq(new_exp, exp);
5992 2426 outChanged := outChanged or changed;
5993
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2426 times.
2426 then
5994 if changed then DAE.DIM_EXP(exp) else dim;
5995
5996 else dim;
5997 end match;
5998
5999 outDims := dim :: outDims;
6000 end for;
6001
6002
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 778757 times.
778757 outDims := if outChanged then listReverse(outDims) else inDims;
6003 end traverseExpTypeDims2;
6004
6005 public function extractUniqueCrefsFromExp
6006 "Extracts all unique ComponentRef from an Expression.
6007 If `expand` is true crefs will be expanded."
6008 input DAE.Exp inExp;
6009 input Boolean expand = true;
6010 output list<DAE.ComponentRef> ocrefs;
6011 algorithm
6012 6421 ocrefs := ComponentReference.uniqueList(extractCrefsFromExp(inExp));
6013
6014
1/2
✓ Branch 0 taken 6421 times.
✗ Branch 1 not taken.
6421 if expand then
6015 ✗ ocrefs := List.flatten(List.map1(ocrefs, ComponentReference.expandCref, true));
6016 end if;
6017 end extractUniqueCrefsFromExp;
6018
6019 public function extractCrefsFromExp "
6020 Author: BZ 2008-06, Extracts all ComponentRef from an Expression."
6021 input DAE.Exp inExp;
6022 output list<DAE.ComponentRef> ocrefs;
6023 algorithm
6024 918109 (_,ocrefs) := traverseExpBottomUp(inExp, traversingComponentRefFinder, {});
6025 end extractCrefsFromExp;
6026
6027 public function traversingComponentRefFinder "
6028 Author: BZ 2008-06
6029 Exp traverser that Union the current ComponentRef with list if it is already there.
6030 Returns a list containing, unique, all componentRef in an Expression."
6031 input DAE.Exp inExp;
6032 input list<DAE.ComponentRef> inCrefs;
6033 output DAE.Exp outExp;
6034 output list<DAE.ComponentRef> crefs;
6035 algorithm
6036 (outExp,crefs) := match (inExp,inCrefs)
6037 local
6038 ComponentRef cr;
6039 case (DAE.CREF(componentRef=cr), crefs)
6040 algorithm
6041 1127061 crefs := List.unionEltOnTrue(cr,crefs,ComponentReferenceBasics.crefEqual);
6042 then (inExp,crefs);
6043 else (inExp,inCrefs);
6044 end match;
6045 end traversingComponentRefFinder;
6046
6047 public function extractUniqueCrefsFromExpDerPreStart
6048 "author mahge: Same as extractUniqueCrefsFromExp except:
6049 This function will not treat der(), pre() and start() as calls
6050 but as unique ids. i.e. x is different from der(x) and given der(x) x will not
6051 be extreacted as a unique id. Instead you get $DER.x. Same goes for pre and start."
6052 input DAE.Exp inExp;
6053 input Boolean expand = true;
6054 output list<DAE.ComponentRef> ocrefs;
6055 algorithm
6056 272177 ocrefs := ComponentReference.uniqueList(extractCrefsFromExpDerPreStart(inExp, expand));
6057 end extractUniqueCrefsFromExpDerPreStart;
6058
6059 public function extractCrefsFromExpDerPreStart
6060 " author mahge: Same as extractCrefsFromExp except:
6061 This function will not treat der(), pre() and start() as calls
6062 but as unique ids. i.e. x is different from der(x) and given der(x) x will not
6063 be extreacted as a unique id. Instead you get $DER.x. Same goes for pre and start.
6064 If `expand` is true crefs will be expanded."
6065 input DAE.Exp inExp;
6066 input Boolean expand = true;
6067 output list<DAE.ComponentRef> ocrefs;
6068 algorithm
6069 275737 (_,ocrefs) := traverseExpTopDown(inExp, traversingComponentRefFinderDerPreStart, {});
6070
2/2
✓ Branch 0 taken 2983 times.
✓ Branch 1 taken 272754 times.
275737 if expand then
6071 272754 ocrefs := List.flatten(List.map1(ocrefs, ComponentReference.expandCref, true));
6072 end if;
6073 end extractCrefsFromExpDerPreStart;
6074
6075 public function traversingComponentRefFinderDerPreStart "
6076 "
6077 input DAE.Exp inExp;
6078 input list<DAE.ComponentRef> inCrefs;
6079 output DAE.Exp e;
6080 output Boolean cont;
6081 output list<DAE.ComponentRef> crefs;
6082 algorithm
6083 (e,cont,crefs) := match (inExp,inCrefs)
6084 local
6085 ComponentRef cr;
6086 case (DAE.CREF(componentRef=cr), crefs)
6087 algorithm
6088 522290 crefs := List.unionEltOnTrue(cr,inCrefs,ComponentReferenceBasics.crefEqual);
6089 then (inExp, false, crefs);
6090
6091 case (DAE.CALL(path = Absyn.IDENT(name="der"), expLst={DAE.CREF(componentRef=cr)}),_) algorithm
6092 4782 cr := ComponentReference.crefPrefixDer(cr);
6093 4782 crefs := List.unionEltOnTrue(cr,inCrefs,ComponentReferenceBasics.crefEqual);
6094 then (inExp, false, crefs);
6095
6096 case (DAE.CALL(path = Absyn.IDENT(name="pre"), expLst={DAE.CREF(componentRef=cr)}),_) algorithm
6097 1126 cr := ComponentReference.crefPrefixPre(cr);
6098 1126 crefs := List.unionEltOnTrue(cr,inCrefs,ComponentReferenceBasics.crefEqual);
6099 then (inExp, false, crefs);
6100
6101 case (DAE.CALL(path = Absyn.IDENT(name="previous"), expLst={DAE.CREF(componentRef=cr)}),_) algorithm
6102 165 cr := ComponentReference.crefPrefixPrevious(cr);
6103 165 crefs := List.unionEltOnTrue(cr,inCrefs,ComponentReferenceBasics.crefEqual);
6104 then (inExp, false, crefs);
6105
6106 case (DAE.CALL(path = Absyn.IDENT(name="start"), expLst={DAE.CREF(componentRef=cr)}),_) algorithm
6107 ✗ Error.addInternalError(getInstanceName() + " - Found a start call expression " + ExpressionBasics.printExpStr(inExp), sourceInfo());
6108 ✗ cr := ComponentReference.crefPrefixStart(cr);
6109 ✗ crefs := List.unionEltOnTrue(cr,inCrefs,ComponentReferenceBasics.crefEqual);
6110 then (inExp, false, crefs);
6111
6112 else (inExp,true,inCrefs);
6113 end match;
6114 end traversingComponentRefFinderDerPreStart;
6115
6116 public function extractUniqueCrefsFromStatmentS
6117 "authot mahge: Extracts all unique ComponentRef from Statments."
6118 input list<DAE.Statement> inStmts;
6119 output list<DAE.ComponentRef> olhscrefs;
6120 output list<DAE.ComponentRef> orhscrefs;
6121 protected
6122 list<list<DAE.ComponentRef>> lhscreflstlst;
6123 list<list<DAE.ComponentRef>> rhscreflstlst;
6124 algorithm
6125 7 (lhscreflstlst,rhscreflstlst) := List.map_2(inStmts,extractCrefsStatment);
6126 7 orhscrefs := ComponentReference.uniqueList(List.flatten(rhscreflstlst));
6127 7 olhscrefs := ComponentReference.uniqueList(List.flatten(lhscreflstlst));
6128 end extractUniqueCrefsFromStatmentS;
6129
6130
6131 public function extractCrefsStatment
6132 "Extracts all ComponentRef from a Statment."
6133 input DAE.Statement inStmt;
6134 output list<DAE.ComponentRef> olcrefs;
6135 output list<DAE.ComponentRef> orcrefs;
6136 algorithm
6137 (olcrefs,orcrefs) := match inStmt
6138 local
6139 Exp exp1,exp2;
6140 list<DAE.Exp> expLst;
6141 list<DAE.Statement> stmtLst;
6142
6143 case DAE.STMT_ASSIGN(exp1 = exp1, exp = exp2)
6144 algorithm
6145 14 olcrefs := extractCrefsFromExpDerPreStart(exp1, false);
6146 14 orcrefs := extractCrefsFromExpDerPreStart(exp2, false);
6147 14 then
6148 (olcrefs,orcrefs);
6149
6150 case DAE.STMT_TUPLE_ASSIGN(expExpLst = expLst, exp = exp2)
6151 algorithm
6152 5 olcrefs := List.flatten(List.map1(expLst, extractCrefsFromExpDerPreStart, false));
6153 5 orcrefs := extractCrefsFromExpDerPreStart(exp2, false);
6154 5 then
6155 (olcrefs,orcrefs);
6156
6157 case DAE.STMT_ASSIGN_ARR(lhs = exp1, exp = exp2)
6158 algorithm
6159 ✗ olcrefs := extractCrefsFromExpDerPreStart(exp1, false);
6160 ✗ orcrefs := extractCrefsFromExpDerPreStart(exp2, false);
6161 ✗ then
6162 (olcrefs,orcrefs);
6163
6164 case DAE.STMT_IF(statementLst = stmtLst)
6165 algorithm
6166 ✗ (olcrefs,orcrefs) := extractUniqueCrefsFromStatmentS(stmtLst);
6167 then
6168 (olcrefs,orcrefs);
6169
6170 case DAE.STMT_FOR(statementLst = stmtLst)
6171 algorithm
6172 1 (olcrefs,orcrefs) := extractUniqueCrefsFromStatmentS(stmtLst);
6173 then
6174 (olcrefs,orcrefs);
6175
6176 case DAE.STMT_WHILE(statementLst = stmtLst)
6177 algorithm
6178 ✗ (olcrefs,orcrefs) := extractUniqueCrefsFromStatmentS(stmtLst);
6179 then
6180 (olcrefs,orcrefs);
6181
6182 case DAE.STMT_WHEN(statementLst = stmtLst)
6183 algorithm
6184 6 (olcrefs,orcrefs) := extractUniqueCrefsFromStatmentS(stmtLst);
6185 then
6186 (olcrefs,orcrefs);
6187
6188 case DAE.STMT_ASSERT(cond = exp1)
6189 algorithm
6190 5 orcrefs := extractCrefsFromExpDerPreStart(exp1, false);
6191 5 then
6192 ({},orcrefs);
6193
6194 ✗ else ({},{});
6195
6196 end match;
6197 end extractCrefsStatment;
6198
6199 public function getLhsCrefsFromStatements "Extracts all lhs crefs from Statements.
6200 author: ptaeuber"
6201 input list<DAE.Statement> inStmts;
6202 output list<DAE.ComponentRef> lhsCrefs;
6203 protected
6204 list<list<DAE.ComponentRef>> lhsCrefsLst;
6205 algorithm
6206 9072 lhsCrefsLst := List.map(inStmts,getLhsCrefsFromStatement);
6207 9072 lhsCrefs := List.flatten(lhsCrefsLst);
6208 end getLhsCrefsFromStatements;
6209
6210 protected function getLhsCrefsFromStatement "Extracts all lhs crefs from a statement.
6211 author: ptaeuber"
6212 input DAE.Statement inStmt;
6213 output list<DAE.ComponentRef> lhsCrefs;
6214 algorithm
6215 lhsCrefs := match inStmt
6216 local
6217 Exp exp1;
6218 list<DAE.Exp> expLst;
6219 list<DAE.Statement> stmtLst;
6220
6221 case DAE.STMT_ASSIGN(exp1 = exp1)
6222 algorithm
6223 2550 lhsCrefs := extractCrefsFromExpDerPreStart(exp1, false);
6224 then lhsCrefs;
6225
6226 case DAE.STMT_TUPLE_ASSIGN(expExpLst = expLst)
6227 algorithm
6228 53 lhsCrefs := List.flatten(List.map1(expLst, extractCrefsFromExpDerPreStart, false));
6229 then lhsCrefs;
6230
6231 case DAE.STMT_ASSIGN_ARR(lhs = exp1)
6232 algorithm
6233 177 lhsCrefs := extractCrefsFromExpDerPreStart(exp1, false);
6234 then lhsCrefs;
6235
6236 case DAE.STMT_IF(statementLst = stmtLst)
6237 algorithm
6238 731 lhsCrefs := getLhsCrefsFromStatements(stmtLst);
6239 then lhsCrefs;
6240
6241 case DAE.STMT_FOR(statementLst = stmtLst)
6242 algorithm
6243 439 lhsCrefs := getLhsCrefsFromStatements(stmtLst);
6244 then lhsCrefs;
6245
6246 case DAE.STMT_WHILE(statementLst = stmtLst)
6247 algorithm
6248 ✗ lhsCrefs := getLhsCrefsFromStatements(stmtLst);
6249 then lhsCrefs;
6250
6251 case DAE.STMT_WHEN(statementLst = stmtLst)
6252 algorithm
6253 370 lhsCrefs := getLhsCrefsFromStatements(stmtLst);
6254 then lhsCrefs;
6255
6256 else {};
6257
6258 end match;
6259 end getLhsCrefsFromStatement;
6260
6261 public function expHasInitial "
6262 returns true if the expression contains any initial() call"
6263 input DAE.Exp exp;
6264 output Boolean found;
6265 algorithm
6266 126 (_,found) := traverseExpTopDown(exp, traversingexpHasInitial, false);
6267 end expHasInitial;
6268
6269 public function traversingexpHasInitial
6270 input output DAE.Exp exp;
6271 output Boolean cont;
6272 input output Boolean found;
6273 algorithm
6274
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 413 times.
413 if found then
6275 cont := false;
6276 ✗ return;
6277 end if;
6278 (cont,found) := match exp
6279 case DAE.CALL(path= Absyn.IDENT("initial"))
6280 then (false,true);
6281 else (true,found);
6282 end match;
6283 end traversingexpHasInitial;
6284
6285 public function expHasCrefs "
6286 @author: adrpo 2011-04-29
6287 returns true if the expression contains crefs"
6288 input DAE.Exp inExp;
6289 output Boolean hasCrefs;
6290 algorithm
6291 hasCrefs := match inExp
6292 local
6293 Boolean b;
6294
6295 case _
6296 algorithm
6297 20719 (_,b) := traverseExpTopDown(inExp, traversingComponentRefPresent, false);
6298 then
6299 b;
6300 end match;
6301 end expHasCrefs;
6302
6303 public function traversingComponentRefPresent "Returns a true if the exp is a componentRef"
6304 input DAE.Exp inExp;
6305 input Boolean found;
6306 output DAE.Exp outExp;
6307 output Boolean cont;
6308 output Boolean outFound;
6309 algorithm
6310 (outExp,cont,outFound) := match (inExp,found)
6311 case (_,true) then (inExp,false,true);
6312 case (DAE.CREF(), _) then (inExp, false, true);
6313 else (inExp,true,false);
6314 end match;
6315 end traversingComponentRefPresent;
6316
6317 public function traversingComponentRefFinderNoPreDer "
6318 Author: BZ 2008-06
6319 Exp traverser that Union the current ComponentRef with list if it is already there.
6320 Returns a list containing, unique, all componentRef in an Expression."
6321 input DAE.Exp inExp;
6322 input list<DAE.ComponentRef> inCrefs;
6323 output DAE.Exp e;
6324 output Boolean cont;
6325 output list<DAE.ComponentRef> crefs;
6326 algorithm
6327 (e,cont,crefs) := match (inExp,inCrefs)
6328 local
6329 ComponentRef cr;
6330 case (DAE.CREF(componentRef=cr), crefs)
6331 algorithm
6332 163613 crefs := List.unionEltOnTrue(cr,crefs,ComponentReferenceBasics.crefEqual);
6333 then (inExp, false, crefs);
6334 case (DAE.CALL(path = Absyn.IDENT(name = "der")), _) then (inExp, false, inCrefs);
6335 case (DAE.CALL(path = Absyn.IDENT(name = "pre")), _) then (inExp, false, inCrefs);
6336 case (DAE.CALL(path = Absyn.IDENT(name = "previous")), _) then (inExp, false, inCrefs);
6337 else (inExp,true,inCrefs);
6338 end match;
6339 end traversingComponentRefFinderNoPreDer;
6340
6341 public function expHasCref "author: Frenkel TUD 2011-04
6342 returns true if the expression contains the cref"
6343 input DAE.Exp inExp;
6344 input DAE.ComponentRef inCr;
6345 output Boolean hasCref;
6346 algorithm
6347 18137 (_,(_,hasCref)) := traverseExpTopDown(inExp, traversingexpHasCref, (inCr,false));
6348 end expHasCref;
6349
6350 public function traversingexpHasCref "
6351 @author: Frenkel TUD 2011-04
6352 Returns a true if the exp the componentRef"
6353 input DAE.Exp inExp;
6354 input tuple<DAE.ComponentRef,Boolean> inTpl;
6355 output DAE.Exp outExp;
6356 output Boolean cont;
6357 output tuple<DAE.ComponentRef,Boolean> outTpl;
6358 algorithm
6359 (outExp,cont,outTpl) := matchcontinue(inExp,inTpl)
6360 local
6361 Boolean b;
6362 ComponentRef cr,cr1;
6363
6364 // pre(cr) does not count because it should be its own variable instead!
6365 case (DAE.CALL(path = Absyn.IDENT("pre")), _)
6366 then (inExp, false, inTpl);
6367
6368 case (DAE.CREF(componentRef = cr1), (cr,false))
6369 algorithm
6370 42346 b := ComponentReferenceBasics.crefEqualNoStringCompare(cr,cr1);
6371
2/2
✓ Branch 0 taken 4908 times.
✓ Branch 1 taken 37438 times.
42346 then
6372 (inExp,not b,if b then (cr,b) else inTpl);
6373
6374 96087 case (_,(_,b)) then (inExp,not b,inTpl);
6375
6376 end matchcontinue;
6377 end traversingexpHasCref;
6378
6379 public function expHasCrefName "Returns a true if the exp contains a cref that starts with the given name"
6380 input DAE.Exp inExp;
6381 input String name;
6382 output Boolean hasCref;
6383 algorithm
6384 636 (_,(_,hasCref)) := traverseExpTopDown(inExp, traversingexpHasName, (name,false));
6385 end expHasCrefName;
6386
6387 public function anyExpHasCrefName "Returns a true if any exp contains a cref that starts with the given name"
6388 input list<DAE.Exp> inExps;
6389 input String name;
6390 output Boolean hasCref;
6391 algorithm
6392 498 hasCref := List.applyAndFold1(inExps, boolOr, expHasCrefName, name, false);
6393 end anyExpHasCrefName;
6394
6395 public function traversingexpHasName "Returns a true if the exp contains a cref that starts with the given name"
6396 input DAE.Exp inExp;
6397 input tuple<String,Boolean> inTpl;
6398 output DAE.Exp outExp;
6399 output Boolean cont;
6400 output tuple<String,Boolean> outTpl;
6401 algorithm
6402 (outExp,cont,outTpl) := match (inExp,inTpl)
6403 local
6404 Boolean b;
6405 String name;
6406 DAE.ComponentRef cr;
6407 case (DAE.CREF(componentRef = cr), (name,false))
6408 algorithm
6409
4/4
✓ Branch 1 taken 76 times.
✓ Branch 2 taken 613 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 73 times.
689 b := name == ComponentReferenceBasics.crefFirstIdent(cr);
6410 689 then (inExp,not b,if b then (name,b) else inTpl);
6411 136 case (_,(_,b)) then (inExp,not b,inTpl);
6412 end match;
6413 end traversingexpHasName;
6414
6415 public function expHasDerCref "
6416 @author: Frenkel TUD 2012-06
6417 returns true if the expression contains the cref in function der"
6418 input DAE.Exp inExp;
6419 input DAE.ComponentRef inCr;
6420 output Boolean hasCref;
6421 algorithm
6422 56602 (_,(_,hasCref)) := traverseExpTopDown(inExp, traversingexpHasDerCref, (inCr,false));
6423 end expHasDerCref;
6424
6425 public function traversingexpHasDerCref "
6426 @author: Frenkel TUD 2012-06
6427 Returns a true if the exp contains the componentRef in der"
6428 input DAE.Exp inExp;
6429 input tuple<DAE.ComponentRef,Boolean> inTpl;
6430 output DAE.Exp outExp;
6431 output Boolean cont;
6432 output tuple<DAE.ComponentRef,Boolean> outTpl;
6433 algorithm
6434 (outExp,cont,outTpl) := matchcontinue(inExp,inTpl)
6435 local
6436 Boolean b;
6437 ComponentRef cr,cr1;
6438
6439 case (DAE.CALL(path= Absyn.IDENT("der"),expLst={DAE.CREF(componentRef = cr1)}), (cr,false))
6440 algorithm
6441 25036 b := ComponentReferenceBasics.crefEqualNoStringCompare(cr,cr1);
6442
2/2
✓ Branch 0 taken 24539 times.
✓ Branch 1 taken 497 times.
25036 then (inExp,not b,if b then (cr,b) else inTpl);
6443
6444 case (DAE.CALL(path= Absyn.IDENT("der"),expLst={DAE.CREF(componentRef = cr1)}), (cr,false))
6445 algorithm
6446 ✗ b := ComponentReferenceBasics.crefPrefixOf(cr,cr1);
6447 ✗ then (inExp,not b,if b then (cr,b) else inTpl);
6448
6449 231670 case (_,(_,b)) then (inExp,not b,inTpl);
6450
6451 end matchcontinue;
6452 end traversingexpHasDerCref;
6453
6454 public function expHasDer "
6455 returns true if the expression contains the function der"
6456 input DAE.Exp inExp;
6457 output Boolean hasCref;
6458 algorithm
6459 6420 (_, hasCref) := traverseExpTopDown(inExp, traversingexpHasDer, false);
6460 end expHasDer;
6461
6462 public function traversingexpHasDer "
6463 Returns a true if the exp contains in der"
6464 input DAE.Exp inExp;
6465 input Boolean inTpl;
6466 output DAE.Exp outExp;
6467 output Boolean cont;
6468 output Boolean outTpl;
6469 algorithm
6470 (outExp,cont,outTpl) := match(inExp,inTpl)
6471 local
6472 Boolean b;
6473 ComponentRef cr;
6474
6475 case (DAE.CALL(path= Absyn.IDENT("der")), false)
6476 then (inExp,false,true);
6477
6478 //isAlias
6479 case(DAE.CREF(componentRef = cr), false)
6480 guard intEq(System.strncmp(ComponentReferenceBasics.crefFirstIdent(cr),"$DERAlias",9),0) //BackendDAE.derivativeNamePrefix
6481 algorithm
6482 then (inExp,false,true);
6483
6484 93915 case (_,b) then (inExp, not b, inTpl);
6485
6486 end match;
6487 end traversingexpHasDer;
6488
6489 public function expHasPre "
6490 Returns true if the expression contains the operator pre"
6491 input DAE.Exp inExp;
6492 output Boolean hasPre;
6493 algorithm
6494 ✗ (_, hasPre) := traverseExpTopDown(inExp, traversingexpHasPre, false);
6495 end expHasPre;
6496
6497 protected function traversingexpHasPre "
6498 Returns true if the exp is pre(..)"
6499 input DAE.Exp inExp;
6500 input Boolean inHasIt;
6501 output DAE.Exp outExp;
6502 output Boolean cont;
6503 output Boolean outHasIt;
6504 algorithm
6505 (outExp,cont,outHasIt) := match(inExp,inHasIt)
6506 local
6507 Boolean b;
6508 case (DAE.CALL(path= Absyn.IDENT("pre")), false)
6509 then (inExp,false,true);
6510 ✗ case (_,b) then (inExp, not b, inHasIt);
6511 end match;
6512 end traversingexpHasPre;
6513
6514 public function expHasPrevious "
6515 Returns true if the expression contains the operator previous"
6516 input DAE.Exp inExp;
6517 output Boolean hasPre;
6518 algorithm
6519 ✗ (_, hasPre) := traverseExpTopDown(inExp, traversingexpHasPrevious, false);
6520 end expHasPrevious;
6521
6522 protected function traversingexpHasPrevious "
6523 Returns true if the exp is pre(..)"
6524 input DAE.Exp inExp;
6525 input Boolean inHasIt;
6526 output DAE.Exp outExp;
6527 output Boolean cont;
6528 output Boolean outHasIt;
6529 algorithm
6530 (outExp,cont,outHasIt) := match(inExp,inHasIt)
6531 local
6532 Boolean b;
6533 case (DAE.CALL(path= Absyn.IDENT("previous")), false)
6534 then (inExp,false,true);
6535 ✗ case (_,b) then (inExp, not b, inHasIt);
6536 end match;
6537 end traversingexpHasPrevious;
6538
6539
6540 public function expHasCrefNoPreorDer "
6541 @author: Frenkel TUD 2011-04
6542 returns true if the expression contains the cref, but not in pre,change,edge"
6543 input DAE.Exp inExp;
6544 input DAE.ComponentRef inCr;
6545 output Boolean hasCref;
6546 algorithm
6547 43675 (_,(_,hasCref)) := traverseExpTopDown(inExp, traversingexpHasCrefNoPreorDer, (inCr,false));
6548 end expHasCrefNoPreorDer;
6549
6550 public function traversingexpHasCrefNoPreorDer "
6551 @author: Frenkel TUD 2011-04
6552 Returns a true if the exp the componentRef"
6553 input DAE.Exp inExp;
6554 input tuple<DAE.ComponentRef,Boolean> inTpl;
6555 output DAE.Exp outExp;
6556 output Boolean cont;
6557 output tuple<DAE.ComponentRef,Boolean> outTpl;
6558 algorithm
6559 (outExp,cont,outTpl) := match (inExp,inTpl)
6560 local
6561 Boolean b;
6562 DAE.ComponentRef cr,cr1;
6563
6564 case (DAE.CALL(path = Absyn.IDENT(name = "pre")), _)
6565 then (inExp,false,inTpl);
6566
6567 case (DAE.CALL(path = Absyn.IDENT(name = "previous")), _)
6568 then (inExp,false,inTpl);
6569
6570 case (DAE.CREF(componentRef = cr1), (cr,false))
6571 algorithm
6572 215393 b := ComponentReferenceBasics.crefEqualNoStringCompare(cr,cr1);
6573
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 215331 times.
215393 then (inExp,not b,if b then (cr,b) else inTpl);
6574
6575 /* Not reachable...
6576 case (DAE.CREF(componentRef = cr1), (cr,false))
6577 algorithm
6578 b = ComponentReferenceBasics.crefPrefixOf(cr1,cr);
6579 then (inExp,not b,(cr,b));
6580 */
6581 573899 case (_,(_,b)) then (inExp,not b,inTpl);
6582
6583 end match;
6584 end traversingexpHasCrefNoPreorDer;
6585
6586 public function expHasCrefsNoPreOrStart "
6587 returns true if the expression contains one cref from the list, but not in pre(),change(),edge(),start(), delay()"
6588 input DAE.Exp inExp;
6589 input list<DAE.ComponentRef> inCr;
6590 output Boolean hasCref = false;
6591 algorithm
6592
2/2
✓ Branch 0 taken 3174 times.
✓ Branch 1 taken 486 times.
3660 for cr in inCr loop
6593 3174 (_,(_,hasCref)) := traverseExpTopDown(inExp, traversingexpHasCrefNoPreOrStart, (cr,false));
6594
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3172 times.
3174 if hasCref then
6595 break;
6596 end if;
6597 end for;
6598 end expHasCrefsNoPreOrStart;
6599
6600
6601 public function expHasCrefNoPreOrStart "
6602 returns true if the expression contains the cref, but not in pre(),change(),edge(),start(), delay()"
6603 input DAE.Exp inExp;
6604 input DAE.ComponentRef inCr;
6605 output Boolean hasCref;
6606 algorithm
6607 2120613 (_,(_,hasCref)) := traverseExpTopDown(inExp, traversingexpHasCrefNoPreOrStart, (inCr,false));
6608 end expHasCrefNoPreOrStart;
6609
6610 protected function traversingexpHasCrefNoPreOrStart "
6611 return true if the exp the componentRef"
6612 input DAE.Exp inExp;
6613 input tuple<DAE.ComponentRef,Boolean> inTpl;
6614 output DAE.Exp outExp;
6615 output Boolean cont;
6616 output tuple<DAE.ComponentRef,Boolean> outTpl;
6617
6618 algorithm
6619 (outExp,cont,outTpl) := match (inExp,inTpl)
6620 local
6621 Boolean b;
6622 DAE.ComponentRef cr,cr1;
6623
6624 case (DAE.CALL(path = Absyn.IDENT(name = "pre")), _)
6625 then (inExp,false,inTpl);
6626 case (DAE.CALL(path = Absyn.IDENT(name = "previous")), _)
6627 then (inExp,false,inTpl);
6628 case (DAE.CALL(path = Absyn.IDENT(name = "change")), _)
6629 then (inExp,false,inTpl);
6630 case (DAE.CALL(path = Absyn.IDENT(name = "delay")), _)
6631 then (inExp,false,inTpl);
6632 case (DAE.CALL(path = Absyn.IDENT(name = "edge")), _)
6633 then (inExp,false,inTpl);
6634 case (DAE.CALL(path = Absyn.IDENT(name = "$_round")), _)
6635 then (inExp,false,inTpl);
6636
6637 case (DAE.CREF(componentRef = cr1), (cr,false))
6638 algorithm
6639 2728031 b := ComponentReferenceBasics.crefEqualNoStringCompare(cr,cr1);
6640
2/2
✓ Branch 0 taken 792849 times.
✓ Branch 1 taken 1935182 times.
2728031 then (inExp,not b,if b then (cr,b) else inTpl);
6641
6642 5901317 case (_,(_,b)) then (inExp,not b,inTpl);
6643
6644 end match;
6645 end traversingexpHasCrefNoPreOrStart;
6646
6647 public function expHasCrefInIf "
6648 Returns a true if the exp contains the componentRef in if,sign,semiLinear"
6649
6650 input DAE.Exp inExp;
6651 input DAE.ComponentRef inCr;
6652 output Boolean hasCref;
6653 algorithm
6654 274805 (_,(_,hasCref)) := traverseExpTopDown(inExp,expHasCrefInIfWork, (inCr,false));
6655 end expHasCrefInIf;
6656
6657 public function expHasCrefInIfWork "
6658 Returns a true if the exp contains the componentRef in if,sign,semiLinear"
6659 input DAE.Exp inExp;
6660 input tuple<DAE.ComponentRef,Boolean> inTpl;
6661 output DAE.Exp outExp;
6662 output Boolean cont;
6663 output tuple<DAE.ComponentRef,Boolean> outTpl;
6664 algorithm
6665 (outExp,cont,outTpl) := match(inExp,inTpl)
6666 local
6667 Boolean b;
6668 Integer i;
6669 ComponentRef cr;
6670 DAE.Exp e1;
6671
6672 case(DAE.IFEXP(e1,_,_),(cr,false))
6673 guard(not isFunCall(e1,"noEvent"))
6674 algorithm
6675 7843 b := expHasCref(e1,cr);
6676
2/2
✓ Branch 0 taken 212 times.
✓ Branch 1 taken 7631 times.
7843 then (e1, true,if b then (cr,b) else inTpl);
6677
6678 case(DAE.CALL(path = Absyn.IDENT(name = "smooth"),expLst = {DAE.ICONST(i),e1}),(cr,false))
6679 guard(i>1)
6680 ✗ then (e1,true, (cr, expHasCref(e1,cr)));
6681
6682 case(DAE.CALL(), (cr,false))
6683 guard(isEventTriggeringFunctionExp(inExp))
6684 algorithm
6685 2 b := expHasCref(inExp, cr);
6686
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 then(inExp, true,if b then (cr,b) else inTpl);
6687
6688 case(DAE.CALL(path = Absyn.IDENT(name = "semiLinear"),expLst = {e1,_,_}),(cr,false))
6689 algorithm
6690 1909 b := expHasCref(e1,cr);
6691
2/2
✓ Branch 0 taken 569 times.
✓ Branch 1 taken 1340 times.
1909 then (e1, true,if b then (cr,b) else inTpl);
6692
6693 case(DAE.CALL(path = Absyn.IDENT(name = "sign"),expLst = {e1}),(cr,false))
6694 algorithm
6695 22 b := expHasCref(e1,cr);
6696
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 20 times.
22 then (e1, not b,if b then (cr,b) else inTpl);
6697
6698 case (_, (_,true)) then (inExp,false,inTpl);
6699 else (inExp, true, inTpl);
6700
6701 end match;
6702 end expHasCrefInIfWork;
6703
6704 public function expHasCrefInSmoothZero
6705 "author: kabdelhak FHB 2019-09
6706 Returns true if the expression contains a function call of the form
6707 smooth(0, cr). Used to determine if an artificial state should
6708 not be differentiated and reverted to be an algebraic variable
6709 instead. "
6710 input DAE.Exp exp;
6711 input DAE.ComponentRef cr;
6712 output Boolean b;
6713 algorithm
6714 2698 (_, (_, b)) := traverseExpBottomUp(exp, expHasCrefInSmoothZeroWork, (cr, false));
6715 end expHasCrefInSmoothZero;
6716
6717 protected function expHasCrefInSmoothZeroWork
6718 "author: kabdelhak FHB 2019-09
6719 Work function to detect smooth(0, cr).
6720 Q: Should it also return true if the smooth call expression
6721 contains the cref in any way not only for direct identity?"
6722 input output DAE.Exp exp;
6723 input output tuple<DAE.ComponentRef, Boolean> tpl;
6724 algorithm
6725 tpl := match (exp, tpl)
6726 local
6727 DAE.ComponentRef cr, sCr;
6728 Boolean b;
6729 case (DAE.CALL(path = Absyn.IDENT(name = "smooth"), expLst = {DAE.ICONST(0), DAE.CREF(componentRef = sCr)}), (cr, false))
6730 algorithm
6731 ✗ b := ComponentReferenceBasics.crefEqual(sCr, cr);
6732 //expHasCref(e, cr); use this instead for full check?
6733 ✗ then (cr, b);
6734 else tpl;
6735 end match;
6736 end expHasCrefInSmoothZeroWork;
6737
6738 public function traverseCrefsFromExp "
6739 Author: Frenkel TUD 2011-05, traverses all ComponentRef from an Expression."
6740 input DAE.Exp inExp;
6741 input FuncCrefTypeA inFunc;
6742 input Type_a inArg;
6743 output Type_a outArg;
6744 partial function FuncCrefTypeA
6745 input DAE.ComponentRef inCref;
6746 input Type_a inArg;
6747 output Type_a outArg;
6748 end FuncCrefTypeA;
6749 replaceable type Type_a subtypeof Any;
6750 algorithm
6751 outArg := match inArg
6752 local Type_a arg;
6753 case _
6754 algorithm
6755 ✗ (_,(_,arg)) := traverseExpBottomUp(inExp, traversingCrefFinder, (inFunc,inArg));
6756 then
6757 arg;
6758 end match;
6759 end traverseCrefsFromExp;
6760
6761 protected function traversingCrefFinder "
6762 Author: Frenkel TUD 2011-05"
6763 input DAE.Exp inExp;
6764 input tuple<FuncCrefTypeA,Type_a> inTpl;
6765 output DAE.Exp outExp;
6766 output tuple<FuncCrefTypeA,Type_a> outTpl;
6767 partial function FuncCrefTypeA
6768 input DAE.ComponentRef inCref;
6769 input Type_a inArg;
6770 output Type_a outArg;
6771 end FuncCrefTypeA;
6772 replaceable type Type_a subtypeof Any;
6773 algorithm
6774 (outExp,outTpl) := match (inExp,inTpl)
6775 local
6776 Type_a arg,arg1;
6777 FuncCrefTypeA func;
6778 ComponentRef cr;
6779
6780 case (DAE.CREF(cr,_),(func,arg))
6781 algorithm
6782 ✗ arg1 := func(cr,arg);
6783 ✗ then (inExp, if referenceEq(arg, arg1) then inTpl else (func,arg1));
6784
6785 else (inExp,inTpl);
6786
6787 end match;
6788 end traversingCrefFinder;
6789
6790 public function extractDivExpFromExp "
6791 Author: Frenkel TUD 2010-02, Extracts all Division DAE.Exp from an Expression."
6792 input DAE.Exp inExp;
6793 output list<DAE.Exp> outExps;
6794 algorithm
6795 ✗ (_,outExps) := traverseExpBottomUp(inExp, traversingDivExpFinder, {});
6796 end extractDivExpFromExp;
6797
6798 protected function traversingDivExpFinder "
6799 Author: Frenkel TUD 2010-02
6800 Returns a list containing, all division DAE.Exp in an Expression."
6801 input DAE.Exp e;
6802 input list<DAE.Exp> exps;
6803 output DAE.Exp outExp;
6804 output list<DAE.Exp> acc;
6805 algorithm
6806 (outExp,acc) := match e
6807 local
6808 DAE.Exp e2;
6809 case DAE.BINARY(operator = DAE.DIV(_),exp2 = e2)
6810 then (e, e2::exps);
6811
6812 case DAE.BINARY(operator = DAE.DIV_ARR(_),exp2 = e2)
6813 then (e, e2::exps);
6814
6815 case DAE.BINARY(operator = DAE.DIV_ARRAY_SCALAR(_),exp2 = e2)
6816 then (e, e2::exps);
6817
6818 case DAE.BINARY(operator = DAE.DIV_SCALAR_ARRAY(_),exp2 = e2)
6819 then (e, e2::exps);
6820
6821 else (e,exps);
6822 end match;
6823 end traversingDivExpFinder;
6824
6825 public function traverseExpListBidir<ArgT>
6826 "Traverses a list of expressions, calling traverseExpBidir on each
6827 expression."
6828 input list<DAE.Exp> inExpl;
6829 input FuncType inEnterFunc;
6830 input FuncType inExitFunc;
6831 input ArgT inArg;
6832 output list<DAE.Exp> outExpl;
6833 output ArgT outArg = inArg;
6834
6835 partial function FuncType
6836 input DAE.Exp inExp;
6837 input ArgT inArg;
6838 output DAE.Exp outExp;
6839 output ArgT outArg;
6840 end FuncType;
6841 protected
6842 DAE.Exp e1;
6843 DoubleEnded.MutableList<DAE.Exp> delst;
6844 list<DAE.Exp> rest = inExpl;
6845 Integer nEq=0;
6846 algorithm
6847 // Preserve reference equality without any allocation if nothing changed.
6848 outExpl := inExpl;
6849
2/2
✓ Branch 0 taken 449281 times.
✓ Branch 1 taken 78971 times.
528252 while not listEmpty(rest) loop
6850 449281 (e1, outArg) := traverseExpBidir(listHead(rest), inEnterFunc, inExitFunc, outArg);
6851
2/2
✓ Branch 1 taken 2270 times.
✓ Branch 2 taken 447011 times.
449281 if not referenceEq(listHead(rest), e1) then
6852 // First change: switch to building a new list with a DoubleEnded list.
6853 2270 delst := DoubleEnded.empty(e1);
6854
1/2
✓ Branch 0 taken 2305 times.
✗ Branch 1 not taken.
2305 for elt in inExpl loop
6855
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 2270 times.
2305 if nEq < 1 then
6856 break;
6857 end if;
6858 35 DoubleEnded.push_back(delst, elt);
6859 35 nEq := nEq-1;
6860 end for;
6861 2270 DoubleEnded.push_back(delst, e1);
6862
2/2
✓ Branch 1 taken 2966 times.
✓ Branch 2 taken 2270 times.
5236 for e in listRest(rest) loop
6863 2966 (e1, outArg) := traverseExpBidir(e, inEnterFunc, inExitFunc, outArg);
6864 2966 DoubleEnded.push_back(delst, e1);
6865 end for;
6866 2270 outExpl := DoubleEnded.toListAndClear(delst);
6867 2270 return;
6868 end if;
6869 447011 nEq := nEq + 1;
6870 447011 rest := listRest(rest);
6871 end while;
6872 end traverseExpListBidir;
6873
6874 public function traverseExpBidir<ArgT>
6875 "This function takes an expression and a tuple with an enter function, an exit
6876 function, and an extra argument. For each expression it encounters it calls
6877 the enter function with the expression and the extra argument. It then
6878 traverses all subexpressions in the expression and calls traverseExpBidir on
6879 them with the updated argument. Finally it calls the exit function, again with
6880 the updated argument. This means that this function is bidirectional, and can
6881 be used to emulate both top-down and bottom-up traversal."
6882 input DAE.Exp inExp;
6883 input FuncType inEnterFunc;
6884 input FuncType inExitFunc;
6885 input ArgT inArg;
6886 output DAE.Exp outExp;
6887 output ArgT outArg;
6888
6889 partial function FuncType
6890 input DAE.Exp inExp;
6891 input ArgT inArg;
6892 output DAE.Exp outExp;
6893 output ArgT outArg;
6894 end FuncType;
6895 algorithm
6896
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 500766 times.
500766 (outExp, outArg) := inEnterFunc(inExp, inArg);
6897 500766 (outExp, outArg) := traverseExpBidirSubExps(outExp, inEnterFunc, inExitFunc, outArg);
6898
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 500766 times.
500766 (outExp, outArg) := inExitFunc(outExp, outArg);
6899 end traverseExpBidir;
6900
6901 public function traverseExpOptBidir<ArgT>
6902 "Same as traverseExpBidir, but with an optional expression. Calls
6903 traverseExpBidir if the option is SOME(), or just returns the input if it's
6904 NONE()"
6905 input Option<DAE.Exp> inExp;
6906 input FuncType inEnterFunc;
6907 input FuncType inExitFunc;
6908 input ArgT inArg;
6909 output Option<DAE.Exp> outExp;
6910 output ArgT outArg;
6911
6912 partial function FuncType
6913 input Exp inExp;
6914 input ArgT inArg;
6915 output Exp outExp;
6916 output ArgT outArg;
6917 end FuncType;
6918 algorithm
6919 (outExp, outArg) := match inExp
6920 local
6921 DAE.Exp e,e1;
6922 ArgT arg;
6923
6924 case SOME(e)
6925 algorithm
6926 957 (e1, arg) := traverseExpBidir(e, inEnterFunc, inExitFunc, inArg);
6927
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 957 times.
957 then
6928 (if referenceEq(e,e1) then inExp else SOME(e1), arg);
6929
6930 else (inExp, inArg);
6931 end match;
6932 end traverseExpOptBidir;
6933
6934 protected function traverseExpBidirSubExps<ArgT>
6935 "Helper function to traverseExpBidir. Traverses the subexpressions of an
6936 expression and calls traverseExpBidir on them."
6937 input DAE.Exp inExp;
6938 input FuncType inEnterFunc;
6939 input FuncType inExitFunc;
6940 input ArgT inArg;
6941 output DAE.Exp outExp;
6942 output ArgT outArg;
6943
6944 partial function FuncType
6945 input DAE.Exp inExp;
6946 input ArgT inArg;
6947 output DAE.Exp outExp;
6948 output ArgT outArg;
6949 end FuncType;
6950 algorithm
6951 (outExp, outArg) := match inExp
6952 local
6953 Integer i;
6954 DAE.Exp e1, e2, e3, e1_1, e2_1, e3_1;
6955 Option<DAE.Exp> oe1, oe1_1;
6956 DAE.Operator op;
6957 ComponentRef cref, cref_1;
6958 list<DAE.Exp> expl, expl_1;
6959 list<list<DAE.Exp>> mat_expl;
6960 DAE.MatchType match_ty;
6961 list<DAE.Element> match_decls;
6962 list<DAE.MatchCase> match_cases;
6963 Integer index, dim;
6964 Option<tuple<DAE.Exp, Integer, Integer>> opt_exp_asub;
6965 Absyn.Path path;
6966 Boolean b1;
6967 Type ty,t;
6968 list<String> strl;
6969 DAE.ReductionInfo reductionInfo;
6970 DAE.ReductionIterators riters, riters_1;
6971 DAE.CallAttributes attr;
6972 list<list<String>> aliases;
6973 ArgT arg;
6974 list<DAE.Type> typeVars;
6975 list<DAE.Subscript> subs;
6976
6977 case DAE.ICONST() then (inExp, inArg);
6978 case DAE.RCONST() then (inExp, inArg);
6979 case DAE.SCONST() then (inExp, inArg);
6980 case DAE.BCONST() then (inExp, inArg);
6981 case DAE.ENUM_LITERAL() then (inExp, inArg);
6982
6983 case DAE.CREF(componentRef = cref, ty = ty)
6984 algorithm
6985 8644 (cref_1, arg) := traverseExpBidirCref(cref, inEnterFunc, inExitFunc, inArg);
6986
1/2
✓ Branch 0 taken 8644 times.
✗ Branch 1 not taken.
8644 then
6987 (if referenceEq(cref, cref_1) then inExp else DAE.CREF(cref_1, ty), arg);
6988
6989 case DAE.BINARY(exp1 = e1, operator = op, exp2 = e2)
6990 algorithm
6991 3837 (e1_1, arg) := traverseExpBidir(e1, inEnterFunc, inExitFunc, inArg);
6992 3837 (e2_1, arg) := traverseExpBidir(e2, inEnterFunc, inExitFunc, arg);
6993
1/2
✓ Branch 0 taken 3837 times.
✗ Branch 1 not taken.
3837 then
6994 (if referenceEq(e1, e1_1) and referenceEq(e2, e2_1) then inExp else DAE.BINARY(e1_1, op, e2_1), arg);
6995
6996 case DAE.UNARY(operator = op, exp = e1)
6997 algorithm
6998 ✗ (e1_1, arg) := traverseExpBidir(e1, inEnterFunc, inExitFunc, inArg);
6999 ✗ then
7000 (if referenceEq(e1, e1_1) then inExp else DAE.UNARY(op, e1), arg);
7001
7002 case DAE.LBINARY(exp1 = e1, operator = op, exp2 = e2)
7003 algorithm
7004 ✗ (e1_1, arg) := traverseExpBidir(e1, inEnterFunc, inExitFunc, inArg);
7005 ✗ (e2_1, arg) := traverseExpBidir(e2, inEnterFunc, inExitFunc, arg);
7006 ✗ then
7007 (if referenceEq(e1, e1_1) and referenceEq(e2, e2_1) then inExp else DAE.LBINARY(e1_1, op, e2_1), arg);
7008
7009 case DAE.LUNARY(operator = op, exp = e1)
7010 algorithm
7011 ✗ (e1_1, arg) := traverseExpBidir(e1, inEnterFunc, inExitFunc, inArg);
7012 ✗ then
7013 (if referenceEq(e1, e1_1) then inExp else DAE.LUNARY(op, e1), arg);
7014
7015 case DAE.RELATION(exp1 = e1, operator = op, exp2 = e2, index = index,
7016 optionExpisASUB = opt_exp_asub)
7017 algorithm
7018 598 (e1_1, arg) := traverseExpBidir(e1, inEnterFunc, inExitFunc, inArg);
7019 598 (e2_1, arg) := traverseExpBidir(e2, inEnterFunc, inExitFunc, arg);
7020
1/2
✓ Branch 0 taken 598 times.
✗ Branch 1 not taken.
598 then
7021 (if referenceEq(e1, e1_1) and referenceEq(e2, e2_1) then inExp else DAE.RELATION(e1_1, op, e2_1, index, opt_exp_asub), arg);
7022
7023 case DAE.IFEXP(expCond = e1, expThen = e2, expElse = e3)
7024 algorithm
7025 596 (e1_1, arg) := traverseExpBidir(e1, inEnterFunc, inExitFunc, inArg);
7026 596 (e2_1, arg) := traverseExpBidir(e2, inEnterFunc, inExitFunc, arg);
7027 596 (e3_1, arg) := traverseExpBidir(e3, inEnterFunc, inExitFunc, arg);
7028
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 596 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
596 then
7029 (if referenceEq(e1, e1_1) and referenceEq(e2, e2_1) and referenceEq(e3, e3_1) then inExp else DAE.IFEXP(e1_1, e2_1, e3_1), arg);
7030
7031 case DAE.CALL(path = path, expLst = expl, attr = attr)
7032 algorithm
7033 1046 (expl_1, arg) := traverseExpListBidir(expl, inEnterFunc, inExitFunc, inArg);
7034
1/2
✓ Branch 0 taken 1046 times.
✗ Branch 1 not taken.
1046 then
7035 (if referenceEq(expl, expl_1) then inExp else DAE.CALL(path, expl_1, attr), arg);
7036
7037 case DAE.RECORD(path = path, exps = expl, comp = strl, ty = ty)
7038 algorithm
7039 ✗ (expl_1, arg) := traverseExpListBidir(expl, inEnterFunc, inExitFunc, inArg);
7040 ✗ then
7041 (if referenceEq(expl, expl_1) then inExp else DAE.RECORD(path, expl_1, strl, ty), arg);
7042
7043 case DAE.PARTEVALFUNCTION(path, expl, ty, t)
7044 algorithm
7045 ✗ (expl_1, arg) := traverseExpListBidir(expl, inEnterFunc, inExitFunc, inArg);
7046 ✗ then
7047 (if referenceEq(expl, expl_1) then inExp else DAE.PARTEVALFUNCTION(path, expl_1, ty, t), arg);
7048
7049 case DAE.ARRAY(ty = ty, scalar = b1, array = expl)
7050 algorithm
7051 80169 (expl_1, arg) := traverseExpListBidir(expl, inEnterFunc, inExitFunc, inArg);
7052
4/4
✓ Branch 0 taken 1212 times.
✓ Branch 1 taken 78957 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1211 times.
80170 then
7053 (if referenceEq(expl, expl_1) then inExp else DAE.ARRAY(ty, b1, expl_1), arg);
7054
7055 case DAE.MATRIX(ty = ty, integer = dim, matrix = mat_expl)
7056 algorithm
7057 6 (mat_expl, arg) := List.map2Fold(mat_expl, traverseExpListBidir,
7058 inEnterFunc, inExitFunc, inArg);
7059 6 then
7060 (DAE.MATRIX(ty, dim, mat_expl), arg);
7061
7062 case DAE.RANGE(ty = ty, start = e1, step = oe1, stop = e2)
7063 algorithm
7064 26 (e1_1, arg) := traverseExpBidir(e1, inEnterFunc, inExitFunc, inArg);
7065 26 (oe1_1, arg) := traverseExpOptBidir(oe1, inEnterFunc, inExitFunc, arg);
7066 26 (e2_1, arg) := traverseExpBidir(e2, inEnterFunc, inExitFunc, arg);
7067
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
26 then
7068 (if referenceEq(e1, e1_1) and referenceEq(e2, e2_1) and referenceEq(oe1, oe1_1) then inExp else DAE.RANGE(ty, e1_1, oe1_1, e2_1), arg);
7069
7070 case DAE.TUPLE(PR = expl)
7071 algorithm
7072 ✗ (expl_1, arg) := traverseExpListBidir(expl, inEnterFunc, inExitFunc, inArg);
7073 ✗ then
7074 (if referenceEq(expl, expl_1) then inExp else DAE.TUPLE(expl_1), arg);
7075
7076 case DAE.CAST(ty = ty, exp = e1)
7077 algorithm
7078 26 (e1_1, arg) := traverseExpBidir(e1, inEnterFunc, inExitFunc, inArg);
7079
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 then
7080 (if referenceEq(e1, e1_1) then inExp else DAE.CAST(ty, e1), arg);
7081
7082 case DAE.ASUB(exp = e1, sub = subs)
7083 algorithm
7084 ✗ expl := list(Expression.getSubscriptExp(sub) for sub in subs);
7085 ✗ (e1_1, arg) := traverseExpBidir(e1, inEnterFunc, inExitFunc, inArg);
7086 ✗ (expl_1, arg) := traverseExpListBidir(expl, inEnterFunc, inExitFunc, arg);
7087 ✗ subs := list(Expression.makeIndexSubscript(sub) for sub in expl);
7088 ✗ then
7089 (if referenceEq(e1, e1_1) and referenceEq(expl, expl_1) then inExp else DAE.ASUB(e1_1, subs), arg);
7090
7091 case e1 as DAE.RSUB()
7092 algorithm
7093 ✗ (e2, arg) := traverseExpBidir(e1.exp, inEnterFunc, inExitFunc, inArg);
7094 ✗ if referenceEq(e1.exp, e2) then
7095 ✗ e1.exp := e2;
7096 end if;
7097 ✗ then
7098 (e1, arg);
7099
7100 case DAE.TSUB(e1, i, ty)
7101 algorithm
7102 2 (e1_1, arg) := traverseExpBidir(e1, inEnterFunc, inExitFunc, inArg);
7103
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 then
7104 (if referenceEq(e1, e1_1) then inExp else DAE.TSUB(e1_1, i, ty), arg);
7105
7106 case DAE.SIZE(exp = e1, sz = oe1)
7107 algorithm
7108 957 (e1_1, arg) := traverseExpBidir(e1, inEnterFunc, inExitFunc, inArg);
7109 957 (oe1_1, arg) := traverseExpOptBidir(oe1, inEnterFunc, inExitFunc, arg);
7110
1/2
✓ Branch 0 taken 957 times.
✗ Branch 1 not taken.
957 then
7111 (if referenceEq(e1, e1_1) and referenceEq(oe1, oe1_1) then inExp else DAE.SIZE(e1_1, oe1_1), arg);
7112
7113 case DAE.CODE()
7114 then (inExp, inArg);
7115
7116 case DAE.REDUCTION(reductionInfo = reductionInfo, expr = e1, iterators = riters)
7117 algorithm
7118 28 (e1_1, arg) := traverseExpBidir(e1, inEnterFunc, inExitFunc, inArg);
7119 28 (riters_1, arg) := List.map2Fold(riters, traverseReductionIteratorBidir,
7120 inEnterFunc, inExitFunc, arg);
7121
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 then
7122 (if referenceEq(e1, e1_1) and referenceEq(riters, riters_1) then inExp else DAE.REDUCTION(reductionInfo, e1, riters), arg);
7123
7124 case DAE.LIST(valList = expl)
7125 algorithm
7126 7 (expl_1, arg) := traverseExpListBidir(expl, inEnterFunc, inExitFunc, inArg);
7127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 then
7128 (if referenceEq(expl, expl_1) then inExp else DAE.LIST(expl_1), arg);
7129
7130 case DAE.CONS(car = e1, cdr = e2)
7131 algorithm
7132 ✗ (e1_1, arg) := traverseExpBidir(e1, inEnterFunc, inExitFunc, inArg);
7133 ✗ (e2_1, arg) := traverseExpBidir(e2, inEnterFunc, inExitFunc, arg);
7134 ✗ then
7135 (if referenceEq(e1, e1_1) and referenceEq(e2, e2_1) then inExp else DAE.CONS(e1_1, e2_1), arg);
7136
7137 case DAE.META_TUPLE(listExp = expl)
7138 algorithm
7139 4 (expl_1, arg) := traverseExpListBidir(expl, inEnterFunc, inExitFunc, inArg);
7140
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 then
7141 (if referenceEq(expl, expl_1) then inExp else DAE.TUPLE(expl_1), arg);
7142
7143 case DAE.META_OPTION(exp = oe1)
7144 algorithm
7145 ✗ (oe1_1, arg) := traverseExpOptBidir(oe1, inEnterFunc, inExitFunc, inArg);
7146 ✗ then
7147 (if referenceEq(oe1, oe1_1) then inExp else DAE.META_OPTION(oe1_1), arg);
7148
7149 case DAE.METARECORDCALL(path = path, args = expl, fieldNames = strl, index = index, typeVars = typeVars)
7150 algorithm
7151 1 (expl_1, arg) := traverseExpListBidir(expl, inEnterFunc, inExitFunc, inArg);
7152
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 then
7153 (if referenceEq(expl, expl_1) then inExp else DAE.METARECORDCALL(path, expl_1, strl, index, typeVars), arg);
7154
7155 case DAE.MATCHEXPRESSION(matchType = match_ty, inputs = expl, aliases=aliases,
7156 localDecls = match_decls, cases = match_cases, et = ty)
7157 algorithm
7158 ✗ (expl_1, arg) := traverseExpListBidir(expl, inEnterFunc, inExitFunc, inArg);
7159 ✗ Error.addSourceMessage(Error.COMPILER_NOTIFICATION, {getInstanceName() + " not yet implemented for match expressions. Called using: " + System.dladdr(inEnterFunc) + " " + System.dladdr(inExitFunc)}, sourceInfo());
7160 //(cases, tup) = List.mapFold(cases, traverseMatchCase, tup);
7161 ✗ then
7162 (if referenceEq(expl, expl_1) then inExp else DAE.MATCHEXPRESSION(match_ty, expl_1, aliases, match_decls, match_cases, ty), arg);
7163
7164 case DAE.BOX(exp = e1)
7165 algorithm
7166 17 (e1_1, arg) := traverseExpBidir(e1, inEnterFunc, inExitFunc, inArg);
7167
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 then
7168 (if referenceEq(e1, e1_1) then inExp else DAE.BOX(e1_1), arg);
7169
7170 case DAE.UNBOX(exp = e1, ty = ty)
7171 algorithm
7172 ✗ (e1_1, arg) := traverseExpBidir(e1, inEnterFunc, inExitFunc, inArg);
7173 ✗ then
7174 (if referenceEq(e1, e1_1) then inExp else DAE.UNBOX(e1_1, ty), arg);
7175
7176 case DAE.SHARED_LITERAL() then (inExp, inArg);
7177 case DAE.PATTERN() then (inExp, inArg);
7178
7179 else
7180 algorithm
7181 ✗ Error.addInternalError(getInstanceName() + " - Unknown expression " + ExpressionBasics.printExpStr(inExp) + ". Called using: " + System.dladdr(inEnterFunc) + " " + System.dladdr(inExitFunc), sourceInfo());
7182 ✗ then
7183 fail();
7184
7185 end match;
7186 end traverseExpBidirSubExps;
7187
7188 public function traverseExpBidirCref<ArgT>
7189 "Helper function to traverseExpBidirSubExps. Traverses any expressions in a
7190 component reference (i.e. in it's subscripts)."
7191 input DAE.ComponentRef inCref;
7192 input FuncType inEnterFunc;
7193 input FuncType inExitFunc;
7194 input ArgT inArg;
7195 output DAE.ComponentRef outCref;
7196 output ArgT outArg;
7197
7198 partial function FuncType
7199 input DAE.Exp inExp;
7200 input ArgT inArg;
7201 output DAE.Exp outExp;
7202 output ArgT outArg;
7203 end FuncType;
7204 algorithm
7205 (outCref, outArg) := match inCref
7206 local
7207 String name;
7208 ComponentRef cr;
7209 Type ty;
7210 list<DAE.Subscript> subs;
7211 ArgT arg;
7212
7213 case DAE.CREF_QUAL(name, ty, subs, cr)
7214 algorithm
7215 ✗ (subs, arg) := List.map2Fold(subs, traverseExpBidirSubs, inEnterFunc,
7216 inExitFunc, inArg);
7217 ✗ (cr, arg) := traverseExpBidirCref(cr, inEnterFunc, inExitFunc, arg);
7218 ✗ then
7219 (DAE.CREF_QUAL(name, ty, subs, cr), arg);
7220
7221 case DAE.CREF_IDENT(ident = name, identType = ty, subscriptLst = subs)
7222 algorithm
7223 8644 (subs, arg) := List.map2Fold(subs, traverseExpBidirSubs, inEnterFunc,
7224 inExitFunc, inArg);
7225 8644 then
7226 (DAE.CREF_IDENT(name, ty, subs), arg);
7227
7228 else (inCref, inArg);
7229 end match;
7230 end traverseExpBidirCref;
7231
7232 public function traverseExpCref
7233 "Helper function to traverseExpBottomUp. Traverses any expressions in a
7234 component reference (i.e. in it's subscripts)."
7235 input DAE.ComponentRef inCref;
7236 input FuncType rel;
7237 input Type_a iarg;
7238 output DAE.ComponentRef outCref;
7239 output Type_a outArg;
7240
7241 partial function FuncType
7242 input DAE.Exp inExp;
7243 input Type_a inArg;
7244 output DAE.Exp outExp;
7245 output Type_a outArg;
7246 end FuncType;
7247
7248 replaceable type Type_a subtypeof Any;
7249 algorithm
7250 (outCref, outArg) := match(inCref, iarg)
7251 local
7252 String name;
7253 ComponentRef cr,cr_1;
7254 Type ty;
7255 list<DAE.Subscript> subs,subs_1;
7256 Type_a arg;
7257 String instant;
7258
7259 case (DAE.CREF_QUAL(ident = name, identType = ty, subscriptLst = subs, componentRef = cr), arg)
7260 algorithm
7261 81449777 (subs_1, arg) := traverseExpSubs(subs, rel, arg);
7262 81449777 (cr_1, arg) := traverseExpCref(cr, rel, arg);
7263
2/2
✓ Branch 0 taken 58260 times.
✓ Branch 1 taken 81391517 times.
81449777 then
7264 (if referenceEq(cr,cr_1) and referenceEq(subs,subs_1) then inCref else DAE.CREF_QUAL(name, ty, subs_1, cr_1), arg);
7265
7266 case (DAE.CREF_IDENT(ident = name, identType = ty, subscriptLst = subs), arg)
7267 algorithm
7268 49052633 (subs_1, arg) := traverseExpSubs(subs, rel, arg);
7269
2/2
✓ Branch 0 taken 37984 times.
✓ Branch 1 taken 49014649 times.
49052633 cr := if referenceEq(subs,subs_1) then inCref else DAE.CREF_IDENT(name, ty, subs_1);
7270 49052633 then
7271 (cr, arg);
7272
7273 case (DAE.OPTIMICA_ATTR_INST_CREF(componentRef = cr, instant = instant), arg)
7274 algorithm
7275 ✗ (cr_1, arg) := traverseExpCref(cr, rel, arg);
7276 ✗ cr := if referenceEq(cr,cr_1) then inCref else DAE.OPTIMICA_ATTR_INST_CREF(cr_1, instant);
7277 ✗ then
7278 (cr, arg);
7279
7280 case (DAE.WILD(), arg) then (inCref, arg);
7281
7282 else
7283 algorithm
7284 ✗ Error.addMessage(Error.INTERNAL_ERROR, {"Expression.traverseExpCref: Unknown cref"});
7285 ✗ then fail();
7286 end match;
7287 end traverseExpCref;
7288
7289 protected function traverseExpSubs
7290 input list<DAE.Subscript> inSubscript;
7291 input FuncType rel;
7292 input Type_a iarg;
7293 output list<DAE.Subscript> outSubscript;
7294 output Type_a outArg;
7295
7296 partial function FuncType
7297 input DAE.Exp inExp;
7298 input Type_a inArg;
7299 output DAE.Exp outExp;
7300 output Type_a outArg;
7301 end FuncType;
7302
7303 replaceable type Type_a subtypeof Any;
7304 algorithm
7305 (outSubscript, outArg) := match(inSubscript, iarg)
7306 local
7307 DAE.Exp sub_exp,sub_exp_1;
7308 list<DAE.Subscript> rest,res;
7309 Type_a arg;
7310
7311 case ({}, arg) then (inSubscript,arg);
7312 case (DAE.WHOLEDIM()::rest, arg)
7313 algorithm
7314 1829 (res,arg) := traverseExpSubs(rest,rel,arg);
7315
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1829 times.
1829 res := if referenceEq(rest,res) then inSubscript else (DAE.WHOLEDIM()::res);
7316 1829 then (res, arg);
7317
7318 case (DAE.SLICE(exp = sub_exp)::rest, arg)
7319 algorithm
7320 903 (sub_exp_1,arg) := traverseExpBottomUp(sub_exp, rel, arg);
7321 903 (res,arg) := traverseExpSubs(rest,rel,arg);
7322
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 895 times.
903 res := if referenceEq(sub_exp,sub_exp_1) and referenceEq(rest,res) then inSubscript else (DAE.SLICE(sub_exp_1)::res);
7323 903 then
7324 (res, arg);
7325
7326 case (DAE.INDEX(exp = sub_exp)::rest, arg)
7327 algorithm
7328 63339876 (sub_exp_1,arg) := traverseExpBottomUp(sub_exp, rel, arg);
7329 63339876 (res,arg) := traverseExpSubs(rest,rel,arg);
7330
2/2
✓ Branch 0 taken 38842 times.
✓ Branch 1 taken 63301034 times.
63339876 res := if referenceEq(sub_exp,sub_exp_1) and referenceEq(rest,res) then inSubscript else (DAE.INDEX(sub_exp_1)::res);
7331 63339876 then
7332 (res, arg);
7333
7334 case (DAE.WHOLE_NONEXP(exp = sub_exp)::rest, arg)
7335 algorithm
7336 ✗ (sub_exp_1,arg) := traverseExpBottomUp(sub_exp, rel, arg);
7337 ✗ (res,arg) := traverseExpSubs(rest,rel,arg);
7338 ✗ res := if referenceEq(sub_exp,sub_exp_1) and referenceEq(rest,res) then inSubscript else (DAE.WHOLE_NONEXP(sub_exp_1)::res);
7339 ✗ then
7340 (res, arg);
7341
7342 end match;
7343 end traverseExpSubs;
7344
7345 public function traverseExpTopDownCrefHelper
7346 input DAE.ComponentRef inCref;
7347 input FuncType rel;
7348 input Argument iarg;
7349 output DAE.ComponentRef outCref;
7350 output Argument outArg;
7351
7352 partial function FuncType
7353 input DAE.Exp inExp;
7354 input Argument inArg;
7355 output DAE.Exp outExp;
7356 output Boolean cont;
7357 output Argument outArg;
7358 end FuncType;
7359
7360 replaceable type Argument subtypeof Any;
7361 algorithm
7362 (outCref, outArg) := match(inCref, iarg)
7363 local
7364 String name;
7365 ComponentRef cr, cr_1;
7366 Type ty;
7367 list<DAE.Subscript> subs, subs_1;
7368 Argument arg;
7369
7370 case (DAE.CREF_QUAL(ident = name, identType = ty, subscriptLst = subs, componentRef = cr), arg)
7371 algorithm
7372 31876710 (subs_1,arg) := traverseExpTopDownSubs(subs, rel, arg);
7373 31876710 (cr_1, arg) := traverseExpTopDownCrefHelper(cr, rel, arg);
7374
2/2
✓ Branch 0 taken 820 times.
✓ Branch 1 taken 31875890 times.
31876710 then
7375 (if referenceEq(subs,subs_1) and referenceEq(cr,cr_1) then inCref else DAE.CREF_QUAL(name, ty, subs_1, cr_1), arg);
7376
7377 case (DAE.CREF_IDENT(ident = name, identType = ty, subscriptLst = subs), arg)
7378 algorithm
7379 15169697 (subs_1,arg) := traverseExpTopDownSubs(subs, rel, arg);
7380
2/2
✓ Branch 0 taken 575 times.
✓ Branch 1 taken 15169122 times.
15169697 then
7381 (if referenceEq(subs,subs_1) then inCref else DAE.CREF_IDENT(name, ty, subs_1), arg);
7382
7383 case (DAE.WILD(), arg) then (inCref, arg);
7384 end match;
7385 end traverseExpTopDownCrefHelper;
7386
7387 protected function traverseExpBidirSubs<ArgT>
7388 "Helper function to traverseExpBidirCref. Traverses expressions in a
7389 subscript."
7390 input DAE.Subscript inSubscript;
7391 input FuncType inEnterFunc;
7392 input FuncType inExitFunc;
7393 input ArgT inArg;
7394 output DAE.Subscript outSubscript;
7395 output ArgT outArg;
7396
7397 partial function FuncType
7398 input DAE.Exp inExp;
7399 input ArgT inArg;
7400 output DAE.Exp outExp;
7401 output ArgT outArg;
7402 end FuncType;
7403 algorithm
7404 (outSubscript, outArg) := match inSubscript
7405 local
7406 DAE.Exp sub_exp;
7407 ArgT arg;
7408
7409 case DAE.WHOLEDIM() then (inSubscript, inArg);
7410
7411 case DAE.SLICE(exp = sub_exp)
7412 algorithm
7413 ✗ (sub_exp, arg) := traverseExpBidir(sub_exp, inEnterFunc, inExitFunc, inArg);
7414 ✗ then
7415 (DAE.SLICE(sub_exp), arg);
7416
7417 case DAE.INDEX(exp = sub_exp)
7418 algorithm
7419 6929 (sub_exp, arg) := traverseExpBidir(sub_exp, inEnterFunc, inExitFunc, inArg);
7420 6929 then
7421 (DAE.INDEX(sub_exp), arg);
7422
7423 case DAE.WHOLE_NONEXP(exp = sub_exp)
7424 algorithm
7425 ✗ (sub_exp, arg) := traverseExpBidir(sub_exp, inEnterFunc, inExitFunc, inArg);
7426 ✗ then
7427 (DAE.WHOLE_NONEXP(sub_exp), arg);
7428
7429 end match;
7430 end traverseExpBidirSubs;
7431
7432 public function traverseExpTopDownSubs
7433 input list<DAE.Subscript> inSubscript;
7434 input FuncType rel;
7435 input Argument iarg;
7436 output list<DAE.Subscript> outSubscript;
7437 output Argument arg=iarg;
7438
7439 partial function FuncType
7440 input DAE.Exp inExp;
7441 input Argument inArg;
7442 output DAE.Exp outExp;
7443 output Boolean cont;
7444 output Argument outArg;
7445 end FuncType;
7446
7447 replaceable type Argument subtypeof Any;
7448 protected
7449 DAE.Exp exp;
7450 DAE.Subscript sub, nsub;
7451 DoubleEnded.MutableList<DAE.Subscript> delst;
7452 list<DAE.Subscript> rest = inSubscript;
7453 Integer nEq=0;
7454 algorithm
7455 // Preserve reference equality without any allocation if nothing changed.
7456 outSubscript := inSubscript;
7457
2/2
✓ Branch 0 taken 20306878 times.
✓ Branch 1 taken 50739500 times.
71046378 while not listEmpty(rest) loop
7458 20306878 sub := listHead(rest);
7459 nsub := match sub
7460 case DAE.WHOLEDIM() then sub;
7461 case DAE.SLICE()
7462 algorithm
7463 310 (exp,arg) := traverseExpTopDown(sub.exp, rel, arg);
7464
2/2
✓ Branch 0 taken 184 times.
✓ Branch 1 taken 126 times.
310 then if referenceEq(sub.exp, exp) then sub else DAE.SLICE(exp);
7465 case DAE.INDEX()
7466 algorithm
7467 20305508 (exp,arg) := traverseExpTopDown(sub.exp, rel, arg);
7468
2/2
✓ Branch 0 taken 395 times.
✓ Branch 1 taken 20305113 times.
20305508 then if referenceEq(sub.exp, exp) then sub else DAE.INDEX(exp);
7469 case DAE.WHOLE_NONEXP()
7470 algorithm
7471 ✗ (exp,arg) := traverseExpTopDown(sub.exp, rel, arg);
7472 ✗ then if referenceEq(sub.exp, exp) then sub else DAE.WHOLE_NONEXP(exp);
7473 end match;
7474
2/2
✓ Branch 0 taken 579 times.
✓ Branch 1 taken 20306299 times.
20306878 if not referenceEq(nsub, sub) then
7475 // First change: switch to building a new list with a DoubleEnded list.
7476 579 delst := DoubleEnded.empty(nsub);
7477
1/2
✓ Branch 0 taken 588 times.
✗ Branch 1 not taken.
588 for elt in inSubscript loop
7478
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 579 times.
588 if nEq < 1 then
7479 break;
7480 end if;
7481 9 DoubleEnded.push_back(delst, elt);
7482 9 nEq := nEq-1;
7483 end for;
7484 579 DoubleEnded.push_back(delst, nsub);
7485
5/7
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 11 times.
✓ Branch 7 taken 579 times.
590 for sub2 in listRest(rest) loop
7486 sub := sub2;
7487 nsub := match sub
7488 case DAE.WHOLEDIM() then sub;
7489 case DAE.SLICE()
7490 algorithm
7491 2 (exp,arg) := traverseExpTopDown(sub.exp, rel, arg);
7492
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 then if referenceEq(sub.exp, exp) then sub else DAE.SLICE(exp);
7493 case DAE.INDEX()
7494 algorithm
7495 3 (exp,arg) := traverseExpTopDown(sub.exp, rel, arg);
7496
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 then if referenceEq(sub.exp, exp) then sub else DAE.INDEX(exp);
7497 case DAE.WHOLE_NONEXP()
7498 algorithm
7499 ✗ (exp,arg) := traverseExpTopDown(sub.exp, rel, arg);
7500 ✗ then if referenceEq(sub.exp, exp) then sub else DAE.WHOLE_NONEXP(exp);
7501 end match;
7502 11 DoubleEnded.push_back(delst, nsub);
7503 end for;
7504 579 outSubscript := DoubleEnded.toListAndClear(delst);
7505 579 return;
7506 end if;
7507 20306299 nEq := nEq + 1;
7508 20306299 rest := listRest(rest);
7509 end while;
7510 end traverseExpTopDownSubs;
7511
7512 /***************************************************/
7513 /* Compare and Check DAE.Exp */
7514 /***************************************************/
7515
7516 public function operatorDivOrMul "returns true if operator is division or multiplication"
7517 input DAE.Operator op;
7518 output Boolean res;
7519 algorithm
7520 res := match op
7521 case DAE.MUL(_) then true;
7522 case DAE.DIV(_) then true;
7523 else false;
7524 end match;
7525 end operatorDivOrMul;
7526
7527 public function isRange
7528 "Returns true if expression is a range expression."
7529 input DAE.Exp inExp;
7530 output Boolean outBoolean;
7531 algorithm
7532 outBoolean := match inExp
7533 case DAE.RANGE() then true;
7534 else false;
7535 end match;
7536 end isRange;
7537
7538 public function isReduction
7539 input DAE.Exp inExp;
7540 output Boolean outBoolean;
7541 algorithm
7542 outBoolean := match inExp
7543 case DAE.REDUCTION() then true;
7544 else false;
7545 end match;
7546 end isReduction;
7547
7548 public function isOne
7549 "Returns true if an expression is constant
7550 and has the value one, otherwise false"
7551 input DAE.Exp inExp;
7552 output Boolean outBoolean;
7553 algorithm
7554 outBoolean := match inExp
7555 local
7556 Integer ival;
7557 Real rval;
7558 Boolean res;
7559 DAE.Exp e;
7560
7561 1 case DAE.ICONST(integer = ival) then intEq(ival,1);
7562 848032 case DAE.RCONST(real = rval) then realEq(rval,1.0);
7563 case DAE.CAST(exp = e)
7564 algorithm
7565 2252 res := isOne(e) "Casting to one is still one" ;
7566 then
7567 res;
7568 else false;
7569 end match;
7570 end isOne;
7571
7572 public function isZero
7573 "Returns true if an expression is constant
7574 and has the value zero, otherwise false"
7575 input DAE.Exp inExp;
7576 output Boolean outBoolean;
7577 algorithm
7578 outBoolean := match inExp
7579 local
7580 Integer ival;
7581 Real rval;
7582 DAE.Exp e;
7583 list<DAE.Exp> ae;
7584 list<list<DAE.Exp>> matrix;
7585
7586 case DAE.ICONST(integer = ival)
7587 353953 then intEq(ival,0);
7588
7589 case DAE.RCONST(real = rval)
7590 23264853 then realEq(rval,0.0);
7591
7592 case DAE.CAST(exp = e)
7593 353670 then isZero(e);
7594
7595 case DAE.UNARY(DAE.UMINUS(_),e)
7596 1563856 then isZero(e);
7597
7598 case DAE.ARRAY(array = ae)
7599 40761 then List.all(ae, isZero);
7600
7601 case DAE.MATRIX(matrix = matrix)
7602 72 then List.all(matrix, function List.all(inFunc = isZero));
7603
7604 case DAE.UNARY(DAE.UMINUS_ARR(_),e)
7605 175 then isZero(e);
7606
7607 else false;
7608
7609 end match;
7610 end isZero;
7611
7612
7613 public function isZeroOrAlmostZero
7614 "Returns true if an expression is constant
7615 and zero or near to zero, otherwise false"
7616 input DAE.Exp inExp;
7617 input DAE.Exp nominal = DAE.RCONST(1.0);
7618 output Boolean outBoolean;
7619 algorithm
7620 outBoolean := match (inExp, nominal)
7621 local
7622 Integer ival;
7623 Real rval;
7624 DAE.Exp e,e1;
7625 list<DAE.Exp> ae;
7626 list<list<DAE.Exp>> matrix;
7627 Real rNom;
7628
7629 case (DAE.ICONST(integer = ival),_)
7630 ✗ then intEq(ival,0);
7631
7632 case (DAE.RCONST(real = rval), DAE.RCONST(real=rNom))
7633 50479 then realLt(abs(rval),1e-6*abs(rNom));
7634
7635 case (DAE.RCONST(real = rval),_)
7636 311 then realLt(abs(rval),1e-6);
7637
7638 case (DAE.CAST(exp = e),_)
7639 110 then isZeroOrAlmostZero(e, nominal);
7640
7641 case (DAE.UNARY(DAE.UMINUS(_),e),_)
7642 17348 then isZeroOrAlmostZero(e, nominal);
7643
7644 case (DAE.ARRAY(array = ae),_)
7645 20 then List.all(ae, function isZeroOrAlmostZero(nominal = nominal));
7646
7647 case (DAE.MATRIX(matrix = matrix),_)
7648 ✗ then List.all(matrix, function List.all(inFunc = function isZeroOrAlmostZero(nominal = nominal)));
7649
7650 case (DAE.UNARY(DAE.UMINUS_ARR(_),e),_)
7651 ✗ then isZeroOrAlmostZero(e, nominal);
7652
7653 case (DAE.IFEXP(_,e,e1),_)
7654
3/4
✓ Branch 1 taken 1968 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 41 times.
✓ Branch 5 taken 1927 times.
1968 then (isZeroOrAlmostZero(e, nominal) or isZeroOrAlmostZero(e1, nominal));
7655
7656 else false;
7657
7658 end match;
7659 end isZeroOrAlmostZero;
7660
7661
7662 public function isPositiveOrZero
7663 "Returns true if an expression is known to be >= 0"
7664 input DAE.Exp inExp;
7665 output Boolean outBoolean;
7666 algorithm
7667 outBoolean := match inExp
7668 local
7669 Integer i;
7670 Real r;
7671 DAE.Exp e1, e2;
7672
7673 /* literals */
7674 13535 case DAE.ICONST(i) then i >= 0;
7675 71218 case DAE.RCONST(r) then r >= 0.0;
7676
7677 /* e1 + e2 */
7678 case DAE.BINARY(e1, DAE.ADD(), e2)
7679
4/4
✓ Branch 1 taken 16668 times.
✓ Branch 2 taken 24724 times.
✓ Branch 4 taken 16657 times.
✓ Branch 5 taken 11 times.
41392 then isPositiveOrZero(e1) and isPositiveOrZero(e2);
7680
7681 /* e1 - e2 */
7682 case DAE.BINARY(e1, DAE.SUB(), e2)
7683
3/4
✓ Branch 1 taken 37847 times.
✓ Branch 2 taken 85352 times.
✓ Branch 4 taken 37847 times.
✗ Branch 5 not taken.
123199 then isPositiveOrZero(e1) and isNegativeOrZero(e2);
7684
7685 /* e1 * e2 , -e1 * -e2, e ^ 2.0 */
7686 case DAE.BINARY(e1, DAE.MUL(), e2)
7687
9/10
✓ Branch 1 taken 253 times.
✓ Branch 2 taken 2208 times.
✓ Branch 4 taken 217 times.
✓ Branch 5 taken 36 times.
✓ Branch 7 taken 82 times.
✓ Branch 8 taken 2343 times.
✓ Branch 10 taken 82 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 21 times.
✓ Branch 14 taken 2404 times.
2461 then (isPositiveOrZero(e1) and isPositiveOrZero(e2)) or
7688 (isNegativeOrZero(e1) and isNegativeOrZero(e2)) or ExpressionBasics.expEqual(e1, e2);
7689
7690 /* e1 / e2, -e1 / -e2 */
7691 case DAE.BINARY(e1, DAE.DIV(), e2)
7692
7/8
✓ Branch 1 taken 117 times.
✓ Branch 2 taken 124 times.
✓ Branch 4 taken 114 times.
✓ Branch 5 taken 3 times.
✓ Branch 7 taken 1 time.
✓ Branch 8 taken 237 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1 time.
241 then (isPositiveOrZero(e1) and isPositiveOrZero(e2)) or
7693 (isNegativeOrZero(e1) and isNegativeOrZero(e2));
7694
7695 /* Integer power we can say something good about */
7696 774 case DAE.BINARY(e1, DAE.POW(), _) then isPositiveOrZero(e1);
7697 ✗ case DAE.BINARY(_, DAE.POW(), e2) then isEven(e2);
7698
7699 /* -(x) */
7700 3025 case DAE.UNARY(DAE.UMINUS(), e1) then isNegativeOrZero(e1);
7701
7702 /* builtin calls */
7703 case DAE.CALL(path = Absyn.IDENT("abs")) then true;
7704 case DAE.CALL(path = Absyn.IDENT("cosh")) then true;
7705 case DAE.CALL(path = Absyn.IDENT("exp")) then true;
7706 ✗ case DAE.CALL(path = Absyn.IDENT("sign"), expLst = {e1}) then isPositiveOrZero(e1);
7707 ✗ case DAE.CALL(path = Absyn.IDENT("sinh"), expLst = {e1}) then isPositiveOrZero(e1);
7708 ✗ case DAE.CALL(path = Absyn.IDENT("tanh"), expLst = {e1}) then isPositiveOrZero(e1);
7709 ✗ case DAE.CALL(path = Absyn.IDENT("ceil"), expLst = {e1}) then isPositiveOrZero(e1);
7710 ✗ case DAE.CALL(path = Absyn.IDENT("floor"), expLst = {e1}) then isPositiveOrZero(e1);
7711 ✗ case DAE.CALL(path = Absyn.IDENT("integer"), expLst = {e1}) then isPositiveOrZero(e1);
7712
7713 // TODO div, mod, rem, ...
7714
7715 169842 else isZero(inExp);
7716 end match;
7717 end isPositiveOrZero;
7718
7719 public function isNegativeOrZero
7720 "Returns true if an expression is known to be <= 0"
7721 input DAE.Exp inExp;
7722 output Boolean outBoolean;
7723 algorithm
7724 outBoolean := match inExp
7725 local
7726 Integer i;
7727 Real r;
7728 DAE.Exp e1, e2;
7729
7730 /* literals */
7731 510 case DAE.ICONST(i) then i <= 0;
7732 84590 case DAE.RCONST(r) then r <= 0.0;
7733
7734 /* e1 + e2 */
7735 case DAE.BINARY(e1, DAE.ADD(), e2)
7736
3/4
✓ Branch 1 taken 30998 times.
✓ Branch 2 taken 26190 times.
✓ Branch 4 taken 30998 times.
✗ Branch 5 not taken.
57188 then isNegativeOrZero(e1) and isNegativeOrZero(e2);
7737
7738 /* e1 - e2 */
7739 case DAE.BINARY(e1, DAE.SUB(), e2)
7740
3/4
✓ Branch 1 taken 2615 times.
✓ Branch 2 taken 125969 times.
✓ Branch 4 taken 2615 times.
✗ Branch 5 not taken.
128584 then isNegativeOrZero(e1) and isPositiveOrZero(e2);
7741
7742 /* e1 * e2 , -e1 * -e2, e ^ 2.0 */
7743 case DAE.BINARY(e1, DAE.MUL(), e2)
7744
6/8
✓ Branch 1 taken 10379 times.
✓ Branch 2 taken 4193 times.
✓ Branch 4 taken 10379 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✓ Branch 8 taken 14568 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 4 times.
14572 then (isPositiveOrZero(e1) and isNegativeOrZero(e2)) or
7745 (isNegativeOrZero(e1) and isPositiveOrZero(e2));
7746
7747 /* e1 / e2, -e1 / -e2 */
7748 case DAE.BINARY(e1, DAE.DIV(), e2)
7749
4/8
✓ Branch 1 taken 53 times.
✓ Branch 2 taken 6063 times.
✓ Branch 4 taken 53 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 6116 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
6116 then (isPositiveOrZero(e1) and isNegativeOrZero(e2)) or
7750 (isNegativeOrZero(e1) and isPositiveOrZero(e2));
7751
7752 /* Integer power we can say something good about */
7753
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 272 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
272 case DAE.BINARY(e1, DAE.POW(), e2) then isNegativeOrZero(e1) and isOdd(e2);
7754
7755 /* -(x) */
7756 6627 case DAE.UNARY(DAE.UMINUS(), e1) then isPositiveOrZero(e1);
7757
7758 /* builtin calls */
7759 9925 case DAE.CALL(path = Absyn.IDENT("abs"), expLst = {e1}) then isZero(e1);
7760 case DAE.CALL(path = Absyn.IDENT("cosh")) then false;
7761 case DAE.CALL(path = Absyn.IDENT("exp")) then false;
7762 ✗ case DAE.CALL(path = Absyn.IDENT("sign"), expLst = {e1}) then isNegativeOrZero(e1);
7763 ✗ case DAE.CALL(path = Absyn.IDENT("sinh"), expLst = {e1}) then isNegativeOrZero(e1);
7764 ✗ case DAE.CALL(path = Absyn.IDENT("tanh"), expLst = {e1}) then isNegativeOrZero(e1);
7765 ✗ case DAE.CALL(path = Absyn.IDENT("ceil"), expLst = {e1}) then isNegativeOrZero(e1);
7766 ✗ case DAE.CALL(path = Absyn.IDENT("floor"), expLst = {e1}) then isNegativeOrZero(e1);
7767 12 case DAE.CALL(path = Absyn.IDENT("integer"), expLst = {e1}) then isNegativeOrZero(e1);
7768
7769 // TODO div, mod, rem, ...
7770
7771 197995 else isZero(inExp);
7772 end match;
7773 end isNegativeOrZero;
7774
7775 public function isPositive
7776 "Returns true if an expression is known to be > 0"
7777 input DAE.Exp inExp;
7778 output Boolean outBoolean;
7779 algorithm
7780 outBoolean := match inExp
7781 local
7782 Integer i;
7783 Real r;
7784 DAE.Exp e1, e2;
7785
7786 /* literals */
7787 ✗ case DAE.ICONST(i) then i > 0;
7788 14 case DAE.RCONST(r) then r > 0.0;
7789
7790 /* e1 + e2 */
7791 case DAE.BINARY(e1, DAE.ADD(), e2)
7792 ✗ then (isPositive(e1) and isPositiveOrZero(e2)) or
7793 (isZero(e1) and isPositive(e2));
7794
7795 /* e1 - e2 */
7796 case DAE.BINARY(e1, DAE.SUB(), e2)
7797 ✗ then isPositive(e1) and isNegativeOrZero(e2) or
7798 (isZero(e1) and isNegative(e2));
7799
7800 /* e1 * e2 , -e1 * -e2, e ^ 2.0 */
7801 case DAE.BINARY(e1, DAE.MUL(), e2)
7802 ✗ then (isPositive(e1) and isPositive(e2)) or
7803 (isNegative(e1) and isNegative(e2));
7804
7805 /* e1 / e2, -e1 / -e2 */
7806 case DAE.BINARY(e1, DAE.DIV(), e2)
7807 ✗ then (isPositive(e1) and isPositive(e2)) or
7808 (isNegative(e1) and isNegative(e2));
7809
7810 /* Integer power we can say something good about */
7811 ✗ case DAE.BINARY(e1, DAE.POW(), _) then isPositive(e1);
7812
7813 /* -(x) */
7814 ✗ case DAE.UNARY(DAE.UMINUS(), e1) then isNegative(e1);
7815
7816 /* builtin calls */
7817 ✗ case DAE.CALL(path = Absyn.IDENT("abs"), expLst = {e1}) then isPositive(e1) or isNegative(e1);
7818 case DAE.CALL(path = Absyn.IDENT("cosh")) then true;
7819 case DAE.CALL(path = Absyn.IDENT("exp")) then true;
7820 ✗ case DAE.CALL(path = Absyn.IDENT("sign"), expLst = {e1}) then isPositive(e1);
7821 ✗ case DAE.CALL(path = Absyn.IDENT("sinh"), expLst = {e1}) then isPositive(e1);
7822 ✗ case DAE.CALL(path = Absyn.IDENT("tanh"), expLst = {e1}) then isPositive(e1);
7823 ✗ case DAE.CALL(path = Absyn.IDENT("ceil"), expLst = {e1}) then isPositive(e1);
7824
7825 // TODO div, mod, rem, ...
7826
7827 else false;
7828 end match;
7829 end isPositive;
7830
7831 public function isNegative
7832 "Returns true if an expression is known to be < 0"
7833 input DAE.Exp inExp;
7834 output Boolean outBoolean;
7835 algorithm
7836 outBoolean := match inExp
7837 local
7838 Integer i;
7839 Real r;
7840 DAE.Exp e1, e2;
7841
7842 /* literals */
7843 ✗ case DAE.ICONST(i) then i < 0;
7844 ✗ case DAE.RCONST(r) then r < 0.0;
7845
7846 /* e1 + e2 */
7847 case DAE.BINARY(e1, DAE.ADD(), e2)
7848 ✗ then (isNegative(e1) and isNegativeOrZero(e2)) or
7849 (isZero(e1) and isNegative(e2));
7850
7851 /* e1 - e2 */
7852 case DAE.BINARY(e1, DAE.SUB(), e2)
7853 ✗ then isNegative(e1) and isPositiveOrZero(e2) or
7854 (isZero(e1) and isPositive(e2));
7855
7856 /* e1 * e2 , -e1 * -e2, e ^ 2.0 */
7857 case DAE.BINARY(e1, DAE.MUL(), e2)
7858 ✗ then (isPositive(e1) and isNegative(e2)) or
7859 (isNegative(e1) and isPositive(e2));
7860
7861 /* e1 / e2, -e1 / -e2 */
7862 case DAE.BINARY(e1, DAE.DIV(), e2)
7863 ✗ then (isPositive(e1) and isNegative(e2)) or
7864 (isNegative(e1) and isPositive(e2));
7865
7866 /* Integer power we can say something good about */
7867 ✗ case DAE.BINARY(e1, DAE.POW(), e2) then isNegative(e1) and isOdd(e2);
7868
7869 /* -(x) */
7870 ✗ case DAE.UNARY(DAE.UMINUS(), e1) then isNegative(e1);
7871
7872 /* builtin calls */
7873 case DAE.CALL(path = Absyn.IDENT("abs")) then false;
7874 case DAE.CALL(path = Absyn.IDENT("cosh")) then false;
7875 case DAE.CALL(path = Absyn.IDENT("exp")) then false;
7876 ✗ case DAE.CALL(path = Absyn.IDENT("sign"), expLst = {e1}) then isNegative(e1);
7877 ✗ case DAE.CALL(path = Absyn.IDENT("sinh"), expLst = {e1}) then isNegative(e1);
7878 ✗ case DAE.CALL(path = Absyn.IDENT("tanh"), expLst = {e1}) then isNegative(e1);
7879 ✗ case DAE.CALL(path = Absyn.IDENT("floor"), expLst = {e1}) then isNegative(e1);
7880
7881 // TODO div, mod, rem, ...
7882
7883 else false;
7884 end match;
7885 end isNegative;
7886
7887 function isGreaterOrEqual
7888 input DAE.Exp exp1;
7889 input DAE.Exp exp2;
7890 output Boolean isGreaterOrEqual = isPositiveOrZero(ExpressionSimplify.simplify(expSub(exp1, exp2)));
7891 end isGreaterOrEqual;
7892
7893 public function isHalf
7894 "Returns true if an expression is 0.5"
7895 input DAE.Exp inExp;
7896 output Boolean outBoolean;
7897 algorithm
7898 outBoolean := match inExp
7899 local
7900 Real rval;
7901
7902 27602 case DAE.RCONST(real = rval) then realEq(rval,0.5);
7903 else false;
7904
7905 end match;
7906 end isHalf;
7907
7908 public function isAtomic
7909 input DAE.Exp inExp;
7910 output Boolean outBoolean;
7911 algorithm
7912 outBoolean := match inExp
7913 case DAE.CREF() then true;
7914 case DAE.CALL() then true;
7915 784 case DAE.ICONST() then inExp.integer >= 0;
7916 25547 case DAE.RCONST() then inExp.real > 0.0;
7917 else false;
7918 end match;
7919 end isAtomic;
7920
7921 public function isDeeperThan
7922 "Whether the expression tree is deeper than inDepth levels."
7923 input DAE.Exp inExp;
7924 input Integer inDepth;
7925 output Boolean outDeeper;
7926 algorithm
7927 outDeeper := match inExp
7928 case _ guard inDepth <= 0 then true;
7929
2/2
✓ Branch 1 taken 38 times.
✓ Branch 2 taken 2699266 times.
2699304 case DAE.BINARY() then if isDeeperThan(inExp.exp1, inDepth - 1) then true
7930 else isDeeperThan(inExp.exp2, inDepth - 1);
7931
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 77 times.
77 case DAE.LBINARY() then if isDeeperThan(inExp.exp1, inDepth - 1) then true
7932 else isDeeperThan(inExp.exp2, inDepth - 1);
7933
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1900 times.
1900 case DAE.RELATION() then if isDeeperThan(inExp.exp1, inDepth - 1) then true
7934 else isDeeperThan(inExp.exp2, inDepth - 1);
7935
2/4
✓ Branch 1 taken 4075 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4075 times.
✗ Branch 5 not taken.
4075 case DAE.IFEXP() then if isDeeperThan(inExp.expCond, inDepth - 1) then true
7936 elseif isDeeperThan(inExp.expThen, inDepth - 1) then true
7937 else isDeeperThan(inExp.expElse, inDepth - 1);
7938 83574 case DAE.UNARY() then isDeeperThan(inExp.exp, inDepth - 1);
7939 462 case DAE.LUNARY() then isDeeperThan(inExp.exp, inDepth - 1);
7940 9730 case DAE.CAST() then isDeeperThan(inExp.exp, inDepth - 1);
7941 else false;
7942 end match;
7943 end isDeeperThan;
7944
7945 public function isImpure "author: lochel
7946 Returns true if an expression contains an impure function call."
7947 input DAE.Exp inExp;
7948 output Boolean outBoolean;
7949 algorithm
7950 20976 outBoolean := isConst(inExp);
7951 20976 (_, outBoolean) := traverseExpTopDown(inExp, isImpureWork, false);
7952 end isImpure;
7953
7954 protected function isImpureWork "author: lochel"
7955 input DAE.Exp inExp;
7956 input Boolean isImpure;
7957 output DAE.Exp outExp;
7958 output Boolean cont;
7959 output Boolean outImpure;
7960 algorithm
7961 (outExp,cont,outImpure) := match (inExp,isImpure)
7962 case (_, true) then (inExp,true,true);
7963
7964 case (DAE.CALL(attr=DAE.CALL_ATTR(isImpure=true)), _)
7965 then (inExp,false,true);
7966
7967 // workaround for builtin functions that are impure, but not marked as impure
7968 case (DAE.CALL(path = Absyn.IDENT(name="alarm"), attr=DAE.CALL_ATTR(builtin=true)), _)
7969 then (inExp,false,true);
7970
7971 case (DAE.CALL(path = Absyn.IDENT(name="compareFilesAndMove"), attr=DAE.CALL_ATTR(builtin=true)), _)
7972 then (inExp,false,true);
7973
7974 case (DAE.CALL(path = Absyn.IDENT(name="delay"), attr=DAE.CALL_ATTR(builtin=true)), _)
7975 then (inExp,false,true);
7976
7977 case (DAE.CALL(path = Absyn.IDENT(name="initial"), attr=DAE.CALL_ATTR(builtin=true)), _)
7978 then (inExp,false,true);
7979
7980 case (DAE.CALL(path = Absyn.IDENT(name="print"), attr=DAE.CALL_ATTR(builtin=true)), _)
7981 then (inExp,false,true);
7982
7983 case (DAE.CALL(path = Absyn.IDENT(name="readFile"), attr=DAE.CALL_ATTR(builtin=true)), _)
7984 then (inExp,false,true);
7985
7986 case (DAE.CALL(path = Absyn.IDENT(name="sample"), attr=DAE.CALL_ATTR(builtin=true)), _)
7987 then (inExp,false,true);
7988
7989 case (DAE.CALL(path = Absyn.IDENT(name="system"), attr=DAE.CALL_ATTR(builtin=true)), _)
7990 then (inExp,false,true);
7991
7992 case (DAE.CALL(path = Absyn.IDENT(name="system_parallel"), attr=DAE.CALL_ATTR(builtin=true)), _)
7993 then (inExp,false,true);
7994
7995 case (DAE.CALL(path = Absyn.IDENT(name="terminal"), attr=DAE.CALL_ATTR(builtin=true)), _)
7996 then (inExp,false,true);
7997
7998 case (DAE.CALL(path = Absyn.IDENT(name="writeFile"), attr=DAE.CALL_ATTR(builtin=true)), _)
7999 then (inExp,false,true);
8000
8001 else (inExp,true,false);
8002 end match;
8003 end isImpureWork;
8004
8005
8006 public function containsRecordType
8007 " Returns true if an expression contains a record type."
8008 input DAE.Exp inExp;
8009 output Boolean isRec;
8010 algorithm
8011 9428 (_, isRec) := traverseExpTopDown(inExp, containsRecordTypeWork, false);
8012 end containsRecordType;
8013
8014 protected function containsRecordTypeWork
8015 input DAE.Exp inExp;
8016 input Boolean inRec;
8017 output DAE.Exp outExp = inExp;
8018 output Boolean cont = false;
8019 output Boolean outRec = inRec;
8020 algorithm
8021
2/2
✓ Branch 0 taken 42955 times.
✓ Branch 1 taken 1080 times.
44035 if not inRec then
8022 (outExp,cont,outRec) := matchcontinue inExp
8023 local
8024 DAE.Type ty;
8025 list<DAE.Exp> expLst;
8026 Boolean subRec;
8027 case DAE.RECORD()
8028 algorithm
8029 then (inExp,false,true);
8030 case DAE.CALL(expLst=expLst, attr=DAE.CALL_ATTR(ty=ty))
8031 algorithm
8032 2491 subRec := isRecordType(ty);
8033
2/2
✓ Branch 0 taken 2279 times.
✓ Branch 1 taken 212 times.
2491 if not subRec then
8034
2/2
✓ Branch 0 taken 4845 times.
✓ Branch 1 taken 1017 times.
5862 for exp in expLst loop
8035 4845 subRec := containsRecordType(exp);
8036
2/2
✓ Branch 0 taken 3583 times.
✓ Branch 1 taken 1262 times.
4845 if subRec then
8037 break;
8038 end if;
8039 end for;
8040 end if;
8041 2491 then (inExp,not subRec,subRec);
8042 else (inExp,true,false);
8043 end matchcontinue;
8044 end if;
8045 end containsRecordTypeWork;
8046
8047 public function isEvaluatedConst
8048 "Returns true if an expression is really a constant scalar value. no calls, casts, or something"
8049 input DAE.Exp inExp;
8050 output Boolean outBoolean;
8051 algorithm
8052 outBoolean := match inExp
8053 case DAE.ICONST() then true;
8054 case DAE.RCONST() then true;
8055 case DAE.BCONST() then true;
8056 case DAE.SCONST() then true;
8057 case DAE.ENUM_LITERAL() then true;
8058 else false;
8059 end match;
8060 end isEvaluatedConst;
8061
8062 public function getEvaluatedConstInteger
8063 "Returns the constant integer value, fails for incorrect types."
8064 input DAE.Exp inExp;
8065 output Integer val;
8066 algorithm
8067 val := match inExp
8068 local
8069 Integer integer;
8070 case DAE.ICONST(integer = integer)
8071 then integer;
8072 case DAE.RCONST()
8073 algorithm
8074
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 132730 times.
✓ Branch 3 taken 541 times.
✓ Branch 4 taken 132189 times.
132730 SOME(integer) := realExpIntLit(inExp);
8075 then integer;
8076 else fail();
8077 end match;
8078 end getEvaluatedConstInteger;
8079
8080 public function getEvaluatedConstReal
8081 "Returns the constant real value, fails for incorrect types."
8082 input DAE.Exp inExp;
8083 output Real val;
8084 algorithm
8085 val := match inExp
8086 local
8087 Real integer;
8088 ✗ case DAE.RCONST() then inExp.real;
8089 ✗ case DAE.ICONST() then intReal(inExp.integer);
8090 else fail();
8091 end match;
8092 end getEvaluatedConstReal;
8093
8094 public function isConst
8095 "Returns true if an expression is constant"
8096 input DAE.Exp inExp;
8097 output Boolean outBoolean;
8098 algorithm
8099 outBoolean := match inExp
8100 local
8101 Boolean res;
8102 DAE.Exp e,e1,e2;
8103 list<DAE.Exp> ae;
8104 list<list<DAE.Exp>> matrix;
8105 Absyn.Path path;
8106 list<DAE.Subscript> subs;
8107
8108 case DAE.ICONST() then true;
8109 case DAE.RCONST() then true;
8110 case DAE.BCONST() then true;
8111 case DAE.SCONST() then true;
8112 case DAE.ENUM_LITERAL() then true;
8113
8114 249186 case DAE.UNARY(exp = e) then isConst(e);
8115
8116 16315 case DAE.CAST(exp = e) then isConst(e);
8117
8118 case DAE.BINARY(e1,_,e2)
8119 algorithm
8120 9551698 res := isConst(e2);
8121
2/2
✓ Branch 0 taken 601188 times.
✓ Branch 1 taken 8950510 times.
9551698 then
8122 if res then isConst(e1) else false;
8123
8124 case DAE.IFEXP(e,e1,e2)
8125 algorithm
8126 46503 res := isConst(e2);
8127
2/2
✓ Branch 0 taken 17475 times.
✓ Branch 1 taken 29028 times.
46503 if res then
8128 17475 res := isConst(e1);
8129 end if;
8130
2/2
✓ Branch 0 taken 10815 times.
✓ Branch 1 taken 35688 times.
46503 then
8131 if res then isConst(e) else false;
8132
8133 case DAE.LBINARY(exp1=e1,exp2=e2)
8134 algorithm
8135 2261 res := isConst(e2);
8136
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2259 times.
2261 then
8137 if res then isConst(e1) else false;
8138
8139 2814 case DAE.LUNARY(exp=e) then isConst(e);
8140
8141 case DAE.RELATION(exp1=e1,exp2=e2)
8142 algorithm
8143 21314 res := isConst(e2);
8144
2/2
✓ Branch 0 taken 16922 times.
✓ Branch 1 taken 4392 times.
21314 then
8145 if res then isConst(e1) else false;
8146
8147 74530 case DAE.ARRAY(array = ae) then isConstWorkList(ae);
8148
8149 11792 case DAE.MATRIX(matrix = matrix) then isConstWorkListList(matrix);
8150
8151 case DAE.RANGE(start=e1,step=NONE(),stop=e2)
8152 algorithm
8153 4464 res := isConst(e2);
8154
2/2
✓ Branch 0 taken 3375 times.
✓ Branch 1 taken 1089 times.
4464 then
8155 if res then isConst(e1) else false;
8156
8157 case DAE.RANGE(start=e,step=SOME(e1),stop=e2)
8158 algorithm
8159 11 res := isConst(e2);
8160
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 4 times.
11 if res then
8161 7 res := isConst(e1);
8162 end if;
8163
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 4 times.
11 then
8164 if res then isConst(e) else false;
8165
8166 455 case DAE.PARTEVALFUNCTION(expList = ae) then isConstWorkList(ae);
8167
8168 517 case DAE.TUPLE(PR = ae) then isConstWorkList(ae);
8169
8170 case DAE.ASUB(exp=e,sub=subs)
8171 algorithm
8172
4/4
✓ Branch 0 taken 5429 times.
✓ Branch 1 taken 5400 times.
✓ Branch 2 taken 5429 times.
✓ Branch 3 taken 5400 times.
10829 ae := list(Expression.getSubscriptExp(sub) for sub in subs);
8173 5400 res := isConst(e);
8174
2/2
✓ Branch 0 taken 1766 times.
✓ Branch 1 taken 3634 times.
5400 then
8175 if res then isConstWorkList(ae) else false;
8176
8177 36 case DAE.TSUB(exp=e) then isConst(e);
8178
8179 1 case DAE.SIZE(exp=e,sz=NONE()) then isConst(e);
8180
8181 case DAE.SIZE(exp=e1,sz=SOME(e2))
8182 algorithm
8183 1158 res := isConst(e2);
8184
1/2
✓ Branch 0 taken 1158 times.
✗ Branch 1 not taken.
1158 then
8185 if res then isConst(e1) else false;
8186
8187 167380 case DAE.CALL(expLst=ae, attr=DAE.CALL_ATTR(builtin=false, isImpure=false)) then isConstWorkList(ae);
8188
2/2
✓ Branch 2 taken 167216 times.
✓ Branch 3 taken 731 times.
167947 case DAE.CALL(path=path, expLst=ae, attr=DAE.CALL_ATTR(builtin=true)) then
8189 if listMember(AbsynUtil.pathFirstIdent(path),
8190 {"initial","terminal","sample" /* der/edge/change/pre belongs to this list usually, but if we optimize the expression, we might end up with pre of a constant expression... */}
8191 ) then false else isConstWorkList(ae);
8192
8193 25254 case DAE.RECORD(exps=ae) then isConstWorkList(ae);
8194
8195 /*TODO:Make this work for multiple iters, guard exps*/
8196 case DAE.REDUCTION(expr=e1,iterators={DAE.REDUCTIONITER(exp=e2)})
8197 algorithm
8198 854 res := isConst(e2);
8199
2/2
✓ Branch 0 taken 245 times.
✓ Branch 1 taken 609 times.
854 then
8200 if res then isConst(e1) else false;
8201
8202 1256 case DAE.BOX(exp=e) then isConst(e);
8203
8204 else false;
8205 end match;
8206 end isConst;
8207
8208 protected function isConstValueWork
8209 "Returns true if an expression is a constant value"
8210 input DAE.Exp inExp;
8211 output Boolean outBoolean;
8212 algorithm
8213 outBoolean := match inExp
8214 local
8215 list<DAE.Exp> ae;
8216 list<list<DAE.Exp>> matrix;
8217
8218 case DAE.ICONST() then true;
8219 case DAE.RCONST() then true;
8220 case DAE.BCONST() then true;
8221 case DAE.SCONST() then true;
8222 case DAE.ENUM_LITERAL() then true;
8223 47760 case DAE.ARRAY(array = ae) then isConstValueWorkList(ae);
8224 1072 case DAE.MATRIX(matrix = matrix) then isConstValueWorkListList(matrix);
8225 case DAE.RECORD() then true;
8226 case DAE.METARECORDCALL() then true;
8227 else false;
8228
8229 end match;
8230 end isConstValueWork;
8231
8232 public function isConstValue
8233 "Returns true if an expression is a constant value (not a composite operation)"
8234 input DAE.Exp inExp;
8235 output Boolean outBoolean;
8236 algorithm
8237 110011687 outBoolean := isConstValueWork(inExp);
8238 end isConstValue;
8239
8240 public function isConstWorkList
8241 "Returns true if a list of expressions is constant"
8242 input list<DAE.Exp> inExps;
8243 output Boolean outBoolean;
8244 protected
8245 DAE.Exp e;
8246 list<DAE.Exp> exps;
8247 Boolean b = true;
8248 algorithm
8249 exps := inExps;
8250
4/4
✓ Branch 0 taken 2534336 times.
✓ Branch 1 taken 1903776 times.
✓ Branch 2 taken 2417608 times.
✓ Branch 3 taken 116728 times.
4438112 while b and not listEmpty(exps) loop
8251 2417608 e::exps := exps;
8252 2417608 b := isConst(e);
8253 end while;
8254 outBoolean := b;
8255 end isConstWorkList;
8256
8257 protected function isConstWorkListList
8258 input list<list<DAE.Exp>> inExps;
8259 output Boolean outIsConst;
8260 protected
8261 list<DAE.Exp> e;
8262 list<list<DAE.Exp>> exps;
8263 Boolean b = true;
8264 algorithm
8265 exps := inExps;
8266
4/4
✓ Branch 0 taken 31475 times.
✓ Branch 1 taken 5451 times.
✓ Branch 2 taken 25134 times.
✓ Branch 3 taken 6341 times.
36926 while b and not listEmpty(exps) loop
8267 25134 e::exps := exps;
8268 25134 b := isConstWorkList(e);
8269 end while;
8270 outIsConst := b;
8271 end isConstWorkListList;
8272
8273 protected function isConstValueWorkList
8274 "Returns true if a list of expressions is a constant value"
8275 input list<DAE.Exp> inExps;
8276 output Boolean outBoolean;
8277 protected
8278 DAE.Exp e;
8279 list<DAE.Exp> exps;
8280 Boolean b = true;
8281 algorithm
8282 exps := inExps;
8283
4/4
✓ Branch 0 taken 68639 times.
✓ Branch 1 taken 43229 times.
✓ Branch 2 taken 62639 times.
✓ Branch 3 taken 6000 times.
111868 while b and not listEmpty(exps) loop
8284 62639 e::exps := exps;
8285 62639 b := isConstValueWork(e);
8286 end while;
8287 outBoolean := b;
8288 end isConstValueWorkList;
8289
8290 protected function isConstValueWorkListList
8291 input list<list<DAE.Exp>> inExps;
8292 output Boolean outIsConst;
8293 protected
8294 list<DAE.Exp> e;
8295 list<list<DAE.Exp>> exps;
8296 Boolean b = true;
8297 algorithm
8298 exps := inExps;
8299
4/4
✓ Branch 0 taken 1788 times.
✓ Branch 1 taken 753 times.
✓ Branch 2 taken 1469 times.
✓ Branch 3 taken 319 times.
2541 while b and not listEmpty(exps) loop
8300 1469 e::exps := exps;
8301 1469 b := isConstValueWorkList(e);
8302 end while;
8303 outIsConst := b;
8304 end isConstValueWorkListList;
8305
8306 public function isNotConst
8307 "author: PA
8308 Check if expression is not constant."
8309 input DAE.Exp e;
8310 output Boolean nb;
8311 protected
8312 Boolean b;
8313 algorithm
8314 4176 b := isConst(e);
8315 4176 nb := boolNot(b);
8316 end isNotConst;
8317
8318 public function isRelation "Returns true if expression is a relation"
8319 input DAE.Exp inExp;
8320 output Boolean outBoolean;
8321 algorithm
8322 outBoolean := match inExp
8323 case DAE.RELATION() then true;
8324 else false;
8325 end match;
8326 end isRelation;
8327
8328 public function isEventTriggeringFunctionExp
8329 input DAE.Exp inExp;
8330 output Boolean outB;
8331 algorithm
8332 outB := match inExp
8333 case DAE.CALL(path = Absyn.IDENT("div")) then true;
8334 case DAE.CALL(path = Absyn.IDENT("mod")) then true;
8335 case DAE.CALL(path = Absyn.IDENT("rem")) then true;
8336 case DAE.CALL(path = Absyn.IDENT("ceil")) then true;
8337 case DAE.CALL(path = Absyn.IDENT("floor")) then true;
8338 case DAE.CALL(path = Absyn.IDENT("integer")) then true;
8339 else false;
8340 end match;
8341 end isEventTriggeringFunctionExp;
8342
8343 public function isAddOrSub "returns true if operator is ADD or SUB"
8344 input DAE.Operator op;
8345 output Boolean res;
8346 algorithm
8347
4/4
✓ Branch 1 taken 11666738 times.
✓ Branch 2 taken 7379880 times.
✓ Branch 4 taken 1614366 times.
✓ Branch 5 taken 10052372 times.
19046618 res := isAdd(op) or isSub(op);
8348 end isAddOrSub;
8349
8350 public function isAdd "returns true if operator is ADD"
8351 input DAE.Operator op;
8352 output Boolean res;
8353 algorithm
8354 res := match op
8355 case DAE.ADD() then true;
8356 case DAE.ADD_ARR() then true;
8357 else false;
8358 end match;
8359 end isAdd;
8360
8361 public function isSub "returns true if operator is SUB"
8362 input DAE.Operator op;
8363 output Boolean res;
8364 algorithm
8365 res := match op
8366 case DAE.SUB() then true;
8367 case DAE.SUB_ARR() then true;
8368 else false;
8369 end match;
8370 end isSub;
8371
8372 public function isAddOrSubBinary "returns true if BINARY is a+b or a-b"
8373 input DAE.Exp iExp;
8374 output Boolean res;
8375 protected
8376 DAE.Operator op;
8377 algorithm
8378 res := match iExp
8379 ✗ case DAE.BINARY(_,op,_) then isAddOrSub(op);
8380 else false;
8381 end match;
8382 end isAddOrSubBinary;
8383
8384 public function isMulOrDiv "returns true if operator is MUL or DIV"
8385 input DAE.Operator op;
8386 output Boolean res = isMul(op) or isDiv(op);
8387 end isMulOrDiv;
8388
8389 public function isMul "returns true if operator is MUL"
8390 input DAE.Operator op;
8391 output Boolean res;
8392 algorithm
8393 res := match op
8394 case DAE.MUL() then true;
8395 case DAE.MUL_ARR() then true;
8396 else false;
8397 end match;
8398 end isMul;
8399
8400 public function isDiv "returns true if operator is DIV"
8401 input DAE.Operator op;
8402 output Boolean res;
8403 algorithm
8404 res := match op
8405 case DAE.DIV() then true;
8406 case DAE.DIV_ARR() then true;
8407 else false;
8408 end match;
8409 end isDiv;
8410
8411 public function isDivBinary "returns true if BINARY is a/b"
8412 input DAE.Exp iExp;
8413 output Boolean res;
8414 protected
8415 DAE.Operator op;
8416 algorithm
8417 res := match iExp
8418 20877 case DAE.BINARY(_,op,_) then isDiv(op);
8419 else false;
8420 end match;
8421 end isDivBinary;
8422
8423
8424 public function isMulorDivBinary "returns true if BINARY is a/b or a*b"
8425 input DAE.Exp iExp;
8426 output Boolean res;
8427 protected
8428 DAE.Operator op;
8429 algorithm
8430 res := match iExp
8431 ✗ case DAE.BINARY(_,op,_) then isMulOrDiv(op);
8432 else false;
8433 end match;
8434 end isMulorDivBinary;
8435
8436 public function isPow "returns true if operator is POW"
8437 input DAE.Operator op;
8438 output Boolean res;
8439 algorithm
8440 res := match op
8441 case DAE.POW() then true;
8442 else false;
8443 end match;
8444 end isPow;
8445
8446
8447 public function isFunCall "return true if expression is DAE.CALL(path=Absyn.IDENT(name))"
8448 input DAE.Exp iExp;
8449 input String name;
8450 output Boolean res;
8451 algorithm
8452 res := match iExp
8453 local String name_;
8454
4/4
✓ Branch 0 taken 1616 times.
✓ Branch 1 taken 3618 times.
✓ Branch 3 taken 812 times.
✓ Branch 4 taken 804 times.
5234 case DAE.CALL(path=Absyn.IDENT(name_)) then name_ == name;
8455 else false;
8456 end match;
8457 end isFunCall;
8458
8459 public function equalTypes ""
8460 input DAE.Type t1,t2;
8461 output Boolean b;
8462 algorithm b := matchcontinue(t1,t2)
8463 local
8464 list<DAE.Var> vars1,vars2;
8465 Type ty1,ty2;
8466 DAE.Dimensions ad1,ad2;
8467 list<Integer> li1,li2;
8468
8469 case(DAE.T_INTEGER(),DAE.T_INTEGER()) then true;
8470 case(DAE.T_REAL(),DAE.T_REAL()) then true;
8471 case(DAE.T_STRING(),DAE.T_STRING()) then true;
8472 case(DAE.T_BOOL(),DAE.T_BOOL()) then true;
8473 // BTH
8474 case(DAE.T_CLOCK(),DAE.T_CLOCK()) then true;
8475
8476 case(DAE.T_COMPLEX(varLst = vars1), DAE.T_COMPLEX(varLst = vars2))
8477 ✗ then equalTypesComplexVars(vars1,vars2);
8478
8479 case(DAE.T_ARRAY(ty1,ad1),DAE.T_ARRAY(ty2,ad2))
8480 algorithm
8481 ✗ li1 := List.map(ad1, dimensionSize);
8482 ✗ li2 := List.map(ad2, dimensionSize);
8483 ✗ true := List.isEqualOnTrue(li1,li2,intEq);
8484 ✗ true := equalTypes(ty1,ty2);
8485 then
8486 true;
8487 else false;
8488 end matchcontinue;
8489 end equalTypes;
8490
8491 protected function equalTypesComplexVars ""
8492 input list<DAE.Var> inVars1,inVars2;
8493 output Boolean b;
8494 algorithm
8495 b := matchcontinue(inVars1,inVars2)
8496 local
8497 DAE.Type t1,t2;
8498 String s1,s2;
8499 list<DAE.Var> vars1,vars2;
8500
8501 case({},{}) then true;
8502
8503 case(DAE.TYPES_VAR(name = s1, ty = t1)::vars1,DAE.TYPES_VAR(name = s2, ty = t2)::vars2)
8504 algorithm
8505 //print(" verify subvars: " + s1 + " and " + s2 + " to go: " + intString(listLength(vars1)) + " , " + intString(listLength(vars2)) + "\n");
8506 ✗ true := stringEq(s1,s2);
8507 //print(" types: " + TypesDump.unparseType(t1) + " and " + TypesDump.unparseType(t2) + "\n");
8508 ✗ true := equalTypes(t1,t2);
8509 //print(s1 + " and " + s2 + " EQUAL \n\n");
8510 ✗ then
8511 equalTypesComplexVars(vars1,vars2);
8512
8513 else false;
8514 end matchcontinue;
8515 end equalTypesComplexVars;
8516
8517 public function typeBuiltin
8518 "Returns true if type is one of the builtin types."
8519 input DAE.Type inType;
8520 output Boolean outBoolean;
8521 algorithm
8522 outBoolean := match inType
8523 case DAE.T_INTEGER() then true;
8524 case DAE.T_REAL() then true;
8525 case DAE.T_STRING() then true;
8526 case DAE.T_BOOL() then true;
8527 // BTH
8528 case DAE.T_CLOCK() then true;
8529 else false;
8530 end match;
8531 end typeBuiltin;
8532
8533 public function isWholeDim ""
8534 input DAE.Subscript s;
8535 output Boolean b;
8536 algorithm
8537 b := match s
8538 case DAE.WHOLEDIM() then true;
8539 else false;
8540 end match;
8541 end isWholeDim;
8542
8543 public function isInt ""
8544 input DAE.Type it;
8545 output Boolean re;
8546 algorithm
8547 re := match it
8548 local
8549 Type t1;
8550 case DAE.T_INTEGER() then true;
8551 ✗ case DAE.T_ARRAY(ty=t1) then isInt(t1);
8552 else false;
8553 end match;
8554 end isInt;
8555
8556 public function isReal ""
8557 input DAE.Type it;
8558 output Boolean re;
8559 algorithm
8560 re := match it
8561 local
8562 Type t1;
8563 case DAE.T_REAL() then true;
8564 ✗ case DAE.T_ARRAY(ty=t1) then isReal(t1);
8565 else false;
8566 end match;
8567 end isReal;
8568
8569 public function isExpReal ""
8570 input DAE.Exp e;
8571 output Boolean re;
8572 algorithm
8573 ✗ re := isReal(typeof(e));
8574 end isExpReal;
8575
8576 public function isConstZeroLength
8577 "Return true if expression has zero-dimension"
8578 input DAE.Exp inExp;
8579 output Boolean outBoolean;
8580 algorithm
8581 outBoolean := match inExp
8582 case DAE.ARRAY(array={}) then true;
8583 case DAE.MATRIX(matrix={}) then true;
8584 else false;
8585 end match;
8586 end isConstZeroLength;
8587
8588 public function isConstFalse
8589 "Return true if expression is false"
8590 input DAE.Exp inExp;
8591 output Boolean outBoolean;
8592 algorithm
8593 outBoolean := match inExp
8594 case DAE.BCONST(false) then true;
8595 else false;
8596 end match;
8597 end isConstFalse;
8598
8599 public function isConstTrue
8600 "Return true if expression is true"
8601 input DAE.Exp inExp;
8602 output Boolean outBoolean;
8603 algorithm
8604 outBoolean := match inExp
8605 case DAE.BCONST(true) then true;
8606 else false;
8607 end match;
8608 end isConstTrue;
8609
8610 public function isConstOne
8611 "Return true if expression is 1"
8612 input DAE.Exp inExp;
8613 output Boolean outBoolean;
8614 algorithm
8615 outBoolean := match inExp
8616 local Real rval; Integer ival;
8617
8618 // constant real 1.0
8619 9180174 case DAE.RCONST(rval) then realEq(rval, 1.0);
8620 // constant integer 1
8621 2999 case DAE.ICONST(ival) then intEq(ival, 1);
8622 // anything else
8623 else false;
8624 end match;
8625 end isConstOne;
8626
8627 public function isConstMinusOne
8628 "Return true if expression is -1"
8629 input DAE.Exp inExp;
8630 output Boolean outBoolean;
8631 algorithm
8632 outBoolean := match inExp
8633 local Real rval; Integer ival;
8634
8635 // is real -1.0
8636 8234698 case DAE.RCONST(rval) then realEq(rval, -1.0);
8637 // is integer -1
8638 2977 case DAE.ICONST(ival) then intEq(ival, -1);
8639 // anything else
8640 else false;
8641 end match;
8642 end isConstMinusOne;
8643
8644
8645 public function isGreatereqOrLesseq
8646 input DAE.Operator op;
8647 output Boolean b;
8648 algorithm
8649 b := match op
8650 case DAE.GREATEREQ() then true;
8651 case DAE.LESSEQ() then true;
8652 else false;
8653 end match;
8654 end isGreatereqOrLesseq;
8655
8656 public function isLesseqOrLess
8657 input DAE.Operator op;
8658 output Boolean b;
8659 algorithm
8660 b := match op
8661 case DAE.LESS() then true;
8662 case DAE.LESSEQ() then true;
8663 else false;
8664 end match;
8665 end isLesseqOrLess;
8666
8667
8668 public function containVectorFunctioncall
8669 "Returns true if expression or subexpression is a
8670 functioncall that returns an array, otherwise false.
8671 Note: the der operator is represented as a
8672 function call but still return false."
8673 input DAE.Exp inExp;
8674 output Boolean outBoolean;
8675 algorithm
8676 outBoolean := match inExp
8677 local
8678 DAE.Exp e1,e2,e,e3;
8679 Boolean res;
8680 list<DAE.Exp> elst,flatexplst;
8681 list<list<DAE.Exp>> explst;
8682
8683 // der is not a vector function
8684 case DAE.CALL(path = Absyn.IDENT(name = "der")) then false;
8685
8686 // pre is not a vector function, adrpo: 2009-03-03 -> pre is also needed here!
8687 case DAE.CALL(path = Absyn.IDENT(name = "pre")) then false;
8688 case DAE.CALL(path = Absyn.IDENT(name = "previous")) then false;
8689 // inStream and actualStream are not a vector function, adrpo: 2010-08-31 -> they are also needed here!
8690 case DAE.CALL(path = Absyn.IDENT(name = "inStream")) then false;
8691 case DAE.CALL(path = Absyn.IDENT(name = "actualStream")) then false;
8692
8693 // a call that has an return array type returns true
8694 case DAE.CALL(attr = DAE.CALL_ATTR(ty = DAE.T_ARRAY())) then true;
8695
8696 // any other call returns false
8697 case DAE.CALL() then false;
8698
8699 // partial evaluation
8700 case DAE.PARTEVALFUNCTION(expList = elst) // stefan
8701 ✗ then
8702 List.any(elst,containVectorFunctioncall);
8703
8704 // binary operators, e1 has a vector function call
8705 case DAE.BINARY(exp1 = e1) guard containVectorFunctioncall(e1)
8706 then
8707 true;
8708 // binary operators, e2 has a vector function call
8709 case DAE.BINARY(exp2 = e2) guard containVectorFunctioncall(e2)
8710 then
8711 true;
8712 // unary operators
8713 case DAE.UNARY(exp = e)
8714 513 then
8715 containVectorFunctioncall(e);
8716 // logical binary operators, e1 is a vector call
8717 case DAE.LBINARY(exp1 = e1) guard containVectorFunctioncall(e1)
8718 then
8719 true;
8720 // logical binary operators, e2 is a vector call
8721 case DAE.LBINARY(exp2 = e2) guard containVectorFunctioncall(e2)
8722 then
8723 true;
8724 // logical unary operators, e is a vector call
8725 case DAE.LUNARY(exp = e)
8726 ✗ then
8727 containVectorFunctioncall(e);
8728 // relations e1 op e2, where e1 is a vector call
8729 case DAE.RELATION(exp1 = e1) guard containVectorFunctioncall(e1)
8730 then
8731 true;
8732 // relations e1 op e2, where e2 is a vector call
8733 case DAE.RELATION(exp2 = e2) guard containVectorFunctioncall(e2)
8734 then
8735 true;
8736 // if expression where the condition is a vector call
8737 case DAE.IFEXP(expCond = e1) guard containVectorFunctioncall(e1)
8738 then
8739 true;
8740 // if expression where the then part is a vector call
8741 case DAE.IFEXP(expThen = e2) guard containVectorFunctioncall(e2)
8742 then
8743 true;
8744 // if expression where the else part is a vector call
8745 case DAE.IFEXP(expElse = e3) guard containVectorFunctioncall(e3)
8746 then
8747 true;
8748 // arrays
8749 case DAE.ARRAY(array = elst)
8750 9784 then
8751 List.any(elst, containVectorFunctioncall);
8752 // matrices
8753 case DAE.MATRIX(matrix = explst)
8754 algorithm
8755 155 flatexplst := List.flatten(explst);
8756 155 res := List.any(flatexplst, containVectorFunctioncall);
8757 then
8758 res;
8759 // ranges [e1:step:e2], where e1 is a vector call
8760 case DAE.RANGE(start = e1) guard containVectorFunctioncall(e1)
8761 then
8762 true;
8763 // ranges [e1:step:e2], where e2 is a vector call
8764 case DAE.RANGE(stop = e2) guard containVectorFunctioncall(e2)
8765 then
8766 true;
8767 // ranges [e1:step:e2], where step is a vector call
8768 case DAE.RANGE(step = SOME(e)) guard containVectorFunctioncall(e)
8769 then
8770 true;
8771 // tuples return true all the time???!! adrpo: FIXME! TODO! is this really true?
8772 case DAE.TUPLE(PR = elst)
8773 ✗ then
8774 List.any(elst, containVectorFunctioncall);
8775 // cast
8776 case DAE.CAST(exp = e)
8777 3 then
8778 containVectorFunctioncall(e);
8779 // size operator
8780 case DAE.SIZE(exp = e1) guard containVectorFunctioncall(e1)
8781 then
8782 true;
8783 // size operator
8784 case DAE.SIZE(sz = SOME(e2)) guard containVectorFunctioncall(e2)
8785 then
8786 true;
8787 // any other expressions return false
8788 else false;
8789 end match;
8790 end containVectorFunctioncall;
8791
8792 public function containFunctioncall
8793 "Returns true if expression or subexpression
8794 is a functioncall, otherwise false.
8795 Note: the der and pre operators are represented
8796 as function calls but still returns false."
8797 input DAE.Exp inExp;
8798 output Boolean outBoolean;
8799 algorithm
8800 outBoolean := match inExp
8801 local
8802 DAE.Exp e1,e2,e,e3;
8803 Boolean res;
8804 list<DAE.Exp> elst,flatexplst;
8805 list<list<DAE.Exp>> explst;
8806
8807 // der(x) is not a function call
8808 case DAE.CALL(path = Absyn.IDENT(name = "der")) then false;
8809
8810 // pre(x) is not a function call
8811 case DAE.CALL(path = Absyn.IDENT(name = "pre")) then false;
8812
8813 case DAE.CALL(path = Absyn.IDENT(name = "previous")) then false;
8814
8815 // any other call is a function call
8816 case DAE.CALL() then true;
8817
8818 // partial evaluation functions
8819 case DAE.PARTEVALFUNCTION(expList = elst) // stefan
8820 algorithm
8821 ✗ res := List.any(elst,containFunctioncall);
8822 then
8823 res;
8824
8825 // binary
8826 case DAE.BINARY(exp1 = e1) guard containFunctioncall(e1)
8827 then
8828 true;
8829
8830 case DAE.BINARY(exp2 = e2) guard containFunctioncall(e2)
8831 then
8832 true;
8833
8834 // unary
8835 case DAE.UNARY(exp = e)
8836 11034 then
8837 containFunctioncall(e);
8838
8839 // logical binary
8840 case DAE.LBINARY(exp1 = e1) guard containFunctioncall(e1)
8841 then
8842 true;
8843
8844 case DAE.LBINARY(exp2 = e2) guard containFunctioncall(e2)
8845 then
8846 true;
8847
8848 // logical unary
8849 case DAE.LUNARY(exp = e)
8850 970 then
8851 containFunctioncall(e);
8852
8853 // relations
8854 case DAE.RELATION(exp1 = e1) guard containFunctioncall(e1)
8855 then
8856 true;
8857
8858 case DAE.RELATION(exp2 = e2) guard containFunctioncall(e2)
8859 then
8860 true;
8861
8862 // if expressions
8863 case DAE.IFEXP(expCond = e1) guard containFunctioncall(e1)
8864 then
8865 true;
8866
8867 case DAE.IFEXP(expThen = e2) guard containFunctioncall(e2)
8868 then
8869 true;
8870
8871 case DAE.IFEXP(expElse = e3) guard containFunctioncall(e3)
8872 then
8873 true;
8874
8875 // arrays
8876 case DAE.ARRAY(array = elst)
8877 6134 then
8878 List.any(elst, containFunctioncall);
8879
8880 // matrix
8881 case DAE.MATRIX(matrix = explst)
8882 algorithm
8883 65 flatexplst := List.flatten(explst);
8884 65 res := List.any(flatexplst, containFunctioncall);
8885 then
8886 res;
8887
8888 // ranges
8889 case DAE.RANGE(start = e1) guard containFunctioncall(e1)
8890 then
8891 true;
8892
8893 case DAE.RANGE(stop = e2) guard containFunctioncall(e2)
8894 then
8895 true;
8896
8897 case DAE.RANGE(step = SOME(e)) guard containFunctioncall(e)
8898 then
8899 true;
8900
8901 // tuples return true all the time???!! adrpo: FIXME! TODO! is this really true?
8902 case DAE.TUPLE(PR = elst)
8903 174 then
8904 List.any(elst, containVectorFunctioncall);
8905
8906 // cast
8907 case DAE.CAST(exp = e)
8908 520 then
8909 containFunctioncall(e);
8910
8911 // asub
8912 case DAE.ASUB(exp = e)
8913 4132 then
8914 containFunctioncall(e);
8915
8916 // size
8917 case DAE.SIZE(exp = e1) guard containFunctioncall(e1)
8918 then
8919 true;
8920
8921 case DAE.SIZE(sz = SOME(e2)) guard containFunctioncall(e2)
8922 then
8923 true;
8924
8925 // anything else
8926 else false;
8927
8928 end match;
8929 end containFunctioncall;
8930
8931 public function expIntOrder "Function: expIntOrder
8932 This function takes a list of Exp, assumes they are all ICONST
8933 and checks wheter the ICONST are in order."
8934 input Integer expectedValue;
8935 input list<DAE.Exp> integers;
8936 output Boolean ob;
8937 algorithm
8938 ob := match(expectedValue,integers)
8939 local
8940 list<DAE.Exp> expl;
8941 Integer x1,x2;
8942 case(_,{}) then true;
8943 case(x1, DAE.ICONST(x2)::expl) guard intEq(x1, x2)
8944 ✗ then
8945 expIntOrder(x1+1,expl);
8946 else false;
8947 end match;
8948 end expIntOrder;
8949
8950 public function isArray "returns true if expression is an array.
8951 "
8952 input DAE.Exp inExp;
8953 output Boolean outB;
8954 algorithm
8955 outB := match inExp
8956 case DAE.ARRAY() then true;
8957 case DAE.UNARY(operator=DAE.UMINUS_ARR(),exp=DAE.ARRAY()) then true;
8958 else false;
8959 end match;
8960 end isArray;
8961
8962 public function isMetaArray "returns true if expression is a MM array."
8963 input DAE.Exp inExp;
8964 output Boolean outB;
8965 algorithm
8966 221 outB := Types.isMetaArray(typeof(inExp));
8967 end isMetaArray;
8968
8969 public function isMatrix "returns true if expression is an matrix.
8970 "
8971 input DAE.Exp inExp;
8972 output Boolean outB;
8973 algorithm
8974 outB := match inExp
8975 case DAE.MATRIX() then true;
8976 case DAE.UNARY(operator=DAE.UMINUS_ARR(),exp=DAE.MATRIX()) then true;
8977 else false;
8978 end match;
8979 end isMatrix;
8980
8981 public function isVector
8982 "Returns true if the expression is a vector, i.e. an array with one dimension,
8983 otherwise false."
8984 input DAE.Exp inExp;
8985 output Boolean outIsVector;
8986 algorithm
8987 outIsVector := match inExp
8988 // Nested arrays are not vectors.
8989 case DAE.ARRAY(ty = DAE.T_ARRAY(ty = DAE.T_ARRAY())) then false;
8990 // Non-nested array with one dimension is a vector.
8991 case DAE.ARRAY(ty = DAE.T_ARRAY(dims = {_})) then true;
8992 else false;
8993 end match;
8994 end isVector;
8995
8996 public function isUnary
8997 "Returns true if expression is an unary."
8998 input DAE.Exp inExp;
8999 output Boolean outB;
9000 algorithm
9001 outB:= match inExp
9002 case DAE.UNARY() then true;
9003 else false;
9004 end match;
9005 end isUnary;
9006
9007 public function isBinary
9008 "Returns true if expression is an binary."
9009 input DAE.Exp inExp;
9010 output Boolean outB;
9011 algorithm
9012 outB:= match inExp
9013 case DAE.BINARY() then true;
9014 else false;
9015 end match;
9016 end isBinary;
9017
9018 public function isNegativeUnary
9019 "Returns true if expression is a negative unary."
9020 input DAE.Exp inExp;
9021 output Boolean outB;
9022 algorithm
9023 outB:= match inExp
9024 case DAE.UNARY(operator=DAE.UMINUS()) then true;
9025 else false;
9026 end match;
9027 end isNegativeUnary;
9028
9029 public function isCref
9030 "Returns true if the given expression is a component reference,
9031 otherwise false."
9032 input DAE.Exp inExp;
9033 output Boolean outIsCref;
9034 algorithm
9035 outIsCref := match inExp
9036 case DAE.CREF() then true;
9037 else false;
9038 end match;
9039 end isCref;
9040
9041 public function isUnaryCref
9042 input DAE.Exp inExp;
9043 output Boolean outIsCref;
9044 algorithm
9045 outIsCref := match inExp
9046 case DAE.UNARY(DAE.UMINUS(), DAE.CREF()) then true;
9047 else false;
9048 end match;
9049
9050 end isUnaryCref;
9051
9052 public function isCall
9053 "Returns true if the given expression is a function call,
9054 otherwise false."
9055 input DAE.Exp inExp;
9056 output Boolean outIsCall;
9057 algorithm
9058 outIsCall := match inExp
9059 case DAE.CALL() then true;
9060 else false;
9061 end match;
9062 end isCall;
9063
9064 public function isTSUB
9065 "Returns true if the given expression is TSUB,
9066 otherwise false."
9067 input DAE.Exp inExp;
9068 output Boolean outIsCall;
9069 algorithm
9070 outIsCall := match inExp
9071 case DAE.TSUB() then true;
9072 else false;
9073 end match;
9074 end isTSUB;
9075
9076 public function isPureCall
9077 "Returns true if the given expression is a pure function call,
9078 otherwise false."
9079 input DAE.Exp inExp;
9080 output Boolean outIsPureCall;
9081 algorithm
9082 ✗ outIsPureCall := isCall(inExp) and not isImpure(inExp);
9083 end isPureCall;
9084
9085 public function isImpureCall
9086 "Returns true if the given expression is a pure function call,
9087 otherwise false."
9088 input DAE.Exp inExp;
9089 output Boolean outIsPureCall;
9090 algorithm
9091
3/4
✓ Branch 1 taken 16035 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 16020 times.
✓ Branch 5 taken 15 times.
16035 outIsPureCall := isCall(inExp) and isImpure(inExp);
9092 end isImpureCall;
9093
9094 public function isRecordCall
9095 "Returns true if the given expression is a record call,i.e. a function call without elements
9096 otherwise false."
9097 input DAE.Exp inExp;
9098 input AvlTreePathFunction.Tree funcsIn;
9099 output Boolean outIsCall;
9100 algorithm
9101 outIsCall := match inExp
9102 local
9103 Absyn.Path path;
9104 DAE.Function func;
9105 case DAE.CALL(path=path)
9106 then match AvlTreePathFunction.getOpt(funcsIn,path)
9107 25343 case SOME(SOME(func)) then listEmpty(DAEUtil.getFunctionElements(func));
9108 else false;
9109 end match;
9110 else false;
9111 end match;
9112 end isRecordCall;
9113
9114 public function isNotCref
9115 "Returns true if the given expression is a not component reference,
9116 otherwise false."
9117 input DAE.Exp inExp;
9118 output Boolean outIsCref;
9119 algorithm
9120 outIsCref := match inExp
9121 case DAE.CREF() then false;
9122 else true;
9123 end match;
9124 end isNotCref;
9125
9126 public function isCrefArray
9127 "Checks whether a cref is an array or not.
9128 "
9129 input DAE.Exp inExp;
9130 output Boolean outIsArray;
9131 algorithm
9132 outIsArray := match inExp
9133 case DAE.CREF(ty = DAE.T_ARRAY()) then true;
9134 else false;
9135 end match;
9136 end isCrefArray;
9137
9138 public function isCrefScalar
9139 "Checks whether an expression is a scalar cref or not."
9140 input DAE.Exp inExp;
9141 output Boolean isScalar;
9142 algorithm
9143 isScalar := matchcontinue inExp
9144 local
9145 ComponentRef cr;
9146 Boolean b;
9147
9148 case DAE.CREF(ty = DAE.T_ARRAY())
9149 algorithm
9150 ✗ cr := expCref(inExp);
9151 ✗ b := ComponentReference.crefHasScalarSubscripts(cr);
9152 then
9153 b;
9154
9155 case DAE.CREF() then true;
9156
9157 else false;
9158 end matchcontinue;
9159 end isCrefScalar;
9160
9161 public function isTuple
9162 "Returns true if the given expression is a tuple,
9163 otherwise false."
9164 input DAE.Exp inExp;
9165 output Boolean outIsTuple;
9166 algorithm
9167 outIsTuple := match inExp
9168 case DAE.TUPLE() then true;
9169 else false;
9170 end match;
9171 end isTuple;
9172
9173 public function isRecord
9174 "Returns true if the given expression is a record,
9175 otherwise false."
9176 input DAE.Exp inExp;
9177 output Boolean outIsRecord;
9178 algorithm
9179 outIsRecord := match inExp
9180 case DAE.RECORD() then true;
9181 else false;
9182 end match;
9183 end isRecord;
9184
9185 public function isScalarConst
9186 "Returns true if the given expression is a scalar constant, otherwise false."
9187 input DAE.Exp inExp;
9188 output Boolean outIsScalar;
9189 algorithm
9190 outIsScalar := match inExp
9191 case DAE.ICONST() then true;
9192 case DAE.RCONST() then true;
9193 case DAE.SCONST() then true;
9194 case DAE.BCONST() then true;
9195 case DAE.ENUM_LITERAL() then true;
9196 else false;
9197 end match;
9198 end isScalarConst;
9199
9200 public function isEven "returns true if const expression is even"
9201 input DAE.Exp e;
9202 output Boolean even;
9203 algorithm
9204 even := match e
9205 local
9206 Integer i;
9207 Real r;
9208 DAE.Exp exp;
9209
9210 ✗ case DAE.ICONST(i) then intMod(i,2) == 0;
9211 9222 case DAE.RCONST(r) then realMod(r, 2.0) == 0.0;
9212 ✗ case DAE.CAST(exp = exp) then isEven(exp);
9213 else false;
9214 end match;
9215 end isEven;
9216
9217 public function isOdd "returns true if const expression is odd"
9218 input DAE.Exp e;
9219 output Boolean even;
9220 algorithm
9221 even := match e
9222 local
9223 Integer i;
9224 Real r;
9225 DAE.Exp exp;
9226
9227 ✗ case DAE.ICONST(i) then intMod(i,2) == 1;
9228 ✗ case DAE.RCONST(r) then realMod(r, 2.0) == 1.0;
9229 ✗ case DAE.CAST(exp = exp) then isOdd(exp);
9230 else false;
9231 end match;
9232 end isOdd;
9233
9234 public function isIntegerOrReal "Returns true if Type is Integer or Real"
9235 input DAE.Type tp;
9236 output Boolean res;
9237 algorithm
9238 res := match tp
9239 case DAE.T_REAL() then true;
9240 case DAE.T_INTEGER() then true;
9241 else false;
9242 end match;
9243 end isIntegerOrReal;
9244
9245 public function expStructuralEqual
9246 "Returns true if the two expressions are structural equal. This means
9247 only the componentreference can be different"
9248 input DAE.Exp inExp1;
9249 input DAE.Exp inExp2;
9250 output Boolean outBoolean;
9251 algorithm
9252 outBoolean := match (inExp1,inExp2)
9253 local
9254 Integer i1,i2;
9255 String s1,s2;
9256 Boolean b,b1,b2,res;
9257 DAE.Exp e11,e12,e21,e22,e1,e2,e13,e23;
9258 Operator op1,op2;
9259 Absyn.Path path1,path2;
9260 list<DAE.Exp> expl1,expl2;
9261 list<list<Exp>> explstlst1,explstlst2;
9262 Type tp1,tp2;
9263 Real r1,r2;
9264 Absyn.Path enum1, enum2;
9265 list<DAE.Exp> ae1,ae2;
9266 list<DAE.Subscript> subs1, subs2;
9267
9268 ✗ case (DAE.ICONST(integer = i1),DAE.ICONST(integer = i2)) then (i1 == i2);
9269 case (DAE.UNARY(DAE.UMINUS(_),DAE.ICONST(integer = i1)),DAE.ICONST(integer = i2))
9270 algorithm
9271 ✗ i1 := - i1;
9272 ✗ then (i1 == i2);
9273 case (DAE.ICONST(integer = i1),DAE.UNARY(DAE.UMINUS(_),DAE.ICONST(integer = i2)))
9274 algorithm
9275 ✗ i2 := - i2;
9276 ✗ then (i1 == i2);
9277 ✗ case (DAE.RCONST(real = r1),DAE.RCONST(real = r2)) then (r1 == r2);
9278 case (DAE.UNARY(DAE.UMINUS(_),DAE.RCONST(real = r1)),DAE.RCONST(real = r2))
9279 algorithm
9280 ✗ r1 := - r1;
9281 ✗ then (r1 == r2);
9282 case (DAE.RCONST(real = r1),DAE.UNARY(DAE.UMINUS(_),DAE.RCONST(real = r2)))
9283 algorithm
9284 ✗ r2 := - r2;
9285 ✗ then (r1 == r2);
9286 ✗ case (DAE.SCONST(string = s1),DAE.SCONST(string = s2)) then stringEq(s1, s2);
9287 ✗ case (DAE.BCONST(bool = b1),DAE.BCONST(bool = b2)) then boolEq(b1, b2);
9288 ✗ case (DAE.ENUM_LITERAL(name = enum1), DAE.ENUM_LITERAL(name = enum2)) then AbsynUtil.pathEqual(enum1, enum2);
9289 case (DAE.CREF(),DAE.CREF()) then true;
9290
9291 // binary ops
9292 case (DAE.BINARY(exp1 = e11,operator = op1,exp2 = e12),DAE.BINARY(exp1 = e21,operator = op2,exp2 = e22))
9293 algorithm
9294 ✗ b := operatorEqual(op1, op2);
9295 ✗ b := if b then expStructuralEqual(e11, e21) else b;
9296 ✗ b := if b then expStructuralEqual(e12, e22) else b;
9297 then
9298 b;
9299
9300 // logical binary ops
9301 case (DAE.LBINARY(exp1 = e11,operator = op1,exp2 = e12),
9302 DAE.LBINARY(exp1 = e21,operator = op2,exp2 = e22))
9303 algorithm
9304 ✗ b := operatorEqual(op1, op2);
9305 ✗ b := if b then expStructuralEqual(e11, e21) else b;
9306 ✗ b := if b then expStructuralEqual(e12, e22) else b;
9307 then
9308 b;
9309
9310 // unary ops
9311 case (DAE.UNARY(operator = op1,exp = e1),DAE.UNARY(operator = op2,exp = e2))
9312 algorithm
9313 ✗ b := operatorEqual(op1, op2);
9314 ✗ b := if b then expStructuralEqual(e1, e2) else b;
9315 then
9316 b;
9317
9318 // logical unary ops
9319 case (DAE.LUNARY(operator = op1,exp = e1),DAE.LUNARY(operator = op2,exp = e2))
9320 algorithm
9321 ✗ b := operatorEqual(op1, op2);
9322 ✗ b := if b then expStructuralEqual(e1, e2) else b;
9323 then
9324 b;
9325
9326 // relational ops
9327 case (DAE.RELATION(exp1 = e11,operator = op1,exp2 = e12),DAE.RELATION(exp1 = e21,operator = op2,exp2 = e22))
9328 algorithm
9329 ✗ b := operatorEqual(op1, op2);
9330 ✗ b := if b then expStructuralEqual(e11, e21) else b;
9331 ✗ b := if b then expStructuralEqual(e12, e22) else b;
9332 then
9333 b;
9334
9335 // if expressions
9336 case (DAE.IFEXP(expCond = e11,expThen = e12,expElse = e13),DAE.IFEXP(expCond = e21,expThen = e22,expElse = e23))
9337 algorithm
9338 ✗ b := expStructuralEqual(e11, e21);
9339 ✗ b := if b then expStructuralEqual(e12, e22) else b;
9340 ✗ b := if b then expStructuralEqual(e13, e23) else b;
9341 then
9342 b;
9343
9344 // function calls
9345 case (DAE.CALL(path = path1,expLst = expl1),DAE.CALL(path = path2,expLst = expl2))
9346 algorithm
9347 ✗ b := AbsynUtil.pathEqual(path1, path2);
9348 ✗ b := if b then expStructuralEqualList(expl1, expl2) else b;
9349 then
9350 b;
9351 case (DAE.RECORD(path = path1,exps = expl1),DAE.RECORD(path = path2,exps = expl2))
9352 algorithm
9353 ✗ b := AbsynUtil.pathEqual(path1, path2);
9354 ✗ b := if b then expStructuralEqualList(expl1, expl2) else b;
9355 then
9356 b;
9357 // partially evaluated functions
9358 case (DAE.PARTEVALFUNCTION(path = path1,expList = expl1),DAE.PARTEVALFUNCTION(path = path2,expList = expl2))
9359 algorithm
9360 ✗ b := AbsynUtil.pathEqual(path1, path2);
9361 ✗ b := if b then expStructuralEqualList(expl1, expl2) else b;
9362 then
9363 b;
9364
9365 // arrays
9366 case (DAE.ARRAY(ty = tp1,array = expl1),DAE.ARRAY(ty = tp2,array = expl2))
9367 algorithm
9368 ✗ b := valueEq(tp1, tp2);
9369 ✗ b := if b then expStructuralEqualList(expl1, expl2) else b;
9370 then
9371 b;
9372
9373 // matrix
9374 case (DAE.MATRIX(matrix = explstlst1), DAE.MATRIX(matrix = explstlst2))
9375 ✗ then
9376 expStructuralEqualListLst(explstlst1,explstlst2);
9377
9378 // ranges [start:stop]
9379 case (DAE.RANGE(start = e11,step = NONE(),stop = e13),
9380 DAE.RANGE(start = e21,step = NONE(),stop = e23))
9381 algorithm
9382 ✗ b := expStructuralEqual(e11, e21);
9383 ✗ b := if b then expStructuralEqual(e13, e23) else b;
9384 then
9385 b;
9386
9387 // ranges [start:step:stop]
9388 case (DAE.RANGE(start = e11,step = SOME(e12),stop = e13),
9389 DAE.RANGE(start = e21,step = SOME(e22),stop = e23))
9390 algorithm
9391 ✗ b := expStructuralEqual(e11, e21);
9392 ✗ b := if b then expStructuralEqual(e12, e22) else b;
9393 ✗ b := if b then expStructuralEqual(e13, e23) else b;
9394 then
9395 b;
9396
9397 // tuples
9398 case (DAE.TUPLE(PR = expl1),DAE.TUPLE(PR = expl2))
9399 ✗ then expStructuralEqualList(expl1, expl2);
9400
9401 // casting
9402 case (DAE.CAST(ty = tp1,exp = e1),DAE.CAST(ty = tp2,exp = e2))
9403 algorithm
9404 ✗ b := valueEq(tp1, tp2);
9405 ✗ b := if b then expStructuralEqual(e1, e2) else b;
9406 then
9407 b;
9408
9409 // array subscripts
9410 case (DAE.ASUB(exp = e1,sub = subs1),DAE.ASUB(sub = subs2))
9411 algorithm
9412 ✗ ae1 := list(Expression.getSubscriptExp(sub) for sub in subs1);
9413 ✗ ae2 := list(Expression.getSubscriptExp(sub) for sub in subs2);
9414 ✗ b := expStructuralEqual(e1, e1);
9415 ✗ b := if b then expStructuralEqualList(ae1, ae2) else b;
9416 then
9417 b;
9418
9419 // size(a)
9420 case (DAE.SIZE(exp = e1,sz = NONE()),DAE.SIZE(exp = e2,sz = NONE()))
9421 ✗ then expStructuralEqual(e1, e2);
9422
9423 // size(a, dim)
9424 case (DAE.SIZE(exp = e1,sz = SOME(e11)),DAE.SIZE(exp = e2,sz = SOME(e22)))
9425 algorithm
9426 ✗ b := expStructuralEqual(e1, e2);
9427 ✗ b := if b then expStructuralEqual(e11, e22) else b;
9428 then
9429 b;
9430
9431 // metamodeling code
9432 case (DAE.CODE(),DAE.CODE())
9433 algorithm
9434 ✗ Debug.trace("exp_equal on CODE not impl.\n");
9435 then
9436 false;
9437
9438 case (DAE.REDUCTION(),DAE.REDUCTION())
9439 algorithm
9440 // Reductions contain too much information to compare equality in a sane manner
9441 ✗ res := valueEq(inExp1,inExp2);
9442 then
9443 res;
9444
9445 // end id
9446 /*// everything else failed, try structural equality
9447 case (e1,e2)
9448 algorithm
9449 equality(e1 = e2);
9450 then true;
9451 case (e1,e2)
9452 algorithm
9453 failure(equality(e1 = e2));
9454 then false;
9455 */
9456 // not equal
9457 case (DAE.LIST(valList = expl1),DAE.LIST(valList = expl2))
9458 ✗ then expStructuralEqualList(expl1, expl2);
9459
9460 case (DAE.CONS(car = e11,cdr = e12),
9461 DAE.CONS(car = e21,cdr = e22))
9462 algorithm
9463 ✗ b := expStructuralEqual(e11, e21);
9464 ✗ b := if b then expStructuralEqual(e12, e22) else b;
9465 then
9466 b;
9467
9468 case (DAE.META_TUPLE(listExp = expl1),DAE.META_TUPLE(listExp = expl2))
9469 ✗ then expStructuralEqualList(expl1, expl2);
9470
9471 case (DAE.META_OPTION(exp = NONE()),
9472 DAE.META_OPTION(exp = NONE()))
9473 then true;
9474
9475 case (DAE.META_OPTION(exp = SOME(e1)),
9476 DAE.META_OPTION(exp = SOME(e2)))
9477 ✗ then expStructuralEqual(e1, e2);
9478
9479 case (DAE.METARECORDCALL(path = path1,args = expl1),DAE.METARECORDCALL(path = path2,args = expl2))
9480 algorithm
9481 ✗ b := AbsynUtil.pathEqual(path1, path2);
9482 ✗ b := if b then expStructuralEqualList(expl1, expl2) else b;
9483 then
9484 b;
9485
9486 case (e1 as DAE.MATCHEXPRESSION(),
9487 e2 as DAE.MATCHEXPRESSION())
9488 ✗ then valueEq(e1,e2);
9489
9490 case (DAE.BOX(e1),DAE.BOX(e2))
9491 ✗ then expStructuralEqual(e1, e2);
9492
9493 case (DAE.UNBOX(exp=e1),DAE.UNBOX(exp=e2))
9494 ✗ then expStructuralEqual(e1, e2);
9495
9496 ✗ case (DAE.SHARED_LITERAL(index=i1),DAE.SHARED_LITERAL(index=i2)) then intEq(i1,i2);
9497
9498 else false;
9499 end match;
9500 end expStructuralEqual;
9501
9502 public function expStructuralEqualList
9503 "Returns true if the two lists of expressions are structural equal."
9504 input list<DAE.Exp> inExp1;
9505 input list<DAE.Exp> inExp2;
9506 output Boolean outBoolean;
9507 algorithm
9508 outBoolean := match (inExp1,inExp2)
9509 local
9510 DAE.Exp e1,e2;
9511 list<DAE.Exp> es1,es2;
9512 case ({},{}) then true;
9513 case (e1::es1,e2::es2) guard expStructuralEqual(e1,e2)
9514 ✗ then
9515 expStructuralEqualList(es1, es2);
9516 else false;
9517 end match;
9518 end expStructuralEqualList;
9519
9520 protected function expStructuralEqualListLst
9521 "Returns true if the two lists of lists of expressions are structural equal."
9522 input list<list<DAE.Exp>> inExp1;
9523 input list<list<DAE.Exp>> inExp2;
9524 output Boolean outBoolean;
9525 algorithm
9526 outBoolean := match (inExp1,inExp2)
9527 local
9528 list<DAE.Exp> e1,e2;
9529 list<list<DAE.Exp>> es1,es2;
9530 case ({},{}) then true;
9531 case (e1::es1,e2::es2) guard expStructuralEqualList(e1,e2)
9532 ✗ then
9533 expStructuralEqualListLst(es1, es2);
9534 else false;
9535 end match;
9536 end expStructuralEqualListLst;
9537
9538 public function expContainsList
9539 input list<DAE.Exp> expl;
9540 input DAE.Exp exp;
9541 output Boolean contains = List.any(expl, function expContains(inExp2 = exp));
9542 end expContainsList;
9543
9544 public function expContains
9545 "Returns true if first expression contains the second one as a sub expression.
9546 Only constants, component references or der(componentReference) can be checked
9547 so far."
9548 input DAE.Exp inExp1;
9549 input DAE.Exp inExp2;
9550 output Boolean outBoolean;
9551 algorithm
9552 outBoolean := matchcontinue (inExp1, inExp2)
9553 local
9554 Boolean b1, b2;
9555 Boolean res;
9556 ComponentRef cr1, cr2;
9557 DAE.Exp e1, e2, e, c, t, f;
9558 Integer i1, i2;
9559 list<DAE.Exp> expLst;
9560 list<list<DAE.Exp>> expl;
9561 Real r1, r2;
9562 String str, s1, s2;
9563 list<DAE.Subscript> subs;
9564
9565 ✗ case (DAE.ICONST(i1), DAE.ICONST(i2)) then i1 == i2;
9566 case (DAE.ICONST(), _) then false;
9567
9568 ✗ case (DAE.RCONST(r1), DAE.RCONST(r2)) then r1 == r2;
9569 case (DAE.RCONST(), _) then false;
9570
9571 ✗ case (DAE.SCONST(s1), DAE.SCONST(s2)) then s1 == s2;
9572 case (DAE.SCONST(), _) then false;
9573
9574 ✗ case (DAE.BCONST(b1), DAE.BCONST(b2)) then b1 == b2;
9575 case (DAE.BCONST(), _) then true;
9576
9577 case (DAE.ENUM_LITERAL(), _) then false;
9578
9579 ✗ case (DAE.ARRAY(array=expLst), _) then expContainsList(expLst, inExp2);
9580 ✗ case (DAE.MATRIX(matrix=expl), _) then List.any(expl, function List.any(inFunc = function expContains(inExp2 = inExp2)));
9581
9582 case (DAE.CREF(componentRef=cr1), DAE.CREF(componentRef=cr2)) algorithm
9583 319 res := ComponentReferenceBasics.crefEqual(cr1, cr2);
9584
2/2
✓ Branch 0 taken 175 times.
✓ Branch 1 taken 144 times.
319 if not res then
9585 175 expLst := List.map(ComponentReferenceBasics.crefSubs(cr1), getSubscriptExp);
9586 175 res := expContainsList(expLst, inExp2);
9587 end if;
9588 then res;
9589
9590 case ((DAE.CREF()), _) then false;
9591
9592 case (DAE.BINARY(exp1=e1, exp2=e2), _)
9593
3/4
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 18 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
30 then expContains(e1, inExp2) or expContains(e2, inExp2);
9594
9595 ✗ case (DAE.UNARY(exp=e), _) then expContains(e, inExp2);
9596
9597 case (DAE.LBINARY(exp1=e1, exp2=e2), _)
9598
2/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 10 times.
10 then expContains(e1, inExp2) or expContains(e2, inExp2);
9599
9600 11 case (DAE.LUNARY(exp=e), _) then expContains(e, inExp2);
9601
9602 case (DAE.RELATION(exp1=e1, exp2=e2), _)
9603
3/4
✓ Branch 1 taken 34 times.
✓ Branch 2 taken 33 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 34 times.
67 then expContains(e1, inExp2) or expContains(e2, inExp2);
9604
9605 case (DAE.IFEXP(expCond=c, expThen=t, expElse=f), _)
9606 ✗ then expContains(c, inExp2) or expContains(t, inExp2) or expContains(f, inExp2);
9607
9608 case (DAE.CALL(path=Absyn.IDENT(name="der"), expLst={DAE.CREF(cr1)}),
9609 DAE.CALL(path=Absyn.IDENT(name="der"), expLst={DAE.CREF(cr2)})) algorithm
9610 ✗ res := ComponentReferenceBasics.crefEqual(cr1, cr2);
9611 then res;
9612
9613 // pre(v) does not contain variable v
9614 case (DAE.CALL(path=Absyn.IDENT(name="pre")), _) then false;
9615 case (DAE.CALL(path=Absyn.IDENT(name="previous")), _) then false;
9616
9617 // special rule for no arguments
9618 case (DAE.CALL(expLst={}), _) then false;
9619
9620 // general case for arguments
9621 ✗ case (DAE.CALL(expLst=expLst), _) then expContainsList(expLst, inExp2);
9622 ✗ case (DAE.RECORD(exps=expLst), _) then expContainsList(expLst, inExp2);
9623 ✗ case (DAE.PARTEVALFUNCTION(expList=expLst), DAE.CREF()) then expContainsList(expLst, inExp2);
9624 case (DAE.CAST(ty=DAE.T_REAL(), exp=DAE.ICONST()), _) then false;
9625 ✗ case (DAE.CAST(ty=DAE.T_REAL(), exp=e), _) then expContains(e, inExp2);
9626 ✗ case (DAE.ASUB(exp=e, sub=subs), _) then expContainsList(list(Expression.getSubscriptExp(sub) for sub in subs), inExp2) or expContains(e, inExp2);
9627 ✗ case (DAE.REDUCTION(expr=e), _) then expContains(e, inExp2);
9628
9629 else algorithm
9630 ✗ true := Flags.isSet(Flags.FAILTRACE);
9631 ✗ Debug.trace("- Expression.expContains failed\n");
9632 ✗ s1 := ExpressionBasics.printExpStr(inExp1);
9633 ✗ s2 := ExpressionBasics.printExpStr(inExp2);
9634 ✗ str := stringAppendList({"exp = ", s1," subexp = ", s2});
9635 ✗ Debug.traceln(str);
9636 ✗ then fail();
9637 end matchcontinue;
9638 end expContains;
9639
9640 public function containsExp
9641 "Author BZ 2008-06 same as expContains, but reversed."
9642 input DAE.Exp inExp1;
9643 input DAE.Exp inExp2;
9644 output Boolean outBoolean;
9645 algorithm
9646 ✗ outBoolean:= expContains(inExp2,inExp1);
9647 end containsExp;
9648
9649 public function isExpCref
9650 "Returns true if expression is a componentRef"
9651 input DAE.Exp e;
9652 output Boolean res;
9653 algorithm
9654 res := match e
9655 case DAE.CREF(_,_) then true;
9656 else false;
9657 end match;
9658 end isExpCref;
9659
9660 public function isExpCrefOrIfExp
9661 "Returns true if expression is a componentRef or an if expression"
9662 input DAE.Exp e;
9663 output Boolean res;
9664 algorithm
9665 res := match e
9666 case DAE.CREF(_,_) then true;
9667 case DAE.IFEXP(_,_,_) then true;
9668 else false;
9669 end match;
9670 end isExpCrefOrIfExp;
9671
9672 public function isExpIfExp
9673 "Returns true if expression is an if expression"
9674 input DAE.Exp e;
9675 output Boolean res;
9676 algorithm
9677 res := match e
9678 case DAE.IFEXP() then true;
9679 else false;
9680 end match;
9681 end isExpIfExp;
9682
9683 public function operatorEqual
9684 "Helper function to expEqual."
9685 input DAE.Operator inOperator1;
9686 input DAE.Operator inOperator2;
9687 output Boolean outBoolean;
9688 algorithm
9689 6620273 outBoolean := 0==ExpressionBasics.operatorCompare(inOperator1,inOperator2);
9690 end operatorEqual;
9691
9692 public function arrayContainZeroDimension
9693 "Checks if one of the dimensions in a list is zero."
9694 input list<DAE.Dimension> inDimensions;
9695 output Boolean outContainZeroDim;
9696 algorithm
9697 outContainZeroDim := match inDimensions
9698 local
9699 list<DAE.Dimension> rest_dims;
9700
9701 case DAE.DIM_INTEGER(0) :: _ then true;
9702 1609 case _ :: rest_dims then arrayContainZeroDimension(rest_dims);
9703 else false;
9704
9705 end match;
9706 end arrayContainZeroDimension;
9707
9708 public function arrayContainWholeDimension
9709 "Checks if a list of dimensions contain a wholedim, i.e. NONE."
9710 input DAE.Dimensions inDim;
9711 output Boolean wholedim;
9712 algorithm
9713 wholedim := match inDim
9714 local
9715 DAE.Dimensions rest_dims;
9716 case DAE.DIM_UNKNOWN() :: _ then true;
9717 ✗ case _ :: rest_dims then arrayContainWholeDimension(rest_dims);
9718 else false;
9719 end match;
9720 end arrayContainWholeDimension;
9721
9722 public function isArrayType
9723 "Returns true if inType is an T_ARRAY"
9724 input DAE.Type inType;
9725 output Boolean b;
9726 algorithm
9727 b := match inType
9728 case DAE.T_ARRAY() then true;
9729 else false;
9730 end match;
9731 end isArrayType;
9732
9733 public function isRecordType
9734 "Return true if the type is a record type."
9735 input DAE.Type inType;
9736 output Boolean b;
9737 algorithm
9738 b := match inType
9739 case DAE.T_COMPLEX(complexClassType = ClassInf.RECORD()) then true;
9740 else false;
9741 end match;
9742 end isRecordType;
9743
9744 public function isNotComplex "returns true if the exp is 1-dimensional"
9745 input DAE.Exp e;
9746 output Boolean b;
9747 algorithm
9748 b := match e
9749 local
9750 Boolean b2;
9751 DAE.Exp e2;
9752 case DAE.CALL()
9753 then
9754 false;
9755 case DAE.RECORD()
9756 then
9757 false;
9758 case DAE.ARRAY()
9759 then
9760 false;
9761 case DAE.CAST(exp=e2)
9762 algorithm
9763 ✗ b2 := isNotComplex(e2);
9764 then b2;
9765 else
9766 true;
9767 end match;
9768 end isNotComplex;
9769
9770 public function isRealType
9771 "Return true if the type is Real."
9772 input DAE.Type inType;
9773 output Boolean b;
9774 algorithm
9775 b := match inType
9776 case DAE.T_REAL() then true;
9777 else false;
9778 end match;
9779 end isRealType;
9780
9781 public function dimensionsEqual
9782 "Returns whether two dimensions are equal or not."
9783 input DAE.Dimension dim1;
9784 input DAE.Dimension dim2;
9785 output Boolean res;
9786 algorithm
9787 res := match(dim1, dim2)
9788 local Boolean b;
9789 case (DAE.DIM_UNKNOWN(), _) then true;
9790 case (_, DAE.DIM_UNKNOWN()) then true;
9791 case (DAE.DIM_EXP(), _) then true;
9792 case (_, DAE.DIM_EXP()) then true;
9793
9794 else
9795 algorithm
9796 30297 b := intEq(dimensionSize(dim1), dimensionSize(dim2));
9797 then
9798 b;
9799 end match;
9800 end dimensionsEqual;
9801
9802 public function dimsEqual
9803 "Returns whether two dimensions are equal or not."
9804 input DAE.Dimensions dims1;
9805 input DAE.Dimensions dims2;
9806 output Boolean res;
9807 algorithm
9808 res := match(dims1, dims2)
9809 local
9810 DAE.Dimension d1, d2;
9811 DAE.Dimensions dl1, dl2;
9812
9813 case ({}, {}) then true;
9814 case (d1::dl1, d2::dl2) guard dimensionsEqual(d1, d2)
9815 27726 then
9816 dimsEqual(dl1, dl2);
9817 else false;
9818 end match;
9819 end dimsEqual;
9820
9821 public function dimsEqualAllowZero
9822 "Returns whether two dimensions are equal or not.
9823 0 == anydim is allowed"
9824 input DAE.Dimensions dims1;
9825 input DAE.Dimensions dims2;
9826 output Boolean res;
9827 algorithm
9828 res := match(dims1, dims2)
9829 local
9830 DAE.Dimension d1, d2;
9831 DAE.Dimensions dl1, dl2;
9832
9833 case ({}, {}) then true;
9834 case (d1::dl1, d2::dl2) guard dimensionsEqualAllowZero(d1, d2)
9835 ✗ then
9836 dimsEqualAllowZero(dl1, dl2);
9837 else false;
9838 end match;
9839 end dimsEqualAllowZero;
9840
9841 public function dimensionsEqualAllowZero
9842 "Returns whether two dimensions are equal or not.
9843 0 == anyDim is allowed"
9844 input DAE.Dimension dim1;
9845 input DAE.Dimension dim2;
9846 output Boolean res;
9847 algorithm
9848 res := match(dim1, dim2)
9849 local
9850 Boolean b;
9851 Integer d1, d2;
9852
9853 case (DAE.DIM_UNKNOWN(), _) then true;
9854 case (_, DAE.DIM_UNKNOWN()) then true;
9855 case (DAE.DIM_EXP(), _) then true;
9856 case (_, DAE.DIM_EXP()) then true;
9857
9858 else
9859 algorithm
9860 ✗ d1 := dimensionSize(dim1);
9861 ✗ d2 := dimensionSize(dim2);
9862 ✗ b := boolOr(
9863 intEq(d1, d2),
9864 boolOr(
9865 boolAnd(intEq(d1,0), intNe(d2,0)),
9866 boolAnd(intEq(d2,0), intNe(d1,0))));
9867 then
9868 b;
9869 end match;
9870 end dimensionsEqualAllowZero;
9871
9872 public function dimensionsKnownAndEqual
9873 "Checks that two dimensions are specified and equal."
9874 input DAE.Dimension dim1;
9875 input DAE.Dimension dim2;
9876 output Boolean res;
9877 algorithm
9878 res := match (dim1,dim2)
9879 case (DAE.DIM_UNKNOWN(),_) then false; // dimensionSizeExp fails on DIM_UNKNOWN...
9880 case (_,DAE.DIM_UNKNOWN()) then false;
9881 416232 else ExpressionBasics.expEqual(dimensionSizeExp(dim1), dimensionSizeExp(dim2));
9882 end match;
9883 end dimensionsKnownAndEqual;
9884
9885 public function dimensionKnown
9886 "Checks whether a dimension is known or not."
9887 input DAE.Dimension dim;
9888 output Boolean known;
9889 algorithm
9890 known := match dim
9891 case DAE.DIM_UNKNOWN() then false;
9892 case DAE.DIM_EXP(exp = DAE.ICONST()) then true;
9893 case DAE.DIM_EXP(exp = DAE.BCONST()) then true;
9894 case DAE.DIM_EXP(exp = DAE.ENUM_LITERAL()) then true;
9895 case DAE.DIM_EXP() then false;
9896 else true;
9897 end match;
9898 end dimensionKnown;
9899
9900 public function dimensionKnownAndNonZero
9901 "Checks whether a dimensions is known or not."
9902 input DAE.Dimension dim;
9903 output Boolean known;
9904 algorithm
9905 known := match dim
9906 case DAE.DIM_EXP(exp = DAE.ICONST(0)) then false;
9907 case DAE.DIM_INTEGER(0) then false;
9908 2467 else dimensionKnown(dim);
9909 end match;
9910 end dimensionKnownAndNonZero;
9911
9912 public function dimensionsKnownAndNonZero
9913 "Checks whether all dimensions are known or not."
9914 input list<DAE.Dimension> dims;
9915 output Boolean allKnown;
9916 algorithm
9917 32044 allKnown := List.all(dims, dimensionKnownAndNonZero);
9918 end dimensionsKnownAndNonZero;
9919
9920 public function dimensionUnknownOrExp
9921 "Checks whether a dimensions is known or not."
9922 input DAE.Dimension dim;
9923 output Boolean known;
9924 algorithm
9925 known := match dim
9926 case DAE.DIM_UNKNOWN() then true;
9927 case DAE.DIM_EXP() then true;
9928 else false;
9929 end match;
9930 end dimensionUnknownOrExp;
9931
9932 public function dimensionUnknown
9933 input DAE.Dimension inDimension;
9934 output Boolean outUnknown;
9935 algorithm
9936 outUnknown := match inDimension
9937 case DAE.DIM_UNKNOWN() then true;
9938 else false;
9939 end match;
9940 end dimensionUnknown;
9941
9942 public function hasUnknownDims
9943 input list<DAE.Dimension> dims;
9944 output Boolean hasUnkown;
9945 algorithm
9946 11097 hasUnkown := List.any(dims, dimensionUnknown);
9947 end hasUnknownDims;
9948
9949 public function subscriptConstant
9950 input DAE.Subscript sub;
9951 output Boolean b;
9952 algorithm
9953 b := match sub
9954 case DAE.INDEX(exp = DAE.ICONST()) then true;
9955 case DAE.INDEX(exp = DAE.ENUM_LITERAL()) then true;
9956 case DAE.INDEX(exp = DAE.BCONST()) then true;
9957 else false;
9958 end match;
9959 end subscriptConstant;
9960
9961 public function subscriptConstants "
9962 returns true if all subscripts are known (i.e no cref) constant values (no slice or wholedim)"
9963 input list<DAE.Subscript> inSubs;
9964 output Boolean areConstant = true;
9965 algorithm
9966
2/2
✓ Branch 0 taken 1488797 times.
✓ Branch 1 taken 1249745 times.
2738542 for sub in inSubs loop
9967 1488797 areConstant := subscriptConstant(sub);
9968
2/2
✓ Branch 0 taken 2274 times.
✓ Branch 1 taken 1486523 times.
1488797 if not areConstant then return; end if;
9969 end for;
9970 end subscriptConstants;
9971
9972 public function isValidSubscript
9973 "Checks if an expression is a valid subscript, i.e. an integer or enumeration
9974 literal."
9975 input DAE.Exp inSub;
9976 output Boolean isValid;
9977 algorithm
9978 isValid := match inSub
9979 case DAE.ICONST() then true;
9980 case DAE.ENUM_LITERAL() then true;
9981 case DAE.BCONST() then true;
9982 else false;
9983 end match;
9984 end isValidSubscript;
9985
9986 public function subscriptContain "This function checks whether sub2 contains sub1 or not(DAE.WHOLEDIM())"
9987 input list<DAE.Subscript> issl1;
9988 input list<DAE.Subscript> issl2;
9989 output Boolean contained;
9990 algorithm
9991 contained := match(issl1,issl2)
9992 local
9993 Boolean b;
9994 Subscript ss1,ss2;
9995 list<DAE.Subscript> ssl1,ssl2;
9996 Integer i;
9997 list<DAE.Exp> expl;
9998
9999 case({},_) then true;
10000
10001 case(_ ::ssl1, (DAE.WHOLEDIM())::ssl2)
10002 algorithm
10003 ✗ b := subscriptContain(ssl1,ssl2);
10004 then b;
10005
10006 // Should there be additional checking in this case?
10007 case(_ ::ssl1, (DAE.WHOLE_NONEXP(_))::ssl2)
10008 algorithm
10009 ✗ b := subscriptContain(ssl1,ssl2);
10010 then b;
10011 /* case(ss1::ssl1, (ss2 as DAE.SLICE(exp)) ::ssl2)
10012 local DAE.Exp exp;
10013 algorithm
10014 b = subscriptContain(ssl1,ssl2);
10015 then
10016 b;
10017 */
10018 case((DAE.INDEX(DAE.ICONST(i)))::ssl1, (DAE.SLICE(DAE.ARRAY(_,_,expl))) ::ssl2)
10019 algorithm
10020 ✗ true := subscriptContain2(i,expl);
10021 ✗ b := subscriptContain(ssl1,ssl2);
10022 then
10023 b;
10024
10025 case(ss1::ssl1,ss2::ssl2)
10026 algorithm
10027 ✗ true := ExpressionBasics.subscriptEqual({ss1},{ss2});
10028 ✗ b := subscriptContain(ssl1,ssl2);
10029 then
10030 b;
10031 else false;
10032 end match;
10033 end subscriptContain;
10034
10035 protected function subscriptContain2 "
10036 "
10037 input Integer inInt;
10038 input list<DAE.Exp> inExp2;
10039 output Boolean contained;
10040 algorithm
10041 contained := match(inInt,inExp2)
10042 local
10043 Boolean b,b2;
10044 list<DAE.Exp> expl,expl2;
10045 Integer i,j;
10046 case(i,( (DAE.ICONST(j)) :: _)) guard (i == j)
10047 then
10048 true;
10049 case(i,(( DAE.ICONST(_)) :: expl)) guard subscriptContain2(i,expl)
10050 then
10051 true;
10052 case(i,( (DAE.ARRAY(_,_,expl2)) :: expl))
10053 algorithm
10054 ✗ b := subscriptContain2(i,expl2);
10055 ✗ b2 := if b then true else subscriptContain2(i,expl);
10056 then
10057 b2;
10058 else false;
10059 end match;
10060 end subscriptContain2;
10061
10062 public function hasNoSideEffects
10063 "Returns true if the expression is free from side-effects. Use with traverseExpBottomUp."
10064 input DAE.Exp inExp;
10065 input Boolean ib;
10066 output DAE.Exp outExp;
10067 output Boolean ob;
10068 algorithm
10069 (outExp,ob) := match inExp
10070 local
10071 case DAE.CALL() then (inExp,false);
10072 case DAE.MATCHEXPRESSION() then (inExp,false);
10073 else (inExp,ib);
10074 end match;
10075 end hasNoSideEffects;
10076
10077 public function isBuiltinFunctionReference
10078 "Returns true if the expression is a reference to a builtin function"
10079 input DAE.Exp exp;
10080 output Boolean b;
10081 algorithm
10082 b := match exp
10083 case DAE.CREF(ty=DAE.T_FUNCTION_REFERENCE_FUNC(builtin=true)) then true;
10084 else false;
10085 end match;
10086 end isBuiltinFunctionReference;
10087
10088 public function makeCons "DAE.CONS"
10089 input DAE.Exp car;
10090 input DAE.Exp cdr;
10091 output DAE.Exp exp;
10092 annotation(__OpenModelica_EarlyInline = true);
10093 algorithm
10094 ✗ exp := DAE.CONS(car,cdr);
10095 end makeCons;
10096
10097 public function makeBuiltinCall
10098 "Create a DAE.CALL with the given data for a call to a builtin function."
10099 input String name;
10100 input list<DAE.Exp> args;
10101 input DAE.Type result_type;
10102 input Boolean isImpure;
10103 output DAE.Exp call;
10104 annotation(__OpenModelica_EarlyInline = true);
10105 algorithm
10106
2/2
✓ Branch 1 taken 29635 times.
✓ Branch 2 taken 4 times.
59274 call := DAE.CALL(Absyn.IDENT(name),args,DAE.CALL_ATTR(result_type,false,true,isImpure,false,DAE.NO_INLINE(),DAE.NO_TAIL(),DAE.NoReturn.RETURNS));
10107 end makeBuiltinCall;
10108
10109 public function makePureBuiltinCall
10110 "Create a DAE.CALL with the given data for a call to a builtin function."
10111 input String name;
10112 input list<DAE.Exp> args;
10113 input DAE.Type result_type;
10114 output DAE.Exp call;
10115 annotation(__OpenModelica_EarlyInline = true);
10116 algorithm
10117 29621 call := makeBuiltinCall(name, args, result_type, false);
10118 end makePureBuiltinCall;
10119
10120 public function makeImpureBuiltinCall
10121 "Create a DAE.CALL with the given data for a call to a builtin function."
10122 input String name;
10123 input list<DAE.Exp> args;
10124 input DAE.Type result_type;
10125 output DAE.Exp call;
10126 annotation(__OpenModelica_EarlyInline = true);
10127 algorithm
10128 4 call := makeBuiltinCall(name, args, result_type, true);
10129 end makeImpureBuiltinCall;
10130
10131 public function reductionIterName
10132 input DAE.ReductionIterator iter;
10133 output String name;
10134 algorithm
10135 28 DAE.REDUCTIONITER(id=name) := iter;
10136 end reductionIterName;
10137
10138 protected function traverseReductionIteratorBidir<ArgT>
10139 input DAE.ReductionIterator inIter;
10140 input FuncType inEnterFunc;
10141 input FuncType inExitFunc;
10142 input ArgT inArg;
10143 output DAE.ReductionIterator outIter;
10144 output ArgT outArg;
10145
10146 partial function FuncType
10147 input DAE.Exp inExp;
10148 input ArgT inArg;
10149 output DAE.Exp outExp;
10150 output ArgT outArg;
10151 end FuncType;
10152 algorithm
10153 (outIter, outArg) := match inIter
10154 local
10155 String id;
10156 DAE.Exp exp;
10157 Option<DAE.Exp> gexp;
10158 DAE.Type ty;
10159 ArgT arg;
10160
10161 case DAE.REDUCTIONITER(id, exp, gexp, ty)
10162 algorithm
10163 28 (exp, arg) := traverseExpBidir(exp, inEnterFunc, inExitFunc, inArg);
10164 28 (gexp, arg) := traverseExpOptBidir(gexp, inEnterFunc, inExitFunc, arg);
10165
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 then
10166 (DAE.REDUCTIONITER(id, exp, gexp, ty), arg);
10167
10168 end match;
10169 end traverseReductionIteratorBidir;
10170
10171 protected function traverseReductionIteratorTopDown
10172 input DAE.ReductionIterator iter;
10173 input FuncExpType func;
10174 input Type_a inArg;
10175 output DAE.ReductionIterator outIter;
10176 output Type_a outArg;
10177
10178 partial function FuncExpType
10179 input DAE.Exp inExp;
10180 input Type_a inTypeA;
10181 output DAE.Exp outExp;
10182 output Boolean cont;
10183 output Type_a outA;
10184 end FuncExpType;
10185
10186 replaceable type Type_a subtypeof Any;
10187 algorithm
10188 (outIter,outArg) := match (iter, inArg)
10189 local
10190 String id;
10191 DAE.Exp exp;
10192 Option<DAE.Exp> gexp;
10193 DAE.Type ty;
10194 Type_a arg;
10195 case (DAE.REDUCTIONITER(id,exp,gexp,ty), arg)
10196 algorithm
10197 249 (exp, arg) := traverseExpTopDown(exp, func, arg);
10198 249 (gexp, arg) := traverseExpOptTopDown(gexp, func, arg);
10199
1/2
✓ Branch 1 taken 249 times.
✗ Branch 2 not taken.
249 then (DAE.REDUCTIONITER(id,exp,gexp,ty),arg);
10200 end match;
10201 end traverseReductionIteratorTopDown;
10202
10203 protected function traverseReductionIteratorsTopDown
10204 input DAE.ReductionIterators inIters;
10205 input FuncExpType func;
10206 input Type_a inArg;
10207 output DAE.ReductionIterators outIters;
10208 output Type_a outArg;
10209
10210 partial function FuncExpType
10211 input DAE.Exp inExp;
10212 input Type_a inTypeA;
10213 output DAE.Exp outExp;
10214 output Boolean cont;
10215 output Type_a outA;
10216 end FuncExpType;
10217
10218 replaceable type Type_a subtypeof Any;
10219 algorithm
10220 (outIters,outArg) := match (inIters, inArg)
10221 local
10222 Type_a arg;
10223 DAE.ReductionIterator iter;
10224 DAE.ReductionIterators iters;
10225
10226 case ({}, arg) then (inIters,arg);
10227 case (iter::iters, arg)
10228 algorithm
10229 249 (iter, arg) := traverseReductionIteratorTopDown(iter, func, arg);
10230 249 (iters, arg) := traverseReductionIteratorsTopDown(iters, func, arg);
10231 249 then (iter::iters,arg);
10232 end match;
10233 end traverseReductionIteratorsTopDown;
10234
10235 protected function traverseReductionIterator
10236 input DAE.ReductionIterator iter;
10237 input FuncExpType func;
10238 input Type_a iarg;
10239 output DAE.ReductionIterator outIter;
10240 output Type_a outArg;
10241
10242 partial function FuncExpType
10243 input DAE.Exp inExp;
10244 input Type_a inTypeA;
10245 output DAE.Exp outExp;
10246 output Type_a outA;
10247 end FuncExpType;
10248 replaceable type Type_a subtypeof Any;
10249 algorithm
10250 (outIter,outArg) := match (iter, iarg)
10251 local
10252 String id;
10253 DAE.Exp exp,exp1;
10254 Option<DAE.Exp> gexp,gexp1;
10255 DAE.Type ty;
10256 Type_a arg;
10257
10258 case (DAE.REDUCTIONITER(id,exp,gexp,ty), arg)
10259 algorithm
10260 3767 (exp1, arg) := traverseExpBottomUp(exp, func, arg);
10261 3767 (gexp1, arg) := traverseExpOpt(gexp, func, arg);
10262
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 3726 times.
3767 outIter := if referenceEq(exp,exp1) and referenceEq(gexp,gexp1) then iter else DAE.REDUCTIONITER(id,exp1,gexp1,ty);
10263
1/2
✓ Branch 0 taken 3767 times.
✗ Branch 1 not taken.
3767 then (outIter, arg);
10264 end match;
10265 end traverseReductionIterator;
10266
10267 protected function traverseReductionIterators
10268 input output DAE.ReductionIterators iters;
10269 input FuncExpType func;
10270 input output Type_a arg;
10271
10272 partial function FuncExpType
10273 input DAE.Exp inExp;
10274 input Type_a inTypeA;
10275 output DAE.Exp outExp;
10276 output Type_a outA;
10277 end FuncExpType;
10278 replaceable type Type_a subtypeof Any;
10279 algorithm
10280 (iters,arg) := match iters
10281 local
10282 DAE.ReductionIterator iter,iter1;
10283 DAE.ReductionIterators rest,iters1;
10284
10285 case {} then (iters,arg);
10286 case iter::rest
10287 algorithm
10288 3767 (iter1, arg) := traverseReductionIterator(iter, func, arg);
10289 3767 (iters1, arg) := traverseReductionIterators(rest, func, arg);
10290
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 3726 times.
3767 iters := if referenceEq(iter,iter1) and referenceEq(rest,iters1) then iters else (iter1::iters1);
10291 3767 then (iters, arg);
10292 end match;
10293 end traverseReductionIterators;
10294
10295 public function simpleCrefName
10296 input DAE.Exp exp;
10297 output String name;
10298 algorithm
10299
6/6
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 6267 times.
✓ Branch 3 taken 486 times.
✓ Branch 4 taken 5781 times.
✓ Branch 6 taken 24 times.
✓ Branch 7 taken 5757 times.
6325 DAE.CREF(componentRef=DAE.CREF_IDENT(ident=name,subscriptLst={})) := exp;
10300 end simpleCrefName;
10301
10302 public function isTailCall
10303 input DAE.Exp exp;
10304 output Boolean isTail;
10305 algorithm
10306 isTail := match exp
10307 case DAE.CALL(attr=DAE.CALL_ATTR(tailCall=DAE.TAIL())) then true;
10308 else false;
10309 end match;
10310 end isTailCall;
10311
10312 public function complexityTraverse
10313 input DAE.Exp exp;
10314 input Integer complexity;
10315 output DAE.Exp outExp;
10316 output Integer outComplexity;
10317 algorithm
10318 ✗ (outExp,outComplexity) := traverseExpBottomUp(exp,complexityTraverse2,complexity);
10319 end complexityTraverse;
10320
10321 protected function complexityTraverse2
10322 input DAE.Exp exp;
10323 input Integer complexity_;
10324 output DAE.Exp outExp;
10325 output Integer outComplexity;
10326 algorithm
10327 ✗ outComplexity := complexity_ + complexity(exp);
10328 outExp := exp;
10329 end complexityTraverse2;
10330
10331 protected constant Integer complexityAlloc = 5;
10332 protected constant Integer complexityVeryBig = 500000 "Things that are too hard to calculate :(";
10333 protected constant Integer complexityDimLarge = 1000 "Unknown dimensions usually aren't big, but might be";
10334
10335 public function complexity
10336 input DAE.Exp exp;
10337 output Integer i;
10338 algorithm
10339 i := match exp
10340 local
10341 DAE.Operator op;
10342 DAE.Exp e,e1,e2,e3;
10343 Integer c1,c2,c3;
10344 list<DAE.Exp> exps;
10345 list<list<DAE.Exp>> matrix;
10346 String str,name;
10347 DAE.Type tp;
10348 list<DAE.Subscript> subs;
10349
10350 case DAE.ICONST() then 0;
10351 case DAE.RCONST() then 0;
10352 case DAE.SCONST() then 0;
10353 case DAE.BCONST() then 0;
10354 case DAE.SHARED_LITERAL() then 0;
10355 case DAE.ENUM_LITERAL() then 0;
10356 ✗ case DAE.CREF(ty=tp) then tpComplexity(tp);
10357 case DAE.BINARY(exp1=e1,operator=op,exp2=e2)
10358 algorithm
10359 ✗ c1 := complexity(e1);
10360 ✗ c2 := complexity(e2);
10361 ✗ c3 := opComplexity(op);
10362 ✗ then c1+c2+c3;
10363 case DAE.UNARY(exp=e,operator=op)
10364 algorithm
10365 ✗ c1 := complexity(e);
10366 ✗ c2 := opComplexity(op);
10367 ✗ then c1+c2;
10368 case DAE.LBINARY(exp1=e1,exp2=e2,operator=op)
10369 algorithm
10370 ✗ c1 := complexity(e1);
10371 ✗ c2 := complexity(e2);
10372 ✗ c3 := opComplexity(op);
10373 ✗ then c1+c2+c3;
10374 case DAE.LUNARY(exp=e,operator=op)
10375 algorithm
10376 ✗ c1 := complexity(e);
10377 ✗ c2 := opComplexity(op);
10378 ✗ then c1+c2;
10379 case DAE.RELATION(exp1=e1,exp2=e2,operator=op)
10380 algorithm
10381 ✗ c1 := complexity(e1);
10382 ✗ c2 := complexity(e2);
10383 ✗ c3 := opComplexity(op);
10384 ✗ then c1+c2+c3;
10385 case DAE.IFEXP(expCond=e1,expThen=e2,expElse=e3)
10386 algorithm
10387 ✗ c1 := complexity(e1);
10388 ✗ c2 := complexity(e2);
10389 ✗ c3 := complexity(e3);
10390 ✗ then c1+intMax(c2,c3);
10391 case DAE.CALL(path=Absyn.IDENT(name),expLst=exps,attr=DAE.CALL_ATTR(ty=tp,builtin=true))
10392 algorithm
10393 ✗ c1 := List.applyAndFold(exps,intAdd,complexity,0);
10394 ✗ c2 := complexityBuiltin(name,tp);
10395 /* TODO: Cost is based on type and size of inputs. Maybe even name for builtins :) */
10396 ✗ then c1+c2;
10397 case DAE.CALL(expLst=exps)
10398 algorithm
10399 ✗ c1 := List.applyAndFold(exps,intAdd,complexity,0);
10400 ✗ c2 := listLength(exps);
10401 /* TODO: Cost is based on type and size of inputs. Maybe even name for builtins :) */
10402 ✗ then c1+c2+25;
10403 case DAE.RECORD(exps=exps)
10404 algorithm
10405 ✗ c1 := List.applyAndFold(exps,intAdd,complexity,1);
10406 then c1;
10407 case DAE.PARTEVALFUNCTION()
10408 then complexityVeryBig; /* This should not be here anyway :) */
10409 case DAE.ARRAY(array=exps,ty=tp)
10410 algorithm
10411 ✗ c1 := List.applyAndFold(exps,intAdd,complexity,if isArrayType(tp) then 0 else complexityAlloc);
10412 ✗ c2 := listLength(exps);
10413 ✗ then c1+c2;
10414 case DAE.MATRIX(matrix=matrix as (exps::_))
10415 algorithm
10416 ✗ c1 := List.applyAndFold(List.flatten(matrix),intAdd,complexity,complexityAlloc);
10417 ✗ c2 := listLength(exps)*listLength(matrix);
10418 ✗ then c1 + c2;
10419 case DAE.RANGE(start=e1,stop=e2,step=NONE())
10420 ✗ then complexityDimLarge+complexity(e1)+complexity(e2); /* TODO: Check type maybe? */
10421 case DAE.RANGE(start=e1,stop=e2,step=SOME(e3))
10422 ✗ then complexityDimLarge+complexity(e1)+complexity(e2)+complexity(e3); /* TODO: Check type maybe? */
10423 case DAE.TUPLE(PR=exps)
10424 algorithm
10425 ✗ c1 := List.applyAndFold(exps,intAdd,complexity,complexityAlloc);
10426 ✗ c2 := listLength(exps);
10427 ✗ then c1+c2;
10428 ✗ case DAE.CAST(exp=e,ty=tp) then tpComplexity(tp)+complexity(e);
10429 case DAE.ASUB(exp=e,sub=subs)
10430 algorithm
10431 ✗ exps := list(Expression.getSubscriptExp(sub) for sub in subs);
10432 ✗ c1 := List.applyAndFold(exps,intAdd,complexity,complexityAlloc);
10433 ✗ c2 := listLength(exps);
10434 c3 := complexity(e);
10435 then c1+c2+c3;
10436 case DAE.TSUB(exp=e) then complexity(e)+1;
10437 case DAE.SIZE(exp=e,sz=NONE()) then complexity(e)+complexityAlloc+10; /* TODO: Cost is based on type (creating the array) */
10438 ✗ case DAE.SIZE(exp=e1,sz=SOME(e2)) then complexity(e1)+complexity(e2)+1;
10439 case DAE.CODE() then complexityVeryBig;
10440 case DAE.EMPTY() then complexityVeryBig;
10441 case DAE.REDUCTION() then complexityVeryBig; /* TODO: We need a real traversal... */
10442 case DAE.LIST(valList=exps)
10443 algorithm
10444 ✗ c1 := List.applyAndFold(exps,intAdd,complexity,complexityAlloc);
10445 ✗ c2 := listLength(exps);
10446 ✗ then c1+c2+complexityAlloc;
10447 case DAE.CONS(car=e1,cdr=e2)
10448 ✗ then complexityAlloc+complexity(e1)+complexity(e2);
10449 case DAE.META_TUPLE(listExp=exps)
10450 algorithm
10451 ✗ c1 := List.applyAndFold(exps,intAdd,complexity,complexityAlloc);
10452 ✗ c2 := listLength(exps);
10453 ✗ then complexityAlloc+c1+c2;
10454 case DAE.META_OPTION(exp=NONE()) then 0;
10455 case DAE.META_OPTION(exp=SOME(e)) then complexity(e)+complexityAlloc;
10456 case DAE.METARECORDCALL(args=exps)
10457 algorithm
10458 ✗ c1 := List.applyAndFold(exps,intAdd,complexity,complexityAlloc);
10459 ✗ c2 := listLength(exps);
10460 ✗ then c1+c2+complexityAlloc;
10461 case DAE.MATCHEXPRESSION() then complexityVeryBig;
10462 case DAE.BOX(exp=e) then complexityAlloc+complexity(e);
10463 case DAE.UNBOX(exp=e) then 1+complexity(e);
10464 case DAE.PATTERN() then 0;
10465 else
10466 algorithm
10467 ✗ str := "Expression.complexityWork failed: " + ExpressionBasics.printExpStr(exp);
10468 ✗ Error.addMessage(Error.INTERNAL_ERROR,{str});
10469 ✗ then fail();
10470 end match;
10471 end complexity;
10472
10473 protected function complexityBuiltin
10474 input String name;
10475 input DAE.Type tp;
10476 output Integer complexity;
10477 algorithm
10478 complexity := match name
10479 ✗ case "identity" then complexityAlloc+tpComplexity(tp);
10480 case "cross" then 3*3;
10481 else 25;
10482 end match;
10483 end complexityBuiltin;
10484
10485 protected function tpComplexity
10486 input DAE.Type tp;
10487 output Integer i;
10488 algorithm
10489 i := match tp
10490 local
10491 list<DAE.Dimension> dims;
10492 case DAE.T_ARRAY(dims=dims)
10493 algorithm
10494 ✗ i := List.applyAndFold(dims,intMul,dimComplexity,1);
10495 then i;
10496 else 0;
10497 end match;
10498 end tpComplexity;
10499
10500 public function dimComplexity
10501 input DAE.Dimension dim;
10502 output Integer i;
10503 algorithm
10504 i := match dim
10505 case DAE.DIM_INTEGER(integer=i) then i;
10506 case DAE.DIM_ENUM(size=i) then i;
10507 case DAE.DIM_BOOLEAN() then 2;
10508 else complexityDimLarge;
10509 end match;
10510 end dimComplexity;
10511
10512 protected function opComplexity
10513 input DAE.Operator op;
10514 output Integer i;
10515 algorithm
10516 i := match op
10517 local
10518 DAE.Type tp;
10519 case DAE.ADD(ty=DAE.T_STRING()) then 100;
10520 case DAE.ADD() then 1;
10521 case DAE.SUB() then 1;
10522 case DAE.MUL() then 1;
10523 case DAE.DIV() then 1;
10524 case DAE.POW() then 30;
10525 case DAE.UMINUS() then 1;
10526 /* TODO: Array dims? */
10527 ✗ case DAE.UMINUS_ARR(ty=tp) then complexityAlloc+tpComplexity(tp);
10528 ✗ case DAE.ADD_ARR(ty=tp) then complexityAlloc+tpComplexity(tp);
10529 ✗ case DAE.SUB_ARR(ty=tp) then complexityAlloc+tpComplexity(tp);
10530 ✗ case DAE.MUL_ARR(ty=tp) then complexityAlloc+tpComplexity(tp);
10531 ✗ case DAE.DIV_ARR(ty=tp) then complexityAlloc+tpComplexity(tp);
10532 ✗ case DAE.MUL_ARRAY_SCALAR(ty=tp) then complexityAlloc+tpComplexity(tp);
10533 ✗ case DAE.ADD_ARRAY_SCALAR(ty=tp) then complexityAlloc+tpComplexity(tp);
10534 ✗ case DAE.SUB_SCALAR_ARRAY(ty=tp) then complexityAlloc+tpComplexity(tp);
10535 ✗ case DAE.MUL_SCALAR_PRODUCT(ty=tp) then complexityAlloc+3*tpComplexity(tp);
10536 ✗ case DAE.MUL_MATRIX_PRODUCT(ty=tp) then complexityAlloc+3*tpComplexity(tp);
10537 ✗ case DAE.DIV_ARRAY_SCALAR(ty=tp) then complexityAlloc+tpComplexity(tp);
10538 ✗ case DAE.DIV_SCALAR_ARRAY(ty=tp) then complexityAlloc+tpComplexity(tp);
10539 ✗ case DAE.POW_ARRAY_SCALAR(ty=tp) then complexityAlloc+30*tpComplexity(tp);
10540 ✗ case DAE.POW_SCALAR_ARRAY(ty=tp) then complexityAlloc+30*tpComplexity(tp);
10541 ✗ case DAE.POW_ARR(ty=tp) then complexityAlloc+30*tpComplexity(tp);
10542 ✗ case DAE.POW_ARR2(ty=tp) then complexityAlloc+30*tpComplexity(tp);
10543 /* TODO: Array ops? */
10544 case DAE.AND() then 1;
10545 case DAE.OR() then 1;
10546 case DAE.NOT() then 1;
10547 case DAE.LESS() then 1;
10548 case DAE.LESSEQ() then 1;
10549 case DAE.GREATER() then 1;
10550 case DAE.GREATEREQ() then 1;
10551 case DAE.EQUAL() then 1;
10552 case DAE.NEQUAL() then 1;
10553 case DAE.USERDEFINED() then 100;
10554 else
10555 algorithm
10556 ✗ Error.addMessage(Error.INTERNAL_ERROR,{"Expression.opWCET failed"});
10557 ✗ then fail();
10558 end match;
10559 end opComplexity;
10560
10561 public function makeEnumLiterals
10562 "Construct a list of enumeration literal expression given the type name of an
10563 enumeration an a list of literal names."
10564 input Absyn.Path inTypeName;
10565 input list<String> inLiterals;
10566 output list<DAE.Exp> outLiterals;
10567 protected
10568 list<Absyn.Path> enum_lit_names;
10569 algorithm
10570 277 enum_lit_names := List.map1r(inLiterals, AbsynUtil.suffixPath, inTypeName);
10571 277 (outLiterals, _) := List.mapFold(enum_lit_names, makeEnumLiteral, 1);
10572 end makeEnumLiterals;
10573
10574 protected function makeEnumLiteral
10575 "Creates a new enumeration literal. For use with listMapAndFold."
10576 input Absyn.Path name;
10577 input Integer index;
10578 output DAE.Exp enumExp;
10579 output Integer newIndex;
10580 algorithm
10581 1488 enumExp := DAE.ENUM_LITERAL(name, index);
10582
1/2
✓ Branch 0 taken 1488 times.
✗ Branch 1 not taken.
1488 newIndex := index + 1;
10583 end makeEnumLiteral;
10584
10585 public function isWild
10586 input DAE.Exp exp;
10587 output Boolean b;
10588 algorithm
10589 b := match exp
10590 case DAE.CREF(componentRef=DAE.WILD()) then true;
10591 else false;
10592 end match;
10593 end isWild;
10594
10595 public function isNotWild
10596 input DAE.Exp exp;
10597 output Boolean b;
10598 algorithm
10599 b := match exp
10600 case DAE.CREF(componentRef=DAE.WILD()) then false;
10601 else true;
10602 end match;
10603 end isNotWild;
10604
10605 public function dimensionsToExps "Takes a list of dimensions and select the expressions dimensions, returning a list of expressions"
10606 input list<DAE.Dimension> dims;
10607 output list<DAE.Exp> exps = {};
10608 algorithm
10609 ✗ for d in dims loop
10610 exps := match d
10611 local
10612 DAE.Exp exp;
10613 case DAE.DIM_EXP(exp) then exp::exps;
10614 else exps;
10615 end match;
10616 end for;
10617 ✗ exps := listReverse(exps);
10618 end dimensionsToExps;
10619
10620 public function splitRecord
10621 "Splits a record into its elements. Works for crefs, records constructor calls, and casts of the same"
10622 input DAE.Exp inExp;
10623 input DAE.Type ty;
10624 output list<DAE.Exp> outExps;
10625 algorithm
10626 outExps := match (inExp,ty)
10627 local
10628 DAE.Exp exp;
10629 list<DAE.Var> vs;
10630 DAE.ComponentRef cr;
10631 Absyn.Path p1,p2;
10632 list<DAE.Exp> exps;
10633 140 case (DAE.CAST(exp=exp),_) then splitRecord(exp,ty);
10634 case (DAE.CREF(),DAE.T_COMPLEX(complexClassType=ClassInf.EXTERNAL_OBJ(), varLst = {}))
10635 //Don't split External objects
10636 30 then fail();
10637 case (DAE.CREF(componentRef=cr),DAE.T_COMPLEX(varLst = vs))
10638 10053 then List.map1(vs,splitRecord2,cr);
10639 case (DAE.CALL(path=p1,expLst=exps,attr=DAE.CALL_ATTR(ty=DAE.T_COMPLEX(complexClassType=ClassInf.RECORD(p2)))),_)
10640 algorithm
10641
2/2
✓ Branch 1 taken 4198 times.
✓ Branch 2 taken 339 times.
4537 true := AbsynUtil.pathEqual(p1,p2) "is record constructor";
10642 then exps;
10643 case (DAE.RECORD(exps=exps),_)
10644 then exps;
10645 end match;
10646 end splitRecord;
10647
10648 protected function splitRecord2
10649 input DAE.Var var;
10650 input DAE.ComponentRef cr;
10651 output DAE.Exp exp;
10652 protected
10653 String n;
10654 DAE.Type tt,ty;
10655 algorithm
10656 49380 DAE.TYPES_VAR(name = n,ty = tt) := var;
10657 49380 ty := Types.simplifyType(tt);
10658 49380 exp := makeCrefExp(ComponentReference.crefPrependIdent(cr, n, {}, ty), ty);
10659 end splitRecord2;
10660
10661 public function splitArray
10662 "Splits an array into a list of elements."
10663 input DAE.Exp inExp;
10664 output list<DAE.Exp> outExp;
10665 output Boolean didSplit;
10666 algorithm
10667 (outExp,didSplit) := match inExp
10668 local
10669 list<DAE.Exp> expl;
10670 list<list<DAE.Exp>> mat;
10671 Integer istart, istop, istep;
10672 Option<DAE.Exp> step;
10673
10674 case DAE.ARRAY(array = expl) then (expl,true);
10675 ✗ case DAE.MATRIX(matrix = mat) then (List.flatten(mat),true);
10676 case DAE.RANGE(start = DAE.ICONST(istart), step = step, stop = DAE.ICONST(istop))
10677 then (list(DAE.ICONST(i) for i in ExpressionSimplify.simplifyRange(istart,match step case NONE() then 1; case SOME(DAE.ICONST(istep)) then istep; end match,istop)),true);
10678 else ({inExp},false);
10679 end match;
10680 end splitArray;
10681
10682 public function equationExpEqual
10683 input DAE.EquationExp exp1;
10684 input DAE.EquationExp exp2;
10685 output Boolean b;
10686 algorithm
10687 b := match (exp1,exp2)
10688 local
10689 DAE.Exp e1,e2,e3,e4;
10690 ✗ case (DAE.PARTIAL_EQUATION(e1),DAE.PARTIAL_EQUATION(e2)) then ExpressionBasics.expEqual(e1,e2);
10691 ✗ case (DAE.RESIDUAL_EXP(e1),DAE.RESIDUAL_EXP(e2)) then ExpressionBasics.expEqual(e1,e2);
10692 ✗ case (DAE.EQUALITY_EXPS(e1,e2),DAE.EQUALITY_EXPS(e3,e4)) then ExpressionBasics.expEqual(e1,e3) and ExpressionBasics.expEqual(e2,e4);
10693 else false;
10694 end match;
10695 end equationExpEqual;
10696
10697 public function promoteExp
10698 "This function corresponds to the promote function described in the Modelica
10699 spec. It takes an expression, the type of the expression and a number of
10700 dimensions, and adds dimensions of size 1 to the right of the expression
10701 until the expression has as many dimensions as given. It also returns the
10702 type of the promoted expression. E.g.:
10703
10704 promoteExp({1, 2, 3}, Integer[3], 3) =>
10705 ({{{1}}, {{2}}, {{3}}}, Integer[3,1,1])
10706
10707 The reason why this function takes a type instead of using the type of the
10708 expression is because it's used by Static.promoteExp, which already knows the
10709 type."
10710 input DAE.Exp inExp;
10711 input DAE.Type inType;
10712 input Integer inDims;
10713 output DAE.Exp outExp;
10714 output DAE.Type outType;
10715 algorithm
10716 (outExp, outType) := matchcontinue inDims
10717 local
10718 Integer dims_to_add;
10719 DAE.Type ty, res_ty;
10720 DAE.Exp exp;
10721 list<DAE.Type> tys;
10722 list<DAE.Dimension> dims, added_dims;
10723 Boolean is_array_ty;
10724
10725 case _
10726 algorithm
10727 // Figure out how many dimensions we need to add.
10728 5482 dims_to_add := inDims - Types.numberOfDimensions(inType);
10729 // If the expression already has at least as many dimensions as we want,
10730 // fail and return the unchanged expression.
10731
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 5465 times.
5482 true := dims_to_add > 0;
10732
10733 // Construct all the types we will need here, to avoid having to
10734 // construct new types for all the subexpressions created.
10735
10736 // Add as many dimensions of size 1 as needed.
10737 5465 added_dims := List.fill(DAE.DIM_INTEGER(1), dims_to_add);
10738 // Append the dimensions from the type and the added dimensions.
10739 5465 dims := listAppend(TypesDump.getDimensions(inType), added_dims);
10740 // Construct the result type.
10741 5465 ty := Types.arrayElementType(inType);
10742 5465 res_ty := Types.liftArrayListDims(ty, dims);
10743 // Construct the expression types.
10744 5465 ty := Types.simplifyType(ty);
10745 5465 tys := makePromotedTypes(dims, ty, {});
10746
10747 // Use the constructed types to promote the expression.
10748 5465 is_array_ty := Types.isArray(inType);
10749 5465 exp := promoteExp2(inExp, is_array_ty, inDims, tys);
10750 then
10751 (exp, res_ty);
10752
10753 else (inExp, inType);
10754
10755 end matchcontinue;
10756 end promoteExp;
10757
10758 protected function makePromotedTypes
10759 "Creates a lift of types given a list of dimensions and an element type. The
10760 types are created by removing the head of the dimension list one by one and
10761 creating types from the remaining dimensions. E.g.:
10762
10763 makePromotedTypes({[2], [3], [1]}, Real) =>
10764 {Real[2,3,1], Real[3,1], Real[1]}
10765 "
10766 input list<DAE.Dimension> inDimensions;
10767 input DAE.Type inElementType;
10768 input list<DAE.Type> inAccumTypes;
10769 output list<DAE.Type> outAccumTypes;
10770 algorithm
10771 outAccumTypes := match inDimensions
10772 local
10773 list<DAE.Dimension> rest_dims;
10774 DAE.Type ty;
10775
10776 case _ :: rest_dims
10777 algorithm
10778 10930 ty := DAE.T_ARRAY(inElementType, inDimensions);
10779 10930 then
10780 makePromotedTypes(rest_dims, inElementType, ty :: inAccumTypes);
10781
10782 5465 case {} then listReverse(inAccumTypes);
10783
10784 end match;
10785 end makePromotedTypes;
10786
10787 protected function promoteExp2
10788 "Helper function to promoteExp."
10789 input DAE.Exp inExp;
10790 input Boolean inIsArray;
10791 input Integer inDims;
10792 input list<DAE.Type> inTypes;
10793 output DAE.Exp outExp;
10794 algorithm
10795 outExp := match(inExp, inIsArray, inTypes)
10796 local
10797 DAE.Type ty;
10798 list<DAE.Exp> expl;
10799 list<DAE.Type> rest_ty;
10800
10801 // No types left, we're done!
10802 case (_, _, {}) then inExp;
10803
10804 // An array, promote each element in the array.
10805 case (DAE.ARRAY(_, _, expl), _, ty :: rest_ty)
10806 algorithm
10807 156 expl := List.map3(expl, promoteExp2, false, inDims, rest_ty);
10808 156 then
10809 DAE.ARRAY(ty, false, expl);
10810
10811 // An expression with array type, but which is not an array expression. Such
10812 // an expression can't be promoted here, so we create a promote call instead.
10813 case (_, true, ty :: _)
10814 108 then makePureBuiltinCall("promote", {inExp, DAE.ICONST(inDims)}, ty);
10815
10816 // Any other expression, call promoteExp3.
10817 5615 else promoteExp3(inExp, inTypes);
10818
10819 end match;
10820 end promoteExp2;
10821
10822 protected function promoteExp3
10823 "Helper function to promoteExp2. Promotes a scalar expression as many times as
10824 the number of types given."
10825 input DAE.Exp inExp;
10826 input list<DAE.Type> inTypes;
10827 output DAE.Exp outExp;
10828 algorithm
10829 outExp := match inTypes
10830 local
10831 DAE.Type ty;
10832 list<DAE.Type> rest_ty;
10833 DAE.Exp exp;
10834
10835 // No types left, were' done!
10836 case {} then inExp;
10837
10838 // Only one type left, create a scalar array with it.
10839 5615 case {ty} then makeArray({inExp}, ty, true);
10840
10841 // Several types left. Promote the expression using the rest of the types,
10842 // and then create an non-scalar array of the expression with the first type.
10843 case ty :: rest_ty
10844 algorithm
10845 5255 exp := promoteExp3(inExp, rest_ty);
10846 5255 then
10847 makeArray({exp}, ty, false);
10848
10849 end match;
10850 end promoteExp3;
10851
10852 public function matrixToArray
10853 input DAE.Exp inMatrix;
10854 output DAE.Exp outArray;
10855 algorithm
10856 outArray := match inMatrix
10857 local
10858 DAE.Type ty, row_ty;
10859 list<list<Exp>> matrix;
10860 list<DAE.Exp> rows;
10861
10862 case DAE.MATRIX(ty = ty, matrix = matrix)
10863 algorithm
10864 896 row_ty := unliftArray(ty);
10865 896 rows := List.map2(matrix, makeArray, row_ty, true);
10866 896 then
10867 DAE.ARRAY(ty, false, rows);
10868
10869 else inMatrix;
10870
10871 end match;
10872 end matrixToArray;
10873
10874 public function transposeArray
10875 input DAE.Exp inArray;
10876 output DAE.Exp outArray;
10877 output Boolean outWasTransposed;
10878 algorithm
10879 (outArray, outWasTransposed) := match inArray
10880 local
10881 DAE.Type ty, row_ty;
10882 DAE.Dimension dim1, dim2;
10883 DAE.Dimensions rest_dims;
10884 list<Exp> expl;
10885 list<list<Exp>> matrix;
10886 Integer i;
10887
10888 // Empty array, just transpose the type.
10889 case DAE.ARRAY(DAE.T_ARRAY(ty, dim1 :: dim2 :: rest_dims), _, {})
10890 ✗ then (DAE.ARRAY(DAE.T_ARRAY(ty, dim2 :: dim1 :: rest_dims), false, {}), true);
10891
10892 case DAE.ARRAY(DAE.T_ARRAY(ty, dim1 :: dim2 :: rest_dims), _, expl)
10893 algorithm
10894 621 row_ty := DAE.T_ARRAY(ty, dim1 :: rest_dims);
10895 621 matrix := List.map(expl, getArrayOrMatrixContents);
10896 621 matrix := List.transposeList(matrix);
10897 621 expl := List.map2(matrix, makeArray, row_ty, true);
10898 621 then
10899 (DAE.ARRAY(DAE.T_ARRAY(ty, dim2 :: dim1 :: rest_dims), false, expl), true);
10900
10901 case DAE.MATRIX (matrix=matrix,ty=DAE.T_ARRAY(ty, {dim1, dim2}))
10902 algorithm
10903 81 matrix := List.transposeList(matrix);
10904 81 ty := DAE.T_ARRAY(ty, {dim2, dim1});
10905 81 i := listLength(matrix);
10906 81 then
10907 (DAE.MATRIX(ty,i,matrix), true);
10908
10909 else (inArray, false);
10910
10911 end match;
10912 end transposeArray;
10913
10914 public function getCrefFromCrefOrAsub
10915 "Get the cref from an expression that might be ASUB. If so, return the base CREF (this function does *not* always return a CREF with the same type as the full expression)."
10916 input DAE.Exp exp;
10917 output DAE.ComponentRef cr;
10918 algorithm
10919 cr := match exp
10920 case DAE.CREF(componentRef=cr) then cr;
10921 case DAE.ASUB(exp=DAE.CREF(componentRef=cr)) then cr;
10922 end match;
10923 end getCrefFromCrefOrAsub;
10924
10925 public function arrayElements
10926 "Returns the array elements of an expression."
10927 input DAE.Exp inExp;
10928 output list<DAE.Exp> outExp;
10929 algorithm
10930 outExp := match inExp
10931 local
10932 list<DAE.Exp> expl;
10933 DAE.ComponentRef cr;
10934 list<DAE.ComponentRef> crl;
10935 list<list<DAE.Exp>> mat;
10936
10937 case DAE.CREF(componentRef = cr)
10938 algorithm
10939 422620 crl := ComponentReference.expandCref(cr, false);
10940 422620 expl := List.map(crl, crefExp);
10941 then
10942 expl;
10943
10944 case DAE.ARRAY(array = expl, ty = DAE.T_ARRAY())
10945 6260 then List.mapFlat(expl, arrayElements);
10946
10947 case DAE.ARRAY(array = expl) then expl;
10948
10949 ✗ case DAE.MATRIX(matrix = mat) then List.flatten(mat);
10950
10951 else {inExp};
10952
10953 end match;
10954 end arrayElements;
10955
10956 public function arrayContent
10957 "Returns the contents of an array expression, i.e. a list of expressions."
10958 input DAE.Exp inExp;
10959 output list<DAE.Exp> outContent;
10960 algorithm
10961
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 15431 times.
15434 DAE.ARRAY(array = outContent) := inExp;
10962 end arrayContent;
10963
10964 public function fromAbsynExp
10965 "@author: adrpo
10966 transform Absyn.Exp into DAE.Exp, unknown types are used"
10967 input Absyn.Exp inAExp;
10968 output DAE.Exp outDExp;
10969 algorithm
10970 outDExp := match inAExp
10971 local
10972 Integer i;
10973 Real r;
10974 Boolean b;
10975 String s;
10976 Absyn.Exp ae, ae1, ae2, cond;
10977 Absyn.Operator aop;
10978 Absyn.ComponentRef acr;
10979 list<Absyn.Exp> aexps;
10980 list<list<Absyn.Exp>> aexpslst;
10981 Absyn.FunctionArgs fargs;
10982 Absyn.Path p;
10983 Option<Absyn.Exp> aoe;
10984 DAE.ComponentRef cr;
10985 DAE.Exp e, e1, e2;
10986 DAE.Operator op;
10987 list<DAE.Exp> exps;
10988 list<list<DAE.Exp>> expslst;
10989 Option<DAE.Exp> oe;
10990
10991 188 case Absyn.INTEGER(i) then DAE.ICONST(i);
10992 case Absyn.REAL(s)
10993 algorithm
10994 ✗ r := stringReal(s);
10995 ✗ then DAE.RCONST(r);
10996
2/2
✓ Branch 0 taken 602 times.
✓ Branch 1 taken 4559 times.
5763 case Absyn.BOOL(b) then DAE.BCONST(b);
10997 ✗ case Absyn.STRING(s) then DAE.SCONST(s);
10998
10999 case Absyn.CREF(acr)
11000 algorithm
11001 186 cr := ComponentReference.toExpCref(acr);
11002 186 e := makeCrefExp(cr, DAE.T_UNKNOWN_DEFAULT);
11003 then
11004 e;
11005
11006 case Absyn.BINARY(ae1, aop, ae2)
11007 algorithm
11008 15 op := fromAbsynOperator(aop, DAE.T_UNKNOWN_DEFAULT);
11009 15 e1 := fromAbsynExp(ae1);
11010 15 e2 := fromAbsynExp(ae2);
11011 15 e := DAE.BINARY(e1, op, e2);
11012 then
11013 e;
11014
11015 case Absyn.UNARY(aop, ae)
11016 algorithm
11017 ✗ op := fromAbsynOperator(aop, DAE.T_UNKNOWN_DEFAULT);
11018 ✗ e := fromAbsynExp(ae);
11019 ✗ e := DAE.UNARY(op, e);
11020 then
11021 e;
11022
11023 case Absyn.LBINARY(ae1, aop, ae2)
11024 algorithm
11025 1 op := fromAbsynOperator(aop, DAE.T_UNKNOWN_DEFAULT);
11026 1 e1 := fromAbsynExp(ae1);
11027 1 e2 := fromAbsynExp(ae2);
11028 1 e := DAE.LBINARY(e1, op, e2);
11029 then
11030 e;
11031
11032 case Absyn.LUNARY(aop, ae)
11033 algorithm
11034 3 op := fromAbsynOperator(aop, DAE.T_UNKNOWN_DEFAULT);
11035 3 e := fromAbsynExp(ae);
11036 3 e := DAE.LUNARY(op, e);
11037 then
11038 e;
11039
11040 case Absyn.RELATION(ae1, aop, ae2)
11041 algorithm
11042 ✗ op := fromAbsynOperator(aop, DAE.T_UNKNOWN_DEFAULT);
11043 ✗ e1 := fromAbsynExp(ae1);
11044 ✗ e2 := fromAbsynExp(ae2);
11045 ✗ e := DAE.RELATION(e1, op, e2, 0, NONE());
11046 then
11047 e;
11048
11049 case ae as Absyn.IFEXP()
11050 algorithm
11051 ✗ Absyn.IFEXP(ifExp = cond, trueBranch = ae1, elseBranch = ae2) := AbsynUtil.canonIfExp(ae);
11052 ✗ e := fromAbsynExp(cond);
11053 ✗ e1 := fromAbsynExp(ae1);
11054 ✗ e2 := fromAbsynExp(ae2);
11055 ✗ e := DAE.IFEXP(e, e1, e2);
11056 then
11057 e;
11058
11059 case Absyn.CALL(acr, fargs)
11060 algorithm
11061 5 exps := fargsToExps(fargs);
11062 5 p := AbsynUtil.crefToPath(acr);
11063 5 e := DAE.CALL(p, exps, DAE.callAttrBuiltinOther);
11064 then
11065 e;
11066
11067 case Absyn.PARTEVALFUNCTION(acr, fargs)
11068 algorithm
11069 ✗ exps := fargsToExps(fargs);
11070 ✗ p := AbsynUtil.crefToPath(acr);
11071 ✗ e := DAE.PARTEVALFUNCTION(p, exps, DAE.T_UNKNOWN_DEFAULT, DAE.T_UNKNOWN_DEFAULT);
11072 then
11073 e;
11074
11075 case Absyn.ARRAY(aexps)
11076 algorithm
11077 ✗ exps := List.map(aexps, fromAbsynExp);
11078 ✗ e := DAE.ARRAY(DAE.T_UNKNOWN_DEFAULT, false, exps);
11079 then
11080 e;
11081
11082 case Absyn.MATRIX(aexpslst)
11083 algorithm
11084 ✗ expslst := List.mapList(aexpslst, fromAbsynExp);
11085 ✗ i := listLength(listHead(expslst));
11086 ✗ e := DAE.MATRIX(DAE.T_UNKNOWN_DEFAULT, i, expslst);
11087 then
11088 e;
11089
11090 case Absyn.RANGE(ae1, aoe, ae2)
11091 algorithm
11092 20 e1 := fromAbsynExp(ae1);
11093 20 e2 := fromAbsynExp(ae2);
11094 20 oe := fromAbsynExpOpt(aoe);
11095 20 e := DAE.RANGE(DAE.T_UNKNOWN_DEFAULT, e1, oe, e2);
11096 then
11097 e;
11098
11099 case Absyn.TUPLE(aexps)
11100 algorithm
11101 ✗ exps := List.map(aexps, fromAbsynExp);
11102 ✗ e := DAE.TUPLE(exps);
11103 then
11104 e;
11105
11106 else
11107 algorithm
11108 ✗ print("Expression.fromAbsynExp: Unhandled expression: " + Dump.printExpStr(inAExp) + "\n");
11109 ✗ then
11110 fail();
11111
11112 end match;
11113 end fromAbsynExp;
11114
11115 public function fargsToExps
11116 input Absyn.FunctionArgs inFargs;
11117 output list<DAE.Exp> outExps;
11118 algorithm
11119 outExps := matchcontinue inFargs
11120 local
11121 list<DAE.Exp> exps;
11122 list<Absyn.Exp> aexps;
11123
11124 case Absyn.FUNCTIONARGS(aexps, {})
11125 algorithm
11126 5 exps := List.map(aexps, fromAbsynExp);
11127 then
11128 exps;
11129
11130 case Absyn.FUNCTIONARGS(_, _)
11131 algorithm
11132 ✗ print("Expression.fargsToExps: Named arguments are not handled!\n");
11133 then
11134 {};
11135
11136 end matchcontinue;
11137 end fargsToExps;
11138
11139 protected function fromAbsynExpOpt
11140 input Option<Absyn.Exp> aoe;
11141 output Option<DAE.Exp> oe;
11142 algorithm
11143 oe := match aoe
11144 local
11145 Absyn.Exp ae;
11146 DAE.Exp e;
11147
11148 case NONE() then NONE();
11149
11150 case SOME(ae)
11151 algorithm
11152 ✗ e := fromAbsynExp(ae);
11153 then
11154 SOME(e);
11155
11156 end match;
11157 end fromAbsynExpOpt;
11158
11159 protected function fromAbsynOperator
11160 "@author: adrpo"
11161 input Absyn.Operator aop;
11162 input DAE.Type ty;
11163 output DAE.Operator op;
11164 algorithm
11165 op := match aop
11166 7 case Absyn.ADD() then DAE.ADD(ty);
11167 8 case Absyn.SUB() then DAE.SUB(ty);
11168 ✗ case Absyn.MUL() then DAE.MUL(ty);
11169 ✗ case Absyn.DIV() then DAE.DIV(ty);
11170 ✗ case Absyn.POW() then DAE.POW(ty);
11171 ✗ case Absyn.UMINUS() then DAE.UMINUS(ty);
11172 1 case Absyn.AND() then DAE.AND(ty);
11173 ✗ case Absyn.OR() then DAE.OR(ty);
11174 3 case Absyn.NOT() then DAE.NOT(ty);
11175 ✗ case Absyn.LESS() then DAE.LESS(ty);
11176 ✗ case Absyn.LESSEQ() then DAE.LESSEQ(ty);
11177 ✗ case Absyn.GREATER() then DAE.GREATER(ty);
11178 ✗ case Absyn.GREATEREQ() then DAE.GREATEREQ(ty);
11179 ✗ case Absyn.EQUAL() then DAE.EQUAL(ty);
11180 ✗ case Absyn.NEQUAL() then DAE.NEQUAL(ty);
11181 else
11182 algorithm
11183 ✗ print("Expression.fromAbsynOperator: Unhandled operator: " + Dump.opSymbol(aop) + "\n");
11184 ✗ then
11185 fail();
11186 end match;
11187 end fromAbsynOperator;
11188
11189 public function replaceDerOpInExp
11190 "Replaces all der(cref) with $DER.cref in an expression."
11191 input DAE.Exp inExp;
11192 output DAE.Exp outExp;
11193 algorithm
11194 24675 (outExp, _) := traverseExpBottomUp(inExp, replaceDerOpInExpTraverser, NONE());
11195 end replaceDerOpInExp;
11196
11197 public function replaceDerOpInExpCond
11198 "Replaces der(cref) with $DER.cref in an expression, where the cref to replace
11199 is explicitly given."
11200 input DAE.Exp e;
11201 input Option<DAE.ComponentRef> cr;
11202 output DAE.Exp outExp;
11203 output Option<DAE.ComponentRef> outCr;
11204 algorithm
11205 283811 (outExp, outCr) := traverseExpBottomUp(e, replaceDerOpInExpTraverser, cr);
11206 end replaceDerOpInExpCond;
11207
11208 public function replaceDerOpInExpTraverser
11209 "Used with Expression.traverseExpBottomUp to traverse an expression an replace calls to
11210 der(cref) with a component reference $DER.cref. If an optional component
11211 reference is supplied, then only that component reference is replaced.
11212 Otherwise all calls to der are replaced.
11213
11214 This is done since some parts of the compiler can't handle der-calls, such as
11215 Derive.differentiateExpression. Ideally these parts should be fixed so that they can
11216 handle der-calls, but until that happens we just replace the der-calls with
11217 crefs."
11218 input DAE.Exp e;
11219 input Option<DAE.ComponentRef> optCr;
11220 output DAE.Exp outExp;
11221 output Option<DAE.ComponentRef> outCr;
11222 algorithm
11223 (outExp,outCr) := matchcontinue (e,optCr)
11224 local
11225 DAE.ComponentRef cr, derCr;
11226 DAE.Exp cref_exp;
11227 DAE.ComponentRef cref;
11228
11229 case (DAE.CALL(path = Absyn.IDENT("der"), expLst = {DAE.CREF(componentRef = cr)}), SOME(cref))
11230 algorithm
11231 ✗ derCr := ComponentReference.crefPrefixDer(cr);
11232 ✗ true := ComponentReferenceBasics.crefEqualNoStringCompare(derCr, cref);
11233 ✗ cref_exp := crefExp(derCr);
11234 then (cref_exp, optCr);
11235
11236 case (DAE.CALL(path = Absyn.IDENT("der"), expLst = {DAE.CREF(componentRef = cr)}), NONE())
11237 algorithm
11238 19263 cr := ComponentReference.crefPrefixDer(cr);
11239 19263 cref_exp := crefExp(cr);
11240 then (cref_exp, NONE());
11241 else (e,optCr);
11242 end matchcontinue;
11243 end replaceDerOpInExpTraverser;
11244
11245 public function makeBinaryExp
11246 input DAE.Exp inLhs;
11247 input DAE.Operator inOp;
11248 input DAE.Exp inRhs;
11249 output DAE.Exp outExp;
11250 algorithm
11251 7714 outExp := DAE.BINARY(inLhs, inOp, inRhs);
11252 end makeBinaryExp;
11253
11254 public function checkExpDimensionSizes
11255 "Extracts an integer from an exp"
11256 input DAE.Exp dim;
11257 output Boolean value;
11258 algorithm
11259 value := match dim
11260 ✗ case DAE.ICONST() then dim.integer > 0;
11261 else
11262 false;
11263 end match;
11264 end checkExpDimensionSizes;
11265
11266 public function checkDimensionSizes
11267 "Extracts an integer from an array dimension. Also handles DIM_EXP and
11268 DIM_UNKNOWN if checkModel is used."
11269 input DAE.Dimension dim;
11270 output Boolean value;
11271 algorithm
11272 value := match dim
11273 case DAE.DIM_INTEGER() then true;
11274 case DAE.DIM_ENUM() then true;
11275 case DAE.DIM_BOOLEAN() then true;
11276 case DAE.DIM_EXP() then true;
11277 case DAE.DIM_UNKNOWN() then false;
11278 end match;
11279 end checkDimensionSizes;
11280
11281 public function dimensionsList
11282 "Extracts a list of integers from a list of array dimensions"
11283 input DAE.Dimensions inDims;
11284 output list<Integer> outValues;
11285 protected
11286 list<Integer> dims;
11287 algorithm
11288 outValues := matchcontinue inDims
11289 case _
11290 algorithm
11291
2/2
✓ Branch 1 taken 45 times.
✓ Branch 2 taken 6088 times.
6133 true := List.all(inDims, checkDimensionSizes);
11292 6088 dims := List.map(inDims, dimensionSizeAll);
11293 then dims;
11294 else {};
11295 end matchcontinue;
11296 end dimensionsList;
11297
11298 public function hasZeroDimension
11299 "Returns true if at least one dimension is zero or dimensions is empty list."
11300 input DAE.Dimensions inDims;
11301 output Boolean hasZeroDimension = false;
11302 protected
11303 list<Integer> intDims;
11304 algorithm
11305
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4345 times.
4345 if listEmpty(inDims)then
11306 hasZeroDimension := true;
11307 ✗ return;
11308 end if;
11309 4345 intDims := dimensionsList(inDims);
11310
2/2
✓ Branch 0 taken 5010 times.
✓ Branch 1 taken 4342 times.
9352 for dim in intDims loop
11311
2/2
✓ Branch 0 taken 5007 times.
✓ Branch 1 taken 3 times.
5010 if dim == 0 then
11312 hasZeroDimension := true;
11313 break;
11314 end if;
11315 end for;
11316 end hasZeroDimension;
11317
11318 public function expDimensionsList
11319 "Extracts a list of integers from a list of expressions"
11320 input list<DAE.Exp> inDims;
11321 output list<Integer> outValues;
11322 protected
11323 list<Integer> dims;
11324 algorithm
11325 outValues := matchcontinue inDims
11326 case _
11327 algorithm
11328 ✗ true := List.all(inDims, checkExpDimensionSizes);
11329 ✗ dims := List.map(inDims, expInt);
11330 then dims;
11331 else {};
11332 end matchcontinue;
11333 end expDimensionsList;
11334
11335 public function isCrefListWithEqualIdents
11336 "Checks if all expressions in the given list are crefs with the same identifiers.
11337 e.g. {A[1],A[2],…,A[n]} -> true
11338 {A[1],B[1]} -> false"
11339 input list<DAE.Exp> iExpressions;
11340 output Boolean oCrefWithEqualIdents;
11341 protected
11342 Boolean tmpCrefWithEqualIdents;
11343 list<DAE.ComponentRef> crefs;
11344 DAE.Exp head;
11345 DAE.ComponentRef headCref;
11346 algorithm
11347 oCrefWithEqualIdents := matchcontinue iExpressions
11348 case head::_
11349 algorithm
11350 //print("isCrefListWithEqualIdents: \n" + stringDelimitList(List.map1(iExpressions, ExpressionDump.dumpExpStr, 1), ""));
11351 ✗ true := List.all(iExpressions, isCref);
11352 //print("isCrefListWithEqualIdents: all crefs!\n");
11353 ✗ crefs := List.map(iExpressions, expCref);
11354 ✗ headCref := expCref(head);
11355 ✗ tmpCrefWithEqualIdents := List.all(crefs, function ComponentReferenceBasics.crefEqualWithoutLastSubs(cr2 = headCref));
11356 //print("isCrefListWithEqualIdents: returns " + boolString(tmpCrefWithEqualIdents) + "\n\n");
11357 then tmpCrefWithEqualIdents;
11358 case {}
11359 then true;
11360 else
11361 algorithm
11362 //print("isCrefListWithEqualIdents: returns false\n\n");
11363 then false;
11364 end matchcontinue;
11365 end isCrefListWithEqualIdents;
11366
11367 public function renameExpCrefIdent
11368 input DAE.Exp inExp;
11369 input tuple<String,String> inTpl;
11370 output DAE.Exp outExp;
11371 output tuple<String,String> outTpl;
11372 algorithm
11373 (outExp,outTpl) := match (inExp,inTpl)
11374 local
11375 DAE.Type ty1,ty2;
11376 String name,from,to;
11377 DAE.Exp exp;
11378 case (DAE.CREF(DAE.CREF_IDENT(name,ty1,{}),ty2),(from,to))
11379 algorithm
11380 ✗ exp := if stringEq(name,from) then DAE.CREF(DAE.CREF_IDENT(to,ty1,{}),ty2) else inExp;
11381 then (exp,inTpl);
11382 else (inExp,inTpl);
11383 end match;
11384 end renameExpCrefIdent;
11385
11386 public function emptyToWild
11387 input DAE.Exp exp;
11388 output DAE.Exp outExp;
11389 protected
11390 DAE.Type ty;
11391 algorithm
11392 117 ty := typeof(exp);
11393
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 117 times.
117 outExp := if Types.isZeroLengthArray(ty) then DAE.CREF(DAE.WILD(),ty) else exp;
11394 end emptyToWild;
11395
11396 public function makeVectorCall
11397 input DAE.Exp exp;
11398 input DAE.Type tp;
11399 output DAE.Exp outExp;
11400 algorithm
11401 ✗ outExp := makePureBuiltinCall("vector",{exp},tp);
11402 end makeVectorCall;
11403
11404
11405 public function expandCrefs
11406 input DAE.Exp inExp;
11407 input Boolean expandRecord;
11408 output DAE.Exp outExp;
11409 input output Integer dummy=0 "For traversal";
11410 algorithm
11411 outExp := match inExp
11412 local
11413 DAE.Type arr_ty;
11414 list<DAE.Exp> exp_lst;
11415 DAE.Exp exp;
11416 case DAE.CREF(ty=arr_ty as DAE.T_ARRAY()) algorithm
11417
4/4
✓ Branch 1 taken 766 times.
✓ Branch 2 taken 77 times.
✓ Branch 3 taken 766 times.
✓ Branch 4 taken 77 times.
843 exp_lst := list(makeCrefExp(cr, arr_ty.ty) for cr in ComponentReference.expandCref(inExp.componentRef, expandRecord));
11418 77 exp := listToArray(exp_lst, arr_ty.dims);
11419 then exp;
11420 else inExp;
11421 end match;
11422 end expandCrefs;
11423
11424 public function expandExpression
11425 " mahge:
11426 Expands a given expression to a list of expression. this means flattening any records in the
11427 expression and vectorizing arrays.
11428
11429 Currently can only handle crefs and array expressions. Maybe we need to handle binary operations at least.
11430
11431 Right now this is used in generating simple residual equations from complex ones in SimCode.
11432 "
11433
11434 input DAE.Exp inExp;
11435 input Boolean expandRecord;
11436 output list<DAE.Exp> outExps;
11437 algorithm
11438 outExps := match inExp
11439 local
11440 DAE.ComponentRef cr;
11441 list<DAE.ComponentRef> crlst;
11442 list<DAE.Exp> expl = {}, expl1, expl2;
11443 String msg;
11444 DAE.Exp e1, e2;
11445 DAE.Operator op;
11446
11447 case DAE.CREF(cr,_)
11448 algorithm
11449 35649 crlst := ComponentReference.expandCref(cr, expandRecord);
11450 35649 outExps := List.map(crlst, crefToExp);
11451 then outExps;
11452
11453 case DAE.UNARY(operator=DAE.UMINUS())
11454 algorithm
11455 ✗ expl := list(DAE.UNARY(inExp.operator, exp) for exp in expandExpression(inExp.exp, expandRecord));
11456 then expl;
11457
11458 case DAE.BINARY()
11459 algorithm
11460 // TODO! FIXME! we should change the type in the operator,
11461 // i.e. use Types.unliftArray on the type inside the operator
11462 ✗ op := inExp.operator;
11463 ✗ expl1 := expandExpression(inExp.exp1, expandRecord);
11464 ✗ expl2 := expandExpression(inExp.exp2, expandRecord);
11465 // TODO! FIXME! maybe we should also support (array op scalar)
11466 // make sure the lists have the same length
11467 ✗ if listLength(expl1) <> listLength(expl2) then
11468 ✗ fail();
11469 end if;
11470 ✗ e1 := listGet(expl1, 1);
11471 ✗ e2 := listGet(expl1, 2);
11472 ✗ for i in 1:listLength(expl1) loop
11473 ✗ e1 := listGet(expl1, i);
11474 ✗ e2 := listGet(expl2, i);
11475 ✗ expl := DAE.BINARY(e1, op, e2)::expl;
11476 end for;
11477 ✗ expl := listReverse(expl);
11478 then expl;
11479
11480 case DAE.ARRAY(_,_,expl)
11481 algorithm
11482 ✗ expl := List.mapFlat(expl, function expandExpression(expandRecord = expandRecord));
11483 then expl;
11484
11485 else
11486 algorithm
11487 ✗ msg := "- Expression.expandExpression failed for " + ExpressionBasics.printExpStr(inExp);
11488 ✗ Error.addMessage(Error.INTERNAL_ERROR, {msg});
11489 ✗ then
11490 fail();
11491 end match;
11492
11493 end expandExpression;
11494
11495 public function extendArrExp "author: Frenkel TUD 2010-07
11496 alternative name: vectorizeExp"
11497 input DAE.Exp inExp;
11498 input Boolean inExpanded = false "True if something was expanded, otherwise false.";
11499 output DAE.Exp outExp;
11500 output Boolean outExpanded;
11501 algorithm
11502 (outExp, outExpanded) := matchcontinue inExp
11503 local
11504 DAE.Exp exp;
11505 Boolean b;
11506
11507 case outExp
11508 algorithm
11509 169843 (exp, b) := traverseExpBottomUp(inExp, traversingextendArrExp, false);
11510 then
11511 (exp, b);
11512
11513 else (inExp, inExpanded);
11514
11515 end matchcontinue;
11516 end extendArrExp;
11517
11518 protected function traversingextendArrExp "author: Frenkel TUD 2010-07.
11519 This function extend all array and record componentrefs to their
11520 elements. This is necessary for BLT and substitution of simple
11521 equations."
11522 input DAE.Exp inExp;
11523 input Boolean inExpanded;
11524 output DAE.Exp outExp;
11525 output Boolean outExpanded;
11526 algorithm
11527 (outExp, outExpanded) := match inExp
11528 local
11529 DAE.ComponentRef cr;
11530 DAE.Type ty;
11531 DAE.Dimension id, jd;
11532 Integer i, j;
11533 list<DAE.Exp> expl;
11534 DAE.Exp e;
11535 list<DAE.Var> varLst;
11536 Absyn.Path name;
11537 list<list<DAE.Exp>> mat;
11538 list<String> field_names;
11539
11540 // CASE for Matrix
11541 case DAE.CREF(ty=ty as DAE.T_ARRAY(dims={id, jd}))
11542 algorithm
11543 8258 i := dimensionSize(id);
11544 8258 j := dimensionSize(jd);
11545 8258 expl := expandExpression(inExp, expandRecord = false);
11546 8258 mat := makeMatrix(expl, j);
11547 8258 e := DAE.MATRIX(ty, i, mat);
11548 then
11549 (e, true);
11550
11551 // CASE for Array
11552 case DAE.CREF(ty=ty as DAE.T_ARRAY())
11553 algorithm
11554 25817 expl := expandExpression(inExp, expandRecord = false);
11555 25817 e := DAE.ARRAY(ty, true, expl);
11556 then
11557 (e, true);
11558
11559 // CASE for Records
11560 case DAE.CREF(componentRef=cr, ty=ty as DAE.T_COMPLEX(varLst=varLst, complexClassType=ClassInf.RECORD(name)))
11561 algorithm
11562 8225 expl := List.map1(varLst, generateCrefsExpFromExpVar, cr);
11563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8225 times.
8225 true := not listEmpty(expl);
11564
4/4
✓ Branch 0 taken 32408 times.
✓ Branch 1 taken 8225 times.
✓ Branch 2 taken 32408 times.
✓ Branch 3 taken 8225 times.
40633 field_names := list(v.name for v in varLst);
11565 8225 e := DAE.RECORD(name, expl, field_names, ty);
11566 8225 (e, _) := traverseExpBottomUp(e, traversingextendArrExp, true);
11567 then
11568 (e, true);
11569
11570 else (inExp, inExpanded);
11571
11572 end match;
11573 end traversingextendArrExp;
11574
11575 protected function makeMatrix
11576 input list<DAE.Exp> expl;
11577 input Integer n;
11578 output list<list<DAE.Exp>> res;
11579 protected
11580 list<DAE.Exp> col;
11581 Integer r;
11582 import listReverse = MetaModelica.Dangerous.listReverseInPlace;
11583 algorithm
11584 res := {};
11585 col := {};
11586 r := n;
11587
2/2
✓ Branch 0 taken 74230 times.
✓ Branch 1 taken 8258 times.
82488 for e in expl loop
11588 74230 r := r-1;
11589 col := e::col;
11590
2/2
✓ Branch 0 taken 24850 times.
✓ Branch 1 taken 49380 times.
74230 if r==0 then
11591 24850 res := listReverse(col)::res;
11592 col := {};
11593 r := n;
11594 end if;
11595 end for;
11596 8258 Error.assertionOrAddSourceMessage(listEmpty(col), Error.INTERNAL_ERROR, {"Expression.makeMatrix failed"}, sourceInfo());
11597 8258 res := listReverse(res);
11598 end makeMatrix;
11599
11600 public function rangesToSubscripts
11601 "This function takes a list of subscript ranges representing dimensions, e.g.
11602 {{1, 2, 3}, {1, 2}} which corresponds to dimensions [3, 2], and generates
11603 all subscript combinations, e.g. {{1, 1}, {1, 2}, {2, 1}, {2, 2}, {3, 1},
11604 {3, 2}}."
11605 input list<list<DAE.Subscript>> inRangelist;
11606 output list<list<DAE.Subscript>> outSubslst;
11607 algorithm
11608 2201 outSubslst := List.allCombinations(inRangelist, NONE(), Absyn.dummyInfo);
11609 end rangesToSubscripts;
11610
11611 public function expandSubscript
11612 "Expands a subscript into a list of subscripts. Also takes a dimension to be
11613 able to evaluate : subscripts."
11614 input DAE.Subscript inSubscript;
11615 input DAE.Dimension inDimension;
11616 output list<DAE.Subscript> outSubscripts;
11617 algorithm
11618 outSubscripts := match inSubscript
11619 local
11620 DAE.Exp exp;
11621
11622 // An index subscript from range.
11623 case DAE.INDEX(exp = DAE.RANGE())
11624
4/4
✓ Branch 1 taken 16167 times.
✓ Branch 2 taken 9115 times.
✓ Branch 3 taken 16167 times.
✓ Branch 4 taken 9115 times.
25470 then list(DAE.INDEX(e) for e in expandRange(inSubscript.exp));
11625
11626 // An index subscript from array.
11627 // This really shouldn't be happening. But the backend creats things like this.
11628 // e.g. When finding Adjacency Matrix entry for for-loops in Algorithm sections.
11629 // That whole creating IM should be done the way checkModel works. but it's not. :( so
11630 // we have this.
11631 case DAE.INDEX(exp = DAE.ARRAY())
11632 ✗ then expandSliceExp(inSubscript.exp);
11633
11634 // An index subscript, return it as an array.
11635 case DAE.INDEX() then {inSubscript};
11636
11637 // A : subscript, use the dimension to generate all subscripts.
11638 case DAE.WHOLEDIM()
11639 97605 then expandDimension(inDimension);
11640
11641 // A slice subscript.
11642 case DAE.SLICE()
11643 287 then expandSliceExp(inSubscript.exp);
11644
11645 end match;
11646 end expandSubscript;
11647
11648 public function expandDimension
11649 "Generates a list of subscripts given an array dimension."
11650 input DAE.Dimension inDimension;
11651 output list<DAE.Subscript> outSubscript;
11652 algorithm
11653 outSubscript := match inDimension
11654 local
11655 Integer dim_int;
11656 Absyn.Path enum_ty;
11657 list<String> enum_lits;
11658 list<DAE.Exp> enum_expl;
11659
11660 // An integer dimension, generate a list of integer subscripts.
11661 case DAE.DIM_INTEGER(integer = dim_int)
11662 97030 then dimensionSizeSubscripts(dim_int);
11663
11664 // An enumeration dimension, construct all enumeration literals and make
11665 // subscript out of them.
11666 case DAE.DIM_ENUM(enumTypeName = enum_ty, literals = enum_lits)
11667 algorithm
11668 242 enum_expl := makeEnumLiterals(enum_ty, enum_lits);
11669 242 then
11670 List.map(enum_expl, makeIndexSubscript);
11671
11672 case DAE.DIM_BOOLEAN()
11673 then DAE.INDEX(DAE.BCONST(false))::DAE.INDEX(DAE.BCONST(true))::{};
11674
11675 else {};
11676 end match;
11677 end expandDimension;
11678
11679 public function expandSliceExp
11680 "Expands a slice subscript expression."
11681 input DAE.Exp inSliceExp;
11682 output list<DAE.Subscript> outSubscripts;
11683 algorithm
11684 outSubscripts := match inSliceExp
11685 local
11686 list<DAE.Exp> expl;
11687
11688 case DAE.ARRAY(array = expl)
11689 159 then List.map(expl, makeIndexSubscript);
11690
11691 case DAE.RANGE()
11692 207 then List.map(Expression.expandRange(inSliceExp), makeIndexSubscript);
11693
11694 end match;
11695 end expandSliceExp;
11696
11697 public function dimensionSizesSubscripts
11698 input list<Integer> inDimSizes;
11699 output list<list<DAE.Subscript>> outSubscripts;
11700 algorithm
11701 26 outSubscripts := List.map(inDimSizes, dimensionSizeSubscripts);
11702 end dimensionSizesSubscripts;
11703
11704 public function dimensionSizesSubcriptsOpt
11705 input list<Option<Integer>> inDimSizes;
11706 output list<list<DAE.Subscript>> outSubscripts;
11707 algorithm
11708 ✗ outSubscripts := List.mapOption(inDimSizes, dimensionSizeSubscripts);
11709 end dimensionSizesSubcriptsOpt;
11710
11711 public function dimensionSizeSubscripts
11712 "Converts a dimension size in the form of an integer into a list of
11713 subscripts, e.g.: [3] => {1, 2, 3}."
11714 input Integer inDimSize;
11715 output list<DAE.Subscript> outSubscripts;
11716 algorithm
11717
2/2
✓ Branch 0 taken 339668 times.
✓ Branch 1 taken 99837 times.
439505 outSubscripts := list(DAE.INDEX(DAE.ICONST(i)) for i in 1:inDimSize);
11718 end dimensionSizeSubscripts;
11719
11720 public function createResidualExp
11721 "author: Frenkel TUD 2012-10
11722 do some numerical helpfull thinks like
11723 a = b/c - > a*c-b"
11724 input DAE.Exp inExp1;
11725 input DAE.Exp inExp2;
11726 output DAE.Exp resExp;
11727 protected
11728 DAE.Exp iExp1, iExp2;
11729 algorithm
11730 34512 (iExp1,iExp2) := createResidualExp2(inExp1,inExp2);
11731
11732 resExp := matchcontinue(iExp1, iExp2)
11733 local
11734 DAE.Exp res, res1, res2, N1, D1, N2, D2;
11735 list<DAE.Exp> explst, explst1;
11736 DAE.Type ty;
11737
11738 4623 case(_, DAE.RCONST(real = 0.0)) then iExp1;
11739 ✗ case(_, DAE.ICONST(0)) then iExp1;
11740 ✗ case(DAE.RCONST(real = 0.0), _) then iExp2;
11741 ✗ case(DAE.ICONST(0), _) then iExp2;
11742 case(_, _)
11743 algorithm
11744 29889 ty := typeof(iExp1);
11745
2/2
✓ Branch 1 taken 259 times.
✓ Branch 2 taken 29630 times.
29889 true := Types.isIntegerOrRealOrSubTypeOfEither(ty);
11746 // N1/D1 = N2/D2
11747 29630 (N1,D1) := makeFraction(iExp1);
11748 29630 (N2,D2) := makeFraction(iExp2);
11749 // N1*D2 = N2*D1 // simplify N1*D2 e.g. N1*D2 = (a/b + c)*b -> a+c/b
11750 29630 res1 := ExpressionSimplify.simplifySumOperatorExpression(N1, DAE.MUL(ty), D2);
11751 29630 res2 := ExpressionSimplify.simplifySumOperatorExpression(N2, DAE.MUL(ty), D1);
11752
11753 //heuristic
11754 29630 explst := terms(iExp1);
11755 29630 explst1 := terms(iExp2);
11756
4/4
✓ Branch 1 taken 29499 times.
✓ Branch 2 taken 131 times.
✓ Branch 5 taken 28496 times.
✓ Branch 6 taken 1003 times.
29630 if isConst(res1) or (listLength(explst1) + 1) > listLength(explst) then
11757 28627 res := expSub(res2,res1);
11758 else
11759 1003 res := expSub(res1,res2);
11760 end if;
11761
11762 29630 (res, _) := ExpressionSimplify.simplify(res);
11763 //print("\n\niExp1:\n");print(ExpressionBasics.printExpStr(iExp1));
11764 //print("\niExp2:\n");print(ExpressionBasics.printExpStr(iExp2));
11765 //print("\nres:\n");print(ExpressionBasics.printExpStr(res));
11766 then
11767 res;
11768 case(_, _)
11769 algorithm
11770 259 ty := typeof(iExp1);
11771
1/2
✓ Branch 1 taken 259 times.
✗ Branch 2 not taken.
259 true := Types.isEnumeration(ty);
11772 ✗ res := expSub(iExp1, iExp2);
11773 then
11774 res;
11775 case(_, _)
11776 algorithm
11777 259 ty := typeof(iExp1);
11778
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 255 times.
259 true := Types.isBooleanOrSubTypeBoolean(ty);
11779 255 res := DAE.LUNARY(DAE.NOT(ty), DAE.RELATION(iExp1, DAE.EQUAL(ty), iExp2, -1, NONE()));
11780 then
11781 res;
11782 case(_, _)
11783 algorithm
11784 4 ty := typeof(iExp1);
11785
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 true := Types.isStringOrSubTypeString(ty);
11786 ✗ res := DAE.LUNARY(DAE.NOT(ty), DAE.RELATION(iExp1, DAE.EQUAL(ty), iExp2, -1, NONE()));
11787 then
11788 res;
11789 else
11790 algorithm
11791 4 res := expSub(iExp1, iExp2);
11792 ✗ (res, _) := ExpressionSimplify.simplify(res);
11793 then
11794 res;
11795 end matchcontinue;
11796 end createResidualExp;
11797
11798 public function makeFraction
11799 "
11800 In: f(x) {+,-} g(x)
11801 Out: {N,D}
11802
11803 where f(x) {+,-} g(x) = N/D
11804
11805 author: Vitalij Ruge
11806
11807 "
11808 input DAE.Exp iExp;
11809 output DAE.Exp n "numerator";
11810 output DAE.Exp d "denominator";
11811 protected
11812 list<DAE.Exp> N, D, T;
11813 algorithm
11814 73899 T := terms(iExp);
11815 73899 T := ExpressionSimplify.simplifyList(T);
11816 73899 (N,D) := moveDivToMul(T, {}, {});
11817 73899 N := ExpressionSimplify.simplifyList(N);
11818 73899 D := ExpressionSimplify.simplifyList(D);
11819 73899 n := makeSum1(N);
11820 73899 d := makeProductLst(D);
11821 73899 (n,_) := ExpressionSimplify.simplify1(n);
11822 73899 (d,_) := ExpressionSimplify.simplify1(d);
11823 end makeFraction;
11824
11825 protected function moveDivToMul
11826 input list<DAE.Exp> iExpLst;
11827 input list<DAE.Exp> iExpLstAcc;
11828 input list<DAE.Exp> iExpMuls;
11829 output list<DAE.Exp> oExpLst;
11830 output list<DAE.Exp> oExpMuls;
11831 algorithm
11832 (oExpLst, oExpMuls) := match iExpLst
11833 local
11834 DAE.Exp e, e1, e2;
11835 list<DAE.Exp> rest, acc, elst, elst1;
11836 case {} then (iExpLstAcc, iExpMuls);
11837 //-(a/b)
11838 case DAE.UNARY(_,DAE.BINARY(exp1=e1, operator=DAE.DIV(), exp2=e2))::rest
11839 algorithm
11840 ✗ acc := List.map1(iExpLstAcc, Expression.expMul, e2);
11841 ✗ rest := List.map1(rest, Expression.expMul, e2);
11842 ✗ rest := ExpressionSimplify.simplifyList(rest);
11843 ✗ (elst, elst1) := moveDivToMul(rest, negate(e1)::acc, e2::iExpMuls);
11844 then
11845 (elst, elst1);
11846 case DAE.UNARY(_,DAE.BINARY(exp1=e1, operator=DAE.DIV_ARRAY_SCALAR(), exp2=e2))::rest
11847 algorithm
11848 ✗ acc := List.map1(iExpLstAcc, Expression.expMul, e2);
11849 ✗ rest := List.map1(rest, Expression.expMul, e2);
11850 ✗ rest := ExpressionSimplify.simplifyList(rest);
11851 ✗ (elst, elst1) := moveDivToMul(rest, negate(e1)::acc, e2::iExpMuls);
11852 then
11853 (elst, elst1);
11854 // a/b
11855 case DAE.BINARY(exp1=e1, operator=DAE.DIV(), exp2=e2)::rest
11856 algorithm
11857 1761 acc := List.map1(iExpLstAcc, Expression.expMul, e2);
11858 1761 rest := List.map1(rest, Expression.expMul, e2);
11859 1761 rest := ExpressionSimplify.simplifyList(rest);
11860 1761 (elst, elst1) := moveDivToMul(rest, e1::acc, e2::iExpMuls);
11861 then
11862 (elst, elst1);
11863 case DAE.BINARY(exp1=e1, operator=DAE.DIV_ARRAY_SCALAR(), exp2=e2)::rest
11864 algorithm
11865 ✗ acc := List.map1(iExpLstAcc, Expression.expMul, e2);
11866 ✗ rest := List.map1(rest, Expression.expMul, e2);
11867 ✗ rest := ExpressionSimplify.simplifyList(rest);
11868 ✗ (elst, elst1) := moveDivToMul(rest, e1::acc, e2::iExpMuls);
11869 then
11870 (elst, elst1);
11871 case e::rest
11872 algorithm
11873 107705 (elst, elst1) := moveDivToMul(rest, e::iExpLstAcc, iExpMuls);
11874 then
11875 (elst, elst1);
11876 end match;
11877 end moveDivToMul;
11878
11879 protected function createResidualExp2
11880 "author: Vitalij
11881 do some numerical helpfull thinks on like
11882 sqrt(f()) - sqrt(g(.)) = 0 -> f(.) - g(.)"
11883 input DAE.Exp iExp1;
11884 input DAE.Exp iExp2;
11885 output DAE.Exp oExp1 = iExp1;
11886 output DAE.Exp oExp2 = iExp2;
11887 protected
11888 Boolean con = true, con1;
11889 Integer ii = 1;
11890 algorithm
11891
11892
2/2
✓ Branch 0 taken 34577 times.
✓ Branch 1 taken 34512 times.
69089 while con and ii < 15 loop
11893 (oExp1, oExp2, con) := matchcontinue oExp2
11894 local DAE.Exp e1, e2;
11895
11896 case _
11897 algorithm
11898
2/2
✓ Branch 1 taken 34574 times.
✓ Branch 2 taken 3 times.
34577 (e1,e2,true) := createResidualExp3(oExp1, oExp2);
11899 3 (e1,_) := ExpressionSimplify.simplify1(e1);
11900 3 (e2,_) := ExpressionSimplify.simplify1(e2);
11901 then (e1 ,e2, true);
11902
11903 case _
11904 algorithm
11905
2/2
✓ Branch 1 taken 34560 times.
✓ Branch 2 taken 14 times.
34574 (e2,e1,true) := createResidualExp3(oExp2, oExp1);
11906 14 (e1,_) := ExpressionSimplify.simplify1(e1);
11907 14 (e2,_) := ExpressionSimplify.simplify1(e2);
11908 then (e1 ,e2, true);
11909 34560 else (oExp1, oExp2, false);
11910 end matchcontinue;
11911
11912 (oExp1, oExp2, con1) := matchcontinue oExp2
11913 local DAE.Exp e1, e2;
11914 case _
11915 algorithm
11916
2/2
✓ Branch 1 taken 32456 times.
✓ Branch 2 taken 2121 times.
34577 true := isZero(oExp1);
11917 2121 (e1,e2) := makeFraction(oExp2);
11918 2121 then (e1 ,oExp1, not isOne(e2));
11919
11920 case _
11921 algorithm
11922
2/2
✓ Branch 1 taken 29939 times.
✓ Branch 2 taken 2517 times.
32456 true := isZero(oExp2);
11923 2517 (e1,e2) := makeFraction(oExp1);
11924 2517 then (e1 ,oExp2, not isOne(e2));
11925
11926 case _
11927 algorithm
11928
2/2
✓ Branch 1 taken 29937 times.
✓ Branch 2 taken 2 times.
29939 true := isOne(oExp1);
11929 2 (e1,e2) := makeFraction(oExp2);
11930 2 then (e1 ,e2, not isOne(e2));
11931
11932 case _
11933 algorithm
11934
2/2
✓ Branch 1 taken 29881 times.
✓ Branch 2 taken 56 times.
29937 true := isOne(oExp2);
11935 56 (e1,e2) := makeFraction(oExp1);
11936 56 then (e1 ,e2, not isOne(e2));
11937
11938 29881 else (oExp1, oExp2, false);
11939 end matchcontinue;
11940 34577 con := con or con1;
11941
11942 34577 ii := ii + 1;
11943
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 34542 times.
34577 if not con then
11944 34542 (oExp1,con) := ExpressionSimplify.simplify1(oExp1);
11945 34542 (oExp2,con1) := ExpressionSimplify.simplify1(oExp2);
11946
4/4
✓ Branch 0 taken 34541 times.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 34512 times.
✓ Branch 3 taken 29 times.
34542 con := con or con1;
11947 34542 ii := ii + 3;
11948 // else
11949 // print("\niExp1");print(ExpressionBasics.printExpStr(iExp1));
11950 // print("\te1");print(ExpressionBasics.printExpStr(oExp2));
11951 // print("\niExp2");print(ExpressionBasics.printExpStr(iExp2));
11952 // print("\te2");print(ExpressionBasics.printExpStr(oExp2));
11953 end if;
11954
11955 end while;
11956
11957 34512 (oExp1,_) := ExpressionSimplify.simplify1(oExp1);
11958 34512 (oExp2,_) := ExpressionSimplify.simplify1(oExp2);
11959
11960 end createResidualExp2;
11961
11962 public function createResidualExp3
11963 "author: Vitalij
11964 helper function of createResidualExp3
11965 swaps args"
11966 input DAE.Exp iExp1;
11967 input DAE.Exp iExp2;
11968 output DAE.Exp oExp1;
11969 output DAE.Exp oExp2;
11970 output Boolean con;
11971 algorithm
11972 (oExp1, oExp2, con) := matchcontinue(iExp1, iExp2)
11973 local
11974 DAE.Exp e,e1,e2;
11975 String s1, s2;
11976 DAE.Type tp;
11977
11978 // f(x) = f(y) -> x = y
11979 case(DAE.CALL(path = Absyn.IDENT(s1), expLst={e1}),DAE.CALL(path = Absyn.IDENT(s2) ,expLst={e2}))
11980 guard s1 == s2 and createResidualExp4(s1)
11981 then (e1,e2, true);
11982 // sqrt(f(x)) = 0.0 -> f(x) = 0
11983 case(DAE.CALL(path = Absyn.IDENT("sqrt"), expLst={e1}), DAE.RCONST(0.0))
11984 then (e1,iExp2,true);
11985 // sqrt(f(x)) = c -> f(x) = c^2
11986 case(DAE.CALL(path = Absyn.IDENT("sqrt"), expLst={e1}), e2)
11987 guard(Expression.isConst(e2))
11988 algorithm
11989 ✗ e := Expression.expPow(iExp2, DAE.RCONST(2.0));
11990 then (e1,e,true);
11991 // log(f(x)) = c -> f(x) = exp(c)
11992 case(DAE.CALL(path = Absyn.IDENT("log"), expLst={e1}), e2)
11993 guard(Expression.isConst(e2))
11994 algorithm
11995 4 tp := Expression.typeof(iExp2);
11996 4 e := Expression.makePureBuiltinCall("exp", {iExp2}, tp);
11997 then (e1,e,true);
11998 // log10(f(x)) = c -> f(x) = 10^(c)
11999 case(DAE.CALL(path = Absyn.IDENT("log10"), expLst={e1}), e2)
12000 guard(Expression.isConst(e2))
12001 algorithm
12002 ✗ e := Expression.expPow(DAE.RCONST(10.0),iExp2);
12003 then (e1,e,true);
12004 /*
12005 // f(x)^y = 0 -> x = 0
12006 case(DAE.BINARY(e1,DAE.POW(_),e2),DAE.RCONST(0.0))
12007 then (e1, iExp2, true);
12008 // abs(f(x)) = 0.0 -> f(x) = 0
12009 case(DAE.CALL(path = Absyn.IDENT("abs"), expLst={e1}), DAE.RCONST(0.0))
12010 then (e1,iExp2,true);
12011 */
12012 // semiLinear(0,e1,e2) = 0 -> e1 - e2 = 0
12013 case(DAE.CALL(path = Absyn.IDENT("semiLinear"), expLst={DAE.RCONST(0.0), e1, e2}), DAE.RCONST(0.0))
12014 then (e1,e2,true);
12015 // -f(.) = 0 -> f(.) = 0
12016 case(DAE.UNARY(operator = DAE.UMINUS(),exp = e1), e2 as DAE.RCONST(0.0))
12017 then (e1,e2,true);
12018 // f(x) - f(y) = 0 -> x = y
12019 case(DAE.BINARY(DAE.CALL(path = Absyn.IDENT(s1), expLst={e1}),DAE.SUB(),DAE.CALL(path = Absyn.IDENT(s2) ,expLst={e2})), DAE.RCONST(0.0))
12020 guard s1 == s2 and createResidualExp4(s1)
12021 then (e1,e2,true);
12022 else (iExp1, iExp2, false);
12023 end matchcontinue;
12024 end createResidualExp3;
12025
12026 protected function createResidualExp4"
12027 author: Vitalij
12028 helper function of createResidualExp3
12029 return true if f(x) = f(y), then it can be transformed into x = y.
12030
12031 Beware: function is not complete, yet!
12032 "
12033 input String f;
12034 output Boolean resB;
12035 algorithm
12036 resB := match f
12037 case "sqrt" then true;
12038 case "exp" then true;
12039 case "log" then true;
12040 case "log10" then true;
12041 case "tanh" then true;
12042 case "sinh" then true;
12043 else false;
12044 end match;
12045 end createResidualExp4;
12046
12047 public function isAsubExp
12048 input DAE.Exp expIn;
12049 output Boolean isAsub;
12050 algorithm
12051 isAsub := match expIn
12052 case DAE.ASUB(_,_) algorithm
12053 then true;
12054 else false;
12055 end match;
12056 end isAsubExp;
12057
12058 public function typeCast
12059 input DAE.Exp inExp;
12060 input DAE.Type inType;
12061 output DAE.Exp outExp;
12062 algorithm
12063 788 outExp := DAE.CAST(inType, inExp);
12064 788 outExp := ExpressionSimplify.simplify1(outExp);
12065 end typeCast;
12066
12067 public function typeCastElements
12068 input DAE.Exp inExp;
12069 input DAE.Type inType;
12070 output DAE.Exp outExp;
12071 protected
12072 DAE.Type ty;
12073 algorithm
12074 788 ty := typeof(inExp);
12075 788 ty := Types.setArrayElementType(ty, inType);
12076 788 outExp := typeCast(inExp, ty);
12077 end typeCastElements;
12078
12079 public function expandRange
12080 "Expands a range expression into its elements:
12081 expandRange(1:4) => {1, 2, 3, 4}"
12082 input DAE.Exp inRange;
12083 output list<DAE.Exp> outValues;
12084 protected
12085 DAE.Exp start_exp, stop_exp;
12086 Option<DAE.Exp> ostep_exp;
12087 Integer istep;
12088 Real rstep;
12089 list<DAE.Exp> vals;
12090 list<String> enum_names;
12091 Absyn.Path enum_type;
12092 DAE.Type range_ty;
12093 algorithm
12094
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41584 times.
41584 DAE.RANGE(start = start_exp, step = ostep_exp, stop = stop_exp) := inRange;
12095
12096 outValues := match (start_exp, stop_exp)
12097 // An integer range, with or without a step value.
12098 case (DAE.ICONST(), DAE.ICONST())
12099 algorithm
12100
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 41177 times.
41177 DAE.ICONST(istep) := Util.getOptionOrDefault(ostep_exp, DAE.ICONST(1));
12101
4/4
✓ Branch 1 taken 117492 times.
✓ Branch 2 taken 41177 times.
✓ Branch 3 taken 117492 times.
✓ Branch 4 taken 41177 times.
158669 then
12102 list(DAE.ICONST(i) for i in
12103 List.intRange3(start_exp.integer, istep, stop_exp.integer));
12104
12105 // A real range, with or without a step value.
12106 case (DAE.RCONST(), DAE.RCONST())
12107 algorithm
12108 ✗ DAE.RCONST(rstep) := Util.getOptionOrDefault(ostep_exp, DAE.RCONST(1.0));
12109 ✗ then
12110 list(DAE.RCONST(r) for r in
12111 ExpressionSimplify.simplifyRangeReal(start_exp.real, rstep, stop_exp.real));
12112
12113 // false:true => {false, true}
12114 case (DAE.BCONST(false), DAE.BCONST(true))
12115 then {start_exp, stop_exp};
12116
12117 // true:false => {}
12118 case (DAE.BCONST(true), DAE.BCONST(false))
12119 then {};
12120
12121 // true:true => true, false:false => false
12122 case (DAE.BCONST(), DAE.BCONST())
12123 then {start_exp};
12124
12125 // An enumeration range, no step value allowed.
12126 case (DAE.ENUM_LITERAL(), DAE.ENUM_LITERAL())
12127 algorithm
12128
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 if start_exp.index > stop_exp.index then
12129 vals := {};
12130 elseif start_exp.index == stop_exp.index then
12131 vals := {start_exp};
12132 else
12133 30 DAE.RANGE(ty = range_ty) := inRange;
12134
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
30 DAE.T_ENUMERATION(path = enum_type, names = enum_names) := Types.arrayElementType(range_ty);
12135 30 enum_names := List.sublist(enum_names, start_exp.index,
12136 (stop_exp.index - start_exp.index) + 1);
12137 30 vals := makeEnumLiterals(enum_type, enum_names);
12138 end if;
12139 then
12140 vals;
12141
12142 end match;
12143 end expandRange;
12144
12145 public function isScalarSubscript
12146 input DAE.Subscript sub;
12147 output Boolean b;
12148 algorithm
12149 b := match sub
12150 ✗ case DAE.SLICE() then isScalar(sub.exp);
12151 78909 case DAE.INDEX() then isScalar(sub.exp);
12152 ✗ case DAE.WHOLE_NONEXP() then isScalar(sub.exp);
12153 else false;
12154 end match;
12155 end isScalarSubscript;
12156
12157 public function isScalar
12158 input DAE.Exp inExp;
12159 output Boolean outIsScalar;
12160 algorithm
12161 outIsScalar := match inExp
12162 case DAE.ICONST() then true;
12163 case DAE.RCONST() then true;
12164 case DAE.SCONST() then true;
12165 case DAE.BCONST() then true;
12166 case DAE.CLKCONST() then true;
12167 case DAE.ENUM_LITERAL() then true;
12168 ✗ case DAE.UNARY() then isScalar(inExp.exp);
12169 ✗ case DAE.LUNARY() then isScalar(inExp.exp);
12170 case DAE.RELATION() then true;
12171 case DAE.ARRAY() then false;
12172 case DAE.MATRIX() then false;
12173 case DAE.RANGE() then false;
12174 ✗ case DAE.CAST() then isScalar(inExp.exp);
12175 ✗ case DAE.SIZE() then isSome(inExp.sz);
12176 4959 else Types.isSimpleType(typeof(inExp));
12177 end match;
12178 end isScalar;
12179
12180 public function containsAnyCall
12181 "Returns true if the given expression contains any function calls,
12182 otherwise false."
12183 input DAE.Exp inExp;
12184 output Boolean outContainsCall;
12185 algorithm
12186 129420 (_, outContainsCall) := traverseExpTopDown(inExp, containsAnyCall_traverser, false);
12187 end containsAnyCall;
12188
12189 protected function containsAnyCall_traverser
12190 input DAE.Exp inExp;
12191 input Boolean inContainsCall;
12192 output DAE.Exp outExp = inExp;
12193 output Boolean outContinue;
12194 output Boolean outContainsCall;
12195 algorithm
12196 outContainsCall := match inExp
12197 case DAE.CALL() then true;
12198 else inContainsCall;
12199 end match;
12200
12201
1/2
✓ Branch 0 taken 129654 times.
✗ Branch 1 not taken.
129654 outContinue := not outContainsCall;
12202 end containsAnyCall_traverser;
12203
12204 public function containsCallTo
12205 "Returns true if the given expression contains any function calls,
12206 otherwise false."
12207 input DAE.Exp inExp;
12208 input Absyn.Path path;
12209 output Boolean outContainsCall;
12210 algorithm
12211 ✗ (_, (_,outContainsCall)) := traverseExpTopDown(inExp, containsCallTo_traverser, (path,false));
12212 end containsCallTo;
12213
12214 protected function containsCallTo_traverser
12215 input DAE.Exp inExp;
12216 input tuple<Absyn.Path,Boolean> inTpl;
12217 output DAE.Exp outExp = inExp;
12218 output Boolean outContinue = false;
12219 output tuple<Absyn.Path,Boolean> outTpl = inTpl;
12220 protected
12221 Boolean containsCall;
12222 Absyn.Path path;
12223 algorithm
12224 ✗ (path,containsCall) := outTpl;
12225 ✗ if containsCall then
12226 ✗ return;
12227 end if;
12228 outContinue := match inExp
12229 ✗ case DAE.CALL() then AbsynUtil.pathEqual(path,inExp.path);
12230 else true;
12231 end match;
12232 ✗ if not outContinue then
12233 ✗ outTpl := (path,false);
12234 end if;
12235 end containsCallTo_traverser;
12236
12237 public function rangeSize
12238 "Tries to figure out the size of a range expression. Either return the size or
12239 fails."
12240 input DAE.Exp inRange;
12241 output Integer outSize;
12242 algorithm
12243 outSize := match inRange
12244 local
12245 Integer start, step, stop;
12246
12247 case DAE.RANGE(ty = DAE.T_ARRAY(dims = {DAE.DIM_INTEGER(outSize)})) then outSize;
12248
12249 case DAE.RANGE(start = DAE.ICONST(start),
12250 step = NONE(),
12251 stop = DAE.ICONST(stop))
12252 ✗ then max(stop - start, 0);
12253
12254 case DAE.RANGE(start = DAE.ICONST(start),
12255 step = SOME(DAE.ICONST(step)),
12256 stop = DAE.ICONST(stop))
12257 algorithm
12258 ✗ if step <> 0 then
12259 ✗ outSize := max(realInt(floor(realDiv(stop - start, step))) + 1, 0);
12260 else
12261 ✗ fail();
12262 end if;
12263 then
12264 outSize;
12265
12266 end match;
12267 end rangeSize;
12268
12269 public function isInvariantExpNoTraverse "For use with traverseExp"
12270 input output DAE.Exp e;
12271 input output Boolean b;
12272 algorithm
12273 ✗ if not b then
12274 ✗ return;
12275 end if;
12276 b := match e
12277 case DAE.ICONST() then true;
12278 case DAE.RCONST() then true;
12279 case DAE.SCONST() then true;
12280 case DAE.BCONST() then true;
12281 case DAE.ENUM_LITERAL() then true;
12282 case DAE.BINARY() then true;
12283 case DAE.UNARY() then true;
12284 case DAE.LBINARY() then true;
12285 case DAE.LUNARY() then true;
12286 case DAE.RELATION() then true;
12287 case DAE.IFEXP() then true;
12288 case DAE.CALL(path=Absyn.FULLYQUALIFIED()) then true;
12289 case DAE.PARTEVALFUNCTION(path=Absyn.FULLYQUALIFIED()) then true;
12290 case DAE.ARRAY() then true;
12291 case DAE.MATRIX() then true;
12292 case DAE.RANGE() then true;
12293 case DAE.CONS() then true;
12294 case DAE.LIST() then true;
12295 else false;
12296 end match;
12297 end isInvariantExpNoTraverse;
12298
12299 public function findCallIsInlineAfterIndexReduction
12300 input output DAE.Exp e;
12301 output Boolean cont;
12302 input output Boolean res;
12303 algorithm
12304
2/2
✓ Branch 0 taken 24188 times.
✓ Branch 1 taken 834 times.
25022 if not res then
12305 res := match e
12306 case DAE.CALL(attr=DAE.CALL_ATTR(inlineType=DAE.AFTER_INDEX_RED_INLINE())) then true;
12307 else false;
12308 end match;
12309 end if;
12310
1/2
✓ Branch 0 taken 25022 times.
✗ Branch 1 not taken.
25022 cont := not res;
12311 end findCallIsInlineAfterIndexReduction;
12312
12313 public function tupleHead
12314 input DAE.Exp exp;
12315 input DAE.Properties prop;
12316 output DAE.Exp outExp;
12317 output DAE.Properties outProp;
12318 algorithm
12319 (outExp, outProp) := match (exp, prop)
12320 local
12321 DAE.Type ty;
12322
12323 case (DAE.Exp.TUPLE(_ :: _), DAE.Properties.PROP_TUPLE())
12324 1 then (listHead(exp.PR), Types.propTupleFirstProp(prop));
12325 case (_, DAE.Properties.PROP_TUPLE(type_ = DAE.T_TUPLE(types = ty :: _)))
12326 ✗ then (DAE.Exp.TSUB(exp, 1, ty), Types.propTupleFirstProp(prop));
12327 else (exp, prop);
12328 end match;
12329 end tupleHead;
12330
12331 public function isSimpleLiteralValue "A value that requires nothing special during code generation. String literals are special and not included."
12332 input DAE.Exp exp;
12333 input Boolean allow_arrays = false;
12334 output Boolean b;
12335 algorithm
12336 b := match exp
12337 case DAE.SCONST() then allow_arrays /* allow string constants with arrays */;
12338 case DAE.ICONST() then true;
12339 case DAE.RCONST() then true;
12340 case DAE.BCONST() then true;
12341 case DAE.ENUM_LITERAL() then true;
12342 89 case DAE.ARRAY() guard(allow_arrays) then List.all(exp.array, function isSimpleLiteralValue(allow_arrays = true));
12343 else false;
12344 end match;
12345 end isSimpleLiteralValue;
12346
12347 public function consToListIgnoreSharedLiteral
12348 input output DAE.Exp e;
12349 algorithm
12350 if match e
12351 case DAE.SHARED_LITERAL() then true;
12352 case DAE.LIST() then true;
12353 case DAE.CONS() then true;
12354 else false; end match then
12355 try
12356 ✗ e := consToListIgnoreSharedLiteralWork(e);
12357 else
12358 end try;
12359 end if;
12360 end consToListIgnoreSharedLiteral;
12361
12362 protected function consToListIgnoreSharedLiteralWork
12363 input output DAE.Exp e;
12364 input list<DAE.Exp> acc={};
12365 algorithm
12366 e := match (e,acc)
12367 ✗ case (DAE.SHARED_LITERAL(),_) then consToListIgnoreSharedLiteralWork(e.exp, acc);
12368 case (DAE.LIST(),{}) then e;
12369 ✗ case (DAE.LIST(),_) then DAE.LIST(List.append_reverse(acc, e.valList));
12370 ✗ case (DAE.CONS(),_) then consToListIgnoreSharedLiteralWork(e.cdr, e.car::acc);
12371 end match;
12372 end consToListIgnoreSharedLiteralWork;
12373
12374 public function arrayFirstScalar
12375 "Returns the first scalar element of an array, i.e. exp[1, 1, ...]."
12376 input DAE.Exp exp;
12377 output DAE.Exp outExp;
12378 algorithm
12379 outExp := match exp
12380 497 case DAE.ARRAY() then arrayFirstScalar(listHead(exp.array));
12381 else exp;
12382 end match;
12383 end arrayFirstScalar;
12384
12385 public function traverseCases
12386 "Traverses the expressions in a list of match-expression cases (bottom-up).
12387 Moved here from Patternm so Expression does not depend on the instantiation
12388 cluster; the body/guard/result are pure DAE expressions."
12389 replaceable type A subtypeof Any;
12390 input list<DAE.MatchCase> inCases;
12391 input FuncExpType func;
12392 input A inA;
12393 output list<DAE.MatchCase> outCases;
12394 output A oa;
12395 partial function FuncExpType
12396 input DAE.Exp inExp;
12397 input A inTypeA;
12398 output DAE.Exp outExp;
12399 output A outA;
12400 end FuncExpType;
12401 algorithm
12402 (outCases,oa) := match (inCases, inA)
12403 local
12404 list<DAE.Pattern> patterns;
12405 list<DAE.Element> decls;
12406 list<DAE.Statement> body,body1;
12407 Option<DAE.Exp> result,result1,patternGuard,patternGuard1;
12408 Integer jump;
12409 SourceInfo resultInfo,info;
12410 list<DAE.MatchCase> cases,cases1;
12411 A a;
12412
12413 case ({}, a) then ({},a);
12414 case (DAE.CASE(patterns,patternGuard,decls,body,result,resultInfo,jump,info)::cases, a)
12415 algorithm
12416 48445 (body1,(_,a)) := DAEUtil.traverseDAEEquationsStmts(body,traverseSubexpressionsHelper,(func,a));
12417 48445 (patternGuard1,a) := traverseExpOpt(patternGuard,func,a);
12418 48445 (result1,a) := traverseExpOpt(result,func,a);
12419 48445 (cases1,a) := traverseCases(cases,func,a);
12420
4/4
✓ Branch 0 taken 27311 times.
✓ Branch 1 taken 21134 times.
✓ Branch 2 taken 552 times.
✓ Branch 3 taken 26759 times.
48445 cases := if referenceEq(cases,cases1) and referenceEq(patternGuard,patternGuard1) and referenceEq(result,result1) and referenceEq(body,body1)
12421 then inCases
12422 else DAE.CASE(patterns,patternGuard1,decls,body1,result1,resultInfo,jump,info)::cases1;
12423 48445 then (cases,a);
12424 end match;
12425 end traverseCases;
12426
12427 protected function traverseMatchCases<A>
12428 "traverseCases for a match expression met by traverseExpBottomUp."
12429 input list<DAE.MatchCase> inCases;
12430 input FuncExpType func;
12431 input A inA;
12432 output list<DAE.MatchCase> outCases;
12433 output A oa;
12434 partial function FuncExpType
12435 input DAE.Exp inExp;
12436 input A inTypeA;
12437 output DAE.Exp outExp;
12438 output A outA;
12439 end FuncExpType;
12440 algorithm
12441 9880 (outCases, oa) := traverseCases(inCases, func, inA);
12442 end traverseMatchCases;
12443
12444 protected function traverseMatchCasesTopDown<A>
12445 "traverseCasesTopDown for a match expression met by traverseExpTopDown."
12446 input list<DAE.MatchCase> inCases;
12447 input FuncExpType func;
12448 input A inA;
12449 output list<DAE.MatchCase> cases;
12450 output A a;
12451 partial function FuncExpType
12452 input DAE.Exp inExp;
12453 input A inTypeA;
12454 output DAE.Exp outExp;
12455 output Boolean cont;
12456 output A outA;
12457 end FuncExpType;
12458 algorithm
12459 1171 (cases, a) := traverseCasesTopDown(inCases, func, inA);
12460 end traverseMatchCasesTopDown;
12461
12462 public function traverseCasesTopDown<A>
12463 "Traverses the expressions in a list of match-expression cases (top-down).
12464 Moved here from Patternm (see traverseCases)."
12465 input list<DAE.MatchCase> inCases;
12466 input FuncExpType func;
12467 input A inA;
12468 output list<DAE.MatchCase> cases = {};
12469 output A a = inA;
12470 partial function FuncExpType
12471 input DAE.Exp inExp;
12472 input A inTypeA;
12473 output DAE.Exp outExp;
12474 output Boolean cont;
12475 output A outA;
12476 end FuncExpType;
12477 protected
12478 list<DAE.Pattern> patterns;
12479 list<DAE.Element> decls;
12480 list<DAE.Statement> body,body1;
12481 Option<DAE.Exp> result,result1,patternGuard,patternGuard1;
12482 Integer jump;
12483 SourceInfo resultInfo,info;
12484 tuple<FuncExpType,A> tpl;
12485 algorithm
12486
2/2
✓ Branch 0 taken 5165 times.
✓ Branch 1 taken 1171 times.
6336 for c in inCases loop
12487 5165 DAE.CASE(patterns,patternGuard,decls,body,result,resultInfo,jump,info) := c;
12488 5165 tpl := (func,a);
12489 5165 (body1,(_,a)) := DAEUtil.traverseDAEEquationsStmts(body,traverseSubexpressionsTopDownHelper,tpl);
12490 5165 (patternGuard1,a) := traverseExpOptTopDown(patternGuard,func,a);
12491 5165 (result1,a) := traverseExpOptTopDown(result,func,a);
12492 5165 cases := DAE.CASE(patterns,patternGuard1,decls,body1,result1,resultInfo,jump,info)::cases;
12493 end for;
12494 1171 cases := listReverse(cases);
12495 end traverseCasesTopDown;
12496
12497 annotation(__OpenModelica_Interface="frontend_base");
12498 end Expression;
12499