OMCompiler/Compiler/FrontEnd/Static.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 Static | ||
| 37 | " file: Static.mo | ||
| 38 | package: Static | ||
| 39 | description: Static analysis of expressions | ||
| 40 | |||
| 41 | |||
| 42 | This module does static analysis on expressions. | ||
| 43 | The analyzed expressions are built using the | ||
| 44 | constructors in the Expression module from expressions defined in Absyn. | ||
| 45 | Also, a set of properties of the expressions is calculated during analysis. | ||
| 46 | Properties of expressions include type information and a boolean indicating if the | ||
| 47 | expression is constant or not. | ||
| 48 | If the expression is constant, the Ceval module is used to evaluate the expression | ||
| 49 | value. A value of an expression is described using the Values module. | ||
| 50 | |||
| 51 | The main function in this module is evalExp which takes an Absyn.Exp and transform it | ||
| 52 | into an DAE.Exp, while performing type checking and automatic type conversions, etc. | ||
| 53 | To determine types of builtin functions and operators, the module also contain an elaboration | ||
| 54 | handler for functions and operators. This function is called elabBuiltinHandler. | ||
| 55 | NOTE: These functions should only determine the type and properties of the builtin functions and | ||
| 56 | operators and not evaluate them. Constant evaluation is performed by the Ceval module. | ||
| 57 | The module also contain a function for deoverloading of operators, in the \'deoverload\' function. | ||
| 58 | It transforms operators like + to its specific form, ADD, ADD_ARR, etc. | ||
| 59 | |||
| 60 | Interactive function calls are also given their types by elabExp, which calls | ||
| 61 | elabCallInteractive. | ||
| 62 | |||
| 63 | Elaboration for functions involve checking the types of the arguments by filling slots of the | ||
| 64 | argument list with first positional and then named arguments to find a matching function. The | ||
| 65 | details of this mechanism can be found in the Modelica specification. | ||
| 66 | The elaboration also contain function deoverloading which will be added to Modelica in the future." | ||
| 67 | |||
| 68 | import Absyn; | ||
| 69 | import DAE; | ||
| 70 | import FCore; | ||
| 71 | import SCode; | ||
| 72 | import Values; | ||
| 73 | |||
| 74 | protected | ||
| 75 | |||
| 76 | import AbsynToSCode; | ||
| 77 | import AbsynUtil; | ||
| 78 | import FGraph; | ||
| 79 | import FNode; | ||
| 80 | import InstMeta; | ||
| 81 | import MetaUtil; | ||
| 82 | import Util; | ||
| 83 | import ValuesDump; | ||
| 84 | |||
| 85 | |||
| 86 | constant Integer SLOT_NOT_EVALUATED = 0; | ||
| 87 | constant Integer SLOT_EVALUATING = 1; | ||
| 88 | constant Integer SLOT_EVALUATED = 2; | ||
| 89 | |||
| 90 | uniontype Slot | ||
| 91 | record SLOT | ||
| 92 | DAE.FuncArg defaultArg "The slots default argument."; | ||
| 93 | Boolean slotFilled "True if the slot has been filled, otherwise false."; | ||
| 94 | Option<DAE.Exp> arg "The argument for the slot given by the function call."; | ||
| 95 | DAE.Dimensions dims "The dimensions of the slot."; | ||
| 96 | Integer idx "The index of the slot, 1 = first slot etc."; | ||
| 97 | Integer evalStatus; | ||
| 98 | end SLOT; | ||
| 99 | end Slot; | ||
| 100 | |||
| 101 | constant Option<tuple<DAE.Exp, DAE.Properties, DAE.Attributes>> BUILTIN_TIME = | ||
| 102 | SOME((DAE.CREF(DAE.CREF_IDENT("time", DAE.T_REAL_DEFAULT, {}), DAE.T_REAL_DEFAULT), | ||
| 103 | DAE.PROP(DAE.T_REAL_DEFAULT, DAE.C_VAR()), | ||
| 104 | DAE.dummyAttrInput)); | ||
| 105 | |||
| 106 | import Array; | ||
| 107 | import BackendInterface; | ||
| 108 | import BackendCevalInterface; | ||
| 109 | import Ceval; | ||
| 110 | import ClassInf; | ||
| 111 | import ComponentReference; | ||
| 112 | protected import ComponentReferenceBasics; | ||
| 113 | import Config; | ||
| 114 | import DAEUtil; | ||
| 115 | import Debug; | ||
| 116 | import Dump; | ||
| 117 | import Error; | ||
| 118 | import ErrorExt; | ||
| 119 | import Expression; | ||
| 120 | protected import ExpressionBasics; | ||
| 121 | import ExpressionDump; | ||
| 122 | import ExpressionSimplify; | ||
| 123 | import Flags; | ||
| 124 | import Global; | ||
| 125 | import Inline; | ||
| 126 | import Inst; | ||
| 127 | import InstFunction; | ||
| 128 | import InstTypes; | ||
| 129 | import InnerOuter; | ||
| 130 | import List; | ||
| 131 | import Lookup; | ||
| 132 | import Mutable; | ||
| 133 | import OperatorOverloading; | ||
| 134 | import Patternm; | ||
| 135 | import PrefixUtil; | ||
| 136 | import Print; | ||
| 137 | import SCodeDump; | ||
| 138 | import SCodeUtil; | ||
| 139 | import System; | ||
| 140 | import Types; | ||
| 141 | import ValuesUtil; | ||
| 142 | import VarTransform; | ||
| 143 | |||
| 144 | public function elabExpList "Expression elaboration of Absyn.Exp list, i.e. lists of expressions." | ||
| 145 | input FCore.Cache inCache; | ||
| 146 | input FCore.Graph inEnv; | ||
| 147 | input list<Absyn.Exp> inExpl; | ||
| 148 | input Boolean inImplicit; | ||
| 149 | input Boolean inDoVect; | ||
| 150 | input DAE.Prefix inPrefix; | ||
| 151 | input SourceInfo inInfo; | ||
| 152 | input DAE.Type inLastType = DAE.T_UNKNOWN_DEFAULT "The type of the last evaluated expression; used to speed up instantiation of enumeration :)"; | ||
| 153 | output FCore.Cache outCache = inCache; | ||
| 154 | output list<DAE.Exp> outExpl = {}; | ||
| 155 | output list<DAE.Properties> outProperties = {}; | ||
| 156 | protected | ||
| 157 | DAE.Exp exp; | ||
| 158 | DAE.Properties prop; | ||
| 159 | DAE.Type last_ty = inLastType; | ||
| 160 | Absyn.ComponentRef cr; | ||
| 161 | Absyn.Path path, path1, path2; | ||
| 162 | String name; | ||
| 163 | list<String> names; | ||
| 164 | Integer idx; | ||
| 165 | algorithm | ||
| 166 |
2/2✓ Branch 0 taken 234969 times.
✓ Branch 1 taken 61421 times.
|
296390 | for e in inExpl loop |
| 167 | try | ||
| 168 | // Hack to make enumeration arrays elaborate a _lot_ faster | ||
| 169 |
4/4✓ Branch 0 taken 223168 times.
✓ Branch 1 taken 11801 times.
✓ Branch 2 taken 11717 times.
✓ Branch 3 taken 84 times.
|
235013 | Absyn.CREF(cr as Absyn.CREF_FULLYQUALIFIED()) := e; |
| 170 |
2/2✓ Branch 0 taken 44 times.
✓ Branch 1 taken 40 times.
|
84 | DAE.T_ENUMERATION(path = path2, names = names) := last_ty; |
| 171 | 40 | path := AbsynUtil.crefToPath(cr); | |
| 172 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
|
40 | (path1, Absyn.IDENT(name)) := AbsynUtil.splitQualAndIdentPath(path); |
| 173 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
|
40 | true := AbsynUtil.pathEqual(path1, path2); |
| 174 | 40 | idx := List.position(name, names); | |
| 175 | 40 | exp := DAE.ENUM_LITERAL(path, idx); | |
| 176 | 40 | prop := DAE.PROP(last_ty, DAE.C_CONST()); | |
| 177 | else | ||
| 178 | 234929 | (outCache, exp, prop) := elabExpInExpression(outCache, inEnv, | |
| 179 | e, inImplicit, inDoVect, inPrefix, inInfo); | ||
| 180 | 234873 | last_ty := Types.getPropType(prop); | |
| 181 | end try; | ||
| 182 | |||
| 183 | 234913 | outExpl := exp :: outExpl; | |
| 184 | 234913 | outProperties := prop :: outProperties; | |
| 185 | end for; | ||
| 186 | |||
| 187 | 61421 | outExpl := listReverse(outExpl); | |
| 188 | 61421 | outProperties := listReverse(outProperties); | |
| 189 | end elabExpList; | ||
| 190 | |||
| 191 | protected function elabExpList_enum | ||
| 192 | input Absyn.Exp inExp; | ||
| 193 | input DAE.Type inLastType; | ||
| 194 | output Integer outIndex; | ||
| 195 | algorithm | ||
| 196 | outIndex := matchcontinue(inExp, inLastType) | ||
| 197 | local | ||
| 198 | Absyn.ComponentRef cr; | ||
| 199 | Absyn.Path path, path1, path2; | ||
| 200 | String name; | ||
| 201 | list<String> names; | ||
| 202 | |||
| 203 | case (Absyn.CREF(cr as Absyn.CREF_FULLYQUALIFIED()), | ||
| 204 | DAE.T_ENUMERATION(path = path2, names = names)) | ||
| 205 | algorithm | ||
| 206 | ✗ | path := AbsynUtil.crefToPath(cr); | |
| 207 | ✗ | (path1, Absyn.IDENT(name)) := AbsynUtil.splitQualAndIdentPath(path); | |
| 208 | ✗ | true := AbsynUtil.pathEqual(path1, path2); | |
| 209 | ✗ | then | |
| 210 | List.position(name, names); | ||
| 211 | |||
| 212 | else -1; | ||
| 213 | |||
| 214 | end matchcontinue; | ||
| 215 | end elabExpList_enum; | ||
| 216 | |||
| 217 | public function elabExpListList | ||
| 218 | "Expression elaboration of lists of lists of expressions. | ||
| 219 | Used in for instance matrices, etc." | ||
| 220 | input FCore.Cache inCache; | ||
| 221 | input FCore.Graph inEnv; | ||
| 222 | input list<list<Absyn.Exp>> inExpl; | ||
| 223 | input Boolean inImplicit; | ||
| 224 | input Boolean inDoVect; | ||
| 225 | input DAE.Prefix inPrefix; | ||
| 226 | input SourceInfo inInfo; | ||
| 227 | input DAE.Type inLastType = DAE.T_UNKNOWN_DEFAULT "The type of the last evaluated expression; used to speed up instantiation of enumerations :)"; | ||
| 228 | output FCore.Cache outCache = inCache; | ||
| 229 | output list<list<DAE.Exp>> outExpl = {}; | ||
| 230 | output list<list<DAE.Properties>> outProperties = {}; | ||
| 231 | protected | ||
| 232 | list<DAE.Exp> expl; | ||
| 233 | list<DAE.Properties> props; | ||
| 234 | DAE.Type last_ty = inLastType; | ||
| 235 | algorithm | ||
| 236 |
2/2✓ Branch 0 taken 1719 times.
✓ Branch 1 taken 645 times.
|
2364 | for lst in inExpl loop |
| 237 | 1719 | (outCache, expl, props) := elabExpList(outCache, inEnv, lst, | |
| 238 | inImplicit, inDoVect, inPrefix, inInfo, last_ty); | ||
| 239 | 1719 | outExpl := expl :: outExpl; | |
| 240 | 1719 | outProperties := props :: outProperties; | |
| 241 | 1719 | last_ty := Types.getPropType(listHead(props)); | |
| 242 | end for; | ||
| 243 | |||
| 244 | 645 | outExpl := listReverse(outExpl); | |
| 245 | 645 | outProperties := listReverse(outProperties); | |
| 246 | end elabExpListList; | ||
| 247 | |||
| 248 | protected function elabExpOptAndMatchType " | ||
| 249 | elabExp, but for Option<Absyn.Exp>,DAE.Type => Option<DAE.Exp>" | ||
| 250 | input FCore.Cache inCache; | ||
| 251 | input FCore.Graph inEnv; | ||
| 252 | input Option<Absyn.Exp> inExp; | ||
| 253 | input DAE.Type inDefaultType; | ||
| 254 | input Boolean inImplicit; | ||
| 255 | input Boolean inDoVect; | ||
| 256 | input DAE.Prefix inPrefix; | ||
| 257 | input SourceInfo inInfo; | ||
| 258 | output FCore.Cache outCache = inCache; | ||
| 259 | output Option<DAE.Exp> outExp; | ||
| 260 | output DAE.Properties outProperties; | ||
| 261 | protected | ||
| 262 | Absyn.Exp exp; | ||
| 263 | DAE.Exp dexp; | ||
| 264 | DAE.Properties prop; | ||
| 265 | algorithm | ||
| 266 | 1509 | outProperties := DAE.PROP(inDefaultType, DAE.C_CONST()); | |
| 267 | |||
| 268 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 1509 times.
✓ Branch 2 taken 332 times.
✓ Branch 3 taken 1177 times.
|
1509 | if isSome(inExp) then |
| 269 | 332 | SOME(exp) := inExp; | |
| 270 | 332 | (outCache, dexp, prop) := elabExpInExpression(outCache, inEnv, | |
| 271 | exp, inImplicit, inDoVect, inPrefix, inInfo); | ||
| 272 | 332 | (dexp, outProperties) := Types.matchProp(dexp, prop, outProperties, true); | |
| 273 | outExp := SOME(dexp); | ||
| 274 | else | ||
| 275 | outExp := NONE(); | ||
| 276 | end if; | ||
| 277 | end elabExpOptAndMatchType; | ||
| 278 | |||
| 279 | public function elabExp " | ||
| 280 | function: elabExp | ||
| 281 | Static analysis of expressions means finding out the properties of | ||
| 282 | the expression. These properties are described by the | ||
| 283 | DAE.Properties type, and include the type and the variability of the | ||
| 284 | expression. This function performs analysis, and returns an | ||
| 285 | DAE.Exp and the properties." | ||
| 286 | extends PartialElabExpFunc; | ||
| 287 | protected | ||
| 288 | Absyn.Exp e; | ||
| 289 | Integer num_errmsgs; | ||
| 290 | PartialElabExpFunc elabfunc; | ||
| 291 | algorithm | ||
| 292 | // Apply any rewrite rules we have, if any. | ||
| 293 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2357736 times.
|
2357736 | e := if BackendInterface.noRewriteRulesFrontEnd() then inExp else |
| 294 | BackendInterface.rewriteFrontEnd(inExp); | ||
| 295 | |||
| 296 | 2357736 | num_errmsgs := Error.getNumErrorMessages(); | |
| 297 | |||
| 298 | try | ||
| 299 | elabfunc := match e | ||
| 300 | case Absyn.END() | ||
| 301 | algorithm | ||
| 302 | ✗ | Error.addSourceMessage(Error.END_ILLEGAL_USE_ERROR, {}, inInfo); | |
| 303 | ✗ | then | |
| 304 | fail(); | ||
| 305 | |||
| 306 | case Absyn.CREF() then elabExp_Cref; | ||
| 307 | case Absyn.BINARY() then elabExp_Binary; | ||
| 308 | case Absyn.UNARY() then elabExp_Unary; | ||
| 309 | case Absyn.LBINARY() then elabExp_Binary; | ||
| 310 | case Absyn.LUNARY() then elabExp_LUnary; | ||
| 311 | case Absyn.RELATION() then elabExp_Binary; | ||
| 312 | case Absyn.IFEXP() then elabExp_If; | ||
| 313 | case Absyn.CALL() then elabExp_Call; | ||
| 314 | case Absyn.PARTEVALFUNCTION() then elabExp_PartEvalFunction; | ||
| 315 | case Absyn.TUPLE() then elabExp_Tuple; | ||
| 316 | case Absyn.RANGE() then elabExp_Range; | ||
| 317 | case Absyn.ARRAY() then elabExp_Array; | ||
| 318 | case Absyn.MATRIX() then elabExp_Matrix; | ||
| 319 | case Absyn.CODE() then elabExp_Code; | ||
| 320 | case Absyn.CONS() then elabExp_Cons; | ||
| 321 | case Absyn.LIST() then elabExp_List; | ||
| 322 | case Absyn.MATCHEXP() then Patternm.elabMatchExpression; | ||
| 323 | case Absyn.DOT() then elabExp_Dot; | ||
| 324 | case Absyn.EXPRESSIONCOMMENT() then elabExp_Comment; | ||
| 325 | case Absyn.UNITFUL_LITERAL() then elabExp_UnitfulLiteral; | ||
| 326 | else elabExp_BuiltinType; | ||
| 327 | end match; | ||
| 328 | |||
| 329 |
5/10✗ Branch 0 not taken.
✓ Branch 1 taken 2357736 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 7 taken 76179 times.
✓ Branch 8 taken 2281557 times.
✓ Branch 9 taken 1207340 times.
✓ Branch 10 taken 1150396 times.
|
3641255 | (outCache, outExp, outProperties) := |
| 330 | elabfunc(inCache, inEnv, e, inImplicit, inDoVect, inPrefix, inInfo); | ||
| 331 | else | ||
| 332 |
2/2✓ Branch 1 taken 4774 times.
✓ Branch 2 taken 1 time.
|
4775 | true := num_errmsgs == Error.getNumErrorMessages(); |
| 333 | 2 | Error.addSourceMessage(Error.GENERIC_ELAB_EXPRESSION, | |
| 334 | {Dump.printExpStr(e)}, inInfo); | ||
| 335 | 1 | fail(); | |
| 336 | end try; | ||
| 337 | end elabExp; | ||
| 338 | |||
| 339 | public partial function PartialElabExpFunc | ||
| 340 | input FCore.Cache inCache; | ||
| 341 | input FCore.Graph inEnv; | ||
| 342 | input Absyn.Exp inExp; | ||
| 343 | input Boolean inImplicit; | ||
| 344 | input Boolean inDoVect; | ||
| 345 | input DAE.Prefix inPrefix; | ||
| 346 | input SourceInfo inInfo; | ||
| 347 | output FCore.Cache outCache = inCache; | ||
| 348 | output DAE.Exp outExp; | ||
| 349 | output DAE.Properties outProperties; | ||
| 350 | end PartialElabExpFunc; | ||
| 351 | |||
| 352 | protected function elabExp_BuiltinType | ||
| 353 | extends PartialElabExpFunc; | ||
| 354 | algorithm | ||
| 355 | (outExp, outProperties) := match inExp | ||
| 356 | // The types below should contain the default values of the attributes of the builtin | ||
| 357 | // types. But since they are default, we can leave them out for now, unit=\"\" is not | ||
| 358 | // that interesting to find out. | ||
| 359 | case Absyn.INTEGER() | ||
| 360 | 380558 | then (DAE.ICONST(inExp.value), | |
| 361 | DAE.PROP(DAE.T_INTEGER_DEFAULT, DAE.C_CONST())); | ||
| 362 | |||
| 363 | case Absyn.REAL() | ||
| 364 | 414271 | then (DAE.RCONST(stringReal(inExp.value)), | |
| 365 | DAE.PROP(DAE.T_REAL_DEFAULT, DAE.C_CONST())); | ||
| 366 | |||
| 367 | case Absyn.STRING() | ||
| 368 | 595704 | then (DAE.SCONST(System.unescapedString(inExp.value)), | |
| 369 | DAE.PROP(DAE.T_STRING_DEFAULT, DAE.C_CONST())); | ||
| 370 | |||
| 371 | case Absyn.BOOL() | ||
| 372 | 56466 | then (DAE.BCONST(inExp.value), | |
| 373 | DAE.PROP(DAE.T_BOOL_DEFAULT, DAE.C_CONST())); | ||
| 374 | |||
| 375 | end match; | ||
| 376 | end elabExp_BuiltinType; | ||
| 377 | |||
| 378 | protected function elabExp_Cref | ||
| 379 | extends PartialElabExpFunc; | ||
| 380 | protected | ||
| 381 | Absyn.ComponentRef cr; | ||
| 382 | DAE.Type ty; | ||
| 383 | DAE.Const c; | ||
| 384 | algorithm | ||
| 385 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 397145 times.
|
397145 | Absyn.CREF(componentRef = cr) := inExp; |
| 386 |
3/4✗ Branch 1 not taken.
✓ Branch 2 taken 397145 times.
✓ Branch 3 taken 2914 times.
✓ Branch 4 taken 394231 times.
|
397145 | (outCache, SOME((outExp, outProperties, _))) := elabCref(inCache, inEnv, cr, |
| 387 | inImplicit, inDoVect, inPrefix, inInfo); | ||
| 388 | |||
| 389 | // BoschRexroth specifics, convert param to var. | ||
| 390 |
1/2✓ Branch 1 taken 394231 times.
✗ Branch 2 not taken.
|
394231 | if not Flags.getConfigBool(Flags.CEVAL_EQUATION) then |
| 391 | ✗ | DAE.PROP(ty, c) := outProperties; | |
| 392 | ✗ | outProperties := if Types.isParameter(c) then | |
| 393 | DAE.PROP(ty, DAE.C_VAR()) else outProperties; | ||
| 394 | end if; | ||
| 395 | end elabExp_Cref; | ||
| 396 | |||
| 397 | protected function elabExp_Binary | ||
| 398 | extends PartialElabExpFunc; | ||
| 399 | protected | ||
| 400 | Absyn.Exp e1, e2; | ||
| 401 | Absyn.Operator op; | ||
| 402 | DAE.Properties prop1, prop2; | ||
| 403 | DAE.Exp exp1, exp2; | ||
| 404 | algorithm | ||
| 405 | () := match inExp | ||
| 406 | case Absyn.BINARY(exp1 = e1, op = op, exp2 = e2) then (); | ||
| 407 | case Absyn.LBINARY(exp1 = e1, op = op, exp2 = e2) then (); | ||
| 408 | case Absyn.RELATION(exp1 = e1, op = op, exp2 = e2) then (); | ||
| 409 | end match; | ||
| 410 | |||
| 411 | 203518 | (outCache, exp1, prop1) := elabExpInExpression(inCache, inEnv, | |
| 412 | e1, inImplicit, inDoVect, inPrefix, inInfo); | ||
| 413 | 203515 | (outCache, exp2, prop2) := elabExpInExpression(outCache, inEnv, | |
| 414 | e2, inImplicit, inDoVect, inPrefix, inInfo); | ||
| 415 | 203515 | (outCache, outExp, outProperties) := OperatorOverloading.binary(outCache, | |
| 416 | inEnv, op, prop1, exp1, prop2, exp2, inExp, e1, e2, inImplicit, inPrefix, inInfo); | ||
| 417 | end elabExp_Binary; | ||
| 418 | |||
| 419 | protected function elabExp_Unary | ||
| 420 | extends PartialElabExpFunc; | ||
| 421 | protected | ||
| 422 | Absyn.Exp e; | ||
| 423 | Absyn.Operator op; | ||
| 424 | DAE.Type ty; | ||
| 425 | DAE.Const c; | ||
| 426 | algorithm | ||
| 427 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 95911 times.
|
95911 | Absyn.UNARY(op = op, exp = e) := inExp; |
| 428 | |||
| 429 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 95911 times.
|
95911 | (outCache, outExp, outProperties as DAE.PROP(ty, c)) := |
| 430 | elabExpInExpression(inCache, inEnv, e, inImplicit, inDoVect, inPrefix, inInfo); | ||
| 431 | |||
| 432 |
3/4✓ Branch 1 taken 131 times.
✓ Branch 2 taken 95780 times.
✓ Branch 5 taken 131 times.
✗ Branch 6 not taken.
|
95911 | if not (valueEq(op, Absyn.UPLUS()) and |
| 433 | Types.isIntegerOrRealOrSubTypeOfEither(Types.arrayElementType(ty))) | ||
| 434 | then | ||
| 435 | 95780 | (outCache, outExp, outProperties) := OperatorOverloading.unary(outCache, inEnv, | |
| 436 | op, outProperties, outExp, inExp, e, inImplicit, inPrefix, inInfo); | ||
| 437 | end if; | ||
| 438 | end elabExp_Unary; | ||
| 439 | |||
| 440 | protected function elabExp_LUnary | ||
| 441 | extends PartialElabExpFunc; | ||
| 442 | protected | ||
| 443 | Absyn.Exp e; | ||
| 444 | Absyn.Operator op; | ||
| 445 | algorithm | ||
| 446 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1744 times.
|
1744 | Absyn.LUNARY(op = op, exp = e) := inExp; |
| 447 | 1744 | (outCache, outExp, outProperties) := elabExpInExpression(outCache, inEnv, e, | |
| 448 | inImplicit, inDoVect, inPrefix, inInfo); | ||
| 449 | 1744 | (outCache, outExp, outProperties) := OperatorOverloading.unary(outCache, | |
| 450 | inEnv, op, outProperties, outExp, inExp, e, inImplicit, inPrefix, inInfo); | ||
| 451 | end elabExp_LUnary; | ||
| 452 | |||
| 453 | protected function elabExp_If | ||
| 454 | "Elaborates an if-expression. If one of the branches can not be elaborated and | ||
| 455 | the condition is parameter or constant; it is evaluated and the correct branch is selected. | ||
| 456 | This is a dirty hack to make MSL CombiTable models work! | ||
| 457 | Note: Because of this, the function has to rollback or delete an ErrorExt checkpoint." | ||
| 458 | extends PartialElabExpFunc; | ||
| 459 | protected | ||
| 460 | Absyn.Exp cond_e, true_e, false_e; | ||
| 461 | DAE.Exp cond_exp, true_exp, false_exp; | ||
| 462 | DAE.Properties cond_prop, true_prop, false_prop; | ||
| 463 | FCore.Cache cache; | ||
| 464 | Boolean b; | ||
| 465 | algorithm | ||
| 466 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8299 times.
|
8299 | Absyn.IFEXP(ifExp = cond_e, trueBranch = true_e, elseBranch = false_e) := |
| 467 | AbsynUtil.canonIfExp(inExp); | ||
| 468 | 8299 | (cache, cond_exp, cond_prop) := elabExpInExpression(inCache, | |
| 469 | inEnv, cond_e, inImplicit, inDoVect, inPrefix, inInfo); | ||
| 470 | |||
| 471 | (outCache, outExp, outProperties) := matchcontinue() | ||
| 472 | case () | ||
| 473 | algorithm | ||
| 474 | 8299 | ErrorExt.setCheckpoint("Static.elabExp:IFEXP"); | |
| 475 | 8299 | (outCache, true_exp, true_prop) := elabExpInExpression(cache, | |
| 476 | inEnv, true_e, inImplicit, inDoVect, inPrefix, inInfo); | ||
| 477 | 8299 | (outCache, false_exp, false_prop) := elabExpInExpression(outCache, | |
| 478 | inEnv, false_e, inImplicit, inDoVect, inPrefix, inInfo); | ||
| 479 | 8298 | (outCache, outExp, outProperties) := makeIfExp(outCache, inEnv, cond_exp, | |
| 480 | cond_prop, true_exp, true_prop, false_exp, false_prop, inImplicit, | ||
| 481 | inPrefix, inInfo); | ||
| 482 | 8296 | ErrorExt.delCheckpoint("Static.elabExp:IFEXP"); | |
| 483 | 8296 | then | |
| 484 | (outCache, outExp, outProperties); | ||
| 485 | |||
| 486 | case () | ||
| 487 | algorithm | ||
| 488 | 3 | ErrorExt.setCheckpoint("Static.elabExp:IFEXP:HACK") "Extra rollback point so we get the regular error message only once if the hack fails"; | |
| 489 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
3 | true := Types.isParameterOrConstant(Types.propAllConst(cond_prop)); |
| 490 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
3 | (outCache, Values.BOOL(b)) := Ceval.ceval(cache, inEnv, cond_exp, |
| 491 | inImplicit, Absyn.MSG(inInfo)); | ||
| 492 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | (outCache, outExp, outProperties) := elabExpInExpression(outCache, inEnv, |
| 493 | if b then true_e else false_e, inImplicit, inDoVect, inPrefix, inInfo); | ||
| 494 | 3 | ErrorExt.delCheckpoint("Static.elabExp:IFEXP:HACK"); | |
| 495 | 3 | ErrorExt.rollBack("Static.elabExp:IFEXP"); | |
| 496 | 3 | then | |
| 497 | (outCache, outExp, outProperties); | ||
| 498 | |||
| 499 | else | ||
| 500 | algorithm | ||
| 501 | ✗ | ErrorExt.rollBack("Static.elabExp:IFEXP:HACK"); | |
| 502 | ✗ | ErrorExt.delCheckpoint("Static.elabExp:IFEXP"); | |
| 503 | ✗ | then | |
| 504 | fail(); | ||
| 505 | |||
| 506 | end matchcontinue; | ||
| 507 | end elabExp_If; | ||
| 508 | |||
| 509 | protected function elabExp_Call | ||
| 510 | extends PartialElabExpFunc; | ||
| 511 | protected | ||
| 512 | Absyn.ComponentRef func_name; | ||
| 513 | Absyn.FunctionArgs args; | ||
| 514 | list<Absyn.Path> type_vars; | ||
| 515 | algorithm | ||
| 516 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 96601 times.
|
96601 | Absyn.CALL(function_ = func_name, functionArgs = args, typeVars = type_vars) := inExp; |
| 517 | |||
| 518 | () := match args | ||
| 519 | case Absyn.FUNCTIONARGS() | ||
| 520 | algorithm | ||
| 521 | 95854 | (outCache, outExp, outProperties) := elabCall(inCache, inEnv, | |
| 522 | func_name, args.args, args.argNames, type_vars, inImplicit, inPrefix, inInfo); | ||
| 523 | 94082 | outExp := ExpressionSimplify.simplify1(outExp); | |
| 524 | then | ||
| 525 | (); | ||
| 526 | |||
| 527 | case Absyn.FOR_ITER_FARG() | ||
| 528 | algorithm | ||
| 529 | 747 | (outCache, outExp, outProperties) := elabCallReduction(inCache, | |
| 530 | inEnv, func_name, args.exp, args.iterType, args.iterators, inImplicit, | ||
| 531 | inDoVect, inPrefix, inInfo); | ||
| 532 | then | ||
| 533 | (); | ||
| 534 | end match; | ||
| 535 | end elabExp_Call; | ||
| 536 | |||
| 537 | protected function elabExp_Dot | ||
| 538 | extends PartialElabExpFunc; | ||
| 539 | algorithm | ||
| 540 | (outExp, outProperties) := match inExp | ||
| 541 | local | ||
| 542 | String s; | ||
| 543 | DAE.Type ty; | ||
| 544 | case Absyn.DOT() | ||
| 545 | algorithm | ||
| 546 | s := match inExp.index | ||
| 547 | case Absyn.CREF(Absyn.CREF_IDENT(name=s)) then s; | ||
| 548 | else | ||
| 549 | algorithm | ||
| 550 | ✗ | Error.addSourceMessage(Error.COMPILER_ERROR, {"Dot operator is only allowed when indexing using a single simple name, got: " + Dump.printExpStr(inExp.index)}, inInfo); | |
| 551 | ✗ | then fail(); | |
| 552 | end match; | ||
| 553 | 4 | (outCache,outExp,outProperties) := elabExp(inCache,inEnv,inExp.exp,inImplicit,inDoVect, inPrefix, inInfo); | |
| 554 | 4 | ty := Types.getPropType(outProperties); | |
| 555 | () := match ty | ||
| 556 | local | ||
| 557 | list<String> names; | ||
| 558 | Integer i; | ||
| 559 | case DAE.T_TUPLE(names=SOME(names)) | ||
| 560 | algorithm | ||
| 561 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
4 | if not listMember(s, names) then |
| 562 | ✗ | Error.addSourceMessage(Error.COMPILER_ERROR, {"Dot operator could not find " + s + " in " + TypesDump.unparseType(ty)}, inInfo); | |
| 563 | ✗ | fail(); | |
| 564 | end if; | ||
| 565 | 4 | i := List.position(s, names); | |
| 566 | 4 | outExp := DAE.TSUB(outExp, i, listGet(ty.types,i)); | |
| 567 | 4 | outProperties := DAE.PROP(listGet(ty.types,i), Types.propAllConst(outProperties)); | |
| 568 | then (); | ||
| 569 | else | ||
| 570 | algorithm | ||
| 571 | ✗ | Error.addSourceMessage(Error.COMPILER_ERROR, {"Dot operator is only allowed when the expression returns a named tuple. Got expression: " + ExpressionBasics.printExpStr(outExp) + " with type " + TypesDump.unparseType(ty)}, inInfo); | |
| 572 | ✗ | then fail(); | |
| 573 | end match; | ||
| 574 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | then (outExp, outProperties); |
| 575 | |||
| 576 | end match; | ||
| 577 | end elabExp_Dot; | ||
| 578 | |||
| 579 | protected function elabExp_Comment | ||
| 580 | extends PartialElabExpFunc; | ||
| 581 | protected | ||
| 582 | Absyn.Exp exp; | ||
| 583 | algorithm | ||
| 584 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 155 times.
|
155 | Absyn.EXPRESSIONCOMMENT(exp=exp) := inExp; |
| 585 | 155 | (outCache, outExp, outProperties) := elabExp(inCache,inEnv,exp,inImplicit,inDoVect, inPrefix, inInfo); | |
| 586 | end elabExp_Comment; | ||
| 587 | |||
| 588 | protected function elabExp_UnitfulLiteral | ||
| 589 | extends PartialElabExpFunc; | ||
| 590 | protected | ||
| 591 | Absyn.Exp exp; | ||
| 592 | algorithm | ||
| 593 | ✗ | Absyn.UNITFUL_LITERAL(value=exp) := inExp; | |
| 594 | ✗ | (outCache, outExp, outProperties) := elabExp(inCache,inEnv,exp,inImplicit,inDoVect, inPrefix, inInfo); | |
| 595 | end elabExp_UnitfulLiteral; | ||
| 596 | |||
| 597 | protected function elabExp_PartEvalFunction | ||
| 598 | "turns an Absyn.PARTEVALFUNCTION into an DAE.PARTEVALFUNCTION" | ||
| 599 | extends PartialElabExpFunc; | ||
| 600 | protected | ||
| 601 | Absyn.ComponentRef cref; | ||
| 602 | list<Absyn.Exp> pos_args; | ||
| 603 | list<Absyn.NamedArg> named_args; | ||
| 604 | Absyn.Path path; | ||
| 605 | DAE.Type ty, tty, tty2; | ||
| 606 | list<DAE.Exp> args; | ||
| 607 | list<DAE.Const> consts; | ||
| 608 | list<Slot> slots; | ||
| 609 | DAE.Const c; | ||
| 610 | algorithm | ||
| 611 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 35 times.
|
35 | Absyn.PARTEVALFUNCTION(cref, Absyn.FUNCTIONARGS(pos_args, named_args)) := inExp; |
| 612 | |||
| 613 |
2/4✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 35 times.
|
35 | if listEmpty(pos_args) and listEmpty(named_args) then |
| 614 | ✗ | (outCache, outExp, outProperties) := elabExpInExpression(inCache, | |
| 615 | inEnv, Absyn.CREF(cref), inImplicit, inDoVect, inPrefix, inInfo); | ||
| 616 | else | ||
| 617 | 35 | path := AbsynUtil.crefToPath(cref); | |
| 618 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 35 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 35 times.
|
35 | (outCache, {tty}) := Lookup.lookupFunctionsInEnv(inCache, inEnv, path, inInfo); |
| 619 | 35 | tty := Types.makeFunctionPolymorphicReference(tty); | |
| 620 | 35 | (outCache, args, consts, _, tty, _, slots) := elabTypes(outCache, inEnv, pos_args, | |
| 621 | named_args, {}, {tty}, true, true, inImplicit, | ||
| 622 | inPrefix, inInfo); | ||
| 623 |
2/2✓ Branch 1 taken 31 times.
✓ Branch 2 taken 4 times.
|
35 | if not Types.isFunctionPointer(tty) then |
| 624 | 31 | (outCache, path) := Inst.makeFullyQualified(outCache, inEnv, path); | |
| 625 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
|
31 | (outCache, Util.SUCCESS()) := instantiateDaeFunction(outCache, inEnv, |
| 626 | path, false, NONE(), true); | ||
| 627 | end if; | ||
| 628 | 35 | tty2 := stripExtraArgsFromType(slots, tty); | |
| 629 | 35 | tty2 := Types.makeFunctionPolymorphicReference(tty2); | |
| 630 | 35 | ty := Types.simplifyType(tty2); | |
| 631 | 35 | tty := Types.simplifyType(tty); | |
| 632 | 35 | c := List.fold(consts, Types.constAnd, DAE.C_CONST()); | |
| 633 | 35 | outExp := DAE.PARTEVALFUNCTION(path, args, ty, tty); | |
| 634 | 35 | outProperties := DAE.PROP(tty2, c); | |
| 635 | end if; | ||
| 636 | end elabExp_PartEvalFunction; | ||
| 637 | |||
| 638 | protected function elabExp_Tuple | ||
| 639 | extends PartialElabExpFunc; | ||
| 640 | algorithm | ||
| 641 | 47208 | (outCache, outExp, outProperties) := elabExp_Tuple_LHS_RHS(inCache, inEnv, inExp, inImplicit, inDoVect, inPrefix, inInfo); | |
| 642 | end elabExp_Tuple; | ||
| 643 | |||
| 644 | protected function elabExp_Tuple_LHS_RHS | ||
| 645 | extends PartialElabExpFunc; | ||
| 646 | input Boolean isLhs=false; | ||
| 647 | protected | ||
| 648 | list<Absyn.Exp> el; | ||
| 649 | list<DAE.Exp> expl; | ||
| 650 | list<DAE.Properties> props; | ||
| 651 | list<DAE.Type> types; | ||
| 652 | list<DAE.TupleConst> consts; | ||
| 653 | algorithm | ||
| 654 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 47293 times.
|
47293 | Absyn.TUPLE(expressions = el) := inExp; |
| 655 |
2/2✓ Branch 1 taken 44143 times.
✓ Branch 2 taken 3150 times.
|
47293 | if listLength(el) == 1 then |
| 656 | 44143 | (outCache, outExp, outProperties) := elabExp(outCache, inEnv, listGet(el,1), inImplicit, inDoVect, inPrefix, inInfo); | |
| 657 | 44143 | return; | |
| 658 | end if; | ||
| 659 | 3150 | (outCache, expl, props) := elabTuple(outCache, inEnv, el, inImplicit, | |
| 660 | inDoVect, inPrefix, inInfo, isLhs); | ||
| 661 | 3149 | (types, consts) := splitProps(props); | |
| 662 | 3149 | (outExp, outProperties) := fixTupleMetaModelica(expl, types, consts); | |
| 663 | end elabExp_Tuple_LHS_RHS; | ||
| 664 | |||
| 665 | public function elabExpLHS "Special check for tuples, which only occur on the LHS" | ||
| 666 | extends PartialElabExpFunc; | ||
| 667 | algorithm | ||
| 668 | (outCache, outExp, outProperties) := match inExp | ||
| 669 | case Absyn.TUPLE() | ||
| 670 | algorithm | ||
| 671 | 85 | (outCache, outExp, outProperties) := elabExp_Tuple_LHS_RHS(inCache, inEnv, inExp, inImplicit, inDoVect, inPrefix, inInfo, isLhs=true); | |
| 672 | then (outCache, outExp, outProperties); | ||
| 673 | else | ||
| 674 | algorithm | ||
| 675 | 20314 | (outCache, outExp, outProperties) := elabExp(inCache, inEnv, inExp, inImplicit, inDoVect, inPrefix, inInfo); | |
| 676 | then (outCache, outExp, outProperties); | ||
| 677 | end match; | ||
| 678 | end elabExpLHS; | ||
| 679 | |||
| 680 | protected function elabExp_Range | ||
| 681 | "Elaborates a range expression on the form start:stop or start:step:stop." | ||
| 682 | extends PartialElabExpFunc; | ||
| 683 | protected | ||
| 684 | Absyn.Exp start, step, stop; | ||
| 685 | Option<Absyn.Exp> ostep; | ||
| 686 | DAE.Exp start_exp, step_exp, stop_exp; | ||
| 687 | Option<DAE.Exp> ostep_exp = NONE(); | ||
| 688 | DAE.Type start_ty, step_ty, stop_ty, ety, ty; | ||
| 689 | Option<DAE.Type> ostep_ty = NONE(); | ||
| 690 | DAE.Const start_c, step_c, stop_c, c; | ||
| 691 | algorithm | ||
| 692 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1947 times.
|
1947 | Absyn.RANGE(start = start, step = ostep, stop = stop) := inExp; |
| 693 | |||
| 694 | // Elaborate start and stop of the range. | ||
| 695 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1947 times.
|
1947 | (outCache, start_exp, DAE.PROP(start_ty, start_c)) := |
| 696 | elabExpInExpression(inCache, inEnv, start, inImplicit, inDoVect, inPrefix, inInfo); | ||
| 697 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1947 times.
|
1947 | (outCache, stop_exp, DAE.PROP(stop_ty, stop_c)) := |
| 698 | elabExpInExpression(outCache, inEnv, stop, inImplicit, inDoVect, inPrefix, inInfo); | ||
| 699 | 1947 | c := Types.constAnd(start_c, stop_c); | |
| 700 | |||
| 701 | // If step was given, elaborate it too. | ||
| 702 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 1947 times.
✓ Branch 2 taken 38 times.
✓ Branch 3 taken 1909 times.
|
1947 | if isSome(ostep) then |
| 703 | 38 | SOME(step) := ostep; | |
| 704 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
|
38 | (outCache, step_exp, DAE.PROP(step_ty, step_c)) := |
| 705 | elabExpInExpression(outCache, inEnv, step, inImplicit, inDoVect, inPrefix, inInfo); | ||
| 706 | 38 | ostep_exp := SOME(step_exp); | |
| 707 | ostep_ty := SOME(step_ty); | ||
| 708 | 38 | c := Types.constAnd(c, step_c); | |
| 709 | end if; | ||
| 710 | |||
| 711 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1947 times.
|
1947 | if Types.isBoxedType(start_ty) then |
| 712 | ✗ | (start_exp, start_ty) := Types.matchType(start_exp, start_ty, Types.unboxedType(start_ty), true); | |
| 713 | end if; | ||
| 714 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1946 times.
|
1947 | if Types.isBoxedType(stop_ty) then |
| 715 | 1 | (stop_exp, stop_ty) := Types.matchType(stop_exp, stop_ty, Types.unboxedType(stop_ty), true); | |
| 716 | end if; | ||
| 717 | |||
| 718 | 1947 | (start_exp, ostep_exp, stop_exp, ety) := | |
| 719 | deoverloadRange(start_exp, start_ty, ostep_exp, ostep_ty, stop_exp, stop_ty, inInfo); | ||
| 720 | 1947 | (outCache, ty) := elabRangeType(outCache, inEnv, start_exp, ostep_exp, | |
| 721 | stop_exp, start_ty, ety, c, inImplicit); | ||
| 722 | |||
| 723 | 1947 | outExp := DAE.RANGE(ty, start_exp, ostep_exp, stop_exp); | |
| 724 | 1947 | outProperties := DAE.PROP(ty, c); | |
| 725 | end elabExp_Range; | ||
| 726 | |||
| 727 | protected function elabExp_Array | ||
| 728 | extends PartialElabExpFunc; | ||
| 729 | protected | ||
| 730 | list<Absyn.Exp> es; | ||
| 731 | list<DAE.Exp> expl; | ||
| 732 | list<DAE.Properties> props; | ||
| 733 | DAE.Type ty, arr_ty; | ||
| 734 | DAE.Const c; | ||
| 735 | DAE.Exp exp; | ||
| 736 | algorithm | ||
| 737 | (outExp, outProperties) := matchcontinue inExp | ||
| 738 | // Part of the MetaModelica extension. This eliminates elabArray failed | ||
| 739 | // failtraces when using the empty list. sjoelund | ||
| 740 | case Absyn.ARRAY({}) guard(Config.acceptMetaModelicaGrammar()) | ||
| 741 | then (DAE.LIST({}), DAE.PROP(DAE.T_METALIST_DEFAULT, DAE.C_CONST())); | ||
| 742 | |||
| 743 | // array expressions, e.g. {1,2,3} | ||
| 744 | case Absyn.ARRAY(arrayExp = es) | ||
| 745 | algorithm | ||
| 746 | 51459 | (outCache, expl, props) := elabExpList(inCache, inEnv, es, inImplicit, | |
| 747 | inDoVect, inPrefix, inInfo); | ||
| 748 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 51407 times.
|
51407 | (expl, DAE.PROP(ty, c)) := elabArray(expl, props, inPrefix, inInfo); // type-checking the array |
| 749 | 102814 | arr_ty := DAE.T_ARRAY(ty, {DAE.DIM_INTEGER(listLength(expl))}); | |
| 750 |
2/2✓ Branch 1 taken 250 times.
✓ Branch 2 taken 51157 times.
|
51657 | exp := DAE.ARRAY(Types.simplifyType(arr_ty), not Types.isArray(ty), expl); |
| 751 | 51407 | InstMeta.checkArrayType(ty); | |
| 752 | 50666 | exp := elabMatrixToMatrixExp(exp); | |
| 753 | 50666 | then | |
| 754 | (exp, DAE.PROP(arr_ty, c)); | ||
| 755 | |||
| 756 | // Part of the MetaModelica extension. KS | ||
| 757 | case Absyn.ARRAY(arrayExp = es) guard(Config.acceptMetaModelicaGrammar()) | ||
| 758 | algorithm | ||
| 759 | 741 | (outCache, outExp, outProperties) := elabExpInExpression(inCache, | |
| 760 | inEnv, Absyn.LIST(es), inImplicit, inDoVect, inPrefix, inInfo); | ||
| 761 | 741 | then | |
| 762 | (outExp, outProperties); | ||
| 763 | |||
| 764 | end matchcontinue; | ||
| 765 | end elabExp_Array; | ||
| 766 | |||
| 767 | protected function elabExp_Matrix | ||
| 768 | extends PartialElabExpFunc; | ||
| 769 | protected | ||
| 770 | list<list<Absyn.Exp>> ess; | ||
| 771 | list<list<DAE.Exp>> dess; | ||
| 772 | list<list<DAE.Properties>> props; | ||
| 773 | list<DAE.Type> tys; | ||
| 774 | Integer nmax; | ||
| 775 | Boolean have_real; | ||
| 776 | DAE.Type ty; | ||
| 777 | DAE.Const c; | ||
| 778 | DAE.Dimension dim1, dim2; | ||
| 779 | algorithm | ||
| 780 | // Elaborate the individual expressions. | ||
| 781 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 645 times.
|
645 | Absyn.MATRIX(matrix = ess) := inExp; |
| 782 | 645 | (outCache, dess, props) := elabExpListList(inCache, inEnv, ess, inImplicit, | |
| 783 | inDoVect, inPrefix, inInfo); | ||
| 784 | |||
| 785 | // Check if any of the expressions is of Real type. | ||
| 786 |
8/8✓ Branch 0 taken 1719 times.
✓ Branch 1 taken 645 times.
✓ Branch 2 taken 1719 times.
✓ Branch 3 taken 645 times.
✓ Branch 4 taken 5443 times.
✓ Branch 5 taken 1719 times.
✓ Branch 6 taken 5443 times.
✓ Branch 7 taken 1719 times.
|
7807 | tys := listAppend(list(Types.getPropType(p) for p in pl) for pl in props); |
| 787 | 645 | nmax := matrixConstrMaxDim(tys); | |
| 788 | 645 | have_real := Types.containReal(tys); | |
| 789 | |||
| 790 | // If we have any Real expressions, cast any Integer expressions to Real. | ||
| 791 |
2/2✓ Branch 0 taken 437 times.
✓ Branch 1 taken 208 times.
|
645 | if have_real then |
| 792 | 437 | (dess, props) := List.threadMapList_2(dess, props, elabExp_Matrix_realCast); | |
| 793 | end if; | ||
| 794 | |||
| 795 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 645 times.
|
645 | (outCache, outExp, DAE.PROP(ty, c), dim1, dim2) := elabMatrixSemi(outCache, |
| 796 | inEnv, dess, props, inImplicit, have_real, nmax, inDoVect, inPrefix, inInfo); | ||
| 797 | |||
| 798 | 645 | outExp := elabMatrixToMatrixExp(outExp); | |
| 799 | 645 | ty := Types.unliftArray(Types.unliftArray(ty)); // All elts promoted to matrix, therefore unlifting. | |
| 800 | 645 | ty := DAE.T_ARRAY(ty, {dim2}); | |
| 801 | 645 | ty := DAE.T_ARRAY(ty, {dim1}); | |
| 802 | 645 | outProperties := DAE.PROP(ty, c); | |
| 803 | end elabExp_Matrix; | ||
| 804 | |||
| 805 | protected function elabExp_Matrix_realCast | ||
| 806 | "Casts an expression and property to Real if it's current type is Integer." | ||
| 807 | input DAE.Exp inExp; | ||
| 808 | input DAE.Properties inProperties; | ||
| 809 | output DAE.Exp outExp; | ||
| 810 | output DAE.Properties outProperties; | ||
| 811 | protected | ||
| 812 | DAE.Type ty; | ||
| 813 | algorithm | ||
| 814 | 2749 | ty := Types.getPropType(inProperties); | |
| 815 | |||
| 816 |
2/2✓ Branch 1 taken 482 times.
✓ Branch 2 taken 2267 times.
|
2749 | if Types.isInteger(ty) then |
| 817 | 482 | ty := Types.setArrayElementType(ty, DAE.T_REAL_DEFAULT); | |
| 818 | 482 | outProperties := Types.setPropType(inProperties, ty); | |
| 819 | 482 | ty := Types.simplifyType(ty); | |
| 820 | 482 | outExp := ExpressionSimplify.simplify1(DAE.CAST(ty, inExp)); | |
| 821 | else | ||
| 822 | outExp := inExp; | ||
| 823 | outProperties := inProperties; | ||
| 824 | end if; | ||
| 825 | end elabExp_Matrix_realCast; | ||
| 826 | |||
| 827 | protected function elabExp_Code | ||
| 828 | extends PartialElabExpFunc; | ||
| 829 | protected | ||
| 830 | DAE.Type ty, ty2; | ||
| 831 | Absyn.CodeNode cn; | ||
| 832 | algorithm | ||
| 833 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 955 times.
|
955 | Absyn.CODE(code = cn) := inExp; |
| 834 | 955 | ty := elabCodeType(cn); | |
| 835 | 955 | ty2 := Types.simplifyType(ty); | |
| 836 | 955 | outExp := DAE.CODE(cn, ty2); | |
| 837 | 955 | outProperties := DAE.PROP(ty, DAE.C_CONST()); | |
| 838 | end elabExp_Code; | ||
| 839 | |||
| 840 | protected function elabExp_Cons | ||
| 841 | extends PartialElabExpFunc; | ||
| 842 | protected | ||
| 843 | Absyn.Exp e1, e2; | ||
| 844 | DAE.Exp exp1, exp2; | ||
| 845 | DAE.Properties prop1; | ||
| 846 | DAE.Type ty, ty1, ty2; | ||
| 847 | DAE.Const c1, c2; | ||
| 848 | String exp_str, ty1_str, ty2_str; | ||
| 849 | algorithm | ||
| 850 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 314 times.
|
314 | Absyn.CONS(e1, e2) := inExp; |
| 851 |
3/6✗ Branch 1 not taken.
✓ Branch 2 taken 314 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 314 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 314 times.
|
314 | {e1, e2} := MetaUtil.transformArrayNodesToListNodes({e1, e2}); |
| 852 | |||
| 853 | // Elaborate both sides of the cons expression. | ||
| 854 | 314 | (outCache, exp1, prop1) := elabExpInExpression(outCache, inEnv, e1, | |
| 855 | inImplicit, inDoVect, inPrefix, inInfo); | ||
| 856 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 314 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 314 times.
|
314 | (outCache, exp2, DAE.PROP(DAE.T_METALIST(ty = ty2), c2)) := elabExpInExpression( |
| 857 | outCache, inEnv, e2, inImplicit, inDoVect, inPrefix, inInfo); | ||
| 858 | |||
| 859 | try | ||
| 860 | // Replace all metarecords with uniontypes with. | ||
| 861 | 314 | ty1 := Types.getUniontypeIfMetarecordReplaceAllSubtypes(Types.getPropType(prop1)); | |
| 862 | 314 | ty2 := Types.getUniontypeIfMetarecordReplaceAllSubtypes(ty2); | |
| 863 | 314 | c1 := Types.propAllConst(prop1); | |
| 864 | 314 | ty := Types.getUniontypeIfMetarecordReplaceAllSubtypes( | |
| 865 | Types.superType(Types.boxIfUnboxedType(ty1), Types.boxIfUnboxedType(ty2))); | ||
| 866 | |||
| 867 | // Make sure the operands have correct types. | ||
| 868 | 314 | exp1 := Types.matchType(exp1, ty1, ty, true); | |
| 869 | 314 | ty := DAE.T_METALIST(ty); | |
| 870 | 314 | exp2 := Types.matchType(exp2, ty, DAE.T_METALIST(ty2), true); | |
| 871 | |||
| 872 | 314 | outExp := DAE.CONS(exp1, exp2); | |
| 873 | 314 | outProperties := DAE.PROP(ty, Types.constAnd(c1, c2)); | |
| 874 | else | ||
| 875 | ✗ | exp_str := Dump.printExpStr(inExp); | |
| 876 | ✗ | ty1_str := TypesDump.unparseType(Types.getPropType(prop1)); | |
| 877 | ✗ | ty2_str := TypesDump.unparseType(ty2); | |
| 878 | ✗ | Error.addSourceMessage(Error.META_CONS_TYPE_MATCH, {exp_str, ty1_str, ty2_str}, inInfo); | |
| 879 | ✗ | fail(); | |
| 880 | end try; | ||
| 881 | end elabExp_Cons; | ||
| 882 | |||
| 883 | protected function elabExp_List | ||
| 884 | extends PartialElabExpFunc; | ||
| 885 | protected | ||
| 886 | list<Absyn.Exp> es; | ||
| 887 | list<DAE.Exp> expl; | ||
| 888 | list<DAE.Properties> props; | ||
| 889 | list<DAE.Type> types; | ||
| 890 | list<DAE.Const> consts; | ||
| 891 | DAE.Const c; | ||
| 892 | DAE.Type ty; | ||
| 893 | algorithm | ||
| 894 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 777 times.
|
777 | Absyn.LIST(exps = es) := inExp; |
| 895 | |||
| 896 | // The Absyn.LIST() node is used for list expressions that are transformed | ||
| 897 | // from Absyn.ARRAY() | ||
| 898 |
2/2✓ Branch 0 taken 754 times.
✓ Branch 1 taken 23 times.
|
777 | if listEmpty(es) then |
| 899 | outExp := DAE.LIST({}); | ||
| 900 | outProperties := DAE.PROP(DAE.T_METALIST_DEFAULT, DAE.C_CONST()); | ||
| 901 | else | ||
| 902 | 754 | (outCache, expl, props) := elabExpList(inCache, inEnv, es, inImplicit, | |
| 903 | inDoVect, inPrefix, inInfo); | ||
| 904 |
4/4✓ Branch 0 taken 3293 times.
✓ Branch 1 taken 754 times.
✓ Branch 2 taken 3293 times.
✓ Branch 3 taken 754 times.
|
4047 | types := list(Types.getPropType(p) for p in props); |
| 905 | 754 | consts := Types.getConstList(props); | |
| 906 | 754 | c := List.fold(consts, Types.constAnd, DAE.C_CONST()); | |
| 907 | 754 | ty := Types.boxIfUnboxedType(List.reduce(types, Types.superType)); | |
| 908 | 754 | expl := Types.matchTypes(expl, types, ty, true); | |
| 909 | |||
| 910 | 754 | outExp := DAE.LIST(expl); | |
| 911 | 754 | outProperties := DAE.PROP(DAE.T_METALIST(ty), c); | |
| 912 | end if; | ||
| 913 | end elabExp_List; | ||
| 914 | |||
| 915 | public function elabExpInExpression "Like elabExp but casts PROP_TUPLE to a PROP" | ||
| 916 | input FCore.Cache inCache; | ||
| 917 | input FCore.Graph inEnv; | ||
| 918 | input Absyn.Exp inExp; | ||
| 919 | input Boolean inImplicit; | ||
| 920 | input Boolean performVectorization; | ||
| 921 | input DAE.Prefix inPrefix; | ||
| 922 | input SourceInfo info; | ||
| 923 | output FCore.Cache outCache; | ||
| 924 | output DAE.Exp outExp; | ||
| 925 | output DAE.Properties outProperties; | ||
| 926 | algorithm | ||
| 927 | 1065358 | (outCache,outExp,outProperties) := elabExp(inCache,inEnv,inExp,inImplicit,performVectorization,inPrefix,info); | |
| 928 | 1062269 | (outExp,outProperties) := elabExpInExpression2(outExp,outProperties); | |
| 929 | end elabExpInExpression; | ||
| 930 | |||
| 931 | protected function elabExpInExpression2 | ||
| 932 | input DAE.Exp inExp; | ||
| 933 | input DAE.Properties inProperties; | ||
| 934 | output DAE.Exp outExp; | ||
| 935 | output DAE.Properties outProperties; | ||
| 936 | algorithm | ||
| 937 | (outExp,outProperties) := match inProperties | ||
| 938 | local | ||
| 939 | DAE.Type ty; | ||
| 940 | DAE.Const c; | ||
| 941 | case DAE.PROP_TUPLE(type_ = DAE.T_TUPLE(types = ty :: _), tupleConst = DAE.TUPLE_CONST(tupleConstLst = DAE.SINGLE_CONST(const = c) :: _)) | ||
| 942 | 16 | then (DAE.TSUB(inExp, 1, ty), DAE.PROP(ty,c)); | |
| 943 | else (inExp,inProperties); | ||
| 944 | end match; | ||
| 945 | end elabExpInExpression2; | ||
| 946 | |||
| 947 | public function checkAssignmentToInput | ||
| 948 | input Absyn.Exp inExp; | ||
| 949 | input DAE.Attributes inAttributes; | ||
| 950 | input FCore.Graph inEnv; | ||
| 951 | input Boolean inAllowTopLevelInputs; | ||
| 952 | input SourceInfo inInfo; | ||
| 953 | algorithm | ||
| 954 | // If we don't allow top level inputs and we're in a function scope and not | ||
| 955 | // using parmodelica, check for assignment to input. | ||
| 956 |
4/6✗ Branch 0 not taken.
✓ Branch 1 taken 74679 times.
✓ Branch 3 taken 1727 times.
✓ Branch 4 taken 72952 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 72952 times.
|
74679 | if not inAllowTopLevelInputs and FGraph.inFunctionScope(inEnv) and |
| 957 | not Config.acceptParModelicaGrammar() then | ||
| 958 | 72952 | checkAssignmentToInput2(inExp, inAttributes, inInfo); | |
| 959 | end if; | ||
| 960 | end checkAssignmentToInput; | ||
| 961 | |||
| 962 | protected function checkAssignmentToInput2 | ||
| 963 | input Absyn.Exp inExp; | ||
| 964 | input DAE.Attributes inAttributes; | ||
| 965 | input SourceInfo inInfo; | ||
| 966 | algorithm | ||
| 967 | () := match(inExp, inAttributes) | ||
| 968 | local | ||
| 969 | Absyn.ComponentRef cr; | ||
| 970 | String cr_str; | ||
| 971 | |||
| 972 | case (Absyn.CREF(cr), DAE.ATTR(direction = Absyn.INPUT())) | ||
| 973 | algorithm | ||
| 974 | 12 | cr_str := Dump.printComponentRefStr(cr); | |
| 975 | 12 | Error.addSourceMessage(Error.ASSIGN_READONLY_ERROR, | |
| 976 | {"input", cr_str}, inInfo); | ||
| 977 | 12 | then | |
| 978 | fail(); | ||
| 979 | |||
| 980 | else (); | ||
| 981 | |||
| 982 | end match; | ||
| 983 | end checkAssignmentToInput2; | ||
| 984 | |||
| 985 | public function checkAssignmentToInputs | ||
| 986 | input list<Absyn.Exp> inExpCrefs; | ||
| 987 | input list<DAE.Attributes> inAttributes; | ||
| 988 | input FCore.Graph inEnv; | ||
| 989 | input SourceInfo inInfo; | ||
| 990 | algorithm | ||
| 991 |
2/2✓ Branch 1 taken 22 times.
✓ Branch 2 taken 884 times.
|
906 | if FGraph.inFunctionScope(inEnv) then |
| 992 | 884 | List.threadMap1_0(inExpCrefs, inAttributes, checkAssignmentToInput2, inInfo); | |
| 993 | end if; | ||
| 994 | end checkAssignmentToInputs; | ||
| 995 | |||
| 996 | public function elabExpCrefNoEvalList | ||
| 997 | "elaborates a list of expressions that are only component references." | ||
| 998 | input FCore.Cache inCache; | ||
| 999 | input FCore.Graph inEnv; | ||
| 1000 | input list<Absyn.Exp> inExpl; | ||
| 1001 | input Boolean inImplicit; | ||
| 1002 | input Boolean inDoVect; | ||
| 1003 | input DAE.Prefix inPrefix; | ||
| 1004 | input SourceInfo inInfo; | ||
| 1005 | output FCore.Cache outCache = inCache; | ||
| 1006 | output list<DAE.Exp> outExpl = {}; | ||
| 1007 | output list<DAE.Properties> outProperties = {}; | ||
| 1008 | output list<DAE.Attributes> outAttributes = {}; | ||
| 1009 | protected | ||
| 1010 | Integer num_err = Error.getNumErrorMessages(); | ||
| 1011 | DAE.Exp exp; | ||
| 1012 | DAE.Properties prop; | ||
| 1013 | list<DAE.Properties> props = {}; | ||
| 1014 | DAE.Attributes attr; | ||
| 1015 | Absyn.ComponentRef cr; | ||
| 1016 | DAE.Type ty; | ||
| 1017 | DAE.Const c; | ||
| 1018 | algorithm | ||
| 1019 |
2/2✓ Branch 0 taken 1917 times.
✓ Branch 1 taken 906 times.
|
2823 | for e in inExpl loop |
| 1020 | try | ||
| 1021 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1917 times.
|
1917 | Absyn.CREF(componentRef = cr) := e; |
| 1022 | 1917 | (outCache, exp, prop, attr) := | |
| 1023 | elabCrefNoEval(outCache, inEnv, cr, inImplicit, inDoVect, inPrefix, inInfo); | ||
| 1024 | 1917 | outExpl := exp :: outExpl; | |
| 1025 | 1917 | outAttributes := attr :: outAttributes; | |
| 1026 | 1917 | props := prop :: props; | |
| 1027 | else | ||
| 1028 | ✗ | true := num_err == Error.getNumErrorMessages(); | |
| 1029 | ✗ | Error.addSourceMessage(Error.GENERIC_ELAB_EXPRESSION, | |
| 1030 | {Dump.printExpStr(e)}, inInfo); | ||
| 1031 | end try; | ||
| 1032 | end for; | ||
| 1033 | |||
| 1034 | // BoschRexroth specifics, convert all params to vars. | ||
| 1035 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 906 times.
|
906 | if not Flags.getConfigBool(Flags.CEVAL_EQUATION) then |
| 1036 | ✗ | for p in props loop | |
| 1037 | ✗ | DAE.PROP(ty, c) := p; | |
| 1038 | ✗ | p := if Types.isParameter(c) then DAE.PROP(ty, DAE.C_VAR()) else p; | |
| 1039 | outProperties := p :: outProperties; | ||
| 1040 | end for; | ||
| 1041 | else | ||
| 1042 | 906 | outProperties := listReverse(props); | |
| 1043 | end if; | ||
| 1044 | |||
| 1045 | 906 | outExpl := listReverse(outExpl); | |
| 1046 | 906 | outAttributes := listReverse(outAttributes); | |
| 1047 | end elabExpCrefNoEvalList; | ||
| 1048 | |||
| 1049 | // Part of MetaModelica extension | ||
| 1050 | public function elabListExp "Function that elaborates the MetaModelica list type, | ||
| 1051 | for instance list<Integer>. | ||
| 1052 | This is used by Inst.mo when handling a var := {...} statement" | ||
| 1053 | input FCore.Cache inCache; | ||
| 1054 | input FCore.Graph inEnv; | ||
| 1055 | input list<Absyn.Exp> inExpList; | ||
| 1056 | input DAE.Properties inProp; | ||
| 1057 | input Boolean inImplicit; | ||
| 1058 | input Boolean inDoVect; | ||
| 1059 | input DAE.Prefix inPrefix; | ||
| 1060 | input SourceInfo inInfo; | ||
| 1061 | output FCore.Cache outCache; | ||
| 1062 | output DAE.Exp outExp; | ||
| 1063 | output DAE.Properties outProperties; | ||
| 1064 | algorithm | ||
| 1065 | (outCache, outExp, outProperties) := matchcontinue inExpList | ||
| 1066 | local | ||
| 1067 | list<DAE.Exp> expl; | ||
| 1068 | list<DAE.Properties> props; | ||
| 1069 | list<DAE.Type> types; | ||
| 1070 | DAE.Const c; | ||
| 1071 | DAE.Type ty; | ||
| 1072 | |||
| 1073 | case {} then (inCache, DAE.LIST({}), inProp); | ||
| 1074 | |||
| 1075 | case _ | ||
| 1076 | algorithm | ||
| 1077 | ✗ | DAE.PROP(DAE.T_METALIST(), c) := inProp; | |
| 1078 | ✗ | (outCache, expl, props) := elabExpList(inCache, inEnv, | |
| 1079 | inExpList, inImplicit, inDoVect, inPrefix, inInfo); | ||
| 1080 | ✗ | types := list(Types.getPropType(p) for p in props); | |
| 1081 | ✗ | (expl, ty) := Types.listMatchSuperType(expl, types, true); | |
| 1082 | ✗ | outProperties := DAE.PROP(DAE.T_METALIST(ty), c); | |
| 1083 | ✗ | then | |
| 1084 | (outCache, DAE.LIST(expl), outProperties); | ||
| 1085 | |||
| 1086 | else | ||
| 1087 | algorithm | ||
| 1088 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 1089 | ✗ | Debug.traceln("- Static.elabListExp failed, non-matching args in list constructor?"); | |
| 1090 | ✗ | then | |
| 1091 | fail(); | ||
| 1092 | end matchcontinue; | ||
| 1093 | end elabListExp; | ||
| 1094 | |||
| 1095 | /* ------------------------------- */ | ||
| 1096 | |||
| 1097 | public function fromEquationsToAlgAssignments " Converts equations to algorithm assignments. | ||
| 1098 | Matchcontinue expressions may contain statements that you won't find | ||
| 1099 | in a normal equation section. For instance: | ||
| 1100 | |||
| 1101 | case(...) | ||
| 1102 | local | ||
| 1103 | algorithm | ||
| 1104 | (var1,_,MYREC(...)) = func(...); | ||
| 1105 | fail(); | ||
| 1106 | then 1;" | ||
| 1107 | input Absyn.ClassPart cp; | ||
| 1108 | output list<Absyn.AlgorithmItem> algsOut; | ||
| 1109 | algorithm | ||
| 1110 | algsOut := match cp | ||
| 1111 | local | ||
| 1112 | list<Absyn.EquationItem> rest; | ||
| 1113 | list<Absyn.AlgorithmItem> alg; | ||
| 1114 | String str; | ||
| 1115 | |||
| 1116 | case Absyn.ALGORITHMS(alg) then alg; | ||
| 1117 | 2558 | case Absyn.EQUATIONS(rest) then fromEquationsToAlgAssignmentsWork(rest); | |
| 1118 | else | ||
| 1119 | algorithm | ||
| 1120 | ✗ | str := Dump.unparseClassPart(cp); | |
| 1121 | ✗ | Error.addInternalError("Static.fromEquationsToAlgAssignments: Unknown classPart in match expression:\n" + str, sourceInfo()); | |
| 1122 | ✗ | then | |
| 1123 | fail(); | ||
| 1124 | end match; | ||
| 1125 | end fromEquationsToAlgAssignments; | ||
| 1126 | |||
| 1127 | protected function fromEquationsToAlgAssignmentsWork | ||
| 1128 | "Converts equations to algorithm assignments. | ||
| 1129 | Matchcontinue expressions may contain statements that you won't find | ||
| 1130 | in a normal equation section. For instance: | ||
| 1131 | |||
| 1132 | case(...) | ||
| 1133 | algorithm | ||
| 1134 | (var1, _, MYREC(...)) = func(...); | ||
| 1135 | fail(); | ||
| 1136 | then | ||
| 1137 | 1;" | ||
| 1138 | input list<Absyn.EquationItem> eqsIn; | ||
| 1139 | output list<Absyn.AlgorithmItem> algsOut = {}; | ||
| 1140 | algorithm | ||
| 1141 |
2/2✓ Branch 0 taken 55 times.
✓ Branch 1 taken 2562 times.
|
2617 | for ei in eqsIn loop |
| 1142 | () := match ei | ||
| 1143 | local | ||
| 1144 | Absyn.Equation eq; | ||
| 1145 | Option<Absyn.Comment> comment; | ||
| 1146 | SourceInfo info; | ||
| 1147 | list<Absyn.AlgorithmItem> algs; | ||
| 1148 | |||
| 1149 | case Absyn.EQUATIONITEM(equation_ = eq, comment = comment, info = info) | ||
| 1150 | algorithm | ||
| 1151 | 53 | algs := fromEquationToAlgAssignment(eq, comment, info); | |
| 1152 | 53 | algsOut := listAppend(algs, algsOut); | |
| 1153 | then | ||
| 1154 | (); | ||
| 1155 | |||
| 1156 | case Absyn.EQUATIONITEMCOMMENT() then (); | ||
| 1157 | end match; | ||
| 1158 | end for; | ||
| 1159 | |||
| 1160 | 2562 | algsOut := listReverse(algsOut); | |
| 1161 | end fromEquationsToAlgAssignmentsWork; | ||
| 1162 | |||
| 1163 | protected function fromEquationBranchesToAlgBranches | ||
| 1164 | "Converts equations to algorithm assignments." | ||
| 1165 | input list<tuple<Absyn.Exp,list<Absyn.EquationItem>>> eqsIn; | ||
| 1166 | output list<tuple<Absyn.Exp,list<Absyn.AlgorithmItem>>> algsOut = {}; | ||
| 1167 | protected | ||
| 1168 | Absyn.Exp e; | ||
| 1169 | list<Absyn.EquationItem> eqs; | ||
| 1170 | list<Absyn.AlgorithmItem> algs; | ||
| 1171 | algorithm | ||
| 1172 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | for branch in eqsIn loop |
| 1173 | ✗ | (e, eqs) := branch; | |
| 1174 | ✗ | algs := fromEquationsToAlgAssignmentsWork(eqs); | |
| 1175 | ✗ | algsOut := (e, algs) :: algsOut; | |
| 1176 | end for; | ||
| 1177 | |||
| 1178 | 2 | algsOut := listReverse(algsOut); | |
| 1179 | end fromEquationBranchesToAlgBranches; | ||
| 1180 | |||
| 1181 | protected function fromEquationToAlgAssignment "function: fromEquationToAlgAssignment" | ||
| 1182 | input Absyn.Equation eq; | ||
| 1183 | input Option<Absyn.Comment> comment; | ||
| 1184 | input SourceInfo info; | ||
| 1185 | output list<Absyn.AlgorithmItem> algStatement; | ||
| 1186 | algorithm | ||
| 1187 | algStatement := matchcontinue eq | ||
| 1188 | local | ||
| 1189 | String str,strLeft,strRight; | ||
| 1190 | Absyn.Exp left,right,e; | ||
| 1191 | Absyn.AlgorithmItem algItem,algItem1,algItem2; | ||
| 1192 | Absyn.Equation eq2; | ||
| 1193 | Option<Absyn.Comment> comment2; | ||
| 1194 | SourceInfo info2; | ||
| 1195 | Absyn.AlgorithmItem res; | ||
| 1196 | Absyn.ComponentRef cref; | ||
| 1197 | Absyn.FunctionArgs fargs; | ||
| 1198 | list<Absyn.AlgorithmItem> algs, algTrueItems, algElseItems; | ||
| 1199 | list<tuple<Absyn.Exp,list<Absyn.AlgorithmItem>>> algBranches; | ||
| 1200 | list<Absyn.EquationItem> eqTrueItems, eqElseItems; | ||
| 1201 | list<tuple<Absyn.Exp,list<Absyn.EquationItem>>> eqBranches; | ||
| 1202 | |||
| 1203 | case Absyn.EQ_EQUALS(Absyn.CREF(Absyn.CREF_IDENT(strLeft,{})),Absyn.CREF(Absyn.CREF_IDENT(strRight,{}))) | ||
| 1204 | algorithm | ||
| 1205 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
|
3 | true := strLeft == strRight; |
| 1206 | // match x case x then ... produces equation x = x; we save a bit of time by removing it here :) | ||
| 1207 | then {}; | ||
| 1208 | |||
| 1209 | // The syntax n>=0 = true; is also used | ||
| 1210 | case Absyn.EQ_EQUALS(left,right) | ||
| 1211 | algorithm | ||
| 1212 |
1/4✓ Branch 1 taken 29 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
29 | Absyn.BOOL(true) := AbsynUtil.stripCommentExpressions(right); |
| 1213 | ✗ | failure(Absyn.CREF(_) := left); // If lhs is a CREF, it should be an assignment | |
| 1214 | ✗ | algItem1 := Absyn.ALGORITHMITEM(Absyn.ALG_NORETCALL(Absyn.CREF_IDENT("fail",{}),Absyn.FUNCTIONARGS({},{})),comment,info); | |
| 1215 | ✗ | algItem2 := Absyn.ALGORITHMITEM(Absyn.ALG_IF(Absyn.LUNARY(Absyn.NOT(),left),{algItem1},{},{}),comment,info); | |
| 1216 | then {algItem2}; | ||
| 1217 | |||
| 1218 | case Absyn.EQ_EQUALS(left,Absyn.BOOL(false)) | ||
| 1219 | algorithm | ||
| 1220 | ✗ | failure(Absyn.CREF(_) := left); // If lhs is a CREF, it should be an assignment | |
| 1221 | ✗ | algItem1 := Absyn.ALGORITHMITEM(Absyn.ALG_NORETCALL(Absyn.CREF_IDENT("fail",{}),Absyn.FUNCTIONARGS({},{})),comment,info); | |
| 1222 | ✗ | algItem2 := Absyn.ALGORITHMITEM(Absyn.ALG_IF(left,{algItem1},{},{}),comment,info); | |
| 1223 | then {algItem2}; | ||
| 1224 | |||
| 1225 | case Absyn.EQ_PDE() | ||
| 1226 | algorithm | ||
| 1227 | // fail("PDE in Static.fromEquationToAlgAssignment() not handled"); | ||
| 1228 | then fail(); | ||
| 1229 | |||
| 1230 | case Absyn.EQ_NORETCALL(Absyn.CREF_IDENT("fail",_),_) | ||
| 1231 | algorithm | ||
| 1232 | 3 | algItem := Absyn.ALGORITHMITEM(Absyn.ALG_NORETCALL(Absyn.CREF_IDENT("fail",{}),Absyn.FUNCTIONARGS({},{})),comment,info); | |
| 1233 | then {algItem}; | ||
| 1234 | |||
| 1235 | case Absyn.EQ_NORETCALL(cref,fargs) | ||
| 1236 | algorithm | ||
| 1237 | 19 | algItem := Absyn.ALGORITHMITEM(Absyn.ALG_NORETCALL(cref,fargs),comment,info); | |
| 1238 | then {algItem}; | ||
| 1239 | |||
| 1240 | case Absyn.EQ_EQUALS(left,right) | ||
| 1241 | algorithm | ||
| 1242 | 29 | algItem := Absyn.ALGORITHMITEM(Absyn.ALG_ASSIGN(left,right),comment,info); | |
| 1243 | then {algItem}; | ||
| 1244 | |||
| 1245 | case Absyn.EQ_FAILURE(Absyn.EQUATIONITEM(eq2,comment2,info2)) | ||
| 1246 | algorithm | ||
| 1247 | 2 | algs := fromEquationToAlgAssignment(eq2,comment2,info2); | |
| 1248 | 2 | res := Absyn.ALGORITHMITEM(Absyn.ALG_FAILURE(algs),comment,info); | |
| 1249 | then {res}; | ||
| 1250 | |||
| 1251 | case Absyn.EQ_IF(ifExp = e, equationTrueItems = eqTrueItems, elseIfBranches = eqBranches, equationElseItems = eqElseItems) | ||
| 1252 | algorithm | ||
| 1253 | 2 | algTrueItems := fromEquationsToAlgAssignmentsWork(eqTrueItems); | |
| 1254 | 2 | algElseItems := fromEquationsToAlgAssignmentsWork(eqElseItems); | |
| 1255 | 2 | algBranches := fromEquationBranchesToAlgBranches(eqBranches); | |
| 1256 | 2 | res := Absyn.ALGORITHMITEM(Absyn.ALG_IF(e, algTrueItems, algBranches, algElseItems),comment,info); | |
| 1257 | then {res}; | ||
| 1258 | |||
| 1259 | else | ||
| 1260 | algorithm | ||
| 1261 | ✗ | str := Dump.equationName(eq); | |
| 1262 | ✗ | Error.addSourceMessage(Error.META_MATCH_EQUATION_FORBIDDEN, {str}, info); | |
| 1263 | ✗ | then fail(); | |
| 1264 | end matchcontinue; | ||
| 1265 | end fromEquationToAlgAssignment; | ||
| 1266 | |||
| 1267 | protected function elabMatrixToMatrixExp | ||
| 1268 | "Convert an 2-dimensional array expression to a matrix expression." | ||
| 1269 | input DAE.Exp inExp; | ||
| 1270 | output DAE.Exp outExp; | ||
| 1271 | algorithm | ||
| 1272 | outExp := matchcontinue inExp | ||
| 1273 | local | ||
| 1274 | list<list<DAE.Exp>> mexpl; | ||
| 1275 | DAE.Type a; | ||
| 1276 | Integer d1; | ||
| 1277 | list<DAE.Exp> expl; | ||
| 1278 | |||
| 1279 | // Convert a 2-dimensional array to a matrix. | ||
| 1280 | case DAE.ARRAY(ty = a as DAE.T_ARRAY(dims = _ :: _ :: {}), array = expl) | ||
| 1281 | algorithm | ||
| 1282 | 1957 | mexpl := List.map(expl, Expression.arrayContent); | |
| 1283 | 1954 | d1 := listLength(mexpl); | |
| 1284 |
2/2✓ Branch 3 taken 24 times.
✓ Branch 4 taken 1930 times.
|
1954 | true := Expression.typeBuiltin(Expression.unliftArray(Expression.unliftArray(a))); |
| 1285 | 1930 | then | |
| 1286 | DAE.MATRIX(a, d1, mexpl); | ||
| 1287 | |||
| 1288 | // if fails, skip conversion, use generic array expression as is. | ||
| 1289 | else inExp; | ||
| 1290 | end matchcontinue; | ||
| 1291 | end elabMatrixToMatrixExp; | ||
| 1292 | |||
| 1293 | protected function matrixConstrMaxDim | ||
| 1294 | "Helper function to elabExp (MATRIX). | ||
| 1295 | Determines the maximum dimension of the array arguments to the matrix | ||
| 1296 | constructor as. | ||
| 1297 | max(2, ndims(A), ndims(B), ndims(C),..) for matrix constructor arguments | ||
| 1298 | A, B, C, ..." | ||
| 1299 | input list<DAE.Type> inTypes; | ||
| 1300 | output Integer outMaxDim = 2; | ||
| 1301 | algorithm | ||
| 1302 |
2/2✓ Branch 0 taken 5443 times.
✓ Branch 1 taken 645 times.
|
6088 | for ty in inTypes loop |
| 1303 | 5443 | outMaxDim := max(Types.numberOfDimensions(ty), outMaxDim); | |
| 1304 | end for; | ||
| 1305 | end matrixConstrMaxDim; | ||
| 1306 | |||
| 1307 | protected function elabCallReduction | ||
| 1308 | "This function elaborates reduction expressions that look like function | ||
| 1309 | calls. For example an array constructor." | ||
| 1310 | input FCore.Cache inCache; | ||
| 1311 | input FCore.Graph inEnv; | ||
| 1312 | input Absyn.ComponentRef inReductionFn; | ||
| 1313 | input Absyn.Exp inReductionExp; | ||
| 1314 | input Absyn.ReductionIterType inIterType; | ||
| 1315 | input Absyn.ForIterators inIterators; | ||
| 1316 | input Boolean inImplicit; | ||
| 1317 | input Boolean inDoVect; | ||
| 1318 | input DAE.Prefix inPrefix; | ||
| 1319 | input SourceInfo inInfo; | ||
| 1320 | output FCore.Cache outCache; | ||
| 1321 | output DAE.Exp outExp; | ||
| 1322 | output DAE.Properties outProperties; | ||
| 1323 | protected | ||
| 1324 | FCore.Graph env, fold_env; | ||
| 1325 | list<DAE.ReductionIterator> reduction_iters; | ||
| 1326 | list<DAE.Dimension> dims; | ||
| 1327 | DAE.Const iter_const, exp_const, c; | ||
| 1328 | Boolean has_guard_exp; | ||
| 1329 | DAE.Exp exp; | ||
| 1330 | Option<Absyn.Exp> afold_exp; | ||
| 1331 | Option<DAE.Exp> fold_exp; | ||
| 1332 | DAE.Type exp_ty, res_ty; | ||
| 1333 | Absyn.Path fn; | ||
| 1334 | Option<Values.Value> v; | ||
| 1335 | String fold_id, res_id; | ||
| 1336 | algorithm | ||
| 1337 | try | ||
| 1338 | 747 | env := FGraph.openScope(inEnv, SCode.NOT_ENCAPSULATED(), | |
| 1339 | FCore.forIterScopeName, NONE()); | ||
| 1340 | |||
| 1341 | // Elaborate the iterators. | ||
| 1342 | 747 | (outCache, env, reduction_iters, dims, iter_const, has_guard_exp) := | |
| 1343 | elabCallReductionIterators(inCache, env, inIterators, | ||
| 1344 | inReductionExp, inImplicit, inDoVect, inPrefix, inInfo); | ||
| 1345 | 745 | dims := fixDimsIterType(inIterType, dims); | |
| 1346 | |||
| 1347 | // Elaborate the expression. | ||
| 1348 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 745 times.
|
745 | (outCache, exp, DAE.PROP(exp_ty, exp_const)) := |
| 1349 | elabExpInExpression(outCache, env, inReductionExp, inImplicit, | ||
| 1350 | inDoVect, inPrefix, inInfo); | ||
| 1351 | |||
| 1352 | // Figure out the type of the reduction. | ||
| 1353 | 745 | c := Types.constAnd(exp_const, iter_const); | |
| 1354 | fn := match inReductionFn | ||
| 1355 | case Absyn.CREF_IDENT("$array",{}) then Absyn.IDENT("array"); | ||
| 1356 | 436 | else AbsynUtil.crefToPath(inReductionFn); | |
| 1357 | end match; | ||
| 1358 | 745 | (outCache, exp, exp_ty, res_ty, v, fn) := reductionType(outCache, inEnv, fn, | |
| 1359 | exp, exp_ty, Types.unboxedType(exp_ty), dims, has_guard_exp, inInfo); | ||
| 1360 | 745 | outProperties := DAE.PROP(exp_ty, c); | |
| 1361 | |||
| 1362 | // Construct the reduction expression. | ||
| 1363 | 745 | fold_id := Util.getTempVariableIndex(); | |
| 1364 | 745 | res_id := Util.getTempVariableIndex(); | |
| 1365 | 745 | (fold_env, afold_exp) := makeReductionFoldExp(env, fn, exp_ty, res_ty, fold_id, res_id); | |
| 1366 | 745 | (outCache, fold_exp, _) := elabExpOptAndMatchType(outCache, fold_env, | |
| 1367 | afold_exp, res_ty, inImplicit, inDoVect, inPrefix, inInfo); | ||
| 1368 | |||
| 1369 | 745 | outExp := DAE.REDUCTION( | |
| 1370 | DAE.REDUCTIONINFO(fn, inIterType, exp_ty, v, fold_id, res_id, fold_exp), | ||
| 1371 | exp, | ||
| 1372 | reduction_iters); | ||
| 1373 | else | ||
| 1374 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | if listLength(inIterators) > 1 then |
| 1375 | ✗ | Error.addSourceMessage(Error.INTERNAL_ERROR, {"Reductions using multiple iterators is not yet implemented. Try rewriting the expression using nested reductions (e.g. array(i+j for i, j) => array(array(i+j for i) for j)."}, inInfo); | |
| 1376 | else | ||
| 1377 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | true := Flags.isSet(Flags.FAILTRACE); |
| 1378 | ✗ | Debug.traceln("Static.elabCallReduction - failed!"); | |
| 1379 | end if; | ||
| 1380 | ✗ | fail(); | |
| 1381 | end try; | ||
| 1382 | end elabCallReduction; | ||
| 1383 | |||
| 1384 | protected function fixDimsIterType | ||
| 1385 | input Absyn.ReductionIterType iterType; | ||
| 1386 | input list<DAE.Dimension> dims; | ||
| 1387 | output list<DAE.Dimension> outDims; | ||
| 1388 | algorithm | ||
| 1389 | outDims := match iterType | ||
| 1390 | case Absyn.COMBINE() then dims; | ||
| 1391 | |||
| 1392 | // TODO: Get the best dimension (if several, choose the one that is integer | ||
| 1393 | // constant; we do run-time checks to assert they are all equal) | ||
| 1394 | 8 | else {listHead(dims)}; | |
| 1395 | end match; | ||
| 1396 | end fixDimsIterType; | ||
| 1397 | |||
| 1398 | protected function elabCallReductionIterators | ||
| 1399 | input FCore.Cache inCache; | ||
| 1400 | input FCore.Graph inEnv; | ||
| 1401 | input Absyn.ForIterators inIterators; | ||
| 1402 | input Absyn.Exp inReductionExp; | ||
| 1403 | input Boolean inImpl; | ||
| 1404 | input Boolean inDoVect; | ||
| 1405 | input DAE.Prefix inPrefix; | ||
| 1406 | input SourceInfo inInfo; | ||
| 1407 | output FCore.Cache outCache = inCache; | ||
| 1408 | output FCore.Graph outIteratorsEnv = inEnv; | ||
| 1409 | output list<DAE.ReductionIterator> outIterators = {}; | ||
| 1410 | output list<DAE.Dimension> outDims = {}; | ||
| 1411 | output DAE.Const outConst = DAE.C_CONST(); | ||
| 1412 | output Boolean outHasGuard = false; | ||
| 1413 | protected | ||
| 1414 | String iter_name; | ||
| 1415 | Absyn.Exp aiter_exp; | ||
| 1416 | Option<Absyn.Exp> oaguard_exp, oaiter_exp; | ||
| 1417 | DAE.Exp iter_exp; | ||
| 1418 | Option<DAE.Exp> guard_exp; | ||
| 1419 | DAE.Type full_iter_ty, iter_ty; | ||
| 1420 | DAE.Const iter_const, guard_const, c; | ||
| 1421 | DAE.Dimension dim; | ||
| 1422 | FCore.Graph env; | ||
| 1423 | algorithm | ||
| 1424 |
2/2✓ Branch 0 taken 766 times.
✓ Branch 1 taken 745 times.
|
1511 | for iter in inIterators loop |
| 1425 | 766 | Absyn.ITERATOR(iter_name, oaguard_exp, oaiter_exp) := iter; | |
| 1426 | |||
| 1427 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 766 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 753 times.
|
766 | if isSome(oaiter_exp) then |
| 1428 | // An explicit iteration range, elaborate it. | ||
| 1429 | 753 | SOME(aiter_exp) := oaiter_exp; | |
| 1430 | |||
| 1431 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 753 times.
|
753 | (outCache, iter_exp, DAE.PROP(full_iter_ty, iter_const)) := |
| 1432 | elabExpInExpression(outCache, inEnv, aiter_exp, inImpl, inDoVect, inPrefix, inInfo); | ||
| 1433 | else | ||
| 1434 | // An implicit iteration range, try to deduce the range based on how the | ||
| 1435 | // iterator is used. | ||
| 1436 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
|
13 | (iter_exp, DAE.PROP(full_iter_ty, iter_const), outCache) := deduceIterationRange(iter_name, |
| 1437 | AbsynUtil.findIteratorIndexedCrefs(inReductionExp, iter_name), inEnv, outCache, inInfo); | ||
| 1438 | end if; | ||
| 1439 | |||
| 1440 | // We need to evaluate the iterator because the rest of the compiler is stupid. | ||
| 1441 |
2/2✓ Branch 1 taken 449 times.
✓ Branch 2 taken 315 times.
|
764 | c := if FGraph.inFunctionScope(inEnv) then iter_const else DAE.C_CONST(); |
| 1442 | 764 | (outCache, iter_exp, _) := | |
| 1443 | Ceval.cevalIfConstant(outCache, inEnv, iter_exp, DAE.PROP(full_iter_ty, c), inImpl, inInfo); | ||
| 1444 | |||
| 1445 | 764 | (iter_ty, dim) := Types.unliftArrayOrList(full_iter_ty); | |
| 1446 | // The iterator needs to be added to two different environments, to hide the | ||
| 1447 | // iterators from the different guard-expressions. | ||
| 1448 | 764 | env := FGraph.addForIterator(inEnv, iter_name, iter_ty, DAE.UNBOUND(), | |
| 1449 | SCode.CONST(), SOME(iter_const)); | ||
| 1450 | 764 | outIteratorsEnv := FGraph.addForIterator(outIteratorsEnv, iter_name, iter_ty, DAE.UNBOUND(), | |
| 1451 | SCode.CONST(), SOME(iter_const)); | ||
| 1452 | |||
| 1453 | // Elaborate the guard expression. | ||
| 1454 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 764 times.
|
764 | (outCache, guard_exp, DAE.PROP(_, guard_const)) := elabExpOptAndMatchType( |
| 1455 | outCache, env, oaguard_exp, DAE.T_BOOL_DEFAULT, inImpl, inDoVect, inPrefix, inInfo); | ||
| 1456 | |||
| 1457 | // If we have a guard expression we don't determine the dimension, since the | ||
| 1458 | // number of elements depend on the guard. | ||
| 1459 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 764 times.
✓ Branch 2 taken 41 times.
✓ Branch 3 taken 723 times.
|
764 | if isSome(guard_exp) then |
| 1460 | outHasGuard := true; | ||
| 1461 | 41 | dim := DAE.DIM_UNKNOWN(); | |
| 1462 | end if; | ||
| 1463 | |||
| 1464 | 764 | outConst := Types.constAnd(outConst, Types.constAnd(guard_const, iter_const)); | |
| 1465 | 764 | outIterators := DAE.REDUCTIONITER(iter_name, iter_exp, guard_exp, iter_ty) :: outIterators; | |
| 1466 | 764 | outDims := dim :: outDims; | |
| 1467 | end for; | ||
| 1468 | |||
| 1469 | 745 | outIterators := listReverse(outIterators); | |
| 1470 | 745 | outDims := listReverse(outDims); | |
| 1471 | end elabCallReductionIterators; | ||
| 1472 | |||
| 1473 | public function deduceIterationRange | ||
| 1474 | "This function tries to deduce the size of an iteration range for a reduction | ||
| 1475 | based on how an iterator is used. It does this by analysing the reduction | ||
| 1476 | expression to find out where the iterator is used as a subscript, and uses | ||
| 1477 | the subscripted components' dimensions to determine the size of the range." | ||
| 1478 | input String inIterator; | ||
| 1479 | input list<AbsynUtil.IteratorIndexedCref> inCrefs; | ||
| 1480 | input FCore.Graph inEnv; | ||
| 1481 | input FCore.Cache inCache; | ||
| 1482 | input Absyn.Info inInfo; | ||
| 1483 | output DAE.Exp outRange = DAE.ICONST(0); | ||
| 1484 | output DAE.Properties outProperties = DAE.PROP(DAE.T_UNKNOWN_DEFAULT, DAE.C_UNKNOWN()); | ||
| 1485 | output FCore.Cache outCache = inCache; | ||
| 1486 | protected | ||
| 1487 | Absyn.ComponentRef acref; | ||
| 1488 | DAE.ComponentRef cref; | ||
| 1489 | Integer idx, i1, i2; | ||
| 1490 | DAE.Type ty; | ||
| 1491 | list<DAE.Dimension> dims; | ||
| 1492 | DAE.Dimension dim; | ||
| 1493 | DAE.Exp range; | ||
| 1494 | list<DAE.Exp> ranges = {}; | ||
| 1495 | String cr_str1, cr_str2; | ||
| 1496 | algorithm | ||
| 1497 | // Check that we have some crefs, otherwise we print an error and fail. | ||
| 1498 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 16 times.
|
17 | if listEmpty(inCrefs) then |
| 1499 | 1 | Error.addSourceMessageAndFail(Error.IMPLICIT_ITERATOR_NOT_FOUND_IN_LOOP_BODY, | |
| 1500 | {inIterator}, inInfo); | ||
| 1501 | end if; | ||
| 1502 | |||
| 1503 | // For each cref-index pair, figure out the range of the subscripted dimension. | ||
| 1504 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 15 times.
|
32 | for cr in inCrefs loop |
| 1505 | 17 | (acref, idx) := cr; | |
| 1506 | 17 | cref := ComponentReference.toExpCref(acref); | |
| 1507 | |||
| 1508 | // Look the cref up to get its type. | ||
| 1509 | try | ||
| 1510 | 17 | (outCache, _, ty) := Lookup.lookupVar(outCache, inEnv, cref); | |
| 1511 | else | ||
| 1512 | 2 | Error.addSourceMessageAndFail(Error.LOOKUP_VARIABLE_ERROR, | |
| 1513 | {Dump.printComponentRefStr(acref), ""}, inInfo); | ||
| 1514 | end try; | ||
| 1515 | |||
| 1516 | // Get the cref's dimensions. | ||
| 1517 | 16 | dims := TypesDump.getDimensions(ty); | |
| 1518 | |||
| 1519 | // Check that the indexed dimension actually exists. | ||
| 1520 |
1/2✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
|
16 | if idx <= listLength(dims) then |
| 1521 | // Get the indexed dimension and construct a range from it. | ||
| 1522 | 16 | dim := listGet(dims, idx); | |
| 1523 | 16 | (range, outProperties) := deduceReductionIterationRange2(dim, cref, ty, idx); | |
| 1524 | else | ||
| 1525 | // The indexed dimension doesn't exist, i.e. we have too many subscripts. | ||
| 1526 | // Return some dummy variables, and let elabCallReduction handle the error | ||
| 1527 | // reporting since we don't know how many subscripts were used here. | ||
| 1528 | range := DAE.ICONST(0); | ||
| 1529 | ✗ | outProperties := DAE.PROP(DAE.T_ARRAY(DAE.T_UNKNOWN_DEFAULT, {DAE.DIM_INTEGER(0)}), DAE.C_UNKNOWN()); | |
| 1530 | end if; | ||
| 1531 | |||
| 1532 | ranges := range :: ranges; | ||
| 1533 | end for; | ||
| 1534 | |||
| 1535 | // If we have more than one range we must check that they are all equal, | ||
| 1536 | // otherwise it's not possible to determine the actual iteration range. | ||
| 1537 | // If they are equal we can just return anyone of them. | ||
| 1538 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
15 | outRange :: ranges := ranges; |
| 1539 | idx := 2; | ||
| 1540 | |||
| 1541 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 15 times.
|
16 | for r in ranges loop |
| 1542 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
|
1 | if not ExpressionBasics.expEqual(r, outRange) then |
| 1543 | ✗ | (acref, i1) := listHead(inCrefs); | |
| 1544 | ✗ | cr_str1 := Dump.printComponentRefStr(acref); | |
| 1545 | ✗ | (acref, i2) := listGet(inCrefs, idx); | |
| 1546 | ✗ | cr_str2 := Dump.printComponentRefStr(acref); | |
| 1547 | ✗ | Error.addSourceMessageAndFail(Error.INCOMPATIBLE_IMPLICIT_RANGES, | |
| 1548 | {intString(i2), cr_str2, intString(i1), cr_str1}, inInfo); | ||
| 1549 | end if; | ||
| 1550 | 1 | idx := idx + 1; | |
| 1551 | end for; | ||
| 1552 | end deduceIterationRange; | ||
| 1553 | |||
| 1554 | protected function iteratorIndexedCrefsEqual | ||
| 1555 | "Checks whether two cref-index pairs are equal." | ||
| 1556 | input tuple<Absyn.ComponentRef, Integer> inCref1; | ||
| 1557 | input tuple<Absyn.ComponentRef, Integer> inCref2; | ||
| 1558 | output Boolean outEqual; | ||
| 1559 | protected | ||
| 1560 | Absyn.ComponentRef cr1, cr2; | ||
| 1561 | Integer idx1, idx2; | ||
| 1562 | algorithm | ||
| 1563 | ✗ | (cr1, idx1) := inCref1; | |
| 1564 | ✗ | (cr2, idx2) := inCref2; | |
| 1565 | ✗ | outEqual := idx1 == idx2 and AbsynUtil.crefEqual(cr1, cr2); | |
| 1566 | end iteratorIndexedCrefsEqual; | ||
| 1567 | |||
| 1568 | protected function deduceReductionIterationRange_traverser | ||
| 1569 | "Traversal function used by deduceReductionIterationRange. Used to find crefs | ||
| 1570 | which are subscripted by a given iterator." | ||
| 1571 | input Absyn.Exp inExp; | ||
| 1572 | input list<tuple<Absyn.ComponentRef, Integer>> inCrefs; | ||
| 1573 | input String inIterator; | ||
| 1574 | output Absyn.Exp outExp = inExp; | ||
| 1575 | output list<tuple<Absyn.ComponentRef, Integer>> outCrefs; | ||
| 1576 | algorithm | ||
| 1577 | outCrefs := match inExp | ||
| 1578 | local | ||
| 1579 | Absyn.ComponentRef cref; | ||
| 1580 | |||
| 1581 | case Absyn.CREF(componentRef = cref) | ||
| 1582 | ✗ | then getIteratorIndexedCrefs(cref, inIterator, inCrefs); | |
| 1583 | |||
| 1584 | else inCrefs; | ||
| 1585 | end match; | ||
| 1586 | end deduceReductionIterationRange_traverser; | ||
| 1587 | |||
| 1588 | protected function getIteratorIndexedCrefs | ||
| 1589 | "Checks if the given component reference is subscripted by the given iterator. | ||
| 1590 | Only cases where a subscript consists of only the iterator is considered. | ||
| 1591 | If so it adds a cref-index pair to the list, where the cref is the subscripted | ||
| 1592 | cref without subscripts, and the index is the subscripted dimension. E.g. for | ||
| 1593 | iterator i: | ||
| 1594 | a[i] => (a, 1), b[1, i] => (b, 2), c[i+1] => (), d[2].e[i] => (d[2].e, 1)" | ||
| 1595 | input Absyn.ComponentRef inCref; | ||
| 1596 | input String inIterator; | ||
| 1597 | input list<tuple<Absyn.ComponentRef, Integer>> inCrefs; | ||
| 1598 | output list<tuple<Absyn.ComponentRef, Integer>> outCrefs = inCrefs; | ||
| 1599 | protected | ||
| 1600 | list<tuple<Absyn.ComponentRef, Integer>> crefs; | ||
| 1601 | algorithm | ||
| 1602 | outCrefs := match inCref | ||
| 1603 | local | ||
| 1604 | list<Absyn.Subscript> subs; | ||
| 1605 | Integer idx; | ||
| 1606 | String name, id; | ||
| 1607 | Absyn.ComponentRef cref; | ||
| 1608 | |||
| 1609 | case Absyn.CREF_IDENT(name = id, subscripts = subs) | ||
| 1610 | algorithm | ||
| 1611 | // For each subscript, check if the subscript consists of only the | ||
| 1612 | // iterator we're looking for. | ||
| 1613 | idx := 1; | ||
| 1614 | ✗ | for sub in subs loop | |
| 1615 | () := match sub | ||
| 1616 | case Absyn.SUBSCRIPT(subscript = Absyn.CREF(componentRef = | ||
| 1617 | Absyn.CREF_IDENT(name = name, subscripts = {}))) | ||
| 1618 | algorithm | ||
| 1619 | ✗ | if name == inIterator then | |
| 1620 | ✗ | outCrefs := (Absyn.CREF_IDENT(id, {}), idx) :: outCrefs; | |
| 1621 | end if; | ||
| 1622 | then | ||
| 1623 | (); | ||
| 1624 | |||
| 1625 | else (); | ||
| 1626 | end match; | ||
| 1627 | |||
| 1628 | ✗ | idx := idx + 1; | |
| 1629 | end for; | ||
| 1630 | then | ||
| 1631 | outCrefs; | ||
| 1632 | |||
| 1633 | case Absyn.CREF_QUAL(name = id, subscripts = subs, componentRef = cref) | ||
| 1634 | algorithm | ||
| 1635 | ✗ | crefs := getIteratorIndexedCrefs(cref, inIterator, {}); | |
| 1636 | |||
| 1637 | // Append the prefix from the qualified cref to any matches, and add | ||
| 1638 | // them to the result list. | ||
| 1639 | ✗ | for cr in crefs loop | |
| 1640 | ✗ | (cref, idx) := cr; | |
| 1641 | ✗ | outCrefs := (Absyn.CREF_QUAL(id, subs, cref), idx) :: outCrefs; | |
| 1642 | end for; | ||
| 1643 | ✗ | then | |
| 1644 | getIteratorIndexedCrefs(Absyn.CREF_IDENT(id, subs), inIterator, outCrefs); | ||
| 1645 | |||
| 1646 | case Absyn.CREF_FULLYQUALIFIED(componentRef = cref) | ||
| 1647 | algorithm | ||
| 1648 | ✗ | crefs := getIteratorIndexedCrefs(cref, inIterator, {}); | |
| 1649 | |||
| 1650 | // Make any matches fully qualified, and add the to the result list. | ||
| 1651 | ✗ | for cr in crefs loop | |
| 1652 | ✗ | (cref, idx) := cr; | |
| 1653 | ✗ | outCrefs := (Absyn.CREF_FULLYQUALIFIED(cref), idx) :: outCrefs; | |
| 1654 | end for; | ||
| 1655 | then | ||
| 1656 | outCrefs; | ||
| 1657 | |||
| 1658 | else inCrefs; | ||
| 1659 | end match; | ||
| 1660 | end getIteratorIndexedCrefs; | ||
| 1661 | |||
| 1662 | protected function deduceReductionIterationRange2 | ||
| 1663 | "Helper function to deduceReductionIterationRange. Constructs a range based on | ||
| 1664 | the given dimension." | ||
| 1665 | input DAE.Dimension inDimension; | ||
| 1666 | input DAE.ComponentRef inCref "The subscripted component without subscripts."; | ||
| 1667 | input DAE.Type inType "The type of the subscripted component."; | ||
| 1668 | input Integer inIndex "The index of the dimension."; | ||
| 1669 | output DAE.Exp outRange "The range expression."; | ||
| 1670 | output DAE.Properties outProperties "The properties of the range expression."; | ||
| 1671 | protected | ||
| 1672 | DAE.Type range_ty; | ||
| 1673 | DAE.Const range_const; | ||
| 1674 | Absyn.Path enum_path, enum_start, enum_end; | ||
| 1675 | list<String> enum_lits; | ||
| 1676 | Integer sz; | ||
| 1677 | DAE.Exp size_exp; | ||
| 1678 | algorithm | ||
| 1679 | outRange := match inDimension | ||
| 1680 | // Boolean dimension => false:true | ||
| 1681 | case DAE.DIM_BOOLEAN() | ||
| 1682 | algorithm | ||
| 1683 | 1 | range_ty := DAE.T_ARRAY(DAE.T_BOOL_DEFAULT, {inDimension}); | |
| 1684 | range_const := DAE.C_CONST(); | ||
| 1685 | 1 | then | |
| 1686 | DAE.RANGE(range_ty, DAE.BCONST(false), NONE(), DAE.BCONST(true)); | ||
| 1687 | |||
| 1688 | // Enumeration dimension => Enum.first:Enum.last | ||
| 1689 | case DAE.DIM_ENUM(enumTypeName = enum_path, literals = enum_lits) | ||
| 1690 | algorithm | ||
| 1691 | 4 | enum_start := AbsynUtil.suffixPath(enum_path, listHead(enum_lits)); | |
| 1692 | 4 | enum_end := AbsynUtil.suffixPath(enum_path, List.last(enum_lits)); | |
| 1693 | 4 | range_ty := DAE.T_ENUMERATION(NONE(), enum_path, enum_lits, {}, {}); | |
| 1694 | 4 | range_ty := DAE.T_ARRAY(range_ty, {inDimension}); | |
| 1695 | range_const := DAE.C_CONST(); | ||
| 1696 | 4 | then | |
| 1697 | DAE.RANGE(range_ty, DAE.ENUM_LITERAL(enum_start, 1), NONE(), | ||
| 1698 | DAE.ENUM_LITERAL(enum_end, listLength(enum_lits))); | ||
| 1699 | |||
| 1700 | // Integer dimension => 1:size | ||
| 1701 | case DAE.DIM_INTEGER(integer = sz) | ||
| 1702 | algorithm | ||
| 1703 | 11 | range_ty := DAE.T_ARRAY(DAE.T_INTEGER_DEFAULT, {inDimension}); | |
| 1704 | range_const := DAE.C_CONST(); | ||
| 1705 | 11 | then | |
| 1706 | DAE.RANGE(range_ty, DAE.ICONST(1), NONE(), DAE.ICONST(sz)); | ||
| 1707 | |||
| 1708 | // Any other kind of dimension => 1:size(cref, index) | ||
| 1709 | else | ||
| 1710 | algorithm | ||
| 1711 | ✗ | size_exp := DAE.SIZE(DAE.CREF(inCref, inType), SOME(DAE.ICONST(inIndex))); | |
| 1712 | ✗ | range_ty := DAE.T_ARRAY(DAE.T_INTEGER_DEFAULT, {inDimension}); | |
| 1713 | range_const := DAE.C_PARAM(); | ||
| 1714 | ✗ | then | |
| 1715 | DAE.RANGE(range_ty, DAE.ICONST(1), NONE(), size_exp); | ||
| 1716 | |||
| 1717 | end match; | ||
| 1718 | |||
| 1719 | // Set the properties of the range expression. | ||
| 1720 | 16 | outProperties := DAE.PROP(range_ty, range_const); | |
| 1721 | end deduceReductionIterationRange2; | ||
| 1722 | |||
| 1723 | protected function makeReductionFoldExp | ||
| 1724 | input FCore.Graph inEnv; | ||
| 1725 | input Absyn.Path path; | ||
| 1726 | input DAE.Type expty; | ||
| 1727 | input DAE.Type resultTy; | ||
| 1728 | input String foldId; | ||
| 1729 | input String resultId; | ||
| 1730 | output FCore.Graph outEnv; | ||
| 1731 | output Option<Absyn.Exp> afoldExp; | ||
| 1732 | algorithm | ||
| 1733 | (outEnv, afoldExp) := match AbsynUtil.makeNotFullyQualified(path) | ||
| 1734 | local | ||
| 1735 | Absyn.Exp exp; | ||
| 1736 | Absyn.ComponentRef cr, cr1, cr2; | ||
| 1737 | FCore.Graph env; | ||
| 1738 | |||
| 1739 | case Absyn.IDENT("$array") then (inEnv, NONE()); | ||
| 1740 | case Absyn.IDENT("array") then (inEnv, NONE()); | ||
| 1741 | case Absyn.IDENT("list") then (inEnv, NONE()); | ||
| 1742 | case Absyn.IDENT("listReverse") then (inEnv, NONE()); | ||
| 1743 | |||
| 1744 | case Absyn.IDENT("sum") | ||
| 1745 | algorithm | ||
| 1746 | 224 | env := FGraph.addForIterator(inEnv, foldId, expty, DAE.UNBOUND(), SCode.VAR(), SOME(DAE.C_VAR())); | |
| 1747 | 224 | env := FGraph.addForIterator(env, resultId, expty, DAE.UNBOUND(), SCode.VAR(), SOME(DAE.C_VAR())); | |
| 1748 | 224 | cr1 := Absyn.CREF_IDENT(foldId, {}); | |
| 1749 | 224 | cr2 := Absyn.CREF_IDENT(resultId, {}); | |
| 1750 | 224 | exp := Absyn.BINARY(Absyn.CREF(cr2), Absyn.ADD(), Absyn.CREF(cr1)); | |
| 1751 | then | ||
| 1752 | (env, SOME(exp)); | ||
| 1753 | |||
| 1754 | case Absyn.IDENT("product") | ||
| 1755 | algorithm | ||
| 1756 | 15 | env := FGraph.addForIterator(inEnv, foldId, expty, DAE.UNBOUND(), SCode.VAR(), SOME(DAE.C_VAR())); | |
| 1757 | 15 | env := FGraph.addForIterator(env, resultId, expty, DAE.UNBOUND(), SCode.VAR(), SOME(DAE.C_VAR())); | |
| 1758 | 15 | cr1 := Absyn.CREF_IDENT(foldId, {}); | |
| 1759 | 15 | cr2 := Absyn.CREF_IDENT(resultId, {}); | |
| 1760 | 15 | exp := Absyn.BINARY(Absyn.CREF(cr2), Absyn.MUL(), Absyn.CREF(cr1)); | |
| 1761 | then | ||
| 1762 | (env, SOME(exp)); | ||
| 1763 | |||
| 1764 | else | ||
| 1765 | algorithm | ||
| 1766 | 52 | cr := AbsynUtil.pathToCref(path); | |
| 1767 | // print("makeReductionFoldExp => " + AbsynUtil.pathString(path) + TypesDump.unparseType(expty) + "\n"); | ||
| 1768 | 52 | env := FGraph.addForIterator(inEnv, foldId, expty, DAE.UNBOUND(), SCode.VAR(), SOME(DAE.C_VAR())); | |
| 1769 | 52 | env := FGraph.addForIterator(env, resultId, resultTy, DAE.UNBOUND(), SCode.VAR(), SOME(DAE.C_VAR())); | |
| 1770 | 52 | cr1 := Absyn.CREF_IDENT(foldId, {}); | |
| 1771 | 52 | cr2 := Absyn.CREF_IDENT(resultId, {}); | |
| 1772 | 104 | exp := Absyn.CALL(cr, Absyn.FUNCTIONARGS({Absyn.CREF(cr1), Absyn.CREF(cr2)}, {}), {}); | |
| 1773 | then | ||
| 1774 | (env, SOME(exp)); | ||
| 1775 | end match; | ||
| 1776 | end makeReductionFoldExp; | ||
| 1777 | |||
| 1778 | protected function reductionType | ||
| 1779 | input FCore.Cache inCache; | ||
| 1780 | input FCore.Graph inEnv; | ||
| 1781 | input Absyn.Path inFn; | ||
| 1782 | input DAE.Exp inExp; | ||
| 1783 | input DAE.Type inType; | ||
| 1784 | input DAE.Type unboxedType; | ||
| 1785 | input DAE.Dimensions dims; | ||
| 1786 | input Boolean hasGuardExp; | ||
| 1787 | input SourceInfo info; | ||
| 1788 | output FCore.Cache outCache = inCache; | ||
| 1789 | output DAE.Exp outExp; | ||
| 1790 | output DAE.Type outType; | ||
| 1791 | output DAE.Type resultType; | ||
| 1792 | output Option<Values.Value> defaultValue; | ||
| 1793 | output Absyn.Path outPath; | ||
| 1794 | protected | ||
| 1795 | Absyn.Path fn = AbsynUtil.makeNotFullyQualified(inFn); | ||
| 1796 | algorithm | ||
| 1797 | (outExp, outType, resultType, defaultValue, outPath) := match(fn, unboxedType) | ||
| 1798 | local | ||
| 1799 | Integer i; | ||
| 1800 | Real r; | ||
| 1801 | list<DAE.Type> fnTypes; | ||
| 1802 | DAE.Type ty,ty2,typeA,typeB,resType; | ||
| 1803 | Absyn.Path path; | ||
| 1804 | Values.Value v; | ||
| 1805 | DAE.Exp exp; | ||
| 1806 | InstTypes.PolymorphicBindings bindings; | ||
| 1807 | Option<Values.Value> defaultBinding; | ||
| 1808 | |||
| 1809 | case (Absyn.IDENT(name = "array"), _) | ||
| 1810 | algorithm | ||
| 1811 | 335 | ty := List.foldr(dims, Types.liftArray, inType); | |
| 1812 | then | ||
| 1813 | (inExp, ty, ty, SOME(Values.ARRAY({},{0})), fn); | ||
| 1814 | |||
| 1815 | case (Absyn.IDENT(name = "$array"), _) | ||
| 1816 | algorithm | ||
| 1817 | ✗ | ty := List.foldr(dims, Types.liftArray, inType); | |
| 1818 | then | ||
| 1819 | (inExp, ty, ty, SOME(Values.ARRAY({},{0})), fn); | ||
| 1820 | |||
| 1821 | case (Absyn.IDENT(name = "list"), _) | ||
| 1822 | algorithm | ||
| 1823 | 111 | (exp, ty) := Types.matchType(inExp, inType, DAE.T_METABOXED_DEFAULT, true); | |
| 1824 | 111 | ty := List.foldr(dims, Types.liftList, ty); | |
| 1825 | then | ||
| 1826 | (exp, ty, ty, SOME(Values.LIST({})), fn); | ||
| 1827 | |||
| 1828 | case (Absyn.IDENT(name = "listReverse"), _) | ||
| 1829 | algorithm | ||
| 1830 | 8 | (exp, ty) := Types.matchType(inExp, inType, DAE.T_METABOXED_DEFAULT, true); | |
| 1831 | 8 | ty := List.foldr(dims, Types.liftList, ty); | |
| 1832 | then | ||
| 1833 | (exp, ty, ty, SOME(Values.LIST({})), fn); | ||
| 1834 | |||
| 1835 | case (Absyn.IDENT("min"), DAE.T_REAL()) | ||
| 1836 | algorithm | ||
| 1837 | 4 | r := System.realMaxLit(); | |
| 1838 | 4 | v := Values.REAL(r); | |
| 1839 | 4 | (exp, ty) := Types.matchType(inExp, inType, DAE.T_REAL_DEFAULT, true); | |
| 1840 | 4 | then | |
| 1841 | (exp, ty, ty, SOME(v), fn); | ||
| 1842 | |||
| 1843 | case (Absyn.IDENT("min"), DAE.T_INTEGER()) | ||
| 1844 | algorithm | ||
| 1845 | 3 | i := System.intMaxLit(); | |
| 1846 | 3 | v := Values.INTEGER(i); | |
| 1847 | 3 | (exp, ty) := Types.matchType(inExp, inType, DAE.T_INTEGER_DEFAULT, true); | |
| 1848 | 3 | then | |
| 1849 | (exp, ty, ty, SOME(v), fn); | ||
| 1850 | |||
| 1851 | case (Absyn.IDENT("min"), DAE.T_BOOL()) | ||
| 1852 | algorithm | ||
| 1853 | v := Values.BOOL(true); | ||
| 1854 | 3 | (exp, ty) := Types.matchType(inExp, inType, DAE.T_BOOL_DEFAULT, true); | |
| 1855 | 3 | then | |
| 1856 | (exp, ty, ty, SOME(v), fn); | ||
| 1857 | |||
| 1858 | case (Absyn.IDENT("min"), DAE.T_STRING()) | ||
| 1859 | algorithm | ||
| 1860 | ✗ | (exp, ty) := Types.matchType(inExp, inType, DAE.T_STRING_DEFAULT, true); | |
| 1861 | ✗ | then | |
| 1862 | (exp, ty, ty, NONE(), fn); | ||
| 1863 | |||
| 1864 | case (Absyn.IDENT("min"), DAE.T_ENUMERATION()) | ||
| 1865 | algorithm | ||
| 1866 | ✗ | v := Values.ENUM_LITERAL(AbsynUtil.suffixPath(unboxedType.path, | |
| 1867 | List.last(unboxedType.names)), listLength(unboxedType.names)); | ||
| 1868 | ✗ | (exp, ty) := Types.matchType(inExp, inType, DAE.T_ENUMERATION_DEFAULT, true); | |
| 1869 | ✗ | then | |
| 1870 | (exp, ty, ty, SOME(v), fn); | ||
| 1871 | |||
| 1872 | case (Absyn.IDENT("max"), DAE.T_REAL()) | ||
| 1873 | algorithm | ||
| 1874 | 5 | r := realNeg(System.realMaxLit()); | |
| 1875 | 5 | v := Values.REAL(r); | |
| 1876 | 5 | (exp, ty) := Types.matchType(inExp, inType, DAE.T_REAL_DEFAULT, true); | |
| 1877 | 5 | then | |
| 1878 | (exp, ty, ty, SOME(v), fn); | ||
| 1879 | |||
| 1880 | case (Absyn.IDENT("max"), DAE.T_INTEGER()) | ||
| 1881 | algorithm | ||
| 1882 | 2 | i := intNeg(System.intMaxLit()); | |
| 1883 | 2 | v := Values.INTEGER(i); | |
| 1884 | 2 | (exp, ty) := Types.matchType(inExp, inType, DAE.T_INTEGER_DEFAULT, true); | |
| 1885 | 2 | then | |
| 1886 | (exp, ty, ty, SOME(v), fn); | ||
| 1887 | |||
| 1888 | case (Absyn.IDENT("max"), DAE.T_BOOL()) | ||
| 1889 | algorithm | ||
| 1890 | v := Values.BOOL(false); | ||
| 1891 | ✗ | (exp,ty) := Types.matchType(inExp, inType, DAE.T_BOOL_DEFAULT, true); | |
| 1892 | ✗ | then | |
| 1893 | (exp, ty, ty, SOME(v), fn); | ||
| 1894 | |||
| 1895 | case (Absyn.IDENT("max"), DAE.T_STRING()) | ||
| 1896 | algorithm | ||
| 1897 | v := Values.STRING(""); | ||
| 1898 | ✗ | (exp, ty) := Types.matchType(inExp, inType, DAE.T_STRING_DEFAULT, true); | |
| 1899 | ✗ | then | |
| 1900 | (exp, ty, ty, SOME(v), fn); | ||
| 1901 | |||
| 1902 | case (Absyn.IDENT("max"), DAE.T_ENUMERATION()) | ||
| 1903 | algorithm | ||
| 1904 | ✗ | v := Values.ENUM_LITERAL(AbsynUtil.suffixPath(unboxedType.path, listHead(unboxedType.names)), 1); | |
| 1905 | ✗ | (exp, ty) := Types.matchType(inExp, inType, DAE.T_ENUMERATION_DEFAULT, true); | |
| 1906 | ✗ | then | |
| 1907 | (exp, ty, ty, SOME(v), fn); | ||
| 1908 | |||
| 1909 | case (Absyn.IDENT("sum"), DAE.T_REAL()) | ||
| 1910 | algorithm | ||
| 1911 | v := Values.REAL(0.0); | ||
| 1912 | 71 | (exp, ty) := Types.matchType(inExp, inType, DAE.T_REAL_DEFAULT, true); | |
| 1913 | 71 | then | |
| 1914 | (exp, ty, ty, SOME(v), fn); | ||
| 1915 | |||
| 1916 | case (Absyn.IDENT("sum"), DAE.T_INTEGER()) | ||
| 1917 | algorithm | ||
| 1918 | v := Values.INTEGER(0); | ||
| 1919 | 6 | (exp, ty) := Types.matchType(inExp, inType, DAE.T_INTEGER_DEFAULT, true); | |
| 1920 | 6 | then | |
| 1921 | (exp, ty, ty, SOME(v), fn); | ||
| 1922 | |||
| 1923 | case (Absyn.IDENT("sum"), DAE.T_BOOL()) | ||
| 1924 | algorithm | ||
| 1925 | v := Values.BOOL(false); | ||
| 1926 | ✗ | (exp, ty) := Types.matchType(inExp, inType, DAE.T_BOOL_DEFAULT, true); | |
| 1927 | ✗ | then | |
| 1928 | (exp, ty, ty, SOME(v), fn); | ||
| 1929 | |||
| 1930 | case (Absyn.IDENT("sum"), DAE.T_STRING()) | ||
| 1931 | algorithm | ||
| 1932 | v := Values.STRING(""); | ||
| 1933 | 146 | (exp, ty) := Types.matchType(inExp, inType, DAE.T_STRING_DEFAULT, true); | |
| 1934 | 146 | then | |
| 1935 | (exp, ty, ty, SOME(v), fn); | ||
| 1936 | |||
| 1937 | case (Absyn.IDENT("sum"), DAE.T_ARRAY()) | ||
| 1938 | then (inExp, inType, inType, NONE(), fn); | ||
| 1939 | |||
| 1940 | case (Absyn.IDENT("product"), DAE.T_REAL()) | ||
| 1941 | algorithm | ||
| 1942 | v := Values.REAL(1.0); | ||
| 1943 | 4 | (exp, ty) := Types.matchType(inExp, inType, DAE.T_REAL_DEFAULT, true); | |
| 1944 | 4 | then | |
| 1945 | (exp, ty, ty, SOME(v), fn); | ||
| 1946 | |||
| 1947 | case (Absyn.IDENT("product"), DAE.T_INTEGER()) | ||
| 1948 | algorithm | ||
| 1949 | v := Values.INTEGER(1); | ||
| 1950 | 11 | (exp, ty) := Types.matchType(inExp, inType, DAE.T_INTEGER_DEFAULT, true); | |
| 1951 | 11 | then | |
| 1952 | (exp, ty, ty, SOME(v), fn); | ||
| 1953 | |||
| 1954 | case (Absyn.IDENT("product"), DAE.T_BOOL()) | ||
| 1955 | algorithm | ||
| 1956 | v := Values.BOOL(true); | ||
| 1957 | ✗ | (exp, ty) := Types.matchType(inExp, inType, DAE.T_BOOL_DEFAULT, true); | |
| 1958 | ✗ | then | |
| 1959 | (exp, ty, ty, SOME(v), fn); | ||
| 1960 | |||
| 1961 | case (Absyn.IDENT("product"), DAE.T_STRING()) | ||
| 1962 | algorithm | ||
| 1963 | ✗ | Error.addSourceMessage(Error.INTERNAL_ERROR, {"product reduction not defined for String"},info); | |
| 1964 | ✗ | then | |
| 1965 | fail(); | ||
| 1966 | |||
| 1967 | case (Absyn.IDENT("product"), DAE.T_ARRAY()) | ||
| 1968 | then (inExp, inType, inType, NONE(), fn); | ||
| 1969 | |||
| 1970 | else | ||
| 1971 | algorithm | ||
| 1972 | 35 | (outCache, fnTypes) := Lookup.lookupFunctionsInEnv(inCache, inEnv, inFn, info); | |
| 1973 | 35 | (typeA,typeB,resType,defaultBinding,path) := checkReductionType1(inEnv,inFn,fnTypes,info); | |
| 1974 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 14 times.
|
35 | ty2 := if isSome(defaultBinding) then typeB else inType; |
| 1975 | 35 | (exp,typeA,bindings) := Types.matchTypePolymorphicWithError(inExp, inType,typeA,SOME(path),{},info); | |
| 1976 | 35 | (_,typeB,bindings) := Types.matchTypePolymorphicWithError(DAE.CREF(DAE.CREF_IDENT("$result",DAE.T_ANYTYPE_DEFAULT,{}),DAE.T_ANYTYPE_DEFAULT),ty2,typeB,SOME(path),bindings,info); | |
| 1977 | 35 | bindings := Types.solvePolymorphicBindings(bindings, info, path); | |
| 1978 | 35 | typeA := Types.fixPolymorphicRestype(typeA, bindings, info); | |
| 1979 | 35 | typeB := Types.fixPolymorphicRestype(typeB, bindings, info); | |
| 1980 | 35 | resType := Types.fixPolymorphicRestype(resType, bindings, info); | |
| 1981 |
4/6✓ Branch 2 taken 9 times.
✓ Branch 3 taken 26 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 9 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 9 times.
|
35 | (exp,ty) := checkReductionType2(exp, inType,typeA,typeB,resType,Types.equivtypes(typeA,typeB) or isSome(defaultBinding),Types.equivtypes(typeB,resType),info); |
| 1982 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 35 times.
|
35 | (outCache, Util.SUCCESS()) := instantiateDaeFunction(outCache, inEnv, path, false, NONE(), true); |
| 1983 |
1/4✗ Branch 1 not taken.
✓ Branch 2 taken 35 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
35 | Error.assertionOrAddSourceMessage(Config.acceptMetaModelicaGrammar() or Flags.isSet(Flags.EXPERIMENTAL_REDUCTIONS), Error.COMPILER_NOTIFICATION, {"Custom reduction functions are an OpenModelica extension to the Modelica Specification. Do not use them if you need your model to compile using other tools or if you are concerned about using experimental features. Use -d=experimentalReductions to disable this message."}, info); |
| 1984 | 35 | then | |
| 1985 | (exp, ty, typeB, defaultBinding, path); | ||
| 1986 | end match; | ||
| 1987 | end reductionType; | ||
| 1988 | |||
| 1989 | protected function checkReductionType1 | ||
| 1990 | input FCore.Graph inEnv; | ||
| 1991 | input Absyn.Path inPath; | ||
| 1992 | input list<DAE.Type> fnTypes; | ||
| 1993 | input SourceInfo info; | ||
| 1994 | output DAE.Type typeA; | ||
| 1995 | output DAE.Type typeB; | ||
| 1996 | output DAE.Type resType; | ||
| 1997 | output Option<Values.Value> startValue; | ||
| 1998 | output Absyn.Path outPath; | ||
| 1999 | algorithm | ||
| 2000 | (typeA, typeB, resType, startValue, outPath) := match fnTypes | ||
| 2001 | local | ||
| 2002 | String str1, str2; | ||
| 2003 | Absyn.Path path; | ||
| 2004 | DAE.Exp e; | ||
| 2005 | Values.Value v; | ||
| 2006 | |||
| 2007 | case {} | ||
| 2008 | algorithm | ||
| 2009 | ✗ | str1 := AbsynUtil.pathString(inPath); | |
| 2010 | ✗ | str2 := FGraph.printGraphPathStr(inEnv); | |
| 2011 | ✗ | Error.addSourceMessage(Error.LOOKUP_FUNCTION_ERROR, {str1, str2}, info); | |
| 2012 | ✗ | then | |
| 2013 | fail(); | ||
| 2014 | |||
| 2015 | case {DAE.T_FUNCTION(funcArg={DAE.FUNCARG(ty = typeA, const = DAE.C_VAR()), | ||
| 2016 | DAE.FUNCARG(ty = typeB, const = DAE.C_VAR(), defaultBinding=SOME(e))}, | ||
| 2017 | funcResultType = resType, path = path)} | ||
| 2018 | algorithm | ||
| 2019 | 21 | v := Ceval.cevalSimple(e); | |
| 2020 | then | ||
| 2021 | (typeA, typeB, resType, SOME(v), path); | ||
| 2022 | |||
| 2023 | case {DAE.T_FUNCTION(funcArg={DAE.FUNCARG(ty = typeA, const = DAE.C_VAR()), | ||
| 2024 | DAE.FUNCARG(ty = typeB, const = DAE.C_VAR(), defaultBinding=NONE())}, | ||
| 2025 | funcResultType = resType, path = path)} | ||
| 2026 | then (typeA, typeB, resType, NONE(), path); | ||
| 2027 | |||
| 2028 | else | ||
| 2029 | algorithm | ||
| 2030 | ✗ | str1 := stringDelimitList(List.map(fnTypes, TypesDump.unparseType), ","); | |
| 2031 | ✗ | Error.addSourceMessage(Error.UNSUPPORTED_REDUCTION_TYPE, {str1}, info); | |
| 2032 | ✗ | then | |
| 2033 | fail(); | ||
| 2034 | |||
| 2035 | end match; | ||
| 2036 | end checkReductionType1; | ||
| 2037 | |||
| 2038 | protected function checkReductionType2 | ||
| 2039 | input DAE.Exp inExp; | ||
| 2040 | input DAE.Type expType; | ||
| 2041 | input DAE.Type typeA; | ||
| 2042 | input DAE.Type typeB; | ||
| 2043 | input DAE.Type typeC; | ||
| 2044 | input Boolean equivAB; | ||
| 2045 | input Boolean equivBC; | ||
| 2046 | input SourceInfo info; | ||
| 2047 | output DAE.Exp outExp; | ||
| 2048 | output DAE.Type outTy; | ||
| 2049 | algorithm | ||
| 2050 | (outExp,outTy) := match(equivAB,equivBC) | ||
| 2051 | local | ||
| 2052 | String str1,str2; | ||
| 2053 | |||
| 2054 | case (true, true) | ||
| 2055 | // (exp,outTy) = Types.matchType(exp,expType,typeA,true); | ||
| 2056 | then (inExp, typeA); | ||
| 2057 | |||
| 2058 | case (_, false) | ||
| 2059 | algorithm | ||
| 2060 | ✗ | str1 := TypesDump.unparseType(typeB); | |
| 2061 | ✗ | str2 := TypesDump.unparseType(typeC); | |
| 2062 | ✗ | Error.addSourceMessage(Error.REDUCTION_TYPE_ERROR,{"second argument", "result-type", "identical", str1, str2},info); | |
| 2063 | ✗ | then | |
| 2064 | fail(); | ||
| 2065 | |||
| 2066 | case (false,true) | ||
| 2067 | algorithm | ||
| 2068 | ✗ | str1 := TypesDump.unparseType(typeA); | |
| 2069 | ✗ | str2 := TypesDump.unparseType(typeB); | |
| 2070 | ✗ | Error.addSourceMessage(Error.REDUCTION_TYPE_ERROR,{"first", "second arguments", "identical", str1, str2},info); | |
| 2071 | ✗ | then | |
| 2072 | fail(); | ||
| 2073 | |||
| 2074 | case (true,true) | ||
| 2075 | algorithm | ||
| 2076 | ✗ | str1 := TypesDump.unparseType(expType); | |
| 2077 | ✗ | str2 := TypesDump.unparseType(typeA); | |
| 2078 | ✗ | Error.addSourceMessage(Error.REDUCTION_TYPE_ERROR,{"reduction expression", "first argument", "compatible", str1, str2},info); | |
| 2079 | ✗ | then | |
| 2080 | fail(); | ||
| 2081 | end match; | ||
| 2082 | end checkReductionType2; | ||
| 2083 | |||
| 2084 | protected function constToVariability "translates an DAE.Const to a SCode.Variability" | ||
| 2085 | input DAE.Const const; | ||
| 2086 | output SCode.Variability variability; | ||
| 2087 | algorithm | ||
| 2088 | variability := match const | ||
| 2089 | case DAE.C_VAR() then SCode.VAR(); | ||
| 2090 | case DAE.C_PARAM() then SCode.PARAM(); | ||
| 2091 | case DAE.C_CONST() then SCode.CONST(); | ||
| 2092 | case DAE.C_UNKNOWN() | ||
| 2093 | algorithm | ||
| 2094 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 2095 | ✗ | Debug.trace("- Static.constToVariability failed on DAE.C_UNKNOWN()\n"); | |
| 2096 | ✗ | then | |
| 2097 | fail(); | ||
| 2098 | end match; | ||
| 2099 | end constToVariability; | ||
| 2100 | |||
| 2101 | protected function constructArrayType | ||
| 2102 | "Helper function for elabCallReduction. Combines the type of the expression in | ||
| 2103 | an array constructor with the type of the generated array by replacing the | ||
| 2104 | placeholder T_UNKNOWN in arrayType with expType. Example: | ||
| 2105 | r[i] for i in 1:5 => | ||
| 2106 | arrayType = type(i in 1:5) = (T_ARRAY(DIM(5), T_UNKNOWN),NONE()) | ||
| 2107 | expType = type(r[i]) = (T_REAL,NONE()) | ||
| 2108 | => resType = (T_ARRAY(DIM(5), (T_REAL,NONE())),NONE())" | ||
| 2109 | input DAE.Type arrayType; | ||
| 2110 | input DAE.Type expType; | ||
| 2111 | output DAE.Type resType; | ||
| 2112 | algorithm | ||
| 2113 | resType := match arrayType | ||
| 2114 | local | ||
| 2115 | DAE.Type ty; | ||
| 2116 | DAE.Dimension dim; | ||
| 2117 | |||
| 2118 | case DAE.T_UNKNOWN() then expType; | ||
| 2119 | |||
| 2120 | case DAE.T_ARRAY(dims = {dim}, ty = ty) | ||
| 2121 | algorithm | ||
| 2122 | ✗ | ty := constructArrayType(ty, expType); | |
| 2123 | ✗ | then | |
| 2124 | DAE.T_ARRAY(ty, {dim}); | ||
| 2125 | end match; | ||
| 2126 | end constructArrayType; | ||
| 2127 | |||
| 2128 | protected function elabCodeType | ||
| 2129 | "This function will construct the correct type for the given Code expression. | ||
| 2130 | The types are built-in classes of different types. E.g. the class TypeName is | ||
| 2131 | the type of Code expressions corresponding to a type name Code expression." | ||
| 2132 | input Absyn.CodeNode inCode; | ||
| 2133 | output DAE.Type outType; | ||
| 2134 | algorithm | ||
| 2135 | outType := match inCode | ||
| 2136 | case Absyn.C_TYPENAME() | ||
| 2137 | then DAE.T_CODE(DAE.C_TYPENAME()); | ||
| 2138 | |||
| 2139 | case Absyn.C_VARIABLENAME() | ||
| 2140 | then DAE.T_CODE(DAE.C_VARIABLENAME()); | ||
| 2141 | |||
| 2142 | case Absyn.C_EQUATIONSECTION() | ||
| 2143 | then DAE.T_COMPLEX(ClassInf.UNKNOWN(Absyn.IDENT("EquationSection")),{},NONE(), false); | ||
| 2144 | |||
| 2145 | case Absyn.C_ALGORITHMSECTION() | ||
| 2146 | then DAE.T_COMPLEX(ClassInf.UNKNOWN(Absyn.IDENT("AlgorithmSection")),{},NONE(), false); | ||
| 2147 | |||
| 2148 | case Absyn.C_ELEMENT() | ||
| 2149 | then DAE.T_COMPLEX(ClassInf.UNKNOWN(Absyn.IDENT("Element")),{},NONE(), false); | ||
| 2150 | |||
| 2151 | case Absyn.C_EXPRESSION() | ||
| 2152 | then DAE.T_CODE(DAE.C_EXPRESSION()); | ||
| 2153 | |||
| 2154 | case Absyn.C_MODIFICATION() | ||
| 2155 | then DAE.T_CODE(DAE.C_EXPRESSION_OR_MODIFICATION()); | ||
| 2156 | end match; | ||
| 2157 | end elabCodeType; | ||
| 2158 | |||
| 2159 | public function elabGraphicsExp | ||
| 2160 | "investigating Modelica 2.0 graphical annotations. | ||
| 2161 | These have an array of records representing graphical objects. These | ||
| 2162 | elements can have different types, therefore elab_graphic_exp will allow | ||
| 2163 | arrays with elements of varying types. " | ||
| 2164 | input FCore.Cache inCache; | ||
| 2165 | input FCore.Graph inEnv; | ||
| 2166 | input Absyn.Exp inExp; | ||
| 2167 | input Boolean inBoolean; | ||
| 2168 | input DAE.Prefix inPrefix; | ||
| 2169 | input SourceInfo info; | ||
| 2170 | output FCore.Cache outCache; | ||
| 2171 | output DAE.Exp outExp; | ||
| 2172 | output DAE.Properties outProperties; | ||
| 2173 | algorithm | ||
| 2174 | (outCache,outExp,outProperties):= | ||
| 2175 | matchcontinue (inCache, inEnv, inExp, inBoolean, inPrefix) | ||
| 2176 | local | ||
| 2177 | Integer i,l,nmax; | ||
| 2178 | Real r; | ||
| 2179 | DAE.Dimension dim1,dim2; | ||
| 2180 | Boolean b,impl,a,havereal; | ||
| 2181 | String s,ps; | ||
| 2182 | DAE.Exp dexp,e1_1,e2_1,e_1,e3_1,start_1,stop_1,start_2,stop_2,step_1,step_2,mexp; | ||
| 2183 | DAE.Properties prop,prop1,prop2,prop3; | ||
| 2184 | FCore.Graph env; | ||
| 2185 | Absyn.ComponentRef cr,fn; | ||
| 2186 | DAE.Type t,start_t,stop_t,step_t,t_1,t_2; | ||
| 2187 | DAE.Const c1,c,c_start,c_stop,const,c_step; | ||
| 2188 | Absyn.Exp e,e1,e2,e3,start,stop,step,exp; | ||
| 2189 | Absyn.Operator op; | ||
| 2190 | list<Absyn.Exp> args,es; | ||
| 2191 | list<Absyn.NamedArg> nargs; | ||
| 2192 | list<DAE.Exp> es_1; | ||
| 2193 | list<DAE.Properties> props; | ||
| 2194 | list<DAE.Type> types,tps_2; | ||
| 2195 | list<DAE.TupleConst> consts; | ||
| 2196 | DAE.Type rt,at; | ||
| 2197 | list<list<DAE.Properties>> tps; | ||
| 2198 | list<list<DAE.Type>> tps_1; | ||
| 2199 | FCore.Cache cache; | ||
| 2200 | DAE.Prefix pre; | ||
| 2201 | list<list<Absyn.Exp>> ess; | ||
| 2202 | list<list<DAE.Exp>> dess; | ||
| 2203 | |||
| 2204 | ✗ | case (cache, _, Absyn.INTEGER(value = i), _, _) then (cache,DAE.ICONST(i),DAE.PROP(DAE.T_INTEGER_DEFAULT,DAE.C_CONST())); /* impl */ | |
| 2205 | |||
| 2206 | case (cache, _, Absyn.REAL(value = s), _, _) | ||
| 2207 | algorithm | ||
| 2208 | ✗ | r := stringReal(s); | |
| 2209 | ✗ | then | |
| 2210 | (cache,DAE.RCONST(r),DAE.PROP(DAE.T_REAL_DEFAULT,DAE.C_CONST())); | ||
| 2211 | |||
| 2212 | case (cache, _, Absyn.STRING(value = s), _, _) | ||
| 2213 | algorithm | ||
| 2214 | 17 | s := System.unescapedString(s); | |
| 2215 | 17 | then | |
| 2216 | (cache,DAE.SCONST(s),DAE.PROP(DAE.T_STRING_DEFAULT,DAE.C_CONST())); | ||
| 2217 | |||
| 2218 | case (cache, _, Absyn.BOOL(value = b), _, _) | ||
| 2219 | ✗ | then | |
| 2220 | (cache,DAE.BCONST(b),DAE.PROP(DAE.T_BOOL_DEFAULT,DAE.C_CONST())); | ||
| 2221 | |||
| 2222 | // adrpo: 2010-11-17 this is now fixed! | ||
| 2223 | // adrpo, if we have useHeatPort, return false. | ||
| 2224 | // this is a workaround for handling Modelica.Electrical.Analog.Basic.Resistor | ||
| 2225 | // case (cache,env,Absyn.CREF(componentRef = cr as Absyn.CREF_IDENT("useHeatPort", _)),impl,pre,info) | ||
| 2226 | // equation | ||
| 2227 | // dexp = DAE.BCONST(false); | ||
| 2228 | // prop = DAE.PROP(DAE.T_BOOL_DEFAULT, DAE.C_CONST()); | ||
| 2229 | // then | ||
| 2230 | // (cache,dexp,prop); | ||
| 2231 | case (cache, env, Absyn.CREF(componentRef = cr), impl, pre) | ||
| 2232 | algorithm | ||
| 2233 | ✗ | (cache,SOME((dexp,prop,_))) := elabCref(cache,env, cr, impl,true /*perform vectorization*/,pre,info); | |
| 2234 | ✗ | then | |
| 2235 | (cache,dexp,prop); | ||
| 2236 | |||
| 2237 | // Binary and unary operations | ||
| 2238 | case (cache, env, (exp as Absyn.BINARY(exp1 = e1,op = op,exp2 = e2)), impl, pre) | ||
| 2239 | algorithm | ||
| 2240 | ✗ | (cache,e1_1,prop1) := elabGraphicsExp(cache,env, e1, impl,pre,info); | |
| 2241 | ✗ | (cache,e2_1,prop2) := elabGraphicsExp(cache,env, e2, impl,pre,info); | |
| 2242 | ✗ | (cache, dexp, prop) := OperatorOverloading.binary(cache, env, op, prop1, e1_1, prop2, e2_1, exp, e1, e2, impl, pre, info); | |
| 2243 | then | ||
| 2244 | (cache, dexp, prop); | ||
| 2245 | case (cache, env, (e as Absyn.UNARY(op = Absyn.UPLUS())), impl, pre) | ||
| 2246 | algorithm | ||
| 2247 | ✗ | (cache,e_1,DAE.PROP(t,c)) := elabGraphicsExp(cache,env, e, impl,pre,info); | |
| 2248 | ✗ | true := Types.isRealOrSubTypeReal(Types.arrayElementType(t)); | |
| 2249 | ✗ | prop := DAE.PROP(t,c); | |
| 2250 | ✗ | then | |
| 2251 | (cache,e_1,prop); | ||
| 2252 | case (cache, env, (exp as Absyn.UNARY(op = op,exp = e)), impl, pre) | ||
| 2253 | algorithm | ||
| 2254 | ✗ | (cache,e_1,prop1) := elabGraphicsExp(cache,env, e, impl,pre,info); | |
| 2255 | ✗ | (cache, dexp, prop) := OperatorOverloading.unary(cache,env, op, prop1, e_1, exp, e, impl, pre, info); | |
| 2256 | then | ||
| 2257 | (cache, dexp, prop); | ||
| 2258 | |||
| 2259 | // Logical binary expressions | ||
| 2260 | case (cache, env, (exp as Absyn.LBINARY(exp1 = e1,op = op,exp2 = e2)), impl, pre) | ||
| 2261 | algorithm | ||
| 2262 | ✗ | (cache,e1_1,prop1) := elabGraphicsExp(cache,env, e1, impl,pre,info); | |
| 2263 | ✗ | (cache,e2_1,prop2) := elabGraphicsExp(cache,env, e2, impl,pre,info); | |
| 2264 | ✗ | (cache, dexp, prop) := OperatorOverloading.binary(cache, env, op, prop1, e1_1, prop2, e2_1, exp, e1, e2, impl, pre, info); | |
| 2265 | then | ||
| 2266 | (cache, dexp, prop); | ||
| 2267 | |||
| 2268 | // Logical unary expressions | ||
| 2269 | case (cache, env, (exp as Absyn.LUNARY(op = op,exp = e)), impl, pre) | ||
| 2270 | algorithm | ||
| 2271 | ✗ | (cache,e_1,prop1) := elabGraphicsExp(cache,env, e, impl,pre,info); | |
| 2272 | ✗ | (cache, dexp, prop) := OperatorOverloading.unary(cache,env, op, prop1, e_1, exp, e, impl, pre, info); | |
| 2273 | then | ||
| 2274 | (cache, dexp, prop); | ||
| 2275 | |||
| 2276 | // Relation expressions | ||
| 2277 | case (cache, env, (exp as Absyn.RELATION(exp1 = e1,op = op,exp2 = e2)), impl, pre) | ||
| 2278 | algorithm | ||
| 2279 | ✗ | (cache,e1_1,prop1) := elabGraphicsExp(cache,env, e1, impl,pre,info); | |
| 2280 | ✗ | (cache,e2_1,prop2) := elabGraphicsExp(cache,env, e2, impl,pre,info); | |
| 2281 | ✗ | (cache, dexp, prop) := OperatorOverloading.binary(cache, env, op, prop1, e1_1, prop2, e2_1, exp, e1, e2, impl, pre, info); | |
| 2282 | then | ||
| 2283 | (cache, dexp, prop); | ||
| 2284 | |||
| 2285 | // Conditional expressions | ||
| 2286 | case (cache, env, e as Absyn.IFEXP(), impl, pre) | ||
| 2287 | algorithm | ||
| 2288 | ✗ | Absyn.IFEXP(ifExp = e1,trueBranch = e2,elseBranch = e3) := AbsynUtil.canonIfExp(e); | |
| 2289 | ✗ | (cache,e1_1,prop1) := elabGraphicsExp(cache,env, e1, impl,pre,info); | |
| 2290 | ✗ | (cache,e2_1,prop2) := elabGraphicsExp(cache,env, e2, impl,pre,info); | |
| 2291 | ✗ | (cache,e3_1,prop3) := elabGraphicsExp(cache,env, e3, impl,pre,info); | |
| 2292 | ✗ | (cache,e_1,prop) := makeIfExp(cache,env, e1_1, prop1, e2_1, prop2, e3_1, prop3, impl,pre, info); | |
| 2293 | then | ||
| 2294 | (cache,e_1,prop); | ||
| 2295 | |||
| 2296 | // Function calls | ||
| 2297 | case (cache, env, Absyn.CALL(function_ = fn,functionArgs = Absyn.FUNCTIONARGS(args = args,argNames = nargs)), _, pre) | ||
| 2298 | algorithm | ||
| 2299 | 13 | (cache,e_1,prop) := elabCall(cache,env, fn, args, nargs, inExp.typeVars, true,pre,info); | |
| 2300 | then | ||
| 2301 | (cache,e_1,prop); | ||
| 2302 | |||
| 2303 | // PR. Get the properties for each expression in the tuple. | ||
| 2304 | // Each expression has its own constflag. | ||
| 2305 | // The output from functions does just have one const flag. Fix this!! | ||
| 2306 | case (cache, env, Absyn.TUPLE(expressions = (es as (_ :: _))), impl, pre) | ||
| 2307 | algorithm | ||
| 2308 | ✗ | (cache,es_1,props) := elabTuple(cache,env,es,impl,false,pre,info,false); | |
| 2309 | ✗ | (types,consts) := splitProps(props); | |
| 2310 | ✗ | then | |
| 2311 | (cache,DAE.TUPLE(es_1),DAE.PROP_TUPLE(DAE.T_TUPLE(types,NONE()),DAE.TUPLE_CONST(consts))); | ||
| 2312 | |||
| 2313 | // array-related expressions | ||
| 2314 | case (cache, env, Absyn.RANGE(start = start,step = NONE(),stop = stop), impl, pre) | ||
| 2315 | algorithm | ||
| 2316 | ✗ | (cache,start_1,DAE.PROP(start_t,c_start)) := elabGraphicsExp(cache,env, start, impl,pre,info); | |
| 2317 | ✗ | (cache,stop_1,DAE.PROP(stop_t,c_stop)) := elabGraphicsExp(cache,env, stop, impl,pre,info); | |
| 2318 | ✗ | (_,NONE(),_,rt) := deoverloadRange(start_1,start_t,NONE(),NONE(),stop_1,stop_t,info); | |
| 2319 | ✗ | const := Types.constAnd(c_start, c_stop); | |
| 2320 | ✗ | (cache, t) := elabRangeType(cache, env, start_1, NONE(), stop_1, start_t, rt, const, impl); | |
| 2321 | ✗ | then | |
| 2322 | (cache,DAE.RANGE(t,start_1,NONE(),stop_1),DAE.PROP(t,const)); | ||
| 2323 | |||
| 2324 | case (cache, env, Absyn.RANGE(start = start,step = SOME(step),stop = stop), impl, pre) | ||
| 2325 | algorithm | ||
| 2326 | ✗ | (cache,start_1,DAE.PROP(start_t,c_start)) := elabGraphicsExp(cache,env, start, impl,pre,info) "fprintln(\"setr\", \"elab_graphics_exp_range2\") &" ; | |
| 2327 | ✗ | (cache,step_1,DAE.PROP(step_t,c_step)) := elabGraphicsExp(cache,env, step, impl,pre,info); | |
| 2328 | ✗ | (cache,stop_1,DAE.PROP(stop_t,c_stop)) := elabGraphicsExp(cache,env, stop, impl,pre,info); | |
| 2329 | ✗ | (start_2,SOME(step_2),stop_2,rt) := deoverloadRange(start_1,start_t, SOME(step_1),SOME(step_t), stop_1,stop_t,info); | |
| 2330 | ✗ | c1 := Types.constAnd(c_start, c_step); | |
| 2331 | ✗ | const := Types.constAnd(c1, c_stop); | |
| 2332 | ✗ | (cache, t) := elabRangeType(cache, env, start_1, SOME(step_1), stop_1, start_t, rt, const, impl); | |
| 2333 | ✗ | then | |
| 2334 | (cache,DAE.RANGE(t,start_2,SOME(step_2),stop_2),DAE.PROP(t,const)); | ||
| 2335 | |||
| 2336 | case (cache, env, Absyn.ARRAY(arrayExp = es), impl, pre) | ||
| 2337 | algorithm | ||
| 2338 | ✗ | (cache,es_1,DAE.PROP(t,const)) := elabGraphicsArray(cache,env, es, impl,pre,info); | |
| 2339 | ✗ | l := listLength(es_1); | |
| 2340 | ✗ | at := Types.simplifyType(t); | |
| 2341 | ✗ | a := Types.isArray(t); | |
| 2342 | ✗ | then | |
| 2343 | (cache,DAE.ARRAY(at,a,es_1),DAE.PROP(DAE.T_ARRAY(t, {DAE.DIM_INTEGER(l)}),const)); | ||
| 2344 | |||
| 2345 | case (cache, env, Absyn.MATRIX(matrix = ess), impl, pre) | ||
| 2346 | algorithm | ||
| 2347 | ✗ | (cache,dess,tps) := elabExpListList(cache,env,ess,impl,true,pre,info); | |
| 2348 | ✗ | tps_1 := List.mapList(tps, Types.getPropType); | |
| 2349 | ✗ | tps_2 := List.flatten(tps_1); | |
| 2350 | ✗ | nmax := matrixConstrMaxDim(tps_2); | |
| 2351 | ✗ | havereal := Types.containReal(tps_2); | |
| 2352 | ✗ | (cache,mexp,DAE.PROP(t,c),dim1,dim2) := elabMatrixSemi(cache,env,dess,tps,impl,havereal,nmax,true,pre,info); | |
| 2353 | ✗ | elabMatrixToMatrixExp(mexp); // TODO: Does this do anything? | |
| 2354 | ✗ | t_1 := Types.unliftArray(t); | |
| 2355 | ✗ | t_2 := Types.unliftArray(t_1); | |
| 2356 | ✗ | then | |
| 2357 | (cache,mexp,DAE.PROP(DAE.T_ARRAY(DAE.T_ARRAY(t_2, {dim2}), {dim1}),c)); | ||
| 2358 | |||
| 2359 | case (_, _, e, _, pre) | ||
| 2360 | algorithm | ||
| 2361 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 2362 | ✗ | Print.printErrorBuf("- Inst.elabGraphicsExp failed: "); | |
| 2363 | ✗ | ps := PrefixUtil.printPrefixStr2(pre); | |
| 2364 | ✗ | s := Dump.printExpStr(e); | |
| 2365 | ✗ | Print.printErrorBuf(ps+s); | |
| 2366 | ✗ | Print.printErrorBuf("\n"); | |
| 2367 | ✗ | then | |
| 2368 | fail(); | ||
| 2369 | end matchcontinue; | ||
| 2370 | end elabGraphicsExp; | ||
| 2371 | |||
| 2372 | protected function deoverloadRange "Does deoverloading of range expressions. | ||
| 2373 | They can be both Integer ranges and Real ranges. | ||
| 2374 | This function determines which one to use." | ||
| 2375 | input DAE.Exp inStartExp; | ||
| 2376 | input DAE.Type inStartType; | ||
| 2377 | input Option<DAE.Exp> inStepExp; | ||
| 2378 | input Option<DAE.Type> inStepType; | ||
| 2379 | input DAE.Exp inStopExp; | ||
| 2380 | input DAE.Type inStopType; | ||
| 2381 | input SourceInfo inInfo; | ||
| 2382 | output DAE.Exp outStart; | ||
| 2383 | output Option<DAE.Exp> outStep; | ||
| 2384 | output DAE.Exp outStop; | ||
| 2385 | output DAE.Type outRangeType; | ||
| 2386 | algorithm | ||
| 2387 | (outStart, outStep, outStop, outRangeType) := match(inStartType, inStepType, inStopType) | ||
| 2388 | local | ||
| 2389 | DAE.Exp step_exp; | ||
| 2390 | DAE.Type step_ty, et; | ||
| 2391 | list<String> ns,ne; | ||
| 2392 | String e1_str, e2_str, t1_str; | ||
| 2393 | |||
| 2394 | // Boolean range has no step value. | ||
| 2395 | case (DAE.T_BOOL(), NONE(), DAE.T_BOOL()) | ||
| 2396 | then (inStartExp, NONE(), inStopExp, DAE.T_BOOL_DEFAULT); | ||
| 2397 | |||
| 2398 | case (DAE.T_INTEGER(), NONE(), DAE.T_INTEGER()) | ||
| 2399 | then (inStartExp, inStepExp, inStopExp, DAE.T_INTEGER_DEFAULT); | ||
| 2400 | |||
| 2401 | case (DAE.T_INTEGER(), SOME(DAE.T_INTEGER()), DAE.T_INTEGER()) | ||
| 2402 | then (inStartExp, inStepExp, inStopExp, DAE.T_INTEGER_DEFAULT); | ||
| 2403 | |||
| 2404 | // Enumeration range has no step value. | ||
| 2405 | case (DAE.T_ENUMERATION(names = ns), NONE(), DAE.T_ENUMERATION(names = ne)) | ||
| 2406 | algorithm | ||
| 2407 | // check if enumtype start and end are equal | ||
| 2408 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | if List.isEqual(ns,ne,true) then |
| 2409 | // convert vars | ||
| 2410 | 4 | et := Types.simplifyType(inStartType); | |
| 2411 | else | ||
| 2412 | // Print an error if the enumerations are different for start and stop. | ||
| 2413 | ✗ | e1_str := ExpressionBasics.printExpStr(inStartExp); | |
| 2414 | ✗ | e2_str := ExpressionBasics.printExpStr(inStopExp); | |
| 2415 | ✗ | t1_str := TypesDump.unparseTypeNoAttr(inStartType); | |
| 2416 | ✗ | Error.addSourceMessageAndFail(Error.UNRESOLVABLE_TYPE, | |
| 2417 | {e1_str + ":" + e2_str, t1_str + ", " + t1_str, ""}, inInfo); | ||
| 2418 | end if; | ||
| 2419 | then | ||
| 2420 | (inStartExp, NONE(), inStopExp, et); | ||
| 2421 | |||
| 2422 | case (_, NONE(), _) | ||
| 2423 | algorithm | ||
| 2424 |
3/6✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
|
4 | ({outStart, outStop},_) := OperatorOverloading.elabArglist( |
| 2425 | {DAE.T_REAL_DEFAULT, DAE.T_REAL_DEFAULT}, | ||
| 2426 | {(inStartExp, inStartType), (inStopExp, inStopType)}); | ||
| 2427 | then | ||
| 2428 | (outStart, NONE(), outStop, DAE.T_REAL_DEFAULT); | ||
| 2429 | |||
| 2430 | case (_, SOME(step_ty), _) | ||
| 2431 | algorithm | ||
| 2432 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
3 | SOME(step_exp) := inStepExp; |
| 2433 |
4/8✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 3 times.
|
6 | ({outStart, step_exp, outStop},_) := OperatorOverloading.elabArglist( |
| 2434 | {DAE.T_REAL_DEFAULT, DAE.T_REAL_DEFAULT, DAE.T_REAL_DEFAULT}, | ||
| 2435 | {(inStartExp, inStartType), (step_exp, step_ty), (inStopExp, inStopType)}); | ||
| 2436 | then | ||
| 2437 | (outStart, SOME(step_exp), outStop, DAE.T_REAL_DEFAULT); | ||
| 2438 | |||
| 2439 | end match; | ||
| 2440 | end deoverloadRange; | ||
| 2441 | |||
| 2442 | protected function elabRangeType | ||
| 2443 | "This function creates a type for a range expression given by a start, stop, | ||
| 2444 | and optional step expression. This function always succeeds, but may return an | ||
| 2445 | array-type of unknown size if the expressions can't be constant evaluated." | ||
| 2446 | input FCore.Cache inCache; | ||
| 2447 | input FCore.Graph inEnv; | ||
| 2448 | input DAE.Exp inStart; | ||
| 2449 | input Option<DAE.Exp> inStep; | ||
| 2450 | input DAE.Exp inStop; | ||
| 2451 | input DAE.Type inType; | ||
| 2452 | input DAE.Type inExpType; | ||
| 2453 | input DAE.Const co; | ||
| 2454 | input Boolean inImpl; | ||
| 2455 | output FCore.Cache outCache; | ||
| 2456 | output DAE.Type outType; | ||
| 2457 | algorithm | ||
| 2458 | (outCache, outType) := matchcontinue(inStep, co) | ||
| 2459 | local | ||
| 2460 | DAE.Exp step_exp; | ||
| 2461 | Values.Value start_val, step_val, stop_val; | ||
| 2462 | Integer dim; | ||
| 2463 | FCore.Cache cache; | ||
| 2464 | |||
| 2465 | case (_, DAE.C_VAR()) | ||
| 2466 | 187 | then (inCache, DAE.T_ARRAY(inType, {DAE.DIM_UNKNOWN()})); | |
| 2467 | |||
| 2468 | // No step value. | ||
| 2469 | case (NONE(), _) | ||
| 2470 | algorithm | ||
| 2471 | 1742 | (cache, start_val) := Ceval.ceval(inCache, inEnv, inStart, inImpl); | |
| 2472 | 1742 | (cache, stop_val) := Ceval.ceval(cache, inEnv, inStop, inImpl); | |
| 2473 | 1739 | dim := elabRangeSize(start_val, NONE(), stop_val); | |
| 2474 | 3478 | then | |
| 2475 | (cache, DAE.T_ARRAY(inType, {DAE.DIM_INTEGER(dim)})); | ||
| 2476 | |||
| 2477 | // Some step value. | ||
| 2478 | case (SOME(step_exp), _) | ||
| 2479 | algorithm | ||
| 2480 | 18 | (cache, start_val) := Ceval.ceval(inCache, inEnv, inStart, inImpl); | |
| 2481 | 18 | (cache, step_val) := Ceval.ceval(cache, inEnv, step_exp, inImpl); | |
| 2482 | 18 | (cache, stop_val) := Ceval.ceval(cache, inEnv, inStop, inImpl); | |
| 2483 | 18 | dim := elabRangeSize(start_val, SOME(step_val), stop_val); | |
| 2484 | 36 | then | |
| 2485 | (cache, DAE.T_ARRAY(inType, {DAE.DIM_INTEGER(dim)})); | ||
| 2486 | |||
| 2487 | // Ceval failed in previous cases, return an array of unknown size. | ||
| 2488 | 3 | else (inCache, DAE.T_ARRAY(inType, {DAE.DIM_UNKNOWN()})); | |
| 2489 | end matchcontinue; | ||
| 2490 | end elabRangeType; | ||
| 2491 | |||
| 2492 | protected function elabRangeSize | ||
| 2493 | "Returns the size of a range, given a start, stop, and optional step value." | ||
| 2494 | input Values.Value inStartValue; | ||
| 2495 | input Option<Values.Value> inStepValue; | ||
| 2496 | input Values.Value inStopValue; | ||
| 2497 | output Integer outSize; | ||
| 2498 | algorithm | ||
| 2499 | outSize := matchcontinue(inStartValue, inStepValue, inStopValue) | ||
| 2500 | local | ||
| 2501 | Integer int_start, int_step, int_stop, dim; | ||
| 2502 | Real real_start, real_step, real_stop; | ||
| 2503 | |||
| 2504 | // start:stop where start > stop gives an empty vector. | ||
| 2505 | case (_, NONE(), _) | ||
| 2506 | algorithm | ||
| 2507 | // start > stop == not (start <= stop) | ||
| 2508 |
2/2✓ Branch 1 taken 1617 times.
✓ Branch 2 taken 122 times.
|
1739 | false := ValuesUtil.safeLessEq(inStartValue, inStopValue); |
| 2509 | then | ||
| 2510 | 0; | ||
| 2511 | |||
| 2512 | case (Values.INTEGER(int_start), NONE(), Values.INTEGER(int_stop)) | ||
| 2513 | algorithm | ||
| 2514 | 1610 | dim := int_stop - int_start + 1; | |
| 2515 | then | ||
| 2516 | dim; | ||
| 2517 | |||
| 2518 | case (Values.INTEGER(int_start), SOME(Values.INTEGER(int_step)), | ||
| 2519 | Values.INTEGER(int_stop)) | ||
| 2520 | algorithm | ||
| 2521 | 15 | dim := int_stop - int_start; | |
| 2522 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
15 | dim := intDiv(dim, int_step) + 1; |
| 2523 | then | ||
| 2524 | dim; | ||
| 2525 | |||
| 2526 | case (Values.REAL(real_start), NONE(), Values.REAL(real_stop)) | ||
| 2527 | ✗ | then Util.realRangeSize(real_start, 1.0, real_stop); | |
| 2528 | |||
| 2529 | case (Values.REAL(real_start), SOME(Values.REAL(real_step)), | ||
| 2530 | Values.REAL(real_stop)) | ||
| 2531 | 3 | then Util.realRangeSize(real_start, real_step, real_stop); | |
| 2532 | |||
| 2533 | case (Values.ENUM_LITERAL(index = int_start), NONE(), | ||
| 2534 | Values.ENUM_LITERAL(index = int_stop)) | ||
| 2535 | algorithm | ||
| 2536 | 4 | dim := int_stop - int_start + 1; | |
| 2537 | then | ||
| 2538 | dim; | ||
| 2539 | |||
| 2540 | case (Values.BOOL(true), NONE(), Values.BOOL(false)) then 0; | ||
| 2541 | case (Values.BOOL(false), NONE(), Values.BOOL(true)) then 2; | ||
| 2542 | case (Values.BOOL(_), NONE(), Values.BOOL(_)) then 1; | ||
| 2543 | end matchcontinue; | ||
| 2544 | end elabRangeSize; | ||
| 2545 | |||
| 2546 | protected function elabTuple | ||
| 2547 | "This function does elaboration of tuples, i.e. function calls returning several values." | ||
| 2548 | input FCore.Cache inCache; | ||
| 2549 | input FCore.Graph inEnv; | ||
| 2550 | input list<Absyn.Exp> inExpl; | ||
| 2551 | input Boolean inImplicit; | ||
| 2552 | input Boolean inDoVect; | ||
| 2553 | input DAE.Prefix inPrefix; | ||
| 2554 | input SourceInfo inInfo; | ||
| 2555 | input Boolean isLhs; | ||
| 2556 | output FCore.Cache outCache = inCache; | ||
| 2557 | output list<DAE.Exp> outExpl = {}; | ||
| 2558 | output list<DAE.Properties> outProperties = {}; | ||
| 2559 | protected | ||
| 2560 | DAE.Exp exp; | ||
| 2561 | DAE.Properties prop; | ||
| 2562 | algorithm | ||
| 2563 | |||
| 2564 |
4/4✓ Branch 0 taken 3068 times.
✓ Branch 1 taken 82 times.
✓ Branch 3 taken 3067 times.
✓ Branch 4 taken 1 time.
|
3150 | if if not isLhs then not Config.acceptMetaModelicaGrammar() else false then |
| 2565 | 2 | Error.addSourceMessage(Error.RHS_TUPLE_EXPRESSION, {Dump.printExpStr(Absyn.TUPLE(inExpl))}, inInfo); | |
| 2566 | 1 | fail(); | |
| 2567 | end if; | ||
| 2568 | |||
| 2569 |
2/2✓ Branch 0 taken 6300 times.
✓ Branch 1 taken 3149 times.
|
9449 | for e in inExpl loop |
| 2570 | 6300 | (outCache, exp, prop) := | |
| 2571 | elabExp(outCache, inEnv, e, inImplicit, inDoVect, inPrefix, inInfo); | ||
| 2572 | |||
| 2573 |
2/2✓ Branch 1 taken 91 times.
✓ Branch 2 taken 6209 times.
|
6300 | if AbsynUtil.isTuple(e) then |
| 2574 | 91 | (exp, prop) := Types.matchProp(exp, prop, | |
| 2575 | DAE.PROP(DAE.T_METABOXED_DEFAULT, DAE.C_CONST()), true); | ||
| 2576 | end if; | ||
| 2577 | |||
| 2578 | 6300 | outExpl := exp :: outExpl; | |
| 2579 | 6300 | outProperties := prop :: outProperties; | |
| 2580 | end for; | ||
| 2581 | |||
| 2582 | 3149 | outExpl := listReverse(outExpl); | |
| 2583 | 3149 | outProperties := listReverse(outProperties); | |
| 2584 | end elabTuple; | ||
| 2585 | |||
| 2586 | protected function stripExtraArgsFromType | ||
| 2587 | input list<Slot> slots; | ||
| 2588 | input DAE.Type inType; | ||
| 2589 | output DAE.Type outType = inType; | ||
| 2590 | algorithm | ||
| 2591 | outType := matchcontinue outType | ||
| 2592 | case DAE.T_FUNCTION() | ||
| 2593 | algorithm | ||
| 2594 | 35 | outType.funcArg := stripExtraArgsFromType2(slots, outType.funcArg); | |
| 2595 | then | ||
| 2596 | outType; | ||
| 2597 | |||
| 2598 | else | ||
| 2599 | algorithm | ||
| 2600 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 2601 | ✗ | Debug.trace("- Static.stripExtraArgsFromType failed\n"); | |
| 2602 | ✗ | then | |
| 2603 | fail(); | ||
| 2604 | end matchcontinue; | ||
| 2605 | end stripExtraArgsFromType; | ||
| 2606 | |||
| 2607 | protected function stripExtraArgsFromType2 | ||
| 2608 | input list<Slot> inSlots; | ||
| 2609 | input list<DAE.FuncArg> inType; | ||
| 2610 | input list<DAE.FuncArg> inAccumType = {}; | ||
| 2611 | output list<DAE.FuncArg> outType; | ||
| 2612 | algorithm | ||
| 2613 | outType := match(inSlots, inType) | ||
| 2614 | local | ||
| 2615 | list<Slot> slotsRest; | ||
| 2616 | list<DAE.FuncArg> rest; | ||
| 2617 | DAE.FuncArg arg; | ||
| 2618 | |||
| 2619 | case (SLOT(slotFilled = true) :: slotsRest, _ :: rest) | ||
| 2620 | 60 | then stripExtraArgsFromType2(slotsRest, rest, inAccumType); | |
| 2621 | |||
| 2622 | case (SLOT(slotFilled = false) :: slotsRest, arg :: rest) | ||
| 2623 | 35 | then stripExtraArgsFromType2(slotsRest, rest, arg :: inAccumType); | |
| 2624 | |||
| 2625 | 35 | case ({}, {}) then listReverse(inAccumType); | |
| 2626 | end match; | ||
| 2627 | end stripExtraArgsFromType2; | ||
| 2628 | |||
| 2629 | protected function elabArray | ||
| 2630 | "This function elaborates on array expressions. | ||
| 2631 | |||
| 2632 | All types of an array should be equivalent. However, mixed Integer and Real | ||
| 2633 | elements are allowed in an array and in that case the Integer elements are | ||
| 2634 | converted to Real elements." | ||
| 2635 | input list<DAE.Exp> inExpl; | ||
| 2636 | input list<DAE.Properties> inProps; | ||
| 2637 | input DAE.Prefix inPrefix; | ||
| 2638 | input SourceInfo inInfo; | ||
| 2639 | output list<DAE.Exp> outExpLst; | ||
| 2640 | output DAE.Properties outProperties; | ||
| 2641 | protected | ||
| 2642 | list<DAE.Type> types = {}; | ||
| 2643 | DAE.Type ty; | ||
| 2644 | DAE.Const c = DAE.C_CONST(), c2; | ||
| 2645 | Boolean mixed; | ||
| 2646 | algorithm | ||
| 2647 | // Empty array constructors are not allowed in Modelica. | ||
| 2648 |
1/2✓ Branch 0 taken 51407 times.
✗ Branch 1 not taken.
|
51407 | if listEmpty(inExpl) then |
| 2649 | ✗ | Error.addSourceMessage(Error.EMPTY_ARRAY, {}, inInfo); | |
| 2650 | ✗ | fail(); | |
| 2651 | end if; | ||
| 2652 | |||
| 2653 | // Get the types of all elements, and the array's variability. | ||
| 2654 |
2/2✓ Branch 0 taken 216889 times.
✓ Branch 1 taken 51407 times.
|
268296 | for p in inProps loop |
| 2655 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 216889 times.
|
216889 | DAE.PROP(type_ = ty, constFlag = c2) := p; |
| 2656 | types := ty :: types; | ||
| 2657 | 216889 | c := Types.constAnd(c, c2); | |
| 2658 | end for; | ||
| 2659 | 51407 | types := listReverse(types); | |
| 2660 | |||
| 2661 | // Check if the array contains a mix of ints and reals. | ||
| 2662 | 51407 | (ty, mixed) := elabArrayHasMixedIntReals(types); | |
| 2663 | |||
| 2664 |
2/2✓ Branch 0 taken 999 times.
✓ Branch 1 taken 50408 times.
|
51407 | if mixed then |
| 2665 | 999 | outExpLst := elabArrayReal2(inExpl, types, ty); | |
| 2666 | else | ||
| 2667 | 50408 | (outExpLst, ty) := elabArray2(inExpl, types, inPrefix, inInfo); | |
| 2668 | end if; | ||
| 2669 | |||
| 2670 | 51407 | outProperties := DAE.PROP(ty, c); | |
| 2671 | end elabArray; | ||
| 2672 | |||
| 2673 | protected function elabArrayHasMixedIntReals | ||
| 2674 | "Helper function to elabArray. Checks if a list of types contains both | ||
| 2675 | Integer and Real types, and returns the first Real type if it does." | ||
| 2676 | input list<DAE.Type> inTypes; | ||
| 2677 | output DAE.Type outType; | ||
| 2678 | output Boolean outIsMixed = true; | ||
| 2679 | protected | ||
| 2680 | DAE.Type ty; | ||
| 2681 | list<DAE.Type> rest_tys; | ||
| 2682 | algorithm | ||
| 2683 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 51407 times.
|
51407 | outType :: rest_tys := inTypes; |
| 2684 | |||
| 2685 | // If the first element is a Real, search for an Integer. | ||
| 2686 |
2/2✓ Branch 1 taken 31532 times.
✓ Branch 2 taken 19875 times.
|
51407 | if Types.isReal(outType) then |
| 2687 |
2/2✓ Branch 0 taken 118953 times.
✓ Branch 1 taken 31114 times.
|
150067 | while not listEmpty(rest_tys) loop |
| 2688 | 118953 | ty :: rest_tys := rest_tys; | |
| 2689 | |||
| 2690 |
2/2✓ Branch 1 taken 118535 times.
✓ Branch 2 taken 418 times.
|
118953 | if Types.isInteger(ty) then |
| 2691 | 418 | return; | |
| 2692 | end if; | ||
| 2693 | end while; | ||
| 2694 | // If the first element is an Integer, search for a Real. | ||
| 2695 | elseif Types.isInteger(outType) then | ||
| 2696 |
2/2✓ Branch 0 taken 37942 times.
✓ Branch 1 taken 15358 times.
|
53300 | while not listEmpty(rest_tys) loop |
| 2697 | 37942 | outType :: rest_tys := rest_tys; | |
| 2698 | |||
| 2699 |
2/2✓ Branch 1 taken 37361 times.
✓ Branch 2 taken 581 times.
|
37942 | if Types.isReal(outType) then |
| 2700 | 581 | return; | |
| 2701 | end if; | ||
| 2702 | end while; | ||
| 2703 | end if; | ||
| 2704 | |||
| 2705 | outIsMixed := false; | ||
| 2706 | end elabArrayHasMixedIntReals; | ||
| 2707 | |||
| 2708 | protected function elabArrayConst | ||
| 2709 | "Constructs a const value from a list of properties, using constAnd." | ||
| 2710 | input list<DAE.Properties> inProperties; | ||
| 2711 | output DAE.Const outConst = DAE.C_CONST(); | ||
| 2712 | algorithm | ||
| 2713 |
2/2✓ Branch 0 taken 156 times.
✓ Branch 1 taken 69 times.
|
225 | for prop in inProperties loop |
| 2714 | 156 | outConst := Types.constAnd(outConst, Types.getPropConst(prop)); | |
| 2715 | end for; | ||
| 2716 | end elabArrayConst; | ||
| 2717 | |||
| 2718 | protected function elabArrayReal2 | ||
| 2719 | "Applies type_convert to all expressions in a list to the type given as | ||
| 2720 | argument." | ||
| 2721 | input list<DAE.Exp> inExpl; | ||
| 2722 | input list<DAE.Type> inTypes; | ||
| 2723 | input DAE.Type inExpectedType; | ||
| 2724 | output list<DAE.Exp> outExpl = {}; | ||
| 2725 | protected | ||
| 2726 | DAE.Exp exp; | ||
| 2727 | list<DAE.Exp> rest_expl = inExpl; | ||
| 2728 | algorithm | ||
| 2729 |
2/2✓ Branch 0 taken 4764 times.
✓ Branch 1 taken 999 times.
|
5763 | for ty in inTypes loop |
| 2730 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4764 times.
|
4764 | exp :: rest_expl := rest_expl; |
| 2731 | |||
| 2732 | // If the types are not equivalent, type convert the expression. | ||
| 2733 |
2/2✓ Branch 1 taken 3155 times.
✓ Branch 2 taken 1609 times.
|
4764 | if not Types.equivtypes(ty, inExpectedType) then |
| 2734 | 3155 | exp := Types.matchType(exp, ty, inExpectedType, true); | |
| 2735 | end if; | ||
| 2736 | |||
| 2737 | outExpl := exp :: outExpl; | ||
| 2738 | end for; | ||
| 2739 | |||
| 2740 | 999 | outExpl := listReverse(outExpl); | |
| 2741 | end elabArrayReal2; | ||
| 2742 | |||
| 2743 | protected function elabArray2 | ||
| 2744 | "Helper function to elabArray, checks that all elements are equivalent." | ||
| 2745 | input list<DAE.Exp> inExpl; | ||
| 2746 | input list<DAE.Type> inTypes; | ||
| 2747 | input DAE.Prefix inPrefix; | ||
| 2748 | input SourceInfo inInfo; | ||
| 2749 | output list<DAE.Exp> outExpl; | ||
| 2750 | output DAE.Type outType; | ||
| 2751 | protected | ||
| 2752 | DAE.Type ty2; | ||
| 2753 | list<DAE.Type> rest_tys; | ||
| 2754 | DAE.Exp exp1; | ||
| 2755 | list<DAE.Exp> rest_expl; | ||
| 2756 | String pre_str, exp_str, expl_str, ty1_str, ty2_str; | ||
| 2757 | algorithm | ||
| 2758 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 50408 times.
|
50408 | exp1 :: rest_expl := inExpl; |
| 2759 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 50408 times.
|
50408 | outType :: rest_tys := inTypes; |
| 2760 | |||
| 2761 | 50408 | outExpl := {exp1}; | |
| 2762 | 50408 | outType := Types.getUniontypeIfMetarecordReplaceAllSubtypes(outType); | |
| 2763 | |||
| 2764 |
2/2✓ Branch 0 taken 161717 times.
✓ Branch 1 taken 50408 times.
|
212125 | for exp2 in rest_expl loop |
| 2765 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 161717 times.
|
161717 | ty2 :: rest_tys := rest_tys; |
| 2766 | 161717 | ty2 := Types.getUniontypeIfMetarecordReplaceAllSubtypes(ty2); | |
| 2767 | |||
| 2768 | // If the types are not equivalent, try type conversion. | ||
| 2769 |
2/2✓ Branch 1 taken 445 times.
✓ Branch 2 taken 161272 times.
|
161717 | if not Types.equivtypes(outType, ty2) then |
| 2770 | try | ||
| 2771 | 445 | (exp2, outType) := Types.matchType(exp2, outType, ty2, false); | |
| 2772 | else | ||
| 2773 | ✗ | ty1_str := TypesDump.unparseTypeNoAttr(outType); | |
| 2774 | ✗ | ty2_str := TypesDump.unparseTypeNoAttr(ty2); | |
| 2775 | ✗ | Types.typeErrorSanityCheck(ty1_str, ty2_str, inInfo); | |
| 2776 | ✗ | pre_str := PrefixUtil.printPrefixStr(inPrefix); | |
| 2777 | ✗ | exp_str := ExpressionBasics.printExpStr(exp2); | |
| 2778 | ✗ | expl_str := List.toStringCustom(inExpl, ExpressionBasics.printExpStr, "", "[", ",", "]", true); | |
| 2779 | ✗ | Error.addSourceMessageAndFail(Error.TYPE_MISMATCH_ARRAY_EXP, | |
| 2780 | {pre_str, exp_str, ty1_str, expl_str, ty2_str}, inInfo); | ||
| 2781 | end try; | ||
| 2782 | end if; | ||
| 2783 | |||
| 2784 | outExpl := exp2 :: outExpl; | ||
| 2785 | end for; | ||
| 2786 | |||
| 2787 | 50408 | outExpl := listReverse(outExpl); | |
| 2788 | end elabArray2; | ||
| 2789 | |||
| 2790 | protected function elabGraphicsArray | ||
| 2791 | "This function elaborates array expressions for graphics elaboration." | ||
| 2792 | input FCore.Cache inCache; | ||
| 2793 | input FCore.Graph inEnv; | ||
| 2794 | input list<Absyn.Exp> inExpl; | ||
| 2795 | input Boolean inImplicit; | ||
| 2796 | input DAE.Prefix inPrefix; | ||
| 2797 | input SourceInfo inInfo; | ||
| 2798 | output FCore.Cache outCache = inCache; | ||
| 2799 | output list<DAE.Exp> outExpl = {}; | ||
| 2800 | output DAE.Properties outProperties; | ||
| 2801 | protected | ||
| 2802 | DAE.Const c = DAE.C_CONST(), c2; | ||
| 2803 | DAE.Exp exp; | ||
| 2804 | DAE.Type ty; | ||
| 2805 | algorithm | ||
| 2806 | // Empty array constructors are not allowed in Modelica. | ||
| 2807 | ✗ | if listEmpty(inExpl) then | |
| 2808 | ✗ | Error.addSourceMessage(Error.EMPTY_ARRAY, {}, inInfo); | |
| 2809 | ✗ | fail(); | |
| 2810 | end if; | ||
| 2811 | |||
| 2812 | ✗ | for e in inExpl loop | |
| 2813 | ✗ | (outCache, exp, DAE.PROP(ty, c2)) := | |
| 2814 | elabGraphicsExp(outCache, inEnv, e, inImplicit, inPrefix, inInfo); | ||
| 2815 | outExpl := exp :: outExpl; | ||
| 2816 | ✗ | c := Types.constAnd(c, c2); | |
| 2817 | end for; | ||
| 2818 | |||
| 2819 | ✗ | outExpl := listReverse(outExpl); | |
| 2820 | ✗ | outProperties := DAE.PROP(ty, c); | |
| 2821 | end elabGraphicsArray; | ||
| 2822 | |||
| 2823 | protected function elabMatrixComma "This function is a helper function for elabMatrixSemi. | ||
| 2824 | It elaborates one matrix row of a matrix." | ||
| 2825 | input list<DAE.Exp> inExpl; | ||
| 2826 | input list<DAE.Properties> inProps; | ||
| 2827 | input Boolean inHaveReal; | ||
| 2828 | input Integer inDims; | ||
| 2829 | input SourceInfo inInfo; | ||
| 2830 | output DAE.Exp outExp; | ||
| 2831 | output DAE.Properties outProperties; | ||
| 2832 | output DAE.Dimension outDim1; | ||
| 2833 | output DAE.Dimension outDim2; | ||
| 2834 | protected | ||
| 2835 | DAE.Exp exp; | ||
| 2836 | list<DAE.Exp> rest_expl, accum_expl = {}; | ||
| 2837 | DAE.Properties prop; | ||
| 2838 | list<DAE.Properties> rest_props; | ||
| 2839 | DAE.Type ty, sty; | ||
| 2840 | DAE.Dimension dim1, dim2; | ||
| 2841 | algorithm | ||
| 2842 | try | ||
| 2843 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1719 times.
|
1719 | exp :: rest_expl := inExpl; |
| 2844 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1719 times.
|
1719 | prop :: rest_props := inProps; |
| 2845 | |||
| 2846 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1719 times.
|
1719 | (exp, outProperties as DAE.PROP(type_ = ty)) := promoteExp(exp, prop, inDims); |
| 2847 | 1719 | accum_expl := exp :: accum_expl; | |
| 2848 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 1719 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1719 times.
|
1719 | outDim1 :: outDim2 :: _ := TypesDump.getDimensions(ty); |
| 2849 | |||
| 2850 |
2/2✓ Branch 0 taken 3724 times.
✓ Branch 1 taken 1719 times.
|
5443 | while not listEmpty(rest_expl) loop |
| 2851 | 3724 | exp :: rest_expl := rest_expl; | |
| 2852 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3724 times.
|
3724 | prop :: rest_props := rest_props; |
| 2853 | |||
| 2854 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3724 times.
|
3724 | (exp, prop as DAE.PROP(type_ = ty)) := promoteExp(exp, prop, inDims); |
| 2855 | 3724 | accum_expl := exp :: accum_expl; | |
| 2856 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 3724 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3724 times.
|
3724 | dim1 :: dim2 :: _ := TypesDump.getDimensions(ty); |
| 2857 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3724 times.
|
3724 | if not Expression.dimensionsEqual(dim1, outDim1) then |
| 2858 | ✗ | Error.addSourceMessageAndFail(Error.COMMA_OPERATOR_DIFFERENT_SIZES, {ExpressionBasics.printExpStr(listHead(inExpl)), ExpressionBasics.dimensionString(outDim1), ExpressionBasics.printExpStr(exp), ExpressionBasics.dimensionString(dim1)}, inInfo); | |
| 2859 | end if; | ||
| 2860 | // Comma between matrices => concatenation along second dimension. | ||
| 2861 | 3724 | outDim2 := Expression.dimensionsAdd(dim2, outDim2); | |
| 2862 | 3724 | outProperties := Types.matchWithPromote(prop, outProperties, inHaveReal); | |
| 2863 | end while; | ||
| 2864 | |||
| 2865 | 1719 | sty := Expression.liftArrayLeftList(Expression.unliftArrayX(ty, 2), {outDim1, outDim2}); | |
| 2866 | 1719 | outExp := DAE.ARRAY(sty, false, listReverse(accum_expl)); | |
| 2867 | else | ||
| 2868 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 2869 | ✗ | Debug.traceln("- Static.elabMatrixComma failed"); | |
| 2870 | ✗ | fail(); | |
| 2871 | end try; | ||
| 2872 | end elabMatrixComma; | ||
| 2873 | |||
| 2874 | protected function elabMatrixCatTwoExp "author: PA | ||
| 2875 | This function takes an array expression of dimension >=3 and | ||
| 2876 | concatenates each array element along the second dimension. | ||
| 2877 | For instance | ||
| 2878 | elab_matrix_cat_two( {{1,2;5,6}, {3,4;7,8}}) => {1,2,3,4;5,6,7,8}" | ||
| 2879 | input DAE.Exp inExp; | ||
| 2880 | output DAE.Exp outExp; | ||
| 2881 | protected | ||
| 2882 | list<DAE.Exp> expl; | ||
| 2883 | algorithm | ||
| 2884 | try | ||
| 2885 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1719 times.
|
1719 | DAE.ARRAY(array = expl) := inExp; |
| 2886 | 1719 | expl := ExpressionSimplify.simplifyList(expl); | |
| 2887 |
4/4✓ Branch 0 taken 5443 times.
✓ Branch 1 taken 1719 times.
✓ Branch 2 taken 5443 times.
✓ Branch 3 taken 1719 times.
|
7162 | expl := list(Expression.matrixToArray(e) for e in expl); |
| 2888 | 1719 | outExp := elabMatrixCatTwo(expl); | |
| 2889 | else | ||
| 2890 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 2891 | ✗ | Debug.traceln("- Static.elabMatrixCatTwoExp failed"); | |
| 2892 | ✗ | fail(); | |
| 2893 | end try; | ||
| 2894 | end elabMatrixCatTwoExp; | ||
| 2895 | |||
| 2896 | protected function elabMatrixCatTwo "author: PA | ||
| 2897 | Concatenates a list of matrix(or higher dim) expressions along | ||
| 2898 | the second dimension." | ||
| 2899 | input list<DAE.Exp> inExpl; | ||
| 2900 | output DAE.Exp outExp; | ||
| 2901 | protected | ||
| 2902 | DAE.Type ty; | ||
| 2903 | algorithm | ||
| 2904 | try | ||
| 2905 |
7/8✓ Branch 1 taken 5443 times.
✓ Branch 2 taken 1716 times.
✓ Branch 3 taken 5443 times.
✓ Branch 4 taken 1716 times.
✓ Branch 5 taken 1719 times.
✓ Branch 6 taken 3724 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1716 times.
|
8878 | outExp := elabMatrixCatTwo2(e for e in listReverse(inExpl)); |
| 2906 | else | ||
| 2907 | 3 | ty := Expression.typeof(listHead(inExpl)); | |
| 2908 | 3 | outExp := Expression.makePureBuiltinCall("cat", DAE.ICONST(2) :: inExpl, ty); | |
| 2909 | end try; | ||
| 2910 | end elabMatrixCatTwo; | ||
| 2911 | |||
| 2912 | protected function elabMatrixCatTwo2 "Helper function to elabMatrixCatTwo | ||
| 2913 | Concatenates two array expressions that are matrices (or higher dimension) | ||
| 2914 | along the first dimension (row)." | ||
| 2915 | input DAE.Exp inExp1; | ||
| 2916 | input DAE.Exp inExp2; | ||
| 2917 | output DAE.Exp outExp; | ||
| 2918 | protected | ||
| 2919 | list<DAE.Exp> expl1, expl2; | ||
| 2920 | Boolean sc; | ||
| 2921 | DAE.Type ty; | ||
| 2922 | algorithm | ||
| 2923 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3721 times.
|
3724 | DAE.ARRAY(scalar = sc, array = expl1) := inExp1; |
| 2924 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3721 times.
|
3721 | DAE.ARRAY(array = expl2) := inExp2; |
| 2925 |
7/8✓ Branch 0 taken 3783 times.
✓ Branch 1 taken 3721 times.
✓ Branch 2 taken 3783 times.
✓ Branch 3 taken 3721 times.
✓ Branch 4 taken 3783 times.
✓ Branch 5 taken 3721 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3721 times.
|
7504 | expl1 := list(elabMatrixCatTwo3(e1, e2) threaded for e1 in expl1, e2 in expl2); |
| 2926 | 3721 | ty := Expression.typeof(listHead(expl1)); | |
| 2927 | 3721 | ty := Expression.liftArrayLeft(ty, DAE.DIM_INTEGER(listLength(expl1))); | |
| 2928 |
1/2✓ Branch 0 taken 3721 times.
✗ Branch 1 not taken.
|
7442 | outExp := DAE.ARRAY(ty, sc, expl1); |
| 2929 | end elabMatrixCatTwo2; | ||
| 2930 | |||
| 2931 | protected function elabMatrixCatTwo3 | ||
| 2932 | input DAE.Exp inExp1; | ||
| 2933 | input DAE.Exp inExp2; | ||
| 2934 | output DAE.Exp outExp; | ||
| 2935 | protected | ||
| 2936 | DAE.Type ty1, ty2; | ||
| 2937 | Boolean sc; | ||
| 2938 | list<DAE.Exp> expl1, expl2; | ||
| 2939 | algorithm | ||
| 2940 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3783 times.
|
3783 | DAE.ARRAY(ty = ty1, scalar = sc, array = expl1) := inExp1; |
| 2941 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3783 times.
|
3783 | DAE.ARRAY(ty = ty2, array = expl2) := inExp2; |
| 2942 | 3783 | expl2 := listAppend(expl1, expl2); | |
| 2943 | 3783 | ty1 := Expression.concatArrayType(ty1, ty2); | |
| 2944 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3783 times.
|
3783 | outExp := DAE.ARRAY(ty1, sc, expl2); |
| 2945 | end elabMatrixCatTwo3; | ||
| 2946 | |||
| 2947 | protected function elabMatrixCatOne "author: PA | ||
| 2948 | Concatenates a list of matrix(or higher dim) expressions along | ||
| 2949 | the first dimension. | ||
| 2950 | i.e. elabMatrixCatOne( { {1,2;3,4}, {5,6;7,8} }) => {1,2;3,4;5,6;7,8}" | ||
| 2951 | input list<DAE.Exp> inExpl; | ||
| 2952 | output DAE.Exp outExp; | ||
| 2953 | protected | ||
| 2954 | DAE.Type ty; | ||
| 2955 | algorithm | ||
| 2956 | try | ||
| 2957 | 1074 | outExp := List.reduce(inExpl, elabMatrixCatOne2); | |
| 2958 | else | ||
| 2959 | 4 | ty := Expression.typeof(listHead(inExpl)); | |
| 2960 | 4 | outExp := Expression.makePureBuiltinCall("cat", DAE.ICONST(1) :: inExpl, ty); | |
| 2961 | end try; | ||
| 2962 | end elabMatrixCatOne; | ||
| 2963 | |||
| 2964 | protected function elabMatrixCatOne2 | ||
| 2965 | "Helper function to elabMatrixCatOne. Concatenates two arrays along the | ||
| 2966 | first dimension." | ||
| 2967 | input DAE.Exp inArray1; | ||
| 2968 | input DAE.Exp inArray2; | ||
| 2969 | output DAE.Exp outExp; | ||
| 2970 | protected | ||
| 2971 | DAE.Type ety; | ||
| 2972 | Boolean at; | ||
| 2973 | DAE.Dimension dim, dim1, dim2; | ||
| 2974 | DAE.Dimensions dim_rest; | ||
| 2975 | list<DAE.Exp> expl, expl1, expl2; | ||
| 2976 | algorithm | ||
| 2977 |
4/6✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1070 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1070 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1070 times.
|
1074 | DAE.ARRAY(DAE.T_ARRAY(ety, dim1 :: dim_rest), at, expl1) := inArray1; |
| 2978 |
3/6✗ Branch 0 not taken.
✓ Branch 1 taken 1070 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1070 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1070 times.
|
1070 | DAE.ARRAY(ty = DAE.T_ARRAY(dims = dim2 :: _), array = expl2) := inArray2; |
| 2979 | 1070 | expl := listAppend(expl1, expl2); | |
| 2980 | 1070 | dim := Expression.dimensionsAdd(dim1, dim2); | |
| 2981 |
1/2✓ Branch 1 taken 1070 times.
✗ Branch 2 not taken.
|
2140 | outExp := DAE.ARRAY(DAE.T_ARRAY(ety, dim :: dim_rest), at, expl); |
| 2982 | end elabMatrixCatOne2; | ||
| 2983 | |||
| 2984 | protected function promoteExp | ||
| 2985 | "Wrapper function for Expression.promoteExp which also handles Properties." | ||
| 2986 | input DAE.Exp inExp; | ||
| 2987 | input DAE.Properties inProperties; | ||
| 2988 | input Integer inDims; | ||
| 2989 | output DAE.Exp outExp; | ||
| 2990 | output DAE.Properties outProperties; | ||
| 2991 | protected | ||
| 2992 | DAE.Type ty; | ||
| 2993 | DAE.Const c; | ||
| 2994 | algorithm | ||
| 2995 | try | ||
| 2996 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5482 times.
|
5482 | DAE.PROP(ty, c) := inProperties; |
| 2997 | 5482 | (outExp, ty) := Expression.promoteExp(inExp, ty, inDims); | |
| 2998 | 5482 | outProperties := DAE.PROP(ty, c); | |
| 2999 | else | ||
| 3000 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 3001 | ✗ | Debug.traceln("- Static.promoteExp failed"); | |
| 3002 | ✗ | fail(); | |
| 3003 | end try; | ||
| 3004 | end promoteExp; | ||
| 3005 | |||
| 3006 | protected function elabMatrixSemi | ||
| 3007 | "This function elaborates Matrix expressions, e.g. {1,0;2,1} | ||
| 3008 | A row is elaborated with elabMatrixComma." | ||
| 3009 | input FCore.Cache inCache; | ||
| 3010 | input FCore.Graph inEnv; | ||
| 3011 | input list<list<DAE.Exp>> inMatrix; | ||
| 3012 | input list<list<DAE.Properties>> inProperties; | ||
| 3013 | input Boolean inImpl; | ||
| 3014 | input Boolean inHaveReal; | ||
| 3015 | input Integer inDims; | ||
| 3016 | input Boolean inDoVectorization; | ||
| 3017 | input DAE.Prefix inPrefix; | ||
| 3018 | input SourceInfo inInfo; | ||
| 3019 | output FCore.Cache outCache = inCache; | ||
| 3020 | output DAE.Exp outExp; | ||
| 3021 | output DAE.Properties outProperties; | ||
| 3022 | output DAE.Dimension outDim1; | ||
| 3023 | output DAE.Dimension outDim2; | ||
| 3024 | protected | ||
| 3025 | list<DAE.Exp> expl; | ||
| 3026 | list<list<DAE.Exp>> rest_expl; | ||
| 3027 | list<DAE.Properties> props; | ||
| 3028 | list<list<DAE.Properties>> rest_props; | ||
| 3029 | DAE.Exp exp; | ||
| 3030 | DAE.Properties prop; | ||
| 3031 | DAE.Dimension dim1, dim2; | ||
| 3032 | String dim1_str, dim2_str, pre_str, el_str, ty1_str, ty2_str; | ||
| 3033 | algorithm | ||
| 3034 | // Elaborate the first row so we have something to compare against. | ||
| 3035 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 645 times.
|
645 | expl :: rest_expl := inMatrix; |
| 3036 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 645 times.
|
645 | props :: rest_props := inProperties; |
| 3037 | |||
| 3038 | 645 | (outExp, outProperties, outDim1, outDim2) := | |
| 3039 | elabMatrixComma(expl, props, inHaveReal, inDims, inInfo); | ||
| 3040 | 645 | outExp := elabMatrixCatTwoExp(outExp); | |
| 3041 | |||
| 3042 | // Elaborate the rest of the rows (if any). | ||
| 3043 |
2/2✓ Branch 0 taken 1074 times.
✓ Branch 1 taken 645 times.
|
1719 | while not listEmpty(rest_expl) loop |
| 3044 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1074 times.
|
1074 | expl :: rest_expl := rest_expl; |
| 3045 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1074 times.
|
1074 | props :: rest_props := rest_props; |
| 3046 | |||
| 3047 | 1074 | (exp, prop, dim1, dim2) := elabMatrixComma(expl, props, inHaveReal, inDims, inInfo); | |
| 3048 | |||
| 3049 | // Check that all rows have the same size, otherwise print an error and fail. | ||
| 3050 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1074 times.
|
1074 | if not Expression.dimensionsEqual(dim2, outDim2) then |
| 3051 | ✗ | dim1_str := ExpressionBasics.dimensionString(dim1); | |
| 3052 | ✗ | dim2_str := ExpressionBasics.dimensionString(dim2); | |
| 3053 | ✗ | pre_str := PrefixUtil.printPrefixStr3(inPrefix); | |
| 3054 | ✗ | el_str := List.toStringCustom(expl, ExpressionBasics.printExpStr, "", "{", ", ", "}", true); | |
| 3055 | ✗ | Error.addSourceMessageAndFail(Error.MATRIX_EXP_ROW_SIZE, | |
| 3056 | {pre_str, el_str, dim1_str, dim2_str}, inInfo); | ||
| 3057 | end if; | ||
| 3058 | |||
| 3059 | // Check that all rows are of the same type, otherwise print an error and fail. | ||
| 3060 | try | ||
| 3061 | 1074 | outProperties := Types.matchWithPromote(outProperties, prop, inHaveReal); | |
| 3062 | else | ||
| 3063 | ✗ | ty1_str := TypesDump.unparsePropTypeNoAttr(outProperties); | |
| 3064 | ✗ | ty2_str := TypesDump.unparsePropTypeNoAttr(prop); | |
| 3065 | ✗ | Types.typeErrorSanityCheck(ty1_str, ty2_str, inInfo); | |
| 3066 | ✗ | pre_str := PrefixUtil.printPrefixStr3(inPrefix); | |
| 3067 | ✗ | el_str := List.toStringCustom(expl, ExpressionBasics.printExpStr, "", "{", ", ", "}", true); | |
| 3068 | ✗ | Error.addSourceMessageAndFail(Error.TYPE_MISMATCH_MATRIX_EXP, | |
| 3069 | {pre_str, el_str, ty1_str, ty2_str}, inInfo); | ||
| 3070 | end try; | ||
| 3071 | |||
| 3072 | // Add the row to the matrix. | ||
| 3073 | 1074 | exp := elabMatrixCatTwoExp(exp); | |
| 3074 | 1074 | outExp := elabMatrixCatOne({outExp, exp}); | |
| 3075 | 1074 | outDim1 := Expression.dimensionsAdd(dim1, outDim1); | |
| 3076 | end while; | ||
| 3077 | end elabMatrixSemi; | ||
| 3078 | |||
| 3079 | protected function verifyBuiltInHandlerType " | ||
| 3080 | Author BZ, 2009-02 | ||
| 3081 | This function validates that arguments to function are of a correct type. | ||
| 3082 | Then call elabCallArgs to vectorize/type-match." | ||
| 3083 | input FCore.Cache inCache; | ||
| 3084 | input FCore.Graph inEnv; | ||
| 3085 | input list<Absyn.Exp> inExpl; | ||
| 3086 | input Boolean inImplicit; | ||
| 3087 | input extraFunc inTypeChecker; | ||
| 3088 | input String inFnName; | ||
| 3089 | input DAE.Prefix inPrefix; | ||
| 3090 | input SourceInfo inInfo; | ||
| 3091 | output FCore.Cache outCache; | ||
| 3092 | output DAE.Exp outExp; | ||
| 3093 | output DAE.Properties outProperties; | ||
| 3094 | |||
| 3095 | partial function extraFunc | ||
| 3096 | input DAE.Type inp1; | ||
| 3097 | output Boolean outp1; | ||
| 3098 | end extraFunc; | ||
| 3099 | protected | ||
| 3100 | Absyn.Exp e; | ||
| 3101 | DAE.Type ty; | ||
| 3102 | algorithm | ||
| 3103 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
|
2 | {e} := inExpl; |
| 3104 | 2 | (outCache, _, outProperties) := elabExpInExpression(inCache, inEnv, e, | |
| 3105 | inImplicit, true, inPrefix, inInfo); | ||
| 3106 | 2 | ty := Types.getPropType(outProperties); | |
| 3107 | 2 | ty := Types.arrayElementType(ty); | |
| 3108 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
2 | true := inTypeChecker(ty); |
| 3109 |
2/4✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
|
4 | (outCache, outExp, outProperties as DAE.PROP()) := elabCallArgs(outCache, |
| 3110 | inEnv, Absyn.FULLYQUALIFIED(Absyn.IDENT(inFnName)), {e}, {}, {}, inImplicit, | ||
| 3111 | inPrefix, inInfo); | ||
| 3112 | end verifyBuiltInHandlerType; | ||
| 3113 | |||
| 3114 | protected function elabBuiltinCardinality | ||
| 3115 | "author: PA | ||
| 3116 | This function elaborates the cardinality operator." | ||
| 3117 | input FCore.Cache inCache; | ||
| 3118 | input FCore.Graph inEnv; | ||
| 3119 | input list<Absyn.Exp> inPosArgs; | ||
| 3120 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 3121 | input Boolean inImplicit; | ||
| 3122 | input DAE.Prefix inPrefix; | ||
| 3123 | input SourceInfo inInfo; | ||
| 3124 | output FCore.Cache outCache; | ||
| 3125 | output DAE.Exp outExp; | ||
| 3126 | output DAE.Properties outProperties; | ||
| 3127 | protected | ||
| 3128 | DAE.Type ty; | ||
| 3129 | Absyn.Exp e; | ||
| 3130 | algorithm | ||
| 3131 | 762 | checkBuiltinCallArgs(inPosArgs, inNamedArgs, 1, "cardinality", inInfo); | |
| 3132 | |||
| 3133 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 762 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 762 times.
|
762 | {e} := inPosArgs; |
| 3134 | 762 | (outCache, outExp, outProperties) := elabExpInExpression(inCache, inEnv, e, | |
| 3135 | inImplicit, true, inPrefix, inInfo); | ||
| 3136 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 762 times.
|
762 | DAE.PROP(type_ = ty) := outProperties; |
| 3137 | 762 | ty := Types.liftArrayListDims(DAE.T_INTEGER_DEFAULT, TypesDump.getDimensions(ty)); | |
| 3138 | 762 | outExp := Expression.makePureBuiltinCall("cardinality", {outExp}, ty); | |
| 3139 | 762 | outProperties := DAE.PROP(ty, DAE.C_CONST()); | |
| 3140 | end elabBuiltinCardinality; | ||
| 3141 | |||
| 3142 | protected function elabBuiltinSmooth | ||
| 3143 | "This function elaborates the smooth operator. | ||
| 3144 | smooth(p,expr) - If p>=0 smooth(p, expr) returns expr and states that expr is p times | ||
| 3145 | continuously differentiable, i.e.: expr is continuous in all real variables appearing in | ||
| 3146 | the expression and all partial derivatives with respect to all appearing real variables | ||
| 3147 | exist and are continuous up to order p. | ||
| 3148 | The only allowed types for expr in smooth are: real expressions, arrays of | ||
| 3149 | allowed expressions, and records containing only components of allowed | ||
| 3150 | expressions." | ||
| 3151 | input FCore.Cache inCache; | ||
| 3152 | input FCore.Graph inEnv; | ||
| 3153 | input list<Absyn.Exp> inPosArgs; | ||
| 3154 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 3155 | input Boolean inImplicit; | ||
| 3156 | input DAE.Prefix inPrefix; | ||
| 3157 | input SourceInfo inInfo; | ||
| 3158 | output FCore.Cache outCache; | ||
| 3159 | output DAE.Exp outExp; | ||
| 3160 | output DAE.Properties outProperties; | ||
| 3161 | protected | ||
| 3162 | String msg_str; | ||
| 3163 | Absyn.Exp p, expr; | ||
| 3164 | DAE.Exp dp, dexpr; | ||
| 3165 | DAE.Type ty; | ||
| 3166 | DAE.Const c; | ||
| 3167 | algorithm | ||
| 3168 |
2/4✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 50 times.
|
50 | if listLength(inPosArgs) <> 2 or not listEmpty(inNamedArgs) then |
| 3169 | msg_str := ", expected smooth(p, expr)"; | ||
| 3170 | ✗ | printBuiltinFnArgError("smooth", msg_str, inPosArgs, inNamedArgs, inPrefix, inInfo); | |
| 3171 | end if; | ||
| 3172 | |||
| 3173 |
3/6✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 50 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 50 times.
|
50 | {p, expr} := inPosArgs; |
| 3174 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
|
50 | (outCache, dp, DAE.PROP(ty, c)) := elabExpInExpression(inCache, inEnv, p, |
| 3175 | inImplicit, true, inPrefix, inInfo); | ||
| 3176 | |||
| 3177 |
2/4✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 50 times.
|
50 | if not Types.isParameterOrConstant(c) or not Types.isInteger(ty) then |
| 3178 | msg_str := ", first argument must be a constant or parameter expression of type Integer"; | ||
| 3179 | ✗ | printBuiltinFnArgError("smooth", msg_str, inPosArgs, inNamedArgs, inPrefix, inInfo); | |
| 3180 | end if; | ||
| 3181 | |||
| 3182 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
|
50 | (outCache, dexpr, outProperties as DAE.PROP(ty, c)) := |
| 3183 | elabExpInExpression(outCache, inEnv, expr, inImplicit, true, inPrefix, inInfo); | ||
| 3184 | |||
| 3185 |
1/4✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
50 | if not (Types.isReal(ty) or Types.isRecordWithOnlyReals(ty)) then |
| 3186 | msg_str := ", second argument must be a Real, array of Reals or record only containing Reals"; | ||
| 3187 | ✗ | printBuiltinFnArgError("smooth", msg_str, inPosArgs, inNamedArgs, inPrefix, inInfo); | |
| 3188 | end if; | ||
| 3189 | |||
| 3190 | 50 | ty := Types.simplifyType(ty); | |
| 3191 | 50 | outExp := Expression.makePureBuiltinCall("smooth", {dp, dexpr}, ty); | |
| 3192 | end elabBuiltinSmooth; | ||
| 3193 | |||
| 3194 | protected function printBuiltinFnArgError | ||
| 3195 | input String inFnName; | ||
| 3196 | input String inMsg; | ||
| 3197 | input list<Absyn.Exp> inPosArgs; | ||
| 3198 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 3199 | input DAE.Prefix inPrefix; | ||
| 3200 | input SourceInfo inInfo; | ||
| 3201 | protected | ||
| 3202 | String args_str, pre_str, msg_str; | ||
| 3203 | list<String> pos_args, named_args; | ||
| 3204 | algorithm | ||
| 3205 | ✗ | pos_args := list(Dump.printExpStr(arg) for arg in inPosArgs); | |
| 3206 | ✗ | named_args := list(Dump.printNamedArgStr(arg) for arg in inNamedArgs); | |
| 3207 | ✗ | args_str := stringDelimitList(listAppend(pos_args, named_args), ", "); | |
| 3208 | ✗ | pre_str := PrefixUtil.printPrefixStr3(inPrefix); | |
| 3209 | ✗ | msg_str := inFnName + "(" + args_str + ")" + inMsg; | |
| 3210 | ✗ | Error.addSourceMessageAndFail(Error.WRONG_TYPE_OR_NO_OF_ARGS, {msg_str, pre_str}, inInfo); | |
| 3211 | end printBuiltinFnArgError; | ||
| 3212 | |||
| 3213 | protected function elabBuiltinSize | ||
| 3214 | "This function elaborates the size operator. | ||
| 3215 | Input is the list of arguments to size as Absyn.Exp | ||
| 3216 | expressions and the environment, FCore.Graph." | ||
| 3217 | input FCore.Cache inCache; | ||
| 3218 | input FCore.Graph inEnv; | ||
| 3219 | input list<Absyn.Exp> inAbsynExpLst; | ||
| 3220 | input list<Absyn.NamedArg> inNamedArg; | ||
| 3221 | input Boolean inBoolean; | ||
| 3222 | input DAE.Prefix inPrefix; | ||
| 3223 | input SourceInfo info; | ||
| 3224 | output FCore.Cache outCache; | ||
| 3225 | output DAE.Exp outExp; | ||
| 3226 | output DAE.Properties outProperties; | ||
| 3227 | algorithm | ||
| 3228 | (outCache,outExp,outProperties) := match (inCache,inEnv,inAbsynExpLst,inBoolean,inPrefix) | ||
| 3229 | local | ||
| 3230 | DAE.Exp dimp,arraycrefe,exp; | ||
| 3231 | DAE.Type arrtp; | ||
| 3232 | DAE.Properties prop; | ||
| 3233 | Boolean impl; | ||
| 3234 | FCore.Graph env; | ||
| 3235 | Absyn.Exp arraycr,dim; | ||
| 3236 | FCore.Cache cache; | ||
| 3237 | DAE.Prefix pre; | ||
| 3238 | DAE.Type ety; | ||
| 3239 | DAE.Dimensions dims, dims1, dims2; | ||
| 3240 | |||
| 3241 | case (cache, env, {arraycr, dim}, impl, pre) | ||
| 3242 | algorithm | ||
| 3243 | 2665 | (cache, dimp, _) := | |
| 3244 | elabExpInExpression(cache, env, dim, impl, true, pre, info); | ||
| 3245 | 2665 | (cache, arraycrefe, prop) := | |
| 3246 | elabExpInExpression(cache, env, arraycr, impl, false, pre, info); | ||
| 3247 | 2573 | ety := Expression.typeof(arraycrefe); | |
| 3248 | 2573 | dims1 := Expression.arrayDimension(ety); | |
| 3249 | 2573 | (,dims2) := TypesDump.flattenArrayType(Types.getPropType(prop)); | |
| 3250 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 2573 times.
|
2573 | dims := if listLength(dims1) >= listLength(dims2) then dims1 else dims2 "In case there is a zero-size array somewhere..."; |
| 3251 | // sent in the props of the arraycrefe as if the array is constant then the size(x, 1) is constant! | ||
| 3252 | // see Modelica.Media.Incompressible.Examples.Glycol47 and Modelica.Media.Incompressible.TableBased (hasDensity) | ||
| 3253 |
5/8✗ Branch 1 not taken.
✓ Branch 2 taken 2573 times.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 2572 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2572 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2572 times.
|
2573 | (SOME(exp), SOME(prop)) := elabBuiltinSizeIndex(arraycrefe, prop, ety, dimp, dims, env, info); |
| 3254 | then | ||
| 3255 | (cache, exp, prop); | ||
| 3256 | |||
| 3257 | case (cache, env, {arraycr}, impl, pre) | ||
| 3258 | algorithm | ||
| 3259 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | (cache, arraycrefe, DAE.PROP(arrtp, _)) := |
| 3260 | elabExpInExpression(cache, env, arraycr, impl, false, pre, info); | ||
| 3261 | 3 | ety := Expression.typeof(arraycrefe); | |
| 3262 | 3 | dims := Expression.arrayDimension(ety); | |
| 3263 | 3 | (exp, prop) := elabBuiltinSizeNoIndex(arraycrefe, ety, dims, arrtp, info); | |
| 3264 | 3 | then | |
| 3265 | (cache, exp, prop); | ||
| 3266 | |||
| 3267 | end match; | ||
| 3268 | end elabBuiltinSize; | ||
| 3269 | |||
| 3270 | protected function elabBuiltinSizeNoIndex | ||
| 3271 | "Helper function to elabBuiltinSize. Elaborates the size(A) operator." | ||
| 3272 | input DAE.Exp inArrayExp; | ||
| 3273 | input DAE.Type inArrayExpType; | ||
| 3274 | input DAE.Dimensions inDimensions; | ||
| 3275 | input DAE.Type inArrayType; | ||
| 3276 | input SourceInfo inInfo; | ||
| 3277 | output DAE.Exp outSizeExp; | ||
| 3278 | output DAE.Properties outProperties; | ||
| 3279 | algorithm | ||
| 3280 | (outSizeExp, outProperties) := matchcontinue inDimensions | ||
| 3281 | local | ||
| 3282 | list<DAE.Exp> dim_expl; | ||
| 3283 | Integer dim_int; | ||
| 3284 | DAE.Exp exp; | ||
| 3285 | DAE.Properties prop; | ||
| 3286 | Boolean b; | ||
| 3287 | DAE.Const cnst; | ||
| 3288 | DAE.Type ty; | ||
| 3289 | String exp_str, size_str; | ||
| 3290 | |||
| 3291 | // size of a scalar is not allowed. | ||
| 3292 | case {} | ||
| 3293 | algorithm | ||
| 3294 | // Make sure that we have a proper type here. We might get DAE.T_UNKNOWN if | ||
| 3295 | // the size expression is part of a modifier, in which case we can't | ||
| 3296 | // determine if it's a scalar or array. | ||
| 3297 | ✗ | false := Types.isUnknownType(inArrayExpType); | |
| 3298 | ✗ | exp_str := ExpressionBasics.printExpStr(inArrayExp); | |
| 3299 | ✗ | size_str := "size(" + exp_str + ")"; | |
| 3300 | ✗ | Error.addSourceMessage(Error.INVALID_ARGUMENT_TYPE_FIRST_ARRAY, {size_str}, inInfo); | |
| 3301 | ✗ | then | |
| 3302 | fail(); | ||
| 3303 | |||
| 3304 | // size(A) for an array A with known dimensions. | ||
| 3305 | // Returns an array of all dimensions of A. | ||
| 3306 | case _ :: _ | ||
| 3307 | algorithm | ||
| 3308 | 3 | dim_expl := List.map(inDimensions, Expression.dimensionSizeExp); | |
| 3309 | 2 | dim_int := listLength(dim_expl); | |
| 3310 | 4 | ty := DAE.T_ARRAY(DAE.T_INTEGER_DEFAULT, {DAE.DIM_INTEGER(dim_int)}); | |
| 3311 | 2 | exp := DAE.ARRAY(ty, true, dim_expl); | |
| 3312 | 2 | prop := DAE.PROP(ty, DAE.C_CONST()); | |
| 3313 | then | ||
| 3314 | (exp, prop); | ||
| 3315 | |||
| 3316 | // If we couldn't evaluate the size expression or find any problems with it, | ||
| 3317 | // just generate a call to size and let the runtime sort it out. | ||
| 3318 | case _ :: _ | ||
| 3319 | algorithm | ||
| 3320 | 1 | b := Types.dimensionsKnown(inArrayType); | |
| 3321 | 1 | cnst := Types.boolConstSize(b); | |
| 3322 | 1 | exp := DAE.SIZE(inArrayExp,NONE()); | |
| 3323 | ty := DAE.T_ARRAY(DAE.T_INTEGER_DEFAULT, {DAE.DIM_UNKNOWN()}); | ||
| 3324 | 1 | prop := DAE.PROP(ty, cnst); | |
| 3325 | then | ||
| 3326 | (exp, prop); | ||
| 3327 | |||
| 3328 | end matchcontinue; | ||
| 3329 | end elabBuiltinSizeNoIndex; | ||
| 3330 | |||
| 3331 | protected function elabBuiltinSizeIndex | ||
| 3332 | "Helper function to elabBuiltinSize. Elaborates the size(A, x) operator." | ||
| 3333 | input DAE.Exp inArrayExp; | ||
| 3334 | input DAE.Properties inArrayProp; | ||
| 3335 | input DAE.Type inArrayType; | ||
| 3336 | input DAE.Exp inIndexExp; | ||
| 3337 | input DAE.Dimensions inDimensions; | ||
| 3338 | input FCore.Graph inEnv; | ||
| 3339 | input SourceInfo inInfo; | ||
| 3340 | output Option<DAE.Exp> outSizeExp; | ||
| 3341 | output Option<DAE.Properties> outProperties; | ||
| 3342 | algorithm | ||
| 3343 | (outSizeExp, outProperties) := matchcontinue inDimensions | ||
| 3344 | local | ||
| 3345 | Integer dim_int, dim_count; | ||
| 3346 | DAE.Exp exp; | ||
| 3347 | DAE.Dimension dim; | ||
| 3348 | DAE.Properties prop; | ||
| 3349 | DAE.Const cnst; | ||
| 3350 | String exp_str, index_str, size_str, dim_str; | ||
| 3351 | |||
| 3352 | // size of a scalar is not allowed. | ||
| 3353 | case {} | ||
| 3354 | algorithm | ||
| 3355 | // Make sure that we have a proper type here. We might get T_UNKNOWN if | ||
| 3356 | // the size expression is part of a modifier, in which case we can't | ||
| 3357 | // determine if it's a scalar or array. | ||
| 3358 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | false := Types.isUnknownType(inArrayType); |
| 3359 | ✗ | exp_str := ExpressionBasics.printExpStr(inArrayExp); | |
| 3360 | ✗ | index_str := ExpressionBasics.printExpStr(inIndexExp); | |
| 3361 | ✗ | size_str := "size(" + exp_str + ", " + index_str + ")"; | |
| 3362 | ✗ | Error.addSourceMessage(Error.INVALID_ARGUMENT_TYPE_FIRST_ARRAY, {size_str}, inInfo); | |
| 3363 | then | ||
| 3364 | (NONE(), NONE()); | ||
| 3365 | |||
| 3366 | // size(A, x) for an array A with known dimensions and constant x. | ||
| 3367 | // Returns the size of the x:th dimension. | ||
| 3368 | case _ | ||
| 3369 | algorithm | ||
| 3370 | 2573 | dim_int := Expression.expInt(inIndexExp); | |
| 3371 | 2573 | dim_count := listLength(inDimensions); | |
| 3372 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2570 times.
|
2573 | true := (dim_int > 0 and dim_int <= dim_count); |
| 3373 | 2570 | dim := listGet(inDimensions, dim_int); | |
| 3374 | 2570 | exp := Expression.dimensionSizeConstantExp(dim); | |
| 3375 | prop := DAE.PROP(DAE.T_INTEGER_DEFAULT, DAE.C_CONST()); | ||
| 3376 | then | ||
| 3377 | (SOME(exp), SOME(prop)); | ||
| 3378 | |||
| 3379 | // The index is out of bounds. | ||
| 3380 | case _ | ||
| 3381 | algorithm | ||
| 3382 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1001 times.
|
1003 | false := Types.isUnknownType(inArrayType); |
| 3383 | 1001 | dim_int := Expression.expInt(inIndexExp); | |
| 3384 | 1001 | dim_count := listLength(inDimensions); | |
| 3385 |
2/2✓ Branch 0 taken 1000 times.
✓ Branch 1 taken 1 time.
|
1001 | true := (dim_int <= 0 or dim_int > dim_count); |
| 3386 | 1 | index_str := intString(dim_int); | |
| 3387 | 1 | exp_str := ExpressionBasics.printExpStr(inArrayExp); | |
| 3388 | 1 | dim_str := intString(dim_count); | |
| 3389 | 1 | Error.addSourceMessage(Error.INVALID_SIZE_INDEX, | |
| 3390 | {index_str, exp_str, dim_str}, inInfo); | ||
| 3391 | then | ||
| 3392 | (NONE(), NONE()); | ||
| 3393 | |||
| 3394 | // If we couldn't evaluate the size expression or find any problems with it, | ||
| 3395 | // just generate a call to size and let the runtime sort it out. | ||
| 3396 | else | ||
| 3397 | algorithm | ||
| 3398 | 1002 | exp := DAE.SIZE(inArrayExp, SOME(inIndexExp)); | |
| 3399 | cnst := DAE.C_PARAM(); // Types.getPropConst(inArrayProp); | ||
| 3400 |
2/2✓ Branch 1 taken 960 times.
✓ Branch 2 taken 42 times.
|
1002 | cnst := if FGraph.inFunctionScope(inEnv) then DAE.C_VAR() else cnst; |
| 3401 | 1002 | prop := DAE.PROP(DAE.T_INTEGER_DEFAULT, cnst); | |
| 3402 | then | ||
| 3403 | (SOME(exp), SOME(prop)); | ||
| 3404 | |||
| 3405 | end matchcontinue; | ||
| 3406 | end elabBuiltinSizeIndex; | ||
| 3407 | |||
| 3408 | protected function elabBuiltinNDims | ||
| 3409 | "@author Stefan Vorkoetter <svorkoetter@maplesoft.com> | ||
| 3410 | ndims(A) : Returns the number of dimensions k of array expression A, with k >= 0. | ||
| 3411 | " | ||
| 3412 | input FCore.Cache inCache; | ||
| 3413 | input FCore.Graph inEnv; | ||
| 3414 | input list<Absyn.Exp> inAbsynExpLst; | ||
| 3415 | input list<Absyn.NamedArg> inNamedArg; | ||
| 3416 | input Boolean inBoolean; | ||
| 3417 | input DAE.Prefix inPrefix; | ||
| 3418 | input SourceInfo info; | ||
| 3419 | output FCore.Cache outCache; | ||
| 3420 | output DAE.Exp outExp; | ||
| 3421 | output DAE.Properties outProperties; | ||
| 3422 | algorithm | ||
| 3423 | (outCache,outExp,outProperties) := matchcontinue (inCache, inEnv, inAbsynExpLst, inBoolean, inPrefix) | ||
| 3424 | local | ||
| 3425 | DAE.Exp exp; | ||
| 3426 | DAE.Type arrtp; | ||
| 3427 | Boolean impl; | ||
| 3428 | FCore.Graph env; | ||
| 3429 | Absyn.Exp arraycr; | ||
| 3430 | FCore.Cache cache; | ||
| 3431 | list<Absyn.Exp> expl; | ||
| 3432 | Integer nd; | ||
| 3433 | DAE.Prefix pre; | ||
| 3434 | String sp; | ||
| 3435 | |||
| 3436 | case (cache, env, {arraycr}, impl, pre) | ||
| 3437 | algorithm | ||
| 3438 | ✗ | (cache,_,DAE.PROP(arrtp,_)) := elabExpInExpression(cache,env, arraycr, impl,true,pre,info); | |
| 3439 | ✗ | nd := Types.numberOfDimensions(arrtp); | |
| 3440 | ✗ | exp := DAE.ICONST(nd); | |
| 3441 | then | ||
| 3442 | (cache,exp,DAE.PROP(DAE.T_INTEGER_DEFAULT,DAE.C_CONST())); | ||
| 3443 | |||
| 3444 | case (_, _, expl, _, pre) | ||
| 3445 | algorithm | ||
| 3446 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 3447 | ✗ | sp := PrefixUtil.printPrefixStr3(pre); | |
| 3448 | ✗ | Debug.traceln("- Static.elabBuiltinNdims failed for: ndims(" + Dump.printExpLstStr(expl) + " in component: " + sp); | |
| 3449 | ✗ | then | |
| 3450 | fail(); | ||
| 3451 | end matchcontinue; | ||
| 3452 | end elabBuiltinNDims; | ||
| 3453 | |||
| 3454 | protected function elabBuiltinFill "This function elaborates the builtin operator fill. | ||
| 3455 | The input is the arguments to fill as Absyn.Exp expressions and the environment FCore.Graph" | ||
| 3456 | input FCore.Cache inCache; | ||
| 3457 | input FCore.Graph inEnv; | ||
| 3458 | input list<Absyn.Exp> inAbsynExpLst; | ||
| 3459 | input list<Absyn.NamedArg> inNamedArg; | ||
| 3460 | input Boolean inBoolean; | ||
| 3461 | input DAE.Prefix inPrefix; | ||
| 3462 | input SourceInfo info; | ||
| 3463 | output FCore.Cache outCache; | ||
| 3464 | output DAE.Exp outExp; | ||
| 3465 | output DAE.Properties outProperties; | ||
| 3466 | algorithm | ||
| 3467 | (outCache,outExp,outProperties) := matchcontinue (inCache, inEnv, inAbsynExpLst, inBoolean, inPrefix) | ||
| 3468 | local | ||
| 3469 | DAE.Exp s_1,exp; | ||
| 3470 | DAE.Properties prop; | ||
| 3471 | list<DAE.Exp> dims_1; | ||
| 3472 | list<DAE.Properties> dimprops; | ||
| 3473 | DAE.Type sty; | ||
| 3474 | list<Values.Value> dimvals; | ||
| 3475 | FCore.Graph env; | ||
| 3476 | Absyn.Exp s; | ||
| 3477 | list<Absyn.Exp> dims; | ||
| 3478 | Boolean impl; | ||
| 3479 | String implstr,expstr,str,sp; | ||
| 3480 | list<String> expstrs; | ||
| 3481 | FCore.Cache cache; | ||
| 3482 | DAE.Const c1; | ||
| 3483 | DAE.Prefix pre; | ||
| 3484 | DAE.Type exp_type; | ||
| 3485 | |||
| 3486 | // try to constant evaluate dimensions | ||
| 3487 | case (cache, env, (s :: dims), impl, pre) | ||
| 3488 | algorithm | ||
| 3489 | 4568 | (cache,s_1,prop) := elabExpInExpression(cache, env, s, impl,true, pre, info); | |
| 3490 | 4568 | (cache,dims_1,dimprops) := elabExpList(cache, env, dims, impl, true, pre, info); | |
| 3491 | 4568 | (dims_1,_) := Types.matchTypes(dims_1, List.map(dimprops,Types.getPropType), DAE.T_INTEGER_DEFAULT, false); | |
| 3492 | 4568 | c1 := Types.propertiesListToConst(dimprops); | |
| 3493 |
3/4✓ Branch 0 taken 4568 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4550 times.
✓ Branch 3 taken 18 times.
|
4568 | failure(DAE.C_VAR() := c1); |
| 3494 | 4550 | c1 := Types.constAnd(c1,Types.propAllConst(prop)); | |
| 3495 | 4550 | sty := Types.getPropType(prop); | |
| 3496 | 4550 | (cache,dimvals) := Ceval.cevalList(cache, env, dims_1, impl, Absyn.NO_MSG(),0); | |
| 3497 | 4550 | (cache,exp,prop) := ExpressionSimplify.elabBuiltinFill2(cache, s_1, sty, dimvals, c1, dims, info); | |
| 3498 | then | ||
| 3499 | (cache, exp, prop); | ||
| 3500 | |||
| 3501 | // If the previous case failed we probably couldn't constant evaluate the | ||
| 3502 | // dimensions. Create a function call to fill instead, and let the compiler sort it out later. | ||
| 3503 | case (cache, env, (s :: dims), impl, pre) | ||
| 3504 | algorithm | ||
| 3505 | 18 | c1 := unevaluatedFunctionVariability(env); | |
| 3506 | 18 | (cache, s_1, prop) := elabExpInExpression(cache, env, s, impl,true, pre, info); | |
| 3507 | 18 | (cache, dims_1, dimprops) := elabExpList(cache, env, dims, impl,true, pre, info); | |
| 3508 | 18 | (dims_1,_) := Types.matchTypes(dims_1, List.map(dimprops,Types.getPropType), DAE.T_INTEGER_DEFAULT, false); | |
| 3509 | 18 | sty := Types.getPropType(prop); | |
| 3510 | 18 | sty := Types.liftTypeWithDimExps(sty, dims_1); | |
| 3511 | 18 | exp_type := Types.simplifyType(sty); | |
| 3512 | 18 | prop := DAE.PROP(sty, c1); | |
| 3513 | 18 | exp := Expression.makePureBuiltinCall("fill", s_1 :: dims_1, exp_type); | |
| 3514 | 18 | then | |
| 3515 | (cache, exp, prop); | ||
| 3516 | |||
| 3517 | // Non-constant dimensons are also allowed in the case of non-expanded arrays | ||
| 3518 | // TODO: check that the diemnsions are parametric? | ||
| 3519 | case (cache, env, (s :: dims), impl, pre) | ||
| 3520 | algorithm | ||
| 3521 | ✗ | false := Config.splitArrays(); | |
| 3522 | ✗ | (cache, s_1, DAE.PROP(sty, c1)) := elabExpInExpression(cache, env, s, impl, true, pre, info); | |
| 3523 | ✗ | (cache, dims_1,_) := elabExpList(cache, env, dims, impl, true, pre, info); | |
| 3524 | ✗ | sty := Types.liftTypeWithDimExps(sty, dims_1); | |
| 3525 | ✗ | exp_type := Types.simplifyType(sty); | |
| 3526 | ✗ | c1 := Types.constAnd(c1, DAE.C_PARAM()); | |
| 3527 | ✗ | prop := DAE.PROP(sty, c1); | |
| 3528 | ✗ | exp := Expression.makePureBuiltinCall("fill", s_1 :: dims_1, exp_type); | |
| 3529 | ✗ | then | |
| 3530 | (cache, exp, prop); | ||
| 3531 | |||
| 3532 | case (_, env, dims, _, _) | ||
| 3533 | algorithm | ||
| 3534 | ✗ | str := "Static.elabBuiltinFill failed in component" + PrefixUtil.printPrefixStr3(inPrefix) + | |
| 3535 | " and scope: " + FGraph.printGraphPathStr(env) + | ||
| 3536 | " for expression: fill(" + Dump.printExpLstStr(dims) + ")"; | ||
| 3537 | ✗ | Error.addSourceMessage(Error.INTERNAL_ERROR, {str}, info); | |
| 3538 | ✗ | then | |
| 3539 | fail(); | ||
| 3540 | |||
| 3541 | case (_, _, dims, impl, pre) | ||
| 3542 | algorithm | ||
| 3543 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 3544 | ✗ | Debug.trace("- Static.elabBuiltinFill: Couldn't elaborate fill(): "); | |
| 3545 | ✗ | implstr := boolString(impl); | |
| 3546 | ✗ | expstrs := List.map(dims, Dump.printExpStr); | |
| 3547 | ✗ | expstr := stringDelimitList(expstrs, ", "); | |
| 3548 | ✗ | sp := PrefixUtil.printPrefixStr3(pre); | |
| 3549 | ✗ | str := stringAppendList({expstr," impl=",implstr,", in component: ",sp}); | |
| 3550 | ✗ | Debug.traceln(str); | |
| 3551 | ✗ | then | |
| 3552 | fail(); | ||
| 3553 | end matchcontinue; | ||
| 3554 | end elabBuiltinFill; | ||
| 3555 | |||
| 3556 | protected function elabBuiltinSymmetric "This function elaborates the builtin operator symmetric" | ||
| 3557 | input FCore.Cache inCache; | ||
| 3558 | input FCore.Graph inEnv; | ||
| 3559 | input list<Absyn.Exp> inAbsynExpLst; | ||
| 3560 | input list<Absyn.NamedArg> inNamedArg; | ||
| 3561 | input Boolean inBoolean; | ||
| 3562 | input DAE.Prefix inPrefix; | ||
| 3563 | input SourceInfo info; | ||
| 3564 | output FCore.Cache outCache; | ||
| 3565 | output DAE.Exp outExp; | ||
| 3566 | output DAE.Properties outProperties; | ||
| 3567 | algorithm | ||
| 3568 | (outCache,outExp,outProperties) := match (inCache, inEnv, inAbsynExpLst, inBoolean, inPrefix) | ||
| 3569 | local | ||
| 3570 | DAE.Type tp; | ||
| 3571 | Boolean impl; | ||
| 3572 | DAE.Dimension d1,d2; | ||
| 3573 | DAE.Type eltp,newtp; | ||
| 3574 | DAE.Properties prop; | ||
| 3575 | DAE.Const c; | ||
| 3576 | FCore.Graph env; | ||
| 3577 | Absyn.Exp matexp; | ||
| 3578 | DAE.Exp exp_1,exp; | ||
| 3579 | FCore.Cache cache; | ||
| 3580 | DAE.Prefix pre; | ||
| 3581 | |||
| 3582 | case (cache, env, {matexp}, impl, pre) | ||
| 3583 | algorithm | ||
| 3584 |
7/14✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 time.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 time.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 time.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 time.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 time.
|
1 | (cache,exp_1,DAE.PROP(DAE.T_ARRAY(dims = {d1}, ty = DAE.T_ARRAY(dims = {d2}, ty = eltp)), c)) |
| 3585 | := elabExpInExpression(cache,env,matexp,impl,true,pre,info); | ||
| 3586 | 2 | newtp := DAE.T_ARRAY(DAE.T_ARRAY(eltp, {d1}), {d2}); | |
| 3587 | 1 | tp := Types.simplifyType(newtp); | |
| 3588 | 1 | exp := Expression.makePureBuiltinCall("symmetric", {exp_1}, tp); | |
| 3589 | 1 | prop := DAE.PROP(newtp,c); | |
| 3590 | then | ||
| 3591 | (cache,exp,prop); | ||
| 3592 | end match; | ||
| 3593 | end elabBuiltinSymmetric; | ||
| 3594 | |||
| 3595 | protected function elabBuiltinClassDirectory | ||
| 3596 | input FCore.Cache inCache; | ||
| 3597 | input FCore.Graph inEnv; | ||
| 3598 | input list<Absyn.Exp> inAbsynExpLst; | ||
| 3599 | input list<Absyn.NamedArg> inNamedArg; | ||
| 3600 | input Boolean inBoolean; | ||
| 3601 | input DAE.Prefix inPrefix; | ||
| 3602 | input SourceInfo info; | ||
| 3603 | output FCore.Cache outCache; | ||
| 3604 | output DAE.Exp outExp; | ||
| 3605 | output DAE.Properties outProperties; | ||
| 3606 | algorithm | ||
| 3607 | (outCache,outExp,outProperties) := match info | ||
| 3608 | local | ||
| 3609 | String str,fileName; | ||
| 3610 | |||
| 3611 | case SOURCEINFO(fileName=fileName) | ||
| 3612 | algorithm | ||
| 3613 | ✗ | str := stringAppend(System.dirname(fileName),"/"); | |
| 3614 | ✗ | Error.addSourceMessage(Error.NON_STANDARD_OPERATOR_CLASS_DIRECTORY, {}, info); | |
| 3615 | ✗ | then | |
| 3616 | (inCache,DAE.SCONST(str),DAE.PROP(DAE.T_STRING_DEFAULT,DAE.C_CONST())); | ||
| 3617 | end match; | ||
| 3618 | end elabBuiltinClassDirectory; | ||
| 3619 | |||
| 3620 | protected function elabBuiltinSourceInfo | ||
| 3621 | input FCore.Cache inCache; | ||
| 3622 | input FCore.Graph inEnv; | ||
| 3623 | input list<Absyn.Exp> inAbsynExpLst; | ||
| 3624 | input list<Absyn.NamedArg> inNamedArg; | ||
| 3625 | input Boolean inBoolean; | ||
| 3626 | input DAE.Prefix inPrefix; | ||
| 3627 | input SourceInfo info; | ||
| 3628 | output FCore.Cache outCache; | ||
| 3629 | output DAE.Exp outExp; | ||
| 3630 | output DAE.Properties outProperties; | ||
| 3631 | algorithm | ||
| 3632 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
|
19 | {} := inAbsynExpLst; |
| 3633 | (outCache,outExp,outProperties) := match info | ||
| 3634 | local | ||
| 3635 | list<DAE.Exp> args; | ||
| 3636 | |||
| 3637 | case SOURCEINFO() | ||
| 3638 | algorithm | ||
| 3639 | 19 | args := { | |
| 3640 | DAE.SCONST(info.fileName), | ||
| 3641 | DAE.BCONST(info.isReadOnly), | ||
| 3642 | DAE.ICONST(info.lineNumberStart), | ||
| 3643 | DAE.ICONST(info.columnNumberStart), | ||
| 3644 | DAE.ICONST(info.lineNumberEnd), | ||
| 3645 | DAE.ICONST(info.columnNumberEnd), | ||
| 3646 | // Deliberately not info.lastModification. This record is constant folded | ||
| 3647 | // into the generated C, so the mtime of the source file would be baked in | ||
| 3648 | // as a literal and the output would depend on when the file happened to be | ||
| 3649 | // checked out. Nothing ever reads the field back off a sourceInfo() value | ||
| 3650 | // (the mtime of a *class* is read from its Absyn.CLASS instead, see | ||
| 3651 | // reloadClass and getTimeStamp in CevalScript), so pin it to 0.0. | ||
| 3652 | // See OpenModelica#14399. | ||
| 3653 | DAE.RCONST(0.0) | ||
| 3654 | }; | ||
| 3655 | 19 | outExp := DAE.METARECORDCALL(Absyn.QUALIFIED("SourceInfo",Absyn.IDENT("SOURCEINFO")),args,{"fileName","isReadOnly","lineNumberStart","columnNumberStart","lineNumberEnd","columnNumberEnd","lastEditTime"},0,{}); | |
| 3656 | then (inCache,outExp,DAE.PROP(DAE.T_SOURCEINFO_DEFAULT,DAE.C_CONST())); | ||
| 3657 | end match; | ||
| 3658 | end elabBuiltinSourceInfo; | ||
| 3659 | |||
| 3660 | protected function elabBuiltinSome | ||
| 3661 | input FCore.Cache inCache; | ||
| 3662 | input FCore.Graph inEnv; | ||
| 3663 | input list<Absyn.Exp> inPosArgs; | ||
| 3664 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 3665 | input Boolean inImplicit; | ||
| 3666 | input DAE.Prefix inPrefix; | ||
| 3667 | input SourceInfo inInfo; | ||
| 3668 | output FCore.Cache outCache; | ||
| 3669 | output DAE.Exp outExp; | ||
| 3670 | output DAE.Properties outProperties; | ||
| 3671 | protected | ||
| 3672 | DAE.Exp arg; | ||
| 3673 | DAE.Properties prop; | ||
| 3674 | DAE.Type ty; | ||
| 3675 | DAE.Const c; | ||
| 3676 | algorithm | ||
| 3677 | // SOME should have exactly one positional argument. | ||
| 3678 |
2/4✓ Branch 1 taken 374 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 374 times.
|
374 | if listLength(inPosArgs) <> 1 or not listEmpty(inNamedArgs) then |
| 3679 | ✗ | Error.addSourceMessageAndFail(Error.WRONG_TYPE_OR_NO_OF_ARGS, | |
| 3680 | {"SOME", ""}, inInfo); | ||
| 3681 | else | ||
| 3682 | 374 | (outCache, arg, prop) := elabExpInExpression(inCache, inEnv, | |
| 3683 | listHead(inPosArgs), inImplicit, true, inPrefix, inInfo); | ||
| 3684 | 374 | ty := Types.getPropType(prop); | |
| 3685 | 374 | (arg, ty) := Types.matchType(arg, ty, DAE.T_METABOXED_DEFAULT, true); | |
| 3686 | 374 | c := Types.propAllConst(prop); | |
| 3687 | 374 | outExp := DAE.META_OPTION(SOME(arg)); | |
| 3688 | 374 | outProperties := DAE.PROP(DAE.T_METAOPTION(ty), c); | |
| 3689 | end if; | ||
| 3690 | end elabBuiltinSome; | ||
| 3691 | |||
| 3692 | protected function elabBuiltinNone | ||
| 3693 | input FCore.Cache inCache; | ||
| 3694 | input FCore.Graph inEnv; | ||
| 3695 | input list<Absyn.Exp> inPosArgs; | ||
| 3696 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 3697 | input Boolean inImplicit; | ||
| 3698 | input DAE.Prefix inPrefix; | ||
| 3699 | input SourceInfo inInfo; | ||
| 3700 | output FCore.Cache outCache = inCache; | ||
| 3701 | output DAE.Exp outExp; | ||
| 3702 | output DAE.Properties outProperties; | ||
| 3703 | protected | ||
| 3704 | algorithm | ||
| 3705 | // NONE shouldn't have any arguments. | ||
| 3706 |
2/4✓ Branch 0 taken 3391 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3391 times.
|
3391 | if not listEmpty(inPosArgs) or not listEmpty(inNamedArgs) then |
| 3707 | ✗ | Error.addSourceMessageAndFail(Error.WRONG_TYPE_OR_NO_OF_ARGS, | |
| 3708 | {"NONE", ""}, inInfo); | ||
| 3709 | else | ||
| 3710 | outExp := DAE.META_OPTION(NONE()); | ||
| 3711 | outProperties := DAE.PROP(DAE.T_METAOPTION(DAE.T_UNKNOWN_DEFAULT), DAE.C_CONST()); | ||
| 3712 | end if; | ||
| 3713 | end elabBuiltinNone; | ||
| 3714 | |||
| 3715 | protected function elabBuiltinHomotopy | ||
| 3716 | input FCore.Cache inCache; | ||
| 3717 | input FCore.Graph inEnv; | ||
| 3718 | input list<Absyn.Exp> inPosArgs; | ||
| 3719 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 3720 | input Boolean inImplicit; | ||
| 3721 | input DAE.Prefix inPrefix; | ||
| 3722 | input SourceInfo inInfo; | ||
| 3723 | output FCore.Cache outCache = inCache; | ||
| 3724 | output DAE.Exp outExp; | ||
| 3725 | output DAE.Properties outProperties; | ||
| 3726 | protected | ||
| 3727 | String replaceWith; | ||
| 3728 | Absyn.Exp e, e1, e2; | ||
| 3729 | algorithm | ||
| 3730 | 43 | replaceWith := Flags.getConfigString(Flags.REPLACE_HOMOTOPY); | |
| 3731 | |||
| 3732 | // Replace homotopy if Flags.REPLACE_HOMOTOPY is "actual" or "simplified" | ||
| 3733 |
2/8✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 43 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
|
43 | if replaceWith == "actual" or replaceWith == "simplified" then |
| 3734 | ✗ | {e1, e2} := getHomotopyArguments(inPosArgs, inNamedArgs); | |
| 3735 | ✗ | e := if replaceWith == "actual" then e1 else e2; | |
| 3736 | |||
| 3737 | ✗ | (outCache, outExp, outProperties) := elabExpInExpression(inCache, inEnv, e, | |
| 3738 | inImplicit, true, inPrefix, inInfo); | ||
| 3739 | else | ||
| 3740 | // Otherwise, handle it like a normal function. | ||
| 3741 | 43 | (outCache, outExp, outProperties) := elabCallArgs(inCache, inEnv, | |
| 3742 | Absyn.IDENT("homotopy"), inPosArgs, inNamedArgs, {}, inImplicit, | ||
| 3743 | inPrefix, inInfo); | ||
| 3744 | end if; | ||
| 3745 | end elabBuiltinHomotopy; | ||
| 3746 | |||
| 3747 | protected function getHomotopyArguments | ||
| 3748 | input list<Absyn.Exp> args; | ||
| 3749 | input list<Absyn.NamedArg> nargs; | ||
| 3750 | output list<Absyn.Exp> outPositionalArgs; | ||
| 3751 | algorithm | ||
| 3752 | outPositionalArgs := match(args, nargs) | ||
| 3753 | local | ||
| 3754 | Absyn.Exp e1, e2; | ||
| 3755 | |||
| 3756 | // only positional | ||
| 3757 | case ({e1, e2}, _) then {e1, e2}; | ||
| 3758 | // only named | ||
| 3759 | case ({}, {Absyn.NAMEDARG("actual", e1), Absyn.NAMEDARG("simplified", e2)}) then {e1, e2}; | ||
| 3760 | case ({}, {Absyn.NAMEDARG("simplified", e2), Absyn.NAMEDARG("actual", e1)}) then {e1, e2}; | ||
| 3761 | // combination | ||
| 3762 | case ({e1}, {Absyn.NAMEDARG("simplified", e2)}) then {e1, e2}; | ||
| 3763 | else | ||
| 3764 | algorithm | ||
| 3765 | ✗ | Error.addCompilerError("+replaceHomotopy: homotopy called with wrong arguments: " + | |
| 3766 | Dump.printFunctionArgsStr(Absyn.FUNCTIONARGS(args, nargs))); | ||
| 3767 | ✗ | then | |
| 3768 | fail(); | ||
| 3769 | end match; | ||
| 3770 | end getHomotopyArguments; | ||
| 3771 | |||
| 3772 | protected function elabBuiltinDynamicSelect | ||
| 3773 | "Elaborates DynamicSelect statements in annotations for OMEdit." | ||
| 3774 | input FCore.Cache inCache; | ||
| 3775 | input FCore.Graph inEnv; | ||
| 3776 | input list<Absyn.Exp> inPosArgs; | ||
| 3777 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 3778 | input Boolean inImplicit; | ||
| 3779 | input DAE.Prefix inPrefix; | ||
| 3780 | input SourceInfo inInfo; | ||
| 3781 | output FCore.Cache outCache = inCache; | ||
| 3782 | output DAE.Exp outExp; | ||
| 3783 | output DAE.Properties outProperties; | ||
| 3784 | protected | ||
| 3785 | String msg_str; | ||
| 3786 | Absyn.Exp astatic, adynamic; | ||
| 3787 | DAE.Exp dstatic, ddynamic; | ||
| 3788 | DAE.Type ty; | ||
| 3789 | algorithm | ||
| 3790 | ✗ | if listLength(inPosArgs) <> 2 or not listEmpty(inNamedArgs) then | |
| 3791 | msg_str := ", expected DynamicSelect(staticExp, dynamicExp)"; | ||
| 3792 | ✗ | printBuiltinFnArgError("DynamicSelect", msg_str, inPosArgs, inNamedArgs, inPrefix, inInfo); | |
| 3793 | end if; | ||
| 3794 | |||
| 3795 | ✗ | {astatic, adynamic} := inPosArgs; | |
| 3796 | ✗ | (outCache, dstatic, outProperties as DAE.PROP(ty, _)) := | |
| 3797 | elabExpInExpression(inCache, inEnv, astatic, inImplicit, true, inPrefix, inInfo); | ||
| 3798 | |||
| 3799 | try | ||
| 3800 | ✗ | (outCache, ddynamic, _) := | |
| 3801 | elabExpInExpression(outCache, inEnv, adynamic, inImplicit, true, inPrefix, inInfo); | ||
| 3802 | ✗ | outExp := Expression.makePureBuiltinCall("DynamicSelect", {dstatic, ddynamic}, ty); | |
| 3803 | else | ||
| 3804 | ✗ | outExp := dstatic; | |
| 3805 | end try; | ||
| 3806 | end elabBuiltinDynamicSelect; | ||
| 3807 | |||
| 3808 | protected function elabBuiltinTranspose | ||
| 3809 | "Elaborates the builtin operator transpose." | ||
| 3810 | input FCore.Cache inCache; | ||
| 3811 | input FCore.Graph inEnv; | ||
| 3812 | input list<Absyn.Exp> inPosArgs; | ||
| 3813 | input list<Absyn.NamedArg> inNamedArg; | ||
| 3814 | input Boolean inImpl; | ||
| 3815 | input DAE.Prefix inPrefix; | ||
| 3816 | input SourceInfo inInfo; | ||
| 3817 | output FCore.Cache outCache; | ||
| 3818 | output DAE.Exp outExp; | ||
| 3819 | output DAE.Properties outProperties; | ||
| 3820 | protected | ||
| 3821 | Absyn.Exp aexp; | ||
| 3822 | DAE.Exp exp; | ||
| 3823 | DAE.Type ty, el_ty; | ||
| 3824 | DAE.Const c; | ||
| 3825 | DAE.Dimension d1, d2; | ||
| 3826 | algorithm | ||
| 3827 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 103 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 103 times.
|
103 | {aexp} := inPosArgs; |
| 3828 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 103 times.
|
103 | (outCache, exp, DAE.PROP(ty, c)) := |
| 3829 | elabExpInExpression(inCache, inEnv, aexp, inImpl, true, inPrefix, inInfo); | ||
| 3830 | // Transpose the type. | ||
| 3831 |
6/12✗ Branch 0 not taken.
✓ Branch 1 taken 103 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 103 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 103 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 103 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 103 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 103 times.
|
103 | DAE.T_ARRAY(DAE.T_ARRAY(el_ty, {d1}), {d2}) := ty; |
| 3832 | 206 | ty := DAE.T_ARRAY(DAE.T_ARRAY(el_ty, {d2}), {d1}); | |
| 3833 | 103 | outProperties := DAE.PROP(ty, c); | |
| 3834 | // Simplify the type and make a call to transpose. | ||
| 3835 | 103 | ty := Types.simplifyType(ty); | |
| 3836 | 103 | outExp := Expression.makePureBuiltinCall("transpose", {exp}, ty); | |
| 3837 | end elabBuiltinTranspose; | ||
| 3838 | |||
| 3839 | protected function elabBuiltinSum "This function elaborates the builtin operator sum. | ||
| 3840 | The input is the arguments to fill as Absyn.Exp expressions and the environment FCore.Graph" | ||
| 3841 | input FCore.Cache inCache; | ||
| 3842 | input FCore.Graph inEnv; | ||
| 3843 | input list<Absyn.Exp> inAbsynExpLst; | ||
| 3844 | input list<Absyn.NamedArg> inNamedArg; | ||
| 3845 | input Boolean inBoolean; | ||
| 3846 | input DAE.Prefix inPrefix; | ||
| 3847 | input SourceInfo info; | ||
| 3848 | output FCore.Cache outCache; | ||
| 3849 | output DAE.Exp outExp; | ||
| 3850 | output DAE.Properties outProperties; | ||
| 3851 | algorithm | ||
| 3852 | (outCache,outExp,outProperties) := match (inCache,inEnv,inAbsynExpLst,inBoolean,inPrefix) | ||
| 3853 | local | ||
| 3854 | DAE.Exp exp_1,exp_2; | ||
| 3855 | DAE.Type t,tp; | ||
| 3856 | DAE.Const c; | ||
| 3857 | FCore.Graph env; | ||
| 3858 | Absyn.Exp arrexp; | ||
| 3859 | Boolean impl,b; | ||
| 3860 | FCore.Cache cache; | ||
| 3861 | DAE.Prefix pre; | ||
| 3862 | String estr,tstr; | ||
| 3863 | DAE.Type etp; | ||
| 3864 | |||
| 3865 | case (cache,env,{arrexp},impl,pre) | ||
| 3866 | algorithm | ||
| 3867 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 312 times.
|
312 | (cache,exp_1,DAE.PROP(t,c)) := elabExpInExpression(cache,env,arrexp,impl,true,pre,info); |
| 3868 | 312 | tp := Types.arrayElementType(t); | |
| 3869 | 312 | etp := Types.simplifyType(tp); | |
| 3870 | 312 | b := Types.isArray(t); | |
| 3871 |
2/4✓ Branch 0 taken 312 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 312 times.
|
312 | b := b and Types.isSimpleType(tp); |
| 3872 | 312 | estr := Dump.printExpStr(arrexp); | |
| 3873 | 312 | tstr := TypesDump.unparseType(t); | |
| 3874 | 312 | Error.assertionOrAddSourceMessage(b,Error.SUM_EXPECTED_ARRAY,{estr,tstr},info); | |
| 3875 | 312 | exp_2 := Expression.makePureBuiltinCall("sum", {exp_1}, etp); | |
| 3876 | 312 | then | |
| 3877 | (cache,exp_2,DAE.PROP(tp,c)); | ||
| 3878 | end match; | ||
| 3879 | end elabBuiltinSum; | ||
| 3880 | |||
| 3881 | protected function elabBuiltinProduct "This function elaborates the builtin operator product. | ||
| 3882 | The input is the arguments to fill as Absyn.Exp expressions and the environment FCore.Graph" | ||
| 3883 | input FCore.Cache inCache; | ||
| 3884 | input FCore.Graph inEnv; | ||
| 3885 | input list<Absyn.Exp> inAbsynExpLst; | ||
| 3886 | input list<Absyn.NamedArg> inNamedArg; | ||
| 3887 | input Boolean inBoolean; | ||
| 3888 | input DAE.Prefix inPrefix; | ||
| 3889 | input SourceInfo info; | ||
| 3890 | output FCore.Cache outCache; | ||
| 3891 | output DAE.Exp outExp; | ||
| 3892 | output DAE.Properties outProperties; | ||
| 3893 | algorithm | ||
| 3894 | (outCache,outExp,outProperties):= | ||
| 3895 | matchcontinue (inCache,inEnv,inAbsynExpLst,inBoolean,inPrefix) | ||
| 3896 | local | ||
| 3897 | DAE.Exp exp_1,exp_2; | ||
| 3898 | DAE.Type t,tp; | ||
| 3899 | DAE.Const c; | ||
| 3900 | FCore.Graph env; | ||
| 3901 | Absyn.Exp arrexp; | ||
| 3902 | Boolean impl; | ||
| 3903 | DAE.Type ty; | ||
| 3904 | FCore.Cache cache; | ||
| 3905 | DAE.Prefix pre; | ||
| 3906 | String str_exp,str_pre; | ||
| 3907 | DAE.Type etp; | ||
| 3908 | |||
| 3909 | case (cache,env,{arrexp},impl,pre) | ||
| 3910 | algorithm | ||
| 3911 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | (cache,exp_1,DAE.PROP(ty,c)) := elabExpInExpression(cache,env,arrexp,impl,true,pre,info); |
| 3912 | 3 | (exp_1,_) := Types.matchType(exp_1, ty, DAE.T_INTEGER_DEFAULT, true); | |
| 3913 | ✗ | str_exp := "product(" + Dump.printExpStr(arrexp) + ")"; | |
| 3914 | ✗ | str_pre := PrefixUtil.printPrefixStr3(pre); | |
| 3915 | ✗ | Error.addSourceMessage(Error.BUILTIN_FUNCTION_PRODUCT_HAS_SCALAR_PARAMETER, {str_exp, str_pre}, info); | |
| 3916 | ✗ | then | |
| 3917 | (cache,exp_1,DAE.PROP(DAE.T_INTEGER_DEFAULT,c)); | ||
| 3918 | |||
| 3919 | case (cache,env,{arrexp},impl,pre) | ||
| 3920 | algorithm | ||
| 3921 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | (cache,exp_1,DAE.PROP(ty,c)) := elabExpInExpression(cache,env, arrexp, impl,true,pre,info); |
| 3922 | 3 | (exp_1,_) := Types.matchType(exp_1, ty, DAE.T_REAL_DEFAULT, true); | |
| 3923 | ✗ | str_exp := "product(" + Dump.printExpStr(arrexp) + ")"; | |
| 3924 | ✗ | str_pre := PrefixUtil.printPrefixStr3(pre); | |
| 3925 | ✗ | Error.addSourceMessage(Error.BUILTIN_FUNCTION_PRODUCT_HAS_SCALAR_PARAMETER, {str_exp, str_pre}, info); | |
| 3926 | ✗ | then | |
| 3927 | (cache,exp_1,DAE.PROP(DAE.T_REAL_DEFAULT,c)); | ||
| 3928 | |||
| 3929 | case (cache,env,{arrexp},impl,pre) | ||
| 3930 | algorithm | ||
| 3931 |
4/8✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
|
3 | (cache,exp_1,DAE.PROP(t as DAE.T_ARRAY(dims = {_}, ty = tp),c)) := elabExpInExpression(cache,env, arrexp, impl,true,pre,info); |
| 3932 | 3 | tp := Types.arrayElementType(t); | |
| 3933 | 3 | etp := Types.simplifyType(tp); | |
| 3934 | 3 | exp_2 := Expression.makePureBuiltinCall("product", {exp_1}, etp); | |
| 3935 | |||
| 3936 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | if not Types.arrayHasUnknownDims(t) then |
| 3937 | 3 | exp_2 := elabBuiltinProduct2(exp_2); | |
| 3938 | end if; | ||
| 3939 | 3 | then | |
| 3940 | (cache,exp_2,DAE.PROP(tp,c)); | ||
| 3941 | end matchcontinue; | ||
| 3942 | end elabBuiltinProduct; | ||
| 3943 | |||
| 3944 | protected function elabBuiltinProduct2 | ||
| 3945 | "Replaces product({a1,a2,...an}) with a1*a2*...*an} and | ||
| 3946 | product([a11,a12,...,a1n;...,am1,am2,..amn]) with a11*a12*...*amn" | ||
| 3947 | input DAE.Exp inExp; | ||
| 3948 | output DAE.Exp outExp; | ||
| 3949 | algorithm | ||
| 3950 | outExp := matchcontinue inExp | ||
| 3951 | local | ||
| 3952 | DAE.Exp array_exp; | ||
| 3953 | |||
| 3954 | case DAE.CALL(expLst = {array_exp}) | ||
| 3955 | 3 | then Expression.makeProductLst(Expression.arrayElements(array_exp)); | |
| 3956 | |||
| 3957 | else inExp; | ||
| 3958 | end matchcontinue; | ||
| 3959 | end elabBuiltinProduct2; | ||
| 3960 | |||
| 3961 | protected function elabBuiltinPre "This function elaborates the builtin operator pre. | ||
| 3962 | Input is the arguments to the pre operator and the environment, FCore.Graph." | ||
| 3963 | input FCore.Cache inCache; | ||
| 3964 | input FCore.Graph inEnv; | ||
| 3965 | input list<Absyn.Exp> inPosArgs; | ||
| 3966 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 3967 | input Boolean inImplicit; | ||
| 3968 | input DAE.Prefix inPrefix; | ||
| 3969 | input SourceInfo inInfo; | ||
| 3970 | output FCore.Cache outCache; | ||
| 3971 | output DAE.Exp outExp; | ||
| 3972 | output DAE.Properties outProperties; | ||
| 3973 | protected | ||
| 3974 | DAE.Exp exp; | ||
| 3975 | DAE.Type ty, ty2; | ||
| 3976 | DAE.Const c; | ||
| 3977 | list<DAE.Exp> expl; | ||
| 3978 | Boolean sc; | ||
| 3979 | String exp_str, pre_str; | ||
| 3980 | algorithm | ||
| 3981 | 424 | checkBuiltinCallArgs(inPosArgs, inNamedArgs, 1, "pre", inInfo); | |
| 3982 | |||
| 3983 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 424 times.
|
424 | (outCache, exp, DAE.PROP(ty, c)) := elabExpInExpression(inCache, inEnv, |
| 3984 | listHead(inPosArgs), inImplicit, true, inPrefix, inInfo); | ||
| 3985 | |||
| 3986 | // A matrix? | ||
| 3987 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 424 times.
|
424 | if Expression.isMatrix(exp) then |
| 3988 | ✗ | DAE.T_ARRAY(ty = ty2) := ty; | |
| 3989 | ✗ | ty2 := Types.unliftArray(ty2); | |
| 3990 | ✗ | outExp := Expression.makePureBuiltinCall("pre", {exp}, Types.simplifyType(ty2)); | |
| 3991 | ✗ | outExp := elabBuiltinPreMatrix(outExp, ty2); | |
| 3992 | // An array? | ||
| 3993 | elseif Types.isArray(ty) then | ||
| 3994 | 13 | ty2 := Types.unliftArray(ty); | |
| 3995 | 13 | outExp := Expression.makePureBuiltinCall("pre", {exp}, Types.simplifyType(ty2)); | |
| 3996 | 13 | (expl, sc) := elabBuiltinPre2(outExp, ty2); | |
| 3997 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | outExp := DAE.ARRAY(Types.simplifyType(ty), sc, expl); |
| 3998 | // A scalar? | ||
| 3999 | else | ||
| 4000 | 411 | ty := Types.arrayElementType(ty); | |
| 4001 | |||
| 4002 |
1/2✓ Branch 1 taken 411 times.
✗ Branch 2 not taken.
|
411 | if Types.basicType(ty) then |
| 4003 | 411 | outExp := Expression.makePureBuiltinCall("pre", {exp}, Types.simplifyType(ty)); | |
| 4004 | else | ||
| 4005 | ✗ | exp_str := ExpressionBasics.printExpStr(exp); | |
| 4006 | ✗ | pre_str := PrefixUtil.printPrefixStr3(inPrefix); | |
| 4007 | ✗ | Error.addSourceMessageAndFail(Error.OPERAND_BUILTIN_TYPE, | |
| 4008 | {"pre", pre_str, exp_str}, inInfo); | ||
| 4009 | end if; | ||
| 4010 | end if; | ||
| 4011 | |||
| 4012 | 424 | outProperties := DAE.PROP(ty, c); | |
| 4013 | end elabBuiltinPre; | ||
| 4014 | |||
| 4015 | protected function elabBuiltinPre2 | ||
| 4016 | "Help function for elabBuiltinPre, when type is array, send it here." | ||
| 4017 | input DAE.Exp inExp; | ||
| 4018 | input DAE.Type inType; | ||
| 4019 | output list<DAE.Exp> outExp; | ||
| 4020 | output Boolean outScalar; | ||
| 4021 | algorithm | ||
| 4022 | (outExp, outScalar) := matchcontinue inExp | ||
| 4023 | local | ||
| 4024 | Boolean sc; | ||
| 4025 | list<DAE.Exp> expl; | ||
| 4026 | Integer i; | ||
| 4027 | list<list<DAE.Exp>> mexpl; | ||
| 4028 | DAE.Type ty; | ||
| 4029 | |||
| 4030 | case DAE.CALL(expLst = {DAE.ARRAY(scalar = sc, array = expl)}) | ||
| 4031 | 13 | then (makePreLst(expl, inType), sc); | |
| 4032 | |||
| 4033 | case DAE.CALL(expLst = {DAE.MATRIX(ty = ty, integer = i, matrix = mexpl)}) | ||
| 4034 | algorithm | ||
| 4035 | ✗ | mexpl := list(makePreLst(e, inType) for e in mexpl); | |
| 4036 | ✗ | then | |
| 4037 | ({DAE.MATRIX(ty, i, mexpl)}, false); | ||
| 4038 | |||
| 4039 | else ({inExp}, false); | ||
| 4040 | end matchcontinue; | ||
| 4041 | end elabBuiltinPre2; | ||
| 4042 | |||
| 4043 | protected function elabBuiltinInStream "This function elaborates the builtin operator inStream. | ||
| 4044 | Input is the arguments to the inStream operator and the environment, FCore.Graph." | ||
| 4045 | input FCore.Cache inCache; | ||
| 4046 | input FCore.Graph inEnv; | ||
| 4047 | input list<Absyn.Exp> inArgs; | ||
| 4048 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 4049 | input Boolean inImpl; | ||
| 4050 | input DAE.Prefix inPrefix; | ||
| 4051 | input SourceInfo inInfo; | ||
| 4052 | output FCore.Cache outCache; | ||
| 4053 | output DAE.Exp outExp; | ||
| 4054 | output DAE.Properties outProperties; | ||
| 4055 | protected | ||
| 4056 | Absyn.Exp e; | ||
| 4057 | DAE.Exp exp; | ||
| 4058 | DAE.Type ty; | ||
| 4059 | algorithm | ||
| 4060 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 228 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 228 times.
|
228 | {e} := inArgs; |
| 4061 | 228 | (outCache, exp, outProperties) := elabExpInExpression(inCache, inEnv, e, | |
| 4062 | inImpl, true, inPrefix, inInfo); | ||
| 4063 | 228 | ty := Types.getPropType(outProperties); | |
| 4064 | 228 | outExp := elabBuiltinStreamOperator(outCache, inEnv, "inStream", exp, ty, inInfo); | |
| 4065 | |||
| 4066 | // Use elabCallArgs to also try vectorized calls | ||
| 4067 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 227 times.
|
227 | if Types.dimensionsKnown(ty) then |
| 4068 | 227 | (outCache, outExp, outProperties) := elabCallArgs(outCache, inEnv, | |
| 4069 | Absyn.IDENT("inStream"), {e}, {}, {}, inImpl, inPrefix, inInfo); | ||
| 4070 | end if; | ||
| 4071 | end elabBuiltinInStream; | ||
| 4072 | |||
| 4073 | protected function elabBuiltinActualStream "This function elaborates the builtin operator actualStream. | ||
| 4074 | Input is the arguments to the actualStream operator and the environment, FCore.Graph." | ||
| 4075 | input FCore.Cache inCache; | ||
| 4076 | input FCore.Graph inEnv; | ||
| 4077 | input list<Absyn.Exp> inArgs; | ||
| 4078 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 4079 | input Boolean inImpl; | ||
| 4080 | input DAE.Prefix inPrefix; | ||
| 4081 | input SourceInfo inInfo; | ||
| 4082 | output FCore.Cache outCache; | ||
| 4083 | output DAE.Exp outExp; | ||
| 4084 | output DAE.Properties outProperties; | ||
| 4085 | protected | ||
| 4086 | Absyn.Exp e; | ||
| 4087 | DAE.Exp exp; | ||
| 4088 | DAE.Type ty; | ||
| 4089 | algorithm | ||
| 4090 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 51 times.
|
51 | {e} := inArgs; |
| 4091 | 51 | (outCache, exp, outProperties) := elabExpInExpression(inCache, inEnv, e, | |
| 4092 | inImpl, true, inPrefix, inInfo); | ||
| 4093 | 51 | ty := Types.getPropType(outProperties); | |
| 4094 | 51 | outExp := elabBuiltinStreamOperator(outCache, inEnv, "actualStream", exp, ty, inInfo); | |
| 4095 | |||
| 4096 | // Use elabCallArgs to also try vectorized calls | ||
| 4097 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 51 times.
|
51 | if Types.dimensionsKnown(ty) then |
| 4098 | 51 | (outCache, outExp, outProperties) := elabCallArgs(outCache, inEnv, | |
| 4099 | Absyn.IDENT("actualStream"), {e}, {}, {}, inImpl, inPrefix, inInfo); | ||
| 4100 | end if; | ||
| 4101 | end elabBuiltinActualStream; | ||
| 4102 | |||
| 4103 | protected function elabBuiltinStreamOperator | ||
| 4104 | input FCore.Cache inCache; | ||
| 4105 | input FCore.Graph inEnv; | ||
| 4106 | input String inOperator; | ||
| 4107 | input DAE.Exp inExp; | ||
| 4108 | input DAE.Type inType; | ||
| 4109 | input SourceInfo inInfo; | ||
| 4110 | output DAE.Exp outExp; | ||
| 4111 | algorithm | ||
| 4112 | outExp := match inExp | ||
| 4113 | local | ||
| 4114 | DAE.Type et; | ||
| 4115 | DAE.Exp exp; | ||
| 4116 | |||
| 4117 | case DAE.ARRAY(array = {}) then inExp; | ||
| 4118 | |||
| 4119 | else | ||
| 4120 | algorithm | ||
| 4121 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 161 times.
|
161 | exp :: _ := Expression.flattenArrayExpToList(inExp); |
| 4122 | 161 | validateBuiltinStreamOperator(inCache, inEnv, exp, inType, inOperator, inInfo); | |
| 4123 | 160 | et := Types.simplifyType(inType); | |
| 4124 | 160 | exp := Expression.makePureBuiltinCall(inOperator, {exp}, et); | |
| 4125 | then | ||
| 4126 | exp; | ||
| 4127 | |||
| 4128 | end match; | ||
| 4129 | end elabBuiltinStreamOperator; | ||
| 4130 | |||
| 4131 | protected function validateBuiltinStreamOperator | ||
| 4132 | input FCore.Cache inCache; | ||
| 4133 | input FCore.Graph inEnv; | ||
| 4134 | input DAE.Exp inOperand; | ||
| 4135 | input DAE.Type inType; | ||
| 4136 | input String inOperator; | ||
| 4137 | input SourceInfo inInfo; | ||
| 4138 | algorithm | ||
| 4139 | () := matchcontinue inOperand | ||
| 4140 | local | ||
| 4141 | DAE.ComponentRef cr; | ||
| 4142 | DAE.Attributes attr; | ||
| 4143 | String op_str; | ||
| 4144 | |||
| 4145 | // Operand is a stream variable, ok! | ||
| 4146 | case DAE.CREF(componentRef = cr) | ||
| 4147 | algorithm | ||
| 4148 | 161 | (_, attr) := Lookup.lookupVar(inCache, inEnv, cr); | |
| 4149 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 160 times.
|
161 | DAE.ATTR(connectorType = DAE.STREAM()) := attr; |
| 4150 | then | ||
| 4151 | (); | ||
| 4152 | |||
| 4153 | // Operand is not a stream variable, error! | ||
| 4154 | else | ||
| 4155 | algorithm | ||
| 4156 | 1 | op_str := ExpressionBasics.printExpStr(inOperand); | |
| 4157 | 1 | Error.addSourceMessage(Error.NON_STREAM_OPERAND_IN_STREAM_OPERATOR, | |
| 4158 | {op_str, inOperator}, inInfo); | ||
| 4159 | 1 | then | |
| 4160 | fail(); | ||
| 4161 | end matchcontinue; | ||
| 4162 | end validateBuiltinStreamOperator; | ||
| 4163 | |||
| 4164 | protected function makePreLst | ||
| 4165 | "Takes a list of expressions and makes a list of pre - expressions" | ||
| 4166 | input list<DAE.Exp> inExpl; | ||
| 4167 | input DAE.Type inType; | ||
| 4168 | output list<DAE.Exp> outExpl; | ||
| 4169 | protected | ||
| 4170 | DAE.Type ty; | ||
| 4171 | algorithm | ||
| 4172 | 13 | ty := Types.simplifyType(inType); | |
| 4173 |
4/4✓ Branch 0 taken 35 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 35 times.
✓ Branch 3 taken 13 times.
|
83 | outExpl := list(Expression.makePureBuiltinCall("pre", {e}, ty) for e in inExpl); |
| 4174 | end makePreLst; | ||
| 4175 | |||
| 4176 | protected function elabBuiltinPreMatrix | ||
| 4177 | "Help function for elabBuiltinPreMatrix, when type is matrix, send it here." | ||
| 4178 | input DAE.Exp inExp; | ||
| 4179 | input DAE.Type inType; | ||
| 4180 | output DAE.Exp outExp; | ||
| 4181 | algorithm | ||
| 4182 | outExp := match inExp | ||
| 4183 | local | ||
| 4184 | DAE.Exp exp; | ||
| 4185 | |||
| 4186 | case DAE.CALL(expLst = {exp as DAE.MATRIX()}) | ||
| 4187 | algorithm | ||
| 4188 | ✗ | exp.matrix := list(makePreLst(row, inType) for row in exp.matrix); | |
| 4189 | then | ||
| 4190 | exp; | ||
| 4191 | |||
| 4192 | else inExp; | ||
| 4193 | end match; | ||
| 4194 | end elabBuiltinPreMatrix; | ||
| 4195 | |||
| 4196 | protected function elabBuiltinArray " | ||
| 4197 | This function elaborates the builtin operator \'array\'. For instance, | ||
| 4198 | array(1,4,6) which is the same as {1,4,6}. | ||
| 4199 | Input is the list of arguments to the operator, as Absyn.Exp list. | ||
| 4200 | " | ||
| 4201 | input FCore.Cache inCache; | ||
| 4202 | input FCore.Graph inEnv; | ||
| 4203 | input list<Absyn.Exp> inPosArgs; | ||
| 4204 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 4205 | input Boolean inImplicit; | ||
| 4206 | input DAE.Prefix inPrefix; | ||
| 4207 | input SourceInfo inInfo; | ||
| 4208 | output FCore.Cache outCache; | ||
| 4209 | output DAE.Exp outExp; | ||
| 4210 | output DAE.Properties outProperties; | ||
| 4211 | protected | ||
| 4212 | list<DAE.Exp> expl; | ||
| 4213 | list<DAE.Properties> props; | ||
| 4214 | DAE.Type ty, arr_ty; | ||
| 4215 | DAE.Const c; | ||
| 4216 | Integer len; | ||
| 4217 | algorithm | ||
| 4218 | 21 | (outCache, expl, props) := elabExpList(inCache, inEnv, inPosArgs, inImplicit, | |
| 4219 | true, inPrefix, inInfo); | ||
| 4220 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
|
21 | (_, DAE.PROP(ty, c)) := elabBuiltinArray2(expl, props, inPrefix, inInfo); |
| 4221 | 20 | len := listLength(expl); | |
| 4222 | 40 | arr_ty := DAE.T_ARRAY(ty, {DAE.DIM_INTEGER(len)}); | |
| 4223 | 20 | outProperties := DAE.PROP(arr_ty, c); | |
| 4224 | 20 | arr_ty := Types.simplifyType(arr_ty); | |
| 4225 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
40 | outExp := DAE.ARRAY(arr_ty, Types.isArray(ty), expl); |
| 4226 | end elabBuiltinArray; | ||
| 4227 | |||
| 4228 | protected function elabBuiltinArray2 | ||
| 4229 | "Helper function to elabBuiltinArray. | ||
| 4230 | Asserts that all types are of same dimensionality and of same builtin types." | ||
| 4231 | input list<DAE.Exp> inExpl; | ||
| 4232 | input list<DAE.Properties> inProperties; | ||
| 4233 | input DAE.Prefix inPrefix; | ||
| 4234 | input SourceInfo inInfo; | ||
| 4235 | output list<DAE.Exp> outExpl; | ||
| 4236 | output DAE.Properties outProperties; | ||
| 4237 | protected | ||
| 4238 | String pre_str; | ||
| 4239 | DAE.Properties prop; | ||
| 4240 | algorithm | ||
| 4241 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 20 times.
|
21 | if not sameDimensions(inProperties) then |
| 4242 | 1 | pre_str := PrefixUtil.printPrefixStr3(inPrefix); | |
| 4243 | 1 | Error.addSourceMessageAndFail(Error.DIFFERENT_DIM_SIZE_IN_ARGUMENTS, | |
| 4244 | {"array", pre_str}, inInfo); | ||
| 4245 | end if; | ||
| 4246 | |||
| 4247 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
|
20 | prop := if Types.propsContainReal(inProperties) then |
| 4248 | DAE.PROP(DAE.T_REAL_DEFAULT, DAE.C_VAR()) else listHead(inProperties); | ||
| 4249 | 20 | (outExpl, outProperties) := elabBuiltinArray3(inExpl, inProperties, prop); | |
| 4250 | end elabBuiltinArray2; | ||
| 4251 | |||
| 4252 | protected function elabBuiltinArray3 | ||
| 4253 | "Helper function to elab_builtin_array." | ||
| 4254 | input list<DAE.Exp> inExpl; | ||
| 4255 | input list<DAE.Properties> inPropertiesLst; | ||
| 4256 | input DAE.Properties inProperties; | ||
| 4257 | output list<DAE.Exp> outExpl = {}; | ||
| 4258 | output DAE.Properties outProperties = listHead(inPropertiesLst); | ||
| 4259 | protected | ||
| 4260 | DAE.Properties prop; | ||
| 4261 | list<DAE.Properties> rest_props = inPropertiesLst; | ||
| 4262 | algorithm | ||
| 4263 |
2/2✓ Branch 0 taken 242 times.
✓ Branch 1 taken 20 times.
|
262 | for e in inExpl loop |
| 4264 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 242 times.
|
242 | prop :: rest_props := rest_props; |
| 4265 | 242 | e := Types.matchProp(e, prop, inProperties, true); | |
| 4266 | outExpl := e :: outExpl; | ||
| 4267 | end for; | ||
| 4268 | |||
| 4269 | 20 | outExpl := listReverse(outExpl); | |
| 4270 | end elabBuiltinArray3; | ||
| 4271 | |||
| 4272 | protected function elabBuiltinZeros "This function elaborates the builtin operator zeros(n)." | ||
| 4273 | input FCore.Cache inCache; | ||
| 4274 | input FCore.Graph inEnv; | ||
| 4275 | input list<Absyn.Exp> inPosArgs; | ||
| 4276 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 4277 | input Boolean inImplicit; | ||
| 4278 | input DAE.Prefix inPrefix; | ||
| 4279 | input SourceInfo inInfo; | ||
| 4280 | output FCore.Cache outCache; | ||
| 4281 | output DAE.Exp outExp; | ||
| 4282 | output DAE.Properties outProperties; | ||
| 4283 | algorithm | ||
| 4284 | 1894 | (outCache, outExp, outProperties) := elabBuiltinFill(inCache, inEnv, | |
| 4285 | Absyn.INTEGER(0) :: inPosArgs, {}, inImplicit, inPrefix, inInfo); | ||
| 4286 | end elabBuiltinZeros; | ||
| 4287 | |||
| 4288 | protected function sameDimensions | ||
| 4289 | "This function returns true if all properties, containing types, have the same | ||
| 4290 | dimensions, otherwise false." | ||
| 4291 | input list<DAE.Properties> inProps; | ||
| 4292 | output Boolean res; | ||
| 4293 | protected | ||
| 4294 | list<DAE.Type> types; | ||
| 4295 | list<DAE.Dimensions> dims; | ||
| 4296 | algorithm | ||
| 4297 | 21 | types := List.map(inProps, Types.getPropType); | |
| 4298 | 21 | dims := List.map(types, TypesDump.getDimensions); | |
| 4299 | 21 | res := sameDimensions2(dims); | |
| 4300 | end sameDimensions; | ||
| 4301 | |||
| 4302 | protected function sameDimensionsExceptionDimX | ||
| 4303 | "This function returns true if all properties, containing types, have the same | ||
| 4304 | dimensions (except for dimension X), otherwise false." | ||
| 4305 | input list<DAE.Properties> inProps; | ||
| 4306 | input Integer dimException; | ||
| 4307 | output Boolean res; | ||
| 4308 | protected | ||
| 4309 | list<DAE.Type> types; | ||
| 4310 | list<DAE.Dimensions> dims; | ||
| 4311 | algorithm | ||
| 4312 | ✗ | types := List.map(inProps, Types.getPropType); | |
| 4313 | ✗ | dims := List.map(types, TypesDump.getDimensions); | |
| 4314 | ✗ | dims := List.map1(dims, listDelete, dimException); | |
| 4315 | ✗ | res := sameDimensions2(dims); | |
| 4316 | end sameDimensionsExceptionDimX; | ||
| 4317 | |||
| 4318 | protected function sameDimensions2 | ||
| 4319 | "Helper function to sameDimensions. Checks that each list of dimensions has | ||
| 4320 | the same dimensions as the other lists." | ||
| 4321 | input list<DAE.Dimensions> inDimensions; | ||
| 4322 | output Boolean outSame = true; | ||
| 4323 | protected | ||
| 4324 | DAE.Dimensions dims; | ||
| 4325 | list<DAE.Dimensions> rest_dims = inDimensions; | ||
| 4326 | algorithm | ||
| 4327 |
1/2✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
|
21 | if listEmpty(inDimensions) then |
| 4328 | ✗ | return; | |
| 4329 | end if; | ||
| 4330 | |||
| 4331 |
2/2✓ Branch 1 taken 20 times.
✓ Branch 2 taken 1 time.
|
21 | while not listEmpty(listHead(rest_dims)) loop |
| 4332 |
4/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 time.
|
3 | dims := list(listHead(d) for d in rest_dims); |
| 4333 | |||
| 4334 |
1/2✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
|
1 | if not sameDimensions3(dims) then |
| 4335 | outSame := false; | ||
| 4336 | 1 | return; | |
| 4337 | end if; | ||
| 4338 | |||
| 4339 | ✗ | rest_dims := list(listRest(d) for d in rest_dims); | |
| 4340 | end while; | ||
| 4341 | |||
| 4342 | // Make sure the lists were the same length. | ||
| 4343 |
2/2✓ Branch 0 taken 242 times.
✓ Branch 1 taken 20 times.
|
262 | for d in rest_dims loop |
| 4344 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 242 times.
|
242 | true := listEmpty(d); |
| 4345 | end for; | ||
| 4346 | end sameDimensions2; | ||
| 4347 | |||
| 4348 | protected function sameDimensions3 | ||
| 4349 | "Helper function to sameDimensions2. Check that all dimensions in a list are equal." | ||
| 4350 | input DAE.Dimensions inDims; | ||
| 4351 | output Boolean outSame = true; | ||
| 4352 | protected | ||
| 4353 | DAE.Dimension dim1; | ||
| 4354 | algorithm | ||
| 4355 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 | if listEmpty(inDims) then |
| 4356 | ✗ | return; | |
| 4357 | end if; | ||
| 4358 | |||
| 4359 | 1 | dim1 := listHead(inDims); | |
| 4360 |
1/2✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
|
1 | for dim2 in listRest(inDims) loop |
| 4361 |
1/2✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
|
1 | if not Expression.dimensionsEqual(dim1, dim2) then |
| 4362 | outSame := false; | ||
| 4363 | 1 | return; | |
| 4364 | end if; | ||
| 4365 | end for; | ||
| 4366 | end sameDimensions3; | ||
| 4367 | |||
| 4368 | protected function elabBuiltinOnes "This function elaborates on the builtin opeator ones(n)." | ||
| 4369 | input FCore.Cache inCache; | ||
| 4370 | input FCore.Graph inEnv; | ||
| 4371 | input list<Absyn.Exp> inPosArgs; | ||
| 4372 | input list<Absyn.NamedArg> inNamedArg; | ||
| 4373 | input Boolean inImplicit; | ||
| 4374 | input DAE.Prefix inPrefix; | ||
| 4375 | input SourceInfo inInfo; | ||
| 4376 | output FCore.Cache outCache; | ||
| 4377 | output DAE.Exp outExp; | ||
| 4378 | output DAE.Properties outProperties; | ||
| 4379 | algorithm | ||
| 4380 | 231 | (outCache, outExp, outProperties) := elabBuiltinFill(inCache, inEnv, | |
| 4381 | Absyn.INTEGER(1) :: inPosArgs, {}, inImplicit, inPrefix, inInfo); | ||
| 4382 | end elabBuiltinOnes; | ||
| 4383 | |||
| 4384 | protected function elabBuiltinMax | ||
| 4385 | "This function elaborates on the builtin operator max(a, b)." | ||
| 4386 | input FCore.Cache inCache; | ||
| 4387 | input FCore.Graph inEnv; | ||
| 4388 | input list<Absyn.Exp> inFnArgs; | ||
| 4389 | input list<Absyn.NamedArg> inNamedArg; | ||
| 4390 | input Boolean inImpl; | ||
| 4391 | input DAE.Prefix inPrefix; | ||
| 4392 | input SourceInfo info; | ||
| 4393 | output FCore.Cache outCache; | ||
| 4394 | output DAE.Exp outExp; | ||
| 4395 | output DAE.Properties outProperties; | ||
| 4396 | algorithm | ||
| 4397 | 804 | (outCache, outExp, outProperties) := | |
| 4398 | elabBuiltinMinMaxCommon(inCache, inEnv, "max", inFnArgs, inImpl, inPrefix, info); | ||
| 4399 | end elabBuiltinMax; | ||
| 4400 | |||
| 4401 | protected function elabBuiltinMin | ||
| 4402 | "This function elaborates the builtin operator min(a, b)" | ||
| 4403 | input FCore.Cache inCache; | ||
| 4404 | input FCore.Graph inEnv; | ||
| 4405 | input list<Absyn.Exp> inFnArgs; | ||
| 4406 | input list<Absyn.NamedArg> inNamedArg; | ||
| 4407 | input Boolean inImpl; | ||
| 4408 | input DAE.Prefix inPrefix; | ||
| 4409 | input SourceInfo info; | ||
| 4410 | output FCore.Cache outCache; | ||
| 4411 | output DAE.Exp outExp; | ||
| 4412 | output DAE.Properties outProperties; | ||
| 4413 | algorithm | ||
| 4414 | 330 | (outCache, outExp, outProperties) := | |
| 4415 | elabBuiltinMinMaxCommon(inCache, inEnv, "min", inFnArgs, inImpl, inPrefix, info); | ||
| 4416 | end elabBuiltinMin; | ||
| 4417 | |||
| 4418 | protected function elabBuiltinMinMaxCommon | ||
| 4419 | "Helper function to elabBuiltinMin and elabBuiltinMax, containing common | ||
| 4420 | functionality." | ||
| 4421 | input output FCore.Cache cache; | ||
| 4422 | input FCore.Graph env; | ||
| 4423 | input String inFnName; | ||
| 4424 | input list<Absyn.Exp> inFnArgs; | ||
| 4425 | input Boolean impl; | ||
| 4426 | input DAE.Prefix prefix; | ||
| 4427 | input SourceInfo info; | ||
| 4428 | output DAE.Exp outExp; | ||
| 4429 | output DAE.Properties outProperties; | ||
| 4430 | algorithm | ||
| 4431 | (outExp, outProperties) := match inFnArgs | ||
| 4432 | local | ||
| 4433 | DAE.Exp arrexp_1,s1_1,s2_1, call; | ||
| 4434 | DAE.Type tp; | ||
| 4435 | DAE.Type ty,ty1,ty2,elt_ty; | ||
| 4436 | DAE.Const c,c1,c2; | ||
| 4437 | Absyn.Exp arrexp,s1,s2; | ||
| 4438 | |||
| 4439 | // min|max(vector) | ||
| 4440 | case {arrexp} | ||
| 4441 | algorithm | ||
| 4442 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 111 times.
|
111 | (cache, arrexp_1, DAE.PROP(ty, c)) := |
| 4443 | elabExpInExpression(cache, env, arrexp, impl, true, prefix, info); | ||
| 4444 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 111 times.
|
111 | true := Types.isArray(ty); |
| 4445 | 111 | arrexp_1 := Expression.matrixToArray(arrexp_1); | |
| 4446 | 111 | elt_ty := Types.arrayElementType(ty); | |
| 4447 | 111 | tp := Types.simplifyType(elt_ty); | |
| 4448 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 111 times.
|
111 | false := Types.isString(tp); |
| 4449 | 111 | call := Expression.makePureBuiltinCall(inFnName, {arrexp_1}, tp); | |
| 4450 | 111 | then | |
| 4451 | (call, DAE.PROP(elt_ty,c)); | ||
| 4452 | |||
| 4453 | // min|max(x,y) where x & y are scalars. | ||
| 4454 | case {s1, s2} | ||
| 4455 | algorithm | ||
| 4456 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1023 times.
|
1023 | (cache, s1_1, DAE.PROP(ty1, c1)) := |
| 4457 | elabExpInExpression(cache, env, s1, impl, true, prefix, info); | ||
| 4458 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1023 times.
|
1023 | (cache, s2_1, DAE.PROP(ty2, c2)) := |
| 4459 | elabExpInExpression(cache, env, s2, impl, true, prefix, info); | ||
| 4460 | |||
| 4461 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1023 times.
|
1023 | (s1_1, s2_1, ty, true) := Types.checkTypeCompat(s1_1, ty1, s2_1, ty2); |
| 4462 | 1023 | c := Types.constAnd(c1, c2); | |
| 4463 | 1023 | tp := Types.simplifyType(ty); | |
| 4464 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1023 times.
|
1023 | false := Types.isString(tp); |
| 4465 | 1023 | call := Expression.makePureBuiltinCall(inFnName, {s1_1, s2_1}, tp); | |
| 4466 | 1023 | then | |
| 4467 | (call, DAE.PROP(ty,c)); | ||
| 4468 | |||
| 4469 | end match; | ||
| 4470 | end elabBuiltinMinMaxCommon; | ||
| 4471 | |||
| 4472 | protected function elabBuiltinClock | ||
| 4473 | "Author: BTH | ||
| 4474 | This function elaborates the builtin Clock constructor Clock(..)." | ||
| 4475 | input FCore.Cache inCache; | ||
| 4476 | input FCore.Graph inEnv; | ||
| 4477 | input list<Absyn.Exp> args; | ||
| 4478 | input list<Absyn.NamedArg> nargs; | ||
| 4479 | input Boolean inBoolean; | ||
| 4480 | input DAE.Prefix inPrefix; | ||
| 4481 | input SourceInfo info; | ||
| 4482 | output FCore.Cache outCache; | ||
| 4483 | output DAE.Exp outExp; | ||
| 4484 | output DAE.Properties outProperties; | ||
| 4485 | algorithm | ||
| 4486 | (outCache,outExp,outProperties) := matchcontinue (inCache, inEnv, args, nargs, inBoolean, inPrefix) | ||
| 4487 | local | ||
| 4488 | DAE.Exp call,interval,intervalCounter,resolution,condition,startInterval,c,solverMethod; | ||
| 4489 | DAE.Type ty1,ty2; | ||
| 4490 | Boolean impl; | ||
| 4491 | FCore.Graph env; | ||
| 4492 | FCore.Cache cache; | ||
| 4493 | DAE.Prefix pre; | ||
| 4494 | DAE.Properties prop1,prop2, prop = DAE.PROP(DAE.T_CLOCK_DEFAULT, DAE.C_VAR()); | ||
| 4495 | Absyn.Exp ainterval, aintervalCounter, aresolution, acondition, astartInterval, ac, asolverMethod; | ||
| 4496 | Values.Value val; | ||
| 4497 | |||
| 4498 | // Inferred clock "Clock()" | ||
| 4499 | case (cache, _, {}, {}, _, _) | ||
| 4500 | algorithm | ||
| 4501 | call := DAE.CLKCONST(DAE.INFERRED_CLOCK()); | ||
| 4502 | then (cache, call, DAE.PROP(DAE.T_CLOCK_DEFAULT, DAE.C_VAR())); | ||
| 4503 | |||
| 4504 | // clock with rational interval "Clock(intervalCounter)" | ||
| 4505 | case (cache, env, {aintervalCounter}, {}, impl, pre) | ||
| 4506 | algorithm | ||
| 4507 | 39 | (cache, intervalCounter, prop1) := elabExpInExpression(cache,env,aintervalCounter,impl,true,pre,info); | |
| 4508 | 39 | ty1 := Types.arrayElementType(Types.getPropType(prop1)); | |
| 4509 | 39 | (intervalCounter,_) := Types.matchType(intervalCounter,ty1,DAE.T_INTEGER_DEFAULT,true); | |
| 4510 | ✗ | call := DAE.CLKCONST(DAE.RATIONAL_CLOCK(intervalCounter, DAE.ICONST(1))); | |
| 4511 | ✗ | then (cache, call, prop); | |
| 4512 | |||
| 4513 | // clock with rational interval "Clock(intervalCounter, resolution)" | ||
| 4514 | case (cache, env, {aintervalCounter, aresolution}, {}, impl, pre) | ||
| 4515 | algorithm | ||
| 4516 | 8 | (cache, intervalCounter, prop1) := elabExpInExpression(cache,env,aintervalCounter,impl,true,pre,info); | |
| 4517 | 8 | (cache, resolution, prop2) := elabExpInExpression(cache,env,aresolution,impl,true,pre,info); | |
| 4518 | 8 | ty1 := Types.arrayElementType(Types.getPropType(prop1)); | |
| 4519 | 8 | ty2 := Types.arrayElementType(Types.getPropType(prop2)); | |
| 4520 | 8 | (intervalCounter,_) := Types.matchType(intervalCounter,ty1,DAE.T_INTEGER_DEFAULT,true); | |
| 4521 | 7 | (resolution,_) := Types.matchType(resolution,ty2,DAE.T_INTEGER_DEFAULT,true); | |
| 4522 | // evaluate and check if resolution >= 1 (rfranke) | ||
| 4523 | 7 | (cache, val) := Ceval.ceval(cache, env, resolution, false, Absyn.MSG(info), 0); | |
| 4524 | 14 | Error.assertionOrAddSourceMessage(ValuesUtil.valueInteger(val) >= 1, | |
| 4525 | Error.WRONG_VALUE_OF_ARG, {"Clock", "resolution", ValuesDump.valString(val), ">= 1"}, info); | ||
| 4526 | 7 | resolution := ValuesUtil.valueExp(val, SOME(resolution)); | |
| 4527 | 7 | call := DAE.CLKCONST(DAE.RATIONAL_CLOCK(intervalCounter, resolution)); | |
| 4528 | 7 | then (cache, call, prop); | |
| 4529 | |||
| 4530 | // clock with Real interval "Clock(interval)" | ||
| 4531 | case (cache, env, {ainterval}, {}, impl, pre) | ||
| 4532 | algorithm | ||
| 4533 | 39 | (cache, interval, prop1) := elabExpInExpression(cache,env,ainterval,impl,true,pre,info); | |
| 4534 | 39 | ty1 := Types.arrayElementType(Types.getPropType(prop1)); | |
| 4535 | 39 | (interval,_) := Types.matchType(interval,ty1,DAE.T_REAL_DEFAULT,true); | |
| 4536 | 37 | call := DAE.CLKCONST(DAE.REAL_CLOCK(interval)); | |
| 4537 | 37 | then (cache, call, prop); | |
| 4538 | |||
| 4539 | // Event Clock (clock triggered by zero-crossing events) "Clock(condition)" | ||
| 4540 | case (cache, env, {acondition}, {}, impl, pre) | ||
| 4541 | algorithm | ||
| 4542 | 2 | (cache, condition, prop1) := elabExpInExpression(cache,env,acondition,impl,true,pre,info); | |
| 4543 | 2 | ty1 := Types.arrayElementType(Types.getPropType(prop1)); | |
| 4544 | 2 | (condition,_) := Types.matchType(condition,ty1,DAE.T_BOOL_DEFAULT,true); | |
| 4545 | 2 | call := DAE.CLKCONST(DAE.EVENT_CLOCK(condition, DAE.RCONST(0.0))); | |
| 4546 | 2 | then (cache, call, prop); | |
| 4547 | |||
| 4548 | // Event Clock (clock triggered by zero-crossing events) "Clock(condition, startInterval)" | ||
| 4549 | case (cache, env, {acondition, astartInterval}, {}, impl, pre) | ||
| 4550 | algorithm | ||
| 4551 | 1 | (cache, condition, prop1) := elabExpInExpression(cache,env,acondition,impl,true,pre,info); | |
| 4552 | 1 | (cache, startInterval, prop2) := elabExpInExpression(cache,env,astartInterval,impl,true,pre,info); | |
| 4553 | 1 | ty1 := Types.arrayElementType(Types.getPropType(prop1)); | |
| 4554 | 1 | ty2 := Types.arrayElementType(Types.getPropType(prop2)); | |
| 4555 | 1 | (condition,_) := Types.matchType(condition,ty1,DAE.T_BOOL_DEFAULT,true); | |
| 4556 | 1 | (startInterval,_) := Types.matchType(startInterval,ty2,DAE.T_REAL_DEFAULT,true); | |
| 4557 | // TODO! check if expression startInterval is >= 0.0 | ||
| 4558 | // rStartInterval = Expression.toReal(startInterval); | ||
| 4559 | // true = rStartInterval >= 0.0; | ||
| 4560 | 1 | call := DAE.CLKCONST(DAE.EVENT_CLOCK(condition, startInterval)); | |
| 4561 | 1 | then (cache, call, prop); | |
| 4562 | |||
| 4563 | // Solver Clock "Clock(c, solverMethod)" | ||
| 4564 | case (cache, env, {ac, asolverMethod}, {}, impl, pre) | ||
| 4565 | algorithm | ||
| 4566 | ✗ | (cache, c, prop1) := elabExpInExpression(cache,env,ac,impl,true,pre,info); | |
| 4567 | ✗ | (cache, solverMethod, prop2) := elabExpInExpression(cache,env,asolverMethod,impl,true,pre,info); | |
| 4568 | ✗ | ty1 := Types.arrayElementType(Types.getPropType(prop1)); | |
| 4569 | ✗ | ty2 := Types.arrayElementType(Types.getPropType(prop2)); | |
| 4570 | ✗ | (c,_) := Types.matchType(c,ty1,DAE.T_CLOCK_DEFAULT,true); | |
| 4571 | ✗ | (solverMethod,_) := Types.matchType(solverMethod,ty2,DAE.T_STRING_DEFAULT,true); | |
| 4572 | // evaluate structural solverMethod (rfranke) | ||
| 4573 | ✗ | (cache, val) := Ceval.ceval(cache, env, solverMethod, false, Absyn.MSG(info), 0); | |
| 4574 | ✗ | solverMethod := ValuesUtil.valueExp(val, SOME(solverMethod)); | |
| 4575 | ✗ | call := DAE.CLKCONST(DAE.SOLVER_CLOCK(c, solverMethod)); | |
| 4576 | ✗ | then (cache, call, prop); | |
| 4577 | |||
| 4578 | // Solver Clock "Clock(c, solverMethod=solverMethod)" with named arguments | ||
| 4579 | case (cache, env, {ac}, {Absyn.NAMEDARG(argName="solverMethod", argValue=asolverMethod)}, impl, pre) | ||
| 4580 | algorithm | ||
| 4581 | 3 | (cache, c, prop1) := elabExpInExpression(cache,env,ac,impl,true,pre,info); | |
| 4582 | 3 | (cache, solverMethod, prop2) := elabExpInExpression(cache,env,asolverMethod,impl,true,pre,info); | |
| 4583 | 3 | ty1 := Types.arrayElementType(Types.getPropType(prop1)); | |
| 4584 | 3 | ty2 := Types.arrayElementType(Types.getPropType(prop2)); | |
| 4585 | 3 | (c,_) := Types.matchType(c,ty1,DAE.T_CLOCK_DEFAULT,true); | |
| 4586 | 3 | (solverMethod,_) := Types.matchType(solverMethod,ty2,DAE.T_STRING_DEFAULT,true); | |
| 4587 | // evaluate structural solverMethod (rfranke) | ||
| 4588 | 3 | (cache, val) := Ceval.ceval(cache, env, solverMethod, false, Absyn.MSG(info), 0); | |
| 4589 | 3 | solverMethod := ValuesUtil.valueExp(val, SOME(solverMethod)); | |
| 4590 | 3 | call := DAE.CLKCONST(DAE.SOLVER_CLOCK(c, solverMethod)); | |
| 4591 | 3 | then (cache, call, prop); | |
| 4592 | |||
| 4593 | end matchcontinue; | ||
| 4594 | end elabBuiltinClock; | ||
| 4595 | |||
| 4596 | protected function elabBuiltinHold " | ||
| 4597 | Author: BTH | ||
| 4598 | This function elaborates the builtin operator hold(u)." | ||
| 4599 | input FCore.Cache inCache; | ||
| 4600 | input FCore.Graph inEnv; | ||
| 4601 | input list<Absyn.Exp> args; | ||
| 4602 | input list<Absyn.NamedArg> nargs; | ||
| 4603 | input Boolean inBoolean; | ||
| 4604 | input DAE.Prefix inPrefix; | ||
| 4605 | input SourceInfo info; | ||
| 4606 | output FCore.Cache outCache; | ||
| 4607 | output DAE.Exp outExp; | ||
| 4608 | output DAE.Properties outProperties; | ||
| 4609 | algorithm | ||
| 4610 | (outCache,outExp,outProperties) := match (inCache, inEnv, args, nargs, inBoolean, inPrefix) | ||
| 4611 | local | ||
| 4612 | DAE.Exp call; | ||
| 4613 | DAE.Type ty1,ty; | ||
| 4614 | Boolean impl; | ||
| 4615 | FCore.Graph env; | ||
| 4616 | FCore.Cache cache; | ||
| 4617 | DAE.Prefix pre; | ||
| 4618 | DAE.Properties prop1, prop; | ||
| 4619 | Absyn.Exp au; | ||
| 4620 | |||
| 4621 | case (cache, env, {au}, {}, impl, pre) | ||
| 4622 | algorithm | ||
| 4623 | 13 | (cache,_, prop1) := elabExpInExpression(cache,env,au,impl,true,pre,info); | |
| 4624 | 13 | ty1 := Types.arrayElementType(Types.getPropType(prop1)); | |
| 4625 | 26 | ty := DAE.T_FUNCTION( | |
| 4626 | {DAE.FUNCARG("u",ty1,DAE.C_VAR(),DAE.NON_PARALLEL(),NONE())}, | ||
| 4627 | ty1, | ||
| 4628 | DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE, | ||
| 4629 | Absyn.IDENT("hold")); | ||
| 4630 |
3/6✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 13 times.
✗ Branch 6 not taken.
|
13 | (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("hold"), args, nargs, {}, impl, pre, info); |
| 4631 | then (cache, call, prop); | ||
| 4632 | end match; | ||
| 4633 | end elabBuiltinHold; | ||
| 4634 | |||
| 4635 | protected function elabBuiltinSample " | ||
| 4636 | Author: BTH | ||
| 4637 | This function elaborates the builtin operator sample(..) variants." | ||
| 4638 | input FCore.Cache inCache; | ||
| 4639 | input FCore.Graph inEnv; | ||
| 4640 | input list<Absyn.Exp> args; | ||
| 4641 | input list<Absyn.NamedArg> nargs; | ||
| 4642 | input Boolean inBoolean; | ||
| 4643 | input DAE.Prefix inPrefix; | ||
| 4644 | input SourceInfo info; | ||
| 4645 | output FCore.Cache outCache; | ||
| 4646 | output DAE.Exp outExp; | ||
| 4647 | output DAE.Properties outProperties; | ||
| 4648 | algorithm | ||
| 4649 | (outCache,outExp,outProperties) := matchcontinue (inCache, inEnv, args, nargs, inBoolean, inPrefix) | ||
| 4650 | local | ||
| 4651 | DAE.Exp call,c,start,interval; | ||
| 4652 | DAE.Type ty1,ty2,ty; | ||
| 4653 | Boolean impl; | ||
| 4654 | FCore.Graph env; | ||
| 4655 | FCore.Cache cache; | ||
| 4656 | DAE.Prefix pre; | ||
| 4657 | DAE.Properties prop1,prop2,prop; | ||
| 4658 | DAE.Const variability; | ||
| 4659 | Absyn.Exp au,ac,astart,ainterval; | ||
| 4660 | |||
| 4661 | // The time event triggering sample(start, interval) | ||
| 4662 | case (cache, env, {astart,ainterval}, {}, impl, pre) | ||
| 4663 | algorithm | ||
| 4664 | 81 | (cache, start, prop1) := elabExpInExpression(cache,env,astart,impl,true,pre,info); | |
| 4665 | 81 | (cache, interval, prop2) := elabExpInExpression(cache,env,ainterval,impl,true,pre,info); | |
| 4666 | 81 | ty1 := Types.getPropType(prop1); | |
| 4667 | 81 | ty2 := Types.getPropType(prop2); | |
| 4668 | 81 | (start,_) := Types.matchType(start,ty1,DAE.T_REAL_DEFAULT,true); | |
| 4669 | 81 | (interval,_) := Types.matchType(interval,ty2,DAE.T_REAL_DEFAULT,true); | |
| 4670 | ty := DAE.T_FUNCTION( | ||
| 4671 | {DAE.FUNCARG("start",DAE.T_REAL_DEFAULT,DAE.C_PARAM(),DAE.NON_PARALLEL(),NONE()), | ||
| 4672 | DAE.FUNCARG("interval",DAE.T_REAL_DEFAULT,DAE.C_PARAM(),DAE.NON_PARALLEL(),NONE())}, | ||
| 4673 | DAE.T_BOOL_DEFAULT, | ||
| 4674 | DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE, | ||
| 4675 | Absyn.IDENT("sample")); | ||
| 4676 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 67 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 67 times.
|
68 | (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("sample"), args, nargs, {}, impl, pre, info); |
| 4677 | then (cache, call, prop); | ||
| 4678 | |||
| 4679 | // The sample from the Synchronous Language Elements chapter (Modelica 3.3) | ||
| 4680 | case (cache, env, {au,ac}, {}, impl, pre) | ||
| 4681 | algorithm | ||
| 4682 | 14 | (cache,_, prop1) := elabExpInExpression(cache,env,au,impl,true,pre,info); | |
| 4683 | 14 | (cache, c, prop2) := elabExpInExpression(cache,env,ac,impl,true,pre,info); | |
| 4684 | 14 | ty1 := Types.arrayElementType(Types.getPropType(prop1)); | |
| 4685 | 14 | ty2 := Types.arrayElementType(Types.getPropType(prop2)); | |
| 4686 | 14 | variability := Types.getPropConst(prop1); | |
| 4687 | 14 | (c,_) := Types.matchType(c,ty2,DAE.T_CLOCK_DEFAULT,true); | |
| 4688 | |||
| 4689 | 26 | ty := DAE.T_FUNCTION( | |
| 4690 | {DAE.FUNCARG("u",ty1,variability,DAE.NON_PARALLEL(),NONE()), | ||
| 4691 | DAE.FUNCARG("c",ty2,DAE.C_VAR(),DAE.NON_PARALLEL(),SOME(DAE.CLKCONST(DAE.INFERRED_CLOCK())))}, | ||
| 4692 | ty1, | ||
| 4693 | DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE, | ||
| 4694 | Absyn.IDENT("sample")); | ||
| 4695 | |||
| 4696 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
|
13 | (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("sample"), |
| 4697 | args, nargs, {}, impl, pre, info); | ||
| 4698 | then (cache, call, prop); | ||
| 4699 | |||
| 4700 | case (cache, env, {au}, {}, impl, pre) | ||
| 4701 | algorithm | ||
| 4702 | 20 | (cache,_, prop1) := elabExpInExpression(cache,env,au,impl,true,pre,info); | |
| 4703 | 20 | ty1 := Types.arrayElementType(Types.getPropType(prop1)); | |
| 4704 | 20 | variability := Types.getPropConst(prop1); | |
| 4705 | |||
| 4706 | 40 | ty := DAE.T_FUNCTION( | |
| 4707 | {DAE.FUNCARG("u",ty1,variability,DAE.NON_PARALLEL(),NONE()), | ||
| 4708 | DAE.FUNCARG("c",DAE.T_CLOCK_DEFAULT,DAE.C_VAR(),DAE.NON_PARALLEL(),SOME(DAE.CLKCONST(DAE.INFERRED_CLOCK())))}, | ||
| 4709 | ty1, | ||
| 4710 | DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE, | ||
| 4711 | Absyn.IDENT("sample")); | ||
| 4712 | |||
| 4713 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20 times.
|
20 | (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("sample"), |
| 4714 | args, nargs, {}, impl, pre, info); | ||
| 4715 | then (cache, call, prop); | ||
| 4716 | |||
| 4717 | |||
| 4718 | end matchcontinue; | ||
| 4719 | end elabBuiltinSample; | ||
| 4720 | |||
| 4721 | protected function elabBuiltinShiftSample " | ||
| 4722 | Author: BTH | ||
| 4723 | This function elaborates the builtin operator shiftSample(u,shiftCounter,resolution)." | ||
| 4724 | input FCore.Cache inCache; | ||
| 4725 | input FCore.Graph inEnv; | ||
| 4726 | input list<Absyn.Exp> args; | ||
| 4727 | input list<Absyn.NamedArg> nargs; | ||
| 4728 | input Boolean inBoolean; | ||
| 4729 | input DAE.Prefix inPrefix; | ||
| 4730 | input SourceInfo info; | ||
| 4731 | output FCore.Cache outCache; | ||
| 4732 | output DAE.Exp outExp; | ||
| 4733 | output DAE.Properties outProperties; | ||
| 4734 | algorithm | ||
| 4735 | (outCache,outExp,outProperties) := match (inCache, inEnv, args, nargs, inBoolean, inPrefix) | ||
| 4736 | local | ||
| 4737 | DAE.Exp call,shiftCounter,resolution; | ||
| 4738 | DAE.Type ty1,ty; | ||
| 4739 | Boolean impl; | ||
| 4740 | FCore.Graph env; | ||
| 4741 | FCore.Cache cache; | ||
| 4742 | DAE.Prefix pre; | ||
| 4743 | DAE.Properties prop1,prop2,prop3,prop; | ||
| 4744 | Absyn.Exp au,ashiftCounter,aresolution; | ||
| 4745 | Values.Value val, rval; | ||
| 4746 | |||
| 4747 | case (cache, env, {au,ashiftCounter}, {}, impl, pre) | ||
| 4748 | algorithm | ||
| 4749 | 4 | (cache,_, prop1) := elabExpInExpression(cache,env,au,impl,true,pre,info); | |
| 4750 | 4 | (cache, shiftCounter, prop2) := elabExpInExpression(cache,env,ashiftCounter,impl,true,pre,info); | |
| 4751 | 4 | (shiftCounter,_) := Types.matchType(shiftCounter,Types.getPropType(prop2),DAE.T_INTEGER_DEFAULT,true); | |
| 4752 | // evaluate and check if shiftCounter >= 0 (rfranke) | ||
| 4753 | 4 | (cache, val) := Ceval.ceval(cache, env, shiftCounter, false, Absyn.MSG(info), 0); | |
| 4754 | 8 | Error.assertionOrAddSourceMessage(ValuesUtil.valueInteger(val) >= 0, | |
| 4755 | Error.WRONG_VALUE_OF_ARG, {"shiftSample", "shiftCounter", ValuesDump.valString(val), ">= 0"}, info); | ||
| 4756 | 4 | ashiftCounter := Absyn.INTEGER(ValuesUtil.valueInteger(val)); | |
| 4757 | aresolution := Absyn.INTEGER(1); | ||
| 4758 | 4 | ty1 := Types.arrayElementType(Types.getPropType(prop1)); | |
| 4759 | 8 | ty := DAE.T_FUNCTION( | |
| 4760 | {DAE.FUNCARG("u",ty1,DAE.C_VAR(),DAE.NON_PARALLEL(),NONE()), | ||
| 4761 | DAE.FUNCARG("shiftCounter",DAE.T_INTEGER_DEFAULT,DAE.C_PARAM(),DAE.NON_PARALLEL(),NONE()), | ||
| 4762 | DAE.FUNCARG("resolution",DAE.T_INTEGER_DEFAULT,DAE.C_PARAM(),DAE.NON_PARALLEL(),NONE())}, | ||
| 4763 | ty1, | ||
| 4764 | DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE, | ||
| 4765 | Absyn.IDENT("shiftSample")); | ||
| 4766 | // Pretend that shiftSample(u,shiftCounter) was shiftSample(u,shiftCounter,1) (resolution=1 is default value) | ||
| 4767 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
|
4 | (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("shiftSample"), {au, ashiftCounter, aresolution}, nargs, {}, impl, pre, info); |
| 4768 | then (cache, call, prop); | ||
| 4769 | |||
| 4770 | case (cache, env, {au,ashiftCounter,aresolution}, {}, impl, pre) | ||
| 4771 | algorithm | ||
| 4772 | 6 | (cache,_, prop1) := elabExpInExpression(cache,env,au,impl,true,pre,info); | |
| 4773 | 6 | (cache, shiftCounter, prop2) := elabExpInExpression(cache,env,ashiftCounter,impl,true,pre,info); | |
| 4774 | 6 | (shiftCounter,_) := Types.matchType(shiftCounter,Types.getPropType(prop2),DAE.T_INTEGER_DEFAULT,true); | |
| 4775 | // evaluate and check if shiftCounter >= 0 (rfranke) | ||
| 4776 | 6 | (cache, val) := Ceval.ceval(cache, env, shiftCounter, false, Absyn.MSG(info), 0); | |
| 4777 | 12 | Error.assertionOrAddSourceMessage(ValuesUtil.valueInteger(val) >= 0, | |
| 4778 | Error.WRONG_VALUE_OF_ARG, {"shiftSample", "shiftCounter", ValuesDump.valString(val), ">= 0"}, info); | ||
| 4779 | 6 | ashiftCounter := Absyn.INTEGER(ValuesUtil.valueInteger(val)); | |
| 4780 | 6 | (cache, resolution, prop3) := elabExpInExpression(cache,env,aresolution,impl,true,pre,info); | |
| 4781 | 6 | (resolution,_) := Types.matchType(resolution,Types.getPropType(prop3),DAE.T_INTEGER_DEFAULT,true); | |
| 4782 | // evaluate and check if resolution >= 1 (rfranke) | ||
| 4783 | 6 | (cache, rval) := Ceval.ceval(cache, env, resolution, false, Absyn.MSG(info), 0); | |
| 4784 | 12 | Error.assertionOrAddSourceMessage(ValuesUtil.valueInteger(rval) >= 1, | |
| 4785 | Error.WRONG_VALUE_OF_ARG, {"shiftSample", "resolution", ValuesDump.valString(rval), ">= 1"}, info); | ||
| 4786 | 6 | aresolution := Absyn.INTEGER(ValuesUtil.valueInteger(rval)); | |
| 4787 | 6 | ty1 := Types.arrayElementType(Types.getPropType(prop1)); | |
| 4788 | 12 | ty := DAE.T_FUNCTION( | |
| 4789 | {DAE.FUNCARG("u",ty1,DAE.C_VAR(),DAE.NON_PARALLEL(),NONE()), | ||
| 4790 | DAE.FUNCARG("shiftCounter",DAE.T_INTEGER_DEFAULT,DAE.C_PARAM(),DAE.NON_PARALLEL(),NONE()), | ||
| 4791 | DAE.FUNCARG("resolution",DAE.T_INTEGER_DEFAULT,DAE.C_PARAM(),DAE.NON_PARALLEL(),NONE())}, | ||
| 4792 | ty1, | ||
| 4793 | DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE, | ||
| 4794 | Absyn.IDENT("shiftSample")); | ||
| 4795 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
|
6 | (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("shiftSample"), {au, ashiftCounter, aresolution}, nargs, {}, impl, pre, info); |
| 4796 | then (cache, call, prop); | ||
| 4797 | end match; | ||
| 4798 | end elabBuiltinShiftSample; | ||
| 4799 | |||
| 4800 | protected function elabBuiltinBackSample " | ||
| 4801 | Author: BTH | ||
| 4802 | This function elaborates the builtin operator backSample(u,backCounter,resolution)." | ||
| 4803 | input FCore.Cache inCache; | ||
| 4804 | input FCore.Graph inEnv; | ||
| 4805 | input list<Absyn.Exp> args; | ||
| 4806 | input list<Absyn.NamedArg> nargs; | ||
| 4807 | input Boolean inBoolean; | ||
| 4808 | input DAE.Prefix inPrefix; | ||
| 4809 | input SourceInfo info; | ||
| 4810 | output FCore.Cache outCache; | ||
| 4811 | output DAE.Exp outExp; | ||
| 4812 | output DAE.Properties outProperties; | ||
| 4813 | algorithm | ||
| 4814 | (outCache,outExp,outProperties) := match (inCache, inEnv, args, nargs, inBoolean, inPrefix) | ||
| 4815 | local | ||
| 4816 | DAE.Exp call,backCounter,resolution; | ||
| 4817 | DAE.Type ty1,ty; | ||
| 4818 | Boolean impl; | ||
| 4819 | FCore.Graph env; | ||
| 4820 | FCore.Cache cache; | ||
| 4821 | DAE.Prefix pre; | ||
| 4822 | DAE.Properties prop1,prop2,prop3,prop; | ||
| 4823 | Absyn.Exp au,abackCounter,aresolution; | ||
| 4824 | Values.Value val, rval; | ||
| 4825 | |||
| 4826 | case (cache, env, {au,abackCounter}, {}, impl, pre) | ||
| 4827 | algorithm | ||
| 4828 | 4 | (cache,_, prop1) := elabExpInExpression(cache,env,au,impl,true,pre,info); | |
| 4829 | 4 | (cache, backCounter, prop2) := elabExpInExpression(cache,env,abackCounter,impl,true,pre,info); | |
| 4830 | 4 | (backCounter,_) := Types.matchType(backCounter,Types.getPropType(prop2),DAE.T_INTEGER_DEFAULT,true); | |
| 4831 | // evaluate and check if backCounter >= 0 (rfranke) | ||
| 4832 | 4 | (cache, val) := Ceval.ceval(cache, env, backCounter, false, Absyn.MSG(info), 0); | |
| 4833 | 8 | Error.assertionOrAddSourceMessage(ValuesUtil.valueInteger(val) >= 0, | |
| 4834 | Error.WRONG_VALUE_OF_ARG, {"backSample", "backCounter", ValuesDump.valString(val), ">= 0"}, info); | ||
| 4835 | 4 | abackCounter := Absyn.INTEGER(ValuesUtil.valueInteger(val)); | |
| 4836 | aresolution := Absyn.INTEGER(1); | ||
| 4837 | 4 | ty1 := Types.arrayElementType(Types.getPropType(prop1)); | |
| 4838 | 8 | ty := DAE.T_FUNCTION( | |
| 4839 | {DAE.FUNCARG("u",ty1,DAE.C_VAR(),DAE.NON_PARALLEL(),NONE()), | ||
| 4840 | DAE.FUNCARG("backCounter",DAE.T_INTEGER_DEFAULT,DAE.C_PARAM(),DAE.NON_PARALLEL(),NONE()), | ||
| 4841 | DAE.FUNCARG("resolution",DAE.T_INTEGER_DEFAULT,DAE.C_PARAM(),DAE.NON_PARALLEL(),NONE())}, | ||
| 4842 | ty1, | ||
| 4843 | DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE, | ||
| 4844 | Absyn.IDENT("backSample")); | ||
| 4845 | // Pretend that backSample(u,backCounter) was backSample(u,backCounter,1) (resolution=1 is default value) | ||
| 4846 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
|
4 | (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("backSample"), {au, abackCounter, aresolution}, nargs, {}, impl, pre, info); |
| 4847 | then (cache, call, prop); | ||
| 4848 | |||
| 4849 | case (cache, env, {au,abackCounter,aresolution}, {}, impl, pre) | ||
| 4850 | algorithm | ||
| 4851 | 2 | (cache,_, prop1) := elabExpInExpression(cache,env,au,impl,true,pre,info); | |
| 4852 | 2 | (cache, backCounter, prop2) := elabExpInExpression(cache,env,abackCounter,impl,true,pre,info); | |
| 4853 | 2 | (backCounter,_) := Types.matchType(backCounter,Types.getPropType(prop2),DAE.T_INTEGER_DEFAULT,true); | |
| 4854 | // evaluate and check if backCounter >= 0 (rfranke) | ||
| 4855 | 2 | (cache, val) := Ceval.ceval(cache, env, backCounter, false, Absyn.MSG(info), 0); | |
| 4856 | 4 | Error.assertionOrAddSourceMessage(ValuesUtil.valueInteger(val) >= 0, | |
| 4857 | Error.WRONG_VALUE_OF_ARG, {"backSample", "backCounter", ValuesDump.valString(val), ">= 0"}, info); | ||
| 4858 | 2 | abackCounter := Absyn.INTEGER(ValuesUtil.valueInteger(val)); | |
| 4859 | 2 | (cache, resolution, prop3) := elabExpInExpression(cache,env,aresolution,impl,true,pre,info); | |
| 4860 | 2 | (resolution,_) := Types.matchType(resolution,Types.getPropType(prop3),DAE.T_INTEGER_DEFAULT,true); | |
| 4861 | // evaluate and check if resolution >= 1 (rfranke) | ||
| 4862 | 2 | (cache, rval) := Ceval.ceval(cache, env, resolution, false, Absyn.MSG(info), 0); | |
| 4863 | 4 | Error.assertionOrAddSourceMessage(ValuesUtil.valueInteger(rval) >= 1, | |
| 4864 | Error.WRONG_VALUE_OF_ARG, {"backSample", "resolution", ValuesDump.valString(rval), ">= 1"}, info); | ||
| 4865 | 2 | aresolution := Absyn.INTEGER(ValuesUtil.valueInteger(rval)); | |
| 4866 | 2 | ty1 := Types.arrayElementType(Types.getPropType(prop1)); | |
| 4867 | 4 | ty := DAE.T_FUNCTION( | |
| 4868 | {DAE.FUNCARG("u",ty1,DAE.C_VAR(),DAE.NON_PARALLEL(),NONE()), | ||
| 4869 | DAE.FUNCARG("backCounter",DAE.T_INTEGER_DEFAULT,DAE.C_PARAM(),DAE.NON_PARALLEL(),NONE()), | ||
| 4870 | DAE.FUNCARG("resolution",DAE.T_INTEGER_DEFAULT,DAE.C_PARAM(),DAE.NON_PARALLEL(),NONE())}, | ||
| 4871 | ty1, | ||
| 4872 | DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE, | ||
| 4873 | Absyn.IDENT("backSample")); | ||
| 4874 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
|
2 | (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("backSample"), {au, abackCounter, aresolution}, nargs, {}, impl, pre, info); |
| 4875 | then (cache, call, prop); | ||
| 4876 | end match; | ||
| 4877 | end elabBuiltinBackSample; | ||
| 4878 | |||
| 4879 | protected function elabBuiltinNoClock " | ||
| 4880 | Author: BTH | ||
| 4881 | This function elaborates the builtin operator noClock(u)." | ||
| 4882 | input FCore.Cache inCache; | ||
| 4883 | input FCore.Graph inEnv; | ||
| 4884 | input list<Absyn.Exp> args; | ||
| 4885 | input list<Absyn.NamedArg> nargs; | ||
| 4886 | input Boolean inBoolean; | ||
| 4887 | input DAE.Prefix inPrefix; | ||
| 4888 | input SourceInfo info; | ||
| 4889 | output FCore.Cache outCache; | ||
| 4890 | output DAE.Exp outExp; | ||
| 4891 | output DAE.Properties outProperties; | ||
| 4892 | algorithm | ||
| 4893 | (outCache,outExp,outProperties) := match (inCache, inEnv, args, nargs, inBoolean, inPrefix) | ||
| 4894 | local | ||
| 4895 | DAE.Exp call; | ||
| 4896 | DAE.Type ty1,ty; | ||
| 4897 | Boolean impl; | ||
| 4898 | FCore.Graph env; | ||
| 4899 | FCore.Cache cache; | ||
| 4900 | DAE.Prefix pre; | ||
| 4901 | DAE.Properties prop1, prop; | ||
| 4902 | Absyn.Exp au; | ||
| 4903 | |||
| 4904 | case (cache, env, {au}, {}, impl, pre) | ||
| 4905 | algorithm | ||
| 4906 | 5 | (cache,_, prop1) := elabExpInExpression(cache,env,au,impl,true,pre,info); | |
| 4907 | 5 | ty1 := Types.arrayElementType(Types.getPropType(prop1)); | |
| 4908 | 10 | ty := DAE.T_FUNCTION( | |
| 4909 | {DAE.FUNCARG("u",ty1,DAE.C_VAR(),DAE.NON_PARALLEL(),NONE())}, | ||
| 4910 | ty1, | ||
| 4911 | DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE, | ||
| 4912 | Absyn.IDENT("noClock")); | ||
| 4913 |
3/6✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 5 times.
✗ Branch 6 not taken.
|
5 | (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("noClock"), args, nargs, {}, impl, pre, info); |
| 4914 | then (cache, call, prop); | ||
| 4915 | end match; | ||
| 4916 | end elabBuiltinNoClock; | ||
| 4917 | |||
| 4918 | protected function elabBuiltinFirstTick " | ||
| 4919 | This function elaborates the builtin operator firstTick(u)." | ||
| 4920 | input FCore.Cache inCache; | ||
| 4921 | input FCore.Graph inEnv; | ||
| 4922 | input list<Absyn.Exp> args; | ||
| 4923 | input list<Absyn.NamedArg> nargs; | ||
| 4924 | input Boolean inBoolean; | ||
| 4925 | input DAE.Prefix inPrefix; | ||
| 4926 | input SourceInfo info; | ||
| 4927 | output FCore.Cache outCache; | ||
| 4928 | output DAE.Exp outExp; | ||
| 4929 | output DAE.Properties outProperties; | ||
| 4930 | algorithm | ||
| 4931 | (outCache,outExp,outProperties) := match (inCache, inEnv, args, nargs, inBoolean, inPrefix) | ||
| 4932 | local | ||
| 4933 | DAE.Exp call; | ||
| 4934 | DAE.Type ty1,ty; | ||
| 4935 | Boolean impl; | ||
| 4936 | FCore.Graph env; | ||
| 4937 | FCore.Cache cache; | ||
| 4938 | DAE.Prefix pre; | ||
| 4939 | DAE.Properties prop1, prop; | ||
| 4940 | Absyn.Exp au; | ||
| 4941 | |||
| 4942 | case (cache, env, {}, {}, impl, pre) | ||
| 4943 | algorithm | ||
| 4944 | ty := DAE.T_FUNCTION( | ||
| 4945 | {}, | ||
| 4946 | DAE.T_BOOL_DEFAULT, | ||
| 4947 | DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE, | ||
| 4948 | Absyn.IDENT("firstTick")); | ||
| 4949 | ✗ | (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("firstTick"), args, nargs, {}, impl, pre, info); | |
| 4950 | then (cache, call, prop); | ||
| 4951 | |||
| 4952 | case (cache, env, {au}, {}, impl, pre) | ||
| 4953 | algorithm | ||
| 4954 | ✗ | (cache,_, prop1) := elabExpInExpression(cache,env,au,impl,true,pre,info); | |
| 4955 | ✗ | ty1 := Types.arrayElementType(Types.getPropType(prop1)); | |
| 4956 | ✗ | ty := DAE.T_FUNCTION( | |
| 4957 | {DAE.FUNCARG("u",ty1,DAE.C_VAR(),DAE.NON_PARALLEL(),NONE())}, | ||
| 4958 | DAE.T_BOOL_DEFAULT, | ||
| 4959 | DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE, | ||
| 4960 | Absyn.IDENT("firstTick")); | ||
| 4961 | ✗ | (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("firstTick"), args, nargs, {}, impl, pre, info); | |
| 4962 | then (cache, call, prop); | ||
| 4963 | end match; | ||
| 4964 | end elabBuiltinFirstTick; | ||
| 4965 | |||
| 4966 | protected function elabBuiltinInterval " | ||
| 4967 | Author: BTH | ||
| 4968 | This function elaborates the builtin operator interval(u)." | ||
| 4969 | input FCore.Cache inCache; | ||
| 4970 | input FCore.Graph inEnv; | ||
| 4971 | input list<Absyn.Exp> args; | ||
| 4972 | input list<Absyn.NamedArg> nargs; | ||
| 4973 | input Boolean inBoolean; | ||
| 4974 | input DAE.Prefix inPrefix; | ||
| 4975 | input SourceInfo info; | ||
| 4976 | output FCore.Cache outCache; | ||
| 4977 | output DAE.Exp outExp; | ||
| 4978 | output DAE.Properties outProperties; | ||
| 4979 | algorithm | ||
| 4980 | (outCache,outExp,outProperties) := match (inCache, inEnv, args, nargs, inBoolean, inPrefix) | ||
| 4981 | local | ||
| 4982 | DAE.Exp call; | ||
| 4983 | DAE.Type ty1,ty; | ||
| 4984 | Boolean impl; | ||
| 4985 | FCore.Graph env; | ||
| 4986 | FCore.Cache cache; | ||
| 4987 | DAE.Prefix pre; | ||
| 4988 | DAE.Properties prop1, prop; | ||
| 4989 | Absyn.Exp au; | ||
| 4990 | |||
| 4991 | case (cache, env, {}, {}, impl, pre) | ||
| 4992 | algorithm | ||
| 4993 | ty := DAE.T_FUNCTION( | ||
| 4994 | {}, | ||
| 4995 | DAE.T_REAL_DEFAULT, | ||
| 4996 | DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE, | ||
| 4997 | Absyn.IDENT("interval")); | ||
| 4998 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
|
2 | (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("interval"), args, nargs, {}, impl, pre, info); |
| 4999 | then (cache, call, prop); | ||
| 5000 | |||
| 5001 | case (cache, env, {au}, {}, impl, pre) | ||
| 5002 | algorithm | ||
| 5003 | 4 | (cache,_, prop1) := elabExpInExpression(cache,env,au,impl,true,pre,info); | |
| 5004 | 4 | ty1 := Types.arrayElementType(Types.getPropType(prop1)); | |
| 5005 | 8 | ty := DAE.T_FUNCTION( | |
| 5006 | {DAE.FUNCARG("u",ty1,DAE.C_VAR(),DAE.NON_PARALLEL(),NONE())}, | ||
| 5007 | DAE.T_REAL_DEFAULT, | ||
| 5008 | DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE, | ||
| 5009 | Absyn.IDENT("interval")); | ||
| 5010 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
|
4 | (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("interval"), args, nargs, {}, impl, pre, info); |
| 5011 | then (cache, call, prop); | ||
| 5012 | end match; | ||
| 5013 | end elabBuiltinInterval; | ||
| 5014 | |||
| 5015 | protected function isBlockTypeWorkaround " | ||
| 5016 | Author: BTH | ||
| 5017 | Helper function to elabBuiltinTransition. | ||
| 5018 | This function checks whether a type is complex. | ||
| 5019 | It is used as a workaround to check for block instances in elabBuiltinTransition, elabBultinActiveState and elabBuiltinInitalState. | ||
| 5020 | This is not perfect since there are also other instances that are 'complex' types which are not block instances. | ||
| 5021 | But allowing more might not be so bad anyway, since the MLS 3.3 restriction to block seems more restrictive than necessary, | ||
| 5022 | e.g., one can be more lenient and allow models as states, too..." | ||
| 5023 | input DAE.Type ity; | ||
| 5024 | output Boolean b; | ||
| 5025 | algorithm | ||
| 5026 | b := match ity | ||
| 5027 | ✗ | case DAE.T_SUBTYPE_BASIC() then isBlockTypeWorkaround(ity.complexType); | |
| 5028 | case DAE.T_COMPLEX() then true; | ||
| 5029 | else false; | ||
| 5030 | end match; | ||
| 5031 | end isBlockTypeWorkaround; | ||
| 5032 | |||
| 5033 | protected function elabBuiltinTransition " | ||
| 5034 | Author: BTH | ||
| 5035 | This function elaborates the builtin operator | ||
| 5036 | transition(from, to, condition, immediate=true, reset=true, synchronize=false, priority=1)." | ||
| 5037 | input FCore.Cache inCache; | ||
| 5038 | input FCore.Graph inEnv; | ||
| 5039 | input list<Absyn.Exp> args; | ||
| 5040 | input list<Absyn.NamedArg> nargs; | ||
| 5041 | input Boolean inBoolean; | ||
| 5042 | input DAE.Prefix inPrefix; | ||
| 5043 | input SourceInfo info; | ||
| 5044 | output FCore.Cache outCache; | ||
| 5045 | output DAE.Exp outExp; | ||
| 5046 | output DAE.Properties outProperties; | ||
| 5047 | algorithm | ||
| 5048 | (outCache,outExp,outProperties) := match (inCache, inEnv, inBoolean, inPrefix) | ||
| 5049 | local | ||
| 5050 | DAE.Exp call; | ||
| 5051 | DAE.Type ty1,ty2,ty; | ||
| 5052 | Boolean impl; | ||
| 5053 | FCore.Graph env; | ||
| 5054 | FCore.Cache cache; | ||
| 5055 | DAE.Prefix pre; | ||
| 5056 | DAE.Properties prop; | ||
| 5057 | Integer n; | ||
| 5058 | String strMsg0,strPre,s1,s2; | ||
| 5059 | list<String> slist; | ||
| 5060 | |||
| 5061 | case (cache, env, impl, pre) | ||
| 5062 | algorithm | ||
| 5063 | 16 | slist := List.map(nargs,Dump.printNamedArgStr); | |
| 5064 | 16 | s1 := Dump.printExpLstStr(args); | |
| 5065 | 16 | s2 := stringDelimitList(s1 :: slist, ", "); | |
| 5066 | 16 | strMsg0 := "transition(" + s2 + ")"; | |
| 5067 | 16 | strPre := PrefixUtil.printPrefixStr3(pre); | |
| 5068 | 16 | n := listLength(args); | |
| 5069 | |||
| 5070 | // Check if "from" and "to" arguments are of complex type and return their type | ||
| 5071 | 16 | ty1 := elabBuiltinTransition2(cache, env, args, nargs, impl, pre, info, "from", n, strMsg0, strPre); | |
| 5072 | 16 | ty2 := elabBuiltinTransition2(cache, env, args, nargs, impl, pre, info, "to", n, strMsg0, strPre); | |
| 5073 | |||
| 5074 | // Alternatively, ty1 and ty2 could be replaced by DAE.T_CODE(DAE.C_VARIABLENAME,{}), not sure if that would be a better solution | ||
| 5075 | 32 | ty := DAE.T_FUNCTION( | |
| 5076 | {DAE.FUNCARG("from",ty1,DAE.C_VAR(),DAE.NON_PARALLEL(),NONE()), | ||
| 5077 | DAE.FUNCARG("to",ty2,DAE.C_VAR(),DAE.NON_PARALLEL(),NONE()), | ||
| 5078 | DAE.FUNCARG("condition",DAE.T_BOOL_DEFAULT,DAE.C_VAR(),DAE.NON_PARALLEL(),NONE()), | ||
| 5079 | DAE.FUNCARG("immediate",DAE.T_BOOL_DEFAULT,DAE.C_PARAM(),DAE.NON_PARALLEL(),SOME(DAE.BCONST(true))), | ||
| 5080 | DAE.FUNCARG("reset",DAE.T_BOOL_DEFAULT,DAE.C_PARAM(),DAE.NON_PARALLEL(),SOME(DAE.BCONST(true))), | ||
| 5081 | DAE.FUNCARG("synchronize",DAE.T_BOOL_DEFAULT,DAE.C_PARAM(),DAE.NON_PARALLEL(),SOME(DAE.BCONST(false))), | ||
| 5082 | DAE.FUNCARG("priority",DAE.T_INTEGER_DEFAULT,DAE.C_PARAM(),DAE.NON_PARALLEL(),SOME(DAE.ICONST(1)))}, | ||
| 5083 | DAE.T_NORETCALL_DEFAULT, | ||
| 5084 | DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE, | ||
| 5085 | Absyn.IDENT("transition")); | ||
| 5086 |
3/6✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16 times.
✓ Branch 5 taken 16 times.
✗ Branch 6 not taken.
|
16 | (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("transition"), args, nargs, {}, impl, pre, info); |
| 5087 | then (cache, call, prop); | ||
| 5088 | end match; | ||
| 5089 | end elabBuiltinTransition; | ||
| 5090 | |||
| 5091 | protected function elabBuiltinTransition2 " | ||
| 5092 | Author: BTH | ||
| 5093 | Helper function to elabBuiltinTransition. | ||
| 5094 | Check if the \"from\" argument or the \"to\" argument is of complex type." | ||
| 5095 | input FCore.Cache inCache; | ||
| 5096 | input FCore.Graph inEnv; | ||
| 5097 | input list<Absyn.Exp> args; | ||
| 5098 | input list<Absyn.NamedArg> nargs; | ||
| 5099 | input Boolean inBoolean; | ||
| 5100 | input DAE.Prefix inPrefix; | ||
| 5101 | input SourceInfo info; | ||
| 5102 | input Absyn.Ident argName; | ||
| 5103 | input Integer n; | ||
| 5104 | input String strMsg0; | ||
| 5105 | input String strPre; | ||
| 5106 | output DAE.Type ty; | ||
| 5107 | protected | ||
| 5108 | Absyn.Exp arg1; | ||
| 5109 | DAE.Properties prop1; | ||
| 5110 | Integer nPos; | ||
| 5111 | String s1,s2,strPos,strMsg1; | ||
| 5112 | Boolean b1; | ||
| 5113 | algorithm | ||
| 5114 |
3/4✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16 times.
|
32 | strPos := if argName == "from" then "first" else "second"; |
| 5115 |
3/4✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16 times.
|
32 | nPos := if argName == "from" then 1 else 2; |
| 5116 | 32 | b1 := List.isMemberOnTrue(argName, nargs, elabBuiltinTransition3); | |
| 5117 | |||
| 5118 | 32 | s1 := strMsg0 + ", named argument \"" + argName + "\" already has a value."; | |
| 5119 | 32 | Error.assertionOrAddSourceMessage(not (b1 and n >= nPos),Error.WRONG_TYPE_OR_NO_OF_ARGS, | |
| 5120 | {s1, strPre}, info); | ||
| 5121 | |||
| 5122 | 32 | s2 := strMsg0 + ", missing value for " + strPos + " argument \"" + argName + "\"."; | |
| 5123 | 32 | Error.assertionOrAddSourceMessage(b1 or n >= nPos, Error.WRONG_TYPE_OR_NO_OF_ARGS, | |
| 5124 | {s2, strPre}, info); | ||
| 5125 | |||
| 5126 | 32 | arg1 := elabBuiltinTransition5(argName, b1, args, nargs); | |
| 5127 | 32 | (_, _, prop1) := elabExpInExpression(inCache,inEnv,arg1,inBoolean,true,inPrefix,info); | |
| 5128 | 32 | ty := Types.getPropType(prop1); | |
| 5129 | 32 | strMsg1 := strMsg0 + ", " + strPos + "argument needs to be a block instance."; | |
| 5130 | 32 | Error.assertionOrAddSourceMessage(isBlockTypeWorkaround(ty),Error.WRONG_TYPE_OR_NO_OF_ARGS, | |
| 5131 | {strMsg1, strPre}, info); | ||
| 5132 | |||
| 5133 | end elabBuiltinTransition2; | ||
| 5134 | |||
| 5135 | |||
| 5136 | protected function elabBuiltinTransition3 " | ||
| 5137 | Author: BTH | ||
| 5138 | Helper function to elabBuiltinTransition. | ||
| 5139 | Checks if namedArg.argName == name" | ||
| 5140 | input Absyn.Ident name; | ||
| 5141 | input Absyn.NamedArg namedArg; | ||
| 5142 | output Boolean outIsEqual; | ||
| 5143 | algorithm | ||
| 5144 | outIsEqual := match namedArg | ||
| 5145 | local | ||
| 5146 | Absyn.Ident argName; | ||
| 5147 | |||
| 5148 | case Absyn.NAMEDARG() | ||
| 5149 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
70 | then stringEq(name, namedArg.argName); |
| 5150 | |||
| 5151 | else false; | ||
| 5152 | end match; | ||
| 5153 | end elabBuiltinTransition3; | ||
| 5154 | |||
| 5155 | protected function elabBuiltinTransition4 " | ||
| 5156 | Author: BTH | ||
| 5157 | Helper function to elabBuiltinTransition. | ||
| 5158 | Extract element argValue." | ||
| 5159 | input Absyn.NamedArg inElement; | ||
| 5160 | output Absyn.Exp argValue; | ||
| 5161 | algorithm | ||
| 5162 | ✗ | Absyn.NAMEDARG(argValue = argValue) := inElement; | |
| 5163 | end elabBuiltinTransition4; | ||
| 5164 | |||
| 5165 | protected function elabBuiltinTransition5 " | ||
| 5166 | Author: BTH | ||
| 5167 | Helper function to elabBuiltinTransition." | ||
| 5168 | input String argName; | ||
| 5169 | input Boolean getAsNamedArg; | ||
| 5170 | input list<Absyn.Exp> args; | ||
| 5171 | input list<Absyn.NamedArg> nargs; | ||
| 5172 | output Absyn.Exp argValue; | ||
| 5173 | algorithm | ||
| 5174 | argValue := match (argName, getAsNamedArg) | ||
| 5175 | local | ||
| 5176 | Absyn.NamedArg namedArg; | ||
| 5177 | |||
| 5178 | case ("from", true) | ||
| 5179 | algorithm | ||
| 5180 | ✗ | namedArg := List.getMemberOnTrue("from", nargs, elabBuiltinTransition3); | |
| 5181 | then elabBuiltinTransition4(namedArg); | ||
| 5182 | case ("from", false) | ||
| 5183 | 16 | then listHead(args); | |
| 5184 | case ("to", true) | ||
| 5185 | algorithm | ||
| 5186 | ✗ | namedArg := List.getMemberOnTrue("to", nargs, elabBuiltinTransition3); | |
| 5187 | then elabBuiltinTransition4(namedArg); | ||
| 5188 | case ("to", false) | ||
| 5189 | 16 | then listGet(args, 2); | |
| 5190 | end match; | ||
| 5191 | end elabBuiltinTransition5; | ||
| 5192 | |||
| 5193 | protected function elabBuiltinInitialState " | ||
| 5194 | Author: BTH | ||
| 5195 | This function elaborates the builtin operator | ||
| 5196 | initialState(state)." | ||
| 5197 | input FCore.Cache inCache; | ||
| 5198 | input FCore.Graph inEnv; | ||
| 5199 | input list<Absyn.Exp> args; | ||
| 5200 | input list<Absyn.NamedArg> nargs; | ||
| 5201 | input Boolean inBoolean; | ||
| 5202 | input DAE.Prefix inPrefix; | ||
| 5203 | input SourceInfo info; | ||
| 5204 | output FCore.Cache outCache; | ||
| 5205 | output DAE.Exp outExp; | ||
| 5206 | output DAE.Properties outProperties; | ||
| 5207 | algorithm | ||
| 5208 | (outCache,outExp,outProperties) := match (inCache, inEnv, args, nargs, inBoolean, inPrefix) | ||
| 5209 | local | ||
| 5210 | DAE.Exp call; | ||
| 5211 | DAE.Type ty1,ty; | ||
| 5212 | Boolean impl; | ||
| 5213 | FCore.Graph env; | ||
| 5214 | FCore.Cache cache; | ||
| 5215 | DAE.Prefix pre; | ||
| 5216 | DAE.Properties prop1,prop; | ||
| 5217 | Absyn.Exp astate; | ||
| 5218 | String strMsg, strPre; | ||
| 5219 | |||
| 5220 | case (cache, env, {astate}, {}, impl, pre) | ||
| 5221 | algorithm | ||
| 5222 | 8 | (cache,_, prop1) := elabExpInExpression(cache,env,astate,impl,true,pre,info); | |
| 5223 | 8 | ty1 := Types.getPropType(prop1); | |
| 5224 | 8 | strMsg := "initialState(" + Dump.printExpLstStr(args) + "), Argument needs to be a block instance."; | |
| 5225 | 8 | strPre := PrefixUtil.printPrefixStr3(pre); | |
| 5226 | 8 | Error.assertionOrAddSourceMessage(isBlockTypeWorkaround(ty1),Error.WRONG_TYPE_OR_NO_OF_ARGS, | |
| 5227 | {strMsg, strPre}, info); | ||
| 5228 | |||
| 5229 | 16 | ty := DAE.T_FUNCTION( | |
| 5230 | {DAE.FUNCARG("state",ty1,DAE.C_VAR(),DAE.NON_PARALLEL(),NONE())}, | ||
| 5231 | DAE.T_NORETCALL_DEFAULT, | ||
| 5232 | DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE, | ||
| 5233 | Absyn.IDENT("initialState")); | ||
| 5234 |
3/6✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 8 times.
✗ Branch 6 not taken.
|
8 | (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("initialState"), args, nargs, {}, impl, pre, info); |
| 5235 | then (cache, call, prop); | ||
| 5236 | end match; | ||
| 5237 | end elabBuiltinInitialState; | ||
| 5238 | |||
| 5239 | protected function elabBuiltinActiveState " | ||
| 5240 | Author: BTH | ||
| 5241 | This function elaborates the builtin operator | ||
| 5242 | activeState(state)." | ||
| 5243 | input FCore.Cache inCache; | ||
| 5244 | input FCore.Graph inEnv; | ||
| 5245 | input list<Absyn.Exp> args; | ||
| 5246 | input list<Absyn.NamedArg> nargs; | ||
| 5247 | input Boolean inBoolean; | ||
| 5248 | input DAE.Prefix inPrefix; | ||
| 5249 | input SourceInfo info; | ||
| 5250 | output FCore.Cache outCache; | ||
| 5251 | output DAE.Exp outExp; | ||
| 5252 | output DAE.Properties outProperties; | ||
| 5253 | algorithm | ||
| 5254 | (outCache,outExp,outProperties) := match (inCache, inEnv, args, nargs, inBoolean, inPrefix) | ||
| 5255 | local | ||
| 5256 | DAE.Exp call; | ||
| 5257 | DAE.Type ty1,ty; | ||
| 5258 | Boolean impl; | ||
| 5259 | FCore.Graph env; | ||
| 5260 | FCore.Cache cache; | ||
| 5261 | DAE.Prefix pre; | ||
| 5262 | DAE.Properties prop1,prop; | ||
| 5263 | Absyn.Exp astate; | ||
| 5264 | String strMsg, strPre; | ||
| 5265 | |||
| 5266 | case (cache, env, {astate}, {}, impl, pre) | ||
| 5267 | algorithm | ||
| 5268 | 4 | (cache,_, prop1) := elabExpInExpression(cache,env,astate,impl,true,pre,info); | |
| 5269 | 4 | ty1 := Types.getPropType(prop1); | |
| 5270 | 4 | strMsg := "activeState(" + Dump.printExpLstStr(args) + "), Argument needs to be a block instance."; | |
| 5271 | 4 | strPre := PrefixUtil.printPrefixStr3(pre); | |
| 5272 | 4 | Error.assertionOrAddSourceMessage(isBlockTypeWorkaround(ty1), Error.WRONG_TYPE_OR_NO_OF_ARGS, | |
| 5273 | {strMsg, strPre}, info); | ||
| 5274 | |||
| 5275 | 8 | ty := DAE.T_FUNCTION( | |
| 5276 | {DAE.FUNCARG("state",ty1,DAE.C_VAR(),DAE.NON_PARALLEL(),NONE())}, | ||
| 5277 | DAE.T_BOOL_DEFAULT, | ||
| 5278 | DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE, | ||
| 5279 | Absyn.IDENT("activeState")); | ||
| 5280 |
3/6✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
|
4 | (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("activeState"), args, nargs, {}, impl, pre, info); |
| 5281 | then (cache, call, prop); | ||
| 5282 | end match; | ||
| 5283 | end elabBuiltinActiveState; | ||
| 5284 | |||
| 5285 | protected function elabBuiltinTicksInState " | ||
| 5286 | Author: BTH | ||
| 5287 | This function elaborates the builtin operator | ||
| 5288 | ticksInState()." | ||
| 5289 | input FCore.Cache inCache; | ||
| 5290 | input FCore.Graph inEnv; | ||
| 5291 | input list<Absyn.Exp> args; | ||
| 5292 | input list<Absyn.NamedArg> nargs; | ||
| 5293 | input Boolean inBoolean; | ||
| 5294 | input DAE.Prefix inPrefix; | ||
| 5295 | input SourceInfo info; | ||
| 5296 | output FCore.Cache outCache; | ||
| 5297 | output DAE.Exp outExp; | ||
| 5298 | output DAE.Properties outProperties; | ||
| 5299 | algorithm | ||
| 5300 | (outCache,outExp,outProperties) := match (inCache, inEnv, args, nargs, inBoolean, inPrefix) | ||
| 5301 | local | ||
| 5302 | DAE.Exp call; | ||
| 5303 | DAE.Type ty; | ||
| 5304 | Boolean impl; | ||
| 5305 | FCore.Graph env; | ||
| 5306 | FCore.Cache cache; | ||
| 5307 | DAE.Prefix pre; | ||
| 5308 | DAE.Properties prop; | ||
| 5309 | |||
| 5310 | case (cache, env, {}, {}, impl, pre) | ||
| 5311 | algorithm | ||
| 5312 | ty := DAE.T_FUNCTION( | ||
| 5313 | {}, | ||
| 5314 | DAE.T_INTEGER_DEFAULT, | ||
| 5315 | DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE, | ||
| 5316 | Absyn.IDENT("ticksInState")); | ||
| 5317 |
3/6✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 1 time.
✗ Branch 6 not taken.
|
1 | (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("ticksInState"), args, nargs, {}, impl, pre, info); |
| 5318 | then (cache, call, prop); | ||
| 5319 | end match; | ||
| 5320 | end elabBuiltinTicksInState; | ||
| 5321 | |||
| 5322 | protected function elabBuiltinTimeInState " | ||
| 5323 | Author: BTH | ||
| 5324 | This function elaborates the builtin operator | ||
| 5325 | timeInState()." | ||
| 5326 | input FCore.Cache inCache; | ||
| 5327 | input FCore.Graph inEnv; | ||
| 5328 | input list<Absyn.Exp> args; | ||
| 5329 | input list<Absyn.NamedArg> nargs; | ||
| 5330 | input Boolean inBoolean; | ||
| 5331 | input DAE.Prefix inPrefix; | ||
| 5332 | input SourceInfo info; | ||
| 5333 | output FCore.Cache outCache; | ||
| 5334 | output DAE.Exp outExp; | ||
| 5335 | output DAE.Properties outProperties; | ||
| 5336 | algorithm | ||
| 5337 | (outCache,outExp,outProperties) := match (inCache, inEnv, args, nargs, inBoolean, inPrefix) | ||
| 5338 | local | ||
| 5339 | DAE.Exp call; | ||
| 5340 | DAE.Type ty; | ||
| 5341 | Boolean impl; | ||
| 5342 | FCore.Graph env; | ||
| 5343 | FCore.Cache cache; | ||
| 5344 | DAE.Prefix pre; | ||
| 5345 | DAE.Properties prop; | ||
| 5346 | |||
| 5347 | case (cache, env, {}, {}, impl, pre) | ||
| 5348 | algorithm | ||
| 5349 | ty := DAE.T_FUNCTION( | ||
| 5350 | {}, | ||
| 5351 | DAE.T_REAL_DEFAULT, | ||
| 5352 | DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE, | ||
| 5353 | Absyn.IDENT("timeInState")); | ||
| 5354 |
3/6✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 1 time.
✗ Branch 6 not taken.
|
1 | (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("timeInState"), args, nargs, {}, impl, pre, info); |
| 5355 | then (cache, call, prop); | ||
| 5356 | end match; | ||
| 5357 | end elabBuiltinTimeInState; | ||
| 5358 | |||
| 5359 | protected function elabBuiltinBoolean | ||
| 5360 | "This function elaborates on the builtin operator boolean, which extracts | ||
| 5361 | the boolean value of a Real, Integer or Boolean value." | ||
| 5362 | input FCore.Cache inCache; | ||
| 5363 | input FCore.Graph inEnv; | ||
| 5364 | input list<Absyn.Exp> inPosArgs; | ||
| 5365 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 5366 | input Boolean inImplicit; | ||
| 5367 | input DAE.Prefix inPrefix; | ||
| 5368 | input SourceInfo inInfo; | ||
| 5369 | output FCore.Cache outCache; | ||
| 5370 | output DAE.Exp outExp; | ||
| 5371 | output DAE.Properties outProperties; | ||
| 5372 | algorithm | ||
| 5373 | ✗ | (outCache, outExp, outProperties) := verifyBuiltInHandlerType(inCache, inEnv, | |
| 5374 | inPosArgs, inImplicit, Types.isIntegerOrRealOrBooleanOrSubTypeOfEither, | ||
| 5375 | "boolean", inPrefix, inInfo); | ||
| 5376 | end elabBuiltinBoolean; | ||
| 5377 | |||
| 5378 | protected function elabBuiltinIntegerEnum | ||
| 5379 | "This function elaborates on the builtin operator Integer for Enumerations, which extracts | ||
| 5380 | the Integer value of a Enumeration element." | ||
| 5381 | input FCore.Cache inCache; | ||
| 5382 | input FCore.Graph inEnv; | ||
| 5383 | input list<Absyn.Exp> inPosArgs; | ||
| 5384 | input list<Absyn.NamedArg> inNamedArg; | ||
| 5385 | input Boolean inImplicit; | ||
| 5386 | input DAE.Prefix inPrefix; | ||
| 5387 | input SourceInfo inInfo; | ||
| 5388 | output FCore.Cache outCache; | ||
| 5389 | output DAE.Exp outExp; | ||
| 5390 | output DAE.Properties outProperties; | ||
| 5391 | algorithm | ||
| 5392 | 2 | (outCache, outExp, outProperties) := verifyBuiltInHandlerType(inCache, inEnv, | |
| 5393 | inPosArgs, inImplicit, Types.isEnumeration, "Integer", inPrefix, inInfo); | ||
| 5394 | end elabBuiltinIntegerEnum; | ||
| 5395 | |||
| 5396 | protected function elabBuiltinNoevent | ||
| 5397 | "The builtin operator noEvent makes sure that events are not generated for the | ||
| 5398 | expression." | ||
| 5399 | input FCore.Cache inCache; | ||
| 5400 | input FCore.Graph inEnv; | ||
| 5401 | input list<Absyn.Exp> inPosArgs; | ||
| 5402 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 5403 | input Boolean inImplicit; | ||
| 5404 | input DAE.Prefix inPrefix; | ||
| 5405 | input SourceInfo inInfo; | ||
| 5406 | output FCore.Cache outCache; | ||
| 5407 | output DAE.Exp outExp; | ||
| 5408 | output DAE.Properties outProperties; | ||
| 5409 | protected | ||
| 5410 | Absyn.Exp e; | ||
| 5411 | algorithm | ||
| 5412 | 132 | checkBuiltinCallArgs(inPosArgs, inNamedArgs, 1, "noEvent", inInfo); | |
| 5413 | |||
| 5414 | 132 | e := listHead(inPosArgs); | |
| 5415 | 132 | (outCache, outExp, outProperties) := elabExpInExpression(inCache, inEnv, e, | |
| 5416 | inImplicit, true, inPrefix, inInfo); | ||
| 5417 | 132 | outExp := Expression.makePureBuiltinCall("noEvent", {outExp}, DAE.T_BOOL_DEFAULT); | |
| 5418 | end elabBuiltinNoevent; | ||
| 5419 | |||
| 5420 | protected function elabBuiltinEdge | ||
| 5421 | "This function handles the built in edge operator." | ||
| 5422 | input FCore.Cache inCache; | ||
| 5423 | input FCore.Graph inEnv; | ||
| 5424 | input list<Absyn.Exp> inPosArgs; | ||
| 5425 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 5426 | input Boolean inImplicit; | ||
| 5427 | input DAE.Prefix inPrefix; | ||
| 5428 | input SourceInfo inInfo; | ||
| 5429 | output FCore.Cache outCache; | ||
| 5430 | output DAE.Exp outExp; | ||
| 5431 | output DAE.Properties outProperties; | ||
| 5432 | protected | ||
| 5433 | DAE.Type ty; | ||
| 5434 | DAE.Const c; | ||
| 5435 | String msg; | ||
| 5436 | algorithm | ||
| 5437 | 9 | checkBuiltinCallArgs(inPosArgs, inNamedArgs, 1, "edge", inInfo); | |
| 5438 | |||
| 5439 | 9 | (outCache, outExp, outProperties) := elabExpInExpression(inCache, inEnv, | |
| 5440 | listHead(inPosArgs), inImplicit, true, inPrefix, inInfo); | ||
| 5441 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | DAE.PROP(ty, c) := outProperties; |
| 5442 | |||
| 5443 | // Print an error if the argument is not a Boolean. | ||
| 5444 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
|
9 | if not Types.isScalarBoolean(ty) then |
| 5445 | ✗ | msg := "edge(" + ExpressionBasics.printExpStr(outExp) + ")"; | |
| 5446 | ✗ | Error.addSourceMessageAndFail(Error.TYPE_ERROR, {msg}, inInfo); | |
| 5447 | end if; | ||
| 5448 | |||
| 5449 | // If the argument is a variable, make a call to edge. Otherwise the | ||
| 5450 | // expression is false. | ||
| 5451 |
1/2✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
|
9 | if Types.isVar(c) then |
| 5452 | 9 | outExp := Expression.makePureBuiltinCall("edge", {outExp}, DAE.T_BOOL_DEFAULT); | |
| 5453 | else | ||
| 5454 | ✗ | outExp := DAE.BCONST(false); | |
| 5455 | end if; | ||
| 5456 | end elabBuiltinEdge; | ||
| 5457 | |||
| 5458 | protected function elabBuiltinDer | ||
| 5459 | "This function handles the built in der operator." | ||
| 5460 | input FCore.Cache inCache; | ||
| 5461 | input FCore.Graph inEnv; | ||
| 5462 | input list<Absyn.Exp> inPosArgs; | ||
| 5463 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 5464 | input Boolean inImplicit; | ||
| 5465 | input DAE.Prefix inPrefix; | ||
| 5466 | input SourceInfo inInfo; | ||
| 5467 | output FCore.Cache outCache; | ||
| 5468 | output DAE.Exp outExp; | ||
| 5469 | output DAE.Properties outProperties; | ||
| 5470 | protected | ||
| 5471 | DAE.Type ty; | ||
| 5472 | DAE.Const c; | ||
| 5473 | list<DAE.Dimension> dims; | ||
| 5474 | String exp_str, ty_str; | ||
| 5475 | algorithm | ||
| 5476 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4068 times.
|
4068 | if FGraph.inFunctionScope(inEnv) then |
| 5477 | ✗ | Error.addSourceMessageAndFail(Error.DERIVATIVE_FUNCTION_CONTEXT, {}, inInfo); | |
| 5478 | end if; | ||
| 5479 | |||
| 5480 | 4068 | checkBuiltinCallArgs(inPosArgs, inNamedArgs, 1, "der", inInfo); | |
| 5481 | |||
| 5482 | 4068 | (outCache, outExp, outProperties) := elabExpInExpression(inCache, inEnv, | |
| 5483 | listHead(inPosArgs), inImplicit, true, inPrefix, inInfo); | ||
| 5484 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4050 times.
|
4050 | DAE.PROP(ty, c) := outProperties; |
| 5485 | |||
| 5486 | // Make sure the argument's type is a subtype of Real. | ||
| 5487 |
2/2✓ Branch 2 taken 1 time.
✓ Branch 3 taken 4049 times.
|
4050 | if not Types.isRealOrSubTypeReal(Types.arrayElementType(ty)) then |
| 5488 | 1 | exp_str := Dump.printExpStr(listHead(inPosArgs)); | |
| 5489 | 1 | ty_str := TypesDump.unparseTypeNoAttr(ty); | |
| 5490 | 1 | Error.addSourceMessageAndFail(Error.DERIVATIVE_NON_REAL, | |
| 5491 | {exp_str, ty_str}, inInfo); | ||
| 5492 | end if; | ||
| 5493 | |||
| 5494 |
2/2✓ Branch 1 taken 4045 times.
✓ Branch 2 taken 4 times.
|
4049 | if Types.isVar(c) then |
| 5495 |
1/2✓ Branch 1 taken 4045 times.
✗ Branch 2 not taken.
|
4045 | if Types.dimensionsKnown(ty) then |
| 5496 | // Use elabCallArgs to handle vectorization if possible. | ||
| 5497 | 4045 | (outCache, outExp, outProperties) := elabCallArgs(inCache, inEnv, | |
| 5498 | Absyn.IDENT("der"), inPosArgs, {}, {}, inImplicit, inPrefix, inInfo); | ||
| 5499 | else | ||
| 5500 | // Otherwise just create a call to der. | ||
| 5501 | ✗ | outExp := Expression.makePureBuiltinCall("der", {outExp}, | |
| 5502 | Types.simplifyType(ty)); | ||
| 5503 | end if; | ||
| 5504 | else | ||
| 5505 | // der(constant) = 0. | ||
| 5506 | 4 | dims := TypesDump.getDimensions(ty); | |
| 5507 | 4 | (outExp, ty) := Expression.makeZeroExpression(dims); | |
| 5508 | 4 | outProperties := DAE.PROP(ty, DAE.C_CONST()); | |
| 5509 | end if; | ||
| 5510 | end elabBuiltinDer; | ||
| 5511 | |||
| 5512 | protected function elabBuiltinChange | ||
| 5513 | "This function handles the built in change operator." | ||
| 5514 | input FCore.Cache inCache; | ||
| 5515 | input FCore.Graph inEnv; | ||
| 5516 | input list<Absyn.Exp> inPosArgs; | ||
| 5517 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 5518 | input Boolean inImplicit; | ||
| 5519 | input DAE.Prefix inPrefix; | ||
| 5520 | input SourceInfo inInfo; | ||
| 5521 | output FCore.Cache outCache; | ||
| 5522 | output DAE.Exp outExp; | ||
| 5523 | output DAE.Properties outProperties; | ||
| 5524 | protected | ||
| 5525 | Absyn.Exp e; | ||
| 5526 | String pre_str; | ||
| 5527 | DAE.Type ty; | ||
| 5528 | DAE.Const c; | ||
| 5529 | DAE.Attributes attr; | ||
| 5530 | DAE.ComponentRef cref; | ||
| 5531 | SCode.Variability var; | ||
| 5532 | algorithm | ||
| 5533 | 44 | checkBuiltinCallArgs(inPosArgs, inNamedArgs, 1, "change", inInfo); | |
| 5534 | |||
| 5535 | 44 | e := listHead(inPosArgs); | |
| 5536 | |||
| 5537 | // Check that the argument is a variable (i.e. a component reference). | ||
| 5538 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 44 times.
|
44 | if not AbsynUtil.isCref(e) then |
| 5539 | ✗ | pre_str := PrefixUtil.printPrefixStr3(inPrefix); | |
| 5540 | ✗ | Error.addSourceMessageAndFail(Error.ARGUMENT_MUST_BE_VARIABLE, | |
| 5541 | {"First", "change", pre_str}, inInfo); | ||
| 5542 | end if; | ||
| 5543 | |||
| 5544 | 44 | (outCache, outExp, outProperties) := elabExpInExpression(inCache, inEnv, e, | |
| 5545 | inImplicit, true, inPrefix, inInfo); | ||
| 5546 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
|
44 | DAE.PROP(ty, c) := outProperties; |
| 5547 | |||
| 5548 |
1/2✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
|
44 | if Types.isSimpleType(ty) then |
| 5549 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 44 times.
|
44 | if Types.isParameterOrConstant(c) then |
| 5550 | // change(constant) = false | ||
| 5551 | ✗ | outExp := DAE.BCONST(false); | |
| 5552 | ✗ | outProperties := DAE.PROP(DAE.T_BOOL_DEFAULT, DAE.C_CONST()); | |
| 5553 | elseif Types.isDiscreteType(ty) then | ||
| 5554 | // If the argument is discrete, make a call to change. | ||
| 5555 | 44 | outExp := Expression.makePureBuiltinCall("change", {outExp}, DAE.T_BOOL_DEFAULT); | |
| 5556 | 44 | outProperties := DAE.PROP(DAE.T_BOOL_DEFAULT, DAE.C_VAR()); | |
| 5557 | else | ||
| 5558 | // Workaround for discrete Reals. Does not handle Reals that become | ||
| 5559 | // discrete due to when-section. | ||
| 5560 | ✗ | cref := Expression.getCrefFromCrefOrAsub(outExp); | |
| 5561 | // Look up the component's variability. | ||
| 5562 | ✗ | (outCache, attr) := Lookup.lookupVar(outCache, inEnv, cref); | |
| 5563 | ✗ | DAE.ATTR(variability = var) := attr; | |
| 5564 | |||
| 5565 | ✗ | if valueEq(var, SCode.DISCRETE()) then | |
| 5566 | // If it's discrete, make a call to change. | ||
| 5567 | ✗ | outExp := Expression.makePureBuiltinCall("change", {outExp}, DAE.T_BOOL_DEFAULT); | |
| 5568 | ✗ | outProperties := DAE.PROP(DAE.T_BOOL_DEFAULT, DAE.C_VAR()); | |
| 5569 | else | ||
| 5570 | // Otherwise, print an error and fail. | ||
| 5571 | ✗ | pre_str := PrefixUtil.printPrefixStr3(inPrefix); | |
| 5572 | ✗ | Error.addSourceMessageAndFail(Error.ARGUMENT_MUST_BE_DISCRETE_VAR, | |
| 5573 | {"First", "change", pre_str}, inInfo); | ||
| 5574 | end if; | ||
| 5575 | end if; | ||
| 5576 | else | ||
| 5577 | // If the argument does not have a simple type, print an error and fail. | ||
| 5578 | ✗ | pre_str := PrefixUtil.printPrefixStr3(inPrefix); | |
| 5579 | ✗ | Error.addSourceMessageAndFail(Error.TYPE_MUST_BE_SIMPLE, | |
| 5580 | {"operand to change", pre_str}, inInfo); | ||
| 5581 | end if; | ||
| 5582 | end elabBuiltinChange; | ||
| 5583 | |||
| 5584 | protected function elabBuiltinCat | ||
| 5585 | "This function handles the built in cat operator." | ||
| 5586 | input FCore.Cache inCache; | ||
| 5587 | input FCore.Graph inEnv; | ||
| 5588 | input list<Absyn.Exp> inPosArgs; | ||
| 5589 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 5590 | input Boolean inImplicit; | ||
| 5591 | input DAE.Prefix inPrefix; | ||
| 5592 | input SourceInfo inInfo; | ||
| 5593 | output FCore.Cache outCache; | ||
| 5594 | output DAE.Exp outExp; | ||
| 5595 | output DAE.Properties outProperties; | ||
| 5596 | protected | ||
| 5597 | DAE.Exp dim_exp; | ||
| 5598 | DAE.Properties dim_props; | ||
| 5599 | DAE.Type dim_ty, ty, result_ty; | ||
| 5600 | DAE.Const dim_c, arr_c, c; | ||
| 5601 | String pre_str, exp_str; | ||
| 5602 | Integer dim_int; | ||
| 5603 | list<DAE.Exp> arr_expl; | ||
| 5604 | list<DAE.Properties> arr_props; | ||
| 5605 | list<DAE.Type> arr_tys, tys; | ||
| 5606 | list<DAE.Dimension> dims; | ||
| 5607 | DAE.Dimension dim; | ||
| 5608 | algorithm | ||
| 5609 |
2/4✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 69 times.
|
69 | if listLength(inPosArgs) < 2 or not listEmpty(inNamedArgs) then |
| 5610 | ✗ | Error.addSourceMessageAndFail(Error.WRONG_NO_OF_ARGS, {"cat"}, inInfo); | |
| 5611 | end if; | ||
| 5612 | |||
| 5613 | // Elaborate the first argument, the dimension to concatenate along. | ||
| 5614 | 69 | (outCache, dim_exp, dim_props) := elabExpInExpression(inCache, inEnv, | |
| 5615 | listHead(inPosArgs), inImplicit, true, inPrefix, inInfo); | ||
| 5616 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
|
69 | DAE.PROP(dim_ty, dim_c) := dim_props; |
| 5617 | |||
| 5618 | // The first argument must be an integer. | ||
| 5619 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
|
69 | if not Types.isScalarInteger(dim_ty) then |
| 5620 | ✗ | pre_str := PrefixUtil.printPrefixStr3(inPrefix); | |
| 5621 | ✗ | Error.addSourceMessageAndFail(Error.ARGUMENT_MUST_BE_INTEGER, | |
| 5622 | {"First", "cat", pre_str}, inInfo); | ||
| 5623 | end if; | ||
| 5624 | |||
| 5625 | // Evaluate the first argument. | ||
| 5626 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 69 times.
|
69 | (outCache, Values.INTEGER(dim_int)) := |
| 5627 | Ceval.ceval(inCache, inEnv, dim_exp, false, Absyn.MSG(inInfo)); | ||
| 5628 | |||
| 5629 | // Elaborate the rest of the arguments, the arrays to concatenate. | ||
| 5630 | 69 | (outCache, arr_expl, arr_props) := elabExpList(outCache, inEnv, | |
| 5631 | listRest(inPosArgs), inImplicit, true, inPrefix, inInfo); | ||
| 5632 | |||
| 5633 | // Type check the arguments and check that all dimensions except the one we | ||
| 5634 | // will concatenate along is equal. | ||
| 5635 |
4/4✓ Branch 0 taken 156 times.
✓ Branch 1 taken 69 times.
✓ Branch 2 taken 156 times.
✓ Branch 3 taken 69 times.
|
225 | arr_tys := list(Types.getPropType(p) for p in arr_props); |
| 5636 |
5/6✓ Branch 0 taken 156 times.
✓ Branch 1 taken 69 times.
✓ Branch 2 taken 156 times.
✓ Branch 3 taken 69 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 69 times.
|
225 | ty :: tys := list(Types.makeNthDimUnknown(t, dim_int) for t in arr_tys); |
| 5637 | 69 | result_ty := List.fold1(tys, Types.arraySuperType, inInfo, ty); | |
| 5638 | |||
| 5639 | try | ||
| 5640 | 69 | (arr_expl, arr_tys) := Types.matchTypes(arr_expl, arr_tys, result_ty, false); | |
| 5641 | else | ||
| 5642 | // Mismatched types, print an error and fail. | ||
| 5643 | ✗ | exp_str := stringDelimitList(list(Dump.printExpStr(e) for e in inPosArgs), ", "); | |
| 5644 | ✗ | exp_str := "cat(" + exp_str + ")"; | |
| 5645 | ✗ | pre_str := PrefixUtil.printPrefixStr3(inPrefix); | |
| 5646 | ✗ | Error.addSourceMessageAndFail(Error.DIFFERENT_DIM_SIZE_IN_ARGUMENTS, | |
| 5647 | {exp_str, pre_str}, inInfo); | ||
| 5648 | end try; | ||
| 5649 | |||
| 5650 | // Calculate the size of the concatenated dimension, and insert it in the | ||
| 5651 | // result type. | ||
| 5652 |
4/4✓ Branch 0 taken 156 times.
✓ Branch 1 taken 69 times.
✓ Branch 2 taken 156 times.
✓ Branch 3 taken 69 times.
|
225 | dims := list(Types.getDimensionNth(t, dim_int) for t in arr_tys); |
| 5653 |
7/8✓ Branch 0 taken 156 times.
✓ Branch 1 taken 69 times.
✓ Branch 2 taken 156 times.
✓ Branch 3 taken 69 times.
✓ Branch 4 taken 69 times.
✓ Branch 5 taken 87 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 69 times.
|
225 | dim := Expression.dimensionsAdd(d for d in dims); |
| 5654 | 69 | result_ty := Types.setDimensionNth(result_ty, dim, dim_int); | |
| 5655 | |||
| 5656 | // Construct a call to cat. | ||
| 5657 | 69 | arr_c := elabArrayConst(arr_props); | |
| 5658 | 69 | c := Types.constAnd(dim_c, arr_c); | |
| 5659 | 69 | ty := Types.simplifyType(result_ty); | |
| 5660 | 69 | outExp := Expression.makePureBuiltinCall("cat", dim_exp :: arr_expl, ty); | |
| 5661 | 69 | outProperties := DAE.PROP(result_ty, c); | |
| 5662 | end elabBuiltinCat; | ||
| 5663 | |||
| 5664 | protected function elabBuiltinIdentity | ||
| 5665 | "This function handles the built in identity operator." | ||
| 5666 | input FCore.Cache inCache; | ||
| 5667 | input FCore.Graph inEnv; | ||
| 5668 | input list<Absyn.Exp> inPosArgs; | ||
| 5669 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 5670 | input Boolean inImplicit; | ||
| 5671 | input DAE.Prefix inPrefix; | ||
| 5672 | input SourceInfo inInfo; | ||
| 5673 | output FCore.Cache outCache; | ||
| 5674 | output DAE.Exp outExp; | ||
| 5675 | output DAE.Properties outProperties; | ||
| 5676 | protected | ||
| 5677 | DAE.Type ty, exp_ty; | ||
| 5678 | DAE.Const c; | ||
| 5679 | String pre_str; | ||
| 5680 | Absyn.Msg msg; | ||
| 5681 | Integer sz; | ||
| 5682 | DAE.Dimension dim_size; | ||
| 5683 | DAE.Exp dim_exp; | ||
| 5684 | Boolean check_model; | ||
| 5685 | algorithm | ||
| 5686 | 84 | checkBuiltinCallArgs(inPosArgs, inNamedArgs, 1, "identity", inInfo); | |
| 5687 | |||
| 5688 | 84 | (outCache, dim_exp, outProperties) := elabExpInExpression(inCache, inEnv, | |
| 5689 | listHead(inPosArgs), inImplicit, true, inPrefix, inInfo); | ||
| 5690 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
|
84 | DAE.PROP(ty, c) := outProperties; |
| 5691 | |||
| 5692 | // Check that the argument is an Integer. | ||
| 5693 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 83 times.
|
84 | if not Types.isScalarInteger(ty) then |
| 5694 | 1 | pre_str := PrefixUtil.printPrefixStr3(inPrefix); | |
| 5695 | 1 | Error.addSourceMessageAndFail(Error.ARGUMENT_MUST_BE_INTEGER, | |
| 5696 | {"First", "identity", pre_str}, inInfo); | ||
| 5697 | end if; | ||
| 5698 | |||
| 5699 |
2/2✓ Branch 1 taken 80 times.
✓ Branch 2 taken 3 times.
|
83 | if Types.isParameterOrConstant(c) then |
| 5700 | // If the argument is a parameter or constant, evaluate it. | ||
| 5701 | 80 | check_model := Flags.getConfigBool(Flags.CHECK_MODEL); | |
| 5702 |
2/2✓ Branch 0 taken 77 times.
✓ Branch 1 taken 3 times.
|
80 | msg := if check_model then Absyn.NO_MSG() else Absyn.MSG(inInfo); |
| 5703 | |||
| 5704 | try | ||
| 5705 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 80 times.
|
80 | (outCache, Values.INTEGER(sz)) := |
| 5706 | Ceval.ceval(outCache, inEnv, dim_exp, false, msg); | ||
| 5707 | 80 | dim_size := DAE.DIM_INTEGER(sz); | |
| 5708 | 80 | dim_exp := DAE.ICONST(sz); | |
| 5709 | else | ||
| 5710 | // Allow evaluation to fail if checkModel is used. | ||
| 5711 | ✗ | if check_model then dim_size := DAE.DIM_UNKNOWN(); else fail(); end if; | |
| 5712 | end try; | ||
| 5713 | else | ||
| 5714 | dim_size := DAE.DIM_UNKNOWN(); | ||
| 5715 | end if; | ||
| 5716 | |||
| 5717 | 83 | ty := Types.liftArrayListDims(DAE.T_INTEGER_DEFAULT, {dim_size, dim_size}); | |
| 5718 | 83 | exp_ty := Types.simplifyType(ty); | |
| 5719 | 83 | outExp := Expression.makePureBuiltinCall("identity", {dim_exp}, exp_ty); | |
| 5720 | 83 | outProperties := DAE.PROP(ty, c); | |
| 5721 | end elabBuiltinIdentity; | ||
| 5722 | |||
| 5723 | protected function zeroSizeOverconstrainedOperator | ||
| 5724 | input DAE.Exp inExp; | ||
| 5725 | input DAE.Exp inFExp; | ||
| 5726 | input SourceInfo inInfo; | ||
| 5727 | algorithm | ||
| 5728 | () := match inExp | ||
| 5729 | local String s; | ||
| 5730 | |||
| 5731 | case DAE.ARRAY(array = {}) | ||
| 5732 | algorithm | ||
| 5733 | ✗ | s := ExpressionBasics.printExpStr(inFExp); | |
| 5734 | ✗ | Error.addSourceMessage(Error.OVERCONSTRAINED_OPERATOR_SIZE_ZERO_RETURN_FALSE, {s}, inInfo); | |
| 5735 | then | ||
| 5736 | (); | ||
| 5737 | |||
| 5738 | else (); | ||
| 5739 | |||
| 5740 | end match; | ||
| 5741 | end zeroSizeOverconstrainedOperator; | ||
| 5742 | |||
| 5743 | protected function elabBuiltinIsRoot | ||
| 5744 | "This function elaborates on the builtin operator Connections.isRoot." | ||
| 5745 | input FCore.Cache inCache; | ||
| 5746 | input FCore.Graph inEnv; | ||
| 5747 | input list<Absyn.Exp> inPosArgs; | ||
| 5748 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 5749 | input Boolean inImplicit; | ||
| 5750 | input DAE.Prefix inPrefix; | ||
| 5751 | input SourceInfo inInfo; | ||
| 5752 | output FCore.Cache outCache; | ||
| 5753 | output DAE.Exp outExp; | ||
| 5754 | output DAE.Properties outProperties; | ||
| 5755 | protected | ||
| 5756 | DAE.Exp exp; | ||
| 5757 | algorithm | ||
| 5758 | 151 | checkBuiltinCallArgs(inPosArgs, inNamedArgs, 1, "Connections.isRoot", inInfo); | |
| 5759 | |||
| 5760 | 151 | (outCache, exp) := elabExpInExpression(inCache, inEnv, listHead(inPosArgs), | |
| 5761 | false, false, inPrefix, inInfo); | ||
| 5762 | 151 | outExp := DAE.CALL(Absyn.QUALIFIED("Connections", Absyn.IDENT("isRoot")), | |
| 5763 | {exp}, DAE.callAttrBuiltinBool); | ||
| 5764 | outProperties := DAE.PROP(DAE.T_BOOL_DEFAULT, DAE.C_VAR()); | ||
| 5765 | |||
| 5766 | 151 | zeroSizeOverconstrainedOperator(exp, outExp, inInfo); | |
| 5767 | end elabBuiltinIsRoot; | ||
| 5768 | |||
| 5769 | protected function elabBuiltinRooted | ||
| 5770 | "author: adrpo | ||
| 5771 | This function handles the built-in rooted operator. (MultiBody). | ||
| 5772 | See more here: http://trac.modelica.org/Modelica/ticket/95" | ||
| 5773 | input FCore.Cache inCache; | ||
| 5774 | input FCore.Graph inEnv; | ||
| 5775 | input list<Absyn.Exp> inPosArgs; | ||
| 5776 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 5777 | input Boolean inImplicit; | ||
| 5778 | input DAE.Prefix inPrefix; | ||
| 5779 | input SourceInfo inInfo; | ||
| 5780 | output FCore.Cache outCache; | ||
| 5781 | output DAE.Exp outExp; | ||
| 5782 | output DAE.Properties outProperties; | ||
| 5783 | protected | ||
| 5784 | DAE.Exp exp; | ||
| 5785 | algorithm | ||
| 5786 | // this operator is not even specified in the specification! | ||
| 5787 | // see: http://trac.modelica.org/Modelica/ticket/95 | ||
| 5788 | 128 | checkBuiltinCallArgs(inPosArgs, inNamedArgs, 1, "rooted", inInfo); | |
| 5789 | |||
| 5790 | 128 | (outCache, exp) := elabExpInExpression(inCache, inEnv, listHead(inPosArgs), | |
| 5791 | false, false, inPrefix, inInfo); | ||
| 5792 | 128 | outExp := DAE.CALL(Absyn.IDENT("rooted"), {exp}, DAE.callAttrBuiltinBool); | |
| 5793 | outProperties := DAE.PROP(DAE.T_BOOL_DEFAULT, DAE.C_VAR()); | ||
| 5794 | |||
| 5795 | 128 | zeroSizeOverconstrainedOperator(exp, outExp, inInfo); | |
| 5796 | end elabBuiltinRooted; | ||
| 5797 | |||
| 5798 | protected function elabBuiltinUniqueRootIndices | ||
| 5799 | "This function elaborates on the builtin operator Connections.uniqueRootIndices. | ||
| 5800 | TODO: assert size(second arg) <= size(first arg) | ||
| 5801 | See Modelica_StateGraph2: | ||
| 5802 | https://github.com/modelica/Modelica_StateGraph2 | ||
| 5803 | and | ||
| 5804 | https://trac.modelica.org/Modelica/ticket/984 | ||
| 5805 | and | ||
| 5806 | http://www.ep.liu.se/ecp/043/041/ecp09430108.pdf | ||
| 5807 | for a specification of this operator" | ||
| 5808 | input FCore.Cache inCache; | ||
| 5809 | input FCore.Graph inEnv; | ||
| 5810 | input list<Absyn.Exp> inAbsynExpLst; | ||
| 5811 | input list<Absyn.NamedArg> inNamedArg; | ||
| 5812 | input Boolean inBoolean; | ||
| 5813 | input DAE.Prefix inPrefix; | ||
| 5814 | input SourceInfo info; | ||
| 5815 | output FCore.Cache outCache; | ||
| 5816 | output DAE.Exp outExp; | ||
| 5817 | output DAE.Properties outProperties; | ||
| 5818 | algorithm | ||
| 5819 | (outCache,outExp,outProperties):= | ||
| 5820 | match (inCache, inEnv, inAbsynExpLst, inNamedArg, inPrefix) | ||
| 5821 | local | ||
| 5822 | FCore.Graph env; | ||
| 5823 | FCore.Cache cache; | ||
| 5824 | Absyn.Exp aexp1, aexp2; | ||
| 5825 | DAE.Exp exp1, exp2, exp3; | ||
| 5826 | DAE.Prefix pre; | ||
| 5827 | list<DAE.Exp> lst; | ||
| 5828 | Integer dim; | ||
| 5829 | DAE.Type ty; | ||
| 5830 | |||
| 5831 | case (cache, env, {aexp1,aexp2}, {}, pre) | ||
| 5832 | algorithm | ||
| 5833 | ✗ | (cache,exp1 as DAE.ARRAY(array = lst),_) := elabExpInExpression(cache, env, aexp1, false, false, pre, info); | |
| 5834 | ✗ | dim := listLength(lst); | |
| 5835 | ✗ | (cache,exp2,_) := elabExpInExpression(cache, env, aexp2, false, false, pre, info); | |
| 5836 | ✗ | exp3 := DAE.SCONST(""); | |
| 5837 | ✗ | ty := DAE.T_ARRAY(DAE.T_INTEGER_DEFAULT, {DAE.DIM_INTEGER(dim)}); | |
| 5838 | ✗ | then | |
| 5839 | (cache, | ||
| 5840 | DAE.CALL(Absyn.QUALIFIED("Connections", Absyn.IDENT("uniqueRootIndices")), {exp1, exp2, exp3}, | ||
| 5841 | DAE.CALL_ATTR(ty,false,true,false,false,DAE.NO_INLINE(),DAE.NO_TAIL(),DAE.NoReturn.RETURNS)), | ||
| 5842 | DAE.PROP(ty, DAE.C_VAR())); | ||
| 5843 | |||
| 5844 | case (cache, env, {aexp1,aexp2,_}, {}, pre) | ||
| 5845 | algorithm | ||
| 5846 | ✗ | (cache,exp1 as DAE.ARRAY(array = lst),_) := elabExpInExpression(cache, env, aexp1, false, false, pre, info); | |
| 5847 | ✗ | dim := listLength(lst); | |
| 5848 | ✗ | (cache,exp2,_) := elabExpInExpression(cache, env, aexp2, false, false, pre, info); | |
| 5849 | ✗ | (cache,exp3,_) := elabExpInExpression(cache, env, aexp2, false, false, pre, info); | |
| 5850 | ✗ | ty := DAE.T_ARRAY(DAE.T_INTEGER_DEFAULT, {DAE.DIM_INTEGER(dim)}); | |
| 5851 | ✗ | then | |
| 5852 | (cache, | ||
| 5853 | DAE.CALL(Absyn.QUALIFIED("Connections", Absyn.IDENT("uniqueRootIndices")), {exp1, exp2, exp3}, | ||
| 5854 | DAE.CALL_ATTR(ty,false,true,false,false,DAE.NO_INLINE(),DAE.NO_TAIL(),DAE.NoReturn.RETURNS)), | ||
| 5855 | DAE.PROP(ty, DAE.C_VAR())); | ||
| 5856 | |||
| 5857 | case (cache, env, {aexp1,aexp2}, {Absyn.NAMEDARG("message", _)}, pre) | ||
| 5858 | algorithm | ||
| 5859 | ✗ | (cache,exp1 as DAE.ARRAY(array = lst),_) := elabExpInExpression(cache, env, aexp1, false, false, pre, info); | |
| 5860 | ✗ | dim := listLength(lst); | |
| 5861 | ✗ | (cache,exp2,_) := elabExpInExpression(cache, env, aexp2, false,false,pre,info); | |
| 5862 | ✗ | (cache,exp3,_) := elabExpInExpression(cache, env, aexp2, false,false,pre,info); | |
| 5863 | ✗ | ty := DAE.T_ARRAY(DAE.T_INTEGER_DEFAULT, {DAE.DIM_INTEGER(dim)}); | |
| 5864 | ✗ | then | |
| 5865 | (cache, | ||
| 5866 | DAE.CALL(Absyn.QUALIFIED("Connections", Absyn.IDENT("uniqueRootIndices")), {exp1, exp2, exp3}, | ||
| 5867 | DAE.CALL_ATTR(ty,false,true,false,false,DAE.NO_INLINE(),DAE.NO_TAIL(),DAE.NoReturn.RETURNS)), | ||
| 5868 | DAE.PROP(ty, DAE.C_VAR())); | ||
| 5869 | |||
| 5870 | end match; | ||
| 5871 | end elabBuiltinUniqueRootIndices; | ||
| 5872 | |||
| 5873 | protected function elabBuiltinScalar | ||
| 5874 | "This function handles the built in scalar operator. | ||
| 5875 | For example, scalar({1}) => 1 or scalar({a}) => a" | ||
| 5876 | input FCore.Cache inCache; | ||
| 5877 | input FCore.Graph inEnv; | ||
| 5878 | input list<Absyn.Exp> inPosArgs; | ||
| 5879 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 5880 | input Boolean inImplicit; | ||
| 5881 | input DAE.Prefix inPrefix; | ||
| 5882 | input SourceInfo inInfo; | ||
| 5883 | output FCore.Cache outCache; | ||
| 5884 | output DAE.Exp outExp; | ||
| 5885 | output DAE.Properties outProperties; | ||
| 5886 | protected | ||
| 5887 | DAE.Type ty, scalar_ty; | ||
| 5888 | DAE.Const c; | ||
| 5889 | list<DAE.Dimension> dims; | ||
| 5890 | String ty_str; | ||
| 5891 | algorithm | ||
| 5892 | 1 | checkBuiltinCallArgs(inPosArgs, inNamedArgs, 1, "scalar", inInfo); | |
| 5893 | |||
| 5894 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
|
1 | (outCache, outExp, DAE.PROP(ty, c)) := elabExpInExpression(inCache, inEnv, |
| 5895 | listHead(inPosArgs), inImplicit, true, inPrefix, inInfo); | ||
| 5896 | |||
| 5897 | 1 | (scalar_ty, dims) := TypesDump.flattenArrayType(ty); | |
| 5898 | |||
| 5899 | // Check that any known dimensions have size 1. | ||
| 5900 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
|
2 | for dim in dims loop |
| 5901 |
1/4✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
1 | if Expression.dimensionKnown(dim) and Expression.dimensionSize(dim) <> 1 then |
| 5902 | ✗ | ty_str := TypesDump.unparseTypeNoAttr(ty); | |
| 5903 | ✗ | Error.addSourceMessageAndFail(Error.INVALID_ARRAY_DIM_IN_CONVERSION_OP, | |
| 5904 | {ty_str}, inInfo); | ||
| 5905 | end if; | ||
| 5906 | end for; | ||
| 5907 | |||
| 5908 | // If the argument is an array, make a call to scalar. Otherwise the | ||
| 5909 | // expression is already a scalar, so return it as it is. | ||
| 5910 |
1/2✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
|
1 | if not listEmpty(dims) then |
| 5911 | 1 | outExp := Expression.makePureBuiltinCall("scalar", {outExp}, scalar_ty); | |
| 5912 | end if; | ||
| 5913 | |||
| 5914 | 1 | outExp := ExpressionSimplify.simplify1(outExp); | |
| 5915 | 1 | outProperties := DAE.PROP(scalar_ty, c); | |
| 5916 | end elabBuiltinScalar; | ||
| 5917 | |||
| 5918 | constant Slot STRING_ARG_MINLENGTH = SLOT(DAE.FUNCARG("minimumLength", | ||
| 5919 | DAE.T_INTEGER_DEFAULT, DAE.C_VAR(), DAE.NON_PARALLEL(), NONE()), false, | ||
| 5920 | SOME(DAE.ICONST(0)), {}, 2, SLOT_NOT_EVALUATED); | ||
| 5921 | |||
| 5922 | constant Slot STRING_ARG_LEFTJUSTIFIED = SLOT(DAE.FUNCARG("leftJustified", | ||
| 5923 | DAE.T_BOOL_DEFAULT, DAE.C_VAR(), DAE.NON_PARALLEL(), NONE()), false, | ||
| 5924 | SOME(DAE.BCONST(true)), {}, 3, SLOT_NOT_EVALUATED); | ||
| 5925 | |||
| 5926 | constant Slot STRING_ARG_SIGNIFICANT_DIGITS = SLOT(DAE.FUNCARG("significantDigits", | ||
| 5927 | DAE.T_INTEGER_DEFAULT, DAE.C_VAR(), DAE.NON_PARALLEL(), NONE()), false, | ||
| 5928 | SOME(DAE.ICONST(6)), {}, 4, SLOT_NOT_EVALUATED); | ||
| 5929 | |||
| 5930 | protected function elabBuiltinString " | ||
| 5931 | author: PA | ||
| 5932 | This function handles the built-in String operator." | ||
| 5933 | input FCore.Cache inCache; | ||
| 5934 | input FCore.Graph inEnv; | ||
| 5935 | input list<Absyn.Exp> inPosArgs; | ||
| 5936 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 5937 | input Boolean inImplicit; | ||
| 5938 | input DAE.Prefix inPrefix; | ||
| 5939 | input SourceInfo inInfo; | ||
| 5940 | output FCore.Cache outCache; | ||
| 5941 | output DAE.Exp outExp; | ||
| 5942 | output DAE.Properties outProperties; | ||
| 5943 | protected | ||
| 5944 | Absyn.Exp e; | ||
| 5945 | DAE.Exp exp; | ||
| 5946 | DAE.Type ty; | ||
| 5947 | DAE.Const c; | ||
| 5948 | list<DAE.Exp> args; | ||
| 5949 | list<DAE.Const> consts; | ||
| 5950 | Slot val_slot; | ||
| 5951 | Option<DAE.Exp> format_arg = NONE(); | ||
| 5952 | list<Slot> slots; | ||
| 5953 | algorithm | ||
| 5954 | try | ||
| 5955 | // Check if 'String' is overloaded. | ||
| 5956 | 1486 | e := Absyn.CALL(Absyn.CREF_IDENT("String", {}), | |
| 5957 | Absyn.FUNCTIONARGS(inPosArgs, inNamedArgs), {}); | ||
| 5958 | 1486 | (outCache, outExp, outProperties) := OperatorOverloading.string(inCache, | |
| 5959 | inEnv, e, inImplicit, true, inPrefix, inInfo); | ||
| 5960 | else | ||
| 5961 | // Elaborate the first argument so we know what type we're dealing with. | ||
| 5962 | 1485 | e := listHead(inPosArgs); | |
| 5963 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1485 times.
|
1485 | (outCache, exp, DAE.PROP(ty, c)) := |
| 5964 | elabExpInExpression(inCache, inEnv, e, inImplicit, true, inPrefix, inInfo); | ||
| 5965 | |||
| 5966 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1481 times.
|
1485 | if Types.isMetaBoxedType(ty) then |
| 5967 | 4 | ty := Types.unboxedType(ty); | |
| 5968 | 4 | exp := DAE.UNBOX(exp, ty); | |
| 5969 | end if; | ||
| 5970 | |||
| 5971 | 1485 | val_slot := SLOT(DAE.FUNCARG("x", ty, DAE.C_VAR(), DAE.NON_PARALLEL(), | |
| 5972 | NONE()), false, NONE(), {}, 1, SLOT_NOT_EVALUATED); | ||
| 5973 | |||
| 5974 | try // Try the String(val, <option>) format. | ||
| 5975 | slots := {STRING_ARG_MINLENGTH, STRING_ARG_LEFTJUSTIFIED}; | ||
| 5976 | |||
| 5977 | // Only String(Real) has the significantDigits option. | ||
| 5978 |
2/2✓ Branch 1 taken 893 times.
✓ Branch 2 taken 592 times.
|
1485 | if Types.isRealOrSubTypeReal(ty) then |
| 5979 | slots := STRING_ARG_SIGNIFICANT_DIGITS :: slots; | ||
| 5980 | end if; | ||
| 5981 | |||
| 5982 | slots := val_slot :: slots; | ||
| 5983 | |||
| 5984 | 1485 | (outCache, args, _, consts) := elabInputArgs(outCache, inEnv, inPosArgs, inNamedArgs, | |
| 5985 | slots, false, true, inImplicit, | ||
| 5986 | inPrefix, inInfo, DAE.T_UNKNOWN_DEFAULT, Absyn.IDENT("String")); | ||
| 5987 | else | ||
| 5988 | // Try the String(val, format = s) format. | ||
| 5989 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
|
1 | if Types.isRealOrSubTypeReal(ty) then |
| 5990 | format_arg := SOME(DAE.SCONST("f")); | ||
| 5991 | elseif Types.isIntegerOrSubTypeInteger(ty) then | ||
| 5992 | format_arg := SOME(DAE.SCONST("d")); | ||
| 5993 | elseif Types.isString(ty) then | ||
| 5994 | format_arg := SOME(DAE.SCONST("s")); | ||
| 5995 | else | ||
| 5996 | format_arg := NONE(); | ||
| 5997 | end if; | ||
| 5998 | |||
| 5999 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
|
1 | if isSome(format_arg) then |
| 6000 | 1 | slots := {val_slot, SLOT(DAE.FUNCARG("format", DAE.T_STRING_DEFAULT, DAE.C_VAR(), | |
| 6001 | DAE.NON_PARALLEL(), NONE()), false, format_arg, {}, 2, | ||
| 6002 | SLOT_NOT_EVALUATED)}; | ||
| 6003 | else | ||
| 6004 | slots := {val_slot}; | ||
| 6005 | end if; | ||
| 6006 | |||
| 6007 | 1 | (outCache, args, _, consts) := elabInputArgs(outCache, inEnv, inPosArgs, inNamedArgs, | |
| 6008 | slots, false, true, inImplicit, | ||
| 6009 | inPrefix, inInfo, DAE.T_UNKNOWN_DEFAULT, Absyn.IDENT("String")); | ||
| 6010 | end try; | ||
| 6011 | |||
| 6012 | 1485 | c := List.fold(consts, Types.constAnd, DAE.C_CONST()); | |
| 6013 | 1485 | outExp := Expression.makePureBuiltinCall("String", args, DAE.T_STRING_DEFAULT); | |
| 6014 | 1485 | outProperties := DAE.PROP(DAE.T_STRING_DEFAULT, c); | |
| 6015 | end try; | ||
| 6016 | end elabBuiltinString; | ||
| 6017 | |||
| 6018 | protected function elabBuiltinGetInstanceName | ||
| 6019 | input FCore.Cache inCache; | ||
| 6020 | input FCore.Graph inEnv; | ||
| 6021 | input list<Absyn.Exp> inPosArgs; | ||
| 6022 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 6023 | input Boolean inImplicit; | ||
| 6024 | input DAE.Prefix inPrefix; | ||
| 6025 | input SourceInfo inInfo; | ||
| 6026 | output FCore.Cache outCache = inCache; | ||
| 6027 | output DAE.Exp outExp; | ||
| 6028 | output DAE.Properties outProperties; | ||
| 6029 | protected | ||
| 6030 | String str; | ||
| 6031 | Absyn.Path name, envName; | ||
| 6032 | algorithm | ||
| 6033 | 5 | checkBuiltinCallArgs(inPosArgs, inNamedArgs, 0, "getInstanceName", inInfo); | |
| 6034 | |||
| 6035 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | FCore.CACHE(modelName = name) := inCache; |
| 6036 | |||
| 6037 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | if PrefixUtil.isNoPrefix(inPrefix) then |
| 6038 | 5 | envName := FGraph.getGraphNameNoImplicitScopes(inEnv); | |
| 6039 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
|
5 | str := if AbsynUtil.pathEqual(envName, name) then |
| 6040 | AbsynUtil.pathLastIdent(name) else AbsynUtil.pathString(envName); | ||
| 6041 | else | ||
| 6042 | ✗ | str := AbsynUtil.pathLastIdent(name) + "." + PrefixUtil.printPrefixStr(inPrefix); | |
| 6043 | end if; | ||
| 6044 | |||
| 6045 | 5 | outExp := DAE.SCONST(str); | |
| 6046 | outProperties := DAE.PROP(DAE.T_STRING_DEFAULT, DAE.C_CONST()); | ||
| 6047 | end elabBuiltinGetInstanceName; | ||
| 6048 | |||
| 6049 | protected function elabBuiltinIsPresent | ||
| 6050 | input FCore.Cache inCache; | ||
| 6051 | input FCore.Graph inEnv; | ||
| 6052 | input list<Absyn.Exp> inPosArgs; | ||
| 6053 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 6054 | input Boolean inImplicit; | ||
| 6055 | input DAE.Prefix inPrefix; | ||
| 6056 | input SourceInfo info; | ||
| 6057 | output FCore.Cache outCache = inCache; | ||
| 6058 | output DAE.Exp outExp; | ||
| 6059 | output DAE.Properties outProperties; | ||
| 6060 | protected | ||
| 6061 | String str; | ||
| 6062 | Absyn.Direction direction; | ||
| 6063 | Absyn.Exp exp; | ||
| 6064 | algorithm | ||
| 6065 | 2 | checkBuiltinCallArgs(inPosArgs, inNamedArgs, 1, "isPresent", info); | |
| 6066 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | if not FGraph.inFunctionScope(inEnv) then |
| 6067 | ✗ | Error.addSourceMessage(Error.IS_PRESENT_WRONG_SCOPE, {SCodeDump.restrString(FGraph.getScopeRestriction(FGraph.currentScope(inEnv)))}, info); | |
| 6068 | end if; | ||
| 6069 | outExp := match listGet(inPosArgs, 1) | ||
| 6070 | case Absyn.CREF(Absyn.CREF_IDENT(name=str)) | ||
| 6071 | algorithm | ||
| 6072 | 2 | (outCache, DAE.TYPES_VAR(attributes=DAE.ATTR(direction=direction)), _, _, _, _) := Lookup.lookupIdentLocal(outCache, inEnv, str); | |
| 6073 | () := match direction | ||
| 6074 | case Absyn.BIDIR() | ||
| 6075 | algorithm | ||
| 6076 | ✗ | Error.addSourceMessage(Error.IS_PRESENT_WRONG_DIRECTION, {}, info); | |
| 6077 | ✗ | then fail(); | |
| 6078 | else (); | ||
| 6079 | end match; | ||
| 6080 | 4 | then Expression.makeImpureBuiltinCall("isPresent", DAE.CREF(DAE.CREF_IDENT(str, DAE.T_BOOL_DEFAULT, {}), DAE.T_BOOL_DEFAULT)::{}, DAE.T_BOOL_DEFAULT); | |
| 6081 | case exp | ||
| 6082 | algorithm | ||
| 6083 | ✗ | Error.addSourceMessage(Error.IS_PRESENT_INVALID_EXP, {Dump.printExpStr(exp)}, info); | |
| 6084 | ✗ | then fail(); | |
| 6085 | end match; | ||
| 6086 | |||
| 6087 | outProperties := DAE.PROP(DAE.T_BOOL_DEFAULT, DAE.C_VAR()); | ||
| 6088 | end elabBuiltinIsPresent; | ||
| 6089 | |||
| 6090 | protected function elabBuiltinVector | ||
| 6091 | "This function handles the built in vector operator." | ||
| 6092 | input FCore.Cache inCache; | ||
| 6093 | input FCore.Graph inEnv; | ||
| 6094 | input list<Absyn.Exp> inPosArgs; | ||
| 6095 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 6096 | input Boolean inImplicit; | ||
| 6097 | input DAE.Prefix inPrefix; | ||
| 6098 | input SourceInfo inInfo; | ||
| 6099 | output FCore.Cache outCache; | ||
| 6100 | output DAE.Exp outExp; | ||
| 6101 | output DAE.Properties outProperties; | ||
| 6102 | protected | ||
| 6103 | Absyn.Exp e; | ||
| 6104 | DAE.Type ty, arr_ty, exp_ty, el_ty; | ||
| 6105 | DAE.Const c; | ||
| 6106 | list<DAE.Exp> expl; | ||
| 6107 | algorithm | ||
| 6108 | 107 | checkBuiltinCallArgs(inPosArgs, inNamedArgs, 1, "vector", inInfo); | |
| 6109 | |||
| 6110 | 107 | e := listHead(inPosArgs); | |
| 6111 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 107 times.
|
107 | (outCache, outExp, outProperties as DAE.PROP(ty, c)) := |
| 6112 | elabExpInExpression(inCache, inEnv, e, inImplicit, true, inPrefix, inInfo); | ||
| 6113 | |||
| 6114 | // Scalar | ||
| 6115 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 107 times.
|
107 | if Types.isSimpleType(ty) then |
| 6116 | // vector(scalar) = {scalar} | ||
| 6117 | ✗ | arr_ty := Types.liftArray(ty, DAE.DIM_INTEGER(1)); | |
| 6118 | ✗ | exp_ty := Types.simplifyType(arr_ty); | |
| 6119 | ✗ | outExp := DAE.ARRAY(exp_ty, true, {outExp}); | |
| 6120 | ✗ | outProperties := DAE.PROP(arr_ty, c); | |
| 6121 | // Array or Matrix | ||
| 6122 | elseif Expression.isArray(outExp) or Expression.isMatrix(outExp) then | ||
| 6123 | // If the array/matrix has more than one dimension, flatten it into a one- | ||
| 6124 | // dimensional array. Otherwise, do nothing and return the expression as is. | ||
| 6125 |
2/2✓ Branch 1 taken 105 times.
✓ Branch 2 taken 2 times.
|
107 | if Types.numberOfDimensions(ty) <> 1 then |
| 6126 | 105 | checkBuiltinVectorDims(e, inEnv, ty, inPrefix, inInfo); | |
| 6127 | 105 | expl := Expression.getArrayOrMatrixContents(outExp); | |
| 6128 | 105 | expl := flattenArray(expl); | |
| 6129 | |||
| 6130 | 105 | el_ty := Types.arrayElementType(ty); | |
| 6131 | 105 | arr_ty := Types.liftArray(el_ty, DAE.DIM_INTEGER(listLength(expl))); | |
| 6132 | |||
| 6133 | 105 | outExp := DAE.ARRAY(Types.simplifyType(arr_ty), false, expl); | |
| 6134 | 105 | outProperties := DAE.PROP(arr_ty, c); | |
| 6135 | end if; | ||
| 6136 | // Anything else | ||
| 6137 | else | ||
| 6138 | // For any other type of expression, make a call to vector. | ||
| 6139 | ✗ | ty := Types.liftArray(Types.arrayElementType(ty), DAE.DIM_UNKNOWN()); | |
| 6140 | ✗ | exp_ty := Types.simplifyType(ty); | |
| 6141 | ✗ | outExp := Expression.makePureBuiltinCall("vector", {outExp}, exp_ty); | |
| 6142 | ✗ | outProperties := DAE.PROP(ty, c); | |
| 6143 | end if; | ||
| 6144 | end elabBuiltinVector; | ||
| 6145 | |||
| 6146 | protected function checkBuiltinVectorDims | ||
| 6147 | "Checks that the argument to vector has at most one dimension which is larger | ||
| 6148 | than one, otherwise prints an error and fails." | ||
| 6149 | input Absyn.Exp inExp; | ||
| 6150 | input FCore.Graph inEnv; | ||
| 6151 | input DAE.Type inType; | ||
| 6152 | input DAE.Prefix inPrefix; | ||
| 6153 | input SourceInfo inInfo; | ||
| 6154 | protected | ||
| 6155 | Boolean found_dim_sz_one = false; | ||
| 6156 | list<Integer> dims; | ||
| 6157 | String arg_str, scope_str, dim_str, pre_str; | ||
| 6158 | algorithm | ||
| 6159 | 105 | dims := Types.getDimensionSizes(inType); | |
| 6160 | |||
| 6161 |
2/2✓ Branch 0 taken 211 times.
✓ Branch 1 taken 105 times.
|
316 | for dim in dims loop |
| 6162 |
2/2✓ Branch 0 taken 105 times.
✓ Branch 1 taken 106 times.
|
211 | if dim > 1 then |
| 6163 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 105 times.
|
105 | if found_dim_sz_one then |
| 6164 | ✗ | scope_str := FGraph.printGraphPathStr(inEnv); | |
| 6165 | ✗ | arg_str := "vector(" + Dump.printExpStr(inExp) + ")"; | |
| 6166 | ✗ | dim_str := "[" + stringDelimitList(list(intString(d) for d in dims), ", ") + "]"; | |
| 6167 | ✗ | pre_str := PrefixUtil.printPrefixStr3(inPrefix); | |
| 6168 | ✗ | Error.addSourceMessageAndFail(Error.BUILTIN_VECTOR_INVALID_DIMENSIONS, | |
| 6169 | {scope_str, pre_str, dim_str, arg_str}, inInfo); | ||
| 6170 | else | ||
| 6171 | found_dim_sz_one := true; | ||
| 6172 | end if; | ||
| 6173 | end if; | ||
| 6174 | end for; | ||
| 6175 | end checkBuiltinVectorDims; | ||
| 6176 | |||
| 6177 | protected function flattenArray | ||
| 6178 | input list<DAE.Exp> arr; | ||
| 6179 | output list<DAE.Exp> flattenedExpl; | ||
| 6180 | algorithm | ||
| 6181 | flattenedExpl := match arr | ||
| 6182 | local | ||
| 6183 | DAE.Exp e; | ||
| 6184 | list<DAE.Exp> expl, expl2, rest_expl; | ||
| 6185 | |||
| 6186 | case {} then {}; | ||
| 6187 | |||
| 6188 | case DAE.ARRAY(array = expl) :: rest_expl | ||
| 6189 | algorithm | ||
| 6190 | 308 | expl := flattenArray(expl); | |
| 6191 | 308 | expl2 := flattenArray(rest_expl); | |
| 6192 | 308 | expl2 := listAppend(expl, expl2); | |
| 6193 | then expl2; | ||
| 6194 | |||
| 6195 | case DAE.MATRIX(matrix = {{e}}) :: rest_expl | ||
| 6196 | algorithm | ||
| 6197 | 4 | expl := flattenArray(rest_expl); | |
| 6198 | then | ||
| 6199 | (e :: expl); | ||
| 6200 | |||
| 6201 | case e :: expl | ||
| 6202 | algorithm | ||
| 6203 | 308 | expl := flattenArray(expl); | |
| 6204 | then | ||
| 6205 | (e :: expl); | ||
| 6206 | end match; | ||
| 6207 | end flattenArray; | ||
| 6208 | |||
| 6209 | public function elabBuiltinMatrix | ||
| 6210 | "Elaborates the builtin matrix function." | ||
| 6211 | input FCore.Cache inCache; | ||
| 6212 | input FCore.Graph inEnv; | ||
| 6213 | input list<Absyn.Exp> inPosArgs; | ||
| 6214 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 6215 | input Boolean inImpl; | ||
| 6216 | input DAE.Prefix inPrefix; | ||
| 6217 | input SourceInfo inInfo; | ||
| 6218 | output FCore.Cache outCache; | ||
| 6219 | output DAE.Exp outExp; | ||
| 6220 | output DAE.Properties outProperties; | ||
| 6221 | protected | ||
| 6222 | DAE.Type ty; | ||
| 6223 | algorithm | ||
| 6224 | 39 | checkBuiltinCallArgs(inPosArgs, inNamedArgs, 1, "matrix", inInfo); | |
| 6225 | |||
| 6226 | 39 | (outCache, outExp, outProperties) := elabExpInExpression(inCache, inEnv, | |
| 6227 | listHead(inPosArgs), inImpl, true, inPrefix, inInfo); | ||
| 6228 | 39 | ty := Types.getPropType(outProperties); | |
| 6229 | 39 | (outExp, outProperties) := elabBuiltinMatrix2(inCache, inEnv, outExp, | |
| 6230 | outProperties, ty, inInfo); | ||
| 6231 | end elabBuiltinMatrix; | ||
| 6232 | |||
| 6233 | protected function elabBuiltinMatrix2 | ||
| 6234 | "Helper function to elabBuiltinMatrix, evaluates the matrix function given the | ||
| 6235 | elaborated argument." | ||
| 6236 | input FCore.Cache inCache; | ||
| 6237 | input FCore.Graph inEnv; | ||
| 6238 | input DAE.Exp inArg; | ||
| 6239 | input DAE.Properties inProperties; | ||
| 6240 | input DAE.Type inType; | ||
| 6241 | input SourceInfo inInfo; | ||
| 6242 | output DAE.Exp outExp; | ||
| 6243 | output DAE.Properties outProperties; | ||
| 6244 | algorithm | ||
| 6245 | (outExp, outProperties) := match inArg | ||
| 6246 | local | ||
| 6247 | DAE.Type ty; | ||
| 6248 | DAE.Exp exp; | ||
| 6249 | DAE.Properties props; | ||
| 6250 | list<DAE.Exp> expl; | ||
| 6251 | DAE.Type ety; | ||
| 6252 | DAE.Dimension dim1, dim2; | ||
| 6253 | Boolean scalar; | ||
| 6254 | |||
| 6255 | // Scalar | ||
| 6256 | case _ guard(Types.isSimpleType(inType)) | ||
| 6257 | algorithm | ||
| 6258 | 1 | (exp, props) := promoteExp(inArg, inProperties, 2); | |
| 6259 | then | ||
| 6260 | (exp, props); | ||
| 6261 | |||
| 6262 | // 1-dimensional array | ||
| 6263 | case _ guard(Types.numberOfDimensions(inType) == 1) | ||
| 6264 | algorithm | ||
| 6265 | 38 | (exp, props) := promoteExp(inArg, inProperties, 2); | |
| 6266 | then | ||
| 6267 | (exp, props); | ||
| 6268 | |||
| 6269 | // Matrix | ||
| 6270 | case DAE.MATRIX() | ||
| 6271 | ✗ | then (inArg, inProperties); | |
| 6272 | |||
| 6273 | // n-dimensional array | ||
| 6274 | case DAE.ARRAY(ty = DAE.T_ARRAY(ety, dim1 :: dim2 :: _), scalar = scalar, array = expl) | ||
| 6275 | algorithm | ||
| 6276 | ✗ | expl := List.map1(expl, elabBuiltinMatrix3, inInfo); | |
| 6277 | ✗ | ty := Types.arrayElementType(inType); | |
| 6278 | ✗ | ty := Types.liftArrayListDims(ty, {dim1, dim2}); | |
| 6279 | ✗ | props := Types.setPropType(inProperties, ty); | |
| 6280 | ✗ | then | |
| 6281 | (DAE.ARRAY(DAE.T_ARRAY(ety, {dim1, dim2}), scalar, expl), props); | ||
| 6282 | |||
| 6283 | end match; | ||
| 6284 | end elabBuiltinMatrix2; | ||
| 6285 | |||
| 6286 | protected function elabBuiltinMatrix3 | ||
| 6287 | "Helper function to elabBuiltinMatrix2." | ||
| 6288 | input DAE.Exp inExp; | ||
| 6289 | input SourceInfo inInfo; | ||
| 6290 | output DAE.Exp outExp; | ||
| 6291 | algorithm | ||
| 6292 | outExp := match inExp | ||
| 6293 | local | ||
| 6294 | DAE.Type ety, ety2; | ||
| 6295 | Boolean scalar; | ||
| 6296 | list<DAE.Exp> expl; | ||
| 6297 | DAE.Dimension dim; | ||
| 6298 | DAE.Dimensions dims; | ||
| 6299 | list<list<DAE.Exp>> matrix_expl; | ||
| 6300 | |||
| 6301 | case DAE.ARRAY(ty = DAE.T_ARRAY(ety, dim :: _),scalar = scalar, array = expl) | ||
| 6302 | algorithm | ||
| 6303 | ✗ | expl := list(arrayScalar(e, 3, "matrix", inInfo) for e in expl); | |
| 6304 | ✗ | then | |
| 6305 | DAE.ARRAY(DAE.T_ARRAY(ety, {dim}), scalar, expl); | ||
| 6306 | |||
| 6307 | case DAE.MATRIX(ty = DAE.T_ARRAY(ety, dim :: dims), matrix = matrix_expl) | ||
| 6308 | algorithm | ||
| 6309 | ✗ | ety2 := DAE.T_ARRAY(ety, dims); | |
| 6310 | ✗ | expl := list(Expression.makeArray(e, ety2, true) for e in matrix_expl); | |
| 6311 | ✗ | expl := list(arrayScalar(e, 3, "matrix", inInfo) for e in expl); | |
| 6312 | ✗ | then | |
| 6313 | DAE.ARRAY(DAE.T_ARRAY(ety, {dim}), true, expl); | ||
| 6314 | |||
| 6315 | end match; | ||
| 6316 | end elabBuiltinMatrix3; | ||
| 6317 | |||
| 6318 | protected function arrayScalar | ||
| 6319 | "Returns the scalar value of an array, or prints an error message and fails if | ||
| 6320 | any dimension of the array isn't of size 1." | ||
| 6321 | input DAE.Exp inExp; | ||
| 6322 | input Integer inDim "The current dimension, used for error message."; | ||
| 6323 | input String inOperator "The current operator name, used for error message."; | ||
| 6324 | input SourceInfo inInfo; | ||
| 6325 | output DAE.Exp outExp; | ||
| 6326 | algorithm | ||
| 6327 | outExp := match inExp | ||
| 6328 | local | ||
| 6329 | DAE.Exp exp; | ||
| 6330 | DAE.Type ty; | ||
| 6331 | list<DAE.Exp> expl; | ||
| 6332 | list<list<DAE.Exp>> mexpl; | ||
| 6333 | String dim_str, size_str; | ||
| 6334 | |||
| 6335 | // An array with one element. | ||
| 6336 | case DAE.ARRAY(array = {exp}) | ||
| 6337 | ✗ | then arrayScalar(exp, inDim + 1, inOperator, inInfo); | |
| 6338 | |||
| 6339 | // Any other array. | ||
| 6340 | case DAE.ARRAY(array = expl) | ||
| 6341 | algorithm | ||
| 6342 | ✗ | dim_str := intString(inDim); | |
| 6343 | ✗ | size_str := intString(listLength(expl)); | |
| 6344 | ✗ | Error.addSourceMessage(Error.INVALID_ARRAY_DIM_IN_CONVERSION_OP, | |
| 6345 | {dim_str, inOperator, "1", size_str}, inInfo); | ||
| 6346 | ✗ | then | |
| 6347 | fail(); | ||
| 6348 | |||
| 6349 | // A matrix where the first dimension is 1. | ||
| 6350 | case DAE.MATRIX(ty = ty, matrix = {expl}) | ||
| 6351 | ✗ | then arrayScalar(DAE.ARRAY(ty, true, expl), inDim + 1, inOperator, inInfo); | |
| 6352 | |||
| 6353 | // Any other matrix. | ||
| 6354 | case DAE.MATRIX(matrix = mexpl) | ||
| 6355 | algorithm | ||
| 6356 | ✗ | dim_str := intString(inDim); | |
| 6357 | ✗ | size_str := intString(listLength(mexpl)); | |
| 6358 | ✗ | Error.addSourceMessage(Error.INVALID_ARRAY_DIM_IN_CONVERSION_OP, | |
| 6359 | {dim_str, inOperator, "1", size_str}, inInfo); | ||
| 6360 | ✗ | then | |
| 6361 | fail(); | ||
| 6362 | |||
| 6363 | // Anything else is assumed to be a scalar. | ||
| 6364 | else inExp; | ||
| 6365 | end match; | ||
| 6366 | end arrayScalar; | ||
| 6367 | |||
| 6368 | public function elabBuiltinHandler | ||
| 6369 | "This function dispatches the elaboration of builtin operators by returning | ||
| 6370 | the appropriate function. When a new builtin operator is added, a new rule | ||
| 6371 | has to be added to this function." | ||
| 6372 | input String inIdent; | ||
| 6373 | output HandlerFunc outHandler; | ||
| 6374 | |||
| 6375 | partial function HandlerFunc | ||
| 6376 | input FCore.Cache inCache; | ||
| 6377 | input FCore.Graph inEnv; | ||
| 6378 | input list<Absyn.Exp> inAbsynExpLst; | ||
| 6379 | input list<Absyn.NamedArg> inNamedArg; | ||
| 6380 | input Boolean inBoolean; | ||
| 6381 | input DAE.Prefix inPrefix; | ||
| 6382 | input SourceInfo info; | ||
| 6383 | output FCore.Cache outCache; | ||
| 6384 | output DAE.Exp outExp; | ||
| 6385 | output DAE.Properties outProperties; | ||
| 6386 | end HandlerFunc; | ||
| 6387 | algorithm | ||
| 6388 | outHandler := match inIdent | ||
| 6389 | case "smooth" then elabBuiltinSmooth; | ||
| 6390 | case "size" then elabBuiltinSize; | ||
| 6391 | case "ndims" then elabBuiltinNDims; | ||
| 6392 | case "zeros" then elabBuiltinZeros; | ||
| 6393 | case "ones" then elabBuiltinOnes; | ||
| 6394 | case "fill" then elabBuiltinFill; | ||
| 6395 | case "max" then elabBuiltinMax; | ||
| 6396 | case "min" then elabBuiltinMin; | ||
| 6397 | case "transpose" then elabBuiltinTranspose; | ||
| 6398 | case "symmetric" then elabBuiltinSymmetric; | ||
| 6399 | case "array" then elabBuiltinArray; | ||
| 6400 | case "sum" then elabBuiltinSum; | ||
| 6401 | case "product" then elabBuiltinProduct; | ||
| 6402 | case "pre" then elabBuiltinPre; | ||
| 6403 | case "firstTick" then elabBuiltinFirstTick; | ||
| 6404 | case "interval" then elabBuiltinInterval; | ||
| 6405 | case "boolean" then elabBuiltinBoolean; | ||
| 6406 | case "noEvent" then elabBuiltinNoevent; | ||
| 6407 | case "edge" then elabBuiltinEdge; | ||
| 6408 | case "der" then elabBuiltinDer; | ||
| 6409 | case "change" then elabBuiltinChange; | ||
| 6410 | case "cat" then elabBuiltinCat; | ||
| 6411 | case "identity" then elabBuiltinIdentity; | ||
| 6412 | case "vector" then elabBuiltinVector; | ||
| 6413 | case "matrix" then elabBuiltinMatrix; | ||
| 6414 | case "scalar" then elabBuiltinScalar; | ||
| 6415 | case "String" then elabBuiltinString; | ||
| 6416 | case "rooted" then elabBuiltinRooted; | ||
| 6417 | case "Integer" then elabBuiltinIntegerEnum; | ||
| 6418 | case "EnumToInteger" then elabBuiltinIntegerEnum; | ||
| 6419 | case "inStream" then elabBuiltinInStream; | ||
| 6420 | case "actualStream" then elabBuiltinActualStream; | ||
| 6421 | case "getInstanceName" then elabBuiltinGetInstanceName; | ||
| 6422 | case "classDirectory" then elabBuiltinClassDirectory; | ||
| 6423 | case "sample" then elabBuiltinSample; | ||
| 6424 | case "cardinality" then elabBuiltinCardinality; | ||
| 6425 | case "homotopy" then elabBuiltinHomotopy; | ||
| 6426 | case "DynamicSelect" then elabBuiltinDynamicSelect; | ||
| 6427 | case "Clock" | ||
| 6428 | algorithm | ||
| 6429 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 108 times.
|
108 | true := Config.synchronousFeaturesAllowed(); |
| 6430 | then elabBuiltinClock; | ||
| 6431 | case "hold" | ||
| 6432 | algorithm | ||
| 6433 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
|
26 | true := Config.synchronousFeaturesAllowed(); |
| 6434 | then elabBuiltinHold; | ||
| 6435 | case "shiftSample" | ||
| 6436 | algorithm | ||
| 6437 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
|
20 | true := Config.synchronousFeaturesAllowed(); |
| 6438 | then elabBuiltinShiftSample; | ||
| 6439 | case "backSample" | ||
| 6440 | algorithm | ||
| 6441 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
|
12 | true := Config.synchronousFeaturesAllowed(); |
| 6442 | then elabBuiltinBackSample; | ||
| 6443 | case "noClock" | ||
| 6444 | algorithm | ||
| 6445 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
|
10 | true := Config.synchronousFeaturesAllowed(); |
| 6446 | then elabBuiltinNoClock; | ||
| 6447 | case "transition" | ||
| 6448 | algorithm | ||
| 6449 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
|
32 | true := Config.synchronousFeaturesAllowed(); |
| 6450 | then elabBuiltinTransition; | ||
| 6451 | case "initialState" | ||
| 6452 | algorithm | ||
| 6453 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
|
16 | true := Config.synchronousFeaturesAllowed(); |
| 6454 | then elabBuiltinInitialState; | ||
| 6455 | case "activeState" | ||
| 6456 | algorithm | ||
| 6457 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
|
8 | true := Config.synchronousFeaturesAllowed(); |
| 6458 | then elabBuiltinActiveState; | ||
| 6459 | case "ticksInState" | ||
| 6460 | algorithm | ||
| 6461 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | true := Config.synchronousFeaturesAllowed(); |
| 6462 | then elabBuiltinTicksInState; | ||
| 6463 | case "timeInState" | ||
| 6464 | algorithm | ||
| 6465 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | true := Config.synchronousFeaturesAllowed(); |
| 6466 | then elabBuiltinTimeInState; | ||
| 6467 | case "sourceInfo" | ||
| 6468 | algorithm | ||
| 6469 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
|
38 | true := Config.acceptMetaModelicaGrammar(); |
| 6470 | then elabBuiltinSourceInfo; | ||
| 6471 | case "SOME" | ||
| 6472 | algorithm | ||
| 6473 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 748 times.
|
748 | true := Config.acceptMetaModelicaGrammar(); |
| 6474 | then elabBuiltinSome; | ||
| 6475 | case "NONE" | ||
| 6476 | algorithm | ||
| 6477 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6783 times.
|
6783 | true := Config.acceptMetaModelicaGrammar(); |
| 6478 | then elabBuiltinNone; | ||
| 6479 | case "isPresent" | ||
| 6480 | algorithm | ||
| 6481 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
4 | true := Config.acceptMetaModelicaGrammar(); |
| 6482 | then elabBuiltinIsPresent; | ||
| 6483 | end match; | ||
| 6484 | end elabBuiltinHandler; | ||
| 6485 | |||
| 6486 | public function isBuiltinFunc "Returns true if the function name given as argument | ||
| 6487 | is a builtin function, which either has a elabBuiltinHandler function | ||
| 6488 | or can be found in the builtin environment." | ||
| 6489 | input Absyn.Path inPath "the path of the found function"; | ||
| 6490 | input DAE.Type ty; | ||
| 6491 | output DAE.FunctionBuiltin isBuiltin; | ||
| 6492 | output Boolean b; | ||
| 6493 | output Absyn.Path outPath "make the path non-FQ"; | ||
| 6494 | algorithm | ||
| 6495 | (isBuiltin,b,outPath) := matchcontinue (inPath,ty) | ||
| 6496 | local | ||
| 6497 | String id; | ||
| 6498 | Absyn.Path path; | ||
| 6499 | |||
| 6500 | case (path,DAE.T_FUNCTION(functionAttributes=DAE.FUNCTION_ATTRIBUTES(isBuiltin=isBuiltin as DAE.FUNCTION_BUILTIN(_)))) | ||
| 6501 | algorithm | ||
| 6502 | 29124 | path := AbsynUtil.makeNotFullyQualified(path); | |
| 6503 | then (isBuiltin, true, path); | ||
| 6504 | |||
| 6505 | case (path,DAE.T_FUNCTION(functionAttributes=DAE.FUNCTION_ATTRIBUTES(isBuiltin=isBuiltin as DAE.FUNCTION_BUILTIN_PTR()))) | ||
| 6506 | algorithm | ||
| 6507 | 316 | path := AbsynUtil.makeNotFullyQualified(path); | |
| 6508 | then (isBuiltin, false, path); | ||
| 6509 | |||
| 6510 | case (Absyn.IDENT(name = id),_) | ||
| 6511 | algorithm | ||
| 6512 | 751 | elabBuiltinHandler(id); | |
| 6513 | ✗ | then (DAE.FUNCTION_BUILTIN(SOME(id), false), true, inPath); | |
| 6514 | |||
| 6515 | case (Absyn.FULLYQUALIFIED(path), _) | ||
| 6516 | algorithm | ||
| 6517 |
1/2✓ Branch 1 taken 26348 times.
✗ Branch 2 not taken.
|
26348 | (isBuiltin as DAE.FUNCTION_BUILTIN(),_,path) := isBuiltinFunc(path,ty); |
| 6518 | then | ||
| 6519 | (isBuiltin, true, path); | ||
| 6520 | |||
| 6521 | case (Absyn.QUALIFIED("Connections", Absyn.IDENT("isRoot")), _) | ||
| 6522 | then (DAE.FUNCTION_BUILTIN(NONE(), false), true, inPath); | ||
| 6523 | |||
| 6524 | else (DAE.FUNCTION_NOT_BUILTIN(), false, inPath); | ||
| 6525 | end matchcontinue; | ||
| 6526 | end isBuiltinFunc; | ||
| 6527 | |||
| 6528 | protected function elabCallBuiltin | ||
| 6529 | "This function elaborates on builtin operators (such as \"pre\", \"der\" etc.), | ||
| 6530 | by calling the builtin handler to retrieve the correct function to call." | ||
| 6531 | input FCore.Cache inCache; | ||
| 6532 | input FCore.Graph inEnv; | ||
| 6533 | input Absyn.ComponentRef inFnName; | ||
| 6534 | input list<Absyn.Exp> inPosArgs; | ||
| 6535 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 6536 | input Boolean inImplicit; | ||
| 6537 | input DAE.Prefix inPrefix; | ||
| 6538 | input SourceInfo inInfo; | ||
| 6539 | output FCore.Cache outCache; | ||
| 6540 | output DAE.Exp outExp; | ||
| 6541 | output DAE.Properties outProperties; | ||
| 6542 | |||
| 6543 | partial function HandlerFunc | ||
| 6544 | input FCore.Cache inCache; | ||
| 6545 | input FCore.Graph inEnv; | ||
| 6546 | input list<Absyn.Exp> inPosArgs; | ||
| 6547 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 6548 | input Boolean inImplicit; | ||
| 6549 | input DAE.Prefix inPrefix; | ||
| 6550 | input SourceInfo inInfo; | ||
| 6551 | output FCore.Cache outCache; | ||
| 6552 | output DAE.Exp outExp; | ||
| 6553 | output DAE.Properties outProperties; | ||
| 6554 | end HandlerFunc; | ||
| 6555 | algorithm | ||
| 6556 | (outCache, outExp, outProperties) := match inFnName | ||
| 6557 | local | ||
| 6558 | HandlerFunc handler; | ||
| 6559 | Absyn.ComponentRef cr; | ||
| 6560 | |||
| 6561 | case Absyn.CREF_IDENT(subscripts = {}) | ||
| 6562 | algorithm | ||
| 6563 | 20425 | handler := elabBuiltinHandler(inFnName.name); | |
| 6564 |
3/6✗ Branch 0 not taken.
✓ Branch 1 taken 20425 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 11923 times.
✓ Branch 6 taken 8502 times.
|
32348 | then |
| 6565 | handler(inCache, inEnv, inPosArgs, inNamedArgs, inImplicit, inPrefix, inInfo); | ||
| 6566 | |||
| 6567 | case Absyn.CREF_QUAL(name = "Connections", componentRef = Absyn.CREF_IDENT(name = "isRoot")) | ||
| 6568 | 151 | then elabBuiltinIsRoot(inCache, inEnv, inPosArgs, inNamedArgs, inImplicit, inPrefix, inInfo); | |
| 6569 | |||
| 6570 | case Absyn.CREF_QUAL(name = "Connections", componentRef = Absyn.CREF_IDENT(name = "uniqueRootIndices")) | ||
| 6571 | algorithm | ||
| 6572 | ✗ | Error.addSourceMessage(Error.NON_STANDARD_OPERATOR, {"Connections.uniqueRootIndices"}, inInfo); | |
| 6573 | ✗ | then elabBuiltinUniqueRootIndices(inCache, inEnv, inPosArgs, inNamedArgs, inImplicit, inPrefix, inInfo); | |
| 6574 | |||
| 6575 | case Absyn.CREF_QUAL(name = "Connections", componentRef = Absyn.CREF_IDENT(name = "rooted")) | ||
| 6576 | 128 | then elabBuiltinRooted(inCache, inEnv, inPosArgs, inNamedArgs, inImplicit, inPrefix, inInfo); | |
| 6577 | |||
| 6578 | case Absyn.CREF_FULLYQUALIFIED(cr) | ||
| 6579 | ✗ | then elabCallBuiltin(inCache, inEnv, cr, inPosArgs, inNamedArgs, inImplicit, inPrefix, inInfo); | |
| 6580 | |||
| 6581 | end match; | ||
| 6582 | end elabCallBuiltin; | ||
| 6583 | |||
| 6584 | protected function elabCall | ||
| 6585 | "This function elaborates on a function call. It converts the name to a | ||
| 6586 | Absyn.Path, and used the Static.elabCallArgs to do the rest of the work." | ||
| 6587 | input output FCore.Cache cache; | ||
| 6588 | input FCore.Graph env; | ||
| 6589 | input Absyn.ComponentRef fn; | ||
| 6590 | input list<Absyn.Exp> args; | ||
| 6591 | input list<Absyn.NamedArg> nargs; | ||
| 6592 | input list<Absyn.Path> typeVars; | ||
| 6593 | input Boolean impl; | ||
| 6594 | input DAE.Prefix pre; | ||
| 6595 | input SourceInfo info; | ||
| 6596 | output DAE.Exp e; | ||
| 6597 | output DAE.Properties prop; | ||
| 6598 | protected | ||
| 6599 | Integer numErrorMessages = Error.getNumErrorMessages(); | ||
| 6600 | list<Integer> handles; | ||
| 6601 | String name, s, s1, s2; | ||
| 6602 | Absyn.Path fn_1; | ||
| 6603 | String fnstr,argstr,prestr; | ||
| 6604 | list<String> argstrs; | ||
| 6605 | algorithm | ||
| 6606 |
2/2✓ Branch 1 taken 20704 times.
✓ Branch 2 taken 75163 times.
|
95867 | if hasBuiltInHandler(fn) then |
| 6607 | try | ||
| 6608 | 20704 | (cache,e,prop) := elabCallBuiltin(cache, env, fn, args, nargs, impl,pre,info) "Built in functions (e.g. \"pre\", \"der\"), have only possitional arguments" ; | |
| 6609 | 20588 | return; | |
| 6610 | else | ||
| 6611 |
1/2✓ Branch 1 taken 116 times.
✗ Branch 2 not taken.
|
116 | true := numErrorMessages == Error.getNumErrorMessages(); |
| 6612 | ✗ | name := Dump.printComponentRefStr(fn); | |
| 6613 | ✗ | s1 := stringDelimitList(List.map(args, Dump.printExpStr), ", "); | |
| 6614 | ✗ | s2 := stringDelimitList(List.map(nargs, Dump.printNamedArgStr), ", "); | |
| 6615 | ✗ | s := if s2 == "" then s1 else s1 + ", " + s2; | |
| 6616 | ✗ | s := stringAppendList({name,"(",s,").\n"}); | |
| 6617 | ✗ | Error.addSourceMessage(Error.WRONG_TYPE_OR_NO_OF_ARGS, {s,PrefixUtil.printPrefixStr3(pre)}, info); | |
| 6618 | ✗ | fail(); | |
| 6619 | end try; | ||
| 6620 | end if; | ||
| 6621 | handles := {}; | ||
| 6622 | try | ||
| 6623 | // Interactive mode | ||
| 6624 | 75163 | ErrorExt.setCheckpoint("elabCall_InteractiveFunction"); | |
| 6625 | 75163 | fn_1 := AbsynUtil.crefToPath(fn); | |
| 6626 | 75163 | (cache,e,prop) := elabCallArgs(cache,env, fn_1, args, nargs, typeVars, impl,pre,info); | |
| 6627 | // If elabCallArgs fails, BackendCevalInterface.elabCallInteractive handles the checkpoint | ||
| 6628 | 72503 | ErrorExt.delCheckpoint("elabCall_InteractiveFunction"); | |
| 6629 | else | ||
| 6630 | // Best-effort failure trace before trying the scripting interface. | ||
| 6631 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 2659 times.
|
2660 | if Flags.isSet(Flags.FAILTRACE) then |
| 6632 | 1 | Debug.traceln("- Static.elabCall failed\n"); | |
| 6633 | 1 | Debug.trace(" function: "); | |
| 6634 | 1 | fnstr := Dump.printComponentRefStr(fn); | |
| 6635 | 1 | Debug.trace(fnstr); | |
| 6636 | 1 | Debug.trace(" posargs: "); | |
| 6637 | 1 | argstrs := List.map(args, Dump.printExpStr); | |
| 6638 | 1 | argstr := stringDelimitList(argstrs, ", "); | |
| 6639 | 1 | Debug.traceln(argstr); | |
| 6640 | 1 | Debug.trace(" prefix: "); | |
| 6641 | 1 | prestr := PrefixUtil.printPrefixStr(pre); | |
| 6642 | 1 | Debug.traceln(prestr); | |
| 6643 | end if; | ||
| 6644 | // Handle the scripting interface: simulate(), plot() etc. | ||
| 6645 | 2660 | (cache,e,prop) := BackendCevalInterface.elabCallInteractive(cache, env, fn, args, nargs, impl, pre, info); | |
| 6646 | end try; | ||
| 6647 | end elabCall; | ||
| 6648 | |||
| 6649 | protected function hasBuiltInHandler "Determine if a function has a builtin handler or not." | ||
| 6650 | input Absyn.ComponentRef fn; | ||
| 6651 | output Boolean b; | ||
| 6652 | algorithm | ||
| 6653 | b := matchcontinue fn | ||
| 6654 | local | ||
| 6655 | Absyn.ComponentRef cr; | ||
| 6656 | String name; | ||
| 6657 | case Absyn.CREF_IDENT(name = name,subscripts = {}) | ||
| 6658 | algorithm | ||
| 6659 | 43091 | elabBuiltinHandler(name); | |
| 6660 | then true; | ||
| 6661 | case Absyn.CREF_QUAL(name = "Connections", componentRef = Absyn.CREF_IDENT(name = "isRoot")) | ||
| 6662 | then true; | ||
| 6663 | |||
| 6664 | case Absyn.CREF_QUAL(name = "Connections", componentRef = Absyn.CREF_IDENT(name = "uniqueRootIndices")) | ||
| 6665 | then true; | ||
| 6666 | |||
| 6667 | case Absyn.CREF_QUAL(name = "Connections", componentRef = Absyn.CREF_IDENT(name = "rooted")) | ||
| 6668 | then true; | ||
| 6669 | |||
| 6670 | 4193 | case Absyn.CREF_FULLYQUALIFIED(cr) then hasBuiltInHandler(cr); | |
| 6671 | else false; | ||
| 6672 | end matchcontinue; | ||
| 6673 | end hasBuiltInHandler; | ||
| 6674 | |||
| 6675 | protected function isValidDerVariableName | ||
| 6676 | "Used to check if a der() expression is a valid VariableName. | ||
| 6677 | Valid forms are der(x), der(der(x)), etc." | ||
| 6678 | input Absyn.Exp exp; | ||
| 6679 | input Boolean nested = false; | ||
| 6680 | output Boolean isValid; | ||
| 6681 | protected | ||
| 6682 | Absyn.Exp arg; | ||
| 6683 | algorithm | ||
| 6684 | isValid := match exp | ||
| 6685 | case Absyn.CREF() then nested; | ||
| 6686 | case Absyn.CALL(function_ = Absyn.CREF_IDENT(name = "der"), functionArgs = Absyn.FUNCTIONARGS({arg}, {})) | ||
| 6687 | 18 | then isValidDerVariableName(arg, true); | |
| 6688 | else false; | ||
| 6689 | end match; | ||
| 6690 | end isValidDerVariableName; | ||
| 6691 | |||
| 6692 | public function elabVariablenames "This function elaborates variablenames to DAE.Expression. A variablename can | ||
| 6693 | be used in e.g. plot(model,{v1{3},v2.t}) It should only be used in interactive | ||
| 6694 | functions that uses variablenames as componentreferences. | ||
| 6695 | " | ||
| 6696 | input list<Absyn.Exp> inExpl; | ||
| 6697 | output list<DAE.Exp> outExpl = {}; | ||
| 6698 | protected | ||
| 6699 | algorithm | ||
| 6700 | ✗ | outExpl := list(match e | |
| 6701 | ✗ | case Absyn.CREF() then DAE.CODE(Absyn.C_VARIABLENAME(e.componentRef), DAE.T_UNKNOWN_DEFAULT); | |
| 6702 | ✗ | case Absyn.CALL() guard isValidDerVariableName(e) then DAE.CODE(Absyn.C_EXPRESSION(e), DAE.T_UNKNOWN_DEFAULT); | |
| 6703 | end match for e in inExpl); | ||
| 6704 | end elabVariablenames; | ||
| 6705 | |||
| 6706 | public function getOptionalNamedArgExpList | ||
| 6707 | input String name; | ||
| 6708 | input list<Absyn.NamedArg> nargs; | ||
| 6709 | output list<DAE.Exp> out; | ||
| 6710 | algorithm | ||
| 6711 | out := matchcontinue nargs | ||
| 6712 | local | ||
| 6713 | list<Absyn.Exp> absynExpList; | ||
| 6714 | String argName; | ||
| 6715 | list<Absyn.NamedArg> rest; | ||
| 6716 | |||
| 6717 | case {} then {}; | ||
| 6718 | |||
| 6719 | case Absyn.NAMEDARG(argName = argName, argValue = Absyn.ARRAY(arrayExp = absynExpList)) :: _ | ||
| 6720 | algorithm | ||
| 6721 | ✗ | true := stringEq(name, argName); | |
| 6722 | ✗ | then | |
| 6723 | absynExpListToDaeExpList(absynExpList); | ||
| 6724 | |||
| 6725 | case _ :: rest | ||
| 6726 | ✗ | then getOptionalNamedArgExpList(name, rest); | |
| 6727 | |||
| 6728 | end matchcontinue; | ||
| 6729 | end getOptionalNamedArgExpList; | ||
| 6730 | |||
| 6731 | protected function absynExpListToDaeExpList | ||
| 6732 | input list<Absyn.Exp> absynExpList; | ||
| 6733 | output list<DAE.Exp> out; | ||
| 6734 | algorithm | ||
| 6735 | out := match absynExpList | ||
| 6736 | local | ||
| 6737 | list<DAE.Exp> daeExpList; | ||
| 6738 | list<Absyn.Exp> absynRest; | ||
| 6739 | Absyn.ComponentRef absynCr; | ||
| 6740 | Absyn.Path absynPath; | ||
| 6741 | DAE.ComponentRef daeCr; | ||
| 6742 | DAE.Exp crefExp; | ||
| 6743 | |||
| 6744 | case {} then {}; | ||
| 6745 | |||
| 6746 | case Absyn.CREF(componentRef = absynCr) :: absynRest | ||
| 6747 | algorithm | ||
| 6748 | ✗ | absynPath := AbsynUtil.crefToPath(absynCr); | |
| 6749 | ✗ | daeCr := ComponentReference.pathToCref(absynPath); | |
| 6750 | ✗ | crefExp := Expression.crefExp(daeCr); | |
| 6751 | ✗ | daeExpList := absynExpListToDaeExpList(absynRest); | |
| 6752 | then | ||
| 6753 | crefExp :: daeExpList; | ||
| 6754 | |||
| 6755 | case _ :: absynRest | ||
| 6756 | ✗ | then absynExpListToDaeExpList(absynRest); | |
| 6757 | end match; | ||
| 6758 | end absynExpListToDaeExpList; | ||
| 6759 | |||
| 6760 | public function getOptionalNamedArg | ||
| 6761 | "This function is used to 'elaborate' interactive functions' optional parameters, | ||
| 6762 | e.g. simulate(A.b, startTime=1), startTime is an optional parameter." | ||
| 6763 | input FCore.Cache inCache; | ||
| 6764 | input FCore.Graph inEnv; | ||
| 6765 | input Boolean inImplicit; | ||
| 6766 | input String inArgName; | ||
| 6767 | input DAE.Type inType; | ||
| 6768 | input list<Absyn.NamedArg> inArgs; | ||
| 6769 | input DAE.Exp inDefaultExp; | ||
| 6770 | input DAE.Prefix inPrefix; | ||
| 6771 | input SourceInfo inInfo; | ||
| 6772 | output FCore.Cache outCache = inCache; | ||
| 6773 | output DAE.Exp outExp = inDefaultExp; | ||
| 6774 | protected | ||
| 6775 | String name; | ||
| 6776 | DAE.Type ty; | ||
| 6777 | Absyn.Exp e; | ||
| 6778 | algorithm | ||
| 6779 |
2/2✓ Branch 0 taken 22348 times.
✓ Branch 1 taken 15023 times.
|
37371 | for arg in inArgs loop |
| 6780 | 22348 | Absyn.NAMEDARG(argName = name) := arg; | |
| 6781 | |||
| 6782 |
4/4✓ Branch 0 taken 3904 times.
✓ Branch 1 taken 18444 times.
✓ Branch 3 taken 1840 times.
✓ Branch 4 taken 2064 times.
|
22348 | if name == inArgName then |
| 6783 | // Found the argument, try to evaluate it. | ||
| 6784 | try | ||
| 6785 | 1840 | Absyn.NAMEDARG(argValue = e) := arg; | |
| 6786 | |||
| 6787 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1840 times.
|
1840 | (outCache, outExp, DAE.PROP(type_ = ty)) := |
| 6788 | elabExpInExpression(inCache, inEnv, e, inImplicit, true, inPrefix, inInfo); | ||
| 6789 | 1840 | outExp := Types.matchType(outExp, ty, inType, true); | |
| 6790 | else | ||
| 6791 | // The argument couldn't be evaluated, possibly due to having the wrong | ||
| 6792 | // type. We should print an error for this, but some API functions like | ||
| 6793 | // simulate depend on the default arguments having the wrong type. | ||
| 6794 | end try; | ||
| 6795 | |||
| 6796 | break; | ||
| 6797 | end if; | ||
| 6798 | end for; | ||
| 6799 | end getOptionalNamedArg; | ||
| 6800 | |||
| 6801 | public function elabUntypedCref | ||
| 6802 | "This function elaborates a ComponentRef without adding type information. | ||
| 6803 | Environment is passed along, such that constant subscripts can be elabed | ||
| 6804 | using existing functions." | ||
| 6805 | input FCore.Cache inCache; | ||
| 6806 | input FCore.Graph inEnv; | ||
| 6807 | input Absyn.ComponentRef inCref; | ||
| 6808 | input Boolean inImplicit; | ||
| 6809 | input DAE.Prefix inPrefix; | ||
| 6810 | input SourceInfo inInfo; | ||
| 6811 | output FCore.Cache outCache; | ||
| 6812 | output DAE.ComponentRef outCref; | ||
| 6813 | algorithm | ||
| 6814 | outCref := match inCref | ||
| 6815 | local | ||
| 6816 | list<DAE.Subscript> subs; | ||
| 6817 | DAE.ComponentRef cr; | ||
| 6818 | |||
| 6819 | case Absyn.CREF_IDENT() | ||
| 6820 | algorithm | ||
| 6821 | 14 | (outCache, subs) := elabSubscripts(inCache, inEnv, inCref.subscripts, inImplicit, inPrefix, inInfo); | |
| 6822 | 14 | then | |
| 6823 | ComponentReferenceBasics.makeCrefIdent(inCref.name, DAE.T_UNKNOWN_DEFAULT, subs); | ||
| 6824 | |||
| 6825 | case Absyn.CREF_QUAL() | ||
| 6826 | algorithm | ||
| 6827 | 14 | (outCache, subs) := elabSubscripts(inCache, inEnv, inCref.subscripts, | |
| 6828 | inImplicit, inPrefix, inInfo); | ||
| 6829 | 14 | (outCache, cr) := elabUntypedCref(outCache, inEnv, inCref.componentRef, | |
| 6830 | inImplicit, inPrefix, inInfo); | ||
| 6831 | 14 | then | |
| 6832 | ComponentReferenceBasics.makeCrefQual(inCref.name, DAE.T_UNKNOWN_DEFAULT, subs, cr); | ||
| 6833 | |||
| 6834 | end match; | ||
| 6835 | end elabUntypedCref; | ||
| 6836 | |||
| 6837 | public function needToRebuild | ||
| 6838 | input String newFile; | ||
| 6839 | input String oldFile; | ||
| 6840 | input Real buildTime; | ||
| 6841 | output Boolean buildNeeded; | ||
| 6842 | algorithm | ||
| 6843 | buildNeeded := matchcontinue(newFile, oldFile) | ||
| 6844 | local String newf,oldf; Real nfmt; | ||
| 6845 | case ("", "") then true; // rebuild all the time if the function has no file! | ||
| 6846 | case (newf, oldf) | ||
| 6847 | algorithm | ||
| 6848 | ✗ | true := stringEq(newf, oldf); // the files should be the same! | |
| 6849 | // the new file nf should have an older modification time than the last build | ||
| 6850 | ✗ | SOME(nfmt) := System.getFileModificationTime(newf); | |
| 6851 | ✗ | true := realGt(buildTime, nfmt); // the file was not modified since last build | |
| 6852 | then false; | ||
| 6853 | else true; | ||
| 6854 | end matchcontinue; | ||
| 6855 | end needToRebuild; | ||
| 6856 | |||
| 6857 | protected function createDummyFarg | ||
| 6858 | input String name; | ||
| 6859 | output DAE.FuncArg farg; | ||
| 6860 | algorithm | ||
| 6861 | 128 | farg := DAE.FUNCARG(name, DAE.T_UNKNOWN_DEFAULT, DAE.C_VAR(), DAE.NON_PARALLEL(), NONE()); | |
| 6862 | end createDummyFarg; | ||
| 6863 | |||
| 6864 | public function elabCallArgs " | ||
| 6865 | function: elabCallArgs | ||
| 6866 | Given the name of a function and two lists of expression and | ||
| 6867 | NamedArg respectively to be used | ||
| 6868 | as actual arguments in a function call to that function, this | ||
| 6869 | function finds the function definition and matches the actual | ||
| 6870 | arguments to the formal parameters." | ||
| 6871 | input FCore.Cache inCache; | ||
| 6872 | input FCore.Graph inEnv; | ||
| 6873 | input Absyn.Path inPath; | ||
| 6874 | input list<Absyn.Exp> inAbsynExpLst; | ||
| 6875 | input list<Absyn.NamedArg> inAbsynNamedArgLst; | ||
| 6876 | input list<Absyn.Path> typeVars; | ||
| 6877 | input Boolean inBoolean; | ||
| 6878 | input DAE.Prefix inPrefix; | ||
| 6879 | input SourceInfo info; | ||
| 6880 | output FCore.Cache outCache; | ||
| 6881 | output DAE.Exp outExp; | ||
| 6882 | output DAE.Properties outProperties; | ||
| 6883 | algorithm | ||
| 6884 |
3/4✗ Branch 3 not taken.
✓ Branch 4 taken 79526 times.
✓ Branch 5 taken 2655 times.
✓ Branch 6 taken 76871 times.
|
79531 | (outCache,SOME((outExp,outProperties))) := |
| 6885 | elabCallArgs2(inCache,inEnv,inPath,inAbsynExpLst,inAbsynNamedArgLst,typeVars,inBoolean,Mutable.create(false),inPrefix,info,Error.getNumErrorMessages()); | ||
| 6886 | 76871 | (outCache,outProperties) := elabCallArgsEvaluateArrayLength(outCache,inEnv,outProperties,inPrefix,info); | |
| 6887 | end elabCallArgs; | ||
| 6888 | |||
| 6889 | protected function elabCallArgsEvaluateArrayLength | ||
| 6890 | "Evaluate array dimensions in the returned type. For a call f(n) we might get | ||
| 6891 | Integer[n] back, where n is a parameter expression. We consider any such | ||
| 6892 | parameter structural since it decides the dimension of an array. We fall | ||
| 6893 | back to not evaluating the parameter if we fail since the dimension may not | ||
| 6894 | be structural (used in another call or reduction, etc)." | ||
| 6895 | input FCore.Cache inCache; | ||
| 6896 | input FCore.Graph env; | ||
| 6897 | input DAE.Properties inProperties; | ||
| 6898 | input DAE.Prefix inPrefix; | ||
| 6899 | input SourceInfo info; | ||
| 6900 | output FCore.Cache outCache; | ||
| 6901 | output DAE.Properties outProperties; | ||
| 6902 | protected | ||
| 6903 | DAE.Type ty; | ||
| 6904 | algorithm | ||
| 6905 | try | ||
| 6906 | // Unsure if we want to evaluate dimensions inside function scope. | ||
| 6907 | // Last scope ref in env is a class scope. | ||
| 6908 |
2/2✓ Branch 2 taken 43452 times.
✓ Branch 3 taken 33419 times.
|
153742 | true := FGraph.checkScopeType({FGraph.lastScopeRef(env)}, SOME(FCore.CLASS_SCOPE())); |
| 6909 | 33419 | ty := Types.getPropType(inProperties); | |
| 6910 | 33419 | (ty, (outCache, _)) := Types.traverseType(ty, (inCache, env), elabCallArgsEvaluateArrayLength2); | |
| 6911 | 33419 | outProperties := Types.setPropType(inProperties, ty); | |
| 6912 | else | ||
| 6913 | outCache := inCache; | ||
| 6914 | outProperties := inProperties; | ||
| 6915 | end try; | ||
| 6916 | end elabCallArgsEvaluateArrayLength; | ||
| 6917 | |||
| 6918 | protected function elabCallArgsEvaluateArrayLength2 | ||
| 6919 | input DAE.Type ty; | ||
| 6920 | input tuple<FCore.Cache,FCore.Graph> inTpl; | ||
| 6921 | output DAE.Type oty = ty; | ||
| 6922 | output tuple<FCore.Cache,FCore.Graph> outTpl; | ||
| 6923 | algorithm | ||
| 6924 | (oty,outTpl) := matchcontinue (oty,inTpl) | ||
| 6925 | local | ||
| 6926 | tuple<FCore.Cache,FCore.Graph> tpl; | ||
| 6927 | DAE.Dimensions dims; | ||
| 6928 | case (DAE.T_ARRAY(),tpl) | ||
| 6929 | algorithm | ||
| 6930 | 16571 | (dims,tpl) := List.mapFold(oty.dims,elabCallArgsEvaluateArrayLength3,tpl); | |
| 6931 | 16571 | oty.dims := dims; | |
| 6932 | 16571 | then (oty,tpl); | |
| 6933 | 90748 | else (oty,inTpl); | |
| 6934 | end matchcontinue; | ||
| 6935 | end elabCallArgsEvaluateArrayLength2; | ||
| 6936 | |||
| 6937 | protected function elabCallArgsEvaluateArrayLength3 | ||
| 6938 | input DAE.Dimension inDim; | ||
| 6939 | input tuple<FCore.Cache,FCore.Graph> inTpl; | ||
| 6940 | output DAE.Dimension outDim; | ||
| 6941 | output tuple<FCore.Cache,FCore.Graph> outTpl; | ||
| 6942 | algorithm | ||
| 6943 | (outDim,outTpl) := matchcontinue (inDim,inTpl) | ||
| 6944 | local | ||
| 6945 | Integer i; | ||
| 6946 | DAE.Exp exp; | ||
| 6947 | FCore.Cache cache; | ||
| 6948 | FCore.Graph env; | ||
| 6949 | case (DAE.DIM_EXP(exp),(cache,env)) | ||
| 6950 | algorithm | ||
| 6951 |
0/2✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
3 | (cache,Values.INTEGER(i)) := Ceval.ceval(cache,env,exp,false,Absyn.NO_MSG(),0); |
| 6952 | ✗ | then (DAE.DIM_INTEGER(i),(cache,env)); | |
| 6953 | else (inDim,inTpl); | ||
| 6954 | end matchcontinue; | ||
| 6955 | end elabCallArgsEvaluateArrayLength3; | ||
| 6956 | |||
| 6957 | protected function createInputVariableReplacements | ||
| 6958 | "@author: adrpo | ||
| 6959 | This function will add the binding expressions for inputs | ||
| 6960 | to the variable replacement structure. This is needed to | ||
| 6961 | be able to replace input variables in default values. | ||
| 6962 | Example: ... " | ||
| 6963 | input list<Slot> inSlotLst; | ||
| 6964 | input VarTransform.VariableReplacements inVarsRepl; | ||
| 6965 | output VarTransform.VariableReplacements outVarsRepl; | ||
| 6966 | algorithm | ||
| 6967 | outVarsRepl := matchcontinue inSlotLst | ||
| 6968 | local | ||
| 6969 | VarTransform.VariableReplacements o; | ||
| 6970 | String id; | ||
| 6971 | DAE.Exp e; | ||
| 6972 | list<Slot> rest; | ||
| 6973 | |||
| 6974 | // handle empty | ||
| 6975 | case {} then inVarsRepl; | ||
| 6976 | |||
| 6977 | // only interested in filled slots that have a optional expression | ||
| 6978 | case SLOT(defaultArg = DAE.FUNCARG(name=id), slotFilled = true, arg = SOME(e)) :: rest | ||
| 6979 | algorithm | ||
| 6980 | ✗ | o := VarTransform.addReplacement(inVarsRepl, ComponentReferenceBasics.makeCrefIdent(id, DAE.T_UNKNOWN_DEFAULT, {}), e); | |
| 6981 | ✗ | then | |
| 6982 | createInputVariableReplacements(rest, o); | ||
| 6983 | |||
| 6984 | // try the next. | ||
| 6985 | ✗ | else createInputVariableReplacements(listRest(inSlotLst), inVarsRepl); | |
| 6986 | end matchcontinue; | ||
| 6987 | end createInputVariableReplacements; | ||
| 6988 | |||
| 6989 | protected function elabCallArgs2 " | ||
| 6990 | function: elabCallArgs | ||
| 6991 | Given the name of a function and two lists of expression and | ||
| 6992 | NamedArg respectively to be used | ||
| 6993 | as actual arguments in a function call to that function, this | ||
| 6994 | function finds the function definition and matches the actual | ||
| 6995 | arguments to the formal parameters." | ||
| 6996 | input FCore.Cache inCache; | ||
| 6997 | input FCore.Graph inEnv; | ||
| 6998 | input Absyn.Path inPath; | ||
| 6999 | input list<Absyn.Exp> inAbsynExpLst; | ||
| 7000 | input list<Absyn.NamedArg> inAbsynNamedArgLst; | ||
| 7001 | input list<Absyn.Path> typeVars; | ||
| 7002 | input Boolean inBoolean; | ||
| 7003 | input Mutable<Boolean> stopElab; | ||
| 7004 | input DAE.Prefix inPrefix; | ||
| 7005 | input SourceInfo info; | ||
| 7006 | input Integer numErrors; | ||
| 7007 | output FCore.Cache outCache; | ||
| 7008 | output Option<tuple<DAE.Exp,DAE.Properties>> expProps; | ||
| 7009 | algorithm | ||
| 7010 | (outCache,expProps) := | ||
| 7011 | matchcontinue (inCache,inEnv,inPath,inAbsynExpLst,inAbsynNamedArgLst,inBoolean,inPrefix) | ||
| 7012 | local | ||
| 7013 | DAE.Type t,outtype,functype,tp1; | ||
| 7014 | list<DAE.FuncArg> fargs; | ||
| 7015 | FCore.Graph env_1,env_2,env,recordEnv; | ||
| 7016 | list<Slot> slots,newslots,newslots2; | ||
| 7017 | list<DAE.Exp> args_1,args_2; | ||
| 7018 | list<DAE.Const> constlist, constInputArgs; | ||
| 7019 | DAE.Const const; | ||
| 7020 | DAE.TupleConst tyconst; | ||
| 7021 | DAE.Properties prop,prop_1; | ||
| 7022 | SCode.Element cl,recordCl; | ||
| 7023 | Absyn.Path fn,fn_1,path; | ||
| 7024 | list<Absyn.Exp> args; | ||
| 7025 | list<Absyn.NamedArg> nargs; | ||
| 7026 | Boolean impl; | ||
| 7027 | list<DAE.Type> typelist; | ||
| 7028 | DAE.Dimensions vect_dims; | ||
| 7029 | DAE.Exp call_exp,callExp,daeexp; | ||
| 7030 | list<String> t_lst,names; | ||
| 7031 | String fn_str,types_str,scope,pre_str; | ||
| 7032 | String s,name,argStr; | ||
| 7033 | FCore.Cache cache; | ||
| 7034 | DAE.Type tp; | ||
| 7035 | DAE.Prefix pre; | ||
| 7036 | SCode.Restriction re; | ||
| 7037 | list<Absyn.Path> operNames; | ||
| 7038 | Absyn.ComponentRef cref; | ||
| 7039 | DAE.ComponentRef daecref; | ||
| 7040 | DAE.Function func; | ||
| 7041 | |||
| 7042 | /* Record constructors that might have come from Graphical expressions with unknown array sizes */ | ||
| 7043 | /* | ||
| 7044 | * adrpo: HACK! HACK! TODO! remove this case if records with unknown sizes can be instantiated | ||
| 7045 | * this could be also fixed by transforming the function call arguments into modifications and | ||
| 7046 | * send the modifications as an option in Lookup.lookup* functions! | ||
| 7047 | */ | ||
| 7048 | case (cache,env,fn,args,nargs,impl,pre) | ||
| 7049 | algorithm | ||
| 7050 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 26 times.
|
79531 | (cache,cl as SCode.CLASS(restriction = SCode.R_PACKAGE()),_) := |
| 7051 | Lookup.lookupClassIdent(cache, env, "GraphicalAnnotationsProgram____"); | ||
| 7052 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
|
26 | (cache,cl as SCode.CLASS( restriction = SCode.R_RECORD(_)),env_1) := Lookup.lookupClass(cache, env, fn); |
| 7053 | 13 | (cache,cl,env_2) := Lookup.lookupRecordConstructorClass(cache, env_1 /* env */, fn); | |
| 7054 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
|
13 | (_,_::names) := SCodeUtil.getClassComponents(cl); // remove the first one as it is the result! |
| 7055 | /* | ||
| 7056 | (cache,(t as (DAE.T_FUNCTION(fargs,(outtype as (DAE.T_COMPLEX(complexClassType as ClassInf.RECORD(name),_,_,_),_))),_)),env_1) | ||
| 7057 | = Lookup.lookupType(cache, env, fn, SOME(info)); | ||
| 7058 | */ | ||
| 7059 | 13 | fargs := List.map(names, createDummyFarg); | |
| 7060 | 13 | slots := makeEmptySlots(fargs); | |
| 7061 | 13 | (cache,_,newslots,_,_) := elabInputArgs(cache, env, args, nargs, slots, true, false /*checkTypes*/ ,impl, pre,info,DAE.T_UNKNOWN_DEFAULT,fn,true); | |
| 7062 | 13 | (cache,newslots2,_,_) := fillGraphicsDefaultSlots(cache, newslots, cl, env_2, impl, pre, info); | |
| 7063 | 13 | args_2 := slotListArgs(newslots2); | |
| 7064 | |||
| 7065 | 13 | tp := complexTypeFromSlots(newslots2,ClassInf.UNKNOWN(Absyn.IDENT(""))); | |
| 7066 | 13 | then | |
| 7067 | (cache,SOME((DAE.CALL(fn,args_2,DAE.CALL_ATTR(tp,false,false,false,false,DAE.NO_INLINE(),DAE.NO_TAIL(),DAE.NoReturn.RETURNS)),DAE.PROP(DAE.T_UNKNOWN_DEFAULT,DAE.C_CONST())))); | ||
| 7068 | |||
| 7069 | // Record constructors, user defined or implicit, try the hard stuff first | ||
| 7070 | case (cache,env,fn,args,nargs,impl,pre) | ||
| 7071 | algorithm | ||
| 7072 | // For unrolling errors if an overloaded 'constructor' matches later. | ||
| 7073 | 79518 | ErrorExt.setCheckpoint("RecordConstructor"); | |
| 7074 | |||
| 7075 | 79518 | (cache,func) := InstFunction.getRecordConstructorFunction(cache,env,fn); | |
| 7076 | |||
| 7077 |
2/2✓ Branch 0 taken 22757 times.
✓ Branch 1 taken 482 times.
|
23239 | DAE.RECORD_CONSTRUCTOR(path,tp1,_) := func; |
| 7078 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 482 times.
|
482 | DAE.T_FUNCTION(fargs, outtype, _, path) := tp1; |
| 7079 | |||
| 7080 | |||
| 7081 | 482 | slots := makeEmptySlots(fargs); | |
| 7082 | 482 | (cache,_,newslots,constInputArgs,_) := elabInputArgs(cache,env, args, nargs, slots,true,true,impl,pre,info,tp1,path); | |
| 7083 | |||
| 7084 | 482 | (args_2, newslots2) := addDefaultArgs(newslots, info); | |
| 7085 | 403 | vect_dims := slotsVectorizable(newslots2, info); | |
| 7086 | |||
| 7087 | 403 | constlist := constInputArgs; | |
| 7088 | 403 | const := List.fold(constlist, Types.constAnd, DAE.C_CONST()); | |
| 7089 | |||
| 7090 | 403 | tyconst := elabConsts(outtype, const); | |
| 7091 | 403 | prop := getProperties(outtype, tyconst); | |
| 7092 | |||
| 7093 | 403 | callExp := DAE.CALL(path,args_2,DAE.CALL_ATTR(outtype,false,false,false,false,DAE.NO_INLINE(),DAE.NO_TAIL(),DAE.NoReturn.RETURNS)); | |
| 7094 | |||
| 7095 | 403 | (call_exp,prop_1) := vectorizeCall(callExp, vect_dims, newslots2, prop, info); | |
| 7096 | 403 | expProps := SOME((call_exp,prop_1)); | |
| 7097 | |||
| 7098 | 403 | Mutable.update(stopElab,true); | |
| 7099 | 403 | ErrorExt.rollBack("RecordConstructor"); | |
| 7100 | |||
| 7101 | 403 | then | |
| 7102 | (cache,expProps); | ||
| 7103 | |||
| 7104 | /* If the default constructor failed and we have an operator record | ||
| 7105 | look for overloaded Record constructors (operators), user defined. | ||
| 7106 | mahge:TODO move this to a function and call it from above. | ||
| 7107 | avoids uneccesary lookup since we already have a record.*/ | ||
| 7108 | case (cache,env,fn,args,nargs,impl,pre) | ||
| 7109 | algorithm | ||
| 7110 | |||
| 7111 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 79115 times.
|
154361 | false := Mutable.access(stopElab); |
| 7112 | |||
| 7113 | 79115 | (cache,recordCl,recordEnv) := Lookup.lookupClass(cache,env,fn); | |
| 7114 |
2/2✓ Branch 1 taken 75246 times.
✓ Branch 2 taken 79 times.
|
75325 | true := SCodeUtil.isOperatorRecord(recordCl); |
| 7115 | |||
| 7116 | 79 | fn_1 := AbsynUtil.joinPaths(fn,Absyn.IDENT("'constructor'")); | |
| 7117 | 79 | (cache,recordCl,recordEnv) := Lookup.lookupClass(cache,recordEnv,fn_1); | |
| 7118 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 79 times.
|
79 | true := SCodeUtil.isOperator(recordCl); |
| 7119 | |||
| 7120 | 79 | operNames := AbsynToSCode.getListofQualOperatorFuncsfromOperator(recordCl); | |
| 7121 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 79 times.
|
79 | (cache,typelist as _::_) := Lookup.lookupFunctionsListInEnv(cache, recordEnv, operNames, info, {}); |
| 7122 | |||
| 7123 | 79 | Mutable.update(stopElab,true); | |
| 7124 | 79 | (cache,expProps) := elabCallArgs3(cache,env,typelist,fn_1,args,nargs,typeVars,impl,pre,info); | |
| 7125 | |||
| 7126 | 79 | ErrorExt.rollBack("RecordConstructor"); | |
| 7127 | |||
| 7128 | 79 | then | |
| 7129 | (cache,expProps); | ||
| 7130 | |||
| 7131 | /* ------ */ | ||
| 7132 | case (cache,env,fn,args,nargs,impl,pre) /* Metamodelica extension, added by simbj */ | ||
| 7133 | algorithm | ||
| 7134 | |||
| 7135 | 79036 | ErrorExt.delCheckpoint("RecordConstructor"); | |
| 7136 | |||
| 7137 |
2/2✓ Branch 1 taken 46562 times.
✓ Branch 2 taken 32474 times.
|
90460 | true := Config.acceptMetaModelicaGrammar(); |
| 7138 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 32474 times.
|
32474 | false := Mutable.access(stopElab); |
| 7139 |
2/2✓ Branch 1 taken 11424 times.
✓ Branch 2 taken 20762 times.
|
32474 | (cache,t as DAE.T_METARECORD(),_) := Lookup.lookupType(cache, env, fn, NONE()); |
| 7140 | 20762 | Mutable.update(stopElab,true); | |
| 7141 | 20762 | (cache,expProps) := elabCallArgsMetarecord(cache,env,t,args,nargs,impl,stopElab,pre,info); | |
| 7142 | then | ||
| 7143 | (cache,expProps); | ||
| 7144 | |||
| 7145 | /* ..Other functions */ | ||
| 7146 | case (cache,env,fn,args,nargs,impl,pre) | ||
| 7147 | algorithm | ||
| 7148 | |||
| 7149 | 58274 | ErrorExt.setCheckpoint("elabCallArgs2FunctionLookup"); | |
| 7150 | |||
| 7151 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 58274 times.
|
60731 | false := Mutable.access(stopElab); |
| 7152 |
2/2✓ Branch 1 taken 2457 times.
✓ Branch 2 taken 55817 times.
|
58274 | (cache,typelist as _::_) := Lookup.lookupFunctionsInEnv(cache, env, fn, info) |
| 7153 | "PR. A function can have several types. Taking an array with | ||
| 7154 | different dimensions as parameter for example. Because of this we | ||
| 7155 | cannot just lookup the function name and trust that it | ||
| 7156 | returns the correct function. It returns just one | ||
| 7157 | functiontype of several possibilites. The solution is to send | ||
| 7158 | in the function type of the user function and check both the | ||
| 7159 | function name and the function\'s type." ; | ||
| 7160 | 55817 | Mutable.update(stopElab,true); | |
| 7161 | 55817 | (cache,expProps) := elabCallArgs3(cache,env,typelist,fn,args,nargs,typeVars,impl,pre,info); | |
| 7162 | |||
| 7163 | 55633 | ErrorExt.delCheckpoint("elabCallArgs2FunctionLookup"); | |
| 7164 | |||
| 7165 | 55633 | then | |
| 7166 | (cache,expProps); | ||
| 7167 | |||
| 7168 | case (cache,env,fn,args,nargs,impl,pre) /* no matching type found, with -one- candidate */ | ||
| 7169 | algorithm | ||
| 7170 |
4/4✓ Branch 1 taken 2457 times.
✓ Branch 2 taken 184 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 181 times.
|
2641 | (cache,typelist as {tp1}) := Lookup.lookupFunctionsInEnv(cache, env, fn, info); |
| 7171 | 181 | (cache,args_1,_,_,functype,_,_) := | |
| 7172 | elabTypes(cache, env, args, nargs, {}, typelist, true, false/* Do not check types*/,impl,pre,info); | ||
| 7173 | 37 | argStr := ExpressionDump.printExpListStr(args_1); | |
| 7174 | 37 | pre_str := PrefixUtil.printPrefixStr3(pre); | |
| 7175 | 37 | fn_str := AbsynUtil.pathString(fn) + "(" + argStr + ")\nof type\n " + TypesDump.unparseType(functype); | |
| 7176 | 37 | types_str := "\n " + TypesDump.unparseType(tp1); | |
| 7177 | 37 | Error.assertionOrAddSourceMessage(Error.getNumErrorMessages()<>numErrors,Error.NO_MATCHING_FUNCTION_FOUND, {fn_str,pre_str,types_str}, info); | |
| 7178 | |||
| 7179 | 37 | ErrorExt.delCheckpoint("elabCallArgs2FunctionLookup"); | |
| 7180 | 37 | then | |
| 7181 | (cache,NONE()); | ||
| 7182 | |||
| 7183 | case (cache,env,fn,_,_,_,_) /* class found; not function */ | ||
| 7184 | algorithm | ||
| 7185 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1328 times.
|
3910 | (cache,SCode.CLASS(restriction = re),_) := Lookup.lookupClass(cache,env,fn); |
| 7186 |
2/2✓ Branch 1 taken 1306 times.
✓ Branch 2 taken 22 times.
|
1328 | false := SCodeUtil.isFunctionRestriction(re); |
| 7187 | 22 | fn_str := AbsynUtil.pathString(fn); | |
| 7188 | 22 | s := SCodeDump.restrString(re); | |
| 7189 | 22 | Error.addSourceMessage(Error.LOOKUP_FUNCTION_GOT_CLASS, {fn_str,s}, info); | |
| 7190 | |||
| 7191 | 22 | ErrorExt.delCheckpoint("elabCallArgs2FunctionLookup"); | |
| 7192 | 22 | then | |
| 7193 | (cache,NONE()); | ||
| 7194 | |||
| 7195 | case (cache,env,fn,_,_,_,pre) /* no matching type found, with candidates */ | ||
| 7196 | algorithm | ||
| 7197 |
4/4✓ Branch 1 taken 2435 times.
✓ Branch 2 taken 147 times.
✓ Branch 3 taken 144 times.
✓ Branch 4 taken 3 times.
|
2582 | (cache,typelist as _::_::_) := Lookup.lookupFunctionsInEnv(cache,env, fn, info); |
| 7198 | 3 | t_lst := List.map(typelist, TypesDump.unparseType); | |
| 7199 | 3 | fn_str := AbsynUtil.pathString(fn); | |
| 7200 | 3 | pre_str := PrefixUtil.printPrefixStr3(pre); | |
| 7201 | 3 | types_str := stringDelimitList(t_lst, "\n -"); | |
| 7202 | //fn_str = fn_str + " in component " + pre_str; | ||
| 7203 | 3 | Error.addSourceMessage(Error.NO_MATCHING_FUNCTION_FOUND, {fn_str,pre_str,types_str}, info); | |
| 7204 | |||
| 7205 | 3 | ErrorExt.delCheckpoint("elabCallArgs2FunctionLookup"); | |
| 7206 | 3 | then | |
| 7207 | (cache,NONE()); | ||
| 7208 | |||
| 7209 | // In Optimica there is an odd syntax like for eg., x(finalTime) + y(finalTime); where both x and y are normal variables | ||
| 7210 | // not functions. So it is not really a call Exp but the compiler treats it as if it is up until this point. | ||
| 7211 | // This is a kind of trick to handle that. | ||
| 7212 | case (cache,env,fn,{Absyn.CREF(Absyn.CREF_IDENT(name,_))},_,impl,pre) | ||
| 7213 | guard Config.acceptOptimicaGrammar() | ||
| 7214 | algorithm | ||
| 7215 | 21 | cref := AbsynUtil.pathToCref(fn); | |
| 7216 | |||
| 7217 |
2/6✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 21 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
21 | (cache,SOME((daeexp as DAE.CREF(daecref,tp),prop,_))) := elabCref(cache,env, cref, impl,true,pre,info); |
| 7218 | ✗ | ErrorExt.rollBack("elabCallArgs2FunctionLookup"); | |
| 7219 | |||
| 7220 | ✗ | daeexp := DAE.CREF(DAE.OPTIMICA_ATTR_INST_CREF(daecref,name), tp); | |
| 7221 | ✗ | expProps := SOME((daeexp,prop)); | |
| 7222 | ✗ | then | |
| 7223 | (cache,expProps); | ||
| 7224 | |||
| 7225 | case (cache,env,fn,_,_,_,_) | ||
| 7226 | algorithm | ||
| 7227 |
2/2✓ Branch 0 taken 2579 times.
✓ Branch 1 taken 2574 times.
|
5153 | failure(Lookup.lookupType(cache,env, fn, NONE())) "msg" ; |
| 7228 | 2574 | scope := FGraph.printGraphPathStr(env) + " (looking for a function or record)"; | |
| 7229 | 2574 | fn_str := AbsynUtil.pathString(fn); | |
| 7230 | 2574 | Error.addSourceMessage(Error.LOOKUP_ERROR, {fn_str,scope}, info); // No need to add prefix because only depends on scope? | |
| 7231 | |||
| 7232 | 2574 | ErrorExt.delCheckpoint("elabCallArgs2FunctionLookup"); | |
| 7233 | 2574 | then | |
| 7234 | (cache,NONE()); | ||
| 7235 | |||
| 7236 | case (cache,env,fn,_,_,_,pre) /* no matching type found, no candidates. */ | ||
| 7237 | algorithm | ||
| 7238 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | (cache,{}) := Lookup.lookupFunctionsInEnv(cache,env,fn,info); |
| 7239 | ✗ | fn_str := AbsynUtil.pathString(fn); | |
| 7240 | ✗ | pre_str := PrefixUtil.printPrefixStr3(pre); | |
| 7241 | ✗ | fn_str := fn_str + " in component " + pre_str; | |
| 7242 | ✗ | Error.addSourceMessage(Error.NO_MATCHING_FUNCTION_FOUND_NO_CANDIDATE, {fn_str}, info); | |
| 7243 | |||
| 7244 | ✗ | ErrorExt.delCheckpoint("elabCallArgs2FunctionLookup"); | |
| 7245 | ✗ | then | |
| 7246 | (cache,NONE()); | ||
| 7247 | |||
| 7248 | case (_,env,fn,_,_,_,_) | ||
| 7249 | algorithm | ||
| 7250 | 5 | ErrorExt.delCheckpoint("elabCallArgs2FunctionLookup"); | |
| 7251 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
5 | true := Flags.isSet(Flags.FAILTRACE); |
| 7252 | ✗ | Debug.traceln("- Static.elabCallArgs failed on: " + AbsynUtil.pathString(fn) + " in env: " + FGraph.printGraphPathStr(env)); | |
| 7253 | ✗ | then | |
| 7254 | fail(); | ||
| 7255 | end matchcontinue; | ||
| 7256 | end elabCallArgs2; | ||
| 7257 | |||
| 7258 | public function elabCallArgs3 | ||
| 7259 | "Elaborates the input given a set of viable function candidates, and vectorizes the arguments+performs type checking" | ||
| 7260 | input FCore.Cache inCache; | ||
| 7261 | input FCore.Graph inEnv; | ||
| 7262 | input list<DAE.Type> typelist; | ||
| 7263 | input Absyn.Path fn; | ||
| 7264 | input list<Absyn.Exp> args; | ||
| 7265 | input list<Absyn.NamedArg> nargs; | ||
| 7266 | input list<Absyn.Path> typeVars; | ||
| 7267 | input Boolean impl; | ||
| 7268 | input DAE.Prefix pre; | ||
| 7269 | input SourceInfo info; | ||
| 7270 | output FCore.Cache outCache; | ||
| 7271 | output Option<tuple<DAE.Exp,DAE.Properties>> expProps; | ||
| 7272 | protected | ||
| 7273 | DAE.Exp callExp,call_exp; | ||
| 7274 | list<DAE.Exp> args_1,args_2; | ||
| 7275 | list<DAE.Const> constlist; | ||
| 7276 | DAE.Const const; | ||
| 7277 | DAE.Type restype,functype; | ||
| 7278 | DAE.FunctionBuiltin isBuiltin; | ||
| 7279 | DAE.FunctionParallelism funcParal; | ||
| 7280 | Boolean tuple_,builtin,isImpure; | ||
| 7281 | DAE.NoReturn noReturn; | ||
| 7282 | DAE.InlineType inlineType; | ||
| 7283 | Absyn.Path fn_1; | ||
| 7284 | DAE.Properties prop,prop_1; | ||
| 7285 | DAE.Type tp; | ||
| 7286 | DAE.TupleConst tyconst; | ||
| 7287 | DAE.Dimensions vect_dims; | ||
| 7288 | list<Slot> slots,slots2; | ||
| 7289 | AvlTreePathFunction.Tree functionTree; | ||
| 7290 | Util.Status status; | ||
| 7291 | FCore.Cache cache; | ||
| 7292 | Boolean didInline; | ||
| 7293 | Boolean onlyOneFunction,isFunctionPointer; | ||
| 7294 | DAE.Purity purity; | ||
| 7295 | algorithm | ||
| 7296 | 56070 | onlyOneFunction := listLength(typelist) == 1; | |
| 7297 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 55889 times.
|
56070 | (cache, |
| 7298 | args_1, | ||
| 7299 | constlist, | ||
| 7300 | restype, | ||
| 7301 | functype as DAE.T_FUNCTION(functionAttributes=DAE.FUNCTION_ATTRIBUTES(purity=purity, | ||
| 7302 | inline=inlineType, | ||
| 7303 | isFunctionPointer=isFunctionPointer, | ||
| 7304 | functionParallelism=funcParal, | ||
| 7305 | noReturn=noReturn)), | ||
| 7306 | vect_dims, | ||
| 7307 | slots) := elabTypes(inCache, inEnv, args, nargs, typeVars, typelist, onlyOneFunction, true/* Check types*/, impl,pre,info) | ||
| 7308 | "The constness of a function depends on the inputs. If all inputs are constant the call itself is constant."; | ||
| 7309 | |||
| 7310 | 55889 | isImpure := purity == DAE.Purity.IMPURE; | |
| 7311 | 55889 | (fn_1,functype) := deoverloadFuncname(fn, functype, inEnv); | |
| 7312 | 55889 | tuple_ := Types.isTuple(restype); | |
| 7313 | 55889 | (isBuiltin,builtin,fn_1) := isBuiltinFunc(fn_1,functype); | |
| 7314 | 55889 | inlineType := inlineBuiltin(isBuiltin,inlineType); | |
| 7315 | //check the env to see if a call to a parallel or kernel function is a valid one. | ||
| 7316 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 55889 times.
|
55889 | true := isValidWRTParallelScope(fn,builtin,funcParal,inEnv,info); |
| 7317 | |||
| 7318 | 55889 | const := List.fold(constlist, Types.constAnd, DAE.C_CONST()); | |
| 7319 |
6/6✓ Branch 1 taken 10666 times.
✓ Branch 2 taken 45223 times.
✓ Branch 3 taken 1823 times.
✓ Branch 4 taken 8843 times.
✓ Branch 5 taken 46870 times.
✓ Branch 6 taken 176 times.
|
55889 | const := if (Flags.isSet(Flags.RML) and not builtin) or purity == DAE.Purity.OM_IMPURE then DAE.C_VAR() else const "in RML no function needs to be ceval'ed; this speeds up compilation significantly when bootstrapping"; |
| 7320 | 55889 | (cache,const) := determineConstSpecialFunc(cache,inEnv,const,fn_1); | |
| 7321 | 55889 | tyconst := elabConsts(restype, const); | |
| 7322 | 55889 | prop := getProperties(restype, tyconst); | |
| 7323 | 55889 | tp := Types.simplifyType(restype); | |
| 7324 | // adrpo: 2011-09-30 NOTE THAT THIS WILL NOT ADD DEFAULT ARGS | ||
| 7325 | // FROM extends (THE BASE CLASS) | ||
| 7326 | 55889 | (args_2, slots2) := addDefaultArgs(slots, info); | |
| 7327 | // DO NOT CHECK IF ALL SLOTS ARE FILLED! | ||
| 7328 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 55885 times.
|
55885 | true := List.fold(slots2, slotAnd, true); |
| 7329 |
8/8✓ Branch 0 taken 55705 times.
✓ Branch 1 taken 180 times.
✓ Branch 2 taken 46382 times.
✓ Branch 3 taken 9503 times.
✓ Branch 4 taken 26796 times.
✓ Branch 5 taken 29089 times.
✓ Branch 6 taken 54319 times.
✓ Branch 7 taken 1566 times.
|
239087 | callExp := DAE.CALL(fn_1,args_2,DAE.CALL_ATTR(tp,tuple_,builtin,isImpure or purity == DAE.Purity.OM_IMPURE,isFunctionPointer,inlineType,DAE.NO_TAIL(),noReturn)); |
| 7330 | // ExpressionDump.dumpExpWithTitle("function elabCallArgs3: ", callExp); | ||
| 7331 | |||
| 7332 | // create a replacement for input variables -> their binding | ||
| 7333 | //inputVarsRepl = createInputVariableReplacements(slots2, VarTransform.emptyReplacements()); | ||
| 7334 | //print("Repls: " + VarTransform.dumpReplacementsStr(inputVarsRepl) + "\n"); | ||
| 7335 | // replace references to inputs in the arguments | ||
| 7336 | //callExp = VarTransform.replaceExp(callExp, inputVarsRepl, NONE()); | ||
| 7337 | |||
| 7338 | //debugPrintString = if_(Util.isEqual(DAE.NORM_INLINE,inline)," Inline: " + AbsynUtil.pathString(fn_1) + "\n", "");print(debugPrintString); | ||
| 7339 | 55885 | (call_exp,prop_1) := vectorizeCall(callExp, vect_dims, slots2, prop, info); | |
| 7340 | // print("3 Prefix: " + PrefixUtil.printPrefixStr(pre) + " path: " + AbsynUtil.pathString(fn_1) + "\n"); | ||
| 7341 | // Instantiate the function and add to dae function tree | ||
| 7342 |
2/2✓ Branch 1 taken 55583 times.
✓ Branch 2 taken 302 times.
|
55885 | (cache,status) := instantiateDaeFunction(cache,inEnv, |
| 7343 | if Lookup.isFunctionCallViaComponent(cache, inEnv, fn) then fn else fn_1, // don't use the fully qualified name for calling component functions | ||
| 7344 | builtin,NONE(),true); | ||
| 7345 | // Instantiate any implicit record constructors needed and add them to the dae function tree | ||
| 7346 | 55885 | cache := instantiateImplicitRecordConstructors(cache, inEnv, args_1); | |
| 7347 | 55885 | functionTree := FCore.getFunctionTree(cache); | |
| 7348 | 55885 | (call_exp,_,didInline,_) := Inline.inlineExp(call_exp,(SOME(functionTree),{DAE.BUILTIN_EARLY_INLINE(),DAE.EARLY_INLINE()}),DAE.emptyElementSource); | |
| 7349 | 55885 | (call_exp,_) := ExpressionSimplify.condsimplify(didInline,call_exp); | |
| 7350 |
4/4✓ Branch 0 taken 656 times.
✓ Branch 1 taken 55229 times.
✓ Branch 3 taken 370 times.
✓ Branch 4 taken 286 times.
|
55885 | didInline := didInline and (not Config.acceptMetaModelicaGrammar() /* Some weird errors when inlining. Becomes boxed even if it shouldn't... */); |
| 7351 |
2/2✓ Branch 0 taken 286 times.
✓ Branch 1 taken 55599 times.
|
55885 | prop_1 := if didInline then Types.setPropType(prop_1, restype) else prop_1; |
| 7352 |
2/2✓ Branch 0 taken 46558 times.
✓ Branch 1 taken 9327 times.
|
55885 | if not isImpure then |
| 7353 | 46558 | (cache, call_exp, prop_1) := Ceval.cevalIfConstant(cache, inEnv, call_exp, prop_1, impl, info); | |
| 7354 | end if; | ||
| 7355 |
2/2✓ Branch 1 taken 55866 times.
✓ Branch 2 taken 19 times.
|
55885 | expProps := if Util.isSuccess(status) then SOME((call_exp,prop_1)) else NONE(); |
| 7356 | outCache := cache; | ||
| 7357 | end elabCallArgs3; | ||
| 7358 | |||
| 7359 | public function inlineBuiltin | ||
| 7360 | input DAE.FunctionBuiltin isBuiltin; | ||
| 7361 | input DAE.InlineType inlineType; | ||
| 7362 | output DAE.InlineType outInlineType; | ||
| 7363 | algorithm | ||
| 7364 | outInlineType := match isBuiltin | ||
| 7365 | case DAE.FUNCTION_BUILTIN_PTR() then DAE.BUILTIN_EARLY_INLINE(); | ||
| 7366 | else inlineType; | ||
| 7367 | end match; | ||
| 7368 | end inlineBuiltin; | ||
| 7369 | |||
| 7370 | protected function isValidWRTParallelScope | ||
| 7371 | input Absyn.Path inFn; | ||
| 7372 | input Boolean isBuiltin; | ||
| 7373 | input DAE.FunctionParallelism inFuncParallelism; | ||
| 7374 | input FCore.Graph inEnv; | ||
| 7375 | input SourceInfo inInfo; | ||
| 7376 | output Boolean isValid; | ||
| 7377 | algorithm | ||
| 7378 | 55889 | isValid := isValidWRTParallelScope_dispatch(inFn, isBuiltin, inFuncParallelism, FGraph.currentScope(inEnv), inInfo); | |
| 7379 | end isValidWRTParallelScope; | ||
| 7380 | |||
| 7381 | protected function isValidWRTParallelScope_dispatch | ||
| 7382 | input Absyn.Path inFn; | ||
| 7383 | input Boolean isBuiltin; | ||
| 7384 | input DAE.FunctionParallelism inFuncParallelism; | ||
| 7385 | input FCore.Scope inScope; | ||
| 7386 | input SourceInfo inInfo; | ||
| 7387 | output Boolean isValid; | ||
| 7388 | algorithm | ||
| 7389 | isValid := matchcontinue(isBuiltin, inFuncParallelism, inScope) | ||
| 7390 | local | ||
| 7391 | String scopeName, errorString; | ||
| 7392 | FCore.Scope restScope; | ||
| 7393 | FCore.Ref ref; | ||
| 7394 | |||
| 7395 | |||
| 7396 | // non-parallel builtin function call is OK everywhere. | ||
| 7397 | case(true, DAE.FP_NON_PARALLEL(), _) | ||
| 7398 | then true; | ||
| 7399 | |||
| 7400 | // If we have a function call in an implicit scope type, then go | ||
| 7401 | // up recursively to find the actuall scope and then check. | ||
| 7402 | // But parfor scope is a parallel type so is handled differently. | ||
| 7403 | case(_, _, ref::restScope) | ||
| 7404 | algorithm | ||
| 7405 |
2/2✓ Branch 1 taken 534 times.
✓ Branch 2 taken 42665 times.
|
43199 | false := FNode.isRefTop(ref); |
| 7406 | 42665 | scopeName := FNode.refName(ref); | |
| 7407 |
2/2✓ Branch 1 taken 26262 times.
✓ Branch 2 taken 16403 times.
|
42665 | true := listMember(scopeName, FCore.implicitScopeNames); |
| 7408 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 16403 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
16403 | false := stringEq(scopeName, FCore.parForScopeName); |
| 7409 | 16403 | then isValidWRTParallelScope_dispatch(inFn,isBuiltin,inFuncParallelism,restScope,inInfo); | |
| 7410 | |||
| 7411 | // This two are common cases so keep them at the top. | ||
| 7412 | // normal(non parallel) function call in a normal scope (function and class scopes) is OK. | ||
| 7413 | case(_, DAE.FP_NON_PARALLEL(), ref::_) | ||
| 7414 | algorithm | ||
| 7415 |
2/2✓ Branch 1 taken 16014 times.
✓ Branch 2 taken 10782 times.
|
26796 | true := FGraph.checkScopeType({ref}, SOME(FCore.CLASS_SCOPE())); |
| 7416 | then | ||
| 7417 | true; | ||
| 7418 | |||
| 7419 | case(_, DAE.FP_NON_PARALLEL(), ref::_) | ||
| 7420 | algorithm | ||
| 7421 |
2/2✓ Branch 1 taken 534 times.
✓ Branch 2 taken 15480 times.
|
16014 | true := FGraph.checkScopeType({ref}, SOME(FCore.FUNCTION_SCOPE())); |
| 7422 | then | ||
| 7423 | true; | ||
| 7424 | |||
| 7425 | // Normal function call in a prallel scope is error, if it is not a built-in function. | ||
| 7426 | case(_, DAE.FP_NON_PARALLEL(), ref::_) | ||
| 7427 | algorithm | ||
| 7428 |
1/2✓ Branch 1 taken 534 times.
✗ Branch 2 not taken.
|
534 | false := FNode.isRefTop(ref); |
| 7429 | ✗ | scopeName := FNode.refName(ref); | |
| 7430 | ✗ | true := FGraph.checkScopeType({ref}, SOME(FCore.PARALLEL_SCOPE())); | |
| 7431 | |||
| 7432 | ✗ | errorString := "\n" + | |
| 7433 | "- Non-Parallel function '" + AbsynUtil.pathString(inFn) + | ||
| 7434 | "' can not be called from a parallel scope." + "\n" + | ||
| 7435 | "- Here called from :" + scopeName + "\n" + | ||
| 7436 | "- Please declare the function as parallel function."; | ||
| 7437 | ✗ | Error.addSourceMessage(Error.PARMODELICA_ERROR, | |
| 7438 | {errorString}, inInfo); | ||
| 7439 | then | ||
| 7440 | false; | ||
| 7441 | |||
| 7442 | |||
| 7443 | // parallel function call in a parallel scope (kernel function, parallel function) is OK. | ||
| 7444 | // Except when it is calling itself, recurssion | ||
| 7445 | case(_, DAE.FP_PARALLEL_FUNCTION(), ref::_) | ||
| 7446 | algorithm | ||
| 7447 | ✗ | false := FNode.isRefTop(ref); | |
| 7448 | ✗ | scopeName := FNode.refName(ref); | |
| 7449 | ✗ | true := FGraph.checkScopeType({ref}, SOME(FCore.PARALLEL_SCOPE())); | |
| 7450 | // make sure the function is not calling itself | ||
| 7451 | // recurrsion is not allowed. | ||
| 7452 | ✗ | false := stringEqual(scopeName,AbsynUtil.pathString(inFn)); | |
| 7453 | then | ||
| 7454 | true; | ||
| 7455 | |||
| 7456 | // If the above case failed (parallel function recurssion) this will print the error message | ||
| 7457 | case(_, DAE.FP_PARALLEL_FUNCTION(), ref::_) | ||
| 7458 | algorithm | ||
| 7459 | ✗ | false := FNode.isRefTop(ref); | |
| 7460 | ✗ | scopeName := FNode.refName(ref); | |
| 7461 | ✗ | true := FGraph.checkScopeType({ref}, SOME(FCore.PARALLEL_SCOPE())); | |
| 7462 | |||
| 7463 | // make sure the function is not calling itself | ||
| 7464 | // recurrsion is not allowed. | ||
| 7465 | ✗ | true := stringEqual(scopeName,AbsynUtil.pathString(inFn)); | |
| 7466 | ✗ | errorString := "\n" + | |
| 7467 | "- Parallel function '" + AbsynUtil.pathString(inFn) + | ||
| 7468 | "' can not call itself. Recurrsion is not allowed for parallel functions currently." + "\n" + | ||
| 7469 | "- Parallel functions can only be called from: 'kernel' functions," + | ||
| 7470 | " OTHER 'parallel' functions (no recurrsion) or from a body of a" + | ||
| 7471 | " 'parfor' loop"; | ||
| 7472 | ✗ | Error.addSourceMessage(Error.PARMODELICA_ERROR, | |
| 7473 | {errorString}, inInfo); | ||
| 7474 | then | ||
| 7475 | false; | ||
| 7476 | |||
| 7477 | // parallel function call in a parfor scope is OK. | ||
| 7478 | case(_, DAE.FP_PARALLEL_FUNCTION(), ref::_) | ||
| 7479 | algorithm | ||
| 7480 | ✗ | false := FNode.isRefTop(ref); | |
| 7481 | ✗ | scopeName := FNode.refName(ref); | |
| 7482 | ✗ | true := stringEqual(scopeName, FCore.parForScopeName); | |
| 7483 | then | ||
| 7484 | true; | ||
| 7485 | |||
| 7486 | //parallel function call in non parallel scope types is error. | ||
| 7487 | case(_, DAE.FP_PARALLEL_FUNCTION(), ref::_) | ||
| 7488 | algorithm | ||
| 7489 | ✗ | false := FNode.isRefTop(ref); | |
| 7490 | ✗ | scopeName := FNode.refName(ref); | |
| 7491 | |||
| 7492 | ✗ | errorString := "\n" + | |
| 7493 | "- Parallel function '" + AbsynUtil.pathString(inFn) + | ||
| 7494 | "' can not be called from a non parallel scope '" + scopeName + "'.\n" + | ||
| 7495 | "- Parallel functions can only be called from: 'kernel' functions," + | ||
| 7496 | " other 'parallel' functions (no recurrsion) or from a body of a" + | ||
| 7497 | " 'parfor' loop"; | ||
| 7498 | ✗ | Error.addSourceMessage(Error.PARMODELICA_ERROR, | |
| 7499 | {errorString}, inInfo); | ||
| 7500 | then false; | ||
| 7501 | |||
| 7502 | // Kernel functions should not call themselves. | ||
| 7503 | case(_, DAE.FP_KERNEL_FUNCTION(), ref::_) | ||
| 7504 | algorithm | ||
| 7505 | ✗ | false := FNode.isRefTop(ref); | |
| 7506 | ✗ | scopeName := FNode.refName(ref); | |
| 7507 | |||
| 7508 | // make sure the function is not calling itself | ||
| 7509 | // recurrsion is not allowed. | ||
| 7510 | ✗ | true := stringEqual(scopeName,AbsynUtil.pathString(inFn)); | |
| 7511 | ✗ | errorString := "\n" + | |
| 7512 | "- Kernel function '" + AbsynUtil.pathString(inFn) + | ||
| 7513 | "' can not call itself. " + "\n" + | ||
| 7514 | "- Recurrsion is not allowed for Kernel functions. "; | ||
| 7515 | ✗ | Error.addSourceMessage(Error.PARMODELICA_ERROR, | |
| 7516 | {errorString}, inInfo); | ||
| 7517 | then | ||
| 7518 | false; | ||
| 7519 | |||
| 7520 | //kernel function call in a parallel scope (kernel function, parallel function) is Error. | ||
| 7521 | case(_, DAE.FP_KERNEL_FUNCTION(), ref::_) | ||
| 7522 | algorithm | ||
| 7523 | ✗ | false := FNode.isRefTop(ref); | |
| 7524 | ✗ | scopeName := FNode.refName(ref); | |
| 7525 | ✗ | true := FGraph.checkScopeType({ref}, SOME(FCore.PARALLEL_SCOPE())); | |
| 7526 | |||
| 7527 | ✗ | errorString := "\n" + | |
| 7528 | "- Kernel function '" + AbsynUtil.pathString(inFn) + | ||
| 7529 | "' can not be called from a parallel scope '" + scopeName + "'.\n" + | ||
| 7530 | "- Kernel functions CAN NOT be called from: 'kernel' functions," + | ||
| 7531 | " 'parallel' functions or from a body of a" + | ||
| 7532 | " 'parfor' loop"; | ||
| 7533 | ✗ | Error.addSourceMessage(Error.PARMODELICA_ERROR, | |
| 7534 | {errorString}, inInfo); | ||
| 7535 | then | ||
| 7536 | false; | ||
| 7537 | |||
| 7538 | //kernel function call in a parfor loop is Error too (similar to above). just different error message. | ||
| 7539 | case(_, DAE.FP_KERNEL_FUNCTION(), ref::_) | ||
| 7540 | algorithm | ||
| 7541 | ✗ | false := FNode.isRefTop(ref); | |
| 7542 | ✗ | scopeName := FNode.refName(ref); | |
| 7543 | |||
| 7544 | ✗ | true := stringEqual(scopeName, FCore.parForScopeName); | |
| 7545 | ✗ | errorString := "\n" + | |
| 7546 | "- Kernel function '" + AbsynUtil.pathString(inFn) + | ||
| 7547 | "' can not be called from inside parallel for (parfor) loop body." + "'.\n" + | ||
| 7548 | "- Kernel functions CAN NOT be called from: 'kernel' functions," + | ||
| 7549 | " 'parallel' functions or from a body of a" + | ||
| 7550 | " 'parfor' loop"; | ||
| 7551 | ✗ | Error.addSourceMessage(Error.PARMODELICA_ERROR, | |
| 7552 | {errorString}, inInfo); | ||
| 7553 | then false; | ||
| 7554 | |||
| 7555 | // Kernel function call in a non-parallel scope is OK. | ||
| 7556 | // Except when it is calling itself, recurssion | ||
| 7557 | case(_, DAE.FP_KERNEL_FUNCTION(), ref::_) | ||
| 7558 | algorithm | ||
| 7559 | ✗ | false := FNode.isRefTop(ref); | |
| 7560 | ✗ | scopeName := FNode.refName(ref); | |
| 7561 | // make sure the function is not calling itself | ||
| 7562 | // recurrsion is not allowed. | ||
| 7563 | ✗ | false := stringEqual(scopeName,AbsynUtil.pathString(inFn)); | |
| 7564 | then | ||
| 7565 | true; | ||
| 7566 | |||
| 7567 | else true; | ||
| 7568 | |||
| 7569 | /* | ||
| 7570 | //Normal (non parallel) function call in a normal function scope is OK. | ||
| 7571 | case(DAE.FP_NON_PARALLEL(), FCore.N(scopeType = FCore.FUNCTION_SCOPE())) then(); | ||
| 7572 | //Normal (non parallel) function call in a normal class scope is OK. | ||
| 7573 | case(DAE.FP_NON_PARALLEL(), FCore.N(scopeType = FCore.CLASS_SCOPE())) then(); | ||
| 7574 | //Normal (non parallel) function call in a normal function scope is OK. | ||
| 7575 | case(DAE.FP_NON_PARALLEL(), FCore.N(scopeType = FCore.FUNCTION_SCOPE())) then(); | ||
| 7576 | //Normal (non parallel) function call in a normal class scope is OK. | ||
| 7577 | case(DAE.FP_KERNEL_FUNCTION(), FCore.N(scopeType = FCore.CLASS_SCOPE())) then(); | ||
| 7578 | //Normal (non parallel) function call in a normal function scope is OK. | ||
| 7579 | case(DAE.FP_KERNEL_FUNCTION(), FCore.N(scopeType = FCore.FUNCTION_SCOPE())) then(); | ||
| 7580 | */ | ||
| 7581 | |||
| 7582 | end matchcontinue; | ||
| 7583 | end isValidWRTParallelScope_dispatch; | ||
| 7584 | |||
| 7585 | protected function elabCallArgsMetarecord | ||
| 7586 | input FCore.Cache inCache; | ||
| 7587 | input FCore.Graph inEnv; | ||
| 7588 | input DAE.Type inType; | ||
| 7589 | input list<Absyn.Exp> inPosArgs; | ||
| 7590 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 7591 | input Boolean inImplicit; | ||
| 7592 | input Mutable<Boolean> stopElab; | ||
| 7593 | input DAE.Prefix inPrefix; | ||
| 7594 | input SourceInfo inInfo; | ||
| 7595 | output FCore.Cache outCache; | ||
| 7596 | output Option<tuple<DAE.Exp,DAE.Properties>> expProps; | ||
| 7597 | algorithm | ||
| 7598 | (outCache, expProps) := matchcontinue ty as inType | ||
| 7599 | local | ||
| 7600 | Absyn.Path fq_path; | ||
| 7601 | String str, fn_str; | ||
| 7602 | list<String> field_names; | ||
| 7603 | list<DAE.Type> tys, typeVars; | ||
| 7604 | list<DAE.FuncArg> fargs; | ||
| 7605 | list<Slot> slots; | ||
| 7606 | list<DAE.Const> const_lst; | ||
| 7607 | DAE.Const const; | ||
| 7608 | DAE.TupleConst ty_const; | ||
| 7609 | DAE.Properties prop; | ||
| 7610 | list<DAE.Exp> args; | ||
| 7611 | InstTypes.PolymorphicBindings bindings; | ||
| 7612 | |||
| 7613 | case DAE.T_METARECORD(path=fq_path) | ||
| 7614 | algorithm | ||
| 7615 | 20762 | DAE.TYPES_VAR(name = str) := List.find(inType.fields, Types.varHasMetaRecordType); | |
| 7616 | ✗ | fn_str := AbsynUtil.pathString(fq_path); | |
| 7617 | ✗ | Error.addSourceMessage(Error.METARECORD_CONTAINS_METARECORD_MEMBER, | |
| 7618 | {fn_str, str}, inInfo); | ||
| 7619 | then | ||
| 7620 | (inCache, NONE()); | ||
| 7621 | |||
| 7622 | case DAE.T_METARECORD() | ||
| 7623 | algorithm | ||
| 7624 |
1/2✓ Branch 3 taken 20762 times.
✗ Branch 4 not taken.
|
20762 | false := listLength(inType.fields) == listLength(inPosArgs) + listLength(inNamedArgs); |
| 7625 | ✗ | fn_str := TypesDump.unparseType(inType); | |
| 7626 | ✗ | Error.addSourceMessage(Error.WRONG_NO_OF_ARGS, {fn_str}, inInfo); | |
| 7627 | then | ||
| 7628 | (inCache, NONE()); | ||
| 7629 | |||
| 7630 | case DAE.T_METARECORD(path = fq_path) | ||
| 7631 | algorithm | ||
| 7632 |
4/4✓ Branch 0 taken 38842 times.
✓ Branch 1 taken 20762 times.
✓ Branch 2 taken 38842 times.
✓ Branch 3 taken 20762 times.
|
59604 | field_names := list(TypesDump.getVarName(var) for var in inType.fields); |
| 7633 |
4/4✓ Branch 0 taken 38842 times.
✓ Branch 1 taken 20762 times.
✓ Branch 2 taken 38842 times.
✓ Branch 3 taken 20762 times.
|
59604 | tys := list(Types.getVarType(var) for var in inType.fields); |
| 7634 |
7/8✓ Branch 0 taken 38842 times.
✓ Branch 1 taken 20762 times.
✓ Branch 2 taken 38842 times.
✓ Branch 3 taken 20762 times.
✓ Branch 4 taken 38842 times.
✓ Branch 5 taken 20762 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 20762 times.
|
59604 | fargs := list(Types.makeDefaultFuncArg(n, t) threaded for n in field_names, t in tys); |
| 7635 | 20762 | slots := makeEmptySlots(fargs); | |
| 7636 | 20762 | (outCache, _, slots, const_lst, bindings) := elabInputArgs(inCache, inEnv, inPosArgs, | |
| 7637 | inNamedArgs, slots, true, true, inImplicit, | ||
| 7638 | inPrefix, inInfo, inType, inType.utPath); | ||
| 7639 | 20762 | const := List.fold(const_lst, Types.constAnd, DAE.C_CONST()); | |
| 7640 | 20762 | ty_const := elabConsts(inType, const); | |
| 7641 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 20762 times.
|
20762 | true := List.fold(slots, slotAnd, true); |
| 7642 | 20762 | args := slotListArgs(slots); | |
| 7643 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 20755 times.
|
20762 | if not listEmpty(bindings) then |
| 7644 | 7 | bindings := Types.solvePolymorphicBindings(bindings, inInfo, inType.path); | |
| 7645 |
4/4✓ Branch 0 taken 8 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 7 times.
|
15 | typeVars := list(Types.fixPolymorphicRestype(tv, bindings, inInfo) for tv in inType.typeVars); |
| 7646 | 7 | ty.typeVars := typeVars; | |
| 7647 | 7 | prop := getProperties(ty, ty_const); | |
| 7648 | else | ||
| 7649 | 20755 | prop := getProperties(ty, ty_const); | |
| 7650 | end if; | ||
| 7651 | 20762 | then | |
| 7652 | (outCache, SOME((DAE.METARECORDCALL(fq_path, args, field_names, inType.index, inType.typeVars), prop))); | ||
| 7653 | |||
| 7654 | // MetaRecord failure. | ||
| 7655 | case DAE.T_METARECORD(path = fq_path) | ||
| 7656 | algorithm | ||
| 7657 | ✗ | (outCache, _, prop) := elabExpInExpression(inCache, inEnv, | |
| 7658 | Absyn.TUPLE(inPosArgs), false, false, inPrefix, inInfo); | ||
| 7659 | ✗ | tys := list(Types.getVarType(var) for var in inType.fields); | |
| 7660 | ✗ | str := "Failed to match types:\n actual: " + | |
| 7661 | TypesDump.unparseType(Types.getPropType(prop)) + | ||
| 7662 | "\n expected: " + | ||
| 7663 | TypesDump.unparseType(DAE.T_TUPLE(tys, NONE())); | ||
| 7664 | ✗ | fn_str := AbsynUtil.pathString(fq_path); | |
| 7665 | ✗ | Error.addSourceMessage(Error.META_RECORD_FOUND_FAILURE, {fn_str, str}, inInfo); | |
| 7666 | then | ||
| 7667 | (outCache, NONE()); | ||
| 7668 | |||
| 7669 | // MetaRecord failure (args). | ||
| 7670 | case DAE.T_METARECORD(path = fq_path) | ||
| 7671 | algorithm | ||
| 7672 | ✗ | str := "Failed to elaborate arguments " + Dump.printExpStr(Absyn.TUPLE(inPosArgs)); | |
| 7673 | ✗ | fn_str := AbsynUtil.pathString(fq_path); | |
| 7674 | ✗ | Error.addSourceMessage(Error.META_RECORD_FOUND_FAILURE, {fn_str, str}, inInfo); | |
| 7675 | then | ||
| 7676 | (inCache, NONE()); | ||
| 7677 | |||
| 7678 | end matchcontinue; | ||
| 7679 | end elabCallArgsMetarecord; | ||
| 7680 | |||
| 7681 | protected uniontype ForceFunctionInst | ||
| 7682 | record FORCE_FUNCTION_INST "Used when blocking function instantiation to instantiate the function anyway" end FORCE_FUNCTION_INST; | ||
| 7683 | record NORMAL_FUNCTION_INST "Used when blocking function instantiation to instantiate the function anyway" end NORMAL_FUNCTION_INST; | ||
| 7684 | end ForceFunctionInst; | ||
| 7685 | |||
| 7686 | public function instantiateDaeFunction | ||
| 7687 | "Help function to elabCallArgs. Instantiates the function as a DAE and adds it | ||
| 7688 | to the functiontree of a newly created DAE." | ||
| 7689 | input FCore.Cache inCache; | ||
| 7690 | input FCore.Graph env; | ||
| 7691 | input Absyn.Path name; | ||
| 7692 | input Boolean builtin "builtin functions create empty dae"; | ||
| 7693 | input Option<SCode.Element> clOpt "if not present, looked up by name in environment"; | ||
| 7694 | input Boolean printErrorMsg "if true, prints an error message if the function could not be instantiated"; | ||
| 7695 | output FCore.Cache outCache; | ||
| 7696 | output Util.Status status; | ||
| 7697 | algorithm | ||
| 7698 | 60997 | (outCache,status) := instantiateDaeFunction2(inCache, env, name, builtin, | |
| 7699 | clOpt, printErrorMsg, NORMAL_FUNCTION_INST()); | ||
| 7700 | end instantiateDaeFunction; | ||
| 7701 | |||
| 7702 | public function instantiateDaeFunctionFromTypes | ||
| 7703 | "Help function to elabCallArgs. Instantiates the function as a DAE and adds it | ||
| 7704 | to the functiontree of a newly created DAE." | ||
| 7705 | input FCore.Cache inCache; | ||
| 7706 | input FCore.Graph env; | ||
| 7707 | input list<DAE.Type> tys; | ||
| 7708 | input Boolean builtin "builtin functions create empty dae"; | ||
| 7709 | input Option<SCode.Element> clOpt "if not present, looked up by name in environment"; | ||
| 7710 | input Boolean printErrorMsg "if true, prints an error message if the function could not be instantiated"; | ||
| 7711 | input Util.Status acc; | ||
| 7712 | output FCore.Cache outCache; | ||
| 7713 | output Util.Status status; | ||
| 7714 | algorithm | ||
| 7715 | (outCache,status) := match (tys, acc) | ||
| 7716 | local | ||
| 7717 | Absyn.Path name; | ||
| 7718 | list<DAE.Type> rest; | ||
| 7719 | |||
| 7720 | case (DAE.T_FUNCTION(path = name) :: rest, Util.SUCCESS()) | ||
| 7721 | algorithm | ||
| 7722 | 500 | (outCache,status) := instantiateDaeFunction(inCache, env, name, builtin, clOpt, printErrorMsg); | |
| 7723 | 500 | then | |
| 7724 | instantiateDaeFunctionFromTypes(inCache, env, rest, builtin, clOpt, printErrorMsg, status); | ||
| 7725 | |||
| 7726 | else (inCache, acc); | ||
| 7727 | end match; | ||
| 7728 | end instantiateDaeFunctionFromTypes; | ||
| 7729 | |||
| 7730 | public function instantiateDaeFunctionForceInst | ||
| 7731 | "Help function to elabCallArgs. Instantiates the function as a DAE and adds it | ||
| 7732 | to the functiontree of a newly created DAE." | ||
| 7733 | input FCore.Cache inCache; | ||
| 7734 | input FCore.Graph env; | ||
| 7735 | input Absyn.Path name; | ||
| 7736 | input Boolean builtin "builtin functions create empty dae"; | ||
| 7737 | input Option<SCode.Element> clOpt "if not present, looked up by name in environment"; | ||
| 7738 | input Boolean printErrorMsg "if true, prints an error message if the function could not be instantiated"; | ||
| 7739 | output FCore.Cache outCache; | ||
| 7740 | output Util.Status status; | ||
| 7741 | algorithm | ||
| 7742 | ✗ | (outCache,status) := instantiateDaeFunction2(inCache, env, name, builtin, | |
| 7743 | clOpt, printErrorMsg, FORCE_FUNCTION_INST()); | ||
| 7744 | end instantiateDaeFunctionForceInst; | ||
| 7745 | |||
| 7746 | protected function instantiateDaeFunction2 | ||
| 7747 | "Help function to elabCallArgs. Instantiates the function as a DAE and adds it | ||
| 7748 | to the functiontree of a newly created DAE." | ||
| 7749 | input FCore.Cache inCache; | ||
| 7750 | input FCore.Graph inEnv; | ||
| 7751 | input Absyn.Path inName; | ||
| 7752 | input Boolean builtin "builtin functions create empty dae"; | ||
| 7753 | input Option<SCode.Element> clOpt "if not present, looked up by name in environment"; | ||
| 7754 | input Boolean printErrorMsg "if true, prints an error message if the function could not be instantiated"; | ||
| 7755 | input ForceFunctionInst forceFunctionInst; | ||
| 7756 | output FCore.Cache outCache; | ||
| 7757 | output Util.Status status; | ||
| 7758 | protected | ||
| 7759 | Integer numError = Error.getNumErrorMessages(); | ||
| 7760 | Boolean instOnlyForcedFunctions = isSome(getGlobalRoot(Global.instOnlyForcedFunctions)); | ||
| 7761 | algorithm | ||
| 7762 | (outCache,status) := matchcontinue(builtin, clOpt, instOnlyForcedFunctions, forceFunctionInst) | ||
| 7763 | local | ||
| 7764 | FCore.Graph env; | ||
| 7765 | SCode.Element cl; | ||
| 7766 | String pathStr,envStr; | ||
| 7767 | DAE.ComponentRef cref; | ||
| 7768 | Absyn.Path name; | ||
| 7769 | DAE.Type ty; | ||
| 7770 | |||
| 7771 | // Skip function instantiation if we set those flags | ||
| 7772 | case (_, _, true, NORMAL_FUNCTION_INST()) | ||
| 7773 | algorithm | ||
| 7774 | // Don't skip builtin functions or functions in the same package; they are useful to inline | ||
| 7775 | ✗ | false := AbsynUtil.pathIsIdent(inName); | |
| 7776 | // print("Skipping: " + AbsynUtil.pathString(name) + "\n"); | ||
| 7777 | then | ||
| 7778 | (inCache, Util.SUCCESS()); | ||
| 7779 | |||
| 7780 | // Builtin functions skipped | ||
| 7781 | case (true, _, _, _) then (inCache, Util.SUCCESS()); | ||
| 7782 | |||
| 7783 | // External object functions skipped | ||
| 7784 | case (_, _, _, NORMAL_FUNCTION_INST()) | ||
| 7785 | algorithm | ||
| 7786 |
2/2✓ Branch 1 taken 31832 times.
✓ Branch 2 taken 45 times.
|
31877 | (_, true) := isExternalObjectFunction(inCache, inEnv, inName); |
| 7787 | then | ||
| 7788 | (inCache, Util.SUCCESS()); | ||
| 7789 | |||
| 7790 | // Recursive calls (by looking at environment) skipped | ||
| 7791 | case (_, NONE(), _, _) | ||
| 7792 | algorithm | ||
| 7793 |
2/2✓ Branch 1 taken 409 times.
✓ Branch 2 taken 31423 times.
|
31832 | false := FGraph.isTopScope(inEnv); |
| 7794 |
2/2✓ Branch 2 taken 31408 times.
✓ Branch 3 taken 15 times.
|
31423 | true := AbsynUtil.pathSuffixOf(inName, FGraph.getGraphName(inEnv)); |
| 7795 | then | ||
| 7796 | (inCache, Util.SUCCESS()); | ||
| 7797 | |||
| 7798 | // Recursive calls (by looking in cache) skipped | ||
| 7799 | case (_, _, _, _) | ||
| 7800 | algorithm | ||
| 7801 | 31817 | (outCache, _, _, name) := lookupAndFullyQualify(inCache, inEnv, inName); | |
| 7802 | 31649 | FCore.checkCachedInstFuncGuard(outCache, name); | |
| 7803 | then | ||
| 7804 | (outCache, Util.SUCCESS()); | ||
| 7805 | |||
| 7806 | // class must be looked up | ||
| 7807 | case (_, NONE(), _, _) | ||
| 7808 | algorithm | ||
| 7809 | 5928 | (outCache, env, cl, name) := lookupAndFullyQualify(inCache, inEnv, inName); | |
| 7810 | 5760 | outCache := FCore.addCachedInstFuncGuard(outCache, name); | |
| 7811 | 5760 | outCache := InstFunction.implicitFunctionInstantiation(outCache, env, | |
| 7812 | InnerOuter.emptyInstHierarchy, DAE.NOMOD(), DAE.NOPRE(), cl, {}); | ||
| 7813 | then | ||
| 7814 | (outCache, Util.SUCCESS()); | ||
| 7815 | |||
| 7816 | // class already available | ||
| 7817 | case (_, SOME(cl), _, _) | ||
| 7818 | algorithm | ||
| 7819 | ✗ | (outCache,_) := Inst.makeFullyQualified(inCache, inEnv, inName); | |
| 7820 | ✗ | outCache := InstFunction.implicitFunctionInstantiation(outCache, inEnv, | |
| 7821 | InnerOuter.emptyInstHierarchy, DAE.NOMOD(), DAE.NOPRE(), cl, {}); | ||
| 7822 | then | ||
| 7823 | (outCache, Util.SUCCESS()); | ||
| 7824 | |||
| 7825 | // call to function reference variable | ||
| 7826 | case (_, NONE(), _, _) | ||
| 7827 | algorithm | ||
| 7828 | 187 | cref := ComponentReference.pathToCref(inName); | |
| 7829 | 187 | (outCache, _, ty) := Lookup.lookupVar(inCache, inEnv, cref); | |
| 7830 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 168 times.
|
168 | DAE.T_FUNCTION() := ty; |
| 7831 | then | ||
| 7832 | (outCache, Util.SUCCESS()); | ||
| 7833 | |||
| 7834 | case (_, _, true, _) | ||
| 7835 | algorithm | ||
| 7836 | ✗ | true := Error.getNumErrorMessages() == numError; | |
| 7837 | ✗ | envStr := FGraph.printGraphPathStr(inEnv); | |
| 7838 | ✗ | pathStr := AbsynUtil.pathString(inName); | |
| 7839 | ✗ | Error.addMessage(Error.GENERIC_INST_FUNCTION, {pathStr, envStr}); | |
| 7840 | ✗ | then | |
| 7841 | fail(); | ||
| 7842 | |||
| 7843 | else (inCache, Util.FAILURE()); | ||
| 7844 | end matchcontinue; | ||
| 7845 | end instantiateDaeFunction2; | ||
| 7846 | |||
| 7847 | protected function lookupAndFullyQualify | ||
| 7848 | input FCore.Cache inCache; | ||
| 7849 | input FCore.Graph inEnv; | ||
| 7850 | input Absyn.Path inFunctionName; | ||
| 7851 | output FCore.Cache outCache; | ||
| 7852 | output FCore.Graph outEnv; | ||
| 7853 | output SCode.Element outClass; | ||
| 7854 | output Absyn.Path outFunctionName; | ||
| 7855 | algorithm | ||
| 7856 |
2/2✓ Branch 1 taken 320 times.
✓ Branch 2 taken 37425 times.
|
37745 | if Lookup.isFunctionCallViaComponent(inCache, inEnv, inFunctionName) then |
| 7857 | // do NOT qualify function calls via component instance! | ||
| 7858 | 320 | (_, outClass, outEnv) := Lookup.lookupClass(inCache, inEnv, inFunctionName); | |
| 7859 | 320 | outFunctionName := FGraph.joinScopePath(outEnv, AbsynUtil.makeIdentPathFromString(SCodeUtil.elementName(outClass))); | |
| 7860 | outCache := inCache; | ||
| 7861 | else | ||
| 7862 | // qualify everything else | ||
| 7863 | 37425 | (outCache, outClass, outEnv) := Lookup.lookupClass(inCache, inEnv, inFunctionName); | |
| 7864 | 37089 | outFunctionName := AbsynUtil.makeFullyQualified( | |
| 7865 | FGraph.joinScopePath(outEnv, AbsynUtil.makeIdentPathFromString(SCodeUtil.elementName(outClass)))); | ||
| 7866 | end if; | ||
| 7867 | end lookupAndFullyQualify; | ||
| 7868 | |||
| 7869 | protected function instantiateImplicitRecordConstructors | ||
| 7870 | "Given a list of arguments to a function, this function checks if any of the | ||
| 7871 | arguments are component references to a record instance, and instantiates the | ||
| 7872 | record constructors for those components. These are implicit record | ||
| 7873 | constructors, because they are not explicitly called, but are needed when code | ||
| 7874 | is generated for record instances as function input arguments." | ||
| 7875 | input FCore.Cache inCache; | ||
| 7876 | input FCore.Graph inEnv; | ||
| 7877 | input list<DAE.Exp> args; | ||
| 7878 | output FCore.Cache outCache; | ||
| 7879 | algorithm | ||
| 7880 | outCache := matchcontinue args | ||
| 7881 | local | ||
| 7882 | list<DAE.Exp> rest_args; | ||
| 7883 | Absyn.Path record_name; | ||
| 7884 | FCore.Cache cache; | ||
| 7885 | |||
| 7886 | // case (_, SOME(_)) then inCache; // TODO: Should this just return now? We always have symbol table! | ||
| 7887 | case {} then inCache; | ||
| 7888 | |||
| 7889 | case DAE.CREF(ty = DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(path = record_name))) :: rest_args | ||
| 7890 | algorithm | ||
| 7891 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4197 times.
|
4197 | (cache, Util.SUCCESS()) := instantiateDaeFunction(inCache, inEnv, record_name, false, NONE(), false); |
| 7892 | 4197 | then | |
| 7893 | instantiateImplicitRecordConstructors(cache, inEnv, rest_args); | ||
| 7894 | |||
| 7895 | case _ :: rest_args | ||
| 7896 | 76435 | then instantiateImplicitRecordConstructors(inCache, inEnv, rest_args); | |
| 7897 | |||
| 7898 | end matchcontinue; | ||
| 7899 | end instantiateImplicitRecordConstructors; | ||
| 7900 | |||
| 7901 | protected function addDefaultArgs | ||
| 7902 | "Adds default values to a list of function slots." | ||
| 7903 | input list<Slot> inSlots; | ||
| 7904 | input SourceInfo inInfo; | ||
| 7905 | output list<DAE.Exp> outArgs; | ||
| 7906 | output list<Slot> outSlots; | ||
| 7907 | algorithm | ||
| 7908 | 56371 | (outArgs, outSlots) := List.map2_2(inSlots, fillDefaultSlot, listArray(inSlots), inInfo); | |
| 7909 | end addDefaultArgs; | ||
| 7910 | |||
| 7911 | protected function fillDefaultSlot | ||
| 7912 | "Fills a function slot with it's default value if it hasn't already been filled." | ||
| 7913 | input Slot inSlot; | ||
| 7914 | input array<Slot> inSlotArray; | ||
| 7915 | input SourceInfo inInfo; | ||
| 7916 | output DAE.Exp outArg; | ||
| 7917 | output Slot outSlot; | ||
| 7918 | algorithm | ||
| 7919 | (outArg, outSlot) := match inSlot | ||
| 7920 | local | ||
| 7921 | DAE.Exp arg; | ||
| 7922 | String id; | ||
| 7923 | Integer idx; | ||
| 7924 | |||
| 7925 | // Slot already filled by function argument. | ||
| 7926 | 81868 | case SLOT(slotFilled = true, arg = SOME(arg)) then (arg, inSlot); | |
| 7927 | |||
| 7928 | // Slot not filled by function argument, but has default value. | ||
| 7929 | case SLOT(slotFilled = false, defaultArg = DAE.FUNCARG(defaultBinding=SOME(_)), idx = idx) | ||
| 7930 | 21872 | then fillDefaultSlot2(inSlotArray[idx], inSlotArray, inInfo); | |
| 7931 | |||
| 7932 | // Slot not filled, and has no default value => error. | ||
| 7933 | case SLOT(defaultArg = DAE.FUNCARG(name = id)) | ||
| 7934 | algorithm | ||
| 7935 | 83 | Error.addSourceMessage(Error.UNFILLED_SLOT, {id}, inInfo); | |
| 7936 | 83 | then | |
| 7937 | fail(); | ||
| 7938 | |||
| 7939 | end match; | ||
| 7940 | end fillDefaultSlot; | ||
| 7941 | |||
| 7942 | protected function fillDefaultSlot2 | ||
| 7943 | input Slot inSlot; | ||
| 7944 | input array<Slot> inSlotArray; | ||
| 7945 | input SourceInfo inInfo; | ||
| 7946 | output DAE.Exp outArg; | ||
| 7947 | output Slot outSlot = inSlot; | ||
| 7948 | algorithm | ||
| 7949 | (outArg, outSlot) := match outSlot | ||
| 7950 | local | ||
| 7951 | DAE.Exp exp; | ||
| 7952 | String id; | ||
| 7953 | Integer idx; | ||
| 7954 | |||
| 7955 | // An already evaluated slot, return its binding. | ||
| 7956 | case SLOT(arg = SOME(exp), evalStatus = 2) | ||
| 7957 | then (exp, inSlot); | ||
| 7958 | |||
| 7959 | // A slot in the process of being evaluated => cyclic bindings. | ||
| 7960 | case SLOT(defaultArg = DAE.FUNCARG(name=id), | ||
| 7961 | evalStatus = 1) | ||
| 7962 | algorithm | ||
| 7963 | ✗ | Error.addSourceMessage(Error.CYCLIC_DEFAULT_VALUE, | |
| 7964 | {id}, inInfo); | ||
| 7965 | ✗ | then | |
| 7966 | fail(); | ||
| 7967 | |||
| 7968 | // A slot with an unevaluated binding, evaluate the binding and return it. | ||
| 7969 | case SLOT(defaultArg = DAE.FUNCARG(defaultBinding=SOME(exp)), | ||
| 7970 | idx = idx, evalStatus = 0) | ||
| 7971 | algorithm | ||
| 7972 | 21872 | outSlot.evalStatus := SLOT_EVALUATING; | |
| 7973 | 21872 | arrayUpdate(inSlotArray, idx, outSlot); | |
| 7974 | |||
| 7975 | 21872 | exp := evaluateSlotExp(exp, inSlotArray, inInfo); | |
| 7976 | 21872 | outSlot.arg := SOME(exp); | |
| 7977 | 21872 | outSlot.slotFilled := true; | |
| 7978 | |||
| 7979 | 21872 | outSlot.evalStatus := SLOT_EVALUATED; | |
| 7980 | 21872 | arrayUpdate(inSlotArray, idx, outSlot); | |
| 7981 | then | ||
| 7982 | (exp, outSlot); | ||
| 7983 | |||
| 7984 | end match; | ||
| 7985 | end fillDefaultSlot2; | ||
| 7986 | |||
| 7987 | protected function evaluateSlotExp | ||
| 7988 | "Evaluates a slot's binding by recursively replacing references to other slots | ||
| 7989 | with their bindings." | ||
| 7990 | input DAE.Exp inExp; | ||
| 7991 | input array<Slot> inSlotArray; | ||
| 7992 | input SourceInfo inInfo; | ||
| 7993 | output DAE.Exp outExp; | ||
| 7994 | algorithm | ||
| 7995 | 21872 | outExp := Expression.traverseExpBottomUp(inExp, evaluateSlotExp_traverser, (inSlotArray, inInfo)); | |
| 7996 | end evaluateSlotExp; | ||
| 7997 | |||
| 7998 | protected function evaluateSlotExp_traverser | ||
| 7999 | input DAE.Exp inExp; | ||
| 8000 | input tuple<array<Slot>, SourceInfo> inTuple; | ||
| 8001 | output DAE.Exp outExp; | ||
| 8002 | output tuple<array<Slot>, SourceInfo> outTuple; | ||
| 8003 | algorithm | ||
| 8004 | (outExp,outTuple) := match (inExp, inTuple) | ||
| 8005 | local | ||
| 8006 | String id; | ||
| 8007 | array<Slot> slots; | ||
| 8008 | Option<Slot> slot; | ||
| 8009 | DAE.Exp exp, orig_exp; | ||
| 8010 | SourceInfo info; | ||
| 8011 | |||
| 8012 | // Only simple identifiers can be slot names. | ||
| 8013 | case (orig_exp as DAE.CREF(componentRef = DAE.CREF_IDENT(ident = id)), (slots, info)) | ||
| 8014 | algorithm | ||
| 8015 | 6 | slot := lookupSlotInArray(id, slots); | |
| 8016 | 6 | exp := getOptSlotDefaultExp(slot, slots, info, orig_exp); | |
| 8017 | 6 | then | |
| 8018 | (exp, (slots, info)); | ||
| 8019 | |||
| 8020 | else (inExp, inTuple); | ||
| 8021 | end match; | ||
| 8022 | end evaluateSlotExp_traverser; | ||
| 8023 | |||
| 8024 | protected function lookupSlotInArray | ||
| 8025 | "Looks up the given name in an array of slots, and returns either SOME(slot) | ||
| 8026 | if a slot with that name was found, or NONE() if a slot couldn't be found." | ||
| 8027 | input String inSlotName; | ||
| 8028 | input array<Slot> inSlots; | ||
| 8029 | output Option<Slot> outSlot; | ||
| 8030 | protected | ||
| 8031 | Slot slot; | ||
| 8032 | algorithm | ||
| 8033 | try | ||
| 8034 | 6 | slot := Array.getMemberOnTrue(inSlotName, inSlots, isSlotNamed); | |
| 8035 | outSlot := SOME(slot); | ||
| 8036 | else | ||
| 8037 | outSlot := NONE(); | ||
| 8038 | end try; | ||
| 8039 | end lookupSlotInArray; | ||
| 8040 | |||
| 8041 | protected function isSlotNamed | ||
| 8042 | input String inName; | ||
| 8043 | input Slot inSlot; | ||
| 8044 | output Boolean outIsNamed; | ||
| 8045 | protected | ||
| 8046 | String id; | ||
| 8047 | algorithm | ||
| 8048 | 8 | SLOT(defaultArg = DAE.FUNCARG(name=id)) := inSlot; | |
| 8049 |
3/4✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 5 times.
|
8 | outIsNamed := stringEq(id, inName); |
| 8050 | end isSlotNamed; | ||
| 8051 | |||
| 8052 | protected function getOptSlotDefaultExp | ||
| 8053 | "Takes an optional slot and tries to evaluate the slot's binding if it's SOME, | ||
| 8054 | otherwise returns the original expression if it's NONE." | ||
| 8055 | input Option<Slot> inSlot; | ||
| 8056 | input array<Slot> inSlots; | ||
| 8057 | input SourceInfo inInfo; | ||
| 8058 | input DAE.Exp inOrigExp; | ||
| 8059 | output DAE.Exp outExp; | ||
| 8060 | algorithm | ||
| 8061 | outExp := match inSlot | ||
| 8062 | local | ||
| 8063 | Slot slot; | ||
| 8064 | DAE.Exp exp; | ||
| 8065 | |||
| 8066 | // Got a slot, evaluate its binding and return it. | ||
| 8067 | case SOME(slot) | ||
| 8068 | algorithm | ||
| 8069 | 5 | exp := fillDefaultSlot(slot, inSlots, inInfo); | |
| 8070 | then | ||
| 8071 | exp; | ||
| 8072 | |||
| 8073 | // No slot, return the original expression. | ||
| 8074 | case NONE() then inOrigExp; | ||
| 8075 | end match; | ||
| 8076 | end getOptSlotDefaultExp; | ||
| 8077 | |||
| 8078 | protected function determineConstSpecialFunc | ||
| 8079 | "For the special functions constructor and destructor, in external object, the | ||
| 8080 | constantness is always variable, even if arguments are constant, because they | ||
| 8081 | should be called during runtime and not during compiletime." | ||
| 8082 | input FCore.Cache inCache; | ||
| 8083 | input FCore.Graph inEnv; | ||
| 8084 | input DAE.Const inConst; | ||
| 8085 | input Absyn.Path inFuncName; | ||
| 8086 | output FCore.Cache outCache; | ||
| 8087 | output DAE.Const outConst; | ||
| 8088 | protected | ||
| 8089 | Boolean is_ext; | ||
| 8090 | algorithm | ||
| 8091 | 55889 | (outCache, is_ext) := isExternalObjectFunction(inCache, inEnv, inFuncName); | |
| 8092 |
2/2✓ Branch 0 taken 45 times.
✓ Branch 1 taken 55844 times.
|
55889 | outConst := if is_ext then DAE.C_VAR() else inConst; |
| 8093 | end determineConstSpecialFunc; | ||
| 8094 | |||
| 8095 | public function isExternalObjectFunction | ||
| 8096 | input FCore.Cache inCache; | ||
| 8097 | input FCore.Graph inEnv; | ||
| 8098 | input Absyn.Path inPath; | ||
| 8099 | output FCore.Cache outCache; | ||
| 8100 | output Boolean outIsExt; | ||
| 8101 | protected | ||
| 8102 | list<SCode.Element> els; | ||
| 8103 | String last_id; | ||
| 8104 | algorithm | ||
| 8105 | try | ||
| 8106 |
3/4✗ Branch 1 not taken.
✓ Branch 2 taken 71543 times.
✓ Branch 3 taken 1591 times.
✓ Branch 4 taken 69952 times.
|
157718 | (outCache, SCode.CLASS(classDef = SCode.PARTS(elementLst = els)), _) := |
| 8107 | Lookup.lookupClass(inCache, inEnv, inPath); | ||
| 8108 |
1/2✓ Branch 1 taken 69952 times.
✗ Branch 2 not taken.
|
69952 | true := SCodeUtil.isExternalObject(els); |
| 8109 | outIsExt := true; | ||
| 8110 | else | ||
| 8111 | 87766 | last_id := AbsynUtil.pathLastIdent(inPath); | |
| 8112 | outCache := inCache; | ||
| 8113 |
7/8✓ Branch 0 taken 5928 times.
✓ Branch 1 taken 81838 times.
✓ Branch 3 taken 5838 times.
✓ Branch 4 taken 90 times.
✓ Branch 5 taken 3530 times.
✓ Branch 6 taken 84146 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3530 times.
|
87766 | outIsExt := last_id == "constructor" or last_id == "destructor"; |
| 8114 | end try; | ||
| 8115 | end isExternalObjectFunction; | ||
| 8116 | |||
| 8117 | protected constant String vectorizeArg = "$vectorizeArg"; | ||
| 8118 | |||
| 8119 | protected function vectorizeCall "author: PA | ||
| 8120 | Takes an expression and a list of array dimensions and the Slot list. | ||
| 8121 | It will vectorize the expression over the dimension given as array dim | ||
| 8122 | for the slots which have that dimension. | ||
| 8123 | For example foo:(Real,Real[:])=> Real | ||
| 8124 | foo(1:2,{1,2;3,4}) vectorizes with arraydim [2] to | ||
| 8125 | {foo(1,{1,2}),foo(2,{3,4})}" | ||
| 8126 | input DAE.Exp inExp; | ||
| 8127 | input DAE.Dimensions inDims; | ||
| 8128 | input list<Slot> inSlots; | ||
| 8129 | input DAE.Properties inProperties; | ||
| 8130 | input SourceInfo info; | ||
| 8131 | output DAE.Exp outExp; | ||
| 8132 | output DAE.Properties outProperties; | ||
| 8133 | algorithm | ||
| 8134 | (outExp, outProperties) := matchcontinue (inExp, inDims, inProperties) | ||
| 8135 | local | ||
| 8136 | DAE.Exp e,vect_exp; | ||
| 8137 | DAE.Type tp; | ||
| 8138 | DAE.Properties prop; | ||
| 8139 | DAE.Type exp_type; | ||
| 8140 | DAE.Const c; | ||
| 8141 | Absyn.Path fn; | ||
| 8142 | list<DAE.Exp> es; | ||
| 8143 | Integer int_dim; | ||
| 8144 | DAE.Dimension dim; | ||
| 8145 | DAE.Dimensions ad; | ||
| 8146 | String str; | ||
| 8147 | DAE.CallAttributes attr; | ||
| 8148 | DAE.ReductionInfo rinfo; | ||
| 8149 | String foldName,resultName; | ||
| 8150 | list<DAE.ReductionIterator> riters; | ||
| 8151 | Absyn.ReductionIterType iterType; | ||
| 8152 | |||
| 8153 | 56288 | case (e, {}, prop) then (e,prop); | |
| 8154 | |||
| 8155 | // If the dimension is not defined we can't vectorize the call. If we are running | ||
| 8156 | // checkModel this should succeed anyway, since we might be checking a function | ||
| 8157 | // that takes a vector of unknown size. So pretend that the dimension is 1. | ||
| 8158 | case (e, (DAE.DIM_UNKNOWN() :: ad), prop) | ||
| 8159 | guard Flags.getConfigBool(Flags.CHECK_MODEL) | ||
| 8160 | ✗ | then vectorizeCall(e, DAE.DIM_INTEGER(1) :: ad, inSlots, prop, info); | |
| 8161 | |||
| 8162 | /* Scalar expression, i.e function call */ | ||
| 8163 | case (e as DAE.CALL(),(dim :: ad),DAE.PROP(tp,c)) | ||
| 8164 | algorithm | ||
| 8165 | 2414 | int_dim := Expression.dimensionSize(dim); | |
| 8166 | 2409 | exp_type := Types.simplifyType(Types.liftArray(tp, dim)) "pass type of vectorized result expr"; | |
| 8167 | 2409 | vect_exp := vectorizeCallScalar(e, exp_type, int_dim, inSlots); | |
| 8168 | 2409 | tp := Types.liftArray(tp, dim); | |
| 8169 | 2409 | then vectorizeCall(vect_exp, ad, inSlots, DAE.PROP(tp,c),info); | |
| 8170 | |||
| 8171 | /* array expression of function calls */ | ||
| 8172 | case (DAE.ARRAY(),(dim :: ad),DAE.PROP(tp,c)) | ||
| 8173 | algorithm | ||
| 8174 | ✗ | int_dim := Expression.dimensionSize(dim); | |
| 8175 | // _ = Types.simplifyType(Types.liftArray(tp, dim)); | ||
| 8176 | ✗ | vect_exp := vectorizeCallArray(inExp, int_dim, inSlots); | |
| 8177 | ✗ | tp := Types.liftArrayRight(tp, dim); | |
| 8178 | ✗ | then vectorizeCall(vect_exp, ad, inSlots, DAE.PROP(tp,c),info); | |
| 8179 | |||
| 8180 | /* Multiple dimensions are possible to change to a reduction, like: | ||
| 8181 | * f(arr1,arr2) => array(f(x,y) thread for x in arr1, y in arr2) | ||
| 8182 | * f(mat1,mat2) => array(array(f(x,y) thread for x in arr1, y in arr2) thread for arr1 in mat1, arr2 in mat2 | ||
| 8183 | */ | ||
| 8184 | case (DAE.CALL(fn,es,attr),dim::ad,prop as DAE.PROP(tp,c)) | ||
| 8185 | algorithm | ||
| 8186 | 5 | (es, riters) := vectorizeCallUnknownDimension(es,inSlots,info); | |
| 8187 | 5 | tp := Types.liftArrayRight(tp, dim); | |
| 8188 | 5 | prop := DAE.PROP(tp,c); | |
| 8189 | 5 | e := DAE.CALL(fn,es,attr); | |
| 8190 | 5 | (e, prop) := vectorizeCall(e,ad,inSlots,prop,info); // Recurse... | |
| 8191 | 5 | foldName := Util.getTempVariableIndex(); | |
| 8192 | 5 | resultName := Util.getTempVariableIndex(); | |
| 8193 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
|
5 | iterType := if listLength(riters)>1 then Absyn.THREAD() else Absyn.COMBINE(); |
| 8194 | 5 | rinfo := DAE.REDUCTIONINFO(Absyn.IDENT("array"),iterType,tp,SOME(Values.ARRAY({},{0})),foldName,resultName,NONE()); | |
| 8195 | 5 | then | |
| 8196 | (DAE.REDUCTION(rinfo, e, riters), prop); | ||
| 8197 | |||
| 8198 | /* Scalar expression, non-constant but known dimensions */ | ||
| 8199 | case (DAE.CALL(),(DAE.DIM_EXP() :: _),DAE.PROP()) | ||
| 8200 | algorithm | ||
| 8201 | ✗ | str := "Cannot vectorize call with dimensions [" + ExpressionBasics.dimensionsString(inDims) + "]"; | |
| 8202 | ✗ | Error.addSourceMessage(Error.INTERNAL_ERROR,{str},info); | |
| 8203 | ✗ | then | |
| 8204 | fail(); | ||
| 8205 | |||
| 8206 | else | ||
| 8207 | algorithm | ||
| 8208 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 8209 | ✗ | str := ExpressionBasics.dimensionString(listHead(inDims)); | |
| 8210 | ✗ | Debug.traceln("- Static.vectorizeCall failed: " + str); | |
| 8211 | ✗ | then | |
| 8212 | fail(); | ||
| 8213 | end matchcontinue; | ||
| 8214 | end vectorizeCall; | ||
| 8215 | |||
| 8216 | protected function vectorizeCallUnknownDimension | ||
| 8217 | "Returns the new call arguments and a reduction iterator argument" | ||
| 8218 | input list<DAE.Exp> inEs; | ||
| 8219 | input list<Slot> inSlots; | ||
| 8220 | input SourceInfo info; | ||
| 8221 | output list<DAE.Exp> oes = {}; | ||
| 8222 | output list<DAE.ReductionIterator> ofound = {}; | ||
| 8223 | protected | ||
| 8224 | list<Slot> rest_slots = inSlots; | ||
| 8225 | list<DAE.Dimension> dims; | ||
| 8226 | DAE.Type ty, tp; | ||
| 8227 | String name; | ||
| 8228 | algorithm | ||
| 8229 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 5 times.
|
12 | for e in inEs loop |
| 8230 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | SLOT(dims = dims, defaultArg = DAE.FUNCARG(ty = ty)) :: rest_slots := rest_slots; |
| 8231 | |||
| 8232 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if listEmpty(dims) then |
| 8233 | oes := e :: oes; | ||
| 8234 | else | ||
| 8235 | 7 | name := Util.getTempVariableIndex(); | |
| 8236 | 7 | tp := Types.expTypetoTypesType(Expression.typeof(e)); // Maybe raise the type from the SLOT instead? | |
| 8237 | 7 | ofound := DAE.REDUCTIONITER(name, e, NONE(), tp) :: ofound; | |
| 8238 | 7 | oes := DAE.CREF(DAE.CREF_IDENT(name, ty, {}), ty) :: oes; | |
| 8239 | end if; | ||
| 8240 | end for; | ||
| 8241 | |||
| 8242 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if listEmpty(ofound) then |
| 8243 | ✗ | Error.addSourceMessageAndFail(Error.INTERNAL_ERROR, | |
| 8244 | {"Static.vectorizeCallUnknownDimension could not find any slot to vectorize"}, info); | ||
| 8245 | end if; | ||
| 8246 | |||
| 8247 | 5 | oes := listReverse(oes); | |
| 8248 | 5 | ofound := listReverse(ofound); | |
| 8249 | end vectorizeCallUnknownDimension; | ||
| 8250 | |||
| 8251 | protected function vectorizeCallArray | ||
| 8252 | "Helper function to vectorizeCall, vectorizes an ARRAY expression to an array | ||
| 8253 | of array expressions." | ||
| 8254 | input DAE.Exp inExp; | ||
| 8255 | input Integer inDim; | ||
| 8256 | input list<Slot> inSlots; | ||
| 8257 | output DAE.Exp outExp; | ||
| 8258 | protected | ||
| 8259 | DAE.Type ty; | ||
| 8260 | list<DAE.Exp> expl; | ||
| 8261 | Boolean sc; | ||
| 8262 | algorithm | ||
| 8263 | ✗ | DAE.ARRAY(ty = ty, array = expl) := inExp; | |
| 8264 | ✗ | expl := vectorizeCallArray2(expl, ty, inDim, inSlots); | |
| 8265 | ✗ | sc := Expression.typeBuiltin(ty); | |
| 8266 | ✗ | ty := Expression.liftArrayRight(ty, DAE.DIM_INTEGER(inDim)); | |
| 8267 | ✗ | outExp := DAE.ARRAY(ty, sc, expl); | |
| 8268 | end vectorizeCallArray; | ||
| 8269 | |||
| 8270 | protected function vectorizeCallArray2 | ||
| 8271 | "Helper function to vectorizeCallArray" | ||
| 8272 | input list<DAE.Exp> inExpl; | ||
| 8273 | input DAE.Type inType; | ||
| 8274 | input Integer inDim; | ||
| 8275 | input list<Slot> inSlots; | ||
| 8276 | output list<DAE.Exp> outExpl; | ||
| 8277 | algorithm | ||
| 8278 | ✗ | outExpl := list( | |
| 8279 | match e | ||
| 8280 | ✗ | case DAE.CALL() then vectorizeCallScalar(e, inType, inDim, inSlots); | |
| 8281 | ✗ | case DAE.ARRAY() then vectorizeCallArray(e, inDim, inSlots); | |
| 8282 | end match for e in inExpl); | ||
| 8283 | end vectorizeCallArray2; | ||
| 8284 | |||
| 8285 | protected function vectorizeCallScalar | ||
| 8286 | "author: PA | ||
| 8287 | Helper function to vectorizeCall, vectorizes CALL expressions to | ||
| 8288 | array expressions." | ||
| 8289 | input DAE.Exp exp "e.g. abs(v)"; | ||
| 8290 | input DAE.Type ty " e.g. Real[3], result of vectorized call"; | ||
| 8291 | input Integer dim; | ||
| 8292 | input list<Slot> slots; | ||
| 8293 | output DAE.Exp outExp; | ||
| 8294 | algorithm | ||
| 8295 | outExp := matchcontinue exp | ||
| 8296 | local | ||
| 8297 | list<DAE.Exp> expl; | ||
| 8298 | Boolean scalar; | ||
| 8299 | DAE.Exp new_exp; | ||
| 8300 | DAE.Type e_type,arr_type; | ||
| 8301 | |||
| 8302 | case DAE.CALL() | ||
| 8303 | algorithm | ||
| 8304 | 2409 | expl := vectorizeCallScalar2(exp.path, exp.expLst, exp.attr, slots, dim); | |
| 8305 | 2409 | e_type := Expression.unliftArray(ty); | |
| 8306 | 2409 | scalar := Expression.typeBuiltin(e_type) " unlift vectorized dimension to find element type"; | |
| 8307 | 4818 | arr_type := DAE.T_ARRAY(e_type, {DAE.DIM_INTEGER(dim)}); | |
| 8308 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2409 times.
|
2409 | new_exp := DAE.ARRAY(arr_type,scalar,expl); |
| 8309 | then | ||
| 8310 | new_exp; | ||
| 8311 | |||
| 8312 | else | ||
| 8313 | algorithm | ||
| 8314 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 8315 | ✗ | Debug.trace("-Static.vectorizeCallScalar failed\n"); | |
| 8316 | ✗ | then | |
| 8317 | fail(); | ||
| 8318 | end matchcontinue; | ||
| 8319 | end vectorizeCallScalar; | ||
| 8320 | |||
| 8321 | protected function vectorizeCallScalar2 | ||
| 8322 | "Iterates through vectorized dimension an creates argument list according to vectorized dimension in corresponding slot." | ||
| 8323 | input Absyn.Path fn; | ||
| 8324 | input list<DAE.Exp> exps; | ||
| 8325 | input DAE.CallAttributes attr; | ||
| 8326 | input list<Slot> slots; | ||
| 8327 | input Integer dim; | ||
| 8328 | output list<DAE.Exp> res = {}; | ||
| 8329 | protected | ||
| 8330 | list<DAE.Exp> callargs; | ||
| 8331 | algorithm | ||
| 8332 |
2/2✓ Branch 0 taken 222 times.
✓ Branch 1 taken 2187 times.
|
8848 | for cur_dim in dim:-1:1 loop |
| 8333 | 6439 | callargs := vectorizeCallScalar3(exps, slots, cur_dim); | |
| 8334 | 6439 | res := DAE.CALL(fn,callargs,attr) :: res; | |
| 8335 | end for; | ||
| 8336 | end vectorizeCallScalar2; | ||
| 8337 | |||
| 8338 | protected function vectorizeCallScalar3 | ||
| 8339 | "author: PA | ||
| 8340 | Helper function to vectorizeCallScalar2" | ||
| 8341 | input list<DAE.Exp> inExpl; | ||
| 8342 | input list<Slot> inSlots; | ||
| 8343 | input Integer inIndex; | ||
| 8344 | output list<DAE.Exp> outExpl = {}; | ||
| 8345 | protected | ||
| 8346 | list<Slot> rest_slots = inSlots; | ||
| 8347 | list<DAE.Dimension> dims; | ||
| 8348 | algorithm | ||
| 8349 |
2/2✓ Branch 0 taken 9682 times.
✓ Branch 1 taken 6439 times.
|
16121 | for e in inExpl loop |
| 8350 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9682 times.
|
9682 | SLOT(dims = dims) :: rest_slots := rest_slots; |
| 8351 | |||
| 8352 |
2/2✓ Branch 0 taken 7775 times.
✓ Branch 1 taken 1907 times.
|
9682 | if not listEmpty(dims) then |
| 8353 | // Foreach argument. | ||
| 8354 | 15550 | e := Expression.makeASUB(e, {DAE.ICONST(inIndex)}); | |
| 8355 | 7775 | e := ExpressionSimplify.simplify1(e); | |
| 8356 | end if; | ||
| 8357 | |||
| 8358 | outExpl := e :: outExpl; | ||
| 8359 | end for; | ||
| 8360 | |||
| 8361 | 6439 | outExpl := listReverse(outExpl); | |
| 8362 | end vectorizeCallScalar3; | ||
| 8363 | |||
| 8364 | protected function deoverloadFuncname | ||
| 8365 | "This function is used to deoverload function calls. It investigates the | ||
| 8366 | type of the function to see if it has the optional functionname set. If | ||
| 8367 | so this is returned. Otherwise return input." | ||
| 8368 | input Absyn.Path inPath; | ||
| 8369 | input DAE.Type inType; | ||
| 8370 | input FCore.Graph inEnv; | ||
| 8371 | output Absyn.Path outPath; | ||
| 8372 | output DAE.Type outType; | ||
| 8373 | algorithm | ||
| 8374 | (outPath,outType) := match inType | ||
| 8375 | local | ||
| 8376 | Absyn.Path fn; | ||
| 8377 | String name; | ||
| 8378 | DAE.Type tty; | ||
| 8379 | |||
| 8380 | case tty as DAE.T_FUNCTION(functionAttributes = DAE.FUNCTION_ATTRIBUTES( | ||
| 8381 | isBuiltin = DAE.FUNCTION_BUILTIN(SOME(name)))) | ||
| 8382 | algorithm | ||
| 8383 | 57278 | tty.path := Absyn.IDENT(name); | |
| 8384 | then (tty.path, tty); | ||
| 8385 | |||
| 8386 | case DAE.T_FUNCTION(path = fn) then (fn,inType); | ||
| 8387 | else (inPath, inType); | ||
| 8388 | |||
| 8389 | end match; | ||
| 8390 | end deoverloadFuncname; | ||
| 8391 | |||
| 8392 | protected function elabTypes | ||
| 8393 | "Elaborate input parameters to a function and select matching function type | ||
| 8394 | from a list of types." | ||
| 8395 | input FCore.Cache inCache; | ||
| 8396 | input FCore.Graph inEnv; | ||
| 8397 | input list<Absyn.Exp> inPosArgs; | ||
| 8398 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 8399 | input list<Absyn.Path> typeVars; | ||
| 8400 | input list<DAE.Type> inTypes; | ||
| 8401 | input Boolean inOnlyOneFunction "if true, we can report errors as soon as possible"; | ||
| 8402 | input Boolean inCheckTypes "if true, checks types"; | ||
| 8403 | input Boolean inImplicit; | ||
| 8404 | input DAE.Prefix inPrefix; | ||
| 8405 | input SourceInfo inInfo; | ||
| 8406 | output FCore.Cache outCache = inCache; | ||
| 8407 | output list<DAE.Exp> outArgs = {}; | ||
| 8408 | output list<DAE.Const> outConsts = {}; | ||
| 8409 | output DAE.Type outResultType = DAE.T_UNKNOWN_DEFAULT; | ||
| 8410 | output DAE.Type outFunctionType = DAE.T_UNKNOWN_DEFAULT; | ||
| 8411 | output DAE.Dimensions outDimensions = {}; | ||
| 8412 | output list<Slot> outSlots = {}; | ||
| 8413 | protected | ||
| 8414 | list<DAE.FuncArg> params; | ||
| 8415 | DAE.Type res_ty, func_ty; | ||
| 8416 | DAE.FunctionAttributes func_attr; | ||
| 8417 | list<Slot> slots; | ||
| 8418 | InstTypes.PolymorphicBindings pb; | ||
| 8419 | Absyn.Path path; | ||
| 8420 | Boolean success = false; | ||
| 8421 | list<DAE.Type> rest_tys = inTypes, tys; | ||
| 8422 | DAE.Exp arg; | ||
| 8423 | Integer numArgs; | ||
| 8424 | DAE.FuncArg funcarg; | ||
| 8425 | constant Boolean debug=false; | ||
| 8426 | algorithm | ||
| 8427 |
2/2✓ Branch 1 taken 877 times.
✓ Branch 2 taken 55409 times.
|
56286 | if listLength(rest_tys)>1 then |
| 8428 | // Filter out some interesting candidates first; this makes us not | ||
| 8429 | // look at overloaded functions with the wrong number of arguments (getting weird error-messages) | ||
| 8430 | 877 | numArgs := listLength(inPosArgs)+listLength(inNamedArgs); | |
| 8431 |
13/14✓ Branch 0 taken 1968 times.
✓ Branch 1 taken 1755 times.
✓ Branch 2 taken 1968 times.
✓ Branch 3 taken 1755 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1968 times.
✓ Branch 6 taken 26 times.
✓ Branch 7 taken 1942 times.
✓ Branch 9 taken 1753 times.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 1748 times.
✓ Branch 12 taken 5 times.
✓ Branch 13 taken 1755 times.
✓ Branch 14 taken 877 times.
|
6355 | tys := list(ty for ty guard match ty case DAE.T_FUNCTION() then |
| 8432 | ((numArgs <= listLength(ty.funcArg)) and numArgs >= sum(if isNone(argument.defaultBinding) then 1 else 0 for argument in ty.funcArg)); | ||
| 8433 | end match in rest_tys); | ||
| 8434 |
1/2✓ Branch 0 taken 877 times.
✗ Branch 1 not taken.
|
877 | if not listEmpty(tys) then |
| 8435 | rest_tys := tys; | ||
| 8436 | end if; | ||
| 8437 | end if; | ||
| 8438 |
2/2✓ Branch 0 taken 57419 times.
✓ Branch 1 taken 55961 times.
|
113380 | while not success loop |
| 8439 |
2/2✓ Branch 0 taken 325 times.
✓ Branch 1 taken 57094 times.
|
57419 | func_ty :: rest_tys := rest_tys; |
| 8440 | |||
| 8441 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 57094 times.
|
57094 | DAE.T_FUNCTION(funcArg = params, funcResultType = res_ty, |
| 8442 | functionAttributes = func_attr, path = path) := func_ty; | ||
| 8443 | if debug then | ||
| 8444 | print("elabTypes, try: " + TypesDump.unparseType(func_ty) + "\n"); | ||
| 8445 | end if; | ||
| 8446 | try | ||
| 8447 | 57094 | slots := makeEmptySlots(params); | |
| 8448 | 57094 | (outCache, outArgs, outSlots, outConsts, pb) := elabInputArgs(inCache, inEnv, | |
| 8449 | inPosArgs, inNamedArgs, slots, inOnlyOneFunction, inCheckTypes, inImplicit, | ||
| 8450 | inPrefix, inInfo, func_ty, path); | ||
| 8451 | 55978 | (outCache, pb) := addPolymorphicTypeVars(outCache, inEnv, typeVars, func_ty, pb, path, inInfo); | |
| 8452 | 55964 | pb := Types.solvePolymorphicBindings(pb, inInfo, path); | |
| 8453 | 55961 | res_ty := Types.fixPolymorphicRestype(res_ty, pb, inInfo); | |
| 8454 | (outArgs, outSlots, params, res_ty) := match func_attr.isBuiltin | ||
| 8455 | case DAE.FUNCTION_BUILTIN(unboxArgs=true) | ||
| 8456 |
4/4✓ Branch 0 taken 186 times.
✓ Branch 1 taken 177 times.
✓ Branch 2 taken 186 times.
✓ Branch 3 taken 177 times.
|
363 | then ( |
| 8457 | List.map(outArgs, Expression.unboxExp), | ||
| 8458 | 369 | list(match slot case SLOT(arg=SOME(arg)) algorithm slot.arg := SOME(Expression.unboxExp(arg)); then slot; else slot; end match for slot in outSlots), | |
| 8459 | 186 | list(match p case funcarg algorithm funcarg.ty := Types.unboxedType(Types.fixPolymorphicRestype(p.ty, pb, inInfo)); then funcarg; end match for p in params), // Fix the types of the inputs (needed for slots evaluation) | |
| 8460 | Types.unboxedType(res_ty)); | ||
| 8461 | 55784 | else (outArgs, outSlots, params, res_ty); | |
| 8462 | end match; | ||
| 8463 | |||
| 8464 | // Check the sanity of function parameters whose types are dependent on other parameters. | ||
| 8465 | // e.g. input Integer i; input Integer a[i]; // type of 'a' depends on the value 'i'. | ||
| 8466 | 55961 | (params, res_ty) := applyArgTypesToFuncType(outSlots, params, res_ty, inEnv, inCheckTypes, inInfo); | |
| 8467 | |||
| 8468 | 55961 | outDimensions := slotsVectorizable(outSlots, inInfo); | |
| 8469 | 55961 | outResultType := res_ty; | |
| 8470 | 55961 | outFunctionType := DAE.T_FUNCTION(params, outResultType, func_attr, path); | |
| 8471 | 55961 | outFunctionType := Types.fixPolymorphicRestype(outFunctionType, pb, inInfo); | |
| 8472 | |||
| 8473 | // Only created when not checking types for error msg. | ||
| 8474 | 55961 | outFunctionType := createActualFunctype(outFunctionType, outSlots, inCheckTypes); | |
| 8475 | success := true; | ||
| 8476 | if debug then | ||
| 8477 | print("elabTypes success for " + TypesDump.unparseType(func_ty) + ": "+TypesDump.unparseType(outFunctionType)+"=>"+TypesDump.unparseType(outResultType)+"\n"); | ||
| 8478 | end if; | ||
| 8479 | else | ||
| 8480 | // The type didn't match, try next function type. | ||
| 8481 | end try; | ||
| 8482 | end while; | ||
| 8483 | end elabTypes; | ||
| 8484 | |||
| 8485 | function addPolymorphicTypeVars | ||
| 8486 | input output FCore.Cache cache; | ||
| 8487 | input FCore.Graph env; | ||
| 8488 | input list<Absyn.Path> typeVars; | ||
| 8489 | input DAE.Type funcTy; | ||
| 8490 | input output InstTypes.PolymorphicBindings pb; | ||
| 8491 | input Absyn.Path fnPath; | ||
| 8492 | input SourceInfo info; | ||
| 8493 | protected | ||
| 8494 | DAE.Type ty; | ||
| 8495 | FCore.Graph scope; | ||
| 8496 | SCode.Element e; | ||
| 8497 | list<String> poly_types; | ||
| 8498 | String ty_name; | ||
| 8499 | algorithm | ||
| 8500 |
2/2✓ Branch 0 taken 55960 times.
✓ Branch 1 taken 18 times.
|
55978 | if listEmpty(typeVars) then |
| 8501 | 55960 | return; | |
| 8502 | end if; | ||
| 8503 | |||
| 8504 | 18 | (cache, e, _) := Lookup.lookupClass(cache, env, fnPath); | |
| 8505 | |||
| 8506 |
6/6✓ Branch 2 taken 27 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 31 times.
✓ Branch 5 taken 18 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 18 times.
|
49 | poly_types := list("$" + SCodeUtil.getElementName(c) |
| 8507 | for c guard SCodeUtil.isPolymorphicTypeVar(c) in SCodeUtil.getClassElements(e)); | ||
| 8508 | |||
| 8509 |
2/2✓ Branch 2 taken 4 times.
✓ Branch 3 taken 14 times.
|
18 | if listLength(typeVars) > listLength(poly_types) then |
| 8510 | 28 | Error.addSourceMessage(Error.TOO_MANY_TYPE_VARS_IN_CALL, | |
| 8511 | {AbsynUtil.pathString(fnPath)}, info); | ||
| 8512 | 14 | fail(); | |
| 8513 | end if; | ||
| 8514 | |||
| 8515 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
|
8 | for tv in typeVars loop |
| 8516 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | ty_name :: poly_types := poly_types; |
| 8517 | 4 | (cache, e, scope) := Lookup.lookupClass(cache, env, tv, SOME(info)); | |
| 8518 | 4 | (cache, _, ty) := Inst.instClassType(cache, scope, e); | |
| 8519 | 4 | pb := Types.addPolymorphicBinding(ty_name, ty, pb); | |
| 8520 | end for; | ||
| 8521 | end addPolymorphicTypeVars; | ||
| 8522 | |||
| 8523 | protected function applyArgTypesToFuncType | ||
| 8524 | "This function is yet another hack trying to handle function parameters with | ||
| 8525 | unknown dimensions. It uses the input arguments to try and figure out the | ||
| 8526 | actual dimensions of the dimensions." | ||
| 8527 | input list<Slot> inSlots; | ||
| 8528 | input list<DAE.FuncArg> inParameters; | ||
| 8529 | input DAE.Type inResultType; | ||
| 8530 | input FCore.Graph inEnv; | ||
| 8531 | input Boolean checkTypes; // If not checking types no need to do any of this. In and out. | ||
| 8532 | input SourceInfo inInfo; | ||
| 8533 | output list<DAE.FuncArg> outParameters; | ||
| 8534 | output DAE.Type outResultType; | ||
| 8535 | protected | ||
| 8536 | list<DAE.Type> tys; | ||
| 8537 | list<DAE.Dimension> dims; | ||
| 8538 | list<String> used_args; | ||
| 8539 | list<Slot> used_slots; | ||
| 8540 | FCore.Cache cache; | ||
| 8541 | FCore.Graph env; | ||
| 8542 | list<DAE.Var> vars; | ||
| 8543 | SCode.Element dummy_var; | ||
| 8544 | algorithm | ||
| 8545 | // If not checking types or no function parameters there is nothing to be done here. | ||
| 8546 | // Even if dims don't match we need the function as candidate for error messages. | ||
| 8547 |
4/4✓ Branch 0 taken 55924 times.
✓ Branch 1 taken 37 times.
✓ Branch 2 taken 2559 times.
✓ Branch 3 taken 53365 times.
|
55961 | if not checkTypes or listEmpty(inParameters) then |
| 8548 | outParameters := inParameters; | ||
| 8549 | outResultType := inResultType; | ||
| 8550 | 2596 | return; | |
| 8551 | end if; | ||
| 8552 | |||
| 8553 | // Get all the dims, bind the actual params to the formal params. | ||
| 8554 | // Build a new env frame with these bindings and evaluate dimensions. | ||
| 8555 | |||
| 8556 | // Extract all dimensions from the parameters. | ||
| 8557 |
4/4✓ Branch 0 taken 102593 times.
✓ Branch 1 taken 53365 times.
✓ Branch 2 taken 102593 times.
✓ Branch 3 taken 53365 times.
|
155958 | tys := list(Types.funcArgType(param) for param in inParameters); |
| 8558 | 53365 | dims := getAllOutputDimensions(inResultType); | |
| 8559 | 53365 | dims := listAppend(List.mapFlat(tys, TypesDump.getDimensions), dims); | |
| 8560 | |||
| 8561 | // Use the dimensions to figure out which parameters are referenced by other | ||
| 8562 | // parameters' dimensions. This is done to minimize the things we need to | ||
| 8563 | // constant evaluate, a.k.a. 'things that go wrong'. | ||
| 8564 | 53365 | used_args := extractNamesFromDims(dims); | |
| 8565 |
6/6✓ Branch 1 taken 101596 times.
✓ Branch 2 taken 997 times.
✓ Branch 3 taken 102593 times.
✓ Branch 4 taken 53365 times.
✓ Branch 5 taken 997 times.
✓ Branch 6 taken 53365 times.
|
155958 | used_slots := list(s for s guard(isSlotUsed(s, used_args)) in inSlots); |
| 8566 | |||
| 8567 | // Create DAE.Vars from the slots. | ||
| 8568 | 53365 | cache := FCore.noCache(); | |
| 8569 |
4/4✓ Branch 0 taken 997 times.
✓ Branch 1 taken 53365 times.
✓ Branch 2 taken 997 times.
✓ Branch 3 taken 53365 times.
|
54362 | vars := list(makeVarFromSlot(s, inEnv, cache) for s in used_slots); |
| 8570 | |||
| 8571 | // Use a dummy SCode.Element, because we're only interested in the DAE.Vars. | ||
| 8572 | dummy_var := SCode.COMPONENT("dummy", SCode.defaultPrefixes, | ||
| 8573 | SCode.defaultVarAttr, Absyn.TPATH(Absyn.IDENT(""), NONE()), SCode.NOMOD(), | ||
| 8574 | SCode.noComment, NONE(), Absyn.dummyInfo); | ||
| 8575 | |||
| 8576 | // Create a new implicit scope with the needed parameters on top of the | ||
| 8577 | // current env so we can find the bindings if needed. We need an implicit | ||
| 8578 | // scope so comp1.comp2 can be looked up without package constant restriction. | ||
| 8579 | 53365 | env := FGraph.openScope(inEnv, SCode.NOT_ENCAPSULATED(), FCore.forScopeName, NONE()); | |
| 8580 | |||
| 8581 | // Add variables to the environment. | ||
| 8582 | 53365 | env := makeDummyFuncEnv(env, vars, dummy_var); | |
| 8583 | // Evaluate the dimensions in the types. | ||
| 8584 |
7/8✓ Branch 0 taken 102593 times.
✓ Branch 1 taken 53365 times.
✓ Branch 2 taken 102593 times.
✓ Branch 3 taken 53365 times.
✓ Branch 4 taken 102593 times.
✓ Branch 5 taken 53365 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 53365 times.
|
155958 | outParameters := list(evaluateFuncParamDimAndMatchTypes(s, p, env, cache, inInfo) |
| 8585 | threaded for s in inSlots, p in inParameters); | ||
| 8586 | 53365 | outResultType := evaluateFuncArgTypeDims(inResultType, env, cache); | |
| 8587 | end applyArgTypesToFuncType; | ||
| 8588 | |||
| 8589 | protected function getAllOutputDimensions | ||
| 8590 | "Return the dimensions of an output type." | ||
| 8591 | input DAE.Type inOutputType; | ||
| 8592 | output list<DAE.Dimension> outDimensions; | ||
| 8593 | algorithm | ||
| 8594 | outDimensions := match inOutputType | ||
| 8595 | local | ||
| 8596 | list<DAE.Type> tys; | ||
| 8597 | |||
| 8598 | // A tuple, get the dimensions of all the types. | ||
| 8599 | case DAE.T_TUPLE(types = tys) | ||
| 8600 | 3123 | then List.mapFlat(tys, TypesDump.getDimensions); | |
| 8601 | |||
| 8602 | 106702 | else TypesDump.getDimensions(inOutputType); | |
| 8603 | end match; | ||
| 8604 | end getAllOutputDimensions; | ||
| 8605 | |||
| 8606 | protected function extractNamesFromDims | ||
| 8607 | "Extracts a list of unique names referenced by the given list of dimensions." | ||
| 8608 | input list<DAE.Dimension> inDimensions; | ||
| 8609 | input list<String> inAccumNames = {}; | ||
| 8610 | output list<String> outNames; | ||
| 8611 | algorithm | ||
| 8612 | outNames := match inDimensions | ||
| 8613 | local | ||
| 8614 | DAE.Exp exp; | ||
| 8615 | list<DAE.Dimension> rest_dims; | ||
| 8616 | list<DAE.ComponentRef> crefs; | ||
| 8617 | list<String> names; | ||
| 8618 | |||
| 8619 | case DAE.DIM_EXP(exp = exp) :: rest_dims | ||
| 8620 | algorithm | ||
| 8621 | 2463 | crefs := Expression.extractCrefsFromExp(exp); | |
| 8622 | 2463 | names := List.fold(crefs, extractNamesFromDims2, inAccumNames); | |
| 8623 | 2463 | then | |
| 8624 | extractNamesFromDims(rest_dims, names); | ||
| 8625 | |||
| 8626 | 44429 | case _ :: rest_dims then extractNamesFromDims(rest_dims, inAccumNames); | |
| 8627 | case {} then inAccumNames; | ||
| 8628 | |||
| 8629 | end match; | ||
| 8630 | end extractNamesFromDims; | ||
| 8631 | |||
| 8632 | protected function extractNamesFromDims2 | ||
| 8633 | input DAE.ComponentRef inCref; | ||
| 8634 | input list<String> inAccumNames; | ||
| 8635 | output list<String> outNames; | ||
| 8636 | algorithm | ||
| 8637 | outNames := match inCref | ||
| 8638 | local | ||
| 8639 | String name; | ||
| 8640 | |||
| 8641 | // Only interested in simple identifier, since that's all we can handle | ||
| 8642 | // anyway. | ||
| 8643 | case DAE.CREF_IDENT(ident = name) | ||
| 8644 | algorithm | ||
| 8645 | // Make sure we haven't added this name yet. | ||
| 8646 |
2/2✓ Branch 1 taken 1995 times.
✓ Branch 2 taken 476 times.
|
2471 | outNames := if List.isMemberOnTrue(name, inAccumNames, stringEq) then |
| 8647 | inAccumNames else name :: inAccumNames; | ||
| 8648 | then | ||
| 8649 | outNames; | ||
| 8650 | |||
| 8651 | else inAccumNames; | ||
| 8652 | |||
| 8653 | end match; | ||
| 8654 | end extractNamesFromDims2; | ||
| 8655 | |||
| 8656 | protected function isSlotUsed | ||
| 8657 | "Checks if a slot is used, in the sense that it's referenced by a function | ||
| 8658 | parameter dimension." | ||
| 8659 | input Slot inSlot; | ||
| 8660 | input list<String> inUsedNames; | ||
| 8661 | output Boolean outIsUsed; | ||
| 8662 | protected | ||
| 8663 | String slot_name; | ||
| 8664 | algorithm | ||
| 8665 | 206556 | SLOT(defaultArg = DAE.FUNCARG(name=slot_name)) := inSlot; | |
| 8666 | 206556 | outIsUsed := List.isMemberOnTrue(slot_name, inUsedNames, stringEq); | |
| 8667 | end isSlotUsed; | ||
| 8668 | |||
| 8669 | protected function makeVarFromSlot | ||
| 8670 | "Converts a Slot to a DAE.Var." | ||
| 8671 | input Slot inSlot; | ||
| 8672 | input FCore.Graph inEnv; | ||
| 8673 | input FCore.Cache inCache; | ||
| 8674 | output DAE.Var outVar; | ||
| 8675 | algorithm | ||
| 8676 | outVar := matchcontinue inSlot | ||
| 8677 | local | ||
| 8678 | DAE.Ident name; | ||
| 8679 | DAE.Type ty; | ||
| 8680 | DAE.Exp exp; | ||
| 8681 | DAE.Binding binding; | ||
| 8682 | Values.Value val; | ||
| 8683 | DAE.FuncArg defaultArg; | ||
| 8684 | |||
| 8685 | // If the argument expression already has known dimensions, no need to | ||
| 8686 | // constant evaluate it. | ||
| 8687 | case SLOT(defaultArg = DAE.FUNCARG(name=name), arg = SOME(exp)) | ||
| 8688 | algorithm | ||
| 8689 |
2/2✓ Branch 2 taken 16 times.
✓ Branch 3 taken 975 times.
|
991 | false := Expression.expHasCref(exp,ComponentReferenceBasics.makeCrefIdent(name,DAE.T_UNKNOWN_DEFAULT,{})); |
| 8690 | 975 | ty := Expression.typeof(exp); | |
| 8691 |
2/2✓ Branch 1 taken 10 times.
✓ Branch 2 taken 965 times.
|
975 | true := Types.dimensionsKnown(ty); |
| 8692 | 965 | binding := DAE.EQBOUND(exp, NONE(), DAE.C_CONST(), DAE.BINDING_FROM_DEFAULT_VALUE()); | |
| 8693 | 965 | then (DAE.TYPES_VAR(name, DAE.dummyAttrParam, ty, binding, false, NONE())); | |
| 8694 | |||
| 8695 | // Otherwise, try to constant evaluate the expression. | ||
| 8696 | case SLOT(defaultArg = DAE.FUNCARG(name=name), arg = SOME(exp)) | ||
| 8697 | algorithm | ||
| 8698 | // Constant evaluate the bound expression. | ||
| 8699 | 26 | (_, val) := Ceval.ceval(inCache, inEnv, exp, false, Absyn.NO_MSG(), 0); | |
| 8700 | ✗ | exp := ValuesUtil.valueExp(val, SOME(exp)); | |
| 8701 | ✗ | ty := Expression.typeof(exp); | |
| 8702 | // Create a binding from the evaluated expression. | ||
| 8703 | ✗ | binding := DAE.EQBOUND(exp, SOME(val), DAE.C_CONST(), DAE.BINDING_FROM_DEFAULT_VALUE()); | |
| 8704 | ✗ | then DAE.TYPES_VAR(name, DAE.dummyAttrParam, ty, binding, false, NONE()); | |
| 8705 | |||
| 8706 | case SLOT(defaultArg = DAE.FUNCARG(name=name, ty=ty)) | ||
| 8707 | 32 | then (DAE.TYPES_VAR(name, DAE.dummyAttrParam, ty, DAE.UNBOUND(), false, NONE())); | |
| 8708 | |||
| 8709 | end matchcontinue; | ||
| 8710 | end makeVarFromSlot; | ||
| 8711 | |||
| 8712 | protected function evaluateStructuralSlots2 | ||
| 8713 | input FCore.Cache inCache; | ||
| 8714 | input FCore.Graph inEnv; | ||
| 8715 | input list<Slot> inSlots; | ||
| 8716 | input list<String> usedSlots; | ||
| 8717 | input list<Slot> acc; | ||
| 8718 | output FCore.Cache cache; | ||
| 8719 | output list<Slot> slots; | ||
| 8720 | algorithm | ||
| 8721 | (cache,slots) := matchcontinue inSlots | ||
| 8722 | local | ||
| 8723 | DAE.Exp exp; | ||
| 8724 | Slot slot; | ||
| 8725 | list<Slot> rest; | ||
| 8726 | DAE.FuncArg defaultArg; | ||
| 8727 | list<DAE.Dimension> dims; | ||
| 8728 | Integer idx; | ||
| 8729 | Values.Value val; | ||
| 8730 | Integer ses; | ||
| 8731 | |||
| 8732 | 56460 | case {} then (inCache,listReverse(acc)); | |
| 8733 | |||
| 8734 | case slot::rest | ||
| 8735 | algorithm | ||
| 8736 |
2/2✓ Branch 1 taken 998 times.
✓ Branch 2 taken 102965 times.
|
103963 | false := isSlotUsed(slot, usedSlots); |
| 8737 | 102965 | (cache,slots) := evaluateStructuralSlots2(inCache,inEnv,rest,usedSlots,slot::acc); | |
| 8738 | then (cache,slots); | ||
| 8739 | |||
| 8740 | // If we are suggested the argument is structural, evaluate it | ||
| 8741 | case SLOT(defaultArg as DAE.FUNCARG(), _, SOME(exp), dims, idx, ses)::rest | ||
| 8742 | algorithm | ||
| 8743 | // Constant evaluate the bound expression. | ||
| 8744 | 992 | (cache, val) := Ceval.ceval(inCache, inEnv, exp, false, Absyn.NO_MSG(), 0); | |
| 8745 | 717 | exp := ValuesUtil.valueExp(val, SOME(exp)); | |
| 8746 | // Create a binding from the evaluated expression. | ||
| 8747 | 717 | slot := SLOT(defaultArg,true,SOME(exp),dims,idx,ses); | |
| 8748 | 717 | (cache,slots) := evaluateStructuralSlots2(cache,inEnv,rest,usedSlots,slot::acc); | |
| 8749 | then (cache,slots); | ||
| 8750 | |||
| 8751 | case slot::rest | ||
| 8752 | algorithm | ||
| 8753 | 281 | (cache,slots) := evaluateStructuralSlots2(inCache,inEnv,rest,usedSlots,slot::acc); | |
| 8754 | then (cache,slots); | ||
| 8755 | end matchcontinue; | ||
| 8756 | end evaluateStructuralSlots2; | ||
| 8757 | |||
| 8758 | protected function evaluateStructuralSlots | ||
| 8759 | input FCore.Cache inCache; | ||
| 8760 | input FCore.Graph inEnv; | ||
| 8761 | input list<Slot> inSlots; | ||
| 8762 | input DAE.Type funcType; | ||
| 8763 | output FCore.Cache cache; | ||
| 8764 | output list<Slot> slots; | ||
| 8765 | algorithm | ||
| 8766 | (cache,slots) := match funcType | ||
| 8767 | local | ||
| 8768 | list<DAE.Type> tys; | ||
| 8769 | list<DAE.Dimension> dims; | ||
| 8770 | list<String> used_args; | ||
| 8771 | list<DAE.FuncArg> funcArg; | ||
| 8772 | DAE.Type funcResultType; | ||
| 8773 | |||
| 8774 | case DAE.T_FUNCTION(funcArg=funcArg,funcResultType=funcResultType) | ||
| 8775 | algorithm | ||
| 8776 |
4/4✓ Branch 0 taken 103963 times.
✓ Branch 1 taken 56460 times.
✓ Branch 2 taken 103963 times.
✓ Branch 3 taken 56460 times.
|
160423 | tys := list(Types.funcArgType(arg) for arg in funcArg); |
| 8777 | 56460 | dims := getAllOutputDimensions(funcResultType); | |
| 8778 | 56460 | dims := listAppend(List.mapFlat(tys, TypesDump.getDimensions), dims); | |
| 8779 | // Use the dimensions to figure out which parameters are referenced by | ||
| 8780 | // other parameters' dimensions. This is done to minimize the things we | ||
| 8781 | // need to constant evaluate, a.k.a. 'things that go wrong'. | ||
| 8782 | 56460 | used_args := extractNamesFromDims(dims); | |
| 8783 | 56460 | (cache, slots) := evaluateStructuralSlots2(inCache, inEnv, inSlots, used_args, {}); | |
| 8784 | then | ||
| 8785 | (cache,slots); | ||
| 8786 | |||
| 8787 | 22260 | else (inCache, inSlots); // T_METARECORD, T_NOTYPE etc for builtins | |
| 8788 | end match; | ||
| 8789 | end evaluateStructuralSlots; | ||
| 8790 | |||
| 8791 | protected function makeDummyFuncEnv | ||
| 8792 | "Helper function to applyArgTypesToFuncType, creates a dummy function | ||
| 8793 | environment." | ||
| 8794 | input FCore.Graph inEnv; | ||
| 8795 | input list<DAE.Var> inVars; | ||
| 8796 | input SCode.Element inDummyVar; | ||
| 8797 | output FCore.Graph outEnv = inEnv; | ||
| 8798 | protected | ||
| 8799 | SCode.Element dummy_var; | ||
| 8800 | algorithm | ||
| 8801 |
2/2✓ Branch 0 taken 997 times.
✓ Branch 1 taken 53365 times.
|
54362 | for var in inVars loop |
| 8802 | 997 | dummy_var := SCodeUtil.setComponentName(inDummyVar, DAEUtil.typeVarIdent(var)); | |
| 8803 | 997 | outEnv := FGraph.mkComponentNode(outEnv, var, dummy_var, DAE.NOMOD(), | |
| 8804 | FCore.VAR_TYPED(), FGraph.empty()); | ||
| 8805 | end for; | ||
| 8806 | end makeDummyFuncEnv; | ||
| 8807 | |||
| 8808 | protected function evaluateFuncParamDimAndMatchTypes | ||
| 8809 | "Constant evaluates the dimensions of a FuncArg and then makes | ||
| 8810 | sure the type matches with the expected type in the slot." | ||
| 8811 | input Slot inSlot; | ||
| 8812 | input DAE.FuncArg inParam; | ||
| 8813 | input FCore.Graph inEnv; | ||
| 8814 | input FCore.Cache inCache; | ||
| 8815 | input SourceInfo inInfo; | ||
| 8816 | output DAE.FuncArg outParam; | ||
| 8817 | algorithm | ||
| 8818 | outParam := match(inSlot, inParam) | ||
| 8819 | local | ||
| 8820 | DAE.Type pty, sty; | ||
| 8821 | DAE.Dimensions dims1, dims2; | ||
| 8822 | DAE.Dimensions vdims; | ||
| 8823 | |||
| 8824 | |||
| 8825 | // If we have a code exp argument we can't check dims... | ||
| 8826 | // There are all kinds of scripting function that complicate things. | ||
| 8827 | case (_, DAE.FUNCARG(ty=DAE.T_CODE())) | ||
| 8828 | then inParam; | ||
| 8829 | |||
| 8830 | // If we have an array constant-evaluate the dimensions and make sure | ||
| 8831 | // They add up | ||
| 8832 | case (SLOT(arg = SOME(DAE.ARRAY(ty = sty)), dims = vdims), _) | ||
| 8833 | algorithm | ||
| 8834 | 14434 | DAE.FUNCARG(ty = pty) := inParam; | |
| 8835 | // evaluate the dimesions | ||
| 8836 | 14434 | pty := evaluateFuncArgTypeDims(pty, inEnv, inCache); | |
| 8837 | // append the vectorization dim if argument is vectorized. | ||
| 8838 | 14434 | dims1 := TypesDump.getDimensions(pty); | |
| 8839 | 14434 | dims1 := listAppend(vdims,dims1); | |
| 8840 | |||
| 8841 | 14434 | dims2 := TypesDump.getDimensions(sty); | |
| 8842 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 14434 times.
|
14434 | true := Expression.dimsEqual(dims1, dims2); |
| 8843 | |||
| 8844 | 14434 | outParam := Types.setFuncArgType(inParam, pty); | |
| 8845 | then | ||
| 8846 | outParam; | ||
| 8847 | |||
| 8848 | case (SLOT(arg = SOME(DAE.MATRIX(ty = sty)), dims = vdims), _) | ||
| 8849 | algorithm | ||
| 8850 | 524 | DAE.FUNCARG(ty=pty) := inParam; | |
| 8851 | // evaluate the dimesions | ||
| 8852 | 524 | pty := evaluateFuncArgTypeDims(pty, inEnv, inCache); | |
| 8853 | // append the vectorization dim if argument is vectorized. | ||
| 8854 | 524 | dims1 := TypesDump.getDimensions(pty); | |
| 8855 | 524 | vdims := listAppend(dims1,vdims); | |
| 8856 | 524 | dims2 := TypesDump.getDimensions(sty); | |
| 8857 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 524 times.
|
524 | true := Expression.dimsEqual(vdims, dims2); |
| 8858 | |||
| 8859 | 524 | outParam := Types.setFuncArgType(inParam, pty); | |
| 8860 | then | ||
| 8861 | outParam; | ||
| 8862 | |||
| 8863 | else | ||
| 8864 | algorithm | ||
| 8865 | 83572 | DAE.FUNCARG(ty=pty) := inParam; | |
| 8866 | 83572 | pty := evaluateFuncArgTypeDims(pty, inEnv, inCache); | |
| 8867 | 83572 | outParam := Types.setFuncArgType(inParam, pty); | |
| 8868 | then | ||
| 8869 | outParam; | ||
| 8870 | |||
| 8871 | end match; | ||
| 8872 | end evaluateFuncParamDimAndMatchTypes; | ||
| 8873 | |||
| 8874 | protected function evaluateFuncArgTypeDims | ||
| 8875 | "Constant evaluates the dimensions of a type." | ||
| 8876 | input DAE.Type inType; | ||
| 8877 | input FCore.Graph inEnv; | ||
| 8878 | input FCore.Cache inCache; | ||
| 8879 | output DAE.Type outType; | ||
| 8880 | algorithm | ||
| 8881 | outType := matchcontinue inType | ||
| 8882 | local | ||
| 8883 | DAE.Type ty; | ||
| 8884 | Integer n; | ||
| 8885 | DAE.Dimension dim; | ||
| 8886 | |||
| 8887 | // Array type, evaluate the dimension. | ||
| 8888 | case DAE.T_ARRAY(ty, {dim}) | ||
| 8889 | algorithm | ||
| 8890 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 19100 times.
|
23015 | (_, Values.INTEGER(n)) := Ceval.cevalDimension(inCache, inEnv, dim, false, Absyn.NO_MSG(), 0); |
| 8891 | 19100 | ty := evaluateFuncArgTypeDims(ty, inEnv, inCache); | |
| 8892 | 38200 | then | |
| 8893 | DAE.T_ARRAY(ty, {DAE.DIM_INTEGER(n)}); | ||
| 8894 | |||
| 8895 | // Previous case failed, keep the dimension but evaluate the rest of the type. | ||
| 8896 | case DAE.T_ARRAY(ty, {dim}) | ||
| 8897 | algorithm | ||
| 8898 | 3915 | ty := evaluateFuncArgTypeDims(ty, inEnv, inCache); | |
| 8899 | 3915 | then | |
| 8900 | DAE.T_ARRAY(ty, {dim}); | ||
| 8901 | |||
| 8902 | case ty as DAE.T_TUPLE() | ||
| 8903 | algorithm | ||
| 8904 | 1556 | ty.types := List.map2(ty.types, evaluateFuncArgTypeDims, inEnv, inCache); | |
| 8905 | then ty; | ||
| 8906 | |||
| 8907 | else inType; | ||
| 8908 | |||
| 8909 | end matchcontinue; | ||
| 8910 | end evaluateFuncArgTypeDims; | ||
| 8911 | |||
| 8912 | protected function createActualFunctype | ||
| 8913 | "Creates the actual function type of a CALL expression, used for error messages. | ||
| 8914 | This type is only created if checkTypes is false." | ||
| 8915 | input DAE.Type tp; | ||
| 8916 | input list<Slot> slots; | ||
| 8917 | input Boolean checkTypes; | ||
| 8918 | output DAE.Type outTp = tp; | ||
| 8919 | algorithm | ||
| 8920 | outTp := match(outTp, checkTypes) | ||
| 8921 | local | ||
| 8922 | |||
| 8923 | case (_, true) then tp; | ||
| 8924 | |||
| 8925 | // When not checking types, create function type by looking at the filled slots | ||
| 8926 | case (DAE.T_FUNCTION(), _) | ||
| 8927 | algorithm | ||
| 8928 | 37 | outTp.funcArg := funcArgsFromSlots(slots); | |
| 8929 | then | ||
| 8930 | outTp; | ||
| 8931 | |||
| 8932 | end match; | ||
| 8933 | end createActualFunctype; | ||
| 8934 | |||
| 8935 | protected function slotsVectorizable | ||
| 8936 | "author: PA | ||
| 8937 | This function checks all vectorized array dimensions in the slots and | ||
| 8938 | confirms that they all are of same dimension,or no dimension, i.e. not | ||
| 8939 | vectorized. The uniform vectorized array dimension is returned." | ||
| 8940 | input list<Slot> inSlots; | ||
| 8941 | input SourceInfo info; | ||
| 8942 | output DAE.Dimensions outDims; | ||
| 8943 | algorithm | ||
| 8944 | outDims := matchcontinue inSlots | ||
| 8945 | local | ||
| 8946 | DAE.Dimensions ad; | ||
| 8947 | list<Slot> rest; | ||
| 8948 | DAE.Exp exp; | ||
| 8949 | String name; | ||
| 8950 | |||
| 8951 | case {} then {}; | ||
| 8952 | |||
| 8953 | case SLOT(defaultArg = DAE.FUNCARG(name=name), arg = SOME(exp), dims = (ad as (_ :: _))) :: rest | ||
| 8954 | algorithm | ||
| 8955 | 2413 | sameSlotsVectorizable(rest, ad, name, exp, info); | |
| 8956 | then | ||
| 8957 | ad; | ||
| 8958 | |||
| 8959 | 100595 | case SLOT(dims = {}) :: rest then slotsVectorizable(rest, info); | |
| 8960 | |||
| 8961 | else | ||
| 8962 | algorithm | ||
| 8963 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 8964 | ✗ | Debug.trace("-slots_vectorizable failed\n"); | |
| 8965 | ✗ | then | |
| 8966 | fail(); | ||
| 8967 | end matchcontinue; | ||
| 8968 | end slotsVectorizable; | ||
| 8969 | |||
| 8970 | protected function sameSlotsVectorizable | ||
| 8971 | "author: PA | ||
| 8972 | This function succeds if all slots in the list either has the array | ||
| 8973 | dimension as given by the second argument or no array dimension at all. | ||
| 8974 | The array dimension must match both in dimension size and number of | ||
| 8975 | dimensions." | ||
| 8976 | input list<Slot> inSlots; | ||
| 8977 | input DAE.Dimensions inDims; | ||
| 8978 | input String name; | ||
| 8979 | input DAE.Exp exp; | ||
| 8980 | input SourceInfo info; | ||
| 8981 | algorithm | ||
| 8982 | () := match inSlots | ||
| 8983 | local | ||
| 8984 | DAE.Dimensions slot_ad; | ||
| 8985 | list<Slot> rest; | ||
| 8986 | DAE.Exp exp2; | ||
| 8987 | String name2; | ||
| 8988 | |||
| 8989 | // Array dims must match. | ||
| 8990 | case SLOT(defaultArg = DAE.FUNCARG(name=name2), arg = SOME(exp2), dims = (slot_ad as (_ :: _))) :: rest | ||
| 8991 | algorithm | ||
| 8992 | 469 | sameArraydimLst(inDims, name, exp, slot_ad, name2, exp2, info); | |
| 8993 | 469 | sameSlotsVectorizable(rest, inDims, name, exp, info); | |
| 8994 | then | ||
| 8995 | (); | ||
| 8996 | |||
| 8997 | // Empty array dims matches too. | ||
| 8998 | case SLOT(dims = {}) :: rest | ||
| 8999 | algorithm | ||
| 9000 | 322 | sameSlotsVectorizable(rest, inDims, name, exp, info); | |
| 9001 | then | ||
| 9002 | (); | ||
| 9003 | |||
| 9004 | case {} then (); | ||
| 9005 | end match; | ||
| 9006 | end sameSlotsVectorizable; | ||
| 9007 | |||
| 9008 | protected function sameArraydimLst | ||
| 9009 | "author: PA | ||
| 9010 | Helper function to sameSlotsVectorizable. " | ||
| 9011 | input DAE.Dimensions inDims1; | ||
| 9012 | input String name1; | ||
| 9013 | input DAE.Exp exp1; | ||
| 9014 | input DAE.Dimensions inDims2; | ||
| 9015 | input String name2; | ||
| 9016 | input DAE.Exp exp2; | ||
| 9017 | input SourceInfo info; | ||
| 9018 | algorithm | ||
| 9019 | ():= matchcontinue (inDims2, inDims2) | ||
| 9020 | local | ||
| 9021 | Integer i1,i2; | ||
| 9022 | DAE.Dimensions ads1,ads2; | ||
| 9023 | DAE.Exp e1,e2; | ||
| 9024 | DAE.Dimension ad1,ad2; | ||
| 9025 | String str1,str2,str3,str4; | ||
| 9026 | |||
| 9027 | case (DAE.DIM_INTEGER(integer = i1) :: ads1, | ||
| 9028 | DAE.DIM_INTEGER(integer = i2) :: ads2) | ||
| 9029 | algorithm | ||
| 9030 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 468 times.
|
468 | true := intEq(i1, i2); |
| 9031 | 468 | sameArraydimLst(ads1, name1, exp1, ads2, name2, exp2, info); | |
| 9032 | then | ||
| 9033 | (); | ||
| 9034 | |||
| 9035 | case (DAE.DIM_UNKNOWN() :: ads1, DAE.DIM_UNKNOWN() :: ads2) | ||
| 9036 | algorithm | ||
| 9037 | ✗ | sameArraydimLst(ads1, name1, exp1, ads2, name2, exp2, info); | |
| 9038 | then | ||
| 9039 | (); | ||
| 9040 | |||
| 9041 | case (DAE.DIM_EXP(e1) :: ads1, DAE.DIM_EXP(e2) :: ads2) | ||
| 9042 | algorithm | ||
| 9043 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | true := ExpressionBasics.expEqual(e1,e2); |
| 9044 | 2 | sameArraydimLst(ads1, name1, exp1, ads2, name2, exp2, info); | |
| 9045 | then | ||
| 9046 | (); | ||
| 9047 | |||
| 9048 | case ({}, {}) then (); | ||
| 9049 | |||
| 9050 | case (ad1 :: _, ad2 :: _) | ||
| 9051 | algorithm | ||
| 9052 | ✗ | str1 := ExpressionBasics.printExpStr(exp1); | |
| 9053 | ✗ | str2 := ExpressionBasics.printExpStr(exp2); | |
| 9054 | ✗ | str3 := ExpressionBasics.dimensionString(ad1); | |
| 9055 | ✗ | str4 := ExpressionBasics.dimensionString(ad2); | |
| 9056 | ✗ | Error.addSourceMessage(Error.VECTORIZE_CALL_DIM_MISMATCH, {name1,str1,name2,str2,str3,str4}, info); | |
| 9057 | ✗ | then | |
| 9058 | fail(); | ||
| 9059 | |||
| 9060 | end matchcontinue; | ||
| 9061 | end sameArraydimLst; | ||
| 9062 | |||
| 9063 | protected function getProperties | ||
| 9064 | "This function creates a Properties object from a DAE.Type and a | ||
| 9065 | DAE.TupleConst value." | ||
| 9066 | input DAE.Type inType; | ||
| 9067 | input DAE.TupleConst inTupleConst; | ||
| 9068 | output DAE.Properties outProperties; | ||
| 9069 | algorithm | ||
| 9070 | outProperties := match(inType,inTupleConst) | ||
| 9071 | local | ||
| 9072 | DAE.Type tt,t,ty; | ||
| 9073 | DAE.TupleConst const; | ||
| 9074 | DAE.Const b; | ||
| 9075 | String tystr,conststr; | ||
| 9076 | |||
| 9077 | // At least two elements in the type list, this is a tuple. LS: Tuples are fixed before here | ||
| 9078 | 1566 | case (tt as DAE.T_TUPLE(),const) then DAE.PROP_TUPLE(tt,const); | |
| 9079 | |||
| 9080 | // One type, this is a tuple with one element. The resulting properties is then identical to that of a single expression. | ||
| 9081 | 75488 | case (t,DAE.TUPLE_CONST(tupleConstLst = (DAE.SINGLE_CONST(const = b) :: {}))) then DAE.PROP(t,b); | |
| 9082 | ✗ | case (t,DAE.TUPLE_CONST(tupleConstLst = (DAE.SINGLE_CONST(const = b) :: {}))) then DAE.PROP(t,b); | |
| 9083 | ✗ | case (t,DAE.SINGLE_CONST(const = b)) then DAE.PROP(t,b); | |
| 9084 | |||
| 9085 | // failure | ||
| 9086 | case (ty,const) | ||
| 9087 | algorithm | ||
| 9088 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 9089 | ✗ | Debug.trace("- Static.getProperties failed: "); | |
| 9090 | ✗ | tystr := TypesDump.unparseType(ty); | |
| 9091 | ✗ | conststr := TypesDump.printTupleConstStr(const); | |
| 9092 | ✗ | Debug.trace(tystr); | |
| 9093 | ✗ | Debug.trace(", "); | |
| 9094 | ✗ | Debug.traceln(conststr); | |
| 9095 | ✗ | then | |
| 9096 | fail(); | ||
| 9097 | |||
| 9098 | end match; | ||
| 9099 | end getProperties; | ||
| 9100 | |||
| 9101 | protected function elabConsts "author: PR | ||
| 9102 | This just splits the properties list into a type list and a const list. | ||
| 9103 | LS: Changed to take a Type, which is the functions return type. | ||
| 9104 | LS: Update: const is derived from the input arguments and sent here." | ||
| 9105 | input DAE.Type inType; | ||
| 9106 | input DAE.Const inConst; | ||
| 9107 | output DAE.TupleConst outTupleConst; | ||
| 9108 | algorithm | ||
| 9109 | outTupleConst := match(inType,inConst) | ||
| 9110 | local | ||
| 9111 | list<DAE.TupleConst> consts; | ||
| 9112 | list<DAE.Type> tys; | ||
| 9113 | DAE.Const c; | ||
| 9114 | DAE.Type ty; | ||
| 9115 | |||
| 9116 | case (DAE.T_TUPLE(types = tys), c) | ||
| 9117 | algorithm | ||
| 9118 | 1566 | consts := checkConsts(tys, c); | |
| 9119 | 1566 | then | |
| 9120 | DAE.TUPLE_CONST(consts); | ||
| 9121 | |||
| 9122 | // LS: If not a tuple then one normal type, T_INTEGER etc, but we make a list of types | ||
| 9123 | // with one element and call the same check_consts, so that we always have DAE.TUPLE_CONST as result | ||
| 9124 | case (ty, c) | ||
| 9125 | algorithm | ||
| 9126 | 75488 | consts := checkConsts({ty}, c); | |
| 9127 | 75488 | then | |
| 9128 | DAE.TUPLE_CONST(consts); | ||
| 9129 | |||
| 9130 | end match; | ||
| 9131 | end elabConsts; | ||
| 9132 | |||
| 9133 | protected function checkConsts | ||
| 9134 | "LS: Changed to take a Type list, which is the functions return type. Only | ||
| 9135 | for functions returning a tuple | ||
| 9136 | LS: Update: const is derived from the input arguments and sent here " | ||
| 9137 | input list<DAE.Type> inTypes; | ||
| 9138 | input DAE.Const inConst; | ||
| 9139 | output list<DAE.TupleConst> outTupleConsts; | ||
| 9140 | algorithm | ||
| 9141 |
4/4✓ Branch 0 taken 79362 times.
✓ Branch 1 taken 77054 times.
✓ Branch 2 taken 79362 times.
✓ Branch 3 taken 77054 times.
|
156416 | outTupleConsts := list(checkConst(ty, inConst) for ty in inTypes); |
| 9142 | end checkConsts; | ||
| 9143 | |||
| 9144 | protected function checkConst "author: PR | ||
| 9145 | At the moment this make all outputs non cons. | ||
| 9146 | All ouputs should be checked in the function body for constness. | ||
| 9147 | LS: but it says true? | ||
| 9148 | LS: Adapted to check one type instead of funcarg, since it just checks | ||
| 9149 | return type | ||
| 9150 | LS: Update: const is derived from the input arguments and sent here" | ||
| 9151 | input DAE.Type inType; | ||
| 9152 | input DAE.Const c; | ||
| 9153 | output DAE.TupleConst outTupleConst; | ||
| 9154 | algorithm | ||
| 9155 | outTupleConst := match inType | ||
| 9156 | case DAE.T_TUPLE() | ||
| 9157 | algorithm | ||
| 9158 | ✗ | Error.addInternalError("No support for tuples built by tuples", sourceInfo()); | |
| 9159 | ✗ | then fail(); | |
| 9160 | |||
| 9161 | 79362 | else DAE.SINGLE_CONST(c); | |
| 9162 | end match; | ||
| 9163 | end checkConst; | ||
| 9164 | |||
| 9165 | protected function splitProps | ||
| 9166 | "Splits the properties list into the separated types list and const list." | ||
| 9167 | input list<DAE.Properties> inProperties; | ||
| 9168 | output list<DAE.Type> outTypes = {}; | ||
| 9169 | output list<DAE.TupleConst> outConsts = {}; | ||
| 9170 | protected | ||
| 9171 | DAE.Type ty; | ||
| 9172 | DAE.Const c; | ||
| 9173 | DAE.TupleConst tc; | ||
| 9174 | algorithm | ||
| 9175 |
2/2✓ Branch 1 taken 6300 times.
✓ Branch 2 taken 3149 times.
|
9449 | for prop in listReverse(inProperties) loop |
| 9176 | tc := match prop | ||
| 9177 | 6300 | case DAE.PROP(type_ = ty, constFlag = c) then DAE.SINGLE_CONST(c); | |
| 9178 | case DAE.PROP_TUPLE(type_ = ty, tupleConst = tc) then tc; | ||
| 9179 | end match; | ||
| 9180 | |||
| 9181 | outTypes := ty :: outTypes; | ||
| 9182 | outConsts := tc :: outConsts; | ||
| 9183 | end for; | ||
| 9184 | end splitProps; | ||
| 9185 | |||
| 9186 | protected function getTypes | ||
| 9187 | "This function returns the types of a DAE.FuncArg list." | ||
| 9188 | input list<DAE.FuncArg> farg; | ||
| 9189 | output list<DAE.Type> outTypes; | ||
| 9190 | algorithm | ||
| 9191 | ✗ | outTypes := list(Types.funcArgType(arg) for arg in farg); | |
| 9192 | end getTypes; | ||
| 9193 | |||
| 9194 | protected function elabInputArgs | ||
| 9195 | "This function_ elaborates on a number of expressions and_ matches them to a | ||
| 9196 | number of `DAE.Var\' objects, applying type_ conversions on the expressions | ||
| 9197 | when necessary to match the type_ of the DAE.Var. | ||
| 9198 | |||
| 9199 | Positional arguments and named arguments are filled in the argument slots as: | ||
| 9200 | 1. Positional arguments fill the first slots according to their position. | ||
| 9201 | 2. Named arguments fill slots with the same name as the named argument. | ||
| 9202 | 3. Unfilled slots are checked so that they have default values, otherwise error." | ||
| 9203 | input FCore.Cache inCache; | ||
| 9204 | input FCore.Graph inEnv; | ||
| 9205 | input list<Absyn.Exp> inPosArgs; | ||
| 9206 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 9207 | input list<Slot> inSlots; | ||
| 9208 | input Boolean inOnlyOneFunction; | ||
| 9209 | input Boolean inCheckTypes "if true, check types"; | ||
| 9210 | input Boolean inImplicit; | ||
| 9211 | input DAE.Prefix inPrefix; | ||
| 9212 | input SourceInfo inInfo; | ||
| 9213 | input DAE.Type inFuncType "Used to determine which arguments are structural. We will evaluate them later to figure if they are used in dimensions. So we evaluate them here to get a more optimised DAE"; | ||
| 9214 | input Absyn.Path inPath; | ||
| 9215 | input Boolean isGraphicsExp = false; | ||
| 9216 | output FCore.Cache outCache = inCache; | ||
| 9217 | output list<DAE.Exp> outExps; | ||
| 9218 | output list<Slot> outSlots = inSlots; | ||
| 9219 | output list<DAE.Const> outConsts; | ||
| 9220 | output InstTypes.PolymorphicBindings outPolymorphicBindings = {}; | ||
| 9221 | protected | ||
| 9222 | list<DAE.FuncArg> fargs; | ||
| 9223 | list<DAE.Const> consts1, consts2; | ||
| 9224 | algorithm | ||
| 9225 | // Empty function call, e.g. foo(), is always constant. | ||
| 9226 | // adrpo 2010-11-09: TODO! FIXME! This is not always true, RecordCall() can | ||
| 9227 | // contain DEFAULT bindings that are param. | ||
| 9228 |
4/4✓ Branch 0 taken 18281 times.
✓ Branch 1 taken 61556 times.
✓ Branch 2 taken 818 times.
✓ Branch 3 taken 17463 times.
|
79837 | if listEmpty(inPosArgs) and listEmpty(inNamedArgs) then |
| 9229 | outConsts := {DAE.C_CONST()}; | ||
| 9230 | else | ||
| 9231 | 62374 | fargs := funcArgsFromSlots(inSlots); | |
| 9232 | |||
| 9233 | // Elaborate positional arguments. | ||
| 9234 | 62374 | (outCache, outSlots, consts1, outPolymorphicBindings) := | |
| 9235 | elabPositionalInputArgs(outCache, inEnv, inPosArgs, fargs, outSlots, | ||
| 9236 | inOnlyOneFunction, inCheckTypes, inImplicit, | ||
| 9237 | outPolymorphicBindings, inPrefix, inInfo, inPath, isGraphicsExp); | ||
| 9238 | |||
| 9239 | // Elaborate named arguments. | ||
| 9240 | 61282 | (outCache, outSlots, consts2, outPolymorphicBindings) := | |
| 9241 | elabNamedInputArgs(outCache, inEnv, inNamedArgs, fargs, outSlots, | ||
| 9242 | inOnlyOneFunction, inCheckTypes, inImplicit, | ||
| 9243 | outPolymorphicBindings, inPrefix, inInfo, inPath, isGraphicsExp); | ||
| 9244 | |||
| 9245 | 61257 | outConsts := listAppend(consts1, consts2); | |
| 9246 | end if; | ||
| 9247 | |||
| 9248 | 78720 | (outCache, outSlots) := evaluateStructuralSlots(outCache, inEnv, outSlots, inFuncType); | |
| 9249 | 78720 | outExps := slotListArgs(outSlots); | |
| 9250 | end elabInputArgs; | ||
| 9251 | |||
| 9252 | protected function makeEmptySlots | ||
| 9253 | "Creates a list of empty slots given a list of function parameters." | ||
| 9254 | input list<DAE.FuncArg> inArgs; | ||
| 9255 | output list<Slot> outSlots; | ||
| 9256 | algorithm | ||
| 9257 | 78351 | outSlots := List.mapFold(inArgs, makeEmptySlot, 1); | |
| 9258 | end makeEmptySlots; | ||
| 9259 | |||
| 9260 | protected function makeEmptySlot | ||
| 9261 | input DAE.FuncArg inArg; | ||
| 9262 | input Integer inIndex; | ||
| 9263 | output Slot outSlot; | ||
| 9264 | output Integer outIndex; | ||
| 9265 | algorithm | ||
| 9266 | 143845 | outSlot := SLOT(inArg, false, NONE(), {}, inIndex, SLOT_NOT_EVALUATED); | |
| 9267 |
1/2✓ Branch 0 taken 143845 times.
✗ Branch 1 not taken.
|
143845 | outIndex := inIndex + 1; |
| 9268 | end makeEmptySlot; | ||
| 9269 | |||
| 9270 | protected function funcArgsFromSlots | ||
| 9271 | "Converts a list of Slot to a list of FuncArg." | ||
| 9272 | input list<Slot> inSlots; | ||
| 9273 | output list<DAE.FuncArg> outFuncArgs; | ||
| 9274 | algorithm | ||
| 9275 |
4/4✓ Branch 0 taken 143695 times.
✓ Branch 1 taken 62411 times.
✓ Branch 2 taken 143695 times.
✓ Branch 3 taken 62411 times.
|
206106 | outFuncArgs := list(funcArgFromSlot(slot) for slot in inSlots); |
| 9276 | end funcArgsFromSlots; | ||
| 9277 | |||
| 9278 | protected function funcArgFromSlot | ||
| 9279 | input Slot inSlot; | ||
| 9280 | output DAE.FuncArg outFuncArg; | ||
| 9281 | algorithm | ||
| 9282 | 143695 | SLOT(defaultArg = outFuncArg) := inSlot; | |
| 9283 | end funcArgFromSlot; | ||
| 9284 | |||
| 9285 | protected function complexTypeFromSlots | ||
| 9286 | "Creates an DAE.T_COMPLEX type from a list of slots. | ||
| 9287 | Used to create type of record constructors " | ||
| 9288 | input list<Slot> inSlots; | ||
| 9289 | input ClassInf.State complexClassType; | ||
| 9290 | output DAE.Type outType; | ||
| 9291 | protected | ||
| 9292 | String id; | ||
| 9293 | DAE.Type ty; | ||
| 9294 | list<DAE.Var> vars = {}; | ||
| 9295 | algorithm | ||
| 9296 |
2/2✓ Branch 0 taken 128 times.
✓ Branch 1 taken 13 times.
|
141 | for slot in inSlots loop |
| 9297 | 128 | SLOT(defaultArg = DAE.FUNCARG(name = id, ty = ty)) := slot; | |
| 9298 | 128 | vars := Expression.makeVar(id, Types.simplifyType(ty)) :: vars; | |
| 9299 | end for; | ||
| 9300 | |||
| 9301 | 13 | vars := listReverse(vars); | |
| 9302 | 13 | outType := DAE.T_COMPLEX(complexClassType, vars, NONE(), false); | |
| 9303 | end complexTypeFromSlots; | ||
| 9304 | |||
| 9305 | protected function slotListArgs | ||
| 9306 | "Gets the argument expressions from a list of slots." | ||
| 9307 | input list<Slot> inSlots; | ||
| 9308 | output list<DAE.Exp> outArgs; | ||
| 9309 | algorithm | ||
| 9310 | 99495 | outArgs := List.filterMap(inSlots, slotArg); | |
| 9311 | end slotListArgs; | ||
| 9312 | |||
| 9313 | protected function slotArg | ||
| 9314 | "Gets the argument from a slot." | ||
| 9315 | input Slot inSlot; | ||
| 9316 | output DAE.Exp outArg; | ||
| 9317 | algorithm | ||
| 9318 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 187249 times.
✓ Branch 2 taken 22076 times.
✓ Branch 3 taken 165173 times.
|
187249 | SLOT(arg = SOME(outArg)) := inSlot; |
| 9319 | end slotArg; | ||
| 9320 | |||
| 9321 | protected function fillGraphicsDefaultSlots | ||
| 9322 | "This function takes a slot list and a class definition of a function | ||
| 9323 | and fills default values into slots which have not been filled. | ||
| 9324 | |||
| 9325 | Special case for graphics exps" | ||
| 9326 | input FCore.Cache inCache; | ||
| 9327 | input list<Slot> inSlots; | ||
| 9328 | input SCode.Element inClass; | ||
| 9329 | input FCore.Graph inEnv; | ||
| 9330 | input Boolean inImplicit; | ||
| 9331 | input DAE.Prefix inPrefix; | ||
| 9332 | input SourceInfo inInfo; | ||
| 9333 | output FCore.Cache outCache = inCache; | ||
| 9334 | output list<Slot> outSlots = {}; | ||
| 9335 | output list<DAE.Const> outConsts = {}; | ||
| 9336 | output InstTypes.PolymorphicBindings outPolymorphicBindings = {}; | ||
| 9337 | protected | ||
| 9338 | Boolean filled; | ||
| 9339 | Absyn.Exp e; | ||
| 9340 | DAE.Exp exp; | ||
| 9341 | DAE.FuncArg defarg; | ||
| 9342 | DAE.Type ty; | ||
| 9343 | DAE.Const c; | ||
| 9344 | algorithm | ||
| 9345 |
2/2✓ Branch 0 taken 128 times.
✓ Branch 1 taken 13 times.
|
141 | for slot in inSlots loop |
| 9346 | 128 | SLOT(slotFilled = filled) := slot; | |
| 9347 | |||
| 9348 | // Try to fill the slot if it's not yet filled. | ||
| 9349 |
2/2✓ Branch 0 taken 82 times.
✓ Branch 1 taken 46 times.
|
128 | if not filled then |
| 9350 | slot := matchcontinue slot | ||
| 9351 | case SLOT(defaultArg = defarg as DAE.FUNCARG()) | ||
| 9352 | algorithm | ||
| 9353 |
4/8✗ Branch 1 not taken.
✓ Branch 2 taken 82 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 82 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 82 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 82 times.
|
82 | SCode.COMPONENT(modifications = SCode.MOD(binding = SOME(e))) := |
| 9354 | SCodeUtil.getElementNamed(defarg.name, inClass); | ||
| 9355 | |||
| 9356 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 82 times.
|
82 | (outCache, exp, DAE.PROP(ty, c)) := |
| 9357 | elabExpInExpression(outCache, inEnv, e, inImplicit, true, inPrefix, inInfo); | ||
| 9358 | |||
| 9359 | 82 | (exp, _, outPolymorphicBindings) := Types.matchTypePolymorphic(exp, | |
| 9360 | ty, defarg.ty, FGraph.getGraphPathNoImplicitScope(inEnv), outPolymorphicBindings, false); | ||
| 9361 | |||
| 9362 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 82 times.
|
82 | true := Types.constEqualOrHigher(c, defarg.const); |
| 9363 | 82 | outConsts := c :: outConsts; | |
| 9364 | |||
| 9365 | 82 | slot.slotFilled := true; | |
| 9366 | 82 | slot.arg := SOME(exp); | |
| 9367 | then | ||
| 9368 | slot; | ||
| 9369 | |||
| 9370 | ✗ | else slot; | |
| 9371 | end matchcontinue; | ||
| 9372 | end if; | ||
| 9373 | |||
| 9374 | outSlots := slot :: outSlots; | ||
| 9375 | end for; | ||
| 9376 | |||
| 9377 | 13 | outSlots := listReverse(outSlots); | |
| 9378 | 13 | outConsts := listReverse(outConsts); | |
| 9379 | end fillGraphicsDefaultSlots; | ||
| 9380 | |||
| 9381 | protected function printSlotsStr | ||
| 9382 | "prints the slots to a string" | ||
| 9383 | input list<Slot> inSlots; | ||
| 9384 | output String outString; | ||
| 9385 | algorithm | ||
| 9386 | outString := match inSlots | ||
| 9387 | local | ||
| 9388 | Boolean filled; | ||
| 9389 | String farg_str,filledStr,str,s,s1,s2,res; | ||
| 9390 | list<String> str_lst; | ||
| 9391 | DAE.FuncArg farg; | ||
| 9392 | Option<DAE.Exp> exp; | ||
| 9393 | DAE.Dimensions ds; | ||
| 9394 | list<Slot> xs; | ||
| 9395 | |||
| 9396 | case SLOT(defaultArg = farg,slotFilled = filled,arg = exp,dims = ds) :: xs | ||
| 9397 | algorithm | ||
| 9398 | ✗ | farg_str := TypesDump.printFargStr(farg); | |
| 9399 | ✗ | filledStr := if filled then "filled" else "not filled"; | |
| 9400 | ✗ | str := Util.applyOptionOrDefault(exp, ExpressionBasics.printExpStr, ""); | |
| 9401 | ✗ | str_lst := List.map(ds, ExpressionBasics.dimensionString); | |
| 9402 | ✗ | s := stringDelimitList(str_lst, ", "); | |
| 9403 | ✗ | s1 := stringAppendList({"SLOT(",farg_str,", ",filledStr,", ",str,", [",s,"])\n"}); | |
| 9404 | ✗ | s2 := printSlotsStr(xs); | |
| 9405 | ✗ | res := stringAppend(s1, s2); | |
| 9406 | then | ||
| 9407 | res; | ||
| 9408 | |||
| 9409 | case {} then ""; | ||
| 9410 | |||
| 9411 | end match; | ||
| 9412 | end printSlotsStr; | ||
| 9413 | |||
| 9414 | protected function isFreeParameterExp | ||
| 9415 | "Checks if inExp is a an expression of free parameters." | ||
| 9416 | input DAE.Exp inExp; | ||
| 9417 | input FCore.Cache inCache; | ||
| 9418 | input FCore.Graph inEnv; | ||
| 9419 | output Boolean isFree; | ||
| 9420 | output FCore.Cache outCache; | ||
| 9421 | algorithm | ||
| 9422 | ✗ | outCache := inCache; | |
| 9423 | isFree := match inExp | ||
| 9424 | local | ||
| 9425 | DAE.ComponentRef cr; | ||
| 9426 | DAE.Binding binding; | ||
| 9427 | DAE.Exp exp1, exp2; | ||
| 9428 | list<DAE.Exp> exps; | ||
| 9429 | list<list<DAE.Exp>> mat; | ||
| 9430 | Boolean isFree2; | ||
| 9431 | |||
| 9432 | case DAE.ICONST() then true; | ||
| 9433 | |||
| 9434 | case DAE.RCONST() then true; | ||
| 9435 | |||
| 9436 | case DAE.SCONST() then true; | ||
| 9437 | |||
| 9438 | case DAE.BCONST() then true; | ||
| 9439 | |||
| 9440 | case DAE.CREF(componentRef = cr) | ||
| 9441 | algorithm | ||
| 9442 | ✗ | (outCache, _, _, binding, _, _, _, _, _) := Lookup.lookupVar(inCache, inEnv, cr); | |
| 9443 | then | ||
| 9444 | match binding | ||
| 9445 | case DAE.VALBOUND() then | ||
| 9446 | true; | ||
| 9447 | case DAE.EQBOUND(exp = exp1) | ||
| 9448 | guard | ||
| 9449 | Expression.isConst(exp1) | ||
| 9450 | then | ||
| 9451 | true; | ||
| 9452 | else | ||
| 9453 | false; | ||
| 9454 | end match; | ||
| 9455 | |||
| 9456 | case DAE.BINARY(exp1 = exp1, exp2 = exp2) | ||
| 9457 | algorithm | ||
| 9458 | ✗ | (isFree, outCache) := isFreeParameterExp(exp1, inCache, inEnv); | |
| 9459 | ✗ | (isFree2, outCache) := isFreeParameterExp(exp2, outCache, inEnv); | |
| 9460 | ✗ | then | |
| 9461 | isFree and isFree2; | ||
| 9462 | |||
| 9463 | case DAE.UNARY(exp = exp1) | ||
| 9464 | algorithm | ||
| 9465 | ✗ | (isFree, outCache) := isFreeParameterExp(exp1, inCache, inEnv); | |
| 9466 | then | ||
| 9467 | isFree; | ||
| 9468 | |||
| 9469 | case DAE.LBINARY(exp1 = exp1, exp2 = exp2) | ||
| 9470 | algorithm | ||
| 9471 | ✗ | (isFree, outCache) := isFreeParameterExp(exp1, inCache, inEnv); | |
| 9472 | ✗ | (isFree2, outCache) := isFreeParameterExp(exp2, outCache, inEnv); | |
| 9473 | ✗ | then | |
| 9474 | isFree and isFree2; | ||
| 9475 | |||
| 9476 | case DAE.LUNARY(exp = exp1) | ||
| 9477 | algorithm | ||
| 9478 | ✗ | (isFree, outCache) := isFreeParameterExp(exp1, inCache, inEnv); | |
| 9479 | then | ||
| 9480 | isFree; | ||
| 9481 | |||
| 9482 | case DAE.CALL(expLst = exps) | ||
| 9483 | algorithm | ||
| 9484 | outCache := inCache; | ||
| 9485 | isFree := true; | ||
| 9486 | ✗ | for exp in exps loop | |
| 9487 | ✗ | (isFree2, outCache) := isFreeParameterExp(exp, outCache, inEnv); | |
| 9488 | ✗ | isFree := isFree and isFree2; | |
| 9489 | end for; | ||
| 9490 | then | ||
| 9491 | isFree; | ||
| 9492 | |||
| 9493 | case DAE.ARRAY(array = exps) | ||
| 9494 | algorithm | ||
| 9495 | outCache := inCache; | ||
| 9496 | isFree := true; | ||
| 9497 | ✗ | for exp in exps loop | |
| 9498 | ✗ | (isFree2, outCache) := isFreeParameterExp(exp, outCache, inEnv); | |
| 9499 | ✗ | isFree := isFree and isFree2; | |
| 9500 | end for; | ||
| 9501 | then | ||
| 9502 | isFree; | ||
| 9503 | |||
| 9504 | case DAE.MATRIX(matrix = mat) | ||
| 9505 | algorithm | ||
| 9506 | outCache := inCache; | ||
| 9507 | isFree := true; | ||
| 9508 | ✗ | for row in mat loop | |
| 9509 | ✗ | for exp in row loop | |
| 9510 | ✗ | (isFree2, outCache) := isFreeParameterExp(exp, outCache, inEnv); | |
| 9511 | ✗ | isFree := isFree and isFree2; | |
| 9512 | end for; | ||
| 9513 | end for; | ||
| 9514 | then | ||
| 9515 | isFree; | ||
| 9516 | |||
| 9517 | case DAE.CAST(exp = exp1) | ||
| 9518 | algorithm | ||
| 9519 | ✗ | (isFree, outCache) := isFreeParameterExp(exp1, inCache, inEnv); | |
| 9520 | then | ||
| 9521 | isFree; | ||
| 9522 | |||
| 9523 | else | ||
| 9524 | false; | ||
| 9525 | end match; | ||
| 9526 | end isFreeParameterExp; | ||
| 9527 | |||
| 9528 | protected function elabPositionalInputArgs | ||
| 9529 | "This function elaborates the positional input arguments of a function. | ||
| 9530 | A list of slots is filled from the beginning with types of each | ||
| 9531 | positional argument." | ||
| 9532 | input FCore.Cache inCache; | ||
| 9533 | input FCore.Graph inEnv; | ||
| 9534 | input list<Absyn.Exp> inPosArgs; | ||
| 9535 | input list<DAE.FuncArg> inFuncArgs; | ||
| 9536 | input list<Slot> inSlots; | ||
| 9537 | input Boolean inOnlyOneFunction; | ||
| 9538 | input Boolean inCheckTypes "if true, check types"; | ||
| 9539 | input Boolean inImplicit; | ||
| 9540 | input InstTypes.PolymorphicBindings inPolymorphicBindings; | ||
| 9541 | input DAE.Prefix inPrefix; | ||
| 9542 | input SourceInfo inInfo; | ||
| 9543 | input Absyn.Path inPath; | ||
| 9544 | input Boolean isGraphicsExp; | ||
| 9545 | output FCore.Cache outCache = inCache; | ||
| 9546 | output list<Slot> outSlots = inSlots; | ||
| 9547 | output list<DAE.Const> outConsts = {}; | ||
| 9548 | output InstTypes.PolymorphicBindings outPolymorphicBindings = inPolymorphicBindings; | ||
| 9549 | protected | ||
| 9550 | DAE.FuncArg farg; | ||
| 9551 | list<DAE.FuncArg> farg_rest = inFuncArgs; | ||
| 9552 | DAE.Const c; | ||
| 9553 | Integer position = 1; | ||
| 9554 | algorithm | ||
| 9555 |
2/2✓ Branch 0 taken 120123 times.
✓ Branch 1 taken 61282 times.
|
181405 | for arg in inPosArgs loop |
| 9556 |
2/2✓ Branch 0 taken 264 times.
✓ Branch 1 taken 119859 times.
|
120123 | farg :: farg_rest := farg_rest; |
| 9557 | |||
| 9558 | 119859 | (outCache, outSlots, c, outPolymorphicBindings) := | |
| 9559 | elabPositionalInputArg(outCache, inEnv, arg, farg, position, outSlots, | ||
| 9560 | inOnlyOneFunction, inCheckTypes, inImplicit, | ||
| 9561 | outPolymorphicBindings, inPrefix, inInfo, inPath, isGraphicsExp); | ||
| 9562 | |||
| 9563 | 119031 | position := position + 1; | |
| 9564 | 119031 | outConsts := c :: outConsts; | |
| 9565 | end for; | ||
| 9566 | |||
| 9567 | 61282 | outConsts := listReverse(outConsts); | |
| 9568 | end elabPositionalInputArgs; | ||
| 9569 | |||
| 9570 | protected function elabPositionalInputArg | ||
| 9571 | "This function elaborates the positional input arguments of a function. | ||
| 9572 | A list of slots is filled from the beginning with types of each | ||
| 9573 | positional argument." | ||
| 9574 | input FCore.Cache inCache; | ||
| 9575 | input FCore.Graph inEnv; | ||
| 9576 | input Absyn.Exp inExp; | ||
| 9577 | input DAE.FuncArg farg; | ||
| 9578 | input Integer position; | ||
| 9579 | input list<Slot> inSlotLst; | ||
| 9580 | input Boolean onlyOneFunction; | ||
| 9581 | input Boolean checkTypes "if true, check types"; | ||
| 9582 | input Boolean impl; | ||
| 9583 | input InstTypes.PolymorphicBindings inPolymorphicBindings; | ||
| 9584 | input DAE.Prefix inPrefix; | ||
| 9585 | input SourceInfo info; | ||
| 9586 | input Absyn.Path path; | ||
| 9587 | input Boolean isGraphicsExp; | ||
| 9588 | output FCore.Cache outCache; | ||
| 9589 | output list<Slot> outSlotLst; | ||
| 9590 | output DAE.Const outConst; | ||
| 9591 | output InstTypes.PolymorphicBindings outPolymorphicBindings; | ||
| 9592 | protected | ||
| 9593 | Integer numErrors = Error.getNumErrorMessages(); | ||
| 9594 | algorithm | ||
| 9595 | (outCache,outSlotLst,outConst,outPolymorphicBindings):= | ||
| 9596 | matchcontinue (inCache, inEnv, inExp, farg, inSlotLst, onlyOneFunction, checkTypes, inPolymorphicBindings, inPrefix) | ||
| 9597 | local | ||
| 9598 | list<Slot> slots,slots_1; | ||
| 9599 | DAE.Exp e_1,e_2; | ||
| 9600 | DAE.Type t,vt; | ||
| 9601 | DAE.Const c1; | ||
| 9602 | DAE.VarParallelism pr; | ||
| 9603 | DAE.Properties prop; | ||
| 9604 | FCore.Graph env; | ||
| 9605 | Absyn.Exp e; | ||
| 9606 | DAE.Dimensions ds; | ||
| 9607 | FCore.Cache cache; | ||
| 9608 | String id; | ||
| 9609 | DAE.Properties props; | ||
| 9610 | DAE.Prefix pre; | ||
| 9611 | DAE.CodeType ct; | ||
| 9612 | InstTypes.PolymorphicBindings polymorphicBindings; | ||
| 9613 | String s1,s2,s3,s4,s5; | ||
| 9614 | |||
| 9615 | case (cache, env, e, DAE.FUNCARG(name=id,ty = vt as DAE.T_CODE(ct),par=pr), slots, _, true, polymorphicBindings, pre) | ||
| 9616 | algorithm | ||
| 9617 | 3836 | e_1 := elabCodeExp(e,cache,env,ct,info); | |
| 9618 | 3836 | slots_1 := fillSlot(DAE.FUNCARG(id,vt,DAE.C_VAR(),pr,NONE()), e_1, {}, slots,pre,info, path); | |
| 9619 | 3836 | then | |
| 9620 | (cache,slots_1,DAE.C_VAR(),polymorphicBindings); | ||
| 9621 | |||
| 9622 | // exact match | ||
| 9623 | case (cache, env, e, DAE.FUNCARG(name=id,ty=vt,par=pr), slots, _, true, polymorphicBindings, pre) | ||
| 9624 | algorithm | ||
| 9625 | 115977 | (cache,e_1,props) := elabExpInExpression(cache,env, e, impl, true,pre,info); | |
| 9626 | 115977 | t := Types.getPropType(props); | |
| 9627 | 115977 | vt := Types.traverseType(vt, -1, Types.makeExpDimensionsUnknown); | |
| 9628 | 115977 | c1 := Types.propAllConst(props); | |
| 9629 | 115977 | (e_2,_,polymorphicBindings) := Types.matchTypePolymorphic(e_1,t,vt,FGraph.getGraphPathNoImplicitScope(env),polymorphicBindings,false); | |
| 9630 | 112303 | slots_1 := fillSlot(DAE.FUNCARG(id,vt,c1,pr,NONE()), e_2, {}, slots,pre,info, path) "no vectorized dim" ; | |
| 9631 | 112300 | then | |
| 9632 | (cache,slots_1,c1,polymorphicBindings); | ||
| 9633 | |||
| 9634 | // check if vectorized argument | ||
| 9635 | case (cache, env, e, DAE.FUNCARG(name=id,ty=vt,par=pr), slots, _, true, polymorphicBindings, pre) | ||
| 9636 | algorithm | ||
| 9637 | 3677 | (cache,e_1,props) := elabExpInExpression(cache,env, e, impl,true,pre,info); | |
| 9638 | 3677 | t := Types.getPropType(props); | |
| 9639 | 3677 | vt := Types.traverseType(vt, -1, Types.makeExpDimensionsUnknown); | |
| 9640 | 3677 | c1 := Types.propAllConst(props); | |
| 9641 | 3677 | (e_2,_,ds,polymorphicBindings) := Types.vectorizableType(e_1, t, vt, FGraph.getGraphPathNoImplicitScope(env)); | |
| 9642 | 2852 | slots_1 := fillSlot(DAE.FUNCARG(id,vt,c1,pr,NONE()), e_2, ds, slots, pre,info, path); | |
| 9643 | 2849 | then | |
| 9644 | (cache,slots_1,c1,polymorphicBindings); | ||
| 9645 | |||
| 9646 | // not checking types | ||
| 9647 | case (cache, env, e, DAE.FUNCARG(name=id,par=pr), slots, _, false, polymorphicBindings, pre) | ||
| 9648 | algorithm | ||
| 9649 | 46 | (cache,e_1,props) := elabExpInExpression(cache,env, e, impl,true,pre,info); | |
| 9650 | 46 | t := Types.getPropType(props); | |
| 9651 | 46 | c1 := Types.propAllConst(props); | |
| 9652 | /* fill slot with actual type for error message*/ | ||
| 9653 | 46 | slots_1 := fillSlot(DAE.FUNCARG(id,t,c1,pr,NONE()), e_1, {}, slots, pre,info, path); | |
| 9654 | 46 | then | |
| 9655 | (cache,slots_1,c1,polymorphicBindings); | ||
| 9656 | |||
| 9657 | // check types and display error | ||
| 9658 | case (cache, env, e, DAE.FUNCARG(name=id,ty=vt), _, true, true, _, pre) | ||
| 9659 | algorithm | ||
| 9660 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 16 times.
|
17 | true := Error.getNumErrorMessages() == numErrors; |
| 9661 | 16 | (cache,e_1,prop) := elabExpInExpression(cache, env, e, impl, true,pre,info); | |
| 9662 | 16 | s1 := intString(position); | |
| 9663 | 16 | s2 := AbsynUtil.pathStringNoQual(path); | |
| 9664 | 16 | s3 := ExpressionBasics.printExpStr(e_1); | |
| 9665 | 16 | s4 := TypesDump.unparseTypeNoAttr(Types.getPropType(prop)); | |
| 9666 | 16 | s5 := TypesDump.unparseTypeNoAttr(vt); | |
| 9667 | 16 | Error.addSourceMessage(Error.ARG_TYPE_MISMATCH, {s1,s2,id,s3,s4,s5}, info); | |
| 9668 | 16 | then fail(); | |
| 9669 | |||
| 9670 | end matchcontinue; | ||
| 9671 | end elabPositionalInputArg; | ||
| 9672 | |||
| 9673 | protected function elabNamedInputArgs | ||
| 9674 | "This function takes an Env, a NamedArg list, a DAE.FuncArg list and a | ||
| 9675 | Slot list. | ||
| 9676 | It builds up a new slot list and a list of elaborated expressions. | ||
| 9677 | If a slot is filled twice the function fails. If a slot is not filled at | ||
| 9678 | all and the | ||
| 9679 | value is not a parameter or a constant the function also fails." | ||
| 9680 | input FCore.Cache inCache; | ||
| 9681 | input FCore.Graph inEnv; | ||
| 9682 | input list<Absyn.NamedArg> inAbsynNamedArgLst; | ||
| 9683 | input list<DAE.FuncArg> inTypesFuncArgLst; | ||
| 9684 | input list<Slot> inSlotLst; | ||
| 9685 | input Boolean onlyOneFunction; | ||
| 9686 | input Boolean checkTypes "if true, check types"; | ||
| 9687 | input Boolean impl; | ||
| 9688 | input InstTypes.PolymorphicBindings inPolymorphicBindings; | ||
| 9689 | input DAE.Prefix inPrefix; | ||
| 9690 | input SourceInfo info; | ||
| 9691 | input Absyn.Path path; | ||
| 9692 | input Boolean isGraphicsExp; | ||
| 9693 | output FCore.Cache outCache; | ||
| 9694 | output list<Slot> outSlotLst; | ||
| 9695 | output list<DAE.Const> outTypesConstLst; | ||
| 9696 | output InstTypes.PolymorphicBindings outPolymorphicBindings; | ||
| 9697 | algorithm | ||
| 9698 | (outCache,outSlotLst,outTypesConstLst,outPolymorphicBindings) := | ||
| 9699 | match (inCache,inEnv,inAbsynNamedArgLst,inTypesFuncArgLst,inSlotLst,inPolymorphicBindings) | ||
| 9700 | local | ||
| 9701 | DAE.Const c1; | ||
| 9702 | list<Slot> slots; | ||
| 9703 | list<DAE.Const> clist; | ||
| 9704 | FCore.Graph env; | ||
| 9705 | Absyn.NamedArg na; | ||
| 9706 | list<Absyn.NamedArg> nas; | ||
| 9707 | list<DAE.FuncArg> farg; | ||
| 9708 | FCore.Cache cache; | ||
| 9709 | InstTypes.PolymorphicBindings polymorphicBindings; | ||
| 9710 | |||
| 9711 | // the empty case | ||
| 9712 | case (cache,_,{},_,slots,_) | ||
| 9713 | then (cache,slots,{},inPolymorphicBindings); | ||
| 9714 | |||
| 9715 | case (cache, env, na :: nas, farg, slots, polymorphicBindings) | ||
| 9716 | algorithm | ||
| 9717 | 3393 | (cache,slots,c1,polymorphicBindings) := | |
| 9718 | elabNamedInputArg(cache, env, na, farg, slots, onlyOneFunction, checkTypes, impl, polymorphicBindings, inPrefix, info, path, Error.getNumErrorMessages(), isGraphicsExp); | ||
| 9719 | 3368 | (cache,slots,clist,polymorphicBindings) := | |
| 9720 | elabNamedInputArgs(cache, env, nas, farg, slots, onlyOneFunction, checkTypes, impl, polymorphicBindings, inPrefix, info, path, isGraphicsExp); | ||
| 9721 | 3362 | then | |
| 9722 | (cache,slots,c1::clist,polymorphicBindings); | ||
| 9723 | |||
| 9724 | end match; | ||
| 9725 | end elabNamedInputArgs; | ||
| 9726 | |||
| 9727 | protected function elabNamedInputArg | ||
| 9728 | "This function takes an Env, a NamedArg list, a DAE.FuncArg list and a | ||
| 9729 | Slot list. | ||
| 9730 | It builds up a new slot list and a list of elaborated expressions. | ||
| 9731 | If a slot is filled twice the function fails. If a slot is not filled at | ||
| 9732 | all and the | ||
| 9733 | value is not a parameter or a constant the function also fails." | ||
| 9734 | input FCore.Cache inCache; | ||
| 9735 | input FCore.Graph inEnv; | ||
| 9736 | input Absyn.NamedArg inNamedArg; | ||
| 9737 | input list<DAE.FuncArg> inTypesFuncArgLst; | ||
| 9738 | input list<Slot> inSlotLst; | ||
| 9739 | input Boolean onlyOneFunction; | ||
| 9740 | input Boolean checkTypes "if true, check types"; | ||
| 9741 | input Boolean impl; | ||
| 9742 | input InstTypes.PolymorphicBindings inPolymorphicBindings; | ||
| 9743 | input DAE.Prefix inPrefix; | ||
| 9744 | input SourceInfo info; | ||
| 9745 | input Absyn.Path path; | ||
| 9746 | input Integer numErrors; | ||
| 9747 | input Boolean isGraphicsExp; | ||
| 9748 | output FCore.Cache outCache; | ||
| 9749 | output list<Slot> outSlotLst; | ||
| 9750 | output DAE.Const outTypesConstLst; | ||
| 9751 | output InstTypes.PolymorphicBindings outPolymorphicBindings; | ||
| 9752 | algorithm | ||
| 9753 | (outCache,outSlotLst,outTypesConstLst,outPolymorphicBindings) := | ||
| 9754 | matchcontinue (inCache, inEnv, inNamedArg, inTypesFuncArgLst, inSlotLst, onlyOneFunction, checkTypes, inPolymorphicBindings, inPrefix) | ||
| 9755 | local | ||
| 9756 | DAE.Exp e_1,e_2; | ||
| 9757 | DAE.Type t,vt; | ||
| 9758 | DAE.Const c1; | ||
| 9759 | DAE.VarParallelism pr; | ||
| 9760 | list<Slot> slots_1,slots; | ||
| 9761 | FCore.Graph env; | ||
| 9762 | String id; | ||
| 9763 | Absyn.Exp e; | ||
| 9764 | list<DAE.FuncArg> farg; | ||
| 9765 | DAE.CodeType ct; | ||
| 9766 | FCore.Cache cache; | ||
| 9767 | DAE.Dimensions ds; | ||
| 9768 | DAE.Prefix pre; | ||
| 9769 | InstTypes.PolymorphicBindings polymorphicBindings; | ||
| 9770 | DAE.Properties prop; | ||
| 9771 | String s1,s2,s3,s4; | ||
| 9772 | |||
| 9773 | case (cache, env, Absyn.NAMEDARG(argName = id,argValue = e), farg, slots, _, true, polymorphicBindings, pre) | ||
| 9774 | algorithm | ||
| 9775 |
2/2✓ Branch 1 taken 3293 times.
✓ Branch 2 taken 26 times.
|
3332 | vt as DAE.T_CODE(ty=ct) := findNamedArgType(id, farg); |
| 9776 | 26 | pr := findNamedArgParallelism(id,farg); | |
| 9777 | 26 | e_1 := elabCodeExp(e,cache,env,ct,info); | |
| 9778 | 26 | slots_1 := fillSlot(DAE.FUNCARG(id,vt,DAE.C_VAR(),pr,NONE()), e_1, {}, slots,pre,info, path); | |
| 9779 | 26 | then (cache,slots_1,DAE.C_VAR(),polymorphicBindings); | |
| 9780 | |||
| 9781 | // check types exact match | ||
| 9782 | case (cache, env, Absyn.NAMEDARG(argName = id,argValue = e), farg, slots, _, true, polymorphicBindings, pre) | ||
| 9783 | algorithm | ||
| 9784 | 3306 | vt := findNamedArgType(id, farg); | |
| 9785 | 3293 | pr := findNamedArgParallelism(id,farg); | |
| 9786 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3293 times.
|
3293 | (cache,e_1,DAE.PROP(t,c1)) := elabExpInExpression(cache, env, e, impl, true,pre,info); |
| 9787 | 3293 | (e_2,_,polymorphicBindings) := Types.matchTypePolymorphic(e_1,t,vt,FGraph.getGraphPathNoImplicitScope(env),polymorphicBindings,false); | |
| 9788 | 3260 | slots_1 := fillSlot(DAE.FUNCARG(id,vt,c1,pr,NONE()), e_2, {}, slots,pre,info, path); | |
| 9789 | 3260 | then (cache,slots_1,c1,polymorphicBindings); | |
| 9790 | |||
| 9791 | // check types vectorized argument | ||
| 9792 | case (cache, env, Absyn.NAMEDARG(argName = id,argValue = e), farg, slots, _, true, polymorphicBindings, pre) | ||
| 9793 | algorithm | ||
| 9794 | 46 | vt := findNamedArgType(id, farg); | |
| 9795 | 33 | pr := findNamedArgParallelism(id,farg); | |
| 9796 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
|
33 | (cache,e_1,DAE.PROP(t,c1)) := elabExpInExpression(cache, env, e, impl, true,pre,info); |
| 9797 | 33 | (e_2,_,ds,polymorphicBindings) := Types.vectorizableType(e_1, t, vt, FGraph.getGraphPathNoImplicitScope(env)); | |
| 9798 | 33 | slots_1 := fillSlot(DAE.FUNCARG(id,vt,c1,pr,NONE()), e_2, ds, slots, pre,info, path); | |
| 9799 | 33 | then (cache,slots_1,c1,polymorphicBindings); | |
| 9800 | |||
| 9801 | // do not check types | ||
| 9802 | case (cache, env, Absyn.NAMEDARG(argName = id,argValue = e), farg, slots, _, false, polymorphicBindings, pre) | ||
| 9803 | algorithm | ||
| 9804 | 61 | vt := findNamedArgType(id, farg); | |
| 9805 | 49 | pr := findNamedArgParallelism(id,farg); | |
| 9806 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
|
49 | (cache,e_1,DAE.PROP(_,c1)) := elabExpInExpression(cache,env, e, impl,true,pre,info); |
| 9807 | 49 | slots_1 := fillSlot(DAE.FUNCARG(id,vt,c1,pr,NONE()), e_1, {}, slots,pre,info, path); | |
| 9808 | 49 | then (cache,slots_1,c1,polymorphicBindings); | |
| 9809 | |||
| 9810 | case (cache, _, Absyn.NAMEDARG(argName = id), farg, slots, true, _, polymorphicBindings, _) | ||
| 9811 | algorithm | ||
| 9812 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 24 times.
|
48 | failure(findNamedArgType(id, farg)); |
| 9813 | 24 | s1 := AbsynUtil.pathStringNoQual(path); | |
| 9814 | 24 | Error.addSourceMessage(Error.NO_SUCH_PARAMETER, {s1,id}, info); | |
| 9815 |
1/2✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
|
24 | true := isGraphicsExp; |
| 9816 | ✗ | then (cache,slots,DAE.C_CONST(),polymorphicBindings); | |
| 9817 | |||
| 9818 | // failure | ||
| 9819 | case (cache, env, Absyn.NAMEDARG(argName = id,argValue = e), farg, _, true, true, _, pre) | ||
| 9820 | algorithm | ||
| 9821 |
1/2✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
|
12 | true := Error.getNumErrorMessages() == numErrors; |
| 9822 | ✗ | vt := findNamedArgType(id, farg); | |
| 9823 | ✗ | (cache,e_1,prop) := elabExpInExpression(cache, env, e, impl, true,pre,info); | |
| 9824 | ✗ | s1 := AbsynUtil.pathStringNoQual(path); | |
| 9825 | ✗ | s2 := ExpressionBasics.printExpStr(e_1); | |
| 9826 | ✗ | s3 := TypesDump.unparseTypeNoAttr(Types.getPropType(prop)); | |
| 9827 | ✗ | s4 := TypesDump.unparseTypeNoAttr(vt); | |
| 9828 | ✗ | Error.addSourceMessage(Error.NAMED_ARG_TYPE_MISMATCH, {s1,id,s2,s3,s4}, info); | |
| 9829 | ✗ | then fail(); | |
| 9830 | end matchcontinue; | ||
| 9831 | end elabNamedInputArg; | ||
| 9832 | |||
| 9833 | protected function findNamedArg | ||
| 9834 | input String inIdent; | ||
| 9835 | input list<DAE.FuncArg> inArgs; | ||
| 9836 | output DAE.FuncArg outArg; | ||
| 9837 | protected | ||
| 9838 | String id; | ||
| 9839 | Boolean haveMM = Config.acceptMetaModelicaGrammar(); | ||
| 9840 | String inIdent2 = if haveMM then "$in_"+inIdent else ""; | ||
| 9841 | algorithm | ||
| 9842 |
2/2✓ Branch 0 taken 30573 times.
✓ Branch 1 taken 75 times.
|
30648 | for arg in inArgs loop |
| 9843 | 30573 | DAE.FUNCARG(name = id) := arg; | |
| 9844 | |||
| 9845 |
7/10✓ Branch 0 taken 14391 times.
✓ Branch 1 taken 16182 times.
✓ Branch 3 taken 4296 times.
✓ Branch 4 taken 10095 times.
✓ Branch 5 taken 534 times.
✓ Branch 6 taken 19944 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 534 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
30573 | if id == inIdent or (haveMM and id == inIdent2) then |
| 9846 | outArg := arg; | ||
| 9847 | 10095 | return; | |
| 9848 | end if; | ||
| 9849 | end for; | ||
| 9850 | 75 | fail(); | |
| 9851 | end findNamedArg; | ||
| 9852 | |||
| 9853 | protected function findNamedArgType | ||
| 9854 | "This function takes an Ident and a FuncArg list, and returns the FuncArg | ||
| 9855 | which has that identifier. | ||
| 9856 | Used for instance when looking up named arguments from the function type." | ||
| 9857 | input String inIdent; | ||
| 9858 | input list<DAE.FuncArg> inArgs; | ||
| 9859 | output DAE.Type outType; | ||
| 9860 | algorithm | ||
| 9861 | 6769 | DAE.FUNCARG(ty = outType) := findNamedArg(inIdent, inArgs); | |
| 9862 | end findNamedArgType; | ||
| 9863 | |||
| 9864 | protected function findNamedArgParallelism | ||
| 9865 | "This function takes an Ident and a FuncArg list, and returns the | ||
| 9866 | parallelism of the FuncArg which has that identifier." | ||
| 9867 | input String inIdent; | ||
| 9868 | input list<DAE.FuncArg> inArgs; | ||
| 9869 | output DAE.VarParallelism outParallelism; | ||
| 9870 | algorithm | ||
| 9871 | 3401 | DAE.FUNCARG(par = outParallelism) := findNamedArg(inIdent, inArgs); | |
| 9872 | end findNamedArgParallelism; | ||
| 9873 | |||
| 9874 | protected function fillSlot | ||
| 9875 | "This function takses a `FuncArg\' and an DAE.Exp and a Slot list and fills | ||
| 9876 | the slot holding the FuncArg, by setting the boolean value of the slot | ||
| 9877 | and setting the expression. The function fails if the slot is allready set." | ||
| 9878 | input DAE.FuncArg inFuncArg; | ||
| 9879 | input DAE.Exp inExp; | ||
| 9880 | input DAE.Dimensions inDims; | ||
| 9881 | input list<Slot> inSlotLst; | ||
| 9882 | input DAE.Prefix inPrefix; | ||
| 9883 | input SourceInfo inInfo; | ||
| 9884 | input Absyn.Path fn; | ||
| 9885 | output list<Slot> outSlotLst = {}; | ||
| 9886 | protected | ||
| 9887 | String fa1, fa2, exp_str, c_str, pre_str; | ||
| 9888 | DAE.Type ty1; | ||
| 9889 | DAE.Const c1, c2; | ||
| 9890 | DAE.VarParallelism prl; | ||
| 9891 | Option<DAE.Exp> binding; | ||
| 9892 | Boolean filled; | ||
| 9893 | Integer idx, ses; | ||
| 9894 | Slot slot; | ||
| 9895 | list<Slot> rest_slots = inSlotLst; | ||
| 9896 | algorithm | ||
| 9897 | 122405 | DAE.FUNCARG(name = fa1, ty = ty1, const = c1) := inFuncArg; | |
| 9898 | |||
| 9899 |
1/2✓ Branch 0 taken 264233 times.
✗ Branch 1 not taken.
|
264233 | while not listEmpty(rest_slots) loop |
| 9900 | 264233 | slot :: rest_slots := rest_slots; | |
| 9901 | 264233 | SLOT(defaultArg = DAE.FUNCARG(name = fa2)) := slot; | |
| 9902 | |||
| 9903 | // Check if this slot has the same name as the one we're looking for. | ||
| 9904 |
7/8✓ Branch 1 taken 143354 times.
✓ Branch 2 taken 120879 times.
✓ Branch 4 taken 20949 times.
✓ Branch 5 taken 122405 times.
✓ Branch 6 taken 3707 times.
✓ Branch 7 taken 138121 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3707 times.
|
264233 | if stringEq(fa1, fa2) or stringEq("$in_"+fa1, fa2) /* OM extension input output arguments */ then |
| 9905 | 122405 | SLOT(defaultArg = DAE.FUNCARG(const = c2, par = prl, defaultBinding = binding), | |
| 9906 | slotFilled = filled, idx = idx, evalStatus = ses) := slot; | ||
| 9907 | |||
| 9908 | // Fail if the slot is already filled. | ||
| 9909 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 122405 times.
|
122405 | if filled then |
| 9910 | ✗ | pre_str := PrefixUtil.printPrefixStr3(inPrefix); | |
| 9911 | ✗ | Error.addSourceMessageAndFail(Error.FUNCTION_SLOT_ALREADY_FILLED, | |
| 9912 | {fa2, pre_str}, inInfo); | ||
| 9913 | end if; | ||
| 9914 | |||
| 9915 | // Fail if the variability is wrong. | ||
| 9916 |
2/2✓ Branch 1 taken 6 times.
✓ Branch 2 taken 122399 times.
|
122405 | if not Types.constEqualOrHigher(c1, c2) then |
| 9917 | 6 | exp_str := ExpressionBasics.printExpStr(inExp); | |
| 9918 | 6 | c_str := TypesDump.unparseConst(c2); | |
| 9919 | 18 | Error.addSourceMessageAndFail(Error.FUNCTION_SLOT_VARIABILITY, | |
| 9920 | {fa1, exp_str, AbsynUtil.pathStringNoQual(fn), TypesDump.unparseConst(c1), c_str}, inInfo); | ||
| 9921 | end if; | ||
| 9922 | |||
| 9923 | // Found a valid slot, fill it and reconstruct the slot list. | ||
| 9924 | 244798 | slot := SLOT(DAE.FUNCARG(fa2, ty1, c2, prl, binding), true, SOME(inExp), inDims, idx, ses); | |
| 9925 | 122399 | outSlotLst := List.append_reverse(outSlotLst, slot :: rest_slots); | |
| 9926 | 122399 | return; | |
| 9927 | end if; | ||
| 9928 | |||
| 9929 | outSlotLst := slot :: outSlotLst; | ||
| 9930 | end while; | ||
| 9931 | |||
| 9932 | ✗ | Error.addSourceMessageAndFail(Error.NO_SUCH_PARAMETER, {"", fa1}, inInfo); | |
| 9933 | end fillSlot; | ||
| 9934 | |||
| 9935 | public function elabCref " | ||
| 9936 | function: elabCref | ||
| 9937 | Elaborate on a component reference. Check the type of the | ||
| 9938 | component referred to, and check if the environment contains | ||
| 9939 | either a constant binding for that variable, or if it contains an | ||
| 9940 | equation binding with a constant expression." | ||
| 9941 | input FCore.Cache inCache; | ||
| 9942 | input FCore.Graph inEnv; | ||
| 9943 | input Absyn.ComponentRef inComponentRef; | ||
| 9944 | input Boolean inImplicit "implicit instantiation"; | ||
| 9945 | input Boolean performVectorization "true => generates vectorized expressions, {v[1],v[2],...}"; | ||
| 9946 | input DAE.Prefix inPrefix; | ||
| 9947 | input SourceInfo info; | ||
| 9948 | output FCore.Cache outCache; | ||
| 9949 | output Option<tuple<DAE.Exp,DAE.Properties,DAE.Attributes>> res; | ||
| 9950 | algorithm | ||
| 9951 | 432315 | (outCache,res) := elabCref1(inCache,inEnv,inComponentRef,inImplicit,performVectorization,inPrefix,true,info); | |
| 9952 | end elabCref; | ||
| 9953 | |||
| 9954 | public function elabCrefNoEval " | ||
| 9955 | Some functions expect a DAE.ComponentRef back and use this instead of elabCref :)" | ||
| 9956 | input FCore.Cache inCache; | ||
| 9957 | input FCore.Graph inEnv; | ||
| 9958 | input Absyn.ComponentRef inComponentRef; | ||
| 9959 | input Boolean inImplicit "implicit instantiation"; | ||
| 9960 | input Boolean performVectorization "true => generates vectorized expressions, {v[1],v[2],...}"; | ||
| 9961 | input DAE.Prefix inPrefix; | ||
| 9962 | input SourceInfo info; | ||
| 9963 | output FCore.Cache outCache; | ||
| 9964 | output DAE.Exp outExp; | ||
| 9965 | output DAE.Properties outProperties; | ||
| 9966 | output DAE.Attributes outAttributes; | ||
| 9967 | algorithm | ||
| 9968 |
3/6✗ Branch 1 not taken.
✓ Branch 2 taken 121041 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 121041 times.
✓ Branch 6 taken 121041 times.
✗ Branch 7 not taken.
|
121041 | (outCache, SOME((outExp, outProperties, outAttributes))) := |
| 9969 | elabCref1(inCache,inEnv,inComponentRef,inImplicit,performVectorization,inPrefix,false,info); | ||
| 9970 | end elabCrefNoEval; | ||
| 9971 | |||
| 9972 | protected function elabCref1 " | ||
| 9973 | function: elabCref | ||
| 9974 | Elaborate on a component reference. Check the type of the | ||
| 9975 | component referred to, and check if the environment contains | ||
| 9976 | either a constant binding for that variable, or if it contains an | ||
| 9977 | equation binding with a constant expression." | ||
| 9978 | input FCore.Cache inCache; | ||
| 9979 | input FCore.Graph inEnv; | ||
| 9980 | input Absyn.ComponentRef inComponentRef; | ||
| 9981 | input Boolean inImplicit "implicit instantiation"; | ||
| 9982 | input Boolean performVectorization "true => generates vectorized expressions, {v[1],v[2],...}"; | ||
| 9983 | input DAE.Prefix inPrefix; | ||
| 9984 | input Boolean evalCref; | ||
| 9985 | input SourceInfo info; | ||
| 9986 | output FCore.Cache outCache; | ||
| 9987 | output Option<tuple<DAE.Exp,DAE.Properties,DAE.Attributes>> res; | ||
| 9988 | algorithm | ||
| 9989 | (outCache,res) := matchcontinue (inCache,inEnv,inComponentRef,inImplicit,inPrefix) | ||
| 9990 | local | ||
| 9991 | DAE.ComponentRef c_1; | ||
| 9992 | DAE.Const const,constSubs; | ||
| 9993 | DAE.Type t,origt; | ||
| 9994 | DAE.Exp exp,crefExp; | ||
| 9995 | FCore.Graph env; | ||
| 9996 | Absyn.ComponentRef c; | ||
| 9997 | FCore.Cache cache; | ||
| 9998 | Boolean impl,isBuiltinFn,isBuiltinFnOrInlineBuiltin,hasZeroSizeDim; | ||
| 9999 | DAE.Type et; | ||
| 10000 | String s,scope; | ||
| 10001 | InstTypes.SplicedExpData splicedExpData; | ||
| 10002 | Absyn.Path path,fpath; | ||
| 10003 | list<String> enum_lit_strs; | ||
| 10004 | String typeStr,id; | ||
| 10005 | DAE.ComponentRef expCref; | ||
| 10006 | Option<DAE.Const> forIteratorConstOpt; | ||
| 10007 | DAE.Prefix pre; | ||
| 10008 | Absyn.Exp e; | ||
| 10009 | SCode.Element cl; | ||
| 10010 | DAE.FunctionBuiltin isBuiltin; | ||
| 10011 | DAE.Attributes attr; | ||
| 10012 | DAE.Binding binding "equation modification"; | ||
| 10013 | list<Absyn.Subscript> subscripts; | ||
| 10014 | Absyn.ComponentRef stripped_cref; | ||
| 10015 | |||
| 10016 | // wildcard | ||
| 10017 | case (cache, _, Absyn.WILD(), _, _) | ||
| 10018 | algorithm | ||
| 10019 | 6994 | t := DAE.T_ANYTYPE_DEFAULT; | |
| 10020 | 6994 | et := Types.simplifyType(t); | |
| 10021 | 6994 | crefExp := Expression.makeCrefExp(DAE.WILD(),et); | |
| 10022 | 6994 | then | |
| 10023 | (cache,SOME((crefExp,DAE.PROP(t, DAE.C_VAR()),DAE.dummyAttrVar))); | ||
| 10024 | |||
| 10025 | // Boolean => {false, true} | ||
| 10026 | case (cache, _, Absyn.CREF_IDENT(name = "Boolean"), _, _) | ||
| 10027 | algorithm | ||
| 10028 | 1 | exp := Expression.makeScalarArray({DAE.BCONST(false), DAE.BCONST(true)}, DAE.T_BOOL_DEFAULT); | |
| 10029 | 1 | t := DAE.T_ARRAY(DAE.T_BOOL_DEFAULT, {DAE.DIM_INTEGER(2)}); | |
| 10030 | 1 | then | |
| 10031 | (cache, SOME((exp, DAE.PROP(t, DAE.C_CONST()), DAE.dummyAttrConst))); | ||
| 10032 | |||
| 10033 | case (_, _, Absyn.CREF_IDENT(name = "time"), _, _) | ||
| 10034 | algorithm | ||
| 10035 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1028 times.
|
1028 | res := if isValidTimeScope(inEnv, info) then BUILTIN_TIME else NONE(); |
| 10036 | 1028 | then | |
| 10037 | (inCache, res); | ||
| 10038 | |||
| 10039 | // qualified subscripted array | ||
| 10040 | case (cache, env, Absyn.CREF_QUAL(), impl, pre) | ||
| 10041 | algorithm | ||
| 10042 |
2/2✓ Branch 1 taken 117337 times.
✓ Branch 2 taken 3964 times.
|
121301 | true := Config.acceptMetaModelicaGrammar(); |
| 10043 |
1/2✓ Branch 1 taken 3964 times.
✗ Branch 2 not taken.
|
3964 | true := AbsynUtil.crefHasSubscripts(inComponentRef); |
| 10044 | |||
| 10045 | // get the last subscripts and then strip them | ||
| 10046 | ✗ | subscripts := AbsynUtil.crefGetLastSubs(inComponentRef); | |
| 10047 | ✗ | stripped_cref := AbsynUtil.crefStripLastSubs(inComponentRef); | |
| 10048 | |||
| 10049 | // fail if there are still subscripts left or more than one have been extracted | ||
| 10050 | ✗ | true := not AbsynUtil.crefHasSubscripts(stripped_cref) and listLength(subscripts) == 1; | |
| 10051 | |||
| 10052 | // elaborate the subscript | ||
| 10053 | ✗ | {Absyn.SUBSCRIPT(e)} := subscripts; | |
| 10054 | ✗ | (cache, res) := elabCrefArraySubscripts( | |
| 10055 | cref = stripped_cref, | ||
| 10056 | e = e, | ||
| 10057 | cache = cache, | ||
| 10058 | env = env, | ||
| 10059 | pre = pre, | ||
| 10060 | evalCref = evalCref, | ||
| 10061 | impl = impl, | ||
| 10062 | info = info | ||
| 10063 | ); | ||
| 10064 | then | ||
| 10065 | (cache, res); | ||
| 10066 | |||
| 10067 | // ident subscripted array | ||
| 10068 | case (cache, env, Absyn.CREF_IDENT(name = id, subscripts = {Absyn.SUBSCRIPT(e)}), impl, pre) | ||
| 10069 | algorithm | ||
| 10070 |
2/2✓ Branch 1 taken 74210 times.
✓ Branch 2 taken 134 times.
|
74344 | true := Config.acceptMetaModelicaGrammar(); |
| 10071 | // elaborate the subscript | ||
| 10072 | 134 | (cache, res) := elabCrefArraySubscripts( | |
| 10073 | cref = Absyn.CREF_IDENT(id, {}), | ||
| 10074 | e = e, | ||
| 10075 | cache = cache, | ||
| 10076 | env = env, | ||
| 10077 | pre = pre, | ||
| 10078 | evalCref = evalCref, | ||
| 10079 | impl = impl, | ||
| 10080 | info = info | ||
| 10081 | ); | ||
| 10082 | then | ||
| 10083 | (cache, res); | ||
| 10084 | |||
| 10085 | // a normal cref | ||
| 10086 | case (cache, env, c, impl, pre) | ||
| 10087 | algorithm | ||
| 10088 | 545333 | c := replaceEnd(c); | |
| 10089 |
2/2✓ Branch 1 taken 2835 times.
✓ Branch 2 taken 542498 times.
|
545333 | env := if AbsynUtil.crefIsFullyQualified(inComponentRef) then FGraph.topScope(inEnv) else inEnv; |
| 10090 | 545333 | (cache,c_1,constSubs,hasZeroSizeDim) := elabCrefSubs(cache, env, inEnv, c, pre, DAE.NOPRE(), impl, false, info); | |
| 10091 | 535354 | (cache,attr,t,binding,forIteratorConstOpt,splicedExpData) := Lookup.lookupVar(cache, env, c_1); | |
| 10092 | // get the binding if is a constant | ||
| 10093 | 535354 | (cache,exp,const,attr) := elabCref2(cache, env, c_1, attr, constSubs, forIteratorConstOpt, t, binding, performVectorization, splicedExpData, pre, evalCref, info); | |
| 10094 | 535354 | t := fixEnumerationType(t); | |
| 10095 |
4/4✓ Branch 0 taken 1803 times.
✓ Branch 1 taken 533551 times.
✓ Branch 2 taken 31 times.
✓ Branch 3 taken 1772 times.
|
1068936 | (exp,const) := evaluateEmptyVariable(hasZeroSizeDim and evalCref,exp,t,const); |
| 10096 | 535354 | then | |
| 10097 | (cache,SOME((exp,DAE.PROP(t, const),attr))); | ||
| 10098 | |||
| 10099 | // An enumeration type => array of enumeration literals. | ||
| 10100 | case (cache, env, c, _, _) | ||
| 10101 | algorithm | ||
| 10102 | 9979 | c := replaceEnd(c); | |
| 10103 | 9979 | path := AbsynUtil.crefToPath(c); | |
| 10104 |
3/4✗ Branch 1 not taken.
✓ Branch 2 taken 372 times.
✓ Branch 3 taken 367 times.
✓ Branch 4 taken 5 times.
|
9286 | (cache, cl as SCode.CLASS(restriction = SCode.R_ENUMERATION()), env) := |
| 10105 | Lookup.lookupClass(cache, env, path); | ||
| 10106 | 5 | typeStr := AbsynUtil.pathLastIdent(path); | |
| 10107 | 5 | path := FGraph.joinScopePath(env, Absyn.IDENT(typeStr)); | |
| 10108 | 5 | enum_lit_strs := SCodeUtil.componentNames(cl); | |
| 10109 | 5 | (exp, t) := makeEnumerationArray(path, enum_lit_strs); | |
| 10110 | 5 | then | |
| 10111 | (cache,SOME((exp,DAE.PROP(t, DAE.C_CONST()),DAE.dummyAttrConst /* RO */))); | ||
| 10112 | |||
| 10113 | // MetaModelica Partial Function | ||
| 10114 | case (cache, env, c, _, _) | ||
| 10115 | algorithm | ||
| 10116 | // true = Flags.isSet(Flags.FNPTR) or Config.acceptMetaModelicaGrammar(); | ||
| 10117 | 9974 | path := AbsynUtil.crefToPath(c); | |
| 10118 | // call the lookup function that removes errors when it fails! | ||
| 10119 |
3/4✓ Branch 1 taken 8938 times.
✓ Branch 2 taken 343 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 343 times.
|
9281 | (cache, {t}) := lookupFunctionsInEnvNoError(cache, env, path, info); |
| 10120 | 343 | (isBuiltin,isBuiltinFn,path) := isBuiltinFunc(path,t); | |
| 10121 | 343 | isBuiltinFnOrInlineBuiltin := not valueEq(DAE.FUNCTION_NOT_BUILTIN(),isBuiltin); | |
| 10122 | // some builtin functions store {} there | ||
| 10123 | fpath := match t | ||
| 10124 | 343 | case DAE.T_FUNCTION() then t.path; | |
| 10125 | end match; | ||
| 10126 | origt := t; | ||
| 10127 | 343 | t := Types.makeFunctionPolymorphicReference(t); | |
| 10128 | 343 | c := AbsynUtil.pathToCref(fpath); | |
| 10129 | 343 | expCref := ComponentReference.toExpCref(c); | |
| 10130 |
2/2✓ Branch 0 taken 264 times.
✓ Branch 1 taken 79 times.
|
607 | exp := Expression.makeCrefExp(expCref,DAE.T_FUNCTION_REFERENCE_FUNC(isBuiltinFnOrInlineBuiltin,origt)); |
| 10131 | // This is not done by lookup - only elabCall. So we should do it here. | ||
| 10132 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 343 times.
|
343 | (cache,Util.SUCCESS()) := instantiateDaeFunction(cache,env,path,isBuiltinFn,NONE(),true); |
| 10133 | 343 | then | |
| 10134 | (cache,SOME((exp,DAE.PROP(t,DAE.C_VAR()),DAE.dummyAttrConst /* RO */))); | ||
| 10135 | |||
| 10136 | // MetaModelica extension | ||
| 10137 | case (cache, _, Absyn.CREF_IDENT("NONE",{}), _, _) | ||
| 10138 | algorithm | ||
| 10139 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
|
1 | true := Config.acceptMetaModelicaGrammar(); |
| 10140 | 1 | Error.addSourceMessage(Error.META_NONE_CREF, {}, info); | |
| 10141 | 1 | then | |
| 10142 | (cache,NONE()); | ||
| 10143 | |||
| 10144 | case (_, env, c, _, _) | ||
| 10145 | algorithm | ||
| 10146 | // enabled with -d=failtrace | ||
| 10147 |
2/2✓ Branch 1 taken 9629 times.
✓ Branch 2 taken 1 time.
|
9630 | true := Flags.isSet(Flags.FAILTRACE); |
| 10148 | 1 | Debug.traceln("- Static.elabCref failed: " + | |
| 10149 | Dump.printComponentRefStr(c) + " in env: " + | ||
| 10150 | FGraph.printGraphPathStr(env)); | ||
| 10151 | // Debug.traceln("ENVIRONMENT:\n" + FGraph.printGraphStr(env)); | ||
| 10152 | 1 | then | |
| 10153 | fail(); | ||
| 10154 | |||
| 10155 | /* | ||
| 10156 | // maybe we do have it but without a binding, so maybe we can actually type it! | ||
| 10157 | case (cache,env,c,impl,doVect,pre,info) | ||
| 10158 | algorithm | ||
| 10159 | failure((_,_,_) = elabCrefSubs(cache,env, c, pre, DAE.NOPRE(),impl,info)); | ||
| 10160 | id = AbsynUtil.crefFirstIdent(c); | ||
| 10161 | (cache,DAE.TYPES_VAR(name, attributes, visibility, ty, binding, constOfForIteratorRange), | ||
| 10162 | SOME((cl as SCode.COMPONENT(n, pref, SCode.ATTR(arrayDims = ad), Absyn.TPATH(tpath, _),m,comment,cond,info),cmod)),instStatus,_) | ||
| 10163 | = Lookup.lookupIdent(cache, env, id); | ||
| 10164 | print("Static: cref:" + Dump.printComponentRefStr(c) + " component first ident:\n" + SCodeDump.unparseElementStr(cl) + "\n"); | ||
| 10165 | (cache, cl, env) = Lookup.lookupClass(cache, env, tpath); | ||
| 10166 | print("Static: cref:" + Dump.printComponentRefStr(c) + " class component first ident:\n" + SCodeDump.unparseElementStr(cl) + "\n"); | ||
| 10167 | then | ||
| 10168 | (cache,NONE());*/ | ||
| 10169 | |||
| 10170 | case (cache, env, c, impl, pre) | ||
| 10171 | algorithm | ||
| 10172 |
2/2✓ Branch 0 taken 9630 times.
✓ Branch 1 taken 9630 times.
|
19260 | failure(elabCrefSubs(cache,env, env,c, pre, DAE.NOPRE(),impl,false,info)); |
| 10173 | 9630 | s := Dump.printComponentRefStr(c); | |
| 10174 | 9630 | scope := FGraph.printGraphPathStr(env); | |
| 10175 | // No need to add prefix info since problem only depends on the scope? | ||
| 10176 | 9630 | Error.addSourceMessage(Error.LOOKUP_VARIABLE_ERROR, {s,scope}, info); | |
| 10177 | 9630 | then | |
| 10178 | (cache,NONE()); | ||
| 10179 | end matchcontinue; | ||
| 10180 | end elabCref1; | ||
| 10181 | |||
| 10182 | protected function elabCrefArraySubscripts | ||
| 10183 | "function: elabCrefArraySubscripts | ||
| 10184 | Parse the subscripts of an array and unbox if necessary." | ||
| 10185 | input Absyn.ComponentRef cref "originally subscripted (now stripped) cref"; | ||
| 10186 | input Absyn.Exp e "the subscript"; | ||
| 10187 | input output FCore.Cache cache "cache"; | ||
| 10188 | input FCore.Graph env "environment"; | ||
| 10189 | input DAE.Prefix pre "cref prefixes"; | ||
| 10190 | input Boolean evalCref "true if cref should be evaluated"; | ||
| 10191 | input Boolean impl "implicit instantiation"; | ||
| 10192 | input SourceInfo info "source information"; | ||
| 10193 | output Option<tuple<DAE.Exp,DAE.Properties,DAE.Attributes>> res "elaborated expression with props and attr"; | ||
| 10194 | protected | ||
| 10195 | DAE.Exp exp, exp1, exp2; | ||
| 10196 | DAE.Const const, const1, const2; | ||
| 10197 | DAE.Type t, sub_ty; | ||
| 10198 | DAE.Attributes attr; | ||
| 10199 | algorithm | ||
| 10200 | // Elaborate the cref without the subscript. | ||
| 10201 |
3/6✗ Branch 1 not taken.
✓ Branch 2 taken 134 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 134 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 134 times.
|
134 | (cache, SOME((exp1, DAE.PROP(t, const1), attr))) := |
| 10202 | elabCref1(cache, env, cref, false, false, pre, evalCref, info); | ||
| 10203 | |||
| 10204 | // Check that the type is a MetaModelica array, and get the element type. | ||
| 10205 | 134 | t := Types.metaArrayElementType(t); | |
| 10206 | |||
| 10207 | // Elaborate the subscript. | ||
| 10208 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 134 times.
|
134 | (cache,exp2,DAE.PROP(sub_ty, const2)) := |
| 10209 | elabExpInExpression(cache,env,e,impl,false,pre,info); | ||
| 10210 | |||
| 10211 | // Unbox the subscript if it's boxed, since it will be converted to an | ||
| 10212 | // arrayGet/arrayUpdate in code generation. | ||
| 10213 |
2/2✓ Branch 1 taken 5 times.
✓ Branch 2 taken 129 times.
|
134 | if Types.isMetaBoxedType(sub_ty) then |
| 10214 | 5 | sub_ty := Types.unboxedType(sub_ty); | |
| 10215 | 5 | exp2 := DAE.UNBOX(exp2, sub_ty); | |
| 10216 | end if; | ||
| 10217 | |||
| 10218 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 134 times.
|
134 | true := Types.isScalarInteger(sub_ty); |
| 10219 | 134 | const := Types.constAnd(const1,const2); | |
| 10220 | 134 | exp := Expression.makeASUB(exp1,{exp2}); | |
| 10221 | 134 | res := SOME((exp, DAE.PROP(t, const), attr)); | |
| 10222 | end elabCrefArraySubscripts; | ||
| 10223 | |||
| 10224 | protected function isValidTimeScope | ||
| 10225 | "Checks if time is allowed to be used in the current scope." | ||
| 10226 | input FCore.Graph inEnv; | ||
| 10227 | input SourceInfo inInfo; | ||
| 10228 | output Boolean outIsValid; | ||
| 10229 | protected | ||
| 10230 | SCode.Restriction res; | ||
| 10231 | algorithm | ||
| 10232 | try | ||
| 10233 | 1028 | res := FGraph.lastScopeRestriction(inEnv); | |
| 10234 | else | ||
| 10235 | outIsValid := true; | ||
| 10236 | 65 | return; | |
| 10237 | end try; | ||
| 10238 | |||
| 10239 | outIsValid := match res | ||
| 10240 | case SCode.R_CLASS() then true; | ||
| 10241 | case SCode.R_OPTIMIZATION() then true; | ||
| 10242 | case SCode.R_MODEL() then true; | ||
| 10243 | case SCode.R_BLOCK() then true; | ||
| 10244 | else | ||
| 10245 | algorithm | ||
| 10246 | ✗ | Error.addSourceMessage(Error.INVALID_TIME_SCOPE, {}, inInfo); | |
| 10247 | then | ||
| 10248 | false; | ||
| 10249 | end match; | ||
| 10250 | end isValidTimeScope; | ||
| 10251 | |||
| 10252 | protected function lookupFunctionsInEnvNoError | ||
| 10253 | input FCore.Cache inCache; | ||
| 10254 | input FCore.Graph inEnv; | ||
| 10255 | input Absyn.Path inPath; | ||
| 10256 | input SourceInfo inInfo; | ||
| 10257 | output FCore.Cache outCache; | ||
| 10258 | output list<DAE.Type> outTypesTypeLst; | ||
| 10259 | algorithm | ||
| 10260 | (outCache, outTypesTypeLst) := match inInfo | ||
| 10261 | |||
| 10262 | case _ | ||
| 10263 | algorithm | ||
| 10264 | 9281 | ErrorExt.setCheckpoint("Static.lookupFunctionsInEnvNoError"); | |
| 10265 | 9281 | (outCache, outTypesTypeLst) := Lookup.lookupFunctionsInEnv(inCache, inEnv, inPath, inInfo); | |
| 10266 | // rollback lookup errors! | ||
| 10267 | 9281 | ErrorExt.rollBack("Static.lookupFunctionsInEnvNoError"); | |
| 10268 |
1/2✓ Branch 0 taken 9281 times.
✗ Branch 1 not taken.
|
9281 | then |
| 10269 | (outCache, outTypesTypeLst); | ||
| 10270 | |||
| 10271 | else | ||
| 10272 | algorithm | ||
| 10273 | // rollback lookup errors! | ||
| 10274 | ✗ | ErrorExt.rollBack("Static.lookupFunctionsInEnvNoError"); | |
| 10275 | ✗ | then | |
| 10276 | fail(); | ||
| 10277 | end match; | ||
| 10278 | end lookupFunctionsInEnvNoError; | ||
| 10279 | |||
| 10280 | |||
| 10281 | protected function evaluateEmptyVariable | ||
| 10282 | "A variable with a 0-length dimension can be evaluated. | ||
| 10283 | This is good to do because otherwise the C-code contains references to non-existing variables" | ||
| 10284 | input Boolean hasZeroSizeDim; | ||
| 10285 | input DAE.Exp inExp; | ||
| 10286 | input DAE.Type ty; | ||
| 10287 | input DAE.Const c; | ||
| 10288 | output DAE.Exp oexp; | ||
| 10289 | output DAE.Const oc; | ||
| 10290 | algorithm | ||
| 10291 | (oexp,oc) := matchcontinue (hasZeroSizeDim, inExp) | ||
| 10292 | local | ||
| 10293 | Boolean sc,a; | ||
| 10294 | DAE.Type et; | ||
| 10295 | list<DAE.Subscript> ss; | ||
| 10296 | DAE.ComponentRef cr; | ||
| 10297 | list<DAE.Exp> expl; | ||
| 10298 | DAE.Exp exp; | ||
| 10299 | |||
| 10300 | case (true, DAE.ASUB(sub=ss)) | ||
| 10301 | algorithm | ||
| 10302 | ✗ | expl := list(Expression.getSubscriptExp(sub) for sub in ss); | |
| 10303 | // TODO: Use a DAE.ERROR() or something if this has subscripts? | ||
| 10304 | ✗ | a := Types.isArray(ty); | |
| 10305 | sc := boolNot(a); | ||
| 10306 | ✗ | et := Types.simplifyType(ty); | |
| 10307 | ✗ | exp := DAE.ARRAY(et,sc,{}); | |
| 10308 | ✗ | exp := Expression.makeASUB(exp,expl); | |
| 10309 | then (exp,c); | ||
| 10310 | |||
| 10311 | case (true, DAE.CREF(componentRef=cr)) | ||
| 10312 | algorithm | ||
| 10313 | 19 | a := Types.isArray(ty); | |
| 10314 | sc := boolNot(a); | ||
| 10315 | 19 | et := Types.simplifyType(ty); | |
| 10316 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 17 times.
|
19 | {} := ComponentReference.crefLastSubs(cr); |
| 10317 |
1/2✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
|
34 | exp := DAE.ARRAY(et,sc,{}); |
| 10318 | then (exp,c); | ||
| 10319 | |||
| 10320 | case (true, DAE.CREF(componentRef=cr)) | ||
| 10321 | algorithm | ||
| 10322 | // TODO: Use a DAE.ERROR() or something if this has subscripts? | ||
| 10323 | 2 | a := Types.isArray(ty); | |
| 10324 | sc := boolNot(a); | ||
| 10325 | 2 | et := Types.simplifyType(ty); | |
| 10326 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | ss as _::_ := ComponentReference.crefLastSubs(cr); |
| 10327 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
4 | exp := DAE.ARRAY(et,sc,{}); |
| 10328 | 2 | exp := Expression.makeASUB(exp,List.map(ss,Expression.getSubscriptExp)); | |
| 10329 | then (exp,c); | ||
| 10330 | |||
| 10331 | else (inExp,c); | ||
| 10332 | end matchcontinue; | ||
| 10333 | end evaluateEmptyVariable; | ||
| 10334 | |||
| 10335 | public function fixEnumerationType | ||
| 10336 | "Removes the index from an enumeration type." | ||
| 10337 | input DAE.Type inType; | ||
| 10338 | output DAE.Type outType; | ||
| 10339 | algorithm | ||
| 10340 | outType := match inType | ||
| 10341 | local | ||
| 10342 | Absyn.Path p; | ||
| 10343 | list<String> n; | ||
| 10344 | list<DAE.Var> v, al; | ||
| 10345 | |||
| 10346 | case DAE.T_ENUMERATION(index = SOME(_), path = p, names = n, literalVarLst = v, attributeLst = al) | ||
| 10347 | 15252 | then DAE.T_ENUMERATION(NONE(), p, n, v, al); | |
| 10348 | |||
| 10349 | else inType; | ||
| 10350 | end match; | ||
| 10351 | end fixEnumerationType; | ||
| 10352 | |||
| 10353 | public function applySubscriptsVariability | ||
| 10354 | "Takes the variability of a variable and the constness of it's subscripts and | ||
| 10355 | determines if the varibility of the variable should be raised. I.e.: | ||
| 10356 | parameter with variable subscripts => variable | ||
| 10357 | constant with variable subscripts => variable | ||
| 10358 | constant with parameter subscripts => parameter" | ||
| 10359 | input SCode.Variability inVariability; | ||
| 10360 | input DAE.Const inSubsConst; | ||
| 10361 | output SCode.Variability outVariability; | ||
| 10362 | algorithm | ||
| 10363 | outVariability := match(inVariability, inSubsConst) | ||
| 10364 | case (SCode.PARAM(), DAE.C_VAR()) then SCode.VAR(); | ||
| 10365 | case (SCode.CONST(), DAE.C_VAR()) then SCode.VAR(); | ||
| 10366 | case (SCode.CONST(), DAE.C_PARAM()) then SCode.PARAM(); | ||
| 10367 | else inVariability; | ||
| 10368 | end match; | ||
| 10369 | end applySubscriptsVariability; | ||
| 10370 | |||
| 10371 | public function makeEnumerationArray | ||
| 10372 | "Expands an enumeration type to an array of it's enumeration literals." | ||
| 10373 | input Absyn.Path enumTypeName; | ||
| 10374 | input list<String> enumLiterals; | ||
| 10375 | output DAE.Exp enumArray; | ||
| 10376 | output DAE.Type enumArrayType; | ||
| 10377 | |||
| 10378 | protected | ||
| 10379 | list<DAE.Exp> enum_lit_expl; | ||
| 10380 | Integer sz; | ||
| 10381 | DAE.Type ety; | ||
| 10382 | algorithm | ||
| 10383 | 5 | enum_lit_expl := Expression.makeEnumLiterals(enumTypeName, enumLiterals); | |
| 10384 | 5 | sz := listLength(enumLiterals); | |
| 10385 | 10 | ety := DAE.T_ARRAY(DAE.T_ENUMERATION(NONE(), enumTypeName, enumLiterals, {}, {}), | |
| 10386 | {DAE.DIM_ENUM(enumTypeName, enumLiterals, sz)}); | ||
| 10387 | 5 | enumArray := DAE.ARRAY(ety, true, enum_lit_expl); | |
| 10388 | enumArrayType := ety; | ||
| 10389 | end makeEnumerationArray; | ||
| 10390 | |||
| 10391 | protected function fillCrefSubscripts | ||
| 10392 | "This is a helper function to elab_cref2. | ||
| 10393 | It investigates a DAE.Type in order to fill the subscript lists of a | ||
| 10394 | component reference. For instance, the name a.b with the type array of | ||
| 10395 | one dimension will become a.b[:]." | ||
| 10396 | input DAE.ComponentRef inComponentRef; | ||
| 10397 | input DAE.Type inType; | ||
| 10398 | output DAE.ComponentRef outComponentRef; | ||
| 10399 | algorithm | ||
| 10400 | outComponentRef := match (inComponentRef,inType/*,slicedExp*/) | ||
| 10401 | local | ||
| 10402 | DAE.ComponentRef e,cref_1,cref; | ||
| 10403 | DAE.Type t; | ||
| 10404 | list<DAE.Subscript> subs_1,subs; | ||
| 10405 | String id; | ||
| 10406 | DAE.Type ty2; | ||
| 10407 | // no subscripts | ||
| 10408 | case ((e as DAE.CREF_IDENT(subscriptLst = {})),_) then e; | ||
| 10409 | |||
| 10410 | // simple ident with non-empty subscripts | ||
| 10411 | case ((DAE.CREF_IDENT(ident = id, identType = ty2, subscriptLst = subs)),t) | ||
| 10412 | algorithm | ||
| 10413 | 77525 | subs_1 := fillSubscripts(subs, t); | |
| 10414 | 77525 | then | |
| 10415 | ComponentReferenceBasics.makeCrefIdent(id,ty2,subs_1); | ||
| 10416 | // qualified ident with non-empty subscrips | ||
| 10417 | case ((DAE.CREF_QUAL(ident = id,subscriptLst = subs,componentRef = cref,identType = ty2 )),t) | ||
| 10418 | algorithm | ||
| 10419 | 96021 | subs := fillSubscripts(subs, ty2); | |
| 10420 | 96021 | t := stripPrefixType(t, ty2); | |
| 10421 | 96021 | cref_1 := fillCrefSubscripts(cref, t); | |
| 10422 | 96021 | then | |
| 10423 | ComponentReferenceBasics.makeCrefQual(id,ty2,subs,cref_1); | ||
| 10424 | end match; | ||
| 10425 | end fillCrefSubscripts; | ||
| 10426 | |||
| 10427 | protected function stripPrefixType | ||
| 10428 | input DAE.Type inType; | ||
| 10429 | input DAE.Type inPrefixType; | ||
| 10430 | output DAE.Type outType; | ||
| 10431 | algorithm | ||
| 10432 | outType := match(inType, inPrefixType) | ||
| 10433 | local | ||
| 10434 | DAE.Type t, pt; | ||
| 10435 | |||
| 10436 | 735 | case (DAE.T_ARRAY(ty = t), DAE.T_ARRAY(ty = pt)) then stripPrefixType(t, pt); | |
| 10437 | else inType; | ||
| 10438 | end match; | ||
| 10439 | end stripPrefixType; | ||
| 10440 | |||
| 10441 | protected function fillSubscripts | ||
| 10442 | "Helper function to fillCrefSubscripts." | ||
| 10443 | input list<DAE.Subscript> inExpSubscriptLst; | ||
| 10444 | input DAE.Type inType; | ||
| 10445 | output list<DAE.Subscript> outExpSubscriptLst; | ||
| 10446 | algorithm | ||
| 10447 | outExpSubscriptLst := matchcontinue inType | ||
| 10448 | local | ||
| 10449 | list<DAE.Subscript> subs; | ||
| 10450 | |||
| 10451 | // an array | ||
| 10452 | case DAE.T_ARRAY() | ||
| 10453 | algorithm | ||
| 10454 | 3597 | subs := List.fill(DAE.WHOLEDIM(), listLength(TypesDump.getDimensions(inType))); | |
| 10455 | 3597 | subs := List.stripN(subs, listLength(inExpSubscriptLst)); | |
| 10456 | 2145 | subs := listAppend(inExpSubscriptLst, subs); | |
| 10457 | then | ||
| 10458 | subs; | ||
| 10459 | |||
| 10460 | // not an array type! | ||
| 10461 | else inExpSubscriptLst; | ||
| 10462 | |||
| 10463 | end matchcontinue; | ||
| 10464 | end fillSubscripts; | ||
| 10465 | |||
| 10466 | protected function elabCref2 | ||
| 10467 | "This function does some more processing of crefs, like replacing a constant | ||
| 10468 | with its value and vectorizing a non-constant." | ||
| 10469 | input FCore.Cache inCache; | ||
| 10470 | input FCore.Graph inEnv; | ||
| 10471 | input DAE.ComponentRef inCref; | ||
| 10472 | input DAE.Attributes inAttributes; | ||
| 10473 | input DAE.Const constSubs; | ||
| 10474 | input Option<DAE.Const> inIteratorConst; | ||
| 10475 | input DAE.Type inType; | ||
| 10476 | input DAE.Binding inBinding; | ||
| 10477 | input Boolean inVectorize "true => vectorized expressions"; | ||
| 10478 | input InstTypes.SplicedExpData splicedExpData; | ||
| 10479 | input DAE.Prefix inPrefix; | ||
| 10480 | input Boolean evalCref; | ||
| 10481 | input SourceInfo info; | ||
| 10482 | output FCore.Cache outCache = inCache; | ||
| 10483 | output DAE.Exp outExp; | ||
| 10484 | output DAE.Const outConst; | ||
| 10485 | output DAE.Attributes outAttributes; | ||
| 10486 | protected | ||
| 10487 | SCode.Variability var = DAEUtil.getAttrVariability(inAttributes); | ||
| 10488 | algorithm | ||
| 10489 | (outExp, outConst, outAttributes) := matchcontinue(var, inType, inBinding, splicedExpData) | ||
| 10490 | local | ||
| 10491 | DAE.Type expTy, idTy, expIdTy; | ||
| 10492 | DAE.ComponentRef cr, subCr1, subCr2; | ||
| 10493 | DAE.Exp e, index; | ||
| 10494 | Option<DAE.Exp> sexp; | ||
| 10495 | Values.Value v; | ||
| 10496 | DAE.Const const; | ||
| 10497 | String s, scope, pre_str; | ||
| 10498 | DAE.Binding binding; | ||
| 10499 | Integer i; | ||
| 10500 | Absyn.Path p; | ||
| 10501 | DAE.Attributes attr; | ||
| 10502 | list<DAE.Subscript> subsc; | ||
| 10503 | |||
| 10504 | // If type not yet determined, component must be referencing itself. | ||
| 10505 | // Use the variability as the constness. | ||
| 10506 | case (_, DAE.T_UNKNOWN(), _, _) | ||
| 10507 | algorithm | ||
| 10508 | 80 | expTy := Types.simplifyType(inType); | |
| 10509 | 80 | const := Types.variabilityToConst(var); | |
| 10510 | 80 | then | |
| 10511 | (DAE.CREF(inCref, expTy), const, inAttributes); | ||
| 10512 | |||
| 10513 | // adrpo: report a warning if the binding came from a start value! | ||
| 10514 | // lochel: I moved the warning to the back end for now | ||
| 10515 | case (SCode.PARAM(), _, DAE.EQBOUND(source = DAE.BINDING_FROM_START_VALUE()), _) | ||
| 10516 | algorithm | ||
| 10517 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 80 times.
|
80 | true := Types.getFixedVarAttributeParameterOrConstant(inType); |
| 10518 | // s := ComponentReferenceBasics.printComponentRefStr(inCref); | ||
| 10519 | // pre_str := PrefixUtil.printPrefixStr2(inPrefix); | ||
| 10520 | // s := pre_str + s; | ||
| 10521 | // str := DAEUtil.printBindingExpStr(inBinding); | ||
| 10522 | // Error.addSourceMessage(Error.UNBOUND_PARAMETER_WITH_START_VALUE_WARNING, {s,str}, info); // Don't add source info here... Many models give multiple errors that are not filtered out | ||
| 10523 | 80 | binding := DAEUtil.setBindingSource(inBinding, DAE.BINDING_FROM_DEFAULT_VALUE()); | |
| 10524 | 80 | (outCache, e, const, attr) := elabCref2(outCache, inEnv, inCref, inAttributes, constSubs, | |
| 10525 | inIteratorConst, inType, binding, inVectorize, splicedExpData, inPrefix, evalCref, info); | ||
| 10526 | 80 | then | |
| 10527 | (e, const, attr); | ||
| 10528 | |||
| 10529 | // an enumeration literal -> simplify to a literal expression | ||
| 10530 | case (SCode.CONST(), DAE.T_ENUMERATION(index = SOME(i), path = p), _, _) guard(evalCref) | ||
| 10531 | algorithm | ||
| 10532 | 12593 | p := AbsynUtil.joinPaths(p, ComponentReference.crefLastPath(inCref)); | |
| 10533 | 12593 | then | |
| 10534 | (DAE.ENUM_LITERAL(p, i), DAE.C_CONST(), inAttributes); | ||
| 10535 | |||
| 10536 | // Don't evaluate constants if evalCref is false. | ||
| 10537 | case (SCode.CONST(), _, _, _) guard(not evalCref) | ||
| 10538 | algorithm | ||
| 10539 | ✗ | expTy := Types.simplifyType(inType); | |
| 10540 | ✗ | then | |
| 10541 | (Expression.makeCrefExp(inCref, expTy), DAE.C_CONST(), inAttributes); | ||
| 10542 | |||
| 10543 | // a constant with variable subscript | ||
| 10544 | case (SCode.CONST(), _, _, InstTypes.SPLICEDEXPDATA()) guard(Types.isVar(constSubs)) | ||
| 10545 | algorithm | ||
| 10546 | 237 | cr := ComponentReferenceBasics.crefStripLastSubs(inCref); | |
| 10547 | 237 | subsc := ComponentReference.crefLastSubs(inCref); | |
| 10548 | 237 | (outCache, v) := Ceval.cevalCref(outCache, inEnv, cr, false, Absyn.MSG(info), 0); | |
| 10549 | 237 | e := ValuesUtil.valueExp(v); | |
| 10550 |
4/4✓ Branch 0 taken 290 times.
✓ Branch 1 taken 232 times.
✓ Branch 2 taken 290 times.
✓ Branch 3 taken 232 times.
|
522 | e := Expression.makeASUB(e, list(Expression.getSubscriptExp(sub) for sub in subsc)); |
| 10551 | then | ||
| 10552 | (e, DAE.C_VAR(), inAttributes); | ||
| 10553 | |||
| 10554 | // a constant -> evaluate binding | ||
| 10555 | case (SCode.CONST(), _, binding, InstTypes.SPLICEDEXPDATA(_, idTy)) | ||
| 10556 | algorithm | ||
| 10557 |
2/2✓ Branch 1 taken 908 times.
✓ Branch 2 taken 56453 times.
|
57361 | true := Types.equivtypes(inType, idTy); |
| 10558 | |||
| 10559 | try | ||
| 10560 | 56453 | (outCache, v) := Ceval.cevalCrefBinding(outCache, inEnv, inCref, binding, false, Absyn.MSG(info), 0); | |
| 10561 | 55167 | e := ValuesUtil.valueExp(v); | |
| 10562 | else | ||
| 10563 | // Couldn't evaluate binding, replace the cref with the unevaluated binding. | ||
| 10564 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 1286 times.
✓ Branch 3 taken 1286 times.
✗ Branch 4 not taken.
|
1286 | SOME(e) := DAEUtil.bindingExp(binding); |
| 10565 | |||
| 10566 | ✗ | e := Expression.makeASUB(e, | |
| 10567 | list(Expression.getSubscriptExp(sub) for sub in ComponentReference.crefLastSubs(inCref))); | ||
| 10568 | end try; | ||
| 10569 | |||
| 10570 | const := DAE.C_CONST(); //Types.constAnd(DAE.C_CONST(), constSubs); | ||
| 10571 | 55167 | then | |
| 10572 | (e, const, inAttributes); | ||
| 10573 | |||
| 10574 | // a constant with some for iterator constness -> don't constant evaluate | ||
| 10575 | case (SCode.CONST(), _, _, _) guard(isSome(inIteratorConst)) | ||
| 10576 | algorithm | ||
| 10577 | 1279 | expTy := Types.simplifyType(inType); | |
| 10578 | 1279 | then | |
| 10579 | (Expression.makeCrefExp(inCref, expTy), DAE.C_CONST(), inAttributes); | ||
| 10580 | |||
| 10581 | // a constant with a binding | ||
| 10582 | case (SCode.CONST(), _, DAE.EQBOUND(constant_ = DAE.C_CONST()), | ||
| 10583 | InstTypes.SPLICEDEXPDATA(sexp, idTy)) | ||
| 10584 | algorithm | ||
| 10585 | 908 | expTy := Types.simplifyType(inType) "Constants with equal bindings should be constant, i.e. true | |
| 10586 | but const is passed on, allowing constants to have wrong bindings | ||
| 10587 | This must be caught later on." ; | ||
| 10588 | 908 | expIdTy := Types.simplifyType(idTy); | |
| 10589 | 908 | cr := fillCrefSubscripts(inCref, inType); | |
| 10590 | 908 | e := Expression.makeCrefExp(cr, expTy); | |
| 10591 | 908 | e := crefVectorize(inVectorize, e, inType, sexp, expIdTy); | |
| 10592 | 908 | (outCache, v) := Ceval.ceval(outCache, inEnv, e, false, Absyn.MSG(info), 0); | |
| 10593 | 739 | e := ValuesUtil.valueExp(v, SOME(e)); | |
| 10594 | then | ||
| 10595 | (e, DAE.C_CONST(), inAttributes); | ||
| 10596 | |||
| 10597 | // evaluate parameters only if "evalparam" or Config.getEvaluateParametersInAnnotations() is set | ||
| 10598 | // TODO! also ceval if annotation Evaluate := true. | ||
| 10599 | case (SCode.PARAM(), _, _, InstTypes.SPLICEDEXPDATA(sexp, idTy)) guard(DAEUtil.isBound(inBinding)) | ||
| 10600 | algorithm | ||
| 10601 |
3/4✓ Branch 1 taken 53762 times.
✓ Branch 2 taken 571 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 53762 times.
|
54333 | true := Flags.isSet(Flags.EVAL_PARAM) or Config.getEvaluateParametersInAnnotations(); |
| 10602 | // make it a constant if evalparam is used | ||
| 10603 | 571 | attr := DAEUtil.setAttrVariability(inAttributes, SCode.CONST()); | |
| 10604 | 571 | expTy := Types.simplifyType(inType) "Constants with equal bindings should be constant, i.e. true | |
| 10605 | but const is passed on, allowing constants to have wrong bindings | ||
| 10606 | This must be caught later on."; | ||
| 10607 | 571 | expIdTy := Types.simplifyType(idTy); | |
| 10608 | 571 | cr := fillCrefSubscripts(inCref, inType); | |
| 10609 | 571 | e := crefVectorize(inVectorize, Expression.makeCrefExp(cr, expTy), inType, sexp, expIdTy); | |
| 10610 | 571 | (outCache, v) := Ceval.ceval(outCache, inEnv, e, false, Absyn.MSG(info), 0); | |
| 10611 | 558 | e := ValuesUtil.valueExp(v, SOME(e)); | |
| 10612 | 558 | then | |
| 10613 | (e, DAE.C_PARAM(), attr); | ||
| 10614 | |||
| 10615 | // a constant array indexed by a for iterator -> transform into an array of values. HACK! HACK! UGLY! TODO! FIXME! | ||
| 10616 | // handles things like fcall(data[i]) in 1:X where data is a package constant of the form: | ||
| 10617 | // data:={Common.SingleGasesData.N2,Common.SingleGasesData.H2,Common.SingleGasesData.CO,Common.SingleGasesData.O2,Common.SingleGasesData.H2O, Common.SingleGasesData.CO2} | ||
| 10618 | case (SCode.CONST(), _, DAE.EQBOUND(evaluatedExp = SOME(v), constant_ = DAE.C_CONST()), | ||
| 10619 | InstTypes.SPLICEDEXPDATA(SOME(DAE.CREF(componentRef = cr)), _)) | ||
| 10620 | algorithm | ||
| 10621 |
7/12✗ Branch 1 not taken.
✓ Branch 2 taken 169 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 169 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 169 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 169 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 169 times.
✓ Branch 11 taken 5 times.
✓ Branch 12 taken 164 times.
|
169 | {DAE.INDEX(DAE.CREF(componentRef = subCr2)), DAE.SLICE(exp = e)} := ComponentReference.crefLastSubs(cr); |
| 10622 |
4/8✗ Branch 1 not taken.
✓ Branch 2 taken 164 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 164 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 164 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 164 times.
|
164 | {DAE.INDEX(index as DAE.CREF(componentRef = subCr1))} := ComponentReference.crefLastSubs(inCref); |
| 10623 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 164 times.
|
164 | true := ComponentReferenceBasics.crefEqual(subCr1, subCr2); |
| 10624 |
2/4✓ Branch 1 taken 164 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 164 times.
|
164 | true := Expression.isArray(e) or Expression.isRange(e); |
| 10625 | 164 | e := ValuesUtil.valueExp(v, SOME(e)); | |
| 10626 | 328 | e := DAE.ASUB(e, {DAE.INDEX(index)}); | |
| 10627 | then | ||
| 10628 | (e, DAE.C_CONST(), inAttributes); | ||
| 10629 | |||
| 10630 | // constants without value should not produce error if they are not in a simulation model! | ||
| 10631 | case (SCode.CONST(), _, DAE.UNBOUND(), _) guard(isNone(inIteratorConst)) | ||
| 10632 | algorithm | ||
| 10633 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
|
7 | if Flags.isSet(Flags.STATIC) then |
| 10634 | ✗ | s := ComponentReferenceBasics.printComponentRefStr(inCref); | |
| 10635 | ✗ | scope := FGraph.printGraphPathStr(inEnv); | |
| 10636 | ✗ | pre_str := PrefixUtil.printPrefixStr2(inPrefix); | |
| 10637 | ✗ | s := pre_str + s; | |
| 10638 | |||
| 10639 | ✗ | Debug.traceln("- Static.elabCref2 failed on: " + pre_str + s + | |
| 10640 | " with no constant binding in scope: " + scope); | ||
| 10641 | end if; | ||
| 10642 | |||
| 10643 | 7 | expTy := Types.simplifyType(inType); | |
| 10644 | 7 | cr := fillCrefSubscripts(inCref, inType); | |
| 10645 | 7 | e := Expression.makeCrefExp(cr, expTy); | |
| 10646 | then | ||
| 10647 | (e, DAE.C_CONST(), inAttributes); | ||
| 10648 | |||
| 10649 | // Everything else, vectorize the cref. | ||
| 10650 | case (_, _, _, InstTypes.SPLICEDEXPDATA(sexp, idTy)) | ||
| 10651 | algorithm | ||
| 10652 | 464535 | expTy := Types.simplifyType(inType); | |
| 10653 | 464535 | expIdTy := Types.simplifyType(idTy); | |
| 10654 | 464535 | cr := fillCrefSubscripts(inCref, inType); | |
| 10655 | 464535 | e := crefVectorize(inVectorize, Expression.makeCrefExp(cr, expTy), inType, sexp, expIdTy); | |
| 10656 | 464535 | const := Types.variabilityToConst(var); | |
| 10657 | 464535 | then | |
| 10658 | (e, const, inAttributes); | ||
| 10659 | |||
| 10660 | // failure! | ||
| 10661 | else | ||
| 10662 | algorithm | ||
| 10663 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 10664 | ✗ | pre_str := PrefixUtil.printPrefixStr2(inPrefix); | |
| 10665 | ✗ | Debug.traceln("- Static.elabCref2 failed for: " + pre_str + | |
| 10666 | ComponentReferenceBasics.printComponentRefStr(inCref) + | ||
| 10667 | "\n env:" + FGraph.printGraphStr(inEnv)); | ||
| 10668 | ✗ | then | |
| 10669 | fail(); | ||
| 10670 | |||
| 10671 | end matchcontinue; | ||
| 10672 | end elabCref2; | ||
| 10673 | |||
| 10674 | public function crefVectorize | ||
| 10675 | "This function takes a DAE.Exp and a DAE.Type and if the expression | ||
| 10676 | is a ComponentRef and the type is an array it returns an array of | ||
| 10677 | component references with subscripts for each index. | ||
| 10678 | For instance, parameter Real x[3]; | ||
| 10679 | gives cref_vectorize('x', <arraytype>) => '{x[1],x[2],x[3]} | ||
| 10680 | This is needed since the DAE does not know what the variable 'x' is, | ||
| 10681 | it only knows the variables 'x[1]', 'x[2]' and 'x[3]'. | ||
| 10682 | NOTE: Currently only works for one and two dimensions." | ||
| 10683 | input Boolean performVectorization "if false, return input"; | ||
| 10684 | input DAE.Exp inExp; | ||
| 10685 | input DAE.Type inType; | ||
| 10686 | input Option<DAE.Exp> splicedExp; | ||
| 10687 | input DAE.Type crefIdType "the type of the last cref ident, without considering subscripts. picked up from splicedExpData and used for crefs in vectorized exp"; | ||
| 10688 | output DAE.Exp outExp; | ||
| 10689 | algorithm | ||
| 10690 | outExp := matchcontinue (performVectorization, inExp, inType, splicedExp) | ||
| 10691 | local | ||
| 10692 | Boolean b1,b2; | ||
| 10693 | DAE.Type exptp; | ||
| 10694 | DAE.Exp e; | ||
| 10695 | DAE.ComponentRef cr; | ||
| 10696 | DAE.Type t; | ||
| 10697 | DAE.Dimension d1, d2; | ||
| 10698 | Integer ds, ds2; | ||
| 10699 | |||
| 10700 | // no vectorization | ||
| 10701 | case(false, e, _, _) then e; | ||
| 10702 | |||
| 10703 | // types extending basictype | ||
| 10704 | case (_, e, DAE.T_SUBTYPE_BASIC(complexType = t), _) | ||
| 10705 | algorithm | ||
| 10706 | 948 | e := crefVectorize(true,e,t,NONE(),crefIdType); | |
| 10707 | then e; | ||
| 10708 | |||
| 10709 | // component reference and an array type with dimensions less than vectorization limit | ||
| 10710 | case (_, _, DAE.T_ARRAY(dims = {d1}, ty = DAE.T_ARRAY(dims = {d2})), SOME(DAE.CREF(componentRef = cr))) | ||
| 10711 | algorithm | ||
| 10712 | 1168 | b1 := (Expression.dimensionSize(d1) < Config.vectorizationLimit()); | |
| 10713 | 1135 | b2 := (Expression.dimensionSize(d2) < Config.vectorizationLimit()); | |
| 10714 |
2/4✓ Branch 0 taken 1135 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1135 times.
✗ Branch 4 not taken.
|
1135 | true := boolAnd(b1, b2) or Config.vectorizationLimit() == 0; |
| 10715 | 1135 | e := elabCrefSlice(cr,crefIdType); | |
| 10716 | 1135 | e := elabMatrixToMatrixExp(e); | |
| 10717 | then | ||
| 10718 | e; | ||
| 10719 | |||
| 10720 | case (_, _, DAE.T_ARRAY(dims = {d1}, ty = t), SOME(DAE.CREF(componentRef = cr))) | ||
| 10721 | algorithm | ||
| 10722 |
2/2✓ Branch 1 taken 33 times.
✓ Branch 2 taken 32853 times.
|
32886 | false := Types.isArray(t); |
| 10723 |
2/4✓ Branch 2 taken 32236 times.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 32236 times.
|
32853 | true := (Expression.dimensionSize(d1) < Config.vectorizationLimit()) or Config.vectorizationLimit() == 0; |
| 10724 | 32236 | e := elabCrefSlice(cr,crefIdType); | |
| 10725 | then | ||
| 10726 | e; | ||
| 10727 | |||
| 10728 | // matrix sizes > vectorization limit is not vectorized | ||
| 10729 | case (_, DAE.CREF(componentRef = cr, ty = exptp), DAE.T_ARRAY(dims = {d1}, ty = t as DAE.T_ARRAY(dims = {d2})), _) | ||
| 10730 | algorithm | ||
| 10731 | 33 | ds := Expression.dimensionSize(d1); | |
| 10732 | ✗ | ds2 := Expression.dimensionSize(d2); | |
| 10733 | ✗ | b1 := (ds < Config.vectorizationLimit()); | |
| 10734 | ✗ | b2 := (ds2 < Config.vectorizationLimit()); | |
| 10735 | ✗ | true := boolAnd(b1, b2) or Config.vectorizationLimit() == 0; | |
| 10736 | ✗ | true := listEmpty(ComponentReference.crefLastSubs(cr)); | |
| 10737 | ✗ | e := createCrefArray2d(cr, 1, ds, ds2, exptp, t,crefIdType); | |
| 10738 | then | ||
| 10739 | e; | ||
| 10740 | |||
| 10741 | // vectorsizes > vectorization limit is not vectorized | ||
| 10742 | case (_, DAE.CREF(componentRef = cr,ty = exptp), DAE.T_ARRAY(dims = {d1},ty = t), _) | ||
| 10743 | algorithm | ||
| 10744 |
2/2✓ Branch 1 taken 33 times.
✓ Branch 2 taken 907 times.
|
940 | false := Types.isArray(t); |
| 10745 | 907 | ds := Expression.dimensionSize(d1); | |
| 10746 |
2/4✓ Branch 1 taken 290 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 290 times.
|
290 | true := ds < Config.vectorizationLimit() or Config.vectorizationLimit() == 0; |
| 10747 | 290 | e := createCrefArray(cr, 1, ds, exptp, t,crefIdType); | |
| 10748 | then | ||
| 10749 | e; | ||
| 10750 | else inExp; | ||
| 10751 | end matchcontinue; | ||
| 10752 | end crefVectorize; | ||
| 10753 | |||
| 10754 | protected function extractDimensionOfChild | ||
| 10755 | "A function for extracting the type-dimension of the child to *me* to dimension *my* array-size. | ||
| 10756 | Also returns wheter the array is a scalar or not." | ||
| 10757 | input DAE.Exp inExp; | ||
| 10758 | output DAE.Dimensions outExp; | ||
| 10759 | output Boolean isScalar; | ||
| 10760 | algorithm | ||
| 10761 | (outExp,isScalar) := matchcontinue inExp | ||
| 10762 | local | ||
| 10763 | DAE.Exp exp2; | ||
| 10764 | list<DAE.Exp> expl1; | ||
| 10765 | DAE.Dimensions tl; | ||
| 10766 | Integer x; | ||
| 10767 | Boolean sc; | ||
| 10768 | |||
| 10769 | case DAE.ARRAY(ty = (DAE.T_ARRAY(dims=(tl))),scalar=sc) | ||
| 10770 | then (tl,sc); | ||
| 10771 | |||
| 10772 | case DAE.ARRAY(array=expl1 as ((exp2 as DAE.ARRAY(_,_,_)) :: _)) | ||
| 10773 | algorithm | ||
| 10774 | 1400 | (tl,_) := extractDimensionOfChild(exp2); | |
| 10775 | 1400 | x := listLength(expl1); | |
| 10776 | 1400 | then | |
| 10777 | (DAE.DIM_INTEGER(x)::tl, false ); | ||
| 10778 | |||
| 10779 | case DAE.ARRAY(array=expl1) | ||
| 10780 | algorithm | ||
| 10781 | 44089 | x := listLength(expl1); | |
| 10782 | 44089 | then ({DAE.DIM_INTEGER(x)},true); | |
| 10783 | |||
| 10784 | case DAE.CREF(_ , _) | ||
| 10785 | then | ||
| 10786 | ({},true); | ||
| 10787 | end matchcontinue; | ||
| 10788 | end extractDimensionOfChild; | ||
| 10789 | |||
| 10790 | protected function elabCrefSlice | ||
| 10791 | "Bjozac, 2007-05-29 Main function from now for vectorizing output. | ||
| 10792 | the subscriptlist should contain either 'done slices' or numbers representing | ||
| 10793 | dimension entries. | ||
| 10794 | Example: | ||
| 10795 | 1) a is a real[2,3] with no subscripts, the input here should be | ||
| 10796 | CREF_IDENT('a',{DAE.SLICE(DAE.ARRAY(_,_,{1,2})), DAE.SLICE(DAE.ARRAY(_,_,{1,2,3}))})> | ||
| 10797 | ==> {{a[1,1],a[1,2],a[1,3]},{a[2,1],a[2,2],a[2,3]}} | ||
| 10798 | 2) a is a real[3,3] with subscripts {1,2},{1,3}, the input should be | ||
| 10799 | CREF_IDENT('a',{DAE.SLICE(DAE.ARRAY(_,_,{DAE.INDEX(1),DAE.INDEX(2)})), | ||
| 10800 | DAE.SLICE(DAE.ARRAY(_,_,{DAE.INDEX(1),DAE.INDEX(3)}))}) | ||
| 10801 | ==> {{a[1,1],a[1,3]},{a[2,1],a[2,3]}}" | ||
| 10802 | input DAE.ComponentRef inCref; | ||
| 10803 | input DAE.Type inType; | ||
| 10804 | output DAE.Exp outCref; | ||
| 10805 | algorithm | ||
| 10806 | outCref := match(inCref, inType) | ||
| 10807 | local | ||
| 10808 | list<DAE.Subscript> ssl; | ||
| 10809 | String id; | ||
| 10810 | DAE.ComponentRef child; | ||
| 10811 | DAE.Exp exp1,childExp; | ||
| 10812 | DAE.Type ety, prety; | ||
| 10813 | |||
| 10814 | case( DAE.CREF_IDENT(ident = id,subscriptLst = ssl),ety) | ||
| 10815 | algorithm | ||
| 10816 | 33371 | exp1 := flattenSubscript(ssl,id,ety); | |
| 10817 | then | ||
| 10818 | exp1; | ||
| 10819 | case( DAE.CREF_QUAL(ident = id, identType = prety, subscriptLst = ssl, componentRef = child),ety) | ||
| 10820 | algorithm | ||
| 10821 | 7754 | childExp := elabCrefSlice(child,ety); | |
| 10822 | 7736 | exp1 := flattenSubscript(ssl,id,prety); | |
| 10823 | 7736 | exp1 := mergeQualWithRest(exp1,childExp,ety); | |
| 10824 | then | ||
| 10825 | exp1; | ||
| 10826 | end match; | ||
| 10827 | end elabCrefSlice; | ||
| 10828 | |||
| 10829 | protected function mergeQualWithRest | ||
| 10830 | "Incase we have a qual with child references, this function merges them. | ||
| 10831 | The input should be an array, or just one CREF_QUAL, of arrays...of arrays | ||
| 10832 | of CREF_QUALS and the same goes for 'rest'. Also the flat type as input." | ||
| 10833 | input DAE.Exp qual; | ||
| 10834 | input DAE.Exp rest; | ||
| 10835 | input DAE.Type inType; | ||
| 10836 | output DAE.Exp outExp; | ||
| 10837 | algorithm | ||
| 10838 | outExp := match(qual,rest,inType) | ||
| 10839 | local | ||
| 10840 | DAE.Exp exp1,exp2; | ||
| 10841 | list<DAE.Exp> expl1; | ||
| 10842 | DAE.Type ety; | ||
| 10843 | DAE.Dimensions iLst; | ||
| 10844 | Boolean scalar; | ||
| 10845 | // a component reference | ||
| 10846 | case(exp1 as DAE.CREF(_,_),exp2,_) | ||
| 10847 | 8195 | then mergeQualWithRest2(exp2,exp1); | |
| 10848 | // an array | ||
| 10849 | case(DAE.ARRAY(_, _, expl1),exp2,ety) | ||
| 10850 | algorithm | ||
| 10851 | 267 | expl1 := List.map2(expl1,mergeQualWithRest,exp2,ety); | |
| 10852 | |||
| 10853 | 267 | exp2 := DAE.ARRAY(DAE.T_INTEGER_DEFAULT,false,expl1); | |
| 10854 | 267 | (iLst, scalar) := extractDimensionOfChild(exp2); | |
| 10855 | 267 | ety := Expression.arrayEltType(ety); | |
| 10856 |
2/2✓ Branch 1 taken 14 times.
✓ Branch 2 taken 253 times.
|
281 | exp2 := DAE.ARRAY(DAE.T_ARRAY(ety, iLst), scalar, expl1); |
| 10857 | then exp2; | ||
| 10858 | end match; | ||
| 10859 | end mergeQualWithRest; | ||
| 10860 | |||
| 10861 | protected function mergeQualWithRest2 | ||
| 10862 | "Helper to mergeQualWithRest, handles the case | ||
| 10863 | when the child-qual is arrays of arrays." | ||
| 10864 | input DAE.Exp rest; | ||
| 10865 | input DAE.Exp qual; | ||
| 10866 | output DAE.Exp outExp; | ||
| 10867 | algorithm | ||
| 10868 | outExp := match(rest,qual) | ||
| 10869 | local | ||
| 10870 | DAE.Exp exp1,exp2; | ||
| 10871 | list<DAE.Exp> expl1; | ||
| 10872 | list<DAE.Subscript> ssl; | ||
| 10873 | DAE.ComponentRef cref,cref_2; | ||
| 10874 | String id; | ||
| 10875 | DAE.Type ety,ty2; | ||
| 10876 | Boolean scalar; | ||
| 10877 | // a component reference | ||
| 10878 | case(DAE.CREF(cref, ety),DAE.CREF(DAE.CREF_IDENT(id,ty2, ssl),_)) | ||
| 10879 | algorithm | ||
| 10880 | 21202 | cref_2 := ComponentReferenceBasics.makeCrefQual(id,ty2, ssl,cref); | |
| 10881 | 21202 | then Expression.makeCrefExp(cref_2,ety); | |
| 10882 | // an array | ||
| 10883 | case(exp1 as DAE.ARRAY(ety, _, expl1), exp2 as DAE.CREF(DAE.CREF_IDENT(_,_, _),_)) | ||
| 10884 | algorithm | ||
| 10885 | 8240 | expl1 := List.map1(expl1,mergeQualWithRest2,exp2); | |
| 10886 | 8240 | exp1 := DAE.ARRAY(DAE.T_INTEGER_DEFAULT,false,expl1); | |
| 10887 | 8240 | (_, scalar) := extractDimensionOfChild(exp1); | |
| 10888 |
2/2✓ Branch 0 taken 252 times.
✓ Branch 1 taken 7988 times.
|
8492 | then DAE.ARRAY(ety, scalar, expl1); |
| 10889 | end match; | ||
| 10890 | end mergeQualWithRest2; | ||
| 10891 | |||
| 10892 | protected function flattenSubscript | ||
| 10893 | "to catch subscript free CREF's." | ||
| 10894 | input list<DAE.Subscript> inSubs; | ||
| 10895 | input String name; | ||
| 10896 | input DAE.Type inType; | ||
| 10897 | output DAE.Exp outExp; | ||
| 10898 | algorithm | ||
| 10899 | outExp := matchcontinue(inSubs,name, inType) | ||
| 10900 | local | ||
| 10901 | String id; | ||
| 10902 | list<DAE.Subscript> subs1; | ||
| 10903 | DAE.Exp exp1,exp2; | ||
| 10904 | DAE.Type ety; | ||
| 10905 | DAE.ComponentRef cref_; | ||
| 10906 | // empty list | ||
| 10907 | case({},id,ety) | ||
| 10908 | algorithm | ||
| 10909 | 7311 | cref_ := ComponentReferenceBasics.makeCrefIdent(id,ety,{}); | |
| 10910 | 7311 | exp1 := Expression.makeCrefExp(cref_,ety); | |
| 10911 | then | ||
| 10912 | exp1; | ||
| 10913 | // some subscripts present | ||
| 10914 | case(subs1,id,ety) // {1,2,3} | ||
| 10915 | algorithm | ||
| 10916 | 33796 | exp2 := flattenSubscript2(subs1,id,ety); | |
| 10917 | then | ||
| 10918 | exp2; | ||
| 10919 | end matchcontinue; | ||
| 10920 | end flattenSubscript; | ||
| 10921 | |||
| 10922 | // BZ(2010-01-29): Changed to public to be able to vectorize crefs from other places | ||
| 10923 | public function flattenSubscript2 | ||
| 10924 | "This function takes the created 'invalid' subscripts | ||
| 10925 | and the name of the CREF and returning the CREFS | ||
| 10926 | Example: flattenSubscript2({SLICE({1,2}},SLICE({1}),\"a\",tp) ==> {{a[1,1]},{a[2,1]}}. | ||
| 10927 | |||
| 10928 | This is done in several function calls, this specific | ||
| 10929 | function extracts the numbers ( 1,2 and 1 ). | ||
| 10930 | " | ||
| 10931 | input list<DAE.Subscript> inSubs; | ||
| 10932 | input String name; | ||
| 10933 | input DAE.Type inType; | ||
| 10934 | output DAE.Exp outExp; | ||
| 10935 | algorithm | ||
| 10936 | outExp := matchcontinue(inSubs,name, inType) | ||
| 10937 | local | ||
| 10938 | String id; | ||
| 10939 | DAE.Subscript sub1; | ||
| 10940 | list<DAE.Subscript> subs1; | ||
| 10941 | list<DAE.Exp> expl1,expl2; | ||
| 10942 | DAE.Exp exp1,exp2,exp3; | ||
| 10943 | DAE.Type ety; | ||
| 10944 | |||
| 10945 | // empty subscript | ||
| 10946 | case({},_,_) then DAE.ARRAY(DAE.T_UNKNOWN_DEFAULT,false,{}); | ||
| 10947 | |||
| 10948 | // first subscript integer, ety | ||
| 10949 | case( ( (DAE.INDEX(exp = exp1 as DAE.ICONST(_))) :: subs1),id,ety) | ||
| 10950 | algorithm | ||
| 10951 | 1513 | exp2 := flattenSubscript2(subs1,id,ety); | |
| 10952 | //print("1. flattened rest into "+ExpressionDump.dumpExpStr(exp2,0)+"\n"); | ||
| 10953 | 1513 | exp2 := applySubscript(exp1, exp2 ,id,Expression.unliftArray(ety)); | |
| 10954 | //print("1. applied this subscript into "+ExpressionDump.dumpExpStr(exp2,0)+"\n"); | ||
| 10955 | then | ||
| 10956 | exp2; | ||
| 10957 | // special case for zero dimension... | ||
| 10958 | case( ((DAE.SLICE( DAE.ARRAY(_,_,(expl1 as DAE.ICONST(0)::{})) )):: subs1),id,ety) // {1,2,3} | ||
| 10959 | algorithm | ||
| 10960 | 1327 | exp2 := flattenSubscript2(subs1,id,ety); | |
| 10961 | 1327 | expl2 := List.map3(expl1,applySubscript,exp2,id,ety); | |
| 10962 | 1327 | exp3 := listHead(expl2); | |
| 10963 | //exp3 = removeDoubleEmptyArrays(exp3); | ||
| 10964 | then | ||
| 10965 | exp3; | ||
| 10966 | // normal case; | ||
| 10967 | case( ((DAE.SLICE( DAE.ARRAY(_,_,expl1) )):: subs1),id,ety) // {1,2,3} | ||
| 10968 | algorithm | ||
| 10969 | 940 | exp2 := flattenSubscript2(subs1,id,ety); | |
| 10970 | 940 | then | |
| 10971 | flattenSubscript3(expl1, id, ety, exp2); | ||
| 10972 | |||
| 10973 | case ((sub1 as DAE.SLICE(exp = DAE.RANGE())) :: subs1, id, ety) | ||
| 10974 | algorithm | ||
| 10975 | 31973 | expl1 := Expression.expandRange(sub1.exp); | |
| 10976 | 31973 | exp2 := flattenSubscript2(subs1, id, ety); | |
| 10977 | 31970 | then | |
| 10978 | flattenSubscript3(expl1, id, ety, exp2); | ||
| 10979 | |||
| 10980 | end matchcontinue; | ||
| 10981 | end flattenSubscript2; | ||
| 10982 | |||
| 10983 | protected function flattenSubscript3 | ||
| 10984 | input list<DAE.Exp> inSubscripts; | ||
| 10985 | input String inName; | ||
| 10986 | input DAE.Type inType; | ||
| 10987 | input DAE.Exp inExp; | ||
| 10988 | output DAE.Exp outExp; | ||
| 10989 | protected | ||
| 10990 | list<DAE.Exp> expl; | ||
| 10991 | list<DAE.Dimension> dims; | ||
| 10992 | Boolean scalar; | ||
| 10993 | DAE.Type ty; | ||
| 10994 | algorithm | ||
| 10995 |
4/4✓ Branch 0 taken 102815 times.
✓ Branch 1 taken 32910 times.
✓ Branch 2 taken 102815 times.
✓ Branch 3 taken 32910 times.
|
135725 | expl := list(applySubscript(e, inExp, inName, inType) for e in inSubscripts); |
| 10996 | 32910 | outExp := DAE.ARRAY(DAE.T_INTEGER_DEFAULT, false, expl); | |
| 10997 | 32910 | (dims, scalar) := extractDimensionOfChild(outExp); | |
| 10998 | 32910 | ty := Expression.arrayEltType(inType); | |
| 10999 |
2/2✓ Branch 1 taken 1121 times.
✓ Branch 2 taken 31789 times.
|
34031 | outExp := DAE.ARRAY(DAE.T_ARRAY(ty, dims), scalar, expl); |
| 11000 | end flattenSubscript3; | ||
| 11001 | |||
| 11002 | protected function removeDoubleEmptyArrays | ||
| 11003 | " A help function, to prevent the {{}} look of empty arrays." | ||
| 11004 | input DAE.Exp inArr; | ||
| 11005 | output DAE.Exp outArr; | ||
| 11006 | algorithm | ||
| 11007 | outArr := matchcontinue inArr | ||
| 11008 | local | ||
| 11009 | DAE.Exp exp1,exp2; | ||
| 11010 | list<DAE.Exp> expl1,expl3; | ||
| 11011 | DAE.Type ty1; | ||
| 11012 | Boolean sc; | ||
| 11013 | case DAE.ARRAY(array = ((exp2 as DAE.ARRAY(array={}))::{}) ) | ||
| 11014 | then | ||
| 11015 | exp2; | ||
| 11016 | case DAE.ARRAY(ty = ty1,scalar=sc,array = expl1 as | ||
| 11017 | ((DAE.ARRAY())::expl3) ) | ||
| 11018 | algorithm | ||
| 11019 | ✗ | expl3 := List.map(expl1,removeDoubleEmptyArrays); | |
| 11020 | ✗ | exp1 := DAE.ARRAY(ty1, sc, (expl3)); | |
| 11021 | then | ||
| 11022 | exp1; | ||
| 11023 | case exp1 then exp1; | ||
| 11024 | case exp1 | ||
| 11025 | algorithm | ||
| 11026 | ✗ | print("- Static.removeDoubleEmptyArrays failure for: " + ExpressionBasics.printExpStr(exp1) + "\n"); | |
| 11027 | ✗ | then | |
| 11028 | fail(); | ||
| 11029 | end matchcontinue; | ||
| 11030 | end removeDoubleEmptyArrays; | ||
| 11031 | |||
| 11032 | protected function applySubscript | ||
| 11033 | "here we apply the subscripts to the IDENTS of the CREF's. | ||
| 11034 | Special case for adressing INDEX[0], make an empty array. | ||
| 11035 | If we have an array of subscript, we call applySubscript2" | ||
| 11036 | input DAE.Exp inSub "dim n "; | ||
| 11037 | input DAE.Exp inSubs "dim >n"; | ||
| 11038 | input String name; | ||
| 11039 | input DAE.Type inType; | ||
| 11040 | output DAE.Exp outExp; | ||
| 11041 | algorithm | ||
| 11042 | outExp := matchcontinue(inSub, inSubs ,name, inType) | ||
| 11043 | local | ||
| 11044 | String id; | ||
| 11045 | DAE.Exp exp1,exp2; | ||
| 11046 | DAE.Type ety,crty; | ||
| 11047 | DAE.Dimensions arrDim; | ||
| 11048 | DAE.ComponentRef cref_; | ||
| 11049 | |||
| 11050 | case(_,exp1 as DAE.ARRAY(DAE.T_ARRAY(dims = arrDim) ,_,{}),_ ,_) | ||
| 11051 | algorithm | ||
| 11052 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 514 times.
|
514 | true := Expression.arrayContainZeroDimension(arrDim); |
| 11053 | then exp1; | ||
| 11054 | |||
| 11055 | /* add dimensions */ | ||
| 11056 | case(DAE.ICONST(integer=0),DAE.ARRAY(DAE.T_ARRAY(dims = arrDim) ,_,_),_ ,ety) | ||
| 11057 | algorithm | ||
| 11058 | 3 | ety := Expression.arrayEltType(ety); | |
| 11059 | 3 | then DAE.ARRAY(DAE.T_ARRAY(ety, DAE.DIM_INTEGER(0)::arrDim),true,{}); | |
| 11060 | |||
| 11061 | case(DAE.ICONST(integer=0),_,_ ,ety) | ||
| 11062 | algorithm | ||
| 11063 | 1322 | ety := Expression.arrayEltType(ety); | |
| 11064 | 1322 | then DAE.ARRAY(DAE.T_ARRAY(ety,{DAE.DIM_INTEGER(0)}),true,{}); | |
| 11065 | |||
| 11066 | case(exp1,DAE.ARRAY(_,_,{}),id ,ety) | ||
| 11067 | algorithm | ||
| 11068 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 99404 times.
|
99404 | true := Expression.isValidSubscript(exp1); |
| 11069 | 99404 | crty := Expression.unliftArray(ety) "only subscripting one dimension, unlifting once "; | |
| 11070 | 198808 | cref_ := ComponentReferenceBasics.makeCrefIdent(id,ety,{DAE.INDEX(exp1)}); | |
| 11071 | 99404 | then Expression.makeCrefExp(cref_,crty); | |
| 11072 | |||
| 11073 | case(exp1, exp2, _ ,ety) | ||
| 11074 | algorithm | ||
| 11075 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4412 times.
|
4412 | true := Expression.isValidSubscript(exp1); |
| 11076 | 4412 | then applySubscript2(exp1, exp2,ety); | |
| 11077 | end matchcontinue; | ||
| 11078 | end applySubscript; | ||
| 11079 | |||
| 11080 | protected function applySubscript2 | ||
| 11081 | "Handles multiple subscripts for the expression. | ||
| 11082 | If it is an array, we listmap applySubscript3" | ||
| 11083 | input DAE.Exp inSub "The subs to add"; | ||
| 11084 | input DAE.Exp inSubs "The already created subs"; | ||
| 11085 | input DAE.Type inType; | ||
| 11086 | output DAE.Exp outExp; | ||
| 11087 | algorithm | ||
| 11088 | outExp := match(inSub, inSubs, inType ) | ||
| 11089 | local | ||
| 11090 | String id; | ||
| 11091 | DAE.Exp exp1,exp2; | ||
| 11092 | list<DAE.Exp> expl1; | ||
| 11093 | list<DAE.Subscript> subs; | ||
| 11094 | DAE.Type ety,ty2,crty; | ||
| 11095 | DAE.Dimensions iLst; | ||
| 11096 | Boolean scalar; | ||
| 11097 | DAE.ComponentRef cref_; | ||
| 11098 | |||
| 11099 | case(exp1, DAE.CREF(DAE.CREF_IDENT(id,ty2,subs),_ ),_ ) | ||
| 11100 | algorithm | ||
| 11101 | 724 | crty := Expression.unliftArrayTypeWithSubs(DAE.INDEX(exp1)::subs,ty2); | |
| 11102 | 724 | cref_ := ComponentReferenceBasics.makeCrefIdent(id,ty2,(DAE.INDEX(exp1)::subs)); | |
| 11103 | 362 | exp2 := Expression.makeCrefExp(cref_,crty); | |
| 11104 | then exp2; | ||
| 11105 | |||
| 11106 | case(exp1, DAE.ARRAY(_,_,expl1),ety ) | ||
| 11107 | algorithm | ||
| 11108 | 4050 | expl1 := List.map2(expl1,applySubscript3,exp1,ety); | |
| 11109 | 4050 | exp2 := DAE.ARRAY(DAE.T_INTEGER_DEFAULT,false,expl1); | |
| 11110 | 4050 | (iLst, scalar) := extractDimensionOfChild(exp2); | |
| 11111 | 4050 | ety := Expression.arrayEltType(ety); | |
| 11112 |
2/2✓ Branch 1 taken 11 times.
✓ Branch 2 taken 4039 times.
|
4061 | exp2 := DAE.ARRAY(DAE.T_ARRAY(ety, iLst), scalar, expl1); |
| 11113 | then exp2; | ||
| 11114 | end match; | ||
| 11115 | end applySubscript2; | ||
| 11116 | |||
| 11117 | protected function applySubscript3 | ||
| 11118 | "Final applySubscript function, here we call ourself | ||
| 11119 | recursive until we have the CREFS we are looking for." | ||
| 11120 | input DAE.Exp inSubs "The already created subs"; | ||
| 11121 | input DAE.Exp inSub "The subs to add"; | ||
| 11122 | input DAE.Type inType; | ||
| 11123 | output DAE.Exp outExp; | ||
| 11124 | algorithm | ||
| 11125 | outExp := match(inSubs,inSub, inType ) | ||
| 11126 | local | ||
| 11127 | String id; | ||
| 11128 | DAE.Exp exp1,exp2; | ||
| 11129 | list<DAE.Exp> expl1; | ||
| 11130 | list<DAE.Subscript> subs; | ||
| 11131 | DAE.Type ety,ty2,crty; | ||
| 11132 | DAE.Dimensions iLst; | ||
| 11133 | Boolean scalar; | ||
| 11134 | DAE.ComponentRef cref_; | ||
| 11135 | |||
| 11136 | case(DAE.CREF(DAE.CREF_IDENT(id,ty2,subs),_), exp1, _ ) | ||
| 11137 | algorithm | ||
| 11138 | 21448 | crty := Expression.unliftArrayTypeWithSubs(DAE.INDEX(exp1)::subs,ty2); | |
| 11139 | 21448 | cref_ := ComponentReferenceBasics.makeCrefIdent(id,ty2,(DAE.INDEX(exp1)::subs)); | |
| 11140 | 10724 | exp2 := Expression.makeCrefExp(cref_,crty); | |
| 11141 | then exp2; | ||
| 11142 | |||
| 11143 | case(DAE.ARRAY(_,_,expl1), exp1, ety) | ||
| 11144 | algorithm | ||
| 11145 | 22 | expl1 := List.map2(expl1,applySubscript3,exp1,ety); | |
| 11146 | 22 | exp2 := DAE.ARRAY(DAE.T_INTEGER_DEFAULT,false,expl1); | |
| 11147 | 22 | (iLst, scalar) := extractDimensionOfChild(exp2); | |
| 11148 | 22 | ety := Expression.arrayEltType(ety); | |
| 11149 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 20 times.
|
24 | exp2 := DAE.ARRAY(DAE.T_ARRAY(ety, iLst), scalar, expl1); |
| 11150 | then exp2; | ||
| 11151 | end match; | ||
| 11152 | end applySubscript3; | ||
| 11153 | |||
| 11154 | |||
| 11155 | protected function callVectorize | ||
| 11156 | "author: PA | ||
| 11157 | |||
| 11158 | Takes an expression that is a function call and an expresion list | ||
| 11159 | and maps the call to each expression in the list. | ||
| 11160 | For instance, call_vectorize(DAE.CALL(XX(\"der\",),...),{1,2,3})) | ||
| 11161 | => {DAE.CALL(XX(\"der\"),{1}), DAE.CALL(XX(\"der\"),{2}),DAE.CALL(XX(\"der\",{3}))} | ||
| 11162 | NOTE: the vectorized expression is inserted first in the argument list | ||
| 11163 | of the call, so if extra arguments should be passed these can be given as | ||
| 11164 | input to the call expression." | ||
| 11165 | input DAE.Exp inExp; | ||
| 11166 | input list<DAE.Exp> inExpExpLst; | ||
| 11167 | output list<DAE.Exp> outExpExpLst; | ||
| 11168 | algorithm | ||
| 11169 | outExpExpLst := matchcontinue (inExp,inExpExpLst) | ||
| 11170 | local | ||
| 11171 | DAE.Exp e,callexp; | ||
| 11172 | list<DAE.Exp> es_1,args,es; | ||
| 11173 | Absyn.Path fn; | ||
| 11174 | DAE.CallAttributes attr; | ||
| 11175 | // empty list | ||
| 11176 | case (_,{}) then {}; | ||
| 11177 | // vectorize call | ||
| 11178 | case ((callexp as DAE.CALL(fn,args,attr)),(e :: es)) | ||
| 11179 | algorithm | ||
| 11180 | ✗ | es_1 := callVectorize(callexp, es); | |
| 11181 | ✗ | then | |
| 11182 | (DAE.CALL(fn,(e :: args),attr) :: es_1); | ||
| 11183 | else | ||
| 11184 | algorithm | ||
| 11185 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 11186 | ✗ | Debug.trace("- Static.callVectorize failed\n"); | |
| 11187 | ✗ | then | |
| 11188 | fail(); | ||
| 11189 | end matchcontinue; | ||
| 11190 | end callVectorize; | ||
| 11191 | |||
| 11192 | protected function createCrefArray | ||
| 11193 | "helper function to crefVectorize, creates each individual cref, | ||
| 11194 | e.g. {x{1},x{2}, ...} from x." | ||
| 11195 | input DAE.ComponentRef inComponentRef1; | ||
| 11196 | input Integer inInteger2; | ||
| 11197 | input Integer inInteger3; | ||
| 11198 | input DAE.Type inType4; | ||
| 11199 | input DAE.Type inType5; | ||
| 11200 | input DAE.Type crefIdType; | ||
| 11201 | output DAE.Exp outExp; | ||
| 11202 | algorithm | ||
| 11203 | outExp := matchcontinue (inComponentRef1, inInteger2, inInteger3, inType4, inType5) | ||
| 11204 | local | ||
| 11205 | DAE.ComponentRef cr,cr_1; | ||
| 11206 | Integer indx,ds,indx_1; | ||
| 11207 | DAE.Type et,elt_tp; | ||
| 11208 | DAE.Type t; | ||
| 11209 | list<DAE.Exp> expl; | ||
| 11210 | DAE.Exp e_1; | ||
| 11211 | // index iterator dimension size | ||
| 11212 | case (_, indx, ds, et, _) guard indx > ds | ||
| 11213 | 290 | then | |
| 11214 | DAE.ARRAY(et,true,{}); | ||
| 11215 | // index | ||
| 11216 | /* | ||
| 11217 | case (cr,indx,ds,et,t,crefIdType) | ||
| 11218 | algorithm | ||
| 11219 | (DAE.INDEX(e_1) :: ss) = ComponentReference.crefLastSubs(cr); | ||
| 11220 | cr_1 = ComponentReferenceBasics.crefStripLastSubs(cr); | ||
| 11221 | cr_1 = ComponentReference.subscriptCref(cr_1,ss); | ||
| 11222 | DAE.ARRAY(_,_,expl) = createCrefArray(cr_1, indx, ds, et, t,crefIdType); | ||
| 11223 | expl = List.map1(expl,Expression.prependSubscriptExp,DAE.INDEX(e_1)); | ||
| 11224 | then | ||
| 11225 | DAE.ARRAY(et,true,expl); | ||
| 11226 | */ | ||
| 11227 | // for crefs with wholedim | ||
| 11228 | case (cr, indx, ds, et, t) | ||
| 11229 | algorithm | ||
| 11230 | 628 | indx_1 := indx + 1; | |
| 11231 | 628 | cr_1 := ComponentReference.replaceWholeDimSubscript(cr,indx); | |
| 11232 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 593 times.
|
593 | DAE.ARRAY(_,_,expl) := createCrefArray(cr, indx_1, ds, et, t,crefIdType); |
| 11233 | 593 | elt_tp := Expression.unliftArray(et); | |
| 11234 | 593 | e_1 := crefVectorize(true,Expression.makeCrefExp(cr_1,elt_tp), t,NONE(),crefIdType); | |
| 11235 | 593 | then | |
| 11236 | DAE.ARRAY(et,true,(e_1 :: expl)); | ||
| 11237 | // no subscript | ||
| 11238 | case (cr, indx, ds, et, t) | ||
| 11239 | algorithm | ||
| 11240 | 35 | indx_1 := indx + 1; | |
| 11241 | // {} = ComponentReference.crefLastSubs(cr); | ||
| 11242 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 35 times.
|
35 | DAE.ARRAY(_,_,expl) := createCrefArray(cr, indx_1, ds, et, t,crefIdType); |
| 11243 | 70 | e_1 := Expression.makeASUB(Expression.makeCrefExp(cr,et),{DAE.ICONST(indx)}); | |
| 11244 | 35 | (e_1,_) := ExpressionSimplify.simplify(e_1); | |
| 11245 | 35 | e_1 := crefVectorize(true,e_1, t,NONE(),crefIdType); | |
| 11246 | 35 | then | |
| 11247 | DAE.ARRAY(et,true,(e_1 :: expl)); | ||
| 11248 | // failure | ||
| 11249 | case (cr, _, _, _, _) | ||
| 11250 | algorithm | ||
| 11251 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 11252 | ✗ | Debug.trace("createCrefArray failed on:" + ComponentReferenceBasics.printComponentRefStr(cr)); | |
| 11253 | ✗ | then | |
| 11254 | fail(); | ||
| 11255 | end matchcontinue; | ||
| 11256 | end createCrefArray; | ||
| 11257 | |||
| 11258 | protected function createCrefArray2d | ||
| 11259 | "helper function to cref_vectorize, creates each | ||
| 11260 | individual cref, e.g. {x{1,1},x{2,1}, ...} from x." | ||
| 11261 | input DAE.ComponentRef inCref; | ||
| 11262 | input Integer inIndex; | ||
| 11263 | input Integer inDim1; | ||
| 11264 | input Integer inDim2; | ||
| 11265 | input DAE.Type inType5; | ||
| 11266 | input DAE.Type inType6; | ||
| 11267 | input DAE.Type crefIdType; | ||
| 11268 | output DAE.Exp outExp; | ||
| 11269 | algorithm | ||
| 11270 | outExp := matchcontinue (inCref, inIndex, inDim1, inDim2, inType5, inType6) | ||
| 11271 | local | ||
| 11272 | DAE.ComponentRef cr,cr_1; | ||
| 11273 | Integer indx,ds,ds2,indx_1; | ||
| 11274 | DAE.Type et,elt_tp; | ||
| 11275 | DAE.Type t; | ||
| 11276 | list<list<DAE.Exp>> ms; | ||
| 11277 | list<DAE.Exp> expl; | ||
| 11278 | // index iterator dimension size 1 dimension size 2 | ||
| 11279 | case (_, indx, ds, _, et, _) guard indx > ds | ||
| 11280 | ✗ | then | |
| 11281 | DAE.MATRIX(et,0,{}); | ||
| 11282 | // increase the index dimension | ||
| 11283 | case (cr, indx, ds, ds2, et, t) | ||
| 11284 | algorithm | ||
| 11285 | ✗ | indx_1 := indx + 1; | |
| 11286 | ✗ | DAE.MATRIX(matrix = ms) := createCrefArray2d(cr, indx_1, ds, ds2, et, t,crefIdType); | |
| 11287 | ✗ | cr_1 := ComponentReference.subscriptCref(cr, {DAE.INDEX(DAE.ICONST(indx))}); | |
| 11288 | ✗ | elt_tp := Expression.unliftArray(et); | |
| 11289 | ✗ | DAE.ARRAY(_,true,expl) := crefVectorize(true,Expression.makeCrefExp(cr_1,elt_tp), t,NONE(),crefIdType); | |
| 11290 | ✗ | then | |
| 11291 | DAE.MATRIX(et,ds,(expl :: ms)); | ||
| 11292 | // | ||
| 11293 | case (cr, _, _, _, _, _) | ||
| 11294 | algorithm | ||
| 11295 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 11296 | ✗ | Debug.traceln("- Static.createCrefArray2d failed on: " + ComponentReferenceBasics.printComponentRefStr(cr)); | |
| 11297 | ✗ | then | |
| 11298 | fail(); | ||
| 11299 | end matchcontinue; | ||
| 11300 | end createCrefArray2d; | ||
| 11301 | |||
| 11302 | public function absynCrefToComponentReference "This function converts an absyn cref to a component reference" | ||
| 11303 | input Absyn.ComponentRef inComponentRef; | ||
| 11304 | output DAE.ComponentRef outComponentRef; | ||
| 11305 | algorithm | ||
| 11306 | outComponentRef := match inComponentRef | ||
| 11307 | local | ||
| 11308 | String i; | ||
| 11309 | Absyn.ComponentRef c; | ||
| 11310 | DAE.ComponentRef cref; | ||
| 11311 | |||
| 11312 | case Absyn.CREF_IDENT(name = i,subscripts = {}) | ||
| 11313 | algorithm | ||
| 11314 | ✗ | cref := ComponentReferenceBasics.makeCrefIdent(i, DAE.T_UNKNOWN_DEFAULT, {}); | |
| 11315 | then | ||
| 11316 | cref; | ||
| 11317 | |||
| 11318 | case Absyn.CREF_QUAL(name = i,subscripts = {},componentRef = c) | ||
| 11319 | algorithm | ||
| 11320 | ✗ | cref := absynCrefToComponentReference(c); | |
| 11321 | ✗ | cref := ComponentReferenceBasics.makeCrefQual(i, DAE.T_UNKNOWN_DEFAULT, {}, cref); | |
| 11322 | then | ||
| 11323 | cref; | ||
| 11324 | |||
| 11325 | case Absyn.CREF_FULLYQUALIFIED(componentRef = c) | ||
| 11326 | algorithm | ||
| 11327 | ✗ | cref := absynCrefToComponentReference(c); | |
| 11328 | then | ||
| 11329 | cref; | ||
| 11330 | end match; | ||
| 11331 | end absynCrefToComponentReference; | ||
| 11332 | |||
| 11333 | protected function elabCrefSubs | ||
| 11334 | "This function elaborates on all subscripts in a component reference." | ||
| 11335 | input FCore.Cache inCache; | ||
| 11336 | input FCore.Graph inCrefEnv "search for the cref in this environment"; | ||
| 11337 | input FCore.Graph inSubsEnv; | ||
| 11338 | input Absyn.ComponentRef inComponentRef; | ||
| 11339 | input DAE.Prefix inTopPrefix "the top prefix, i.e. the one send down by elabCref1, needed to prefix expressions in subscript types!"; | ||
| 11340 | input DAE.Prefix inCrefPrefix "the accumulated cref, required for lookup"; | ||
| 11341 | input Boolean inBoolean; | ||
| 11342 | input Boolean inHasZeroSizeDim; | ||
| 11343 | input SourceInfo info; | ||
| 11344 | output FCore.Cache outCache; | ||
| 11345 | output DAE.ComponentRef outComponentRef; | ||
| 11346 | output DAE.Const outConst "The constness of the subscripts. Note: This is not the same as | ||
| 11347 | the constness of a cref with subscripts! (just becase x[1,2] has a constant subscript list does | ||
| 11348 | not mean that the variable x[1,2] is constant)"; | ||
| 11349 | output Boolean outHasZeroSizeDim; | ||
| 11350 | algorithm | ||
| 11351 | (outCache,outComponentRef,outConst,outHasZeroSizeDim) := matchcontinue (inCache, inCrefEnv, inSubsEnv, inComponentRef, inTopPrefix, inCrefPrefix, inBoolean, inHasZeroSizeDim) | ||
| 11352 | local | ||
| 11353 | DAE.Type t; | ||
| 11354 | DAE.Dimensions sl; | ||
| 11355 | DAE.Const const,const1,const2; | ||
| 11356 | FCore.Graph crefEnv, crefSubs; | ||
| 11357 | String id; | ||
| 11358 | list<Absyn.Subscript> ss; | ||
| 11359 | Boolean impl, hasZeroSizeDim; | ||
| 11360 | DAE.ComponentRef cr; | ||
| 11361 | Absyn.ComponentRef absynCr; | ||
| 11362 | DAE.Type ty, id_ty; | ||
| 11363 | list<DAE.Subscript> ss_1; | ||
| 11364 | Absyn.ComponentRef restCref,absynCref; | ||
| 11365 | FCore.Cache cache; | ||
| 11366 | SCode.Variability vt; | ||
| 11367 | DAE.Prefix crefPrefix; | ||
| 11368 | DAE.Prefix topPrefix; | ||
| 11369 | |||
| 11370 | // IDENT | ||
| 11371 | case (cache, crefEnv, crefSubs, Absyn.CREF_IDENT(name = id,subscripts = ss), topPrefix, crefPrefix, impl, hasZeroSizeDim) | ||
| 11372 | algorithm | ||
| 11373 | // Debug.traceln("Try elabSucscriptsDims " + id); | ||
| 11374 | 584823 | (cache,cr) := PrefixUtil.prefixCref(cache,crefEnv,InnerOuter.emptyInstHierarchy,crefPrefix, | |
| 11375 | ComponentReferenceBasics.makeCrefIdent(id,DAE.T_UNKNOWN_DEFAULT,{})); | ||
| 11376 | 584823 | (cache,_,_,_,_,InstTypes.SPLICEDEXPDATA(identType = id_ty),_,_,_) := Lookup.lookupVar(cache, crefEnv, cr); | |
| 11377 | // false = Types.isUnknownType(t); | ||
| 11378 | // print("elabCrefSubs type of: " + id + " is " + TypesDump.printTypeStr(t) + "\n"); | ||
| 11379 | // Debug.traceln(" elabSucscriptsDims " + id + " got var"); | ||
| 11380 | // _ = Types.simplifyType(t); | ||
| 11381 | 535356 | id_ty := Types.simplifyType(id_ty); | |
| 11382 | 535356 | hasZeroSizeDim := Types.isZeroLengthArray(id_ty); | |
| 11383 | 535356 | sl := TypesDump.getDimensions(id_ty); | |
| 11384 | // Constant evaluate subscripts on form x[1,p,q] where p,q are constants or parameters | ||
| 11385 | 535356 | (cache,ss_1,const) := elabSubscriptsDims(cache, crefSubs, ss, sl, impl, topPrefix, inComponentRef, info); | |
| 11386 | 535354 | then | |
| 11387 | (cache,ComponentReferenceBasics.makeCrefIdent(id,id_ty,ss_1),const,hasZeroSizeDim); | ||
| 11388 | |||
| 11389 | // QUAL,with no subscripts => looking for var in the top env! | ||
| 11390 | case (cache, crefEnv, crefSubs, Absyn.CREF_QUAL(name = id,subscripts = {},componentRef = restCref), topPrefix, crefPrefix, impl, hasZeroSizeDim) | ||
| 11391 | algorithm | ||
| 11392 | 187439 | (cache,cr) := PrefixUtil.prefixCref(cache,crefEnv,InnerOuter.emptyInstHierarchy,crefPrefix, | |
| 11393 | ComponentReferenceBasics.makeCrefIdent(id,DAE.T_UNKNOWN_DEFAULT,{})); | ||
| 11394 | //print("env:");print(FGraph.printGraphStr(env));print("\n"); | ||
| 11395 | 187439 | (cache,_,t,_,_,_,_,_,_) := Lookup.lookupVar(cache, crefEnv, cr); | |
| 11396 | 127939 | ty := Types.simplifyType(t); | |
| 11397 | 127939 | sl := TypesDump.getDimensions(ty); | |
| 11398 | 127939 | crefPrefix := PrefixUtil.prefixAdd(id,sl,{},crefPrefix,SCode.VAR(),ClassInf.UNKNOWN(Absyn.IDENT("")),info); // variability doesn't matter | |
| 11399 | 127939 | (cache,cr,const,hasZeroSizeDim) := elabCrefSubs(cache, crefEnv, crefSubs, restCref, topPrefix, crefPrefix, impl, hasZeroSizeDim, info); | |
| 11400 | 98035 | then | |
| 11401 | (cache,ComponentReferenceBasics.makeCrefQual(id,ty,{},cr),const,hasZeroSizeDim); | ||
| 11402 | |||
| 11403 | // QUAL,with no subscripts second case => look for class | ||
| 11404 | case (cache, crefEnv, crefSubs, Absyn.CREF_QUAL(name = id,subscripts = {},componentRef = restCref), topPrefix, crefPrefix, impl, hasZeroSizeDim) | ||
| 11405 | algorithm | ||
| 11406 | 89404 | crefPrefix := PrefixUtil.prefixAdd(id,{},{},crefPrefix,SCode.VAR(),ClassInf.UNKNOWN(Absyn.IDENT("")),info); // variability doesn't matter | |
| 11407 | 89404 | (cache,cr,const,hasZeroSizeDim) := elabCrefSubs(cache, crefEnv, crefSubs, restCref, topPrefix, crefPrefix, impl, hasZeroSizeDim, info); | |
| 11408 | 58117 | then | |
| 11409 | (cache,ComponentReferenceBasics.makeCrefQual(id,DAE.T_COMPLEX_DEFAULT,{},cr),const,hasZeroSizeDim); | ||
| 11410 | |||
| 11411 | // QUAL,with constant subscripts | ||
| 11412 | case (cache, crefEnv, crefSubs, Absyn.CREF_QUAL(name = id,subscripts = ss as _::_,componentRef = restCref), topPrefix, crefPrefix, impl, hasZeroSizeDim) | ||
| 11413 | algorithm | ||
| 11414 | 994 | (cache,cr) := PrefixUtil.prefixCref(cache,crefEnv,InnerOuter.emptyInstHierarchy,crefPrefix, | |
| 11415 | ComponentReferenceBasics.makeCrefIdent(id,DAE.T_UNKNOWN_DEFAULT,{})); | ||
| 11416 | 994 | (cache,DAE.ATTR(variability = vt),t,_,_,InstTypes.SPLICEDEXPDATA(identType = id_ty),_,_,_) := Lookup.lookupVar(cache, crefEnv, cr); | |
| 11417 | 950 | ty := Types.simplifyType(t); | |
| 11418 | 950 | id_ty := Types.simplifyType(id_ty); | |
| 11419 | 950 | sl := TypesDump.getDimensions(id_ty); | |
| 11420 | 950 | (cache,ss_1,const1) := elabSubscriptsDims(cache, crefSubs, ss, sl, impl, topPrefix, inComponentRef, info); | |
| 11421 | 950 | crefPrefix := PrefixUtil.prefixAdd(id, sl, ss_1, crefPrefix, vt, ClassInf.UNKNOWN(Absyn.IDENT("")),info); | |
| 11422 | 950 | (cache,cr,const2,hasZeroSizeDim) := elabCrefSubs(cache, crefEnv, crefSubs, restCref, topPrefix, crefPrefix, impl, hasZeroSizeDim, info); | |
| 11423 | 950 | const := Types.constAnd(const1, const2); | |
| 11424 | 950 | then | |
| 11425 | (cache,ComponentReferenceBasics.makeCrefQual(id,ty,ss_1,cr),const,hasZeroSizeDim); | ||
| 11426 | |||
| 11427 | case (cache, crefEnv, crefSubs, Absyn.CREF_FULLYQUALIFIED(componentRef = absynCr), topPrefix, crefPrefix, impl, hasZeroSizeDim) | ||
| 11428 | algorithm | ||
| 11429 | 2835 | crefEnv := FGraph.topScope(crefEnv); | |
| 11430 | 2835 | (cache, cr, const1, hasZeroSizeDim) := elabCrefSubs(cache, crefEnv, crefSubs, absynCr, topPrefix, crefPrefix, impl, hasZeroSizeDim, info); | |
| 11431 | then | ||
| 11432 | (cache, cr, const1, hasZeroSizeDim); | ||
| 11433 | |||
| 11434 | // failure | ||
| 11435 | case (_, crefEnv, _, absynCref, topPrefix, crefPrefix, _, _) | ||
| 11436 | algorithm | ||
| 11437 | // FAILTRACE REMOVE | ||
| 11438 |
2/2✓ Branch 1 taken 80798 times.
✓ Branch 2 taken 2 times.
|
80800 | true := Flags.isSet(Flags.FAILTRACE); |
| 11439 | 2 | Debug.traceln("- Static.elabCrefSubs failed on: " + | |
| 11440 | "[top:" + PrefixUtil.printPrefixStr(topPrefix) + "]." + | ||
| 11441 | PrefixUtil.printPrefixStr(crefPrefix) + "." + | ||
| 11442 | Dump.printComponentRefStr(absynCref) + " env: " + | ||
| 11443 | FGraph.printGraphPathStr(crefEnv)); | ||
| 11444 | 2 | then | |
| 11445 | fail(); | ||
| 11446 | end matchcontinue; | ||
| 11447 | end elabCrefSubs; | ||
| 11448 | |||
| 11449 | public function elabSubscripts | ||
| 11450 | "This function converts a list of Absyn.Subscript to a list of | ||
| 11451 | DAE.Subscript, and checks if all subscripts are constant. | ||
| 11452 | HJ: not checking for constant, returning if constant or not" | ||
| 11453 | input FCore.Cache inCache; | ||
| 11454 | input FCore.Graph inEnv; | ||
| 11455 | input list<Absyn.Subscript> inAbsynSubscriptLst; | ||
| 11456 | input Boolean inBoolean; | ||
| 11457 | input DAE.Prefix inPrefix; | ||
| 11458 | input SourceInfo info; | ||
| 11459 | output FCore.Cache outCache; | ||
| 11460 | output list<DAE.Subscript> outExpSubscriptLst; | ||
| 11461 | output DAE.Const outConst; | ||
| 11462 | algorithm | ||
| 11463 | (outCache,outExpSubscriptLst,outConst) := match (inCache, inEnv, inAbsynSubscriptLst, inBoolean, inPrefix) | ||
| 11464 | local | ||
| 11465 | DAE.Subscript sub_1; | ||
| 11466 | DAE.Const const1,const2,const; | ||
| 11467 | list<DAE.Subscript> subs_1; | ||
| 11468 | FCore.Graph env; | ||
| 11469 | Absyn.Subscript sub; | ||
| 11470 | list<Absyn.Subscript> subs; | ||
| 11471 | Boolean impl; | ||
| 11472 | FCore.Cache cache; | ||
| 11473 | DAE.Prefix pre; | ||
| 11474 | |||
| 11475 | // empty list | ||
| 11476 | case (cache, _, {}, _, _) then (cache,{},DAE.C_CONST()); | ||
| 11477 | // elab a subscript then recurse | ||
| 11478 | case (cache, env, (sub :: subs), impl, pre) | ||
| 11479 | algorithm | ||
| 11480 | 13 | (cache,sub_1,const1, _) := elabSubscript(cache,env, sub, impl,pre,info); | |
| 11481 | 13 | (cache,subs_1,const2) := elabSubscripts(cache,env, subs, impl,pre,info); | |
| 11482 | 13 | const := Types.constAnd(const1, const2); | |
| 11483 | 13 | then | |
| 11484 | (cache,(sub_1 :: subs_1),const); | ||
| 11485 | end match; | ||
| 11486 | end elabSubscripts; | ||
| 11487 | |||
| 11488 | protected function elabSubscriptsDims | ||
| 11489 | "Elaborates a list of subscripts and checks that they are valid for the given dimensions." | ||
| 11490 | input FCore.Cache inCache; | ||
| 11491 | input FCore.Graph inEnv; | ||
| 11492 | input list<Absyn.Subscript> inSubscripts; | ||
| 11493 | input list<DAE.Dimension> inDimensions; | ||
| 11494 | input Boolean inImpl; | ||
| 11495 | input DAE.Prefix inPrefix; | ||
| 11496 | input Absyn.ComponentRef inCref; | ||
| 11497 | input SourceInfo inInfo; | ||
| 11498 | output FCore.Cache outCache = inCache; | ||
| 11499 | output list<DAE.Subscript> outSubs = {}; | ||
| 11500 | output DAE.Const outConst = DAE.C_CONST(); | ||
| 11501 | protected | ||
| 11502 | list<DAE.Dimension> rest_dims = inDimensions; | ||
| 11503 | DAE.Dimension dim; | ||
| 11504 | DAE.Subscript dsub; | ||
| 11505 | DAE.Const const; | ||
| 11506 | Option<DAE.Properties> prop; | ||
| 11507 | String subl_str, diml_str, cref_str; | ||
| 11508 | Integer nrdims, nrsubs; | ||
| 11509 | algorithm | ||
| 11510 |
2/2✓ Branch 0 taken 82318 times.
✓ Branch 1 taken 536304 times.
|
618622 | for asub in inSubscripts loop |
| 11511 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 82318 times.
|
82318 | if listEmpty(rest_dims) then |
| 11512 | // Check that we don't have more subscripts than there are dimensions. | ||
| 11513 | ✗ | cref_str := Dump.printComponentRefStr(inCref); | |
| 11514 | ✗ | subl_str := intString(listLength(inSubscripts)); | |
| 11515 | ✗ | diml_str := intString(listLength(inDimensions)); | |
| 11516 | |||
| 11517 | ✗ | Error.addSourceMessageAndFail(Error.WRONG_NUMBER_OF_SUBSCRIPTS, | |
| 11518 | {cref_str, subl_str, diml_str}, inInfo); | ||
| 11519 | else | ||
| 11520 | 82318 | dim :: rest_dims := rest_dims; | |
| 11521 | end if; | ||
| 11522 | |||
| 11523 | 82318 | (outCache, dsub, const, prop) := | |
| 11524 | elabSubscript(outCache, inEnv, asub, inImpl, inPrefix, inInfo); | ||
| 11525 | 82316 | outConst := Types.constAnd(const, outConst); | |
| 11526 | 82316 | (outCache, dsub) := elabSubscriptsDims2(outCache, inEnv, dsub, dim, | |
| 11527 | outConst, prop, inImpl, inCref, inInfo); | ||
| 11528 | |||
| 11529 | 82316 | outSubs := dsub :: outSubs; | |
| 11530 | end for; | ||
| 11531 | |||
| 11532 | 536304 | nrsubs := listLength(outSubs); | |
| 11533 | |||
| 11534 | // If there are subs and the number of subs is less than dims | ||
| 11535 | // then fill in whole dims for the missing subs. i.e. We have a slice. | ||
| 11536 | // If there are no subs then it is a whole array so we do nothing. | ||
| 11537 |
2/2✓ Branch 0 taken 78703 times.
✓ Branch 1 taken 457601 times.
|
536304 | if nrsubs > 0 then |
| 11538 | 78703 | nrdims := listLength(inDimensions); | |
| 11539 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 78703 times.
|
78703 | while nrsubs < nrdims loop |
| 11540 | outSubs := DAE.WHOLEDIM()::outSubs; | ||
| 11541 | ✗ | nrsubs := nrsubs + 1; | |
| 11542 | end while; | ||
| 11543 | end if; | ||
| 11544 | |||
| 11545 | 536304 | outSubs := listReverse(outSubs); | |
| 11546 | end elabSubscriptsDims; | ||
| 11547 | |||
| 11548 | protected function elabSubscriptsDims2 | ||
| 11549 | "Helper function to elabSubscriptsDims." | ||
| 11550 | input FCore.Cache inCache; | ||
| 11551 | input FCore.Graph inEnv; | ||
| 11552 | input DAE.Subscript inSubscript; | ||
| 11553 | input DAE.Dimension inDimension; | ||
| 11554 | input DAE.Const inConst; | ||
| 11555 | input Option<DAE.Properties> inProperties; | ||
| 11556 | input Boolean inImpl; | ||
| 11557 | input Absyn.ComponentRef inCref; | ||
| 11558 | input SourceInfo inInfo; | ||
| 11559 | output FCore.Cache outCache; | ||
| 11560 | output DAE.Subscript outSubscript; | ||
| 11561 | algorithm | ||
| 11562 | (outCache, outSubscript) := matchcontinue(inDimension, inProperties) | ||
| 11563 | local | ||
| 11564 | FCore.Cache cache; | ||
| 11565 | DAE.Subscript sub; | ||
| 11566 | Integer int_dim; | ||
| 11567 | DAE.Properties prop; | ||
| 11568 | DAE.Type ty; | ||
| 11569 | DAE.Exp e; | ||
| 11570 | String sub_str, dim_str, cref_str; | ||
| 11571 | |||
| 11572 | // If in for iterator loop scope the subscript should never be evaluated to | ||
| 11573 | // a value (since the parameter/const value of iterator variables are not | ||
| 11574 | // available until expansion, which happens later on) | ||
| 11575 | // Note that for loops are expanded 'on the fly' and should therefore not be | ||
| 11576 | // treated in this way. | ||
| 11577 | case (_, _) | ||
| 11578 | algorithm | ||
| 11579 |
2/2✓ Branch 1 taken 81107 times.
✓ Branch 2 taken 1209 times.
|
82316 | true := FGraph.inForOrParforIterLoopScope(inEnv); |
| 11580 |
2/2✓ Branch 1 taken 8 times.
✓ Branch 2 taken 1201 times.
|
1209 | true := Expression.dimensionKnown(inDimension); |
| 11581 | 1201 | then | |
| 11582 | (inCache, inSubscript); | ||
| 11583 | |||
| 11584 | // Keep non-fixed parameters. | ||
| 11585 | case (_, SOME(prop)) | ||
| 11586 | algorithm | ||
| 11587 |
2/2✓ Branch 1 taken 78906 times.
✓ Branch 2 taken 963 times.
|
79869 | true := Types.isParameter(inConst); |
| 11588 | 963 | ty := Types.getPropType(prop); | |
| 11589 |
1/2✓ Branch 1 taken 963 times.
✗ Branch 2 not taken.
|
963 | false := Types.getFixedVarAttributeParameterOrConstant(ty); |
| 11590 | ✗ | then | |
| 11591 | (inCache, inSubscript); | ||
| 11592 | |||
| 11593 | /*/ Keep parameters as they are: | ||
| 11594 | // adrpo 2012-12-02 this does not work as we need to evaluate final parameters! | ||
| 11595 | // and we have now way yet of knowing which ones those are | ||
| 11596 | case (_, _, _, _, _, _, _, _, _) | ||
| 11597 | algorithm | ||
| 11598 | true = Types.isParameter(inConst); | ||
| 11599 | then | ||
| 11600 | (inCache, inSubscript);*/ | ||
| 11601 | |||
| 11602 | // If the subscript contains a const then it should be evaluated to | ||
| 11603 | // the value. | ||
| 11604 | case (_, _) | ||
| 11605 | algorithm | ||
| 11606 | 81115 | int_dim := Expression.dimensionSize(inDimension); | |
| 11607 |
2/2✓ Branch 1 taken 903 times.
✓ Branch 2 taken 79321 times.
|
80224 | true := Types.isParameterOrConstant(inConst); |
| 11608 | 79321 | (cache, sub) := Ceval.cevalSubscript(inCache, inEnv, inSubscript, int_dim, inImpl, Absyn.MSG(inInfo), 0); | |
| 11609 | then | ||
| 11610 | (cache, sub); | ||
| 11611 | |||
| 11612 | case (DAE.DIM_EXP(exp=e), _) | ||
| 11613 | algorithm | ||
| 11614 |
2/2✓ Branch 1 taken 215 times.
✓ Branch 2 taken 41 times.
|
256 | true := Types.isParameterOrConstant(inConst); |
| 11615 |
0/2✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
41 | (_, Values.INTEGER(integer=int_dim)) := Ceval.ceval(inCache,inEnv,e,true,Absyn.MSG(inInfo),0); |
| 11616 | ✗ | (cache, sub) := Ceval.cevalSubscript(inCache, inEnv, inSubscript, int_dim, inImpl, Absyn.MSG(inInfo), 0); | |
| 11617 | then | ||
| 11618 | (cache, sub); | ||
| 11619 | |||
| 11620 | // If the previous case failed and we're just checking the model, try again | ||
| 11621 | // but skip the constant evaluation. | ||
| 11622 | case (_, _) | ||
| 11623 | algorithm | ||
| 11624 |
2/2✓ Branch 1 taken 1769 times.
✓ Branch 2 taken 25 times.
|
1794 | true := Flags.getConfigBool(Flags.CHECK_MODEL); |
| 11625 |
2/2✓ Branch 1 taken 20 times.
✓ Branch 2 taken 5 times.
|
25 | true := Types.isParameterOrConstant(inConst); |
| 11626 | 5 | then | |
| 11627 | (inCache, inSubscript); | ||
| 11628 | |||
| 11629 | // Keep variables and parameters inside of for-loops as they are. | ||
| 11630 | case (_, _) | ||
| 11631 | algorithm | ||
| 11632 |
2/2✓ Branch 1 taken 886 times.
✓ Branch 2 taken 903 times.
|
1789 | true := Expression.dimensionKnown(inDimension); |
| 11633 |
2/6✓ Branch 1 taken 903 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 903 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
|
903 | false := Types.isConstant(inConst) or |
| 11634 | (Types.isParameter(inConst) and not FGraph.inForLoopScope(inEnv)); | ||
| 11635 | 903 | then | |
| 11636 | (inCache, inSubscript); | ||
| 11637 | |||
| 11638 | // For unknown dimensions, ':', keep as is. | ||
| 11639 | case (DAE.DIM_UNKNOWN(), _) | ||
| 11640 | 630 | then (inCache, inSubscript); | |
| 11641 | case (DAE.DIM_EXP(_), _) | ||
| 11642 | 256 | then (inCache, inSubscript); | |
| 11643 | |||
| 11644 | else | ||
| 11645 | algorithm | ||
| 11646 | ✗ | sub_str := ExpressionBasics.printSubscriptStr(inSubscript); | |
| 11647 | ✗ | dim_str := ExpressionBasics.dimensionString(inDimension); | |
| 11648 | ✗ | cref_str := Dump.printComponentRefStr(inCref); | |
| 11649 | ✗ | Error.addSourceMessage(Error.ILLEGAL_SUBSCRIPT, {sub_str, dim_str, cref_str}, inInfo); | |
| 11650 | ✗ | then | |
| 11651 | fail(); | ||
| 11652 | |||
| 11653 | end matchcontinue; | ||
| 11654 | end elabSubscriptsDims2; | ||
| 11655 | |||
| 11656 | protected function elabSubscript "This function converts an Absyn.Subscript to an | ||
| 11657 | DAE.Subscript." | ||
| 11658 | input FCore.Cache inCache; | ||
| 11659 | input FCore.Graph inEnv; | ||
| 11660 | input Absyn.Subscript inSubscript; | ||
| 11661 | input Boolean inBoolean; | ||
| 11662 | input DAE.Prefix inPrefix; | ||
| 11663 | input SourceInfo info; | ||
| 11664 | output FCore.Cache outCache; | ||
| 11665 | output DAE.Subscript outSubscript; | ||
| 11666 | output DAE.Const outConst; | ||
| 11667 | output Option<DAE.Properties> outProperties; | ||
| 11668 | algorithm | ||
| 11669 | (outCache, outSubscript, outConst, outProperties) := | ||
| 11670 | matchcontinue(inCache, inEnv, inSubscript, inBoolean, inPrefix) | ||
| 11671 | local | ||
| 11672 | Boolean impl; | ||
| 11673 | DAE.Exp sub_1; | ||
| 11674 | DAE.Type ty; | ||
| 11675 | DAE.Const const; | ||
| 11676 | DAE.Subscript sub_2; | ||
| 11677 | FCore.Graph env; | ||
| 11678 | Absyn.Exp sub; | ||
| 11679 | FCore.Cache cache; | ||
| 11680 | DAE.Properties prop; | ||
| 11681 | DAE.Prefix pre; | ||
| 11682 | |||
| 11683 | // no subscript | ||
| 11684 | case (cache, _, Absyn.NOSUB(), _, _) | ||
| 11685 | then (cache, DAE.WHOLEDIM(), DAE.C_CONST(), NONE()); | ||
| 11686 | |||
| 11687 | // some subscript, try to elaborate it | ||
| 11688 | case (cache, env, Absyn.SUBSCRIPT(subscript = sub), impl, pre) | ||
| 11689 | algorithm | ||
| 11690 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 80837 times.
|
80839 | (cache, sub_1, prop as DAE.PROP(constFlag = const)) := |
| 11691 | elabExpInExpression(cache, env, sub, impl, true, pre, info); | ||
| 11692 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 80837 times.
|
80837 | (cache, sub_1, prop as DAE.PROP(type_ = ty)) := |
| 11693 | Ceval.cevalIfConstant(cache, env, sub_1, prop, impl, info); | ||
| 11694 | 80837 | sub_2 := elabSubscriptType(ty, sub, sub_1, info); | |
| 11695 | then | ||
| 11696 | (cache, sub_2, const, SOME(prop)); | ||
| 11697 | |||
| 11698 | // failtrace | ||
| 11699 | else | ||
| 11700 | algorithm | ||
| 11701 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | true := Flags.isSet(Flags.FAILTRACE); |
| 11702 | ✗ | Debug.traceln("- Static.elabSubscript failed on " + | |
| 11703 | Dump.printSubscriptStr(inSubscript) + " in env: " + | ||
| 11704 | FGraph.printGraphPathStr(inEnv)); | ||
| 11705 | ✗ | then | |
| 11706 | fail(); | ||
| 11707 | end matchcontinue; | ||
| 11708 | end elabSubscript; | ||
| 11709 | |||
| 11710 | protected function elabSubscriptType | ||
| 11711 | "This function is used to find the correct constructor for DAE.Subscript to | ||
| 11712 | use for an indexing expression. If a scalar is given as index, DAE.INDEX() | ||
| 11713 | is used, and if an array is given, DAE.SLICE() is used." | ||
| 11714 | input DAE.Type inType; | ||
| 11715 | input Absyn.Exp inAbsynExp; | ||
| 11716 | input DAE.Exp inDaeExp; | ||
| 11717 | input SourceInfo inInfo; | ||
| 11718 | output DAE.Subscript outSubscript; | ||
| 11719 | algorithm | ||
| 11720 | outSubscript := match inType | ||
| 11721 | local | ||
| 11722 | String e_str,t_str; | ||
| 11723 | |||
| 11724 | 79622 | case DAE.T_INTEGER() then DAE.INDEX(inDaeExp); | |
| 11725 | 197 | case DAE.T_ENUMERATION() then DAE.INDEX(inDaeExp); | |
| 11726 | 1 | case DAE.T_BOOL() then DAE.INDEX(inDaeExp); | |
| 11727 | 1011 | case DAE.T_ARRAY(ty = DAE.T_INTEGER()) then DAE.SLICE(inDaeExp); | |
| 11728 | 2 | case DAE.T_ARRAY(ty = DAE.T_ENUMERATION()) then DAE.SLICE(inDaeExp); | |
| 11729 | 4 | case DAE.T_ARRAY(ty = DAE.T_BOOL()) then DAE.SLICE(inDaeExp); | |
| 11730 | case DAE.T_METABOXED() | ||
| 11731 | ✗ | then elabSubscriptType(inType.ty, inAbsynExp, inDaeExp, inInfo); | |
| 11732 | |||
| 11733 | else | ||
| 11734 | algorithm | ||
| 11735 | ✗ | e_str := Dump.printExpStr(inAbsynExp); | |
| 11736 | ✗ | t_str := TypesDump.unparseType(inType); | |
| 11737 | ✗ | Error.addSourceMessage(Error.WRONG_DIMENSION_TYPE, {e_str, t_str}, inInfo); | |
| 11738 | ✗ | then | |
| 11739 | fail(); | ||
| 11740 | end match; | ||
| 11741 | end elabSubscriptType; | ||
| 11742 | |||
| 11743 | protected function subscriptCrefType | ||
| 11744 | "If a component of an array type is subscripted, the type of the | ||
| 11745 | component reference is of lower dimensionality than the | ||
| 11746 | component. This function shows the function between the component | ||
| 11747 | type and the component reference expression type. | ||
| 11748 | |||
| 11749 | This function might actually not be needed. | ||
| 11750 | " | ||
| 11751 | input DAE.Exp inExp; | ||
| 11752 | input DAE.Type inType; | ||
| 11753 | output DAE.Type outType; | ||
| 11754 | algorithm | ||
| 11755 | outType := matchcontinue (inExp,inType) | ||
| 11756 | local | ||
| 11757 | DAE.Type t_1,t; | ||
| 11758 | DAE.ComponentRef c; | ||
| 11759 | |||
| 11760 | case (DAE.CREF(componentRef = c),t) | ||
| 11761 | algorithm | ||
| 11762 | ✗ | t_1 := subscriptCrefType2(c, t); | |
| 11763 | then | ||
| 11764 | t_1; | ||
| 11765 | |||
| 11766 | else inType; | ||
| 11767 | end matchcontinue; | ||
| 11768 | end subscriptCrefType; | ||
| 11769 | |||
| 11770 | protected function subscriptCrefType2 | ||
| 11771 | input DAE.ComponentRef inComponentRef; | ||
| 11772 | input DAE.Type inType; | ||
| 11773 | output DAE.Type outType; | ||
| 11774 | algorithm | ||
| 11775 | outType := match (inComponentRef,inType) | ||
| 11776 | local | ||
| 11777 | DAE.Type t,t_1; | ||
| 11778 | list<DAE.Subscript> subs; | ||
| 11779 | DAE.ComponentRef c; | ||
| 11780 | |||
| 11781 | case (DAE.CREF_IDENT(subscriptLst = {}),t) then t; | ||
| 11782 | case (DAE.CREF_IDENT(subscriptLst = subs),t) | ||
| 11783 | algorithm | ||
| 11784 | ✗ | t_1 := subscriptType(t, subs); | |
| 11785 | then | ||
| 11786 | t_1; | ||
| 11787 | case (DAE.CREF_QUAL(componentRef = c),t) | ||
| 11788 | algorithm | ||
| 11789 | ✗ | t_1 := subscriptCrefType2(c, t); | |
| 11790 | then | ||
| 11791 | t_1; | ||
| 11792 | end match; | ||
| 11793 | end subscriptCrefType2; | ||
| 11794 | |||
| 11795 | protected function subscriptType "Given an array dimensionality and a list of subscripts, this | ||
| 11796 | function reduces the dimensionality. | ||
| 11797 | This does not handle slices or check that subscripts are not out | ||
| 11798 | of bounds." | ||
| 11799 | input DAE.Type inType; | ||
| 11800 | input list<DAE.Subscript> inExpSubscriptLst; | ||
| 11801 | output DAE.Type outType; | ||
| 11802 | algorithm | ||
| 11803 | outType := matchcontinue (inType,inExpSubscriptLst) | ||
| 11804 | local | ||
| 11805 | DAE.Type t,t_1; | ||
| 11806 | list<DAE.Subscript> subs; | ||
| 11807 | DAE.Dimension dim; | ||
| 11808 | |||
| 11809 | case (t,{}) then t; | ||
| 11810 | |||
| 11811 | case (DAE.T_ARRAY(dims = {DAE.DIM_INTEGER()}, ty = t),(DAE.INDEX() :: subs)) | ||
| 11812 | algorithm | ||
| 11813 | ✗ | t_1 := subscriptType(t, subs); | |
| 11814 | then | ||
| 11815 | t_1; | ||
| 11816 | |||
| 11817 | case (DAE.T_ARRAY(dims = {dim}, ty = t),(DAE.SLICE() :: subs)) | ||
| 11818 | algorithm | ||
| 11819 | ✗ | t_1 := subscriptType(t, subs); | |
| 11820 | ✗ | then | |
| 11821 | DAE.T_ARRAY(t_1,{dim}); | ||
| 11822 | |||
| 11823 | case (DAE.T_ARRAY(dims = {dim}, ty = t),(DAE.WHOLEDIM() :: subs)) | ||
| 11824 | algorithm | ||
| 11825 | ✗ | t_1 := subscriptType(t, subs); | |
| 11826 | ✗ | then | |
| 11827 | DAE.T_ARRAY(t_1,{dim}); | ||
| 11828 | |||
| 11829 | case (t,_) | ||
| 11830 | algorithm | ||
| 11831 | ✗ | Print.printBuf("- subscript_type failed ("); | |
| 11832 | ✗ | Print.printBuf(TypesDump.printTypeStr(t)); | |
| 11833 | ✗ | Print.printBuf(" , [...])\n"); | |
| 11834 | ✗ | then | |
| 11835 | fail(); | ||
| 11836 | end matchcontinue; | ||
| 11837 | end subscriptType; | ||
| 11838 | |||
| 11839 | protected function makeIfExp | ||
| 11840 | input FCore.Cache inCache; | ||
| 11841 | input FCore.Graph inEnv; | ||
| 11842 | input DAE.Exp inCondition; | ||
| 11843 | input DAE.Properties inCondProp; | ||
| 11844 | input DAE.Exp inTrueBranch; | ||
| 11845 | input DAE.Properties inTrueProp; | ||
| 11846 | input DAE.Exp inFalseBranch; | ||
| 11847 | input DAE.Properties inFalseProp; | ||
| 11848 | input Boolean inImplicit; | ||
| 11849 | input DAE.Prefix inPrefix; | ||
| 11850 | input SourceInfo inInfo; | ||
| 11851 | output FCore.Cache outCache = inCache; | ||
| 11852 | output DAE.Exp outExp; | ||
| 11853 | output DAE.Properties outProperties; | ||
| 11854 | protected | ||
| 11855 | Boolean ty_match, cond; | ||
| 11856 | DAE.Type cond_ty, true_ty, false_ty, exp_ty; | ||
| 11857 | DAE.Const cond_c, true_c, false_c, exp_c; | ||
| 11858 | String cond_str, cond_ty_str, e1_str, e2_str, ty1_str, ty2_str, pre_str; | ||
| 11859 | DAE.Exp cond_exp, true_exp, false_exp; | ||
| 11860 | algorithm | ||
| 11861 | // Check that the condition is a boolean expression. | ||
| 11862 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8298 times.
|
8298 | DAE.PROP(type_ = cond_ty, constFlag = cond_c) := inCondProp; |
| 11863 | 8298 | (cond_exp, _, ty_match) := Types.matchTypeNoFail(inCondition, cond_ty, DAE.T_BOOL_DEFAULT); | |
| 11864 | |||
| 11865 | // Print an error message and fail if the condition is not a boolean expression. | ||
| 11866 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8298 times.
|
8298 | if not ty_match then |
| 11867 | ✗ | cond_str := ExpressionBasics.printExpStr(inCondition); | |
| 11868 | ✗ | cond_ty_str := TypesDump.unparseTypeNoAttr(cond_ty); | |
| 11869 | ✗ | Error.addSourceMessageAndFail(Error.IF_CONDITION_TYPE_ERROR, | |
| 11870 | {cond_str, cond_ty_str}, inInfo); | ||
| 11871 | end if; | ||
| 11872 | |||
| 11873 | // Check that both branches are type compatible. | ||
| 11874 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8298 times.
|
8298 | DAE.PROP(type_ = true_ty, constFlag = true_c) := inTrueProp; |
| 11875 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8298 times.
|
8298 | DAE.PROP(type_ = false_ty, constFlag = false_c) := inFalseProp; |
| 11876 | |||
| 11877 | 8298 | (true_exp, false_exp, exp_ty, ty_match) := | |
| 11878 | Types.checkTypeCompat(inTrueBranch, true_ty, inFalseBranch, false_ty); | ||
| 11879 | |||
| 11880 | // If the compatible type is an array with some unknown dimensions, and we're | ||
| 11881 | // not in a function, then we need to choose one of the branches. | ||
| 11882 |
4/4✓ Branch 1 taken 27 times.
✓ Branch 2 taken 8271 times.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 17 times.
|
8298 | if Types.arrayHasUnknownDims(exp_ty) and not FGraph.inFunctionScope(inEnv) then |
| 11883 | // Check if the condition is reasonably constant, so we can evaluate it. | ||
| 11884 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
|
10 | if Types.isParameterOrConstant(cond_c) then |
| 11885 | cond_c := DAE.C_CONST(); | ||
| 11886 | else | ||
| 11887 | // Otherwise it's a type error. | ||
| 11888 | ✗ | ty_match := false; | |
| 11889 | end if; | ||
| 11890 | end if; | ||
| 11891 | |||
| 11892 | // If the types are not matching, print an error and fail. | ||
| 11893 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8296 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
|
8298 | if (not ty_match) and not Config.getGraphicsExpMode() then |
| 11894 | 2 | e1_str := ExpressionBasics.printExpStr(inTrueBranch); | |
| 11895 | 2 | e2_str := ExpressionBasics.printExpStr(inFalseBranch); | |
| 11896 | 2 | ty1_str := TypesDump.unparseTypeNoAttr(true_ty); | |
| 11897 | 2 | ty2_str := TypesDump.unparseTypeNoAttr(false_ty); | |
| 11898 | 2 | pre_str := PrefixUtil.printPrefixStr3(inPrefix); | |
| 11899 | 2 | Error.addSourceMessageAndFail(Error.TYPE_MISMATCH_IF_EXP, | |
| 11900 | {pre_str, e1_str, ty1_str, e2_str, ty2_str}, inInfo); | ||
| 11901 | end if; | ||
| 11902 | |||
| 11903 |
2/2✓ Branch 1 taken 758 times.
✓ Branch 2 taken 7538 times.
|
8296 | if Types.isConstant(cond_c) then |
| 11904 | // If the condition is constant, try to evaluate it and choose a branch. | ||
| 11905 | try | ||
| 11906 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 718 times.
|
758 | (outCache, Values.BOOL(cond)) := Ceval.ceval(inCache, inEnv, cond_exp, |
| 11907 | inImplicit, Absyn.NO_MSG(), 0); | ||
| 11908 | |||
| 11909 |
2/2✓ Branch 0 taken 564 times.
✓ Branch 1 taken 154 times.
|
718 | if cond then |
| 11910 | 564 | outExp := true_exp; | |
| 11911 | outProperties := inTrueProp; | ||
| 11912 | else | ||
| 11913 | 154 | outExp := false_exp; | |
| 11914 | outProperties := inFalseProp; | ||
| 11915 | end if; | ||
| 11916 | |||
| 11917 | // Evaluation succeeded, return the chosen branch. | ||
| 11918 | 718 | return; | |
| 11919 | else | ||
| 11920 | end try; | ||
| 11921 | end if; | ||
| 11922 | |||
| 11923 | // If the condition is not constant or ceval failed, create an if-expression. | ||
| 11924 |
7/8✓ Branch 0 taken 22734 times.
✓ Branch 1 taken 7578 times.
✓ Branch 2 taken 22734 times.
✓ Branch 3 taken 7578 times.
✓ Branch 4 taken 7578 times.
✓ Branch 5 taken 15156 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7578 times.
|
30312 | exp_c := Types.constAnd(c for c in {cond_c, false_c, true_c}); |
| 11925 | 7578 | outExp := DAE.IFEXP(cond_exp, true_exp, false_exp); | |
| 11926 | 7578 | outProperties := DAE.PROP(exp_ty, exp_c); | |
| 11927 | end makeIfExp; | ||
| 11928 | |||
| 11929 | protected function canonCref2 "This function relates a DAE.ComponentRef to its canonical form, | ||
| 11930 | which is when all subscripts are evaluated to constant values. | ||
| 11931 | If Such an evaluation is not possible, there is no canonical | ||
| 11932 | form and this function fails." | ||
| 11933 | input FCore.Cache inCache; | ||
| 11934 | input FCore.Graph inEnv; | ||
| 11935 | input DAE.ComponentRef inComponentRef; | ||
| 11936 | input DAE.ComponentRef inPrefixCref; | ||
| 11937 | input Boolean inBoolean; | ||
| 11938 | output FCore.Cache outCache; | ||
| 11939 | output DAE.ComponentRef outComponentRef; | ||
| 11940 | algorithm | ||
| 11941 | (outCache,outComponentRef) := | ||
| 11942 | match (inCache,inEnv,inComponentRef,inPrefixCref,inBoolean) | ||
| 11943 | local | ||
| 11944 | list<DAE.Subscript> ss_1,ss; | ||
| 11945 | FCore.Graph env; | ||
| 11946 | String n; | ||
| 11947 | Boolean impl; | ||
| 11948 | FCore.Cache cache; | ||
| 11949 | DAE.ComponentRef prefixCr,cr; | ||
| 11950 | list<Integer> sl; | ||
| 11951 | DAE.Type t; | ||
| 11952 | DAE.Type ty2; | ||
| 11953 | case (cache,env,DAE.CREF_IDENT(ident = n,identType = ty2, subscriptLst = ss),prefixCr,impl) /* impl */ | ||
| 11954 | algorithm | ||
| 11955 | ✗ | cr := ComponentReference.crefPrependIdent(prefixCr,n,{},ty2); | |
| 11956 | ✗ | (cache,_,t) := Lookup.lookupVar(cache,env, cr); | |
| 11957 | ✗ | sl := Types.getDimensionSizes(t); | |
| 11958 | ✗ | (cache,ss_1) := Ceval.cevalSubscripts(cache,env, ss, sl, impl, Absyn.NO_MSG(),0); | |
| 11959 | ✗ | then | |
| 11960 | (cache,ComponentReferenceBasics.makeCrefIdent(n,ty2,ss_1)); | ||
| 11961 | end match; | ||
| 11962 | end canonCref2; | ||
| 11963 | |||
| 11964 | public function canonCref "Transform expression to canonical form | ||
| 11965 | by constant evaluating all subscripts." | ||
| 11966 | input FCore.Cache inCache; | ||
| 11967 | input FCore.Graph inEnv; | ||
| 11968 | input DAE.ComponentRef inComponentRef; | ||
| 11969 | input Boolean inBoolean; | ||
| 11970 | output FCore.Cache outCache; | ||
| 11971 | output DAE.ComponentRef outComponentRef; | ||
| 11972 | algorithm | ||
| 11973 | (outCache,outComponentRef) := | ||
| 11974 | matchcontinue (inCache,inEnv,inComponentRef,inBoolean) | ||
| 11975 | local | ||
| 11976 | DAE.Type t; | ||
| 11977 | list<Integer> sl; | ||
| 11978 | list<DAE.Subscript> ss_1,ss; | ||
| 11979 | FCore.Graph env, componentEnv; | ||
| 11980 | String n; | ||
| 11981 | Boolean impl; | ||
| 11982 | DAE.ComponentRef c_1,c,cr; | ||
| 11983 | FCore.Cache cache; | ||
| 11984 | DAE.Type ty2; | ||
| 11985 | |||
| 11986 | // handle wild _ | ||
| 11987 | case (cache,_,DAE.WILD(),_) | ||
| 11988 | algorithm | ||
| 11989 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
|
2 | true := Config.acceptMetaModelicaGrammar(); |
| 11990 | then | ||
| 11991 | (cache,DAE.WILD()); | ||
| 11992 | |||
| 11993 | // an unqualified component reference | ||
| 11994 | case (cache,env,DAE.CREF_IDENT(ident = n,subscriptLst = ss),impl) /* impl */ | ||
| 11995 | algorithm | ||
| 11996 | 61960 | (cache,_,t,_,_,_,_,_,_) := Lookup.lookupVarIdent(cache, env, n); | |
| 11997 | 61931 | sl := Types.getDimensionSizes(t); | |
| 11998 | 61931 | (cache,ss_1) := Ceval.cevalSubscripts(cache, env, ss, sl, impl, Absyn.NO_MSG(),0); | |
| 11999 | 61931 | ty2 := Types.simplifyType(t); | |
| 12000 | 61931 | then | |
| 12001 | (cache,ComponentReferenceBasics.makeCrefIdent(n,ty2,ss_1)); | ||
| 12002 | |||
| 12003 | // a qualified component reference | ||
| 12004 | case (cache,env,DAE.CREF_QUAL(ident = n,subscriptLst = ss,componentRef = c),impl) | ||
| 12005 | algorithm | ||
| 12006 | 39094 | (cache,_,t,_,_,_,_,componentEnv,_) := Lookup.lookupVarIdent(cache, env, n); | |
| 12007 | 39094 | ty2 := Types.simplifyType(t); | |
| 12008 | 39094 | sl := Types.getDimensionSizes(t); | |
| 12009 | 39094 | (cache,ss_1) := Ceval.cevalSubscripts(cache, env, ss, sl, impl, Absyn.NO_MSG(),0); | |
| 12010 | //(cache,c_1) = canonCref2(cache, env, c, ComponentReferenceBasics.makeCrefIdent(n,ty2,ss), impl); | ||
| 12011 | 39094 | (cache, c_1) := canonCref(cache, componentEnv, c, impl); | |
| 12012 | 39065 | then | |
| 12013 | (cache,ComponentReferenceBasics.makeCrefQual(n,ty2, ss_1,c_1)); | ||
| 12014 | |||
| 12015 | // failtrace | ||
| 12016 | case (_,_,cr,_) | ||
| 12017 | algorithm | ||
| 12018 |
1/2✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
|
58 | true := Flags.isSet(Flags.FAILTRACE); |
| 12019 | ✗ | Debug.trace("- Static.canonCref failed, cr: "); | |
| 12020 | ✗ | Debug.traceln(ComponentReferenceBasics.printComponentRefStr(cr)); | |
| 12021 | ✗ | then | |
| 12022 | fail(); | ||
| 12023 | end matchcontinue; | ||
| 12024 | end canonCref; | ||
| 12025 | |||
| 12026 | protected function unevaluatedFunctionVariability | ||
| 12027 | "In a function we might have input arguments with unknown dimensions, and in | ||
| 12028 | that case we can't expand calls such as fill. A function call is therefore | ||
| 12029 | created with variable variability. This function checks that we're inside a | ||
| 12030 | function and returns DAE.C_VAR(), or fails if we're not inside a function. | ||
| 12031 | |||
| 12032 | The exception is if checkModel is used, in which case we don't know what the | ||
| 12033 | variability would have been had all parameters received a binding. We can't | ||
| 12034 | set the variability to variable or parameter because then we might get | ||
| 12035 | bindings with higher variability than the component, and we can't set it to | ||
| 12036 | constant because that would cause the compiler to try and constant evaluate | ||
| 12037 | the call. So we set it to DAE.C_UNKNOWN() instead." | ||
| 12038 | input FCore.Graph inEnv; | ||
| 12039 | output DAE.Const outConst; | ||
| 12040 | algorithm | ||
| 12041 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 16 times.
|
18 | if FGraph.inFunctionScope(inEnv) then |
| 12042 | outConst := DAE.C_VAR(); | ||
| 12043 | elseif Flags.getConfigBool(Flags.CHECK_MODEL) or Config.splitArrays() then | ||
| 12044 | // bug #2113, seems that there is nothing in the specs | ||
| 12045 | // that requires that fill arguments are of parameter/constant | ||
| 12046 | // variability, so allow it. | ||
| 12047 | outConst := DAE.C_UNKNOWN(); | ||
| 12048 | else | ||
| 12049 | ✗ | fail(); | |
| 12050 | end if; | ||
| 12051 | end unevaluatedFunctionVariability; | ||
| 12052 | |||
| 12053 | protected function slotAnd | ||
| 12054 | "Use with listFold to check if all slots have been filled" | ||
| 12055 | input Slot s; | ||
| 12056 | input Boolean b; | ||
| 12057 | output Boolean res; | ||
| 12058 | algorithm | ||
| 12059 | 141328 | SLOT(slotFilled = res) := s; | |
| 12060 | 141328 | res := b and res; | |
| 12061 | end slotAnd; | ||
| 12062 | |||
| 12063 | public function elabCodeExp | ||
| 12064 | input Absyn.Exp exp; | ||
| 12065 | input FCore.Cache cache; | ||
| 12066 | input FCore.Graph env; | ||
| 12067 | input DAE.CodeType ct; | ||
| 12068 | input SourceInfo info; | ||
| 12069 | output DAE.Exp outExp; | ||
| 12070 | algorithm | ||
| 12071 | outExp := matchcontinue (exp,ct) | ||
| 12072 | local | ||
| 12073 | String s1,s2; | ||
| 12074 | Absyn.ComponentRef cr; | ||
| 12075 | Absyn.Path path; | ||
| 12076 | list<DAE.Exp> es_1; | ||
| 12077 | list<Absyn.Exp> es; | ||
| 12078 | DAE.Type et; | ||
| 12079 | Integer i; | ||
| 12080 | DAE.Exp dexp; | ||
| 12081 | |||
| 12082 | // first; try to elaborate the exp (maybe there is a binding in the environment that says v is a VariableName | ||
| 12083 | case (_,_) | ||
| 12084 | algorithm | ||
| 12085 | // adrpo: be very careful with this as it can take quite a long time, for example a call to: | ||
| 12086 | // getDerivedClassModifierValue(Modelica.Fluid.Vessels.BaseClasses.PartialLumpedVessel.Medium.MassFlowRate,unit); | ||
| 12087 | // will instantiate Modelica.Fluid.Vessels.BaseClasses.PartialLumpedVessel.Medium.MassFlowRate | ||
| 12088 | // if we're not careful | ||
| 12089 | 5337 | dexp := elabCodeExp_dispatch(exp,cache,env,ct,info); | |
| 12090 | then | ||
| 12091 | dexp; | ||
| 12092 | |||
| 12093 | case (Absyn.CODE(code=Absyn.C_MODIFICATION()),DAE.C_EXPRESSION_OR_MODIFICATION()) | ||
| 12094 | ✗ | then DAE.CODE(exp.code,DAE.T_UNKNOWN_DEFAULT); | |
| 12095 | case (Absyn.CODE(code=Absyn.C_EXPRESSION()),DAE.C_EXPRESSION()) | ||
| 12096 | ✗ | then DAE.CODE(exp.code,DAE.T_UNKNOWN_DEFAULT); | |
| 12097 | |||
| 12098 | // Expression | ||
| 12099 | case (_,DAE.C_EXPRESSION()) | ||
| 12100 | 14 | then DAE.CODE(Absyn.C_EXPRESSION(exp),DAE.T_UNKNOWN_DEFAULT); | |
| 12101 | case (_,DAE.C_EXPRESSION_OR_MODIFICATION()) | ||
| 12102 | 13 | then DAE.CODE(Absyn.C_EXPRESSION(exp),DAE.T_UNKNOWN_DEFAULT); | |
| 12103 | |||
| 12104 | // Type Name | ||
| 12105 | case (Absyn.CREF(componentRef=cr),DAE.C_TYPENAME()) | ||
| 12106 | algorithm | ||
| 12107 | 2503 | path := AbsynUtil.crefToPath(cr); | |
| 12108 | 2503 | then DAE.CODE(Absyn.C_TYPENAME(path),DAE.T_UNKNOWN_DEFAULT); | |
| 12109 | |||
| 12110 | // Variable Names | ||
| 12111 | case (Absyn.ARRAY(es),DAE.C_VARIABLENAMES()) | ||
| 12112 | algorithm | ||
| 12113 | 52 | es_1 := List.map4(es,elabCodeExp,cache,env,DAE.C_VARIABLENAME(),info); | |
| 12114 | 52 | i := listLength(es); | |
| 12115 | 104 | et := DAE.T_ARRAY(DAE.T_UNKNOWN_DEFAULT, {DAE.DIM_INTEGER(i)}); | |
| 12116 | 52 | then DAE.ARRAY(et,false,es_1); | |
| 12117 | |||
| 12118 | case (_,DAE.C_VARIABLENAMES()) | ||
| 12119 | algorithm | ||
| 12120 | et := DAE.T_ARRAY(DAE.T_UNKNOWN_DEFAULT, {DAE.DIM_INTEGER(1)}); | ||
| 12121 | ✗ | dexp := elabCodeExp(exp,cache,env,DAE.C_VARIABLENAME(),info); | |
| 12122 | ✗ | then DAE.ARRAY(et,false,{dexp}); | |
| 12123 | |||
| 12124 | // Variable Name | ||
| 12125 | case (Absyn.CREF(componentRef=cr),DAE.C_VARIABLENAME()) | ||
| 12126 | 2265 | then DAE.CODE(Absyn.C_VARIABLENAME(cr),DAE.T_UNKNOWN_DEFAULT); | |
| 12127 | |||
| 12128 | // der() expression | ||
| 12129 | case (Absyn.CALL(), DAE.C_VARIABLENAME()) | ||
| 12130 | guard isValidDerVariableName(exp) | ||
| 12131 | 18 | then DAE.CODE(Absyn.C_EXPRESSION(exp),DAE.T_UNKNOWN_DEFAULT); | |
| 12132 | |||
| 12133 | // failure | ||
| 12134 | else | ||
| 12135 | algorithm | ||
| 12136 | ✗ | failure(DAE.C_VARIABLENAMES() := ct); | |
| 12137 | ✗ | s1 := Dump.printExpStr(exp); | |
| 12138 | ✗ | s2 := TypesDump.printCodeTypeStr(ct); | |
| 12139 | ✗ | Error.addSourceMessage(Error.ELAB_CODE_EXP_FAILED, {s1,s2}, info); | |
| 12140 | ✗ | then fail(); | |
| 12141 | end matchcontinue; | ||
| 12142 | end elabCodeExp; | ||
| 12143 | |||
| 12144 | public function elabCodeExp_dispatch | ||
| 12145 | "@author: adrpo | ||
| 12146 | evaluate a code expression. | ||
| 12147 | be careful how much you lookup" | ||
| 12148 | input Absyn.Exp exp; | ||
| 12149 | input FCore.Cache cache; | ||
| 12150 | input FCore.Graph env; | ||
| 12151 | input DAE.CodeType ct; | ||
| 12152 | input Absyn.Info info; | ||
| 12153 | output DAE.Exp outExp; | ||
| 12154 | algorithm | ||
| 12155 | outExp := matchcontinue exp | ||
| 12156 | local | ||
| 12157 | Absyn.ComponentRef cr; | ||
| 12158 | DAE.Exp dexp; | ||
| 12159 | DAE.Properties prop; | ||
| 12160 | DAE.Type ty; | ||
| 12161 | DAE.CodeType ct2; | ||
| 12162 | Absyn.Ident id; | ||
| 12163 | |||
| 12164 | // for a component reference make sure the first ident is either "OpenModelica" or not a class | ||
| 12165 | case Absyn.CREF(componentRef=cr) | ||
| 12166 | algorithm | ||
| 12167 | 5186 | ErrorExt.setCheckpoint("elabCodeExp_dispatch1"); | |
| 12168 | 5186 | id := AbsynUtil.crefFirstIdent(cr); | |
| 12169 | try | ||
| 12170 | // if the first one is OpenModelica, search | ||
| 12171 |
4/4✓ Branch 0 taken 142 times.
✓ Branch 1 taken 5044 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 140 times.
|
5186 | true := id == "OpenModelica"; |
| 12172 | 2 | (_,dexp,prop) := elabExpInExpression(cache,env,exp,false,false,DAE.NOPRE(),info); | |
| 12173 | else | ||
| 12174 | // not a class or OpenModelica, continue; a class which is not | ||
| 12175 | // OpenModelica makes this fail (and the enclosing case rolls back). | ||
| 12176 |
2/2✓ Branch 0 taken 5186 times.
✓ Branch 1 taken 3092 times.
|
8278 | failure(Lookup.lookupClassIdent(cache, env, id)); |
| 12177 | 3092 | (_,dexp,prop) := elabExpInExpression(cache,env,exp,false,false,DAE.NOPRE(),info); | |
| 12178 | end try; | ||
| 12179 |
2/2✓ Branch 1 taken 36 times.
✓ Branch 2 taken 418 times.
|
454 | DAE.T_CODE(ty=ct2) := Types.getPropType(prop); |
| 12180 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 418 times.
|
418 | true := valueEq(ct,ct2); |
| 12181 | 418 | ErrorExt.delCheckpoint("elabCodeExp_dispatch1"); | |
| 12182 | // print(ExpressionBasics.printExpStr(dexp) + " " + TypesDump.unparseType(ty) + "\n"); | ||
| 12183 | 418 | then dexp; | |
| 12184 | |||
| 12185 | case Absyn.CREF() | ||
| 12186 | algorithm | ||
| 12187 | 4768 | ErrorExt.rollBack("elabCodeExp_dispatch1"); | |
| 12188 | 4768 | then fail(); | |
| 12189 | |||
| 12190 | case _ | ||
| 12191 | algorithm | ||
| 12192 |
2/2✓ Branch 1 taken 4768 times.
✓ Branch 2 taken 151 times.
|
4919 | false := AbsynUtil.isCref(exp); |
| 12193 | 151 | ErrorExt.setCheckpoint("elabCodeExp_dispatch"); | |
| 12194 | 151 | (_,dexp,prop) := elabExpInExpression(cache,env,exp,false,false,DAE.NOPRE(),info); | |
| 12195 |
2/2✓ Branch 1 taken 10 times.
✓ Branch 2 taken 54 times.
|
64 | DAE.T_CODE(ty=ct2) := Types.getPropType(prop); |
| 12196 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 54 times.
|
54 | true := valueEq(ct,ct2); |
| 12197 | 54 | ErrorExt.delCheckpoint("elabCodeExp_dispatch"); | |
| 12198 | // print(ExpressionBasics.printExpStr(dexp) + " " + TypesDump.unparseType(ty) + "\n"); | ||
| 12199 | 54 | then dexp; | |
| 12200 | |||
| 12201 | else | ||
| 12202 | algorithm | ||
| 12203 |
2/2✓ Branch 1 taken 4768 times.
✓ Branch 2 taken 97 times.
|
4865 | false := AbsynUtil.isCref(exp); |
| 12204 | 97 | ErrorExt.rollBack("elabCodeExp_dispatch"); | |
| 12205 | 97 | then fail(); | |
| 12206 | |||
| 12207 | end matchcontinue; | ||
| 12208 | end elabCodeExp_dispatch; | ||
| 12209 | |||
| 12210 | public function elabArrayDims | ||
| 12211 | "Elaborates a list of array dimensions." | ||
| 12212 | input FCore.Cache inCache; | ||
| 12213 | input FCore.Graph inEnv; | ||
| 12214 | input Absyn.ComponentRef inComponentRef; | ||
| 12215 | input list<Absyn.Subscript> inDimensions; | ||
| 12216 | input Boolean inImplicit; | ||
| 12217 | input Boolean inDoVect; | ||
| 12218 | input DAE.Prefix inPrefix; | ||
| 12219 | input SourceInfo inInfo; | ||
| 12220 | output FCore.Cache outCache; | ||
| 12221 | output DAE.Dimensions outDimensions; | ||
| 12222 | algorithm | ||
| 12223 | 225155 | (outCache, outDimensions) := elabArrayDims2(inCache, inEnv, inComponentRef, | |
| 12224 | inDimensions, inImplicit, inDoVect, inPrefix, inInfo, {}); | ||
| 12225 | end elabArrayDims; | ||
| 12226 | |||
| 12227 | protected function elabArrayDims2 | ||
| 12228 | "Helper function to elabArrayDims. Needed because of tail recursion." | ||
| 12229 | input FCore.Cache inCache; | ||
| 12230 | input FCore.Graph inEnv; | ||
| 12231 | input Absyn.ComponentRef inCref; | ||
| 12232 | input list<Absyn.Subscript> inDimensions; | ||
| 12233 | input Boolean inImplicit; | ||
| 12234 | input Boolean inDoVect; | ||
| 12235 | input DAE.Prefix inPrefix; | ||
| 12236 | input SourceInfo inInfo; | ||
| 12237 | input DAE.Dimensions inElaboratedDims; | ||
| 12238 | output FCore.Cache outCache; | ||
| 12239 | output DAE.Dimensions outDimensions; | ||
| 12240 | algorithm | ||
| 12241 | (outCache, outDimensions) := match inDimensions | ||
| 12242 | local | ||
| 12243 | FCore.Cache cache; | ||
| 12244 | Absyn.Subscript dim; | ||
| 12245 | list<Absyn.Subscript> rest_dims; | ||
| 12246 | DAE.Dimension elab_dim; | ||
| 12247 | DAE.Dimensions elab_dims; | ||
| 12248 | |||
| 12249 | case {} | ||
| 12250 | 225054 | then (inCache, listReverse(inElaboratedDims)); | |
| 12251 | |||
| 12252 | case dim :: rest_dims | ||
| 12253 | algorithm | ||
| 12254 | 69953 | (cache, elab_dim) := elabArrayDim(inCache, inEnv, inCref, dim, | |
| 12255 | inImplicit, inDoVect, inPrefix, inInfo); | ||
| 12256 | 69852 | elab_dims := elab_dim :: inElaboratedDims; | |
| 12257 | 69852 | (cache, elab_dims) := elabArrayDims2(cache, inEnv, inCref, rest_dims, | |
| 12258 | inImplicit, inDoVect, inPrefix, inInfo, elab_dims); | ||
| 12259 | then | ||
| 12260 | (cache, elab_dims); | ||
| 12261 | end match; | ||
| 12262 | end elabArrayDims2; | ||
| 12263 | |||
| 12264 | protected function elabArrayDim | ||
| 12265 | "Elaborates a single array dimension." | ||
| 12266 | input FCore.Cache inCache; | ||
| 12267 | input FCore.Graph inEnv; | ||
| 12268 | input Absyn.ComponentRef inCref; | ||
| 12269 | input Absyn.Subscript inDimension; | ||
| 12270 | input Boolean inImpl; | ||
| 12271 | input Boolean inDoVect; | ||
| 12272 | input DAE.Prefix inPrefix; | ||
| 12273 | input SourceInfo inInfo; | ||
| 12274 | output FCore.Cache outCache; | ||
| 12275 | output DAE.Dimension outDimension; | ||
| 12276 | algorithm | ||
| 12277 | (outCache, outDimension) := matchcontinue(inCache, inDimension) | ||
| 12278 | local | ||
| 12279 | Absyn.ComponentRef cr; | ||
| 12280 | DAE.Dimension dim; | ||
| 12281 | FCore.Cache cache; | ||
| 12282 | Absyn.Path type_path; | ||
| 12283 | String name; | ||
| 12284 | Absyn.Exp sub, cr_exp; | ||
| 12285 | DAE.Exp e, dim_exp; | ||
| 12286 | DAE.Properties prop; | ||
| 12287 | Absyn.Exp size_arg; | ||
| 12288 | DAE.Type t; | ||
| 12289 | |||
| 12290 | // The : operator results in an unknown dimension. | ||
| 12291 | case (_, Absyn.NOSUB()) | ||
| 12292 | 6641 | then (inCache, DAE.DIM_UNKNOWN()); | |
| 12293 | |||
| 12294 | // Size expression that refers to the array itself, such as | ||
| 12295 | // Real x(:, size(x, 1)). | ||
| 12296 | case (_, Absyn.SUBSCRIPT(subscript = Absyn.CALL(function_ = | ||
| 12297 | Absyn.CREF_IDENT(name = "size"), functionArgs = Absyn.FUNCTIONARGS(args = | ||
| 12298 | {cr_exp as Absyn.CREF(componentRef = cr), size_arg})))) | ||
| 12299 | algorithm | ||
| 12300 |
2/2✓ Branch 1 taken 818 times.
✓ Branch 2 taken 115 times.
|
933 | true := AbsynUtil.crefEqual(inCref, cr); |
| 12301 | 115 | (cache, e, _) := elabExpInExpression(inCache, inEnv, cr_exp, inImpl, | |
| 12302 | inDoVect, inPrefix, inInfo); | ||
| 12303 | 23 | (cache, dim_exp, _) := elabExpInExpression(cache, inEnv, size_arg, inImpl, | |
| 12304 | inDoVect, inPrefix, inInfo); | ||
| 12305 | 23 | dim := DAE.DIM_EXP(DAE.SIZE(e, SOME(dim_exp))); | |
| 12306 | //dim = DAE.DIM_UNKNOWN(); | ||
| 12307 | 23 | then | |
| 12308 | (inCache, dim); | ||
| 12309 | |||
| 12310 | case (_, Absyn.SUBSCRIPT(subscript = Absyn.CREF(componentRef = Absyn.CREF_IDENT(name = "Boolean")))) | ||
| 12311 | 5 | then | |
| 12312 | (inCache, DAE.DIM_BOOLEAN()); | ||
| 12313 | |||
| 12314 | // Array dimension from a Boolean or enumeration. | ||
| 12315 | case (cache, Absyn.SUBSCRIPT(subscript = Absyn.CREF(cr))) | ||
| 12316 | algorithm | ||
| 12317 | 4381 | type_path := AbsynUtil.crefToPath(cr); | |
| 12318 | 4381 | cache := Lookup.lookupClass(cache, inEnv, type_path); | |
| 12319 | 138 | (cache, t) := Lookup.lookupType(cache, inEnv, type_path, NONE()); | |
| 12320 | dim := match t | ||
| 12321 | case DAE.T_ENUMERATION(index=NONE()) | ||
| 12322 | 122 | then DAE.DIM_ENUM(t.path, t.names, listLength(t.names)); | |
| 12323 | case DAE.T_BOOL() | ||
| 12324 | then DAE.DIM_BOOLEAN(); | ||
| 12325 | end match; | ||
| 12326 | 122 | then | |
| 12327 | (cache, dim); | ||
| 12328 | |||
| 12329 | case (_, Absyn.SUBSCRIPT(subscript = Absyn.EXPRESSIONCOMMENT(exp=sub))) | ||
| 12330 | algorithm | ||
| 12331 | ✗ | (cache, dim) := elabArrayDim(inCache, inEnv, inCref, Absyn.SUBSCRIPT(sub), inImpl, inDoVect, inPrefix, inInfo); | |
| 12332 | then | ||
| 12333 | (cache, dim); | ||
| 12334 | |||
| 12335 | // For all other cases we need to elaborate the subscript expression, so the | ||
| 12336 | // expression is elaborated and passed on to elabArrayDim2 to avoid doing | ||
| 12337 | // the elaboration several times. | ||
| 12338 | case (_, Absyn.SUBSCRIPT(subscript = sub)) | ||
| 12339 | algorithm | ||
| 12340 | 63162 | (cache, e, prop) := elabExpInExpression(inCache, inEnv, sub, inImpl, | |
| 12341 | inDoVect, inPrefix, inInfo); | ||
| 12342 |
3/4✗ Branch 1 not taken.
✓ Branch 2 taken 63064 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 63061 times.
|
63064 | (cache, SOME(dim)) := elabArrayDim2(cache, inEnv, inCref, e, prop, inImpl, |
| 12343 | inDoVect, inPrefix, inInfo); | ||
| 12344 | 63061 | then | |
| 12345 | (cache, dim); | ||
| 12346 | |||
| 12347 | else | ||
| 12348 | algorithm | ||
| 12349 |
1/2✓ Branch 1 taken 101 times.
✗ Branch 2 not taken.
|
101 | true := Flags.isSet(Flags.FAILTRACE); |
| 12350 | ✗ | Debug.traceln("- Static.elabArrayDim failed on: " + | |
| 12351 | Dump.printComponentRefStr(inCref) + | ||
| 12352 | Dump.printArraydimStr({inDimension})); | ||
| 12353 | ✗ | then | |
| 12354 | fail(); | ||
| 12355 | |||
| 12356 | end matchcontinue; | ||
| 12357 | end elabArrayDim; | ||
| 12358 | |||
| 12359 | protected function elabArrayDim2 | ||
| 12360 | "Helper function to elabArrayDim. Continues the work from the last case in | ||
| 12361 | elabArrayDim to avoid unnecessary elaboration." | ||
| 12362 | input FCore.Cache inCache; | ||
| 12363 | input FCore.Graph inEnv; | ||
| 12364 | input Absyn.ComponentRef inCref; | ||
| 12365 | input DAE.Exp inExp; | ||
| 12366 | input DAE.Properties inProperties; | ||
| 12367 | input Boolean inImpl; | ||
| 12368 | input Boolean inDoVect; | ||
| 12369 | input DAE.Prefix inPrefix; | ||
| 12370 | input SourceInfo inInfo; | ||
| 12371 | output FCore.Cache outCache; | ||
| 12372 | output Option<DAE.Dimension> outDimension; | ||
| 12373 | algorithm | ||
| 12374 | (outCache, outDimension) := matchcontinue(inProperties, inImpl) | ||
| 12375 | local | ||
| 12376 | DAE.Const cnst; | ||
| 12377 | FCore.Cache cache; | ||
| 12378 | DAE.Exp e; | ||
| 12379 | DAE.Type ty; | ||
| 12380 | String e_str, t_str, a_str; | ||
| 12381 | Integer i; | ||
| 12382 | |||
| 12383 | // Constant dimension creates DIM_INTEGER. | ||
| 12384 | case (DAE.PROP(DAE.T_INTEGER(), cnst), _) | ||
| 12385 | algorithm | ||
| 12386 |
2/2✓ Branch 1 taken 1055 times.
✓ Branch 2 taken 62009 times.
|
63067 | true := Types.isParameterOrConstant(cnst); |
| 12387 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 61999 times.
|
62009 | (cache, Values.INTEGER(i)) := Ceval.ceval(inCache, inEnv, inExp, inImpl); |
| 12388 | 61999 | then | |
| 12389 | (cache, SOME(DAE.DIM_INTEGER(i))); | ||
| 12390 | |||
| 12391 | // When arrays are non-expanded, non-constant parametric dimensions are allowed. | ||
| 12392 | case (DAE.PROP(DAE.T_INTEGER(), DAE.C_PARAM()), _) | ||
| 12393 | algorithm | ||
| 12394 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
8 | false := Config.splitArrays(); |
| 12395 | ✗ | then | |
| 12396 | (inCache, SOME(DAE.DIM_EXP(inExp))); | ||
| 12397 | |||
| 12398 | // When not implicit instantiation, array dimension must be constant. | ||
| 12399 | case (DAE.PROP(DAE.T_INTEGER(), DAE.C_VAR()), false) | ||
| 12400 | algorithm | ||
| 12401 | ✗ | e_str := ExpressionBasics.printExpStr(inExp); | |
| 12402 | ✗ | Error.addSourceMessage(Error.DIMENSION_NOT_KNOWN, {e_str}, inInfo); | |
| 12403 | then | ||
| 12404 | (inCache, NONE()); | ||
| 12405 | |||
| 12406 | // Non-constant dimension creates DIM_EXP. | ||
| 12407 | case (DAE.PROP(DAE.T_INTEGER(), _), true) | ||
| 12408 | algorithm | ||
| 12409 | 1062 | (cache, e, _) := | |
| 12410 | Ceval.cevalIfConstant(inCache, inEnv, inExp, inProperties, inImpl, inInfo); | ||
| 12411 | 1062 | then | |
| 12412 | (cache, SOME(DAE.DIM_EXP(e))); | ||
| 12413 | |||
| 12414 | case (_, _) | ||
| 12415 | algorithm | ||
| 12416 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | (cache, e as DAE.SIZE(_, _), _) := |
| 12417 | Ceval.cevalIfConstant(inCache, inEnv, inExp, inProperties, inImpl, inInfo); | ||
| 12418 | ✗ | then | |
| 12419 | (cache, SOME(DAE.DIM_EXP(e))); | ||
| 12420 | |||
| 12421 | case (_, _) | ||
| 12422 | algorithm | ||
| 12423 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | true := Flags.getConfigBool(Flags.CHECK_MODEL); |
| 12424 | then | ||
| 12425 | (inCache, SOME(DAE.DIM_UNKNOWN())); | ||
| 12426 | |||
| 12427 | // an integer parameter with no binding | ||
| 12428 | case (DAE.PROP(DAE.T_INTEGER(), cnst), _) | ||
| 12429 | algorithm | ||
| 12430 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | true := Types.isParameterOrConstant(cnst); |
| 12431 | 3 | e_str := ExpressionBasics.printExpStr(inExp); | |
| 12432 | 3 | a_str := Dump.printComponentRefStr(inCref) + "[" + e_str + "]"; | |
| 12433 | 3 | Error.addSourceMessage(Error.STRUCTURAL_PARAMETER_OR_CONSTANT_WITH_NO_BINDING, {e_str, a_str}, inInfo); | |
| 12434 | //(_, _) = elabArrayDim2(inCache, inEnv, inCref, inExp, inProperties, inImpl, inDoVect, inPrefix, inInfo); | ||
| 12435 | then | ||
| 12436 | (inCache, NONE()); | ||
| 12437 | |||
| 12438 | case (DAE.PROP(ty, _), _) | ||
| 12439 | algorithm | ||
| 12440 | ✗ | e_str := ExpressionBasics.printExpStr(inExp); | |
| 12441 | ✗ | t_str := TypesDump.unparseType(ty); | |
| 12442 | ✗ | Types.typeErrorSanityCheck(t_str, "Integer", inInfo); | |
| 12443 | ✗ | Error.addSourceMessage(Error.ARRAY_DIMENSION_INTEGER, | |
| 12444 | {e_str, t_str}, inInfo); | ||
| 12445 | then | ||
| 12446 | (inCache, NONE()); | ||
| 12447 | |||
| 12448 | end matchcontinue; | ||
| 12449 | end elabArrayDim2; | ||
| 12450 | |||
| 12451 | protected function consStrippedCref | ||
| 12452 | input Absyn.Exp e; | ||
| 12453 | input list<Absyn.Exp> es; | ||
| 12454 | output list<Absyn.Exp> oes; | ||
| 12455 | algorithm | ||
| 12456 | oes := match e | ||
| 12457 | local | ||
| 12458 | Absyn.ComponentRef cr; | ||
| 12459 | case Absyn.CREF(cr) | ||
| 12460 | algorithm | ||
| 12461 | ✗ | cr := AbsynUtil.crefStripLastSubs(cr); | |
| 12462 | ✗ | then Absyn.CREF(cr)::es; | |
| 12463 | else es; | ||
| 12464 | end match; | ||
| 12465 | end consStrippedCref; | ||
| 12466 | |||
| 12467 | protected function replaceEnd | ||
| 12468 | "Replaces end-expressions in a cref with the appropriate size-expressions." | ||
| 12469 | input Absyn.ComponentRef inCref; | ||
| 12470 | output Absyn.ComponentRef outCref; | ||
| 12471 | protected | ||
| 12472 | list<Absyn.ComponentRef> cr_parts; | ||
| 12473 | Absyn.ComponentRef cr, cr_no_subs; | ||
| 12474 | algorithm | ||
| 12475 | //print("Before replace: " + Dump.printComponentRefStr(inCref) + "\n"); | ||
| 12476 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 578833 times.
|
578833 | outCref :: cr_parts := AbsynUtil.crefExplode(inCref); |
| 12477 | |||
| 12478 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 578833 times.
|
578833 | if not AbsynUtil.crefIsIdent(outCref) then |
| 12479 | outCref := inCref; | ||
| 12480 | ✗ | return; | |
| 12481 | end if; | ||
| 12482 | |||
| 12483 |
2/2✓ Branch 1 taken 2881 times.
✓ Branch 2 taken 575952 times.
|
578833 | if AbsynUtil.crefIsFullyQualified(inCref) then |
| 12484 | 2881 | outCref := AbsynUtil.crefMakeFullyQualified(outCref); | |
| 12485 | end if; | ||
| 12486 | |||
| 12487 | 578833 | outCref := replaceEndInSubs(AbsynUtil.crefStripLastSubs(outCref), AbsynUtil.crefLastSubs(outCref)); | |
| 12488 | |||
| 12489 |
2/2✓ Branch 0 taken 181309 times.
✓ Branch 1 taken 578833 times.
|
760142 | for cr in cr_parts loop |
| 12490 | 181309 | cr_no_subs := AbsynUtil.crefStripLastSubs(cr); | |
| 12491 | 181309 | outCref := AbsynUtil.joinCrefs(outCref, cr_no_subs); | |
| 12492 | 181309 | outCref := replaceEndInSubs(outCref, AbsynUtil.crefLastSubs(cr)); | |
| 12493 | end for; | ||
| 12494 | //print("After replace: " + Dump.printComponentRefStr(outCref) + "\n"); | ||
| 12495 | end replaceEnd; | ||
| 12496 | |||
| 12497 | protected function replaceEndInSubs | ||
| 12498 | input Absyn.ComponentRef inCref; | ||
| 12499 | input list<Absyn.Subscript> inSubscripts; | ||
| 12500 | output Absyn.ComponentRef outCref = inCref; | ||
| 12501 | protected | ||
| 12502 | list<Absyn.Subscript> subs = {}; | ||
| 12503 | Absyn.Subscript new_sub; | ||
| 12504 | Integer i = 1; | ||
| 12505 | algorithm | ||
| 12506 |
2/2✓ Branch 0 taken 80126 times.
✓ Branch 1 taken 680016 times.
|
760142 | if listEmpty(inSubscripts) then |
| 12507 | 680016 | return; | |
| 12508 | end if; | ||
| 12509 | |||
| 12510 |
2/2✓ Branch 0 taken 84011 times.
✓ Branch 1 taken 80126 times.
|
164137 | for sub in inSubscripts loop |
| 12511 | 84011 | new_sub := replaceEndInSub(sub, i, inCref); | |
| 12512 | subs := new_sub :: subs; | ||
| 12513 | 84011 | i := i + 1; | |
| 12514 | end for; | ||
| 12515 | |||
| 12516 | 80126 | outCref := AbsynUtil.crefSetLastSubs(outCref, listReverse(subs)); | |
| 12517 | end replaceEndInSubs; | ||
| 12518 | |||
| 12519 | protected function replaceEndInSub | ||
| 12520 | input Absyn.Subscript inSubscript; | ||
| 12521 | input Integer inDimIndex; | ||
| 12522 | input Absyn.ComponentRef inCref; | ||
| 12523 | output Absyn.Subscript outSubscript; | ||
| 12524 | algorithm | ||
| 12525 | outSubscript := match inSubscript | ||
| 12526 | case Absyn.SUBSCRIPT() | ||
| 12527 | 82521 | then Absyn.SUBSCRIPT(replaceEndTraverser(inSubscript.subscript, (inCref, inDimIndex))); | |
| 12528 | |||
| 12529 | else inSubscript; | ||
| 12530 | end match; | ||
| 12531 | end replaceEndInSub; | ||
| 12532 | |||
| 12533 | protected function replaceEndTraverser | ||
| 12534 | input Absyn.Exp inExp; | ||
| 12535 | input tuple<Absyn.ComponentRef, Integer> inTuple; | ||
| 12536 | output Absyn.Exp outExp; | ||
| 12537 | algorithm | ||
| 12538 | outExp := match inExp | ||
| 12539 | local | ||
| 12540 | Absyn.ComponentRef cr; | ||
| 12541 | Integer i; | ||
| 12542 | |||
| 12543 | case Absyn.END() | ||
| 12544 | algorithm | ||
| 12545 | 41 | (cr, i) := inTuple; | |
| 12546 | 82 | then | |
| 12547 | Absyn.CALL(Absyn.CREF_IDENT("size", {}), | ||
| 12548 | Absyn.FUNCTIONARGS({Absyn.CREF(cr), Absyn.INTEGER(i)}, {}), {}); | ||
| 12549 | |||
| 12550 | case Absyn.CREF() | ||
| 12551 | 23521 | then Absyn.CREF(replaceEnd(inExp.componentRef)); | |
| 12552 | |||
| 12553 | 85539 | else AbsynUtil.traverseExpShallow(inExp, inTuple, replaceEndTraverser); | |
| 12554 | |||
| 12555 | end match; | ||
| 12556 | end replaceEndTraverser; | ||
| 12557 | |||
| 12558 | protected function fixTupleMetaModelica | ||
| 12559 | input list<DAE.Exp> exps; | ||
| 12560 | input list<DAE.Type> types; | ||
| 12561 | input list<DAE.TupleConst> consts; | ||
| 12562 | output DAE.Exp exp; | ||
| 12563 | output DAE.Properties prop; | ||
| 12564 | protected | ||
| 12565 | DAE.Const c; | ||
| 12566 | list<DAE.Type> tys2; | ||
| 12567 | list<DAE.Exp> exps2; | ||
| 12568 | algorithm | ||
| 12569 |
2/2✓ Branch 1 taken 3067 times.
✓ Branch 2 taken 82 times.
|
3149 | if Config.acceptMetaModelicaGrammar() then |
| 12570 | 3067 | c := Types.tupleConstListToConst(consts); | |
| 12571 |
4/4✓ Branch 0 taken 6097 times.
✓ Branch 1 taken 3067 times.
✓ Branch 2 taken 6097 times.
✓ Branch 3 taken 3067 times.
|
9164 | tys2 := list(Types.boxIfUnboxedType(ty) for ty in types); |
| 12572 | 3067 | (exps2, tys2) := Types.matchTypeTuple(exps, types, tys2, false); | |
| 12573 | 3067 | exp := DAE.META_TUPLE(exps2); | |
| 12574 | 3067 | prop := DAE.PROP(DAE.T_METATUPLE(tys2), c); | |
| 12575 | else | ||
| 12576 | 82 | exp := DAE.TUPLE(exps); | |
| 12577 | 82 | prop := DAE.PROP_TUPLE(DAE.T_TUPLE(types, NONE()), DAE.TUPLE_CONST(consts)); | |
| 12578 | end if; | ||
| 12579 | end fixTupleMetaModelica; | ||
| 12580 | |||
| 12581 | protected function checkBuiltinCallArgs | ||
| 12582 | input list<Absyn.Exp> inPosArgs; | ||
| 12583 | input list<Absyn.NamedArg> inNamedArgs; | ||
| 12584 | input Integer inExpectedArgs; | ||
| 12585 | input String inFnName; | ||
| 12586 | input Absyn.Info inInfo; | ||
| 12587 | protected | ||
| 12588 | algorithm | ||
| 12589 |
2/4✓ Branch 1 taken 5956 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5956 times.
✗ Branch 4 not taken.
|
5956 | if listLength(inPosArgs) <> inExpectedArgs or not listEmpty(inNamedArgs) then |
| 12590 | ✗ | Error.addSourceMessageAndFail(Error.WRONG_NO_OF_ARGS, {inFnName}, inInfo); | |
| 12591 | end if; | ||
| 12592 | end checkBuiltinCallArgs; | ||
| 12593 | |||
| 12594 | annotation(__OpenModelica_Interface="frontend"); | ||
| 12595 | end Static; | ||
| 12596 |