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