OMCompiler/Compiler/NFFrontEnd/NFExpression.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 uniontype NFExpression | ||
| 37 | protected | ||
| 38 | import Array; | ||
| 39 | import Util; | ||
| 40 | import Absyn; | ||
| 41 | import AbsynUtil; | ||
| 42 | import List; | ||
| 43 | import System; | ||
| 44 | import Flags; | ||
| 45 | |||
| 46 | import NFBackendExtension.{BackendInfo, VariableKind}; | ||
| 47 | import Builtin = NFBuiltin; | ||
| 48 | import BuiltinCall = NFBuiltinCall; | ||
| 49 | import Ceval = NFCeval; | ||
| 50 | import ComplexType = NFComplexType; | ||
| 51 | import ExpandExp = NFExpandExp; | ||
| 52 | import Expression = NFExpression; | ||
| 53 | import Function = NFFunction; | ||
| 54 | import JSON; | ||
| 55 | import MetaModelica.Dangerous.*; | ||
| 56 | import NFPrefixes.{Variability, Purity}; | ||
| 57 | import Prefixes = NFPrefixes; | ||
| 58 | import RangeIterator = NFRangeIterator; | ||
| 59 | import SimplifyExp = NFSimplifyExp; | ||
| 60 | import TypeCheck = NFTypeCheck; | ||
| 61 | import UnorderedSet; | ||
| 62 | import ValuesMake; | ||
| 63 | import Variable = NFVariable; | ||
| 64 | |||
| 65 | public | ||
| 66 | import Absyn.Path; | ||
| 67 | import BaseModelica; | ||
| 68 | import DAE; | ||
| 69 | import NFInstNode.InstNode; | ||
| 70 | import Operator = NFOperator; | ||
| 71 | import Subscript = NFSubscript; | ||
| 72 | import Dimension = NFDimension; | ||
| 73 | import Type = NFType; | ||
| 74 | import ComponentRef = NFComponentRef; | ||
| 75 | import Call = NFCall; | ||
| 76 | import Binding = NFBinding; | ||
| 77 | import NFClassTree.ClassTree; | ||
| 78 | import Class = NFClass; | ||
| 79 | import NFComponentRef.Origin; | ||
| 80 | import Values; | ||
| 81 | import Record = NFRecord; | ||
| 82 | import ClockKind = NFClockKind; | ||
| 83 | import ExpressionIterator = NFExpressionIterator; | ||
| 84 | import InstContext = NFInstContext; | ||
| 85 | import UnorderedMap; | ||
| 86 | |||
| 87 | record INTEGER | ||
| 88 | Integer value; | ||
| 89 | end INTEGER; | ||
| 90 | |||
| 91 | record REAL | ||
| 92 | Real value; | ||
| 93 | end REAL; | ||
| 94 | |||
| 95 | record STRING | ||
| 96 | String value; | ||
| 97 | end STRING; | ||
| 98 | |||
| 99 | record BOOLEAN | ||
| 100 | Boolean value; | ||
| 101 | end BOOLEAN; | ||
| 102 | |||
| 103 | record ENUM_LITERAL | ||
| 104 | Type ty; | ||
| 105 | String name; | ||
| 106 | Integer index; | ||
| 107 | end ENUM_LITERAL; | ||
| 108 | |||
| 109 | record CLKCONST "Clock constructors" | ||
| 110 | ClockKind clk "Clock kinds"; | ||
| 111 | end CLKCONST; | ||
| 112 | |||
| 113 | record CREF | ||
| 114 | Type ty; | ||
| 115 | ComponentRef cref; | ||
| 116 | end CREF; | ||
| 117 | |||
| 118 | record TYPENAME "Represents a type used as a range, e.g. Boolean." | ||
| 119 | Type ty; | ||
| 120 | end TYPENAME; | ||
| 121 | |||
| 122 | record ARRAY | ||
| 123 | Type ty; | ||
| 124 | array<Expression> elements; | ||
| 125 | Boolean literal "True if the array is known to only contain literal expressions."; | ||
| 126 | end ARRAY; | ||
| 127 | |||
| 128 | record MATRIX "The array concatentation operator [a,b; c,d]; this should be removed during type-checking" | ||
| 129 | // Does not have a type since we only keep this operator before type-checking | ||
| 130 | list<list<Expression>> elements; | ||
| 131 | end MATRIX; | ||
| 132 | |||
| 133 | record RANGE | ||
| 134 | Type ty; | ||
| 135 | Expression start; | ||
| 136 | Option<Expression> step; | ||
| 137 | Expression stop; | ||
| 138 | end RANGE; | ||
| 139 | |||
| 140 | record TUPLE | ||
| 141 | Type ty; | ||
| 142 | list<Expression> elements; | ||
| 143 | end TUPLE; | ||
| 144 | |||
| 145 | record RECORD | ||
| 146 | Path path; // Maybe not needed since the type contains the name. Prefix? | ||
| 147 | Type ty; | ||
| 148 | list<Expression> elements; | ||
| 149 | end RECORD; | ||
| 150 | |||
| 151 | record CALL | ||
| 152 | Call call; | ||
| 153 | end CALL; | ||
| 154 | |||
| 155 | record SIZE | ||
| 156 | Expression exp; | ||
| 157 | Option<Expression> dimIndex; | ||
| 158 | end SIZE; | ||
| 159 | |||
| 160 | record END | ||
| 161 | end END; | ||
| 162 | |||
| 163 | record BINARY "Binary operations, e.g. a+4" | ||
| 164 | Expression exp1; | ||
| 165 | Operator operator; | ||
| 166 | Expression exp2; | ||
| 167 | end BINARY; | ||
| 168 | |||
| 169 | record UNARY "Unary operations, -(4x)" | ||
| 170 | Operator operator; | ||
| 171 | Expression exp; | ||
| 172 | end UNARY; | ||
| 173 | |||
| 174 | record LBINARY "Logical binary operations: and, or" | ||
| 175 | Expression exp1; | ||
| 176 | Operator operator; | ||
| 177 | Expression exp2; | ||
| 178 | end LBINARY; | ||
| 179 | |||
| 180 | record LUNARY "Logical unary operations: not" | ||
| 181 | Operator operator; | ||
| 182 | Expression exp; | ||
| 183 | end LUNARY; | ||
| 184 | |||
| 185 | record RELATION "Relation, e.g. a <= 0" | ||
| 186 | Expression exp1; | ||
| 187 | Operator operator; | ||
| 188 | Expression exp2; | ||
| 189 | Integer index "index for event codegen"; // TODO: remove me :) | ||
| 190 | end RELATION; | ||
| 191 | |||
| 192 | record MULTARY | ||
| 193 | "Multary expressions with the same operator, e.g. a+b+c | ||
| 194 | An empty list has to be interpreted as the neutral element of the operator space" | ||
| 195 | list<Expression> arguments "arguments that are chained with the operator (+, *)"; | ||
| 196 | list<Expression> inv_arguments "arguments that are chained with the inverse operator (-, :)"; | ||
| 197 | Operator operator "Can only be + or * (commutative)"; | ||
| 198 | end MULTARY; | ||
| 199 | |||
| 200 | record IF | ||
| 201 | Type ty; | ||
| 202 | Expression condition; | ||
| 203 | Expression trueBranch; | ||
| 204 | Expression falseBranch; | ||
| 205 | end IF; | ||
| 206 | |||
| 207 | record CAST | ||
| 208 | Type ty; | ||
| 209 | Expression exp; | ||
| 210 | end CAST; | ||
| 211 | |||
| 212 | record BOX "MetaModelica boxed value" | ||
| 213 | Expression exp; | ||
| 214 | end BOX; | ||
| 215 | |||
| 216 | record UNBOX "MetaModelica value unboxing (similar to a cast)" | ||
| 217 | Expression exp; | ||
| 218 | Type ty; | ||
| 219 | end UNBOX; | ||
| 220 | |||
| 221 | record SUBSCRIPTED_EXP | ||
| 222 | Expression exp; | ||
| 223 | list<Subscript> subscripts; | ||
| 224 | Type ty; | ||
| 225 | Boolean split; | ||
| 226 | end SUBSCRIPTED_EXP; | ||
| 227 | |||
| 228 | record TUPLE_ELEMENT | ||
| 229 | Expression tupleExp; | ||
| 230 | Integer index; | ||
| 231 | Type ty; | ||
| 232 | end TUPLE_ELEMENT; | ||
| 233 | |||
| 234 | record RECORD_ELEMENT | ||
| 235 | Expression recordExp; | ||
| 236 | Integer index; | ||
| 237 | String fieldName; | ||
| 238 | Type ty; | ||
| 239 | end RECORD_ELEMENT; | ||
| 240 | |||
| 241 | record MUTABLE | ||
| 242 | Mutable<Expression> exp; | ||
| 243 | end MUTABLE; | ||
| 244 | |||
| 245 | record EMPTY | ||
| 246 | Type ty; | ||
| 247 | end EMPTY; | ||
| 248 | |||
| 249 | record PARTIAL_FUNCTION_APPLICATION | ||
| 250 | ComponentRef fn; | ||
| 251 | list<Expression> args; | ||
| 252 | list<String> argNames; | ||
| 253 | Type ty; | ||
| 254 | end PARTIAL_FUNCTION_APPLICATION; | ||
| 255 | |||
| 256 | record FILENAME | ||
| 257 | String filename; | ||
| 258 | end FILENAME; | ||
| 259 | |||
| 260 | record SHARED_LITERAL | ||
| 261 | "Before code generation, we make a pass that replaces constant literals | ||
| 262 | with a SHARED_LITERAL expression. Any immutable type can be shared: | ||
| 263 | basic MetaModelica types and Modelica strings are fine. There is no point | ||
| 264 | to share Real, Integer, Boolean or Enum though." | ||
| 265 | Integer index "A unique indexing that can be used to point to a single shared literal in generated code"; | ||
| 266 | Expression exp "For printing strings, code generators that do not support this kind of literal, or for getting the type in case the code generator needs that"; | ||
| 267 | end SHARED_LITERAL; | ||
| 268 | |||
| 269 | record INSTANCE_NAME | ||
| 270 | InstNode scope; | ||
| 271 | end INSTANCE_NAME; | ||
| 272 | |||
| 273 | function isArray | ||
| 274 | input Expression exp; | ||
| 275 | output Boolean isArray; | ||
| 276 | algorithm | ||
| 277 | isArray := match exp | ||
| 278 | case ARRAY() then true; | ||
| 279 | else false; | ||
| 280 | end match; | ||
| 281 | end isArray; | ||
| 282 | |||
| 283 | function isEmptyArray | ||
| 284 | input Expression exp; | ||
| 285 | output Boolean emptyArray; | ||
| 286 | algorithm | ||
| 287 | emptyArray := match exp | ||
| 288 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 157906 times.
|
315812 | case ARRAY() then arrayEmpty(exp.elements); |
| 289 | else false; | ||
| 290 | end match; | ||
| 291 | end isEmptyArray; | ||
| 292 | |||
| 293 | function isVector | ||
| 294 | input Expression exp; | ||
| 295 | output Boolean res; | ||
| 296 | algorithm | ||
| 297 | res := match exp | ||
| 298 | 106427 | case ARRAY() then Type.isVector(exp.ty); | |
| 299 | else false; | ||
| 300 | end match; | ||
| 301 | end isVector; | ||
| 302 | |||
| 303 | function isCref | ||
| 304 | input Expression exp; | ||
| 305 | output Boolean isCref; | ||
| 306 | algorithm | ||
| 307 | isCref := match exp | ||
| 308 | case CREF() then true; | ||
| 309 | else false; | ||
| 310 | end match; | ||
| 311 | end isCref; | ||
| 312 | |||
| 313 | function isFunctionInputCref | ||
| 314 | input Expression exp; | ||
| 315 | output Boolean res; | ||
| 316 | algorithm | ||
| 317 | res := match exp | ||
| 318 | 294 | case CREF() then ComponentRef.isInput(ComponentRef.last(exp.cref)); | |
| 319 | else false; | ||
| 320 | end match; | ||
| 321 | end isFunctionInputCref; | ||
| 322 | |||
| 323 | function isWildCref | ||
| 324 | input Expression exp; | ||
| 325 | output Boolean wild; | ||
| 326 | algorithm | ||
| 327 | wild := match exp | ||
| 328 | case CREF(cref = ComponentRef.WILD()) then true; | ||
| 329 | else false; | ||
| 330 | end match; | ||
| 331 | end isWildCref; | ||
| 332 | |||
| 333 | function isCall | ||
| 334 | input Expression exp; | ||
| 335 | output Boolean isCall; | ||
| 336 | algorithm | ||
| 337 | isCall := match exp | ||
| 338 | case CALL() then true; | ||
| 339 | else false; | ||
| 340 | end match; | ||
| 341 | end isCall; | ||
| 342 | |||
| 343 | function isImpureCall | ||
| 344 | input Expression exp; | ||
| 345 | output Boolean isImpure; | ||
| 346 | algorithm | ||
| 347 | isImpure := match exp | ||
| 348 | 35201 | case CALL() then Call.isImpure(exp.call); | |
| 349 | else false; | ||
| 350 | end match; | ||
| 351 | end isImpureCall; | ||
| 352 | |||
| 353 | function isExternalCall | ||
| 354 | input Expression exp; | ||
| 355 | output Boolean res; | ||
| 356 | algorithm | ||
| 357 | res := match exp | ||
| 358 | 28522 | case CALL() then Call.isExternal(exp.call); | |
| 359 | else false; | ||
| 360 | end match; | ||
| 361 | end isExternalCall; | ||
| 362 | |||
| 363 | function isCallNamed | ||
| 364 | input Expression exp; | ||
| 365 | input String name; | ||
| 366 | output Boolean res; | ||
| 367 | algorithm | ||
| 368 | res := match exp | ||
| 369 | 14666 | case CALL() then Call.isNamed(exp.call, name); | |
| 370 | else false; | ||
| 371 | end match; | ||
| 372 | end isCallNamed; | ||
| 373 | |||
| 374 | function isConnectionCall | ||
| 375 | input Expression exp; | ||
| 376 | output Boolean isConnection; | ||
| 377 | algorithm | ||
| 378 | isConnection := match exp | ||
| 379 | case CALL() | ||
| 380 |
6/6✓ Branch 1 taken 486 times.
✓ Branch 2 taken 15 times.
✓ Branch 4 taken 480 times.
✓ Branch 5 taken 6 times.
✓ Branch 7 taken 5 times.
✓ Branch 8 taken 475 times.
|
501 | then Call.isConnectionsOperator(exp.call) or |
| 381 | Call.isStreamOperator(exp.call) or | ||
| 382 | Call.isCardinality(exp.call); | ||
| 383 | else false; | ||
| 384 | end match; | ||
| 385 | end isConnectionCall; | ||
| 386 | |||
| 387 | function isTrue | ||
| 388 | input Expression exp; | ||
| 389 | output Boolean isTrue; | ||
| 390 | algorithm | ||
| 391 | isTrue := match exp | ||
| 392 | case BOOLEAN(true) then true; | ||
| 393 | else false; | ||
| 394 | end match; | ||
| 395 | end isTrue; | ||
| 396 | |||
| 397 | function isAllTrue | ||
| 398 | input Expression exp; | ||
| 399 | output Boolean isTrue; | ||
| 400 | algorithm | ||
| 401 | isTrue := match exp | ||
| 402 | local | ||
| 403 | Expression e; | ||
| 404 | case BOOLEAN(true) then true; | ||
| 405 | 45 | case ARRAY() then Array.all(exp.elements, isAllTrue); | |
| 406 | 825 | case CALL(call = Call.TYPED_ARRAY_CONSTRUCTOR(exp = e)) then isAllTrue(e); | |
| 407 | else false; | ||
| 408 | end match; | ||
| 409 | end isAllTrue; | ||
| 410 | |||
| 411 | function isFalse | ||
| 412 | input Expression exp; | ||
| 413 | output Boolean isTrue; | ||
| 414 | algorithm | ||
| 415 | isTrue := match exp | ||
| 416 | case BOOLEAN(false) then true; | ||
| 417 | else false; | ||
| 418 | end match; | ||
| 419 | end isFalse; | ||
| 420 | |||
| 421 | function isTrivialCref | ||
| 422 | input Expression exp; | ||
| 423 | output Boolean b; | ||
| 424 | algorithm | ||
| 425 | b := match exp | ||
| 426 | case CREF() then true; | ||
| 427 | case UNARY(exp = CREF()) then true; | ||
| 428 | case LUNARY(exp = CREF()) then true; | ||
| 429 | else false; | ||
| 430 | end match; | ||
| 431 | end isTrivialCref; | ||
| 432 | |||
| 433 | function hash | ||
| 434 | input Expression exp; | ||
| 435 | output Integer hash = hashContinue(exp, Util.HASH_SEED); | ||
| 436 | end hash; | ||
| 437 | |||
| 438 | function hashContinue | ||
| 439 | input Expression exp; | ||
| 440 | input output Integer hash; | ||
| 441 | algorithm | ||
| 442 | hash := match exp | ||
| 443 | local | ||
| 444 | Absyn.Path path; | ||
| 445 | |||
| 446 | 967 | case INTEGER() then intHashDjb2Continue(exp.value, hash); | |
| 447 | 8229 | case REAL() then stringHashDjb2Continue(realString(exp.value), hash); | |
| 448 | 4266 | case STRING() then stringHashDjb2Continue(exp.value, hash); | |
| 449 | ✗ | case BOOLEAN() then stringHashDjb2Continue(boolString(exp.value), hash); | |
| 450 | |||
| 451 | case ENUM_LITERAL(ty = Type.ENUMERATION(typePath = path)) | ||
| 452 | algorithm | ||
| 453 | ✗ | hash := AbsynUtil.pathHashContinue(path, hash); | |
| 454 | ✗ | hash := stringHashDjb2Continue(".", hash); | |
| 455 | ✗ | hash := stringHashDjb2Continue(exp.name, hash); | |
| 456 | then hash; | ||
| 457 | |||
| 458 | ✗ | case CLKCONST() then ClockKind.hashContinue(exp.clk, hash); | |
| 459 | 56795 | case CREF() then ComponentRef.hashContinue(exp.cref, false, hash); | |
| 460 | ✗ | case TYPENAME() then Type.hashContinue(Type.arrayElementType(exp.ty), hash); | |
| 461 | |||
| 462 | case ARRAY() | ||
| 463 | algorithm | ||
| 464 | 859 | hash := stringHashDjb2Continue("{", hash); | |
| 465 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 859 times.
✓ Branch 3 taken 4058 times.
✓ Branch 4 taken 859 times.
|
5776 | for e in exp.elements loop |
| 466 | 4058 | hash := hashContinue(e, hash); | |
| 467 | 4058 | hash := stringHashDjb2Continue(", ", hash); // trailing comma, don't care... | |
| 468 | end for; | ||
| 469 | 859 | hash := stringHashDjb2Continue("}", hash); | |
| 470 | then hash; | ||
| 471 | |||
| 472 | case MATRIX() | ||
| 473 | algorithm | ||
| 474 | ✗ | hash := stringHashDjb2Continue("[", hash); | |
| 475 | ✗ | for el in exp.elements loop | |
| 476 | ✗ | for e in el loop | |
| 477 | ✗ | hash := hashContinue(e, hash); | |
| 478 | ✗ | hash := stringHashDjb2Continue(", ", hash); // trailing comma, don't care... | |
| 479 | end for; | ||
| 480 | ✗ | hash := stringHashDjb2Continue("; ", hash); // trailing semicolon, don't care... | |
| 481 | end for; | ||
| 482 | ✗ | hash := stringHashDjb2Continue("]", hash); | |
| 483 | then hash; | ||
| 484 | |||
| 485 | case RANGE() | ||
| 486 | algorithm | ||
| 487 | ✗ | hash := hashContinue(exp.start, hash); | |
| 488 | ✗ | hash := stringHashDjb2Continue(":", hash); | |
| 489 | ✗ | if isSome(exp.step) then | |
| 490 | ✗ | hash := hashContinue(Util.getOption(exp.step), hash); | |
| 491 | ✗ | hash := stringHashDjb2Continue(":", hash); | |
| 492 | end if; | ||
| 493 | ✗ | hash := hashContinue(exp.stop, hash); | |
| 494 | then hash; | ||
| 495 | |||
| 496 | case TUPLE() | ||
| 497 | algorithm | ||
| 498 | 4 | hash := stringHashDjb2Continue("(", hash); | |
| 499 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
|
20 | for e in exp.elements loop |
| 500 | 16 | hash := hashContinue(e, hash); | |
| 501 | 16 | hash := stringHashDjb2Continue(", ", hash); // trailing comma, don't care... | |
| 502 | end for; | ||
| 503 | 4 | hash := stringHashDjb2Continue(")", hash); | |
| 504 | then hash; | ||
| 505 | |||
| 506 | case RECORD() | ||
| 507 | algorithm | ||
| 508 | 62 | hash := AbsynUtil.pathHashContinue(exp.path, hash); | |
| 509 | 62 | hash := stringHashDjb2Continue("(", hash); | |
| 510 |
2/2✓ Branch 0 taken 604 times.
✓ Branch 1 taken 62 times.
|
666 | for e in exp.elements loop |
| 511 | 604 | hash := hashContinue(e, hash); | |
| 512 | 604 | hash := stringHashDjb2Continue(", ", hash); // trailing comma, don't care... | |
| 513 | end for; | ||
| 514 | 62 | hash := stringHashDjb2Continue(")", hash); | |
| 515 | then hash; | ||
| 516 | |||
| 517 | 3757 | case CALL() then stringHashDjb2Continue(Call.toString(exp.call), hash); // TODO use Call.hashContinue | |
| 518 | |||
| 519 | case SIZE() | ||
| 520 | algorithm | ||
| 521 | ✗ | hash := stringHashDjb2Continue("size(", hash); | |
| 522 | ✗ | hash := hashContinue(exp.exp, hash); | |
| 523 | ✗ | if isSome(exp.dimIndex) then | |
| 524 | ✗ | hash := stringHashDjb2Continue(", ", hash); | |
| 525 | ✗ | hash := hashContinue(Util.getOption(exp.dimIndex), hash); | |
| 526 | end if; | ||
| 527 | ✗ | hash := stringHashDjb2Continue(")", hash); | |
| 528 | then hash; | ||
| 529 | |||
| 530 | ✗ | case END() then stringHashDjb2Continue("end", hash); | |
| 531 | |||
| 532 | case BINARY() | ||
| 533 | algorithm | ||
| 534 | 6236 | hash := hashContinue(exp.exp1, hash); | |
| 535 | 6236 | hash := stringHashDjb2Continue(Operator.symbol(exp.operator), hash); | |
| 536 | 6236 | hash := hashContinue(exp.exp2, hash); | |
| 537 | then hash; | ||
| 538 | |||
| 539 | case UNARY() | ||
| 540 | algorithm | ||
| 541 | 204 | hash := stringHashDjb2Continue(Operator.symbol(exp.operator, ""), hash); | |
| 542 | 204 | hash := hashContinue(exp.exp, hash); | |
| 543 | then hash; | ||
| 544 | |||
| 545 | case LBINARY() | ||
| 546 | algorithm | ||
| 547 | ✗ | hash := hashContinue(exp.exp1, hash); | |
| 548 | ✗ | hash := stringHashDjb2Continue(Operator.symbol(exp.operator), hash); | |
| 549 | ✗ | hash := hashContinue(exp.exp2, hash); | |
| 550 | then hash; | ||
| 551 | |||
| 552 | case LUNARY() | ||
| 553 | algorithm | ||
| 554 | ✗ | hash := stringHashDjb2Continue(Operator.symbol(exp.operator, ""), hash); | |
| 555 | ✗ | hash := stringHashDjb2Continue(" ", hash); | |
| 556 | ✗ | hash := hashContinue(exp.exp, hash); | |
| 557 | then hash; | ||
| 558 | |||
| 559 | case RELATION() | ||
| 560 | algorithm | ||
| 561 | 317 | hash := hashContinue(exp.exp1, hash); | |
| 562 | 317 | hash := stringHashDjb2Continue(Operator.symbol(exp.operator), hash); | |
| 563 | 317 | hash := hashContinue(exp.exp2, hash); | |
| 564 | then hash; | ||
| 565 | |||
| 566 | case MULTARY() | ||
| 567 | algorithm | ||
| 568 | 11906 | hash := stringHashDjb2Continue("(", hash); | |
| 569 |
2/2✓ Branch 0 taken 21779 times.
✓ Branch 1 taken 11906 times.
|
33685 | for e in exp.arguments loop |
| 570 | 21779 | hash := stringHashDjb2Continue(Operator.symbol(exp.operator), hash); | |
| 571 | 21779 | hash := hashContinue(e, hash); | |
| 572 | end for; | ||
| 573 | 11906 | hash := stringHashDjb2Continue(")", hash); | |
| 574 | 11906 | hash := stringHashDjb2Continue(Operator.symbol(Operator.invert(exp.operator)), hash); | |
| 575 | 11906 | hash := stringHashDjb2Continue("(", hash); | |
| 576 |
2/2✓ Branch 0 taken 2594 times.
✓ Branch 1 taken 11906 times.
|
14500 | for e in exp.inv_arguments loop |
| 577 | 2594 | hash := stringHashDjb2Continue(Operator.symbol(exp.operator), hash); | |
| 578 | 2594 | hash := hashContinue(e, hash); | |
| 579 | end for; | ||
| 580 | 11906 | hash := stringHashDjb2Continue(")", hash); | |
| 581 | then hash; | ||
| 582 | |||
| 583 | case IF() | ||
| 584 | algorithm | ||
| 585 | 329 | hash := stringHashDjb2Continue("if ", hash); | |
| 586 | 329 | hash := hashContinue(exp.condition, hash); | |
| 587 | 329 | hash := stringHashDjb2Continue(" then ", hash); | |
| 588 | 329 | hash := hashContinue(exp.trueBranch, hash); | |
| 589 | 329 | hash := stringHashDjb2Continue(" else ", hash); | |
| 590 | 329 | hash := hashContinue(exp.falseBranch, hash); | |
| 591 | then hash; | ||
| 592 | |||
| 593 | case CAST() | ||
| 594 | algorithm | ||
| 595 | 183 | hash := stringHashDjb2Continue("CAST(", hash); | |
| 596 | 183 | hash := Type.hashContinue(exp.ty, hash); | |
| 597 | 183 | hash := stringHashDjb2Continue(", ", hash); | |
| 598 | 183 | hash := hashContinue(exp.exp, hash); | |
| 599 | 183 | hash := stringHashDjb2Continue(")", hash); | |
| 600 | then hash; | ||
| 601 | |||
| 602 | case BOX() | ||
| 603 | algorithm | ||
| 604 | ✗ | hash := stringHashDjb2Continue("BOX(", hash); | |
| 605 | ✗ | hash := hashContinue(exp.exp, hash); | |
| 606 | ✗ | hash := stringHashDjb2Continue(")", hash); | |
| 607 | then hash; | ||
| 608 | |||
| 609 | case UNBOX() | ||
| 610 | algorithm | ||
| 611 | ✗ | hash := stringHashDjb2Continue("UNBOX(", hash); | |
| 612 | ✗ | hash := hashContinue(exp.exp, hash); | |
| 613 | ✗ | hash := stringHashDjb2Continue(")", hash); | |
| 614 | then hash; | ||
| 615 | |||
| 616 | case SUBSCRIPTED_EXP() | ||
| 617 | algorithm | ||
| 618 | 129 | hash := stringHashDjb2Continue("(", hash); | |
| 619 | 129 | hash := hashContinue(exp.exp, hash); | |
| 620 | 129 | hash := stringHashDjb2Continue(")[", hash); | |
| 621 |
2/2✓ Branch 0 taken 129 times.
✓ Branch 1 taken 129 times.
|
258 | for sub in exp.subscripts loop |
| 622 | 129 | hash := Subscript.hashContinue(sub, hash); | |
| 623 | 129 | hash := stringHashDjb2Continue(", ", hash); // trailing comma, don't care... | |
| 624 | end for; | ||
| 625 | 129 | hash := stringHashDjb2Continue("]", hash); | |
| 626 | then hash; | ||
| 627 | |||
| 628 | case TUPLE_ELEMENT() | ||
| 629 | algorithm | ||
| 630 | ✗ | hash := hashContinue(exp.tupleExp, hash); | |
| 631 | ✗ | hash := stringHashDjb2Continue("[", hash); | |
| 632 | ✗ | hash := stringHashDjb2Continue(intString(exp.index), hash); | |
| 633 | ✗ | hash := stringHashDjb2Continue("]", hash); | |
| 634 | then hash; | ||
| 635 | |||
| 636 | case RECORD_ELEMENT() | ||
| 637 | algorithm | ||
| 638 | 59 | hash := stringHashDjb2Continue("(", hash); | |
| 639 | 59 | hash := hashContinue(exp.recordExp, hash); | |
| 640 | 59 | hash := stringHashDjb2Continue(").", hash); | |
| 641 | 59 | hash := stringHashDjb2Continue(exp.fieldName, hash); | |
| 642 | then hash; | ||
| 643 | |||
| 644 | ✗ | case MUTABLE() then hashContinue(Mutable.access(exp.exp), hash); | |
| 645 | ✗ | case EMPTY() then stringHashDjb2Continue("#EMPTY#", hash); | |
| 646 | |||
| 647 | case PARTIAL_FUNCTION_APPLICATION() | ||
| 648 | algorithm | ||
| 649 | ✗ | hash := stringHashDjb2Continue("function ", hash); | |
| 650 | ✗ | hash := ComponentRef.hashContinue(exp.fn, false, hash); | |
| 651 | ✗ | hash := stringHashDjb2Continue("(", hash); | |
| 652 | //list(n + " = " + toString(a) threaded for a in exp.args, n in exp.argNames) | ||
| 653 | ✗ | for n in exp.argNames loop | |
| 654 | ✗ | hash := stringHashDjb2Continue(n, hash); | |
| 655 | ✗ | hash := stringHashDjb2Continue(", ", hash); // trailing comma, don't care... | |
| 656 | end for; | ||
| 657 | ✗ | hash := stringHashDjb2Continue(" = ", hash); | |
| 658 | ✗ | for a in exp.args loop | |
| 659 | ✗ | hash := hashContinue(a, hash); | |
| 660 | ✗ | hash := stringHashDjb2Continue(", ", hash); // trailing comma, don't care... | |
| 661 | end for; | ||
| 662 | ✗ | hash := stringHashDjb2Continue(")", hash); | |
| 663 | then hash; | ||
| 664 | |||
| 665 | ✗ | case FILENAME() then stringHashDjb2Continue(exp.filename, hash); | |
| 666 | |||
| 667 | case SHARED_LITERAL() | ||
| 668 | algorithm | ||
| 669 | 346 | hash := stringHashDjb2Continue("LITERAL(", hash); | |
| 670 | 346 | hash := stringHashDjb2Continue(intString(exp.index), hash); | |
| 671 | 346 | hash := stringHashDjb2Continue(", ", hash); | |
| 672 | 346 | hash := hashContinue(exp.exp, hash); | |
| 673 | 346 | hash := stringHashDjb2Continue(")", hash); | |
| 674 | then hash; | ||
| 675 | |||
| 676 | ✗ | case INSTANCE_NAME() then stringHashDjb2Continue("getInstanceName()", hash); | |
| 677 | else hash; | ||
| 678 | end match; | ||
| 679 | end hashContinue; | ||
| 680 | |||
| 681 | function isEqual | ||
| 682 | "Returns true if the two expressions are equal, otherwise false." | ||
| 683 | input Expression exp1; | ||
| 684 | input Expression exp2; | ||
| 685 | output Boolean isEqual; | ||
| 686 | algorithm | ||
| 687 | 313055 | isEqual := 0 == compare(exp1, exp2); | |
| 688 | end isEqual; | ||
| 689 | |||
| 690 | function compare | ||
| 691 | "Checks whether two expressions are equal, and returns 0 if they are. | ||
| 692 | If the first expression is 'less' than the second it returns an integer | ||
| 693 | less than 0, otherwise an integer greater than 0." | ||
| 694 | input Expression exp1; | ||
| 695 | input Expression exp2; | ||
| 696 | output Integer comp; | ||
| 697 | algorithm | ||
| 698 | // Check if the expressions are the same object. | ||
| 699 |
2/2✓ Branch 0 taken 18073 times.
✓ Branch 1 taken 373145 times.
|
391218 | if referenceEq(exp1, exp2) then |
| 700 | comp := 0; | ||
| 701 | 18073 | return; | |
| 702 | end if; | ||
| 703 | |||
| 704 | // Return false if the expressions are of different kinds. | ||
| 705 | 373145 | comp := Util.intCompare(valueConstructor(exp1), valueConstructor(exp2)); | |
| 706 |
2/2✓ Branch 0 taken 128448 times.
✓ Branch 1 taken 244697 times.
|
373145 | if comp <> 0 then |
| 707 | 128448 | return; | |
| 708 | end if; | ||
| 709 | |||
| 710 | comp := match exp1 | ||
| 711 | local | ||
| 712 | Integer i; | ||
| 713 | Real r; | ||
| 714 | String s; | ||
| 715 | Boolean b; | ||
| 716 | ComponentRef cr; | ||
| 717 | Type ty; | ||
| 718 | list<Expression> expl, inv_expl; | ||
| 719 | Expression e1, e2, e3; | ||
| 720 | Option<Expression> oe; | ||
| 721 | Path p; | ||
| 722 | Operator op; | ||
| 723 | Call c; | ||
| 724 | list<Subscript> subs; | ||
| 725 | ClockKind clk; | ||
| 726 | Mutable<Expression> me; | ||
| 727 | list<list<Expression>> mat; | ||
| 728 | array<Expression> arr; | ||
| 729 | InstNode node; | ||
| 730 | |||
| 731 | case INTEGER() | ||
| 732 | algorithm | ||
| 733 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 112920 times.
|
112920 | INTEGER(value = i) := exp2; |
| 734 | 112920 | then | |
| 735 | Util.intCompare(exp1.value, i); | ||
| 736 | |||
| 737 | case REAL() | ||
| 738 | algorithm | ||
| 739 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4358 times.
|
4358 | REAL(value = r) := exp2; |
| 740 | 4358 | then | |
| 741 | Util.realCompare(exp1.value, r); | ||
| 742 | |||
| 743 | case STRING() | ||
| 744 | algorithm | ||
| 745 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3503 times.
|
3503 | STRING(value = s) := exp2; |
| 746 | 3503 | then | |
| 747 | stringCompare(exp1.value, s); | ||
| 748 | |||
| 749 | case BOOLEAN() | ||
| 750 | algorithm | ||
| 751 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
|
52 | BOOLEAN(value = b) := exp2; |
| 752 | 52 | then | |
| 753 | Util.boolCompare(exp1.value, b); | ||
| 754 | |||
| 755 | case ENUM_LITERAL() | ||
| 756 | algorithm | ||
| 757 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 231 times.
|
231 | ENUM_LITERAL(ty = ty, index = i) := exp2; |
| 758 | 231 | comp := AbsynUtil.pathCompare(Type.enumName(exp1.ty), Type.enumName(ty)); | |
| 759 | |||
| 760 |
1/2✓ Branch 0 taken 231 times.
✗ Branch 1 not taken.
|
231 | if comp == 0 then |
| 761 | 231 | comp := Util.intCompare(exp1.index, i); | |
| 762 | end if; | ||
| 763 | then | ||
| 764 | comp; | ||
| 765 | |||
| 766 | case CLKCONST() | ||
| 767 | algorithm | ||
| 768 | ✗ | CLKCONST(clk) := exp2; | |
| 769 | ✗ | then | |
| 770 | ClockKind.compare(exp1.clk, clk); | ||
| 771 | |||
| 772 | case CREF() | ||
| 773 | algorithm | ||
| 774 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 67245 times.
|
67245 | CREF(cref = cr) := exp2; |
| 775 | 67245 | then | |
| 776 | ComponentRef.compare(exp1.cref, cr); | ||
| 777 | |||
| 778 | case TYPENAME() | ||
| 779 | algorithm | ||
| 780 | ✗ | TYPENAME(ty = ty) := exp2; | |
| 781 | ✗ | then | |
| 782 | valueCompare(exp1.ty, ty); | ||
| 783 | |||
| 784 | case ARRAY() | ||
| 785 | algorithm | ||
| 786 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1167 times.
|
1167 | ARRAY(ty = ty, elements = arr) := exp2; |
| 787 | 1167 | comp := valueCompare(ty, exp1.ty); | |
| 788 |
2/2✓ Branch 0 taken 1161 times.
✓ Branch 1 taken 6 times.
|
1167 | then |
| 789 | if comp == 0 then Array.compare(exp1.elements, arr, compare) else comp; | ||
| 790 | |||
| 791 | case MATRIX() | ||
| 792 | algorithm | ||
| 793 | ✗ | MATRIX(elements = mat) := exp2; | |
| 794 | ✗ | then | |
| 795 | List.compare(exp1.elements, mat, function List.compare(compareFn = compare)); | ||
| 796 | |||
| 797 | case RANGE() | ||
| 798 | algorithm | ||
| 799 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 338 times.
|
338 | RANGE(start = e1, step = oe, stop = e2) := exp2; |
| 800 | 338 | comp := compare(exp1.start, e1); | |
| 801 |
2/2✓ Branch 0 taken 325 times.
✓ Branch 1 taken 13 times.
|
338 | if comp == 0 then |
| 802 | 325 | comp := compare(exp1.stop, e2); | |
| 803 |
2/2✓ Branch 0 taken 321 times.
✓ Branch 1 taken 4 times.
|
325 | if comp == 0 then |
| 804 | 321 | comp := compareOpt(exp1.step, oe); | |
| 805 | end if; | ||
| 806 | end if; | ||
| 807 | then | ||
| 808 | comp; | ||
| 809 | |||
| 810 | case TUPLE() | ||
| 811 | algorithm | ||
| 812 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | TUPLE(elements = expl) := exp2; |
| 813 | 3 | then | |
| 814 | List.compare(exp1.elements, expl, compare); | ||
| 815 | |||
| 816 | case RECORD() | ||
| 817 | algorithm | ||
| 818 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 73 times.
|
73 | RECORD(path = p, elements = expl) := exp2; |
| 819 | 73 | comp := AbsynUtil.pathCompare(exp1.path, p); | |
| 820 |
1/2✓ Branch 0 taken 73 times.
✗ Branch 1 not taken.
|
73 | then |
| 821 | if comp == 0 then List.compare(exp1.elements, expl, compare) else comp; | ||
| 822 | |||
| 823 | case CALL() | ||
| 824 | algorithm | ||
| 825 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2194 times.
|
2194 | CALL(call = c) := exp2; |
| 826 | 2194 | then | |
| 827 | Call.compare(exp1.call, c); | ||
| 828 | |||
| 829 | case SIZE() | ||
| 830 | algorithm | ||
| 831 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 125 times.
|
125 | SIZE(exp = e1, dimIndex = oe) := exp2; |
| 832 | 125 | comp := compareOpt(exp1.dimIndex, oe); | |
| 833 |
2/2✓ Branch 0 taken 124 times.
✓ Branch 1 taken 1 time.
|
125 | then |
| 834 | if comp == 0 then compare(exp1.exp, e1) else comp; | ||
| 835 | |||
| 836 | case END() then 0; | ||
| 837 | |||
| 838 | case MULTARY() | ||
| 839 | algorithm | ||
| 840 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7113 times.
|
7113 | MULTARY(arguments = expl, inv_arguments = inv_expl, operator = op) := exp2; |
| 841 | 7113 | comp := Operator.compare(exp1.operator, op); | |
| 842 |
2/2✓ Branch 0 taken 7077 times.
✓ Branch 1 taken 36 times.
|
7113 | if comp == 0 then |
| 843 | 7077 | comp := compareList(exp1.arguments, expl); | |
| 844 | end if; | ||
| 845 |
2/2✓ Branch 0 taken 6910 times.
✓ Branch 1 taken 203 times.
|
7113 | if comp == 0 then |
| 846 | 6910 | comp := compareList(exp1.inv_arguments, inv_expl); | |
| 847 | end if; | ||
| 848 | then | ||
| 849 | comp; | ||
| 850 | |||
| 851 | case BINARY() | ||
| 852 | algorithm | ||
| 853 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 43774 times.
|
43774 | BINARY(exp1 = e1, operator = op, exp2 = e2) := exp2; |
| 854 | 43774 | comp := Operator.compare(exp1.operator, op); | |
| 855 |
2/2✓ Branch 0 taken 29569 times.
✓ Branch 1 taken 14205 times.
|
43774 | if comp == 0 then |
| 856 | 29569 | comp := compare(exp1.exp1, e1); | |
| 857 |
2/2✓ Branch 0 taken 1509 times.
✓ Branch 1 taken 28060 times.
|
29569 | if comp == 0 then |
| 858 | 1509 | comp := compare(exp1.exp2, e2); | |
| 859 | end if; | ||
| 860 | end if; | ||
| 861 | then | ||
| 862 | comp; | ||
| 863 | |||
| 864 | case UNARY() | ||
| 865 | algorithm | ||
| 866 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 568 times.
|
568 | UNARY(operator = op, exp = e1) := exp2; |
| 867 | 568 | comp := Operator.compare(exp1.operator, op); | |
| 868 |
1/2✓ Branch 0 taken 568 times.
✗ Branch 1 not taken.
|
568 | then |
| 869 | if comp == 0 then compare(exp1.exp, e1) else comp; | ||
| 870 | |||
| 871 | case LBINARY() | ||
| 872 | algorithm | ||
| 873 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 64 times.
|
64 | LBINARY(exp1 = e1, operator = op, exp2 = e2) := exp2; |
| 874 | 64 | comp := Operator.compare(exp1.operator, op); | |
| 875 |
1/2✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
|
64 | if comp == 0 then |
| 876 | 64 | comp := compare(exp1.exp1, e1); | |
| 877 |
1/2✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
|
64 | if comp == 0 then |
| 878 | 64 | comp := compare(exp1.exp2, e2); | |
| 879 | end if; | ||
| 880 | end if; | ||
| 881 | then | ||
| 882 | comp; | ||
| 883 | |||
| 884 | case LUNARY() | ||
| 885 | algorithm | ||
| 886 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
|
21 | LUNARY(operator = op, exp = e1) := exp2; |
| 887 | 21 | comp := Operator.compare(exp1.operator, op); | |
| 888 |
1/2✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
|
21 | then |
| 889 | if comp == 0 then compare(exp1.exp, e1) else comp; | ||
| 890 | |||
| 891 | case RELATION() | ||
| 892 | algorithm | ||
| 893 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 246 times.
|
246 | RELATION(exp1 = e1, operator = op, exp2 = e2) := exp2; |
| 894 | 246 | comp := Operator.compare(exp1.operator, op); | |
| 895 |
2/2✓ Branch 0 taken 223 times.
✓ Branch 1 taken 23 times.
|
246 | if comp == 0 then |
| 896 | 223 | comp := compare(exp1.exp1, e1); | |
| 897 |
2/2✓ Branch 0 taken 221 times.
✓ Branch 1 taken 2 times.
|
223 | if comp == 0 then |
| 898 | 221 | comp := compare(exp1.exp2, e2); | |
| 899 | end if; | ||
| 900 | end if; | ||
| 901 | then | ||
| 902 | comp; | ||
| 903 | |||
| 904 | case IF() | ||
| 905 | algorithm | ||
| 906 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 157 times.
|
157 | IF(condition = e1, trueBranch = e2, falseBranch = e3) := exp2; |
| 907 | 157 | comp := compare(exp1.condition, e1); | |
| 908 |
2/2✓ Branch 0 taken 130 times.
✓ Branch 1 taken 27 times.
|
157 | if comp == 0 then |
| 909 | 130 | comp := compare(exp1.trueBranch, e2); | |
| 910 |
1/2✓ Branch 0 taken 130 times.
✗ Branch 1 not taken.
|
130 | if comp == 0 then |
| 911 | 130 | comp := compare(exp1.falseBranch, e3); | |
| 912 | end if; | ||
| 913 | end if; | ||
| 914 | then | ||
| 915 | comp; | ||
| 916 | |||
| 917 | case CAST() | ||
| 918 | algorithm | ||
| 919 | e1 := match exp2 | ||
| 920 | case CAST(exp = e1) then e1; | ||
| 921 | case e1 then e1; | ||
| 922 | end match; | ||
| 923 | 150 | then | |
| 924 | compare(exp1.exp, e1); | ||
| 925 | |||
| 926 | case BOX() | ||
| 927 | algorithm | ||
| 928 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 65 times.
|
65 | BOX(exp = e2) := exp2; |
| 929 | 65 | then | |
| 930 | compare(exp1.exp, e2); | ||
| 931 | |||
| 932 | case UNBOX() | ||
| 933 | algorithm | ||
| 934 | ✗ | UNBOX(exp = e1) := exp2; | |
| 935 | ✗ | then | |
| 936 | compare(exp1.exp, e1); | ||
| 937 | |||
| 938 | case SUBSCRIPTED_EXP() | ||
| 939 | algorithm | ||
| 940 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 89 times.
|
89 | SUBSCRIPTED_EXP(exp = e1, subscripts = subs) := exp2; |
| 941 | 89 | comp := compare(exp1.exp, e1); | |
| 942 | |||
| 943 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 43 times.
|
89 | if comp == 0 then |
| 944 | 46 | comp := Subscript.compareList(exp1.subscripts, subs); | |
| 945 | end if; | ||
| 946 | then | ||
| 947 | comp; | ||
| 948 | |||
| 949 | case TUPLE_ELEMENT() | ||
| 950 | algorithm | ||
| 951 | ✗ | TUPLE_ELEMENT(tupleExp = e1, index = i) := exp2; | |
| 952 | ✗ | comp := Util.intCompare(exp1.index, i); | |
| 953 | |||
| 954 | ✗ | if comp == 0 then | |
| 955 | ✗ | comp := compare(exp1.tupleExp, e1); | |
| 956 | end if; | ||
| 957 | then | ||
| 958 | comp; | ||
| 959 | |||
| 960 | case RECORD_ELEMENT() | ||
| 961 | algorithm | ||
| 962 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
|
60 | RECORD_ELEMENT(recordExp = e1, index = i) := exp2; |
| 963 | 60 | comp := Util.intCompare(exp1.index, i); | |
| 964 | |||
| 965 |
1/2✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
|
60 | if comp == 0 then |
| 966 | 60 | comp := compare(exp1.recordExp, e1); | |
| 967 | end if; | ||
| 968 | then | ||
| 969 | comp; | ||
| 970 | |||
| 971 | case MUTABLE() | ||
| 972 | algorithm | ||
| 973 | ✗ | MUTABLE(exp = me) := exp2; | |
| 974 | ✗ | then | |
| 975 | compare(Mutable.access(exp1.exp), Mutable.access(me)); | ||
| 976 | |||
| 977 | case SHARED_LITERAL() | ||
| 978 | algorithm | ||
| 979 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 158 times.
|
158 | SHARED_LITERAL(exp = e1) := exp2; |
| 980 | 158 | then | |
| 981 | compare(exp1.exp, e1); | ||
| 982 | |||
| 983 | case EMPTY() | ||
| 984 | algorithm | ||
| 985 | ✗ | EMPTY(ty = ty) := exp2; | |
| 986 | ✗ | then | |
| 987 | valueCompare(exp1.ty, ty); | ||
| 988 | |||
| 989 | case PARTIAL_FUNCTION_APPLICATION() | ||
| 990 | algorithm | ||
| 991 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
|
23 | PARTIAL_FUNCTION_APPLICATION(fn = cr, args = expl) := exp2; |
| 992 | 23 | comp := ComponentRef.compare(exp1.fn, cr); | |
| 993 | |||
| 994 |
1/2✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
|
23 | if comp == 0 then |
| 995 | 23 | comp := List.compare(exp1.args, expl, compare); | |
| 996 | end if; | ||
| 997 | then | ||
| 998 | comp; | ||
| 999 | |||
| 1000 | case FILENAME() | ||
| 1001 | algorithm | ||
| 1002 | ✗ | FILENAME(filename = s) := exp2; | |
| 1003 | ✗ | then | |
| 1004 | stringCompare(exp1.filename, s); | ||
| 1005 | |||
| 1006 | case INSTANCE_NAME() | ||
| 1007 | algorithm | ||
| 1008 | ✗ | INSTANCE_NAME(scope = node) := exp2; | |
| 1009 | ✗ | then | |
| 1010 | InstNode.refCompare(exp1.scope, node); | ||
| 1011 | |||
| 1012 | else | ||
| 1013 | algorithm | ||
| 1014 | ✗ | Error.terminate(getInstanceName() + " got unknown expression.", sourceInfo()); | |
| 1015 | ✗ | then | |
| 1016 | fail(); | ||
| 1017 | |||
| 1018 | end match; | ||
| 1019 | end compare; | ||
| 1020 | |||
| 1021 | function compareOpt | ||
| 1022 | input Option<Expression> expl1; | ||
| 1023 | input Option<Expression> expl2; | ||
| 1024 | output Integer comp; | ||
| 1025 | protected | ||
| 1026 | Expression e1, e2; | ||
| 1027 | algorithm | ||
| 1028 | comp := match(expl1, expl2) | ||
| 1029 | case (NONE(), NONE()) then 0; | ||
| 1030 | case (NONE(), _) then -1; | ||
| 1031 | case (_, NONE()) then 1; | ||
| 1032 | 144 | case (SOME(e1), SOME(e2)) then compare(e1, e2); | |
| 1033 | end match; | ||
| 1034 | end compareOpt; | ||
| 1035 | |||
| 1036 | function compareList | ||
| 1037 | input list<Expression> expl1; | ||
| 1038 | input list<Expression> expl2; | ||
| 1039 | output Integer comp = List.compare(expl1, expl2, compare); | ||
| 1040 | end compareList; | ||
| 1041 | |||
| 1042 | function typeOf | ||
| 1043 | input Expression exp; | ||
| 1044 | output Type ty; | ||
| 1045 | algorithm | ||
| 1046 | ty := match exp | ||
| 1047 | case INTEGER() then Type.INTEGER(); | ||
| 1048 | case REAL() then Type.REAL(); | ||
| 1049 | case STRING() then Type.STRING(); | ||
| 1050 | case BOOLEAN() then Type.BOOLEAN(); | ||
| 1051 | 86975 | case ENUM_LITERAL() then exp.ty; | |
| 1052 | case CLKCONST() then Type.CLOCK(); | ||
| 1053 | 2672183 | case CREF() then exp.ty; | |
| 1054 | 5 | case TYPENAME() then exp.ty; | |
| 1055 | 669297 | case ARRAY() then exp.ty; | |
| 1056 | 38893 | case RANGE() then exp.ty; | |
| 1057 | 1221 | case TUPLE() then exp.ty; | |
| 1058 | 25852 | case RECORD() then exp.ty; | |
| 1059 | 745815 | case CALL() then Call.typeOf(exp.call); | |
| 1060 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 18761 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 18755 times.
|
18761 | case SIZE() then if isSome(exp.dimIndex) then |
| 1061 | Type.INTEGER() else Type.sizeType(typeOf(exp.exp)); | ||
| 1062 | case END() then Type.INTEGER(); | ||
| 1063 | 105865 | case MULTARY() then Operator.typeOf(exp.operator); | |
| 1064 | 1367733 | case BINARY() then Operator.typeOf(exp.operator); | |
| 1065 | 111833 | case UNARY() then Operator.typeOf(exp.operator); | |
| 1066 | 15071 | case LBINARY() then Operator.typeOf(exp.operator); | |
| 1067 | 5274 | case LUNARY() then Operator.typeOf(exp.operator); | |
| 1068 | 63503 | case RELATION() then Type.copyDims(Operator.typeOf(exp.operator), Type.BOOLEAN()); | |
| 1069 | 33072 | case IF() then exp.ty; | |
| 1070 | 31145 | case CAST() then exp.ty; | |
| 1071 | 116 | case BOX() then Type.METABOXED(typeOf(exp.exp)); | |
| 1072 | 67 | case UNBOX() then exp.ty; | |
| 1073 | 22651 | case SUBSCRIPTED_EXP() then exp.ty; | |
| 1074 | 170 | case TUPLE_ELEMENT() then exp.ty; | |
| 1075 | 318 | case RECORD_ELEMENT() then exp.ty; | |
| 1076 | 97472 | case MUTABLE() then typeOf(Mutable.access(exp.exp)); | |
| 1077 | 9 | case SHARED_LITERAL() then typeOf(exp.exp); | |
| 1078 | 47449 | case EMPTY() then exp.ty; | |
| 1079 | 123 | case PARTIAL_FUNCTION_APPLICATION() then exp.ty; | |
| 1080 | case FILENAME() then Type.STRING(); | ||
| 1081 | case INSTANCE_NAME() then Type.STRING(); | ||
| 1082 | else Type.UNKNOWN(); | ||
| 1083 | end match; | ||
| 1084 | end typeOf; | ||
| 1085 | |||
| 1086 | function sizeOf | ||
| 1087 | "this can fail for certain untyped expressions" | ||
| 1088 | input Expression exp; | ||
| 1089 | output Integer sz = Type.sizeOf(typeOf(exp)); | ||
| 1090 | end sizeOf; | ||
| 1091 | |||
| 1092 | function callOf | ||
| 1093 | input Expression exp; | ||
| 1094 | output Call call; | ||
| 1095 | algorithm | ||
| 1096 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 | CALL(call = call) := exp; |
| 1097 | end callOf; | ||
| 1098 | |||
| 1099 | function sizeZero | ||
| 1100 | "returns true if its a constructor that is definitely of size zero;" | ||
| 1101 | input Expression exp; | ||
| 1102 | output Boolean b; | ||
| 1103 | algorithm | ||
| 1104 | try | ||
| 1105 | 528 | b := 0 == sizeOf(exp); | |
| 1106 | else | ||
| 1107 | // fill(x, ..., 0, ...) is empty even if its dimension is not known as an integer | ||
| 1108 | b := false; | ||
| 1109 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 3 times.
|
4 | if isCallNamed(exp, "fill") then |
| 1110 |
2/2✓ Branch 3 taken 1 time.
✓ Branch 4 taken 1 time.
|
3 | for arg in listRest(Call.arguments(callOf(exp))) loop |
| 1111 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
|
1 | if isZero(arg) then |
| 1112 | b := true; | ||
| 1113 | end if; | ||
| 1114 | end for; | ||
| 1115 | end if; | ||
| 1116 | end try; | ||
| 1117 | end sizeZero; | ||
| 1118 | |||
| 1119 | function setType | ||
| 1120 | input Type ty; | ||
| 1121 | input output Expression exp; | ||
| 1122 | algorithm | ||
| 1123 | exp := match exp | ||
| 1124 | ✗ | case ENUM_LITERAL() algorithm exp.ty := ty; then exp; | |
| 1125 | 200921 | case CREF() algorithm exp.ty := ty; then exp; | |
| 1126 | 4 | case TYPENAME() algorithm exp.ty := ty; then exp; | |
| 1127 | 496445 | case ARRAY() algorithm exp.ty := ty; then exp; | |
| 1128 | 18980 | case RANGE() algorithm exp.ty := ty; then exp; | |
| 1129 | ✗ | case TUPLE() algorithm exp.ty := ty; then exp; | |
| 1130 | ✗ | case RECORD() algorithm exp.ty := ty; then exp; | |
| 1131 | 320790 | case CALL() algorithm exp.call := Call.setType(exp.call, ty); then exp; | |
| 1132 | 37077 | case BINARY() algorithm exp.operator := Operator.setType(ty, exp.operator); then exp; | |
| 1133 | 2164 | case UNARY() algorithm exp.operator := Operator.setType(ty, exp.operator); then exp; | |
| 1134 | 4 | case LBINARY() algorithm exp.operator := Operator.setType(ty, exp.operator); then exp; | |
| 1135 | 1 | case LUNARY() algorithm exp.operator := Operator.setType(ty, exp.operator); then exp; | |
| 1136 | ✗ | case RELATION() algorithm exp.operator := Operator.setType(ty, exp.operator); then exp; | |
| 1137 | 8993 | case IF() algorithm exp.ty := ty; then exp; | |
| 1138 | 16519 | case CAST() algorithm exp.ty := ty; then exp; | |
| 1139 | ✗ | case UNBOX() algorithm exp.ty := ty; then exp; | |
| 1140 | 20 | case SUBSCRIPTED_EXP() algorithm exp.ty := ty; then exp; | |
| 1141 | 27 | case TUPLE_ELEMENT() algorithm exp.ty := ty; then exp; | |
| 1142 | 8 | case RECORD_ELEMENT() algorithm exp.ty := ty; then exp; | |
| 1143 | ✗ | case PARTIAL_FUNCTION_APPLICATION() algorithm exp.ty := ty; then exp; | |
| 1144 | else exp; | ||
| 1145 | end match; | ||
| 1146 | end setType; | ||
| 1147 | |||
| 1148 | function applyToType | ||
| 1149 | input output Expression exp; | ||
| 1150 | input typeFunc func; | ||
| 1151 | partial function typeFunc | ||
| 1152 | input output Type ty; | ||
| 1153 | end typeFunc; | ||
| 1154 | algorithm | ||
| 1155 | exp := match exp | ||
| 1156 | local | ||
| 1157 | Operator o; | ||
| 1158 |
1/2✓ Branch 0 taken 1658 times.
✗ Branch 1 not taken.
|
1658 | case ENUM_LITERAL() algorithm exp.ty := func(exp.ty); then exp; |
| 1159 |
1/2✓ Branch 0 taken 112173 times.
✗ Branch 1 not taken.
|
224346 | case CREF() algorithm exp.ty := func(exp.ty); exp.cref := ComponentRef.applyToType(exp.cref, func); then exp; |
| 1160 | ✗ | case TYPENAME() algorithm exp.ty := func(exp.ty); then exp; | |
| 1161 |
1/2✓ Branch 0 taken 2870 times.
✗ Branch 1 not taken.
|
2870 | case ARRAY() algorithm exp.ty := func(exp.ty); then exp; |
| 1162 |
1/2✓ Branch 0 taken 5360 times.
✗ Branch 1 not taken.
|
5360 | case RANGE() algorithm exp.ty := func(exp.ty); then exp; |
| 1163 |
1/2✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
|
24 | case TUPLE() algorithm exp.ty := func(exp.ty); then exp; |
| 1164 |
1/2✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
|
45 | case RECORD() algorithm exp.ty := func(exp.ty); then exp; |
| 1165 |
1/2✓ Branch 0 taken 12352 times.
✗ Branch 1 not taken.
|
12352 | case CALL() algorithm exp.call := Call.setType(exp.call, func(Call.typeOf(exp.call))); then exp; |
| 1166 | ✗ | case SIZE() algorithm exp.exp := applyToType(exp.exp, func); then exp; | |
| 1167 |
1/2✓ Branch 0 taken 35707 times.
✗ Branch 1 not taken.
|
71414 | case MULTARY(operator = o) algorithm o.ty := func(o.ty); exp.operator := o; then exp; |
| 1168 |
1/2✓ Branch 0 taken 5034 times.
✗ Branch 1 not taken.
|
10068 | case BINARY(operator = o) algorithm o.ty := func(o.ty); exp.operator := o; then exp; |
| 1169 |
1/2✓ Branch 0 taken 2063 times.
✗ Branch 1 not taken.
|
4126 | case UNARY(operator = o) algorithm o.ty := func(o.ty); exp.operator := o; then exp; |
| 1170 |
1/2✓ Branch 0 taken 645 times.
✗ Branch 1 not taken.
|
1290 | case LBINARY(operator = o) algorithm o.ty := func(o.ty); exp.operator := o; then exp; |
| 1171 |
1/2✓ Branch 0 taken 425 times.
✗ Branch 1 not taken.
|
850 | case LUNARY(operator = o) algorithm o.ty := func(o.ty); exp.operator := o; then exp; |
| 1172 |
1/2✓ Branch 0 taken 3036 times.
✗ Branch 1 not taken.
|
6072 | case RELATION(operator = o) algorithm o.ty := func(o.ty); exp.operator := o; then exp; |
| 1173 |
1/2✓ Branch 0 taken 723 times.
✗ Branch 1 not taken.
|
723 | case IF() algorithm exp.ty := func(exp.ty); then exp; |
| 1174 |
1/2✓ Branch 0 taken 533 times.
✗ Branch 1 not taken.
|
533 | case CAST() algorithm exp.ty := func(exp.ty); then exp; |
| 1175 | 294 | case BOX() algorithm exp.exp := applyToType(exp.exp, func); then exp; | |
| 1176 | ✗ | case UNBOX() algorithm exp.ty := func(exp.ty); then exp; | |
| 1177 |
1/2✓ Branch 0 taken 368 times.
✗ Branch 1 not taken.
|
368 | case SUBSCRIPTED_EXP() algorithm exp.ty := func(exp.ty); then exp; |
| 1178 | ✗ | case TUPLE_ELEMENT() algorithm exp.ty := func(exp.ty); then exp; | |
| 1179 |
1/2✓ Branch 0 taken 239 times.
✗ Branch 1 not taken.
|
239 | case RECORD_ELEMENT() algorithm exp.ty := func(exp.ty); then exp; |
| 1180 | ✗ | case MUTABLE() algorithm Mutable.update(exp.exp, applyToType(Mutable.access(exp.exp), func)); then exp; | |
| 1181 | ✗ | case SHARED_LITERAL() algorithm exp.exp := applyToType(exp.exp, func); then exp; | |
| 1182 | ✗ | case EMPTY() algorithm exp.ty := func(exp.ty); then exp; | |
| 1183 |
1/2✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
|
70 | case PARTIAL_FUNCTION_APPLICATION() algorithm exp.ty := func(exp.ty); then exp; |
| 1184 | else exp; | ||
| 1185 | end match; | ||
| 1186 | end applyToType; | ||
| 1187 | |||
| 1188 | |||
| 1189 | function typeCastOpt | ||
| 1190 | input Option<Expression> exp; | ||
| 1191 | input Type ty; | ||
| 1192 | output Option<Expression> outExp = Util.applyOption(exp, function typeCast(ty = ty)); | ||
| 1193 | end typeCastOpt; | ||
| 1194 | |||
| 1195 | function typeCast | ||
| 1196 | "Converts an expression to the given type. Dimensions of array types can be | ||
| 1197 | omitted, and are ignored by this function, since arrays can't be cast to a | ||
| 1198 | different size. Only the element type of the type is used, so for example: | ||
| 1199 | typeCast({1, 2, 3}, Type.REAL()) => {1.0, 2.0, 3.0} | ||
| 1200 | |||
| 1201 | The function does not check that the cast is valid, and expressions that | ||
| 1202 | can't be converted outright will be wrapped as a CAST expression." | ||
| 1203 | input output Expression exp; | ||
| 1204 | input Type ty; | ||
| 1205 | protected | ||
| 1206 | Type t, ety; | ||
| 1207 | Expression e1, e2; | ||
| 1208 | array<Expression> arr; | ||
| 1209 | algorithm | ||
| 1210 | 276953 | ety := Type.arrayElementType(ty); | |
| 1211 | |||
| 1212 | exp := match exp | ||
| 1213 | // Integer can be cast to Real. | ||
| 1214 | case INTEGER() | ||
| 1215 |
1/6✓ Branch 1 taken 223708 times.
✗ Branch 2 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
223708 | then if Type.isReal(ety) then REAL(intReal(exp.value)) |
| 1216 | elseif Type.isEnumeration(ety) and Flags.isConfigFlagSet(Flags.ALLOW_NON_STANDARD_MODELICA, "nonStdIntegersAsEnumeration") // Integer can be cast to Enumeration with non-standard Modelica | ||
| 1217 | then ENUM_LITERAL(ety, Type.nthEnumLiteral(ety, exp.value), exp.value) | ||
| 1218 | else typeCastGeneric(exp, ety); | ||
| 1219 | |||
| 1220 | // Enumeration can be cast to Integer with non-standard Modelica | ||
| 1221 | case ENUM_LITERAL() guard Flags.isConfigFlagSet(Flags.ALLOW_NON_STANDARD_MODELICA, "nonStdEnumerationAsIntegers") | ||
| 1222 | ✗ | then if Type.isInteger(ety) then INTEGER(toInteger(exp)) else typeCastGeneric(exp, ety); | |
| 1223 | |||
| 1224 | // Boolean can be cast to Real (only if -d=nfAPI is on) | ||
| 1225 | // as there are annotations having expressions such as Boolean x > 0.5 | ||
| 1226 | case BOOLEAN() | ||
| 1227 | ✗ | then if Type.isReal(ety) and Flags.isSet(Flags.NF_API) then | |
| 1228 | REAL(if exp.value then 1.0 else 0.0) else typeCastGeneric(exp, ety); | ||
| 1229 | |||
| 1230 | // Real doesn't need to be cast to Real, since we convert e.g. array with | ||
| 1231 | // a mix of Integers and Reals to only Reals. | ||
| 1232 | case REAL() | ||
| 1233 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 486 times.
|
486 | then if Type.isReal(ety) then exp else typeCastGeneric(exp, ety); |
| 1234 | |||
| 1235 | // For arrays we typecast each element and update the type of the array. | ||
| 1236 | case ARRAY(ty = t, elements = arr) | ||
| 1237 | algorithm | ||
| 1238 | 22757 | arr := Array.map(arr, function typeCast(ty = ety)); | |
| 1239 | 22757 | t := Type.setArrayElementType(t, ety); | |
| 1240 | 22757 | then | |
| 1241 | makeArray(t, arr, exp.literal); | ||
| 1242 | |||
| 1243 | case RANGE(ty = t) | ||
| 1244 | algorithm | ||
| 1245 | 34 | t := Type.setArrayElementType(t, ety); | |
| 1246 | 34 | then | |
| 1247 | RANGE(t, typeCast(exp.start, ety), typeCastOpt(exp.step, ety), typeCast(exp.stop, ety)); | ||
| 1248 | |||
| 1249 | // Unary operators (i.e. -) are handled by casting the operand. | ||
| 1250 | case UNARY() | ||
| 1251 | algorithm | ||
| 1252 | 148 | t := Type.setArrayElementType(Operator.typeOf(exp.operator), ety); | |
| 1253 | 148 | then | |
| 1254 | UNARY(Operator.setType(t, exp.operator), typeCast(exp.exp, ety)); | ||
| 1255 | |||
| 1256 | // Integer arithmetic is cast by casting the operands, so that a result | ||
| 1257 | // that does not fit in an Integer is still the exact Real one. | ||
| 1258 | case BINARY() | ||
| 1259 | guard Type.isReal(ety) and isCastableIntegerArithmetic(exp.operator) | ||
| 1260 | algorithm | ||
| 1261 | 1329 | t := Type.setArrayElementType(Operator.typeOf(exp.operator), ety); | |
| 1262 | 1329 | then | |
| 1263 | BINARY(typeCast(exp.exp1, ety), Operator.setType(t, exp.operator), typeCast(exp.exp2, ety)); | ||
| 1264 | |||
| 1265 | // If-expressions are handled by casting each of the branches. | ||
| 1266 | case IF() | ||
| 1267 | algorithm | ||
| 1268 | 1274 | e1 := typeCast(exp.trueBranch, ety); | |
| 1269 | 1274 | e2 := typeCast(exp.falseBranch, ety); | |
| 1270 |
2/2✓ Branch 1 taken 51 times.
✓ Branch 2 taken 1223 times.
|
1274 | t := if Type.isConditionalArray(ty) then |
| 1271 | Type.setConditionalArrayTypes(ty, typeOf(e1), typeOf(e2)) else typeOf(e1); | ||
| 1272 | 1274 | then | |
| 1273 | IF(t, exp.condition, e1, e2); | ||
| 1274 | |||
| 1275 | // Calls are handled by Call.typeCast, which has special rules for some functions. | ||
| 1276 | case CALL() | ||
| 1277 | 11492 | then Call.typeCast(exp, ety); | |
| 1278 | |||
| 1279 | // Casting a cast expression overrides its current cast type. | ||
| 1280 | ✗ | case CAST() then typeCast(exp.exp, ty); | |
| 1281 | |||
| 1282 | case SUBSCRIPTED_EXP() | ||
| 1283 | algorithm | ||
| 1284 | 6075 | e1 := typeCast(exp.exp, ety); | |
| 1285 | 6075 | t := Type.setArrayElementType(exp.ty, ety); | |
| 1286 | 6075 | then | |
| 1287 | SUBSCRIPTED_EXP(e1, exp.subscripts, t, exp.split); | ||
| 1288 | |||
| 1289 | // Other expressions are handled by making a CAST expression. | ||
| 1290 | 9650 | else typeCastGeneric(exp, ety); | |
| 1291 | end match; | ||
| 1292 | end typeCast; | ||
| 1293 | |||
| 1294 | function isCastableIntegerArithmetic | ||
| 1295 | "Whether an Integer operation gives the same value on the operands cast to | ||
| 1296 | Real: addition, subtraction and multiplication, but not division or ^." | ||
| 1297 | input Operator op; | ||
| 1298 | output Boolean res; | ||
| 1299 | protected | ||
| 1300 | import NFOperator.Op; | ||
| 1301 | algorithm | ||
| 1302 | res := Type.isInteger(Type.arrayElementType(Operator.typeOf(op))) and | ||
| 1303 | (match op.op | ||
| 1304 | case Op.ADD then true; | ||
| 1305 | case Op.SUB then true; | ||
| 1306 | case Op.MUL then true; | ||
| 1307 | case Op.ADD_EW then true; | ||
| 1308 | case Op.SUB_EW then true; | ||
| 1309 | case Op.MUL_EW then true; | ||
| 1310 | case Op.ADD_SCALAR_ARRAY then true; | ||
| 1311 | case Op.ADD_ARRAY_SCALAR then true; | ||
| 1312 | case Op.SUB_SCALAR_ARRAY then true; | ||
| 1313 | case Op.SUB_ARRAY_SCALAR then true; | ||
| 1314 | case Op.MUL_SCALAR_ARRAY then true; | ||
| 1315 | case Op.MUL_ARRAY_SCALAR then true; | ||
| 1316 | case Op.MUL_VECTOR_MATRIX then true; | ||
| 1317 | case Op.MUL_MATRIX_VECTOR then true; | ||
| 1318 | case Op.SCALAR_PRODUCT then true; | ||
| 1319 | case Op.MATRIX_PRODUCT then true; | ||
| 1320 | else false; | ||
| 1321 | end match); | ||
| 1322 | end isCastableIntegerArithmetic; | ||
| 1323 | |||
| 1324 | function typeCastGeneric | ||
| 1325 | input output Expression exp; | ||
| 1326 | input Type ty; | ||
| 1327 | protected | ||
| 1328 | Type exp_ty = typeOf(exp); | ||
| 1329 | algorithm | ||
| 1330 |
2/2✓ Branch 2 taken 641 times.
✓ Branch 3 taken 9086 times.
|
9727 | if not Type.isEqual(ty, Type.arrayElementType(exp_ty)) then |
| 1331 | 9086 | exp := CAST(Type.setArrayElementType(exp_ty, ty), exp); | |
| 1332 | end if; | ||
| 1333 | end typeCastGeneric; | ||
| 1334 | |||
| 1335 | function realValue | ||
| 1336 | input Expression exp; | ||
| 1337 | output Real value; | ||
| 1338 | algorithm | ||
| 1339 | value := match exp | ||
| 1340 | 3361 | case REAL() then exp.value; | |
| 1341 | 26 | case INTEGER() then intReal(exp.value); | |
| 1342 | end match; | ||
| 1343 | end realValue; | ||
| 1344 | |||
| 1345 | function makeReal | ||
| 1346 | input Real value; | ||
| 1347 | output Expression exp = REAL(value); | ||
| 1348 | end makeReal; | ||
| 1349 | |||
| 1350 | function integerValue | ||
| 1351 | input Expression exp; | ||
| 1352 | output Integer value; | ||
| 1353 | algorithm | ||
| 1354 | try | ||
| 1355 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 506 times.
|
506 | INTEGER(value=value) := exp; |
| 1356 | else | ||
| 1357 | ✗ | Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because expression is not an integer:\n" | |
| 1358 | + toString(exp)}); | ||
| 1359 | ✗ | fail(); | |
| 1360 | end try; | ||
| 1361 | end integerValue; | ||
| 1362 | |||
| 1363 | function integerValueOrDefault | ||
| 1364 | input Expression exp; | ||
| 1365 | input output Integer value = 0; | ||
| 1366 | algorithm | ||
| 1367 | value := match exp | ||
| 1368 | 166 | case INTEGER() then exp.value; | |
| 1369 | else value; | ||
| 1370 | end match; | ||
| 1371 | end integerValueOrDefault; | ||
| 1372 | |||
| 1373 | function makeInteger | ||
| 1374 | input Integer value; | ||
| 1375 | output Expression exp = INTEGER(value); | ||
| 1376 | end makeInteger; | ||
| 1377 | |||
| 1378 | function stringValue | ||
| 1379 | input Expression exp; | ||
| 1380 | output String value; | ||
| 1381 | algorithm | ||
| 1382 | value := match exp | ||
| 1383 | 7061 | case STRING() then exp.value; | |
| 1384 | ✗ | case FILENAME() then exp.filename; | |
| 1385 | else ""; | ||
| 1386 | end match; | ||
| 1387 | end stringValue; | ||
| 1388 | |||
| 1389 | function booleanValue | ||
| 1390 | input Expression exp; | ||
| 1391 | output Boolean value; | ||
| 1392 | algorithm | ||
| 1393 | try | ||
| 1394 | ✗ | BOOLEAN(value=value) := exp; | |
| 1395 | else | ||
| 1396 | value := false; | ||
| 1397 | end try; | ||
| 1398 | end booleanValue; | ||
| 1399 | |||
| 1400 | function makeArray | ||
| 1401 | input Type ty; | ||
| 1402 | input array<Expression> expl; | ||
| 1403 | input Boolean literal = false; | ||
| 1404 | output Expression outExp; | ||
| 1405 | algorithm | ||
| 1406 |
2/2✓ Branch 0 taken 835130 times.
✓ Branch 1 taken 124442 times.
|
1794702 | outExp := ARRAY(ty, expl, literal); |
| 1407 | annotation(__OpenModelica_EarlyInline = true); | ||
| 1408 | end makeArray; | ||
| 1409 | |||
| 1410 | function makeArrayCheckLiteral | ||
| 1411 | input Type ty; | ||
| 1412 | input array<Expression> expl; | ||
| 1413 | output Expression outExp; | ||
| 1414 | algorithm | ||
| 1415 |
2/2✓ Branch 1 taken 37373 times.
✓ Branch 2 taken 218354 times.
|
293100 | outExp := ARRAY(ty, expl, Array.all(expl, isLiteral)); |
| 1416 | annotation(__OpenModelica_EarlyInline = true); | ||
| 1417 | end makeArrayCheckLiteral; | ||
| 1418 | |||
| 1419 | function makeEmptyArray | ||
| 1420 | "Creates an array from a type where at least one of the dimensions is zero." | ||
| 1421 | input Type ty; | ||
| 1422 | output Expression outExp; | ||
| 1423 | protected | ||
| 1424 | list<Dimension> dims, non_empty_dims = {}; | ||
| 1425 | Type arr_ty; | ||
| 1426 | algorithm | ||
| 1427 | // Split the dimensions on the first zero dimension. | ||
| 1428 | 482 | dims := Type.arrayDims(ty); | |
| 1429 | |||
| 1430 |
2/2✓ Branch 2 taken 34 times.
✓ Branch 3 taken 476 times.
|
516 | while not Dimension.isZero(listHead(dims)) loop |
| 1431 | 34 | non_empty_dims := listHead(dims) :: non_empty_dims; | |
| 1432 | 34 | dims := listRest(dims); | |
| 1433 | end while; | ||
| 1434 | |||
| 1435 | // Create an empty array with the zero dimension and the dimensions after. | ||
| 1436 | 476 | arr_ty := Type.ARRAY(Type.arrayElementType(ty), dims); | |
| 1437 | 476 | outExp := ARRAY(arr_ty, listArray({}), true); | |
| 1438 | // Lift the empty array with the dimensions preceeding the zero dimension. | ||
| 1439 | 476 | outExp := liftArrayList(non_empty_dims, outExp); | |
| 1440 | end makeEmptyArray; | ||
| 1441 | |||
| 1442 | function makeIntegerArray | ||
| 1443 | input list<Integer> values; | ||
| 1444 | output Expression exp; | ||
| 1445 | algorithm | ||
| 1446 | 14 | exp := makeArray(Type.ARRAY(Type.INTEGER(), {Dimension.fromInteger(listLength(values))}), | |
| 1447 | Array.mapList(values, makeInteger), | ||
| 1448 | literal = true); | ||
| 1449 | end makeIntegerArray; | ||
| 1450 | |||
| 1451 | function makeRealArray | ||
| 1452 | input list<Real> values; | ||
| 1453 | output Expression exp; | ||
| 1454 | algorithm | ||
| 1455 | 14 | exp := makeArray(Type.ARRAY(Type.REAL(), {Dimension.fromInteger(listLength(values))}), | |
| 1456 | Array.mapList(values, makeReal), | ||
| 1457 | literal = true); | ||
| 1458 | end makeRealArray; | ||
| 1459 | |||
| 1460 | function makeRealMatrix | ||
| 1461 | input list<list<Real>> values; | ||
| 1462 | output Expression exp; | ||
| 1463 | protected | ||
| 1464 | Type ty; | ||
| 1465 | list<Expression> expl; | ||
| 1466 | algorithm | ||
| 1467 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | if listEmpty(values) then |
| 1468 | ✗ | ty := Type.ARRAY(Type.REAL(), {Dimension.fromInteger(0), Dimension.UNKNOWN()}); | |
| 1469 | ✗ | exp := makeEmptyArray(ty); | |
| 1470 | else | ||
| 1471 | 28 | ty := Type.ARRAY(Type.REAL(), {Dimension.fromInteger(listLength(listHead(values)))}); | |
| 1472 |
8/8✓ Branch 0 taken 126 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 126 times.
✓ Branch 3 taken 14 times.
✓ Branch 4 taken 252 times.
✓ Branch 5 taken 126 times.
✓ Branch 6 taken 252 times.
✓ Branch 7 taken 126 times.
|
392 | expl := list(makeArray(ty, listArray(list(REAL(v) for v in row)), literal = true) for row in values); |
| 1473 | 14 | ty := Type.liftArrayLeft(ty, Dimension.fromInteger(listLength(expl))); | |
| 1474 | 14 | exp := makeArray(ty, listArray(expl), literal = true); | |
| 1475 | end if; | ||
| 1476 | end makeRealMatrix; | ||
| 1477 | |||
| 1478 | function makeExpArray | ||
| 1479 | input array<Expression> elements; | ||
| 1480 | input Type elementType; | ||
| 1481 | input Boolean isLiteral = false; | ||
| 1482 | output Expression exp; | ||
| 1483 | protected | ||
| 1484 | Type ty; | ||
| 1485 | algorithm | ||
| 1486 | 2027 | ty := Type.liftArrayLeft(elementType, Dimension.fromInteger(arrayLength(elements))); | |
| 1487 | 2027 | exp := makeArray(ty, elements, isLiteral); | |
| 1488 | end makeExpArray; | ||
| 1489 | |||
| 1490 | function makeRecord | ||
| 1491 | input Absyn.Path recordName; | ||
| 1492 | input Type recordType; | ||
| 1493 | input list<Expression> fields; | ||
| 1494 | output Expression exp; | ||
| 1495 | algorithm | ||
| 1496 | 10566 | exp := RECORD(recordName, recordType, fields); | |
| 1497 | end makeRecord; | ||
| 1498 | |||
| 1499 | function makeRange | ||
| 1500 | input Expression start; | ||
| 1501 | input Option<Expression> step; | ||
| 1502 | input Expression stop; | ||
| 1503 | output Expression rangeExp; | ||
| 1504 | algorithm | ||
| 1505 | 2173 | rangeExp := RANGE( | |
| 1506 | TypeCheck.getRangeType(start, step, stop, typeOf(start), Absyn.dummyInfo), | ||
| 1507 | start, step, stop | ||
| 1508 | ); | ||
| 1509 | end makeRange; | ||
| 1510 | |||
| 1511 | function makeIntegerRange | ||
| 1512 | input Integer start; | ||
| 1513 | input Integer step; | ||
| 1514 | input Integer stop; | ||
| 1515 | output Expression rangeExp; | ||
| 1516 | protected | ||
| 1517 | Expression start_exp, stop_exp; | ||
| 1518 | Option<Expression> step_exp; | ||
| 1519 | algorithm | ||
| 1520 | 11 | start_exp := INTEGER(start); | |
| 1521 | 11 | stop_exp := INTEGER(stop); | |
| 1522 | |||
| 1523 |
2/6✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
11 | if start == stop or |
| 1524 | step == 1 and start <= stop or | ||
| 1525 | step == -1 and start >= stop then | ||
| 1526 | step_exp := NONE(); | ||
| 1527 | else | ||
| 1528 | ✗ | step_exp := SOME(INTEGER(step)); | |
| 1529 | end if; | ||
| 1530 | |||
| 1531 | 11 | rangeExp := makeRange(start_exp, step_exp, stop_exp); | |
| 1532 | end makeIntegerRange; | ||
| 1533 | |||
| 1534 | function getIntegerRange | ||
| 1535 | input Expression range "has to be RANGE()!"; | ||
| 1536 | input Boolean resize; | ||
| 1537 | output Integer start; | ||
| 1538 | output Integer step; | ||
| 1539 | output Integer stop; | ||
| 1540 | algorithm | ||
| 1541 | (start, step, stop) := match range | ||
| 1542 | case RANGE() algorithm | ||
| 1543 | try | ||
| 1544 | 1180 | start := getInteger(range.start, resize); | |
| 1545 | 1180 | stop := getInteger(range.stop, resize); | |
| 1546 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 1180 times.
✓ Branch 2 taken 1176 times.
✓ Branch 3 taken 4 times.
|
1180 | if isSome(range.step) then |
| 1547 | 4 | step := getInteger(Util.getOption(range.step), resize); | |
| 1548 | else | ||
| 1549 |
1/2✓ Branch 0 taken 1176 times.
✗ Branch 1 not taken.
|
1176 | step := if start > stop then -1 else 1; |
| 1550 | end if; | ||
| 1551 | else | ||
| 1552 | ✗ | Error.terminate(getInstanceName() + " range could not be parsed to integer values: " + toString(range), sourceInfo()); | |
| 1553 | ✗ | fail(); | |
| 1554 | end try; | ||
| 1555 | then (start, step, stop); | ||
| 1556 | else algorithm | ||
| 1557 | ✗ | Error.terminate(getInstanceName() + " expression not RANGE(): " + toString(range), sourceInfo()); | |
| 1558 | ✗ | then fail(); | |
| 1559 | end match; | ||
| 1560 | end getIntegerRange; | ||
| 1561 | |||
| 1562 | function getInteger | ||
| 1563 | input Expression exp; | ||
| 1564 | input Boolean resize; | ||
| 1565 | output Integer i; | ||
| 1566 | protected | ||
| 1567 | Expression e; | ||
| 1568 | algorithm | ||
| 1569 |
2/2✓ Branch 0 taken 1850 times.
✓ Branch 1 taken 1966 times.
|
3816 | if resize then |
| 1570 | 1850 | e := Expression.map(exp, Expression.replaceResizableParameter); | |
| 1571 | else | ||
| 1572 | 1966 | e := Expression.map(exp, Expression.replaceResizableParameterWithOriginal); | |
| 1573 | end if; | ||
| 1574 | i := match SimplifyExp.simplify(e) | ||
| 1575 | case INTEGER(i) then i; | ||
| 1576 | else algorithm | ||
| 1577 | ✗ | Error.terminate(getInstanceName() + " cannot be parsed to an integer: " + toString(exp), sourceInfo()); | |
| 1578 | ✗ | then fail(); | |
| 1579 | end match; | ||
| 1580 | end getInteger; | ||
| 1581 | |||
| 1582 | function makeTuple | ||
| 1583 | input list<Expression> expl; | ||
| 1584 | output Expression tupleExp; | ||
| 1585 | protected | ||
| 1586 | list<Type> tyl; | ||
| 1587 | algorithm | ||
| 1588 |
2/2✓ Branch 1 taken 5 times.
✓ Branch 2 taken 17 times.
|
22 | if listLength(expl) == 1 then |
| 1589 | 5 | tupleExp := listHead(expl); | |
| 1590 | else | ||
| 1591 |
4/4✓ Branch 0 taken 34 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 34 times.
✓ Branch 3 taken 17 times.
|
51 | tyl := list(typeOf(e) for e in expl); |
| 1592 | 17 | tupleExp := TUPLE(Type.TUPLE(tyl, NONE()), expl); | |
| 1593 | end if; | ||
| 1594 | end makeTuple; | ||
| 1595 | |||
| 1596 | function emptyRange | ||
| 1597 | "returns true if the range is size 0 or less and not resizable" | ||
| 1598 | input Expression range "has to be RANGE()!"; | ||
| 1599 | output Boolean b = (not contains(range, isResizableCref)) and 0 >= Dimension.size(Type.nthDimension(typeOf(range), 1), false); | ||
| 1600 | end emptyRange; | ||
| 1601 | |||
| 1602 | function rangeSize | ||
| 1603 | input Expression range "has to be RANGE()!"; | ||
| 1604 | input Boolean resize = false; | ||
| 1605 | output Integer size = Dimension.size(Type.nthDimension(typeOf(range), 1), resize); | ||
| 1606 | end rangeSize; | ||
| 1607 | |||
| 1608 | function rangeSizeExp | ||
| 1609 | input Expression range "has to be RANGE()!"; | ||
| 1610 | output Expression size = Dimension.sizeExp(Type.nthDimension(typeOf(range), 1)); | ||
| 1611 | end rangeSizeExp; | ||
| 1612 | |||
| 1613 | function applySubscripts | ||
| 1614 | "Subscripts an expression with the given list of subscripts." | ||
| 1615 | input list<Subscript> subscripts; | ||
| 1616 | input Expression exp; | ||
| 1617 | input Boolean applyToScope = false; | ||
| 1618 | output Expression outExp; | ||
| 1619 | algorithm | ||
| 1620 |
2/2✓ Branch 0 taken 400527 times.
✓ Branch 1 taken 904423 times.
|
1304950 | if listEmpty(subscripts) then |
| 1621 | outExp := exp; | ||
| 1622 | else | ||
| 1623 | 400527 | outExp := applySubscript(listHead(subscripts), exp, listRest(subscripts), applyToScope); | |
| 1624 | end if; | ||
| 1625 | end applySubscripts; | ||
| 1626 | |||
| 1627 | function applySubscript | ||
| 1628 | "Subscripts an expression with the given subscript, and then applies the | ||
| 1629 | optional list of subscripts to each element of the subscripted expression." | ||
| 1630 | input Subscript subscript; | ||
| 1631 | input Expression exp; | ||
| 1632 | input list<Subscript> restSubscripts = {}; | ||
| 1633 | input Boolean applyToScope = false; | ||
| 1634 | output Expression outExp; | ||
| 1635 | algorithm | ||
| 1636 | outExp := match exp | ||
| 1637 | 99329 | case CREF() then applySubscriptCref(subscript, exp.cref, restSubscripts, applyToScope); | |
| 1638 | |||
| 1639 | case TYPENAME() guard listEmpty(restSubscripts) | ||
| 1640 | ✗ | then applySubscriptTypename(subscript, exp.ty); | |
| 1641 | |||
| 1642 | 127104 | case ARRAY() then applySubscriptArray(subscript, exp, restSubscripts, applyToScope); | |
| 1643 | |||
| 1644 | case RANGE() guard listEmpty(restSubscripts) | ||
| 1645 | 1269 | then applySubscriptRange(subscript, exp); | |
| 1646 | |||
| 1647 | case CALL() | ||
| 1648 | 90303 | then applySubscriptCall(subscript, exp, restSubscripts, applyToScope); | |
| 1649 | |||
| 1650 | 265 | case IF() then applySubscriptIf(subscript, exp, restSubscripts, applyToScope); | |
| 1651 | |||
| 1652 | case BINARY() guard List.all(subscript :: restSubscripts, isCheapSubscript) | ||
| 1653 | 4157 | then applySubscriptBinary(subscript, exp, restSubscripts, applyToScope); | |
| 1654 | |||
| 1655 | case UNARY() guard Type.isArray(Operator.typeOf(exp.operator)) and | ||
| 1656 | List.all(subscript :: restSubscripts, isCheapSubscript) | ||
| 1657 | algorithm | ||
| 1658 | 26 | outExp := applySubscript(subscript, exp.exp, restSubscripts, applyToScope); | |
| 1659 | 26 | then | |
| 1660 | UNARY(Operator.setType(typeOf(outExp), exp.operator), outExp); | ||
| 1661 | |||
| 1662 | case UNBOX() | ||
| 1663 | algorithm | ||
| 1664 | ✗ | outExp := applySubscript(subscript, exp.exp, restSubscripts, applyToScope); | |
| 1665 | ✗ | then | |
| 1666 | unbox(outExp); | ||
| 1667 | |||
| 1668 | ✗ | case BOX() then box(applySubscript(subscript, exp.exp, restSubscripts, applyToScope)); | |
| 1669 | |||
| 1670 | case CAST() | ||
| 1671 | algorithm | ||
| 1672 | 5 | outExp := applySubscript(subscript, exp.exp, restSubscripts, applyToScope); | |
| 1673 | 5 | then | |
| 1674 | CAST(Type.copyElementType(typeOf(outExp), exp.ty), outExp); | ||
| 1675 | |||
| 1676 | 94144 | else makeSubscriptedExp(subscript :: restSubscripts, exp); | |
| 1677 | end match; | ||
| 1678 | end applySubscript; | ||
| 1679 | |||
| 1680 | function applySubscriptCref | ||
| 1681 | input Subscript subscript; | ||
| 1682 | input ComponentRef cref; | ||
| 1683 | input list<Subscript> restSubscripts; | ||
| 1684 | input Boolean applyToScope; | ||
| 1685 | output Expression outExp; | ||
| 1686 | protected | ||
| 1687 | ComponentRef cr; | ||
| 1688 | Type ty; | ||
| 1689 | algorithm | ||
| 1690 | 99329 | cr := ComponentRef.mergeSubscripts(subscript :: restSubscripts, cref, applyToScope); | |
| 1691 | 99329 | ty := ComponentRef.getSubscriptedType(cr); | |
| 1692 | 99329 | outExp := CREF(ty, cr); | |
| 1693 | end applySubscriptCref; | ||
| 1694 | |||
| 1695 | function applySubscriptTypename | ||
| 1696 | input Subscript subscript; | ||
| 1697 | input Type ty; | ||
| 1698 | output Expression outExp; | ||
| 1699 | protected | ||
| 1700 | Subscript sub; | ||
| 1701 | array<Expression> expl; | ||
| 1702 | algorithm | ||
| 1703 | ✗ | sub := Subscript.expandSlice(subscript, false); | |
| 1704 | |||
| 1705 | outExp := match sub | ||
| 1706 | ✗ | case Subscript.INDEX() then applyIndexSubscriptTypename(ty, sub); | |
| 1707 | |||
| 1708 | case Subscript.SLICE() | ||
| 1709 | ✗ | then SUBSCRIPTED_EXP(TYPENAME(ty), {subscript}, Type.ARRAY(ty, {Subscript.toDimension(sub)}), false); | |
| 1710 | |||
| 1711 | case Subscript.WHOLE() | ||
| 1712 | ✗ | then TYPENAME(ty); | |
| 1713 | |||
| 1714 | case Subscript.EXPANDED_SLICE() | ||
| 1715 | algorithm | ||
| 1716 | ✗ | expl := Array.mapList(sub.indices, function applyIndexSubscriptTypename(ty = ty)); | |
| 1717 | ✗ | then | |
| 1718 | makeArray(Type.liftArrayLeft(ty, Dimension.fromInteger(arrayLength(expl))), expl, literal = true); | ||
| 1719 | |||
| 1720 | end match; | ||
| 1721 | end applySubscriptTypename; | ||
| 1722 | |||
| 1723 | function applyIndexSubscriptTypename | ||
| 1724 | input Type ty; | ||
| 1725 | input Subscript index; | ||
| 1726 | output Expression subscriptedExp; | ||
| 1727 | protected | ||
| 1728 | Expression idx_exp; | ||
| 1729 | Integer idx; | ||
| 1730 | algorithm | ||
| 1731 | ✗ | idx_exp := Subscript.toExp(index); | |
| 1732 | |||
| 1733 | ✗ | if isScalarLiteral(idx_exp) then | |
| 1734 | ✗ | idx := toInteger(idx_exp); | |
| 1735 | |||
| 1736 | subscriptedExp := match ty | ||
| 1737 | case Type.BOOLEAN() guard idx <= 2 | ||
| 1738 | ✗ | then if idx == 1 then BOOLEAN(false) else BOOLEAN(true); | |
| 1739 | |||
| 1740 | ✗ | case Type.ENUMERATION() then nthEnumLiteral(ty, idx); | |
| 1741 | end match; | ||
| 1742 | else | ||
| 1743 | ✗ | subscriptedExp := SUBSCRIPTED_EXP(TYPENAME(ty), {index}, ty, false); | |
| 1744 | end if; | ||
| 1745 | end applyIndexSubscriptTypename; | ||
| 1746 | |||
| 1747 | function applySubscriptArray | ||
| 1748 | input Subscript subscript; | ||
| 1749 | input Expression exp; | ||
| 1750 | input list<Subscript> restSubscripts; | ||
| 1751 | input Boolean applyToScope; | ||
| 1752 | output Expression outExp; | ||
| 1753 | protected | ||
| 1754 | Subscript sub, s; | ||
| 1755 | list<Subscript> rest_subs; | ||
| 1756 | array<Expression> expl; | ||
| 1757 | Type ty; | ||
| 1758 | Boolean literal; | ||
| 1759 | algorithm | ||
| 1760 |
2/2✓ Branch 1 taken 114 times.
✓ Branch 2 taken 126990 times.
|
127104 | if isEmptyArray(exp) then |
| 1761 | 114 | outExp := makeSubscriptedExp(subscript :: restSubscripts, exp); | |
| 1762 | 114 | return; | |
| 1763 | end if; | ||
| 1764 | |||
| 1765 | 126990 | sub := Subscript.expandSlice(subscript, false); | |
| 1766 | |||
| 1767 | outExp := match sub | ||
| 1768 | 122707 | case Subscript.INDEX() then applyIndexSubscriptArray(exp, sub, restSubscripts); | |
| 1769 | 4 | case Subscript.SLICE() then makeSubscriptedExp(subscript :: restSubscripts, exp); | |
| 1770 | case Subscript.WHOLE() | ||
| 1771 | algorithm | ||
| 1772 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 129 times.
|
139 | if listEmpty(restSubscripts) then |
| 1773 | outExp := exp; | ||
| 1774 | else | ||
| 1775 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | ARRAY(ty = ty, elements = expl, literal = literal) := exp; |
| 1776 | 10 | s :: rest_subs := restSubscripts; | |
| 1777 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
20 | expl := Array.map(expl, function applySubscript(subscript = s, restSubscripts = rest_subs, applyToScope = applyToScope)); |
| 1778 | 10 | (ty, literal) := typeSubscriptedArray(expl, restSubscripts, ty, literal); | |
| 1779 | 10 | outExp := makeArray(ty, expl, literal); | |
| 1780 | end if; | ||
| 1781 | then | ||
| 1782 | outExp; | ||
| 1783 | |||
| 1784 | case Subscript.EXPANDED_SLICE() | ||
| 1785 | algorithm | ||
| 1786 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 269 times.
|
269 | ARRAY(ty = ty, literal = literal) := exp; |
| 1787 | 269 | expl := Array.mapList(sub.indices, | |
| 1788 | function applyIndexSubscriptArray(exp = exp, restSubscripts = restSubscripts)); | ||
| 1789 | 269 | (ty, literal) := typeSubscriptedArray(expl, restSubscripts, ty, literal); | |
| 1790 | 269 | then | |
| 1791 | makeArray(ty, expl, literal); | ||
| 1792 | |||
| 1793 | 3870 | case Subscript.SPLIT_INDEX() then makeSubscriptedExp(subscript :: restSubscripts, exp); | |
| 1794 | |||
| 1795 | end match; | ||
| 1796 | end applySubscriptArray; | ||
| 1797 | |||
| 1798 | function typeSubscriptedArray | ||
| 1799 | input array<Expression> elements; | ||
| 1800 | input list<Subscript> subscripts; | ||
| 1801 | input output Type ty; | ||
| 1802 | input output Boolean literal; | ||
| 1803 | protected | ||
| 1804 | Integer count; | ||
| 1805 | Expression e; | ||
| 1806 | algorithm | ||
| 1807 | count := arrayLength(elements); | ||
| 1808 | |||
| 1809 |
2/2✓ Branch 0 taken 122 times.
✓ Branch 1 taken 157 times.
|
279 | if count > 0 then |
| 1810 | // If the array isn't empty, use the type of the first element. | ||
| 1811 | e := elements[1]; | ||
| 1812 | 122 | ty := typeOf(e); | |
| 1813 | // Non-literal subscripts might change an array from literal to non-literal. | ||
| 1814 |
3/4✓ Branch 0 taken 112 times.
✓ Branch 1 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 112 times.
|
122 | literal := literal and isLiteral(e); |
| 1815 | else | ||
| 1816 | // If the array is empty, use the slower method of subscripting the type. | ||
| 1817 | 157 | ty := Type.subscript(Type.unliftArray(ty), subscripts); | |
| 1818 | end if; | ||
| 1819 | |||
| 1820 | 279 | ty := Type.liftArrayLeft(ty, Dimension.fromInteger(count)); | |
| 1821 | end typeSubscriptedArray; | ||
| 1822 | |||
| 1823 | function applyIndexSubscriptArray | ||
| 1824 | input Expression exp; | ||
| 1825 | input Subscript index; | ||
| 1826 | input list<Subscript> restSubscripts; | ||
| 1827 | output Expression outExp; | ||
| 1828 | algorithm | ||
| 1829 | 123122 | outExp := applyIndexExpArray(exp, Subscript.toExp(index), restSubscripts); | |
| 1830 | end applyIndexSubscriptArray; | ||
| 1831 | |||
| 1832 | function applyIndexExpArray | ||
| 1833 | input Expression exp; | ||
| 1834 | input Expression index; | ||
| 1835 | input list<Subscript> restSubscripts; | ||
| 1836 | output Expression outExp; | ||
| 1837 | protected | ||
| 1838 | array<Expression> expl; | ||
| 1839 | Integer idx; | ||
| 1840 | algorithm | ||
| 1841 | // Try to subscript the array if the index is known. | ||
| 1842 |
2/2✓ Branch 1 taken 116158 times.
✓ Branch 2 taken 6964 times.
|
123122 | if isScalarLiteral(index) then |
| 1843 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 116158 times.
|
116158 | ARRAY(elements = expl) := exp; |
| 1844 | 116158 | idx := toInteger(index); | |
| 1845 | |||
| 1846 | // Check that the index is in bounds. We don't want to fail here if it's | ||
| 1847 | // out of bounds, that's someone else's problem and might be fine. | ||
| 1848 |
3/4✓ Branch 0 taken 116158 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 116155 times.
✓ Branch 3 taken 3 times.
|
232316 | if idx > 0 and idx <= arrayLength(expl) then |
| 1849 | 116155 | outExp := applySubscripts(restSubscripts, expl[idx]); | |
| 1850 | 116155 | return; | |
| 1851 | end if; | ||
| 1852 | end if; | ||
| 1853 | |||
| 1854 | // Otherwise create a subscript expression. | ||
| 1855 | 13934 | outExp := makeSubscriptedExp(Subscript.INDEX(index) :: restSubscripts, exp); | |
| 1856 | end applyIndexExpArray; | ||
| 1857 | |||
| 1858 | function applySubscriptRange | ||
| 1859 | input Subscript subscript; | ||
| 1860 | input Expression exp; | ||
| 1861 | output Expression outExp; | ||
| 1862 | protected | ||
| 1863 | Subscript sub; | ||
| 1864 | Type ty; | ||
| 1865 | array<Expression> expl; | ||
| 1866 | algorithm | ||
| 1867 | 1269 | sub := Subscript.expandSlice(subscript, false); | |
| 1868 | |||
| 1869 | outExp := match sub | ||
| 1870 | 1122 | case Subscript.INDEX() then applyIndexSubscriptRange(exp, sub); | |
| 1871 | |||
| 1872 | case Subscript.SLICE() | ||
| 1873 | algorithm | ||
| 1874 | ✗ | RANGE(ty = ty) := exp; | |
| 1875 | ✗ | ty := Type.ARRAY(Type.unliftArray(ty), {Subscript.toDimension(sub)}); | |
| 1876 | ✗ | then | |
| 1877 | SUBSCRIPTED_EXP(exp, {subscript}, ty, false); | ||
| 1878 | |||
| 1879 | case Subscript.WHOLE() then exp; | ||
| 1880 | |||
| 1881 | case Subscript.EXPANDED_SLICE() | ||
| 1882 | algorithm | ||
| 1883 | ✗ | expl := Array.mapList(sub.indices, function applyIndexSubscriptRange(rangeExp = exp)); | |
| 1884 | ✗ | RANGE(ty = ty) := exp; | |
| 1885 | ✗ | then | |
| 1886 | makeArray(Type.liftArrayLeft(ty, Dimension.fromInteger(arrayLength(expl))), expl); | ||
| 1887 | |||
| 1888 | case Subscript.SPLIT_INDEX() | ||
| 1889 | algorithm | ||
| 1890 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 147 times.
|
147 | RANGE(ty = ty) := exp; |
| 1891 | 147 | ty := Type.unliftArray(ty); | |
| 1892 | 147 | then | |
| 1893 | SUBSCRIPTED_EXP(exp, {sub}, ty, true); | ||
| 1894 | |||
| 1895 | else | ||
| 1896 | algorithm | ||
| 1897 | ✗ | Error.terminate(getInstanceName() + " got unknown subscript '" + Subscript.toString(sub) + "'", sourceInfo()); | |
| 1898 | ✗ | then | |
| 1899 | fail(); | ||
| 1900 | |||
| 1901 | end match; | ||
| 1902 | end applySubscriptRange; | ||
| 1903 | |||
| 1904 | function applyIndexSubscriptRange | ||
| 1905 | input Expression rangeExp; | ||
| 1906 | input Subscript index; | ||
| 1907 | output Expression outExp; | ||
| 1908 | protected | ||
| 1909 | Expression index_exp, start_exp, stop_exp; | ||
| 1910 | Option<Expression> step_exp; | ||
| 1911 | Type ty; | ||
| 1912 | list<Subscript> subs; | ||
| 1913 | Integer step, offset; | ||
| 1914 | algorithm | ||
| 1915 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1122 times.
|
1122 | Subscript.INDEX(index = index_exp) := index; |
| 1916 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1122 times.
|
1122 | RANGE(ty = ty, start = start_exp, step = step_exp, stop = stop_exp) := rangeExp; |
| 1917 | |||
| 1918 |
4/6✓ Branch 1 taken 628 times.
✓ Branch 2 taken 494 times.
✓ Branch 4 taken 628 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 628 times.
✗ Branch 8 not taken.
|
1122 | if isScalarLiteral(index_exp) and isScalarLiteral(start_exp) and |
| 1919 | Util.applyOptionOrDefault(step_exp, isScalarLiteral, true) then | ||
| 1920 | 628 | outExp := applyIndexSubscriptRange2(start_exp, step_exp, stop_exp, toInteger(index_exp)); | |
| 1921 | elseif isScalarLiteral(index_exp) and toInteger(index_exp) == 1 then | ||
| 1922 | outExp := start_exp; | ||
| 1923 | elseif Type.isInteger(Type.arrayElementType(ty)) and isScalarLiteral(start_exp) and | ||
| 1924 | Util.applyOptionOrDefault(step_exp, isScalarLiteral, true) then | ||
| 1925 | // (start:step:stop)[i] = step*i + (start - step), e.g. (1:n)[i] = i | ||
| 1926 | 492 | step := Util.applyOptionOrDefault(step_exp, toInteger, 1); | |
| 1927 | 492 | offset := toInteger(start_exp) - step; | |
| 1928 | outExp := index_exp; | ||
| 1929 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 492 times.
|
492 | if step <> 1 then |
| 1930 | ✗ | outExp := BINARY(INTEGER(step), Operator.makeMul(Type.INTEGER()), outExp); | |
| 1931 | end if; | ||
| 1932 |
2/2✓ Branch 0 taken 100 times.
✓ Branch 1 taken 392 times.
|
492 | if offset <> 0 then |
| 1933 | 100 | outExp := BINARY(outExp, Operator.makeAdd(Type.INTEGER()), INTEGER(offset)); | |
| 1934 | end if; | ||
| 1935 | else | ||
| 1936 | subs := {index}; | ||
| 1937 | 2 | ty := Type.subscript(ty, subs); | |
| 1938 | 2 | outExp := SUBSCRIPTED_EXP(rangeExp, subs, ty, false); | |
| 1939 | end if; | ||
| 1940 | end applyIndexSubscriptRange; | ||
| 1941 | |||
| 1942 | function applyIndexSubscriptRange2 | ||
| 1943 | input Expression startExp; | ||
| 1944 | input Option<Expression> stepExp; | ||
| 1945 | input Expression stopExp; | ||
| 1946 | input Integer index; | ||
| 1947 | output Expression subscriptedExp; | ||
| 1948 | protected | ||
| 1949 | Integer iidx; | ||
| 1950 | Real ridx; | ||
| 1951 | algorithm | ||
| 1952 | subscriptedExp := match (startExp, stepExp) | ||
| 1953 | case (INTEGER(), SOME(INTEGER(iidx))) | ||
| 1954 | ✗ | then INTEGER(startExp.value + (index - 1) * iidx); | |
| 1955 | |||
| 1956 | case (INTEGER(), _) | ||
| 1957 | 628 | then INTEGER(startExp.value + index - 1); | |
| 1958 | |||
| 1959 | case (REAL(), SOME(REAL(ridx))) | ||
| 1960 | ✗ | then REAL(startExp.value + (index - 1) * ridx); | |
| 1961 | |||
| 1962 | case (REAL(), _) | ||
| 1963 | ✗ | then REAL(startExp.value + index - 1.0); | |
| 1964 | |||
| 1965 | case (BOOLEAN(), _) | ||
| 1966 | ✗ | then if index == 1 then startExp else stopExp; | |
| 1967 | |||
| 1968 | case (ENUM_LITERAL(index = iidx), _) | ||
| 1969 | algorithm | ||
| 1970 | ✗ | iidx := iidx + index - 1; | |
| 1971 | ✗ | then | |
| 1972 | nthEnumLiteral(startExp.ty, iidx); | ||
| 1973 | |||
| 1974 | end match; | ||
| 1975 | end applyIndexSubscriptRange2; | ||
| 1976 | |||
| 1977 | function applySubscriptCall | ||
| 1978 | input Subscript subscript; | ||
| 1979 | input Expression exp; | ||
| 1980 | input list<Subscript> restSubscripts; | ||
| 1981 | input Boolean applyToScope; | ||
| 1982 | output Expression outExp; | ||
| 1983 | protected | ||
| 1984 | Call call; | ||
| 1985 | algorithm | ||
| 1986 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 90303 times.
|
90303 | CALL(call = call) := exp; |
| 1987 | |||
| 1988 | outExp := match call | ||
| 1989 | local | ||
| 1990 | Expression arg; | ||
| 1991 | Type ty; | ||
| 1992 | |||
| 1993 | case Call.TYPED_CALL(arguments = {arg}) | ||
| 1994 | guard Function.Function.isSubscriptableBuiltin(call.fn) | ||
| 1995 | algorithm | ||
| 1996 | 12 | arg := applySubscript(subscript, arg, restSubscripts, applyToScope); | |
| 1997 | 12 | ty := Type.copyDims(typeOf(arg), call.ty); | |
| 1998 | 12 | then | |
| 1999 | CALL(Call.TYPED_CALL(call.fn, ty, call.var, call.purity, {arg}, call.attributes)); | ||
| 2000 | |||
| 2001 | case Call.TYPED_ARRAY_CONSTRUCTOR() | ||
| 2002 | 2254 | then applySubscriptArrayConstructor(subscript, call, restSubscripts); | |
| 2003 | |||
| 2004 | 88037 | else makeSubscriptedExp(subscript :: restSubscripts, exp); | |
| 2005 | end match; | ||
| 2006 | end applySubscriptCall; | ||
| 2007 | |||
| 2008 | function applySubscriptArrayConstructor | ||
| 2009 | input Subscript subscript; | ||
| 2010 | input Call call; | ||
| 2011 | input list<Subscript> restSubscripts; | ||
| 2012 | output Expression outExp; | ||
| 2013 | algorithm | ||
| 2014 |
3/4✓ Branch 1 taken 1675 times.
✓ Branch 2 taken 579 times.
✓ Branch 3 taken 1675 times.
✗ Branch 4 not taken.
|
2254 | if Subscript.isIndex(subscript) and listEmpty(restSubscripts) then |
| 2015 | 1675 | outExp := applyIndexSubscriptArrayConstructor(call, subscript); | |
| 2016 | else | ||
| 2017 | // TODO: Handle slicing and multiple subscripts better. | ||
| 2018 | 579 | outExp := makeSubscriptedExp(subscript :: restSubscripts, CALL(call)); | |
| 2019 | end if; | ||
| 2020 | end applySubscriptArrayConstructor; | ||
| 2021 | |||
| 2022 | function applyIndexSubscriptArrayConstructor | ||
| 2023 | input Call call; | ||
| 2024 | input Subscript index; | ||
| 2025 | output Expression subscriptedExp; | ||
| 2026 | protected | ||
| 2027 | Type ty; | ||
| 2028 | Variability var; | ||
| 2029 | Purity pur; | ||
| 2030 | Expression exp, iter_exp; | ||
| 2031 | list<tuple<InstNode, Expression>> iters; | ||
| 2032 | InstNode iter; | ||
| 2033 | algorithm | ||
| 2034 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1675 times.
|
1675 | Call.TYPED_ARRAY_CONSTRUCTOR(ty, var, pur, exp, iters) := call; |
| 2035 | 1675 | ((iter, iter_exp), iters) := List.splitLast(iters); | |
| 2036 | 1675 | iter_exp := applySubscript(index, iter_exp); | |
| 2037 | 1675 | subscriptedExp := replaceIterator(exp, iter, iter_exp); | |
| 2038 | |||
| 2039 |
1/2✓ Branch 0 taken 1675 times.
✗ Branch 1 not taken.
|
1675 | if not listEmpty(iters) then |
| 2040 | ✗ | subscriptedExp := CALL(Call.TYPED_ARRAY_CONSTRUCTOR(Type.unliftArray(ty), var, pur, subscriptedExp, iters)); | |
| 2041 | end if; | ||
| 2042 | end applyIndexSubscriptArrayConstructor; | ||
| 2043 | |||
| 2044 | function applySubscriptIf | ||
| 2045 | input Subscript subscript; | ||
| 2046 | input Expression exp; | ||
| 2047 | input list<Subscript> restSubscripts; | ||
| 2048 | input Boolean applyToScope; | ||
| 2049 | output Expression outExp; | ||
| 2050 | protected | ||
| 2051 | Expression cond, tb, fb; | ||
| 2052 | Type ty; | ||
| 2053 | algorithm | ||
| 2054 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 265 times.
|
265 | IF(ty, cond, tb, fb) := exp; |
| 2055 | |||
| 2056 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 263 times.
|
265 | if Type.isConditionalArray(ty) then |
| 2057 | // Subscripting both branches of a conditional array might not be possible | ||
| 2058 | // since they have different dimensions. If it fails just subscript the | ||
| 2059 | // whole if-expression instead. | ||
| 2060 | try | ||
| 2061 | 2 | tb := applySubscript(subscript, tb, restSubscripts, applyToScope); | |
| 2062 | 2 | fb := applySubscript(subscript, fb, restSubscripts, applyToScope); | |
| 2063 | 2 | ty := Type.setConditionalArrayTypes(ty, typeOf(tb), typeOf(fb)); | |
| 2064 | 2 | outExp := IF(ty, cond, tb, fb); | |
| 2065 | else | ||
| 2066 | ✗ | outExp := makeSubscriptedExp(subscript :: restSubscripts, exp); | |
| 2067 | end try; | ||
| 2068 | else | ||
| 2069 | 263 | tb := applySubscript(subscript, tb, restSubscripts, applyToScope); | |
| 2070 | 263 | fb := applySubscript(subscript, fb, restSubscripts, applyToScope); | |
| 2071 | 263 | ty := typeOf(tb); | |
| 2072 | 263 | outExp := IF(ty, cond, tb, fb); | |
| 2073 | end if; | ||
| 2074 | end applySubscriptIf; | ||
| 2075 | |||
| 2076 | function isCheapSubscript | ||
| 2077 | "Whether the subscript can be duplicated into the operands of an operator." | ||
| 2078 | input Subscript subscript; | ||
| 2079 | output Boolean cheap; | ||
| 2080 | algorithm | ||
| 2081 | cheap := match subscript | ||
| 2082 |
3/4✓ Branch 1 taken 1662 times.
✓ Branch 2 taken 2521 times.
✓ Branch 4 taken 1662 times.
✗ Branch 5 not taken.
|
4183 | case Subscript.INDEX() then isCref(subscript.index) or isScalarLiteral(subscript.index); |
| 2083 | case Subscript.WHOLE() then true; | ||
| 2084 | else false; | ||
| 2085 | end match; | ||
| 2086 | end isCheapSubscript; | ||
| 2087 | |||
| 2088 | function applySubscriptBinary | ||
| 2089 | "Moves the subscripts into the operands of an element-wise operator: | ||
| 2090 | (a .* b)[i] = a[i] * b[i], (a * s)[i] = a[i] * s." | ||
| 2091 | input Subscript subscript; | ||
| 2092 | input Expression exp; | ||
| 2093 | input list<Subscript> restSubscripts; | ||
| 2094 | input Boolean applyToScope; | ||
| 2095 | output Expression outExp; | ||
| 2096 | protected | ||
| 2097 | import NFOperator.Op; | ||
| 2098 | Expression e1, e2; | ||
| 2099 | Operator op; | ||
| 2100 | Op scalar_op; | ||
| 2101 | Boolean sub1, sub2; | ||
| 2102 | algorithm | ||
| 2103 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4157 times.
|
4157 | BINARY(e1, op, e2) := exp; |
| 2104 | |||
| 2105 | (sub1, sub2, scalar_op) := match op.op | ||
| 2106 | case Op.ADD guard Type.isArray(op.ty) then (true, true, Op.ADD); | ||
| 2107 | case Op.SUB guard Type.isArray(op.ty) then (true, true, Op.SUB); | ||
| 2108 | case Op.ADD_EW then (true, true, Op.ADD); | ||
| 2109 | case Op.SUB_EW then (true, true, Op.SUB); | ||
| 2110 | case Op.MUL_EW then (true, true, Op.MUL); | ||
| 2111 | case Op.DIV_EW then (true, true, Op.DIV); | ||
| 2112 | case Op.POW_EW then (true, true, Op.POW); | ||
| 2113 | case Op.ADD_ARRAY_SCALAR then (true, false, Op.ADD); | ||
| 2114 | case Op.SUB_ARRAY_SCALAR then (true, false, Op.SUB); | ||
| 2115 | case Op.MUL_ARRAY_SCALAR then (true, false, Op.MUL); | ||
| 2116 | case Op.DIV_ARRAY_SCALAR then (true, false, Op.DIV); | ||
| 2117 | case Op.POW_ARRAY_SCALAR then (true, false, Op.POW); | ||
| 2118 | case Op.ADD_SCALAR_ARRAY then (false, true, Op.ADD); | ||
| 2119 | case Op.SUB_SCALAR_ARRAY then (false, true, Op.SUB); | ||
| 2120 | case Op.MUL_SCALAR_ARRAY then (false, true, Op.MUL); | ||
| 2121 | case Op.DIV_SCALAR_ARRAY then (false, true, Op.DIV); | ||
| 2122 | case Op.POW_SCALAR_ARRAY then (false, true, Op.POW); | ||
| 2123 | 1354 | else (false, false, op.op); | |
| 2124 | end match; | ||
| 2125 | |||
| 2126 |
2/2✓ Branch 0 taken 1354 times.
✓ Branch 1 taken 2803 times.
|
4157 | if not (sub1 or sub2) then |
| 2127 | 1354 | outExp := makeSubscriptedExp(subscript :: restSubscripts, exp); | |
| 2128 | 1354 | return; | |
| 2129 | end if; | ||
| 2130 | |||
| 2131 |
2/2✓ Branch 0 taken 2281 times.
✓ Branch 1 taken 522 times.
|
2803 | if sub1 then |
| 2132 | 2281 | e1 := applySubscript(subscript, e1, restSubscripts, applyToScope); | |
| 2133 | end if; | ||
| 2134 | |||
| 2135 |
2/2✓ Branch 0 taken 1705 times.
✓ Branch 1 taken 1098 times.
|
2803 | if sub2 then |
| 2136 | 1705 | e2 := applySubscript(subscript, e2, restSubscripts, applyToScope); | |
| 2137 | end if; | ||
| 2138 | |||
| 2139 |
2/2✓ Branch 0 taken 522 times.
✓ Branch 1 taken 2281 times.
|
3325 | op.ty := typeOf(if sub1 then e1 else e2); |
| 2140 | |||
| 2141 |
2/2✓ Branch 1 taken 2790 times.
✓ Branch 2 taken 13 times.
|
2803 | if Type.isScalar(op.ty) then |
| 2142 | 2790 | op.op := scalar_op; | |
| 2143 | end if; | ||
| 2144 | |||
| 2145 | 2803 | outExp := BINARY(e1, op, e2); | |
| 2146 | end applySubscriptBinary; | ||
| 2147 | |||
| 2148 | function makeSubscriptedExp | ||
| 2149 | input list<Subscript> subscripts; | ||
| 2150 | input Expression exp; | ||
| 2151 | input Boolean backend = false; | ||
| 2152 | output Expression outExp; | ||
| 2153 | protected | ||
| 2154 | Expression e; | ||
| 2155 | list<Subscript> subs, extra_subs; | ||
| 2156 | Type ty; | ||
| 2157 | Integer dim_count; | ||
| 2158 | Boolean split; | ||
| 2159 | algorithm | ||
| 2160 | // If the expression is already a SUBSCRIPTED_EXP we need to concatenate the | ||
| 2161 | // old subscripts with the new. Otherwise we just create a new SUBSCRIPTED_EXP. | ||
| 2162 | (e, subs, ty, split) := match exp | ||
| 2163 | 940 | case SUBSCRIPTED_EXP() then (exp.exp, exp.subscripts, typeOf(exp.exp), exp.split); | |
| 2164 | 194130 | else (exp, {}, typeOf(exp), false); | |
| 2165 | end match; | ||
| 2166 | |||
| 2167 |
2/2✓ Branch 0 taken 195068 times.
✓ Branch 1 taken 2 times.
|
195070 | if not split then |
| 2168 | 195068 | split := List.any(subscripts, Subscript.isSplitIndex); | |
| 2169 | end if; | ||
| 2170 | |||
| 2171 | 195070 | dim_count := Type.dimensionCount(ty); | |
| 2172 | 195070 | (subs, extra_subs) := Subscript.mergeList(subscripts, subs, dim_count, backend); | |
| 2173 | |||
| 2174 | // Check that the expression has enough dimensions to be subscripted. | ||
| 2175 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 195070 times.
|
195070 | if not listEmpty(extra_subs) then |
| 2176 | ✗ | Error.terminate(getInstanceName() + ": too few dimensions in " + | |
| 2177 | toString(exp) + " to apply subscripts " + Subscript.toStringList(subscripts), sourceInfo()); | ||
| 2178 | end if; | ||
| 2179 | |||
| 2180 | 195070 | ty := Type.subscript(ty, subs); | |
| 2181 |
2/2✓ Branch 0 taken 108666 times.
✓ Branch 1 taken 86404 times.
|
303736 | outExp := SUBSCRIPTED_EXP(e, subs, ty, split); |
| 2182 | end makeSubscriptedExp; | ||
| 2183 | |||
| 2184 | function replaceIterator | ||
| 2185 | "Replaces the given iterator with the given value in an expression." | ||
| 2186 | input output Expression exp; | ||
| 2187 | input InstNode iterator; | ||
| 2188 | input Expression iteratorValue; | ||
| 2189 | algorithm | ||
| 2190 | 32148 | exp := map(exp, function replaceIterator2(iterator = iterator, iteratorValue = iteratorValue)); | |
| 2191 | end replaceIterator; | ||
| 2192 | |||
| 2193 | function replaceIterator2 | ||
| 2194 | input Expression exp; | ||
| 2195 | input InstNode iterator; | ||
| 2196 | input Expression iteratorValue; | ||
| 2197 | output Expression outExp; | ||
| 2198 | algorithm | ||
| 2199 | outExp := match exp | ||
| 2200 | local | ||
| 2201 | InstNode node; | ||
| 2202 | ComponentRef cref; | ||
| 2203 | list<String> fields; | ||
| 2204 | |||
| 2205 | // Cref is simple identifier, i | ||
| 2206 | case CREF(cref = ComponentRef.CREF()) | ||
| 2207 | guard ComponentRef.isSimple(exp.cref) | ||
| 2208 |
2/2✓ Branch 2 taken 31166 times.
✓ Branch 3 taken 61693 times.
|
92859 | then if InstNode.refEqual(iterator, ComponentRef.node(exp.cref)) then iteratorValue else exp; |
| 2209 | |||
| 2210 | // Cref is qualified identifier, i.x | ||
| 2211 | case CREF(cref = ComponentRef.CREF()) | ||
| 2212 | algorithm | ||
| 2213 | // Only the first (last in stored order) part of a cref can be an iterator. | ||
| 2214 | 50870 | node := ComponentRef.node(ComponentRef.last(exp.cref)); | |
| 2215 | |||
| 2216 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 50869 times.
|
50870 | if InstNode.refEqual(iterator, node) then |
| 2217 | // Start with the given value. | ||
| 2218 | outExp := iteratorValue; | ||
| 2219 | |||
| 2220 | // Go down into the record fields using the rest of the cref. | ||
| 2221 |
4/4✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 1 time.
|
2 | fields := list(InstNode.name(n) for n in listRest(ComponentRef.nodes(exp.cref))); |
| 2222 | |||
| 2223 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
|
2 | for f in fields loop |
| 2224 | 1 | outExp := recordElement(f, outExp); | |
| 2225 | end for; | ||
| 2226 | else | ||
| 2227 | outExp := exp; | ||
| 2228 | end if; | ||
| 2229 | then | ||
| 2230 | outExp; | ||
| 2231 | |||
| 2232 | else exp; | ||
| 2233 | end match; | ||
| 2234 | end replaceIterator2; | ||
| 2235 | |||
| 2236 | function containsIterator | ||
| 2237 | input Expression exp; | ||
| 2238 | input InstNode iterator; | ||
| 2239 | output Boolean res; | ||
| 2240 | protected | ||
| 2241 | function containsIterator2 | ||
| 2242 | input Expression exp; | ||
| 2243 | input InstNode iterator; | ||
| 2244 | output Boolean res; | ||
| 2245 | algorithm | ||
| 2246 | res := match exp | ||
| 2247 | // Only the first (last in stored order) part of a cref can be an iterator: `i.x`. | ||
| 2248 | case CREF() guard ComponentRef.isIterator(exp.cref) | ||
| 2249 | 621 | then InstNode.refEqual(ComponentRef.node(ComponentRef.last(exp.cref)), iterator); | |
| 2250 | else false; | ||
| 2251 | end match; | ||
| 2252 | end containsIterator2; | ||
| 2253 | algorithm | ||
| 2254 | 3356 | res := contains(exp, function containsIterator2(iterator = iterator)); | |
| 2255 | end containsIterator; | ||
| 2256 | |||
| 2257 | function arrayFromList | ||
| 2258 | input list<Expression> inExps; | ||
| 2259 | input Type elemTy; | ||
| 2260 | input list<Dimension> inDims; | ||
| 2261 | output Expression outExp; | ||
| 2262 | algorithm | ||
| 2263 | 9787 | outExp := arrayFromList_impl(inExps, elemTy, listReverse(inDims)); | |
| 2264 | end arrayFromList; | ||
| 2265 | |||
| 2266 | function arrayFromList_impl | ||
| 2267 | input list<Expression> inExps; | ||
| 2268 | input Type elemTy; | ||
| 2269 | input list<Dimension> inDims; | ||
| 2270 | output Expression outExp; | ||
| 2271 | protected | ||
| 2272 | Dimension ldim; | ||
| 2273 | list<Dimension> restdims; | ||
| 2274 | Type ty; | ||
| 2275 | list<Expression> newlst; | ||
| 2276 | list<list<Expression>> partexps; | ||
| 2277 | Integer dimsize; | ||
| 2278 | algorithm | ||
| 2279 | 16455 | Error.assertion(not listEmpty(inDims), "Empty dimension list given in arrayFromList.", sourceInfo()); | |
| 2280 | |||
| 2281 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16455 times.
|
16455 | ldim::restdims := inDims; |
| 2282 | 16455 | dimsize := Dimension.size(ldim); | |
| 2283 | 16455 | ty := Type.liftArrayLeft(elemTy, ldim); | |
| 2284 | |||
| 2285 |
2/2✓ Branch 1 taken 9787 times.
✓ Branch 2 taken 6668 times.
|
16455 | if List.hasOneElement(inDims) then |
| 2286 | 9787 | Error.assertion(dimsize == listLength(inExps), "Length mismatch in arrayFromList.", sourceInfo()); | |
| 2287 | 9787 | outExp := makeArray(ty, listArray(inExps)); | |
| 2288 | 9787 | return; | |
| 2289 | end if; | ||
| 2290 | |||
| 2291 | 6668 | partexps := List.partition(inExps, dimsize); | |
| 2292 | |||
| 2293 | newlst := {}; | ||
| 2294 |
2/2✓ Branch 0 taken 6975 times.
✓ Branch 1 taken 6668 times.
|
13643 | for arrexp in partexps loop |
| 2295 | 6975 | newlst := makeArray(ty, listArray(arrexp))::newlst; | |
| 2296 | end for; | ||
| 2297 | |||
| 2298 | 6668 | newlst := listReverse(newlst); | |
| 2299 | 6668 | outExp := arrayFromList_impl(newlst, ty, restdims); | |
| 2300 | end arrayFromList_impl; | ||
| 2301 | |||
| 2302 | function makeEnumLiteral | ||
| 2303 | input Type enumType; | ||
| 2304 | input Integer index; | ||
| 2305 | output Expression literal; | ||
| 2306 | protected | ||
| 2307 | list<String> literals; | ||
| 2308 | algorithm | ||
| 2309 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | Type.ENUMERATION(literals = literals) := enumType; |
| 2310 | 3 | literal := ENUM_LITERAL(enumType, listGet(literals, index), index); | |
| 2311 | end makeEnumLiteral; | ||
| 2312 | |||
| 2313 | function makeEnumLiterals | ||
| 2314 | input Type enumType; | ||
| 2315 | output list<Expression> literals; | ||
| 2316 | protected | ||
| 2317 | list<String> lits; | ||
| 2318 | algorithm | ||
| 2319 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
|
27 | Type.ENUMERATION(literals = lits) := enumType; |
| 2320 |
7/8✓ Branch 1 taken 178 times.
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 178 times.
✓ Branch 4 taken 27 times.
✓ Branch 5 taken 178 times.
✓ Branch 6 taken 27 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 27 times.
|
205 | literals := list(ENUM_LITERAL(enumType, l, i) |
| 2321 | threaded for l in lits, i in 1:listLength(lits)); | ||
| 2322 | end makeEnumLiterals; | ||
| 2323 | |||
| 2324 | function isIntegerValue | ||
| 2325 | "Returns true if the expression is an Integer expression with the given | ||
| 2326 | value, otherwise false." | ||
| 2327 | input Expression exp; | ||
| 2328 | input Integer value; | ||
| 2329 | output Boolean result; | ||
| 2330 | algorithm | ||
| 2331 | result := match exp | ||
| 2332 | 4 | case INTEGER() then exp.value == value; | |
| 2333 | else false; | ||
| 2334 | end match; | ||
| 2335 | end isIntegerValue; | ||
| 2336 | |||
| 2337 | function toInteger | ||
| 2338 | input Expression exp; | ||
| 2339 | output Integer i; | ||
| 2340 | algorithm | ||
| 2341 | i := match exp | ||
| 2342 | 497097 | case INTEGER() then exp.value; | |
| 2343 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 | case BOOLEAN() then if exp.value then 2 else 1; |
| 2344 | 8 | case ENUM_LITERAL() then exp.index; | |
| 2345 | end match; | ||
| 2346 | end toInteger; | ||
| 2347 | |||
| 2348 | function toStringTyped | ||
| 2349 | input Expression exp; | ||
| 2350 | output String str; | ||
| 2351 | algorithm | ||
| 2352 | ✗ | str := "/*" + Type.toString(typeOf(exp)) + "*/ " + toString(exp); | |
| 2353 | end toStringTyped; | ||
| 2354 | |||
| 2355 | function toString | ||
| 2356 | input Expression exp; | ||
| 2357 | output String str; | ||
| 2358 | protected | ||
| 2359 | Type t; | ||
| 2360 | algorithm | ||
| 2361 | str := match exp | ||
| 2362 | 39652 | case INTEGER() then intString(exp.value); | |
| 2363 | 10365 | case REAL() then realString(exp.value); | |
| 2364 | 269 | case STRING() then "\"" + System.escapedString(exp.value, false) + "\""; | |
| 2365 |
2/2✓ Branch 0 taken 29 times.
✓ Branch 1 taken 169 times.
|
198 | case BOOLEAN() then boolString(exp.value); |
| 2366 | |||
| 2367 | case ENUM_LITERAL(ty = t as Type.ENUMERATION()) | ||
| 2368 | 443 | then AbsynUtil.pathString(t.typePath) + "." + exp.name; | |
| 2369 | |||
| 2370 | 2 | case CLKCONST() then ClockKind.toString(exp.clk); | |
| 2371 | 111397 | case CREF() then ComponentRef.toString(exp.cref); | |
| 2372 | ✗ | case TYPENAME() then Type.typenameString(Type.arrayElementType(exp.ty)); | |
| 2373 |
4/4✓ Branch 0 taken 12795 times.
✓ Branch 1 taken 3607 times.
✓ Branch 3 taken 12795 times.
✓ Branch 4 taken 3607 times.
|
32804 | case ARRAY() then "{" + stringDelimitList(list(toString(e) for e in exp.elements), ", ") + "}"; |
| 2374 | ✗ | case MATRIX() then "[" + stringDelimitList(list(stringDelimitList(list(toString(e) for e in el), ", ") for el in exp.elements), "; ") + "]"; | |
| 2375 | |||
| 2376 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 1839 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 1826 times.
|
1839 | case RANGE() then operandString(exp.start, exp, false) + |
| 2377 | ( | ||
| 2378 | if isSome(exp.step) | ||
| 2379 | then ":" + operandString(Util.getOption(exp.step), exp, false) | ||
| 2380 | else "" | ||
| 2381 | ) + ":" + operandString(exp.stop, exp, false); | ||
| 2382 | |||
| 2383 |
4/4✓ Branch 0 taken 233 times.
✓ Branch 1 taken 79 times.
✓ Branch 2 taken 233 times.
✓ Branch 3 taken 79 times.
|
312 | case TUPLE() then "(" + stringDelimitList(list(toString(e) for e in exp.elements), ", ") + ")"; |
| 2384 | 158 | case RECORD() then List.toStringCustom(exp.elements, toString, AbsynUtil.pathString(exp.path), "(", ", ", ")", true); | |
| 2385 | 4691 | case CALL() then Call.toString(exp.call); | |
| 2386 |
2/4✗ Branch 2 not taken.
✓ Branch 3 taken 35 times.
✓ Branch 4 taken 35 times.
✗ Branch 5 not taken.
|
35 | case SIZE() then "size(" + toString(exp.exp) + |
| 2387 | ( | ||
| 2388 | if isSome(exp.dimIndex) | ||
| 2389 | then ", " + toString(Util.getOption(exp.dimIndex)) | ||
| 2390 | else "" | ||
| 2391 | ) + ")"; | ||
| 2392 | case END() then "end"; | ||
| 2393 | |||
| 2394 | 7154 | case MULTARY() guard(listEmpty(exp.inv_arguments)) then multaryString(exp.arguments, exp, exp.operator, false); | |
| 2395 | |||
| 2396 | case MULTARY() guard(listEmpty(exp.arguments) and Operator.isDashClassification(Operator.getMathClassification(exp.operator))) | ||
| 2397 | 7 | then "-" + multaryString(exp.inv_arguments, exp, exp.operator); | |
| 2398 | |||
| 2399 | 71 | case MULTARY() guard(listEmpty(exp.arguments)) then "1/" + multaryString(exp.inv_arguments, exp, exp.operator); | |
| 2400 | |||
| 2401 | 2179 | case MULTARY() then multaryString(exp.arguments, exp, exp.operator) + | |
| 2402 | Operator.symbol(Operator.invert(exp.operator)) + | ||
| 2403 | multaryString(exp.inv_arguments, exp, exp.operator); | ||
| 2404 | |||
| 2405 | 11087 | case BINARY() then operandString(exp.exp1, exp, true) + | |
| 2406 | Operator.symbol(exp.operator) + | ||
| 2407 | operandString(exp.exp2, exp, false); | ||
| 2408 | |||
| 2409 | 2407 | case UNARY() then Operator.symbol(exp.operator, "") + | |
| 2410 | operandString(exp.exp, exp, false); | ||
| 2411 | |||
| 2412 | 96 | case LBINARY() then operandString(exp.exp1, exp, true) + | |
| 2413 | Operator.symbol(exp.operator) + | ||
| 2414 | operandString(exp.exp2, exp, false); | ||
| 2415 | |||
| 2416 | 17 | case LUNARY() then Operator.symbol(exp.operator, "") + " " + | |
| 2417 | operandString(exp.exp, exp, false); | ||
| 2418 | |||
| 2419 | 613 | case RELATION() then operandString(exp.exp1, exp, true) + | |
| 2420 | Operator.symbol(exp.operator) + | ||
| 2421 | operandString(exp.exp2, exp, false); | ||
| 2422 | |||
| 2423 | 135 | case IF() then "if " + toString(exp.condition) + " then " + toString(exp.trueBranch) + " else " + toString(exp.falseBranch); | |
| 2424 | |||
| 2425 |
2/2✓ Branch 1 taken 45 times.
✓ Branch 2 taken 414 times.
|
459 | case CAST() then if Flags.isSet(Flags.NF_API) then |
| 2426 | toString(exp.exp) | ||
| 2427 | else | ||
| 2428 | "CAST(" + Type.toString(exp.ty) + ", " + toString(exp.exp) + ")"; | ||
| 2429 | |||
| 2430 | 3 | case BOX() then "BOX(" + toString(exp.exp) + ")"; | |
| 2431 | ✗ | case UNBOX() then "UNBOX(" + toString(exp.exp) + ")"; | |
| 2432 | 69 | case SUBSCRIPTED_EXP() then "(" + toString(exp.exp) + ")" + Subscript.toStringList(exp.subscripts); | |
| 2433 | 30 | case TUPLE_ELEMENT() then toString(exp.tupleExp) + "[" + intString(exp.index) + "]"; | |
| 2434 | 10 | case RECORD_ELEMENT() then "(" + toString(exp.recordExp) + ")." + exp.fieldName; | |
| 2435 | ✗ | case MUTABLE() then toString(Mutable.access(exp.exp)); | |
| 2436 | ✗ | case SHARED_LITERAL() then "LITERAL(" + intString(exp.index) + ", " + toString(exp.exp) + ")"; | |
| 2437 | case EMPTY() then "#EMPTY#"; | ||
| 2438 | case PARTIAL_FUNCTION_APPLICATION() | ||
| 2439 |
7/8✓ Branch 3 taken 3 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 3 times.
✓ Branch 8 taken 3 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 3 times.
|
6 | then "function " + ComponentRef.toString(exp.fn) + "(" + stringDelimitList( |
| 2440 | list(n + " = " + toString(a) threaded for a in exp.args, n in exp.argNames), ", ") + ")"; | ||
| 2441 | |||
| 2442 | ✗ | case FILENAME() then "\"" + System.escapedString(exp.filename, false) + "\""; | |
| 2443 | case INSTANCE_NAME() then "getInstanceName()"; | ||
| 2444 | ✗ | else anyString(exp); | |
| 2445 | end match; | ||
| 2446 | end toString; | ||
| 2447 | |||
| 2448 | function toFlatString | ||
| 2449 | input Expression exp; | ||
| 2450 | input BaseModelica.OutputFormat format; | ||
| 2451 | output String str; | ||
| 2452 | protected | ||
| 2453 | Type t; | ||
| 2454 | algorithm | ||
| 2455 | str := match exp | ||
| 2456 | 1703 | case INTEGER() then intString(exp.value); | |
| 2457 | 1467 | case REAL() then realString(exp.value); | |
| 2458 | 3 | case STRING() then "\"" + Util.escapeModelicaStringToCString(exp.value) + "\""; | |
| 2459 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 12 times.
|
15 | case BOOLEAN() then boolString(exp.value); |
| 2460 | |||
| 2461 | case ENUM_LITERAL(ty = t as Type.ENUMERATION()) | ||
| 2462 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
4 | then if Type.isBuiltinEnumeration(t) then |
| 2463 | AbsynUtil.pathString(t.typePath) + "." + exp.name | ||
| 2464 | else | ||
| 2465 | Util.makeQuotedIdentifier(AbsynUtil.pathString(t.typePath)) + "." + Util.makeQuotedIdentifier(exp.name); | ||
| 2466 | |||
| 2467 | ✗ | case CLKCONST() then ClockKind.toFlatString(exp.clk, format); | |
| 2468 | |||
| 2469 | 672 | case CREF() then ComponentRef.toFlatString(exp.cref, format); | |
| 2470 | ✗ | case TYPENAME() then Type.typenameString(Type.arrayElementType(exp.ty)); | |
| 2471 | |||
| 2472 | case ARRAY() | ||
| 2473 |
6/8✗ Branch 0 not taken.
✓ Branch 1 taken 337 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 337 times.
✓ Branch 12 taken 988 times.
✓ Branch 13 taken 337 times.
✓ Branch 15 taken 988 times.
✓ Branch 16 taken 337 times.
|
2987 | then if arrayEmpty(exp.elements) then |
| 2474 | "fill("+toFlatString(makeDefaultValue(Type.elementType(exp.ty)), format)+", " + Type.dimensionsToFlatString(exp.ty, format) + ")" | ||
| 2475 | else | ||
| 2476 | "{" + stringDelimitList(list(toFlatString(e, format) for e in exp.elements), ", ") + "}"; | ||
| 2477 | |||
| 2478 | ✗ | case MATRIX() then "[" + stringDelimitList(list(stringDelimitList(list(toFlatString(e, format) for e in el), ", ") for el in exp.elements), "; ") + "]"; | |
| 2479 | |||
| 2480 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 19 times.
|
19 | case RANGE() then operandFlatString(exp.start, exp, false, format) + |
| 2481 | ( | ||
| 2482 | if isSome(exp.step) | ||
| 2483 | then ":" + operandFlatString(Util.getOption(exp.step), exp, false, format) | ||
| 2484 | else "" | ||
| 2485 | ) + ":" + operandFlatString(exp.stop, exp, false, format); | ||
| 2486 | |||
| 2487 | ✗ | case TUPLE() then "(" + stringDelimitList(list(toFlatString(e, format) for e in exp.elements), ", ") + ")"; | |
| 2488 | 137 | case RECORD() then List.toStringCustom(exp.elements, function toFlatString(format = format), Type.toFlatString(exp.ty, format), "(", ", ", ")", true); | |
| 2489 | 106 | case CALL() then Call.toFlatString(exp.call, format); | |
| 2490 | ✗ | case SIZE() then "size(" + toFlatString(exp.exp, format) + | |
| 2491 | ( | ||
| 2492 | if isSome(exp.dimIndex) | ||
| 2493 | then ", " + toFlatString(Util.getOption(exp.dimIndex), format) | ||
| 2494 | else "" | ||
| 2495 | ) + ")"; | ||
| 2496 | case END() then "end"; | ||
| 2497 | |||
| 2498 | 4 | case MULTARY() guard(listEmpty(exp.inv_arguments)) then multaryFlatString(exp.arguments, exp, exp.operator, format, false); | |
| 2499 | |||
| 2500 | case MULTARY() guard(listEmpty(exp.arguments) and Operator.isDashClassification(Operator.getMathClassification(exp.operator))) | ||
| 2501 | 1 | then "-" + multaryFlatString(exp.inv_arguments, exp, exp.operator, format); | |
| 2502 | |||
| 2503 | ✗ | case MULTARY() guard(listEmpty(exp.arguments)) then "1/" + multaryFlatString(exp.inv_arguments, exp, exp.operator, format); | |
| 2504 | |||
| 2505 | 4 | case MULTARY() then multaryFlatString(exp.arguments, exp, exp.operator, format) + | |
| 2506 | Operator.symbol(Operator.invert(exp.operator)) + | ||
| 2507 | multaryFlatString(exp.inv_arguments, exp, exp.operator, format); | ||
| 2508 | |||
| 2509 | 155 | case BINARY() then operandFlatString(exp.exp1, exp, true, format) + | |
| 2510 | Operator.symbol(exp.operator) + | ||
| 2511 | operandFlatString(exp.exp2, exp, false, format); | ||
| 2512 | |||
| 2513 | 15 | case UNARY() then Operator.symbol(exp.operator, "") + | |
| 2514 | operandFlatString(exp.exp, exp, false, format); | ||
| 2515 | |||
| 2516 | ✗ | case LBINARY() then operandFlatString(exp.exp1, exp, true, format) + | |
| 2517 | Operator.symbol(exp.operator) + | ||
| 2518 | operandFlatString(exp.exp2, exp, false, format); | ||
| 2519 | |||
| 2520 | ✗ | case LUNARY() then Operator.symbol(exp.operator, "") + " " + | |
| 2521 | operandFlatString(exp.exp, exp, false, format); | ||
| 2522 | |||
| 2523 | 18 | case RELATION() then operandFlatString(exp.exp1, exp, true, format) + | |
| 2524 | Operator.symbol(exp.operator) + | ||
| 2525 | operandFlatString(exp.exp2, exp, false, format); | ||
| 2526 | |||
| 2527 | 16 | case IF() then "if " + toFlatString(exp.condition, format) + " then " + toFlatString(exp.trueBranch, format) + " else " + toFlatString(exp.falseBranch, format); | |
| 2528 | |||
| 2529 | 1 | case CAST() then toFlatString(exp.exp, format); | |
| 2530 | ✗ | case UNBOX() then toFlatString(exp.exp, format); | |
| 2531 | ✗ | case BOX() then toFlatString(exp.exp, format); | |
| 2532 | |||
| 2533 | 8 | case SUBSCRIPTED_EXP() then "(" + toFlatString(exp.exp, format) + ")" + Subscript.toFlatStringList(exp.subscripts, format, escapeQuotes = false); | |
| 2534 | 1 | case TUPLE_ELEMENT() then toFlatString(exp.tupleExp, format); | |
| 2535 | ✗ | case RECORD_ELEMENT() then "(" + toFlatString(exp.recordExp, format) + ")." + exp.fieldName; | |
| 2536 | ✗ | case MUTABLE() then toFlatString(Mutable.access(exp.exp), format); | |
| 2537 | ✗ | case SHARED_LITERAL() then "[literal: " + intString(exp.index) + ", " + toString(exp.exp) + "]"; | |
| 2538 | case EMPTY() then "#EMPTY#"; | ||
| 2539 | case PARTIAL_FUNCTION_APPLICATION() | ||
| 2540 | ✗ | then "function " + ComponentRef.toFlatString(exp.fn, format) + "(" + stringDelimitList( | |
| 2541 | list(n + " = " + toFlatString(a, format) threaded for a in exp.args, n in exp.argNames), ", ") + ")"; | ||
| 2542 | |||
| 2543 | ✗ | case FILENAME() then "\"" + Util.escapeModelicaStringToCString(exp.filename) + "\""; | |
| 2544 | case INSTANCE_NAME() then "getInstanceName()"; | ||
| 2545 | ✗ | else anyString(exp); | |
| 2546 | end match; | ||
| 2547 | end toFlatString; | ||
| 2548 | |||
| 2549 | function operandString | ||
| 2550 | "Helper function to toString, prints an operator and adds parentheses as needed." | ||
| 2551 | input Expression operand; | ||
| 2552 | input Expression operator; | ||
| 2553 | input Boolean lhs; | ||
| 2554 | output String str; | ||
| 2555 | protected | ||
| 2556 | Integer operand_prio, operator_prio; | ||
| 2557 | Boolean parenthesize = false; | ||
| 2558 | algorithm | ||
| 2559 | 48898 | str := toString(operand); | |
| 2560 | 48898 | operand_prio := priority(operand, lhs); | |
| 2561 | |||
| 2562 |
2/2✓ Branch 0 taken 46604 times.
✓ Branch 1 taken 2294 times.
|
48898 | if operand_prio == 4 then |
| 2563 | parenthesize := true; | ||
| 2564 | else | ||
| 2565 | 46604 | operator_prio := priority(operator, lhs); | |
| 2566 | |||
| 2567 |
2/2✓ Branch 0 taken 44413 times.
✓ Branch 1 taken 2191 times.
|
46604 | if operand_prio > operator_prio then |
| 2568 | parenthesize := true; | ||
| 2569 | elseif operand_prio == operator_prio then | ||
| 2570 |
2/2✓ Branch 0 taken 2157 times.
✓ Branch 1 taken 809 times.
|
2966 | parenthesize := if lhs then isNonAssociativeExp(operand) else not |
| 2571 | isAssociativeExp(operand); | ||
| 2572 | end if; | ||
| 2573 | end if; | ||
| 2574 | |||
| 2575 |
2/2✓ Branch 0 taken 2246 times.
✓ Branch 1 taken 720 times.
|
2966 | if parenthesize then |
| 2576 | 5205 | str := "(" + str + ")"; | |
| 2577 | end if; | ||
| 2578 | end operandString; | ||
| 2579 | |||
| 2580 | function operandFlatString | ||
| 2581 | "Helper function to toString, prints an operator and adds parentheses as needed." | ||
| 2582 | input Expression operand; | ||
| 2583 | input Expression operator; | ||
| 2584 | input Boolean lhs; | ||
| 2585 | input BaseModelica.OutputFormat format; | ||
| 2586 | output String str; | ||
| 2587 | protected | ||
| 2588 | Integer operand_prio, operator_prio; | ||
| 2589 | Boolean parenthesize = false; | ||
| 2590 | algorithm | ||
| 2591 | 424 | str := toFlatString(operand, format); | |
| 2592 | 424 | operand_prio := priority(operand, lhs); | |
| 2593 | |||
| 2594 |
1/2✓ Branch 0 taken 424 times.
✗ Branch 1 not taken.
|
424 | if operand_prio == 4 then |
| 2595 | parenthesize := true; | ||
| 2596 | else | ||
| 2597 | 424 | operator_prio := priority(operator, lhs); | |
| 2598 | |||
| 2599 |
2/2✓ Branch 0 taken 398 times.
✓ Branch 1 taken 26 times.
|
424 | if operand_prio > operator_prio then |
| 2600 | parenthesize := true; | ||
| 2601 | elseif operand_prio == operator_prio then | ||
| 2602 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 4 times.
|
31 | parenthesize := if lhs then isNonAssociativeExp(operand) |
| 2603 | else not isAssociativeExp(operand); | ||
| 2604 | end if; | ||
| 2605 | end if; | ||
| 2606 | |||
| 2607 |
2/2✓ Branch 0 taken 29 times.
✓ Branch 1 taken 2 times.
|
31 | if parenthesize then |
| 2608 | 28 | str := "(" + str + ")"; | |
| 2609 | end if; | ||
| 2610 | end operandFlatString; | ||
| 2611 | |||
| 2612 | function multaryString | ||
| 2613 | input list<Expression> arguments; | ||
| 2614 | input Expression exp; | ||
| 2615 | input Operator operator; | ||
| 2616 | input Boolean parenthesize = true; | ||
| 2617 | output String str; | ||
| 2618 | algorithm | ||
| 2619 |
4/4✓ Branch 0 taken 19191 times.
✓ Branch 1 taken 11590 times.
✓ Branch 2 taken 19191 times.
✓ Branch 3 taken 11590 times.
|
30781 | str := stringDelimitList(list(operandString(e, exp, false) for e in arguments), Operator.symbol(operator)); |
| 2620 |
4/4✓ Branch 0 taken 7154 times.
✓ Branch 1 taken 4436 times.
✓ Branch 3 taken 4347 times.
✓ Branch 4 taken 89 times.
|
11590 | if parenthesize and listLength(arguments) > 1 then |
| 2621 | 89 | str := "(" + str + ")"; | |
| 2622 | end if; | ||
| 2623 | end multaryString; | ||
| 2624 | |||
| 2625 | function multaryFlatString | ||
| 2626 | input list<Expression> arguments; | ||
| 2627 | input Expression exp; | ||
| 2628 | input Operator operator; | ||
| 2629 | input BaseModelica.OutputFormat format; | ||
| 2630 | input Boolean parenthesize = true; | ||
| 2631 | output String str; | ||
| 2632 | algorithm | ||
| 2633 |
4/4✓ Branch 0 taken 25 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 13 times.
|
38 | str := stringDelimitList(list(operandFlatString(e, exp, false, format) for e in arguments), Operator.symbol(operator)); |
| 2634 |
4/4✓ Branch 0 taken 4 times.
✓ Branch 1 taken 9 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 5 times.
|
13 | if parenthesize and listLength(arguments) > 1 then |
| 2635 | 5 | str := "(" + str + ")"; | |
| 2636 | end if; | ||
| 2637 | end multaryFlatString; | ||
| 2638 | |||
| 2639 | function priority | ||
| 2640 | input Expression exp; | ||
| 2641 | input Boolean lhs; | ||
| 2642 | output Integer priority; | ||
| 2643 | algorithm | ||
| 2644 | priority := match exp | ||
| 2645 | 12972 | case INTEGER() then if exp.value < 0 then 4 else 0; | |
| 2646 |
2/2✓ Branch 0 taken 3148 times.
✓ Branch 1 taken 211 times.
|
3359 | case REAL() then if exp.value < 0.0 then 4 else 0; |
| 2647 | 20274 | case MULTARY() then Operator.priority(exp.operator, lhs); | |
| 2648 | 28059 | case BINARY() then Operator.priority(exp.operator, lhs); | |
| 2649 | case UNARY() then 4; | ||
| 2650 | 221 | case LBINARY() then Operator.priority(exp.operator, lhs); | |
| 2651 | case LUNARY() then 7; | ||
| 2652 | case RELATION() then 6; | ||
| 2653 | case RANGE() then 10; | ||
| 2654 | case IF() then 11; | ||
| 2655 | 387 | case CAST() then priority(exp.exp, lhs); | |
| 2656 | ✗ | case BOX() then priority(exp.exp, lhs); | |
| 2657 | ✗ | case UNBOX() then priority(exp.exp, lhs); | |
| 2658 | else 0; | ||
| 2659 | end match; | ||
| 2660 | end priority; | ||
| 2661 | |||
| 2662 | function isAssociativeExp | ||
| 2663 | input Expression exp; | ||
| 2664 | output Boolean isAssociative; | ||
| 2665 | algorithm | ||
| 2666 | isAssociative := match exp | ||
| 2667 | 182 | case BINARY() then Operator.isAssociative(exp.operator); | |
| 2668 | case LBINARY() then true; | ||
| 2669 | else false; | ||
| 2670 | end match; | ||
| 2671 | end isAssociativeExp; | ||
| 2672 | |||
| 2673 | function isNonAssociativeExp | ||
| 2674 | input Expression exp; | ||
| 2675 | output Boolean isAssociative; | ||
| 2676 | algorithm | ||
| 2677 | isAssociative := match exp | ||
| 2678 | 2174 | case BINARY() then Operator.isNonAssociative(exp.operator); | |
| 2679 | case LBINARY() then true; | ||
| 2680 | else false; | ||
| 2681 | end match; | ||
| 2682 | end isNonAssociativeExp; | ||
| 2683 | |||
| 2684 | function getName | ||
| 2685 | "Returns the 'name' of an Expression, for example the function name of a | ||
| 2686 | call or the record class name of a record expression." | ||
| 2687 | input Expression exp; | ||
| 2688 | output String name; | ||
| 2689 | algorithm | ||
| 2690 | name := match exp | ||
| 2691 | ✗ | case RECORD() then AbsynUtil.pathString(exp.path); | |
| 2692 | 18 | case CALL() then AbsynUtil.pathString(Call.functionName(exp.call)); | |
| 2693 | ✗ | case CAST() then getName(exp.exp); | |
| 2694 | ✗ | case BOX() then getName(exp.exp); | |
| 2695 | ✗ | case UNBOX() then getName(exp.exp); | |
| 2696 | ✗ | case MUTABLE() then getName(Mutable.access(exp.exp)); | |
| 2697 | ✗ | case SHARED_LITERAL() then getName(exp.exp); | |
| 2698 | ✗ | case PARTIAL_FUNCTION_APPLICATION() then ComponentRef.toString(exp.fn); | |
| 2699 | case INSTANCE_NAME() then "getInstanceName"; | ||
| 2700 | ✗ | else toString(exp); | |
| 2701 | end match; | ||
| 2702 | end getName; | ||
| 2703 | |||
| 2704 | function enumLiteralPath | ||
| 2705 | input Expression exp; | ||
| 2706 | output Absyn.Path path; | ||
| 2707 | protected | ||
| 2708 | String name; | ||
| 2709 | Absyn.Path ty_path; | ||
| 2710 | algorithm | ||
| 2711 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 20546 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20546 times.
|
20546 | ENUM_LITERAL(name = name, ty = Type.ENUMERATION(typePath = ty_path)) := exp; |
| 2712 | 20546 | path := AbsynUtil.suffixPath(ty_path, name); | |
| 2713 | end enumLiteralPath; | ||
| 2714 | |||
| 2715 | function getNominal | ||
| 2716 | input output Expression exp; | ||
| 2717 | algorithm | ||
| 2718 | 54 | exp := Expression.map(exp, computeNominal); | |
| 2719 | 54 | exp := SimplifyExp.simplify(exp); | |
| 2720 | end getNominal; | ||
| 2721 | |||
| 2722 | function computeNominal | ||
| 2723 | "Replaces variable crefs with their nominal values and normalizes by removing all negations. | ||
| 2724 | Needs to be mapped with Expression.map()" | ||
| 2725 | input output Expression exp; | ||
| 2726 | algorithm | ||
| 2727 | exp := match exp | ||
| 2728 | local | ||
| 2729 | PointerWeak<Variable> varPointer; | ||
| 2730 | Option<Expression> nominal; | ||
| 2731 | Operator operator; | ||
| 2732 | Operator.SizeClassification sizeClass; | ||
| 2733 | |||
| 2734 | // replace variables with their nominal values | ||
| 2735 | case CREF(cref = ComponentRef.CREF()) | ||
| 2736 | guard InstNode.isVar(ComponentRef.node(exp.cref)) | ||
| 2737 | algorithm | ||
| 2738 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
4 | InstNode.VAR_NODE(varPointer = varPointer) := ComponentRef.node(exp.cref); |
| 2739 | 4 | nominal := Variable.getNominal(Pointer.access(PointerWeak.upgrade(varPointer))); | |
| 2740 | 4 | then Util.getOptionOrDefault(nominal, exp); | |
| 2741 | |||
| 2742 | // remove negation | ||
| 2743 | 18 | case INTEGER() then INTEGER(abs(exp.value)); | |
| 2744 | 79 | case REAL() then REAL(abs(exp.value)); | |
| 2745 | 1 | case UNARY() then exp.exp; | |
| 2746 | |||
| 2747 | // replace binary - with + | ||
| 2748 | case BINARY(operator = operator) guard(Operator.getMathClassification(operator) == NFOperator.MathClassification.SUBTRACTION) algorithm | ||
| 2749 | ✗ | (_, sizeClass) := Operator.classify(operator); | |
| 2750 | ✗ | exp.operator := Operator.fromClassification((NFOperator.MathClassification.ADDITION, sizeClass), operator.ty); | |
| 2751 | then exp; | ||
| 2752 | |||
| 2753 | // replace multary - with + | ||
| 2754 | case MULTARY(operator = operator) guard(Operator.getMathClassification(operator) == NFOperator.MathClassification.ADDITION) algorithm | ||
| 2755 | 11 | exp.arguments := listAppend(exp.arguments, exp.inv_arguments); | |
| 2756 | 11 | exp.inv_arguments := {}; | |
| 2757 | then exp; | ||
| 2758 | |||
| 2759 | else exp; | ||
| 2760 | end match; | ||
| 2761 | end computeNominal; | ||
| 2762 | |||
| 2763 | function toAbsyn | ||
| 2764 | input Expression exp; | ||
| 2765 | output Absyn.Exp aexp; | ||
| 2766 | algorithm | ||
| 2767 | aexp := match exp | ||
| 2768 | local | ||
| 2769 | Type ty; | ||
| 2770 | |||
| 2771 | ✗ | case INTEGER() then Absyn.Exp.INTEGER(exp.value); | |
| 2772 | ✗ | case REAL() then Absyn.Exp.REAL(String(exp.value)); | |
| 2773 | ✗ | case STRING() then Absyn.Exp.STRING(exp.value); | |
| 2774 | 4773 | case BOOLEAN() then Absyn.Exp.BOOL(exp.value); | |
| 2775 | case ENUM_LITERAL(ty=Type.ENUMERATION()) | ||
| 2776 | ✗ | then Absyn.Exp.CREF(AbsynUtil.pathToCref(enumLiteralPath(exp))); | |
| 2777 | ✗ | case CLKCONST() then ClockKind.toAbsyn(exp.clk); | |
| 2778 | ✗ | case CREF() then Absyn.Exp.CREF(ComponentRef.toAbsyn(exp.cref)); | |
| 2779 | ✗ | case TYPENAME() then Absyn.Exp.CREF(Absyn.ComponentRef.CREF_IDENT(Type.toString(exp.ty), {})); | |
| 2780 | ✗ | case ARRAY() then Absyn.Exp.ARRAY(list(toAbsyn(e) for e in exp.elements)); | |
| 2781 | ✗ | case MATRIX() then Absyn.Exp.MATRIX(list(list(toAbsyn(e) for e in l) for l in exp.elements)); | |
| 2782 | ✗ | case RANGE() then Absyn.Exp.RANGE(toAbsyn(exp.start), Util.applyOption(exp.step, toAbsyn), toAbsyn(exp.stop)); | |
| 2783 | ✗ | case TUPLE() then Absyn.Exp.TUPLE(list(toAbsyn(e) for e in exp.elements)); | |
| 2784 | ✗ | case RECORD() then AbsynUtil.makeCall(AbsynUtil.pathToCref(exp.path), list(toAbsyn(e) for e in exp.elements)); | |
| 2785 | ✗ | case CALL() then Call.toAbsyn(exp.call); | |
| 2786 | ✗ | case SIZE() then AbsynUtil.makeCall(Absyn.ComponentRef.CREF_IDENT("size", {}), | |
| 2787 | if isSome(exp.dimIndex) then {toAbsyn(Util.getOption(exp.dimIndex))} else {}); | ||
| 2788 | case END() then Absyn.Exp.END(); | ||
| 2789 | ✗ | case BINARY() then Absyn.Exp.BINARY(toAbsyn(exp.exp1), Operator.toAbsyn(exp.operator), toAbsyn(exp.exp2)); | |
| 2790 | ✗ | case UNARY() then Absyn.Exp.UNARY(Operator.toAbsyn(exp.operator), toAbsyn(exp.exp)); | |
| 2791 | ✗ | case LBINARY() then Absyn.Exp.LBINARY(toAbsyn(exp.exp1), Operator.toAbsyn(exp.operator), toAbsyn(exp.exp2)); | |
| 2792 | ✗ | case LUNARY() then Absyn.Exp.LUNARY(Operator.toAbsyn(exp.operator), toAbsyn(exp.exp)); | |
| 2793 | ✗ | case RELATION() then Absyn.Exp.RELATION(toAbsyn(exp.exp1), Operator.toAbsyn(exp.operator), toAbsyn(exp.exp2)); | |
| 2794 | ✗ | case IF() then Absyn.Exp.IFEXP(toAbsyn(exp.condition), toAbsyn(exp.trueBranch), toAbsyn(exp.falseBranch), {}); | |
| 2795 | ✗ | case CAST() then toAbsyn(exp.exp); | |
| 2796 | ✗ | case BOX() then toAbsyn(exp.exp); | |
| 2797 | ✗ | case UNBOX() then toAbsyn(exp.exp); | |
| 2798 | ✗ | case MUTABLE() then toAbsyn(Mutable.access(exp.exp)); | |
| 2799 | ✗ | case SHARED_LITERAL() then toAbsyn(exp.exp); | |
| 2800 | case PARTIAL_FUNCTION_APPLICATION() | ||
| 2801 | ✗ | then Absyn.Exp.PARTEVALFUNCTION(ComponentRef.toAbsyn(exp.fn), | |
| 2802 | Absyn.FunctionArgs.FUNCTIONARGS(list(toAbsyn(e) for e in exp.args), {})); | ||
| 2803 | ✗ | case FILENAME() then Absyn.Exp.STRING(exp.filename); | |
| 2804 | ✗ | case INSTANCE_NAME() then AbsynUtil.makeCall(Absyn.ComponentRef.CREF_IDENT("getInstanceName", {}), {}); | |
| 2805 | |||
| 2806 | else | ||
| 2807 | algorithm | ||
| 2808 | ✗ | Error.terminate(getInstanceName() + " got unknown expression '" + toString(exp) + "'", sourceInfo()); | |
| 2809 | ✗ | then | |
| 2810 | fail(); | ||
| 2811 | |||
| 2812 | end match; | ||
| 2813 | end toAbsyn; | ||
| 2814 | |||
| 2815 | function toDAE | ||
| 2816 | input Expression exp; | ||
| 2817 | input Boolean allowEmpty = false "Whether to allow conversion of EMPTY or not"; | ||
| 2818 | output DAE.Exp dexp; | ||
| 2819 | algorithm | ||
| 2820 | dexp := match exp | ||
| 2821 | local | ||
| 2822 | DAE.Operator daeOp; | ||
| 2823 | Boolean swap, negate; | ||
| 2824 | DAE.Exp dae1, dae2; | ||
| 2825 | Function.Function fn; | ||
| 2826 | DAE.Type dty; | ||
| 2827 | |||
| 2828 | 934927 | case INTEGER() then DAE.ICONST(exp.value); | |
| 2829 | 657928 | case REAL() then DAE.RCONST(exp.value); | |
| 2830 | 518698 | case STRING() then DAE.SCONST(exp.value); | |
| 2831 | 33636 | case BOOLEAN() then DAE.BCONST(exp.value); | |
| 2832 | 20546 | case ENUM_LITERAL() then DAE.ENUM_LITERAL(enumLiteralPath(exp), exp.index); | |
| 2833 | |||
| 2834 | case CLKCONST() | ||
| 2835 | 76 | then DAE.CLKCONST(ClockKind.toDAE(exp.clk)); | |
| 2836 | |||
| 2837 | case CREF() | ||
| 2838 | 966752 | then DAE.CREF(ComponentRef.toDAE(exp.cref), Type.toDAE(exp.ty)); | |
| 2839 | |||
| 2840 | case TYPENAME() | ||
| 2841 | ✗ | then toDAE(ExpandExp.expandTypename(exp.ty)); | |
| 2842 | |||
| 2843 | case ARRAY() | ||
| 2844 |
6/6✓ Branch 0 taken 160263 times.
✓ Branch 1 taken 37335 times.
✓ Branch 3 taken 160263 times.
✓ Branch 4 taken 37335 times.
✓ Branch 7 taken 2701 times.
✓ Branch 8 taken 34634 times.
|
397897 | then DAE.ARRAY(Type.toDAE(exp.ty), Type.isVector(exp.ty), |
| 2845 | list(toDAE(e) for e in exp.elements)); | ||
| 2846 | |||
| 2847 | 2454 | case RECORD() then toDAERecord(exp.ty, exp.path, exp.elements); | |
| 2848 | |||
| 2849 | case RANGE() | ||
| 2850 |
3/4✗ Branch 1 not taken.
✓ Branch 2 taken 1299 times.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 1287 times.
|
1311 | then DAE.RANGE( |
| 2851 | Type.toDAE(exp.ty), | ||
| 2852 | toDAE(exp.start), | ||
| 2853 | if isSome(exp.step) | ||
| 2854 | then SOME(toDAE(Util.getOption(exp.step))) | ||
| 2855 | else NONE(), | ||
| 2856 | toDAE(exp.stop)); | ||
| 2857 | |||
| 2858 |
4/4✓ Branch 0 taken 345 times.
✓ Branch 1 taken 161 times.
✓ Branch 2 taken 345 times.
✓ Branch 3 taken 161 times.
|
506 | case TUPLE() then DAE.TUPLE(list(toDAE(e) for e in exp.elements)); |
| 2859 | 73055 | case CALL() then Call.toDAE(exp.call); | |
| 2860 | |||
| 2861 | case SIZE() | ||
| 2862 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 4756 times.
✓ Branch 2 taken 4753 times.
✓ Branch 3 taken 3 times.
|
9509 | then DAE.SIZE(toDAE(exp.exp), |
| 2863 | if isSome(exp.dimIndex) | ||
| 2864 | then SOME(toDAE(Util.getOption(exp.dimIndex))) | ||
| 2865 | else NONE()); | ||
| 2866 | |||
| 2867 | // END() doesn't have a DAE representation. | ||
| 2868 | |||
| 2869 | // convert to binaries by splitting then use toDAE on result | ||
| 2870 | 35991 | case MULTARY() then toDAE(SimplifyExp.splitMultary(exp)); | |
| 2871 | |||
| 2872 | case BINARY() | ||
| 2873 | algorithm | ||
| 2874 | 709747 | (daeOp, swap, negate) := Operator.toDAE(exp.operator); | |
| 2875 | 709747 | dae1 := toDAE(exp.exp1); | |
| 2876 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 709746 times.
|
709747 | dae2 := toDAE(if negate then negate(exp.exp2) else exp.exp2); |
| 2877 |
4/4✓ Branch 0 taken 709401 times.
✓ Branch 1 taken 346 times.
✓ Branch 2 taken 709401 times.
✓ Branch 3 taken 346 times.
|
2128549 | then |
| 2878 | DAE.BINARY(if swap then dae2 else dae1, daeOp, if swap then dae1 else dae2); | ||
| 2879 | |||
| 2880 | 27443 | case UNARY() then DAE.UNARY(Operator.toDAE(exp.operator), toDAE(exp.exp)); | |
| 2881 | 3802 | case LBINARY() then DAE.LBINARY(toDAE(exp.exp1), Operator.toDAE(exp.operator), toDAE(exp.exp2)); | |
| 2882 | 920 | case LUNARY() then DAE.LUNARY(Operator.toDAE(exp.operator), toDAE(exp.exp)); | |
| 2883 | 19565 | case RELATION() then DAE.RELATION(toDAE(exp.exp1), Operator.toDAE(exp.operator), toDAE(exp.exp2), exp.index, NONE()); | |
| 2884 | 6383 | case IF() then DAE.IFEXP(toDAE(exp.condition), toDAE(exp.trueBranch), toDAE(exp.falseBranch)); | |
| 2885 | 4333 | case CAST() then DAE.CAST(Type.toDAE(exp.ty), toDAE(exp.exp)); | |
| 2886 | 195 | case BOX() then DAE.BOX(toDAE(exp.exp)); | |
| 2887 | 65 | case UNBOX() then DAE.UNBOX(toDAE(exp.exp), Type.toDAE(exp.ty)); | |
| 2888 | |||
| 2889 | case SUBSCRIPTED_EXP() | ||
| 2890 |
4/4✓ Branch 0 taken 2529 times.
✓ Branch 1 taken 2390 times.
✓ Branch 2 taken 2529 times.
✓ Branch 3 taken 2390 times.
|
4919 | then DAE.ASUB(toDAE(exp.exp), list(Subscript.toDAE(s) for s in exp.subscripts)); |
| 2891 | |||
| 2892 | case TUPLE_ELEMENT() | ||
| 2893 | 108 | then DAE.TSUB(toDAE(exp.tupleExp), exp.index, Type.toDAE(exp.ty)); | |
| 2894 | |||
| 2895 | case RECORD_ELEMENT() | ||
| 2896 | 113 | then DAE.RSUB(toDAE(exp.recordExp), -1, exp.fieldName, Type.toDAE(exp.ty)); | |
| 2897 | |||
| 2898 | case PARTIAL_FUNCTION_APPLICATION() | ||
| 2899 | algorithm | ||
| 2900 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
|
33 | fn :: _ := Function.Function.typeRefCache(exp.fn); |
| 2901 |
4/4✓ Branch 0 taken 106 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 106 times.
✓ Branch 3 taken 33 times.
|
139 | then |
| 2902 | DAE.PARTEVALFUNCTION(Function.Function.nameConsiderBuiltin(fn), | ||
| 2903 | list(toDAE(arg) for arg in exp.args), | ||
| 2904 | Type.toDAE(exp.ty), | ||
| 2905 | Type.toDAE(Type.FUNCTION(fn, NFType.FunctionType.FUNCTIONAL_VARIABLE))); | ||
| 2906 | |||
| 2907 | ✗ | case MUTABLE() then toDAE(Mutable.access(exp.exp)); | |
| 2908 | |||
| 2909 | // EMPTY expressions can be a sign of something having gone wrong, but we want to allow them in | ||
| 2910 | // some cases such as in records, so only allow them if the caller requests it. | ||
| 2911 | case EMPTY() | ||
| 2912 | guard allowEmpty | ||
| 2913 | algorithm | ||
| 2914 | ✗ | dty := Type.toDAE(exp.ty); | |
| 2915 | ✗ | then | |
| 2916 | DAE.EMPTY("", DAE.CREF_IDENT("$dummy", dty, {}), dty, Type.toString(exp.ty)); | ||
| 2917 | |||
| 2918 | 2723 | case SHARED_LITERAL() then DAE.SHARED_LITERAL(exp.index, toDAE(exp.exp)); | |
| 2919 | case FILENAME() | ||
| 2920 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
|
1 | then if Flags.getConfigBool(Flags.BUILDING_FMU) then |
| 2921 | DAE.CALL(Absyn.Path.IDENT("OpenModelica_fmuLoadResource"), | ||
| 2922 | {DAE.SCONST(exp.filename)}, DAE.callAttrBuiltinImpureString) | ||
| 2923 | else | ||
| 2924 | DAE.SCONST(exp.filename); | ||
| 2925 | case INSTANCE_NAME() then DAE.CALL(Absyn.Path.IDENT("getInstanceName"), {}, DAE.callAttrBuiltinString); | ||
| 2926 | |||
| 2927 | else | ||
| 2928 | algorithm | ||
| 2929 | ✗ | Error.terminate(getInstanceName() + " got unknown expression '" + toString(exp) + "'", sourceInfo()); | |
| 2930 | ✗ | then | |
| 2931 | fail(); | ||
| 2932 | |||
| 2933 | end match; | ||
| 2934 | end toDAE; | ||
| 2935 | |||
| 2936 | function toDAERecord | ||
| 2937 | input Type ty; | ||
| 2938 | input Absyn.Path path; | ||
| 2939 | input list<Expression> args; | ||
| 2940 | output DAE.Exp exp; | ||
| 2941 | protected | ||
| 2942 | list<String> field_names = {}; | ||
| 2943 | Expression arg; | ||
| 2944 | list<Expression> rest_args = args; | ||
| 2945 | list<DAE.Exp> dargs = {}; | ||
| 2946 | algorithm | ||
| 2947 |
2/2✓ Branch 2 taken 27115 times.
✓ Branch 3 taken 2454 times.
|
29569 | for field in Type.recordFields(Type.unbox(ty)) loop |
| 2948 |
3/5✗ Branch 0 not taken.
✓ Branch 1 taken 27115 times.
✓ Branch 3 taken 27113 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
27115 | arg :: rest_args := rest_args; |
| 2949 | |||
| 2950 | () := match field | ||
| 2951 | case Record.Field.INPUT() | ||
| 2952 | algorithm | ||
| 2953 | 27113 | field_names := field.name :: field_names; | |
| 2954 | 27113 | dargs := toDAE(arg, allowEmpty = true) :: dargs; | |
| 2955 | then | ||
| 2956 | (); | ||
| 2957 | |||
| 2958 | // TODO: Constants/parameters shouldn't be added to record expressions | ||
| 2959 | // since that causes issues with the backend, but removing them | ||
| 2960 | // currently causes even worse issues. | ||
| 2961 | case Record.Field.LOCAL() | ||
| 2962 | algorithm | ||
| 2963 | 2 | field_names := field.name :: field_names; | |
| 2964 | 2 | dargs := toDAE(arg, allowEmpty = true) :: dargs; | |
| 2965 | then | ||
| 2966 | (); | ||
| 2967 | |||
| 2968 | else (); | ||
| 2969 | end match; | ||
| 2970 | end for; | ||
| 2971 | |||
| 2972 | 2454 | field_names := listReverseInPlace(field_names); | |
| 2973 | 2454 | dargs := listReverseInPlace(dargs); | |
| 2974 | |||
| 2975 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2451 times.
|
2454 | exp := if Type.isBoxed(ty) then |
| 2976 | DAE.METARECORDCALL(path, dargs, field_names, -1, {}) | ||
| 2977 | else | ||
| 2978 | DAE.RECORD(path, dargs, field_names, Type.toDAE(ty)); | ||
| 2979 | end toDAERecord; | ||
| 2980 | |||
| 2981 | function toDAEValue | ||
| 2982 | input Expression exp; | ||
| 2983 | output Values.Value value; | ||
| 2984 | algorithm | ||
| 2985 | value := match exp | ||
| 2986 | local | ||
| 2987 | Type ty; | ||
| 2988 | |||
| 2989 | 3 | case INTEGER() then Values.INTEGER(exp.value); | |
| 2990 | 47 | case REAL() then Values.REAL(exp.value); | |
| 2991 | ✗ | case STRING() then Values.STRING(exp.value); | |
| 2992 | ✗ | case BOOLEAN() then Values.BOOL(exp.value); | |
| 2993 | case ENUM_LITERAL(ty = ty as Type.ENUMERATION()) | ||
| 2994 | ✗ | then Values.ENUM_LITERAL(AbsynUtil.suffixPath(ty.typePath, exp.name), exp.index); | |
| 2995 | ✗ | case ARRAY() then ValuesMake.makeArray(list(toDAEValue(e) for e in exp.elements)); | |
| 2996 | 1 | case RECORD() then toDAEValueRecord(exp.ty, exp.path, exp.elements); | |
| 2997 | ✗ | case FILENAME() then Values.STRING(exp.filename); | |
| 2998 | |||
| 2999 | else | ||
| 3000 | algorithm | ||
| 3001 | ✗ | Error.terminate(getInstanceName() + " got unhandled expression " + toString(exp), sourceInfo()); | |
| 3002 | ✗ | then | |
| 3003 | fail(); | ||
| 3004 | end match; | ||
| 3005 | end toDAEValue; | ||
| 3006 | |||
| 3007 | function toDAEValueRecord | ||
| 3008 | input Type ty; | ||
| 3009 | input Absyn.Path path; | ||
| 3010 | input list<Expression> args; | ||
| 3011 | output Values.Value value; | ||
| 3012 | protected | ||
| 3013 | list<String> field_names = {}; | ||
| 3014 | Expression arg; | ||
| 3015 | list<Expression> rest_args = args; | ||
| 3016 | list<Values.Value> values = {}; | ||
| 3017 | algorithm | ||
| 3018 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 time.
|
3 | for field in Type.recordFields(ty) loop |
| 3019 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | arg :: rest_args := rest_args; |
| 3020 | |||
| 3021 | () := match field | ||
| 3022 | case Record.Field.INPUT() | ||
| 3023 | algorithm | ||
| 3024 | 2 | field_names := field.name :: field_names; | |
| 3025 | 2 | values := toDAEValue(arg) :: values; | |
| 3026 | then | ||
| 3027 | (); | ||
| 3028 | |||
| 3029 | else (); | ||
| 3030 | end match; | ||
| 3031 | end for; | ||
| 3032 | |||
| 3033 | 1 | field_names := listReverseInPlace(field_names); | |
| 3034 | 1 | values := listReverseInPlace(values); | |
| 3035 | 1 | value := Values.RECORD(path, values, field_names, -1); | |
| 3036 | end toDAEValueRecord; | ||
| 3037 | |||
| 3038 | function dimensionCount | ||
| 3039 | input Expression exp; | ||
| 3040 | input Boolean isDim = false; | ||
| 3041 | output Integer dimCount; | ||
| 3042 | algorithm | ||
| 3043 | dimCount := match exp | ||
| 3044 | // Typenames expand to arrays when used as e.g. iteration ranges, but when used as a | ||
| 3045 | // dimension they work the same as an Integer and are treated as scalars. | ||
| 3046 | 53 | case TYPENAME() then if isDim then 0 else 1; | |
| 3047 | case ARRAY(ty = Type.UNKNOWN()) | ||
| 3048 | ✗ | then 1 + dimensionCount(arrayGet(exp.elements, 1)); | |
| 3049 | case MATRIX() then 2; | ||
| 3050 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 664 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 664 times.
|
664 | case SIZE() then if isNone(exp.dimIndex) then dimensionCount(exp.exp) else 0; |
| 3051 | 265374 | else Type.dimensionCount(typeOf(exp)); | |
| 3052 | end match; | ||
| 3053 | end dimensionCount; | ||
| 3054 | |||
| 3055 | function dimensions | ||
| 3056 | input Expression exp; | ||
| 3057 | output list<Dimension> dims; | ||
| 3058 | algorithm | ||
| 3059 | ✗ | dims := Type.arrayDims(typeOf(exp)); | |
| 3060 | end dimensions; | ||
| 3061 | |||
| 3062 | function map | ||
| 3063 | "Applies a function recursively (depth-first, post-order) to an expression | ||
| 3064 | and creates a new expression from the returned values. | ||
| 3065 | NOTE: For performance reasons this function does not recurse into arrays | ||
| 3066 | marked as literal." | ||
| 3067 | input Expression exp; | ||
| 3068 | input MapFunc func; | ||
| 3069 | output Expression outExp; | ||
| 3070 | |||
| 3071 | partial function MapFunc | ||
| 3072 | input output Expression e; | ||
| 3073 | end MapFunc; | ||
| 3074 | algorithm | ||
| 3075 | outExp := match exp | ||
| 3076 | local | ||
| 3077 | Expression e1, e2, e3, e4; | ||
| 3078 | |||
| 3079 | 525 | case CLKCONST() then CLKCONST(ClockKind.mapExp(exp.clk, func)); | |
| 3080 | 4381439 | case CREF() then CREF(exp.ty, ComponentRef.mapExp(exp.cref, func)); | |
| 3081 | 574203 | case ARRAY() guard not exp.literal then makeArray(exp.ty, Array.map(exp.elements, function map(func = func)), exp.literal); | |
| 3082 |
8/8✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 16 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 16 times.
✓ Branch 7 taken 8 times.
|
26 | case MATRIX() then MATRIX(list(list(map(e, func) for e in row) for row in exp.elements)); |
| 3083 | |||
| 3084 | case RANGE(step = SOME(e2)) | ||
| 3085 | algorithm | ||
| 3086 | 292 | e1 := map(exp.start, func); | |
| 3087 | 292 | e4 := map(e2, func); | |
| 3088 | 292 | e3 := map(exp.stop, func); | |
| 3089 |
5/6✓ Branch 0 taken 273 times.
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 273 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 267 times.
|
317 | then |
| 3090 | if referenceEq(exp.start, e1) and referenceEq(e2, e4) and | ||
| 3091 | referenceEq(exp.stop, e3) then exp else RANGE(exp.ty, e1, SOME(e4), e3); | ||
| 3092 | |||
| 3093 | case RANGE() | ||
| 3094 | algorithm | ||
| 3095 | 36050 | e1 := map(exp.start, func); | |
| 3096 | 36050 | e3 := map(exp.stop, func); | |
| 3097 |
4/4✓ Branch 0 taken 35810 times.
✓ Branch 1 taken 240 times.
✓ Branch 2 taken 4638 times.
✓ Branch 3 taken 31172 times.
|
36050 | then |
| 3098 | if referenceEq(exp.start, e1) and referenceEq(exp.stop, e3) | ||
| 3099 | then exp else RANGE(exp.ty, e1, NONE(), e3); | ||
| 3100 | |||
| 3101 |
4/4✓ Branch 0 taken 6415 times.
✓ Branch 1 taken 2519 times.
✓ Branch 2 taken 6415 times.
✓ Branch 3 taken 2519 times.
|
8934 | case TUPLE() then TUPLE(exp.ty, list(map(e, func) for e in exp.elements)); |
| 3102 | |||
| 3103 | case RECORD() | ||
| 3104 |
4/4✓ Branch 0 taken 406599 times.
✓ Branch 1 taken 28416 times.
✓ Branch 2 taken 406599 times.
✓ Branch 3 taken 28416 times.
|
435015 | then RECORD(exp.path, exp.ty, list(map(e, func) for e in exp.elements)); |
| 3105 | |||
| 3106 | 719210 | case CALL() then CALL(Call.mapExp(exp.call, func)); | |
| 3107 | |||
| 3108 | case SIZE(dimIndex = SOME(e2)) | ||
| 3109 | algorithm | ||
| 3110 | 15996 | e1 := map(exp.exp, func); | |
| 3111 | 15996 | e3 := map(e2, func); | |
| 3112 |
3/4✓ Branch 0 taken 108 times.
✓ Branch 1 taken 15888 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 108 times.
|
31884 | then |
| 3113 | if referenceEq(exp.exp, e1) and referenceEq(e2, e3) then exp else SIZE(e1, SOME(e3)); | ||
| 3114 | |||
| 3115 | case SIZE() | ||
| 3116 | algorithm | ||
| 3117 | 11 | e1 := map(exp.exp, func); | |
| 3118 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | then |
| 3119 | if referenceEq(exp.exp, e1) then exp else SIZE(e1, NONE()); | ||
| 3120 | |||
| 3121 | case BINARY() | ||
| 3122 | algorithm | ||
| 3123 | 2368335 | e1 := map(exp.exp1, func); | |
| 3124 | 2368335 | e2 := map(exp.exp2, func); | |
| 3125 |
4/4✓ Branch 0 taken 407342 times.
✓ Branch 1 taken 1960993 times.
✓ Branch 2 taken 399832 times.
✓ Branch 3 taken 7510 times.
|
2368335 | then |
| 3126 | if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2) | ||
| 3127 | then exp else BINARY(e1, exp.operator, e2); | ||
| 3128 | |||
| 3129 | case MULTARY() | ||
| 3130 | algorithm | ||
| 3131 | // ToDo: referenceEq ? | ||
| 3132 |
4/4✓ Branch 0 taken 421507 times.
✓ Branch 1 taken 232112 times.
✓ Branch 2 taken 421507 times.
✓ Branch 3 taken 232112 times.
|
885731 | exp.arguments := list(map(arg, func) for arg in exp.arguments); |
| 3133 |
4/4✓ Branch 0 taken 73326 times.
✓ Branch 1 taken 232112 times.
✓ Branch 2 taken 73326 times.
✓ Branch 3 taken 232112 times.
|
537550 | exp.inv_arguments := list(map(arg, func) for arg in exp.inv_arguments); |
| 3134 | then exp; | ||
| 3135 | |||
| 3136 | case UNARY() | ||
| 3137 | algorithm | ||
| 3138 | 108485 | e1 := map(exp.exp, func); | |
| 3139 |
2/2✓ Branch 0 taken 108444 times.
✓ Branch 1 taken 41 times.
|
108485 | then |
| 3140 | if referenceEq(exp.exp, e1) then exp else UNARY(exp.operator, e1); | ||
| 3141 | |||
| 3142 | case LBINARY() | ||
| 3143 | algorithm | ||
| 3144 | 19129 | e1 := map(exp.exp1, func); | |
| 3145 | 19129 | e2 := map(exp.exp2, func); | |
| 3146 |
4/4✓ Branch 0 taken 52 times.
✓ Branch 1 taken 19077 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 28 times.
|
19129 | then |
| 3147 | if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2) | ||
| 3148 | then exp else LBINARY(e1, exp.operator, e2); | ||
| 3149 | |||
| 3150 | case LUNARY() | ||
| 3151 | algorithm | ||
| 3152 | 6275 | e1 := map(exp.exp, func); | |
| 3153 |
2/2✓ Branch 0 taken 6247 times.
✓ Branch 1 taken 28 times.
|
6275 | then |
| 3154 | if referenceEq(exp.exp, e1) then exp else LUNARY(exp.operator, e1); | ||
| 3155 | |||
| 3156 | case RELATION() | ||
| 3157 | algorithm | ||
| 3158 | 198022 | e1 := map(exp.exp1, func); | |
| 3159 | 198022 | e2 := map(exp.exp2, func); | |
| 3160 |
4/4✓ Branch 0 taken 5073 times.
✓ Branch 1 taken 192949 times.
✓ Branch 2 taken 151 times.
✓ Branch 3 taken 4922 times.
|
198022 | then |
| 3161 | if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2) | ||
| 3162 | then exp else RELATION(e1, exp.operator, e2, exp.index); | ||
| 3163 | |||
| 3164 | case IF() | ||
| 3165 | algorithm | ||
| 3166 | 139884 | e1 := map(exp.condition, func); | |
| 3167 | 139884 | e2 := map(exp.trueBranch, func); | |
| 3168 | 139884 | e3 := map(exp.falseBranch, func); | |
| 3169 |
6/6✓ Branch 0 taken 4875 times.
✓ Branch 1 taken 135009 times.
✓ Branch 2 taken 4114 times.
✓ Branch 3 taken 761 times.
✓ Branch 4 taken 3873 times.
✓ Branch 5 taken 241 times.
|
139884 | then |
| 3170 | if referenceEq(exp.condition, e1) and referenceEq(exp.trueBranch, e2) and | ||
| 3171 | referenceEq(exp.falseBranch, e3) then exp else IF(exp.ty, e1, e2, e3); | ||
| 3172 | |||
| 3173 | case CAST() | ||
| 3174 | algorithm | ||
| 3175 | 45275 | e1 := map(exp.exp, func); | |
| 3176 |
2/2✓ Branch 0 taken 44886 times.
✓ Branch 1 taken 389 times.
|
45275 | then |
| 3177 | if referenceEq(exp.exp, e1) then exp else CAST(exp.ty, e1); | ||
| 3178 | |||
| 3179 | case BOX() | ||
| 3180 | algorithm | ||
| 3181 | 2219 | e1 := map(exp.exp, func); | |
| 3182 |
2/2✓ Branch 0 taken 1148 times.
✓ Branch 1 taken 1071 times.
|
2219 | then |
| 3183 | if referenceEq(exp.exp, e1) then exp else box(e1); | ||
| 3184 | |||
| 3185 | case UNBOX() | ||
| 3186 | algorithm | ||
| 3187 | 117 | e1 := map(exp.exp, func); | |
| 3188 |
1/2✓ Branch 0 taken 117 times.
✗ Branch 1 not taken.
|
117 | then |
| 3189 | if referenceEq(exp.exp, e1) then exp else unbox(e1); | ||
| 3190 | |||
| 3191 | case SUBSCRIPTED_EXP() | ||
| 3192 |
4/4✓ Branch 0 taken 190551 times.
✓ Branch 1 taken 189760 times.
✓ Branch 2 taken 190551 times.
✓ Branch 3 taken 189760 times.
|
380311 | then SUBSCRIPTED_EXP(map(exp.exp, func), |
| 3193 | list(Subscript.mapExp(s, func) for s in exp.subscripts), exp.ty, exp.split); | ||
| 3194 | |||
| 3195 | case TUPLE_ELEMENT() | ||
| 3196 | algorithm | ||
| 3197 | 210 | e1 := map(exp.tupleExp, func); | |
| 3198 |
1/2✓ Branch 0 taken 210 times.
✗ Branch 1 not taken.
|
210 | then |
| 3199 | if referenceEq(exp.tupleExp, e1) then exp else TUPLE_ELEMENT(e1, exp.index, exp.ty); | ||
| 3200 | |||
| 3201 | case RECORD_ELEMENT() | ||
| 3202 | algorithm | ||
| 3203 | 1508 | e1 := map(exp.recordExp, func); | |
| 3204 |
1/2✓ Branch 0 taken 1508 times.
✗ Branch 1 not taken.
|
1508 | then |
| 3205 | if referenceEq(exp.recordExp, e1) then exp else RECORD_ELEMENT(e1, exp.index, exp.fieldName, exp.ty); | ||
| 3206 | |||
| 3207 | case MUTABLE() | ||
| 3208 | algorithm | ||
| 3209 | 659721 | Mutable.update(exp.exp, map(Mutable.access(exp.exp), func)); | |
| 3210 | then | ||
| 3211 | exp; | ||
| 3212 | |||
| 3213 | case SHARED_LITERAL() | ||
| 3214 | algorithm | ||
| 3215 | 20 | exp.exp := map(exp.exp, func); | |
| 3216 | then | ||
| 3217 | exp; | ||
| 3218 | |||
| 3219 | case PARTIAL_FUNCTION_APPLICATION() | ||
| 3220 | algorithm | ||
| 3221 |
4/4✓ Branch 0 taken 2054 times.
✓ Branch 1 taken 509 times.
✓ Branch 2 taken 2054 times.
✓ Branch 3 taken 509 times.
|
3072 | exp.args := list(map(e, func) for e in exp.args); |
| 3222 | then | ||
| 3223 | exp; | ||
| 3224 | |||
| 3225 | else exp; | ||
| 3226 | end match; | ||
| 3227 | |||
| 3228 |
2/2✓ Branch 0 taken 11487387 times.
✓ Branch 1 taken 8300136 times.
|
19787523 | outExp := func(outExp); |
| 3229 | end map; | ||
| 3230 | |||
| 3231 | function fakeMap | ||
| 3232 | "has an interface like map but just applies the function directly. | ||
| 3233 | used for functions that map itself but need to use mapping interfaces" | ||
| 3234 | input Expression exp; | ||
| 3235 | input MapFunc func; | ||
| 3236 | output Expression outExp = func(exp); | ||
| 3237 | |||
| 3238 | partial function MapFunc | ||
| 3239 | input output Expression e; | ||
| 3240 | end MapFunc; | ||
| 3241 | end fakeMap; | ||
| 3242 | |||
| 3243 | function mapOpt | ||
| 3244 | input Option<Expression> exp; | ||
| 3245 | input MapFunc func; | ||
| 3246 | output Option<Expression> outExp; | ||
| 3247 | |||
| 3248 | partial function MapFunc | ||
| 3249 | input output Expression e; | ||
| 3250 | end MapFunc; | ||
| 3251 | protected | ||
| 3252 | Expression e; | ||
| 3253 | algorithm | ||
| 3254 | outExp := match exp | ||
| 3255 | 438 | case SOME(e) then SOME(map(e, func)); | |
| 3256 | else exp; | ||
| 3257 | end match; | ||
| 3258 | end mapOpt; | ||
| 3259 | |||
| 3260 | function mapReverse | ||
| 3261 | "Applies a function recursively (depth-first, pre-order) to an expression | ||
| 3262 | and creates a new expression from the returned values. | ||
| 3263 | NOTE: For performance reasons this function does not recurse into arrays | ||
| 3264 | marked as literal." | ||
| 3265 | input output Expression exp; | ||
| 3266 | input MapFunc func; | ||
| 3267 | |||
| 3268 | partial function MapFunc | ||
| 3269 | input output Expression e; | ||
| 3270 | end MapFunc; | ||
| 3271 | algorithm | ||
| 3272 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 17611 times.
|
17615 | exp := func(exp); |
| 3273 | exp := match exp | ||
| 3274 | local | ||
| 3275 | Expression e1, e2, e3, e4; | ||
| 3276 | |||
| 3277 | ✗ | case CLKCONST() then CLKCONST(ClockKind.mapExp(exp.clk, func)); | |
| 3278 | 8889 | case CREF() then CREF(exp.ty, ComponentRef.mapExp(exp.cref, func)); | |
| 3279 | 45 | case ARRAY() guard not exp.literal then makeArray(exp.ty, Array.map(exp.elements, function mapReverse(func = func)), exp.literal); | |
| 3280 | ✗ | case MATRIX() then MATRIX(list(list(mapReverse(e, func) for e in row) for row in exp.elements)); | |
| 3281 | |||
| 3282 | case RANGE(step = SOME(e2)) | ||
| 3283 | algorithm | ||
| 3284 | 4 | e1 := mapReverse(exp.start, func); | |
| 3285 | 4 | e4 := mapReverse(e2, func); | |
| 3286 | 4 | e3 := mapReverse(exp.stop, func); | |
| 3287 |
3/6✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 4 times.
|
4 | then |
| 3288 | if referenceEq(exp.start, e1) and referenceEq(e2, e4) and | ||
| 3289 | referenceEq(exp.stop, e3) then exp else RANGE(exp.ty, e1, SOME(e4), e3); | ||
| 3290 | |||
| 3291 | case RANGE() | ||
| 3292 | algorithm | ||
| 3293 | 338 | e1 := mapReverse(exp.start, func); | |
| 3294 | 338 | e3 := mapReverse(exp.stop, func); | |
| 3295 |
3/4✓ Branch 0 taken 338 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 63 times.
✓ Branch 3 taken 275 times.
|
338 | then |
| 3296 | if referenceEq(exp.start, e1) and referenceEq(exp.stop, e3) | ||
| 3297 | then exp else RANGE(exp.ty, e1, NONE(), e3); | ||
| 3298 | |||
| 3299 |
4/4✓ Branch 0 taken 10 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 3 times.
|
13 | case TUPLE() then TUPLE(exp.ty, list(mapReverse(e, func) for e in exp.elements)); |
| 3300 | |||
| 3301 | case RECORD() | ||
| 3302 | ✗ | then RECORD(exp.path, exp.ty, list(mapReverse(e, func) for e in exp.elements)); | |
| 3303 | |||
| 3304 | 1293 | case CALL() then CALL(Call.mapExp(exp.call, func)); | |
| 3305 | |||
| 3306 | case SIZE(dimIndex = SOME(e2)) | ||
| 3307 | algorithm | ||
| 3308 | ✗ | e1 := mapReverse(exp.exp, func); | |
| 3309 | ✗ | e3 := mapReverse(e2, func); | |
| 3310 | ✗ | then | |
| 3311 | if referenceEq(exp.exp, e1) and referenceEq(e2, e3) then exp else SIZE(e1, SOME(e3)); | ||
| 3312 | |||
| 3313 | case SIZE() | ||
| 3314 | algorithm | ||
| 3315 | ✗ | e1 := mapReverse(exp.exp, func); | |
| 3316 | ✗ | then | |
| 3317 | if referenceEq(exp.exp, e1) then exp else SIZE(e1, NONE()); | ||
| 3318 | |||
| 3319 | case BINARY() | ||
| 3320 | algorithm | ||
| 3321 | 439 | e1 := mapReverse(exp.exp1, func); | |
| 3322 | 439 | e2 := mapReverse(exp.exp2, func); | |
| 3323 |
3/4✓ Branch 0 taken 70 times.
✓ Branch 1 taken 369 times.
✓ Branch 2 taken 70 times.
✗ Branch 3 not taken.
|
439 | then |
| 3324 | if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2) | ||
| 3325 | then exp else BINARY(e1, exp.operator, e2); | ||
| 3326 | |||
| 3327 | case MULTARY() | ||
| 3328 | algorithm | ||
| 3329 | // ToDo: referenceEq ? | ||
| 3330 |
4/4✓ Branch 0 taken 5764 times.
✓ Branch 1 taken 3205 times.
✓ Branch 2 taken 5764 times.
✓ Branch 3 taken 3205 times.
|
12174 | exp.arguments := list(mapReverse(arg, func) for arg in exp.arguments); |
| 3331 |
4/4✓ Branch 0 taken 901 times.
✓ Branch 1 taken 3205 times.
✓ Branch 2 taken 901 times.
✓ Branch 3 taken 3205 times.
|
7311 | exp.inv_arguments := list(mapReverse(arg, func) for arg in exp.inv_arguments); |
| 3332 | then exp; | ||
| 3333 | |||
| 3334 | case UNARY() | ||
| 3335 | algorithm | ||
| 3336 | 56 | e1 := mapReverse(exp.exp, func); | |
| 3337 |
1/2✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
|
56 | then |
| 3338 | if referenceEq(exp.exp, e1) then exp else UNARY(exp.operator, e1); | ||
| 3339 | |||
| 3340 | case LBINARY() | ||
| 3341 | algorithm | ||
| 3342 | 79 | e1 := mapReverse(exp.exp1, func); | |
| 3343 | 79 | e2 := mapReverse(exp.exp2, func); | |
| 3344 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
79 | then |
| 3345 | if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2) | ||
| 3346 | then exp else LBINARY(e1, exp.operator, e2); | ||
| 3347 | |||
| 3348 | case LUNARY() | ||
| 3349 | algorithm | ||
| 3350 | 55 | e1 := mapReverse(exp.exp, func); | |
| 3351 |
1/2✓ Branch 0 taken 55 times.
✗ Branch 1 not taken.
|
55 | then |
| 3352 | if referenceEq(exp.exp, e1) then exp else LUNARY(exp.operator, e1); | ||
| 3353 | |||
| 3354 | case RELATION() | ||
| 3355 | algorithm | ||
| 3356 | 189 | e1 := mapReverse(exp.exp1, func); | |
| 3357 | 189 | e2 := mapReverse(exp.exp2, func); | |
| 3358 |
3/4✓ Branch 0 taken 1 time.
✓ Branch 1 taken 188 times.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
|
189 | then |
| 3359 | if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2) | ||
| 3360 | then exp else RELATION(e1, exp.operator, e2, exp.index); | ||
| 3361 | |||
| 3362 | case IF() | ||
| 3363 | algorithm | ||
| 3364 | 58 | e1 := mapReverse(exp.condition, func); | |
| 3365 | 58 | e2 := mapReverse(exp.trueBranch, func); | |
| 3366 | 58 | e3 := mapReverse(exp.falseBranch, func); | |
| 3367 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
58 | then |
| 3368 | if referenceEq(exp.condition, e1) and referenceEq(exp.trueBranch, e2) and | ||
| 3369 | referenceEq(exp.falseBranch, e3) then exp else IF(exp.ty, e1, e2, e3); | ||
| 3370 | |||
| 3371 | case CAST() | ||
| 3372 | algorithm | ||
| 3373 | 50 | e1 := mapReverse(exp.exp, func); | |
| 3374 |
1/2✓ Branch 0 taken 50 times.
✗ Branch 1 not taken.
|
50 | then |
| 3375 | if referenceEq(exp.exp, e1) then exp else CAST(exp.ty, e1); | ||
| 3376 | |||
| 3377 | case BOX() | ||
| 3378 | algorithm | ||
| 3379 | ✗ | e1 := mapReverse(exp.exp, func); | |
| 3380 | ✗ | then | |
| 3381 | if referenceEq(exp.exp, e1) then exp else box(e1); | ||
| 3382 | |||
| 3383 | case UNBOX() | ||
| 3384 | algorithm | ||
| 3385 | ✗ | e1 := mapReverse(exp.exp, func); | |
| 3386 | ✗ | then | |
| 3387 | if referenceEq(exp.exp, e1) then exp else unbox(e1); | ||
| 3388 | |||
| 3389 | case SUBSCRIPTED_EXP() | ||
| 3390 |
4/4✓ Branch 0 taken 40 times.
✓ Branch 1 taken 40 times.
✓ Branch 2 taken 40 times.
✓ Branch 3 taken 40 times.
|
80 | then SUBSCRIPTED_EXP(mapReverse(exp.exp, func), |
| 3391 | list(Subscript.mapExp(s, func) for s in exp.subscripts), exp.ty, exp.split); | ||
| 3392 | |||
| 3393 | case TUPLE_ELEMENT() | ||
| 3394 | algorithm | ||
| 3395 | ✗ | e1 := mapReverse(exp.tupleExp, func); | |
| 3396 | ✗ | then | |
| 3397 | if referenceEq(exp.tupleExp, e1) then exp else TUPLE_ELEMENT(e1, exp.index, exp.ty); | ||
| 3398 | |||
| 3399 | case RECORD_ELEMENT() | ||
| 3400 | algorithm | ||
| 3401 | ✗ | e1 := mapReverse(exp.recordExp, func); | |
| 3402 | ✗ | then | |
| 3403 | if referenceEq(exp.recordExp, e1) then exp else RECORD_ELEMENT(e1, exp.index, exp.fieldName, exp.ty); | ||
| 3404 | |||
| 3405 | case MUTABLE() | ||
| 3406 | algorithm | ||
| 3407 | ✗ | Mutable.update(exp.exp, mapReverse(Mutable.access(exp.exp), func)); | |
| 3408 | then | ||
| 3409 | exp; | ||
| 3410 | |||
| 3411 | case SHARED_LITERAL() | ||
| 3412 | algorithm | ||
| 3413 | ✗ | exp.exp := mapReverse(exp.exp, func); | |
| 3414 | then | ||
| 3415 | exp; | ||
| 3416 | |||
| 3417 | case PARTIAL_FUNCTION_APPLICATION() | ||
| 3418 | algorithm | ||
| 3419 | ✗ | exp.args := list(mapReverse(e, func) for e in exp.args); | |
| 3420 | then | ||
| 3421 | exp; | ||
| 3422 | |||
| 3423 | else exp; | ||
| 3424 | end match; | ||
| 3425 | end mapReverse; | ||
| 3426 | |||
| 3427 | function mapShallow | ||
| 3428 | "Applies a function recursively to each subexpression in an expression, | ||
| 3429 | without recursion, and creates a new expression from the returned values. | ||
| 3430 | NOTE: For performance reasons this function does not recurse into arrays | ||
| 3431 | marked as literal." | ||
| 3432 | input Expression exp; | ||
| 3433 | input MapFunc func; | ||
| 3434 | output Expression outExp; | ||
| 3435 | |||
| 3436 | partial function MapFunc | ||
| 3437 | input output Expression e; | ||
| 3438 | end MapFunc; | ||
| 3439 | algorithm | ||
| 3440 | outExp := match exp | ||
| 3441 | local | ||
| 3442 | Expression e1, e2, e3, e4; | ||
| 3443 | |||
| 3444 | 154 | case CLKCONST() then CLKCONST(ClockKind.mapExpShallow(exp.clk, func)); | |
| 3445 | 1221707 | case CREF() then CREF(exp.ty, ComponentRef.mapExpShallow(exp.cref, func)); | |
| 3446 | 84963 | case ARRAY() guard not exp.literal then makeArray(exp.ty, Array.map(exp.elements, func), exp.literal); | |
| 3447 | ✗ | case MATRIX() then MATRIX(list(list(func(e) for e in row) for row in exp.elements)); | |
| 3448 | |||
| 3449 | case RANGE(step = SOME(e2)) | ||
| 3450 | algorithm | ||
| 3451 |
2/2✓ Branch 0 taken 135 times.
✓ Branch 1 taken 6 times.
|
141 | e1 := func(exp.start); |
| 3452 |
2/2✓ Branch 0 taken 135 times.
✓ Branch 1 taken 6 times.
|
141 | e4 := func(e2); |
| 3453 |
2/2✓ Branch 0 taken 135 times.
✓ Branch 1 taken 6 times.
|
141 | e3 := func(exp.stop); |
| 3454 |
5/6✓ Branch 0 taken 129 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 129 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 121 times.
|
161 | then |
| 3455 | if referenceEq(exp.start, e1) and referenceEq(e2, e4) and | ||
| 3456 | referenceEq(exp.stop, e3) then exp else RANGE(exp.ty, e1, SOME(e4), e3); | ||
| 3457 | |||
| 3458 | case RANGE() | ||
| 3459 | algorithm | ||
| 3460 |
2/2✓ Branch 0 taken 17346 times.
✓ Branch 1 taken 10 times.
|
17356 | e1 := func(exp.start); |
| 3461 |
2/2✓ Branch 0 taken 17346 times.
✓ Branch 1 taken 10 times.
|
17356 | e3 := func(exp.stop); |
| 3462 |
4/4✓ Branch 0 taken 17331 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 2752 times.
✓ Branch 3 taken 14579 times.
|
17356 | then |
| 3463 | if referenceEq(exp.start, e1) and referenceEq(exp.stop, e3) | ||
| 3464 | then exp else RANGE(exp.ty, e1, NONE(), e3); | ||
| 3465 | |||
| 3466 |
5/6✓ Branch 0 taken 604 times.
✓ Branch 1 taken 259 times.
✓ Branch 2 taken 604 times.
✓ Branch 3 taken 259 times.
✓ Branch 4 taken 604 times.
✗ Branch 5 not taken.
|
863 | case TUPLE() then TUPLE(exp.ty, list(func(e) for e in exp.elements)); |
| 3467 | |||
| 3468 | case RECORD() | ||
| 3469 |
6/6✓ Branch 0 taken 101121 times.
✓ Branch 1 taken 6953 times.
✓ Branch 2 taken 101121 times.
✓ Branch 3 taken 6953 times.
✓ Branch 4 taken 100696 times.
✓ Branch 5 taken 425 times.
|
108074 | then RECORD(exp.path, exp.ty, list(func(e) for e in exp.elements)); |
| 3470 | |||
| 3471 | 317611 | case CALL() then CALL(Call.mapExpShallow(exp.call, func)); | |
| 3472 | |||
| 3473 | case SIZE(dimIndex = SOME(e2)) | ||
| 3474 | algorithm | ||
| 3475 |
2/2✓ Branch 0 taken 407 times.
✓ Branch 1 taken 36 times.
|
443 | e1 := func(exp.exp); |
| 3476 |
2/2✓ Branch 0 taken 407 times.
✓ Branch 1 taken 36 times.
|
443 | e3 := func(e2); |
| 3477 |
3/4✓ Branch 0 taken 9 times.
✓ Branch 1 taken 434 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
|
877 | then |
| 3478 | if referenceEq(exp.exp, e1) and referenceEq(e2, e3) then exp else SIZE(e1, SOME(e3)); | ||
| 3479 | |||
| 3480 | case SIZE() | ||
| 3481 | algorithm | ||
| 3482 |
1/2✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
|
1 | e1 := func(exp.exp); |
| 3483 |
1/2✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
|
1 | then |
| 3484 | if referenceEq(exp.exp, e1) then exp else SIZE(e1, NONE()); | ||
| 3485 | |||
| 3486 | case BINARY() | ||
| 3487 | algorithm | ||
| 3488 |
2/2✓ Branch 0 taken 985489 times.
✓ Branch 1 taken 6365 times.
|
991854 | e1 := func(exp.exp1); |
| 3489 |
2/2✓ Branch 0 taken 985489 times.
✓ Branch 1 taken 6365 times.
|
991854 | e2 := func(exp.exp2); |
| 3490 |
4/4✓ Branch 0 taken 149266 times.
✓ Branch 1 taken 842588 times.
✓ Branch 2 taken 127481 times.
✓ Branch 3 taken 21785 times.
|
991854 | then |
| 3491 | if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2) | ||
| 3492 | then exp else BINARY(e1, exp.operator, e2); | ||
| 3493 | |||
| 3494 | case MULTARY() | ||
| 3495 | algorithm | ||
| 3496 | // ToDo: referenceEq ? | ||
| 3497 |
6/6✓ Branch 0 taken 93048 times.
✓ Branch 1 taken 47877 times.
✓ Branch 2 taken 93048 times.
✓ Branch 3 taken 47877 times.
✓ Branch 4 taken 91067 times.
✓ Branch 5 taken 1981 times.
|
188802 | exp.arguments := list(func(arg) for arg in exp.arguments); |
| 3498 |
6/6✓ Branch 0 taken 10063 times.
✓ Branch 1 taken 47877 times.
✓ Branch 2 taken 10063 times.
✓ Branch 3 taken 47877 times.
✓ Branch 4 taken 9826 times.
✓ Branch 5 taken 237 times.
|
105817 | exp.inv_arguments := list(func(arg) for arg in exp.inv_arguments); |
| 3499 | then exp; | ||
| 3500 | |||
| 3501 | case UNARY() | ||
| 3502 | algorithm | ||
| 3503 |
2/2✓ Branch 0 taken 53204 times.
✓ Branch 1 taken 368 times.
|
53572 | e1 := func(exp.exp); |
| 3504 |
2/2✓ Branch 0 taken 52169 times.
✓ Branch 1 taken 1403 times.
|
53572 | then |
| 3505 | if referenceEq(exp.exp, e1) then exp else UNARY(exp.operator, e1); | ||
| 3506 | |||
| 3507 | case LBINARY() | ||
| 3508 | algorithm | ||
| 3509 |
1/2✓ Branch 0 taken 9673 times.
✗ Branch 1 not taken.
|
9673 | e1 := func(exp.exp1); |
| 3510 |
1/2✓ Branch 0 taken 9673 times.
✗ Branch 1 not taken.
|
9673 | e2 := func(exp.exp2); |
| 3511 |
4/4✓ Branch 0 taken 272 times.
✓ Branch 1 taken 9401 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 259 times.
|
9673 | then |
| 3512 | if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2) | ||
| 3513 | then exp else LBINARY(e1, exp.operator, e2); | ||
| 3514 | |||
| 3515 | case LUNARY() | ||
| 3516 | algorithm | ||
| 3517 |
1/2✓ Branch 0 taken 4022 times.
✗ Branch 1 not taken.
|
4022 | e1 := func(exp.exp); |
| 3518 |
2/2✓ Branch 0 taken 3637 times.
✓ Branch 1 taken 385 times.
|
4022 | then |
| 3519 | if referenceEq(exp.exp, e1) then exp else LUNARY(exp.operator, e1); | ||
| 3520 | |||
| 3521 | case RELATION() | ||
| 3522 | algorithm | ||
| 3523 |
2/2✓ Branch 0 taken 29213 times.
✓ Branch 1 taken 921 times.
|
30134 | e1 := func(exp.exp1); |
| 3524 |
2/2✓ Branch 0 taken 29213 times.
✓ Branch 1 taken 921 times.
|
30134 | e2 := func(exp.exp2); |
| 3525 |
4/4✓ Branch 0 taken 1110 times.
✓ Branch 1 taken 29024 times.
✓ Branch 2 taken 113 times.
✓ Branch 3 taken 997 times.
|
30134 | then |
| 3526 | if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2) | ||
| 3527 | then exp else RELATION(e1, exp.operator, e2, exp.index); | ||
| 3528 | |||
| 3529 | case IF() | ||
| 3530 | algorithm | ||
| 3531 |
2/2✓ Branch 0 taken 18403 times.
✓ Branch 1 taken 926 times.
|
19329 | e1 := func(exp.condition); |
| 3532 |
2/2✓ Branch 0 taken 18403 times.
✓ Branch 1 taken 926 times.
|
19329 | e2 := func(exp.trueBranch); |
| 3533 |
2/2✓ Branch 0 taken 18403 times.
✓ Branch 1 taken 926 times.
|
19329 | e3 := func(exp.falseBranch); |
| 3534 |
6/6✓ Branch 0 taken 551 times.
✓ Branch 1 taken 18778 times.
✓ Branch 2 taken 414 times.
✓ Branch 3 taken 137 times.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 401 times.
|
19329 | then |
| 3535 | if referenceEq(exp.condition, e1) and referenceEq(exp.trueBranch, e2) and | ||
| 3536 | referenceEq(exp.falseBranch, e3) then exp else IF(exp.ty, e1, e2, e3); | ||
| 3537 | |||
| 3538 | case CAST() | ||
| 3539 | algorithm | ||
| 3540 |
2/2✓ Branch 0 taken 15307 times.
✓ Branch 1 taken 18 times.
|
15325 | e1 := func(exp.exp); |
| 3541 |
2/2✓ Branch 0 taken 14671 times.
✓ Branch 1 taken 654 times.
|
15325 | then |
| 3542 | if referenceEq(exp.exp, e1) then exp else CAST(exp.ty, e1); | ||
| 3543 | |||
| 3544 | case BOX() | ||
| 3545 | algorithm | ||
| 3546 |
2/2✓ Branch 0 taken 522 times.
✓ Branch 1 taken 72 times.
|
594 | e1 := func(exp.exp); |
| 3547 |
2/2✓ Branch 0 taken 247 times.
✓ Branch 1 taken 347 times.
|
594 | then |
| 3548 | if referenceEq(exp.exp, e1) then exp else box(e1); | ||
| 3549 | |||
| 3550 | case UNBOX() | ||
| 3551 | algorithm | ||
| 3552 |
1/2✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
|
72 | e1 := func(exp.exp); |
| 3553 |
1/2✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
|
72 | then |
| 3554 | if referenceEq(exp.exp, e1) then exp else unbox(e1); | ||
| 3555 | |||
| 3556 | case SUBSCRIPTED_EXP() | ||
| 3557 |
6/6✓ Branch 0 taken 10418 times.
✓ Branch 1 taken 10136 times.
✓ Branch 2 taken 10418 times.
✓ Branch 3 taken 10136 times.
✓ Branch 5 taken 10125 times.
✓ Branch 6 taken 11 times.
|
20554 | then SUBSCRIPTED_EXP(func(exp.exp), |
| 3558 | list(Subscript.mapShallowExp(e, func) for e in exp.subscripts), exp.ty, exp.split); | ||
| 3559 | |||
| 3560 | case TUPLE_ELEMENT() | ||
| 3561 | algorithm | ||
| 3562 |
1/2✓ Branch 0 taken 134 times.
✗ Branch 1 not taken.
|
134 | e1 := func(exp.tupleExp); |
| 3563 |
1/2✓ Branch 0 taken 134 times.
✗ Branch 1 not taken.
|
134 | then |
| 3564 | if referenceEq(exp.tupleExp, e1) then exp else TUPLE_ELEMENT(e1, exp.index, exp.ty); | ||
| 3565 | |||
| 3566 | case RECORD_ELEMENT() | ||
| 3567 | algorithm | ||
| 3568 |
2/2✓ Branch 0 taken 119 times.
✓ Branch 1 taken 37 times.
|
156 | e1 := func(exp.recordExp); |
| 3569 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 110 times.
|
156 | then |
| 3570 | if referenceEq(exp.recordExp, e1) then exp else RECORD_ELEMENT(e1, exp.index, exp.fieldName, exp.ty); | ||
| 3571 | |||
| 3572 | case MUTABLE() | ||
| 3573 | algorithm | ||
| 3574 | ✗ | Mutable.update(exp.exp, func(Mutable.access(exp.exp))); | |
| 3575 | then | ||
| 3576 | exp; | ||
| 3577 | |||
| 3578 | case SHARED_LITERAL() | ||
| 3579 | algorithm | ||
| 3580 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | exp.exp := func(exp.exp); |
| 3581 | then | ||
| 3582 | exp; | ||
| 3583 | |||
| 3584 | case PARTIAL_FUNCTION_APPLICATION() | ||
| 3585 | algorithm | ||
| 3586 |
6/6✓ Branch 0 taken 461 times.
✓ Branch 1 taken 122 times.
✓ Branch 2 taken 461 times.
✓ Branch 3 taken 122 times.
✓ Branch 4 taken 389 times.
✓ Branch 5 taken 72 times.
|
705 | exp.args := list(func(e) for e in exp.args); |
| 3587 | then | ||
| 3588 | exp; | ||
| 3589 | |||
| 3590 | else exp; | ||
| 3591 | end match; | ||
| 3592 | end mapShallow; | ||
| 3593 | |||
| 3594 | function mapShallowOpt | ||
| 3595 | input Option<Expression> exp; | ||
| 3596 | input MapFunc func; | ||
| 3597 | output Option<Expression> outExp; | ||
| 3598 | |||
| 3599 | partial function MapFunc | ||
| 3600 | input output Expression e; | ||
| 3601 | end MapFunc; | ||
| 3602 | protected | ||
| 3603 | Expression e; | ||
| 3604 | algorithm | ||
| 3605 | outExp := match exp | ||
| 3606 |
2/2✓ Branch 0 taken 229 times.
✓ Branch 1 taken 6 times.
|
235 | case SOME(e) then SOME(func(e)); |
| 3607 | else exp; | ||
| 3608 | end match; | ||
| 3609 | end mapShallowOpt; | ||
| 3610 | |||
| 3611 | function mapArrayElements | ||
| 3612 | "Applies the given function to each scalar elements of an array." | ||
| 3613 | input Expression exp; | ||
| 3614 | input MapFunc func; | ||
| 3615 | output Expression outExp; | ||
| 3616 | |||
| 3617 | partial function MapFunc | ||
| 3618 | input output Expression e; | ||
| 3619 | end MapFunc; | ||
| 3620 | algorithm | ||
| 3621 | outExp := match exp | ||
| 3622 | case ARRAY() | ||
| 3623 | algorithm | ||
| 3624 | 8758 | exp.elements := Array.map(exp.elements, function mapArrayElements(func = func)); | |
| 3625 |
2/2✓ Branch 1 taken 4180 times.
✓ Branch 2 taken 199 times.
|
8559 | exp.literal := Array.all(exp.elements, isLiteral); |
| 3626 | then | ||
| 3627 | exp; | ||
| 3628 | |||
| 3629 |
1/2✓ Branch 0 taken 60931 times.
✗ Branch 1 not taken.
|
60931 | else func(exp); |
| 3630 | end match; | ||
| 3631 | end mapArrayElements; | ||
| 3632 | |||
| 3633 | function foldArray<ArgT> | ||
| 3634 | input array<Expression> expl; | ||
| 3635 | input FoldFunc func; | ||
| 3636 | input ArgT arg; | ||
| 3637 | output ArgT result = arg; | ||
| 3638 | |||
| 3639 | partial function FoldFunc | ||
| 3640 | input Expression exp; | ||
| 3641 | input output ArgT arg; | ||
| 3642 | end FoldFunc; | ||
| 3643 | algorithm | ||
| 3644 |
2/2✓ Branch 1 taken 797550 times.
✓ Branch 2 taken 208054 times.
|
1005604 | for e in expl loop |
| 3645 | 797550 | result := fold(e, func, result); | |
| 3646 | end for; | ||
| 3647 | end foldArray; | ||
| 3648 | |||
| 3649 | function foldList<ArgT> | ||
| 3650 | input list<Expression> expl; | ||
| 3651 | input FoldFunc func; | ||
| 3652 | input ArgT arg; | ||
| 3653 | output ArgT result = arg; | ||
| 3654 | |||
| 3655 | partial function FoldFunc | ||
| 3656 | input Expression exp; | ||
| 3657 | input output ArgT arg; | ||
| 3658 | end FoldFunc; | ||
| 3659 | algorithm | ||
| 3660 |
2/2✓ Branch 0 taken 318239 times.
✓ Branch 1 taken 154719 times.
|
472958 | for e in expl loop |
| 3661 | 318239 | result := fold(e, func, result); | |
| 3662 | end for; | ||
| 3663 | end foldList; | ||
| 3664 | |||
| 3665 | function foldOpt<ArgT> | ||
| 3666 | input Option<Expression> exp; | ||
| 3667 | input FoldFunc func; | ||
| 3668 | input ArgT arg; | ||
| 3669 | output ArgT result; | ||
| 3670 | |||
| 3671 | partial function FoldFunc | ||
| 3672 | input Expression exp; | ||
| 3673 | input output ArgT arg; | ||
| 3674 | end FoldFunc; | ||
| 3675 | algorithm | ||
| 3676 | result := match exp | ||
| 3677 | local | ||
| 3678 | Expression e; | ||
| 3679 | |||
| 3680 |
2/2✓ Branch 0 taken 62 times.
✓ Branch 1 taken 227 times.
|
289 | case SOME(e) then func(e, arg); |
| 3681 | else arg; | ||
| 3682 | end match; | ||
| 3683 | end foldOpt; | ||
| 3684 | |||
| 3685 | function fold<ArgT> | ||
| 3686 | input Expression exp; | ||
| 3687 | input FoldFunc func; | ||
| 3688 | input ArgT arg; | ||
| 3689 | output ArgT result; | ||
| 3690 | |||
| 3691 | partial function FoldFunc | ||
| 3692 | input Expression exp; | ||
| 3693 | input output ArgT arg; | ||
| 3694 | end FoldFunc; | ||
| 3695 | algorithm | ||
| 3696 | result := match exp | ||
| 3697 | local | ||
| 3698 | Expression e; | ||
| 3699 | |||
| 3700 | 179 | case CLKCONST() then ClockKind.foldExp(exp.clk, func, arg); | |
| 3701 | 1682779 | case CREF() then ComponentRef.foldExp(exp.cref, func, arg); | |
| 3702 | 208054 | case ARRAY() then foldArray(exp.elements, func, arg); | |
| 3703 | |||
| 3704 | case MATRIX() | ||
| 3705 | algorithm | ||
| 3706 | result := arg; | ||
| 3707 | ✗ | for row in exp.elements loop | |
| 3708 | ✗ | result := foldList(row, func, result); | |
| 3709 | end for; | ||
| 3710 | then | ||
| 3711 | result; | ||
| 3712 | |||
| 3713 | case RANGE() | ||
| 3714 | algorithm | ||
| 3715 | 3680 | result := fold(exp.start, func, arg); | |
| 3716 | 3680 | result := foldOpt(exp.step, func, result); | |
| 3717 | 3680 | then | |
| 3718 | fold(exp.stop, func, result); | ||
| 3719 | |||
| 3720 | 967 | case TUPLE() then foldList(exp.elements, func, arg); | |
| 3721 | 5183 | case RECORD() then foldList(exp.elements, func, arg); | |
| 3722 | 150754 | case CALL() then Call.foldExp(exp.call, func, arg); | |
| 3723 | |||
| 3724 | case SIZE(dimIndex = SOME(e)) | ||
| 3725 | algorithm | ||
| 3726 | 7929 | result := fold(exp.exp, func, arg); | |
| 3727 | 7929 | then | |
| 3728 | fold(e, func, result); | ||
| 3729 | |||
| 3730 | 5 | case SIZE() then fold(exp.exp, func, arg); | |
| 3731 | |||
| 3732 | case BINARY() | ||
| 3733 | algorithm | ||
| 3734 | 910172 | result := fold(exp.exp1, func, arg); | |
| 3735 | 910172 | then | |
| 3736 | fold(exp.exp2, func, result); | ||
| 3737 | |||
| 3738 | case MULTARY() | ||
| 3739 | algorithm | ||
| 3740 | result := arg; | ||
| 3741 |
2/2✓ Branch 0 taken 72778 times.
✓ Branch 1 taken 38868 times.
|
111646 | for argument in exp.arguments loop |
| 3742 | 72778 | result := fold(argument, func, result); | |
| 3743 | end for; | ||
| 3744 |
2/2✓ Branch 0 taken 20329 times.
✓ Branch 1 taken 38868 times.
|
59197 | for argument in exp.inv_arguments loop |
| 3745 | 20329 | result := fold(argument, func, result); | |
| 3746 | end for; | ||
| 3747 | then | ||
| 3748 | result; | ||
| 3749 | |||
| 3750 | 35083 | case UNARY() then fold(exp.exp, func, arg); | |
| 3751 | |||
| 3752 | case LBINARY() | ||
| 3753 | algorithm | ||
| 3754 | 7247 | result := fold(exp.exp1, func, arg); | |
| 3755 | 7247 | then | |
| 3756 | fold(exp.exp2, func, result); | ||
| 3757 | |||
| 3758 | 1678 | case LUNARY() then fold(exp.exp, func, arg); | |
| 3759 | |||
| 3760 | case RELATION() | ||
| 3761 | algorithm | ||
| 3762 | 33830 | result := fold(exp.exp1, func, arg); | |
| 3763 | 33830 | then | |
| 3764 | fold(exp.exp2, func, result); | ||
| 3765 | |||
| 3766 | case IF() | ||
| 3767 | algorithm | ||
| 3768 | 12417 | result := fold(exp.condition, func, arg); | |
| 3769 | 12417 | result := fold(exp.trueBranch, func, result); | |
| 3770 | 12417 | then | |
| 3771 | fold(exp.falseBranch, func, result); | ||
| 3772 | |||
| 3773 | 6730 | case CAST() then fold(exp.exp, func, arg); | |
| 3774 | 355 | case BOX() then fold(exp.exp, func, arg); | |
| 3775 | 131 | case UNBOX() then fold(exp.exp, func, arg); | |
| 3776 | |||
| 3777 | case SUBSCRIPTED_EXP() | ||
| 3778 | algorithm | ||
| 3779 | 21451 | result := fold(exp.exp, func, arg); | |
| 3780 | 21451 | then | |
| 3781 | List.fold(exp.subscripts, function Subscript.foldExp(func = func), result); | ||
| 3782 | |||
| 3783 | 144 | case TUPLE_ELEMENT() then fold(exp.tupleExp, func, arg); | |
| 3784 | 49 | case RECORD_ELEMENT() then fold(exp.recordExp, func, arg); | |
| 3785 | ✗ | case MUTABLE() then fold(Mutable.access(exp.exp), func, arg); | |
| 3786 | 4401 | case SHARED_LITERAL() then fold(exp.exp, func, arg); | |
| 3787 | 58 | case PARTIAL_FUNCTION_APPLICATION() then foldList(exp.args, func, arg); | |
| 3788 | else arg; | ||
| 3789 | end match; | ||
| 3790 | |||
| 3791 |
2/2✓ Branch 0 taken 642132 times.
✓ Branch 1 taken 5697938 times.
|
6340070 | result := func(exp, result); |
| 3792 | end fold; | ||
| 3793 | |||
| 3794 | function applyArray | ||
| 3795 | input array<Expression> expl; | ||
| 3796 | input ApplyFunc func; | ||
| 3797 | |||
| 3798 | partial function ApplyFunc | ||
| 3799 | input Expression exp; | ||
| 3800 | end ApplyFunc; | ||
| 3801 | algorithm | ||
| 3802 |
2/2✓ Branch 1 taken 240103 times.
✓ Branch 2 taken 106020 times.
|
346123 | for e in expl loop |
| 3803 | 240103 | apply(e, func); | |
| 3804 | end for; | ||
| 3805 | end applyArray; | ||
| 3806 | |||
| 3807 | function applyList | ||
| 3808 | input list<Expression> expl; | ||
| 3809 | input ApplyFunc func; | ||
| 3810 | |||
| 3811 | partial function ApplyFunc | ||
| 3812 | input Expression exp; | ||
| 3813 | end ApplyFunc; | ||
| 3814 | algorithm | ||
| 3815 |
2/2✓ Branch 0 taken 438567 times.
✓ Branch 1 taken 220372 times.
|
658939 | for e in expl loop |
| 3816 | 438567 | apply(e, func); | |
| 3817 | end for; | ||
| 3818 | end applyList; | ||
| 3819 | |||
| 3820 | function applyOpt | ||
| 3821 | input Option<Expression> exp; | ||
| 3822 | input ApplyFunc func; | ||
| 3823 | |||
| 3824 | partial function ApplyFunc | ||
| 3825 | input Expression exp; | ||
| 3826 | end ApplyFunc; | ||
| 3827 | protected | ||
| 3828 | Expression e; | ||
| 3829 | algorithm | ||
| 3830 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 7871 times.
✓ Branch 2 taken 864 times.
✓ Branch 3 taken 7007 times.
|
7871 | if isSome(exp) then |
| 3831 | 864 | SOME(e) := exp; | |
| 3832 | 864 | apply(e, func); | |
| 3833 | end if; | ||
| 3834 | end applyOpt; | ||
| 3835 | |||
| 3836 | function apply | ||
| 3837 | input Expression exp; | ||
| 3838 | input ApplyFunc func; | ||
| 3839 | |||
| 3840 | partial function ApplyFunc | ||
| 3841 | input Expression exp; | ||
| 3842 | end ApplyFunc; | ||
| 3843 | algorithm | ||
| 3844 | () := match exp | ||
| 3845 | local | ||
| 3846 | |||
| 3847 | 164 | case CLKCONST() algorithm ClockKind.applyExp(exp.clk, func); then (); | |
| 3848 | 1539213 | case CREF() algorithm ComponentRef.applyExp(exp.cref, func); then (); | |
| 3849 | 106020 | case ARRAY() algorithm applyArray(exp.elements, func); then (); | |
| 3850 | |||
| 3851 | case MATRIX() | ||
| 3852 | algorithm | ||
| 3853 |
2/2✓ Branch 0 taken 3306 times.
✓ Branch 1 taken 1266 times.
|
4572 | for row in exp.elements loop |
| 3854 | 3306 | applyList(row, func); | |
| 3855 | end for; | ||
| 3856 | then | ||
| 3857 | (); | ||
| 3858 | |||
| 3859 | case RANGE() | ||
| 3860 | algorithm | ||
| 3861 | 7108 | apply(exp.start, func); | |
| 3862 | 7108 | applyOpt(exp.step, func); | |
| 3863 | 7108 | apply(exp.stop, func); | |
| 3864 | then | ||
| 3865 | (); | ||
| 3866 | |||
| 3867 | 371 | case TUPLE() algorithm applyList(exp.elements, func); then (); | |
| 3868 | 2581 | case RECORD() algorithm applyList(exp.elements, func); then (); | |
| 3869 | 218926 | case CALL() algorithm Call.applyExp(exp.call, func); then (); | |
| 3870 | |||
| 3871 | case SIZE() | ||
| 3872 | algorithm | ||
| 3873 | 621 | apply(exp.exp, func); | |
| 3874 | 621 | applyOpt(exp.dimIndex, func); | |
| 3875 | then | ||
| 3876 | (); | ||
| 3877 | |||
| 3878 | case BINARY() | ||
| 3879 | algorithm | ||
| 3880 | 808571 | apply(exp.exp1, func); | |
| 3881 | 808571 | apply(exp.exp2, func); | |
| 3882 | then | ||
| 3883 | (); | ||
| 3884 | |||
| 3885 | case MULTARY() | ||
| 3886 | algorithm | ||
| 3887 |
2/2✓ Branch 0 taken 78647 times.
✓ Branch 1 taken 38060 times.
|
116707 | for arg in exp.arguments loop |
| 3888 | 78647 | apply(arg, func); | |
| 3889 | end for; | ||
| 3890 |
2/2✓ Branch 0 taken 11092 times.
✓ Branch 1 taken 38060 times.
|
49152 | for arg in exp.inv_arguments loop |
| 3891 | 11092 | apply(arg, func); | |
| 3892 | end for; | ||
| 3893 | then (); | ||
| 3894 | |||
| 3895 | 51497 | case UNARY() algorithm apply(exp.exp, func); then (); | |
| 3896 | |||
| 3897 | case LBINARY() | ||
| 3898 | algorithm | ||
| 3899 | 9304 | apply(exp.exp1, func); | |
| 3900 | 9304 | apply(exp.exp2, func); | |
| 3901 | then | ||
| 3902 | (); | ||
| 3903 | |||
| 3904 | 2564 | case LUNARY() algorithm apply(exp.exp, func); then (); | |
| 3905 | |||
| 3906 | case RELATION() | ||
| 3907 | algorithm | ||
| 3908 | 33102 | apply(exp.exp1, func); | |
| 3909 | 33102 | apply(exp.exp2, func); | |
| 3910 | then | ||
| 3911 | (); | ||
| 3912 | |||
| 3913 | case IF() | ||
| 3914 | algorithm | ||
| 3915 | 17326 | apply(exp.condition, func); | |
| 3916 | 17326 | apply(exp.trueBranch, func); | |
| 3917 | 17326 | apply(exp.falseBranch, func); | |
| 3918 | then | ||
| 3919 | (); | ||
| 3920 | |||
| 3921 | 12068 | case CAST() algorithm apply(exp.exp, func); then (); | |
| 3922 | 161 | case BOX() algorithm apply(exp.exp, func); then (); | |
| 3923 | 66 | case UNBOX() algorithm apply(exp.exp, func); then (); | |
| 3924 | |||
| 3925 | case SUBSCRIPTED_EXP() | ||
| 3926 | algorithm | ||
| 3927 | 57657 | apply(exp.exp, func); | |
| 3928 | |||
| 3929 |
2/2✓ Branch 0 taken 58034 times.
✓ Branch 1 taken 57657 times.
|
115691 | for s in exp.subscripts loop |
| 3930 | 58034 | Subscript.applyExp(s, func); | |
| 3931 | end for; | ||
| 3932 | then | ||
| 3933 | (); | ||
| 3934 | |||
| 3935 | 134 | case TUPLE_ELEMENT() algorithm apply(exp.tupleExp, func); then (); | |
| 3936 | 1 | case RECORD_ELEMENT() algorithm apply(exp.recordExp, func); then (); | |
| 3937 | ✗ | case MUTABLE() algorithm apply(Mutable.access(exp.exp), func); then (); | |
| 3938 | ✗ | case SHARED_LITERAL() algorithm apply(exp.exp, func); then (); | |
| 3939 | 25 | case PARTIAL_FUNCTION_APPLICATION() algorithm applyList(exp.args, func); then (); | |
| 3940 | else (); | ||
| 3941 | end match; | ||
| 3942 | |||
| 3943 |
2/2✓ Branch 0 taken 5324673 times.
✓ Branch 1 taken 301852 times.
|
5626525 | func(exp); |
| 3944 | end apply; | ||
| 3945 | |||
| 3946 | function applyArrayShallow | ||
| 3947 | input array<Expression> expl; | ||
| 3948 | input ApplyFunc func; | ||
| 3949 | |||
| 3950 | partial function ApplyFunc | ||
| 3951 | input Expression exp; | ||
| 3952 | end ApplyFunc; | ||
| 3953 | algorithm | ||
| 3954 |
2/2✓ Branch 1 taken 7476 times.
✓ Branch 2 taken 2499 times.
|
9975 | for e in expl loop |
| 3955 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7476 times.
|
7476 | func(e); |
| 3956 | end for; | ||
| 3957 | end applyArrayShallow; | ||
| 3958 | |||
| 3959 | function applyListShallow | ||
| 3960 | input list<Expression> expl; | ||
| 3961 | input ApplyFunc func; | ||
| 3962 | |||
| 3963 | partial function ApplyFunc | ||
| 3964 | input Expression exp; | ||
| 3965 | end ApplyFunc; | ||
| 3966 | algorithm | ||
| 3967 |
2/2✓ Branch 0 taken 4419 times.
✓ Branch 1 taken 2013 times.
|
6432 | for e in expl loop |
| 3968 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4419 times.
|
4419 | func(e); |
| 3969 | end for; | ||
| 3970 | end applyListShallow; | ||
| 3971 | |||
| 3972 | function applyShallow | ||
| 3973 | input Expression exp; | ||
| 3974 | input ApplyFunc func; | ||
| 3975 | |||
| 3976 | partial function ApplyFunc | ||
| 3977 | input Expression exp; | ||
| 3978 | end ApplyFunc; | ||
| 3979 | algorithm | ||
| 3980 | () := match exp | ||
| 3981 | local | ||
| 3982 | |||
| 3983 | ✗ | case CLKCONST() algorithm ClockKind.applyExpShallow(exp.clk, func); then (); | |
| 3984 | 62769 | case CREF() algorithm ComponentRef.applyExpShallow(exp.cref, func); then (); | |
| 3985 | 2499 | case ARRAY() algorithm applyArrayShallow(exp.elements, func); then (); | |
| 3986 | |||
| 3987 | case MATRIX() | ||
| 3988 | algorithm | ||
| 3989 |
2/2✓ Branch 0 taken 58 times.
✓ Branch 1 taken 23 times.
|
81 | for row in exp.elements loop |
| 3990 | 58 | applyListShallow(row, func); | |
| 3991 | end for; | ||
| 3992 | then | ||
| 3993 | (); | ||
| 3994 | |||
| 3995 | case RANGE() | ||
| 3996 | algorithm | ||
| 3997 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16427 times.
|
16427 | func(exp.start); |
| 3998 | 16427 | applyShallowOpt(exp.step, func); | |
| 3999 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16427 times.
|
16427 | func(exp.stop); |
| 4000 | then | ||
| 4001 | (); | ||
| 4002 | |||
| 4003 | 6 | case TUPLE() algorithm applyListShallow(exp.elements, func); then (); | |
| 4004 | ✗ | case RECORD() algorithm applyListShallow(exp.elements, func); then (); | |
| 4005 | 1959 | case CALL() algorithm Call.applyExpShallow(exp.call, func); then (); | |
| 4006 | |||
| 4007 | case SIZE() | ||
| 4008 | algorithm | ||
| 4009 | ✗ | func(exp.exp); | |
| 4010 | ✗ | applyShallowOpt(exp.dimIndex, func); | |
| 4011 | then | ||
| 4012 | (); | ||
| 4013 | |||
| 4014 | case BINARY() | ||
| 4015 | algorithm | ||
| 4016 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11892 times.
|
11892 | func(exp.exp1); |
| 4017 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11892 times.
|
11892 | func(exp.exp2); |
| 4018 | then | ||
| 4019 | (); | ||
| 4020 | |||
| 4021 | case MULTARY() | ||
| 4022 | algorithm | ||
| 4023 | ✗ | for arg in exp.arguments loop | |
| 4024 | ✗ | func(arg); | |
| 4025 | end for; | ||
| 4026 | ✗ | for arg in exp.inv_arguments loop | |
| 4027 | ✗ | func(arg); | |
| 4028 | end for; | ||
| 4029 | then (); | ||
| 4030 | |||
| 4031 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
|
51 | case UNARY() algorithm func(exp.exp); then (); |
| 4032 | |||
| 4033 | case LBINARY() | ||
| 4034 | algorithm | ||
| 4035 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4894 times.
|
4894 | func(exp.exp1); |
| 4036 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4894 times.
|
4894 | func(exp.exp2); |
| 4037 | then | ||
| 4038 | (); | ||
| 4039 | |||
| 4040 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2484 times.
|
2484 | case LUNARY() algorithm func(exp.exp); then (); |
| 4041 | |||
| 4042 | case RELATION() | ||
| 4043 | algorithm | ||
| 4044 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4808 times.
|
4808 | func(exp.exp1); |
| 4045 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4808 times.
|
4808 | func(exp.exp2); |
| 4046 | then | ||
| 4047 | (); | ||
| 4048 | |||
| 4049 | case IF() | ||
| 4050 | algorithm | ||
| 4051 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3271 times.
|
3271 | func(exp.condition); |
| 4052 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3271 times.
|
3271 | func(exp.trueBranch); |
| 4053 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3271 times.
|
3271 | func(exp.falseBranch); |
| 4054 | then | ||
| 4055 | (); | ||
| 4056 | |||
| 4057 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 114 times.
|
114 | case CAST() algorithm func(exp.exp); then (); |
| 4058 | ✗ | case BOX() algorithm func(exp.exp); then (); | |
| 4059 | ✗ | case UNBOX() algorithm func(exp.exp); then (); | |
| 4060 | |||
| 4061 | case SUBSCRIPTED_EXP() | ||
| 4062 | algorithm | ||
| 4063 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11188 times.
|
11188 | func(exp.exp); |
| 4064 | |||
| 4065 |
2/2✓ Branch 0 taken 13738 times.
✓ Branch 1 taken 11188 times.
|
24926 | for s in exp.subscripts loop |
| 4066 | 13738 | Subscript.applyExpShallow(s, func); | |
| 4067 | end for; | ||
| 4068 | then | ||
| 4069 | (); | ||
| 4070 | |||
| 4071 | ✗ | case TUPLE_ELEMENT() algorithm func(exp.tupleExp); then (); | |
| 4072 | ✗ | case RECORD_ELEMENT() algorithm func(exp.recordExp); then (); | |
| 4073 | ✗ | case MUTABLE() algorithm func(Mutable.access(exp.exp)); then (); | |
| 4074 | ✗ | case SHARED_LITERAL() algorithm func(exp.exp); then (); | |
| 4075 | ✗ | case PARTIAL_FUNCTION_APPLICATION() algorithm applyListShallow(exp.args, func); then (); | |
| 4076 | else (); | ||
| 4077 | end match; | ||
| 4078 | end applyShallow; | ||
| 4079 | |||
| 4080 | function applyShallowOpt | ||
| 4081 | input Option<Expression> exp; | ||
| 4082 | input ApplyFunc func; | ||
| 4083 | |||
| 4084 | partial function ApplyFunc | ||
| 4085 | input Expression exp; | ||
| 4086 | end ApplyFunc; | ||
| 4087 | protected | ||
| 4088 | Expression e; | ||
| 4089 | algorithm | ||
| 4090 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 16427 times.
✓ Branch 2 taken 84 times.
✓ Branch 3 taken 16343 times.
|
16427 | if isSome(exp) then |
| 4091 | 84 | SOME(e) := exp; | |
| 4092 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
|
84 | func(e); |
| 4093 | end if; | ||
| 4094 | end applyShallowOpt; | ||
| 4095 | |||
| 4096 | function mapFold<ArgT> | ||
| 4097 | input Expression exp; | ||
| 4098 | input MapFunc func; | ||
| 4099 | output Expression outExp; | ||
| 4100 | input output ArgT arg; | ||
| 4101 | |||
| 4102 | partial function MapFunc | ||
| 4103 | input output Expression e; | ||
| 4104 | input output ArgT arg; | ||
| 4105 | end MapFunc; | ||
| 4106 | algorithm | ||
| 4107 | outExp := match exp | ||
| 4108 | local | ||
| 4109 | Expression e1, e2, e3, e4; | ||
| 4110 | ComponentRef cr; | ||
| 4111 | list<Expression> expl; | ||
| 4112 | Call call; | ||
| 4113 | list<Subscript> subs; | ||
| 4114 | ClockKind ck; | ||
| 4115 | list<list<Expression>> mat; | ||
| 4116 | array<Expression> arr; | ||
| 4117 | |||
| 4118 | case CLKCONST() | ||
| 4119 | algorithm | ||
| 4120 | ✗ | (ck, arg) := ClockKind.mapFoldExp(exp.clk, func, arg); | |
| 4121 | ✗ | then | |
| 4122 | if referenceEq(exp.clk, ck) then exp else CLKCONST(ck); | ||
| 4123 | |||
| 4124 | case CREF() | ||
| 4125 | algorithm | ||
| 4126 | 1998 | (cr, arg) := ComponentRef.mapFoldExp(exp.cref, func, arg); | |
| 4127 |
1/2✓ Branch 0 taken 1998 times.
✗ Branch 1 not taken.
|
1998 | then |
| 4128 | if referenceEq(exp.cref, cr) then exp else CREF(exp.ty, cr); | ||
| 4129 | |||
| 4130 | case ARRAY() | ||
| 4131 | algorithm | ||
| 4132 | 19 | (arr, arg) := Array.mapFold(exp.elements, function mapFold(func = func), arg); | |
| 4133 | 19 | then | |
| 4134 | makeArray(exp.ty, arr, exp.literal); | ||
| 4135 | |||
| 4136 | case MATRIX() | ||
| 4137 | algorithm | ||
| 4138 | ✗ | (mat, arg) := List.mapFoldList(exp.elements, function mapFold(func = func), arg); | |
| 4139 | ✗ | then | |
| 4140 | MATRIX(mat); | ||
| 4141 | |||
| 4142 | case RANGE(step = SOME(e2)) | ||
| 4143 | algorithm | ||
| 4144 | ✗ | (e1, arg) := mapFold(exp.start, func, arg); | |
| 4145 | ✗ | (e4, arg) := mapFold(e2, func, arg); | |
| 4146 | ✗ | (e3, arg) := mapFold(exp.stop, func, arg); | |
| 4147 | ✗ | then | |
| 4148 | if referenceEq(exp.start, e1) and referenceEq(e2, e4) and | ||
| 4149 | referenceEq(exp.stop, e3) then exp else RANGE(exp.ty, e1, SOME(e4), e3); | ||
| 4150 | |||
| 4151 | case RANGE() | ||
| 4152 | algorithm | ||
| 4153 | ✗ | (e1, arg) := mapFold(exp.start, func, arg); | |
| 4154 | ✗ | (e3, arg) := mapFold(exp.stop, func, arg); | |
| 4155 | ✗ | then | |
| 4156 | if referenceEq(exp.start, e1) and referenceEq(exp.stop, e3) | ||
| 4157 | then exp else RANGE(exp.ty, e1, NONE(), e3); | ||
| 4158 | |||
| 4159 | case TUPLE() | ||
| 4160 | algorithm | ||
| 4161 | ✗ | (expl, arg) := List.map1Fold(exp.elements, mapFold, func, arg); | |
| 4162 | ✗ | then | |
| 4163 | TUPLE(exp.ty, expl); | ||
| 4164 | |||
| 4165 | case RECORD() | ||
| 4166 | algorithm | ||
| 4167 | 18 | (expl, arg) := List.map1Fold(exp.elements, mapFold, func, arg); | |
| 4168 | 18 | then | |
| 4169 | RECORD(exp.path, exp.ty, expl); | ||
| 4170 | |||
| 4171 | case CALL() | ||
| 4172 | algorithm | ||
| 4173 | 28 | (call, arg) := Call.mapFoldExp(exp.call, func, arg); | |
| 4174 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | then |
| 4175 | if referenceEq(exp.call, call) then exp else CALL(call); | ||
| 4176 | |||
| 4177 | case SIZE(dimIndex = SOME(e2)) | ||
| 4178 | algorithm | ||
| 4179 | ✗ | (e1, arg) := mapFold(exp.exp, func, arg); | |
| 4180 | ✗ | (e3, arg) := mapFold(e2, func, arg); | |
| 4181 | ✗ | then | |
| 4182 | if referenceEq(exp.exp, e1) and referenceEq(e2, e3) then exp else SIZE(e1, SOME(e3)); | ||
| 4183 | |||
| 4184 | case SIZE() | ||
| 4185 | algorithm | ||
| 4186 | ✗ | (e1, arg) := mapFold(exp.exp, func, arg); | |
| 4187 | ✗ | then | |
| 4188 | if referenceEq(exp.exp, e1) then exp else SIZE(e1, NONE()); | ||
| 4189 | |||
| 4190 | case BINARY() | ||
| 4191 | algorithm | ||
| 4192 | 8 | (e1, arg) := mapFold(exp.exp1, func, arg); | |
| 4193 | 8 | (e2, arg) := mapFold(exp.exp2, func, arg); | |
| 4194 |
3/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
8 | then |
| 4195 | if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2) | ||
| 4196 | then exp else BINARY(e1, exp.operator, e2); | ||
| 4197 | |||
| 4198 | case MULTARY() | ||
| 4199 | algorithm | ||
| 4200 | // ToDo: referenceEq ? | ||
| 4201 | expl := {}; | ||
| 4202 |
2/2✓ Branch 0 taken 282 times.
✓ Branch 1 taken 143 times.
|
425 | for argument in exp.arguments loop |
| 4203 | 282 | (e1, arg) := mapFold(argument, func, arg); | |
| 4204 | expl := e1 :: expl; | ||
| 4205 | end for; | ||
| 4206 | 143 | exp.arguments := listReverse(expl); | |
| 4207 | expl := {}; | ||
| 4208 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 143 times.
|
147 | for argument in exp.inv_arguments loop |
| 4209 | 4 | (e1, arg) := mapFold(argument, func, arg); | |
| 4210 | expl := e1 :: expl; | ||
| 4211 | end for; | ||
| 4212 | 143 | exp.inv_arguments := listReverse(expl); | |
| 4213 | then exp; | ||
| 4214 | |||
| 4215 | case UNARY() | ||
| 4216 | algorithm | ||
| 4217 | 230 | (e1, arg) := mapFold(exp.exp, func, arg); | |
| 4218 |
1/2✓ Branch 0 taken 230 times.
✗ Branch 1 not taken.
|
230 | then |
| 4219 | if referenceEq(exp.exp, e1) then exp else UNARY(exp.operator, e1); | ||
| 4220 | |||
| 4221 | case LBINARY() | ||
| 4222 | algorithm | ||
| 4223 | 25 | (e1, arg) := mapFold(exp.exp1, func, arg); | |
| 4224 | 25 | (e2, arg) := mapFold(exp.exp2, func, arg); | |
| 4225 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
25 | then |
| 4226 | if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2) | ||
| 4227 | then exp else LBINARY(e1, exp.operator, e2); | ||
| 4228 | |||
| 4229 | case LUNARY() | ||
| 4230 | algorithm | ||
| 4231 | 21 | (e1, arg) := mapFold(exp.exp, func, arg); | |
| 4232 |
1/2✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
|
21 | then |
| 4233 | if referenceEq(exp.exp, e1) then exp else LUNARY(exp.operator, e1); | ||
| 4234 | |||
| 4235 | case RELATION() | ||
| 4236 | algorithm | ||
| 4237 | 114 | (e1, arg) := mapFold(exp.exp1, func, arg); | |
| 4238 | 114 | (e2, arg) := mapFold(exp.exp2, func, arg); | |
| 4239 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
114 | then |
| 4240 | if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2) | ||
| 4241 | then exp else RELATION(e1, exp.operator, e2, exp.index); | ||
| 4242 | |||
| 4243 | case IF() | ||
| 4244 | algorithm | ||
| 4245 | ✗ | (e1, arg) := mapFold(exp.condition, func, arg); | |
| 4246 | ✗ | (e2, arg) := mapFold(exp.trueBranch, func, arg); | |
| 4247 | ✗ | (e3, arg) := mapFold(exp.falseBranch, func, arg); | |
| 4248 | ✗ | then | |
| 4249 | if referenceEq(exp.condition, e1) and referenceEq(exp.trueBranch, e2) and | ||
| 4250 | referenceEq(exp.falseBranch, e3) then exp else IF(exp.ty, e1, e2, e3); | ||
| 4251 | |||
| 4252 | case CAST() | ||
| 4253 | algorithm | ||
| 4254 | 11 | (e1, arg) := mapFold(exp.exp, func, arg); | |
| 4255 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | then |
| 4256 | if referenceEq(exp.exp, e1) then exp else CAST(exp.ty, e1); | ||
| 4257 | |||
| 4258 | case BOX() | ||
| 4259 | algorithm | ||
| 4260 | ✗ | (e1, arg) := mapFold(exp.exp, func, arg); | |
| 4261 | ✗ | then | |
| 4262 | if referenceEq(exp.exp, e1) then exp else box(e1); | ||
| 4263 | |||
| 4264 | case UNBOX() | ||
| 4265 | algorithm | ||
| 4266 | ✗ | (e1, arg) := mapFold(exp.exp, func, arg); | |
| 4267 | ✗ | then | |
| 4268 | if referenceEq(exp.exp, e1) then exp else unbox(e1); | ||
| 4269 | |||
| 4270 | case SUBSCRIPTED_EXP() | ||
| 4271 | algorithm | ||
| 4272 | 17 | (e1, arg) := mapFold(exp.exp, func, arg); | |
| 4273 | 17 | (subs, arg) := List.mapFold(exp.subscripts, function Subscript.mapFoldExp(func = func), arg); | |
| 4274 | 17 | then | |
| 4275 | SUBSCRIPTED_EXP(e1, subs, exp.ty, exp.split); | ||
| 4276 | |||
| 4277 | case TUPLE_ELEMENT() | ||
| 4278 | algorithm | ||
| 4279 | ✗ | (e1, arg) := mapFold(exp.tupleExp, func, arg); | |
| 4280 | ✗ | then | |
| 4281 | if referenceEq(exp.tupleExp, e1) then exp else TUPLE_ELEMENT(e1, exp.index, exp.ty); | ||
| 4282 | |||
| 4283 | case RECORD_ELEMENT() | ||
| 4284 | algorithm | ||
| 4285 | ✗ | (e1, arg) := mapFold(exp.recordExp, func, arg); | |
| 4286 | ✗ | then | |
| 4287 | if referenceEq(exp.recordExp, e1) then exp else RECORD_ELEMENT(e1, exp.index, exp.fieldName, exp.ty); | ||
| 4288 | |||
| 4289 | case MUTABLE() | ||
| 4290 | algorithm | ||
| 4291 | ✗ | (e1, arg) := mapFold(Mutable.access(exp.exp), func, arg); | |
| 4292 | ✗ | Mutable.update(exp.exp, e1); | |
| 4293 | then | ||
| 4294 | exp; | ||
| 4295 | |||
| 4296 | case SHARED_LITERAL() | ||
| 4297 | algorithm | ||
| 4298 | ✗ | (e1, arg) := mapFold(exp.exp, func, arg); | |
| 4299 | ✗ | exp.exp := e1; | |
| 4300 | then | ||
| 4301 | exp; | ||
| 4302 | |||
| 4303 | case PARTIAL_FUNCTION_APPLICATION() | ||
| 4304 | algorithm | ||
| 4305 | ✗ | (expl, arg) := List.map1Fold(exp.args, mapFold, func, arg); | |
| 4306 | ✗ | exp.args := expl; | |
| 4307 | then | ||
| 4308 | exp; | ||
| 4309 | |||
| 4310 | else exp; | ||
| 4311 | end match; | ||
| 4312 | |||
| 4313 |
2/2✓ Branch 0 taken 3409 times.
✓ Branch 1 taken 147 times.
|
3556 | (outExp, arg) := func(outExp, arg); |
| 4314 | end mapFold; | ||
| 4315 | |||
| 4316 | function mapFoldOpt<ArgT> | ||
| 4317 | input Option<Expression> exp; | ||
| 4318 | input MapFunc func; | ||
| 4319 | output Option<Expression> outExp; | ||
| 4320 | input output ArgT arg; | ||
| 4321 | |||
| 4322 | partial function MapFunc | ||
| 4323 | input output Expression e; | ||
| 4324 | input output ArgT arg; | ||
| 4325 | end MapFunc; | ||
| 4326 | protected | ||
| 4327 | Expression e; | ||
| 4328 | algorithm | ||
| 4329 | outExp := match exp | ||
| 4330 | case SOME(e) | ||
| 4331 | algorithm | ||
| 4332 | ✗ | (e, arg) := mapFold(e, func, arg); | |
| 4333 | then | ||
| 4334 | SOME(e); | ||
| 4335 | |||
| 4336 | else exp; | ||
| 4337 | end match; | ||
| 4338 | end mapFoldOpt; | ||
| 4339 | |||
| 4340 | function mapFoldShallow<ArgT> | ||
| 4341 | input Expression exp; | ||
| 4342 | input MapFunc func; | ||
| 4343 | output Expression outExp; | ||
| 4344 | input output ArgT arg; | ||
| 4345 | |||
| 4346 | partial function MapFunc | ||
| 4347 | input output Expression e; | ||
| 4348 | input output ArgT arg; | ||
| 4349 | end MapFunc; | ||
| 4350 | algorithm | ||
| 4351 | outExp := match exp | ||
| 4352 | local | ||
| 4353 | Expression e1, e2, e3; | ||
| 4354 | Option<Expression> oe; | ||
| 4355 | ComponentRef cr; | ||
| 4356 | list<Expression> expl; | ||
| 4357 | Call call; | ||
| 4358 | list<Subscript> subs; | ||
| 4359 | ClockKind ck; | ||
| 4360 | list<list<Expression>> mat; | ||
| 4361 | array<Expression> arr; | ||
| 4362 | |||
| 4363 | case CLKCONST() | ||
| 4364 | algorithm | ||
| 4365 | 87 | (ck, arg) := ClockKind.mapFoldExpShallow(exp.clk, func, arg); | |
| 4366 |
2/2✓ Branch 0 taken 32 times.
✓ Branch 1 taken 55 times.
|
87 | then |
| 4367 | if referenceEq(exp.clk, ck) then exp else CLKCONST(ck); | ||
| 4368 | |||
| 4369 | case CREF() | ||
| 4370 | algorithm | ||
| 4371 | 1181884 | (cr, arg) := ComponentRef.mapFoldExpShallow(exp.cref, func, arg); | |
| 4372 |
2/2✓ Branch 0 taken 1181881 times.
✓ Branch 1 taken 3 times.
|
1181884 | then |
| 4373 | if referenceEq(exp.cref, cr) then exp else CREF(exp.ty, cr); | ||
| 4374 | |||
| 4375 | case ARRAY() | ||
| 4376 | algorithm | ||
| 4377 | 55553 | (arr, arg) := Array.mapFold(exp.elements, func, arg); | |
| 4378 | 55553 | then | |
| 4379 | makeArray(exp.ty, arr, exp.literal); | ||
| 4380 | |||
| 4381 | case MATRIX() | ||
| 4382 | algorithm | ||
| 4383 | ✗ | (mat, arg) := List.mapFoldList(exp.elements, func, arg); | |
| 4384 | ✗ | then | |
| 4385 | MATRIX(mat); | ||
| 4386 | |||
| 4387 | case RANGE(step = oe) | ||
| 4388 | algorithm | ||
| 4389 |
1/2✓ Branch 0 taken 3985 times.
✗ Branch 1 not taken.
|
3985 | (e1, arg) := func(exp.start, arg); |
| 4390 | 3985 | (oe, arg) := mapFoldOptShallow(exp.step, func, arg); | |
| 4391 |
1/2✓ Branch 0 taken 3985 times.
✗ Branch 1 not taken.
|
3985 | (e3, arg) := func(exp.stop, arg); |
| 4392 |
5/6✓ Branch 0 taken 3968 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 3968 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1026 times.
✓ Branch 5 taken 2942 times.
|
3985 | then |
| 4393 | if referenceEq(e1, exp.start) and referenceEq(oe, exp.step) and referenceEq(e3, exp.stop) then | ||
| 4394 | exp else RANGE(exp.ty, e1, oe, e3); | ||
| 4395 | |||
| 4396 | case TUPLE() | ||
| 4397 | algorithm | ||
| 4398 | 817 | (expl, arg) := List.mapFold(exp.elements, func, arg); | |
| 4399 | 817 | then | |
| 4400 | TUPLE(exp.ty, expl); | ||
| 4401 | |||
| 4402 | case RECORD() | ||
| 4403 | algorithm | ||
| 4404 | 6542 | (expl, arg) := List.mapFold(exp.elements, func, arg); | |
| 4405 | 6542 | then | |
| 4406 | RECORD(exp.path, exp.ty, expl); | ||
| 4407 | |||
| 4408 | case CALL() | ||
| 4409 | algorithm | ||
| 4410 | 167306 | (call, arg) := Call.mapFoldExpShallow(exp.call, func, arg); | |
| 4411 |
1/2✓ Branch 0 taken 167306 times.
✗ Branch 1 not taken.
|
167306 | then |
| 4412 | if referenceEq(exp.call, call) then exp else CALL(call); | ||
| 4413 | |||
| 4414 | case SIZE() | ||
| 4415 | algorithm | ||
| 4416 |
1/2✓ Branch 0 taken 1944 times.
✗ Branch 1 not taken.
|
1944 | (e1, arg) := func(exp.exp, arg); |
| 4417 | 1944 | (oe, arg) := mapFoldOptShallow(exp.dimIndex, func, arg); | |
| 4418 |
3/4✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1943 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
|
1944 | then |
| 4419 | if referenceEq(exp.exp, e1) and referenceEq(exp.dimIndex, oe) then | ||
| 4420 | exp else SIZE(e1, oe); | ||
| 4421 | |||
| 4422 | case BINARY() | ||
| 4423 | algorithm | ||
| 4424 |
1/2✓ Branch 0 taken 708444 times.
✗ Branch 1 not taken.
|
708444 | (e1, arg) := func(exp.exp1, arg); |
| 4425 |
1/2✓ Branch 0 taken 708442 times.
✗ Branch 1 not taken.
|
708442 | (e2, arg) := func(exp.exp2, arg); |
| 4426 |
4/4✓ Branch 0 taken 146743 times.
✓ Branch 1 taken 561699 times.
✓ Branch 2 taken 136258 times.
✓ Branch 3 taken 10485 times.
|
708442 | then |
| 4427 | if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2) | ||
| 4428 | then exp else BINARY(e1, exp.operator, e2); | ||
| 4429 | |||
| 4430 | case MULTARY() | ||
| 4431 | algorithm | ||
| 4432 | // ToDo: referenceEq ? | ||
| 4433 | expl := {}; | ||
| 4434 |
2/2✓ Branch 0 taken 37432 times.
✓ Branch 1 taken 15785 times.
|
53217 | for argument in exp.arguments loop |
| 4435 |
1/2✓ Branch 0 taken 37432 times.
✗ Branch 1 not taken.
|
37432 | (e1, arg) := func(argument, arg); |
| 4436 | expl := e1 :: expl; | ||
| 4437 | end for; | ||
| 4438 | 15785 | exp.arguments := listReverse(expl); | |
| 4439 | expl := {}; | ||
| 4440 |
2/2✓ Branch 0 taken 158 times.
✓ Branch 1 taken 15785 times.
|
15943 | for argument in exp.inv_arguments loop |
| 4441 |
1/2✓ Branch 0 taken 158 times.
✗ Branch 1 not taken.
|
158 | (e1, arg) := func(argument, arg); |
| 4442 | expl := e1 :: expl; | ||
| 4443 | end for; | ||
| 4444 | 15785 | exp.inv_arguments := listReverse(expl); | |
| 4445 | then exp; | ||
| 4446 | |||
| 4447 | case UNARY() | ||
| 4448 | algorithm | ||
| 4449 |
1/2✓ Branch 0 taken 48098 times.
✗ Branch 1 not taken.
|
48098 | (e1, arg) := func(exp.exp, arg); |
| 4450 |
2/2✓ Branch 0 taken 47965 times.
✓ Branch 1 taken 133 times.
|
48098 | then |
| 4451 | if referenceEq(exp.exp, e1) then exp else UNARY(exp.operator, e1); | ||
| 4452 | |||
| 4453 | case LBINARY() | ||
| 4454 | algorithm | ||
| 4455 |
1/2✓ Branch 0 taken 5829 times.
✗ Branch 1 not taken.
|
5829 | (e1, arg) := func(exp.exp1, arg); |
| 4456 |
1/2✓ Branch 0 taken 5829 times.
✗ Branch 1 not taken.
|
5829 | (e2, arg) := func(exp.exp2, arg); |
| 4457 |
4/4✓ Branch 0 taken 514 times.
✓ Branch 1 taken 5315 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 510 times.
|
5829 | then |
| 4458 | if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2) | ||
| 4459 | then exp else LBINARY(e1, exp.operator, e2); | ||
| 4460 | |||
| 4461 | case LUNARY() | ||
| 4462 | algorithm | ||
| 4463 |
1/2✓ Branch 0 taken 1725 times.
✗ Branch 1 not taken.
|
1725 | (e1, arg) := func(exp.exp, arg); |
| 4464 |
2/2✓ Branch 0 taken 1510 times.
✓ Branch 1 taken 215 times.
|
1725 | then |
| 4465 | if referenceEq(exp.exp, e1) then exp else LUNARY(exp.operator, e1); | ||
| 4466 | |||
| 4467 | case RELATION() | ||
| 4468 | algorithm | ||
| 4469 |
1/2✓ Branch 0 taken 24235 times.
✗ Branch 1 not taken.
|
24235 | (e1, arg) := func(exp.exp1, arg); |
| 4470 |
1/2✓ Branch 0 taken 24235 times.
✗ Branch 1 not taken.
|
24235 | (e2, arg) := func(exp.exp2, arg); |
| 4471 |
4/4✓ Branch 0 taken 2622 times.
✓ Branch 1 taken 21613 times.
✓ Branch 2 taken 94 times.
✓ Branch 3 taken 2528 times.
|
24235 | then |
| 4472 | if referenceEq(exp.exp1, e1) and referenceEq(exp.exp2, e2) | ||
| 4473 | then exp else RELATION(e1, exp.operator, e2, exp.index); | ||
| 4474 | |||
| 4475 | case IF() | ||
| 4476 | algorithm | ||
| 4477 |
1/2✓ Branch 0 taken 2807 times.
✗ Branch 1 not taken.
|
2807 | (e1, arg) := func(exp.condition, arg); |
| 4478 |
1/2✓ Branch 0 taken 2807 times.
✗ Branch 1 not taken.
|
2807 | (e2, arg) := func(exp.trueBranch, arg); |
| 4479 |
1/2✓ Branch 0 taken 2807 times.
✗ Branch 1 not taken.
|
2807 | (e3, arg) := func(exp.falseBranch, arg); |
| 4480 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 2807 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
2807 | then |
| 4481 | if referenceEq(exp.condition, e1) and referenceEq(exp.trueBranch, e2) and | ||
| 4482 | referenceEq(exp.falseBranch, e3) then exp else IF(exp.ty, e1, e2, e3); | ||
| 4483 | |||
| 4484 | case CAST() | ||
| 4485 | algorithm | ||
| 4486 |
1/2✓ Branch 0 taken 9517 times.
✗ Branch 1 not taken.
|
9517 | (e1, arg) := func(exp.exp, arg); |
| 4487 |
2/2✓ Branch 0 taken 9107 times.
✓ Branch 1 taken 410 times.
|
9517 | then |
| 4488 | if referenceEq(exp.exp, e1) then exp else CAST(exp.ty, e1); | ||
| 4489 | |||
| 4490 | case BOX() | ||
| 4491 | algorithm | ||
| 4492 |
1/2✓ Branch 0 taken 137 times.
✗ Branch 1 not taken.
|
137 | (e1, arg) := func(exp.exp, arg); |
| 4493 |
1/2✓ Branch 0 taken 137 times.
✗ Branch 1 not taken.
|
137 | then |
| 4494 | if referenceEq(exp.exp, e1) then exp else box(e1); | ||
| 4495 | |||
| 4496 | case UNBOX() | ||
| 4497 | algorithm | ||
| 4498 |
1/2✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
|
65 | (e1, arg) := func(exp.exp, arg); |
| 4499 |
1/2✓ Branch 0 taken 65 times.
✗ Branch 1 not taken.
|
65 | then |
| 4500 | if referenceEq(exp.exp, e1) then exp else unbox(e1); | ||
| 4501 | |||
| 4502 | case SUBSCRIPTED_EXP() | ||
| 4503 | algorithm | ||
| 4504 |
1/2✓ Branch 0 taken 4787 times.
✗ Branch 1 not taken.
|
4787 | (e1, arg) := func(exp.exp, arg); |
| 4505 | 4787 | (subs, arg) := List.mapFold(exp.subscripts, function Subscript.mapFoldExpShallow(func = func), arg); | |
| 4506 | 4787 | then | |
| 4507 | SUBSCRIPTED_EXP(e1, subs, exp.ty, exp.split); | ||
| 4508 | |||
| 4509 | case TUPLE_ELEMENT() | ||
| 4510 | algorithm | ||
| 4511 |
1/2✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
|
95 | (e1, arg) := func(exp.tupleExp, arg); |
| 4512 |
1/2✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
|
95 | then |
| 4513 | if referenceEq(exp.tupleExp, e1) then exp else TUPLE_ELEMENT(e1, exp.index, exp.ty); | ||
| 4514 | |||
| 4515 | case RECORD_ELEMENT() | ||
| 4516 | algorithm | ||
| 4517 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | (e1, arg) := func(exp.recordExp, arg); |
| 4518 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | then |
| 4519 | if referenceEq(exp.recordExp, e1) then exp else RECORD_ELEMENT(e1, exp.index, exp.fieldName, exp.ty); | ||
| 4520 | |||
| 4521 | case MUTABLE() | ||
| 4522 | algorithm | ||
| 4523 |
1/2✓ Branch 0 taken 134 times.
✗ Branch 1 not taken.
|
134 | (e1, arg) := func(Mutable.access(exp.exp), arg); |
| 4524 | 134 | Mutable.update(exp.exp, e1); | |
| 4525 | then | ||
| 4526 | exp; | ||
| 4527 | |||
| 4528 | case SHARED_LITERAL() | ||
| 4529 | algorithm | ||
| 4530 | ✗ | (e1, arg) := func(exp.exp, arg); | |
| 4531 | ✗ | exp.exp := e1; | |
| 4532 | then | ||
| 4533 | exp; | ||
| 4534 | |||
| 4535 | case PARTIAL_FUNCTION_APPLICATION() | ||
| 4536 | algorithm | ||
| 4537 | 25 | (expl, arg) := List.mapFold(exp.args, func, arg); | |
| 4538 | 25 | exp.args := expl; | |
| 4539 | then | ||
| 4540 | exp; | ||
| 4541 | |||
| 4542 | else exp; | ||
| 4543 | end match; | ||
| 4544 | end mapFoldShallow; | ||
| 4545 | |||
| 4546 | function mapFoldOptShallow<ArgT> | ||
| 4547 | input Option<Expression> exp; | ||
| 4548 | input MapFunc func; | ||
| 4549 | output Option<Expression> outExp; | ||
| 4550 | input output ArgT arg; | ||
| 4551 | |||
| 4552 | partial function MapFunc | ||
| 4553 | input output Expression e; | ||
| 4554 | input output ArgT arg; | ||
| 4555 | end MapFunc; | ||
| 4556 | protected | ||
| 4557 | Expression e1, e2; | ||
| 4558 | algorithm | ||
| 4559 | outExp := match exp | ||
| 4560 | case SOME(e1) | ||
| 4561 | algorithm | ||
| 4562 |
1/2✓ Branch 0 taken 2545 times.
✗ Branch 1 not taken.
|
2545 | (e2, arg) := func(e1, arg); |
| 4563 |
2/2✓ Branch 0 taken 279 times.
✓ Branch 1 taken 2266 times.
|
2545 | then |
| 4564 | if referenceEq(e1, e2) then exp else SOME(e2); | ||
| 4565 | |||
| 4566 | else exp; | ||
| 4567 | end match; | ||
| 4568 | end mapFoldOptShallow; | ||
| 4569 | |||
| 4570 | function containsOpt | ||
| 4571 | input Option<Expression> exp; | ||
| 4572 | input ContainsPred func; | ||
| 4573 | output Boolean res; | ||
| 4574 | |||
| 4575 | partial function ContainsPred | ||
| 4576 | input Expression exp; | ||
| 4577 | output Boolean res; | ||
| 4578 | end ContainsPred; | ||
| 4579 | protected | ||
| 4580 | Expression e; | ||
| 4581 | algorithm | ||
| 4582 | res := match exp | ||
| 4583 | 4336 | case SOME(e) then contains(e, func); | |
| 4584 | else false; | ||
| 4585 | end match; | ||
| 4586 | end containsOpt; | ||
| 4587 | |||
| 4588 | function contains | ||
| 4589 | input Expression exp; | ||
| 4590 | input ContainsPred func; | ||
| 4591 | output Boolean res; | ||
| 4592 | |||
| 4593 | partial function ContainsPred | ||
| 4594 | input Expression exp; | ||
| 4595 | output Boolean res; | ||
| 4596 | end ContainsPred; | ||
| 4597 | algorithm | ||
| 4598 |
4/4✓ Branch 0 taken 140377 times.
✓ Branch 1 taken 14145449 times.
✓ Branch 4 taken 125184 times.
✓ Branch 5 taken 14160642 times.
|
14285826 | if func(exp) then |
| 4599 | res := true; | ||
| 4600 | 125184 | return; | |
| 4601 | end if; | ||
| 4602 | |||
| 4603 | res := match exp | ||
| 4604 | local | ||
| 4605 | |||
| 4606 | 3 | case CLKCONST() then ClockKind.containsExp(exp.clk, func); | |
| 4607 | 4249875 | case CREF() then ComponentRef.containsExp(exp.cref, func); | |
| 4608 | 77357 | case ARRAY() then arrayContains(exp.elements, func); | |
| 4609 | |||
| 4610 | case MATRIX() | ||
| 4611 | algorithm | ||
| 4612 | res := false; | ||
| 4613 | |||
| 4614 | ✗ | for row in exp.elements loop | |
| 4615 | ✗ | if listContains(row, func) then | |
| 4616 | res := true; | ||
| 4617 | break; | ||
| 4618 | end if; | ||
| 4619 | end for; | ||
| 4620 | then | ||
| 4621 | res; | ||
| 4622 | |||
| 4623 | case RANGE() | ||
| 4624 |
4/6✓ Branch 1 taken 6027 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 6027 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 60 times.
✓ Branch 8 taken 5967 times.
|
6027 | then contains(exp.start, func) or |
| 4625 | containsOpt(exp.step, func) or | ||
| 4626 | contains(exp.stop, func); | ||
| 4627 | |||
| 4628 | 6 | case TUPLE() then listContains(exp.elements, func); | |
| 4629 | 6603 | case RECORD() then listContains(exp.elements, func); | |
| 4630 | 61374 | case CALL() then Call.containsExp(exp.call, func); | |
| 4631 | |||
| 4632 | case SIZE() | ||
| 4633 |
3/4✓ Branch 1 taken 4323 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 50 times.
✓ Branch 5 taken 4273 times.
|
4323 | then containsOpt(exp.dimIndex, func) or |
| 4634 | contains(exp.exp, func); | ||
| 4635 | |||
| 4636 |
4/4✓ Branch 1 taken 5204022 times.
✓ Branch 2 taken 3877 times.
✓ Branch 4 taken 5745 times.
✓ Branch 5 taken 5198277 times.
|
5207899 | case BINARY() then contains(exp.exp1, func) or contains(exp.exp2, func); |
| 4637 | case MULTARY() | ||
| 4638 | algorithm | ||
| 4639 | res := false; | ||
| 4640 |
2/2✓ Branch 0 taken 4483 times.
✓ Branch 1 taken 1783 times.
|
6266 | for arg in exp.arguments loop |
| 4641 |
2/2✓ Branch 0 taken 4465 times.
✓ Branch 1 taken 18 times.
|
4483 | if res then break; end if; |
| 4642 | 4465 | res := contains(arg, func); | |
| 4643 | end for; | ||
| 4644 |
2/2✓ Branch 0 taken 341 times.
✓ Branch 1 taken 1770 times.
|
2111 | for arg in exp.inv_arguments loop |
| 4645 |
2/2✓ Branch 0 taken 310 times.
✓ Branch 1 taken 31 times.
|
341 | if res then break; end if; |
| 4646 | 310 | res := contains(arg, func); | |
| 4647 | end for; | ||
| 4648 | then res; | ||
| 4649 | 177041 | case UNARY() then contains(exp.exp, func); | |
| 4650 |
2/4✓ Branch 1 taken 449 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 449 times.
|
449 | case LBINARY() then contains(exp.exp1, func) or contains(exp.exp2, func); |
| 4651 | 344 | case LUNARY() then contains(exp.exp, func); | |
| 4652 |
4/4✓ Branch 1 taken 5146 times.
✓ Branch 2 taken 6 times.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 5145 times.
|
5152 | case RELATION() then contains(exp.exp1, func) or contains(exp.exp2, func); |
| 4653 | |||
| 4654 | case IF() | ||
| 4655 |
6/6✓ Branch 1 taken 6309 times.
✓ Branch 2 taken 3 times.
✓ Branch 4 taken 6282 times.
✓ Branch 5 taken 27 times.
✓ Branch 7 taken 9 times.
✓ Branch 8 taken 6273 times.
|
6312 | then contains(exp.condition, func) or |
| 4656 | contains(exp.trueBranch, func) or | ||
| 4657 | contains(exp.falseBranch, func); | ||
| 4658 | |||
| 4659 | 6463 | case CAST() then contains(exp.exp, func); | |
| 4660 | 20 | case BOX() then contains(exp.exp, func); | |
| 4661 | 18 | case UNBOX() then contains(exp.exp, func); | |
| 4662 | |||
| 4663 | case SUBSCRIPTED_EXP() | ||
| 4664 |
4/4✓ Branch 1 taken 9585 times.
✓ Branch 2 taken 1389 times.
✓ Branch 4 taken 438 times.
✓ Branch 5 taken 9147 times.
|
10974 | then contains(exp.exp, func) or Subscript.listContainsExp(exp.subscripts, func); |
| 4665 | |||
| 4666 | 36 | case TUPLE_ELEMENT() then contains(exp.tupleExp, func); | |
| 4667 | ✗ | case RECORD_ELEMENT() then contains(exp.recordExp, func); | |
| 4668 | 6880 | case MUTABLE() then contains(Mutable.access(exp.exp), func); | |
| 4669 | ✗ | case SHARED_LITERAL() then contains(exp.exp, func); | |
| 4670 | 1 | case PARTIAL_FUNCTION_APPLICATION() then listContains(exp.args, func); | |
| 4671 | else false; | ||
| 4672 | end match; | ||
| 4673 | end contains; | ||
| 4674 | |||
| 4675 | function arrayContains | ||
| 4676 | input array<Expression> expl; | ||
| 4677 | input ContainsPred func; | ||
| 4678 | output Boolean res; | ||
| 4679 | |||
| 4680 | partial function ContainsPred | ||
| 4681 | input Expression exp; | ||
| 4682 | output Boolean res; | ||
| 4683 | end ContainsPred; | ||
| 4684 | algorithm | ||
| 4685 |
2/2✓ Branch 1 taken 231966 times.
✓ Branch 2 taken 69946 times.
|
301912 | for e in expl loop |
| 4686 |
2/2✓ Branch 1 taken 7411 times.
✓ Branch 2 taken 224555 times.
|
231966 | if contains(e, func) then |
| 4687 | res := true; | ||
| 4688 | 7411 | return; | |
| 4689 | end if; | ||
| 4690 | end for; | ||
| 4691 | |||
| 4692 | res := false; | ||
| 4693 | end arrayContains; | ||
| 4694 | |||
| 4695 | function listContains | ||
| 4696 | input list<Expression> expl; | ||
| 4697 | input ContainsPred func; | ||
| 4698 | output Boolean res; | ||
| 4699 | |||
| 4700 | partial function ContainsPred | ||
| 4701 | input Expression exp; | ||
| 4702 | output Boolean res; | ||
| 4703 | end ContainsPred; | ||
| 4704 | algorithm | ||
| 4705 |
2/2✓ Branch 0 taken 281539 times.
✓ Branch 1 taken 66984 times.
|
348523 | for e in expl loop |
| 4706 |
2/2✓ Branch 1 taken 698 times.
✓ Branch 2 taken 280841 times.
|
281539 | if contains(e, func) then |
| 4707 | res := true; | ||
| 4708 | 698 | return; | |
| 4709 | end if; | ||
| 4710 | end for; | ||
| 4711 | |||
| 4712 | res := false; | ||
| 4713 | end listContains; | ||
| 4714 | |||
| 4715 | function containsShallow | ||
| 4716 | input Expression exp; | ||
| 4717 | input ContainsPred func; | ||
| 4718 | output Boolean res; | ||
| 4719 | |||
| 4720 | partial function ContainsPred | ||
| 4721 | input Expression exp; | ||
| 4722 | output Boolean res; | ||
| 4723 | end ContainsPred; | ||
| 4724 | algorithm | ||
| 4725 | res := match exp | ||
| 4726 | 24 | case CLKCONST() then ClockKind.containsExpShallow(exp.clk, func); | |
| 4727 | 31963 | case CREF() then ComponentRef.containsExpShallow(exp.cref, func); | |
| 4728 | 8244 | case ARRAY() then Array.any(exp.elements, func); | |
| 4729 | |||
| 4730 | case MATRIX() | ||
| 4731 | algorithm | ||
| 4732 | res := false; | ||
| 4733 | |||
| 4734 | ✗ | for row in exp.elements loop | |
| 4735 | ✗ | if List.any(row, func) then | |
| 4736 | res := true; | ||
| 4737 | break; | ||
| 4738 | end if; | ||
| 4739 | end for; | ||
| 4740 | then | ||
| 4741 | res; | ||
| 4742 | |||
| 4743 | case RANGE() | ||
| 4744 |
9/14✓ Branch 0 taken 1550 times.
✓ Branch 1 taken 8704 times.
✓ Branch 3 taken 1550 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 8704 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 10254 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 1550 times.
✓ Branch 12 taken 8704 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 1550 times.
✗ Branch 17 not taken.
✓ Branch 18 taken 8704 times.
|
10254 | then func(exp.start) or |
| 4745 | Util.applyOptionOrDefault(exp.step, func, false) or | ||
| 4746 | func(exp.stop); | ||
| 4747 | |||
| 4748 | ✗ | case TUPLE() then List.any(exp.elements, func); | |
| 4749 | 4962 | case RECORD() then List.any(exp.elements, func); | |
| 4750 | 133692 | case CALL() then Call.containsExpShallow(exp.call, func); | |
| 4751 | |||
| 4752 | case SIZE() | ||
| 4753 |
3/8✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 18 times.
|
18 | then Util.applyOptionOrDefault(exp.dimIndex, func, false) or |
| 4754 | func(exp.exp); | ||
| 4755 | |||
| 4756 |
11/12✓ Branch 0 taken 1696 times.
✓ Branch 1 taken 307938 times.
✓ Branch 3 taken 1644 times.
✓ Branch 4 taken 52 times.
✓ Branch 6 taken 307938 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1644 times.
✓ Branch 9 taken 307938 times.
✓ Branch 11 taken 36 times.
✓ Branch 12 taken 1608 times.
✓ Branch 14 taken 1 time.
✓ Branch 15 taken 307937 times.
|
309634 | case BINARY() then func(exp.exp1) or func(exp.exp2); |
| 4757 | case MULTARY() | ||
| 4758 | algorithm | ||
| 4759 | res := false; | ||
| 4760 | ✗ | for arg in exp.arguments loop | |
| 4761 | ✗ | if res then break; end if; | |
| 4762 | ✗ | res := func(arg); | |
| 4763 | end for; | ||
| 4764 | ✗ | for arg in exp.inv_arguments loop | |
| 4765 | ✗ | if res then break; end if; | |
| 4766 | ✗ | res := func(arg); | |
| 4767 | end for; | ||
| 4768 | then res; | ||
| 4769 |
2/2✓ Branch 0 taken 49 times.
✓ Branch 1 taken 880 times.
|
929 | case UNARY() then func(exp.exp); |
| 4770 |
10/12✓ Branch 0 taken 1194 times.
✓ Branch 1 taken 6126 times.
✓ Branch 3 taken 1089 times.
✓ Branch 4 taken 105 times.
✓ Branch 6 taken 6125 times.
✓ Branch 7 taken 1 time.
✓ Branch 8 taken 1089 times.
✓ Branch 9 taken 6125 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 1089 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 6125 times.
|
7320 | case LBINARY() then func(exp.exp1) or func(exp.exp2); |
| 4771 |
2/2✓ Branch 0 taken 2244 times.
✓ Branch 1 taken 494 times.
|
2738 | case LUNARY() then func(exp.exp); |
| 4772 |
10/12✓ Branch 0 taken 5041 times.
✓ Branch 1 taken 34213 times.
✓ Branch 3 taken 4544 times.
✓ Branch 4 taken 497 times.
✓ Branch 6 taken 34210 times.
✓ Branch 7 taken 3 times.
✓ Branch 8 taken 4544 times.
✓ Branch 9 taken 34210 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 4544 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 34210 times.
|
39254 | case RELATION() then func(exp.exp1) or func(exp.exp2); |
| 4773 |
14/18✓ Branch 0 taken 259 times.
✓ Branch 1 taken 11310 times.
✓ Branch 3 taken 259 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 11310 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 259 times.
✓ Branch 9 taken 11310 times.
✓ Branch 11 taken 154 times.
✓ Branch 12 taken 105 times.
✓ Branch 14 taken 11310 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 154 times.
✓ Branch 17 taken 11310 times.
✓ Branch 19 taken 57 times.
✓ Branch 20 taken 97 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 11310 times.
|
11569 | case IF() then func(exp.condition) or func(exp.trueBranch) or func(exp.falseBranch); |
| 4774 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 401 times.
|
413 | case CAST() then func(exp.exp); |
| 4775 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 | case BOX() then func(exp.exp); |
| 4776 | ✗ | case UNBOX() then func(exp.exp); | |
| 4777 | |||
| 4778 | case SUBSCRIPTED_EXP() | ||
| 4779 |
6/8✓ Branch 0 taken 18430 times.
✓ Branch 1 taken 876 times.
✓ Branch 3 taken 18326 times.
✓ Branch 4 taken 104 times.
✓ Branch 6 taken 876 times.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 19202 times.
|
19306 | then func(exp.exp) or Subscript.listContainsExpShallow(exp.subscripts, func); |
| 4780 | |||
| 4781 | ✗ | case TUPLE_ELEMENT() then func(exp.tupleExp); | |
| 4782 | ✗ | case RECORD_ELEMENT() then func(exp.recordExp); | |
| 4783 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2625 times.
|
2625 | case MUTABLE() then func(Mutable.access(exp.exp)); |
| 4784 | ✗ | case SHARED_LITERAL() then func(exp.exp); | |
| 4785 | 1 | case PARTIAL_FUNCTION_APPLICATION() then listContains(exp.args, func); | |
| 4786 | else false; | ||
| 4787 | end match; | ||
| 4788 | end containsShallow; | ||
| 4789 | |||
| 4790 | function arrayFirstScalar | ||
| 4791 | "Returns the first scalar element of an array. Fails if the array is empty." | ||
| 4792 | input Expression arrayExp; | ||
| 4793 | output Expression exp; | ||
| 4794 | algorithm | ||
| 4795 | exp := match arrayExp | ||
| 4796 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
|
44 | case ARRAY() then arrayFirstScalar(arrayGet(arrayExp.elements, 1)); |
| 4797 | else arrayExp; | ||
| 4798 | end match; | ||
| 4799 | end arrayFirstScalar; | ||
| 4800 | |||
| 4801 | function arrayAllEqual | ||
| 4802 | "Checks if all scalar elements in an array are equal to each other." | ||
| 4803 | input Expression arrayExp; | ||
| 4804 | output Boolean allEqual; | ||
| 4805 | algorithm | ||
| 4806 | allEqual := matchcontinue arrayExp | ||
| 4807 | 17 | case ARRAY() then arrayAllEqual2(arrayExp, arrayFirstScalar(arrayExp)); | |
| 4808 | else true; | ||
| 4809 | end matchcontinue; | ||
| 4810 | end arrayAllEqual; | ||
| 4811 | |||
| 4812 | function arrayAllEqual2 | ||
| 4813 | input Expression arrayExp; | ||
| 4814 | input Expression element; | ||
| 4815 | output Boolean allEqual; | ||
| 4816 | algorithm | ||
| 4817 | allEqual := match arrayExp | ||
| 4818 | case ARRAY() | ||
| 4819 | guard not arrayEmpty(arrayExp.elements) and isArray(arrayGet(arrayExp.elements, 1)) | ||
| 4820 | 1 | then Array.all(arrayExp.elements, function arrayAllEqual2(element = element)); | |
| 4821 | case ARRAY() | ||
| 4822 | 17 | then Array.all(arrayExp.elements, function isEqual(exp2 = element)); | |
| 4823 | else true; | ||
| 4824 | end match; | ||
| 4825 | end arrayAllEqual2; | ||
| 4826 | |||
| 4827 | function fromCref | ||
| 4828 | input ComponentRef cref; | ||
| 4829 | input Boolean includeScope = false; | ||
| 4830 | output Expression exp; | ||
| 4831 | algorithm | ||
| 4832 | 259030 | exp := CREF(ComponentRef.getSubscriptedType(cref, includeScope), cref); | |
| 4833 | end fromCref; | ||
| 4834 | |||
| 4835 | function fromTypedCref | ||
| 4836 | input ComponentRef cref; | ||
| 4837 | input Type ty; | ||
| 4838 | output Expression exp = CREF(ty, cref); | ||
| 4839 | end fromTypedCref; | ||
| 4840 | |||
| 4841 | function toCref | ||
| 4842 | input Expression exp; | ||
| 4843 | output ComponentRef cref; | ||
| 4844 | algorithm | ||
| 4845 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2886 times.
|
2886 | CREF(cref = cref) := exp; |
| 4846 | end toCref; | ||
| 4847 | |||
| 4848 | function extractCrefs | ||
| 4849 | input Expression exp; | ||
| 4850 | output UnorderedSet<ComponentRef> crefs = fold(exp, extractCref, UnorderedSet.new(ComponentRef.hash, ComponentRef.isEqual)); | ||
| 4851 | end extractCrefs; | ||
| 4852 | |||
| 4853 | function extractCref | ||
| 4854 | input Expression exp; | ||
| 4855 | input output UnorderedSet<ComponentRef> crefs; | ||
| 4856 | algorithm | ||
| 4857 | crefs := match exp | ||
| 4858 | case CREF() algorithm | ||
| 4859 | 5545 | UnorderedSet.add(exp.cref, crefs); | |
| 4860 | then crefs; | ||
| 4861 | else crefs; | ||
| 4862 | end match; | ||
| 4863 | end extractCref; | ||
| 4864 | |||
| 4865 | function isResizableCref | ||
| 4866 | input Expression exp; | ||
| 4867 | output Boolean b; | ||
| 4868 | algorithm | ||
| 4869 | b := match exp | ||
| 4870 | 13925 | case CREF() then ComponentRef.isResizable(exp.cref); | |
| 4871 | else false; | ||
| 4872 | end match; | ||
| 4873 | end isResizableCref; | ||
| 4874 | |||
| 4875 | function isIterator | ||
| 4876 | input Expression exp; | ||
| 4877 | output Boolean isIterator; | ||
| 4878 | algorithm | ||
| 4879 | isIterator := match exp | ||
| 4880 | 1004 | case CREF() then ComponentRef.isIterator(exp.cref); | |
| 4881 | else false; | ||
| 4882 | end match; | ||
| 4883 | end isIterator; | ||
| 4884 | |||
| 4885 | function containsAnyIterator | ||
| 4886 | input Expression exp; | ||
| 4887 | input InstContext.Type context; | ||
| 4888 | output Boolean iter; | ||
| 4889 | algorithm | ||
| 4890 | ✗ | if InstContext.inFor(context) then | |
| 4891 | ✗ | iter := contains(exp, isIterator); | |
| 4892 | else | ||
| 4893 | iter := false; | ||
| 4894 | end if; | ||
| 4895 | end containsAnyIterator; | ||
| 4896 | |||
| 4897 | function isTime | ||
| 4898 | input Expression exp; | ||
| 4899 | output Boolean b; | ||
| 4900 | algorithm | ||
| 4901 | b := match exp | ||
| 4902 | 35 | case CREF() then ComponentRef.isTime(exp.cref); | |
| 4903 | else false; | ||
| 4904 | end match; | ||
| 4905 | end isTime; | ||
| 4906 | |||
| 4907 | function isSubstitute | ||
| 4908 | input Expression exp; | ||
| 4909 | output Boolean b; | ||
| 4910 | algorithm | ||
| 4911 | b := match exp | ||
| 4912 | 2850 | case CREF() then ComponentRef.isSubstitute(exp.cref); | |
| 4913 | else false; | ||
| 4914 | end match; | ||
| 4915 | end isSubstitute; | ||
| 4916 | |||
| 4917 | function isZero | ||
| 4918 | input Expression exp; | ||
| 4919 | output Boolean b; | ||
| 4920 | algorithm | ||
| 4921 | b := match exp | ||
| 4922 | 55437 | case INTEGER() then exp.value == 0; | |
| 4923 | 228386 | case REAL() then exp.value == 0.0; | |
| 4924 | 1250 | case CAST() then isZero(exp.exp); | |
| 4925 | 16083 | case UNARY() then isZero(exp.exp); | |
| 4926 | 2821 | case ARRAY() then Array.all(exp.elements, isZero); | |
| 4927 | else false; | ||
| 4928 | end match; | ||
| 4929 | end isZero; | ||
| 4930 | |||
| 4931 | function isNonZero | ||
| 4932 | input Expression exp; | ||
| 4933 | output Boolean res = isPositive(exp) or isNegative(exp); | ||
| 4934 | end isNonZero; | ||
| 4935 | |||
| 4936 | function isOne | ||
| 4937 | input Expression exp; | ||
| 4938 | output Boolean b; | ||
| 4939 | algorithm | ||
| 4940 | b := match exp | ||
| 4941 | 1509 | case INTEGER() then exp.value == 1; | |
| 4942 | 26843 | case REAL() then exp.value == 1.0; | |
| 4943 | 600 | case CAST() then isOne(exp.exp); | |
| 4944 | 104 | case UNARY() then isMinusOne(exp.exp); | |
| 4945 | 55 | case ARRAY() then Array.all(exp.elements, isOne); | |
| 4946 | else false; | ||
| 4947 | end match; | ||
| 4948 | end isOne; | ||
| 4949 | |||
| 4950 | function isMinusOne | ||
| 4951 | input Expression exp; | ||
| 4952 | output Boolean isOne; | ||
| 4953 | algorithm | ||
| 4954 | isOne := match exp | ||
| 4955 | ✗ | case INTEGER() then exp.value == -1; | |
| 4956 | 8296 | case REAL() then exp.value == -1.0; | |
| 4957 | 445 | case CAST() then isMinusOne(exp.exp); | |
| 4958 | 99 | case UNARY() then isOne(exp.exp); | |
| 4959 | else false; | ||
| 4960 | end match; | ||
| 4961 | end isMinusOne; | ||
| 4962 | |||
| 4963 | function isNaN | ||
| 4964 | input Expression nan; | ||
| 4965 | output Boolean b; | ||
| 4966 | algorithm | ||
| 4967 | b := match nan | ||
| 4968 |
2/6✓ Branch 1 taken 198 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 198 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
|
198 | case BINARY() then Operator.getMathClassification(nan.operator) == NFOperator.MathClassification.DIVISION and isZero(nan.exp1) and isZero(nan.exp2); |
| 4969 | else false; | ||
| 4970 | end match; | ||
| 4971 | end isNaN; | ||
| 4972 | |||
| 4973 | function isPositive | ||
| 4974 | input Expression exp; | ||
| 4975 | output Boolean positive "true if exp is known to be > 0, otherwise false"; | ||
| 4976 | algorithm | ||
| 4977 | positive := match exp | ||
| 4978 | 387 | case INTEGER() then exp.value > 0; | |
| 4979 | 12 | case REAL() then exp.value > 0.0; | |
| 4980 | ✗ | case CAST() then isPositive(exp.exp); | |
| 4981 | 3 | case UNARY() then isNegative(exp.exp); | |
| 4982 | 57 | case CREF() then Util.applyOptionOrDefault(ComponentRef.lookupVarAttr(exp.cref, "min"), isPositive, false); | |
| 4983 | 4 | case CALL() then Call.isPositive(exp.call); | |
| 4984 | else false; | ||
| 4985 | end match; | ||
| 4986 | end isPositive; | ||
| 4987 | |||
| 4988 | function isNegative | ||
| 4989 | input Expression exp; | ||
| 4990 | output Boolean negative "true if exp is known to be < 0, otherwise false"; | ||
| 4991 | algorithm | ||
| 4992 | negative := match exp | ||
| 4993 | 352 | case INTEGER() then exp.value < 0; | |
| 4994 | 415 | case REAL() then exp.value < 0.0; | |
| 4995 | ✗ | case CAST() then isNegative(exp.exp); | |
| 4996 | 3 | case UNARY() then isPositive(exp.exp); | |
| 4997 | 59 | case CREF() then Util.applyOptionOrDefault(ComponentRef.lookupVarAttr(exp.cref, "max"), isNegative, false); | |
| 4998 | ✗ | case CALL() then Call.isNegative(exp.call); | |
| 4999 | else false; | ||
| 5000 | end match; | ||
| 5001 | end isNegative; | ||
| 5002 | |||
| 5003 | function isNonPositive | ||
| 5004 | input Expression exp; | ||
| 5005 | output Boolean res "true if exp is known to be <= 0, otherwise false"; | ||
| 5006 | algorithm | ||
| 5007 | res := match exp | ||
| 5008 | 224 | case INTEGER() then exp.value <= 0; | |
| 5009 | 437 | case REAL() then exp.value <= 0.0; | |
| 5010 | ✗ | case CAST() then isNonPositive(exp.exp); | |
| 5011 | 1442 | case UNARY() then isNonNegative(exp.exp); | |
| 5012 | 146 | case CREF() then Util.applyOptionOrDefault(ComponentRef.lookupVarAttr(exp.cref, "max"), isNonPositive, false); | |
| 5013 | ✗ | case CALL() then Call.isNonPositive(exp.call); | |
| 5014 | 4 | case ARRAY() then Array.all(exp.elements, isNonPositive); | |
| 5015 | else false; | ||
| 5016 | end match; | ||
| 5017 | end isNonPositive; | ||
| 5018 | |||
| 5019 | function isNonNegative | ||
| 5020 | input Expression exp; | ||
| 5021 | output Boolean res "true if exp is known to be >= 0, otherwise false"; | ||
| 5022 | algorithm | ||
| 5023 | res := match exp | ||
| 5024 | 2 | case INTEGER() then exp.value >= 0; | |
| 5025 | 1240 | case REAL() then exp.value >= 0.0; | |
| 5026 | ✗ | case CAST() then isNonNegative(exp.exp); | |
| 5027 | ✗ | case UNARY() then isNonPositive(exp.exp); | |
| 5028 | 1442 | case CREF() then Util.applyOptionOrDefault(ComponentRef.lookupVarAttr(exp.cref, "min"), isNonNegative, false); | |
| 5029 | ✗ | case CALL() then Call.isNonNegative(exp.call); | |
| 5030 | else false; | ||
| 5031 | end match; | ||
| 5032 | end isNonNegative; | ||
| 5033 | |||
| 5034 | function isEven | ||
| 5035 | input Expression exp; | ||
| 5036 | output Boolean even; | ||
| 5037 | algorithm | ||
| 5038 | even := match exp | ||
| 5039 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
10 | case INTEGER() then intMod(exp.value, 2) == 0; |
| 5040 | ✗ | case REAL() then realMod(exp.value, 2.0) == 0.0; | |
| 5041 | ✗ | case CAST() then isEven(exp.exp); | |
| 5042 | else false; | ||
| 5043 | end match; | ||
| 5044 | end isEven; | ||
| 5045 | |||
| 5046 | function isGreaterOrEqual | ||
| 5047 | input Expression lhs; | ||
| 5048 | input Expression rhs; | ||
| 5049 | output Boolean res "true if we know that lhs >= rhs, otherwise false"; | ||
| 5050 | algorithm | ||
| 5051 | res := match (lhs, rhs) | ||
| 5052 | ✗ | case (REAL(), REAL()) then lhs.value >= rhs.value; | |
| 5053 | 146 | case (CREF(), _) then Util.applyOptionOrDefault(ComponentRef.lookupVarAttr(lhs.cref, "min"), function isGreaterOrEqual(rhs=rhs), false); | |
| 5054 | 1442 | case (_, CREF()) then Util.applyOptionOrDefault(ComponentRef.lookupVarAttr(rhs.cref, "max"), function isGreaterOrEqual(lhs=lhs), false); | |
| 5055 | 1442 | case (UNARY(exp = CREF()), _) then isGreaterOrEqual(negate(rhs), lhs.exp); | |
| 5056 | ✗ | case (_, UNARY(exp = CREF())) then isGreaterOrEqual(rhs.exp, negate(lhs)); | |
| 5057 | else false; | ||
| 5058 | end match; | ||
| 5059 | end isGreaterOrEqual; | ||
| 5060 | |||
| 5061 | function hasArrayType | ||
| 5062 | input Expression exp; | ||
| 5063 | output Boolean b = Type.isArray(typeOf(exp)); | ||
| 5064 | end hasArrayType; | ||
| 5065 | |||
| 5066 | function isScalar | ||
| 5067 | input Expression exp; | ||
| 5068 | output Boolean scalar = Type.isScalar(typeOf(exp)); | ||
| 5069 | end isScalar; | ||
| 5070 | |||
| 5071 | function isScalarLiteral | ||
| 5072 | input Expression exp; | ||
| 5073 | output Boolean literal; | ||
| 5074 | algorithm | ||
| 5075 | literal := match exp | ||
| 5076 | case INTEGER() then true; | ||
| 5077 | case REAL() then true; | ||
| 5078 | case STRING() then true; | ||
| 5079 | case BOOLEAN() then true; | ||
| 5080 | case ENUM_LITERAL() then true; | ||
| 5081 | case FILENAME() then true; | ||
| 5082 | else false; | ||
| 5083 | end match; | ||
| 5084 | end isScalarLiteral; | ||
| 5085 | |||
| 5086 | function isLiteral | ||
| 5087 | input Expression exp; | ||
| 5088 | output Boolean literal; | ||
| 5089 | algorithm | ||
| 5090 | literal := match exp | ||
| 5091 | case INTEGER() then true; | ||
| 5092 | case REAL() then true; | ||
| 5093 | case STRING() then true; | ||
| 5094 | case BOOLEAN() then true; | ||
| 5095 | case ENUM_LITERAL() then true; | ||
| 5096 |
4/4✓ Branch 0 taken 48759 times.
✓ Branch 1 taken 36515 times.
✓ Branch 3 taken 25721 times.
✓ Branch 4 taken 23038 times.
|
85274 | case ARRAY() then exp.literal or Array.all(exp.elements, isLiteral); |
| 5097 | 2265 | case RECORD() then List.all(exp.elements, isLiteral); | |
| 5098 |
5/6✓ Branch 1 taken 4228 times.
✓ Branch 2 taken 1 time.
✓ Branch 4 taken 4123 times.
✓ Branch 5 taken 105 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 4123 times.
|
4229 | case RANGE() then isLiteral(exp.start) and isLiteral(exp.stop) and |
| 5099 | Util.applyOptionOrDefault(exp.step, isLiteral, true); | ||
| 5100 | case FILENAME() then true; | ||
| 5101 | else false; | ||
| 5102 | end match; | ||
| 5103 | end isLiteral; | ||
| 5104 | |||
| 5105 | function isLiteralXML | ||
| 5106 | "allows for expressions additionally for init_xml" | ||
| 5107 | input Expression exp; | ||
| 5108 | output Boolean literal; | ||
| 5109 | algorithm | ||
| 5110 | literal := match exp | ||
| 5111 | local | ||
| 5112 | Expression call_exp; | ||
| 5113 | case INTEGER() then true; | ||
| 5114 | case REAL() then true; | ||
| 5115 | case STRING() then true; | ||
| 5116 | case BOOLEAN() then true; | ||
| 5117 | case ENUM_LITERAL() then true; | ||
| 5118 | 313 | case ARRAY() then Array.all(exp.elements, isLiteralXML); | |
| 5119 | 24 | case RECORD() then List.all(exp.elements, isLiteralXML); | |
| 5120 |
3/6✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 5 times.
|
5 | case RANGE() then isLiteralXML(exp.start) and isLiteralXML(exp.stop) and |
| 5121 | Util.applyOptionOrDefault(exp.step, isLiteralXML, true); | ||
| 5122 | case FILENAME() then true; | ||
| 5123 | 149 | case CALL(call = Call.TYPED_ARRAY_CONSTRUCTOR(exp = call_exp)) then isLiteralXML(call_exp); | |
| 5124 | else false; | ||
| 5125 | end match; | ||
| 5126 | end isLiteralXML; | ||
| 5127 | |||
| 5128 | function isLiteralReplace | ||
| 5129 | input Expression exp; | ||
| 5130 | output Boolean b; | ||
| 5131 | algorithm | ||
| 5132 | b := match exp | ||
| 5133 | case STRING() then true; | ||
| 5134 | case BOX(STRING()) then true; | ||
| 5135 | 73 | case RECORD() then isLiteral(exp); | |
| 5136 | 409 | case ARRAY() then isLiteral(exp); | |
| 5137 | else false; | ||
| 5138 | end match; | ||
| 5139 | end isLiteralReplace; | ||
| 5140 | |||
| 5141 | function isKnownSizeFill | ||
| 5142 | input Expression exp; | ||
| 5143 | output Boolean literal; | ||
| 5144 | algorithm | ||
| 5145 | literal := match exp | ||
| 5146 | 502 | case CALL() then Call.isKnownSizeFill(exp.call); | |
| 5147 | else false; | ||
| 5148 | end match; | ||
| 5149 | end isKnownSizeFill; | ||
| 5150 | |||
| 5151 | function isInteger | ||
| 5152 | input Expression exp; | ||
| 5153 | output Boolean isInteger; | ||
| 5154 | algorithm | ||
| 5155 | isInteger := match exp | ||
| 5156 | case INTEGER() then true; | ||
| 5157 | else false; | ||
| 5158 | end match; | ||
| 5159 | end isInteger; | ||
| 5160 | |||
| 5161 | function isReal | ||
| 5162 | input Expression exp; | ||
| 5163 | output Boolean isReal; | ||
| 5164 | algorithm | ||
| 5165 | isReal := match exp | ||
| 5166 | case REAL() then true; | ||
| 5167 | else false; | ||
| 5168 | end match; | ||
| 5169 | end isReal; | ||
| 5170 | |||
| 5171 | function isConstNumber | ||
| 5172 | input Expression exp; | ||
| 5173 | output Boolean b; | ||
| 5174 | algorithm | ||
| 5175 | b := match exp | ||
| 5176 | case INTEGER() then true; | ||
| 5177 | case REAL() then true; | ||
| 5178 | ✗ | case CAST() then isConstNumber(exp.exp); | |
| 5179 | 232 | case UNARY() then isConstNumber(exp.exp); | |
| 5180 | else false; | ||
| 5181 | end match; | ||
| 5182 | end isConstNumber; | ||
| 5183 | |||
| 5184 | function isBoolean | ||
| 5185 | input Expression exp; | ||
| 5186 | output Boolean isBool; | ||
| 5187 | algorithm | ||
| 5188 | isBool := match exp | ||
| 5189 | case BOOLEAN() then true; | ||
| 5190 | else false; | ||
| 5191 | end match; | ||
| 5192 | end isBoolean; | ||
| 5193 | |||
| 5194 | function isRecord | ||
| 5195 | input Expression exp; | ||
| 5196 | output Boolean isRecord; | ||
| 5197 | algorithm | ||
| 5198 | isRecord := match exp | ||
| 5199 | case RECORD() then true; | ||
| 5200 | else false; | ||
| 5201 | end match; | ||
| 5202 | end isRecord; | ||
| 5203 | |||
| 5204 | function isRecordOrRecordArray | ||
| 5205 | input Expression exp; | ||
| 5206 | output Boolean isRecord; | ||
| 5207 | algorithm | ||
| 5208 | isRecord := match exp | ||
| 5209 | case RECORD() then true; | ||
| 5210 | 154 | case ARRAY() then Array.all(exp.elements, isRecordOrRecordArray); | |
| 5211 | else false; | ||
| 5212 | end match; | ||
| 5213 | end isRecordOrRecordArray; | ||
| 5214 | |||
| 5215 | function fillType | ||
| 5216 | "Creates an array with the given type, filling it with the given scalar | ||
| 5217 | expression." | ||
| 5218 | input Type ty; | ||
| 5219 | input Expression fillExp; | ||
| 5220 | output Expression exp = fillExp; | ||
| 5221 | protected | ||
| 5222 | list<Dimension> dims = Type.arrayDims(ty); | ||
| 5223 | Type arr_ty = Type.arrayElementType(ty); | ||
| 5224 | Boolean is_literal = isLiteral(exp); | ||
| 5225 | algorithm | ||
| 5226 |
2/2✓ Branch 1 taken 8027 times.
✓ Branch 2 taken 6413 times.
|
14440 | for dim in listReverse(dims) loop |
| 5227 | 8027 | (exp, arr_ty) := fillArray_impl(Dimension.size(dim), exp, arr_ty, is_literal); | |
| 5228 | end for; | ||
| 5229 | end fillType; | ||
| 5230 | |||
| 5231 | function fillArgs | ||
| 5232 | "Creates an array from the given fill expression and list of dimensions, | ||
| 5233 | similar to fill(fillExp, dims...). Fails if not all dimensions can be | ||
| 5234 | converted to Integer values." | ||
| 5235 | input Expression fillExp; | ||
| 5236 | input list<Expression> dims; | ||
| 5237 | output Expression result = fillExp; | ||
| 5238 | protected | ||
| 5239 | Type arr_ty = typeOf(result); | ||
| 5240 | Boolean is_literal = isLiteral(fillExp); | ||
| 5241 | Expression d_resizable; | ||
| 5242 | algorithm | ||
| 5243 |
2/2✓ Branch 1 taken 79955 times.
✓ Branch 2 taken 77462 times.
|
157417 | for d in listReverse(dims) loop |
| 5244 | 79955 | d_resizable := map(d, function replaceResizableParameter()); | |
| 5245 | 79955 | (result, arr_ty) := fillArray_impl(toInteger(d_resizable), result, arr_ty, is_literal); | |
| 5246 | end for; | ||
| 5247 | end fillArgs; | ||
| 5248 | |||
| 5249 | function fillArray | ||
| 5250 | input Integer n; | ||
| 5251 | input Expression fillExp; | ||
| 5252 | output Expression result; | ||
| 5253 | algorithm | ||
| 5254 | ✗ | result := fillArray_impl(n, fillExp, typeOf(fillExp), isLiteral(fillExp)); | |
| 5255 | end fillArray; | ||
| 5256 | |||
| 5257 | function fillArray_impl | ||
| 5258 | input Integer n; | ||
| 5259 | input Expression fillExp; | ||
| 5260 | input Type ty; | ||
| 5261 | input Boolean isLiteral; | ||
| 5262 | output Expression result; | ||
| 5263 | output Type resultType; | ||
| 5264 | protected | ||
| 5265 | array<Expression> arr; | ||
| 5266 | algorithm | ||
| 5267 | 87978 | arr := Array.generate(n, function clone(exp = fillExp)); | |
| 5268 | 87978 | resultType := Type.liftArrayLeft(ty, Dimension.fromInteger(n)); | |
| 5269 | 87978 | result := makeArray(resultType, arr, isLiteral); | |
| 5270 | end fillArray_impl; | ||
| 5271 | |||
| 5272 | function liftArray | ||
| 5273 | "Creates an array with the given dimension, where each element is the given | ||
| 5274 | expression. Example: liftArray([3], 1) => {1, 1, 1}" | ||
| 5275 | input Dimension dim; | ||
| 5276 | input output Expression exp; | ||
| 5277 | output Type arrayType = typeOf(exp); | ||
| 5278 | algorithm | ||
| 5279 | ✗ | (exp, arrayType) := fillArray_impl(Dimension.size(dim), exp, arrayType, isLiteral(exp)); | |
| 5280 | end liftArray; | ||
| 5281 | |||
| 5282 | function liftArrayList | ||
| 5283 | "Creates an array from the given list of dimensions, where each element is | ||
| 5284 | the given expression. Example: | ||
| 5285 | liftArrayList([2, 3], 1) => {{1, 1, 1}, {1, 1, 1}}" | ||
| 5286 | input list<Dimension> dims; | ||
| 5287 | input output Expression exp; | ||
| 5288 | output Type arrayType = typeOf(exp); | ||
| 5289 | protected | ||
| 5290 | Boolean is_literal = isLiteral(exp); | ||
| 5291 | algorithm | ||
| 5292 |
2/2✓ Branch 1 taken 28 times.
✓ Branch 2 taken 476 times.
|
504 | for dim in listReverse(dims) loop |
| 5293 | 28 | (exp, arrayType) := fillArray_impl(Dimension.size(dim), exp, arrayType, is_literal); | |
| 5294 | end for; | ||
| 5295 | end liftArrayList; | ||
| 5296 | |||
| 5297 | function makeZero | ||
| 5298 | input Type ty; | ||
| 5299 | output Expression zeroExp; | ||
| 5300 | algorithm | ||
| 5301 | zeroExp := match ty | ||
| 5302 | case Type.REAL() then REAL(0.0); | ||
| 5303 | case Type.INTEGER() then INTEGER(0); | ||
| 5304 | case Type.BOOLEAN() then BOOLEAN(false); | ||
| 5305 | 426 | case Type.ARRAY() then fillType(ty, makeZero(Type.arrayElementType(ty))); | |
| 5306 | 2 | case Type.COMPLEX() then makeOperatorRecordZero(Type.complexNode(ty)); | |
| 5307 | else algorithm | ||
| 5308 | ✗ | Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for: " + Type.toString(ty)}); | |
| 5309 | ✗ | then fail(); | |
| 5310 | end match; | ||
| 5311 | end makeZero; | ||
| 5312 | |||
| 5313 | function makeOperatorRecordZero | ||
| 5314 | input InstNode recordNode; | ||
| 5315 | output Expression zeroExp; | ||
| 5316 | protected | ||
| 5317 | InstNode op_node; | ||
| 5318 | Function.Function fn; | ||
| 5319 | algorithm | ||
| 5320 | try | ||
| 5321 | 2 | op_node := Class.lookupElement("'0'", InstNode.getClass(recordNode)); | |
| 5322 | 2 | Function.Function.instFunctionNode(op_node, NFInstContext.NO_CONTEXT, InstNode.info(InstNode.parent(op_node))); | |
| 5323 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
|
2 | {fn} := Function.Function.typeNodeCache(op_node); |
| 5324 | 2 | zeroExp := CALL(Call.makeTypedCall(fn, {}, Variability.CONSTANT, Purity.PURE)); | |
| 5325 | 2 | zeroExp := Ceval.evalExp(zeroExp); | |
| 5326 | else | ||
| 5327 | ✗ | Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for: " + InstNode.toString(recordNode)}); | |
| 5328 | ✗ | fail(); | |
| 5329 | end try; | ||
| 5330 | end makeOperatorRecordZero; | ||
| 5331 | |||
| 5332 | function makeOne | ||
| 5333 | input Type ty; | ||
| 5334 | output Expression oneExp; | ||
| 5335 | algorithm | ||
| 5336 | oneExp := match ty | ||
| 5337 | case Type.REAL() then REAL(1.0); | ||
| 5338 | case Type.INTEGER() then INTEGER(1); | ||
| 5339 | 165 | case Type.ARRAY() then fillType(ty, makeOne(Type.arrayElementType(ty))); | |
| 5340 | else algorithm | ||
| 5341 | ✗ | Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for: " + Type.toString(ty)}); | |
| 5342 | ✗ | then fail(); | |
| 5343 | end match; | ||
| 5344 | end makeOne; | ||
| 5345 | |||
| 5346 | function makeMinusOne | ||
| 5347 | input Type ty; | ||
| 5348 | output Expression oneExp; | ||
| 5349 | algorithm | ||
| 5350 | oneExp := match ty | ||
| 5351 | case Type.REAL() then REAL(-1.0); | ||
| 5352 | case Type.INTEGER() then INTEGER(-1); | ||
| 5353 | ✗ | case Type.ARRAY() then fillType(ty, makeMinusOne(Type.arrayElementType(ty))); | |
| 5354 | else algorithm | ||
| 5355 | ✗ | Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for: " + Type.toString(ty)}); | |
| 5356 | ✗ | then fail(); | |
| 5357 | end match; | ||
| 5358 | end makeMinusOne; | ||
| 5359 | |||
| 5360 | function makeNaN | ||
| 5361 | input Type ty; | ||
| 5362 | output Expression nan; | ||
| 5363 | protected | ||
| 5364 | Expression zero = Expression.makeZero(ty); | ||
| 5365 | algorithm | ||
| 5366 | ✗ | nan := BINARY(zero, Operator.makeDiv(ty), zero); | |
| 5367 | end makeNaN; | ||
| 5368 | |||
| 5369 | function makeMaxValue | ||
| 5370 | input Type ty; | ||
| 5371 | output Expression exp; | ||
| 5372 | algorithm | ||
| 5373 | exp := match ty | ||
| 5374 | 22 | case Type.REAL() then REAL(System.realMaxLit()); | |
| 5375 | 4 | case Type.INTEGER() then INTEGER(System.intMaxLit()); | |
| 5376 | case Type.BOOLEAN() then BOOLEAN(true); | ||
| 5377 | 4 | case Type.ENUMERATION() then ENUM_LITERAL(ty, List.last(ty.literals), listLength(ty.literals)); | |
| 5378 | ✗ | case Type.ARRAY() then fillType(ty, makeMaxValue(Type.arrayElementType(ty))); | |
| 5379 | ✗ | else REAL(System.realMaxLit()); // backup case just for backend; | |
| 5380 | end match; | ||
| 5381 | end makeMaxValue; | ||
| 5382 | |||
| 5383 | function makeMinValue | ||
| 5384 | input Type ty; | ||
| 5385 | output Expression exp; | ||
| 5386 | algorithm | ||
| 5387 | exp := match ty | ||
| 5388 | 7 | case Type.REAL() then REAL(-System.realMaxLit()); | |
| 5389 | 4 | case Type.INTEGER() then INTEGER(-System.intMaxLit()); | |
| 5390 | case Type.BOOLEAN() then BOOLEAN(false); | ||
| 5391 | 4 | case Type.ENUMERATION() then ENUM_LITERAL(ty, listHead(ty.literals), 1); | |
| 5392 | ✗ | case Type.ARRAY() then fillType(ty, makeMinValue(Type.arrayElementType(ty))); | |
| 5393 | ✗ | else REAL(-System.realMaxLit()); // backup case just for backend; | |
| 5394 | end match; | ||
| 5395 | end makeMinValue; | ||
| 5396 | |||
| 5397 | function makeDefaultValue | ||
| 5398 | input Type ty; | ||
| 5399 | input Option<Expression> min = NONE(); | ||
| 5400 | input Option<Expression> max = NONE(); | ||
| 5401 | output Expression exp; | ||
| 5402 | algorithm | ||
| 5403 | exp := match ty | ||
| 5404 | case Type.INTEGER() | ||
| 5405 | algorithm | ||
| 5406 |
5/6✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 time.
✓ Branch 6 taken 1 time.
✓ Branch 7 taken 1 time.
|
3 | if isSome(min) and isNonNegative(Util.getOption(min)) then |
| 5407 | // default = min if min >= 0 | ||
| 5408 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
|
1 | SOME(exp) := min; |
| 5409 | elseif isSome(max) and isNonPositive(Util.getOption(max)) then | ||
| 5410 | // default = max if max <= 0 | ||
| 5411 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
|
1 | SOME(exp) := max; |
| 5412 | else | ||
| 5413 | exp := INTEGER(0); | ||
| 5414 | end if; | ||
| 5415 | then | ||
| 5416 | exp; | ||
| 5417 | |||
| 5418 | case Type.REAL() | ||
| 5419 | algorithm | ||
| 5420 |
5/6✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 time.
✓ Branch 6 taken 1 time.
✓ Branch 7 taken 1 time.
|
3 | if isSome(min) and isNonNegative(Util.getOption(min)) then |
| 5421 | // default = min if min >= 0.0 | ||
| 5422 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
|
1 | SOME(exp) := min; |
| 5423 | elseif isSome(max) and isNonPositive(Util.getOption(max)) then | ||
| 5424 | // default = max if max <= 0.0 | ||
| 5425 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
|
1 | SOME(exp) := max; |
| 5426 | else | ||
| 5427 | exp := REAL(0.0); | ||
| 5428 | end if; | ||
| 5429 | then | ||
| 5430 | exp; | ||
| 5431 | |||
| 5432 | case Type.STRING() then STRING(""); | ||
| 5433 | case Type.BOOLEAN() then BOOLEAN(false); | ||
| 5434 | |||
| 5435 | case Type.ENUMERATION() | ||
| 5436 | algorithm | ||
| 5437 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1 time.
|
2 | if isSome(min) then |
| 5438 | 1 | SOME(exp) := min; | |
| 5439 | else | ||
| 5440 | 1 | exp := ENUM_LITERAL(ty, listHead(ty.literals), 1); | |
| 5441 | end if; | ||
| 5442 | then | ||
| 5443 | exp; | ||
| 5444 | |||
| 5445 | ✗ | case Type.ARRAY() then fillType(ty, makeDefaultValue(Type.arrayElementType(ty))); | |
| 5446 | ✗ | case Type.TUPLE() then TUPLE(ty, list(makeDefaultValue(t) for t in ty.types)); | |
| 5447 | end match; | ||
| 5448 | end makeDefaultValue; | ||
| 5449 | |||
| 5450 | function box | ||
| 5451 | input Expression exp; | ||
| 5452 | output Expression boxedExp; | ||
| 5453 | algorithm | ||
| 5454 | boxedExp := match exp | ||
| 5455 | case STRING() then exp; | ||
| 5456 | case RECORD() | ||
| 5457 |
4/4✓ Branch 0 taken 30 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 3 times.
|
33 | then RECORD(exp.path, Type.box(exp.ty), list(box(e) for e in exp.elements)); |
| 5458 | case BOX() then exp; | ||
| 5459 | case FILENAME() then exp; | ||
| 5460 | 1775 | else BOX(exp); | |
| 5461 | end match; | ||
| 5462 | end box; | ||
| 5463 | |||
| 5464 | function unbox | ||
| 5465 | input Expression boxedExp; | ||
| 5466 | output Expression exp; | ||
| 5467 | algorithm | ||
| 5468 | exp := match boxedExp | ||
| 5469 | local | ||
| 5470 | Type ty; | ||
| 5471 | |||
| 5472 | 15 | case BOX() then boxedExp.exp; | |
| 5473 | |||
| 5474 | else | ||
| 5475 | algorithm | ||
| 5476 | 462 | ty := typeOf(boxedExp); | |
| 5477 |
2/2✓ Branch 1 taken 319 times.
✓ Branch 2 taken 143 times.
|
462 | then |
| 5478 | if Type.isBoxed(ty) then UNBOX(boxedExp, Type.unbox(ty)) else boxedExp; | ||
| 5479 | |||
| 5480 | end match; | ||
| 5481 | end unbox; | ||
| 5482 | |||
| 5483 | function isNegated | ||
| 5484 | input Expression exp; | ||
| 5485 | output Boolean negated; | ||
| 5486 | algorithm | ||
| 5487 | negated := match exp | ||
| 5488 | 63009 | case INTEGER() then exp.value < 0; | |
| 5489 | 160979 | case REAL() then exp.value < 0; | |
| 5490 | 2215 | case CAST() then isNegated(exp.exp); | |
| 5491 | case UNARY() then true; | ||
| 5492 | else false; | ||
| 5493 | end match; | ||
| 5494 | end isNegated; | ||
| 5495 | |||
| 5496 | function negate | ||
| 5497 | "Returns '-exp'" | ||
| 5498 | input output Expression exp; | ||
| 5499 | algorithm | ||
| 5500 | exp := match exp | ||
| 5501 | 10222 | case INTEGER() then INTEGER(-exp.value); | |
| 5502 | 384267 | case REAL() then REAL(-exp.value); | |
| 5503 | 2 | case CAST() then CAST(exp.ty, negate(exp.exp)); | |
| 5504 | 25508 | case UNARY() then exp.exp; | |
| 5505 | 147215 | else UNARY(Operator.makeUMinus(typeOf(exp)), exp); | |
| 5506 | end match; | ||
| 5507 | end negate; | ||
| 5508 | |||
| 5509 | function logicNegate | ||
| 5510 | "Returns 'not exp'" | ||
| 5511 | input Expression exp; | ||
| 5512 | output Expression outExp; | ||
| 5513 | algorithm | ||
| 5514 | outExp := match exp | ||
| 5515 | ✗ | case BOOLEAN() then BOOLEAN(not exp.value); | |
| 5516 | 33 | case LUNARY() then exp.exp; | |
| 5517 | 189 | else LUNARY(Operator.makeNot(typeOf(exp)), exp); | |
| 5518 | end match; | ||
| 5519 | end logicNegate; | ||
| 5520 | |||
| 5521 | function revertRange | ||
| 5522 | "reverts the direction of a range" | ||
| 5523 | input output Expression range; | ||
| 5524 | algorithm | ||
| 5525 | range := match range | ||
| 5526 | local | ||
| 5527 | Expression step; | ||
| 5528 | ✗ | case RANGE(step = SOME(step)) then RANGE(range.ty, range.stop, SOME(negate(step)), range.start); | |
| 5529 | 1 | case RANGE() then RANGE(range.ty, range.stop, SOME(INTEGER(-1)), range.start); | |
| 5530 | else algorithm | ||
| 5531 | ✗ | Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because expression is not a range:\n" | |
| 5532 | + toString(range)}); | ||
| 5533 | ✗ | then fail(); | |
| 5534 | end match; | ||
| 5535 | end revertRange; | ||
| 5536 | |||
| 5537 | function sliceRange | ||
| 5538 | "slices the range with a given zero-based start and one-based step" | ||
| 5539 | input output Expression range; | ||
| 5540 | input tuple<Integer, Integer, Integer> slice "start step stop"; | ||
| 5541 | algorithm | ||
| 5542 | range := match (range, slice) | ||
| 5543 | local | ||
| 5544 | Integer start, step, stop; | ||
| 5545 | Integer slice_start, slice_step, slice_stop; | ||
| 5546 | |||
| 5547 | case (RANGE(), (slice_start, slice_step, slice_stop)) algorithm | ||
| 5548 | ✗ | step := Util.applyOptionOrDefault(range.step, integerValue, 1); | |
| 5549 | ✗ | start := integerValue(range.start); | |
| 5550 | // shift start and stop accordingly, multiply step | ||
| 5551 | ✗ | stop := start + slice_stop * step; | |
| 5552 | ✗ | start := start + slice_start * step; | |
| 5553 | ✗ | step := slice_step * step; | |
| 5554 | ✗ | range := RANGE(range.ty, INTEGER(start), SOME(INTEGER(step)), INTEGER(stop)); | |
| 5555 | ✗ | then retype(range); | |
| 5556 | |||
| 5557 | else algorithm | ||
| 5558 | ✗ | Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed because expression is not a range:\n" | |
| 5559 | + toString(range)}); | ||
| 5560 | ✗ | then fail(); | |
| 5561 | end match; | ||
| 5562 | end sliceRange; | ||
| 5563 | |||
| 5564 | function arrayElements | ||
| 5565 | input Expression array; | ||
| 5566 | output array<Expression> elements; | ||
| 5567 | algorithm | ||
| 5568 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 121251 times.
|
121251 | ARRAY(elements = elements) := array; |
| 5569 | end arrayElements; | ||
| 5570 | |||
| 5571 | function arrayElementList | ||
| 5572 | input Expression array; | ||
| 5573 | output list<Expression> elements; | ||
| 5574 | algorithm | ||
| 5575 | elements := match array | ||
| 5576 | 49677 | case ARRAY() then arrayList(array.elements); | |
| 5577 | end match; | ||
| 5578 | end arrayElementList; | ||
| 5579 | |||
| 5580 | function arrayScalarElements | ||
| 5581 | input Expression exp; | ||
| 5582 | output list<Expression> elements; | ||
| 5583 | algorithm | ||
| 5584 | 1437 | elements := listReverseInPlace(arrayScalarElements_impl(exp, {})); | |
| 5585 | end arrayScalarElements; | ||
| 5586 | |||
| 5587 | function arrayScalarElements_impl | ||
| 5588 | input Expression exp; | ||
| 5589 | input output list<Expression> elements; | ||
| 5590 | algorithm | ||
| 5591 | elements := match exp | ||
| 5592 | case ARRAY() | ||
| 5593 | algorithm | ||
| 5594 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 4446 times.
✓ Branch 3 taken 7694 times.
✓ Branch 4 taken 4446 times.
|
16586 | for e in exp.elements loop |
| 5595 | 7694 | elements := arrayScalarElements_impl(e, elements); | |
| 5596 | end for; | ||
| 5597 | then | ||
| 5598 | elements; | ||
| 5599 | |||
| 5600 | else exp :: elements; | ||
| 5601 | end match; | ||
| 5602 | end arrayScalarElements_impl; | ||
| 5603 | |||
| 5604 | function arrayScalarElement | ||
| 5605 | input Expression arrayExp; | ||
| 5606 | output Expression scalarExp; | ||
| 5607 | algorithm | ||
| 5608 | scalarExp := match arrayExp | ||
| 5609 | case ARRAY() | ||
| 5610 | guard arrayLength(arrayExp.elements) == 1 | ||
| 5611 | then arrayGet(arrayExp.elements, 1); | ||
| 5612 | end match; | ||
| 5613 | end arrayScalarElement; | ||
| 5614 | |||
| 5615 | function hasArrayCall | ||
| 5616 | "Returns true if the given expression contains a function call that returns | ||
| 5617 | an array, otherwise false." | ||
| 5618 | input Expression exp; | ||
| 5619 | output Boolean hasArrayCall; | ||
| 5620 | algorithm | ||
| 5621 | 841425 | hasArrayCall := contains(exp, hasArrayCall2); | |
| 5622 | end hasArrayCall; | ||
| 5623 | |||
| 5624 | function hasArrayCall2 | ||
| 5625 | input Expression exp; | ||
| 5626 | output Boolean hasArrayCall; | ||
| 5627 | protected | ||
| 5628 | Call call; | ||
| 5629 | Type ty; | ||
| 5630 | algorithm | ||
| 5631 | hasArrayCall := match exp | ||
| 5632 | case CALL(call = call) | ||
| 5633 | algorithm | ||
| 5634 | 52950 | ty := Call.typeOf(call); | |
| 5635 |
4/4✓ Branch 1 taken 8444 times.
✓ Branch 2 taken 44506 times.
✓ Branch 4 taken 1399 times.
✓ Branch 5 taken 7045 times.
|
52950 | then |
| 5636 | Type.isArray(ty) and Call.isVectorizeable(call); | ||
| 5637 | |||
| 5638 | case TUPLE_ELEMENT(tupleExp = CALL(call = call)) | ||
| 5639 | algorithm | ||
| 5640 | 11 | ty := Type.nthTupleType(Call.typeOf(call), exp.index); | |
| 5641 |
3/4✓ Branch 1 taken 8 times.
✓ Branch 2 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 8 times.
|
11 | then |
| 5642 | Type.isArray(ty) and Call.isVectorizeable(call); | ||
| 5643 | |||
| 5644 | else false; | ||
| 5645 | end match; | ||
| 5646 | end hasArrayCall2; | ||
| 5647 | |||
| 5648 | function transposeArray | ||
| 5649 | input Expression arrayExp; | ||
| 5650 | output Expression outExp; | ||
| 5651 | protected | ||
| 5652 | Dimension dim1, dim2; | ||
| 5653 | list<Dimension> rest_dims; | ||
| 5654 | Type ty, row_ty; | ||
| 5655 | Boolean literal; | ||
| 5656 | array<Expression> arr; | ||
| 5657 | array<array<Expression>> matrix_arr; | ||
| 5658 | algorithm | ||
| 5659 | outExp := match arrayExp | ||
| 5660 | case ARRAY(Type.ARRAY(ty, dim1 :: dim2 :: rest_dims), arr, literal) | ||
| 5661 | algorithm | ||
| 5662 |
1/2✓ Branch 0 taken 1246 times.
✗ Branch 1 not taken.
|
1246 | if not arrayEmpty(arr) then |
| 5663 | 1246 | row_ty := Type.ARRAY(ty, dim1 :: rest_dims); | |
| 5664 | 1246 | matrix_arr := Array.map(arr, arrayElements); | |
| 5665 | 1246 | matrix_arr := Array.transpose(matrix_arr); | |
| 5666 |
2/2✓ Branch 0 taken 1220 times.
✓ Branch 1 taken 26 times.
|
2466 | arr := Array.map(matrix_arr, function makeArray(ty = row_ty, literal = literal)); |
| 5667 | end if; | ||
| 5668 | 1246 | then | |
| 5669 | makeArray(Type.ARRAY(ty, dim2 :: dim1 :: rest_dims), arr, literal); | ||
| 5670 | end match; | ||
| 5671 | end transposeArray; | ||
| 5672 | |||
| 5673 | function makeIdentityMatrix | ||
| 5674 | input Integer n; | ||
| 5675 | input Type elementType; | ||
| 5676 | output Expression matrix; | ||
| 5677 | protected | ||
| 5678 | array<Expression> row, rows; | ||
| 5679 | Expression zero, one; | ||
| 5680 | Type row_ty; | ||
| 5681 | algorithm | ||
| 5682 | 1112 | zero := makeZero(elementType); | |
| 5683 | 1112 | one := makeOne(elementType); | |
| 5684 | |||
| 5685 | 1112 | rows := arrayCreateNoInit(n, zero); | |
| 5686 | 2224 | row_ty := Type.ARRAY(elementType, {Dimension.fromInteger(n)}); | |
| 5687 | |||
| 5688 |
1/2✓ Branch 0 taken 1112 times.
✗ Branch 1 not taken.
|
4446 | for i in 1:n loop |
| 5689 | 3334 | row := arrayCreateNoInit(n, zero); | |
| 5690 | |||
| 5691 | 10000 | for j in 1:n loop | |
| 5692 |
2/2✓ Branch 0 taken 6666 times.
✓ Branch 1 taken 3334 times.
|
10000 | arrayUpdateNoBoundsChecking(row, j, if i == j then one else zero); |
| 5693 | end for; | ||
| 5694 | |||
| 5695 | 3334 | arrayUpdateNoBoundsChecking(rows, i, makeArray(row_ty, row, true)); | |
| 5696 | end for; | ||
| 5697 | |||
| 5698 | 1112 | matrix := makeExpArray(rows, row_ty, true); | |
| 5699 | end makeIdentityMatrix; | ||
| 5700 | |||
| 5701 | |||
| 5702 | // Upper-triangular mask (including diagonal) as a literal matrix. | ||
| 5703 | // Mask U[i,j] = 1 if i <= j else 0 | ||
| 5704 | function makeTriuMask | ||
| 5705 | input Integer n; | ||
| 5706 | input Type elTy; | ||
| 5707 | output Expression mask; | ||
| 5708 | protected | ||
| 5709 | array<Expression> row, rows; | ||
| 5710 | Expression zero, one; | ||
| 5711 | Type row_ty; | ||
| 5712 | Integer i, j; | ||
| 5713 | algorithm | ||
| 5714 | ✗ | zero := Expression.makeZero(elTy); | |
| 5715 | ✗ | one := Expression.makeOne(elTy); | |
| 5716 | |||
| 5717 | ✗ | rows := arrayCreateNoInit(n, zero); | |
| 5718 | ✗ | row_ty := Type.ARRAY(elTy, {Dimension.fromInteger(n)}); | |
| 5719 | |||
| 5720 | ✗ | for i in 1:n loop | |
| 5721 | ✗ | row := arrayCreateNoInit(n, zero); | |
| 5722 | |||
| 5723 | ✗ | for j in 1:n loop | |
| 5724 | ✗ | arrayUpdateNoBoundsChecking(row, j, if i <= j then one else zero); | |
| 5725 | end for; | ||
| 5726 | |||
| 5727 | ✗ | arrayUpdateNoBoundsChecking(rows, i, Expression.makeArray(row_ty, row, true)); | |
| 5728 | end for; | ||
| 5729 | |||
| 5730 | ✗ | mask := Expression.makeExpArray(rows, row_ty, true); | |
| 5731 | end makeTriuMask; | ||
| 5732 | |||
| 5733 | function promote | ||
| 5734 | input output Expression e; | ||
| 5735 | input output Type ty; | ||
| 5736 | input Integer n; | ||
| 5737 | protected | ||
| 5738 | list<Dimension> dims; | ||
| 5739 | Type ety; | ||
| 5740 | list<Type> tys = {}; | ||
| 5741 | Boolean is_array; | ||
| 5742 | algorithm | ||
| 5743 | // Construct the dimensions that needs to be added. | ||
| 5744 |
2/2✓ Branch 2 taken 36310 times.
✓ Branch 3 taken 24325 times.
|
60635 | dims := list(Dimension.fromInteger(1) for i in Type.dimensionCount(ty):n-1); |
| 5745 | |||
| 5746 |
2/2✓ Branch 0 taken 5652 times.
✓ Branch 1 taken 18673 times.
|
24325 | if not listEmpty(dims) then |
| 5747 | // Concatenate the existing dimensions and the added ones. | ||
| 5748 | 18673 | dims := listAppend(Type.arrayDims(ty), dims); | |
| 5749 | |||
| 5750 | // Construct the result type. | ||
| 5751 | 18673 | is_array := Type.isArray(ty); | |
| 5752 | 18673 | ety := Type.arrayElementType(ty); | |
| 5753 | 18673 | ty := Type.liftArrayLeftList(ety, dims); | |
| 5754 | |||
| 5755 | // Construct the expression types, to avoid having to create a new type | ||
| 5756 | // for each subexpression that will be created. | ||
| 5757 |
2/2✓ Branch 0 taken 37346 times.
✓ Branch 1 taken 18673 times.
|
56019 | while not listEmpty(dims) loop |
| 5758 | 37346 | tys := Type.liftArrayLeftList(ety, dims) :: tys; | |
| 5759 | 37346 | dims := listRest(dims); | |
| 5760 | end while; | ||
| 5761 | |||
| 5762 | 18673 | e := promote2(e, is_array, n, listReverse(tys)); | |
| 5763 | end if; | ||
| 5764 | end promote; | ||
| 5765 | |||
| 5766 | function promote2 | ||
| 5767 | input Expression exp; | ||
| 5768 | input Boolean isArray; | ||
| 5769 | input Integer dims; | ||
| 5770 | input list<Type> types; | ||
| 5771 | output Expression outExp = exp; | ||
| 5772 | algorithm | ||
| 5773 | outExp := match (exp, types) | ||
| 5774 | local | ||
| 5775 | Type ty; | ||
| 5776 | list<Type> rest_ty; | ||
| 5777 | Boolean expanded; | ||
| 5778 | |||
| 5779 | // No types left, we're done! | ||
| 5780 | case (_, {}) then exp; | ||
| 5781 | |||
| 5782 | // An array, promote each element in the array. | ||
| 5783 | case (ARRAY(), ty :: rest_ty) | ||
| 5784 | 845 | then makeArray(ty, Array.map(exp.elements, | |
| 5785 | function promote2(isArray = false, dims = dims, types = rest_ty))); | ||
| 5786 | |||
| 5787 | // An expression with array type, but which is not an array expression. | ||
| 5788 | // Such an expression can't be promoted here, so we create a promote call instead. | ||
| 5789 | case (_, _) guard isArray | ||
| 5790 | algorithm | ||
| 5791 |
3/4✓ Branch 1 taken 8 times.
✓ Branch 2 taken 859 times.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
|
867 | if Flags.getConfigBool(Flags.NEW_BACKEND) and not Expression.isLiteral(exp) then |
| 5792 | 8 | expanded := false; | |
| 5793 | else | ||
| 5794 | 859 | (outExp, expanded) := ExpandExp.expand(exp); | |
| 5795 | end if; | ||
| 5796 | |||
| 5797 | // The ARRAY case above is what consumes the expansion; recursing on | ||
| 5798 | // anything else would not terminate. | ||
| 5799 |
3/4✓ Branch 0 taken 676 times.
✓ Branch 1 taken 191 times.
✓ Branch 3 taken 676 times.
✗ Branch 4 not taken.
|
867 | if expanded and isArray(outExp) then |
| 5800 | 676 | outExp := promote2(outExp, true, dims, types); | |
| 5801 | else | ||
| 5802 | 382 | outExp := CALL(Call.makeTypedCall( | |
| 5803 | NFBuiltinFuncs.PROMOTE, {exp, INTEGER(dims)}, variability(exp), purity(exp), listHead(types))); | ||
| 5804 | end if; | ||
| 5805 | then | ||
| 5806 | outExp; | ||
| 5807 | |||
| 5808 | // A scalar expression, promote it as many times as the number of types given. | ||
| 5809 | else | ||
| 5810 | algorithm | ||
| 5811 | outExp := exp; | ||
| 5812 |
2/2✓ Branch 1 taken 38250 times.
✓ Branch 2 taken 20613 times.
|
58863 | for ty in listReverse(types) loop |
| 5813 | 38250 | outExp := makeArray(ty, arrayCreate(1, outExp)); | |
| 5814 | end for; | ||
| 5815 | then | ||
| 5816 | outExp; | ||
| 5817 | |||
| 5818 | end match; | ||
| 5819 | end promote2; | ||
| 5820 | |||
| 5821 | function variability | ||
| 5822 | input Expression exp; | ||
| 5823 | output Variability var; | ||
| 5824 | algorithm | ||
| 5825 | var := match exp | ||
| 5826 | case INTEGER() then Variability.CONSTANT; | ||
| 5827 | case REAL() then Variability.CONSTANT; | ||
| 5828 | case STRING() then Variability.CONSTANT; | ||
| 5829 | case BOOLEAN() then Variability.CONSTANT; | ||
| 5830 | case ENUM_LITERAL() then Variability.CONSTANT; | ||
| 5831 | case CLKCONST() then Variability.DISCRETE; | ||
| 5832 | 6088175 | case CREF() then ComponentRef.variability(exp.cref); | |
| 5833 | case TYPENAME() then Variability.CONSTANT; | ||
| 5834 | 289 | case ARRAY() then variabilityArray(exp.elements); | |
| 5835 | ✗ | case MATRIX() then List.fold(exp.elements, variabilityList, Variability.CONSTANT); | |
| 5836 | |||
| 5837 | case RANGE() | ||
| 5838 | algorithm | ||
| 5839 | 5 | var := variability(exp.start); | |
| 5840 | 5 | var := Prefixes.variabilityMax(var, variability(exp.stop)); | |
| 5841 | |||
| 5842 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 3 times.
|
5 | if isSome(exp.step) then |
| 5843 | 2 | var := Prefixes.variabilityMax(var, variability(Util.getOption(exp.step))); | |
| 5844 | end if; | ||
| 5845 | then | ||
| 5846 | var; | ||
| 5847 | |||
| 5848 | ✗ | case TUPLE() then variabilityList(exp.elements); | |
| 5849 | 76 | case RECORD() then variabilityList(exp.elements); | |
| 5850 | 7306 | case CALL() then Call.variability(exp.call); | |
| 5851 | case SIZE() | ||
| 5852 | algorithm | ||
| 5853 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 2019 times.
✓ Branch 2 taken 2019 times.
✗ Branch 3 not taken.
|
2019 | if isSome(exp.dimIndex) then |
| 5854 | 2019 | var := Prefixes.variabilityMax(Variability.PARAMETER, | |
| 5855 | variability(Util.getOption(exp.dimIndex))); | ||
| 5856 | else | ||
| 5857 | var := Variability.PARAMETER; | ||
| 5858 | end if; | ||
| 5859 | then | ||
| 5860 | var; | ||
| 5861 | |||
| 5862 | case END() then Variability.PARAMETER; | ||
| 5863 | 1409717 | case MULTARY() then Prefixes.variabilityMax(variabilityList(exp.arguments), variabilityList(exp.arguments)); | |
| 5864 | 6278522 | case BINARY() then Prefixes.variabilityMax(variability(exp.exp1), variability(exp.exp2)); | |
| 5865 | 1135 | case UNARY() then variability(exp.exp); | |
| 5866 | 495 | case LBINARY() then Prefixes.variabilityMax(variability(exp.exp1), variability(exp.exp2)); | |
| 5867 | 75 | case LUNARY() then variability(exp.exp); | |
| 5868 | case RELATION() | ||
| 5869 | 5898 | then Prefixes.variabilityMin( | |
| 5870 | Prefixes.variabilityMax(variability(exp.exp1), variability(exp.exp2)), | ||
| 5871 | Variability.DISCRETE); | ||
| 5872 | |||
| 5873 | case IF() | ||
| 5874 | 949 | then Prefixes.variabilityMax(variability(exp.condition), | |
| 5875 | Prefixes.variabilityMax(variability(exp.trueBranch), variability(exp.falseBranch))); | ||
| 5876 | |||
| 5877 | 23 | case CAST() then variability(exp.exp); | |
| 5878 | ✗ | case BOX() then variability(exp.exp); | |
| 5879 | ✗ | case UNBOX() then variability(exp.exp); | |
| 5880 | case SUBSCRIPTED_EXP() | ||
| 5881 | 204 | then Prefixes.variabilityMax(variability(exp.exp), Subscript.variabilityList(exp.subscripts)); | |
| 5882 | 6 | case TUPLE_ELEMENT() then variability(exp.tupleExp); | |
| 5883 | 114 | case RECORD_ELEMENT() then variability(exp.recordExp); | |
| 5884 | ✗ | case MUTABLE() then variability(Mutable.access(exp.exp)); | |
| 5885 | ✗ | case SHARED_LITERAL() then variability(exp.exp); | |
| 5886 | case EMPTY() then Variability.CONSTANT; | ||
| 5887 | case PARTIAL_FUNCTION_APPLICATION() then Variability.CONTINUOUS; | ||
| 5888 | case FILENAME() then Variability.CONSTANT; | ||
| 5889 | case INSTANCE_NAME() then Variability.CONSTANT; | ||
| 5890 | else | ||
| 5891 | algorithm | ||
| 5892 | ✗ | Error.terminate(getInstanceName() + " got unknown expression.", sourceInfo()); | |
| 5893 | ✗ | then | |
| 5894 | fail(); | ||
| 5895 | end match; | ||
| 5896 | end variability; | ||
| 5897 | |||
| 5898 | function variabilityArray | ||
| 5899 | input array<Expression> expl; | ||
| 5900 | input output Variability var = Variability.CONSTANT; | ||
| 5901 | algorithm | ||
| 5902 |
2/2✓ Branch 1 taken 3291 times.
✓ Branch 2 taken 289 times.
|
3580 | for e in expl loop |
| 5903 | 3291 | var := Prefixes.variabilityMax(var, variability(e)); | |
| 5904 | end for; | ||
| 5905 | end variabilityArray; | ||
| 5906 | |||
| 5907 | function variabilityList | ||
| 5908 | input list<Expression> expl; | ||
| 5909 | input output Variability var = Variability.CONSTANT; | ||
| 5910 | algorithm | ||
| 5911 |
2/2✓ Branch 0 taken 5620712 times.
✓ Branch 1 taken 2819510 times.
|
8440222 | for e in expl loop |
| 5912 | 5620712 | var := Prefixes.variabilityMax(var, variability(e)); | |
| 5913 | end for; | ||
| 5914 | end variabilityList; | ||
| 5915 | |||
| 5916 | function purity | ||
| 5917 | input Expression exp; | ||
| 5918 | output Purity pur; | ||
| 5919 | algorithm | ||
| 5920 | pur := match exp | ||
| 5921 | case INTEGER() then Purity.PURE; | ||
| 5922 | case REAL() then Purity.PURE; | ||
| 5923 | case STRING() then Purity.PURE; | ||
| 5924 | case BOOLEAN() then Purity.PURE; | ||
| 5925 | case ENUM_LITERAL() then Purity.PURE; | ||
| 5926 | case CLKCONST() then Purity.PURE; | ||
| 5927 | 29552 | case CREF() then ComponentRef.purity(exp.cref); | |
| 5928 | case TYPENAME() then Purity.PURE; | ||
| 5929 | 25 | case ARRAY() then purityArray(exp.elements); | |
| 5930 | ✗ | case MATRIX() then List.fold(exp.elements, purityList, Purity.PURE); | |
| 5931 | |||
| 5932 | case RANGE() | ||
| 5933 | algorithm | ||
| 5934 | 5882 | pur := purity(exp.start); | |
| 5935 | 5882 | pur := Prefixes.purityMin(pur, purity(exp.stop)); | |
| 5936 | |||
| 5937 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 5882 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 5880 times.
|
5882 | if isSome(exp.step) then |
| 5938 | 2 | pur := Prefixes.purityMin(pur, purity(Util.getOption(exp.step))); | |
| 5939 | end if; | ||
| 5940 | then | ||
| 5941 | pur; | ||
| 5942 | |||
| 5943 | ✗ | case TUPLE() then purityList(exp.elements); | |
| 5944 | 75 | case RECORD() then purityList(exp.elements); | |
| 5945 | 158 | case CALL() then Call.purity(exp.call); | |
| 5946 | case SIZE() | ||
| 5947 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
✓ Branch 2 taken 63 times.
✗ Branch 3 not taken.
|
63 | then if isSome(exp.dimIndex) then purity(Util.getOption(exp.dimIndex)) else Purity.PURE; |
| 5948 | |||
| 5949 | case END() then Purity.PURE; | ||
| 5950 | 6766 | case BINARY() then Prefixes.purityMin(purity(exp.exp1), purity(exp.exp2)); | |
| 5951 | 233 | case UNARY() then purity(exp.exp); | |
| 5952 | ✗ | case LBINARY() then Prefixes.purityMin(purity(exp.exp1), purity(exp.exp2)); | |
| 5953 | 15 | case LUNARY() then purity(exp.exp); | |
| 5954 | 68 | case RELATION() then Prefixes.purityMin(purity(exp.exp1), purity(exp.exp2)); | |
| 5955 | 89 | case MULTARY() then Prefixes.purityMin(purityList(exp.arguments), purityList(exp.inv_arguments)); | |
| 5956 | 71 | case IF() then Prefixes.purityMin(purity(exp.condition), | |
| 5957 | Prefixes.purityMin(purity(exp.trueBranch), purity(exp.falseBranch))); | ||
| 5958 | 16 | case CAST() then purity(exp.exp); | |
| 5959 | ✗ | case BOX() then purity(exp.exp); | |
| 5960 | ✗ | case UNBOX() then purity(exp.exp); | |
| 5961 | case SUBSCRIPTED_EXP() | ||
| 5962 | 183 | then Prefixes.purityMin(purity(exp.exp), Subscript.purityList(exp.subscripts)); | |
| 5963 | ✗ | case TUPLE_ELEMENT() then purity(exp.tupleExp); | |
| 5964 | 60 | case RECORD_ELEMENT() then purity(exp.recordExp); | |
| 5965 | ✗ | case MUTABLE() then purity(Mutable.access(exp.exp)); | |
| 5966 | ✗ | case SHARED_LITERAL() then purity(exp.exp); | |
| 5967 | case EMPTY() then Purity.PURE; | ||
| 5968 | case PARTIAL_FUNCTION_APPLICATION() then Purity.PURE; | ||
| 5969 | case FILENAME() then Purity.PURE; | ||
| 5970 | case INSTANCE_NAME() then Purity.PURE; | ||
| 5971 | else | ||
| 5972 | algorithm | ||
| 5973 | ✗ | Error.terminate(getInstanceName() + " got unknown expression.", sourceInfo()); | |
| 5974 | ✗ | then | |
| 5975 | fail(); | ||
| 5976 | end match; | ||
| 5977 | end purity; | ||
| 5978 | |||
| 5979 | function purityArray | ||
| 5980 | input array<Expression> expl; | ||
| 5981 | input output Purity pur = Purity.PURE; | ||
| 5982 | algorithm | ||
| 5983 |
2/2✓ Branch 1 taken 77 times.
✓ Branch 2 taken 25 times.
|
102 | for e in expl loop |
| 5984 | 77 | pur := Prefixes.purityMin(pur, purity(e)); | |
| 5985 | end for; | ||
| 5986 | end purityArray; | ||
| 5987 | |||
| 5988 | function purityList | ||
| 5989 | input list<Expression> expl; | ||
| 5990 | input output Purity pur = Purity.PURE; | ||
| 5991 | algorithm | ||
| 5992 |
2/2✓ Branch 0 taken 548 times.
✓ Branch 1 taken 253 times.
|
801 | for e in expl loop |
| 5993 | 548 | pur := Prefixes.purityMin(pur, purity(e)); | |
| 5994 | end for; | ||
| 5995 | end purityList; | ||
| 5996 | |||
| 5997 | function makeMutable | ||
| 5998 | input Expression exp; | ||
| 5999 | output Expression outExp; | ||
| 6000 | algorithm | ||
| 6001 | 134325 | outExp := MUTABLE(Mutable.create(exp)); | |
| 6002 | end makeMutable; | ||
| 6003 | |||
| 6004 | function makeImmutable | ||
| 6005 | input Expression exp; | ||
| 6006 | output Expression outExp; | ||
| 6007 | algorithm | ||
| 6008 | outExp := match exp | ||
| 6009 | 117371 | case MUTABLE() then Mutable.access(exp.exp); | |
| 6010 | else exp; | ||
| 6011 | end match; | ||
| 6012 | end makeImmutable; | ||
| 6013 | |||
| 6014 | function isMutable | ||
| 6015 | input Expression exp; | ||
| 6016 | output Boolean isMutable; | ||
| 6017 | algorithm | ||
| 6018 | isMutable := match exp | ||
| 6019 | case MUTABLE() then true; | ||
| 6020 | else false; | ||
| 6021 | end match; | ||
| 6022 | end isMutable; | ||
| 6023 | |||
| 6024 | function updateMutable | ||
| 6025 | input Expression mutableExp; | ||
| 6026 | input Expression value; | ||
| 6027 | protected | ||
| 6028 | Mutable<Expression> exp_ptr; | ||
| 6029 | algorithm | ||
| 6030 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
|
38 | MUTABLE(exp = exp_ptr) := mutableExp; |
| 6031 | 38 | Mutable.update(exp_ptr, value); | |
| 6032 | end updateMutable; | ||
| 6033 | |||
| 6034 | function applyMutable | ||
| 6035 | input Expression mutableExp; | ||
| 6036 | input FuncType func; | ||
| 6037 | |||
| 6038 | partial function FuncType | ||
| 6039 | input output Expression exp; | ||
| 6040 | end FuncType; | ||
| 6041 | protected | ||
| 6042 | Mutable<Expression> exp_ptr; | ||
| 6043 | algorithm | ||
| 6044 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 133747 times.
|
133747 | MUTABLE(exp = exp_ptr) := mutableExp; |
| 6045 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 133747 times.
|
133747 | Mutable.update(exp_ptr, func(Mutable.access(exp_ptr))); |
| 6046 | end applyMutable; | ||
| 6047 | |||
| 6048 | function isEmpty | ||
| 6049 | input Expression exp; | ||
| 6050 | output Boolean empty; | ||
| 6051 | algorithm | ||
| 6052 | empty := match exp | ||
| 6053 | case EMPTY() then true; | ||
| 6054 | else false; | ||
| 6055 | end match; | ||
| 6056 | end isEmpty; | ||
| 6057 | |||
| 6058 | function isEnd | ||
| 6059 | input Expression exp; | ||
| 6060 | output Boolean isend; | ||
| 6061 | algorithm | ||
| 6062 | isend := match exp | ||
| 6063 | case END() then true; | ||
| 6064 | else false; | ||
| 6065 | end match; | ||
| 6066 | end isEnd; | ||
| 6067 | |||
| 6068 | function enumIndexExp | ||
| 6069 | input Expression enumExp; | ||
| 6070 | output Expression indexExp; | ||
| 6071 | algorithm | ||
| 6072 | indexExp := match enumExp | ||
| 6073 | ✗ | case ENUM_LITERAL() then INTEGER(enumExp.index); | |
| 6074 | ✗ | else CALL(Call.makeTypedCall( | |
| 6075 | NFBuiltinFuncs.INTEGER_ENUM, {enumExp}, variability(enumExp), Purity.PURE)); | ||
| 6076 | end match; | ||
| 6077 | end enumIndexExp; | ||
| 6078 | |||
| 6079 | function toScalar | ||
| 6080 | input Expression exp; | ||
| 6081 | output Expression outExp; | ||
| 6082 | algorithm | ||
| 6083 | outExp := match exp | ||
| 6084 | case ARRAY() | ||
| 6085 | guard arrayLength(exp.elements) == 1 | ||
| 6086 | ✗ | then toScalar(arrayGet(exp.elements, 1)); | |
| 6087 | else exp; | ||
| 6088 | end match; | ||
| 6089 | end toScalar; | ||
| 6090 | |||
| 6091 | function tupleElement | ||
| 6092 | input Expression exp; | ||
| 6093 | input Integer index; | ||
| 6094 | output Expression tupleElem; | ||
| 6095 | algorithm | ||
| 6096 | tupleElem := match exp | ||
| 6097 | 7 | case TUPLE() then listGet(exp.elements, index); | |
| 6098 | |||
| 6099 | case ARRAY() | ||
| 6100 | algorithm | ||
| 6101 | ✗ | exp.elements := Array.map(exp.elements, function tupleElement(index = index)); | |
| 6102 | then | ||
| 6103 | exp; | ||
| 6104 | |||
| 6105 | case SUBSCRIPTED_EXP(split = true) | ||
| 6106 | ✗ | then mapSplitExpressions(exp, function tupleElement(index = index)); | |
| 6107 | |||
| 6108 | 1853 | else TUPLE_ELEMENT(exp, index, Type.nthTupleType(typeOf(exp), index)); | |
| 6109 | end match; | ||
| 6110 | end tupleElement; | ||
| 6111 | |||
| 6112 | function recordElement | ||
| 6113 | "Returns the field with the given name in a record expression. If the | ||
| 6114 | expression is an array it will return the equivalent of calling the | ||
| 6115 | function on each element of the array." | ||
| 6116 | input String elementName; | ||
| 6117 | input Expression recordExp; | ||
| 6118 | output Expression outExp; | ||
| 6119 | algorithm | ||
| 6120 | outExp := match recordExp | ||
| 6121 | local | ||
| 6122 | InstNode node; | ||
| 6123 | Class cls; | ||
| 6124 | ClassTree cls_tree; | ||
| 6125 | Type ty; | ||
| 6126 | Integer index; | ||
| 6127 | ComponentRef cref; | ||
| 6128 | array<Expression> arr; | ||
| 6129 | |||
| 6130 | case RECORD(ty = Type.COMPLEX()) | ||
| 6131 | algorithm | ||
| 6132 | 174271 | node := Type.complexNode(recordExp.ty); | |
| 6133 | 174271 | cls := InstNode.getClass(node); | |
| 6134 | 174271 | index := Class.lookupComponentIndex(elementName, cls); | |
| 6135 | 174271 | then | |
| 6136 | listGet(recordExp.elements, index); | ||
| 6137 | |||
| 6138 | case CREF() | ||
| 6139 | algorithm | ||
| 6140 | 1129 | node := Type.complexNode(Type.arrayElementType(recordExp.ty)); | |
| 6141 | 1129 | cls_tree := Class.classTree(InstNode.getClass(node)); | |
| 6142 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1129 times.
|
1129 | (node, false) := ClassTree.lookupElement(elementName, cls_tree); |
| 6143 | 1129 | ty := InstNode.getType(node); | |
| 6144 | 1129 | cref := ComponentRef.prefixCref(node, ty, {}, recordExp.cref); | |
| 6145 | 1129 | ty := Type.liftArrayLeftList(ty, Type.arrayDims(recordExp.ty)); | |
| 6146 | 1129 | then | |
| 6147 | CREF(ty, cref); | ||
| 6148 | |||
| 6149 | case ARRAY(ty = Type.ARRAY(elementType = Type.COMPLEX())) | ||
| 6150 | guard arrayEmpty(recordExp.elements) | ||
| 6151 | algorithm | ||
| 6152 | ✗ | node := Type.complexNode(Type.arrayElementType(recordExp.ty)); | |
| 6153 | ✗ | cls := InstNode.getClass(node); | |
| 6154 | ✗ | index := Class.lookupComponentIndex(elementName, cls); | |
| 6155 | ✗ | ty := InstNode.getType(Class.nthComponent(index, cls)); | |
| 6156 | ✗ | ty := Type.liftArrayLeftList(ty, Type.arrayDims(recordExp.ty)); | |
| 6157 | ✗ | then | |
| 6158 | makeEmptyArray(ty); | ||
| 6159 | |||
| 6160 | case ARRAY(ty = Type.ARRAY(elementType = Type.COMPLEX())) | ||
| 6161 | algorithm | ||
| 6162 | 366 | node := Type.complexNode(Type.arrayElementType(recordExp.ty)); | |
| 6163 | 366 | index := Class.lookupComponentIndex(elementName, InstNode.getClass(node)); | |
| 6164 | 366 | arr := Array.map(recordExp.elements, function nthRecordElement(index = index)); | |
| 6165 | 732 | ty := Type.liftArrayLeft(typeOf(arrayGet(arr, 1)), | |
| 6166 | Dimension.fromInteger(arrayLength(arr))); | ||
| 6167 | 366 | then | |
| 6168 | makeArray(ty, arr, recordExp.literal); | ||
| 6169 | |||
| 6170 | case SUBSCRIPTED_EXP() | ||
| 6171 | algorithm | ||
| 6172 | 305 | outExp := recordElement(elementName, recordExp.exp); | |
| 6173 | 305 | ty := Type.subscript(typeOf(outExp), recordExp.subscripts); | |
| 6174 | 305 | then | |
| 6175 | SUBSCRIPTED_EXP(outExp, recordExp.subscripts, ty, recordExp.split); | ||
| 6176 | |||
| 6177 | ✗ | case EMPTY() then fail(); | |
| 6178 | |||
| 6179 | else | ||
| 6180 | algorithm | ||
| 6181 | 1192 | ty := typeOf(recordExp); | |
| 6182 | 1192 | node := Type.complexNode(Type.arrayElementType(ty)); | |
| 6183 | 1192 | cls := InstNode.getClass(node); | |
| 6184 | 1192 | index := Class.lookupComponentIndex(elementName, cls); | |
| 6185 | 1192 | ty := Type.liftArrayLeftList( | |
| 6186 | InstNode.getType(Class.nthComponent(index, cls)), | ||
| 6187 | Type.arrayDims(ty)); | ||
| 6188 | 1192 | then | |
| 6189 | RECORD_ELEMENT(recordExp, index, elementName, ty); | ||
| 6190 | |||
| 6191 | end match; | ||
| 6192 | end recordElement; | ||
| 6193 | |||
| 6194 | function nthRecordElement | ||
| 6195 | "Returns the nth field of a record expression. If the expression is an array | ||
| 6196 | it will return an array with the nth field in each array element." | ||
| 6197 | input Integer index; | ||
| 6198 | input Expression recordExp; | ||
| 6199 | output Expression outExp; | ||
| 6200 | algorithm | ||
| 6201 | outExp := match recordExp | ||
| 6202 | local | ||
| 6203 | InstNode node; | ||
| 6204 | Type ty; | ||
| 6205 | array<Expression> arr; | ||
| 6206 | Expression trueBranch, falseBranch; | ||
| 6207 | |||
| 6208 | 241 | case RECORD() then listGet(recordExp.elements, index); | |
| 6209 | |||
| 6210 | case CREF() | ||
| 6211 | algorithm | ||
| 6212 | 2187 | node := Type.complexNode(Type.arrayElementType(typeOf(recordExp))); | |
| 6213 | 2187 | node := Class.nthComponent(index, InstNode.getClass(node)); | |
| 6214 | 2187 | then | |
| 6215 | fromCref(ComponentRef.prefixCref(node, InstNode.getType(node), {}, recordExp.cref)); | ||
| 6216 | |||
| 6217 | case ARRAY(ty = Type.ARRAY(elementType = Type.COMPLEX())) | ||
| 6218 | guard arrayEmpty(recordExp.elements) | ||
| 6219 | 6 | then makeEmptyArray(InstNode.getType(Class.nthComponent(index, | |
| 6220 | InstNode.getClass(Type.complexNode(Type.arrayElementType(recordExp.ty)))))); | ||
| 6221 | |||
| 6222 | case ARRAY() | ||
| 6223 | algorithm | ||
| 6224 | 35 | arr := Array.map(recordExp.elements, function nthRecordElement(index = index)); | |
| 6225 | 70 | ty := Type.liftArrayLeft(typeOf(arrayGet(arr, 1)), listHead(Type.arrayDims(recordExp.ty))); | |
| 6226 | 35 | then | |
| 6227 | makeArray(ty, arr); | ||
| 6228 | |||
| 6229 | case RECORD_ELEMENT(ty = Type.ARRAY(elementType = Type.COMPLEX())) | ||
| 6230 | algorithm | ||
| 6231 | ✗ | node := Type.complexNode(Type.arrayElementType(recordExp.ty)); | |
| 6232 | ✗ | node := Class.nthComponent(index, InstNode.getClass(node)); | |
| 6233 | ✗ | then | |
| 6234 | RECORD_ELEMENT(recordExp, index, InstNode.name(node), | ||
| 6235 | Type.liftArrayLeftList(InstNode.getType(node), Type.arrayDims(recordExp.ty))); | ||
| 6236 | |||
| 6237 | case SUBSCRIPTED_EXP() | ||
| 6238 | algorithm | ||
| 6239 | ✗ | outExp := nthRecordElement(index, recordExp.exp); | |
| 6240 | ✗ | ty := Type.subscript(typeOf(outExp), recordExp.subscripts); | |
| 6241 | ✗ | then | |
| 6242 | SUBSCRIPTED_EXP(outExp, recordExp.subscripts, ty, recordExp.split); | ||
| 6243 | |||
| 6244 | case IF() | ||
| 6245 | algorithm | ||
| 6246 | ✗ | trueBranch := nthRecordElement(index, recordExp.trueBranch); | |
| 6247 | ✗ | falseBranch := nthRecordElement(index, recordExp.falseBranch); | |
| 6248 | ✗ | then | |
| 6249 | IF(typeOf(trueBranch), recordExp.condition, trueBranch, falseBranch); | ||
| 6250 | |||
| 6251 | else | ||
| 6252 | algorithm | ||
| 6253 | 199 | node := Type.complexNode(typeOf(recordExp)); | |
| 6254 | 199 | node := Class.nthComponent(index, InstNode.getClass(node)); | |
| 6255 | 199 | then | |
| 6256 | RECORD_ELEMENT(recordExp, index, InstNode.name(node), InstNode.getType(node)); | ||
| 6257 | |||
| 6258 | end match; | ||
| 6259 | end nthRecordElement; | ||
| 6260 | |||
| 6261 | function getRecordElements | ||
| 6262 | input Expression exp; | ||
| 6263 | output list<Expression> elements = {}; | ||
| 6264 | protected | ||
| 6265 | Type ty = Type.arrayElementType(typeOf(exp)); | ||
| 6266 | algorithm | ||
| 6267 | elements := match ty | ||
| 6268 | local | ||
| 6269 | ComplexType complexTy; | ||
| 6270 | |||
| 6271 | case Type.COMPLEX(complexTy = complexTy as ComplexType.RECORD()) algorithm | ||
| 6272 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 96 times.
✓ Branch 2 taken 96 times.
✗ Branch 3 not taken.
|
1311 | for i in arrayLength(complexTy.fields):-1:1 loop |
| 6273 | 1119 | elements := recordElement(Record.Field.name(complexTy.fields[i]), exp) :: elements; | |
| 6274 | end for; | ||
| 6275 | then elements; | ||
| 6276 | else elements; | ||
| 6277 | end match; | ||
| 6278 | end getRecordElements; | ||
| 6279 | |||
| 6280 | function retype | ||
| 6281 | input output Expression exp; | ||
| 6282 | algorithm | ||
| 6283 | () := match exp | ||
| 6284 | local | ||
| 6285 | Type ty; | ||
| 6286 | |||
| 6287 | case RANGE() | ||
| 6288 | algorithm | ||
| 6289 | 608 | exp.ty := TypeCheck.keepRangeSize( | |
| 6290 | TypeCheck.getRangeType(exp.start, exp.step, exp.stop, | ||
| 6291 | typeOf(exp.start), Absyn.dummyInfo), exp.ty); | ||
| 6292 | then | ||
| 6293 | (); | ||
| 6294 | |||
| 6295 | case CALL(call = Call.TYPED_ARRAY_CONSTRUCTOR()) | ||
| 6296 | algorithm | ||
| 6297 | 19 | exp.call := Call.retype(exp.call); | |
| 6298 | then | ||
| 6299 | (); | ||
| 6300 | |||
| 6301 | else | ||
| 6302 | algorithm | ||
| 6303 | 22127 | ty := typeOf(exp); | |
| 6304 | |||
| 6305 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 22127 times.
|
22127 | if Type.isConditionalArray(ty) then |
| 6306 | ✗ | ty := Type.simplifyConditionalArray(ty); | |
| 6307 | ✗ | exp := setType(ty, exp); | |
| 6308 | end if; | ||
| 6309 | then | ||
| 6310 | (); | ||
| 6311 | |||
| 6312 | end match; | ||
| 6313 | end retype; | ||
| 6314 | |||
| 6315 | function nthEnumLiteral | ||
| 6316 | input Type ty; | ||
| 6317 | input Integer n; | ||
| 6318 | output Expression exp; | ||
| 6319 | algorithm | ||
| 6320 | ✗ | exp := ENUM_LITERAL(ty, Type.nthEnumLiteral(ty, n), n); | |
| 6321 | end nthEnumLiteral; | ||
| 6322 | |||
| 6323 | function createIterationRanges | ||
| 6324 | input output Expression exp; | ||
| 6325 | input list<tuple<InstNode, Expression>> iterators; | ||
| 6326 | output list<Expression> ranges = {}; | ||
| 6327 | output list<Mutable<Expression>> iters = {}; | ||
| 6328 | protected | ||
| 6329 | InstNode node; | ||
| 6330 | Expression range; | ||
| 6331 | Mutable<Expression> iter; | ||
| 6332 | algorithm | ||
| 6333 |
2/2✓ Branch 0 taken 806 times.
✓ Branch 1 taken 805 times.
|
1611 | for i in iterators loop |
| 6334 | 806 | (node, range) := i; | |
| 6335 | 806 | iter := Mutable.create(INTEGER(0)); | |
| 6336 |
4/4✓ Branch 0 taken 1 time.
✓ Branch 1 taken 806 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 806 times.
|
807 | ranges := list(replaceIterator(r, node, MUTABLE(iter)) for r in ranges); |
| 6337 | 806 | exp := replaceIterator(exp, node, MUTABLE(iter)); | |
| 6338 | iters := iter :: iters; | ||
| 6339 | ranges := range :: ranges; | ||
| 6340 | end for; | ||
| 6341 | end createIterationRanges; | ||
| 6342 | |||
| 6343 | function foldReduction | ||
| 6344 | input Expression exp; | ||
| 6345 | input list<tuple<InstNode, Expression>> iterators; | ||
| 6346 | input Expression foldExp; | ||
| 6347 | input MapFn mapFn; | ||
| 6348 | input FoldFn foldFn; | ||
| 6349 | output Expression result; | ||
| 6350 | |||
| 6351 | partial function MapFn | ||
| 6352 | input output Expression exp; | ||
| 6353 | end MapFn; | ||
| 6354 | |||
| 6355 | partial function FoldFn | ||
| 6356 | input Expression exp1; | ||
| 6357 | input Expression exp2; | ||
| 6358 | output Expression result; | ||
| 6359 | end FoldFn; | ||
| 6360 | protected | ||
| 6361 | Expression e; | ||
| 6362 | list<Expression> ranges = {}; | ||
| 6363 | list<Mutable<Expression>> iters = {}; | ||
| 6364 | algorithm | ||
| 6365 | 274 | (e, ranges, iters) := createIterationRanges(exp, iterators); | |
| 6366 | 274 | result := foldReduction2(e, ranges, iters, foldExp, mapFn, foldFn); | |
| 6367 | end foldReduction; | ||
| 6368 | |||
| 6369 | function foldReduction2 | ||
| 6370 | input Expression exp; | ||
| 6371 | input list<Expression> ranges; | ||
| 6372 | input list<Mutable<Expression>> iterators; | ||
| 6373 | input Expression foldExp; | ||
| 6374 | input MapFn mapFn; | ||
| 6375 | input FoldFn foldFn; | ||
| 6376 | output Expression result; | ||
| 6377 | |||
| 6378 | partial function MapFn | ||
| 6379 | input output Expression exp; | ||
| 6380 | end MapFn; | ||
| 6381 | |||
| 6382 | partial function FoldFn | ||
| 6383 | input Expression exp1; | ||
| 6384 | input Expression exp2; | ||
| 6385 | output Expression result; | ||
| 6386 | end FoldFn; | ||
| 6387 | protected | ||
| 6388 | Expression range, value; | ||
| 6389 | list<Expression> ranges_rest; | ||
| 6390 | Mutable<Expression> iter; | ||
| 6391 | list<Mutable<Expression>> iters_rest; | ||
| 6392 | ExpressionIterator range_iter; | ||
| 6393 | algorithm | ||
| 6394 |
2/2✓ Branch 0 taken 6692 times.
✓ Branch 1 taken 281 times.
|
6973 | if listEmpty(ranges) then |
| 6395 |
4/6✓ Branch 0 taken 6362 times.
✓ Branch 1 taken 330 times.
✓ Branch 2 taken 6362 times.
✗ Branch 3 not taken.
✓ Branch 7 taken 330 times.
✗ Branch 8 not taken.
|
6692 | result := foldFn(foldExp, mapFn(exp)); |
| 6396 | else | ||
| 6397 | 281 | range :: ranges_rest := ranges; | |
| 6398 | 281 | range := Ceval.evalExp(range); | |
| 6399 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 281 times.
|
281 | iter :: iters_rest := iterators; |
| 6400 | 281 | range_iter := ExpressionIterator.fromExp(range); | |
| 6401 | result := foldExp; | ||
| 6402 | |||
| 6403 |
2/2✓ Branch 1 taken 6699 times.
✓ Branch 2 taken 281 times.
|
6980 | while ExpressionIterator.hasNext(range_iter) loop |
| 6404 | 6699 | (range_iter, value) := ExpressionIterator.next(range_iter); | |
| 6405 | 6699 | Mutable.update(iter, value); | |
| 6406 | 6699 | result := foldReduction2(exp, ranges_rest, iters_rest, result, mapFn, foldFn); | |
| 6407 | end while; | ||
| 6408 | end if; | ||
| 6409 | end foldReduction2; | ||
| 6410 | |||
| 6411 | function isPure | ||
| 6412 | input Expression exp; | ||
| 6413 | output Boolean isPure; | ||
| 6414 | algorithm | ||
| 6415 | isPure := match exp | ||
| 6416 | 3199 | case CREF() then not ComponentRef.isIterator(exp.cref); | |
| 6417 | case CALL() | ||
| 6418 | then match AbsynUtil.pathFirstIdent(Call.functionName(exp.call)) | ||
| 6419 | case "Connections" then false; | ||
| 6420 | case "cardinality" then false; | ||
| 6421 | 3 | else not Call.isImpure(exp.call); | |
| 6422 | end match; | ||
| 6423 | else true; | ||
| 6424 | end match; | ||
| 6425 | end isPure; | ||
| 6426 | |||
| 6427 | function containsCref | ||
| 6428 | "returns true if the expression contains the cref" | ||
| 6429 | input Expression exp; | ||
| 6430 | input ComponentRef cref; | ||
| 6431 | output Boolean b; | ||
| 6432 | algorithm | ||
| 6433 | 7180 | b := fold(exp, function isCrefEqual(cref = cref), false); | |
| 6434 | end containsCref; | ||
| 6435 | |||
| 6436 | function isCrefEqual | ||
| 6437 | input Expression exp; | ||
| 6438 | input output Boolean b; | ||
| 6439 | input ComponentRef cref; | ||
| 6440 | algorithm | ||
| 6441 | b := match (b, exp) | ||
| 6442 | 11062 | case (false, CREF()) then ComponentRef.isEqual(exp.cref, cref); | |
| 6443 | else b; | ||
| 6444 | end match; | ||
| 6445 | end isCrefEqual; | ||
| 6446 | |||
| 6447 | function containsCrefSet | ||
| 6448 | "returns true if the expression contains any crefs in the set" | ||
| 6449 | input Expression exp; | ||
| 6450 | input UnorderedSet<ComponentRef> set; | ||
| 6451 | output Boolean b; | ||
| 6452 | algorithm | ||
| 6453 | ✗ | b := fold(exp, function isCrefEqualSet(set = set), false); | |
| 6454 | end containsCrefSet; | ||
| 6455 | |||
| 6456 | function isCrefEqualSet | ||
| 6457 | input Expression exp; | ||
| 6458 | input output Boolean b; | ||
| 6459 | input UnorderedSet<ComponentRef> set; | ||
| 6460 | algorithm | ||
| 6461 | b := match (b, exp) | ||
| 6462 | ✗ | case (false, CREF()) then UnorderedSet.contains(exp.cref, set); | |
| 6463 | else b; | ||
| 6464 | end match; | ||
| 6465 | end isCrefEqualSet; | ||
| 6466 | |||
| 6467 | function filterSplitIndices | ||
| 6468 | input output Expression exp; | ||
| 6469 | input InstNode node; | ||
| 6470 | protected | ||
| 6471 | list<Subscript> subs; | ||
| 6472 | algorithm | ||
| 6473 | exp := match exp | ||
| 6474 | case SUBSCRIPTED_EXP(exp = _, subscripts = subs) | ||
| 6475 | algorithm | ||
| 6476 |
6/6✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 1 time.
✓ Branch 6 taken 1 time.
|
3 | subs := list(s for s guard not filterSplitIndices2(s, node) in subs); |
| 6477 |
3/6✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✓ Branch 3 taken 1 time.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 time.
|
1 | then |
| 6478 | if listEmpty(subs) then | ||
| 6479 | exp.exp | ||
| 6480 | elseif Type.isUnknown(exp.ty) then | ||
| 6481 | SUBSCRIPTED_EXP(exp.exp, subs, exp.ty, List.any(subs, Subscript.isSplit)) | ||
| 6482 | else | ||
| 6483 | applySubscripts(subs, exp.exp); | ||
| 6484 | |||
| 6485 | else exp; | ||
| 6486 | end match; | ||
| 6487 | end filterSplitIndices; | ||
| 6488 | |||
| 6489 | function filterSplitIndices2 | ||
| 6490 | input Subscript sub; | ||
| 6491 | input InstNode node; | ||
| 6492 | output Boolean matching; | ||
| 6493 | algorithm | ||
| 6494 | matching := match sub | ||
| 6495 | ✗ | case Subscript.SPLIT_INDEX() then InstNode.refEqual(InstNode.borrow(sub.node), node); | |
| 6496 | 2 | case Subscript.SPLIT_PROXY() then InstNode.refEqual(InstNode.borrow(sub.parent), node); | |
| 6497 | else false; | ||
| 6498 | end match; | ||
| 6499 | end filterSplitIndices2; | ||
| 6500 | |||
| 6501 | function expandSplitIndices | ||
| 6502 | "Replaces split indices in a subscripted expression with : subscripts." | ||
| 6503 | input Expression exp; | ||
| 6504 | output Expression outExp; | ||
| 6505 | algorithm | ||
| 6506 | outExp := match exp | ||
| 6507 | case SUBSCRIPTED_EXP() | ||
| 6508 | 4814 | then applySubscripts(Subscript.expandSplitIndices(exp.subscripts, {}), exp.exp); | |
| 6509 | |||
| 6510 | case CREF() | ||
| 6511 | algorithm | ||
| 6512 | 101955 | exp.cref := ComponentRef.expandSplitSubscripts(exp.cref); | |
| 6513 | then | ||
| 6514 | exp; | ||
| 6515 | |||
| 6516 | else exp; | ||
| 6517 | end match; | ||
| 6518 | end expandSplitIndices; | ||
| 6519 | |||
| 6520 | function expandNonListedSplitIndices | ||
| 6521 | "Replaces split indices in a subscripted expression with : subscripts, | ||
| 6522 | except for indices that reference nodes in the given list." | ||
| 6523 | input Expression exp; | ||
| 6524 | input list<InstNode> indicesToKeep; | ||
| 6525 | output Expression outExp; | ||
| 6526 | algorithm | ||
| 6527 | outExp := match exp | ||
| 6528 | case SUBSCRIPTED_EXP(split = true) | ||
| 6529 | 5 | then applySubscripts(Subscript.expandSplitIndices(exp.subscripts, indicesToKeep), exp.exp); | |
| 6530 | else exp; | ||
| 6531 | end match; | ||
| 6532 | end expandNonListedSplitIndices; | ||
| 6533 | |||
| 6534 | function isSplitSubscriptedExp | ||
| 6535 | input Expression exp; | ||
| 6536 | output Boolean split; | ||
| 6537 | algorithm | ||
| 6538 | split := match exp | ||
| 6539 | case SUBSCRIPTED_EXP(split = split) then split; | ||
| 6540 | else false; | ||
| 6541 | end match; | ||
| 6542 | end isSplitSubscriptedExp; | ||
| 6543 | |||
| 6544 | function mapSplitExpressions | ||
| 6545 | input Expression exp; | ||
| 6546 | input Func func; | ||
| 6547 | output Expression outExp; | ||
| 6548 | |||
| 6549 | partial function Func | ||
| 6550 | input output Expression exp; | ||
| 6551 | end Func; | ||
| 6552 | protected | ||
| 6553 | Option<UnorderedMap<Subscript, Expression>> osub_repls; | ||
| 6554 | UnorderedMap<Subscript, Expression> sub_repls; | ||
| 6555 | list<Subscript> subs; | ||
| 6556 | list<Expression> sub_exps, dim_sizes; | ||
| 6557 | algorithm | ||
| 6558 |
2/2✓ Branch 1 taken 508016 times.
✓ Branch 2 taken 14 times.
|
508030 | if not containsSplitSubscriptedExp(exp) then |
| 6559 |
2/2✓ Branch 0 taken 446125 times.
✓ Branch 1 taken 61891 times.
|
508016 | outExp := func(exp); |
| 6560 | 507748 | return; | |
| 6561 | end if; | ||
| 6562 | |||
| 6563 | 14 | (outExp, osub_repls) := mapFold(exp, replaceSplitSubscripts, NONE()); | |
| 6564 | |||
| 6565 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
|
14 | if isNone(osub_repls) then |
| 6566 | ✗ | outExp := func(exp); | |
| 6567 | else | ||
| 6568 | 14 | SOME(sub_repls) := osub_repls; | |
| 6569 | 14 | subs := UnorderedMap.keyList(sub_repls); | |
| 6570 | 14 | sub_exps := UnorderedMap.valueList(sub_repls); | |
| 6571 |
4/4✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 14 times.
|
28 | dim_sizes := list(Subscript.splitIndexDimExp(s) for s in subs); |
| 6572 |
4/4✓ Branch 0 taken 14 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 14 times.
|
42 | dim_sizes := list(replaceSplitSubscripts(d, SOME(sub_repls)) for d in dim_sizes); |
| 6573 | 14 | outExp := mapSplitExpressions2(outExp, dim_sizes, sub_exps, func); | |
| 6574 | 14 | outExp := applySubscripts(subs, outExp); | |
| 6575 | end if; | ||
| 6576 | end mapSplitExpressions; | ||
| 6577 | |||
| 6578 | function containsSplitSubscriptedExp | ||
| 6579 | "Like contains(exp, isSplitSubscriptedExp), but also looks into iterator | ||
| 6580 | ranges like mapFold does. Literal arrays are skipped, like in | ||
| 6581 | Ceval.subscriptBinding2." | ||
| 6582 | input Expression exp; | ||
| 6583 | output Boolean res; | ||
| 6584 | algorithm | ||
| 6585 | res := match exp | ||
| 6586 | case SUBSCRIPTED_EXP(split = true) then true; | ||
| 6587 | case ARRAY(literal = true) then false; | ||
| 6588 | case CALL() | ||
| 6589 |
7/8✓ Branch 1 taken 683 times.
✓ Branch 2 taken 130973 times.
✓ Branch 3 taken 683 times.
✓ Branch 4 taken 130973 times.
✓ Branch 7 taken 130964 times.
✓ Branch 8 taken 9 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 130964 times.
|
131656 | then containsShallow(exp, containsSplitSubscriptedExp) or |
| 6590 | List.any(list(Util.tuple22(i) for i in Call.iterators(exp.call)), containsSplitSubscriptedExp); | ||
| 6591 | 1477717 | else containsShallow(exp, containsSplitSubscriptedExp); | |
| 6592 | end match; | ||
| 6593 | end containsSplitSubscriptedExp; | ||
| 6594 | |||
| 6595 | function replaceSplitSubscripts | ||
| 6596 | input output Expression exp; | ||
| 6597 | input output Option<UnorderedMap<Subscript, Expression>> subRepls; | ||
| 6598 | algorithm | ||
| 6599 | exp := match exp | ||
| 6600 | local | ||
| 6601 | list<Subscript> subs; | ||
| 6602 | |||
| 6603 | case SUBSCRIPTED_EXP(split = true) | ||
| 6604 | algorithm | ||
| 6605 | 17 | (subs, subRepls) := List.mapFold(exp.subscripts, replaceSplitSubscripts2, subRepls); | |
| 6606 | 17 | then | |
| 6607 | applySubscripts(subs, exp.exp); | ||
| 6608 | |||
| 6609 | else exp; | ||
| 6610 | end match; | ||
| 6611 | end replaceSplitSubscripts; | ||
| 6612 | |||
| 6613 | function replaceSplitSubscripts2 | ||
| 6614 | input output Subscript subscript; | ||
| 6615 | input output Option<UnorderedMap<Subscript, Expression>> subRepls; | ||
| 6616 | protected | ||
| 6617 | Expression sub_exp; | ||
| 6618 | UnorderedMap<Subscript, Expression> sub_repls; | ||
| 6619 | algorithm | ||
| 6620 | subscript := match subscript | ||
| 6621 | case Subscript.SPLIT_INDEX() | ||
| 6622 | algorithm | ||
| 6623 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 3 times.
|
17 | if isSome(subRepls) then |
| 6624 | 3 | SOME(sub_repls) := subRepls; | |
| 6625 | else | ||
| 6626 | 14 | sub_repls := UnorderedMap.new<Expression>(Subscript.hash, Subscript.isEqual); | |
| 6627 | subRepls := SOME(sub_repls); | ||
| 6628 | end if; | ||
| 6629 | |||
| 6630 | 17 | sub_exp := makeMutable(INTEGER(0)); | |
| 6631 | 17 | sub_exp := UnorderedMap.tryAdd(subscript, sub_exp, sub_repls); | |
| 6632 | 17 | then | |
| 6633 | Subscript.INDEX(sub_exp); | ||
| 6634 | |||
| 6635 | else subscript; | ||
| 6636 | end match; | ||
| 6637 | end replaceSplitSubscripts2; | ||
| 6638 | |||
| 6639 | function mapSplitExpressions2 | ||
| 6640 | input Expression exp; | ||
| 6641 | input list<Expression> dimSizes; | ||
| 6642 | input list<Expression> subExps; | ||
| 6643 | input Func func; | ||
| 6644 | output Expression outExp; | ||
| 6645 | |||
| 6646 | partial function Func | ||
| 6647 | input output Expression exp; | ||
| 6648 | end Func; | ||
| 6649 | protected | ||
| 6650 | Expression dim_size; | ||
| 6651 | list<Expression> rest_dims; | ||
| 6652 | Integer dim_size_int; | ||
| 6653 | Expression sub_exp; | ||
| 6654 | list<Expression> rest_subs; | ||
| 6655 | array<Expression> expl; | ||
| 6656 | Type ty; | ||
| 6657 | algorithm | ||
| 6658 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 14 times.
|
52 | if listEmpty(dimSizes) then |
| 6659 | 38 | outExp := map(exp, mapSplitExpressions3); | |
| 6660 |
2/2✓ Branch 0 taken 30 times.
✓ Branch 1 taken 8 times.
|
38 | outExp := func(outExp); |
| 6661 | else | ||
| 6662 | 14 | dim_size :: rest_dims := dimSizes; | |
| 6663 | 14 | dim_size_int := toInteger(Ceval.evalExp(dim_size)); | |
| 6664 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | sub_exp :: rest_subs := subExps; |
| 6665 | 14 | expl := arrayCreateNoInit(dim_size_int, exp); | |
| 6666 | |||
| 6667 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
52 | for i in 1:dim_size_int loop |
| 6668 | 38 | updateMutable(sub_exp, INTEGER(i)); | |
| 6669 | 38 | arrayUpdateNoBoundsChecking(expl, i, | |
| 6670 | mapSplitExpressions2(exp, rest_dims, rest_subs, func)); | ||
| 6671 | end for; | ||
| 6672 | |||
| 6673 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
28 | ty := typeOf(if arrayEmpty(expl) then exp else arrayGet(expl, 1)); |
| 6674 | 14 | outExp := makeExpArray(expl, ty, Array.all(expl, isLiteral)); | |
| 6675 | end if; | ||
| 6676 | end mapSplitExpressions2; | ||
| 6677 | |||
| 6678 | function mapSplitExpressions3 | ||
| 6679 | input output Expression exp; | ||
| 6680 | protected | ||
| 6681 | list<Subscript> subs; | ||
| 6682 | algorithm | ||
| 6683 | exp := match exp | ||
| 6684 | 47 | case MUTABLE() then Mutable.access(exp.exp); | |
| 6685 | |||
| 6686 | case SUBSCRIPTED_EXP(subscripts = subs) | ||
| 6687 | 47 | then applySubscripts(subs, exp.exp); | |
| 6688 | |||
| 6689 | else exp; | ||
| 6690 | end match; | ||
| 6691 | end mapSplitExpressions3; | ||
| 6692 | |||
| 6693 | function mapCrefScalars | ||
| 6694 | "Takes a cref expression and applies a function to each scalar cref, | ||
| 6695 | creating a new expression with the same dimensions as the given cref. | ||
| 6696 | Ex: mapCrefScalars(/*Real[2, 2]*/ x, ComponentRef.toString) => | ||
| 6697 | {{'x[1, 1]', 'x[1, 2]'}, {'x[2, 1]', 'x[2, 2]'}}" | ||
| 6698 | input Expression crefExp; | ||
| 6699 | input MapFn mapFn; | ||
| 6700 | output Expression outExp; | ||
| 6701 | |||
| 6702 | partial function MapFn | ||
| 6703 | input ComponentRef cref; | ||
| 6704 | output Expression exp; | ||
| 6705 | end MapFn; | ||
| 6706 | algorithm | ||
| 6707 | 2 | outExp := ExpandExp.expand(crefExp); | |
| 6708 | 2 | outExp := mapCrefScalars2(outExp, mapFn); | |
| 6709 | end mapCrefScalars; | ||
| 6710 | |||
| 6711 | function mapCrefScalars2 | ||
| 6712 | input Expression exp; | ||
| 6713 | input MapFn mapFn; | ||
| 6714 | output Expression outExp; | ||
| 6715 | |||
| 6716 | partial function MapFn | ||
| 6717 | input ComponentRef cref; | ||
| 6718 | output Expression exp; | ||
| 6719 | end MapFn; | ||
| 6720 | protected | ||
| 6721 | Type ty; | ||
| 6722 | Boolean literal; | ||
| 6723 | ComponentRef cref; | ||
| 6724 | array<Expression> arr; | ||
| 6725 | algorithm | ||
| 6726 | outExp := match exp | ||
| 6727 | case ARRAY() | ||
| 6728 | guard not arrayEmpty(exp.elements) | ||
| 6729 | algorithm | ||
| 6730 | 1 | arr := Array.map(exp.elements, function mapCrefScalars2(mapFn = mapFn)); | |
| 6731 | 1 | ty := typeOf(arrayGet(arr, 1)); | |
| 6732 | 1 | literal := Array.all(arr, isLiteral); | |
| 6733 | 1 | then | |
| 6734 | makeExpArray(arr, ty, literal); | ||
| 6735 | |||
| 6736 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | case CREF() then mapFn(exp.cref); |
| 6737 | else exp; | ||
| 6738 | end match; | ||
| 6739 | end mapCrefScalars2; | ||
| 6740 | |||
| 6741 | function isFunctionPointer | ||
| 6742 | input Expression exp; | ||
| 6743 | output Boolean res; | ||
| 6744 | algorithm | ||
| 6745 | res := match exp | ||
| 6746 | case CREF(ty = Type.FUNCTION()) then true; | ||
| 6747 | case PARTIAL_FUNCTION_APPLICATION() then true; | ||
| 6748 | else false; | ||
| 6749 | end match; | ||
| 6750 | end isFunctionPointer; | ||
| 6751 | |||
| 6752 | function isClockOrSampleFunction | ||
| 6753 | "returns true if the expression is any form of clock sampling function" | ||
| 6754 | input Expression exp; | ||
| 6755 | output Boolean b; | ||
| 6756 | algorithm | ||
| 6757 | b := match exp | ||
| 6758 | local | ||
| 6759 | Call call; | ||
| 6760 | Expression arg; | ||
| 6761 | case CALL(call = call as Call.TYPED_CALL(arguments = arg :: _)) | ||
| 6762 | then match AbsynUtil.pathString(Function.Function.nameConsiderBuiltin(call.fn)) | ||
| 6763 | 61 | case "sample" then not isLiteral(arg); // sample has a non clocked meaning as well | |
| 6764 | case "subSample" then true; | ||
| 6765 | case "superSample" then true; | ||
| 6766 | case "shiftSample" then true; | ||
| 6767 | case "backSample" then true; | ||
| 6768 | else false; | ||
| 6769 | end match; | ||
| 6770 | case Expression.CLKCONST() then true; | ||
| 6771 | else false; | ||
| 6772 | end match; | ||
| 6773 | end isClockOrSampleFunction; | ||
| 6774 | |||
| 6775 | function isConnector | ||
| 6776 | "Returns true if the expression is a component reference that refers to a | ||
| 6777 | connector, otherwise false." | ||
| 6778 | input Expression exp; | ||
| 6779 | output Boolean res; | ||
| 6780 | protected | ||
| 6781 | InstNode node; | ||
| 6782 | algorithm | ||
| 6783 | res := match exp | ||
| 6784 | case CREF() | ||
| 6785 | algorithm | ||
| 6786 | 2354 | node := ComponentRef.node(exp.cref); | |
| 6787 |
2/4✓ Branch 1 taken 2354 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2354 times.
|
2354 | then |
| 6788 | InstNode.isComponent(node) and InstNode.isConnector(node); | ||
| 6789 | |||
| 6790 | else false; | ||
| 6791 | end match; | ||
| 6792 | end isConnector; | ||
| 6793 | |||
| 6794 | function isComponentExpression | ||
| 6795 | "Returns true if the expression is a component reference that refers to an | ||
| 6796 | actual component (and not e.g. a function), otherwise false" | ||
| 6797 | input Expression exp; | ||
| 6798 | output Boolean res; | ||
| 6799 | algorithm | ||
| 6800 | res := match exp | ||
| 6801 | case CREF() | ||
| 6802 |
2/4✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 44 times.
|
44 | then ComponentRef.isCref(exp.cref) and |
| 6803 | InstNode.isComponent(ComponentRef.node(exp.cref)); | ||
| 6804 | |||
| 6805 | else false; | ||
| 6806 | end match; | ||
| 6807 | end isComponentExpression; | ||
| 6808 | |||
| 6809 | function clone | ||
| 6810 | "Clones an expression to make it and any expression it contains unique, | ||
| 6811 | such that e.g. arrays don't share their internal arrays." | ||
| 6812 | input output Expression exp; | ||
| 6813 | algorithm | ||
| 6814 | exp := match exp | ||
| 6815 | case ARRAY() | ||
| 6816 | algorithm | ||
| 6817 | 16714 | exp.elements := Array.map(exp.elements, clone); | |
| 6818 | then | ||
| 6819 | exp; | ||
| 6820 | |||
| 6821 | 336232 | else mapShallow(exp, clone); | |
| 6822 | end match; | ||
| 6823 | end clone; | ||
| 6824 | |||
| 6825 | function toJSON | ||
| 6826 | input Expression exp; | ||
| 6827 | output JSON json; | ||
| 6828 | protected | ||
| 6829 | function dump_arg | ||
| 6830 | input String name; | ||
| 6831 | input Expression arg; | ||
| 6832 | output JSON json = JSON.emptyListObject(); | ||
| 6833 | algorithm | ||
| 6834 | ✗ | json := JSON.addPair("name", JSON.makeString(name), json); | |
| 6835 | ✗ | json := JSON.addPair("value", toJSON(arg), json); | |
| 6836 | end dump_arg; | ||
| 6837 | algorithm | ||
| 6838 | json := match exp | ||
| 6839 | 429 | case INTEGER() then JSON.makeInteger(exp.value); | |
| 6840 | 389 | case REAL() then JSON.makeNumber(exp.value); | |
| 6841 | 24 | case STRING() then JSON.makeString(exp.value); | |
| 6842 | 42 | case BOOLEAN() then JSON.makeBoolean(exp.value); | |
| 6843 | case ENUM_LITERAL() | ||
| 6844 | algorithm | ||
| 6845 | 115 | json := JSON.emptyListObject(); | |
| 6846 | 115 | json := JSON.addPair("$kind", JSON.STRING("enum"), json); | |
| 6847 | 115 | json := JSON.addPair("name", JSON.makeString(toString(exp)), json); | |
| 6848 | 115 | json := JSON.addPair("index", JSON.makeInteger(exp.index), json); | |
| 6849 | then | ||
| 6850 | json; | ||
| 6851 | |||
| 6852 | case CLKCONST() | ||
| 6853 | ✗ | then ClockKind.toJSON(exp.clk); | |
| 6854 | |||
| 6855 | 26 | case CREF() then ComponentRef.toJSON(exp.cref); | |
| 6856 | |||
| 6857 | case TYPENAME() | ||
| 6858 | algorithm | ||
| 6859 | ✗ | json := JSON.emptyListObject(); | |
| 6860 | ✗ | json := JSON.addPair("$kind", JSON.STRING("typename"), json); | |
| 6861 | ✗ | json := JSON.addPair("name", JSON.makeString(Type.typenameString(Type.arrayElementType(exp.ty))), json); | |
| 6862 | then | ||
| 6863 | json; | ||
| 6864 | |||
| 6865 | case ARRAY() | ||
| 6866 |
4/4✓ Branch 0 taken 672 times.
✓ Branch 1 taken 300 times.
✓ Branch 3 taken 672 times.
✓ Branch 4 taken 300 times.
|
1944 | then JSON.makeList(list(toJSON(e) for e in exp.elements)); |
| 6867 | |||
| 6868 | case RANGE() | ||
| 6869 | algorithm | ||
| 6870 | 1 | json := JSON.emptyListObject(); | |
| 6871 | 1 | json := JSON.addPair("$kind", JSON.STRING("range"), json); | |
| 6872 | 1 | json := JSON.addPair("start", toJSON(exp.start), json); | |
| 6873 | |||
| 6874 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
|
1 | if isSome(exp.step) then |
| 6875 | ✗ | json := JSON.addPair("step", toJSON(Util.getOption(exp.step)), json); | |
| 6876 | end if; | ||
| 6877 | |||
| 6878 | 1 | json := JSON.addPair("stop", toJSON(exp.stop), json); | |
| 6879 | then | ||
| 6880 | json; | ||
| 6881 | |||
| 6882 | case TUPLE() | ||
| 6883 | algorithm | ||
| 6884 | ✗ | json := JSON.emptyListObject(); | |
| 6885 | ✗ | json := JSON.addPair("$kind", JSON.STRING("tuple"), json); | |
| 6886 | ✗ | json := JSON.addPair("elements", | |
| 6887 | JSON.makeList(list(toJSON(e) for e in exp.elements)), json); | ||
| 6888 | then | ||
| 6889 | json; | ||
| 6890 | |||
| 6891 | case RECORD() | ||
| 6892 | algorithm | ||
| 6893 | 47 | json := JSON.emptyListObject(); | |
| 6894 | 47 | json := JSON.addPair("$kind", JSON.STRING("record"), json); | |
| 6895 | 47 | json := JSON.addPair("name", JSON.makeString(AbsynUtil.pathString(exp.path)), json); | |
| 6896 |
4/4✓ Branch 0 taken 463 times.
✓ Branch 1 taken 47 times.
✓ Branch 2 taken 463 times.
✓ Branch 3 taken 47 times.
|
510 | json := JSON.addPair("elements", |
| 6897 | JSON.makeList(list(toJSON(e) for e in exp.elements)), json); | ||
| 6898 | then | ||
| 6899 | json; | ||
| 6900 | |||
| 6901 | case CALL() | ||
| 6902 | 5 | then Call.toJSON(exp.call); | |
| 6903 | |||
| 6904 | case SIZE() | ||
| 6905 | algorithm | ||
| 6906 | ✗ | json := JSON.emptyListObject(); | |
| 6907 | ✗ | json := JSON.addPair("$kind", JSON.STRING("call"), json); | |
| 6908 | ✗ | json := JSON.addPair("name", JSON.STRING("size"), json); | |
| 6909 | |||
| 6910 | ✗ | if isSome(exp.dimIndex) then | |
| 6911 | ✗ | json := JSON.addPair("arguments", | |
| 6912 | JSON.makeList({toJSON(exp.exp), toJSON(Util.getOption(exp.dimIndex))}), json); | ||
| 6913 | else | ||
| 6914 | ✗ | json := JSON.addPair("arguments", JSON.makeArray({toJSON(exp.exp)}), json); | |
| 6915 | end if; | ||
| 6916 | then | ||
| 6917 | json; | ||
| 6918 | |||
| 6919 | case BINARY() | ||
| 6920 | algorithm | ||
| 6921 | 2 | json := JSON.emptyListObject(); | |
| 6922 | 2 | json := JSON.addPair("$kind", JSON.STRING("binary_op"), json); | |
| 6923 | 2 | json := JSON.addPair("lhs", toJSON(exp.exp1), json); | |
| 6924 | 2 | json := JSON.addPair("op", Operator.toJSON(exp.operator), json); | |
| 6925 | 2 | json := JSON.addPair("rhs", toJSON(exp.exp2), json); | |
| 6926 | then | ||
| 6927 | json; | ||
| 6928 | |||
| 6929 | case UNARY() | ||
| 6930 | algorithm | ||
| 6931 | ✗ | json := JSON.emptyListObject(); | |
| 6932 | ✗ | json := JSON.addPair("$kind", JSON.STRING("unary_op"), json); | |
| 6933 | ✗ | json := JSON.addPair("op", Operator.toJSON(exp.operator), json); | |
| 6934 | ✗ | json := JSON.addPair("exp", toJSON(exp.exp), json); | |
| 6935 | then | ||
| 6936 | json; | ||
| 6937 | |||
| 6938 | case LBINARY() | ||
| 6939 | algorithm | ||
| 6940 | ✗ | json := JSON.emptyListObject(); | |
| 6941 | ✗ | json := JSON.addPair("$kind", JSON.STRING("binary_op"), json); | |
| 6942 | ✗ | json := JSON.addPair("lhs", toJSON(exp.exp1), json); | |
| 6943 | ✗ | json := JSON.addPair("op", Operator.toJSON(exp.operator), json); | |
| 6944 | ✗ | json := JSON.addPair("rhs", toJSON(exp.exp2), json); | |
| 6945 | then | ||
| 6946 | json; | ||
| 6947 | |||
| 6948 | case LUNARY() | ||
| 6949 | algorithm | ||
| 6950 | ✗ | json := JSON.emptyListObject(); | |
| 6951 | ✗ | json := JSON.addPair("$kind", JSON.STRING("unary_op"), json); | |
| 6952 | ✗ | json := JSON.addPair("op", Operator.toJSON(exp.operator), json); | |
| 6953 | ✗ | json := JSON.addPair("exp", toJSON(exp.exp), json); | |
| 6954 | then | ||
| 6955 | json; | ||
| 6956 | |||
| 6957 | case RELATION() | ||
| 6958 | algorithm | ||
| 6959 | 1 | json := JSON.emptyListObject(); | |
| 6960 | 1 | json := JSON.addPair("$kind", JSON.STRING("binary_op"), json); | |
| 6961 | 1 | json := JSON.addPair("lhs", toJSON(exp.exp1), json); | |
| 6962 | 1 | json := JSON.addPair("op", Operator.toJSON(exp.operator), json); | |
| 6963 | 1 | json := JSON.addPair("rhs", toJSON(exp.exp2), json); | |
| 6964 | then | ||
| 6965 | json; | ||
| 6966 | |||
| 6967 | case MULTARY() | ||
| 6968 | algorithm | ||
| 6969 | ✗ | json := JSON.emptyListObject(); | |
| 6970 | ✗ | json := JSON.addPair("$kind", JSON.STRING("multary_op"), json); | |
| 6971 | ✗ | json := JSON.addPair("args", | |
| 6972 | JSON.makeArray(list(toJSON(a) for a in exp.arguments)), json); | ||
| 6973 | ✗ | json := JSON.addPair("inv_args", | |
| 6974 | JSON.makeArray(list(toJSON(a) for a in exp.inv_arguments)), json); | ||
| 6975 | ✗ | json := JSON.addPair("op", Operator.toJSON(exp.operator), json); | |
| 6976 | then | ||
| 6977 | json; | ||
| 6978 | |||
| 6979 | case IF() | ||
| 6980 | algorithm | ||
| 6981 | 1 | json := JSON.emptyListObject(); | |
| 6982 | 1 | json := JSON.addPair("$kind", JSON.STRING("if"), json); | |
| 6983 | 1 | json := JSON.addPair("condition", toJSON(exp.condition), json); | |
| 6984 | 1 | json := JSON.addPair("true", toJSON(exp.trueBranch), json); | |
| 6985 | 1 | json := JSON.addPair("false", toJSON(exp.falseBranch), json); | |
| 6986 | then | ||
| 6987 | json; | ||
| 6988 | |||
| 6989 | 1 | case CAST() then toJSON(exp.exp); | |
| 6990 | ✗ | case BOX() then toJSON(exp.exp); | |
| 6991 | ✗ | case UNBOX() then toJSON(exp.exp); | |
| 6992 | |||
| 6993 | case SUBSCRIPTED_EXP() | ||
| 6994 | algorithm | ||
| 6995 | ✗ | json := JSON.emptyListObject(); | |
| 6996 | ✗ | json := JSON.addPair("$kind", JSON.STRING("sub"), json); | |
| 6997 | ✗ | json := JSON.addPair("exp", toJSON(exp.exp), json); | |
| 6998 | ✗ | json := JSON.addPair("subscripts", Subscript.toJSONList(exp.subscripts), json); | |
| 6999 | then | ||
| 7000 | json; | ||
| 7001 | |||
| 7002 | case TUPLE_ELEMENT() | ||
| 7003 | algorithm | ||
| 7004 | ✗ | json := JSON.emptyListObject(); | |
| 7005 | ✗ | json := JSON.addPair("$kind", JSON.STRING("tuple_element"), json); | |
| 7006 | ✗ | json := JSON.addPair("exp", toJSON(exp.tupleExp), json); | |
| 7007 | ✗ | json := JSON.addPair("index", JSON.makeInteger(exp.index), json); | |
| 7008 | then | ||
| 7009 | json; | ||
| 7010 | |||
| 7011 | case RECORD_ELEMENT() | ||
| 7012 | algorithm | ||
| 7013 | ✗ | json := JSON.emptyListObject(); | |
| 7014 | ✗ | json := JSON.addPair("$kind", JSON.STRING("record_element"), json); | |
| 7015 | ✗ | json := JSON.addPair("exp", toJSON(exp.recordExp), json); | |
| 7016 | ✗ | json := JSON.addPair("index", JSON.makeInteger(exp.index), json); | |
| 7017 | ✗ | json := JSON.addPair("field", JSON.makeString(exp.fieldName), json); | |
| 7018 | then | ||
| 7019 | json; | ||
| 7020 | |||
| 7021 | case PARTIAL_FUNCTION_APPLICATION() | ||
| 7022 | algorithm | ||
| 7023 | ✗ | json := JSON.emptyListObject(); | |
| 7024 | ✗ | json := JSON.addPair("$kind", JSON.STRING("function"), json); | |
| 7025 | ✗ | json := JSON.addPair("name", JSON.makeString(ComponentRef.toString(exp.fn)), json); | |
| 7026 | ✗ | json := JSON.addPair("arguments", JSON.makeList( | |
| 7027 | list(dump_arg(name, arg) threaded for arg in exp.args, name in exp.argNames)), json); | ||
| 7028 | then | ||
| 7029 | json; | ||
| 7030 | |||
| 7031 | ✗ | case FILENAME() then JSON.makeString(exp.filename); | |
| 7032 | |||
| 7033 | ✗ | else JSON.makeString(toString(exp)); | |
| 7034 | end match; | ||
| 7035 | end toJSON; | ||
| 7036 | |||
| 7037 | function tupleElements | ||
| 7038 | input Expression exp; | ||
| 7039 | output list<Expression> expl; | ||
| 7040 | algorithm | ||
| 7041 | expl := match exp | ||
| 7042 | 32 | case TUPLE() then exp.elements; | |
| 7043 | else {exp}; | ||
| 7044 | end match; | ||
| 7045 | end tupleElements; | ||
| 7046 | |||
| 7047 | function wrapCall | ||
| 7048 | "wrapper function to apply a Call function" | ||
| 7049 | input output Expression exp; | ||
| 7050 | input callFun fun; | ||
| 7051 | partial function callFun | ||
| 7052 | input output Call call; | ||
| 7053 | end callFun; | ||
| 7054 | algorithm | ||
| 7055 | exp := match exp | ||
| 7056 | case CALL() algorithm | ||
| 7057 |
1/2✓ Branch 0 taken 2732 times.
✗ Branch 1 not taken.
|
2732 | exp.call := fun(exp.call); |
| 7058 | then exp; | ||
| 7059 | else exp; | ||
| 7060 | end match; | ||
| 7061 | end wrapCall; | ||
| 7062 | |||
| 7063 | function repairOperator | ||
| 7064 | input output Expression exp; | ||
| 7065 | algorithm | ||
| 7066 | exp := match exp | ||
| 7067 | case BINARY() algorithm | ||
| 7068 | 22 | exp.operator := Operator.repairBinary(exp.operator, typeOf(exp.exp1), typeOf(exp.exp2)); | |
| 7069 | then exp; | ||
| 7070 | |||
| 7071 | case MULTARY() algorithm | ||
| 7072 |
4/4✓ Branch 1 taken 425 times.
✓ Branch 2 taken 211 times.
✓ Branch 3 taken 425 times.
✓ Branch 4 taken 211 times.
|
847 | exp.operator := Operator.repairMultary(exp.operator, list(typeOf(e) for e in listAppend(exp.arguments, exp.inv_arguments))); |
| 7073 | then exp; | ||
| 7074 | |||
| 7075 | else exp; | ||
| 7076 | end match; | ||
| 7077 | end repairOperator; | ||
| 7078 | |||
| 7079 | function makeUnary | ||
| 7080 | input Operator op; | ||
| 7081 | input Expression exp; | ||
| 7082 | output Expression unaryExp; | ||
| 7083 | algorithm | ||
| 7084 |
2/2✓ Branch 0 taken 396610 times.
✓ Branch 1 taken 739 times.
|
397349 | if op.op == NFOperator.Op.ADD then |
| 7085 | unaryExp := exp; | ||
| 7086 | elseif op.op == NFOperator.Op.UMINUS then | ||
| 7087 | 396610 | unaryExp := negate(exp); | |
| 7088 | else | ||
| 7089 | ✗ | unaryExp := UNARY(op, exp); | |
| 7090 | end if; | ||
| 7091 | end makeUnary; | ||
| 7092 | |||
| 7093 | function replaceLiteral | ||
| 7094 | "use with fake map because it maps itself" | ||
| 7095 | input output Expression exp; | ||
| 7096 | input UnorderedMap<Expression, Integer> map; | ||
| 7097 | input Pointer<Integer> idx_ptr; | ||
| 7098 | protected | ||
| 7099 | function replace | ||
| 7100 | input output Expression exp; | ||
| 7101 | input UnorderedMap<Expression, Integer> map; | ||
| 7102 | input Pointer<Integer> idx_ptr; | ||
| 7103 | protected | ||
| 7104 | Integer idx; | ||
| 7105 | Option<Integer> idx_opt; | ||
| 7106 | algorithm | ||
| 7107 | 4177 | idx_opt := UnorderedMap.get(exp, map); | |
| 7108 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 4177 times.
✓ Branch 2 taken 454 times.
✓ Branch 3 taken 3723 times.
|
4177 | if isSome(idx_opt) then |
| 7109 | // this literal already exists | ||
| 7110 | 3723 | idx := Util.getOption(idx_opt); | |
| 7111 | else | ||
| 7112 | // new literal found | ||
| 7113 | 454 | idx := Pointer.access(idx_ptr); | |
| 7114 | 454 | Pointer.update(idx_ptr, idx + 1); | |
| 7115 | 454 | UnorderedMap.add(exp, idx, map); | |
| 7116 | end if; | ||
| 7117 | 4177 | exp := SHARED_LITERAL(idx, exp); | |
| 7118 | end replace; | ||
| 7119 | algorithm | ||
| 7120 | exp := match exp | ||
| 7121 | // do nothing on shared literal | ||
| 7122 | case Expression.SHARED_LITERAL() then exp; | ||
| 7123 | |||
| 7124 | // replace literal array expressions that are not trivial | ||
| 7125 | 299 | case ARRAY() guard(isLiteralReplace(exp)) then replace(replaceLiteralArrayElements(exp, map, idx_ptr), map, idx_ptr); | |
| 7126 | |||
| 7127 | case RECORD() guard(isLiteralReplace(exp)) algorithm | ||
| 7128 |
4/4✓ Branch 0 taken 382 times.
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 382 times.
✓ Branch 3 taken 39 times.
|
460 | exp.elements := list(replaceLiteral(elem, map, idx_ptr) for elem in exp.elements); |
| 7129 | 39 | then replace(exp, map, idx_ptr); | |
| 7130 | |||
| 7131 | // replace literal expressions that are not trivial | ||
| 7132 | 3839 | case _ guard(isLiteralReplace(exp)) then replace(exp, map, idx_ptr); | |
| 7133 | |||
| 7134 | // map down for other expressions | ||
| 7135 | 38193 | else Expression.mapShallow(exp, function replaceLiteral(map = map, idx_ptr = idx_ptr)); | |
| 7136 | end match; | ||
| 7137 | end replaceLiteral; | ||
| 7138 | |||
| 7139 | function replaceLiteralArrayElements | ||
| 7140 | input output Expression exp; | ||
| 7141 | input UnorderedMap<Expression, Integer> map; | ||
| 7142 | input Pointer<Integer> idx_ptr; | ||
| 7143 | algorithm | ||
| 7144 | exp := match exp | ||
| 7145 | case ARRAY() algorithm | ||
| 7146 | 636 | exp.elements := Array.map(exp.elements, function replaceLiteralArrayElements(map = map, idx_ptr = idx_ptr)); | |
| 7147 | then exp; | ||
| 7148 | 1407 | else replaceLiteral(exp, map, idx_ptr); | |
| 7149 | end match; | ||
| 7150 | end replaceLiteralArrayElements; | ||
| 7151 | |||
| 7152 | function replaceCrefWithBinding | ||
| 7153 | input ComponentRef cref; | ||
| 7154 | input output Expression exp; | ||
| 7155 | input recurse func; | ||
| 7156 | partial function recurse | ||
| 7157 | input output Expression exp; | ||
| 7158 | end recurse; | ||
| 7159 | protected | ||
| 7160 | Expression e; | ||
| 7161 | algorithm | ||
| 7162 | exp := match InstNode.getBindingExpOpt(ComponentRef.node(cref)) | ||
| 7163 | case SOME(e as Expression.INTEGER()) then e; | ||
| 7164 | 27 | case SOME(e as Expression.CREF()) then replaceCrefWithBinding(e.cref, e, func); | |
| 7165 | case SOME(Expression.SUBSCRIPTED_EXP(exp = e as Expression.INTEGER())) then e; | ||
| 7166 | 6 | case SOME(Expression.SUBSCRIPTED_EXP(exp = e as Expression.CREF())) then replaceCrefWithBinding(e.cref, e, func); | |
| 7167 | case SOME(e) algorithm | ||
| 7168 | ✗ | e := Expression.map(e, func); | |
| 7169 | then e; | ||
| 7170 | else exp; | ||
| 7171 | end match; | ||
| 7172 | end replaceCrefWithBinding; | ||
| 7173 | |||
| 7174 | function replaceResizableParameterWithOriginal | ||
| 7175 | input output Expression exp; | ||
| 7176 | algorithm | ||
| 7177 | exp := match exp | ||
| 7178 | // frontend replacement | ||
| 7179 | case Expression.CREF() guard(ComponentRef.isResizable(exp.cref)) algorithm | ||
| 7180 | 1346 | then replaceCrefWithBinding(exp.cref, exp, replaceResizableParameterWithOriginal); | |
| 7181 | else exp; | ||
| 7182 | end match; | ||
| 7183 | end replaceResizableParameterWithOriginal; | ||
| 7184 | |||
| 7185 | function replaceResizableParameter | ||
| 7186 | input output Expression exp; | ||
| 7187 | algorithm | ||
| 7188 | exp := match exp | ||
| 7189 | local | ||
| 7190 | PointerWeak<Variable> var; | ||
| 7191 | Integer v; | ||
| 7192 | |||
| 7193 | // backend replacement | ||
| 7194 | case Expression.CREF(cref = ComponentRef.CREF()) | ||
| 7195 | guard InstNode.isVar(ComponentRef.node(exp.cref)) and ComponentRef.isResizable(exp.cref) | ||
| 7196 | then match Pointer.access(PointerWeak.upgrade( | ||
| 7197 | InstNode.varPointer(ComponentRef.node(exp.cref)))) | ||
| 7198 | // optimal value has already been determined | ||
| 7199 | case Variable.VARIABLE(backendinfo = BackendInfo.BACKEND_INFO(varKind = VariableKind.PARAMETER(resize_value = SOME(v)))) | ||
| 7200 | 707 | then Expression.INTEGER(v); | |
| 7201 | |||
| 7202 | // optimal value not yet computed | ||
| 7203 | 143 | else replaceCrefWithBinding(exp.cref, exp, replaceResizableParameter); | |
| 7204 | end match; | ||
| 7205 | |||
| 7206 | // frontend replacement | ||
| 7207 | case Expression.CREF() guard(ComponentRef.isResizable(exp.cref)) | ||
| 7208 | 557 | then replaceCrefWithBinding(exp.cref, exp, replaceResizableParameter); | |
| 7209 | |||
| 7210 | else exp; | ||
| 7211 | end match; | ||
| 7212 | end replaceResizableParameter; | ||
| 7213 | |||
| 7214 | // Helper: compute multiplication result type from operand types. | ||
| 7215 | function mulResultType | ||
| 7216 | input Type tl; | ||
| 7217 | input Type tr; | ||
| 7218 | output Type tres; | ||
| 7219 | algorithm | ||
| 7220 |
1/4✗ Branch 1 not taken.
✓ Branch 2 taken 60 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
60 | if Type.isArray(tl) and Type.isArray(tr) then |
| 7221 | // Both arrays: keep (left) array type (sizes should already match semantically) | ||
| 7222 | tres := tl; | ||
| 7223 | elseif Type.isArray(tl) then | ||
| 7224 | tres := tl; // array * scalar | ||
| 7225 | elseif Type.isArray(tr) then | ||
| 7226 | tres := tr; // scalar * array | ||
| 7227 | else | ||
| 7228 | // both scalar -> promote numeric type (use left for now; scalar promotion elsewhere already handled) | ||
| 7229 | tres := tl; | ||
| 7230 | end if; | ||
| 7231 | end mulResultType; | ||
| 7232 | |||
| 7233 | // Helper: binary multiply with simple scalar/array size classification. | ||
| 7234 | function mmul | ||
| 7235 | input Expression lhs; | ||
| 7236 | input Expression rhs; | ||
| 7237 | input Operator baseOp; | ||
| 7238 | output Expression prod; | ||
| 7239 | protected | ||
| 7240 | Type tl = typeOf(lhs); | ||
| 7241 | Type tr = typeOf(rhs); | ||
| 7242 | Boolean lArr = Type.isArray(tl); | ||
| 7243 | Boolean rArr = Type.isArray(tr); | ||
| 7244 | Operator.SizeClassification sizeClass; | ||
| 7245 | Type resTy; | ||
| 7246 | Operator op; | ||
| 7247 | algorithm | ||
| 7248 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
|
60 | if not lArr and not rArr then |
| 7249 | sizeClass := NFOperator.SizeClassification.SCALAR; | ||
| 7250 | elseif not lArr and rArr then | ||
| 7251 | sizeClass := NFOperator.SizeClassification.SCALAR_ARRAY; | ||
| 7252 | elseif lArr and not rArr then | ||
| 7253 | sizeClass := NFOperator.SizeClassification.ARRAY_SCALAR; | ||
| 7254 | else | ||
| 7255 | sizeClass := NFOperator.SizeClassification.ELEMENT_WISE; | ||
| 7256 | end if; | ||
| 7257 | |||
| 7258 | 60 | resTy := mulResultType(tl, tr); | |
| 7259 | 60 | op := Operator.fromClassification((NFOperator.MathClassification.MULTIPLICATION, sizeClass), resTy); | |
| 7260 | 60 | prod := BINARY(lhs, op, rhs); | |
| 7261 | end mmul; | ||
| 7262 | |||
| 7263 | function productOfListExceptSelf | ||
| 7264 | "prod(f_k | k <> i) for each i. | ||
| 7265 | For arguments = {f1, f2, ..., fn} returns list: | ||
| 7266 | { Π_{k≠1} fk, Π_{k≠2} fk, ..., Π_{k≠n} fk }. | ||
| 7267 | Uses a prefix/suffix O(n) algorithm (no repeated full products). | ||
| 7268 | https://leetcode.com/problems/product-of-array-except-self/solutions/65622/simple-java-solution-in-o-n-without-extra-space/ | ||
| 7269 | If n = 0 -> {}, if n = 1 -> {1} (multiplicative identity of operator.ty)." | ||
| 7270 | input list<Expression> arguments; | ||
| 7271 | input Operator mulOp "Base multiplication operator (will be repaired per pair)"; | ||
| 7272 | output list<Expression> products; | ||
| 7273 | protected | ||
| 7274 | Integer n = listLength(arguments); | ||
| 7275 | array<Expression> argsArr; | ||
| 7276 | array<Expression> pref; | ||
| 7277 | array<Expression> res; | ||
| 7278 | Integer i; | ||
| 7279 | Expression rightProd; | ||
| 7280 | Type baseTy = mulOp.ty; | ||
| 7281 | Type elTy; | ||
| 7282 | algorithm | ||
| 7283 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if n == 0 then |
| 7284 | products := {}; | ||
| 7285 | ✗ | return; | |
| 7286 | end if; | ||
| 7287 | |||
| 7288 | // Determine element (scalar) type to build multiplicative identity | ||
| 7289 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
|
12 | elTy := if Type.isArray(baseTy) then Type.arrayElementType(baseTy) else baseTy; |
| 7290 | // Load arguments into array for indexed access | ||
| 7291 | 12 | argsArr := arrayCreate(n, Expression.makeOne(elTy)); | |
| 7292 | i := 1; | ||
| 7293 |
2/2✓ Branch 1 taken 24 times.
✓ Branch 2 taken 12 times.
|
36 | for a in arguments loop |
| 7294 | 24 | argsArr[i] := a; | |
| 7295 | 24 | i := i + 1; | |
| 7296 | end for; | ||
| 7297 | |||
| 7298 | // Allocate prefix array & result | ||
| 7299 | 12 | pref := arrayCreate(n, Expression.makeOne(elTy)); // pref[i] = product of args before i with pref[1] = 1. | |
| 7300 | 12 | res := arrayCreate(n, Expression.makeOne(elTy)); | |
| 7301 | |||
| 7302 | // Build prefix products: pref[i] = f1 * f2 * ... * f_{i-1} | ||
| 7303 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
24 | for i in 2:n loop |
| 7304 | 12 | pref[i] := mmul(pref[i-1], argsArr[i-1], mulOp); | |
| 7305 | end for; | ||
| 7306 | |||
| 7307 | // Suffix accumulation | ||
| 7308 | 12 | rightProd := Expression.makeOne(elTy); | |
| 7309 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
36 | for i in n:-1:1 loop |
| 7310 | // res[i] = (product of left side) * (product of right side) | ||
| 7311 | 24 | res[i] := mmul(pref[i], rightProd, mulOp); | |
| 7312 | // update rightProd *= argsArr[i] | ||
| 7313 | 24 | rightProd := mmul(rightProd, argsArr[i], mulOp); | |
| 7314 | end for; | ||
| 7315 | |||
| 7316 | // Collect back to list (in order) | ||
| 7317 | products := {}; | ||
| 7318 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
36 | for i in n:-1:1 loop |
| 7319 | //res[i] := map(res[i], repairOperator); | ||
| 7320 | 24 | products := SimplifyExp.simplify(res[i]) :: products; | |
| 7321 | end for; | ||
| 7322 | end productOfListExceptSelf; | ||
| 7323 | annotation(__OpenModelica_Interface="nf_frontend"); | ||
| 7324 | end NFExpression; | ||
| 7325 |