OMCompiler/Compiler/NFFrontEnd/NFEvalConstants.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 NFEvalConstants | ||
| 37 | |||
| 38 | import FlatModel = NFFlatModel; | ||
| 39 | import Equation = NFEquation; | ||
| 40 | import Statement = NFStatement; | ||
| 41 | import Expression = NFExpression; | ||
| 42 | import Type = NFType; | ||
| 43 | import ComponentRef = NFComponentRef; | ||
| 44 | import NFFlatten.FunctionTree; | ||
| 45 | import Class = NFClass; | ||
| 46 | import NFInstNode.InstNode; | ||
| 47 | import NFInstNode; | ||
| 48 | import NFFunction.Function; | ||
| 49 | import Sections = NFSections; | ||
| 50 | import Binding = NFBinding; | ||
| 51 | import Variable = NFVariable; | ||
| 52 | import Algorithm = NFAlgorithm; | ||
| 53 | import NFEquation.Branch; | ||
| 54 | import Dimension = NFDimension; | ||
| 55 | import InstContext = NFInstContext; | ||
| 56 | import Component = NFComponent; | ||
| 57 | import NFClassTree.ClassTree; | ||
| 58 | |||
| 59 | protected | ||
| 60 | import MetaModelica.Dangerous.*; | ||
| 61 | import ExecStat.execStat; | ||
| 62 | import NFPrefixes.Variability; | ||
| 63 | import Ceval = NFCeval; | ||
| 64 | import Package = NFPackage; | ||
| 65 | import SimplifyExp = NFSimplifyExp; | ||
| 66 | import ErrorExt; | ||
| 67 | import Record = NFRecord; | ||
| 68 | import Flatten = NFFlatten; | ||
| 69 | |||
| 70 | public | ||
| 71 | |||
| 72 | uniontype EvalSettings | ||
| 73 | record SETTINGS | ||
| 74 | Boolean scalarize; | ||
| 75 | end SETTINGS; | ||
| 76 | end EvalSettings; | ||
| 77 | |||
| 78 | function evaluate | ||
| 79 | input output FlatModel flatModel; | ||
| 80 | input InstContext.Type context; | ||
| 81 | protected | ||
| 82 | EvalSettings settings; | ||
| 83 | algorithm | ||
| 84 |
2/2✓ Branch 1 taken 219 times.
✓ Branch 2 taken 1364 times.
|
1802 | settings := EvalSettings.SETTINGS( |
| 85 | Flags.isSet(Flags.NF_SCALARIZE) | ||
| 86 | ); | ||
| 87 | |||
| 88 |
4/4✓ Branch 0 taken 240734 times.
✓ Branch 1 taken 1577 times.
✓ Branch 2 taken 240734 times.
✓ Branch 3 taken 1577 times.
|
242311 | flatModel.variables := list(evaluateVariable(v, context, settings) for v in flatModel.variables); |
| 89 | flatModel.equations := evaluateEquations(flatModel.equations); | ||
| 90 | flatModel.initialEquations := evaluateEquations(flatModel.initialEquations); | ||
| 91 | flatModel.algorithms := evaluateAlgorithms(flatModel.algorithms); | ||
| 92 | flatModel.initialAlgorithms := evaluateAlgorithms(flatModel.initialAlgorithms); | ||
| 93 | |||
| 94 | 1576 | execStat(getInstanceName()); | |
| 95 | end evaluate; | ||
| 96 | |||
| 97 | function evaluateVariable | ||
| 98 | input output Variable var; | ||
| 99 | input InstContext.Type context; | ||
| 100 | input EvalSettings settings; | ||
| 101 | protected | ||
| 102 | Binding binding; | ||
| 103 | Boolean structural; | ||
| 104 | Variability variability; | ||
| 105 | algorithm | ||
| 106 | 241179 | variability := Variable.variability(var); | |
| 107 |
4/4✓ Branch 0 taken 41645 times.
✓ Branch 1 taken 199534 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 41643 times.
|
241179 | structural := variability <= Variability.STRUCTURAL_PARAMETER and |
| 108 | not Type.isExternalObject(var.ty); | ||
| 109 | 241179 | binding := evaluateBinding(var.binding, var.name, structural, variability, context); | |
| 110 | |||
| 111 |
2/2✓ Branch 0 taken 42636 times.
✓ Branch 1 taken 198537 times.
|
241173 | if not referenceEq(binding, var.binding) then |
| 112 | 42636 | var.binding := binding; | |
| 113 | end if; | ||
| 114 | |||
| 115 |
8/8✓ Branch 0 taken 471577 times.
✓ Branch 1 taken 241173 times.
✓ Branch 2 taken 471577 times.
✓ Branch 3 taken 241173 times.
✓ Branch 5 taken 445 times.
✓ Branch 6 taken 241173 times.
✓ Branch 7 taken 445 times.
✓ Branch 8 taken 241173 times.
|
713195 | var.typeAttributes := list(evaluateTypeAttribute(a, var.name, context) for a in var.typeAttributes); |
| 116 | var.children := list(evaluateVariable(v, context, settings) for v in var.children); | ||
| 117 | end evaluateVariable; | ||
| 118 | |||
| 119 | function evaluateBinding | ||
| 120 | input output Binding binding; | ||
| 121 | input ComponentRef prefix; | ||
| 122 | input Boolean structural; | ||
| 123 | input Variability variability; | ||
| 124 | input InstContext.Type context; | ||
| 125 | protected | ||
| 126 | Expression exp, eexp; | ||
| 127 | SourceInfo info; | ||
| 128 | algorithm | ||
| 129 |
2/2✓ Branch 1 taken 109998 times.
✓ Branch 2 taken 602758 times.
|
712756 | if Binding.isBound(binding) then |
| 130 | 602758 | exp := Binding.getTypedExp(binding); | |
| 131 | |||
| 132 |
2/2✓ Branch 0 taken 48036 times.
✓ Branch 1 taken 554722 times.
|
602758 | if structural then |
| 133 | 48036 | info := Binding.getInfo(binding); | |
| 134 | 48036 | eexp := evaluateExp(exp, info); | |
| 135 | 48035 | eexp := SimplifyExp.simplify(eexp); | |
| 136 | |||
| 137 |
4/4✓ Branch 1 taken 649 times.
✓ Branch 2 taken 47386 times.
✓ Branch 4 taken 180 times.
✓ Branch 5 taken 469 times.
|
48035 | if not (Expression.isLiteral(eexp) or Expression.isKnownSizeFill(eexp)) then |
| 138 | // Any structural parameter that hasn't already been evaluated in earlier stages, | ||
| 139 | // such as parameters with Evaluate=true annotations, are probably not critical to evaluate. | ||
| 140 |
3/4✓ Branch 0 taken 31 times.
✓ Branch 1 taken 149 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 31 times.
|
180 | if variability > Variability.CONSTANT or InstContext.inRelaxed(context) then |
| 141 | 149 | eexp := Ceval.tryEvalExp(eexp); | |
| 142 | else | ||
| 143 | 31 | eexp := Ceval.evalExp(eexp, Ceval.EvalTarget.new(info, context)); | |
| 144 | end if; | ||
| 145 | end if; | ||
| 146 | |||
| 147 | 48030 | eexp := Flatten.flattenExp(eexp, Flatten.PREFIX(InstNode.EMPTY_NODE(), prefix), info); | |
| 148 | else | ||
| 149 | 554722 | eexp := evaluateExp(exp, Binding.getInfo(binding)); | |
| 150 | end if; | ||
| 151 | |||
| 152 |
2/2✓ Branch 0 taken 468233 times.
✓ Branch 1 taken 134519 times.
|
602752 | if not referenceEq(exp, eexp) then |
| 153 | 134519 | binding := Binding.setTypedExp(eexp, binding); | |
| 154 | end if; | ||
| 155 | end if; | ||
| 156 | end evaluateBinding; | ||
| 157 | |||
| 158 | function evaluateTypeAttribute | ||
| 159 | input output tuple<String, Binding> attribute; | ||
| 160 | input ComponentRef prefix; | ||
| 161 | input InstContext.Type context; | ||
| 162 | protected | ||
| 163 | String name; | ||
| 164 | Binding binding, sbinding; | ||
| 165 | Boolean structural; | ||
| 166 | algorithm | ||
| 167 | 471577 | (name, binding) := attribute; | |
| 168 |
8/8✓ Branch 0 taken 63917 times.
✓ Branch 1 taken 407660 times.
✓ Branch 3 taken 61087 times.
✓ Branch 4 taken 2830 times.
✓ Branch 5 taken 26712 times.
✓ Branch 6 taken 442035 times.
✓ Branch 8 taken 3567 times.
✓ Branch 9 taken 23145 times.
|
471577 | structural := name == "fixed" or name == "stateSelect"; |
| 169 | 471577 | sbinding := evaluateBinding(binding, prefix, structural, Variability.PARAMETER, context); | |
| 170 | |||
| 171 |
2/2✓ Branch 0 taken 379694 times.
✓ Branch 1 taken 91883 times.
|
471577 | if not referenceEq(binding, sbinding) then |
| 172 | 91883 | attribute := (name, sbinding); | |
| 173 | end if; | ||
| 174 | end evaluateTypeAttribute; | ||
| 175 | |||
| 176 | function evaluateExp | ||
| 177 | input Expression exp; | ||
| 178 | input SourceInfo info; | ||
| 179 | output Expression outExp; | ||
| 180 | algorithm | ||
| 181 | 903290 | outExp := evaluateExpTraverser(exp, info); | |
| 182 | end evaluateExp; | ||
| 183 | |||
| 184 | function evaluateExpTraverser | ||
| 185 | input Expression exp; | ||
| 186 | input SourceInfo info; | ||
| 187 | input Boolean changed = false; | ||
| 188 | output Expression outExp; | ||
| 189 | output Boolean outChanged = changed; | ||
| 190 | protected | ||
| 191 | Expression e; | ||
| 192 | ComponentRef cref; | ||
| 193 | Type ty, ty2; | ||
| 194 | Variability var; | ||
| 195 | algorithm | ||
| 196 | (outExp, outChanged) := match exp | ||
| 197 | case Expression.CREF() | ||
| 198 | algorithm | ||
| 199 |
1/2✗ Branch 3 not taken.
✓ Branch 4 taken 511684 times.
|
511684 | (outExp as Expression.CREF(cref = cref, ty = ty), outChanged) := |
| 200 | Expression.mapFoldShallow(exp, | ||
| 201 | function evaluateExpTraverser(info = info), false); | ||
| 202 | |||
| 203 | 511684 | var := ComponentRef.nodeVariability(cref); | |
| 204 | |||
| 205 |
4/4✓ Branch 0 taken 66618 times.
✓ Branch 1 taken 445066 times.
✓ Branch 3 taken 66616 times.
✓ Branch 4 taken 2 times.
|
511684 | if var <= Variability.STRUCTURAL_PARAMETER and not Type.isExternalObject(ty) then |
| 206 | // Evaluate all constants and structural parameters. | ||
| 207 |
2/2✓ Branch 0 taken 34270 times.
✓ Branch 1 taken 32346 times.
|
66616 | if var > Variability.CONSTANT then |
| 208 | 34270 | ErrorExt.setCheckpoint(getInstanceName()); | |
| 209 | try | ||
| 210 | 34270 | e := Ceval.evalCref(cref, outExp, NFCeval.noTarget, evalSubscripts = false); | |
| 211 | 34270 | e := Flatten.flattenExp(e, Flatten.Prefix.PREFIX(InstNode.EMPTY_NODE(), cref), info); | |
| 212 | outExp := e; | ||
| 213 | outChanged := true; | ||
| 214 | else | ||
| 215 | end try; | ||
| 216 | 34270 | ErrorExt.rollBack(getInstanceName()); | |
| 217 | else | ||
| 218 | 32346 | outExp := Ceval.evalCref(cref, outExp, Ceval.EvalTarget.new(info), evalSubscripts = false); | |
| 219 | 32344 | outExp := Flatten.flattenExp(outExp, Flatten.Prefix.PREFIX(InstNode.EMPTY_NODE(), cref), info); | |
| 220 | outChanged := true; | ||
| 221 | end if; | ||
| 222 | elseif outChanged then | ||
| 223 | 3798 | ty := ComponentRef.getSubscriptedType(cref); | |
| 224 | end if; | ||
| 225 | |||
| 226 | 511682 | ty2 := evaluateType(ty, info); | |
| 227 |
2/2✓ Branch 0 taken 66301 times.
✓ Branch 1 taken 445381 times.
|
511682 | if not referenceEq(ty, ty2) then |
| 228 | 66301 | outExp := Expression.setType(ty2, outExp); | |
| 229 | end if; | ||
| 230 | 511682 | then | |
| 231 | (outExp, outChanged); | ||
| 232 | |||
| 233 | 16730 | case Expression.ARRAY(literal = true) then (exp, false); | |
| 234 | 8365 | case Expression.IF() then evaluateIfExp(exp, info); | |
| 235 | |||
| 236 | // Only evaluate the index for size expressions. | ||
| 237 | case Expression.SIZE() | ||
| 238 | algorithm | ||
| 239 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
|
1 | if isSome(exp.dimIndex) then |
| 240 | 1 | SOME(e) := exp.dimIndex; | |
| 241 | 1 | (e, outChanged) := Expression.mapFoldShallow(e, | |
| 242 | function evaluateExpTraverser(info = info), false); | ||
| 243 | |||
| 244 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 | if outChanged then |
| 245 | ✗ | exp.dimIndex := SOME(e); | |
| 246 | end if; | ||
| 247 | end if; | ||
| 248 | 1 | then | |
| 249 | (exp, outChanged); | ||
| 250 | |||
| 251 | case Expression.RANGE() | ||
| 252 | algorithm | ||
| 253 | 2675 | (outExp, outChanged) := Expression.mapFoldShallow(exp, | |
| 254 | function evaluateExpTraverser(info = info), false); | ||
| 255 | |||
| 256 | // If anything in a range is evaluated its better to just retype it | ||
| 257 | // rather than evaluating the type, since it's usually faster and gives | ||
| 258 | // better results in some cases. | ||
| 259 |
2/2✓ Branch 0 taken 574 times.
✓ Branch 1 taken 2101 times.
|
2675 | if outChanged then |
| 260 | 574 | outExp := Expression.retype(outExp); | |
| 261 | end if; | ||
| 262 | 2675 | then | |
| 263 | (outExp, outChanged); | ||
| 264 | |||
| 265 | else | ||
| 266 | algorithm | ||
| 267 | 1389738 | (outExp, outChanged) := Expression.mapFoldShallow(exp, | |
| 268 | function evaluateExpTraverser(info = info), false); | ||
| 269 | |||
| 270 | 1389737 | ty := Expression.typeOf(outExp); | |
| 271 | 1389737 | ty2 := evaluateType(ty, info); | |
| 272 |
2/2✓ Branch 0 taken 159817 times.
✓ Branch 1 taken 1229920 times.
|
1389737 | then |
| 273 | (if referenceEq(ty, ty2) then outExp else Expression.setType(ty2, outExp), outChanged); | ||
| 274 | end match; | ||
| 275 | |||
| 276 |
2/2✓ Branch 0 taken 1020780 times.
✓ Branch 1 taken 908410 times.
|
1929190 | outChanged := changed or outChanged; |
| 277 | end evaluateExpTraverser; | ||
| 278 | |||
| 279 | function evaluateType | ||
| 280 | input output Type ty; | ||
| 281 | input SourceInfo info; | ||
| 282 | algorithm | ||
| 283 | ty := match ty | ||
| 284 | case Type.ARRAY() | ||
| 285 | algorithm | ||
| 286 |
4/4✓ Branch 0 taken 269372 times.
✓ Branch 1 taken 226118 times.
✓ Branch 2 taken 269372 times.
✓ Branch 3 taken 226118 times.
|
721608 | ty.dimensions := list(evaluateDimension(d, info) for d in ty.dimensions); |
| 287 | then | ||
| 288 | ty; | ||
| 289 | |||
| 290 | case Type.CONDITIONAL_ARRAY() | ||
| 291 | ✗ | then Type.simplifyConditionalArray(ty); | |
| 292 | |||
| 293 | else ty; | ||
| 294 | end match; | ||
| 295 | end evaluateType; | ||
| 296 | |||
| 297 | function evaluateDimension | ||
| 298 | input Dimension dim; | ||
| 299 | input SourceInfo info; | ||
| 300 | output Dimension outDim; | ||
| 301 | algorithm | ||
| 302 | outDim := match dim | ||
| 303 | local | ||
| 304 | Expression e; | ||
| 305 | |||
| 306 | case Dimension.EXP() | ||
| 307 | algorithm | ||
| 308 | 243 | e := evaluateExp(dim.exp, info); | |
| 309 |
1/2✓ Branch 0 taken 243 times.
✗ Branch 1 not taken.
|
243 | then |
| 310 | if referenceEq(e, dim.exp) then dim else Dimension.fromExp(e, dim.var); | ||
| 311 | |||
| 312 | else dim; | ||
| 313 | end match; | ||
| 314 | end evaluateDimension; | ||
| 315 | |||
| 316 | function evaluateIfExp | ||
| 317 | "Evaluates constants in an if-expression. This is done by first checking if | ||
| 318 | the condition can be evaluated, in which case branch selection is done to | ||
| 319 | avoid issues that can arise when evaluating constants in branches that are | ||
| 320 | expected to be discarded." | ||
| 321 | input Expression exp; | ||
| 322 | input SourceInfo info; | ||
| 323 | output Expression outExp; | ||
| 324 | output Boolean outChanged; | ||
| 325 | protected | ||
| 326 | Type ty; | ||
| 327 | Expression cond, tb, fb; | ||
| 328 | Boolean c1, c2; | ||
| 329 | algorithm | ||
| 330 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8365 times.
|
8365 | Expression.IF(ty, cond, tb, fb) := exp; |
| 331 | 8365 | (cond, outChanged) := evaluateExpTraverser(cond, info); | |
| 332 | |||
| 333 | // Simplify the condition in case it can be reduced to a literal value. | ||
| 334 | 8365 | cond := SimplifyExp.simplify(cond); | |
| 335 | |||
| 336 | (outExp, outChanged) := match cond | ||
| 337 | // Only evaluate constants in and return one of the branches if the | ||
| 338 | // condition is a literal boolean value. | ||
| 339 | case Expression.BOOLEAN() | ||
| 340 | algorithm | ||
| 341 |
2/2✓ Branch 0 taken 3655 times.
✓ Branch 1 taken 1467 times.
|
8777 | outExp := evaluateExpTraverser(if cond.value then tb else fb, info); |
| 342 | then | ||
| 343 | (outExp, true); | ||
| 344 | |||
| 345 | // Otherwise evaluate constants in both branches and return the whole | ||
| 346 | // if-expression. | ||
| 347 | else | ||
| 348 | algorithm | ||
| 349 | 3243 | (tb, c1) := evaluateExpTraverser(tb, info); | |
| 350 | 3243 | (fb, c2) := evaluateExpTraverser(fb, info); | |
| 351 |
6/6✓ Branch 1 taken 2894 times.
✓ Branch 2 taken 349 times.
✓ Branch 3 taken 2785 times.
✓ Branch 4 taken 109 times.
✓ Branch 5 taken 2470 times.
✓ Branch 6 taken 315 times.
|
3243 | then |
| 352 | (Expression.IF(ty, cond, tb, fb), outChanged or c1 or c2); | ||
| 353 | |||
| 354 | end match; | ||
| 355 | end evaluateIfExp; | ||
| 356 | |||
| 357 | function evaluateEquations | ||
| 358 | input list<Equation> eql; | ||
| 359 | output list<Equation> outEql = list(evaluateEquation(e) for e in eql); | ||
| 360 | end evaluateEquations; | ||
| 361 | |||
| 362 | function evaluateEquation | ||
| 363 | input output Equation eq; | ||
| 364 | protected | ||
| 365 | SourceInfo info = Equation.info(eq); | ||
| 366 | algorithm | ||
| 367 | eq := match eq | ||
| 368 | local | ||
| 369 | Expression e1, e2, e3; | ||
| 370 | Type ty; | ||
| 371 | |||
| 372 | case Equation.EQUALITY() | ||
| 373 | algorithm | ||
| 374 | 140706 | ty := Type.mapDims(eq.ty, function evaluateDimension(info = info)); | |
| 375 | 140706 | e1 := evaluateExp(eq.lhs, info); | |
| 376 | 140706 | e2 := evaluateExp(eq.rhs, info); | |
| 377 | 140705 | then | |
| 378 | Equation.EQUALITY(e1, e2, ty, eq.scope, eq.source, eq.scalarizeMode); | ||
| 379 | |||
| 380 | case Equation.FOR() | ||
| 381 | algorithm | ||
| 382 | 712 | eq.range := Util.applyOption(eq.range, function evaluateExp(info = info)); | |
| 383 | 356 | eq.body := evaluateEquations(eq.body); | |
| 384 | then | ||
| 385 | eq; | ||
| 386 | |||
| 387 | case Equation.IF() | ||
| 388 | algorithm | ||
| 389 |
4/4✓ Branch 0 taken 2599 times.
✓ Branch 1 taken 1463 times.
✓ Branch 2 taken 2599 times.
✓ Branch 3 taken 1463 times.
|
5525 | eq.branches := list(evaluateEqBranch(b, info) for b in eq.branches); |
| 390 | then | ||
| 391 | eq; | ||
| 392 | |||
| 393 | case Equation.WHEN() | ||
| 394 | algorithm | ||
| 395 |
4/4✓ Branch 0 taken 363 times.
✓ Branch 1 taken 322 times.
✓ Branch 2 taken 363 times.
✓ Branch 3 taken 322 times.
|
1007 | eq.branches := list(evaluateEqBranch(b, info) for b in eq.branches); |
| 396 | then | ||
| 397 | eq; | ||
| 398 | |||
| 399 | case Equation.ASSERT() | ||
| 400 | algorithm | ||
| 401 | 4577 | e1 := evaluateExp(eq.condition, info); | |
| 402 | 4577 | e2 := evaluateExp(eq.message, info); | |
| 403 | 4577 | e3 := evaluateExp(eq.level, info); | |
| 404 | 4577 | then | |
| 405 | Equation.ASSERT(e1, e2, e3, eq.scope, eq.source); | ||
| 406 | |||
| 407 | case Equation.TERMINATE() | ||
| 408 | algorithm | ||
| 409 | 6 | eq.message := evaluateExp(eq.message, info); | |
| 410 | then | ||
| 411 | eq; | ||
| 412 | |||
| 413 | case Equation.REINIT() | ||
| 414 | algorithm | ||
| 415 | 28 | eq.reinitExp := evaluateExp(eq.reinitExp, info); | |
| 416 | then | ||
| 417 | eq; | ||
| 418 | |||
| 419 | case Equation.NORETCALL() | ||
| 420 | algorithm | ||
| 421 | 70 | eq.exp := evaluateExp(eq.exp, info); | |
| 422 | then | ||
| 423 | eq; | ||
| 424 | |||
| 425 | else eq; | ||
| 426 | end match; | ||
| 427 | end evaluateEquation; | ||
| 428 | |||
| 429 | function evaluateEqBranch | ||
| 430 | input Branch branch; | ||
| 431 | input SourceInfo info; | ||
| 432 | output Branch outBranch; | ||
| 433 | algorithm | ||
| 434 | outBranch := match branch | ||
| 435 | local | ||
| 436 | Expression condition; | ||
| 437 | list<Equation> body; | ||
| 438 | |||
| 439 | case Branch.BRANCH(condition = condition, body = body) | ||
| 440 | algorithm | ||
| 441 | 2957 | condition := evaluateExp(condition, info); | |
| 442 | 2957 | body := evaluateEquations(body); | |
| 443 | 2957 | then | |
| 444 | Branch.BRANCH(condition, branch.conditionVar, body); | ||
| 445 | |||
| 446 | else branch; | ||
| 447 | end match; | ||
| 448 | end evaluateEqBranch; | ||
| 449 | |||
| 450 | function evaluateAlgorithms | ||
| 451 | input list<Algorithm> algs; | ||
| 452 | output list<Algorithm> outAlgs = list(evaluateAlgorithm(a) for a in algs); | ||
| 453 | end evaluateAlgorithms; | ||
| 454 | |||
| 455 | function evaluateAlgorithm | ||
| 456 | input output Algorithm alg; | ||
| 457 | algorithm | ||
| 458 | 197 | alg.statements := evaluateStatements(alg.statements); | |
| 459 | end evaluateAlgorithm; | ||
| 460 | |||
| 461 | function evaluateStatements | ||
| 462 | input list<Statement> stmts; | ||
| 463 | output list<Statement> outStmts = list(evaluateStatement(s) for s in stmts); | ||
| 464 | end evaluateStatements; | ||
| 465 | |||
| 466 | function evaluateStatement | ||
| 467 | input output Statement stmt; | ||
| 468 | protected | ||
| 469 | SourceInfo info = Statement.info(stmt); | ||
| 470 | algorithm | ||
| 471 | stmt := match stmt | ||
| 472 | local | ||
| 473 | Expression e1, e2, e3; | ||
| 474 | Type ty; | ||
| 475 | |||
| 476 | case Statement.ASSIGNMENT() | ||
| 477 | algorithm | ||
| 478 | 539 | ty := Type.mapDims(stmt.ty, function evaluateDimension(info = info)); | |
| 479 | 539 | e1 := evaluateExp(stmt.lhs, info); | |
| 480 | 539 | e2 := evaluateExp(stmt.rhs, info); | |
| 481 | 539 | then | |
| 482 | Statement.ASSIGNMENT(e1, e2, ty, stmt.source); | ||
| 483 | |||
| 484 | case Statement.FOR() | ||
| 485 | algorithm | ||
| 486 | 188 | stmt.range := Util.applyOption(stmt.range, function evaluateExp(info = info)); | |
| 487 | 94 | stmt.body := evaluateStatements(stmt.body); | |
| 488 | then | ||
| 489 | stmt; | ||
| 490 | |||
| 491 | case Statement.IF() | ||
| 492 | algorithm | ||
| 493 |
4/4✓ Branch 0 taken 237 times.
✓ Branch 1 taken 176 times.
✓ Branch 2 taken 237 times.
✓ Branch 3 taken 176 times.
|
589 | stmt.branches := list(evaluateStmtBranch(b, info) for b in stmt.branches); |
| 494 | then | ||
| 495 | stmt; | ||
| 496 | |||
| 497 | case Statement.WHEN() | ||
| 498 | algorithm | ||
| 499 |
4/4✓ Branch 0 taken 118 times.
✓ Branch 1 taken 82 times.
✓ Branch 2 taken 118 times.
✓ Branch 3 taken 82 times.
|
282 | stmt.branches := list(evaluateStmtBranch(b, info) for b in stmt.branches); |
| 500 | then | ||
| 501 | stmt; | ||
| 502 | |||
| 503 | case Statement.ASSERT() | ||
| 504 | algorithm | ||
| 505 | 57 | e1 := evaluateExp(stmt.condition, info); | |
| 506 | 57 | e2 := evaluateExp(stmt.message, info); | |
| 507 | 57 | e3 := evaluateExp(stmt.level, info); | |
| 508 | 57 | then | |
| 509 | Statement.ASSERT(e1, e2, e3, stmt.source); | ||
| 510 | |||
| 511 | case Statement.TERMINATE() | ||
| 512 | algorithm | ||
| 513 | 1 | stmt.message := evaluateExp(stmt.message, info); | |
| 514 | then | ||
| 515 | stmt; | ||
| 516 | |||
| 517 | case Statement.REINIT() | ||
| 518 | algorithm | ||
| 519 | 4 | stmt.reinitExp := evaluateExp(stmt.reinitExp, info); | |
| 520 | then | ||
| 521 | stmt; | ||
| 522 | |||
| 523 | case Statement.NORETCALL() | ||
| 524 | algorithm | ||
| 525 | 24 | stmt.exp := evaluateExp(stmt.exp, info); | |
| 526 | then | ||
| 527 | stmt; | ||
| 528 | |||
| 529 | case Statement.WHILE() | ||
| 530 | algorithm | ||
| 531 | ✗ | stmt.condition := evaluateExp(stmt.condition, info); | |
| 532 | ✗ | stmt.body := evaluateStatements(stmt.body); | |
| 533 | then | ||
| 534 | stmt; | ||
| 535 | |||
| 536 | else stmt; | ||
| 537 | end match; | ||
| 538 | end evaluateStatement; | ||
| 539 | |||
| 540 | function evaluateStmtBranch | ||
| 541 | input tuple<Expression, list<Statement>> branch; | ||
| 542 | input SourceInfo info; | ||
| 543 | output tuple<Expression, list<Statement>> outBranch; | ||
| 544 | protected | ||
| 545 | Expression cond; | ||
| 546 | list<Statement> body; | ||
| 547 | algorithm | ||
| 548 | 355 | (cond, body) := branch; | |
| 549 | 355 | cond := evaluateExp(cond, info); | |
| 550 | 355 | body := evaluateStatements(body); | |
| 551 | 355 | outBranch := (cond, body); | |
| 552 | end evaluateStmtBranch; | ||
| 553 | |||
| 554 | function evaluateFunction | ||
| 555 | input output Function func; | ||
| 556 | protected | ||
| 557 | Boolean is_con; | ||
| 558 | algorithm | ||
| 559 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 12185 times.
|
12185 | if not Function.isEvaluated(func) then |
| 560 | 12185 | Function.markEvaluated(func); | |
| 561 | 12185 | is_con := Function.isDefaultRecordConstructor(func); | |
| 562 | |||
| 563 |
2/2✓ Branch 0 taken 10610 times.
✓ Branch 1 taken 1575 times.
|
22795 | func := Function.mapExp(func, |
| 564 | function evaluateFuncExp(fnNode = InstNode.fromHandle(func.node), evaluateAll = is_con), | ||
| 565 | function evaluateFuncExp(fnNode = InstNode.fromHandle(func.node), evaluateAll = true)); | ||
| 566 | |||
| 567 |
2/2✓ Branch 0 taken 1575 times.
✓ Branch 1 taken 10610 times.
|
12185 | if is_con then |
| 568 | 1575 | Record.checkLocalFieldOrder(func.locals, InstNode.fromHandle(func.node), InstNode.info(InstNode.fromHandle(func.node))); | |
| 569 | end if; | ||
| 570 | |||
| 571 |
2/2✓ Branch 0 taken 800 times.
✓ Branch 1 taken 12185 times.
|
12985 | for fn_der in func.derivatives loop |
| 572 |
2/2✓ Branch 2 taken 800 times.
✓ Branch 3 taken 800 times.
|
1600 | for der_fn in Function.getCachedFuncs(InstNode.borrow(fn_der.derivativeFn)) loop |
| 573 | 800 | evaluateFunction(der_fn); | |
| 574 | end for; | ||
| 575 | end for; | ||
| 576 | end if; | ||
| 577 | end evaluateFunction; | ||
| 578 | |||
| 579 | function evaluateFuncExp | ||
| 580 | input Expression exp; | ||
| 581 | input InstNode fnNode; | ||
| 582 | input Boolean evaluateAll; | ||
| 583 | output Expression outExp; | ||
| 584 | algorithm | ||
| 585 | 494332 | outExp := evaluateFuncExpTraverser(exp, fnNode, evaluateAll, false); | |
| 586 | end evaluateFuncExp; | ||
| 587 | |||
| 588 | function evaluateFuncExpTraverser | ||
| 589 | input Expression exp; | ||
| 590 | input InstNode fnNode; | ||
| 591 | input Boolean evaluateAll; | ||
| 592 | input Boolean changed; | ||
| 593 | output Expression outExp; | ||
| 594 | output Boolean outChanged; | ||
| 595 | protected | ||
| 596 | Expression e; | ||
| 597 | algorithm | ||
| 598 |
2/2✓ Branch 0 taken 1673129 times.
✓ Branch 1 taken 280866 times.
|
3627124 | (e, outChanged) := Expression.mapFoldShallow(exp, |
| 599 | function evaluateFuncExpTraverser(fnNode = fnNode, evaluateAll = evaluateAll), false); | ||
| 600 | |||
| 601 | outExp := match e | ||
| 602 | case Expression.CREF() | ||
| 603 | algorithm | ||
| 604 |
4/4✓ Branch 0 taken 654018 times.
✓ Branch 1 taken 12061 times.
✓ Branch 3 taken 12830 times.
✓ Branch 4 taken 641188 times.
|
666079 | if evaluateAll or not isLocalFunctionVariable(e.cref, fnNode) then |
| 605 | 24891 | ErrorExt.setCheckpoint(getInstanceName()); | |
| 606 | try | ||
| 607 | 24891 | outExp := Ceval.evalCref(e.cref, e, NFCeval.noTarget, evalSubscripts = false); | |
| 608 | else | ||
| 609 | ✗ | outExp := e; | |
| 610 | end try; | ||
| 611 | 24891 | ErrorExt.rollBack(getInstanceName()); | |
| 612 | outChanged := true; | ||
| 613 | elseif outChanged then | ||
| 614 | // If the cref's subscripts changed, recalculate its type. | ||
| 615 | 1202 | outExp := Expression.CREF(ComponentRef.getSubscriptedType(e.cref), e.cref); | |
| 616 | else | ||
| 617 | outExp := e; | ||
| 618 | end if; | ||
| 619 | then | ||
| 620 | outExp; | ||
| 621 | |||
| 622 |
2/2✓ Branch 0 taken 22180 times.
✓ Branch 1 taken 1265736 times.
|
1287916 | else if outChanged then Expression.retype(e) else e; |
| 623 | end match; | ||
| 624 | |||
| 625 |
2/2✓ Branch 0 taken 1459663 times.
✓ Branch 1 taken 494332 times.
|
1953995 | outChanged := changed or outChanged; |
| 626 | end evaluateFuncExpTraverser; | ||
| 627 | |||
| 628 | function isLocalFunctionVariable | ||
| 629 | input ComponentRef cref; | ||
| 630 | input InstNode fnNode; | ||
| 631 | output Boolean res; | ||
| 632 | protected | ||
| 633 | InstNode node; | ||
| 634 | list<Function> fnl; | ||
| 635 | Function fn; | ||
| 636 | algorithm | ||
| 637 |
2/2✓ Branch 1 taken 642766 times.
✓ Branch 2 taken 11252 times.
|
654018 | if ComponentRef.isPackageConstant(cref) then |
| 638 | res := false; | ||
| 639 | elseif ComponentRef.nodeVariability(cref) <= Variability.PARAMETER and ComponentRef.isCref(cref) then | ||
| 640 | 6131 | node := InstNode.instanceParent(ComponentRef.node(ComponentRef.last(cref))); | |
| 641 | |||
| 642 |
2/2✓ Branch 1 taken 4816 times.
✓ Branch 2 taken 1315 times.
|
6131 | if InstNode.isClass(node) then |
| 643 | 4816 | fnl := Function.getCachedFuncs(node); | |
| 644 | |||
| 645 |
2/2✓ Branch 0 taken 4553 times.
✓ Branch 1 taken 263 times.
|
4816 | if listEmpty(fnl) then |
| 646 | res := false; | ||
| 647 | else | ||
| 648 | 4553 | fn := listHead(fnl); | |
| 649 | 4553 | res := InstNode.refEqual(fnNode, InstNode.fromHandle(fn.node)); | |
| 650 | end if; | ||
| 651 | else | ||
| 652 | res := false; | ||
| 653 | end if; | ||
| 654 | else | ||
| 655 | res := true; | ||
| 656 | end if; | ||
| 657 | end isLocalFunctionVariable; | ||
| 658 | |||
| 659 | function evaluateRecordDeclaration | ||
| 660 | input InstNode recordNode; | ||
| 661 | algorithm | ||
| 662 | 26 | ClassTree.applyComponents(Class.classTree(InstNode.getClass(recordNode)), | |
| 663 | function evaluateRecordDeclarationField(recordNode = recordNode)); | ||
| 664 | end evaluateRecordDeclaration; | ||
| 665 | |||
| 666 | function evaluateRecordDeclarationField | ||
| 667 | input InstNode fieldNode; | ||
| 668 | input InstNode recordNode; | ||
| 669 | protected | ||
| 670 | Component comp; | ||
| 671 | Binding binding; | ||
| 672 | InstNode cls_inst; | ||
| 673 | algorithm | ||
| 674 | 1272 | comp := InstNode.component(fieldNode); | |
| 675 | 1272 | binding := Component.getBinding(comp); | |
| 676 | |||
| 677 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1268 times.
|
1272 | if Binding.isBound(binding) then |
| 678 | 4 | binding := Binding.mapExp(binding, function evaluateFuncExp(fnNode = fieldNode, evaluateAll = false)); | |
| 679 | 4 | comp := Component.setBinding(binding, comp); | |
| 680 | end if; | ||
| 681 | |||
| 682 | 1272 | cls_inst := Component.classInstance(comp); | |
| 683 |
2/2✓ Branch 1 taken 123 times.
✓ Branch 2 taken 1149 times.
|
1272 | if not InstNode.isEmpty(cls_inst) then |
| 684 | 123 | ClassTree.applyComponents(Class.classTree(InstNode.getClass(cls_inst)), | |
| 685 | function evaluateRecordDeclarationField(recordNode = recordNode)); | ||
| 686 | end if; | ||
| 687 | |||
| 688 | 1272 | InstNode.updateComponent(comp, fieldNode); | |
| 689 | end evaluateRecordDeclarationField; | ||
| 690 | |||
| 691 | annotation(__OpenModelica_Interface="nf_frontend"); | ||
| 692 | end NFEvalConstants; | ||
| 693 |