Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 91.1% 216 / 0 / 237
Functions: -% 0 / 1 / 1
Branches: 71.2% 168 / 0 / 236

OMCompiler/Compiler/FrontEnd/ExpressionBasics.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 ExpressionBasics
37 " file: ExpressionBasics.mo
38 package: ExpressionBasics
39 description: ExpressionBasics
40
41
42 This file contains the module ExpressionDump, which contains the most basic functions
43 to print and work with DAE.Expression."
44
45 // public imports
46 import DAE;
47 protected
48 import AbsynUtil;
49 import ComponentReferenceBasics;
50 import Error;
51 import ExpressionDumpTpl;
52 import List;
53 import MetaModelica.Dangerous;
54 import Tpl;
55 import Util;
56
57 public function printExpStr
58 "This function prints a complete expression."
59 input DAE.Exp e;
60 output String s;
61 algorithm
62 1311879 s := Tpl.tplString2(ExpressionDumpTpl.dumpExp, e, "\"");
63 end printExpStr;
64
65 public function dimensionString
66 "Returns a string representation of an array dimension."
67 input DAE.Dimension dim;
68 output String str;
69 algorithm
70 str := match dim
71 local
72 String s;
73 Integer x;
74 Absyn.Path p;
75 DAE.Exp e;
76 case DAE.DIM_UNKNOWN() then ":";
77
78 case DAE.DIM_ENUM(enumTypeName = p)
79 algorithm
80 1 s := AbsynUtil.pathString(p);
81 then
82 s;
83
84 case DAE.DIM_BOOLEAN() then "Boolean";
85
86 case DAE.DIM_INTEGER(integer = x)
87 algorithm
88 13450 s := intString(x);
89 then
90 s;
91
92 case DAE.DIM_EXP(exp = e)
93 algorithm
94 4 s := printExpStr(e);
95 then
96 s;
97 end match;
98 end dimensionString;
99
100 public function dimensionsString
101 "Returns a string representation of an array dimension."
102 input DAE.Dimensions dims;
103 output String str;
104 algorithm
105 20317 str := stringDelimitList(List.map(dims,dimensionString),",");
106 end dimensionsString;
107
108 public function shouldParenthesize
109 "Determines whether an operand in an expression needs parentheses around it."
110 input DAE.Exp inOperand;
111 input DAE.Exp inOperator;
112 input Boolean inLhs;
113 output Boolean outShouldParenthesize;
114 algorithm
115 outShouldParenthesize := match inOperand
116 local
117 Integer diff;
118
119 case DAE.UNARY() then true;
120
121 else
122 algorithm
123 2622704 diff := Util.intCompare(priority(inOperand, inLhs),
124 priority(inOperator, inLhs));
125 2622704 then
126 shouldParenthesize2(diff, inOperand, inLhs);
127
128 end match;
129 end shouldParenthesize;
130
131 protected function shouldParenthesize2
132 input Integer inPrioDiff;
133 input DAE.Exp inOperand;
134 input Boolean inLhs;
135 output Boolean outShouldParenthesize;
136 algorithm
137 outShouldParenthesize := match inPrioDiff
138 case 1 then true;
139
2/2
✓ Branch 0 taken 81832 times.
✓ Branch 1 taken 124424 times.
206256 case 0 then if inLhs then isNonAssociativeExp(inOperand) else
140 not isAssociativeExp(inOperand);
141 else false;
142 end match;
143 end shouldParenthesize2;
144
145 protected function isAssociativeExp
146 "Determines whether the given expression represents an associative operation or not."
147 input DAE.Exp inExp;
148 output Boolean outIsAssociative;
149 algorithm
150 outIsAssociative := match inExp
151 local
152 DAE.Operator op;
153
154 124365 case DAE.BINARY(operator = op) then isAssociativeOp(op);
155 case DAE.LBINARY() then true;
156 else false;
157 end match;
158 end isAssociativeExp;
159
160 protected function isAssociativeOp
161 "Determines whether the given operator is associative or not."
162 input DAE.Operator inOperator;
163 output Boolean outIsAssociative;
164 algorithm
165 outIsAssociative := match inOperator
166 case DAE.ADD() then true;
167 case DAE.MUL() then true;
168 case DAE.ADD_ARR() then true;
169 case DAE.MUL_ARRAY_SCALAR() then true;
170 case DAE.ADD_ARRAY_SCALAR() then true;
171 else false;
172 end match;
173 end isAssociativeOp;
174
175 protected function isNonAssociativeExp
176 input DAE.Exp exp;
177 output Boolean isNonAssociative;
178 algorithm
179 isNonAssociative := match exp
180 75764 case DAE.BINARY() then isNonAssociativeOp(exp.operator);
181 else false;
182 end match;
183 end isNonAssociativeExp;
184
185 protected function isNonAssociativeOp
186 input DAE.Operator inOperator;
187 output Boolean isNonAssociative;
188 algorithm
189 isNonAssociative := match inOperator
190 case DAE.POW() then true;
191 case DAE.POW_ARRAY_SCALAR() then true;
192 case DAE.POW_SCALAR_ARRAY() then true;
193 case DAE.POW_ARR() then true;
194 case DAE.POW_ARR2() then true;
195 else false;
196 end match;
197 end isNonAssociativeOp;
198
199 public function priority
200 "Returns an integer priority given an expression, which is used by
201 ExpressionDumpTpl to add parentheses when dumping expressions. The inLhs
202 argument should be true if the expression occurs on the left side of a binary
203 operation, otherwise false. This is because we don't need to add parentheses
204 to expressions such as x * y / z, but x / (y * z) needs them, so the
205 priorities of some binary operations differ depending on which side they are."
206 input DAE.Exp inExp;
207 input Boolean inLhs;
208 output Integer outPriority;
209 algorithm
210 outPriority := match(inExp, inLhs)
211 local
212 DAE.Operator op;
213
214 1500676 case (DAE.BINARY(operator = op), false) then priorityBinopRhs(op);
215 1344230 case (DAE.BINARY(operator = op), true) then priorityBinopLhs(op);
216 case (DAE.RCONST(), _) guard inExp.real < 0.0 then 4; // Same as unary minus of a real literal
217 case (DAE.UNARY(), _) then 4;
218 121211 case (DAE.LBINARY(operator = op), _) then priorityLBinop(op);
219 case (DAE.LUNARY(), _) then 7;
220 case (DAE.RELATION(), _) then 6;
221 case (DAE.RANGE(), _) then 10;
222 case (DAE.IFEXP(), _) then 11;
223 else 0;
224 end match;
225 end priority;
226
227 protected function priorityBinopLhs
228 "Returns the priority for a binary operation on the left hand side. Add and
229 sub has the same priority, and mul and div too, in contrast with
230 priorityBinopRhs."
231 input DAE.Operator inOp;
232 output Integer outPriority;
233 algorithm
234 outPriority := match inOp
235 case DAE.ADD() then 5;
236 case DAE.SUB() then 5;
237 case DAE.MUL() then 2;
238 case DAE.DIV() then 2;
239 case DAE.POW() then 1;
240 case DAE.ADD_ARR() then 5;
241 case DAE.SUB_ARR() then 5;
242 case DAE.MUL_ARR() then 2;
243 case DAE.DIV_ARR() then 2;
244 case DAE.MUL_ARRAY_SCALAR() then 2;
245 case DAE.ADD_ARRAY_SCALAR() then 5;
246 case DAE.SUB_SCALAR_ARRAY() then 5;
247 case DAE.MUL_SCALAR_PRODUCT() then 2;
248 case DAE.MUL_MATRIX_PRODUCT() then 2;
249 case DAE.DIV_ARRAY_SCALAR() then 2;
250 case DAE.DIV_SCALAR_ARRAY() then 2;
251 case DAE.POW_ARRAY_SCALAR() then 1;
252 case DAE.POW_SCALAR_ARRAY() then 1;
253 case DAE.POW_ARR() then 1;
254 case DAE.POW_ARR2() then 1;
255 end match;
256 end priorityBinopLhs;
257
258 protected function priorityBinopRhs
259 "Returns the priority for a binary operation on the right hand side. Add and
260 sub has different priorities, and mul and div too, in contrast with
261 priorityBinopLhs."
262 input DAE.Operator inOp;
263 output Integer outPriority;
264 algorithm
265 outPriority := match inOp
266 case DAE.ADD() then 6;
267 case DAE.SUB() then 5;
268 case DAE.MUL() then 3;
269 case DAE.DIV() then 2;
270 case DAE.POW() then 1;
271 case DAE.ADD_ARR() then 6;
272 case DAE.SUB_ARR() then 5;
273 case DAE.MUL_ARR() then 3;
274 case DAE.DIV_ARR() then 2;
275 case DAE.MUL_ARRAY_SCALAR() then 3;
276 case DAE.ADD_ARRAY_SCALAR() then 6;
277 case DAE.SUB_SCALAR_ARRAY() then 5;
278 case DAE.MUL_SCALAR_PRODUCT() then 3;
279 case DAE.MUL_MATRIX_PRODUCT() then 3;
280 case DAE.DIV_ARRAY_SCALAR() then 2;
281 case DAE.DIV_SCALAR_ARRAY() then 2;
282 case DAE.POW_ARRAY_SCALAR() then 1;
283 case DAE.POW_SCALAR_ARRAY() then 1;
284 case DAE.POW_ARR() then 1;
285 case DAE.POW_ARR2() then 1;
286 end match;
287 end priorityBinopRhs;
288
289 protected function priorityLBinop
290 input DAE.Operator inOp;
291 output Integer outPriority;
292 algorithm
293 outPriority := match inOp
294 case DAE.AND() then 8;
295 case DAE.OR() then 9;
296 end match;
297 end priorityLBinop;
298
299 public function evalCat<Exp>
300 input Integer dim;
301 input list<Exp> exps;
302 input GetArrayContents getArrayContents;
303 input ToString toString;
304 output list<Exp> outExps;
305 output list<Integer> outDims;
306 partial function GetArrayContents
307 input Exp e;
308 output list<Exp> es;
309 end GetArrayContents;
310 partial function MakeArrayFromList
311 input list<Exp> es;
312 output Exp e;
313 end MakeArrayFromList;
314 partial function ToString
315 input Exp e;
316 output String s;
317 end ToString;
318 protected
319 list<Exp> arr;
320 list<list<Exp>> arrs={};
321 list<Integer> dims, firstDims={}, lastDims, reverseDims;
322 list<list<Integer>> dimsLst={};
323 Integer j, k, l, thisDim, lastDim;
324 array<Exp> expArr;
325 algorithm
326
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10111 times.
10111 true := dim >= 1;
327
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10111 times.
10111 false := listEmpty(exps);
328
2/2
✓ Branch 0 taken 3435 times.
✓ Branch 1 taken 6676 times.
10111 if 1 == dim then
329
5/6
✓ Branch 1 taken 9272 times.
✓ Branch 2 taken 3120 times.
✓ Branch 3 taken 9272 times.
✓ Branch 4 taken 3120 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 9272 times.
12392 outExps := listAppend(getArrayContents(e) for e in listReverse(exps));
330 3120 outDims := {listLength(outExps)};
331 3120 return;
332 end if;
333
2/2
✓ Branch 1 taken 20113 times.
✓ Branch 2 taken 6668 times.
26781 for e in listReverse(exps) loop
334 // Here we get a linear representation of all expressions in the array
335 // and the dimensions necessary to build up the array again
336 20113 (arr,dims) := evalCatGetFlatArray(e, dim, getArrayContents=getArrayContents, toString=toString);
337 arrs := arr::arrs;
338 20105 dimsLst := dims::dimsLst;
339 end for;
340 6668 for i in 1:(dim-1) loop
341
4/4
✓ Branch 0 taken 20108 times.
✓ Branch 1 taken 6669 times.
✓ Branch 2 taken 20108 times.
✓ Branch 3 taken 6669 times.
26777 j := min(listHead(d) for d in dimsLst);
342
343
5/6
✓ Branch 0 taken 20108 times.
✓ Branch 1 taken 6669 times.
✓ Branch 2 taken 20108 times.
✓ Branch 3 taken 6669 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6669 times.
26777 if j <> max(listHead(d) for d in dimsLst) then
344 ✗ Error.terminate(getInstanceName() + ": cat got uneven dimensions for dim=" + String(i) + " " + stringDelimitList(list(toString(e) for e in exps), ", "), sourceInfo());
345 end if;
346
347 firstDims := j :: firstDims;
348
4/4
✓ Branch 0 taken 20108 times.
✓ Branch 1 taken 6669 times.
✓ Branch 2 taken 20108 times.
✓ Branch 3 taken 6669 times.
26777 dimsLst := list(listRest(d) for d in dimsLst);
349 end for;
350 reverseDims := firstDims;
351 6668 firstDims := listReverse(firstDims);
352
4/4
✓ Branch 0 taken 20105 times.
✓ Branch 1 taken 6668 times.
✓ Branch 2 taken 20105 times.
✓ Branch 3 taken 6668 times.
26773 lastDims := list(listHead(d) for d in dimsLst);
353
4/4
✓ Branch 0 taken 20105 times.
✓ Branch 1 taken 6668 times.
✓ Branch 2 taken 20105 times.
✓ Branch 3 taken 6668 times.
26773 lastDim := sum(d for d in lastDims);
354 reverseDims := lastDim::reverseDims;
355 // Fill in the elements of the new array in the new order; this uses
356 // an array structure for random access
357
4/4
✓ Branch 0 taken 6669 times.
✓ Branch 1 taken 6668 times.
✓ Branch 2 taken 6669 times.
✓ Branch 3 taken 6668 times.
13337 expArr := Dangerous.arrayCreateNoInit(lastDim*product(d for d in firstDims), listHead(exps));
358 k := 1;
359
2/2
✓ Branch 0 taken 20105 times.
✓ Branch 1 taken 6668 times.
26773 for exps in arrs loop
360
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20105 times.
20105 thisDim :: lastDims := lastDims;
361 l := 0;
362
2/2
✓ Branch 0 taken 20914 times.
✓ Branch 1 taken 20105 times.
41019 for e in exps loop
363
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20914 times.
41828 arrayUpdate(expArr, k+mod(l, thisDim)+(lastDim*div(l, thisDim)), e);
364 20914 l := l+1;
365 end for;
366 20105 k := k + thisDim;
367 end for;
368 // Convert the flat array structure to a tree array structure with the
369 // correct dimensions
370 6668 outExps := arrayList(expArr);
371 6668 outDims := listReverse(reverseDims);
372 end evalCat;
373
374 protected function evalCatGetFlatArray<Exp>
375 input Exp e;
376 input Integer dim;
377 input GetArrayContents getArrayContents;
378 input ToString toString;
379 output list<Exp> outExps={};
380 output list<Integer> outDims={};
381 partial function GetArrayContents
382 input Exp e;
383 output list<Exp> es;
384 end GetArrayContents;
385 partial function ToString
386 input Exp e;
387 output String s;
388 end ToString;
389 protected
390 list<Exp> arr;
391 list<Integer> dims;
392 Integer i;
393 algorithm
394
2/2
✓ Branch 0 taken 20908 times.
✓ Branch 1 taken 20116 times.
41024 if dim == 1 then
395
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20908 times.
20908 outExps := getArrayContents(e);
396 20908 outDims := {listLength(outExps)};
397 20908 return;
398 end if;
399 i := 0;
400
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 20116 times.
✓ Branch 5 taken 20911 times.
✓ Branch 6 taken 20108 times.
41027 for exp in listReverse(getArrayContents(e)) loop
401 20911 (arr, dims) := evalCatGetFlatArray(exp, dim-1, getArrayContents=getArrayContents, toString=toString);
402
2/2
✓ Branch 0 taken 20108 times.
✓ Branch 1 taken 803 times.
20911 if listEmpty(outDims) then
403 20108 outDims := dims;
404 elseif not valueEq(dims, outDims) then
405 ✗ Error.terminate(getInstanceName() + ": Got unbalanced array from " + toString(e), sourceInfo());
406 end if;
407 20911 outExps := listAppend(arr, outExps);
408 20911 i := i+1;
409 end for;
410 outDims := i :: outDims;
411 end evalCatGetFlatArray;
412
413 public function expEqual
414 "Returns true if the two expressions are equal, otherwise false."
415 input DAE.Exp inExp1;
416 input DAE.Exp inExp2;
417 output Boolean outEqual;
418 algorithm
419 97526297 outEqual := 0==compare(inExp1, inExp2);
420 end expEqual;
421
422 function compare
423 input DAE.Exp inExp1, inExp2;
424 output Integer comp;
425 algorithm
426 // Return true if the references are the same.
427
2/2
✓ Branch 0 taken 9033154 times.
✓ Branch 1 taken 107777394 times.
116810548 if referenceEq(inExp1, inExp2) then
428 comp := 0;
429 9033154 return;
430 end if;
431
432 107777394 comp := Util.intCompare(valueConstructor(inExp1), valueConstructor(inExp2));
433 // Return false if the expressions are not of the same type.
434
2/2
✓ Branch 0 taken 62438024 times.
✓ Branch 1 taken 45339370 times.
107777394 if comp <> 0 then
435 62438024 return;
436 end if;
437
438 // Otherwise, check if the expressions are equal or not.
439 // Since the expressions have already been verified to be of the same type
440 // above we can match on only one of them to allow the pattern matching to
441 // optimize this to jump directly to the correct case.
442 comp := match inExp1
443 local
444 Integer i;
445 Real r;
446 String s;
447 Boolean b;
448 Absyn.Path p;
449 DAE.Exp e, e1, e2;
450 Option<DAE.Exp> oe;
451 list<DAE.Exp> expl;
452 list<list<DAE.Exp>> mexpl;
453 DAE.Operator op;
454 DAE.ComponentRef cr;
455 DAE.Type ty;
456 list<DAE.Subscript> subs;
457
458 case DAE.ICONST()
459 algorithm
460
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 692987 times.
692987 DAE.ICONST(integer = i) := inExp2;
461 692987 then
462 Util.intCompare(inExp1.integer, i);
463
464 case DAE.RCONST()
465 algorithm
466
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3647982 times.
3647982 DAE.RCONST(real = r) := inExp2;
467 3647982 then Util.realCompare(inExp1.real, r);
468
469 case DAE.SCONST()
470 algorithm
471
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 233273 times.
233273 DAE.SCONST(string = s) := inExp2;
472 233273 then stringCompare(inExp1.string, s);
473
474 case DAE.BCONST()
475 algorithm
476
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2725 times.
2725 DAE.BCONST(bool = b) := inExp2;
477 2725 then Util.boolCompare(inExp1.bool, b);
478
479 case DAE.ENUM_LITERAL()
480 algorithm
481
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38671 times.
38671 DAE.ENUM_LITERAL(name = p) := inExp2;
482 38671 then AbsynUtil.pathCompare(inExp1.name, p);
483
484 case DAE.CREF()
485 algorithm
486
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16331243 times.
16331243 DAE.CREF(componentRef = cr) := inExp2;
487 16331243 then ComponentReferenceBasics.crefCompareGeneric(inExp1.componentRef, cr);
488
489 case DAE.ARRAY()
490 algorithm
491
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66084 times.
66084 DAE.ARRAY(ty = ty, array = expl) := inExp2;
492 66084 comp := valueCompare(inExp1.ty, ty);
493
2/2
✓ Branch 0 taken 65919 times.
✓ Branch 1 taken 165 times.
66084 then if 0==comp then compareList(inExp1.array, expl) else comp;
494
495 case DAE.MATRIX()
496 algorithm
497
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1078 times.
1078 DAE.MATRIX(ty = ty, matrix = mexpl) := inExp2;
498 1078 comp := valueCompare(inExp1.ty, ty);
499
1/2
✓ Branch 0 taken 1078 times.
✗ Branch 1 not taken.
1078 then if 0==comp then compareListList(inExp1.matrix, mexpl) else comp;
500
501 case DAE.BINARY()
502 algorithm
503
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22432147 times.
22432147 DAE.BINARY(exp1 = e1, operator = op, exp2 = e2) := inExp2;
504 22432147 comp := operatorCompare(inExp1.operator, op);
505
2/2
✓ Branch 0 taken 12569886 times.
✓ Branch 1 taken 9862261 times.
22432147 comp := if 0==comp then compare(inExp1.exp1, e1) else comp;
506
2/2
✓ Branch 0 taken 4092401 times.
✓ Branch 1 taken 18339746 times.
22432147 then if 0==comp then compare(inExp1.exp2, e2) else comp;
507
508 case DAE.LBINARY()
509 algorithm
510
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 134914 times.
134914 DAE.LBINARY(exp1 = e1, operator = op, exp2 = e2) := inExp2;
511 134914 comp := operatorCompare(inExp1.operator, op);
512
2/2
✓ Branch 0 taken 130556 times.
✓ Branch 1 taken 4358 times.
134914 comp := if 0==comp then compare(inExp1.exp1, e1) else comp;
513
2/2
✓ Branch 0 taken 111277 times.
✓ Branch 1 taken 23637 times.
134914 then if 0==comp then compare(inExp1.exp2, e2) else comp;
514
515 case DAE.UNARY()
516 algorithm
517
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 201997 times.
201997 DAE.UNARY(exp = e, operator = op) := inExp2;
518 201997 comp := operatorCompare(inExp1.operator, op);
519
1/2
✓ Branch 0 taken 201997 times.
✗ Branch 1 not taken.
201997 then if 0==comp then compare(inExp1.exp, e) else comp;
520
521 case DAE.LUNARY()
522 algorithm
523
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2362 times.
2362 DAE.LUNARY(exp = e, operator = op) := inExp2;
524 2362 comp := operatorCompare(inExp1.operator, op);
525
1/2
✓ Branch 0 taken 2362 times.
✗ Branch 1 not taken.
2362 then if 0==comp then compare(inExp1.exp, e) else comp;
526
527 case DAE.RELATION()
528 algorithm
529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 293282 times.
293282 DAE.RELATION(exp1 = e1, operator = op, exp2 = e2) := inExp2;
530 293282 comp := operatorCompare(inExp1.operator, op);
531
2/2
✓ Branch 0 taken 208916 times.
✓ Branch 1 taken 84366 times.
293282 comp := if 0==comp then compare(inExp1.exp1, e1) else comp;
532
2/2
✓ Branch 0 taken 161939 times.
✓ Branch 1 taken 131343 times.
293282 then if 0==comp then compare(inExp1.exp2, e2) else comp;
533
534 case DAE.IFEXP()
535 algorithm
536
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25849 times.
25849 DAE.IFEXP(expCond = e, expThen = e1, expElse = e2) := inExp2;
537 25849 comp := compare(inExp1.expCond, e);
538
2/2
✓ Branch 0 taken 19186 times.
✓ Branch 1 taken 6663 times.
25849 comp := if 0==comp then compare(inExp1.expThen, e1) else comp;
539
2/2
✓ Branch 0 taken 16615 times.
✓ Branch 1 taken 9234 times.
25849 then if 0==comp then compare(inExp1.expElse, e2) else comp;
540
541 case DAE.CALL()
542 algorithm
543
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1037081 times.
1037081 DAE.CALL(path = p, expLst = expl) := inExp2;
544 1037081 comp := AbsynUtil.pathCompare(inExp1.path, p);
545
2/2
✓ Branch 0 taken 953446 times.
✓ Branch 1 taken 83635 times.
1037081 then if 0==comp then compareList(inExp1.expLst, expl) else comp;
546
547 case DAE.RECORD()
548 algorithm
549
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14043 times.
14043 DAE.RECORD(path = p, exps = expl) := inExp2;
550 14043 comp := AbsynUtil.pathCompare(inExp1.path, p);
551
1/2
✓ Branch 0 taken 14043 times.
✗ Branch 1 not taken.
14043 then if 0==comp then compareList(inExp1.exps, expl) else comp;
552
553 case DAE.PARTEVALFUNCTION()
554 algorithm
555
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 553 times.
553 DAE.PARTEVALFUNCTION(path = p, expList = expl) := inExp2;
556 553 comp := AbsynUtil.pathCompare(inExp1.path, p);
557
1/2
✓ Branch 0 taken 553 times.
✗ Branch 1 not taken.
553 then if 0==comp then compareList(inExp1.expList, expl) else comp;
558
559 case DAE.RANGE()
560 algorithm
561
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 DAE.RANGE(start = e1, step = oe, stop = e2) := inExp2;
562 4 comp := compare(inExp1.start, e1);
563
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 3 times.
4 comp := if 0==comp then compare(inExp1.stop, e2) else comp;
564
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 3 times.
4 then if 0==comp then compareOpt(inExp1.step, oe) else comp;
565
566 case DAE.TUPLE()
567 algorithm
568
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 528 times.
528 DAE.TUPLE(PR = expl) := inExp2;
569 528 then compareList(inExp1.PR, expl);
570
571 case DAE.CAST()
572 algorithm
573
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22358 times.
22358 DAE.CAST(ty = ty, exp = e) := inExp2;
574 22358 comp := valueCompare(inExp1.ty, ty);
575
1/2
✓ Branch 0 taken 22358 times.
✗ Branch 1 not taken.
22358 then if 0==comp then compare(inExp1.exp, e) else comp;
576
577 case DAE.ASUB()
578 algorithm
579
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11155 times.
11155 DAE.ASUB(exp = e, sub = subs) := inExp2;
580 11155 comp := compare(inExp1.exp, e);
581
2/2
✓ Branch 0 taken 7609 times.
✓ Branch 1 taken 3546 times.
11155 then if comp==0 then compareSubscriptList(inExp1.sub, subs) else comp;
582
583 case DAE.RSUB()
584 algorithm
585
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 126755 times.
126755 DAE.RSUB(exp = e, ix=i, fieldName=s, ty=ty) := inExp2;
586 126755 comp := Util.intCompare(inExp1.ix, i);
587
2/2
✓ Branch 0 taken 126741 times.
✓ Branch 1 taken 14 times.
126755 comp := if comp==0 then valueCompare(inExp1.ty, ty) else comp;
588
2/2
✓ Branch 0 taken 126685 times.
✓ Branch 1 taken 70 times.
126755 comp := if comp==0 then stringCompare(inExp1.fieldName, s) else comp;
589
2/2
✓ Branch 0 taken 37495 times.
✓ Branch 1 taken 89260 times.
126755 then if comp==0 then compare(inExp1.exp, e) else comp;
590
591 case DAE.TSUB()
592 algorithm
593
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
70 DAE.TSUB(exp = e, ix=i, ty = ty) := inExp2;
594 70 comp := Util.intCompare(inExp1.ix, i);
595
1/2
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
70 comp := if 0==comp then valueCompare(inExp1.ty, ty) else comp;
596
1/2
✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
70 then if 0==comp then compare(inExp1.exp, e) else comp;
597
598 case DAE.SIZE()
599 algorithm
600
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
30 DAE.SIZE(exp = e, sz = oe) := inExp2;
601 30 comp := compare(inExp1.exp, e);
602
1/2
✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
30 then if comp==0 then compareOpt(inExp1.sz, oe) else comp;
603
604 case DAE.REDUCTION()
605 // Reductions contain too much information to compare in a sane manner.
606 4 then valueCompare(inExp1, inExp2);
607
608 case DAE.LIST()
609 algorithm
610
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 DAE.LIST(valList = expl) := inExp2;
611 14 then
612 compareList(inExp1.valList, expl);
613
614 case DAE.CONS()
615 algorithm
616
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 693 times.
693 DAE.CONS(car = e1, cdr = e2) := inExp2;
617 693 comp := compare(inExp1.car, e1);
618
2/2
✓ Branch 0 taken 691 times.
✓ Branch 1 taken 2 times.
693 then if 0==comp then compare(inExp1.cdr, e2) else comp;
619
620 case DAE.META_TUPLE()
621 algorithm
622
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 604 times.
604 DAE.META_TUPLE(listExp = expl) := inExp2;
623 604 then
624 compareList(inExp1.listExp, expl);
625
626 case DAE.META_OPTION()
627 algorithm
628
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 239 times.
239 DAE.META_OPTION(exp = oe) := inExp2;
629 239 then
630 compareOpt(inExp1.exp, oe);
631
632 case DAE.METARECORDCALL()
633 algorithm
634
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5298 times.
5298 DAE.METARECORDCALL(path = p, args = expl) := inExp2;
635 5298 comp := AbsynUtil.pathCompare(inExp1.path, p);
636
2/2
✓ Branch 0 taken 5155 times.
✓ Branch 1 taken 143 times.
5298 then if comp==0 then compareList(inExp1.args, expl) else comp;
637
638 case DAE.MATCHEXPRESSION()
639 ✗ then valueCompare(inExp1, inExp2);
640
641 case DAE.BOX()
642 algorithm
643
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3926 times.
3926 DAE.BOX(exp = e) := inExp2;
644 3926 then
645 compare(inExp1.exp, e);
646
647 case DAE.UNBOX()
648 algorithm
649
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
65 DAE.UNBOX(exp = e) := inExp2;
650 65 then
651 compare(inExp1.exp, e);
652
653 case DAE.SHARED_LITERAL()
654 algorithm
655
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11169 times.
11169 DAE.SHARED_LITERAL(index = i) := inExp2;
656 11169 then Util.intCompare(inExp1.index, i);
657
658 case DAE.EMPTY()
659 algorithm
660 ✗ DAE.EMPTY(name=cr) := inExp2;
661 ✗ then ComponentReferenceBasics.crefCompareGeneric(inExp1.name, cr);
662
663 case DAE.CODE()
664 187 then valueCompare(inExp1, inExp2);
665
666 else
667 algorithm
668 ✗ Error.addInternalError("ExpressionBasics.compare failed: ctor:" + String(valueConstructor(inExp1)) + " " + printExpStr(inExp1) + " " + printExpStr(inExp2), sourceInfo());
669 ✗ then fail();
670 end match;
671 end compare;
672
673 protected function compareList
674 input list<DAE.Exp> inExpl1;
675 input list<DAE.Exp> inExpl2;
676 output Integer comp;
677 protected
678 Integer len1, len2;
679 DAE.Exp e2;
680 list<DAE.Exp> rest_expl2 = inExpl2;
681 algorithm
682 // Check that the lists have the same length, otherwise they can't be equal.
683 1042436 len1 := listLength(inExpl1);
684 1042436 len2 := listLength(inExpl2);
685 1042436 comp := Util.intCompare(len1, len2);
686
2/2
✓ Branch 0 taken 1036893 times.
✓ Branch 1 taken 5543 times.
1042436 if comp <> 0 then
687 5543 return;
688 end if;
689
690
2/2
✓ Branch 0 taken 1546383 times.
✓ Branch 1 taken 394548 times.
1940931 for e1 in inExpl1 loop
691
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1546383 times.
1546383 e2 :: rest_expl2 := rest_expl2;
692
693 // Return false if the expressions are not equal.
694 1546383 comp := compare(e1, e2);
695
2/2
✓ Branch 0 taken 642345 times.
✓ Branch 1 taken 904038 times.
1546383 if 0 <> comp then
696 642345 return;
697 end if;
698 end for;
699
700 comp := 0;
701 end compareList;
702
703 protected function compareListList
704 input list<list<DAE.Exp>> inExpl1;
705 input list<list<DAE.Exp>> inExpl2;
706 output Integer comp;
707 protected
708 list<DAE.Exp> expl2;
709 list<list<DAE.Exp>> rest_expl2 = inExpl2;
710 Integer len1, len2;
711 algorithm
712 // Check that the lists have the same length, otherwise they can't be equal.
713 1078 len1 := listLength(inExpl1);
714 1078 len2 := listLength(inExpl2);
715 1078 comp := Util.intCompare(len1, len2);
716
1/2
✓ Branch 0 taken 1078 times.
✗ Branch 1 not taken.
1078 if comp <> 0 then
717 ✗ return;
718 end if;
719
720
2/2
✓ Branch 0 taken 2174 times.
✓ Branch 1 taken 505 times.
2679 for expl1 in inExpl1 loop
721
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2174 times.
2174 expl2 :: rest_expl2 := rest_expl2;
722
723 // Return false if the expression lists are not equal.
724 2174 comp := compareList(expl1, expl2);
725
2/2
✓ Branch 0 taken 573 times.
✓ Branch 1 taken 1601 times.
2174 if 0 <> comp then
726 573 return;
727 end if;
728 end for;
729
730 comp := 0;
731 end compareListList;
732
733 protected function compareOpt
734 input Option<DAE.Exp> inExp1;
735 input Option<DAE.Exp> inExp2;
736 output Integer comp;
737 protected
738 DAE.Exp e1, e2;
739 algorithm
740 comp := match(inExp1, inExp2)
741 case (NONE(), NONE()) then 0;
742 case (NONE(), _) then -1;
743 case (_, NONE()) then 1;
744 269 case (SOME(e1), SOME(e2)) then compare(e1, e2);
745 end match;
746 end compareOpt;
747
748 public function operatorCompare
749 "Helper function to expEqual."
750 input DAE.Operator inOperator1;
751 input DAE.Operator inOperator2;
752 output Integer comp;
753 algorithm
754 comp := match (inOperator1,inOperator2)
755 local
756 Absyn.Path p1,p2;
757
758 case (DAE.USERDEFINED(fqName = p1),DAE.USERDEFINED(fqName = p2))
759 ✗ then AbsynUtil.pathCompare(p1, p2);
760 29684975 else Util.intCompare(valueConstructor(inOperator1), valueConstructor(inOperator2));
761 end match;
762 end operatorCompare;
763
764 function compareSubscripts
765 input DAE.Subscript sub1;
766 input DAE.Subscript sub2;
767 output Integer res;
768 algorithm
769
2/2
✓ Branch 0 taken 35881 times.
✓ Branch 1 taken 20339 times.
56220 if referenceEq(sub1, sub2) then
770 res := 0;
771 else
772 res := match (sub1, sub2)
773 case (DAE.Subscript.WHOLEDIM(), DAE.Subscript.WHOLEDIM()) then 0;
774 ✗ case (DAE.Subscript.SLICE(), DAE.Subscript.SLICE()) then compare(sub1.exp, sub2.exp);
775 35881 case (DAE.Subscript.INDEX(), DAE.Subscript.INDEX()) then compare(sub1.exp, sub2.exp);
776 ✗ case (DAE.Subscript.WHOLE_NONEXP(), DAE.Subscript.WHOLE_NONEXP()) then compare(sub1.exp, sub2.exp);
777 ✗ else Util.intCompare(valueConstructor(sub1), valueConstructor(sub2));
778 end match;
779 end if;
780 end compareSubscripts;
781
782 protected function compareSubscriptList
783 input list<DAE.Subscript> subs1;
784 input list<DAE.Subscript> subs2;
785 output Integer comp;
786 protected
787 Integer len1, len2;
788 DAE.Subscript s2;
789 list<DAE.Subscript> rest_subs2 = subs2;
790 algorithm
791 // Check that the lists have the same length, otherwise they can't be equal.
792 7609 len1 := listLength(subs1);
793 7609 len2 := listLength(subs2);
794 7609 comp := Util.intCompare(len1, len2);
795
1/2
✓ Branch 0 taken 7609 times.
✗ Branch 1 not taken.
7609 if comp <> 0 then
796 ✗ return;
797 end if;
798
799
2/2
✓ Branch 0 taken 8203 times.
✓ Branch 1 taken 1096 times.
9299 for s1 in subs1 loop
800
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8203 times.
8203 s2 :: rest_subs2 := rest_subs2;
801
802 // Return false if the expressions are not equal.
803 8203 comp := compareSubscripts(s1, s2);
804
2/2
✓ Branch 0 taken 6513 times.
✓ Branch 1 taken 1690 times.
8203 if 0 <> comp then
805 6513 return;
806 end if;
807 end for;
808
809 comp := 0;
810 end compareSubscriptList;
811
812
813 public function subscriptInt
814 "Tries to convert a subscript to an integer index."
815 input DAE.Subscript inSubscript;
816 output Integer outInteger = expArrayIndex(subscriptIndexExp(inSubscript));
817 end subscriptInt;
818
819 public function subscriptsInt
820 "Tries to convert a list of subscripts to integer indices."
821 input list<DAE.Subscript> inSubscripts;
822 output list<Integer> outIntegers;
823 algorithm
824 618056 outIntegers := List.map(inSubscripts, subscriptInt);
825 end subscriptsInt;
826
827 public function expArrayIndex
828 "Returns the array index that an expression represents as an integer."
829 input DAE.Exp inExp;
830 output Integer outIndex;
831 algorithm
832 outIndex := match inExp
833 1201894 case DAE.ICONST() then inExp.integer;
834 27594 case DAE.ENUM_LITERAL() then inExp.index;
835
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 case DAE.BCONST() then if inExp.bool then 2 else 1;
836 end match;
837 end expArrayIndex;
838
839 public function subscriptIndexExp
840 "Returns the expression in a subscript index.
841 If the subscript is not an index the function fails."
842 input DAE.Subscript inSubscript;
843 output DAE.Exp outExp;
844 algorithm
845
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1017724 times.
1017724 DAE.INDEX(exp = outExp) := inSubscript;
846 end subscriptIndexExp;
847
848 public function subscriptEqual
849 "Returns true if two subscript lists are equal."
850 input list<DAE.Subscript> inSubscriptLst1;
851 input list<DAE.Subscript> inSubscriptLst2;
852 output Boolean outBoolean;
853 algorithm
854 outBoolean := match (inSubscriptLst1,inSubscriptLst2)
855 local
856 list<DAE.Subscript> xs1,xs2;
857 DAE.Exp e1,e2;
858 Integer i1,i2;
859
860 // both lists are empty
861 case ({},{}) then true;
862
863 // wholedims as list heads, compare the rest
864 case ((DAE.WHOLEDIM() :: xs1),(DAE.WHOLEDIM() :: xs2))
865 2 then subscriptEqual(xs1, xs2);
866
867 // slices as heads, compare the slice exps and then compare the rest
868 case ((DAE.SLICE(exp = e1) :: xs1),(DAE.SLICE(exp = e2) :: xs2))
869
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
9 then if expEqual(e1, e2) then subscriptEqual(xs1, xs2) else false;
870
871 case ((DAE.INDEX(exp = DAE.ICONST(i1)) :: xs1),(DAE.INDEX(exp = DAE.ICONST(i2)) :: xs2))
872
2/2
✓ Branch 0 taken 14582045 times.
✓ Branch 1 taken 3158217 times.
17740262 then if i1 == i2 then subscriptEqual(xs1, xs2) else false;
873
874 // indexes as heads, compare the index exps and then compare the rest
875 case ((DAE.INDEX(exp = e1) :: xs1),(DAE.INDEX(exp = e2) :: xs2))
876
2/2
✓ Branch 1 taken 4123 times.
✓ Branch 2 taken 3769 times.
7892 then if expEqual(e1, e2) then subscriptEqual(xs1, xs2) else false;
877
878 case ((DAE.WHOLE_NONEXP(exp = e1) :: xs1),(DAE.WHOLE_NONEXP(exp = e2) :: xs2))
879 ✗ then if expEqual(e1, e2) then subscriptEqual(xs1, xs2) else false;
880
881 // subscripts are not equal, return false
882 else false;
883 end match;
884 end subscriptEqual;
885
886 public function printListStr
887 "Same as printList, except it returns
888 a string instead of printing."
889 input list<Type_a> inTypeALst;
890 input FuncTypeType_aToString inFuncTypeTypeAToString;
891 input String inString;
892 output String outString;
893 replaceable type Type_a subtypeof Any;
894 partial function FuncTypeType_aToString
895 input Type_a inTypeA;
896 output String outString;
897 end FuncTypeType_aToString;
898 algorithm
899 482450 outString := stringDelimitList(List.map(inTypeALst,inFuncTypeTypeAToString),inString);
900 end printListStr;
901
902 public function printSubscriptStr "
903 Print a Subscript into a String."
904 input DAE.Subscript sub;
905 output String outString;
906 algorithm
907 outString := match sub
908 case DAE.WHOLEDIM() then ":";
909 646902 case DAE.INDEX() then printExpStr(sub.exp);
910 12 case DAE.SLICE() then printExpStr(sub.exp);
911 ✗ case DAE.WHOLE_NONEXP() then "1:" + printExpStr(sub.exp);
912 end match;
913 end printSubscriptStr;
914
915 public function hashExp "help function to hashExpMod"
916 input DAE.Exp e;
917 output Integer hash;
918 algorithm
919 hash := matchcontinue e
920 local
921 Real r;
922 Integer i;
923 Boolean b;
924 String s;
925 Absyn.Path path;
926 DAE.Exp e1,e2,e3;
927 DAE.Operator op;
928 list<DAE.Exp> expl;
929 list<list<DAE.Exp>> mexpl;
930 DAE.ComponentRef cr;
931 DAE.ReductionIterators iters;
932 DAE.ReductionInfo info;
933 list<DAE.Subscript> subs;
934
935 109388 case DAE.ICONST(i) then stringHashDjb2(intString(i));
936 1315825 case DAE.RCONST(r) then stringHashDjb2(realString(r));
937
2/2
✓ Branch 0 taken 25466 times.
✓ Branch 1 taken 14401 times.
65333 case DAE.BCONST(b) then stringHashDjb2(boolString(b));
938 466231 case DAE.SCONST(s) then stringHashDjb2(s);
939 221579 case DAE.ENUM_LITERAL(name=path) then stringHashDjb2(AbsynUtil.pathString(path));
940 2489884 case DAE.CREF(componentRef=cr) then ComponentReferenceBasics.hashComponentRef(cr);
941
942 1381697 case DAE.BINARY(e1,op,e2) then 1 + hashExp(e1)+hashOp(op)+hashExp(e2);
943 52857 case DAE.UNARY(op,e1) then 2 + hashOp(op)+hashExp(e1);
944 153313 case DAE.LBINARY(e1,op,e2) then 3 + hashExp(e1)+hashOp(op)+hashExp(e2);
945 15692 case DAE.LUNARY(op,e1) then 4 + hashOp(op)+hashExp(e1);
946 374494 case DAE.RELATION(e1,op,e2,_,_) then 5 + hashExp(e1)+hashOp(op)+hashExp(e2);
947 27294 case DAE.IFEXP(e1,e2,e3) then 6 + hashExp(e1)+hashExp(e2)+hashExp(e3);
948 435923 case DAE.CALL(path=path,expLst=expl) then 7 + stringHashDjb2(AbsynUtil.pathString(path))+List.reduce(List.map(expl,hashExp),intAdd);
949 15641 case DAE.RECORD(path=path,exps=expl) then 8 + stringHashDjb2(AbsynUtil.pathString(path))+List.reduce(List.map(expl,hashExp),intAdd);
950 1002 case DAE.PARTEVALFUNCTION(path=path,expList=expl) then 9 + stringHashDjb2(AbsynUtil.pathString(path))+List.reduce(List.map(expl,hashExp),intAdd);
951 83417 case DAE.ARRAY(array=expl) then 10 + List.reduce(List.map(expl,hashExp),intAdd);
952 1224 case DAE.MATRIX(matrix=mexpl) then 11 + List.reduce(List.map(List.flatten(mexpl),hashExp),intAdd);
953 6 case DAE.RANGE(_,e1,SOME(e2),e3) then 12 + hashExp(e1)+hashExp(e2)+hashExp(e3);
954 9973 case DAE.RANGE(_,e1,NONE(),e3) then 13 + hashExp(e1)+hashExp(e3);
955 36 case DAE.TUPLE(expl) then 14 + List.reduce(List.map(expl,hashExp),intAdd);
956 4336 case DAE.CAST(_,e1) then 15 + hashExp(e1);
957
4/4
✓ Branch 0 taken 2833 times.
✓ Branch 1 taken 2231 times.
✓ Branch 2 taken 2833 times.
✓ Branch 3 taken 2231 times.
5064 case DAE.ASUB(e1,subs) then 16 + hashExp(e1)+List.reduce(list(hashExp(getSubscriptExp(sub)) for sub in subs),intAdd);
958 68 case DAE.TSUB(e1,i,_) then 17 + hashExp(e1)+stringHashDjb2(intString(i));
959 9 case DAE.SIZE(e1,SOME(e2)) then 18 + hashExp(e1)+hashExp(e2);
960 ✗ case DAE.SIZE(e1,NONE()) then 19 + hashExp(e1);
961 // case(DAE.CODE(_,_)) then 20; // TODO: implement hashing of CODE AST
962 // case(DAE.EMPTY(scope=_)) then 21; // TODO: implement hashing of EMTPY (needed ?)
963 ✗ case DAE.REDUCTION(info,e1,iters) then 22 + hashReductionInfo(info)+hashExp(e1)+List.reduce(List.map(iters,hashReductionIter),intAdd);
964 // TODO: hashing of all MetaModelica extensions
965 37912 else stringHashDjb2(printExpStr(e));
966 end matchcontinue;
967 end hashExp;
968
969 protected function hashReductionInfo "help function to hashExp"
970 input DAE.ReductionInfo info;
971 output Integer hash;
972 algorithm
973 hash := match info
974 local
975 Absyn.Path path;
976
977 // TODO: complete hasing of all subexpressions
978 ✗ case DAE.REDUCTIONINFO(path=path) then 22 + stringHashDjb2(AbsynUtil.pathString(path));
979 end match;
980 end hashReductionInfo;
981
982 protected function hashReductionIter "help function to hashExp"
983 input DAE.ReductionIterator iter;
984 output Integer hash;
985 algorithm
986 hash := match iter
987 local
988 String id;
989 DAE.Exp e1,e2;
990
991
992 ✗ case DAE.REDUCTIONITER(id,e1,SOME(e2),_) then 23 + stringHashDjb2(id)+hashExp(e1)+hashExp(e2);
993 ✗ case DAE.REDUCTIONITER(id,e1,NONE(),_) then 24 + stringHashDjb2(id)+hashExp(e1);
994 end match;
995
996 end hashReductionIter;
997
998 protected function hashOp "help function to hashExp"
999 input DAE.Operator op;
1000 output Integer hash;
1001 algorithm
1002 hash := match op
1003 local
1004 Absyn.Path path;
1005
1006 case DAE.ADD(_) then 25;
1007 case DAE.SUB(_) then 26;
1008 case DAE.MUL(_) then 27;
1009 case DAE.DIV(_) then 28;
1010 case DAE.POW(_) then 29;
1011 case DAE.UMINUS(_) then 30;
1012 case DAE.UMINUS_ARR(_) then 31;
1013 case DAE.ADD_ARR(_) then 32;
1014 case DAE.SUB_ARR(_) then 33;
1015 case DAE.MUL_ARR(_) then 34;
1016 case DAE.DIV_ARR(_) then 35;
1017 case DAE.MUL_ARRAY_SCALAR(_) then 36;
1018 case DAE.ADD_ARRAY_SCALAR(_) then 37;
1019 case DAE.SUB_SCALAR_ARRAY(_) then 38;
1020 case DAE.MUL_SCALAR_PRODUCT(_) then 39;
1021 case DAE.MUL_MATRIX_PRODUCT(_) then 40;
1022 case DAE.DIV_ARRAY_SCALAR(_) then 41;
1023 case DAE.DIV_SCALAR_ARRAY(_) then 42;
1024 case DAE.POW_ARRAY_SCALAR(_) then 43;
1025 case DAE.POW_SCALAR_ARRAY(_) then 44;
1026 case DAE.POW_ARR(_) then 45;
1027 case DAE.POW_ARR2(_) then 46;
1028 case DAE.AND(_) then 47;
1029 case DAE.OR(_) then 48;
1030 case DAE.NOT(_) then 49;
1031 case DAE.LESS(_) then 50;
1032 case DAE.LESSEQ(_) then 51;
1033 case DAE.GREATER(_) then 52;
1034 case DAE.GREATEREQ(_) then 53;
1035 case DAE.EQUAL(_) then 54;
1036 case DAE.NEQUAL(_) then 55;
1037 ✗ case DAE.USERDEFINED(path) then 56 + stringHashDjb2(AbsynUtil.pathString(path)) ;
1038 end match;
1039 end hashOp;
1040
1041 protected function getSubscriptExp
1042 "Returns the subscript expression, or fails on DAE.WHOLEDIM."
1043 input DAE.Subscript inSubscript;
1044 output DAE.Exp outExp;
1045 algorithm
1046 outExp := match inSubscript
1047 local DAE.Exp e;
1048
1049 case DAE.SLICE(exp = e) then e;
1050 case DAE.INDEX(exp = e) then e;
1051 case DAE.WHOLE_NONEXP(exp = e) then e;
1052 end match;
1053 end getSubscriptExp;
1054
1055 annotation(__OpenModelica_Interface="frontend_dump");
1056 end ExpressionBasics;
1057