OMCompiler/Compiler/FrontEnd/CevalFunction.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 CevalFunction | ||
| 37 | " file: CevalFunction.mo | ||
| 38 | package: CevalFunction | ||
| 39 | description: This module constant evaluates DAE.Function objects, i.e. | ||
| 40 | modelica functions defined by the user. | ||
| 41 | |||
| 42 | |||
| 43 | TODO: | ||
| 44 | * Implement evaluation of MetaModelica statements. | ||
| 45 | * Enable NORETCALL (see comment in evaluateStatement). | ||
| 46 | * Implement terminate and assert(false, ...). | ||
| 47 | * Arrays of records probably doesn't work yet. | ||
| 48 | " | ||
| 49 | |||
| 50 | // Jump table for CevalFunction: | ||
| 51 | // [TYPE] Types. | ||
| 52 | // [EVAL] Constant evaluation functions. | ||
| 53 | // [EENV] Environment extension functions (add variables). | ||
| 54 | // [MENV] Environment manipulation functions (set and get variables). | ||
| 55 | // [DEPS] Function variable dependency handling. | ||
| 56 | // [EOPT] Expression optimization functions. | ||
| 57 | |||
| 58 | // public imports | ||
| 59 | public import Absyn; | ||
| 60 | public import AbsynUtil; | ||
| 61 | public import DAE; | ||
| 62 | public import FCore; | ||
| 63 | public import SCode; | ||
| 64 | public import Values; | ||
| 65 | |||
| 66 | // protected imports | ||
| 67 | protected import Ceval; | ||
| 68 | protected import ClassInf; | ||
| 69 | protected import ComponentReference; | ||
| 70 | protected import ComponentReferenceBasics; | ||
| 71 | protected import DAEDump; | ||
| 72 | protected import DAEUtil; | ||
| 73 | protected import Debug; | ||
| 74 | protected import ElementSource; | ||
| 75 | protected import Error; | ||
| 76 | protected import Expression; | ||
| 77 | protected import Flags; | ||
| 78 | protected import Graph; | ||
| 79 | protected import Lapack; | ||
| 80 | protected import List; | ||
| 81 | protected import Lookup; | ||
| 82 | protected import Types; | ||
| 83 | protected import Util; | ||
| 84 | protected import ValuesUtil; | ||
| 85 | protected import FGraph; | ||
| 86 | protected import FNode; | ||
| 87 | protected import ExpressionBasics; | ||
| 88 | |||
| 89 | // [TYPE] Types | ||
| 90 | protected type FunctionVar = tuple<DAE.Element, Option<Values.Value>>; | ||
| 91 | |||
| 92 | // LoopControl is used to control the functions behaviour in different | ||
| 93 | // situations. All evaluation functions returns a LoopControl variable that | ||
| 94 | // tells the caller whether it should continue evaluating or not. | ||
| 95 | protected uniontype LoopControl | ||
| 96 | record NEXT "Continue to the next statement." end NEXT; | ||
| 97 | record BREAK "Exit the current loop." end BREAK; | ||
| 98 | record RETURN "Exit the function." end RETURN; | ||
| 99 | end LoopControl; | ||
| 100 | |||
| 101 | // [EVAL] Constant evaluation functions. | ||
| 102 | |||
| 103 | public function evaluate | ||
| 104 | "This is the entry point of CevalFunction. This function constant evaluates a | ||
| 105 | function given an instantiated function and a list of function arguments." | ||
| 106 | input FCore.Cache inCache; | ||
| 107 | input FCore.Graph inEnv; | ||
| 108 | input DAE.Function inFunction; | ||
| 109 | input list<Values.Value> inFunctionArguments; | ||
| 110 | output FCore.Cache outCache; | ||
| 111 | output Values.Value outResult; | ||
| 112 | algorithm | ||
| 113 | (outCache, outResult) := | ||
| 114 | matchcontinue inFunction | ||
| 115 | local | ||
| 116 | Absyn.Path p; | ||
| 117 | DAE.FunctionDefinition func; | ||
| 118 | DAE.Type ty; | ||
| 119 | Values.Value result; | ||
| 120 | String func_name; | ||
| 121 | FCore.Cache cache; | ||
| 122 | Boolean partialPrefix; | ||
| 123 | DAE.ElementSource src; | ||
| 124 | |||
| 125 | // The DAE.FUNCTION structure might contain an optional function derivative | ||
| 126 | // mapping which is why functions below is a list. We only evaluate the | ||
| 127 | // first function, which is hopefully the one we want. | ||
| 128 | case DAE.FUNCTION( | ||
| 129 | path = p, | ||
| 130 | functions = func :: _, | ||
| 131 | type_ = ty, | ||
| 132 | partialPrefix = false, | ||
| 133 | source = src) | ||
| 134 | algorithm | ||
| 135 | 38177 | func_name := AbsynUtil.pathString(p); | |
| 136 | 38177 | (cache, result) := evaluateFunctionDefinition(inCache, inEnv, func_name, | |
| 137 | func, ty, inFunctionArguments, src); | ||
| 138 | then | ||
| 139 | (cache, result); | ||
| 140 | |||
| 141 | case DAE.FUNCTION( | ||
| 142 | path = p, | ||
| 143 | functions = _ :: _, | ||
| 144 | partialPrefix = partialPrefix) | ||
| 145 | algorithm | ||
| 146 |
1/2✓ Branch 1 taken 226 times.
✗ Branch 2 not taken.
|
226 | true := Flags.isSet(Flags.FAILTRACE); |
| 147 | ✗ | Debug.traceln("- CevalFunction.evaluate failed for function: " + (if partialPrefix then "partial " else "") + AbsynUtil.pathString(p)); | |
| 148 | ✗ | then | |
| 149 | fail(); | ||
| 150 | end matchcontinue; | ||
| 151 | end evaluate; | ||
| 152 | |||
| 153 | protected function evaluateFunctionDefinition | ||
| 154 | "This function constant evaluates a function definition." | ||
| 155 | input FCore.Cache inCache; | ||
| 156 | input FCore.Graph inEnv; | ||
| 157 | input String inFuncName; | ||
| 158 | input DAE.FunctionDefinition inFunc; | ||
| 159 | input DAE.Type inFuncType; | ||
| 160 | input list<Values.Value> inFuncArgs; | ||
| 161 | input DAE.ElementSource inSource; | ||
| 162 | output FCore.Cache outCache; | ||
| 163 | output Values.Value outResult; | ||
| 164 | algorithm | ||
| 165 | (outCache, outResult) := | ||
| 166 | matchcontinue inFunc | ||
| 167 | local | ||
| 168 | list<DAE.Element> body; | ||
| 169 | list<DAE.Element> vars, output_vars; | ||
| 170 | list<FunctionVar> func_params; | ||
| 171 | FCore.Cache cache; | ||
| 172 | FCore.Graph env; | ||
| 173 | list<Values.Value> return_values; | ||
| 174 | Values.Value return_value; | ||
| 175 | String ext_fun_name; | ||
| 176 | list<DAE.ExtArg> ext_fun_args; | ||
| 177 | |||
| 178 | case DAE.FUNCTION_DEF(body = body) | ||
| 179 | algorithm | ||
| 180 | // Split the definition into function variables and statements. | ||
| 181 | 38139 | (vars, body) := List.splitOnFirstMatch(body, DAEUtil.isNotVar); | |
| 182 | 38139 | vars := List.map(vars, removeSelfReferentialDims); | |
| 183 | |||
| 184 | // Save the output variables, so that we can return their values when | ||
| 185 | // we're done. | ||
| 186 | 38139 | output_vars := List.filterOnTrue(vars, DAEUtil.isOutputVar); | |
| 187 | |||
| 188 | // Pair the input arguments to input parameters and sort the function | ||
| 189 | // variables by dependencies. | ||
| 190 | 38139 | func_params := pairFuncParamsWithArgs(vars, inFuncArgs); | |
| 191 | 38139 | func_params := sortFunctionVarsByDependency(func_params, inSource); | |
| 192 | |||
| 193 | // Create an environment for the function and add all function variables. | ||
| 194 | 38139 | (cache, env) := | |
| 195 | setupFunctionEnvironment(inCache, inEnv, inFuncName, func_params); | ||
| 196 | // Evaluate the body of the function. | ||
| 197 | 38139 | (cache, env, _) := evaluateElements(body, cache, env, NEXT()); | |
| 198 | // Fetch the values of the output variables. | ||
| 199 | 37947 | return_values := List.map1(output_vars, getFunctionReturnValue, env); | |
| 200 | // If we have several output variables they should be boxed into a tuple. | ||
| 201 | 37947 | return_value := boxReturnValue(return_values); | |
| 202 | then | ||
| 203 | (cache, return_value); | ||
| 204 | |||
| 205 | case DAE.FUNCTION_EXT(body = body, externalDecl = | ||
| 206 | DAE.EXTERNALDECL(name = ext_fun_name, | ||
| 207 | args = ext_fun_args)) | ||
| 208 | algorithm | ||
| 209 | // Get all variables from the function. Ignore everything else, since | ||
| 210 | // external functions shouldn't have statements. | ||
| 211 | 38 | (vars, _) := List.splitOnFirstMatch(body, DAEUtil.isNotVar); | |
| 212 | 38 | vars := List.map(vars, removeSelfReferentialDims); | |
| 213 | |||
| 214 | // Save the output variables, so that we can return their values when | ||
| 215 | // we're done. | ||
| 216 | 38 | output_vars := List.filterOnTrue(vars, DAEUtil.isOutputVar); | |
| 217 | |||
| 218 | // Pair the input arguments to input parameters and sort the function | ||
| 219 | // variables by dependencies. | ||
| 220 | 38 | func_params := pairFuncParamsWithArgs(vars, inFuncArgs); | |
| 221 | 38 | func_params := sortFunctionVarsByDependency(func_params, inSource); | |
| 222 | |||
| 223 | // Create an environment for the function and add all function variables. | ||
| 224 | 38 | (cache, env) := | |
| 225 | setupFunctionEnvironment(inCache, inEnv, inFuncName, func_params); | ||
| 226 | |||
| 227 | // Call the function. | ||
| 228 | 38 | (cache, env) := | |
| 229 | evaluateExternalFunc(ext_fun_name, ext_fun_args, cache, env); | ||
| 230 | |||
| 231 | // Fetch the values of the output variables. | ||
| 232 | 4 | return_values := List.map1(output_vars, getFunctionReturnValue, env); | |
| 233 | // If we have several output variables they should be boxed into a tuple. | ||
| 234 | 4 | return_value := boxReturnValue(return_values); | |
| 235 | then | ||
| 236 | (cache, return_value); | ||
| 237 | |||
| 238 | else | ||
| 239 | algorithm | ||
| 240 |
1/2✓ Branch 1 taken 226 times.
✗ Branch 2 not taken.
|
226 | true := Flags.isSet(Flags.FAILTRACE); |
| 241 | ✗ | Debug.trace("- CevalFunction.evaluateFunction failed.\n"); | |
| 242 | ✗ | then | |
| 243 | fail(); | ||
| 244 | end matchcontinue; | ||
| 245 | end evaluateFunctionDefinition; | ||
| 246 | |||
| 247 | protected function pairFuncParamsWithArgs | ||
| 248 | "This function pairs up the input arguments to the input parameters, so that | ||
| 249 | each input parameter get one input argument. This is done since we sort the | ||
| 250 | function variables by dependencies, and need to keep track of which argument | ||
| 251 | belongs to which parameter." | ||
| 252 | input list<DAE.Element> inElements; | ||
| 253 | input list<Values.Value> inValues; | ||
| 254 | output list<FunctionVar> outFunctionVars; | ||
| 255 | algorithm | ||
| 256 | outFunctionVars := match(inElements, inValues) | ||
| 257 | local | ||
| 258 | DAE.Element var; | ||
| 259 | list<DAE.Element> rest_vars; | ||
| 260 | Values.Value val; | ||
| 261 | list<Values.Value> rest_vals; | ||
| 262 | list<FunctionVar> params; | ||
| 263 | |||
| 264 | case ({}, {}) then {}; | ||
| 265 | |||
| 266 | case ((DAE.VAR(direction = DAE.INPUT())) :: _, {}) | ||
| 267 | algorithm | ||
| 268 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 269 | ✗ | Debug.trace("- CevalFunction.pairFuncParamsWithArgs failed because of too few input arguments.\n"); | |
| 270 | ✗ | then | |
| 271 | fail(); | ||
| 272 | |||
| 273 | case ((var as DAE.VAR(direction = DAE.INPUT())) :: rest_vars, val :: rest_vals) | ||
| 274 | algorithm | ||
| 275 | 51711 | params := pairFuncParamsWithArgs(rest_vars, rest_vals); | |
| 276 | 51711 | then | |
| 277 | (var, SOME(val)) :: params; | ||
| 278 | |||
| 279 | case (var :: rest_vars, _) | ||
| 280 | algorithm | ||
| 281 | 47915 | params := pairFuncParamsWithArgs(rest_vars, inValues); | |
| 282 | 47915 | then | |
| 283 | (var, NONE()) :: params; | ||
| 284 | |||
| 285 | end match; | ||
| 286 | end pairFuncParamsWithArgs; | ||
| 287 | |||
| 288 | protected function removeSelfReferentialDims | ||
| 289 | "We can't handle self-referential dimensions in function parameters, i.e. | ||
| 290 | x[:, size(x, 1)], so just replace them with : instead." | ||
| 291 | input DAE.Element inElement; | ||
| 292 | output DAE.Element outElement; | ||
| 293 | algorithm | ||
| 294 | outElement := match inElement | ||
| 295 | local | ||
| 296 | DAE.ComponentRef cref; | ||
| 297 | DAE.VarKind vk; | ||
| 298 | DAE.VarDirection vd; | ||
| 299 | DAE.VarParallelism vp; | ||
| 300 | DAE.VarVisibility vv; | ||
| 301 | DAE.Type ty; | ||
| 302 | Option<DAE.Exp> bind; | ||
| 303 | DAE.InstDims dims; | ||
| 304 | DAE.ConnectorType ct; | ||
| 305 | DAE.ElementSource es; | ||
| 306 | Option<DAE.VariableAttributes> va; | ||
| 307 | Option<SCode.Comment> cmt; | ||
| 308 | Absyn.InnerOuter io; | ||
| 309 | Boolean e; | ||
| 310 | String name; | ||
| 311 | |||
| 312 | case DAE.VAR(cref as DAE.CREF_IDENT(ident = name), vk, vd, vp, vv, ty, | ||
| 313 | bind, dims, ct, es, va, cmt, io, e) | ||
| 314 | algorithm | ||
| 315 | 99626 | dims := List.map1(dims, removeSelfReferentialDim, name); | |
| 316 |
1/2✓ Branch 0 taken 99626 times.
✗ Branch 1 not taken.
|
199252 | then |
| 317 | DAE.VAR(cref, vk, vd, vp, vv, ty, bind, dims, ct, es, va, cmt, io, e); | ||
| 318 | |||
| 319 | end match; | ||
| 320 | end removeSelfReferentialDims; | ||
| 321 | |||
| 322 | protected function removeSelfReferentialDim | ||
| 323 | input DAE.Dimension inDim; | ||
| 324 | input String inName; | ||
| 325 | output DAE.Dimension outDim; | ||
| 326 | algorithm | ||
| 327 | outDim := matchcontinue inDim | ||
| 328 | local | ||
| 329 | DAE.Exp exp; | ||
| 330 | list<DAE.ComponentRef> crefs; | ||
| 331 | |||
| 332 | case DAE.DIM_EXP(exp = exp) | ||
| 333 | algorithm | ||
| 334 | 904 | crefs := Expression.extractCrefsFromExp(exp); | |
| 335 |
2/2✓ Branch 1 taken 896 times.
✓ Branch 2 taken 8 times.
|
904 | true := List.isMemberOnTrue(inName, crefs, isCrefNamed); |
| 336 | then | ||
| 337 | DAE.DIM_UNKNOWN(); | ||
| 338 | |||
| 339 | else inDim; | ||
| 340 | |||
| 341 | end matchcontinue; | ||
| 342 | end removeSelfReferentialDim; | ||
| 343 | |||
| 344 | protected function isCrefNamed | ||
| 345 | input String inName; | ||
| 346 | input DAE.ComponentRef inCref; | ||
| 347 | output Boolean outIsNamed; | ||
| 348 | algorithm | ||
| 349 | outIsNamed := match inCref | ||
| 350 | local | ||
| 351 | String name; | ||
| 352 | |||
| 353 |
4/4✓ Branch 0 taken 41 times.
✓ Branch 1 taken 864 times.
✓ Branch 3 taken 33 times.
✓ Branch 4 taken 8 times.
|
905 | case DAE.CREF_IDENT(ident = name) then stringEq(inName, name); |
| 354 | else false; | ||
| 355 | end match; | ||
| 356 | end isCrefNamed; | ||
| 357 | |||
| 358 | protected function evaluateExtInputArg | ||
| 359 | "Evaluates an external function argument to a value." | ||
| 360 | input DAE.ExtArg inArgument; | ||
| 361 | input FCore.Cache inCache; | ||
| 362 | input FCore.Graph inEnv; | ||
| 363 | output Values.Value outValue; | ||
| 364 | output FCore.Cache outCache; | ||
| 365 | algorithm | ||
| 366 | (outValue, outCache) := matchcontinue(inArgument, inCache) | ||
| 367 | local | ||
| 368 | DAE.ComponentRef cref; | ||
| 369 | DAE.Type ty; | ||
| 370 | DAE.Exp exp; | ||
| 371 | Values.Value val; | ||
| 372 | FCore.Cache cache; | ||
| 373 | String err_str; | ||
| 374 | |||
| 375 | case (DAE.EXTARG(componentRef = cref, type_ = ty), _) | ||
| 376 | algorithm | ||
| 377 | 24 | val := getVariableValue(cref, ty, inEnv); | |
| 378 | then | ||
| 379 | (val, inCache); | ||
| 380 | |||
| 381 | case (DAE.EXTARGEXP(exp = exp), cache) | ||
| 382 | algorithm | ||
| 383 | ✗ | (cache, val) := cevalExp(exp, cache, inEnv); | |
| 384 | ✗ | then | |
| 385 | (val, cache); | ||
| 386 | |||
| 387 | case (DAE.EXTARGSIZE(componentRef = cref, exp = exp), cache) | ||
| 388 | algorithm | ||
| 389 | ✗ | exp := DAE.SIZE(DAE.CREF(cref, DAE.T_UNKNOWN_DEFAULT), SOME(exp)); | |
| 390 | ✗ | (cache, val) := cevalExp(exp, cache, inEnv); | |
| 391 | ✗ | then | |
| 392 | (val, cache); | ||
| 393 | |||
| 394 | else | ||
| 395 | algorithm | ||
| 396 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 397 | ✗ | err_str := DAEDump.dumpExtArgStr(inArgument); | |
| 398 | ✗ | Debug.traceln("- CevalFunction.evaluateExtInputArg failed on " + err_str); | |
| 399 | ✗ | then | |
| 400 | fail(); | ||
| 401 | |||
| 402 | end matchcontinue; | ||
| 403 | end evaluateExtInputArg; | ||
| 404 | |||
| 405 | protected function evaluateExtIntArg | ||
| 406 | "Evaluates an external function argument to an Integer." | ||
| 407 | input DAE.ExtArg inArg; | ||
| 408 | input FCore.Cache inCache; | ||
| 409 | input FCore.Graph inEnv; | ||
| 410 | output Integer outValue; | ||
| 411 | output FCore.Cache outCache; | ||
| 412 | algorithm | ||
| 413 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
|
16 | (Values.INTEGER(outValue), outCache) := |
| 414 | evaluateExtInputArg(inArg, inCache, inEnv); | ||
| 415 | end evaluateExtIntArg; | ||
| 416 | |||
| 417 | protected function evaluateExtRealArg | ||
| 418 | "Evaluates an external function argument to a Real." | ||
| 419 | input DAE.ExtArg inArg; | ||
| 420 | input FCore.Cache inCache; | ||
| 421 | input FCore.Graph inEnv; | ||
| 422 | output Real outValue; | ||
| 423 | output FCore.Cache outCache; | ||
| 424 | algorithm | ||
| 425 | ✗ | (Values.REAL(outValue), outCache) := | |
| 426 | evaluateExtInputArg(inArg, inCache, inEnv); | ||
| 427 | end evaluateExtRealArg; | ||
| 428 | |||
| 429 | protected function evaluateExtStringArg | ||
| 430 | "Evaluates an external function argument to a String." | ||
| 431 | input DAE.ExtArg inArg; | ||
| 432 | input FCore.Cache inCache; | ||
| 433 | input FCore.Graph inEnv; | ||
| 434 | output String outValue; | ||
| 435 | output FCore.Cache outCache; | ||
| 436 | algorithm | ||
| 437 | ✗ | (Values.STRING(outValue), outCache) := | |
| 438 | evaluateExtInputArg(inArg, inCache, inEnv); | ||
| 439 | end evaluateExtStringArg; | ||
| 440 | |||
| 441 | protected function evaluateExtIntArrayArg | ||
| 442 | "Evaluates an external function argument to an Integer array." | ||
| 443 | input DAE.ExtArg inArg; | ||
| 444 | input FCore.Cache inCache; | ||
| 445 | input FCore.Graph inEnv; | ||
| 446 | output list<Integer> outValue; | ||
| 447 | output FCore.Cache outCache; | ||
| 448 | protected | ||
| 449 | Values.Value val; | ||
| 450 | algorithm | ||
| 451 | ✗ | (val, outCache) := | |
| 452 | evaluateExtInputArg(inArg, inCache, inEnv); | ||
| 453 | ✗ | outValue := ValuesUtil.arrayValueInts(val); | |
| 454 | end evaluateExtIntArrayArg; | ||
| 455 | |||
| 456 | protected function evaluateExtRealArrayArg | ||
| 457 | "Evaluates an external function argument to a Real array." | ||
| 458 | input DAE.ExtArg inArg; | ||
| 459 | input FCore.Cache inCache; | ||
| 460 | input FCore.Graph inEnv; | ||
| 461 | output list<Real> outValue; | ||
| 462 | output FCore.Cache outCache; | ||
| 463 | protected | ||
| 464 | Values.Value val; | ||
| 465 | algorithm | ||
| 466 | ✗ | (val, outCache) := | |
| 467 | evaluateExtInputArg(inArg, inCache, inEnv); | ||
| 468 | ✗ | outValue := ValuesUtil.arrayValueReals(val); | |
| 469 | end evaluateExtRealArrayArg; | ||
| 470 | |||
| 471 | protected function evaluateExtRealMatrixArg | ||
| 472 | "Evaluates an external function argument to a Real matrix." | ||
| 473 | input DAE.ExtArg inArg; | ||
| 474 | input FCore.Cache inCache; | ||
| 475 | input FCore.Graph inEnv; | ||
| 476 | output list<list<Real>> outValue; | ||
| 477 | output FCore.Cache outCache; | ||
| 478 | protected | ||
| 479 | Values.Value val; | ||
| 480 | algorithm | ||
| 481 | 8 | (val, outCache) := | |
| 482 | evaluateExtInputArg(inArg, inCache, inEnv); | ||
| 483 | 8 | outValue := ValuesUtil.matrixValueReals(val); | |
| 484 | end evaluateExtRealMatrixArg; | ||
| 485 | |||
| 486 | protected function evaluateExtOutputArg | ||
| 487 | "Returns the component reference to an external function output." | ||
| 488 | input DAE.ExtArg inArg; | ||
| 489 | output DAE.ComponentRef outCref; | ||
| 490 | algorithm | ||
| 491 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 16 times.
|
16 | DAE.EXTARG(componentRef = outCref) := inArg; |
| 492 | end evaluateExtOutputArg; | ||
| 493 | |||
| 494 | protected function assignExtOutputs | ||
| 495 | "Assigns the outputs from an external function to the correct variables in the | ||
| 496 | environment." | ||
| 497 | input list<DAE.ExtArg> inArgs; | ||
| 498 | input list<Values.Value> inValues; | ||
| 499 | input FCore.Cache inCache; | ||
| 500 | input FCore.Graph inEnv; | ||
| 501 | output FCore.Cache outCache; | ||
| 502 | output FCore.Graph outEnv; | ||
| 503 | algorithm | ||
| 504 | (outCache, outEnv) := match(inArgs, inValues, inCache, inEnv) | ||
| 505 | local | ||
| 506 | DAE.ExtArg arg; | ||
| 507 | Values.Value val; | ||
| 508 | list<DAE.ExtArg> rest_args; | ||
| 509 | list<Values.Value> rest_vals; | ||
| 510 | FCore.Cache cache; | ||
| 511 | FCore.Graph env; | ||
| 512 | DAE.ComponentRef cr; | ||
| 513 | |||
| 514 | case ({}, {}, _, _) then (inCache, inEnv); | ||
| 515 | |||
| 516 | case (arg :: rest_args, val :: rest_vals, cache, env) | ||
| 517 | algorithm | ||
| 518 | 16 | cr := evaluateExtOutputArg(arg); | |
| 519 | 16 | val := unliftExtOutputValue(cr, val, env); | |
| 520 | 16 | (cache, env) := assignVariable(cr, val, cache, env); | |
| 521 | 16 | (cache, env) := assignExtOutputs(rest_args, rest_vals, cache, env); | |
| 522 | then | ||
| 523 | (cache, env); | ||
| 524 | |||
| 525 | end match; | ||
| 526 | end assignExtOutputs; | ||
| 527 | |||
| 528 | protected function unliftExtOutputValue | ||
| 529 | "Some external functions don't make much difference between arrays and | ||
| 530 | matrices, so this function converts a matrix value to an array value when | ||
| 531 | needed." | ||
| 532 | input DAE.ComponentRef inCref; | ||
| 533 | input Values.Value inValue; | ||
| 534 | input FCore.Graph inEnv; | ||
| 535 | output Values.Value outValue; | ||
| 536 | algorithm | ||
| 537 | outValue := matchcontinue inValue | ||
| 538 | local | ||
| 539 | DAE.Type ty; | ||
| 540 | list<Values.Value> vals; | ||
| 541 | Integer dim; | ||
| 542 | DAE.Dimensions dims; | ||
| 543 | |||
| 544 | // Matrix value, array type => convert. | ||
| 545 | case Values.ARRAY(valueLst = vals as Values.ARRAY() :: _, dimLst = dim :: _) | ||
| 546 | algorithm | ||
| 547 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
8 | (DAE.T_ARRAY(ty = ty, dims = dims), _) := getVariableTypeAndBinding(inCref, inEnv); |
| 548 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
|
8 | false := Types.isNonscalarArray(ty, dims); |
| 549 | 4 | vals := List.map(vals, ValuesUtil.arrayScalar); | |
| 550 | 4 | then | |
| 551 | Values.ARRAY(vals, {dim}); | ||
| 552 | |||
| 553 | // Otherwise, do nothing. | ||
| 554 | else inValue; | ||
| 555 | end matchcontinue; | ||
| 556 | end unliftExtOutputValue; | ||
| 557 | |||
| 558 | protected function evaluateExternalFunc | ||
| 559 | "This function evaluates an external function, at the moment this means a | ||
| 560 | LAPACK function. This function was automatically generated. No programmers | ||
| 561 | were hurt during the generation of this function." | ||
| 562 | input String inFuncName; | ||
| 563 | input list<DAE.ExtArg> inFuncArgs; | ||
| 564 | input FCore.Cache inCache; | ||
| 565 | input FCore.Graph inEnv; | ||
| 566 | output FCore.Cache outCache; | ||
| 567 | output FCore.Graph outEnv; | ||
| 568 | algorithm | ||
| 569 | (outCache, outEnv) := | ||
| 570 | match(inFuncName, inFuncArgs, inCache, inEnv) | ||
| 571 | local | ||
| 572 | DAE.ExtArg arg_JOBU, arg_JOBVL, arg_JOBVR, arg_JOBVT, arg_TRANS, arg_INFO, arg_K; | ||
| 573 | DAE.ExtArg arg_KL, arg_KU, arg_LDA, arg_LDAB, arg_LDB, arg_LDU, arg_LDVL; | ||
| 574 | DAE.ExtArg arg_LDVR, arg_LDVT, arg_LWORK, arg_M, arg_N, arg_NRHS, arg_P; | ||
| 575 | DAE.ExtArg arg_RANK, arg_RCOND, arg_IPIV, arg_JPVT, arg_ALPHAI, arg_ALPHAR, arg_BETA; | ||
| 576 | DAE.ExtArg arg_C, arg_D, arg_DL, arg_DU, arg_TAU, arg_WI, arg_WORK; | ||
| 577 | DAE.ExtArg arg_WR, arg_X, arg_A, arg_AB, arg_B, arg_S, arg_U; | ||
| 578 | DAE.ExtArg arg_VL, arg_VR, arg_VT; | ||
| 579 | Values.Value val_INFO, val_RANK, val_IPIV, val_JPVT, val_ALPHAI, val_ALPHAR, val_BETA; | ||
| 580 | Values.Value val_C, val_D, val_DL, val_DU, val_TAU, val_WI, val_WORK; | ||
| 581 | Values.Value val_WR, val_X, val_A, val_AB, val_B, val_S, val_U; | ||
| 582 | Values.Value val_VL, val_VR, val_VT; | ||
| 583 | Integer INFO, K, KL, KU, LDA, LDAB, LDB, LDU, LDVL, LDVR, LDVT, LWORK, M, N, NRHS, P, RANK; | ||
| 584 | Real RCOND; | ||
| 585 | String JOBU, JOBVL, JOBVR, JOBVT, TRANS; | ||
| 586 | list<Integer> IPIV, JPVT; | ||
| 587 | list<Real> ALPHAI, ALPHAR, BETA, C, D, DL, DU, TAU, WI, WORK, WR, X, S; | ||
| 588 | list<list<Real>> A, AB, B, U, VL, VR, VT; | ||
| 589 | list<DAE.ExtArg> arg_out; | ||
| 590 | list<Values.Value> val_out; | ||
| 591 | FCore.Cache cache; | ||
| 592 | FCore.Graph env; | ||
| 593 | |||
| 594 | case("dgeev", {arg_JOBVL, arg_JOBVR, arg_N, arg_A, arg_LDA, arg_WR, arg_WI, | ||
| 595 | arg_VL, arg_LDVL, arg_VR, arg_LDVR, arg_WORK, arg_LWORK, arg_INFO}, | ||
| 596 | cache, env) | ||
| 597 | algorithm | ||
| 598 | ✗ | (JOBVL, cache) := evaluateExtStringArg(arg_JOBVL, cache, env); | |
| 599 | ✗ | (JOBVR, cache) := evaluateExtStringArg(arg_JOBVR, cache, env); | |
| 600 | ✗ | (N, cache) := evaluateExtIntArg(arg_N, cache, env); | |
| 601 | ✗ | (A, cache) := evaluateExtRealMatrixArg(arg_A, cache, env); | |
| 602 | ✗ | (LDA, cache) := evaluateExtIntArg(arg_LDA, cache, env); | |
| 603 | ✗ | (LDVL, cache) := evaluateExtIntArg(arg_LDVL, cache, env); | |
| 604 | ✗ | (LDVR, cache) := evaluateExtIntArg(arg_LDVR, cache, env); | |
| 605 | ✗ | (WORK, cache) := evaluateExtRealArrayArg(arg_WORK, cache, env); | |
| 606 | ✗ | (LWORK, cache) := evaluateExtIntArg(arg_LWORK, cache, env); | |
| 607 | ✗ | (A, WR, WI, VL, VR, WORK, INFO) := | |
| 608 | Lapack.dgeev(JOBVL, JOBVR, N, A, LDA, LDVL, LDVR, WORK, LWORK); | ||
| 609 | ✗ | val_A := ValuesMake.makeRealMatrix(A); | |
| 610 | ✗ | val_WR := ValuesMake.makeRealArray(WR); | |
| 611 | ✗ | val_WI := ValuesMake.makeRealArray(WI); | |
| 612 | ✗ | val_VL := ValuesMake.makeRealMatrix(VL); | |
| 613 | ✗ | val_VR := ValuesMake.makeRealMatrix(VR); | |
| 614 | ✗ | val_WORK := ValuesMake.makeRealArray(WORK); | |
| 615 | ✗ | val_INFO := ValuesMake.makeInteger(INFO); | |
| 616 | arg_out := {arg_A, arg_WR, arg_WI, arg_VL, arg_VR, arg_WORK, arg_INFO}; | ||
| 617 | val_out := {val_A, val_WR, val_WI, val_VL, val_VR, val_WORK, val_INFO}; | ||
| 618 | ✗ | (cache, env) := assignExtOutputs(arg_out, val_out, cache, env); | |
| 619 | then | ||
| 620 | (cache, env); | ||
| 621 | |||
| 622 | case("dgegv", {arg_JOBVL, arg_JOBVR, arg_N, arg_A, arg_LDA, arg_B, arg_LDB, | ||
| 623 | arg_ALPHAR, arg_ALPHAI, arg_BETA, arg_VL, arg_LDVL, arg_VR, arg_LDVR, | ||
| 624 | arg_WORK, arg_LWORK, arg_INFO}, | ||
| 625 | cache, env) | ||
| 626 | algorithm | ||
| 627 | ✗ | (JOBVL, cache) := evaluateExtStringArg(arg_JOBVL, cache, env); | |
| 628 | ✗ | (JOBVR, cache) := evaluateExtStringArg(arg_JOBVR, cache, env); | |
| 629 | ✗ | (N, cache) := evaluateExtIntArg(arg_N, cache, env); | |
| 630 | ✗ | (A, cache) := evaluateExtRealMatrixArg(arg_A, cache, env); | |
| 631 | ✗ | (LDA, cache) := evaluateExtIntArg(arg_LDA, cache, env); | |
| 632 | ✗ | (B, cache) := evaluateExtRealMatrixArg(arg_B, cache, env); | |
| 633 | ✗ | (LDB, cache) := evaluateExtIntArg(arg_LDB, cache, env); | |
| 634 | ✗ | (LDVL, cache) := evaluateExtIntArg(arg_LDVL, cache, env); | |
| 635 | ✗ | (LDVR, cache) := evaluateExtIntArg(arg_LDVR, cache, env); | |
| 636 | ✗ | (WORK, cache) := evaluateExtRealArrayArg(arg_WORK, cache, env); | |
| 637 | ✗ | (LWORK, cache) := evaluateExtIntArg(arg_LWORK, cache, env); | |
| 638 | ✗ | (ALPHAR, ALPHAI, BETA, VL, VR, WORK, INFO) := | |
| 639 | Lapack.dgegv(JOBVL, JOBVR, N, A, LDA, B, LDB, LDVL, LDVR, WORK, LWORK); | ||
| 640 | ✗ | val_ALPHAR := ValuesMake.makeRealArray(ALPHAR); | |
| 641 | ✗ | val_ALPHAI := ValuesMake.makeRealArray(ALPHAI); | |
| 642 | ✗ | val_BETA := ValuesMake.makeRealArray(BETA); | |
| 643 | ✗ | val_VL := ValuesMake.makeRealMatrix(VL); | |
| 644 | ✗ | val_VR := ValuesMake.makeRealMatrix(VR); | |
| 645 | ✗ | val_WORK := ValuesMake.makeRealArray(WORK); | |
| 646 | ✗ | val_INFO := ValuesMake.makeInteger(INFO); | |
| 647 | arg_out := {arg_ALPHAR, arg_ALPHAI, arg_BETA, arg_VL, arg_VR, arg_WORK, arg_INFO}; | ||
| 648 | val_out := {val_ALPHAR, val_ALPHAI, val_BETA, val_VL, val_VR, val_WORK, val_INFO}; | ||
| 649 | ✗ | (cache, env) := assignExtOutputs(arg_out, val_out, cache, env); | |
| 650 | then | ||
| 651 | (cache, env); | ||
| 652 | |||
| 653 | case("dgels", {arg_TRANS, arg_M, arg_N, arg_NRHS, arg_A, arg_LDA, arg_B, | ||
| 654 | arg_LDB, arg_WORK, arg_LWORK, arg_INFO}, | ||
| 655 | cache, env) | ||
| 656 | algorithm | ||
| 657 | ✗ | (TRANS, cache) := evaluateExtStringArg(arg_TRANS, cache, env); | |
| 658 | ✗ | (M, cache) := evaluateExtIntArg(arg_M, cache, env); | |
| 659 | ✗ | (N, cache) := evaluateExtIntArg(arg_N, cache, env); | |
| 660 | ✗ | (NRHS, cache) := evaluateExtIntArg(arg_NRHS, cache, env); | |
| 661 | ✗ | (A, cache) := evaluateExtRealMatrixArg(arg_A, cache, env); | |
| 662 | ✗ | (LDA, cache) := evaluateExtIntArg(arg_LDA, cache, env); | |
| 663 | ✗ | (B, cache) := evaluateExtRealMatrixArg(arg_B, cache, env); | |
| 664 | ✗ | (LDB, cache) := evaluateExtIntArg(arg_LDB, cache, env); | |
| 665 | ✗ | (WORK, cache) := evaluateExtRealArrayArg(arg_WORK, cache, env); | |
| 666 | ✗ | (LWORK, cache) := evaluateExtIntArg(arg_LWORK, cache, env); | |
| 667 | ✗ | (A, B, WORK, INFO) := | |
| 668 | Lapack.dgels(TRANS, M, N, NRHS, A, LDA, B, LDB, WORK, LWORK); | ||
| 669 | ✗ | val_A := ValuesMake.makeRealMatrix(A); | |
| 670 | ✗ | val_B := ValuesMake.makeRealMatrix(B); | |
| 671 | ✗ | val_WORK := ValuesMake.makeRealArray(WORK); | |
| 672 | ✗ | val_INFO := ValuesMake.makeInteger(INFO); | |
| 673 | arg_out := {arg_A, arg_B, arg_WORK, arg_INFO}; | ||
| 674 | val_out := {val_A, val_B, val_WORK, val_INFO}; | ||
| 675 | ✗ | (cache, env) := assignExtOutputs(arg_out, val_out, cache, env); | |
| 676 | then | ||
| 677 | (cache, env); | ||
| 678 | |||
| 679 | case("dgelsx", {arg_M, arg_N, arg_NRHS, arg_A, arg_LDA, arg_B, arg_LDB, | ||
| 680 | arg_JPVT, arg_RCOND, arg_RANK, arg_WORK, arg_INFO}, | ||
| 681 | cache, env) | ||
| 682 | algorithm | ||
| 683 | ✗ | (M, cache) := evaluateExtIntArg(arg_M, cache, env); | |
| 684 | ✗ | (N, cache) := evaluateExtIntArg(arg_N, cache, env); | |
| 685 | ✗ | (NRHS, cache) := evaluateExtIntArg(arg_NRHS, cache, env); | |
| 686 | ✗ | (A, cache) := evaluateExtRealMatrixArg(arg_A, cache, env); | |
| 687 | ✗ | (LDA, cache) := evaluateExtIntArg(arg_LDA, cache, env); | |
| 688 | ✗ | (B, cache) := evaluateExtRealMatrixArg(arg_B, cache, env); | |
| 689 | ✗ | (LDB, cache) := evaluateExtIntArg(arg_LDB, cache, env); | |
| 690 | ✗ | (JPVT, cache) := evaluateExtIntArrayArg(arg_JPVT, cache, env); | |
| 691 | ✗ | (RCOND, cache) := evaluateExtRealArg(arg_RCOND, cache, env); | |
| 692 | ✗ | (WORK, cache) := evaluateExtRealArrayArg(arg_WORK, cache, env); | |
| 693 | ✗ | (A, B, JPVT, RANK, INFO) := | |
| 694 | Lapack.dgelsx(M, N, NRHS, A, LDA, B, LDB, JPVT, RCOND, WORK); | ||
| 695 | ✗ | val_A := ValuesMake.makeRealMatrix(A); | |
| 696 | ✗ | val_B := ValuesMake.makeRealMatrix(B); | |
| 697 | ✗ | val_JPVT := ValuesMake.makeIntArray(JPVT); | |
| 698 | ✗ | val_RANK := ValuesMake.makeInteger(RANK); | |
| 699 | ✗ | val_INFO := ValuesMake.makeInteger(INFO); | |
| 700 | arg_out := {arg_A, arg_B, arg_JPVT, arg_RANK, arg_INFO}; | ||
| 701 | val_out := {val_A, val_B, val_JPVT, val_RANK, val_INFO}; | ||
| 702 | ✗ | (cache, env) := assignExtOutputs(arg_out, val_out, cache, env); | |
| 703 | then | ||
| 704 | (cache, env); | ||
| 705 | |||
| 706 | case("dgelsx", {arg_M, arg_N, arg_NRHS, arg_A, arg_LDA, arg_B, arg_LDB, | ||
| 707 | arg_JPVT, arg_RCOND, arg_RANK, arg_WORK, _, arg_INFO}, | ||
| 708 | cache, env) | ||
| 709 | algorithm | ||
| 710 | ✗ | (M, cache) := evaluateExtIntArg(arg_M, cache, env); | |
| 711 | ✗ | (N, cache) := evaluateExtIntArg(arg_N, cache, env); | |
| 712 | ✗ | (NRHS, cache) := evaluateExtIntArg(arg_NRHS, cache, env); | |
| 713 | ✗ | (A, cache) := evaluateExtRealMatrixArg(arg_A, cache, env); | |
| 714 | ✗ | (LDA, cache) := evaluateExtIntArg(arg_LDA, cache, env); | |
| 715 | ✗ | (B, cache) := evaluateExtRealMatrixArg(arg_B, cache, env); | |
| 716 | ✗ | (LDB, cache) := evaluateExtIntArg(arg_LDB, cache, env); | |
| 717 | ✗ | (JPVT, cache) := evaluateExtIntArrayArg(arg_JPVT, cache, env); | |
| 718 | ✗ | (RCOND, cache) := evaluateExtRealArg(arg_RCOND, cache, env); | |
| 719 | ✗ | (WORK, cache) := evaluateExtRealArrayArg(arg_WORK, cache, env); | |
| 720 | ✗ | (A, B, JPVT, RANK, INFO) := | |
| 721 | Lapack.dgelsx(M, N, NRHS, A, LDA, B, LDB, JPVT, RCOND, WORK); | ||
| 722 | ✗ | val_A := ValuesMake.makeRealMatrix(A); | |
| 723 | ✗ | val_B := ValuesMake.makeRealMatrix(B); | |
| 724 | ✗ | val_JPVT := ValuesMake.makeIntArray(JPVT); | |
| 725 | ✗ | val_RANK := ValuesMake.makeInteger(RANK); | |
| 726 | ✗ | val_INFO := ValuesMake.makeInteger(INFO); | |
| 727 | arg_out := {arg_A, arg_B, arg_JPVT, arg_RANK, arg_INFO}; | ||
| 728 | val_out := {val_A, val_B, val_JPVT, val_RANK, val_INFO}; | ||
| 729 | ✗ | (cache, env) := assignExtOutputs(arg_out, val_out, cache, env); | |
| 730 | then | ||
| 731 | (cache, env); | ||
| 732 | |||
| 733 | case("dgelsy", {arg_M, arg_N, arg_NRHS, arg_A, arg_LDA, arg_B, arg_LDB, | ||
| 734 | arg_JPVT, arg_RCOND, arg_RANK, arg_WORK, arg_LWORK, arg_INFO}, | ||
| 735 | cache, env) | ||
| 736 | algorithm | ||
| 737 | ✗ | (M, cache) := evaluateExtIntArg(arg_M, cache, env); | |
| 738 | ✗ | (N, cache) := evaluateExtIntArg(arg_N, cache, env); | |
| 739 | ✗ | (NRHS, cache) := evaluateExtIntArg(arg_NRHS, cache, env); | |
| 740 | ✗ | (A, cache) := evaluateExtRealMatrixArg(arg_A, cache, env); | |
| 741 | ✗ | (LDA, cache) := evaluateExtIntArg(arg_LDA, cache, env); | |
| 742 | ✗ | (B, cache) := evaluateExtRealMatrixArg(arg_B, cache, env); | |
| 743 | ✗ | (LDB, cache) := evaluateExtIntArg(arg_LDB, cache, env); | |
| 744 | ✗ | (JPVT, cache) := evaluateExtIntArrayArg(arg_JPVT, cache, env); | |
| 745 | ✗ | (RCOND, cache) := evaluateExtRealArg(arg_RCOND, cache, env); | |
| 746 | ✗ | (WORK, cache) := evaluateExtRealArrayArg(arg_WORK, cache, env); | |
| 747 | ✗ | (LWORK, cache) := evaluateExtIntArg(arg_LWORK, cache, env); | |
| 748 | ✗ | (A, B, JPVT, RANK, WORK, INFO) := | |
| 749 | Lapack.dgelsy(M, N, NRHS, A, LDA, B, LDB, JPVT, RCOND, WORK, LWORK); | ||
| 750 | ✗ | val_A := ValuesMake.makeRealMatrix(A); | |
| 751 | ✗ | val_B := ValuesMake.makeRealMatrix(B); | |
| 752 | ✗ | val_JPVT := ValuesMake.makeIntArray(JPVT); | |
| 753 | ✗ | val_RANK := ValuesMake.makeInteger(RANK); | |
| 754 | ✗ | val_WORK := ValuesMake.makeRealArray(WORK); | |
| 755 | ✗ | val_INFO := ValuesMake.makeInteger(INFO); | |
| 756 | arg_out := {arg_A, arg_B, arg_JPVT, arg_RANK, arg_WORK, arg_INFO}; | ||
| 757 | val_out := {val_A, val_B, val_JPVT, val_RANK, val_WORK, val_INFO}; | ||
| 758 | ✗ | (cache, env) := assignExtOutputs(arg_out, val_out, cache, env); | |
| 759 | then | ||
| 760 | (cache, env); | ||
| 761 | |||
| 762 | case("dgesv", {arg_N, arg_NRHS, arg_A, arg_LDA, arg_IPIV, arg_B, arg_LDB, | ||
| 763 | arg_INFO}, | ||
| 764 | cache, env) | ||
| 765 | algorithm | ||
| 766 | 4 | (N, cache) := evaluateExtIntArg(arg_N, cache, env); | |
| 767 | 4 | (NRHS, cache) := evaluateExtIntArg(arg_NRHS, cache, env); | |
| 768 | 4 | (A, cache) := evaluateExtRealMatrixArg(arg_A, cache, env); | |
| 769 | 4 | (LDA, cache) := evaluateExtIntArg(arg_LDA, cache, env); | |
| 770 | 4 | (B, cache) := evaluateExtRealMatrixArg(arg_B, cache, env); | |
| 771 | 4 | (LDB, cache) := evaluateExtIntArg(arg_LDB, cache, env); | |
| 772 | 4 | (A, IPIV, B, INFO) := | |
| 773 | Lapack.dgesv(N, NRHS, A, LDA, B, LDB); | ||
| 774 | 4 | val_A := ValuesMake.makeRealMatrix(A); | |
| 775 | 4 | val_IPIV := ValuesMake.makeIntArray(IPIV); | |
| 776 | 4 | val_B := ValuesMake.makeRealMatrix(B); | |
| 777 | 4 | val_INFO := ValuesMake.makeInteger(INFO); | |
| 778 | arg_out := {arg_A, arg_IPIV, arg_B, arg_INFO}; | ||
| 779 | val_out := {val_A, val_IPIV, val_B, val_INFO}; | ||
| 780 | 4 | (cache, env) := assignExtOutputs(arg_out, val_out, cache, env); | |
| 781 | then | ||
| 782 | (cache, env); | ||
| 783 | |||
| 784 | case("dgglse", {arg_M, arg_N, arg_P, arg_A, arg_LDA, arg_B, arg_LDB, | ||
| 785 | arg_C, arg_D, arg_X, arg_WORK, arg_LWORK, arg_INFO}, | ||
| 786 | cache, env) | ||
| 787 | algorithm | ||
| 788 | ✗ | (M, cache) := evaluateExtIntArg(arg_M, cache, env); | |
| 789 | ✗ | (N, cache) := evaluateExtIntArg(arg_N, cache, env); | |
| 790 | ✗ | (P, cache) := evaluateExtIntArg(arg_P, cache, env); | |
| 791 | ✗ | (A, cache) := evaluateExtRealMatrixArg(arg_A, cache, env); | |
| 792 | ✗ | (LDA, cache) := evaluateExtIntArg(arg_LDA, cache, env); | |
| 793 | ✗ | (B, cache) := evaluateExtRealMatrixArg(arg_B, cache, env); | |
| 794 | ✗ | (LDB, cache) := evaluateExtIntArg(arg_LDB, cache, env); | |
| 795 | ✗ | (C, cache) := evaluateExtRealArrayArg(arg_C, cache, env); | |
| 796 | ✗ | (D, cache) := evaluateExtRealArrayArg(arg_D, cache, env); | |
| 797 | ✗ | (WORK, cache) := evaluateExtRealArrayArg(arg_WORK, cache, env); | |
| 798 | ✗ | (LWORK, cache) := evaluateExtIntArg(arg_LWORK, cache, env); | |
| 799 | ✗ | (A, B, C, D, X, WORK, INFO) := | |
| 800 | Lapack.dgglse(M, N, P, A, LDA, B, LDB, C, D, WORK, LWORK); | ||
| 801 | ✗ | val_A := ValuesMake.makeRealMatrix(A); | |
| 802 | ✗ | val_B := ValuesMake.makeRealMatrix(B); | |
| 803 | ✗ | val_C := ValuesMake.makeRealArray(C); | |
| 804 | ✗ | val_D := ValuesMake.makeRealArray(D); | |
| 805 | ✗ | val_X := ValuesMake.makeRealArray(X); | |
| 806 | ✗ | val_WORK := ValuesMake.makeRealArray(WORK); | |
| 807 | ✗ | val_INFO := ValuesMake.makeInteger(INFO); | |
| 808 | arg_out := {arg_A, arg_B, arg_C, arg_D, arg_X, arg_WORK, arg_INFO}; | ||
| 809 | val_out := {val_A, val_B, val_C, val_D, val_X, val_WORK, val_INFO}; | ||
| 810 | ✗ | (cache, env) := assignExtOutputs(arg_out, val_out, cache, env); | |
| 811 | then | ||
| 812 | (cache, env); | ||
| 813 | |||
| 814 | case("dgtsv", {arg_N, arg_NRHS, arg_DL, arg_D, arg_DU, arg_B, arg_LDB, | ||
| 815 | arg_INFO}, | ||
| 816 | cache, env) | ||
| 817 | algorithm | ||
| 818 | ✗ | (N, cache) := evaluateExtIntArg(arg_N, cache, env); | |
| 819 | ✗ | (NRHS, cache) := evaluateExtIntArg(arg_NRHS, cache, env); | |
| 820 | ✗ | (DL, cache) := evaluateExtRealArrayArg(arg_DL, cache, env); | |
| 821 | ✗ | (D, cache) := evaluateExtRealArrayArg(arg_D, cache, env); | |
| 822 | ✗ | (DU, cache) := evaluateExtRealArrayArg(arg_DU, cache, env); | |
| 823 | ✗ | (B, cache) := evaluateExtRealMatrixArg(arg_B, cache, env); | |
| 824 | ✗ | (LDB, cache) := evaluateExtIntArg(arg_LDB, cache, env); | |
| 825 | ✗ | (DL, D, DU, B, INFO) := | |
| 826 | Lapack.dgtsv(N, NRHS, DL, D, DU, B, LDB); | ||
| 827 | ✗ | val_DL := ValuesMake.makeRealArray(DL); | |
| 828 | ✗ | val_D := ValuesMake.makeRealArray(D); | |
| 829 | ✗ | val_DU := ValuesMake.makeRealArray(DU); | |
| 830 | ✗ | val_B := ValuesMake.makeRealMatrix(B); | |
| 831 | ✗ | val_INFO := ValuesMake.makeInteger(INFO); | |
| 832 | arg_out := {arg_DL, arg_D, arg_DU, arg_B, arg_INFO}; | ||
| 833 | val_out := {val_DL, val_D, val_DU, val_B, val_INFO}; | ||
| 834 | ✗ | (cache, env) := assignExtOutputs(arg_out, val_out, cache, env); | |
| 835 | then | ||
| 836 | (cache, env); | ||
| 837 | |||
| 838 | case("dgbsv", {arg_N, arg_KL, arg_KU, arg_NRHS, arg_AB, arg_LDAB, arg_IPIV, | ||
| 839 | arg_B, arg_LDB, arg_INFO}, | ||
| 840 | cache, env) | ||
| 841 | algorithm | ||
| 842 | ✗ | (N, cache) := evaluateExtIntArg(arg_N, cache, env); | |
| 843 | ✗ | (KL, cache) := evaluateExtIntArg(arg_KL, cache, env); | |
| 844 | ✗ | (KU, cache) := evaluateExtIntArg(arg_KU, cache, env); | |
| 845 | ✗ | (NRHS, cache) := evaluateExtIntArg(arg_NRHS, cache, env); | |
| 846 | ✗ | (AB, cache) := evaluateExtRealMatrixArg(arg_AB, cache, env); | |
| 847 | ✗ | (LDAB, cache) := evaluateExtIntArg(arg_LDAB, cache, env); | |
| 848 | ✗ | (B, cache) := evaluateExtRealMatrixArg(arg_B, cache, env); | |
| 849 | ✗ | (LDB, cache) := evaluateExtIntArg(arg_LDB, cache, env); | |
| 850 | ✗ | (AB, IPIV, B, INFO) := | |
| 851 | Lapack.dgbsv(N, KL, KU, NRHS, AB, LDAB, B, LDB); | ||
| 852 | ✗ | val_AB := ValuesMake.makeRealMatrix(AB); | |
| 853 | ✗ | val_IPIV := ValuesMake.makeIntArray(IPIV); | |
| 854 | ✗ | val_B := ValuesMake.makeRealMatrix(B); | |
| 855 | ✗ | val_INFO := ValuesMake.makeInteger(INFO); | |
| 856 | arg_out := {arg_AB, arg_IPIV, arg_B, arg_INFO}; | ||
| 857 | val_out := {val_AB, val_IPIV, val_B, val_INFO}; | ||
| 858 | ✗ | (cache, env) := assignExtOutputs(arg_out, val_out, cache, env); | |
| 859 | then | ||
| 860 | (cache, env); | ||
| 861 | |||
| 862 | case("dgesvd", {arg_JOBU, arg_JOBVT, arg_M, arg_N, arg_A, arg_LDA, arg_S, | ||
| 863 | arg_U, arg_LDU, arg_VT, arg_LDVT, arg_WORK, arg_LWORK, arg_INFO}, | ||
| 864 | cache, env) | ||
| 865 | algorithm | ||
| 866 | ✗ | (JOBU, cache) := evaluateExtStringArg(arg_JOBU, cache, env); | |
| 867 | ✗ | (JOBVT, cache) := evaluateExtStringArg(arg_JOBVT, cache, env); | |
| 868 | ✗ | (M, cache) := evaluateExtIntArg(arg_M, cache, env); | |
| 869 | ✗ | (N, cache) := evaluateExtIntArg(arg_N, cache, env); | |
| 870 | ✗ | (A, cache) := evaluateExtRealMatrixArg(arg_A, cache, env); | |
| 871 | ✗ | (LDA, cache) := evaluateExtIntArg(arg_LDA, cache, env); | |
| 872 | ✗ | (LDU, cache) := evaluateExtIntArg(arg_LDU, cache, env); | |
| 873 | ✗ | (LDVT, cache) := evaluateExtIntArg(arg_LDVT, cache, env); | |
| 874 | ✗ | (WORK, cache) := evaluateExtRealArrayArg(arg_WORK, cache, env); | |
| 875 | ✗ | (LWORK, cache) := evaluateExtIntArg(arg_LWORK, cache, env); | |
| 876 | ✗ | (A, S, U, VT, WORK, INFO) := | |
| 877 | Lapack.dgesvd(JOBU, JOBVT, M, N, A, LDA, LDU, LDVT, WORK, LWORK); | ||
| 878 | ✗ | val_A := ValuesMake.makeRealMatrix(A); | |
| 879 | ✗ | val_S := ValuesMake.makeRealArray(S); | |
| 880 | ✗ | val_U := ValuesMake.makeRealMatrix(U); | |
| 881 | ✗ | val_VT := ValuesMake.makeRealMatrix(VT); | |
| 882 | ✗ | val_WORK := ValuesMake.makeRealArray(WORK); | |
| 883 | ✗ | val_INFO := ValuesMake.makeInteger(INFO); | |
| 884 | arg_out := {arg_A, arg_S, arg_U, arg_VT, arg_WORK, arg_INFO}; | ||
| 885 | val_out := {val_A, val_S, val_U, val_VT, val_WORK, val_INFO}; | ||
| 886 | ✗ | (cache, env) := assignExtOutputs(arg_out, val_out, cache, env); | |
| 887 | then | ||
| 888 | (cache, env); | ||
| 889 | |||
| 890 | case("dgetrf", {arg_M, arg_N, arg_A, arg_LDA, arg_IPIV, arg_INFO}, | ||
| 891 | cache, env) | ||
| 892 | algorithm | ||
| 893 | ✗ | (M, cache) := evaluateExtIntArg(arg_M, cache, env); | |
| 894 | ✗ | (N, cache) := evaluateExtIntArg(arg_N, cache, env); | |
| 895 | ✗ | (A, cache) := evaluateExtRealMatrixArg(arg_A, cache, env); | |
| 896 | ✗ | (LDA, cache) := evaluateExtIntArg(arg_LDA, cache, env); | |
| 897 | ✗ | (A, IPIV, INFO) := | |
| 898 | Lapack.dgetrf(M, N, A, LDA); | ||
| 899 | ✗ | val_A := ValuesMake.makeRealMatrix(A); | |
| 900 | ✗ | val_IPIV := ValuesMake.makeIntArray(IPIV); | |
| 901 | ✗ | val_INFO := ValuesMake.makeInteger(INFO); | |
| 902 | arg_out := {arg_A, arg_IPIV, arg_INFO}; | ||
| 903 | val_out := {val_A, val_IPIV, val_INFO}; | ||
| 904 | ✗ | (cache, env) := assignExtOutputs(arg_out, val_out, cache, env); | |
| 905 | then | ||
| 906 | (cache, env); | ||
| 907 | |||
| 908 | case("dgetrs", {arg_TRANS, arg_N, arg_NRHS, arg_A, arg_LDA, arg_IPIV, arg_B, | ||
| 909 | arg_LDB, arg_INFO}, | ||
| 910 | cache, env) | ||
| 911 | algorithm | ||
| 912 | ✗ | (TRANS, cache) := evaluateExtStringArg(arg_TRANS, cache, env); | |
| 913 | ✗ | (N, cache) := evaluateExtIntArg(arg_N, cache, env); | |
| 914 | ✗ | (NRHS, cache) := evaluateExtIntArg(arg_NRHS, cache, env); | |
| 915 | ✗ | (A, cache) := evaluateExtRealMatrixArg(arg_A, cache, env); | |
| 916 | ✗ | (LDA, cache) := evaluateExtIntArg(arg_LDA, cache, env); | |
| 917 | ✗ | (IPIV, cache) := evaluateExtIntArrayArg(arg_IPIV, cache, env); | |
| 918 | ✗ | (B, cache) := evaluateExtRealMatrixArg(arg_B, cache, env); | |
| 919 | ✗ | (LDB, cache) := evaluateExtIntArg(arg_LDB, cache, env); | |
| 920 | ✗ | (B, INFO) := | |
| 921 | Lapack.dgetrs(TRANS, N, NRHS, A, LDA, IPIV, B, LDB); | ||
| 922 | ✗ | val_B := ValuesMake.makeRealMatrix(B); | |
| 923 | ✗ | val_INFO := ValuesMake.makeInteger(INFO); | |
| 924 | arg_out := {arg_B, arg_INFO}; | ||
| 925 | val_out := {val_B, val_INFO}; | ||
| 926 | ✗ | (cache, env) := assignExtOutputs(arg_out, val_out, cache, env); | |
| 927 | then | ||
| 928 | (cache, env); | ||
| 929 | |||
| 930 | case("dgetri", {arg_N, arg_A, arg_LDA, arg_IPIV, arg_WORK, arg_LWORK, arg_INFO}, | ||
| 931 | cache, env) | ||
| 932 | algorithm | ||
| 933 | ✗ | (N, cache) := evaluateExtIntArg(arg_N, cache, env); | |
| 934 | ✗ | (A, cache) := evaluateExtRealMatrixArg(arg_A, cache, env); | |
| 935 | ✗ | (LDA, cache) := evaluateExtIntArg(arg_LDA, cache, env); | |
| 936 | ✗ | (IPIV, cache) := evaluateExtIntArrayArg(arg_IPIV, cache, env); | |
| 937 | ✗ | (WORK, cache) := evaluateExtRealArrayArg(arg_WORK, cache, env); | |
| 938 | ✗ | (LWORK, cache) := evaluateExtIntArg(arg_LWORK, cache, env); | |
| 939 | ✗ | (A, WORK, INFO) := | |
| 940 | Lapack.dgetri(N, A, LDA, IPIV, WORK, LWORK); | ||
| 941 | ✗ | val_A := ValuesMake.makeRealMatrix(A); | |
| 942 | ✗ | val_WORK := ValuesMake.makeRealArray(WORK); | |
| 943 | ✗ | val_INFO := ValuesMake.makeInteger(INFO); | |
| 944 | arg_out := {arg_A, arg_WORK, arg_INFO}; | ||
| 945 | val_out := {val_A, val_WORK, val_INFO}; | ||
| 946 | ✗ | (cache, env) := assignExtOutputs(arg_out, val_out, cache, env); | |
| 947 | then | ||
| 948 | (cache, env); | ||
| 949 | |||
| 950 | case("dgeqpf", {arg_M, arg_N, arg_A, arg_LDA, arg_JPVT, arg_TAU, arg_WORK, | ||
| 951 | arg_INFO}, | ||
| 952 | cache, env) | ||
| 953 | algorithm | ||
| 954 | ✗ | (M, cache) := evaluateExtIntArg(arg_M, cache, env); | |
| 955 | ✗ | (N, cache) := evaluateExtIntArg(arg_N, cache, env); | |
| 956 | ✗ | (A, cache) := evaluateExtRealMatrixArg(arg_A, cache, env); | |
| 957 | ✗ | (LDA, cache) := evaluateExtIntArg(arg_LDA, cache, env); | |
| 958 | ✗ | (JPVT, cache) := evaluateExtIntArrayArg(arg_JPVT, cache, env); | |
| 959 | ✗ | (WORK, cache) := evaluateExtRealArrayArg(arg_WORK, cache, env); | |
| 960 | ✗ | (A, JPVT, TAU, INFO) := | |
| 961 | Lapack.dgeqpf(M, N, A, LDA, JPVT, WORK); | ||
| 962 | ✗ | val_A := ValuesMake.makeRealMatrix(A); | |
| 963 | ✗ | val_JPVT := ValuesMake.makeIntArray(JPVT); | |
| 964 | ✗ | val_TAU := ValuesMake.makeRealArray(TAU); | |
| 965 | ✗ | val_INFO := ValuesMake.makeInteger(INFO); | |
| 966 | arg_out := {arg_A, arg_JPVT, arg_TAU, arg_INFO}; | ||
| 967 | val_out := {val_A, val_JPVT, val_TAU, val_INFO}; | ||
| 968 | ✗ | (cache, env) := assignExtOutputs(arg_out, val_out, cache, env); | |
| 969 | then | ||
| 970 | (cache, env); | ||
| 971 | |||
| 972 | case("dorgqr", {arg_M, arg_N, arg_K, arg_A, arg_LDA, arg_TAU, arg_WORK, | ||
| 973 | arg_LWORK, arg_INFO}, | ||
| 974 | cache, env) | ||
| 975 | algorithm | ||
| 976 | ✗ | (M, cache) := evaluateExtIntArg(arg_M, cache, env); | |
| 977 | ✗ | (N, cache) := evaluateExtIntArg(arg_N, cache, env); | |
| 978 | ✗ | (K, cache) := evaluateExtIntArg(arg_K, cache, env); | |
| 979 | ✗ | (A, cache) := evaluateExtRealMatrixArg(arg_A, cache, env); | |
| 980 | ✗ | (LDA, cache) := evaluateExtIntArg(arg_LDA, cache, env); | |
| 981 | ✗ | (TAU, cache) := evaluateExtRealArrayArg(arg_TAU, cache, env); | |
| 982 | ✗ | (WORK, cache) := evaluateExtRealArrayArg(arg_WORK, cache, env); | |
| 983 | ✗ | (LWORK, cache) := evaluateExtIntArg(arg_LWORK, cache, env); | |
| 984 | ✗ | (A, WORK, INFO) := | |
| 985 | Lapack.dorgqr(M, N, K, A, LDA, TAU, WORK, LWORK); | ||
| 986 | ✗ | val_A := ValuesMake.makeRealMatrix(A); | |
| 987 | ✗ | val_WORK := ValuesMake.makeRealArray(WORK); | |
| 988 | ✗ | val_INFO := ValuesMake.makeInteger(INFO); | |
| 989 | arg_out := {arg_A, arg_WORK, arg_INFO}; | ||
| 990 | val_out := {val_A, val_WORK, val_INFO}; | ||
| 991 | ✗ | (cache, env) := assignExtOutputs(arg_out, val_out, cache, env); | |
| 992 | then | ||
| 993 | (cache, env); | ||
| 994 | end match; | ||
| 995 | end evaluateExternalFunc; | ||
| 996 | |||
| 997 | protected function evaluateElements | ||
| 998 | "This function evaluates a list of elements." | ||
| 999 | input list<DAE.Element> inElements; | ||
| 1000 | input FCore.Cache inCache; | ||
| 1001 | input FCore.Graph inEnv; | ||
| 1002 | input LoopControl inLoopControl; | ||
| 1003 | output FCore.Cache outCache; | ||
| 1004 | output FCore.Graph outEnv; | ||
| 1005 | output LoopControl outLoopControl; | ||
| 1006 | algorithm | ||
| 1007 | (outCache, outEnv, outLoopControl) := | ||
| 1008 | match(inElements, inLoopControl) | ||
| 1009 | local | ||
| 1010 | DAE.Element elem; | ||
| 1011 | list<DAE.Element> rest_elems; | ||
| 1012 | FCore.Cache cache; | ||
| 1013 | FCore.Graph env; | ||
| 1014 | LoopControl loop_ctrl; | ||
| 1015 | |||
| 1016 | case (_, RETURN()) then (inCache, inEnv, inLoopControl); | ||
| 1017 | case ({}, _) then (inCache, inEnv, NEXT()); | ||
| 1018 | case (elem :: rest_elems, _) | ||
| 1019 | algorithm | ||
| 1020 | 38094 | (cache, env, loop_ctrl) := evaluateElement(elem, inCache, inEnv); | |
| 1021 | 37902 | (cache, env, loop_ctrl) := | |
| 1022 | evaluateElements(rest_elems, cache, env, loop_ctrl); | ||
| 1023 | then | ||
| 1024 | (cache, env, loop_ctrl); | ||
| 1025 | end match; | ||
| 1026 | end evaluateElements; | ||
| 1027 | |||
| 1028 | protected function evaluateElement | ||
| 1029 | "This function evaluates a single element, which should be an algorithm." | ||
| 1030 | input DAE.Element inElement; | ||
| 1031 | input FCore.Cache inCache; | ||
| 1032 | input FCore.Graph inEnv; | ||
| 1033 | output FCore.Cache outCache; | ||
| 1034 | output FCore.Graph outEnv; | ||
| 1035 | output LoopControl outLoopControl; | ||
| 1036 | algorithm | ||
| 1037 | (outCache, outEnv, outLoopControl) := match inElement | ||
| 1038 | local | ||
| 1039 | FCore.Cache cache; | ||
| 1040 | FCore.Graph env; | ||
| 1041 | LoopControl loop_ctrl; | ||
| 1042 | list<DAE.Statement> sl; | ||
| 1043 | |||
| 1044 | case DAE.ALGORITHM(algorithm_ = DAE.ALGORITHM_STMTS(statementLst = sl)) | ||
| 1045 | algorithm | ||
| 1046 | 38094 | (sl, (_,env)) := DAEUtil.traverseDAEEquationsStmts(sl, Expression.traverseSubexpressionsHelper, (optimizeExpTraverser, inEnv)); | |
| 1047 | 38094 | (cache, env, loop_ctrl) := evaluateStatements(sl, inCache, env); | |
| 1048 | then | ||
| 1049 | (cache, env, loop_ctrl); | ||
| 1050 | end match; | ||
| 1051 | end evaluateElement; | ||
| 1052 | |||
| 1053 | protected function evaluateStatement | ||
| 1054 | "This function evaluates a statement." | ||
| 1055 | input DAE.Statement inStatement; | ||
| 1056 | input FCore.Cache inCache; | ||
| 1057 | input FCore.Graph inEnv; | ||
| 1058 | output FCore.Cache outCache; | ||
| 1059 | output FCore.Graph outEnv; | ||
| 1060 | output LoopControl outLoopControl; | ||
| 1061 | algorithm | ||
| 1062 | (outCache, outEnv, outLoopControl) := | ||
| 1063 | match(inStatement, inCache, inEnv) | ||
| 1064 | local | ||
| 1065 | FCore.Cache cache; | ||
| 1066 | FCore.Graph env; | ||
| 1067 | DAE.Exp lhs, rhs, condition; | ||
| 1068 | DAE.ComponentRef lhs_cref; | ||
| 1069 | Values.Value rhs_val, v; | ||
| 1070 | list<DAE.Exp> exps; | ||
| 1071 | list<Values.Value> vals; | ||
| 1072 | list<DAE.Statement> statements; | ||
| 1073 | LoopControl loop_ctrl; | ||
| 1074 | DAE.TailCall tailCall; | ||
| 1075 | String var; | ||
| 1076 | list<String> vars; | ||
| 1077 | |||
| 1078 | case (DAE.STMT_ASSIGN(exp1 = lhs, exp = rhs), cache, env) | ||
| 1079 | algorithm | ||
| 1080 | 77292 | (cache, rhs_val) := cevalExp(rhs, cache, env); | |
| 1081 | 77126 | lhs_cref := extractLhsComponentRef(lhs); | |
| 1082 | 77122 | (cache, env) := assignVariable(lhs_cref, rhs_val, cache, env); | |
| 1083 | 77121 | then | |
| 1084 | (cache, env, NEXT()); | ||
| 1085 | |||
| 1086 | case (DAE.STMT_TUPLE_ASSIGN(), _, _) | ||
| 1087 | algorithm | ||
| 1088 | 944 | (cache, env) := | |
| 1089 | evaluateTupleAssignStatement(inStatement, inCache, inEnv); | ||
| 1090 | 937 | then | |
| 1091 | (cache, env, NEXT()); | ||
| 1092 | |||
| 1093 | case (DAE.STMT_ASSIGN_ARR(lhs = lhs, exp = rhs), _, env) | ||
| 1094 | algorithm | ||
| 1095 | 8055 | (cache, rhs_val) := cevalExp(rhs, inCache, env); | |
| 1096 | 8055 | lhs_cref := extractLhsComponentRef(lhs); | |
| 1097 | 8055 | (cache, env) := assignVariable(lhs_cref, rhs_val, cache, env); | |
| 1098 | 8055 | then | |
| 1099 | (cache, env, NEXT()); | ||
| 1100 | |||
| 1101 | case (DAE.STMT_IF(), _, _) | ||
| 1102 | algorithm | ||
| 1103 | 7694 | (cache, env, loop_ctrl) := | |
| 1104 | evaluateIfStatement(inStatement, inCache, inEnv); | ||
| 1105 | then | ||
| 1106 | (cache, env, loop_ctrl); | ||
| 1107 | |||
| 1108 | case (DAE.STMT_FOR(), _, _) | ||
| 1109 | algorithm | ||
| 1110 | 952 | (cache, env, loop_ctrl) := | |
| 1111 | evaluateForStatement(inStatement, inCache, inEnv); | ||
| 1112 | then | ||
| 1113 | (cache, env, loop_ctrl); | ||
| 1114 | |||
| 1115 | case (DAE.STMT_WHILE(exp = condition, statementLst = statements), _, _) | ||
| 1116 | algorithm | ||
| 1117 | 125 | (cache, env, loop_ctrl) := | |
| 1118 | evaluateWhileStatement(condition, statements, inCache, inEnv, NEXT()); | ||
| 1119 | then | ||
| 1120 | (cache, env, loop_ctrl); | ||
| 1121 | |||
| 1122 | // If the condition is true in the assert, do nothing. If the condition | ||
| 1123 | // is false we should stop the instantiation (depending on the assertion | ||
| 1124 | // level), but we can't really do much about that here. So right now we just | ||
| 1125 | // fail. | ||
| 1126 | case (DAE.STMT_ASSERT(cond = condition), _, _) | ||
| 1127 | algorithm | ||
| 1128 |
3/4✗ Branch 1 not taken.
✓ Branch 2 taken 1786 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 1780 times.
|
1786 | (cache, Values.BOOL(boolean = true)) := |
| 1129 | cevalExp(condition, inCache, inEnv); | ||
| 1130 | 1780 | then | |
| 1131 | (cache, inEnv, NEXT()); | ||
| 1132 | |||
| 1133 | case (DAE.STMT_ASSERT(cond = condition), _, _) | ||
| 1134 | algorithm | ||
| 1135 | ✗ | (cache, Values.BOOL(boolean = true)) := | |
| 1136 | cevalExp(condition, inCache, inEnv); | ||
| 1137 | ✗ | then | |
| 1138 | (cache, inEnv, NEXT()); | ||
| 1139 | // Special case for print, and other known calls for now; evaluated even when there is no ST | ||
| 1140 | case (DAE.STMT_NORETCALL(exp = rhs as DAE.CALL( expLst = exps, attr=DAE.CALL_ATTR(tailCall=tailCall))), _, _) | ||
| 1141 | algorithm | ||
| 1142 | 69 | (cache, vals) := cevalExpList(exps, inCache, inEnv); | |
| 1143 | 68 | (cache, v) := cevalExp(rhs, cache, inEnv); | |
| 1144 | (cache, env, outLoopControl) := match tailCall | ||
| 1145 | 60 | case DAE.NO_TAIL() then (cache, inEnv, NEXT()); | |
| 1146 | // Handle tail recursion; same as a assigning all outputs followed by a return | ||
| 1147 | ✗ | case DAE.TAIL(outVars={}) then (cache, inEnv, RETURN()); | |
| 1148 | case DAE.TAIL(outVars={var}) | ||
| 1149 | algorithm | ||
| 1150 | 4 | (cache, env) := assignVariable(ComponentReference.makeUntypedCrefIdent(var), v, cache, inEnv); | |
| 1151 | 4 | then (cache, env, RETURN()); | |
| 1152 | case DAE.TAIL(outVars=vars) | ||
| 1153 | algorithm | ||
| 1154 | ✗ | env := inEnv; | |
| 1155 | ✗ | Values.TUPLE(vals) := v; | |
| 1156 | ✗ | for val in vals loop | |
| 1157 | ✗ | var::vars := vars; | |
| 1158 | ✗ | (cache, env) := assignVariable(ComponentReference.makeUntypedCrefIdent(var), val, cache, inEnv); | |
| 1159 | end for; | ||
| 1160 | ✗ | then (cache, env, RETURN()); | |
| 1161 | end match; | ||
| 1162 | 64 | then | |
| 1163 | (cache, env, NEXT()); | ||
| 1164 | |||
| 1165 | case (DAE.STMT_RETURN(), _, _) | ||
| 1166 | ✗ | then | |
| 1167 | (inCache, inEnv, RETURN()); | ||
| 1168 | |||
| 1169 | case (DAE.STMT_BREAK(), _, _) | ||
| 1170 | ✗ | then | |
| 1171 | (inCache, inEnv, BREAK()); | ||
| 1172 | |||
| 1173 | else | ||
| 1174 | algorithm | ||
| 1175 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | true := Flags.isSet(Flags.FAILTRACE); |
| 1176 | ✗ | Debug.traceln("- CevalFunction.evaluateStatement failed for:"); | |
| 1177 | ✗ | Debug.traceln(DAEDump.ppStatementStr(inStatement)); | |
| 1178 | ✗ | then | |
| 1179 | fail(); | ||
| 1180 | end match; | ||
| 1181 | end evaluateStatement; | ||
| 1182 | |||
| 1183 | protected function evaluateStatements | ||
| 1184 | "This function evaluates a list of statements. This is just a wrapper for | ||
| 1185 | evaluateStatements2." | ||
| 1186 | input list<DAE.Statement> inStatement; | ||
| 1187 | input FCore.Cache inCache; | ||
| 1188 | input FCore.Graph inEnv; | ||
| 1189 | output FCore.Cache outCache; | ||
| 1190 | output FCore.Graph outEnv; | ||
| 1191 | output LoopControl outLoopControl; | ||
| 1192 | algorithm | ||
| 1193 | 47553 | (outCache, outEnv, outLoopControl) := | |
| 1194 | evaluateStatements2(inStatement, inCache, inEnv, NEXT()); | ||
| 1195 | end evaluateStatements; | ||
| 1196 | |||
| 1197 | protected function evaluateStatements2 | ||
| 1198 | "This is a helper function to evaluateStatements that evaluates a list of | ||
| 1199 | statements." | ||
| 1200 | input list<DAE.Statement> inStatement; | ||
| 1201 | input FCore.Cache inCache; | ||
| 1202 | input FCore.Graph inEnv; | ||
| 1203 | input LoopControl inLoopControl; | ||
| 1204 | output FCore.Cache outCache; | ||
| 1205 | output FCore.Graph outEnv; | ||
| 1206 | output LoopControl outLoopControl; | ||
| 1207 | algorithm | ||
| 1208 | (outCache, outEnv, outLoopControl) := | ||
| 1209 | match(inStatement, inLoopControl) | ||
| 1210 | local | ||
| 1211 | DAE.Statement stmt; | ||
| 1212 | list<DAE.Statement> rest_stmts; | ||
| 1213 | FCore.Cache cache; | ||
| 1214 | FCore.Graph env; | ||
| 1215 | LoopControl loop_ctrl; | ||
| 1216 | case (_, BREAK()) then (inCache, inEnv, inLoopControl); | ||
| 1217 | case (_, RETURN()) then (inCache, inEnv, inLoopControl); | ||
| 1218 | case ({}, _) then (inCache, inEnv, inLoopControl); | ||
| 1219 | case (stmt :: rest_stmts, NEXT()) | ||
| 1220 | algorithm | ||
| 1221 | 96920 | (cache, env, loop_ctrl) := evaluateStatement(stmt, inCache, inEnv); | |
| 1222 | 96704 | (cache, env, loop_ctrl) := | |
| 1223 | evaluateStatements2(rest_stmts, cache, env, loop_ctrl); | ||
| 1224 | then | ||
| 1225 | (cache, env, loop_ctrl); | ||
| 1226 | end match; | ||
| 1227 | end evaluateStatements2; | ||
| 1228 | |||
| 1229 | protected function evaluateTupleAssignStatement | ||
| 1230 | "This function evaluates tuple assignment statements, i.e. assignment | ||
| 1231 | statements where the right hand side expression is a tuple. Ex: | ||
| 1232 | (x, y, z) := fun(...)" | ||
| 1233 | input DAE.Statement inStatement; | ||
| 1234 | input FCore.Cache inCache; | ||
| 1235 | input FCore.Graph inEnv; | ||
| 1236 | output FCore.Cache outCache; | ||
| 1237 | output FCore.Graph outEnv; | ||
| 1238 | algorithm | ||
| 1239 | (outCache, outEnv) := match(inStatement, inEnv) | ||
| 1240 | local | ||
| 1241 | list<DAE.Exp> lhs_expl; | ||
| 1242 | DAE.Exp rhs; | ||
| 1243 | list<Values.Value> rhs_vals; | ||
| 1244 | list<DAE.ComponentRef> lhs_crefs; | ||
| 1245 | FCore.Cache cache; | ||
| 1246 | FCore.Graph env; | ||
| 1247 | |||
| 1248 | case (DAE.STMT_TUPLE_ASSIGN(expExpLst = lhs_expl, exp = rhs), env) | ||
| 1249 | algorithm | ||
| 1250 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 937 times.
|
944 | (cache, Values.TUPLE(valueLst = rhs_vals)) := |
| 1251 | cevalExp(rhs, inCache, env); | ||
| 1252 | 937 | lhs_crefs := List.map(lhs_expl, extractLhsComponentRef); | |
| 1253 | 937 | (cache, env) := assignTuple(lhs_crefs, rhs_vals, cache, env); | |
| 1254 | then | ||
| 1255 | (cache, env); | ||
| 1256 | end match; | ||
| 1257 | end evaluateTupleAssignStatement; | ||
| 1258 | |||
| 1259 | protected function evaluateIfStatement | ||
| 1260 | "This function evaluates an if statement." | ||
| 1261 | input DAE.Statement inStatement; | ||
| 1262 | input FCore.Cache inCache; | ||
| 1263 | input FCore.Graph inEnv; | ||
| 1264 | output FCore.Cache outCache; | ||
| 1265 | output FCore.Graph outEnv; | ||
| 1266 | output LoopControl outLoopControl; | ||
| 1267 | algorithm | ||
| 1268 | (outCache, outEnv, outLoopControl) := | ||
| 1269 | match inStatement | ||
| 1270 | local | ||
| 1271 | DAE.Exp cond; | ||
| 1272 | list<DAE.Statement> stmts; | ||
| 1273 | DAE.Else else_branch; | ||
| 1274 | FCore.Cache cache; | ||
| 1275 | FCore.Graph env; | ||
| 1276 | Boolean bool_cond; | ||
| 1277 | LoopControl loop_ctrl; | ||
| 1278 | |||
| 1279 | case DAE.STMT_IF(exp = cond, statementLst = stmts, else_ = else_branch) | ||
| 1280 | algorithm | ||
| 1281 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 7694 times.
|
7694 | (cache, Values.BOOL(boolean = bool_cond)) := |
| 1282 | cevalExp(cond, inCache, inEnv); | ||
| 1283 | 7694 | (cache, env, loop_ctrl) := evaluateIfStatement2(bool_cond, stmts, | |
| 1284 | else_branch, cache, inEnv); | ||
| 1285 | then | ||
| 1286 | (cache, env, loop_ctrl); | ||
| 1287 | end match; | ||
| 1288 | end evaluateIfStatement; | ||
| 1289 | |||
| 1290 | protected function evaluateIfStatement2 | ||
| 1291 | "Helper function to evaluateIfStatement." | ||
| 1292 | input Boolean inCondition; | ||
| 1293 | input list<DAE.Statement> inStatements; | ||
| 1294 | input DAE.Else inElse; | ||
| 1295 | input FCore.Cache inCache; | ||
| 1296 | input FCore.Graph inEnv; | ||
| 1297 | output FCore.Cache outCache; | ||
| 1298 | output FCore.Graph outEnv; | ||
| 1299 | output LoopControl outLoopControl; | ||
| 1300 | algorithm | ||
| 1301 | (outCache, outEnv, outLoopControl) := | ||
| 1302 | match(inCondition, inStatements, inElse, inEnv) | ||
| 1303 | local | ||
| 1304 | FCore.Cache cache; | ||
| 1305 | FCore.Graph env; | ||
| 1306 | list<DAE.Statement> statements; | ||
| 1307 | DAE.Exp condition; | ||
| 1308 | Boolean bool_condition; | ||
| 1309 | DAE.Else else_branch; | ||
| 1310 | LoopControl loop_ctrl; | ||
| 1311 | |||
| 1312 | // If the condition is true, evaluate the statements in the if branch. | ||
| 1313 | case (true, statements, _, env) | ||
| 1314 | algorithm | ||
| 1315 | 1905 | (cache, env, loop_ctrl) := | |
| 1316 | evaluateStatements(statements, inCache, env); | ||
| 1317 | then | ||
| 1318 | (cache, env, loop_ctrl); | ||
| 1319 | // If the condition is false and we have an else, evaluate the statements in | ||
| 1320 | // the else branch. | ||
| 1321 | case (false, _, DAE.ELSE(statementLst = statements), env) | ||
| 1322 | algorithm | ||
| 1323 | 2462 | (cache, env, loop_ctrl) := | |
| 1324 | evaluateStatements(statements, inCache, env); | ||
| 1325 | then | ||
| 1326 | (cache, env, loop_ctrl); | ||
| 1327 | // If the condition is false and we have an else if, call this function | ||
| 1328 | // again recursively. | ||
| 1329 | case (false, _, DAE.ELSEIF(exp = condition, statementLst = statements, | ||
| 1330 | else_ = else_branch), env) | ||
| 1331 | algorithm | ||
| 1332 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 477 times.
|
477 | (cache, Values.BOOL(boolean = bool_condition)) := |
| 1333 | cevalExp(condition, inCache, env); | ||
| 1334 | 477 | (cache, env, loop_ctrl) := | |
| 1335 | evaluateIfStatement2(bool_condition, statements, else_branch, cache, env); | ||
| 1336 | then | ||
| 1337 | (cache, env, loop_ctrl); | ||
| 1338 | // If the condition is false and we have no else branch, just continue. | ||
| 1339 | 3327 | case (false, _, DAE.NOELSE(), _) then (inCache, inEnv, NEXT()); | |
| 1340 | end match; | ||
| 1341 | end evaluateIfStatement2; | ||
| 1342 | |||
| 1343 | protected function evaluateForStatement | ||
| 1344 | "This function evaluates for statements." | ||
| 1345 | input DAE.Statement inStatement; | ||
| 1346 | input FCore.Cache inCache; | ||
| 1347 | input FCore.Graph inEnv; | ||
| 1348 | output FCore.Cache outCache; | ||
| 1349 | output FCore.Graph outEnv; | ||
| 1350 | output LoopControl outLoopControl; | ||
| 1351 | algorithm | ||
| 1352 | (outCache, outEnv, outLoopControl) := | ||
| 1353 | matchcontinue(inStatement, inEnv) | ||
| 1354 | local | ||
| 1355 | DAE.Type ety; | ||
| 1356 | DAE.Type ty; | ||
| 1357 | String iter_name; | ||
| 1358 | DAE.Exp range; | ||
| 1359 | list<DAE.Statement> statements; | ||
| 1360 | list<Values.Value> range_vals; | ||
| 1361 | FCore.Cache cache; | ||
| 1362 | FCore.Graph env; | ||
| 1363 | DAE.ComponentRef iter_cr; | ||
| 1364 | LoopControl loop_ctrl; | ||
| 1365 | |||
| 1366 | // The case where the range is an array. | ||
| 1367 | case (DAE.STMT_FOR(type_ = ety, iter = iter_name, | ||
| 1368 | range = range, statementLst = statements), env) | ||
| 1369 | algorithm | ||
| 1370 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 952 times.
|
952 | (cache, Values.ARRAY(valueLst = range_vals)) := |
| 1371 | cevalExp(range, inCache, env); | ||
| 1372 | 952 | (env, ty, iter_cr) := extendEnvWithForScope(iter_name, ety, env); | |
| 1373 | 952 | (cache, env, loop_ctrl) := evaluateForLoopArray(cache, env, iter_cr, | |
| 1374 | ty, range_vals, statements, NEXT()); | ||
| 1375 | then | ||
| 1376 | (cache, env, loop_ctrl); | ||
| 1377 | |||
| 1378 | case (DAE.STMT_FOR(range = range), _) | ||
| 1379 | algorithm | ||
| 1380 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | true := Flags.isSet(Flags.FAILTRACE); |
| 1381 | ✗ | Debug.traceln("- evaluateForStatement not implemented for:"); | |
| 1382 | ✗ | Debug.traceln(ExpressionBasics.printExpStr(range)); | |
| 1383 | ✗ | then | |
| 1384 | fail(); | ||
| 1385 | end matchcontinue; | ||
| 1386 | end evaluateForStatement; | ||
| 1387 | |||
| 1388 | protected function evaluateForLoopArray | ||
| 1389 | "This function evaluates a for loop where the range is an array." | ||
| 1390 | input FCore.Cache inCache; | ||
| 1391 | input FCore.Graph inEnv; | ||
| 1392 | input DAE.ComponentRef inIter; | ||
| 1393 | input DAE.Type inIterType; | ||
| 1394 | input list<Values.Value> inValues; | ||
| 1395 | input list<DAE.Statement> inStatements; | ||
| 1396 | input LoopControl inLoopControl; | ||
| 1397 | output FCore.Cache outCache; | ||
| 1398 | output FCore.Graph outEnv; | ||
| 1399 | output LoopControl outLoopControl; | ||
| 1400 | algorithm | ||
| 1401 | (outCache, outEnv, outLoopControl) := match(inEnv, inValues, inLoopControl) | ||
| 1402 | local | ||
| 1403 | Values.Value value; | ||
| 1404 | list<Values.Value> rest_vals; | ||
| 1405 | FCore.Cache cache; | ||
| 1406 | FCore.Graph env; | ||
| 1407 | LoopControl loop_ctrl; | ||
| 1408 | |||
| 1409 | case (_, _, BREAK()) then (inCache, inEnv, NEXT()); | ||
| 1410 | case (_, _, RETURN()) then (inCache, inEnv, inLoopControl); | ||
| 1411 | case (_, {}, _) then (inCache, inEnv, inLoopControl); | ||
| 1412 | case (env, value :: rest_vals, NEXT()) | ||
| 1413 | algorithm | ||
| 1414 | 4032 | env := updateVariableBinding(inIter, env, inIterType, value); | |
| 1415 | 4032 | (cache, env, loop_ctrl) := | |
| 1416 | evaluateStatements(inStatements, inCache, env); | ||
| 1417 | 4029 | (cache, env, loop_ctrl) := evaluateForLoopArray(cache, env, inIter, | |
| 1418 | inIterType, rest_vals, inStatements, loop_ctrl); | ||
| 1419 | then | ||
| 1420 | (cache, env, loop_ctrl); | ||
| 1421 | end match; | ||
| 1422 | end evaluateForLoopArray; | ||
| 1423 | |||
| 1424 | protected function evaluateWhileStatement | ||
| 1425 | "This function evaluates a while statement." | ||
| 1426 | input DAE.Exp inCondition; | ||
| 1427 | input list<DAE.Statement> inStatements; | ||
| 1428 | input FCore.Cache inCache; | ||
| 1429 | input FCore.Graph inEnv; | ||
| 1430 | input LoopControl inLoopControl; | ||
| 1431 | output FCore.Cache outCache; | ||
| 1432 | output FCore.Graph outEnv; | ||
| 1433 | output LoopControl outLoopControl; | ||
| 1434 | algorithm | ||
| 1435 | (outCache, outEnv, outLoopControl) := | ||
| 1436 | match inLoopControl | ||
| 1437 | local | ||
| 1438 | FCore.Cache cache; | ||
| 1439 | FCore.Graph env; | ||
| 1440 | LoopControl loop_ctrl; | ||
| 1441 | Boolean b; | ||
| 1442 | |||
| 1443 | case BREAK() then (inCache, inEnv, NEXT()); | ||
| 1444 | case RETURN() then (inCache, inEnv, inLoopControl); | ||
| 1445 | case _ | ||
| 1446 | algorithm | ||
| 1447 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1165 times.
|
1165 | (cache, Values.BOOL(boolean = b)) := cevalExp(inCondition, inCache, inEnv); |
| 1448 |
2/2✓ Branch 0 taken 1060 times.
✓ Branch 1 taken 105 times.
|
1165 | if b then |
| 1449 | 1060 | (cache, env, loop_ctrl) := evaluateStatements(inStatements, cache, inEnv); | |
| 1450 | 1040 | (cache, env, loop_ctrl) := evaluateWhileStatement(inCondition, inStatements, cache, env, loop_ctrl); | |
| 1451 | else | ||
| 1452 | 105 | loop_ctrl := NEXT(); | |
| 1453 | 105 | env := inEnv; | |
| 1454 | end if; | ||
| 1455 | 1145 | then | |
| 1456 | (cache, env, loop_ctrl); | ||
| 1457 | |||
| 1458 | end match; | ||
| 1459 | end evaluateWhileStatement; | ||
| 1460 | |||
| 1461 | protected function extractLhsComponentRef | ||
| 1462 | "This function extracts a component reference from an expression. It's used to | ||
| 1463 | get the left hand side component reference in simple assignments." | ||
| 1464 | input DAE.Exp inExp; | ||
| 1465 | output DAE.ComponentRef outCref; | ||
| 1466 | algorithm | ||
| 1467 | outCref := match inExp | ||
| 1468 | local | ||
| 1469 | DAE.ComponentRef cref; | ||
| 1470 | case DAE.CREF(componentRef = cref) then cref; | ||
| 1471 | else | ||
| 1472 | algorithm | ||
| 1473 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | true := Flags.isSet(Flags.FAILTRACE); |
| 1474 | ✗ | Debug.traceln("- CevalFunction.extractLhsComponentRef failed on " + ExpressionBasics.printExpStr(inExp)); | |
| 1475 | ✗ | then | |
| 1476 | fail(); | ||
| 1477 | end match; | ||
| 1478 | end extractLhsComponentRef; | ||
| 1479 | |||
| 1480 | protected function cevalExp | ||
| 1481 | "A wrapper for Ceval with most of the arguments filled in." | ||
| 1482 | input DAE.Exp inExp; | ||
| 1483 | input FCore.Cache inCache; | ||
| 1484 | input FCore.Graph inEnv; | ||
| 1485 | output FCore.Cache outCache; | ||
| 1486 | output Values.Value outValue; | ||
| 1487 | algorithm | ||
| 1488 | 129821 | (outCache, outValue) := Ceval.ceval(inCache, inEnv, inExp, true, Absyn.MSG(Absyn.dummyInfo), 0); | |
| 1489 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 129644 times.
|
129644 | false := valueEq(Values.META_FAIL(), outValue); |
| 1490 | end cevalExp; | ||
| 1491 | |||
| 1492 | protected function cevalExpList | ||
| 1493 | "A wrapper for Ceval with most of the arguments filled in." | ||
| 1494 | input list<DAE.Exp> inExpLst; | ||
| 1495 | input FCore.Cache inCache; | ||
| 1496 | input FCore.Graph inEnv; | ||
| 1497 | output FCore.Cache outCache; | ||
| 1498 | output list<Values.Value> outValue; | ||
| 1499 | algorithm | ||
| 1500 | 69 | (outCache, outValue) := Ceval.cevalList(inCache, inEnv, inExpLst, true, Absyn.MSG(Absyn.dummyInfo), 0); | |
| 1501 | end cevalExpList; | ||
| 1502 | |||
| 1503 | // [EENV] Environment extension functions (add variables). | ||
| 1504 | |||
| 1505 | protected function setupFunctionEnvironment | ||
| 1506 | "Opens up a new scope for the functions and adds all function variables to it." | ||
| 1507 | input FCore.Cache inCache; | ||
| 1508 | input FCore.Graph inEnv; | ||
| 1509 | input String inFuncName; | ||
| 1510 | input list<FunctionVar> inFuncParams; | ||
| 1511 | output FCore.Cache outCache; | ||
| 1512 | output FCore.Graph outEnv; | ||
| 1513 | algorithm | ||
| 1514 | 38177 | outEnv := FGraph.openScope(inEnv, SCode.NOT_ENCAPSULATED(), inFuncName, SOME(FCore.FUNCTION_SCOPE())); | |
| 1515 | 38177 | (outCache, outEnv) := | |
| 1516 | extendEnvWithFunctionVars(inCache, outEnv, inFuncParams); | ||
| 1517 | end setupFunctionEnvironment; | ||
| 1518 | |||
| 1519 | protected function extendEnvWithFunctionVars | ||
| 1520 | "Extends the environment with a list of variables. The list of values is the | ||
| 1521 | input arguments to the function." | ||
| 1522 | input FCore.Cache inCache; | ||
| 1523 | input FCore.Graph inEnv; | ||
| 1524 | input list<FunctionVar> inFuncParams; | ||
| 1525 | output FCore.Cache outCache; | ||
| 1526 | output FCore.Graph outEnv; | ||
| 1527 | algorithm | ||
| 1528 | (outCache, outEnv) := match(inCache, inEnv, inFuncParams) | ||
| 1529 | local | ||
| 1530 | FunctionVar param; | ||
| 1531 | list<FunctionVar> rest_params; | ||
| 1532 | FCore.Cache cache; | ||
| 1533 | FCore.Graph env; | ||
| 1534 | |||
| 1535 | case (_, _, {}) then (inCache, inEnv); | ||
| 1536 | |||
| 1537 | case (cache, env, param :: rest_params) | ||
| 1538 | algorithm | ||
| 1539 | 99626 | (cache, env) := extendEnvWithFunctionVar(cache, env, param); | |
| 1540 | 99626 | (cache, env) := extendEnvWithFunctionVars(cache, env, rest_params); | |
| 1541 | then | ||
| 1542 | (cache, env); | ||
| 1543 | |||
| 1544 | end match; | ||
| 1545 | end extendEnvWithFunctionVars; | ||
| 1546 | |||
| 1547 | protected function extendEnvWithFunctionVar | ||
| 1548 | input FCore.Cache inCache; | ||
| 1549 | input FCore.Graph inEnv; | ||
| 1550 | input FunctionVar inFuncParam; | ||
| 1551 | output FCore.Cache outCache; | ||
| 1552 | output FCore.Graph outEnv; | ||
| 1553 | algorithm | ||
| 1554 | (outCache, outEnv) := matchcontinue(inEnv, inFuncParam) | ||
| 1555 | local | ||
| 1556 | DAE.Element e; | ||
| 1557 | Option<Values.Value> val; | ||
| 1558 | FCore.Cache cache; | ||
| 1559 | FCore.Graph env; | ||
| 1560 | Option<DAE.Exp> binding_exp; | ||
| 1561 | |||
| 1562 | // Input parameters are assigned their corresponding input argument given to | ||
| 1563 | // the function. | ||
| 1564 | case (env, (e, val as SOME(_))) | ||
| 1565 | algorithm | ||
| 1566 | 51711 | (cache, env) := extendEnvWithElement(e, val, inCache, env); | |
| 1567 | then | ||
| 1568 | (cache, env); | ||
| 1569 | |||
| 1570 | // Non-input parameters might have a default binding, so we use that if it's | ||
| 1571 | // available. | ||
| 1572 | case (env, ((e as DAE.VAR(binding = binding_exp)), NONE())) | ||
| 1573 | algorithm | ||
| 1574 | 47915 | (val, cache) := evaluateBinding(binding_exp, inCache, inEnv); | |
| 1575 | 47915 | (cache, env) := extendEnvWithElement(e, val, cache, env); | |
| 1576 | then | ||
| 1577 | (cache, env); | ||
| 1578 | |||
| 1579 | case (_, (e, _)) | ||
| 1580 | algorithm | ||
| 1581 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 1582 | ✗ | Debug.traceln("- CevalFunction.extendEnvWithFunctionVars failed for:"); | |
| 1583 | ✗ | Debug.traceln(DAEDump.dumpElementsStr({e})); | |
| 1584 | ✗ | then | |
| 1585 | fail(); | ||
| 1586 | end matchcontinue; | ||
| 1587 | end extendEnvWithFunctionVar; | ||
| 1588 | |||
| 1589 | protected function evaluateBinding | ||
| 1590 | "Evaluates an optional binding expression. If SOME expression is given, | ||
| 1591 | returns SOME value or fails. If NONE expression given, returns NONE value." | ||
| 1592 | input Option<DAE.Exp> inBinding; | ||
| 1593 | input FCore.Cache inCache; | ||
| 1594 | input FCore.Graph inEnv; | ||
| 1595 | output Option<Values.Value> outValue; | ||
| 1596 | output FCore.Cache outCache; | ||
| 1597 | algorithm | ||
| 1598 | (outValue, outCache) := match inBinding | ||
| 1599 | local | ||
| 1600 | DAE.Exp binding_exp; | ||
| 1601 | FCore.Cache cache; | ||
| 1602 | Values.Value val; | ||
| 1603 | |||
| 1604 | case SOME(binding_exp) | ||
| 1605 | algorithm | ||
| 1606 | 2829 | (cache, val) := cevalExp(binding_exp, inCache, inEnv); | |
| 1607 | 2829 | then | |
| 1608 | (SOME(val), cache); | ||
| 1609 | |||
| 1610 | case NONE() then (NONE(), inCache); | ||
| 1611 | end match; | ||
| 1612 | end evaluateBinding; | ||
| 1613 | |||
| 1614 | protected function extendEnvWithElement | ||
| 1615 | "This function extracts the necessary data from a variable element, and calls | ||
| 1616 | extendEnvWithVar to add a new variable to the environment." | ||
| 1617 | input DAE.Element inElement; | ||
| 1618 | input Option<Values.Value> inBindingValue; | ||
| 1619 | input FCore.Cache inCache; | ||
| 1620 | input FCore.Graph inEnv; | ||
| 1621 | output FCore.Cache outCache; | ||
| 1622 | output FCore.Graph outEnv; | ||
| 1623 | algorithm | ||
| 1624 | (outCache, outEnv) := | ||
| 1625 | match inElement | ||
| 1626 | local | ||
| 1627 | DAE.ComponentRef cr; | ||
| 1628 | String name; | ||
| 1629 | DAE.Type ty; | ||
| 1630 | DAE.InstDims dims; | ||
| 1631 | FCore.Cache cache; | ||
| 1632 | FCore.Graph env; | ||
| 1633 | |||
| 1634 | case DAE.VAR(componentRef = cr, ty = ty, dims = dims) | ||
| 1635 | algorithm | ||
| 1636 | 99626 | name := ComponentReference.crefStr(cr); | |
| 1637 | 99626 | (cache, env) := | |
| 1638 | extendEnvWithVar(name, ty, inBindingValue, dims, inCache, inEnv); | ||
| 1639 | then | ||
| 1640 | (cache, env); | ||
| 1641 | end match; | ||
| 1642 | end extendEnvWithElement; | ||
| 1643 | |||
| 1644 | protected function extendEnvWithVar | ||
| 1645 | "This function does the actual work of extending the environment with a | ||
| 1646 | variable." | ||
| 1647 | input String inName; | ||
| 1648 | input DAE.Type inType; | ||
| 1649 | input Option<Values.Value> inOptValue; | ||
| 1650 | input DAE.InstDims inDims; | ||
| 1651 | input FCore.Cache inCache; | ||
| 1652 | input FCore.Graph inEnv; | ||
| 1653 | output FCore.Cache outCache; | ||
| 1654 | output FCore.Graph outEnv; | ||
| 1655 | algorithm | ||
| 1656 | (outCache, outEnv) := | ||
| 1657 | matchcontinue inEnv | ||
| 1658 | local | ||
| 1659 | DAE.Type ty; | ||
| 1660 | DAE.Var var; | ||
| 1661 | DAE.Binding binding; | ||
| 1662 | FCore.Cache cache; | ||
| 1663 | FCore.Graph env, record_env; | ||
| 1664 | |||
| 1665 | // Records are special, since they have their own environment with their | ||
| 1666 | // components in them. A record variable is thus always unbound, and their | ||
| 1667 | // values are instead determined by their components values. | ||
| 1668 | case _ | ||
| 1669 | algorithm | ||
| 1670 |
2/2✓ Branch 1 taken 129483 times.
✓ Branch 2 taken 5211 times.
|
134694 | true := Types.isRecord(inType); |
| 1671 | 5211 | binding := makeBinding(inOptValue); | |
| 1672 | 5211 | (cache, ty) := | |
| 1673 | appendDimensions(inType, inOptValue, inDims, inCache, inEnv); | ||
| 1674 | 5211 | var := makeFunctionVariable(inName, ty, binding); | |
| 1675 | 5211 | (cache, record_env) := | |
| 1676 | makeRecordEnvironment(inType, inOptValue, cache, inEnv); | ||
| 1677 | 5211 | env := FGraph.mkComponentNode( | |
| 1678 | inEnv, | ||
| 1679 | var, | ||
| 1680 | SCode.COMPONENT( | ||
| 1681 | inName, | ||
| 1682 | SCode.defaultPrefixes, | ||
| 1683 | SCode.ATTR({}, SCode.POTENTIAL(), SCode.NON_PARALLEL(), SCode.VAR(), Absyn.BIDIR(),Absyn.NONFIELD()), | ||
| 1684 | Absyn.TPATH(Absyn.IDENT(""), NONE()), SCode.NOMOD(), | ||
| 1685 | SCode.noComment, NONE(), Absyn.dummyInfo), | ||
| 1686 | DAE.NOMOD(), | ||
| 1687 | FCore.VAR_TYPED(), | ||
| 1688 | record_env); | ||
| 1689 | then | ||
| 1690 | (cache, env); | ||
| 1691 | |||
| 1692 | // Normal variables. | ||
| 1693 | else | ||
| 1694 | algorithm | ||
| 1695 | 129483 | binding := makeBinding(inOptValue); | |
| 1696 | 129483 | (cache, ty) := | |
| 1697 | appendDimensions(inType, inOptValue, inDims, inCache, inEnv); | ||
| 1698 | 129483 | var := makeFunctionVariable(inName, ty, binding); | |
| 1699 | 129483 | env := FGraph.mkComponentNode( | |
| 1700 | inEnv, | ||
| 1701 | var, | ||
| 1702 | SCode.COMPONENT( | ||
| 1703 | inName, | ||
| 1704 | SCode.defaultPrefixes, | ||
| 1705 | SCode.ATTR({}, SCode.POTENTIAL(), SCode.NON_PARALLEL(), SCode.VAR(), Absyn.BIDIR(),Absyn.NONFIELD()), | ||
| 1706 | Absyn.TPATH(Absyn.IDENT(""), NONE()), SCode.NOMOD(), | ||
| 1707 | SCode.noComment, NONE(), Absyn.dummyInfo), | ||
| 1708 | DAE.NOMOD(), | ||
| 1709 | FCore.VAR_TYPED(), | ||
| 1710 | FGraph.empty()); | ||
| 1711 | then | ||
| 1712 | (cache, env); | ||
| 1713 | |||
| 1714 | end matchcontinue; | ||
| 1715 | end extendEnvWithVar; | ||
| 1716 | |||
| 1717 | protected function makeFunctionVariable | ||
| 1718 | "This function creates a new variable ready to be added to an environment | ||
| 1719 | given a name, type and binding." | ||
| 1720 | input String inName; | ||
| 1721 | input DAE.Type inType; | ||
| 1722 | input DAE.Binding inBinding; | ||
| 1723 | output DAE.Var outVar; | ||
| 1724 | annotation(__OpenModelica_EarlyInline = true); | ||
| 1725 | algorithm | ||
| 1726 | 97617 | outVar := DAE.TYPES_VAR(inName, DAE.dummyAttrVar, inType, inBinding, false, NONE()); | |
| 1727 | end makeFunctionVariable; | ||
| 1728 | |||
| 1729 | protected function makeBinding | ||
| 1730 | "Creates a binding from an optional value. If some value is given we return a | ||
| 1731 | value bound binding, otherwise an unbound binding." | ||
| 1732 | input Option<Values.Value> inBindingValue; | ||
| 1733 | output DAE.Binding outBinding; | ||
| 1734 | algorithm | ||
| 1735 | outBinding := match inBindingValue | ||
| 1736 | local Values.Value val; | ||
| 1737 | 66257 | case SOME(val) then DAE.VALBOUND(val, DAE.BINDING_FROM_DEFAULT_VALUE()); | |
| 1738 | case NONE() then DAE.UNBOUND(); | ||
| 1739 | end match; | ||
| 1740 | end makeBinding; | ||
| 1741 | |||
| 1742 | protected function makeRecordEnvironment | ||
| 1743 | "This function creates an environment for a record variable by creating a new | ||
| 1744 | environment and adding the records components to it. If an optional value is | ||
| 1745 | supplied it also gives the components a value binding." | ||
| 1746 | input DAE.Type inRecordType; | ||
| 1747 | input Option<Values.Value> inOptValue; | ||
| 1748 | input FCore.Cache inCache; | ||
| 1749 | input FCore.Graph inGraph; | ||
| 1750 | output FCore.Cache outCache; | ||
| 1751 | output FCore.Graph outRecordEnv; | ||
| 1752 | algorithm | ||
| 1753 | (outCache, outRecordEnv) := | ||
| 1754 | match inRecordType | ||
| 1755 | local | ||
| 1756 | list<DAE.Var> var_lst; | ||
| 1757 | list<Option<Values.Value>> vals; | ||
| 1758 | FCore.Cache cache; | ||
| 1759 | FCore.Graph graph; | ||
| 1760 | FCore.Ref parent, child; | ||
| 1761 | FCore.Node node; | ||
| 1762 | |||
| 1763 | case DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(),varLst = var_lst) | ||
| 1764 | algorithm | ||
| 1765 | 5211 | parent := FGraph.lastScopeRef(inGraph); | |
| 1766 | 5211 | (graph, node) := FGraph.node(inGraph, FNode.feNodeName, {parent}, FCore.ND(NONE())); | |
| 1767 | 5211 | child := FNode.toRef(node); | |
| 1768 | 5211 | FNode.addChildRef(parent, FNode.feNodeName, child); | |
| 1769 | 5211 | graph := FGraph.pushScopeRef(graph, child); | |
| 1770 | |||
| 1771 | 5211 | vals := getRecordValues(inOptValue, inRecordType); | |
| 1772 |
1/2✓ Branch 2 taken 5211 times.
✗ Branch 3 not taken.
|
5211 | (cache, graph) := List.threadFold(var_lst, vals, |
| 1773 | extendEnvWithRecordVar, (inCache, graph)); | ||
| 1774 | then | ||
| 1775 | (cache, graph); | ||
| 1776 | end match; | ||
| 1777 | end makeRecordEnvironment; | ||
| 1778 | |||
| 1779 | protected function getRecordValues | ||
| 1780 | "This function returns a list of optional values that will be assigned to a | ||
| 1781 | records components. If some record value is given it returns the list of | ||
| 1782 | values inside it, made into options, otherwise it returns a list of as many | ||
| 1783 | NONE as there are components in the record." | ||
| 1784 | input Option<Values.Value> inOptValue; | ||
| 1785 | input DAE.Type inRecordType; | ||
| 1786 | output list<Option<Values.Value>> outValues; | ||
| 1787 | algorithm | ||
| 1788 | outValues := match(inOptValue, inRecordType) | ||
| 1789 | local | ||
| 1790 | list<Values.Value> vals; | ||
| 1791 | list<Option<Values.Value>> opt_vals; | ||
| 1792 | list<DAE.Var> vars; | ||
| 1793 | Integer n; | ||
| 1794 | case (SOME(Values.RECORD(orderd = vals)), _) | ||
| 1795 | algorithm | ||
| 1796 | 1562 | opt_vals := List.map(vals, Util.makeOption); | |
| 1797 | then | ||
| 1798 | opt_vals; | ||
| 1799 | |||
| 1800 | case (NONE(), DAE.T_COMPLEX(varLst = vars)) | ||
| 1801 | algorithm | ||
| 1802 | 3649 | n := listLength(vars); | |
| 1803 | 3649 | opt_vals := List.fill(NONE(), n); | |
| 1804 | then | ||
| 1805 | opt_vals; | ||
| 1806 | end match; | ||
| 1807 | end getRecordValues; | ||
| 1808 | |||
| 1809 | protected function extendEnvWithRecordVar | ||
| 1810 | "This function extends an environment with a record component." | ||
| 1811 | input DAE.Var inVar; | ||
| 1812 | input Option<Values.Value> inOptValue; | ||
| 1813 | input tuple<FCore.Cache, FCore.Graph> inEnv; | ||
| 1814 | output tuple<FCore.Cache, FCore.Graph> outEnv; | ||
| 1815 | algorithm | ||
| 1816 | outEnv := match(inVar, inEnv) | ||
| 1817 | local | ||
| 1818 | String name; | ||
| 1819 | DAE.Type ty; | ||
| 1820 | FCore.Cache cache; | ||
| 1821 | FCore.Graph env; | ||
| 1822 | |||
| 1823 | case (DAE.TYPES_VAR(name = name, ty = ty), (cache, env)) | ||
| 1824 | algorithm | ||
| 1825 | 35068 | (cache, env) := | |
| 1826 | extendEnvWithVar(name, ty, inOptValue, {}, cache, env); | ||
| 1827 | 35068 | outEnv := (cache, env); | |
| 1828 | then | ||
| 1829 | outEnv; | ||
| 1830 | end match; | ||
| 1831 | end extendEnvWithRecordVar; | ||
| 1832 | |||
| 1833 | protected function extendEnvWithForScope | ||
| 1834 | "This function opens a new for loop scope in the environment by opening a new | ||
| 1835 | scope and adding the given iterator to it. For convenience it also returns the | ||
| 1836 | type and component reference of the iterator." | ||
| 1837 | input String inIterName; | ||
| 1838 | input DAE.Type inIterType; | ||
| 1839 | input FCore.Graph inEnv; | ||
| 1840 | output FCore.Graph outEnv; | ||
| 1841 | output DAE.Type outIterType; | ||
| 1842 | output DAE.ComponentRef outIterCref; | ||
| 1843 | algorithm | ||
| 1844 | 952 | outIterType := Types.expTypetoTypesType(inIterType); | |
| 1845 | 952 | outEnv := FGraph.addForIterator(inEnv, inIterName, outIterType, | |
| 1846 | DAE.UNBOUND(), SCode.CONST(), SOME(DAE.C_CONST())); | ||
| 1847 | 952 | outIterCref := ComponentReferenceBasics.makeCrefIdent(inIterName, inIterType, {}); | |
| 1848 | end extendEnvWithForScope; | ||
| 1849 | |||
| 1850 | protected function appendDimensions | ||
| 1851 | "This function appends dimensions to a type. This is needed because DAE.VAR | ||
| 1852 | separates the type and dimensions, while DAE.TYPES_VAR keeps the dimension | ||
| 1853 | information in the type itself. The dimensions can come from two sources: | ||
| 1854 | either they are specified in the variable itself as DAE.InstDims, or if the | ||
| 1855 | variable is declared with unknown dimensions they can be determined from the | ||
| 1856 | variables binding (i.e. input argument to the function)." | ||
| 1857 | input DAE.Type inType; | ||
| 1858 | input Option<Values.Value> inOptBinding; | ||
| 1859 | input DAE.InstDims inDims; | ||
| 1860 | input FCore.Cache inCache; | ||
| 1861 | input FCore.Graph inEnv; | ||
| 1862 | output FCore.Cache outCache; | ||
| 1863 | output DAE.Type outType; | ||
| 1864 | protected | ||
| 1865 | list<Integer> binding_dims; | ||
| 1866 | algorithm | ||
| 1867 | 134694 | binding_dims := ValuesUtil.valueDimensions( | |
| 1868 | Util.getOptionOrDefault(inOptBinding, Values.INTEGER(0))); | ||
| 1869 | 134694 | (outCache, outType) := | |
| 1870 | appendDimensions2(inType, inDims, binding_dims, inCache, inEnv); | ||
| 1871 | end appendDimensions; | ||
| 1872 | |||
| 1873 | protected function appendDimensions2 | ||
| 1874 | "Helper function to appendDimensions. Appends dimensions to a type. inDims is | ||
| 1875 | the declared dimensions of the variable while inBindingDims is the dimensions | ||
| 1876 | of the variables binding (empty list if it doesn't have a binding)." | ||
| 1877 | input DAE.Type inType; | ||
| 1878 | input DAE.InstDims inDims; | ||
| 1879 | input list<Integer> inBindingDims; | ||
| 1880 | input FCore.Cache inCache; | ||
| 1881 | input FCore.Graph inEnv; | ||
| 1882 | output FCore.Cache outCache; | ||
| 1883 | output DAE.Type outType; | ||
| 1884 | algorithm | ||
| 1885 | (outCache, outType) := | ||
| 1886 | matchcontinue(inType, inDims, inBindingDims) | ||
| 1887 | local | ||
| 1888 | DAE.InstDims rest_dims; | ||
| 1889 | DAE.Exp dim_exp; | ||
| 1890 | Values.Value dim_val; | ||
| 1891 | Integer dim_int; | ||
| 1892 | DAE.Dimension dim; | ||
| 1893 | DAE.Type ty; | ||
| 1894 | list<Integer> bind_dims; | ||
| 1895 | FCore.Cache cache; | ||
| 1896 | |||
| 1897 | case (ty, {}, _) then (inCache, ty); | ||
| 1898 | |||
| 1899 | case (ty, DAE.DIM_UNKNOWN() :: rest_dims, dim_int :: bind_dims) | ||
| 1900 | algorithm | ||
| 1901 | 4847 | dim := Expression.intDimension(dim_int); | |
| 1902 | 4847 | (cache, ty) := appendDimensions2(ty, rest_dims, bind_dims, inCache, inEnv); | |
| 1903 | 4847 | then | |
| 1904 | (cache, DAE.T_ARRAY(ty, {dim})); | ||
| 1905 | |||
| 1906 | // If the variable is not an input, set the dimension size to 0 (dynamic size). | ||
| 1907 | case (ty, DAE.DIM_UNKNOWN() :: rest_dims, bind_dims) | ||
| 1908 | algorithm | ||
| 1909 | 8 | (cache, ty) := appendDimensions2(ty, rest_dims, bind_dims, inCache, inEnv); | |
| 1910 | 8 | then | |
| 1911 | (cache, DAE.T_ARRAY(ty, {DAE.DIM_INTEGER(0)})); | ||
| 1912 | |||
| 1913 | case (ty, DAE.DIM_INTEGER(dim_int) :: rest_dims, bind_dims) | ||
| 1914 | algorithm | ||
| 1915 | 20095 | dim := DAE.DIM_INTEGER(dim_int); | |
| 1916 | 20095 | bind_dims := List.restOrEmpty(bind_dims); | |
| 1917 | 20095 | (cache, ty) := appendDimensions2(ty, rest_dims, bind_dims, inCache, inEnv); | |
| 1918 | 20095 | then | |
| 1919 | (cache, DAE.T_ARRAY(ty, {dim})); | ||
| 1920 | |||
| 1921 | case (ty, DAE.DIM_BOOLEAN() :: rest_dims, bind_dims) | ||
| 1922 | algorithm | ||
| 1923 | dim := DAE.DIM_INTEGER(2); | ||
| 1924 | ✗ | bind_dims := List.restOrEmpty(bind_dims); | |
| 1925 | ✗ | (cache, ty) := appendDimensions2(ty, rest_dims, bind_dims, inCache, inEnv); | |
| 1926 | ✗ | then | |
| 1927 | (cache, DAE.T_ARRAY(ty, {dim})); | ||
| 1928 | |||
| 1929 | case (ty, DAE.DIM_ENUM(size = dim_int) :: rest_dims, bind_dims) | ||
| 1930 | algorithm | ||
| 1931 | ✗ | dim := DAE.DIM_INTEGER(dim_int); | |
| 1932 | ✗ | bind_dims := List.restOrEmpty(bind_dims); | |
| 1933 | ✗ | (cache, ty) := appendDimensions2(ty, rest_dims, bind_dims, inCache, inEnv); | |
| 1934 | ✗ | then | |
| 1935 | (cache, DAE.T_ARRAY(ty, {dim})); | ||
| 1936 | |||
| 1937 | case (ty, DAE.DIM_EXP(exp = dim_exp) :: rest_dims, bind_dims) | ||
| 1938 | algorithm | ||
| 1939 | 896 | (cache, dim_val) := cevalExp(dim_exp, inCache, inEnv); | |
| 1940 | 896 | dim_int := ValuesUtil.valueInteger(dim_val); | |
| 1941 | 896 | dim := DAE.DIM_INTEGER(dim_int); | |
| 1942 | 896 | bind_dims := List.restOrEmpty(bind_dims); | |
| 1943 | 896 | (cache, ty) := appendDimensions2(ty, rest_dims, bind_dims, inCache, inEnv); | |
| 1944 | 896 | then | |
| 1945 | (cache, DAE.T_ARRAY(ty, {dim})); | ||
| 1946 | |||
| 1947 | case (_, _ :: _, _) | ||
| 1948 | algorithm | ||
| 1949 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 1950 | ✗ | Debug.trace("- CevalFunction.appendDimensions2 failed\n"); | |
| 1951 | ✗ | then | |
| 1952 | fail(); | ||
| 1953 | end matchcontinue; | ||
| 1954 | end appendDimensions2; | ||
| 1955 | |||
| 1956 | // [MENV] Environment manipulation functions (set and get variables). | ||
| 1957 | |||
| 1958 | protected function assignVariable | ||
| 1959 | "This function assigns a variable in the environment a new value." | ||
| 1960 | input DAE.ComponentRef inCref; | ||
| 1961 | input Values.Value inNewValue; | ||
| 1962 | input FCore.Cache inCache; | ||
| 1963 | input FCore.Graph inEnv; | ||
| 1964 | output FCore.Cache outCache; | ||
| 1965 | output FCore.Graph outEnv; | ||
| 1966 | algorithm | ||
| 1967 | (outCache, outEnv) := | ||
| 1968 | matchcontinue inCref | ||
| 1969 | local | ||
| 1970 | DAE.ComponentRef cr, cr_rest; | ||
| 1971 | FCore.Cache cache; | ||
| 1972 | FCore.Graph env; | ||
| 1973 | list<DAE.Subscript> subs; | ||
| 1974 | DAE.Type ty; | ||
| 1975 | DAE.Type ety; | ||
| 1976 | Values.Value val; | ||
| 1977 | DAE.Var var; | ||
| 1978 | FCore.Status inst_status; | ||
| 1979 | String id, comp_id; | ||
| 1980 | |||
| 1981 | // Wildcard, no need to assign anything. | ||
| 1982 | case DAE.WILD() then (inCache, inEnv); | ||
| 1983 | |||
| 1984 | // A record assignment. | ||
| 1985 | case DAE.CREF_IDENT(ident = id, subscriptLst = {}, identType = ety as | ||
| 1986 | DAE.T_COMPLEX(complexClassType = ClassInf.RECORD())) | ||
| 1987 | algorithm | ||
| 1988 | 2417 | (_, var, _, _, inst_status, env) := | |
| 1989 | Lookup.lookupIdentLocal(inCache, inEnv, id); | ||
| 1990 | 2417 | (cache, env) := assignRecord(ety, inNewValue, inCache, env); | |
| 1991 | 2417 | var := updateRecordBinding(var, inNewValue); | |
| 1992 | 2417 | env := FGraph.updateComp(inEnv, var, inst_status, env); | |
| 1993 | then | ||
| 1994 | (cache, env); | ||
| 1995 | |||
| 1996 | // If we get a scalar we just update the value. | ||
| 1997 | case cr as DAE.CREF_IDENT(subscriptLst = {}) | ||
| 1998 | algorithm | ||
| 1999 | 66905 | ty := Types.unflattenArrayType(Expression.typeof(ValuesUtil.valueExp(inNewValue))); // In case of zero-dimensions, update the dimensions; they are all known now | |
| 2000 | 66905 | env := updateVariableBinding(cr, inEnv, ty, inNewValue); | |
| 2001 | then | ||
| 2002 | (inCache, env); | ||
| 2003 | |||
| 2004 | // If we get a vector we first get the old value and update the relevant | ||
| 2005 | // part of it, and then update the variables value. | ||
| 2006 | case DAE.CREF_IDENT(subscriptLst = subs) | ||
| 2007 | algorithm | ||
| 2008 | 26680 | cr := ComponentReference.crefStripSubs(inCref); | |
| 2009 | 26680 | (ty, val) := getVariableTypeAndValue(cr, inEnv); | |
| 2010 | 26680 | (cache, val) := assignVector(inNewValue, val, subs, inCache, inEnv); | |
| 2011 | 26680 | env := updateVariableBinding(cr, inEnv, ty, val); | |
| 2012 | then | ||
| 2013 | (cache, env); | ||
| 2014 | |||
| 2015 | // A qualified component reference is a record component, so first lookup | ||
| 2016 | // the records environment, and then assign the variable in that environment. | ||
| 2017 | case DAE.CREF_QUAL(ident = id, subscriptLst = {}, | ||
| 2018 | componentRef = cr_rest) | ||
| 2019 | algorithm | ||
| 2020 | 9874 | (_, var, _, _, inst_status, env) := | |
| 2021 | Lookup.lookupIdentLocal(inCache, inEnv, id); | ||
| 2022 | 9874 | (cache, env) := assignVariable(cr_rest, inNewValue, inCache, env); | |
| 2023 | 9874 | comp_id := ComponentReferenceBasics.crefFirstIdent(cr_rest); | |
| 2024 | 9874 | var := updateRecordComponentBinding(var, comp_id, inNewValue); | |
| 2025 | 9874 | env := FGraph.updateComp(inEnv, var, inst_status, env); | |
| 2026 | then | ||
| 2027 | (cache, env); | ||
| 2028 | end matchcontinue; | ||
| 2029 | end assignVariable; | ||
| 2030 | |||
| 2031 | protected function assignTuple | ||
| 2032 | "This function assign a tuple by calling assignVariable for each tuple | ||
| 2033 | component." | ||
| 2034 | input list<DAE.ComponentRef> inLhsCrefs; | ||
| 2035 | input list<Values.Value> inRhsValues; | ||
| 2036 | input FCore.Cache inCache; | ||
| 2037 | input FCore.Graph inEnv; | ||
| 2038 | output FCore.Cache outCache; | ||
| 2039 | output FCore.Graph outEnv; | ||
| 2040 | algorithm | ||
| 2041 | (outCache, outEnv) := | ||
| 2042 | match(inLhsCrefs, inRhsValues, inCache, inEnv) | ||
| 2043 | local | ||
| 2044 | DAE.ComponentRef cr; | ||
| 2045 | list<DAE.ComponentRef> rest_crefs; | ||
| 2046 | Values.Value value; | ||
| 2047 | list<Values.Value> rest_vals; | ||
| 2048 | FCore.Cache cache; | ||
| 2049 | FCore.Graph env; | ||
| 2050 | case ({}, _, cache, env) then (cache, env); | ||
| 2051 | case (cr :: rest_crefs, value :: rest_vals, cache, env) | ||
| 2052 | algorithm | ||
| 2053 | 1880 | (cache, env) := assignVariable(cr, value, cache, env); | |
| 2054 | 1880 | (cache, env) := assignTuple(rest_crefs, rest_vals, cache, env); | |
| 2055 | then | ||
| 2056 | (cache, env); | ||
| 2057 | end match; | ||
| 2058 | end assignTuple; | ||
| 2059 | |||
| 2060 | protected function assignRecord | ||
| 2061 | input DAE.Type inType; | ||
| 2062 | input Values.Value inValue; | ||
| 2063 | input FCore.Cache inCache; | ||
| 2064 | input FCore.Graph inEnv; | ||
| 2065 | output FCore.Cache outCache; | ||
| 2066 | output FCore.Graph outEnv; | ||
| 2067 | algorithm | ||
| 2068 | (outCache, outEnv) := match(inType, inValue) | ||
| 2069 | local | ||
| 2070 | list<Values.Value> values; | ||
| 2071 | list<DAE.Var> vars; | ||
| 2072 | FCore.Cache cache; | ||
| 2073 | FCore.Graph env; | ||
| 2074 | case (DAE.T_COMPLEX(varLst = vars), Values.RECORD(orderd = values)) | ||
| 2075 | algorithm | ||
| 2076 | 2417 | (cache, env) := assignRecordComponents(vars, values, inCache, inEnv); | |
| 2077 | then | ||
| 2078 | (cache, env); | ||
| 2079 | end match; | ||
| 2080 | end assignRecord; | ||
| 2081 | |||
| 2082 | protected function assignRecordComponents | ||
| 2083 | input list<DAE.Var> inVars; | ||
| 2084 | input list<Values.Value> inValues; | ||
| 2085 | input FCore.Cache inCache; | ||
| 2086 | input FCore.Graph inEnv; | ||
| 2087 | output FCore.Cache outCache; | ||
| 2088 | output FCore.Graph outEnv; | ||
| 2089 | algorithm | ||
| 2090 | (outCache, outEnv) := match(inVars, inValues) | ||
| 2091 | local | ||
| 2092 | list<DAE.Var> rest_vars; | ||
| 2093 | Values.Value val; | ||
| 2094 | list<Values.Value> rest_vals; | ||
| 2095 | String name; | ||
| 2096 | DAE.ComponentRef cr; | ||
| 2097 | DAE.Type ty; | ||
| 2098 | FCore.Cache cache; | ||
| 2099 | FCore.Graph env; | ||
| 2100 | |||
| 2101 | case ({}, {}) then (inCache, inEnv); | ||
| 2102 | |||
| 2103 | case (DAE.TYPES_VAR(name = name, ty = ty) :: rest_vars, val :: rest_vals) | ||
| 2104 | algorithm | ||
| 2105 | 8926 | cr := ComponentReferenceBasics.makeCrefIdent(name, ty, {}); | |
| 2106 | 8926 | (cache, env) := assignVariable(cr, val, inCache, inEnv); | |
| 2107 | 8926 | (cache, env) := assignRecordComponents(rest_vars, rest_vals, cache, env); | |
| 2108 | then | ||
| 2109 | (cache, env); | ||
| 2110 | end match; | ||
| 2111 | end assignRecordComponents; | ||
| 2112 | |||
| 2113 | public function assignVector | ||
| 2114 | "This function assigns a part of a vector by replacing the parts indicated by | ||
| 2115 | the subscripts in the old value with the new value." | ||
| 2116 | input Values.Value inNewValue; | ||
| 2117 | input Values.Value inOldValue; | ||
| 2118 | input list<DAE.Subscript> inSubscripts; | ||
| 2119 | input FCore.Cache inCache; | ||
| 2120 | input FCore.Graph inEnv; | ||
| 2121 | output FCore.Cache outCache; | ||
| 2122 | output Values.Value outResult; | ||
| 2123 | algorithm | ||
| 2124 | (outCache, outResult) := | ||
| 2125 | matchcontinue(inNewValue, inOldValue, inSubscripts) | ||
| 2126 | local | ||
| 2127 | DAE.Exp e; | ||
| 2128 | Values.Value index, val; | ||
| 2129 | list<Values.Value> values, values2; | ||
| 2130 | list<Values.Value> old_values, old_values2, indices; | ||
| 2131 | list<Integer> dims; | ||
| 2132 | Integer i; | ||
| 2133 | DAE.Subscript sub; | ||
| 2134 | list<DAE.Subscript> rest_subs; | ||
| 2135 | FCore.Cache cache; | ||
| 2136 | |||
| 2137 | // No subscripts, we have either reached the end of the recursion or the | ||
| 2138 | // whole vector was assigned. | ||
| 2139 | case (_, _, {}) then (inCache, inNewValue); | ||
| 2140 | |||
| 2141 | // An index subscript. Extract the indicated vector element and update it | ||
| 2142 | // with assignVector, and then put it back in the list of old values. | ||
| 2143 | case (_, Values.ARRAY(valueLst = values, dimLst = dims), DAE.INDEX(exp = e) :: rest_subs) | ||
| 2144 | algorithm | ||
| 2145 | 27658 | (cache, index) := cevalExp(e, inCache, inEnv); | |
| 2146 | 27658 | i := ValuesUtil.valueInteger(index); | |
| 2147 | 27658 | val := listGet(values, i); | |
| 2148 | 27658 | (cache, val) := assignVector(inNewValue, val, rest_subs, cache, inEnv); | |
| 2149 | 27658 | values := List.replaceAt(val, i, values); | |
| 2150 | 27658 | then | |
| 2151 | (cache, Values.ARRAY(values, dims)); | ||
| 2152 | |||
| 2153 | // A slice. | ||
| 2154 | case (Values.ARRAY(valueLst = values), Values.ARRAY(valueLst = old_values, dimLst = dims), DAE.SLICE(exp = e) :: rest_subs) | ||
| 2155 | algorithm | ||
| 2156 | // Evaluate the slice range to a list of values. | ||
| 2157 |
3/6✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
|
5 | (cache, Values.ARRAY(valueLst = (indices as (Values.INTEGER(integer = i) :: _)))) := |
| 2158 | cevalExp(e, inCache, inEnv); | ||
| 2159 | // Split the list of old values at the first slice index. | ||
| 2160 | 5 | (old_values, old_values2) := List.splitr(old_values, i - 1); | |
| 2161 | // Update the rest of the old value with assignSlice. | ||
| 2162 | 5 | (cache, values2) := | |
| 2163 | assignSlice(values, old_values2, indices, rest_subs, i, cache, inEnv); | ||
| 2164 | // Assemble the list of values again. | ||
| 2165 | 5 | values := List.append_reverse(old_values, values2); | |
| 2166 | 5 | then | |
| 2167 | (cache, Values.ARRAY(values, dims)); | ||
| 2168 | |||
| 2169 | // A : (whole dimension). | ||
| 2170 | case (Values.ARRAY(valueLst = values), Values.ARRAY(valueLst = values2, dimLst = dims), DAE.WHOLEDIM() :: rest_subs) | ||
| 2171 | algorithm | ||
| 2172 | 9 | (cache, values) := | |
| 2173 | assignWholeDim(values, values2, rest_subs, inCache, inEnv); | ||
| 2174 | 9 | then | |
| 2175 | (cache, Values.ARRAY(values, dims)); | ||
| 2176 | |||
| 2177 | case (_, _, sub :: _) | ||
| 2178 | algorithm | ||
| 2179 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 2180 | ✗ | print("- CevalFunction.assignVector failed on: "); | |
| 2181 | ✗ | print(ExpressionBasics.printSubscriptStr(sub) + "\n"); | |
| 2182 | ✗ | then | |
| 2183 | fail(); | ||
| 2184 | end matchcontinue; | ||
| 2185 | end assignVector; | ||
| 2186 | |||
| 2187 | protected function assignSlice | ||
| 2188 | "This function assigns a slice of a vector given a list of new and old values | ||
| 2189 | and a list of indices." | ||
| 2190 | input list<Values.Value> inNewValues; | ||
| 2191 | input list<Values.Value> inOldValues; | ||
| 2192 | input list<Values.Value> inIndices; | ||
| 2193 | input list<DAE.Subscript> inSubscripts; | ||
| 2194 | input Integer inIndex; | ||
| 2195 | input FCore.Cache inCache; | ||
| 2196 | input FCore.Graph inEnv; | ||
| 2197 | output FCore.Cache outCache; | ||
| 2198 | output list<Values.Value> outResult; | ||
| 2199 | algorithm | ||
| 2200 | (outCache, outResult) := | ||
| 2201 | matchcontinue(inNewValues, inOldValues, inIndices) | ||
| 2202 | local | ||
| 2203 | Values.Value v1, v2, index; | ||
| 2204 | list<Values.Value> vl1, vl2, rest_indices; | ||
| 2205 | FCore.Cache cache; | ||
| 2206 | |||
| 2207 | case (_, _, {}) then (inCache, inOldValues); | ||
| 2208 | |||
| 2209 | // Skip indices that are smaller than the next index in the slice. | ||
| 2210 | case (vl1, v2 :: vl2, index :: _) | ||
| 2211 | algorithm | ||
| 2212 |
2/2✓ Branch 1 taken 21 times.
✓ Branch 2 taken 7 times.
|
28 | true := (inIndex < ValuesUtil.valueInteger(index)); |
| 2213 | 7 | (cache, vl1) := assignSlice(vl1, vl2, inIndices, inSubscripts, | |
| 2214 | inIndex + 1, inCache, inEnv); | ||
| 2215 | 7 | then | |
| 2216 | (cache, v2 :: vl1); | ||
| 2217 | |||
| 2218 | case (v1 :: vl1, v2 :: vl2, _ :: rest_indices) | ||
| 2219 | algorithm | ||
| 2220 | 21 | (cache, v1) := assignVector(v1, v2, inSubscripts, inCache, inEnv); | |
| 2221 | 21 | (cache, vl1) := assignSlice(vl1, vl2, rest_indices, inSubscripts, | |
| 2222 | inIndex + 1, inCache, inEnv); | ||
| 2223 | 21 | then | |
| 2224 | (cache, v1 :: vl1); | ||
| 2225 | end matchcontinue; | ||
| 2226 | end assignSlice; | ||
| 2227 | |||
| 2228 | protected function assignWholeDim | ||
| 2229 | "This function assigns a whole dimension of a vector." | ||
| 2230 | input list<Values.Value> inNewValues; | ||
| 2231 | input list<Values.Value> inOldValues; | ||
| 2232 | input list<DAE.Subscript> inSubscripts; | ||
| 2233 | input FCore.Cache inCache; | ||
| 2234 | input FCore.Graph inEnv; | ||
| 2235 | output FCore.Cache outCache; | ||
| 2236 | output list<Values.Value> outResult; | ||
| 2237 | algorithm | ||
| 2238 | (outCache, outResult) := | ||
| 2239 | match(inNewValues, inOldValues) | ||
| 2240 | local | ||
| 2241 | Values.Value v1, v2; | ||
| 2242 | list<Values.Value> vl1, vl2; | ||
| 2243 | FCore.Cache cache; | ||
| 2244 | case ({}, _) then (inCache, {}); | ||
| 2245 | case (v1 :: vl1, v2 :: vl2) | ||
| 2246 | algorithm | ||
| 2247 | 25 | (cache, v1) := assignVector(v1, v2, inSubscripts, inCache, inEnv); | |
| 2248 | 25 | (cache, vl1) := assignWholeDim(vl1, vl2, inSubscripts, inCache, inEnv); | |
| 2249 | 25 | then | |
| 2250 | (cache, v1 :: vl1); | ||
| 2251 | end match; | ||
| 2252 | end assignWholeDim; | ||
| 2253 | |||
| 2254 | protected function updateVariableBinding | ||
| 2255 | "This function updates a variables binding in the environment." | ||
| 2256 | input DAE.ComponentRef inVariableCref; | ||
| 2257 | input FCore.Graph inEnv; | ||
| 2258 | input DAE.Type inType; | ||
| 2259 | input Values.Value inNewValue; | ||
| 2260 | output FCore.Graph outEnv; | ||
| 2261 | protected | ||
| 2262 | String var_name; | ||
| 2263 | DAE.Var var; | ||
| 2264 | algorithm | ||
| 2265 | 97617 | var_name := ComponentReference.crefStr(inVariableCref); | |
| 2266 | 97617 | var := makeFunctionVariable(var_name, inType, | |
| 2267 | DAE.VALBOUND(inNewValue, DAE.BINDING_FROM_DEFAULT_VALUE())); | ||
| 2268 | 97617 | outEnv := FGraph.updateComp(inEnv, var, FCore.VAR_TYPED(), FGraph.empty()); | |
| 2269 | end updateVariableBinding; | ||
| 2270 | |||
| 2271 | protected function updateRecordBinding | ||
| 2272 | "Updates the binding of a record variable." | ||
| 2273 | input DAE.Var inVar; | ||
| 2274 | input Values.Value inValue; | ||
| 2275 | output DAE.Var outVar; | ||
| 2276 | protected | ||
| 2277 | algorithm | ||
| 2278 | outVar := inVar; | ||
| 2279 | 2417 | outVar.binding := DAE.VALBOUND(inValue, DAE.BINDING_FROM_DEFAULT_VALUE()); | |
| 2280 | end updateRecordBinding; | ||
| 2281 | |||
| 2282 | protected function updateRecordComponentBinding | ||
| 2283 | "Updates the binding of a record component." | ||
| 2284 | input DAE.Var inVar; | ||
| 2285 | input String inComponentId; | ||
| 2286 | input Values.Value inValue; | ||
| 2287 | output DAE.Var outVar; | ||
| 2288 | protected | ||
| 2289 | Values.Value val; | ||
| 2290 | algorithm | ||
| 2291 | outVar := inVar; | ||
| 2292 | 9874 | val := getBindingOrDefault(outVar.binding, outVar.ty); | |
| 2293 | 9874 | val := updateRecordComponentValue(inComponentId, inValue, val); | |
| 2294 | 9874 | outVar.binding := DAE.VALBOUND(val, DAE.BINDING_FROM_DEFAULT_VALUE()); | |
| 2295 | end updateRecordComponentBinding; | ||
| 2296 | |||
| 2297 | protected function updateRecordComponentValue | ||
| 2298 | input String inComponentId; | ||
| 2299 | input Values.Value inComponentValue; | ||
| 2300 | input Values.Value inRecordValue; | ||
| 2301 | output Values.Value outRecordValue; | ||
| 2302 | protected | ||
| 2303 | Absyn.Path name; | ||
| 2304 | list<Values.Value> vals; | ||
| 2305 | list<String> comps; | ||
| 2306 | Integer pos; | ||
| 2307 | algorithm | ||
| 2308 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 9874 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9874 times.
|
9874 | Values.RECORD(name, vals, comps, -1) := inRecordValue; |
| 2309 | 9874 | pos := List.position(inComponentId, comps); | |
| 2310 | 9874 | vals := List.replaceAt(inComponentValue, pos, vals); | |
| 2311 | 9874 | outRecordValue := Values.RECORD(name, vals, comps, -1); | |
| 2312 | end updateRecordComponentValue; | ||
| 2313 | |||
| 2314 | protected function getVariableTypeAndBinding | ||
| 2315 | "This function looks a variable up in the environment, and returns it's type | ||
| 2316 | and binding." | ||
| 2317 | input DAE.ComponentRef inCref; | ||
| 2318 | input FCore.Graph inEnv; | ||
| 2319 | output DAE.Type outType; | ||
| 2320 | output DAE.Binding outBinding; | ||
| 2321 | algorithm | ||
| 2322 | 62802 | (_, _, outType, outBinding, _, _, _, _, _) := | |
| 2323 | Lookup.lookupVar(FCore.emptyCache(), inEnv, inCref); | ||
| 2324 | end getVariableTypeAndBinding; | ||
| 2325 | |||
| 2326 | protected function getVariableTypeAndValue | ||
| 2327 | "This function looks a variable up in the environment, and returns it's type | ||
| 2328 | and value. If it doesn't have a value, then a default value will be returned." | ||
| 2329 | input DAE.ComponentRef inCref; | ||
| 2330 | input FCore.Graph inEnv; | ||
| 2331 | output DAE.Type outType; | ||
| 2332 | output Values.Value outValue; | ||
| 2333 | protected | ||
| 2334 | DAE.Binding binding; | ||
| 2335 | algorithm | ||
| 2336 | 62794 | (outType, binding) := getVariableTypeAndBinding(inCref, inEnv); | |
| 2337 | 62794 | outValue := getBindingOrDefault(binding, outType); | |
| 2338 | end getVariableTypeAndValue; | ||
| 2339 | |||
| 2340 | protected function getBindingValueOpt | ||
| 2341 | "Returns the value in a binding, or NONE()." | ||
| 2342 | input DAE.Binding inBinding; | ||
| 2343 | output Option<Values.Value> outValue; | ||
| 2344 | algorithm | ||
| 2345 | outValue := match inBinding | ||
| 2346 | local | ||
| 2347 | Values.Value val; | ||
| 2348 | case DAE.VALBOUND(valBound = val) then SOME(val); | ||
| 2349 | case DAE.EQBOUND(evaluatedExp = SOME(val)) then SOME(val); | ||
| 2350 | else NONE(); | ||
| 2351 | end match; | ||
| 2352 | end getBindingValueOpt; | ||
| 2353 | |||
| 2354 | protected function getBindingOrDefault | ||
| 2355 | "Returns the value in a binding, or a default value if binding isn't a value | ||
| 2356 | binding." | ||
| 2357 | input DAE.Binding inBinding; | ||
| 2358 | input DAE.Type inType; | ||
| 2359 | output Values.Value outValue; | ||
| 2360 | algorithm | ||
| 2361 | outValue := match inBinding | ||
| 2362 | local | ||
| 2363 | Values.Value val; | ||
| 2364 | case DAE.VALBOUND(valBound = val) then val; | ||
| 2365 | case DAE.EQBOUND(evaluatedExp = SOME(val)) then val; | ||
| 2366 | 11624 | else generateDefaultBinding(inType); | |
| 2367 | end match; | ||
| 2368 | end getBindingOrDefault; | ||
| 2369 | |||
| 2370 | protected function generateDefaultBinding | ||
| 2371 | "This function generates a default value for a type. This is needed when | ||
| 2372 | assigning parts of an array, since we can only assign parts of an already | ||
| 2373 | existing array. The value will be the types equivalence to zero." | ||
| 2374 | input DAE.Type inType; | ||
| 2375 | output Values.Value outValue; | ||
| 2376 | algorithm | ||
| 2377 | outValue := matchcontinue inType | ||
| 2378 | local | ||
| 2379 | DAE.Dimension dim; | ||
| 2380 | Integer int_dim; | ||
| 2381 | list<Integer> dims; | ||
| 2382 | DAE.Type ty; | ||
| 2383 | list<Values.Value> values; | ||
| 2384 | Values.Value value; | ||
| 2385 | Absyn.Path path; | ||
| 2386 | list<DAE.Var> vars; | ||
| 2387 | list<String> var_names; | ||
| 2388 | |||
| 2389 | case DAE.T_INTEGER() then Values.INTEGER(0); | ||
| 2390 | case DAE.T_REAL() then Values.REAL(0.0); | ||
| 2391 | case DAE.T_STRING() then Values.STRING(""); | ||
| 2392 | case DAE.T_BOOL() then Values.BOOL(false); | ||
| 2393 | case DAE.T_ENUMERATION() | ||
| 2394 | then Values.ENUM_LITERAL(Absyn.IDENT(""), 0); | ||
| 2395 | |||
| 2396 | case DAE.T_ARRAY(dims = {dim}, ty = ty) | ||
| 2397 | algorithm | ||
| 2398 | 1540 | int_dim := Expression.dimensionSize(dim); | |
| 2399 | 1540 | value := generateDefaultBinding(ty); | |
| 2400 | 1540 | values := List.fill(value, int_dim); | |
| 2401 | 1540 | dims := ValuesUtil.valueDimensions(value); | |
| 2402 | 1540 | then | |
| 2403 | Values.ARRAY(values, int_dim :: dims); | ||
| 2404 | |||
| 2405 | case DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(path = path), varLst = vars) | ||
| 2406 | algorithm | ||
| 2407 | 709 | (values, var_names) := List.map_2(vars, getRecordVarBindingAndName); | |
| 2408 | 709 | then | |
| 2409 | Values.RECORD(path, values, var_names, -1); | ||
| 2410 | |||
| 2411 | else | ||
| 2412 | algorithm | ||
| 2413 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 2414 | ✗ | Debug.trace("- CevalFunction.generateDefaultBinding failed\n"); | |
| 2415 | ✗ | then | |
| 2416 | fail(); | ||
| 2417 | end matchcontinue; | ||
| 2418 | end generateDefaultBinding; | ||
| 2419 | |||
| 2420 | protected function getRecordVarBindingAndName | ||
| 2421 | input DAE.Var inVar; | ||
| 2422 | output Values.Value outBinding; | ||
| 2423 | output String outName; | ||
| 2424 | algorithm | ||
| 2425 | (outBinding, outName) := matchcontinue inVar | ||
| 2426 | local | ||
| 2427 | String name; | ||
| 2428 | DAE.Type ty; | ||
| 2429 | DAE.Binding binding; | ||
| 2430 | Values.Value val; | ||
| 2431 | |||
| 2432 | case DAE.TYPES_VAR(name = name, ty = ty, binding = binding) | ||
| 2433 | algorithm | ||
| 2434 | 9386 | val := getBindingOrDefault(binding, ty); | |
| 2435 | then | ||
| 2436 | (val, name); | ||
| 2437 | |||
| 2438 | case DAE.TYPES_VAR(name = name) | ||
| 2439 | algorithm | ||
| 2440 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 2441 | ✗ | Debug.traceln("- CevalFunction.getRecordVarBindingAndName failed on variable " | |
| 2442 | + name + "\n"); | ||
| 2443 | ✗ | then | |
| 2444 | fail(); | ||
| 2445 | end matchcontinue; | ||
| 2446 | end getRecordVarBindingAndName; | ||
| 2447 | |||
| 2448 | protected function getFunctionReturnValue | ||
| 2449 | "This function fetches one return value for the function, given an output | ||
| 2450 | variable and an environment." | ||
| 2451 | input DAE.Element inOutputVar; | ||
| 2452 | input FCore.Graph inEnv; | ||
| 2453 | output Values.Value outValue; | ||
| 2454 | algorithm | ||
| 2455 | outValue := match inOutputVar | ||
| 2456 | local | ||
| 2457 | DAE.ComponentRef cr; | ||
| 2458 | DAE.Type ty; | ||
| 2459 | Values.Value val; | ||
| 2460 | case DAE.VAR(componentRef = cr, ty = ty) | ||
| 2461 | algorithm | ||
| 2462 | 38876 | val := getVariableValue(cr, ty, inEnv); | |
| 2463 | then | ||
| 2464 | val; | ||
| 2465 | end match; | ||
| 2466 | end getFunctionReturnValue; | ||
| 2467 | |||
| 2468 | protected function getVariableValue | ||
| 2469 | "Helper function to getFunctionReturnValue. Fetches a variables value from the | ||
| 2470 | environment." | ||
| 2471 | input DAE.ComponentRef inCref; | ||
| 2472 | input DAE.Type inType; | ||
| 2473 | input FCore.Graph inEnv; | ||
| 2474 | output Values.Value outValue; | ||
| 2475 | algorithm | ||
| 2476 | outValue := matchcontinue inType | ||
| 2477 | local | ||
| 2478 | Values.Value val; | ||
| 2479 | Absyn.Path p; | ||
| 2480 | |||
| 2481 | // A record doesn't have a value, but an environment with it's components. | ||
| 2482 | // So we need to assemble the records value. | ||
| 2483 | case DAE.T_COMPLEX(complexClassType = ClassInf.RECORD()) | ||
| 2484 | algorithm | ||
| 2485 | 2787 | p := ComponentReference.crefToPath(inCref); | |
| 2486 | 2787 | val := getRecordValue(p, inType, inEnv); | |
| 2487 | then | ||
| 2488 | val; | ||
| 2489 | |||
| 2490 | // All other variables we can just look up in the environment. | ||
| 2491 | else | ||
| 2492 | algorithm | ||
| 2493 | 36114 | (_, val) := getVariableTypeAndValue(inCref, inEnv); | |
| 2494 | 36114 | then | |
| 2495 | val; | ||
| 2496 | end matchcontinue; | ||
| 2497 | end getVariableValue; | ||
| 2498 | |||
| 2499 | protected function getRecordValue | ||
| 2500 | "Looks up the value of a record by looking up the record components in the | ||
| 2501 | records environment and assembling a record value." | ||
| 2502 | input Absyn.Path inRecordName; | ||
| 2503 | input DAE.Type inType; | ||
| 2504 | input FCore.Graph inEnv; | ||
| 2505 | output Values.Value outValue; | ||
| 2506 | algorithm | ||
| 2507 | outValue := match(inRecordName, inType) | ||
| 2508 | local | ||
| 2509 | list<DAE.Var> vars; | ||
| 2510 | list<Values.Value> vals; | ||
| 2511 | list<String> var_names; | ||
| 2512 | String id; | ||
| 2513 | Absyn.Path p; | ||
| 2514 | FCore.Graph env; | ||
| 2515 | case (Absyn.IDENT(name = id), DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(path = p), | ||
| 2516 | varLst = vars)) | ||
| 2517 | algorithm | ||
| 2518 | 2795 | (_, _, _, _, _, env) := | |
| 2519 | Lookup.lookupIdentLocal(FCore.emptyCache(), inEnv, id); | ||
| 2520 | 2795 | vals := List.map1(vars, getRecordComponentValue, env); | |
| 2521 | 2794 | var_names := List.map(vars, TypesDump.getVarName); | |
| 2522 | 2794 | then | |
| 2523 | Values.RECORD(p, vals, var_names, -1); | ||
| 2524 | end match; | ||
| 2525 | end getRecordValue; | ||
| 2526 | |||
| 2527 | protected function getRecordComponentValue | ||
| 2528 | "Looks up the value for a record component." | ||
| 2529 | input DAE.Var inVars; | ||
| 2530 | input FCore.Graph inEnv; | ||
| 2531 | output Values.Value outValues; | ||
| 2532 | algorithm | ||
| 2533 | outValues := match inVars | ||
| 2534 | local | ||
| 2535 | Values.Value val; | ||
| 2536 | Option<Values.Value> oval; | ||
| 2537 | String id; | ||
| 2538 | DAE.Type ty; | ||
| 2539 | DAE.Binding binding, tvbinding; | ||
| 2540 | |||
| 2541 | // The component is a record itself. | ||
| 2542 | case DAE.TYPES_VAR( | ||
| 2543 | name = id, | ||
| 2544 | ty = ty as DAE.T_COMPLEX(complexClassType = ClassInf.RECORD())) | ||
| 2545 | algorithm | ||
| 2546 | 8 | val := getRecordValue(Absyn.IDENT(id), ty, inEnv); | |
| 2547 | then | ||
| 2548 | val; | ||
| 2549 | |||
| 2550 | // A non-record variable. | ||
| 2551 | case DAE.TYPES_VAR(name = id, ty = ty, binding = tvbinding) | ||
| 2552 | algorithm | ||
| 2553 | 14256 | (_, DAE.TYPES_VAR(binding = binding), _, _, _, _) := | |
| 2554 | Lookup.lookupIdentLocal(FCore.emptyCache(), inEnv, id); | ||
| 2555 | 14255 | oval := getBindingValueOpt(binding); | |
| 2556 | |||
| 2557 | // if no binding from env then use the typesvar binding. | ||
| 2558 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 14255 times.
✓ Branch 2 taken 42 times.
✓ Branch 3 taken 14213 times.
|
14255 | if isNone(oval) then |
| 2559 | 42 | oval := getBindingValueOpt(tvbinding); | |
| 2560 | end if; | ||
| 2561 | |||
| 2562 | // if there is still no binding in the typesvar then generated default | ||
| 2563 | // binding. IDK if this is a good idea. It is like generating a default | ||
| 2564 | // equation for a variable if in a model. But this is how it was done. | ||
| 2565 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 14255 times.
✓ Branch 2 taken 42 times.
✓ Branch 3 taken 14213 times.
|
14255 | if isSome(oval) then |
| 2566 | 14213 | SOME(val) := oval; | |
| 2567 | else | ||
| 2568 | 42 | val := generateDefaultBinding(ty); | |
| 2569 | end if; | ||
| 2570 | |||
| 2571 | then | ||
| 2572 | val; | ||
| 2573 | end match; | ||
| 2574 | end getRecordComponentValue; | ||
| 2575 | |||
| 2576 | protected function boxReturnValue | ||
| 2577 | "This function takes a list of return values, and return either a NORETCALL, a | ||
| 2578 | single value or a tuple with the values depending on how many return variables | ||
| 2579 | there are." | ||
| 2580 | input list<Values.Value> inReturnValues; | ||
| 2581 | output Values.Value outValue; | ||
| 2582 | algorithm | ||
| 2583 | outValue := match inReturnValues | ||
| 2584 | local | ||
| 2585 | Values.Value val; | ||
| 2586 | |||
| 2587 | case {} then Values.NORETCALL(); | ||
| 2588 | case {val} then val; | ||
| 2589 | 961 | case _ :: _ then Values.TUPLE(inReturnValues); | |
| 2590 | end match; | ||
| 2591 | end boxReturnValue; | ||
| 2592 | |||
| 2593 | // [DEPS] Function variable dependency handling. | ||
| 2594 | |||
| 2595 | protected function sortFunctionVarsByDependency | ||
| 2596 | "A functions variables might depend on each other, for example by defining | ||
| 2597 | dimensions that depend on the size of another variable. This function sorts | ||
| 2598 | the list of variables so that any dependencies to a variable will be before | ||
| 2599 | the variable in resulting list." | ||
| 2600 | input list<FunctionVar> inFuncVars; | ||
| 2601 | input DAE.ElementSource inSource; | ||
| 2602 | output list<FunctionVar> outFuncVars; | ||
| 2603 | protected | ||
| 2604 | list<tuple<FunctionVar, list<FunctionVar>>> cycles; | ||
| 2605 | algorithm | ||
| 2606 | 38177 | (outFuncVars, cycles) := Graph.topologicalSort( | |
| 2607 | Graph.buildGraph(inFuncVars, getElementDependencies, inFuncVars), | ||
| 2608 | isElementEqual); | ||
| 2609 | 38177 | checkCyclicalComponents(cycles, inSource); | |
| 2610 | end sortFunctionVarsByDependency; | ||
| 2611 | |||
| 2612 | protected function getElementDependencies | ||
| 2613 | "Returns the dependencies given an element." | ||
| 2614 | input FunctionVar inElement; | ||
| 2615 | input list<FunctionVar> inAllElements; | ||
| 2616 | output list<FunctionVar> outDependencies; | ||
| 2617 | type Arg = tuple<list<FunctionVar>, list<FunctionVar>, list<DAE.Ident>>; | ||
| 2618 | algorithm | ||
| 2619 | outDependencies := matchcontinue inElement | ||
| 2620 | local | ||
| 2621 | DAE.Exp bind_exp; | ||
| 2622 | list<FunctionVar> deps; | ||
| 2623 | list<DAE.Dimension> dims; | ||
| 2624 | Arg arg; | ||
| 2625 | |||
| 2626 | case (DAE.VAR(binding = SOME(bind_exp), dims = dims), _) | ||
| 2627 | algorithm | ||
| 2628 | 7874 | (_, arg as (_, deps, _)) := Expression.traverseExpBidir( | |
| 2629 | bind_exp, | ||
| 2630 | getElementDependenciesTraverserEnter, | ||
| 2631 | getElementDependenciesTraverserExit, | ||
| 2632 | (inAllElements, {}, {})); | ||
| 2633 | 7874 | (_, (_, deps, _)) := List.mapFold(dims, | |
| 2634 | getElementDependenciesFromDims, arg); | ||
| 2635 | then | ||
| 2636 | deps; | ||
| 2637 | |||
| 2638 | case (DAE.VAR(dims = dims), _) | ||
| 2639 | algorithm | ||
| 2640 | 91752 | (_, (_, deps, _)) := List.mapFold(dims, | |
| 2641 | getElementDependenciesFromDims, (inAllElements, {}, {})); | ||
| 2642 | then | ||
| 2643 | deps; | ||
| 2644 | |||
| 2645 | else {}; | ||
| 2646 | end matchcontinue; | ||
| 2647 | end getElementDependencies; | ||
| 2648 | |||
| 2649 | protected function getElementDependenciesFromDims | ||
| 2650 | "Helper function to getElementDependencies that gets the dependencies from the | ||
| 2651 | dimensions of a variable." | ||
| 2652 | input DAE.Dimension inDimension; | ||
| 2653 | input Arg inArg; | ||
| 2654 | output DAE.Dimension outDimension; | ||
| 2655 | output Arg outArg; | ||
| 2656 | type Arg = tuple<list<FunctionVar>, list<FunctionVar>, list<DAE.Ident>>; | ||
| 2657 | algorithm | ||
| 2658 | (outDimension, outArg) := matchcontinue inArg | ||
| 2659 | local | ||
| 2660 | Arg arg; | ||
| 2661 | DAE.Exp dim_exp; | ||
| 2662 | |||
| 2663 | case _ | ||
| 2664 | algorithm | ||
| 2665 | 25846 | dim_exp := Expression.dimensionSizeExp(inDimension); | |
| 2666 | 20991 | (_, arg) := Expression.traverseExpBidir( | |
| 2667 | dim_exp, | ||
| 2668 | getElementDependenciesTraverserEnter, | ||
| 2669 | getElementDependenciesTraverserExit, | ||
| 2670 | inArg); | ||
| 2671 | 20991 | then | |
| 2672 | (inDimension, arg); | ||
| 2673 | |||
| 2674 | else (inDimension, inArg); | ||
| 2675 | end matchcontinue; | ||
| 2676 | end getElementDependenciesFromDims; | ||
| 2677 | |||
| 2678 | protected function getElementDependenciesTraverserEnter | ||
| 2679 | "Traverse function used by getElementDependencies to collect all dependencies | ||
| 2680 | for an element. The extra arguments are a list of all elements, a list of | ||
| 2681 | accumulated depencies and a list of iterators from enclosing for-loops." | ||
| 2682 | input DAE.Exp inExp; | ||
| 2683 | input Arg inArg; | ||
| 2684 | output DAE.Exp outExp; | ||
| 2685 | output Arg outArg; | ||
| 2686 | type Arg = tuple<list<FunctionVar>, list<FunctionVar>, list<DAE.Ident>>; | ||
| 2687 | algorithm | ||
| 2688 | (outExp, outArg) := matchcontinue(inExp, inArg) | ||
| 2689 | local | ||
| 2690 | DAE.Exp exp; | ||
| 2691 | DAE.ComponentRef cref; | ||
| 2692 | list<FunctionVar> all_el, accum_el; | ||
| 2693 | FunctionVar e; | ||
| 2694 | DAE.Ident iter; | ||
| 2695 | list<DAE.Ident> iters; | ||
| 2696 | DAE.ReductionIterators riters; | ||
| 2697 | |||
| 2698 | // Check if the crefs matches any of the iterators that might shadow a | ||
| 2699 | // function variable, and don't add it as a dependency if that's the case. | ||
| 2700 | case (exp as DAE.CREF(componentRef = DAE.CREF_IDENT(ident = iter)), | ||
| 2701 | (all_el, accum_el, iters as _ :: _)) | ||
| 2702 | algorithm | ||
| 2703 |
2/2✓ Branch 1 taken 28 times.
✓ Branch 2 taken 40 times.
|
68 | true := List.isMemberOnTrue(iter, iters, stringEqual); |
| 2704 | 40 | then | |
| 2705 | (exp, (all_el, accum_el, iters)); | ||
| 2706 | |||
| 2707 | // Otherwise, try to delete the cref from the list of all elements. If that | ||
| 2708 | // succeeds, add it to the list of dependencies. Since we have deleted the | ||
| 2709 | // element from the list of all variables this ensures that the dependency | ||
| 2710 | // list only contains unique elements. | ||
| 2711 | case (exp as DAE.CREF(componentRef = cref), (all_el, accum_el, iters)) | ||
| 2712 | algorithm | ||
| 2713 |
3/4✗ Branch 1 not taken.
✓ Branch 2 taken 8604 times.
✓ Branch 3 taken 5460 times.
✓ Branch 4 taken 3144 times.
|
8604 | (all_el, SOME(e)) := List.deleteMemberOnTrue(cref, all_el, |
| 2714 | isElementNamed); | ||
| 2715 | 3144 | then | |
| 2716 | (exp, (all_el, e :: accum_el, iters)); | ||
| 2717 | |||
| 2718 | // If we encounter a reduction, add the iterator to the iterator list so | ||
| 2719 | // that we know which iterators shadow function variables. | ||
| 2720 | case (exp as DAE.REDUCTION(iterators = riters), (all_el, accum_el, iters)) | ||
| 2721 | algorithm | ||
| 2722 | 28 | iters := listAppend(List.map(riters, Expression.reductionIterName), iters); | |
| 2723 | 28 | then | |
| 2724 | (exp, (all_el, accum_el, iters)); | ||
| 2725 | |||
| 2726 | else (inExp, inArg); | ||
| 2727 | end matchcontinue; | ||
| 2728 | end getElementDependenciesTraverserEnter; | ||
| 2729 | |||
| 2730 | protected function getElementDependenciesTraverserExit | ||
| 2731 | "Exit traversal function used by getElementDependencies." | ||
| 2732 | input DAE.Exp inExp; | ||
| 2733 | input Arg inArg; | ||
| 2734 | output DAE.Exp outExp; | ||
| 2735 | output Arg outArg; | ||
| 2736 | type Arg = tuple<list<FunctionVar>, list<FunctionVar>, list<DAE.Ident>>; | ||
| 2737 | algorithm | ||
| 2738 | (outExp, outArg) := match(inExp, inArg) | ||
| 2739 | local | ||
| 2740 | DAE.Exp exp; | ||
| 2741 | list<FunctionVar> all_el, accum_el; | ||
| 2742 | list<DAE.Ident> iters; | ||
| 2743 | DAE.ReductionIterators riters; | ||
| 2744 | |||
| 2745 | // If we encounter a reduction, make sure that its iterator matches the | ||
| 2746 | // first iterator in the iterator list, and if so remove it from the list. | ||
| 2747 | case (exp as DAE.REDUCTION(iterators = riters), (all_el, accum_el, iters)) | ||
| 2748 | algorithm | ||
| 2749 | 28 | iters := compareIterators(listReverse(riters), iters); | |
| 2750 | 28 | then | |
| 2751 | (exp, (all_el, accum_el, iters)); | ||
| 2752 | |||
| 2753 | else (inExp, inArg); | ||
| 2754 | end match; | ||
| 2755 | end getElementDependenciesTraverserExit; | ||
| 2756 | |||
| 2757 | protected function compareIterators | ||
| 2758 | input DAE.ReductionIterators inRiters; | ||
| 2759 | input list<String> inIters; | ||
| 2760 | output list<String> outIters; | ||
| 2761 | algorithm | ||
| 2762 | outIters := matchcontinue(inRiters,inIters) | ||
| 2763 | local | ||
| 2764 | String id1,id2; | ||
| 2765 | DAE.ReductionIterators riters; | ||
| 2766 | list<String> iters; | ||
| 2767 | |||
| 2768 | case (DAE.REDUCTIONITER(id = id1) :: riters, id2 :: iters) | ||
| 2769 | algorithm | ||
| 2770 |
2/4✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 28 times.
✗ Branch 4 not taken.
|
28 | true := stringEqual(id1, id2); |
| 2771 | 28 | then | |
| 2772 | compareIterators(riters, iters); | ||
| 2773 | |||
| 2774 | case ({}, _) then inIters; | ||
| 2775 | |||
| 2776 | // This should never happen, print an error if it does. | ||
| 2777 | else | ||
| 2778 | algorithm | ||
| 2779 | ✗ | Error.addMessage(Error.INTERNAL_ERROR, | |
| 2780 | {"Different iterators in CevalFunction.compareIterators."}); | ||
| 2781 | ✗ | then | |
| 2782 | fail(); | ||
| 2783 | |||
| 2784 | end matchcontinue; | ||
| 2785 | end compareIterators; | ||
| 2786 | |||
| 2787 | protected function isElementNamed | ||
| 2788 | "Checks if a function parameter has the given name." | ||
| 2789 | input DAE.ComponentRef inName; | ||
| 2790 | input FunctionVar inElement; | ||
| 2791 | output Boolean isNamed; | ||
| 2792 | protected | ||
| 2793 | DAE.ComponentRef name; | ||
| 2794 | algorithm | ||
| 2795 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 49722 times.
|
49722 | (DAE.VAR(componentRef = name), _) := inElement; |
| 2796 | 49722 | isNamed := ComponentReferenceBasics.crefEqualWithoutSubs(name, inName); | |
| 2797 | end isElementNamed; | ||
| 2798 | |||
| 2799 | protected function isElementEqual | ||
| 2800 | "Checks if two function parameters are equal, i.e. have the same name." | ||
| 2801 | input FunctionVar inElement1; | ||
| 2802 | input FunctionVar inElement2; | ||
| 2803 | output Boolean isEqual; | ||
| 2804 | protected | ||
| 2805 | DAE.ComponentRef cr1, cr2; | ||
| 2806 | algorithm | ||
| 2807 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9425 times.
|
9425 | (DAE.VAR(componentRef = cr1), _) := inElement1; |
| 2808 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9425 times.
|
9425 | (DAE.VAR(componentRef = cr2), _) := inElement2; |
| 2809 | 9425 | isEqual := ComponentReferenceBasics.crefEqualWithoutSubs(cr1, cr2); | |
| 2810 | end isElementEqual; | ||
| 2811 | |||
| 2812 | protected function checkCyclicalComponents | ||
| 2813 | "Checks the return value from Graph.topologicalSort. If the list of cycles is | ||
| 2814 | not empty, print an error message and fail, since it's not allowed for | ||
| 2815 | constants or parameters to have cyclic dependencies." | ||
| 2816 | input list<tuple<FunctionVar, list<FunctionVar>>> inCycles; | ||
| 2817 | input DAE.ElementSource inSource; | ||
| 2818 | algorithm | ||
| 2819 | () := match inCycles | ||
| 2820 | local | ||
| 2821 | list<list<FunctionVar>> cycles; | ||
| 2822 | list<list<DAE.Element>> elements; | ||
| 2823 | list<list<DAE.ComponentRef>> crefs; | ||
| 2824 | list<list<String>> names; | ||
| 2825 | list<String> cycles_strs; | ||
| 2826 | String cycles_str, scope_str; | ||
| 2827 | SourceInfo info; | ||
| 2828 | |||
| 2829 | case {} then (); | ||
| 2830 | |||
| 2831 | else | ||
| 2832 | algorithm | ||
| 2833 | ✗ | cycles := Graph.findCycles(inCycles, isElementEqual); | |
| 2834 | ✗ | elements := List.mapList(cycles, Util.tuple21); | |
| 2835 | ✗ | crefs := List.mapList(elements, DAEUtil.varCref); | |
| 2836 | ✗ | names := List.mapList(crefs, | |
| 2837 | ComponentReferenceBasics.printComponentRefStr); | ||
| 2838 | ✗ | cycles_strs := List.map1(names, stringDelimitList, ","); | |
| 2839 | ✗ | cycles_str := stringDelimitList(cycles_strs, "}, {"); | |
| 2840 | ✗ | cycles_str := "{" + cycles_str + "}"; | |
| 2841 | scope_str := ""; | ||
| 2842 | ✗ | info := ElementSource.getElementSourceFileInfo(inSource); | |
| 2843 | ✗ | Error.addSourceMessage(Error.CIRCULAR_COMPONENTS, {scope_str, cycles_str}, info); | |
| 2844 | ✗ | then | |
| 2845 | fail(); | ||
| 2846 | |||
| 2847 | end match; | ||
| 2848 | end checkCyclicalComponents; | ||
| 2849 | |||
| 2850 | // [EOPT] Expression optimization functions. | ||
| 2851 | |||
| 2852 | protected function optimizeExpTraverser | ||
| 2853 | "This function optimizes expressions in a function. So far this is only used | ||
| 2854 | to transform ASUB expressions to CREFs so that this doesn't need to be done | ||
| 2855 | while evaluating the function. But it's possible that more forms of | ||
| 2856 | optimization can be done too." | ||
| 2857 | input DAE.Exp inExp; | ||
| 2858 | input FCore.Graph inEnv; | ||
| 2859 | output DAE.Exp outExp; | ||
| 2860 | output FCore.Graph outEnv; | ||
| 2861 | algorithm | ||
| 2862 | (outExp,outEnv) := match (inExp,inEnv) | ||
| 2863 | local | ||
| 2864 | DAE.ComponentRef cref; | ||
| 2865 | DAE.Type ety; | ||
| 2866 | list<DAE.Subscript> subs; | ||
| 2867 | FCore.Graph env; | ||
| 2868 | DAE.Exp exp; | ||
| 2869 | |||
| 2870 | case (DAE.ASUB(exp = DAE.CREF(componentRef = cref, ty = ety), sub = subs), env) | ||
| 2871 | algorithm | ||
| 2872 | 6 | cref := ComponentReference.subscriptCref(cref, subs); | |
| 2873 | 6 | exp := Expression.makeCrefExp(cref, ety); | |
| 2874 | then (exp, env); | ||
| 2875 | |||
| 2876 | case (DAE.TSUB(exp = DAE.TUPLE(exp::_), ix = 1), env) | ||
| 2877 | then (exp, env); | ||
| 2878 | |||
| 2879 | else (inExp,inEnv); | ||
| 2880 | end match; | ||
| 2881 | end optimizeExpTraverser; | ||
| 2882 | |||
| 2883 | annotation(__OpenModelica_Interface="frontend"); | ||
| 2884 | end CevalFunction; | ||
| 2885 |