OMCompiler/Compiler/NFFrontEnd/NFCall.mo
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * This file is part of OpenModelica. | ||
| 3 | * | ||
| 4 | * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC), | ||
| 5 | * c/o Linköpings universitet, Department of Computer and Information Science, | ||
| 6 | * SE-58183 Linköping, Sweden. | ||
| 7 | * | ||
| 8 | * All rights reserved. | ||
| 9 | * | ||
| 10 | * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR | ||
| 11 | * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8. | ||
| 12 | * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES | ||
| 13 | * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL | ||
| 14 | * VERSION 3, ACCORDING TO RECIPIENTS CHOICE. | ||
| 15 | * | ||
| 16 | * The OpenModelica software and the OSMC (Open Source Modelica Consortium) | ||
| 17 | * Public License (OSMC-PL) are obtained from OSMC, either from the above | ||
| 18 | * address, from the URLs: | ||
| 19 | * http://www.openmodelica.org or | ||
| 20 | * https://github.com/OpenModelica/ or | ||
| 21 | * http://www.ida.liu.se/projects/OpenModelica, | ||
| 22 | * and in the OpenModelica distribution. | ||
| 23 | * | ||
| 24 | * GNU AGPL version 3 is obtained from: | ||
| 25 | * https://www.gnu.org/licenses/licenses.html#GPL | ||
| 26 | * | ||
| 27 | * This program is distributed WITHOUT ANY WARRANTY; without | ||
| 28 | * even the implied warranty of MERCHANTABILITY or FITNESS | ||
| 29 | * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH | ||
| 30 | * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. | ||
| 31 | * | ||
| 32 | * See the full OSMC Public License conditions for more details. | ||
| 33 | * | ||
| 34 | */ | ||
| 35 | |||
| 36 | encapsulated uniontype NFCall | ||
| 37 | |||
| 38 | import Absyn; | ||
| 39 | import AbsynUtil; | ||
| 40 | import BaseModelica; | ||
| 41 | import DAE; | ||
| 42 | import Expression = NFExpression; | ||
| 43 | import NFCallAttributes; | ||
| 44 | import NFInstNode.InstNode; | ||
| 45 | import NFInstNode; | ||
| 46 | import NFPrefixes.{Variability, Purity}; | ||
| 47 | import Type = NFType; | ||
| 48 | import Record = NFRecord; | ||
| 49 | |||
| 50 | protected | ||
| 51 | import Binding = NFBinding; | ||
| 52 | import BuiltinCall = NFBuiltinCall; | ||
| 53 | import Ceval = NFCeval; | ||
| 54 | import Component = NFComponent; | ||
| 55 | import ComponentRef = NFComponentRef; | ||
| 56 | import Dimension = NFDimension; | ||
| 57 | import ErrorExt; | ||
| 58 | import EvalFunction = NFEvalFunction; | ||
| 59 | import Inline = NFInline; | ||
| 60 | import Inst = NFInst; | ||
| 61 | import JSON; | ||
| 62 | import List; | ||
| 63 | import Lookup = NFLookup; | ||
| 64 | import MetaModelica.Dangerous.listReverseInPlace; | ||
| 65 | import Class = NFClass; | ||
| 66 | import NFFunction.Function; | ||
| 67 | import NFFunction.FunctionMatchKind; | ||
| 68 | import NFFunction.MatchedFunction; | ||
| 69 | import NFFunction.NamedArg; | ||
| 70 | import NFFunction.TypedArg; | ||
| 71 | import NFInstNode.CachedData; | ||
| 72 | import Operator = NFOperator; | ||
| 73 | import Prefixes = NFPrefixes; | ||
| 74 | import Restriction = NFRestriction; | ||
| 75 | import SCodeUtil; | ||
| 76 | import SimplifyExp = NFSimplifyExp; | ||
| 77 | import Structural = NFStructural; | ||
| 78 | import Subscript = NFSubscript; | ||
| 79 | import TypeCheck = NFTypeCheck; | ||
| 80 | import Typing = NFTyping; | ||
| 81 | import Util; | ||
| 82 | import InstContext = NFInstContext; | ||
| 83 | import ComplexType = NFComplexType; | ||
| 84 | |||
| 85 | import Call = NFCall; | ||
| 86 | |||
| 87 | protected | ||
| 88 | import NFCallParameterTree; | ||
| 89 | type ParameterTree = NFCallParameterTree.Tree; | ||
| 90 | public | ||
| 91 | record UNTYPED_CALL | ||
| 92 | ComponentRef ref; | ||
| 93 | list<Expression> arguments; | ||
| 94 | list<NamedArg> named_args; | ||
| 95 | NFInstNode.ScopeRef call_scope "Weakly: the scope owns the class this call | ||
| 96 | sits in."; | ||
| 97 | end UNTYPED_CALL; | ||
| 98 | |||
| 99 | record ARG_TYPED_CALL | ||
| 100 | ComponentRef ref; | ||
| 101 | list<TypedArg> positional_args; | ||
| 102 | list<TypedArg> named_args; | ||
| 103 | NFInstNode.ScopeRef call_scope "See UNTYPED_CALL.call_scope."; | ||
| 104 | end ARG_TYPED_CALL; | ||
| 105 | |||
| 106 | record TYPED_CALL | ||
| 107 | Function fn; | ||
| 108 | Type ty; | ||
| 109 | Variability var; | ||
| 110 | Purity purity; | ||
| 111 | list<Expression> arguments; | ||
| 112 | NFCallAttributes attributes; | ||
| 113 | end TYPED_CALL; | ||
| 114 | |||
| 115 | record UNTYPED_ARRAY_CONSTRUCTOR | ||
| 116 | Expression exp; | ||
| 117 | list<tuple<InstNode, Expression>> iters; | ||
| 118 | end UNTYPED_ARRAY_CONSTRUCTOR; | ||
| 119 | |||
| 120 | record TYPED_ARRAY_CONSTRUCTOR | ||
| 121 | Type ty; | ||
| 122 | Variability var; | ||
| 123 | Purity purity; | ||
| 124 | Expression exp; | ||
| 125 | list<tuple<InstNode, Expression>> iters; | ||
| 126 | end TYPED_ARRAY_CONSTRUCTOR; | ||
| 127 | |||
| 128 | record UNTYPED_REDUCTION | ||
| 129 | ComponentRef ref; | ||
| 130 | Expression exp; | ||
| 131 | list<tuple<InstNode, Expression>> iters; | ||
| 132 | end UNTYPED_REDUCTION; | ||
| 133 | |||
| 134 | record TYPED_REDUCTION | ||
| 135 | Function fn; | ||
| 136 | Type ty; | ||
| 137 | Variability var; | ||
| 138 | Purity purity; | ||
| 139 | Expression exp; | ||
| 140 | list<tuple<InstNode, Expression>> iters; | ||
| 141 | Option<Expression> defaultExp; | ||
| 142 | tuple<Option<Expression>, String, String> foldExp; | ||
| 143 | end TYPED_REDUCTION; | ||
| 144 | |||
| 145 | function instantiate | ||
| 146 | input Absyn.ComponentRef functionName; | ||
| 147 | input Absyn.FunctionArgs functionArgs; | ||
| 148 | input InstNode scope; | ||
| 149 | input InstContext.Type context; | ||
| 150 | input SourceInfo info; | ||
| 151 | output Expression callExp; | ||
| 152 | algorithm | ||
| 153 | callExp := match functionArgs | ||
| 154 | 110173 | case Absyn.FUNCTIONARGS() then instNormalCall(functionName, functionArgs, scope, context, info); | |
| 155 | 1775 | case Absyn.FOR_ITER_FARG() then instIteratorCall(functionName, functionArgs, scope, context, info); | |
| 156 | else | ||
| 157 | algorithm | ||
| 158 | ✗ | Error.terminate(getInstanceName() + " got unknown call type", sourceInfo()); | |
| 159 | ✗ | then | |
| 160 | fail(); | ||
| 161 | end match; | ||
| 162 | end instantiate; | ||
| 163 | |||
| 164 | function typeCall | ||
| 165 | input Expression callExp; | ||
| 166 | input InstContext.Type context; | ||
| 167 | input SourceInfo info; | ||
| 168 | input Boolean retype = false; | ||
| 169 | output Expression outExp; | ||
| 170 | output Type ty; | ||
| 171 | output Variability var; | ||
| 172 | output Purity pur; | ||
| 173 | protected | ||
| 174 | NFCall call, ty_call; | ||
| 175 | ComponentRef cref; | ||
| 176 | algorithm | ||
| 177 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 103726 times.
|
103726 | Expression.CALL(call = call) := callExp; |
| 178 | |||
| 179 | outExp := match call | ||
| 180 | // 1. typing all the untyped calls | ||
| 181 | case UNTYPED_CALL(ref = cref) | ||
| 182 | algorithm | ||
| 183 |
2/2✓ Branch 1 taken 30062 times.
✓ Branch 2 taken 71573 times.
|
101635 | if BuiltinCall.needSpecialHandling(call) then |
| 184 | 30062 | (outExp, ty, var, pur) := BuiltinCall.typeSpecial(call, context, info); | |
| 185 | else | ||
| 186 | 71573 | checkNotPartial(cref, context, info); | |
| 187 | 71573 | ty_call := typeMatchNormalCall(call, context, info); | |
| 188 | 71560 | (outExp, ty, var, pur) := typeCallExp(ty_call); | |
| 189 | end if; | ||
| 190 | then | ||
| 191 | outExp; | ||
| 192 | |||
| 193 | case UNTYPED_ARRAY_CONSTRUCTOR() | ||
| 194 | algorithm | ||
| 195 | 1354 | (ty_call, ty, var, pur) := typeArrayConstructor(call, context, info); | |
| 196 | 1354 | then | |
| 197 | Expression.CALL(ty_call); | ||
| 198 | |||
| 199 | case UNTYPED_REDUCTION() | ||
| 200 | algorithm | ||
| 201 | 300 | checkNotPartial(call.ref, context, info); | |
| 202 | 300 | (ty_call, ty, var, pur) := typeReduction(call, context, info); | |
| 203 | 298 | then | |
| 204 | Expression.CALL(ty_call); | ||
| 205 | |||
| 206 | // 2. retyping already typed calls | ||
| 207 | case TYPED_CALL() guard(retype and not BuiltinCall.needSpecialHandling(call)) | ||
| 208 | algorithm | ||
| 209 | 165 | ty_call := retypeCall(call, context, info); | |
| 210 | 165 | (outExp, ty, var, pur) := typeCallExp(ty_call); | |
| 211 | then | ||
| 212 | outExp; | ||
| 213 | |||
| 214 | // 3. not retyping already typed calls | ||
| 215 | case TYPED_CALL() | ||
| 216 | algorithm | ||
| 217 | 262 | ty := call.ty; | |
| 218 | 262 | var := call.var; | |
| 219 | 262 | pur := call.purity; | |
| 220 | then | ||
| 221 | callExp; | ||
| 222 | |||
| 223 | case TYPED_ARRAY_CONSTRUCTOR() | ||
| 224 | algorithm | ||
| 225 | 10 | ty := call.ty; | |
| 226 | 10 | var := call.var; | |
| 227 | 10 | pur := call.purity; | |
| 228 | then | ||
| 229 | callExp; | ||
| 230 | |||
| 231 | case TYPED_REDUCTION() | ||
| 232 | algorithm | ||
| 233 | ✗ | ty := call.ty; | |
| 234 | ✗ | var := call.var; | |
| 235 | ✗ | pur := call.purity; | |
| 236 | then | ||
| 237 | callExp; | ||
| 238 | |||
| 239 | else | ||
| 240 | algorithm | ||
| 241 | ✗ | Error.terminate(getInstanceName() + ": " + Expression.toString(callExp), sourceInfo()); | |
| 242 | ✗ | then fail(); | |
| 243 | end match; | ||
| 244 | end typeCall; | ||
| 245 | |||
| 246 | function checkNotPartial | ||
| 247 | input ComponentRef fnRef; | ||
| 248 | input InstContext.Type context; | ||
| 249 | input SourceInfo info; | ||
| 250 | algorithm | ||
| 251 |
3/4✓ Branch 2 taken 1 time.
✓ Branch 3 taken 71872 times.
✓ Branch 5 taken 1 time.
✗ Branch 6 not taken.
|
71873 | if InstNode.isPartial(ComponentRef.node(fnRef)) and not InstContext.inRelaxed(context) then |
| 252 | ✗ | Error.addSourceMessage(Error.PARTIAL_FUNCTION_CALL, | |
| 253 | {ComponentRef.toString(fnRef)}, info); | ||
| 254 | ✗ | fail(); | |
| 255 | end if; | ||
| 256 | end checkNotPartial; | ||
| 257 | |||
| 258 | function typeCallExp | ||
| 259 | input Call ty_call; | ||
| 260 | output Expression outExp; | ||
| 261 | output Type ty; | ||
| 262 | output Variability var; | ||
| 263 | output Purity pur; | ||
| 264 | algorithm | ||
| 265 | 71725 | ty := typeOf(ty_call); | |
| 266 | 71725 | var := variability(ty_call); | |
| 267 | 71725 | pur := purity(ty_call); | |
| 268 |
2/2✓ Branch 1 taken 832 times.
✓ Branch 2 taken 70893 times.
|
71725 | if isRecordConstructor(ty_call) then |
| 269 | 832 | outExp := toRecordExpression(ty_call, ty); | |
| 270 | else | ||
| 271 |
2/2✓ Branch 2 taken 123 times.
✓ Branch 3 taken 70770 times.
|
70893 | if Function.hasUnboxArgs(typedFunction(ty_call)) then |
| 272 | 123 | outExp := Expression.CALL(unboxArgs(ty_call)); | |
| 273 | else | ||
| 274 | 70770 | outExp := Expression.CALL(ty_call); | |
| 275 | end if; | ||
| 276 | 70893 | outExp := Inline.inlineCallExp(outExp); | |
| 277 | |||
| 278 | // The parameters of a partial function are boxed, so calling a functional | ||
| 279 | // input argument gives a boxed value. Unbox it here so the rest of the | ||
| 280 | // expression sees the actual type, otherwise the boxed type leaks into | ||
| 281 | // e.g. array constructors and reductions and gives invalid code. | ||
| 282 |
4/6✓ Branch 1 taken 70824 times.
✓ Branch 2 taken 69 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 69 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 69 times.
|
70893 | if Type.isBoxed(ty) and isUnboxableType(Type.unbox(ty)) and |
| 283 | Function.isFunctionPointer(typedFunction(ty_call)) then | ||
| 284 | 69 | ty := Type.unbox(ty); | |
| 285 | 69 | outExp := Expression.UNBOX(outExp, ty); | |
| 286 | end if; | ||
| 287 | end if; | ||
| 288 | end typeCallExp; | ||
| 289 | |||
| 290 | function isUnboxableType | ||
| 291 | "Returns true for the types that the code generator knows how to unbox." | ||
| 292 | input Type ty; | ||
| 293 | output Boolean unboxable = Type.isScalarBuiltin(ty) or Type.isRecord(ty); | ||
| 294 | end isUnboxableType; | ||
| 295 | |||
| 296 | function typeNormalCall | ||
| 297 | input output NFCall call; | ||
| 298 | input InstContext.Type context; | ||
| 299 | input SourceInfo info; | ||
| 300 | algorithm | ||
| 301 | call := match call | ||
| 302 | local | ||
| 303 | InstContext.Type fn_context; | ||
| 304 | |||
| 305 | case UNTYPED_CALL() | ||
| 306 | algorithm | ||
| 307 | // Strip any contexts that don't apply inside the function itself. | ||
| 308 |
2/2✓ Branch 1 taken 14290 times.
✓ Branch 2 taken 64466 times.
|
78756 | if InstContext.inRelaxed(context) then |
| 309 | 14290 | fn_context := InstContext.set(NFInstContext.FUNCTION, NFInstContext.RELAXED); | |
| 310 | else | ||
| 311 | fn_context := NFInstContext.FUNCTION; | ||
| 312 | end if; | ||
| 313 | |||
| 314 | 78756 | Function.typeRefCache(call.ref, fn_context); | |
| 315 | 78748 | then | |
| 316 | typeArgs(call, context, info); | ||
| 317 | |||
| 318 | else | ||
| 319 | algorithm | ||
| 320 | ✗ | Error.terminate(getInstanceName() + " got invalid function call expression", sourceInfo()); | |
| 321 | ✗ | then | |
| 322 | fail(); | ||
| 323 | end match; | ||
| 324 | end typeNormalCall; | ||
| 325 | |||
| 326 | function makeTypedCall | ||
| 327 | input Function fn; | ||
| 328 | input list<Expression> args; | ||
| 329 | input Variability variability; | ||
| 330 | input Purity purity; | ||
| 331 | input Type returnType = fn.returnType; | ||
| 332 | output NFCall call; | ||
| 333 | protected | ||
| 334 | NFCallAttributes ca; | ||
| 335 | algorithm | ||
| 336 |
8/8✓ Branch 2 taken 196976 times.
✓ Branch 3 taken 69 times.
✓ Branch 5 taken 195945 times.
✓ Branch 6 taken 1100 times.
✓ Branch 8 taken 61646 times.
✓ Branch 9 taken 135399 times.
✓ Branch 11 taken 195898 times.
✓ Branch 12 taken 1147 times.
|
847510 | ca := NFCallAttributes.CALL_ATTR( |
| 337 | Type.isTuple(returnType), | ||
| 338 | Function.isBuiltin(fn), | ||
| 339 | Function.isImpure(fn), | ||
| 340 | Function.isFunctionPointer(fn), | ||
| 341 | Function.inlineBuiltin(fn), | ||
| 342 | DAE.NO_TAIL() | ||
| 343 | ); | ||
| 344 | |||
| 345 | 197045 | call := TYPED_CALL(fn, returnType, variability, purity, args, ca); | |
| 346 | end makeTypedCall; | ||
| 347 | |||
| 348 | function unboxArgs | ||
| 349 | input output NFCall call; | ||
| 350 | protected | ||
| 351 | Call c; | ||
| 352 | algorithm | ||
| 353 | () := match call | ||
| 354 | case TYPED_CALL() | ||
| 355 | algorithm | ||
| 356 |
4/4✓ Branch 0 taken 151 times.
✓ Branch 1 taken 363 times.
✓ Branch 2 taken 151 times.
✓ Branch 3 taken 363 times.
|
877 | call.arguments := list(Expression.unbox(arg) for arg in call.arguments); |
| 357 | then | ||
| 358 | (); | ||
| 359 | |||
| 360 | case TYPED_ARRAY_CONSTRUCTOR(exp = Expression.CALL(call = c)) | ||
| 361 | algorithm | ||
| 362 | ✗ | call.exp := Expression.CALL(unboxArgs(c)); | |
| 363 | then | ||
| 364 | (); | ||
| 365 | |||
| 366 | else (); | ||
| 367 | end match; | ||
| 368 | end unboxArgs; | ||
| 369 | |||
| 370 | function typeMatchNormalCall | ||
| 371 | input output NFCall call; | ||
| 372 | input InstContext.Type context; | ||
| 373 | input SourceInfo info; | ||
| 374 | input Boolean vectorize = true; | ||
| 375 | protected | ||
| 376 | NFCall argtycall; | ||
| 377 | algorithm | ||
| 378 | 74338 | argtycall := typeNormalCall(call, context, info); | |
| 379 | 74329 | call := matchTypedNormalCall(argtycall, context, info, vectorize); | |
| 380 | end typeMatchNormalCall; | ||
| 381 | |||
| 382 | function matchTypedNormalCall | ||
| 383 | input output NFCall call; | ||
| 384 | input InstContext.Type context; | ||
| 385 | input SourceInfo info; | ||
| 386 | input Boolean vectorize = true; | ||
| 387 | protected | ||
| 388 | Function func; | ||
| 389 | list<Expression> args; | ||
| 390 | list<TypedArg> typed_args; | ||
| 391 | MatchedFunction matchedFunc; | ||
| 392 | NFInstNode.ScopeRef scope; | ||
| 393 | Variability var, arg_var; | ||
| 394 | Purity pur, arg_pur; | ||
| 395 | Type ty; | ||
| 396 | Expression arg_exp; | ||
| 397 | algorithm | ||
| 398 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 78603 times.
|
78603 | ARG_TYPED_CALL(call_scope = scope) := call; |
| 399 | 78603 | matchedFunc := checkMatchingFunctions(call, context, info, vectorize); | |
| 400 | |||
| 401 | 78598 | func := matchedFunc.func; | |
| 402 | 78598 | typed_args := matchedFunc.args; | |
| 403 | |||
| 404 | args := {}; | ||
| 405 | var := Variability.CONSTANT; | ||
| 406 |
2/2✓ Branch 1 taken 77719 times.
✓ Branch 2 taken 879 times.
|
78598 | pur := if Function.isImpure(func) then Purity.IMPURE else Purity.PURE; |
| 407 | |||
| 408 |
2/2✓ Branch 0 taken 153449 times.
✓ Branch 1 taken 78598 times.
|
232047 | for a in typed_args loop |
| 409 | 153449 | TypedArg.TYPED_ARG(value = arg_exp, var = arg_var, purity = arg_pur) := a; | |
| 410 | args := arg_exp :: args; | ||
| 411 | 153449 | var := Prefixes.variabilityMax(var, arg_var); | |
| 412 | 153449 | pur := Prefixes.purityMin(pur, arg_pur); | |
| 413 | end for; | ||
| 414 | 78598 | args := listReverseInPlace(args); | |
| 415 | |||
| 416 | 78598 | ty := Function.returnType(func); | |
| 417 | 78598 | ty := resolvePolymorphicReturnType(func, typed_args, ty); | |
| 418 | |||
| 419 |
4/4✓ Branch 0 taken 4460 times.
✓ Branch 1 taken 74138 times.
✓ Branch 3 taken 4326 times.
✓ Branch 4 taken 134 times.
|
78598 | if var == Variability.PARAMETER and Function.isExternal(func) then |
| 420 | // Mark external functions with parameter expressions as non-structural, | ||
| 421 | // to avoid them being marked as structural unnecessarily. | ||
| 422 | var := Variability.NON_STRUCTURAL_PARAMETER; | ||
| 423 | elseif Type.isDiscrete(ty) and var == Variability.CONTINUOUS then | ||
| 424 | // Functions that return a discrete type, e.g. Integer, should probably be | ||
| 425 | // treated as implicitly discrete if the arguments are continuous. | ||
| 426 | var := Variability.IMPLICITLY_DISCRETE; | ||
| 427 | end if; | ||
| 428 | |||
| 429 | 78598 | ty := evaluateCallType(ty, func, args); | |
| 430 | 78598 | call := makeTypedCall(func, args, var, pur, ty); | |
| 431 | |||
| 432 | // If the matching was a vectorized one then create a map call | ||
| 433 | // using the vectorization dim. This means going through each argument | ||
| 434 | // and subscripting it with an iterator for each dim and creating a map call. | ||
| 435 |
2/2✓ Branch 1 taken 1515 times.
✓ Branch 2 taken 77083 times.
|
78598 | if MatchedFunction.isVectorized(matchedFunc) then |
| 436 | 1515 | call := vectorizeCall(call, matchedFunc.mk, scope, info); | |
| 437 | end if; | ||
| 438 | |||
| 439 |
2/2✓ Branch 1 taken 78018 times.
✓ Branch 2 taken 580 times.
|
78598 | if Function.isExternal(func) then |
| 440 | 580 | updateExternalRecordArgs(args); | |
| 441 | 580 | updateExternalRecordArgsInType(ty); | |
| 442 | end if; | ||
| 443 | end matchTypedNormalCall; | ||
| 444 | |||
| 445 | function retypeCall | ||
| 446 | input Call call; | ||
| 447 | input InstContext.Type context; | ||
| 448 | input SourceInfo info; | ||
| 449 | output Call ty_call; | ||
| 450 | protected | ||
| 451 | InstContext.Type next_context; | ||
| 452 | Type ty, arg_ty; | ||
| 453 | Variability arg_var; | ||
| 454 | Purity arg_pur; | ||
| 455 | list<TypedArg> typed_args = {}; | ||
| 456 | list<Expression> args = {}; | ||
| 457 | algorithm | ||
| 458 | ty_call := match call | ||
| 459 | case TYPED_CALL() algorithm | ||
| 460 | 165 | next_context := InstContext.set(context, NFInstContext.SUBEXPRESSION); | |
| 461 |
2/2✓ Branch 1 taken 319 times.
✓ Branch 2 taken 165 times.
|
484 | for arg in listReverse(call.arguments) loop |
| 462 | 319 | (arg, arg_ty, arg_var, arg_pur) := Typing.typeExp(arg, next_context, info, true); | |
| 463 | 319 | typed_args := TypedArg.TYPED_ARG(NONE(), arg, arg_ty, arg_var, arg_pur) :: typed_args; | |
| 464 | args := arg :: args; | ||
| 465 | end for; | ||
| 466 | |||
| 467 | 165 | ty := Function.returnType(call.fn); | |
| 468 | 165 | ty := resolvePolymorphicReturnType(call.fn, typed_args, ty); | |
| 469 | |||
| 470 | 165 | ty := evaluateCallType(ty, call.fn, args); | |
| 471 | 165 | ty_call := makeTypedCall(call.fn, args, call.var, call.purity, ty); | |
| 472 | then ty_call; | ||
| 473 | |||
| 474 | else | ||
| 475 | algorithm | ||
| 476 | ✗ | Error.terminate(getInstanceName() + " got invalid function call expression", sourceInfo()); | |
| 477 | ✗ | then | |
| 478 | fail(); | ||
| 479 | end match; | ||
| 480 | end retypeCall; | ||
| 481 | |||
| 482 | function typeOf | ||
| 483 | input NFCall call; | ||
| 484 | output Type ty; | ||
| 485 | algorithm | ||
| 486 | ty := match call | ||
| 487 | 876474 | case TYPED_CALL() then call.ty; | |
| 488 | 11639 | case TYPED_ARRAY_CONSTRUCTOR() then call.ty; | |
| 489 | 511 | case TYPED_REDUCTION() then call.ty; | |
| 490 | else Type.UNKNOWN(); | ||
| 491 | end match; | ||
| 492 | end typeOf; | ||
| 493 | |||
| 494 | function setType | ||
| 495 | input output NFCall call; | ||
| 496 | input Type ty; | ||
| 497 | algorithm | ||
| 498 | call := match call | ||
| 499 | 324893 | case TYPED_CALL() algorithm call.ty := ty; then call; | |
| 500 | 8187 | case TYPED_ARRAY_CONSTRUCTOR() algorithm call.ty := ty; then call; | |
| 501 | 62 | case TYPED_REDUCTION() algorithm call.ty := ty; then call; | |
| 502 | end match; | ||
| 503 | end setType; | ||
| 504 | |||
| 505 | function variability | ||
| 506 | input NFCall call; | ||
| 507 | output Variability var = Variability.CONTINUOUS; | ||
| 508 | algorithm | ||
| 509 | var := match call | ||
| 510 | local | ||
| 511 | Boolean var_set; | ||
| 512 | |||
| 513 | case UNTYPED_CALL() | ||
| 514 | algorithm | ||
| 515 | var_set := true; | ||
| 516 | |||
| 517 | ✗ | if ComponentRef.isSimple(call.ref) then | |
| 518 | var := match ComponentRef.firstName(call.ref) | ||
| 519 | case "change" then Variability.DISCRETE; | ||
| 520 | case "edge" then Variability.DISCRETE; | ||
| 521 | case "pre" then Variability.DISCRETE; | ||
| 522 | case "ndims" then Variability.PARAMETER; | ||
| 523 | case "cardinality" then Variability.PARAMETER; | ||
| 524 | else algorithm var_set := false; then Variability.CONTINUOUS; | ||
| 525 | end match; | ||
| 526 | else | ||
| 527 | var_set := false; | ||
| 528 | end if; | ||
| 529 | |||
| 530 | if not var_set then | ||
| 531 | ✗ | var := Expression.variabilityList(call.arguments); | |
| 532 | |||
| 533 | ✗ | for narg in call.named_args loop | |
| 534 | ✗ | var := Prefixes.variabilityMax(var, Expression.variability(Util.tuple22(narg))); | |
| 535 | end for; | ||
| 536 | end if; | ||
| 537 | then | ||
| 538 | var; | ||
| 539 | |||
| 540 | 1 | case UNTYPED_ARRAY_CONSTRUCTOR() then Expression.variability(call.exp); | |
| 541 | ✗ | case UNTYPED_REDUCTION() then Expression.variability(call.exp); | |
| 542 | 93665 | case TYPED_CALL() then call.var; | |
| 543 | 1569 | case TYPED_ARRAY_CONSTRUCTOR() then call.var; | |
| 544 | ✗ | case TYPED_REDUCTION() then call.var; | |
| 545 | else algorithm | ||
| 546 | ✗ | Error.terminate(getInstanceName() + " got untyped call", sourceInfo()); | |
| 547 | ✗ | then fail(); | |
| 548 | end match; | ||
| 549 | end variability; | ||
| 550 | |||
| 551 | function purity | ||
| 552 | input Call call; | ||
| 553 | output Purity purity; | ||
| 554 | algorithm | ||
| 555 | purity := match call | ||
| 556 | 77132 | case TYPED_CALL() then call.purity; | |
| 557 | 1515 | case TYPED_ARRAY_CONSTRUCTOR() then call.purity; | |
| 558 | ✗ | case TYPED_REDUCTION() then call.purity; | |
| 559 | else Purity.PURE; | ||
| 560 | end match; | ||
| 561 | end purity; | ||
| 562 | |||
| 563 | function compare | ||
| 564 | input NFCall call1; | ||
| 565 | input NFCall call2; | ||
| 566 | output Integer comp; | ||
| 567 | algorithm | ||
| 568 | 2194 | comp := AbsynUtil.pathCompare(functionName(call1), functionName(call2)); | |
| 569 | |||
| 570 |
2/2✓ Branch 0 taken 1947 times.
✓ Branch 1 taken 247 times.
|
2194 | if comp == 0 then |
| 571 | 1947 | comp := Expression.compareList(arguments(call1), arguments(call2)); | |
| 572 | end if; | ||
| 573 | |||
| 574 |
2/2✓ Branch 0 taken 522 times.
✓ Branch 1 taken 1672 times.
|
2194 | if comp == 0 then |
| 575 | 1672 | comp := List.compare(iterators(call1), iterators(call2), compareIterator); | |
| 576 | end if; | ||
| 577 | end compare; | ||
| 578 | |||
| 579 | function compareIterator | ||
| 580 | input tuple<InstNode, Expression> iter1; | ||
| 581 | input tuple<InstNode, Expression> iter2; | ||
| 582 | output Integer comp; | ||
| 583 | protected | ||
| 584 | InstNode n1, n2; | ||
| 585 | Expression e1, e2; | ||
| 586 | algorithm | ||
| 587 | 54 | (n1, e1) := iter1; | |
| 588 | 54 | (n2, e2) := iter2; | |
| 589 | 54 | comp := stringCompare(InstNode.name(n1), InstNode.name(n2)); | |
| 590 | |||
| 591 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
|
54 | if comp == 0 then |
| 592 | 54 | comp := Expression.compare(e1, e2); | |
| 593 | end if; | ||
| 594 | end compareIterator; | ||
| 595 | |||
| 596 | function isExternal | ||
| 597 | input NFCall call; | ||
| 598 | output Boolean isExternal; | ||
| 599 | algorithm | ||
| 600 | isExternal := match call | ||
| 601 | 1496 | case UNTYPED_CALL() then Class.isExternalFunction(InstNode.getClass(ComponentRef.node(call.ref))); | |
| 602 | ✗ | case ARG_TYPED_CALL() then Class.isExternalFunction(InstNode.getClass(ComponentRef.node(call.ref))); | |
| 603 | 216552 | case TYPED_CALL() then Function.isExternal(call.fn); | |
| 604 | else false; | ||
| 605 | end match; | ||
| 606 | end isExternal; | ||
| 607 | |||
| 608 | function isImpure | ||
| 609 | input NFCall call; | ||
| 610 | output Boolean isImpure; | ||
| 611 | algorithm | ||
| 612 | isImpure := match call | ||
| 613 | 1496 | case UNTYPED_CALL() then Function.isImpure(listHead(Function.getRefCache(call.ref))); | |
| 614 | 773 | case TYPED_CALL(purity = Purity.IMPURE) then Function.isImpure(call.fn); | |
| 615 | else false; | ||
| 616 | end match; | ||
| 617 | end isImpure; | ||
| 618 | |||
| 619 | function isRecordConstructor | ||
| 620 | input NFCall call; | ||
| 621 | output Boolean isConstructor; | ||
| 622 | algorithm | ||
| 623 | isConstructor := match call | ||
| 624 | case UNTYPED_CALL() | ||
| 625 | ✗ | then SCodeUtil.isRecord(InstNode.definition(ComponentRef.node(call.ref))); | |
| 626 | case TYPED_CALL() guard(not InstNode.isEmpty(InstNode.fromHandle(call.fn.node))) | ||
| 627 | 70210 | then SCodeUtil.isRecord(InstNode.definition(InstNode.fromHandle(call.fn.node))); | |
| 628 | else false; | ||
| 629 | end match; | ||
| 630 | end isRecordConstructor; | ||
| 631 | |||
| 632 | function isExternalObjectConstructor | ||
| 633 | input NFCall call; | ||
| 634 | output Boolean isConstructor; | ||
| 635 | algorithm | ||
| 636 | isConstructor := match call | ||
| 637 | // Only constructors may return external objects... | ||
| 638 | case TYPED_CALL() | ||
| 639 | 30 | then Type.isExternalObject(call.ty); | |
| 640 | else false; | ||
| 641 | end match; | ||
| 642 | end isExternalObjectConstructor; | ||
| 643 | |||
| 644 | function isLiteral | ||
| 645 | input Call call; | ||
| 646 | output Boolean literal; | ||
| 647 | protected | ||
| 648 | function is_literal_iter | ||
| 649 | input tuple<InstNode, Expression> iter; | ||
| 650 | output Boolean literal = Expression.isLiteral(Util.tuple22(iter)); | ||
| 651 | end is_literal_iter; | ||
| 652 | algorithm | ||
| 653 | literal := match call | ||
| 654 | ✗ | case TYPED_CALL() then List.all(call.arguments, Expression.isLiteral); | |
| 655 | |||
| 656 | case TYPED_REDUCTION() | ||
| 657 | ✗ | then Expression.isLiteral(call.exp) and List.all(call.iters, is_literal_iter); | |
| 658 | |||
| 659 | case TYPED_ARRAY_CONSTRUCTOR() | ||
| 660 | ✗ | then Expression.isLiteral(call.exp) and List.all(call.iters, is_literal_iter); | |
| 661 | |||
| 662 | else false; | ||
| 663 | end match; | ||
| 664 | end isLiteral; | ||
| 665 | |||
| 666 | function isKnownSizeFill | ||
| 667 | input Call call; | ||
| 668 | output Boolean res; | ||
| 669 | protected | ||
| 670 | function is_literal_iter | ||
| 671 | input tuple<InstNode, Expression> iter; | ||
| 672 | output Boolean literal = Expression.isLiteral(Util.tuple22(iter)); | ||
| 673 | end is_literal_iter; | ||
| 674 | algorithm | ||
| 675 | res := match call | ||
| 676 |
4/4✓ Branch 1 taken 28 times.
✓ Branch 2 taken 27 times.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 22 times.
|
55 | case TYPED_CALL() then isNamed(call, "fill") and List.all(listRest(call.arguments), Expression.isLiteral); |
| 677 | 447 | case TYPED_ARRAY_CONSTRUCTOR() then List.all(call.iters, is_literal_iter); | |
| 678 | else false; | ||
| 679 | end match; | ||
| 680 | end isKnownSizeFill; | ||
| 681 | |||
| 682 | function isReduction | ||
| 683 | "returns true if the call is a typed reduction or if the call is a typed | ||
| 684 | call of a function that represents an array reduction" | ||
| 685 | input Call call; | ||
| 686 | output Boolean b; | ||
| 687 | algorithm | ||
| 688 | b := match call | ||
| 689 | case TYPED_REDUCTION() then true; | ||
| 690 | case TYPED_CALL() then match AbsynUtil.pathString(Function.nameConsiderBuiltin(call.fn)) | ||
| 691 | case "min" then true; | ||
| 692 | case "max" then true; | ||
| 693 | case "sum" then true; | ||
| 694 | case "product" then true; | ||
| 695 | else false; | ||
| 696 | end match; | ||
| 697 | else false; | ||
| 698 | end match; | ||
| 699 | end isReduction; | ||
| 700 | |||
| 701 | function isPositive | ||
| 702 | "True if the return value of the function is known to be > 0, otherwise false." | ||
| 703 | input Call call; | ||
| 704 | output Boolean positive; | ||
| 705 | algorithm | ||
| 706 | positive := match call | ||
| 707 | case TYPED_CALL() | ||
| 708 | then match functionNameFirst(call) | ||
| 709 | ✗ | case "abs" then Expression.isNonZero(listHead(call.arguments)); | |
| 710 | 2 | case "max" then List.any(call.arguments, Expression.isPositive); | |
| 711 | ✗ | case "min" then List.all(call.arguments, Expression.isPositive); | |
| 712 | else false; | ||
| 713 | end match; | ||
| 714 | |||
| 715 | else false; | ||
| 716 | end match; | ||
| 717 | end isPositive; | ||
| 718 | |||
| 719 | function isNegative | ||
| 720 | "True if the return value of the function is known to be < 0, otherwise false." | ||
| 721 | input Call call; | ||
| 722 | output Boolean negative; | ||
| 723 | algorithm | ||
| 724 | negative := match call | ||
| 725 | case TYPED_CALL() | ||
| 726 | then match functionNameFirst(call) | ||
| 727 | case "abs" then false; | ||
| 728 | ✗ | case "min" then List.any(call.arguments, Expression.isNegative); | |
| 729 | ✗ | case "max" then List.all(call.arguments, Expression.isNegative); | |
| 730 | else false; | ||
| 731 | end match; | ||
| 732 | |||
| 733 | else false; | ||
| 734 | end match; | ||
| 735 | end isNegative; | ||
| 736 | |||
| 737 | function isNonPositive | ||
| 738 | "True if the return value of the function is known to be <= 0, otherwise false." | ||
| 739 | input Call call; | ||
| 740 | output Boolean nonPositive; | ||
| 741 | algorithm | ||
| 742 | nonPositive := match call | ||
| 743 | case TYPED_CALL() | ||
| 744 | then match functionNameFirst(call) | ||
| 745 | ✗ | case "abs" then Expression.isZero(listHead(call.arguments)); | |
| 746 | ✗ | case "max" then List.all(call.arguments, Expression.isNonPositive); | |
| 747 | ✗ | case "min" then List.any(call.arguments, Expression.isNonPositive); | |
| 748 | else false; | ||
| 749 | end match; | ||
| 750 | |||
| 751 | else false; | ||
| 752 | end match; | ||
| 753 | end isNonPositive; | ||
| 754 | |||
| 755 | function isNonNegative | ||
| 756 | "True if the return value of the function is known to be >= 0, otherwise false." | ||
| 757 | input Call call; | ||
| 758 | output Boolean nonNegative; | ||
| 759 | algorithm | ||
| 760 | nonNegative := match call | ||
| 761 | case TYPED_CALL() | ||
| 762 | then match functionNameFirst(call) | ||
| 763 | case "abs" then true; | ||
| 764 | ✗ | case "max" then List.any(call.arguments, Expression.isNonNegative); | |
| 765 | ✗ | case "min" then List.all(call.arguments, Expression.isNonNegative); | |
| 766 | else false; | ||
| 767 | end match; | ||
| 768 | |||
| 769 | else false; | ||
| 770 | end match; | ||
| 771 | end isNonNegative; | ||
| 772 | |||
| 773 | function inlineType | ||
| 774 | input NFCall call; | ||
| 775 | output DAE.InlineType inlineTy; | ||
| 776 | algorithm | ||
| 777 | inlineTy := match call | ||
| 778 | case TYPED_CALL(attributes = NFCallAttributes.CALL_ATTR(inlineType = inlineTy)) | ||
| 779 | then inlineTy; | ||
| 780 | else DAE.InlineType.NO_INLINE(); | ||
| 781 | end match; | ||
| 782 | end inlineType; | ||
| 783 | |||
| 784 | function typedFunction | ||
| 785 | input NFCall call; | ||
| 786 | output Function fn; | ||
| 787 | algorithm | ||
| 788 | fn := match call | ||
| 789 | 147806 | case TYPED_CALL() then call.fn; | |
| 790 | 2711 | case TYPED_ARRAY_CONSTRUCTOR() then NFBuiltinFuncs.ARRAY_FUNC; | |
| 791 | 36 | case TYPED_REDUCTION() then call.fn; | |
| 792 | else | ||
| 793 | algorithm | ||
| 794 | ✗ | Error.terminate(getInstanceName() + " got untyped function", sourceInfo()); | |
| 795 | ✗ | then | |
| 796 | fail(); | ||
| 797 | end match; | ||
| 798 | end typedFunction; | ||
| 799 | |||
| 800 | function functionName | ||
| 801 | input NFCall call; | ||
| 802 | output Absyn.Path name; | ||
| 803 | algorithm | ||
| 804 | name := match call | ||
| 805 | ✗ | case UNTYPED_CALL() then ComponentRef.toPath(call.ref); | |
| 806 | ✗ | case ARG_TYPED_CALL() then ComponentRef.toPath(call.ref); | |
| 807 | 49152 | case TYPED_CALL() then Function.nameConsiderBuiltin(call.fn); | |
| 808 | case UNTYPED_ARRAY_CONSTRUCTOR() then Absyn.IDENT("array"); | ||
| 809 | case TYPED_ARRAY_CONSTRUCTOR() then Absyn.IDENT("array"); | ||
| 810 | ✗ | case UNTYPED_REDUCTION() then ComponentRef.toPath(call.ref); | |
| 811 | 80 | case TYPED_REDUCTION() then Function.nameConsiderBuiltin(call.fn); | |
| 812 | end match; | ||
| 813 | end functionName; | ||
| 814 | |||
| 815 | function functionNameLast | ||
| 816 | input Call call; | ||
| 817 | output String ident = AbsynUtil.pathLastIdent(functionName(call)); | ||
| 818 | end functionNameLast; | ||
| 819 | |||
| 820 | function functionNameFirst | ||
| 821 | input Call call; | ||
| 822 | output String ident = AbsynUtil.pathFirstIdent(functionName(call)); | ||
| 823 | end functionNameFirst; | ||
| 824 | |||
| 825 | function isNamed | ||
| 826 | input Call call; | ||
| 827 | input String name; | ||
| 828 | output Boolean res; | ||
| 829 | protected | ||
| 830 | Absyn.Path path; | ||
| 831 | algorithm | ||
| 832 | 32860 | path := functionName(call); | |
| 833 | |||
| 834 | res := match path | ||
| 835 |
4/4✓ Branch 0 taken 19495 times.
✓ Branch 1 taken 7522 times.
✓ Branch 3 taken 3163 times.
✓ Branch 4 taken 16332 times.
|
27017 | case Absyn.IDENT() then path.name == name; |
| 836 | else false; | ||
| 837 | end match; | ||
| 838 | end isNamed; | ||
| 839 | |||
| 840 | function arguments | ||
| 841 | input NFCall call; | ||
| 842 | output list<Expression> arguments; | ||
| 843 | algorithm | ||
| 844 | arguments := match call | ||
| 845 | ✗ | case UNTYPED_CALL() then call.arguments; | |
| 846 | 14087 | case TYPED_CALL() then call.arguments; | |
| 847 | ✗ | case UNTYPED_ARRAY_CONSTRUCTOR() then {call.exp}; | |
| 848 | 127 | case TYPED_ARRAY_CONSTRUCTOR() then {call.exp}; | |
| 849 | ✗ | case UNTYPED_REDUCTION() then {call.exp}; | |
| 850 | 31 | case TYPED_REDUCTION() then {call.exp}; | |
| 851 | end match; | ||
| 852 | end arguments; | ||
| 853 | |||
| 854 | function setArguments | ||
| 855 | input output NFCall call; | ||
| 856 | input list<Expression> arguments; | ||
| 857 | algorithm | ||
| 858 | call := match call | ||
| 859 | ✗ | case UNTYPED_CALL() algorithm call.arguments := arguments; then call; | |
| 860 | 203 | case TYPED_CALL() algorithm call.arguments := arguments; then call; | |
| 861 | end match; | ||
| 862 | end setArguments; | ||
| 863 | |||
| 864 | function iterators | ||
| 865 | input Call call; | ||
| 866 | output list<tuple<InstNode, Expression>> iters; | ||
| 867 | algorithm | ||
| 868 | iters := match call | ||
| 869 | ✗ | case UNTYPED_ARRAY_CONSTRUCTOR() then call.iters; | |
| 870 | 699 | case TYPED_ARRAY_CONSTRUCTOR() then call.iters; | |
| 871 | ✗ | case UNTYPED_REDUCTION() then call.iters; | |
| 872 | 89 | case TYPED_REDUCTION() then call.iters; | |
| 873 | else {}; | ||
| 874 | end match; | ||
| 875 | end iterators; | ||
| 876 | |||
| 877 | function toRecordExpression | ||
| 878 | input NFCall call; | ||
| 879 | input Type ty; | ||
| 880 | output Expression exp; | ||
| 881 | algorithm | ||
| 882 | exp := match call | ||
| 883 | case TYPED_CALL() | ||
| 884 | 832 | then EvalFunction.evaluateRecordConstructor(call.fn, ty, call.arguments, evaluate = false); | |
| 885 | |||
| 886 | else | ||
| 887 | algorithm | ||
| 888 | ✗ | Error.terminate(getInstanceName() + " got unknown call", sourceInfo()); | |
| 889 | ✗ | then | |
| 890 | fail(); | ||
| 891 | |||
| 892 | end match; | ||
| 893 | end toRecordExpression; | ||
| 894 | |||
| 895 | function toString | ||
| 896 | input NFCall call; | ||
| 897 | output String str; | ||
| 898 | protected | ||
| 899 | String name, arg_str,c; | ||
| 900 | list<InstNode> iters; | ||
| 901 | algorithm | ||
| 902 | str := match call | ||
| 903 | case UNTYPED_CALL() | ||
| 904 | algorithm | ||
| 905 | 62 | name := ComponentRef.toString(call.ref); | |
| 906 |
4/4✓ Branch 0 taken 209 times.
✓ Branch 1 taken 62 times.
✓ Branch 2 taken 209 times.
✓ Branch 3 taken 62 times.
|
271 | arg_str := stringDelimitList(list(Expression.toString(arg) for arg in call.arguments), ", "); |
| 907 | 62 | then | |
| 908 | name + "(" + arg_str + ")"; | ||
| 909 | |||
| 910 | case ARG_TYPED_CALL() | ||
| 911 | algorithm | ||
| 912 | ✗ | name := ComponentRef.toString(call.ref); | |
| 913 | ✗ | arg_str := | |
| 914 | stringDelimitList(list(Expression.toString(arg.value) for arg in call.positional_args), ", "); | ||
| 915 | ✗ | for arg in call.named_args loop | |
| 916 | ✗ | c := if arg_str == "" then "" else ", "; | |
| 917 | ✗ | arg_str := arg_str + c + Util.getOption(arg.name) + " = " + Expression.toString(arg.value); | |
| 918 | end for; | ||
| 919 | ✗ | then | |
| 920 | name + "(" + arg_str + ")"; | ||
| 921 | |||
| 922 | case UNTYPED_ARRAY_CONSTRUCTOR() | ||
| 923 | algorithm | ||
| 924 | ✗ | name := AbsynUtil.pathString(Function.nameConsiderBuiltin(NFBuiltinFuncs.ARRAY_FUNC)); | |
| 925 | ✗ | arg_str := Expression.toString(call.exp); | |
| 926 | ✗ | c := stringDelimitList(list(InstNode.name(Util.tuple21(iter)) + " in " + | |
| 927 | Expression.toString(Util.tuple22(iter)) for iter in call.iters), ", "); | ||
| 928 | ✗ | then | |
| 929 | "{" + arg_str + " for " + c + "}"; | ||
| 930 | |||
| 931 | case UNTYPED_REDUCTION() | ||
| 932 | algorithm | ||
| 933 | ✗ | name := ComponentRef.toString(call.ref); | |
| 934 | ✗ | arg_str := Expression.toString(call.exp); | |
| 935 | ✗ | c := stringDelimitList(list(InstNode.name(Util.tuple21(iter)) + " in " + | |
| 936 | Expression.toString(Util.tuple22(iter)) for iter in call.iters), ", "); | ||
| 937 | ✗ | then | |
| 938 | name + "(" + arg_str + " for " + c + ")"; | ||
| 939 | |||
| 940 | case TYPED_CALL() | ||
| 941 | algorithm | ||
| 942 | 8273 | name := AbsynUtil.pathString(Function.nameConsiderBuiltin(call.fn)); | |
| 943 |
4/4✓ Branch 0 taken 15883 times.
✓ Branch 1 taken 8273 times.
✓ Branch 2 taken 15883 times.
✓ Branch 3 taken 8273 times.
|
24156 | arg_str := stringDelimitList(list(Expression.toString(arg) for arg in call.arguments), ", "); |
| 944 | 8273 | then | |
| 945 | name + "(" + arg_str + ")"; | ||
| 946 | |||
| 947 | case TYPED_ARRAY_CONSTRUCTOR() | ||
| 948 | algorithm | ||
| 949 | 80 | name := AbsynUtil.pathString(Function.nameConsiderBuiltin(NFBuiltinFuncs.ARRAY_FUNC)); | |
| 950 | 80 | arg_str := Expression.toString(call.exp); | |
| 951 |
4/4✓ Branch 0 taken 84 times.
✓ Branch 1 taken 80 times.
✓ Branch 2 taken 84 times.
✓ Branch 3 taken 80 times.
|
164 | c := stringDelimitList(list(InstNode.name(Util.tuple21(iter)) + " in " + |
| 952 | Expression.toString(Util.tuple22(iter)) for iter in call.iters), ", "); | ||
| 953 | 80 | then | |
| 954 | "{" + arg_str + " for " + c + "}"; | ||
| 955 | |||
| 956 | case TYPED_REDUCTION() | ||
| 957 | algorithm | ||
| 958 | 37 | name := AbsynUtil.pathString(Function.nameConsiderBuiltin(call.fn)); | |
| 959 | 37 | arg_str := Expression.toString(call.exp); | |
| 960 |
4/4✓ Branch 0 taken 37 times.
✓ Branch 1 taken 37 times.
✓ Branch 2 taken 37 times.
✓ Branch 3 taken 37 times.
|
74 | c := stringDelimitList(list(InstNode.name(Util.tuple21(iter)) + " in " + |
| 961 | Expression.toString(Util.tuple22(iter)) for iter in call.iters), ", "); | ||
| 962 | 37 | then | |
| 963 | name + "(" + arg_str + " for " + c + ")"; | ||
| 964 | |||
| 965 | end match; | ||
| 966 | end toString; | ||
| 967 | |||
| 968 | function toFlatString | ||
| 969 | input NFCall call; | ||
| 970 | input BaseModelica.OutputFormat format; | ||
| 971 | output String str; | ||
| 972 | protected | ||
| 973 | String name, arg_str,c; | ||
| 974 | list<InstNode> iters; | ||
| 975 | algorithm | ||
| 976 | str := match call | ||
| 977 | case TYPED_CALL() | ||
| 978 | algorithm | ||
| 979 | 105 | name := AbsynUtil.pathString(Function.nameConsiderBuiltin(call.fn)); | |
| 980 | 105 | arg_str := toFlatStringArgs(call.arguments, name, format); | |
| 981 |
3/4✓ Branch 1 taken 75 times.
✓ Branch 2 taken 30 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 30 times.
|
240 | then |
| 982 | if Function.isBuiltin(call.fn) then | ||
| 983 | stringAppendList({name, "(", arg_str, ")"}) | ||
| 984 | elseif isExternalObjectConstructor(call) then | ||
| 985 | stringAppendList({Type.toFlatString(call.ty, format), "(", arg_str, ")"}) | ||
| 986 | else | ||
| 987 | stringAppendList({Util.makeQuotedIdentifier(name), "(", arg_str, ")"}); | ||
| 988 | |||
| 989 | case TYPED_ARRAY_CONSTRUCTOR() | ||
| 990 | algorithm | ||
| 991 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
|
1 | if isVectorized(call) then |
| 992 | // Vectorized calls contains iterators with illegal Modelica names | ||
| 993 | // (to avoid name conflicts), to make the flat output legal such | ||
| 994 | // calls are reverted to their original form here. | ||
| 995 | ✗ | str := Expression.toFlatString(devectorizeCall(call), format); | |
| 996 | else | ||
| 997 | 1 | name := AbsynUtil.pathString(Function.nameConsiderBuiltin(NFBuiltinFuncs.ARRAY_FUNC)); | |
| 998 | 1 | arg_str := Expression.toFlatString(call.exp, format); | |
| 999 |
4/4✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1 time.
|
2 | c := stringDelimitList(list(Util.makeQuotedIdentifier(InstNode.name(Util.tuple21(iter))) + " in " + |
| 1000 | Expression.toFlatString(Util.tuple22(iter), format) for iter in call.iters), ", "); | ||
| 1001 | 1 | str := stringAppendList({"{", arg_str, " for ", c, "}"}); | |
| 1002 | end if; | ||
| 1003 | then | ||
| 1004 | str; | ||
| 1005 | |||
| 1006 | case TYPED_REDUCTION() | ||
| 1007 | algorithm | ||
| 1008 | ✗ | name := AbsynUtil.pathString(Function.nameConsiderBuiltin(call.fn)); | |
| 1009 | ✗ | arg_str := Expression.toFlatString(call.exp, format); | |
| 1010 | ✗ | c := stringDelimitList(list(Util.makeQuotedIdentifier(InstNode.name(Util.tuple21(iter))) + " in " + | |
| 1011 | Expression.toFlatString(Util.tuple22(iter), format) for iter in call.iters), ", "); | ||
| 1012 | ✗ | then | |
| 1013 | if Function.isBuiltin(call.fn) then | ||
| 1014 | stringAppendList({name, "(", arg_str, " for ", c, ")"}) | ||
| 1015 | else | ||
| 1016 | stringAppendList({Util.makeQuotedIdentifier(name), "(", arg_str, " for ", c, ")"}); | ||
| 1017 | |||
| 1018 | end match; | ||
| 1019 | end toFlatString; | ||
| 1020 | |||
| 1021 | function toFlatStringArgs | ||
| 1022 | input list<Expression> args; | ||
| 1023 | input String fnName; | ||
| 1024 | input BaseModelica.OutputFormat format; | ||
| 1025 | output String argsString; | ||
| 1026 | protected | ||
| 1027 | Expression arg1, arg2; | ||
| 1028 | list<Expression> rest_args; | ||
| 1029 | algorithm | ||
| 1030 | argsString := match fnName | ||
| 1031 | case "String" | ||
| 1032 | then match args | ||
| 1033 | case {arg1, arg2} | ||
| 1034 | 2 | then Expression.toFlatString(arg1, format) + ", format = " + Expression.toFlatString(arg2, format); | |
| 1035 | |||
| 1036 | else | ||
| 1037 | algorithm | ||
| 1038 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | arg1 :: rest_args := args; |
| 1039 | 10 | argsString := Expression.toFlatString(arg1, format); | |
| 1040 | |||
| 1041 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 6 times.
|
10 | if listLength(rest_args) == 3 then |
| 1042 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | arg1 :: rest_args := rest_args; |
| 1043 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 3 times.
|
4 | if not Expression.isIntegerValue(arg1, 6) then |
| 1044 | 1 | argsString := argsString + ", significantDigits = " + Expression.toFlatString(arg1, format); | |
| 1045 | end if; | ||
| 1046 | end if; | ||
| 1047 | |||
| 1048 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | arg1 :: rest_args := rest_args; |
| 1049 |
2/2✓ Branch 1 taken 5 times.
✓ Branch 2 taken 5 times.
|
10 | if not Expression.isZero(arg1) then |
| 1050 | 5 | argsString := argsString + ", minimumLength = " + Expression.toFlatString(arg1, format); | |
| 1051 | end if; | ||
| 1052 | |||
| 1053 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | arg1 :: rest_args := rest_args; |
| 1054 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 7 times.
|
10 | if not Expression.isTrue(arg1) then |
| 1055 | 3 | argsString := argsString + ", leftJustified = " + Expression.toFlatString(arg1, format); | |
| 1056 | end if; | ||
| 1057 | then | ||
| 1058 | argsString; | ||
| 1059 | end match; | ||
| 1060 | |||
| 1061 |
4/4✓ Branch 0 taken 165 times.
✓ Branch 1 taken 93 times.
✓ Branch 2 taken 165 times.
✓ Branch 3 taken 93 times.
|
258 | else stringDelimitList(list(Expression.toFlatString(arg, format) for arg in args), ", "); |
| 1062 | end match; | ||
| 1063 | end toFlatStringArgs; | ||
| 1064 | |||
| 1065 | function typedString | ||
| 1066 | "Like toString, but prefixes each argument with its type as a comment." | ||
| 1067 | input NFCall call; | ||
| 1068 | output String str; | ||
| 1069 | protected | ||
| 1070 | String name, arg_str,c; | ||
| 1071 | algorithm | ||
| 1072 | str := match call | ||
| 1073 | case ARG_TYPED_CALL() | ||
| 1074 | algorithm | ||
| 1075 | 2 | name := ComponentRef.toString(call.ref); | |
| 1076 |
4/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
|
4 | arg_str := stringDelimitList(list("/*" + Type.toString(arg.ty) + "*/ " + |
| 1077 | Expression.toString(arg.value) for arg in call.positional_args), ", "); | ||
| 1078 | |||
| 1079 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | for arg in call.named_args loop |
| 1080 | ✗ | c := if arg_str == "" then "" else ", "; | |
| 1081 | ✗ | arg_str := arg_str + c + Util.getOption(arg.name) + " = /*" + | |
| 1082 | Type.toString(arg.ty) + "*/ " + Expression.toString(arg.value); | ||
| 1083 | end for; | ||
| 1084 | 2 | then | |
| 1085 | name + "(" + arg_str + ")"; | ||
| 1086 | |||
| 1087 | case TYPED_CALL() | ||
| 1088 | algorithm | ||
| 1089 | ✗ | name := AbsynUtil.pathString(Function.name(call.fn)); | |
| 1090 | ✗ | arg_str := stringDelimitList(list(Expression.toStringTyped(arg) for arg in call.arguments), ", "); | |
| 1091 | ✗ | then | |
| 1092 | name + "(" + arg_str + ")"; | ||
| 1093 | |||
| 1094 | ✗ | else toString(call); | |
| 1095 | end match; | ||
| 1096 | end typedString; | ||
| 1097 | |||
| 1098 | function toJSON | ||
| 1099 | input Call call; | ||
| 1100 | output JSON json = JSON.emptyListObject(); | ||
| 1101 | |||
| 1102 | function iterators_json | ||
| 1103 | input list<tuple<InstNode, Expression>> iters; | ||
| 1104 | output JSON json = JSON.emptyArray(listLength(iters)); | ||
| 1105 | protected | ||
| 1106 | JSON j; | ||
| 1107 | algorithm | ||
| 1108 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
|
2 | for i in iters loop |
| 1109 | 1 | j := JSON.emptyListObject(); | |
| 1110 | 1 | j := JSON.addPair("name", JSON.makeString(InstNode.name(Util.tuple21(i))), j); | |
| 1111 | 1 | j := JSON.addPair("range", Expression.toJSON(Util.tuple22(i)), j); | |
| 1112 | 1 | json := JSON.addElement(j, json); | |
| 1113 | end for; | ||
| 1114 | end iterators_json; | ||
| 1115 | protected | ||
| 1116 | Absyn.Path path; | ||
| 1117 | algorithm | ||
| 1118 | () := match call | ||
| 1119 | case TYPED_CALL() | ||
| 1120 | algorithm | ||
| 1121 | 4 | path := Function.nameConsiderBuiltin(call.fn); | |
| 1122 | 4 | json := JSON.addPair("$kind", JSON.makeString("call"), json); | |
| 1123 | 4 | json := JSON.addPair("name", JSON.makeString(AbsynUtil.pathString(path)), json); | |
| 1124 | |||
| 1125 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 3 times.
|
4 | if isNamed(call, "String") then |
| 1126 | 1 | json := toJSONStringArgs(call.arguments, json); | |
| 1127 | else | ||
| 1128 |
4/4✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 3 times.
|
9 | json := JSON.addPair("arguments", JSON.makeArray( |
| 1129 | list(Expression.toJSON(a) for a in call.arguments)), json); | ||
| 1130 | end if; | ||
| 1131 | then | ||
| 1132 | (); | ||
| 1133 | |||
| 1134 | case TYPED_ARRAY_CONSTRUCTOR() | ||
| 1135 | algorithm | ||
| 1136 | 1 | json := JSON.addPair("$kind", JSON.makeString("iterator_call"), json); | |
| 1137 | 1 | json := JSON.addPair("name", JSON.makeString("$array"), json); | |
| 1138 | 1 | json := JSON.addPair("exp", Expression.toJSON(call.exp), json); | |
| 1139 | 1 | json := JSON.addPair("iterators", iterators_json(call.iters), json); | |
| 1140 | then | ||
| 1141 | (); | ||
| 1142 | |||
| 1143 | case TYPED_REDUCTION() | ||
| 1144 | algorithm | ||
| 1145 | ✗ | path := Function.nameConsiderBuiltin(call.fn); | |
| 1146 | ✗ | json := JSON.addPair("$kind", JSON.makeString("iterator_call"), json); | |
| 1147 | ✗ | json := JSON.addPair("name", JSON.makeString(AbsynUtil.pathString(path)), json); | |
| 1148 | ✗ | json := JSON.addPair("exp", Expression.toJSON(call.exp), json); | |
| 1149 | ✗ | json := JSON.addPair("iterators", iterators_json(call.iters), json); | |
| 1150 | then | ||
| 1151 | (); | ||
| 1152 | |||
| 1153 | else | ||
| 1154 | algorithm | ||
| 1155 | ✗ | json := JSON.addPair("$kind", JSON.makeString("call"), json); | |
| 1156 | then | ||
| 1157 | (); | ||
| 1158 | |||
| 1159 | end match; | ||
| 1160 | end toJSON; | ||
| 1161 | |||
| 1162 | function toJSONStringArgs | ||
| 1163 | input list<Expression> args; | ||
| 1164 | input output JSON json; | ||
| 1165 | protected | ||
| 1166 | Integer arg_count; | ||
| 1167 | Expression value, arg; | ||
| 1168 | list<Expression> rest_args; | ||
| 1169 | list<JSON> json_args; | ||
| 1170 | |||
| 1171 | function make_arg | ||
| 1172 | input String name; | ||
| 1173 | input Expression value; | ||
| 1174 | output JSON json = JSON.emptyListObject(); | ||
| 1175 | algorithm | ||
| 1176 | 1 | json := JSON.addPair("$kind", JSON.makeString("named_arg"), json); | |
| 1177 | 1 | json := JSON.addPair(name, Expression.toJSON(value), json); | |
| 1178 | end make_arg; | ||
| 1179 | algorithm | ||
| 1180 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 | value :: rest_args := args; |
| 1181 | 1 | arg_count := listLength(rest_args); | |
| 1182 | 1 | json_args := {Expression.toJSON(value)}; | |
| 1183 | |||
| 1184 |
1/2✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
|
1 | if arg_count == 1 then |
| 1185 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
|
1 | arg :: _ := rest_args; |
| 1186 | 1 | json_args := make_arg("format", arg) :: json_args; | |
| 1187 | else | ||
| 1188 | ✗ | if arg_count == 3 then | |
| 1189 | ✗ | arg :: rest_args := rest_args; | |
| 1190 | ✗ | if not Expression.isIntegerValue(arg, 6) then | |
| 1191 | ✗ | json_args := make_arg("significantDigits", arg) :: json_args; | |
| 1192 | end if; | ||
| 1193 | end if; | ||
| 1194 | |||
| 1195 | ✗ | arg :: rest_args := rest_args; | |
| 1196 | ✗ | if not Expression.isZero(arg) then | |
| 1197 | ✗ | json_args := make_arg("minimumLength", arg) :: json_args; | |
| 1198 | end if; | ||
| 1199 | |||
| 1200 | ✗ | arg :: rest_args := rest_args; | |
| 1201 | ✗ | if not Expression.isTrue(arg) then | |
| 1202 | ✗ | json_args := make_arg("leftJustified", arg) :: json_args; | |
| 1203 | end if; | ||
| 1204 | end if; | ||
| 1205 | |||
| 1206 | 1 | json := JSON.addPair("arguments", JSON.makeList(listReverseInPlace(json_args)), json); | |
| 1207 | end toJSONStringArgs; | ||
| 1208 | |||
| 1209 | function toAbsyn | ||
| 1210 | input Call call; | ||
| 1211 | output Absyn.Exp absynCall; | ||
| 1212 | algorithm | ||
| 1213 | absynCall := match call | ||
| 1214 | local | ||
| 1215 | list<Absyn.Exp> pargs; | ||
| 1216 | list<Absyn.NamedArg> nargs; | ||
| 1217 | |||
| 1218 | case UNTYPED_CALL() | ||
| 1219 | algorithm | ||
| 1220 | ✗ | pargs := list(Expression.toAbsyn(arg) for arg in call.arguments); | |
| 1221 | ✗ | nargs := list(Absyn.NamedArg.NAMEDARG(Util.tuple21(arg), | |
| 1222 | Expression.toAbsyn(Util.tuple22(arg))) for arg in call.named_args); | ||
| 1223 | ✗ | then | |
| 1224 | AbsynUtil.makeCall(ComponentRef.toAbsyn(call.ref), pargs, nargs); | ||
| 1225 | |||
| 1226 | case ARG_TYPED_CALL() | ||
| 1227 | algorithm | ||
| 1228 | ✗ | pargs := list(Expression.toAbsyn(arg.value) for arg in call.positional_args); | |
| 1229 | ✗ | nargs := list(Absyn.NamedArg.NAMEDARG(Util.getOption(arg.name), | |
| 1230 | Expression.toAbsyn(arg.value)) for arg in call.named_args); | ||
| 1231 | ✗ | then | |
| 1232 | AbsynUtil.makeCall(ComponentRef.toAbsyn(call.ref), pargs, nargs); | ||
| 1233 | |||
| 1234 | case TYPED_CALL() | ||
| 1235 | algorithm | ||
| 1236 | ✗ | pargs := list(Expression.toAbsyn(arg) for arg in call.arguments); | |
| 1237 | ✗ | then | |
| 1238 | AbsynUtil.makeCall(AbsynUtil.pathToCref(Function.name(call.fn)), pargs); | ||
| 1239 | |||
| 1240 | case UNTYPED_ARRAY_CONSTRUCTOR() | ||
| 1241 | ✗ | then Absyn.Exp.CALL(Absyn.ComponentRef.CREF_IDENT("array", {}), toAbsynIterators(call.exp, call.iters), {}); | |
| 1242 | |||
| 1243 | case TYPED_ARRAY_CONSTRUCTOR() | ||
| 1244 | ✗ | then Absyn.Exp.CALL(Absyn.ComponentRef.CREF_IDENT("array", {}), toAbsynIterators(call.exp, call.iters), {}); | |
| 1245 | |||
| 1246 | case UNTYPED_REDUCTION() | ||
| 1247 | ✗ | then Absyn.Exp.CALL(ComponentRef.toAbsyn(call.ref), toAbsynIterators(call.exp, call.iters), {}); | |
| 1248 | |||
| 1249 | case TYPED_REDUCTION() | ||
| 1250 | ✗ | then Absyn.Exp.CALL(AbsynUtil.pathToCref(Function.name(call.fn)), toAbsynIterators(call.exp, call.iters), {}); | |
| 1251 | |||
| 1252 | else | ||
| 1253 | algorithm | ||
| 1254 | ✗ | Error.terminate(getInstanceName() + " got unknown call", sourceInfo()); | |
| 1255 | ✗ | then | |
| 1256 | fail(); | ||
| 1257 | end match; | ||
| 1258 | end toAbsyn; | ||
| 1259 | |||
| 1260 | function toAbsynIterators | ||
| 1261 | input Expression iterExp; | ||
| 1262 | input list<tuple<InstNode, Expression>> iters; | ||
| 1263 | output Absyn.FunctionArgs args; | ||
| 1264 | algorithm | ||
| 1265 | ✗ | args := Absyn.FunctionArgs.FOR_ITER_FARG( | |
| 1266 | Expression.toAbsyn(iterExp), | ||
| 1267 | Absyn.ReductionIterType.COMBINE(), | ||
| 1268 | list(Absyn.ForIterator.ITERATOR( | ||
| 1269 | InstNode.name(Util.tuple21(i)), | ||
| 1270 | NONE(), | ||
| 1271 | SOME(Expression.toAbsyn(Util.tuple22(i))) | ||
| 1272 | ) for i in iters)); | ||
| 1273 | end toAbsynIterators; | ||
| 1274 | |||
| 1275 | function toDAE | ||
| 1276 | input NFCall call; | ||
| 1277 | output DAE.Exp daeCall; | ||
| 1278 | algorithm | ||
| 1279 | // The code generation can't handle reductions/array constructors with | ||
| 1280 | // multiple iterators so we need to convert them to nested calls with one | ||
| 1281 | // iterator each. But the frontend can handle multiple iterators more | ||
| 1282 | // efficiently so we do it only just before passing them to the backend. | ||
| 1283 | 73055 | daeCall := toDAE_work(expandReduction(call)); | |
| 1284 | end toDAE; | ||
| 1285 | |||
| 1286 | function toDAE_work | ||
| 1287 | input NFCall call; | ||
| 1288 | output DAE.Exp daeCall; | ||
| 1289 | algorithm | ||
| 1290 | daeCall := match call | ||
| 1291 | local | ||
| 1292 | String fold_id, res_id; | ||
| 1293 | Option<Expression> fold_exp; | ||
| 1294 | |||
| 1295 | case TYPED_CALL() | ||
| 1296 |
4/4✓ Branch 0 taken 126258 times.
✓ Branch 1 taken 72457 times.
✓ Branch 2 taken 126258 times.
✓ Branch 3 taken 72457 times.
|
198715 | then DAE.CALL( |
| 1297 | Function.nameConsiderBuiltin(call.fn), | ||
| 1298 | list(Expression.toDAE(e) for e in call.arguments), | ||
| 1299 | NFCallAttributes.toDAE(call.attributes, call.ty)); | ||
| 1300 | |||
| 1301 | case TYPED_ARRAY_CONSTRUCTOR() | ||
| 1302 | algorithm | ||
| 1303 | 548 | fold_id := Util.getTempVariableIndex(); | |
| 1304 | 548 | res_id := Util.getTempVariableIndex(); | |
| 1305 |
4/4✓ Branch 5 taken 548 times.
✓ Branch 6 taken 548 times.
✓ Branch 7 taken 548 times.
✓ Branch 8 taken 548 times.
|
1096 | then |
| 1306 | DAE.REDUCTION( | ||
| 1307 | DAE.REDUCTIONINFO( | ||
| 1308 | Function.name(NFBuiltinFuncs.ARRAY_FUNC), | ||
| 1309 | Absyn.COMBINE(), | ||
| 1310 | Type.toDAE(call.ty), | ||
| 1311 | NONE(), | ||
| 1312 | fold_id, | ||
| 1313 | res_id, | ||
| 1314 | NONE()), | ||
| 1315 | Expression.toDAE(call.exp), | ||
| 1316 | list(iteratorToDAE(iter) for iter in call.iters)); | ||
| 1317 | |||
| 1318 | case TYPED_REDUCTION() | ||
| 1319 | algorithm | ||
| 1320 | 50 | (fold_exp, fold_id, res_id) := call.foldExp; | |
| 1321 |
4/4✓ Branch 7 taken 50 times.
✓ Branch 8 taken 50 times.
✓ Branch 9 taken 50 times.
✓ Branch 10 taken 50 times.
|
100 | then |
| 1322 | DAE.REDUCTION( | ||
| 1323 | DAE.REDUCTIONINFO( | ||
| 1324 | Function.name(call.fn), | ||
| 1325 | Absyn.COMBINE(), | ||
| 1326 | Type.toDAE(call.ty), | ||
| 1327 | Util.applyOption(call.defaultExp, Expression.toDAEValue), | ||
| 1328 | fold_id, | ||
| 1329 | res_id, | ||
| 1330 | Util.applyOption(fold_exp, function Expression.toDAE(allowEmpty = false))), | ||
| 1331 | Expression.toDAE(call.exp), | ||
| 1332 | list(iteratorToDAE(iter) for iter in call.iters)); | ||
| 1333 | |||
| 1334 | else | ||
| 1335 | algorithm | ||
| 1336 | ✗ | Error.terminate(getInstanceName() + " got untyped call", sourceInfo()); | |
| 1337 | ✗ | then | |
| 1338 | fail(); | ||
| 1339 | end match; | ||
| 1340 | end toDAE_work; | ||
| 1341 | |||
| 1342 | function expandReduction | ||
| 1343 | "Turns reductions/array constructors with multiple iterators into nested | ||
| 1344 | reductions/array constructors." | ||
| 1345 | input Call call; | ||
| 1346 | output Call outCall; | ||
| 1347 | algorithm | ||
| 1348 | outCall := match call | ||
| 1349 | local | ||
| 1350 | list<tuple<InstNode, Expression>> iters; | ||
| 1351 | tuple<InstNode, Expression> iter; | ||
| 1352 | Type ty; | ||
| 1353 | |||
| 1354 | case TYPED_ARRAY_CONSTRUCTOR(iters = iters) | ||
| 1355 | guard listLength(iters) > 1 | ||
| 1356 | algorithm | ||
| 1357 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | iter :: iters := iters; |
| 1358 | 6 | ty := Type.liftArrayLeftList(Expression.typeOf(call.exp), | |
| 1359 | Type.arrayDims(Expression.typeOf(Util.tuple22(iter)))); | ||
| 1360 | 6 | outCall := TYPED_ARRAY_CONSTRUCTOR(ty, call.var, call.purity, call.exp, {iter}); | |
| 1361 | |||
| 1362 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 6 times.
|
13 | for i in iters loop |
| 1363 | 7 | ty := Type.liftArrayLeftList(ty, Type.arrayDims(Expression.typeOf(Util.tuple22(i)))); | |
| 1364 | 14 | outCall := TYPED_ARRAY_CONSTRUCTOR(ty, call.var, call.purity, Expression.CALL(outCall), {i}); | |
| 1365 | end for; | ||
| 1366 | then | ||
| 1367 | outCall; | ||
| 1368 | |||
| 1369 | case TYPED_REDUCTION(iters = iters) | ||
| 1370 | guard listLength(iters) > 1 | ||
| 1371 | algorithm | ||
| 1372 | ✗ | iter :: iters := iters; | |
| 1373 | ✗ | outCall := makeTypedReduction(call.fn, call.ty, call.var, call.purity, | |
| 1374 | call.exp, {iter}, Absyn.dummyInfo); | ||
| 1375 | |||
| 1376 | ✗ | for i in iters loop | |
| 1377 | ✗ | outCall := makeTypedReduction(call.fn, call.ty, call.var, call.purity, | |
| 1378 | Expression.CALL(outCall), {i}, Absyn.dummyInfo); | ||
| 1379 | end for; | ||
| 1380 | then | ||
| 1381 | outCall; | ||
| 1382 | |||
| 1383 | else call; | ||
| 1384 | end match; | ||
| 1385 | end expandReduction; | ||
| 1386 | |||
| 1387 | function isVectorizeable | ||
| 1388 | input NFCall call; | ||
| 1389 | output Boolean isVect; | ||
| 1390 | algorithm | ||
| 1391 | isVect := match call | ||
| 1392 | local | ||
| 1393 | String name; | ||
| 1394 | |||
| 1395 | case TYPED_CALL(fn = Function.FUNCTION(path = Absyn.IDENT(name = name))) | ||
| 1396 | then match name | ||
| 1397 | case "der" then false; | ||
| 1398 | case "pre" then false; | ||
| 1399 | case "previous" then false; | ||
| 1400 | else true; | ||
| 1401 | end match; | ||
| 1402 | |||
| 1403 | else true; | ||
| 1404 | end match; | ||
| 1405 | end isVectorizeable; | ||
| 1406 | |||
| 1407 | function retype | ||
| 1408 | input output NFCall call; | ||
| 1409 | algorithm | ||
| 1410 | () := match call | ||
| 1411 | local | ||
| 1412 | Type ty; | ||
| 1413 | list<Dimension> dims; | ||
| 1414 | |||
| 1415 | case TYPED_ARRAY_CONSTRUCTOR() | ||
| 1416 | algorithm | ||
| 1417 | dims := {}; | ||
| 1418 | |||
| 1419 |
2/2✓ Branch 1 taken 19 times.
✓ Branch 2 taken 19 times.
|
38 | for i in listReverse(call.iters) loop |
| 1420 | 19 | dims := listAppend(Type.arrayDims(Expression.typeOf(Util.tuple22(i))), dims); | |
| 1421 | end for; | ||
| 1422 | |||
| 1423 | 19 | call.ty := Type.liftArrayLeftList(Type.arrayElementType(call.ty), dims); | |
| 1424 | then | ||
| 1425 | (); | ||
| 1426 | |||
| 1427 | else (); | ||
| 1428 | end match; | ||
| 1429 | end retype; | ||
| 1430 | |||
| 1431 | function typeCast | ||
| 1432 | input output Expression callExp; | ||
| 1433 | input Type ty; | ||
| 1434 | protected | ||
| 1435 | NFCall call; | ||
| 1436 | Type cast_ty; | ||
| 1437 | algorithm | ||
| 1438 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11492 times.
|
11492 | Expression.CALL(call = call) := callExp; |
| 1439 | |||
| 1440 | callExp := match call | ||
| 1441 | case TYPED_CALL() guard Function.isBuiltin(call.fn) | ||
| 1442 | algorithm | ||
| 1443 | 11415 | cast_ty := Type.setArrayElementType(call.ty, ty); | |
| 1444 | then | ||
| 1445 | match AbsynUtil.pathFirstIdent(Function.name(call.fn)) | ||
| 1446 | // For 'fill' we can type cast the first argument rather than the | ||
| 1447 | // whole array that 'fill' constructs. | ||
| 1448 | case "fill" | ||
| 1449 | algorithm | ||
| 1450 | 19204 | call.arguments := Expression.typeCast(listHead(call.arguments), ty) :: | |
| 1451 | listRest(call.arguments); | ||
| 1452 | 9602 | call.ty := cast_ty; | |
| 1453 | 9602 | then | |
| 1454 | Expression.CALL(call); | ||
| 1455 | |||
| 1456 | // For diagonal we can type cast the argument rather than the | ||
| 1457 | // matrix that diagonal constructs. | ||
| 1458 | case "diagonal" | ||
| 1459 | algorithm | ||
| 1460 | 4 | call.arguments := {Expression.typeCast(listHead(call.arguments), ty)}; | |
| 1461 | 2 | call.ty := cast_ty; | |
| 1462 | 2 | then | |
| 1463 | Expression.CALL(call); | ||
| 1464 | |||
| 1465 | // For DynamicSelect we type cast both of the arguments. | ||
| 1466 | case "DynamicSelect" | ||
| 1467 | algorithm | ||
| 1468 |
4/4✓ Branch 0 taken 8 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 4 times.
|
16 | call.arguments := list(Expression.typeCast(arg, ty) for arg in call.arguments); |
| 1469 | 4 | then | |
| 1470 | Expression.CALL(call); | ||
| 1471 | |||
| 1472 | 1807 | else Expression.CAST(cast_ty, callExp); | |
| 1473 | end match; | ||
| 1474 | |||
| 1475 | 77 | else Expression.typeCastGeneric(callExp, ty); | |
| 1476 | end match; | ||
| 1477 | end typeCast; | ||
| 1478 | |||
| 1479 | function containsExp | ||
| 1480 | input Call call; | ||
| 1481 | input ContainsPred func; | ||
| 1482 | output Boolean res; | ||
| 1483 | |||
| 1484 | partial function ContainsPred | ||
| 1485 | input Expression exp; | ||
| 1486 | output Boolean res; | ||
| 1487 | end ContainsPred; | ||
| 1488 | algorithm | ||
| 1489 | res := match call | ||
| 1490 | local | ||
| 1491 | Expression e; | ||
| 1492 | |||
| 1493 | case UNTYPED_CALL() | ||
| 1494 | algorithm | ||
| 1495 | ✗ | res := Expression.listContains(call.arguments, func); | |
| 1496 | |||
| 1497 | ✗ | if not res then | |
| 1498 | ✗ | for arg in call.named_args loop | |
| 1499 | ✗ | (_, e) := arg; | |
| 1500 | |||
| 1501 | ✗ | if Expression.contains(e, func) then | |
| 1502 | res := true; | ||
| 1503 | break; | ||
| 1504 | end if; | ||
| 1505 | end for; | ||
| 1506 | end if; | ||
| 1507 | then | ||
| 1508 | res; | ||
| 1509 | |||
| 1510 | case ARG_TYPED_CALL() | ||
| 1511 | algorithm | ||
| 1512 | ✗ | for arg in call.positional_args loop | |
| 1513 | ✗ | if Expression.contains(arg.value, func) then | |
| 1514 | res := true; | ||
| 1515 | ✗ | return; | |
| 1516 | end if; | ||
| 1517 | end for; | ||
| 1518 | |||
| 1519 | ✗ | for arg in call.named_args loop | |
| 1520 | ✗ | if Expression.contains(arg.value, func) then | |
| 1521 | res := true; | ||
| 1522 | ✗ | return; | |
| 1523 | end if; | ||
| 1524 | end for; | ||
| 1525 | then | ||
| 1526 | false; | ||
| 1527 | |||
| 1528 | 61071 | case TYPED_CALL() then Expression.listContains(call.arguments, func); | |
| 1529 | case UNTYPED_ARRAY_CONSTRUCTOR() | ||
| 1530 | ✗ | then Expression.contains(call.exp, func) or itersContainExp(call.iters, func); | |
| 1531 | case TYPED_ARRAY_CONSTRUCTOR() | ||
| 1532 |
3/4✓ Branch 1 taken 283 times.
✓ Branch 2 taken 7 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 283 times.
|
290 | then Expression.contains(call.exp, func) or itersContainExp(call.iters, func); |
| 1533 | case UNTYPED_REDUCTION() | ||
| 1534 | ✗ | then Expression.contains(call.exp, func) or itersContainExp(call.iters, func); | |
| 1535 | case TYPED_REDUCTION() | ||
| 1536 |
2/4✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 13 times.
|
13 | then Expression.contains(call.exp, func) or itersContainExp(call.iters, func); |
| 1537 | end match; | ||
| 1538 | end containsExp; | ||
| 1539 | |||
| 1540 | function itersContainExp | ||
| 1541 | "An iterator range is a subexpression too: `sum(x[k] for k in i:n)` uses `i`." | ||
| 1542 | input list<tuple<InstNode, Expression>> iters; | ||
| 1543 | input ContainsPred func; | ||
| 1544 | output Boolean res = false; | ||
| 1545 | |||
| 1546 | partial function ContainsPred | ||
| 1547 | input Expression exp; | ||
| 1548 | output Boolean res; | ||
| 1549 | end ContainsPred; | ||
| 1550 | algorithm | ||
| 1551 |
2/2✓ Branch 0 taken 296 times.
✓ Branch 1 taken 296 times.
|
592 | for iter in iters loop |
| 1552 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 296 times.
|
296 | if Expression.contains(Util.tuple22(iter), func) then |
| 1553 | res := true; | ||
| 1554 | ✗ | return; | |
| 1555 | end if; | ||
| 1556 | end for; | ||
| 1557 | end itersContainExp; | ||
| 1558 | |||
| 1559 | function containsExpShallow | ||
| 1560 | input Call call; | ||
| 1561 | input ContainsPred func; | ||
| 1562 | output Boolean res; | ||
| 1563 | |||
| 1564 | partial function ContainsPred | ||
| 1565 | input Expression exp; | ||
| 1566 | output Boolean res; | ||
| 1567 | end ContainsPred; | ||
| 1568 | algorithm | ||
| 1569 | res := match call | ||
| 1570 | local | ||
| 1571 | Expression e; | ||
| 1572 | |||
| 1573 | case UNTYPED_CALL() | ||
| 1574 | algorithm | ||
| 1575 | 1496 | res := List.any(call.arguments, func); | |
| 1576 | |||
| 1577 |
2/2✓ Branch 0 taken 1343 times.
✓ Branch 1 taken 153 times.
|
1496 | if not res then |
| 1578 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1343 times.
|
1345 | for arg in call.named_args loop |
| 1579 | 2 | (_, e) := arg; | |
| 1580 | |||
| 1581 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | if func(e) then |
| 1582 | res := true; | ||
| 1583 | break; | ||
| 1584 | end if; | ||
| 1585 | end for; | ||
| 1586 | end if; | ||
| 1587 | then | ||
| 1588 | res; | ||
| 1589 | |||
| 1590 | case ARG_TYPED_CALL() | ||
| 1591 | algorithm | ||
| 1592 | ✗ | for arg in call.positional_args loop | |
| 1593 | ✗ | if func(arg.value) then | |
| 1594 | res := true; | ||
| 1595 | ✗ | return; | |
| 1596 | end if; | ||
| 1597 | end for; | ||
| 1598 | |||
| 1599 | ✗ | for arg in call.named_args loop | |
| 1600 | ✗ | if func(arg.value) then | |
| 1601 | res := true; | ||
| 1602 | ✗ | return; | |
| 1603 | end if; | ||
| 1604 | end for; | ||
| 1605 | then | ||
| 1606 | false; | ||
| 1607 | |||
| 1608 | 131502 | case TYPED_CALL() then List.any(call.arguments, func); | |
| 1609 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | case UNTYPED_ARRAY_CONSTRUCTOR() then func(call.exp); |
| 1610 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 621 times.
|
624 | case TYPED_ARRAY_CONSTRUCTOR() then func(call.exp); |
| 1611 | ✗ | case UNTYPED_REDUCTION() then func(call.exp); | |
| 1612 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
|
61 | case TYPED_REDUCTION() then func(call.exp); |
| 1613 | end match; | ||
| 1614 | end containsExpShallow; | ||
| 1615 | |||
| 1616 | function applyExp | ||
| 1617 | input Call call; | ||
| 1618 | input ApplyFunc func; | ||
| 1619 | |||
| 1620 | partial function ApplyFunc | ||
| 1621 | input Expression exp; | ||
| 1622 | end ApplyFunc; | ||
| 1623 | algorithm | ||
| 1624 | () := match call | ||
| 1625 | local | ||
| 1626 | Expression e; | ||
| 1627 | |||
| 1628 | case UNTYPED_CALL() | ||
| 1629 | algorithm | ||
| 1630 | 16299 | Expression.applyList(call.arguments, func); | |
| 1631 | |||
| 1632 |
2/2✓ Branch 0 taken 801 times.
✓ Branch 1 taken 16299 times.
|
17100 | for arg in call.named_args loop |
| 1633 | 801 | (_, e) := arg; | |
| 1634 | 801 | Expression.apply(e, func); | |
| 1635 | end for; | ||
| 1636 | then | ||
| 1637 | (); | ||
| 1638 | |||
| 1639 | case ARG_TYPED_CALL() | ||
| 1640 | algorithm | ||
| 1641 | ✗ | for arg in call.positional_args loop | |
| 1642 | ✗ | Expression.apply(arg.value, func); | |
| 1643 | end for; | ||
| 1644 | |||
| 1645 | ✗ | for arg in call.named_args loop | |
| 1646 | ✗ | Expression.apply(arg.value, func); | |
| 1647 | end for; | ||
| 1648 | then | ||
| 1649 | (); | ||
| 1650 | |||
| 1651 | case TYPED_CALL() | ||
| 1652 | algorithm | ||
| 1653 | 197790 | Expression.applyList(call.arguments, func); | |
| 1654 | then | ||
| 1655 | (); | ||
| 1656 | |||
| 1657 | case UNTYPED_ARRAY_CONSTRUCTOR() | ||
| 1658 | algorithm | ||
| 1659 | 896 | Expression.apply(call.exp, func); | |
| 1660 | |||
| 1661 |
2/2✓ Branch 0 taken 896 times.
✓ Branch 1 taken 896 times.
|
1792 | for i in call.iters loop |
| 1662 | 896 | Expression.apply(Util.tuple22(i), func); | |
| 1663 | end for; | ||
| 1664 | then | ||
| 1665 | (); | ||
| 1666 | |||
| 1667 | case TYPED_ARRAY_CONSTRUCTOR() | ||
| 1668 | algorithm | ||
| 1669 | 3842 | Expression.apply(call.exp, func); | |
| 1670 | |||
| 1671 |
2/2✓ Branch 0 taken 3952 times.
✓ Branch 1 taken 3842 times.
|
7794 | for i in call.iters loop |
| 1672 | 3952 | Expression.apply(Util.tuple22(i), func); | |
| 1673 | end for; | ||
| 1674 | then | ||
| 1675 | (); | ||
| 1676 | |||
| 1677 | case UNTYPED_REDUCTION() | ||
| 1678 | algorithm | ||
| 1679 | 28 | Expression.apply(call.exp, func); | |
| 1680 | |||
| 1681 |
2/2✓ Branch 0 taken 29 times.
✓ Branch 1 taken 28 times.
|
57 | for i in call.iters loop |
| 1682 | 29 | Expression.apply(Util.tuple22(i), func); | |
| 1683 | end for; | ||
| 1684 | then | ||
| 1685 | (); | ||
| 1686 | |||
| 1687 | case TYPED_REDUCTION() | ||
| 1688 | algorithm | ||
| 1689 | 71 | Expression.apply(call.exp, func); | |
| 1690 | |||
| 1691 |
2/2✓ Branch 0 taken 72 times.
✓ Branch 1 taken 71 times.
|
143 | for i in call.iters loop |
| 1692 | 72 | Expression.apply(Util.tuple22(i), func); | |
| 1693 | end for; | ||
| 1694 | |||
| 1695 | 71 | Expression.applyOpt(call.defaultExp, func); | |
| 1696 | 71 | Expression.applyOpt(Util.tuple31(call.foldExp), func); | |
| 1697 | then | ||
| 1698 | (); | ||
| 1699 | end match; | ||
| 1700 | end applyExp; | ||
| 1701 | |||
| 1702 | function applyExpShallow | ||
| 1703 | input Call call; | ||
| 1704 | input ApplyFunc func; | ||
| 1705 | |||
| 1706 | partial function ApplyFunc | ||
| 1707 | input Expression exp; | ||
| 1708 | end ApplyFunc; | ||
| 1709 | algorithm | ||
| 1710 | () := match call | ||
| 1711 | local | ||
| 1712 | Expression e; | ||
| 1713 | |||
| 1714 | case UNTYPED_CALL() | ||
| 1715 | algorithm | ||
| 1716 | 1797 | Expression.applyListShallow(call.arguments, func); | |
| 1717 | |||
| 1718 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1797 times.
|
1801 | for arg in call.named_args loop |
| 1719 | 4 | (_, e) := arg; | |
| 1720 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | func(e); |
| 1721 | end for; | ||
| 1722 | then | ||
| 1723 | (); | ||
| 1724 | |||
| 1725 | case ARG_TYPED_CALL() | ||
| 1726 | algorithm | ||
| 1727 | ✗ | for arg in call.positional_args loop | |
| 1728 | ✗ | func(arg.value); | |
| 1729 | end for; | ||
| 1730 | |||
| 1731 | ✗ | for arg in call.named_args loop | |
| 1732 | ✗ | func(arg.value); | |
| 1733 | end for; | ||
| 1734 | then | ||
| 1735 | (); | ||
| 1736 | |||
| 1737 | case TYPED_CALL() | ||
| 1738 | algorithm | ||
| 1739 | 152 | Expression.applyListShallow(call.arguments, func); | |
| 1740 | then | ||
| 1741 | (); | ||
| 1742 | |||
| 1743 | case UNTYPED_ARRAY_CONSTRUCTOR() | ||
| 1744 | algorithm | ||
| 1745 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | func(call.exp); |
| 1746 | |||
| 1747 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
|
20 | for i in call.iters loop |
| 1748 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | func(Util.tuple22(i)); |
| 1749 | end for; | ||
| 1750 | then | ||
| 1751 | (); | ||
| 1752 | |||
| 1753 | case TYPED_ARRAY_CONSTRUCTOR() | ||
| 1754 | algorithm | ||
| 1755 | ✗ | func(call.exp); | |
| 1756 | |||
| 1757 | ✗ | for i in call.iters loop | |
| 1758 | ✗ | func(Util.tuple22(i)); | |
| 1759 | end for; | ||
| 1760 | then | ||
| 1761 | (); | ||
| 1762 | |||
| 1763 | case UNTYPED_REDUCTION() | ||
| 1764 | algorithm | ||
| 1765 | ✗ | func(call.exp); | |
| 1766 | |||
| 1767 | ✗ | for i in call.iters loop | |
| 1768 | ✗ | func(Util.tuple22(i)); | |
| 1769 | end for; | ||
| 1770 | then | ||
| 1771 | (); | ||
| 1772 | |||
| 1773 | case TYPED_REDUCTION() | ||
| 1774 | algorithm | ||
| 1775 | ✗ | func(call.exp); | |
| 1776 | |||
| 1777 | ✗ | for i in call.iters loop | |
| 1778 | ✗ | func(Util.tuple22(i)); | |
| 1779 | end for; | ||
| 1780 | |||
| 1781 | ✗ | Expression.applyShallowOpt(call.defaultExp, func); | |
| 1782 | ✗ | Expression.applyShallowOpt(Util.tuple31(call.foldExp), func); | |
| 1783 | then | ||
| 1784 | (); | ||
| 1785 | end match; | ||
| 1786 | end applyExpShallow; | ||
| 1787 | |||
| 1788 | function foldExp<ArgT> | ||
| 1789 | input Call call; | ||
| 1790 | input FoldFunc func; | ||
| 1791 | input output ArgT foldArg; | ||
| 1792 | |||
| 1793 | partial function FoldFunc | ||
| 1794 | input Expression exp; | ||
| 1795 | input output ArgT arg; | ||
| 1796 | end FoldFunc; | ||
| 1797 | algorithm | ||
| 1798 | () := match call | ||
| 1799 | local | ||
| 1800 | Expression e; | ||
| 1801 | |||
| 1802 | case UNTYPED_CALL() | ||
| 1803 | algorithm | ||
| 1804 | 2 | foldArg := Expression.foldList(call.arguments, func, foldArg); | |
| 1805 | |||
| 1806 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | for arg in call.named_args loop |
| 1807 | ✗ | (_, e) := arg; | |
| 1808 | ✗ | foldArg := Expression.fold(e, func, foldArg); | |
| 1809 | end for; | ||
| 1810 | then | ||
| 1811 | (); | ||
| 1812 | |||
| 1813 | case ARG_TYPED_CALL() | ||
| 1814 | algorithm | ||
| 1815 | ✗ | for arg in call.positional_args loop | |
| 1816 | ✗ | foldArg := Expression.fold(arg.value, func, foldArg); | |
| 1817 | end for; | ||
| 1818 | |||
| 1819 | ✗ | for arg in call.named_args loop | |
| 1820 | ✗ | foldArg := Expression.fold(arg.value, func, foldArg); | |
| 1821 | end for; | ||
| 1822 | then | ||
| 1823 | (); | ||
| 1824 | |||
| 1825 | case TYPED_CALL() | ||
| 1826 | algorithm | ||
| 1827 | 148509 | foldArg := Expression.foldList(call.arguments, func, foldArg); | |
| 1828 | then | ||
| 1829 | (); | ||
| 1830 | |||
| 1831 | case UNTYPED_ARRAY_CONSTRUCTOR() | ||
| 1832 | algorithm | ||
| 1833 | 2 | foldArg := Expression.fold(call.exp, func, foldArg); | |
| 1834 | |||
| 1835 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
|
4 | for i in call.iters loop |
| 1836 | 2 | foldArg := Expression.fold(Util.tuple22(i), func, foldArg); | |
| 1837 | end for; | ||
| 1838 | then | ||
| 1839 | (); | ||
| 1840 | |||
| 1841 | case TYPED_ARRAY_CONSTRUCTOR() | ||
| 1842 | algorithm | ||
| 1843 | 2150 | foldArg := Expression.fold(call.exp, func, foldArg); | |
| 1844 | |||
| 1845 |
2/2✓ Branch 0 taken 2170 times.
✓ Branch 1 taken 2150 times.
|
4320 | for i in call.iters loop |
| 1846 | 2170 | foldArg := Expression.fold(Util.tuple22(i), func, foldArg); | |
| 1847 | end for; | ||
| 1848 | then | ||
| 1849 | (); | ||
| 1850 | |||
| 1851 | case UNTYPED_REDUCTION() | ||
| 1852 | algorithm | ||
| 1853 | ✗ | foldArg := Expression.fold(call.exp, func, foldArg); | |
| 1854 | |||
| 1855 | ✗ | for i in call.iters loop | |
| 1856 | ✗ | foldArg := Expression.fold(Util.tuple22(i), func, foldArg); | |
| 1857 | end for; | ||
| 1858 | then | ||
| 1859 | (); | ||
| 1860 | |||
| 1861 | case TYPED_REDUCTION() | ||
| 1862 | algorithm | ||
| 1863 | 91 | foldArg := Expression.fold(call.exp, func, foldArg); | |
| 1864 | |||
| 1865 |
2/2✓ Branch 0 taken 91 times.
✓ Branch 1 taken 91 times.
|
182 | for i in call.iters loop |
| 1866 | 91 | foldArg := Expression.fold(Util.tuple22(i), func, foldArg); | |
| 1867 | end for; | ||
| 1868 | |||
| 1869 | 91 | foldArg := Expression.foldOpt(call.defaultExp, func, foldArg); | |
| 1870 | 91 | foldArg := Expression.foldOpt(Util.tuple31(call.foldExp), func, foldArg); | |
| 1871 | then | ||
| 1872 | (); | ||
| 1873 | end match; | ||
| 1874 | end foldExp; | ||
| 1875 | |||
| 1876 | function mapExp | ||
| 1877 | input Call call; | ||
| 1878 | input MapFunc func; | ||
| 1879 | output Call outCall; | ||
| 1880 | |||
| 1881 | partial function MapFunc | ||
| 1882 | input output Expression e; | ||
| 1883 | end MapFunc; | ||
| 1884 | algorithm | ||
| 1885 | outCall := match call | ||
| 1886 | local | ||
| 1887 | list<Expression> args; | ||
| 1888 | list<NamedArg> nargs; | ||
| 1889 | list<TypedArg> targs, tnargs; | ||
| 1890 | String s; | ||
| 1891 | Expression e; | ||
| 1892 | list<tuple<InstNode, Expression>> iters; | ||
| 1893 | Option<Expression> default_exp; | ||
| 1894 | tuple<Option<Expression>, String, String> fold_exp; | ||
| 1895 | |||
| 1896 | case UNTYPED_CALL() | ||
| 1897 | algorithm | ||
| 1898 |
4/4✓ Branch 0 taken 373 times.
✓ Branch 1 taken 544 times.
✓ Branch 2 taken 373 times.
✓ Branch 3 taken 544 times.
|
917 | args := list(Expression.map(arg, func) for arg in call.arguments); |
| 1899 | nargs := {}; | ||
| 1900 | |||
| 1901 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 544 times.
|
544 | for arg in call.named_args loop |
| 1902 | ✗ | (s, e) := arg; | |
| 1903 | ✗ | e := Expression.map(e, func); | |
| 1904 | ✗ | nargs := (s, e) :: nargs; | |
| 1905 | end for; | ||
| 1906 | 544 | then | |
| 1907 | UNTYPED_CALL(call.ref, args, listReverse(nargs), call.call_scope); | ||
| 1908 | |||
| 1909 | case ARG_TYPED_CALL() | ||
| 1910 | algorithm | ||
| 1911 | targs := {}; | ||
| 1912 | tnargs := {}; | ||
| 1913 | |||
| 1914 | ✗ | for arg in call.positional_args loop | |
| 1915 | ✗ | arg.value := Expression.map(arg.value, func); | |
| 1916 | targs := arg :: targs; | ||
| 1917 | end for; | ||
| 1918 | |||
| 1919 | ✗ | for arg in call.named_args loop | |
| 1920 | ✗ | arg.value := Expression.map(arg.value, func); | |
| 1921 | tnargs := arg :: tnargs; | ||
| 1922 | end for; | ||
| 1923 | ✗ | then | |
| 1924 | ARG_TYPED_CALL(call.ref, listReverse(targs), listReverse(tnargs), call.call_scope); | ||
| 1925 | |||
| 1926 | case TYPED_CALL() | ||
| 1927 | algorithm | ||
| 1928 |
4/4✓ Branch 0 taken 1301551 times.
✓ Branch 1 taken 710361 times.
✓ Branch 2 taken 1301551 times.
✓ Branch 3 taken 710361 times.
|
2011912 | args := list(Expression.map(arg, func) for arg in call.arguments); |
| 1929 | 710361 | then | |
| 1930 | TYPED_CALL(call.fn, call.ty, call.var, call.purity, args, call.attributes); | ||
| 1931 | |||
| 1932 | case UNTYPED_ARRAY_CONSTRUCTOR() | ||
| 1933 | algorithm | ||
| 1934 | 1 | e := Expression.map(call.exp, func); | |
| 1935 | 1 | iters := mapIteratorsExp(call.iters, func); | |
| 1936 | 1 | then | |
| 1937 | UNTYPED_ARRAY_CONSTRUCTOR(e, iters); | ||
| 1938 | |||
| 1939 | case TYPED_ARRAY_CONSTRUCTOR() | ||
| 1940 | algorithm | ||
| 1941 | 9159 | e := Expression.map(call.exp, func); | |
| 1942 | 9159 | iters := mapIteratorsExp(call.iters, func); | |
| 1943 | 9159 | then | |
| 1944 | TYPED_ARRAY_CONSTRUCTOR(call.ty, call.var, call.purity, e, iters); | ||
| 1945 | |||
| 1946 | case UNTYPED_REDUCTION() | ||
| 1947 | algorithm | ||
| 1948 | ✗ | e := Expression.map(call.exp, func); | |
| 1949 | ✗ | iters := mapIteratorsExp(call.iters, func); | |
| 1950 | ✗ | then | |
| 1951 | UNTYPED_REDUCTION(call.ref, e, iters); | ||
| 1952 | |||
| 1953 | case TYPED_REDUCTION() | ||
| 1954 | algorithm | ||
| 1955 | 438 | e := Expression.map(call.exp, func); | |
| 1956 | 438 | iters := mapIteratorsExp(call.iters, func); | |
| 1957 | 438 | default_exp := Util.applyOption(call.defaultExp, function Expression.map(func = func)); | |
| 1958 | 438 | fold_exp := Util.applyTuple31(call.foldExp, function Expression.mapOpt(func = func)); | |
| 1959 | 438 | then | |
| 1960 | TYPED_REDUCTION(call.fn, call.ty, call.var, call.purity, e, iters, default_exp, fold_exp); | ||
| 1961 | |||
| 1962 | end match; | ||
| 1963 | end mapExp; | ||
| 1964 | |||
| 1965 | function mapIteratorsExp | ||
| 1966 | input list<tuple<InstNode, Expression>> iters; | ||
| 1967 | input MapFunc func; | ||
| 1968 | output list<tuple<InstNode, Expression>> outIters = {}; | ||
| 1969 | |||
| 1970 | partial function MapFunc | ||
| 1971 | input output Expression e; | ||
| 1972 | end MapFunc; | ||
| 1973 | protected | ||
| 1974 | InstNode node; | ||
| 1975 | Expression exp, new_exp; | ||
| 1976 | algorithm | ||
| 1977 |
2/2✓ Branch 0 taken 9971 times.
✓ Branch 1 taken 9598 times.
|
19569 | for i in iters loop |
| 1978 | 9971 | (node, exp) := i; | |
| 1979 | 9971 | new_exp := Expression.map(exp, func); | |
| 1980 |
2/2✓ Branch 0 taken 3101 times.
✓ Branch 1 taken 6870 times.
|
9971 | outIters := (if referenceEq(new_exp, exp) then i else (node, new_exp)) :: outIters; |
| 1981 | end for; | ||
| 1982 | |||
| 1983 | 9598 | outIters := listReverseInPlace(outIters); | |
| 1984 | end mapIteratorsExp; | ||
| 1985 | |||
| 1986 | function mapExpShallow | ||
| 1987 | input Call call; | ||
| 1988 | input MapFunc func; | ||
| 1989 | output Call outCall; | ||
| 1990 | |||
| 1991 | partial function MapFunc | ||
| 1992 | input output Expression e; | ||
| 1993 | end MapFunc; | ||
| 1994 | algorithm | ||
| 1995 | outCall := match call | ||
| 1996 | local | ||
| 1997 | list<Expression> args; | ||
| 1998 | list<NamedArg> nargs; | ||
| 1999 | list<TypedArg> targs, tnargs; | ||
| 2000 | String s; | ||
| 2001 | Expression e; | ||
| 2002 | list<tuple<InstNode, Expression>> iters; | ||
| 2003 | Option<Expression> default_exp; | ||
| 2004 | tuple<Option<Expression>, String, String> fold_exp; | ||
| 2005 | |||
| 2006 | case UNTYPED_CALL() | ||
| 2007 | algorithm | ||
| 2008 |
5/6✓ Branch 0 taken 104 times.
✓ Branch 1 taken 88 times.
✓ Branch 2 taken 104 times.
✓ Branch 3 taken 88 times.
✓ Branch 4 taken 104 times.
✗ Branch 5 not taken.
|
192 | args := list(func(arg) for arg in call.arguments); |
| 2009 | nargs := {}; | ||
| 2010 | |||
| 2011 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 88 times.
|
88 | for arg in call.named_args loop |
| 2012 | ✗ | (s, e) := arg; | |
| 2013 | ✗ | e := func(e); | |
| 2014 | ✗ | nargs := (s, e) :: nargs; | |
| 2015 | end for; | ||
| 2016 | 88 | then | |
| 2017 | UNTYPED_CALL(call.ref, args, listReverse(nargs), call.call_scope); | ||
| 2018 | |||
| 2019 | case ARG_TYPED_CALL() | ||
| 2020 | algorithm | ||
| 2021 | targs := {}; | ||
| 2022 | tnargs := {}; | ||
| 2023 | |||
| 2024 | ✗ | for arg in call.positional_args loop | |
| 2025 | ✗ | arg.value := func(arg.value); | |
| 2026 | targs := arg :: targs; | ||
| 2027 | end for; | ||
| 2028 | |||
| 2029 | ✗ | for arg in call.named_args loop | |
| 2030 | ✗ | arg.value := func(arg.value); | |
| 2031 | tnargs := arg :: tnargs; | ||
| 2032 | end for; | ||
| 2033 | ✗ | then | |
| 2034 | ARG_TYPED_CALL(call.ref, listReverse(targs), listReverse(tnargs), call.call_scope); | ||
| 2035 | |||
| 2036 | case TYPED_CALL() | ||
| 2037 | algorithm | ||
| 2038 |
6/6✓ Branch 0 taken 605910 times.
✓ Branch 1 taken 312544 times.
✓ Branch 2 taken 605910 times.
✓ Branch 3 taken 312544 times.
✓ Branch 4 taken 601439 times.
✓ Branch 5 taken 4471 times.
|
918454 | args := list(func(arg) for arg in call.arguments); |
| 2039 | 312544 | then | |
| 2040 | TYPED_CALL(call.fn, call.ty, call.var, call.purity, args, call.attributes); | ||
| 2041 | |||
| 2042 | case UNTYPED_ARRAY_CONSTRUCTOR() | ||
| 2043 | algorithm | ||
| 2044 | ✗ | e := func(call.exp); | |
| 2045 | ✗ | iters := mapIteratorsExpShallow(call.iters, func); | |
| 2046 | ✗ | then | |
| 2047 | UNTYPED_ARRAY_CONSTRUCTOR(e, iters); | ||
| 2048 | |||
| 2049 | case TYPED_ARRAY_CONSTRUCTOR() | ||
| 2050 | algorithm | ||
| 2051 |
2/2✓ Branch 0 taken 4854 times.
✓ Branch 1 taken 7 times.
|
4861 | e := func(call.exp); |
| 2052 | 4861 | iters := mapIteratorsExpShallow(call.iters, func); | |
| 2053 | 4861 | then | |
| 2054 | TYPED_ARRAY_CONSTRUCTOR(call.ty, call.var, call.purity, e, iters); | ||
| 2055 | |||
| 2056 | case UNTYPED_REDUCTION() | ||
| 2057 | algorithm | ||
| 2058 | ✗ | e := func(call.exp); | |
| 2059 | ✗ | iters := mapIteratorsExpShallow(call.iters, func); | |
| 2060 | ✗ | then | |
| 2061 | UNTYPED_REDUCTION(call.ref, e, iters); | ||
| 2062 | |||
| 2063 | case TYPED_REDUCTION() | ||
| 2064 | algorithm | ||
| 2065 |
2/2✓ Branch 0 taken 115 times.
✓ Branch 1 taken 3 times.
|
118 | e := func(call.exp); |
| 2066 | 118 | iters := mapIteratorsExpShallow(call.iters, func); | |
| 2067 | 118 | default_exp := Expression.mapShallowOpt(call.defaultExp, func); | |
| 2068 | 118 | fold_exp := Util.applyTuple31(call.foldExp, function Expression.mapShallowOpt(func = func)); | |
| 2069 | 118 | then | |
| 2070 | TYPED_REDUCTION(call.fn, call.ty, call.var, call.purity, e, iters, default_exp, fold_exp); | ||
| 2071 | |||
| 2072 | end match; | ||
| 2073 | end mapExpShallow; | ||
| 2074 | |||
| 2075 | function mapIteratorsExpShallow | ||
| 2076 | input list<tuple<InstNode, Expression>> iters; | ||
| 2077 | input MapFunc func; | ||
| 2078 | output list<tuple<InstNode, Expression>> outIters = {}; | ||
| 2079 | |||
| 2080 | partial function MapFunc | ||
| 2081 | input output Expression e; | ||
| 2082 | end MapFunc; | ||
| 2083 | protected | ||
| 2084 | InstNode node; | ||
| 2085 | Expression exp, new_exp; | ||
| 2086 | algorithm | ||
| 2087 |
2/2✓ Branch 0 taken 5592 times.
✓ Branch 1 taken 5565 times.
|
11157 | for i in iters loop |
| 2088 | 5592 | (node, exp) := i; | |
| 2089 |
2/2✓ Branch 0 taken 4995 times.
✓ Branch 1 taken 597 times.
|
5592 | new_exp := func(exp); |
| 2090 |
2/2✓ Branch 0 taken 2911 times.
✓ Branch 1 taken 2681 times.
|
5592 | outIters := (if referenceEq(new_exp, exp) then i else (node, new_exp)) :: outIters; |
| 2091 | end for; | ||
| 2092 | |||
| 2093 | 5565 | outIters := listReverseInPlace(outIters); | |
| 2094 | end mapIteratorsExpShallow; | ||
| 2095 | |||
| 2096 | function mapFoldExp<ArgT> | ||
| 2097 | input Call call; | ||
| 2098 | input MapFunc func; | ||
| 2099 | output Call outCall; | ||
| 2100 | input output ArgT foldArg; | ||
| 2101 | |||
| 2102 | partial function MapFunc | ||
| 2103 | input output Expression e; | ||
| 2104 | input output ArgT arg; | ||
| 2105 | end MapFunc; | ||
| 2106 | algorithm | ||
| 2107 | outCall := match call | ||
| 2108 | local | ||
| 2109 | list<Expression> args; | ||
| 2110 | list<NamedArg> nargs; | ||
| 2111 | list<TypedArg> targs, tnargs; | ||
| 2112 | String s; | ||
| 2113 | Expression e; | ||
| 2114 | list<tuple<InstNode, Expression>> iters; | ||
| 2115 | Option<Expression> default_exp; | ||
| 2116 | tuple<Option<Expression>, String, String> fold_exp; | ||
| 2117 | Option<Expression> oe; | ||
| 2118 | |||
| 2119 | case UNTYPED_CALL() | ||
| 2120 | algorithm | ||
| 2121 | ✗ | (args, foldArg) := List.map1Fold(call.arguments, Expression.mapFold, func, foldArg); | |
| 2122 | nargs := {}; | ||
| 2123 | |||
| 2124 | ✗ | for arg in call.named_args loop | |
| 2125 | ✗ | (s, e) := arg; | |
| 2126 | ✗ | (e, foldArg) := Expression.mapFold(e, func, foldArg); | |
| 2127 | ✗ | nargs := (s, e) :: nargs; | |
| 2128 | end for; | ||
| 2129 | ✗ | then | |
| 2130 | UNTYPED_CALL(call.ref, args, listReverse(nargs), call.call_scope); | ||
| 2131 | |||
| 2132 | case ARG_TYPED_CALL() | ||
| 2133 | algorithm | ||
| 2134 | targs := {}; | ||
| 2135 | tnargs := {}; | ||
| 2136 | |||
| 2137 | ✗ | for arg in call.positional_args loop | |
| 2138 | ✗ | (e, foldArg) := Expression.mapFold(arg.value, func, foldArg); | |
| 2139 | ✗ | arg.value := e; | |
| 2140 | targs := arg :: targs; | ||
| 2141 | end for; | ||
| 2142 | |||
| 2143 | ✗ | for arg in call.named_args loop | |
| 2144 | ✗ | (e, foldArg) := Expression.mapFold(arg.value, func, foldArg); | |
| 2145 | ✗ | arg.value := e; | |
| 2146 | targs := arg :: targs; | ||
| 2147 | end for; | ||
| 2148 | ✗ | then | |
| 2149 | ARG_TYPED_CALL(call.ref, listReverse(targs), listReverse(tnargs), call.call_scope); | ||
| 2150 | |||
| 2151 | case TYPED_CALL() | ||
| 2152 | algorithm | ||
| 2153 | 27 | (args, foldArg) := List.map1Fold(call.arguments, Expression.mapFold, func, foldArg); | |
| 2154 | 27 | then | |
| 2155 | TYPED_CALL(call.fn, call.ty, call.var, call.purity, args, call.attributes); | ||
| 2156 | |||
| 2157 | case UNTYPED_ARRAY_CONSTRUCTOR() | ||
| 2158 | algorithm | ||
| 2159 | ✗ | (e, foldArg) := Expression.mapFold(call.exp, func, foldArg); | |
| 2160 | ✗ | (iters, foldArg) := mapFoldIteratorsExp(call.iters, func, foldArg); | |
| 2161 | ✗ | then | |
| 2162 | UNTYPED_ARRAY_CONSTRUCTOR(e, iters); | ||
| 2163 | |||
| 2164 | case TYPED_ARRAY_CONSTRUCTOR() | ||
| 2165 | algorithm | ||
| 2166 | 1 | (e, foldArg) := Expression.mapFold(call.exp, func, foldArg); | |
| 2167 | 1 | (iters, foldArg) := mapFoldIteratorsExp(call.iters, func, foldArg); | |
| 2168 | 1 | then | |
| 2169 | TYPED_ARRAY_CONSTRUCTOR(call.ty, call.var, call.purity, e, iters); | ||
| 2170 | |||
| 2171 | case UNTYPED_REDUCTION() | ||
| 2172 | algorithm | ||
| 2173 | ✗ | (e, foldArg) := Expression.mapFold(call.exp, func, foldArg); | |
| 2174 | ✗ | (iters, foldArg) := mapFoldIteratorsExp(call.iters, func, foldArg); | |
| 2175 | ✗ | then | |
| 2176 | UNTYPED_REDUCTION(call.ref, e, iters); | ||
| 2177 | |||
| 2178 | case TYPED_REDUCTION() | ||
| 2179 | algorithm | ||
| 2180 | ✗ | (e, foldArg) := Expression.mapFold(call.exp, func, foldArg); | |
| 2181 | ✗ | (iters, foldArg) := mapFoldIteratorsExp(call.iters, func, foldArg); | |
| 2182 | ✗ | (default_exp, foldArg) := Expression.mapFoldOpt(call.defaultExp, func, foldArg); | |
| 2183 | ✗ | oe := Util.tuple31(call.foldExp); | |
| 2184 | |||
| 2185 | ✗ | if isSome(oe) then | |
| 2186 | ✗ | (oe, foldArg) := Expression.mapFoldOpt(oe, func, foldArg); | |
| 2187 | ✗ | fold_exp := Util.applyTuple31(call.foldExp, function Util.replace(arg = oe)); | |
| 2188 | else | ||
| 2189 | ✗ | fold_exp := call.foldExp; | |
| 2190 | end if; | ||
| 2191 | ✗ | then | |
| 2192 | TYPED_REDUCTION(call.fn, call.ty, call.var, call.purity, e, iters, default_exp, fold_exp); | ||
| 2193 | end match; | ||
| 2194 | end mapFoldExp; | ||
| 2195 | |||
| 2196 | function mapFoldIteratorsExp<ArgT> | ||
| 2197 | input list<tuple<InstNode, Expression>> iters; | ||
| 2198 | input MapFunc func; | ||
| 2199 | output list<tuple<InstNode, Expression>> outIters = {}; | ||
| 2200 | input output ArgT arg; | ||
| 2201 | |||
| 2202 | partial function MapFunc | ||
| 2203 | input output Expression e; | ||
| 2204 | input output ArgT arg; | ||
| 2205 | end MapFunc; | ||
| 2206 | protected | ||
| 2207 | InstNode node; | ||
| 2208 | Expression exp, new_exp; | ||
| 2209 | algorithm | ||
| 2210 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
|
2 | for i in iters loop |
| 2211 | 1 | (node, exp) := i; | |
| 2212 | 1 | (new_exp, arg) := Expression.mapFold(exp, func, arg); | |
| 2213 |
1/2✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
|
1 | outIters := (if referenceEq(new_exp, exp) then i else (node, new_exp)) :: outIters; |
| 2214 | end for; | ||
| 2215 | |||
| 2216 | 1 | outIters := listReverseInPlace(outIters); | |
| 2217 | end mapFoldIteratorsExp; | ||
| 2218 | |||
| 2219 | function mapFoldExpShallow<ArgT> | ||
| 2220 | input Call call; | ||
| 2221 | input MapFunc func; | ||
| 2222 | output Call outCall; | ||
| 2223 | input output ArgT foldArg; | ||
| 2224 | |||
| 2225 | partial function MapFunc | ||
| 2226 | input output Expression e; | ||
| 2227 | input output ArgT arg; | ||
| 2228 | end MapFunc; | ||
| 2229 | algorithm | ||
| 2230 | outCall := match call | ||
| 2231 | local | ||
| 2232 | list<Expression> args; | ||
| 2233 | list<NamedArg> nargs; | ||
| 2234 | list<TypedArg> targs, tnargs; | ||
| 2235 | String s; | ||
| 2236 | Expression e; | ||
| 2237 | list<tuple<InstNode, Expression>> iters; | ||
| 2238 | Option<Expression> default_exp; | ||
| 2239 | tuple<Option<Expression>, String, String> fold_exp; | ||
| 2240 | Option<Expression> oe; | ||
| 2241 | |||
| 2242 | case UNTYPED_CALL() | ||
| 2243 | algorithm | ||
| 2244 | ✗ | (args, foldArg) := List.mapFold(call.arguments, func, foldArg); | |
| 2245 | nargs := {}; | ||
| 2246 | |||
| 2247 | ✗ | for arg in call.named_args loop | |
| 2248 | ✗ | (s, e) := arg; | |
| 2249 | ✗ | (e, foldArg) := func(e, foldArg); | |
| 2250 | ✗ | nargs := (s, e) :: nargs; | |
| 2251 | end for; | ||
| 2252 | ✗ | then | |
| 2253 | UNTYPED_CALL(call.ref, args, listReverse(nargs), call.call_scope); | ||
| 2254 | |||
| 2255 | case ARG_TYPED_CALL() | ||
| 2256 | algorithm | ||
| 2257 | targs := {}; | ||
| 2258 | tnargs := {}; | ||
| 2259 | |||
| 2260 | ✗ | for arg in call.positional_args loop | |
| 2261 | ✗ | (e, foldArg) := func(arg.value, foldArg); | |
| 2262 | ✗ | arg.value := e; | |
| 2263 | targs := arg :: targs; | ||
| 2264 | end for; | ||
| 2265 | |||
| 2266 | ✗ | for arg in call.named_args loop | |
| 2267 | ✗ | (e, foldArg) := func(arg.value, foldArg); | |
| 2268 | ✗ | arg.value := e; | |
| 2269 | targs := arg :: targs; | ||
| 2270 | end for; | ||
| 2271 | ✗ | then | |
| 2272 | ARG_TYPED_CALL(call.ref, listReverse(targs), listReverse(tnargs), call.call_scope); | ||
| 2273 | |||
| 2274 | case TYPED_CALL() | ||
| 2275 | algorithm | ||
| 2276 | 165291 | (args, foldArg) := List.mapFold(call.arguments, func, foldArg); | |
| 2277 | 165291 | then | |
| 2278 | TYPED_CALL(call.fn, call.ty, call.var, call.purity, args, call.attributes); | ||
| 2279 | |||
| 2280 | case UNTYPED_ARRAY_CONSTRUCTOR() | ||
| 2281 | algorithm | ||
| 2282 | ✗ | (e, foldArg) := func(call.exp, foldArg); | |
| 2283 | ✗ | iters := mapFoldIteratorsExpShallow(call.iters, func, foldArg); | |
| 2284 | ✗ | then | |
| 2285 | UNTYPED_ARRAY_CONSTRUCTOR(e, iters); | ||
| 2286 | |||
| 2287 | case TYPED_ARRAY_CONSTRUCTOR() | ||
| 2288 | algorithm | ||
| 2289 |
1/2✓ Branch 0 taken 1738 times.
✗ Branch 1 not taken.
|
1738 | (e, foldArg) := func(call.exp, foldArg); |
| 2290 | 1738 | iters := mapFoldIteratorsExpShallow(call.iters, func, foldArg); | |
| 2291 | 1738 | then | |
| 2292 | TYPED_ARRAY_CONSTRUCTOR(call.ty, call.var, call.purity, e, iters); | ||
| 2293 | |||
| 2294 | case UNTYPED_REDUCTION() | ||
| 2295 | algorithm | ||
| 2296 | ✗ | (e, foldArg) := func(call.exp, foldArg); | |
| 2297 | ✗ | iters := mapFoldIteratorsExpShallow(call.iters, func, foldArg); | |
| 2298 | ✗ | then | |
| 2299 | UNTYPED_REDUCTION(call.ref, e, iters); | ||
| 2300 | |||
| 2301 | case TYPED_REDUCTION() | ||
| 2302 | algorithm | ||
| 2303 |
1/2✓ Branch 0 taken 277 times.
✗ Branch 1 not taken.
|
277 | (e, foldArg) := func(call.exp, foldArg); |
| 2304 | 277 | iters := mapFoldIteratorsExpShallow(call.iters, func, foldArg); | |
| 2305 | 277 | (default_exp, foldArg) := Expression.mapFoldOptShallow(call.defaultExp, func, foldArg); | |
| 2306 | 277 | oe := Util.tuple31(call.foldExp); | |
| 2307 | |||
| 2308 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 277 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 277 times.
|
277 | if isSome(oe) then |
| 2309 | 277 | (oe, foldArg) := Expression.mapFoldOptShallow(oe, func, foldArg); | |
| 2310 | 277 | fold_exp := Util.applyTuple31(call.foldExp, function Util.replace(arg = oe)); | |
| 2311 | else | ||
| 2312 | ✗ | fold_exp := call.foldExp; | |
| 2313 | end if; | ||
| 2314 | 277 | then | |
| 2315 | TYPED_REDUCTION(call.fn, call.ty, call.var, call.purity, e, iters, default_exp, fold_exp); | ||
| 2316 | |||
| 2317 | end match; | ||
| 2318 | end mapFoldExpShallow; | ||
| 2319 | |||
| 2320 | function mapFoldIteratorsExpShallow<ArgT> | ||
| 2321 | input list<tuple<InstNode, Expression>> iters; | ||
| 2322 | input MapFunc func; | ||
| 2323 | output list<tuple<InstNode, Expression>> outIters = {}; | ||
| 2324 | input output ArgT arg; | ||
| 2325 | |||
| 2326 | partial function MapFunc | ||
| 2327 | input output Expression e; | ||
| 2328 | input output ArgT arg; | ||
| 2329 | end MapFunc; | ||
| 2330 | protected | ||
| 2331 | InstNode node; | ||
| 2332 | Expression exp, new_exp; | ||
| 2333 | algorithm | ||
| 2334 |
2/2✓ Branch 0 taken 2025 times.
✓ Branch 1 taken 2015 times.
|
4040 | for i in iters loop |
| 2335 | 2025 | (node, exp) := i; | |
| 2336 |
1/2✓ Branch 0 taken 2025 times.
✗ Branch 1 not taken.
|
2025 | (new_exp, arg) := func(exp, arg); |
| 2337 |
2/2✓ Branch 0 taken 121 times.
✓ Branch 1 taken 1904 times.
|
2025 | outIters := (if referenceEq(new_exp, exp) then i else (node, new_exp)) :: outIters; |
| 2338 | end for; | ||
| 2339 | |||
| 2340 | 2015 | outIters := listReverseInPlace(outIters); | |
| 2341 | end mapFoldIteratorsExpShallow; | ||
| 2342 | |||
| 2343 | function updateExternalRecordArgs | ||
| 2344 | input list<Expression> args; | ||
| 2345 | algorithm | ||
| 2346 |
2/2✓ Branch 0 taken 1786 times.
✓ Branch 1 taken 733 times.
|
2519 | for arg in args loop |
| 2347 | 1786 | updateExternalRecordArgsInType(Expression.typeOf(arg)); | |
| 2348 | end for; | ||
| 2349 | end updateExternalRecordArgs; | ||
| 2350 | |||
| 2351 | function updateExternalRecordArgsInType | ||
| 2352 | input Type ty; | ||
| 2353 | protected | ||
| 2354 | InstNode node; | ||
| 2355 | Class cls; | ||
| 2356 | Restriction res; | ||
| 2357 | algorithm | ||
| 2358 |
2/2✓ Branch 1 taken 5027 times.
✓ Branch 2 taken 13 times.
|
5040 | if Type.isRecord(ty) then |
| 2359 | 13 | node := Type.complexNode(ty); | |
| 2360 | 13 | cls := InstNode.getClass(node); | |
| 2361 | 13 | res := Restriction.setExternalRecord(Class.restriction(cls)); | |
| 2362 | 13 | cls := Class.setRestriction(res, cls); | |
| 2363 | 13 | InstNode.updateClass(cls, node); | |
| 2364 | end if; | ||
| 2365 | end updateExternalRecordArgsInType; | ||
| 2366 | |||
| 2367 | function toArrayConstructor | ||
| 2368 | "tries to make an array constructor from any call" | ||
| 2369 | input Call iCall; | ||
| 2370 | input Pointer<Integer> index_ptr; | ||
| 2371 | output Call oCall; | ||
| 2372 | algorithm | ||
| 2373 | oCall := match iCall | ||
| 2374 | local | ||
| 2375 | InstNode iter_name; | ||
| 2376 | Expression start, body, iter_range; | ||
| 2377 | Option<Expression> step; | ||
| 2378 | list<Expression> rest; | ||
| 2379 | list<tuple<InstNode, Expression>> iterators = {}; | ||
| 2380 | Call body_call; | ||
| 2381 | Integer index; | ||
| 2382 | |||
| 2383 | case TYPED_CALL() then match AbsynUtil.pathString(Function.nameConsiderBuiltin(iCall.fn)) | ||
| 2384 | case "fill" algorithm | ||
| 2385 | 1730 | index := Pointer.access(index_ptr); | |
| 2386 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1730 times.
|
1730 | body :: rest := iCall.arguments; |
| 2387 | start := Expression.INTEGER(1); | ||
| 2388 | step := NONE(); | ||
| 2389 |
2/2✓ Branch 1 taken 1770 times.
✓ Branch 2 taken 1730 times.
|
3500 | for stop in listReverse(rest) loop |
| 2390 | 1770 | iter_name := InstNode.newIndexedIterator(index, "f"); | |
| 2391 | 1770 | iter_range := Expression.makeRange(start, step, stop); | |
| 2392 | 1770 | iterators := (iter_name, iter_range) :: iterators; | |
| 2393 | 1770 | index := index + 1; | |
| 2394 | end for; | ||
| 2395 | |||
| 2396 | // if there are nested calls, combine them | ||
| 2397 | (body, iterators) := match body | ||
| 2398 | case Expression.CALL(call = body_call as TYPED_ARRAY_CONSTRUCTOR()) algorithm | ||
| 2399 | 54 | then (body_call.exp, listAppend(iterators, body_call.iters)); | |
| 2400 | else (body, iterators); | ||
| 2401 | end match; | ||
| 2402 | |||
| 2403 | 1730 | Pointer.update(index_ptr, index); | |
| 2404 | 1730 | then TYPED_ARRAY_CONSTRUCTOR(iCall.ty, iCall.var, iCall.purity, body, listReverse(iterators)); | |
| 2405 | else iCall; | ||
| 2406 | end match; | ||
| 2407 | else iCall; | ||
| 2408 | end match; | ||
| 2409 | end toArrayConstructor; | ||
| 2410 | |||
| 2411 | function isConnectionsOperator | ||
| 2412 | input Call call; | ||
| 2413 | output Boolean isOp; | ||
| 2414 | algorithm | ||
| 2415 | isOp := match call | ||
| 2416 | case TYPED_CALL() | ||
| 2417 |
6/6✓ Branch 1 taken 697 times.
✓ Branch 2 taken 99 times.
✓ Branch 5 taken 313 times.
✓ Branch 6 taken 384 times.
✓ Branch 10 taken 5 times.
✓ Branch 11 taken 308 times.
|
796 | then Function.isBuiltin(call.fn) and AbsynUtil.pathFirstIdent(Function.name(call.fn)) == "Connections"; |
| 2418 | else false; | ||
| 2419 | end match; | ||
| 2420 | end isConnectionsOperator; | ||
| 2421 | |||
| 2422 | function isStreamOperator | ||
| 2423 | input Call call; | ||
| 2424 | output Boolean isOp; | ||
| 2425 | protected | ||
| 2426 | String name; | ||
| 2427 | algorithm | ||
| 2428 | isOp := match call | ||
| 2429 | case TYPED_CALL() | ||
| 2430 | guard Function.isBuiltin(call.fn) | ||
| 2431 | algorithm | ||
| 2432 | 389 | name := functionNameFirst(call); | |
| 2433 |
5/8✗ Branch 0 not taken.
✓ Branch 1 taken 389 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 39 times.
✓ Branch 6 taken 350 times.
✓ Branch 8 taken 6 times.
✓ Branch 9 taken 33 times.
|
389 | then |
| 2434 | name == "actualStream" or name == "inStream"; | ||
| 2435 | |||
| 2436 | else false; | ||
| 2437 | end match; | ||
| 2438 | end isStreamOperator; | ||
| 2439 | |||
| 2440 | function isCardinality | ||
| 2441 | input Call call; | ||
| 2442 | output Boolean isCardinality; | ||
| 2443 | algorithm | ||
| 2444 | isCardinality := match call | ||
| 2445 | case TYPED_CALL() guard Function.isBuiltin(call.fn) | ||
| 2446 |
3/4✓ Branch 1 taken 5 times.
✓ Branch 2 taken 378 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5 times.
|
383 | then functionNameFirst(call) == "cardinality"; |
| 2447 | else false; | ||
| 2448 | end match; | ||
| 2449 | end isCardinality; | ||
| 2450 | |||
| 2451 | protected | ||
| 2452 | function instNormalCall | ||
| 2453 | input Absyn.ComponentRef functionName; | ||
| 2454 | input Absyn.FunctionArgs functionArgs; | ||
| 2455 | input InstNode scope; | ||
| 2456 | input InstContext.Type context; | ||
| 2457 | input SourceInfo info; | ||
| 2458 | output Expression callExp; | ||
| 2459 | protected | ||
| 2460 | ComponentRef fn_ref; | ||
| 2461 | list<Expression> args; | ||
| 2462 | list<NamedArg> named_args; | ||
| 2463 | String name; | ||
| 2464 | algorithm | ||
| 2465 | |||
| 2466 | 110173 | name := AbsynUtil.crefFirstIdent(functionName); | |
| 2467 | |||
| 2468 | // try to inst the parameters | ||
| 2469 | try | ||
| 2470 | 110173 | (args, named_args) := instArgs(functionArgs, scope, context, info); | |
| 2471 | else | ||
| 2472 | // didn't work, is this DynamicSelect dynamic part?! #5631 | ||
| 2473 |
3/8✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 time.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
|
2 | if InstContext.inAnnotation(context) and not InstContext.inInstanceAPI(context) and |
| 2474 | stringEq(name, "DynamicSelect") then | ||
| 2475 | // return just the first part of DynamicSelect | ||
| 2476 | callExp := match functionArgs | ||
| 2477 | ✗ | case Absyn.FUNCTIONARGS() then | |
| 2478 | Inst.instExp(listHead(functionArgs.args), scope, context, info); | ||
| 2479 | end match; | ||
| 2480 | ✗ | return; | |
| 2481 | else | ||
| 2482 | 2 | fail(); | |
| 2483 | end if; | ||
| 2484 | end try; | ||
| 2485 | |||
| 2486 | callExp := match name | ||
| 2487 | // size creates Expression.SIZE instead of Expression.CALL. | ||
| 2488 | 2642 | case "size" then BuiltinCall.makeSizeExp(args, named_args, info); | |
| 2489 | // array() call with no iterators creates Expression.ARRAY instead of Expression.CALL. | ||
| 2490 | // If it had iterators then it will not reach here. The args would have been parsed to | ||
| 2491 | // Absyn.FOR_ITER_FARG and that is handled in instIteratorCall. | ||
| 2492 | 149 | case "array" then BuiltinCall.makeArrayExp(args, named_args, info); | |
| 2493 | |||
| 2494 | else | ||
| 2495 | algorithm | ||
| 2496 | 107380 | fn_ref := Function.instFunction(functionName, scope, context, info); | |
| 2497 | 107369 | then | |
| 2498 | Expression.CALL(UNTYPED_CALL(fn_ref, args, named_args, InstNode.scopeRef(scope))); | ||
| 2499 | |||
| 2500 | end match; | ||
| 2501 | end instNormalCall; | ||
| 2502 | |||
| 2503 | function instArgs | ||
| 2504 | input Absyn.FunctionArgs args; | ||
| 2505 | input InstNode scope; | ||
| 2506 | input InstContext.Type context; | ||
| 2507 | input SourceInfo info; | ||
| 2508 | output list<Expression> posArgs; | ||
| 2509 | output list<NamedArg> namedArgs; | ||
| 2510 | algorithm | ||
| 2511 | (posArgs, namedArgs) := match args | ||
| 2512 | case Absyn.FUNCTIONARGS() | ||
| 2513 | algorithm | ||
| 2514 |
4/4✓ Branch 0 taken 175550 times.
✓ Branch 1 taken 110172 times.
✓ Branch 2 taken 175550 times.
✓ Branch 3 taken 110172 times.
|
285722 | posArgs := list(Inst.instExp(a, scope, context, info) for a in args.args); |
| 2515 |
5/6✓ Branch 0 taken 6119 times.
✓ Branch 1 taken 110171 times.
✓ Branch 2 taken 6119 times.
✓ Branch 3 taken 110171 times.
✓ Branch 5 taken 110171 times.
✗ Branch 6 not taken.
|
116290 | namedArgs := list(instNamedArg(a, scope, context, info) for a in args.argNames); |
| 2516 | then | ||
| 2517 | (posArgs, namedArgs); | ||
| 2518 | |||
| 2519 | else | ||
| 2520 | algorithm | ||
| 2521 | ✗ | Error.terminate(getInstanceName() + " got unknown function args", sourceInfo()); | |
| 2522 | ✗ | then | |
| 2523 | fail(); | ||
| 2524 | end match; | ||
| 2525 | end instArgs; | ||
| 2526 | |||
| 2527 | function instNamedArg | ||
| 2528 | input Absyn.NamedArg absynArg; | ||
| 2529 | input InstNode scope; | ||
| 2530 | input InstContext.Type context; | ||
| 2531 | input SourceInfo info; | ||
| 2532 | output NamedArg arg; | ||
| 2533 | protected | ||
| 2534 | String name; | ||
| 2535 | Absyn.Exp exp; | ||
| 2536 | algorithm | ||
| 2537 | 6119 | Absyn.NAMEDARG(argName = name, argValue = exp) := absynArg; | |
| 2538 | 6119 | arg := (name, Inst.instExp(exp, scope, context, info)); | |
| 2539 | end instNamedArg; | ||
| 2540 | |||
| 2541 | function instIteratorCall | ||
| 2542 | input Absyn.ComponentRef functionName; | ||
| 2543 | input Absyn.FunctionArgs functionArgs; | ||
| 2544 | input InstNode scope; | ||
| 2545 | input InstContext.Type context; | ||
| 2546 | input SourceInfo info; | ||
| 2547 | output Expression callExp; | ||
| 2548 | protected | ||
| 2549 | Absyn.ComponentRef fn_name; | ||
| 2550 | ComponentRef fn_ref; | ||
| 2551 | Expression exp; | ||
| 2552 | list<tuple<InstNode, Expression>> iters; | ||
| 2553 | algorithm | ||
| 2554 | // The parser turns {exp for i in ...} into $array(exp for i in ...), but we | ||
| 2555 | // change it to just array here so we can handle array constructors uniformly. | ||
| 2556 | fn_name := match functionName | ||
| 2557 | case Absyn.CREF_IDENT("$array") then Absyn.CREF_IDENT("array", {}); | ||
| 2558 | else functionName; | ||
| 2559 | end match; | ||
| 2560 | |||
| 2561 | 1775 | (exp, iters) := instIteratorCallArgs(functionArgs, scope, context, info); | |
| 2562 | |||
| 2563 |
3/4✓ Branch 1 taken 1471 times.
✓ Branch 2 taken 304 times.
✓ Branch 5 taken 1471 times.
✗ Branch 6 not taken.
|
1775 | if AbsynUtil.crefFirstIdent(fn_name) == "array" then |
| 2564 | 1471 | callExp := Expression.CALL(UNTYPED_ARRAY_CONSTRUCTOR(exp, iters)); | |
| 2565 | else | ||
| 2566 | 304 | fn_ref := Function.instFunction(fn_name, scope, context, info); | |
| 2567 | 304 | callExp := Expression.CALL(UNTYPED_REDUCTION(fn_ref, exp, iters)); | |
| 2568 | end if; | ||
| 2569 | end instIteratorCall; | ||
| 2570 | |||
| 2571 | function instIteratorCallArgs | ||
| 2572 | input Absyn.FunctionArgs args; | ||
| 2573 | input InstNode scope; | ||
| 2574 | input InstContext.Type context; | ||
| 2575 | input SourceInfo info; | ||
| 2576 | output Expression exp; | ||
| 2577 | output list<tuple<InstNode, Expression>> iters; | ||
| 2578 | algorithm | ||
| 2579 | () := match args | ||
| 2580 | local | ||
| 2581 | InstNode for_scope; | ||
| 2582 | |||
| 2583 | case Absyn.FOR_ITER_FARG() | ||
| 2584 | algorithm | ||
| 2585 | 1775 | (for_scope, iters) := instIterators(args.iterators, scope, context, info); | |
| 2586 | 1775 | exp := Inst.instExp(args.exp, for_scope, context, info); | |
| 2587 | then | ||
| 2588 | (); | ||
| 2589 | end match; | ||
| 2590 | end instIteratorCallArgs; | ||
| 2591 | |||
| 2592 | function instIterators | ||
| 2593 | input list<Absyn.ForIterator> inIters; | ||
| 2594 | input InstNode scope; | ||
| 2595 | input InstContext.Type context; | ||
| 2596 | input SourceInfo info; | ||
| 2597 | output InstNode outScope = scope; | ||
| 2598 | output list<tuple<InstNode, Expression>> outIters = {}; | ||
| 2599 | protected | ||
| 2600 | Expression range; | ||
| 2601 | InstNode iter, range_node; | ||
| 2602 | Type ty; | ||
| 2603 | algorithm | ||
| 2604 |
2/2✓ Branch 1 taken 1776 times.
✓ Branch 2 taken 1775 times.
|
3551 | for i in listReverse(inIters) loop |
| 2605 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 1776 times.
✓ Branch 2 taken 1775 times.
✓ Branch 3 taken 1 time.
|
1776 | if isSome(i.range) then |
| 2606 | 1775 | range := Inst.instExp(Util.getOption(i.range), outScope, context, info); | |
| 2607 | else | ||
| 2608 | // Use an empty expression to indicate that the range is missing and | ||
| 2609 | // needs to be deduced during typing. | ||
| 2610 | range := Expression.EMPTY(Type.UNKNOWN()); | ||
| 2611 | end if; | ||
| 2612 | |||
| 2613 | // If the range is a cref, use it as the iterator type to allow lookup in | ||
| 2614 | // the iterator. | ||
| 2615 | ty := match range | ||
| 2616 | case Expression.CREF(cref = ComponentRef.CREF()) | ||
| 2617 | guard InstNode.isComponent(ComponentRef.node(range.cref)) | ||
| 2618 | 1 | then Type.COMPLEX(InstNode.identityCell(Component.classInstance( | |
| 2619 | InstNode.component(ComponentRef.node(range.cref)))), ComplexType.CLASS()); | ||
| 2620 | else Type.UNKNOWN(); | ||
| 2621 | end match; | ||
| 2622 | |||
| 2623 | 1776 | (outScope, iter) := Inst.addIteratorToScope(i.name, outScope, info, ty); | |
| 2624 | 1776 | outIters := (iter, range) :: outIters; | |
| 2625 | end for; | ||
| 2626 | end instIterators; | ||
| 2627 | |||
| 2628 | function typeArrayConstructor | ||
| 2629 | input output NFCall call; | ||
| 2630 | input InstContext.Type context; | ||
| 2631 | input SourceInfo info; | ||
| 2632 | output Type ty; | ||
| 2633 | output Variability variability; | ||
| 2634 | output Purity purity; | ||
| 2635 | protected | ||
| 2636 | Expression arg, range; | ||
| 2637 | Type iter_ty; | ||
| 2638 | Variability iter_var, exp_var; | ||
| 2639 | Purity iter_pur, exp_pur; | ||
| 2640 | InstNode iter; | ||
| 2641 | list<Dimension> dims = {}; | ||
| 2642 | list<tuple<InstNode, Expression>> iters = {}; | ||
| 2643 | InstContext.Type next_context; | ||
| 2644 | Boolean is_structural, has_iterator; | ||
| 2645 | algorithm | ||
| 2646 | (call, ty, variability, purity) := match call | ||
| 2647 | case UNTYPED_ARRAY_CONSTRUCTOR() | ||
| 2648 | algorithm | ||
| 2649 | variability := Variability.CONSTANT; | ||
| 2650 | purity := Purity.PURE; | ||
| 2651 | // The size of the expression must be known unless we're in a function. | ||
| 2652 | 1354 | is_structural := not InstContext.inFunction(context); | |
| 2653 | 1354 | next_context := InstContext.set(context, NFInstContext.SUBEXPRESSION); | |
| 2654 | |||
| 2655 |
2/2✓ Branch 1 taken 1354 times.
✓ Branch 2 taken 1354 times.
|
2708 | for i in listReverse(call.iters) loop |
| 2656 | 1354 | (iter, range) := i; | |
| 2657 | |||
| 2658 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1352 times.
|
1354 | if Expression.isEmpty(range) then |
| 2659 | 2 | range := Typing.deduceIterationRangeExp(Expression.CALL(call), iter, info); | |
| 2660 | end if; | ||
| 2661 | |||
| 2662 | 1354 | (range, iter_ty, iter_var, iter_pur) := Typing.typeIterator(iter, range, next_context, is_structural); | |
| 2663 | |||
| 2664 | // Don't try to evaluate the range if it contains an iterator. | ||
| 2665 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1352 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
|
1354 | has_iterator := iter_pur == Purity.IMPURE and Expression.contains(range, Expression.isIterator); |
| 2666 | |||
| 2667 |
2/2✓ Branch 0 taken 1278 times.
✓ Branch 1 taken 76 times.
|
1354 | if is_structural and not has_iterator then |
| 2668 |
2/2✓ Branch 1 taken 352 times.
✓ Branch 2 taken 926 times.
|
1278 | if InstContext.inRelaxed(context) then |
| 2669 | 352 | range := Ceval.tryEvalExp(range); | |
| 2670 | else | ||
| 2671 | 926 | range := Ceval.evalExp(range, Ceval.EvalTarget.new(info, NFInstContext.ITERATION_RANGE)); | |
| 2672 | end if; | ||
| 2673 | 1278 | iter_ty := Expression.typeOf(range); | |
| 2674 | end if; | ||
| 2675 | |||
| 2676 | 1354 | dims := List.append_reverse(Type.arrayDims(iter_ty), dims); | |
| 2677 | 1354 | variability := Prefixes.variabilityMax(variability, iter_var); | |
| 2678 | 1354 | purity := Prefixes.purityMin(purity, iter_pur); | |
| 2679 | 1354 | iters := (iter, range) :: iters; | |
| 2680 | end for; | ||
| 2681 | |||
| 2682 | 1354 | dims := listReverseInPlace(dims); | |
| 2683 | |||
| 2684 | // InstContext.FOR is used here as a marker that this expression may contain iterators. | ||
| 2685 | 1354 | next_context := InstContext.set(next_context, NFInstContext.FOR); | |
| 2686 | 1354 | (arg, ty, exp_var, exp_pur) := Typing.typeExp(call.exp, next_context, info); | |
| 2687 | 1354 | variability := Prefixes.variabilityMax(variability, exp_var); | |
| 2688 | 1354 | purity := Prefixes.purityMin(purity, exp_pur); | |
| 2689 | 1354 | ty := Type.liftArrayLeftList(ty, dims); | |
| 2690 |
1/2✓ Branch 1 taken 1354 times.
✗ Branch 2 not taken.
|
1354 | then |
| 2691 | (TYPED_ARRAY_CONSTRUCTOR(ty, variability, purity, arg, iters), ty, variability, purity); | ||
| 2692 | |||
| 2693 | else | ||
| 2694 | algorithm | ||
| 2695 | ✗ | Error.terminate(getInstanceName() + " got invalid function call expression", sourceInfo()); | |
| 2696 | ✗ | then | |
| 2697 | fail(); | ||
| 2698 | end match; | ||
| 2699 | end typeArrayConstructor; | ||
| 2700 | |||
| 2701 | function typeReduction | ||
| 2702 | input output NFCall call; | ||
| 2703 | input InstContext.Type context; | ||
| 2704 | input SourceInfo info; | ||
| 2705 | output Type ty; | ||
| 2706 | output Variability variability; | ||
| 2707 | output Purity purity; | ||
| 2708 | protected | ||
| 2709 | Expression range, arg; | ||
| 2710 | InstNode iter; | ||
| 2711 | Variability iter_var, exp_var; | ||
| 2712 | Purity iter_pur, exp_pur; | ||
| 2713 | list<tuple<InstNode, Expression>> iters = {}; | ||
| 2714 | InstContext.Type next_context; | ||
| 2715 | Function fn; | ||
| 2716 | algorithm | ||
| 2717 | (call, ty, variability, purity) := match call | ||
| 2718 | case UNTYPED_REDUCTION() | ||
| 2719 | algorithm | ||
| 2720 | variability := Variability.CONSTANT; | ||
| 2721 | purity := Purity.PURE; | ||
| 2722 | 300 | next_context := InstContext.set(context, NFInstContext.SUBEXPRESSION); | |
| 2723 | |||
| 2724 |
2/2✓ Branch 1 taken 301 times.
✓ Branch 2 taken 300 times.
|
601 | for i in listReverse(call.iters) loop |
| 2725 | 301 | (iter, range) := i; | |
| 2726 | |||
| 2727 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 301 times.
|
301 | if Expression.isEmpty(range) then |
| 2728 | ✗ | range := Typing.deduceIterationRangeExp(Expression.CALL(call), iter, info); | |
| 2729 | end if; | ||
| 2730 | |||
| 2731 | 301 | (range, _, iter_var, iter_pur) := Typing.typeIterator(iter, range, context, structural = false); | |
| 2732 | 301 | variability := Variability.variabilityMax(variability, iter_var); | |
| 2733 | 301 | purity := Variability.purityMin(purity, iter_pur); | |
| 2734 | 301 | iters := (iter, range) :: iters; | |
| 2735 | end for; | ||
| 2736 | |||
| 2737 | // InstContext.FOR is used here as a marker that this expression may contain iterators. | ||
| 2738 | 300 | next_context := InstContext.set(next_context, NFInstContext.FOR); | |
| 2739 | 300 | (arg, ty, exp_var, exp_pur) := Typing.typeExp(call.exp, next_context, info); | |
| 2740 | 300 | variability := Variability.variabilityMax(variability, exp_var); | |
| 2741 | 300 | purity := Variability.purityMin(purity, exp_pur); | |
| 2742 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 300 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 300 times.
|
300 | {fn} := Function.typeRefCache(call.ref); |
| 2743 | 300 | TypeCheck.checkReductionType(ty, Function.name(fn), call.exp, info); | |
| 2744 |
1/2✓ Branch 1 taken 298 times.
✗ Branch 2 not taken.
|
298 | then |
| 2745 | (makeTypedReduction(fn, ty, variability, purity, arg, iters, info), ty, variability, purity); | ||
| 2746 | |||
| 2747 | else | ||
| 2748 | algorithm | ||
| 2749 | ✗ | Error.terminate(getInstanceName() + " got invalid reduction call", sourceInfo()); | |
| 2750 | ✗ | then | |
| 2751 | fail(); | ||
| 2752 | end match; | ||
| 2753 | end typeReduction; | ||
| 2754 | |||
| 2755 | public | ||
| 2756 | function makeTypedReduction | ||
| 2757 | input Function fn; | ||
| 2758 | input Type ty; | ||
| 2759 | input Variability var; | ||
| 2760 | input Purity purity; | ||
| 2761 | input Expression arg; | ||
| 2762 | input list<tuple<InstNode, Expression>> iters; | ||
| 2763 | input SourceInfo info; | ||
| 2764 | output Call call; | ||
| 2765 | protected | ||
| 2766 | String fold_id, res_id; | ||
| 2767 | Option<Expression> default_exp, fold_exp; | ||
| 2768 | tuple<Option<Expression>, String, String> fold_tuple; | ||
| 2769 | algorithm | ||
| 2770 | 308 | fold_id := Util.getTempVariableIndex(); | |
| 2771 | 308 | res_id := Util.getTempVariableIndex(); | |
| 2772 | 308 | default_exp := reductionDefaultValue(fn, ty); | |
| 2773 | 308 | fold_exp := reductionFoldExpression(fn, ty, var, purity, fold_id, res_id, info); | |
| 2774 | 308 | fold_tuple := (fold_exp, fold_id, res_id); | |
| 2775 | |||
| 2776 | 308 | call := TYPED_REDUCTION(fn, ty, var, purity, arg, iters, default_exp, fold_tuple); | |
| 2777 | end makeTypedReduction; | ||
| 2778 | |||
| 2779 | protected | ||
| 2780 | function reductionDefaultValue | ||
| 2781 | input Function fn; | ||
| 2782 | input Type ty; | ||
| 2783 | output Option<Expression> defaultValue; | ||
| 2784 | algorithm | ||
| 2785 |
2/2✓ Branch 1 taken 307 times.
✓ Branch 2 taken 1 time.
|
308 | if Type.isArray(ty) then |
| 2786 | defaultValue := NONE(); | ||
| 2787 | else | ||
| 2788 | defaultValue := match AbsynUtil.pathFirstIdent(Function.name(fn)) | ||
| 2789 | 283 | case "sum" then SOME(Expression.makeZero(ty)); | |
| 2790 | 4 | case "product" then SOME(Expression.makeOne(ty)); | |
| 2791 | 9 | case "min" then SOME(Expression.makeMaxValue(ty)); | |
| 2792 | 11 | case "max" then SOME(Expression.makeMinValue(ty)); | |
| 2793 | else | ||
| 2794 | algorithm | ||
| 2795 | ✗ | Error.addSourceMessage(Error.INTERNAL_ERROR, | |
| 2796 | {getInstanceName() + " got unknown reduction name " + AbsynUtil.pathFirstIdent(Function.name(fn))}, | ||
| 2797 | sourceInfo()); | ||
| 2798 | ✗ | then | |
| 2799 | fail(); | ||
| 2800 | end match; | ||
| 2801 | end if; | ||
| 2802 | end reductionDefaultValue; | ||
| 2803 | |||
| 2804 | function reductionFoldExpression | ||
| 2805 | input Function reductionFn; | ||
| 2806 | input Type reductionType; | ||
| 2807 | input Variability reductionVar; | ||
| 2808 | input Purity reductionPurity; | ||
| 2809 | input String foldId; | ||
| 2810 | input String resultId; | ||
| 2811 | input SourceInfo info; | ||
| 2812 | output Option<Expression> foldExp; | ||
| 2813 | protected | ||
| 2814 | InstNode op_node; | ||
| 2815 | Function fn; | ||
| 2816 | algorithm | ||
| 2817 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 307 times.
|
308 | if Type.isComplex(reductionType) then |
| 2818 | foldExp := match AbsynUtil.pathFirstIdent(Function.name(reductionFn)) | ||
| 2819 | case "sum" | ||
| 2820 | algorithm | ||
| 2821 | 1 | op_node := Type.complexNode(reductionType); | |
| 2822 | 1 | op_node := Class.lookupElement("'+'", InstNode.getClass(op_node)); | |
| 2823 | 1 | Function.instFunctionNode(op_node, NFInstContext.NO_CONTEXT, info); | |
| 2824 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
|
1 | {fn} := Function.typeNodeCache(op_node); |
| 2825 | 3 | then | |
| 2826 | SOME(Expression.CALL(makeTypedCall(fn, | ||
| 2827 | {reductionFoldIterator(resultId, reductionType), | ||
| 2828 | reductionFoldIterator(foldId, reductionType)}, reductionVar, reductionPurity))); | ||
| 2829 | |||
| 2830 | else NONE(); | ||
| 2831 | end match; | ||
| 2832 | else | ||
| 2833 | foldExp := match AbsynUtil.pathFirstIdent(Function.name(reductionFn)) | ||
| 2834 | case "sum" | ||
| 2835 | 283 | then SOME(Expression.BINARY( | |
| 2836 | reductionFoldIterator(resultId, reductionType), | ||
| 2837 | Operator.makeAdd(reductionType), | ||
| 2838 | reductionFoldIterator(foldId, reductionType))); | ||
| 2839 | |||
| 2840 | case "product" | ||
| 2841 | 4 | then SOME(Expression.BINARY( | |
| 2842 | reductionFoldIterator(resultId, reductionType), | ||
| 2843 | Operator.makeMul(reductionType), | ||
| 2844 | reductionFoldIterator(foldId, reductionType))); | ||
| 2845 | |||
| 2846 | case "$array" then NONE(); | ||
| 2847 | case "array" then NONE(); | ||
| 2848 | case "list" then NONE(); | ||
| 2849 | case "listReverse" then NONE(); | ||
| 2850 | |||
| 2851 | 60 | else | |
| 2852 | SOME(Expression.CALL(makeTypedCall(reductionFn, | ||
| 2853 | {reductionFoldIterator(foldId, reductionType), | ||
| 2854 | reductionFoldIterator(resultId, reductionType)}, | ||
| 2855 | reductionVar, reductionPurity, reductionType))); | ||
| 2856 | |||
| 2857 | end match; | ||
| 2858 | end if; | ||
| 2859 | end reductionFoldExpression; | ||
| 2860 | |||
| 2861 | function reductionFoldIterator | ||
| 2862 | input String name; | ||
| 2863 | input Type ty; | ||
| 2864 | output Expression iterExp; | ||
| 2865 | algorithm | ||
| 2866 | 616 | iterExp := Expression.CREF(ty, ComponentRef.makeIterator(InstNode.NAME_NODE(name), ty)); | |
| 2867 | end reductionFoldIterator; | ||
| 2868 | |||
| 2869 | function typeArgs | ||
| 2870 | input output NFCall call; | ||
| 2871 | input InstContext.Type context; | ||
| 2872 | input SourceInfo info; | ||
| 2873 | algorithm | ||
| 2874 | call := match call | ||
| 2875 | local | ||
| 2876 | Expression arg; | ||
| 2877 | Type arg_ty; | ||
| 2878 | Variability arg_var; | ||
| 2879 | Purity arg_pur; | ||
| 2880 | list<TypedArg> typed_args, typed_nargs; | ||
| 2881 | String name; | ||
| 2882 | InstContext.Type next_context; | ||
| 2883 | |||
| 2884 | case UNTYPED_CALL() | ||
| 2885 | algorithm | ||
| 2886 | typed_args := {}; | ||
| 2887 | 78748 | next_context := InstContext.set(context, NFInstContext.SUBEXPRESSION); | |
| 2888 | |||
| 2889 |
2/2✓ Branch 0 taken 130926 times.
✓ Branch 1 taken 78747 times.
|
209673 | for arg in call.arguments loop |
| 2890 | 130926 | (arg, arg_ty, arg_var, arg_pur) := Typing.typeExp(arg, next_context, info); | |
| 2891 | 130925 | typed_args := TypedArg.TYPED_ARG(NONE(), arg, arg_ty, arg_var, arg_pur) :: typed_args; | |
| 2892 | end for; | ||
| 2893 | |||
| 2894 | 78747 | typed_args := listReverse(typed_args); | |
| 2895 | |||
| 2896 | typed_nargs := {}; | ||
| 2897 |
2/2✓ Branch 0 taken 5321 times.
✓ Branch 1 taken 78747 times.
|
84068 | for narg in call.named_args loop |
| 2898 | 5321 | (name, arg) := narg; | |
| 2899 | 5321 | (arg, arg_ty, arg_var, arg_pur) := Typing.typeExp(arg, next_context, info); | |
| 2900 | 5321 | typed_nargs := TypedArg.TYPED_ARG(SOME(name), arg, arg_ty, arg_var, arg_pur) :: typed_nargs; | |
| 2901 | end for; | ||
| 2902 | |||
| 2903 | 78747 | typed_nargs := listReverse(typed_nargs); | |
| 2904 | 78747 | then | |
| 2905 | ARG_TYPED_CALL(call.ref, typed_args, typed_nargs, call.call_scope); | ||
| 2906 | end match; | ||
| 2907 | end typeArgs; | ||
| 2908 | |||
| 2909 | function checkMatchingFunctions | ||
| 2910 | input NFCall call; | ||
| 2911 | input InstContext.Type context; | ||
| 2912 | input SourceInfo info; | ||
| 2913 | input Boolean vectorize = true; | ||
| 2914 | output MatchedFunction matchedFunc; | ||
| 2915 | protected | ||
| 2916 | list<MatchedFunction> matchedFunctions, exactMatches; | ||
| 2917 | Function func; | ||
| 2918 | list<Function> allfuncs; | ||
| 2919 | InstNode fn_node; | ||
| 2920 | Integer numerr = Error.getNumErrorMessages(); | ||
| 2921 | algorithm | ||
| 2922 | 78603 | ErrorExt.setCheckpoint("NFCall:checkMatchingFunctions"); | |
| 2923 | |||
| 2924 | matchedFunctions := match call | ||
| 2925 | case ARG_TYPED_CALL(ref = ComponentRef.CREF()) | ||
| 2926 | algorithm | ||
| 2927 | 78603 | fn_node := ComponentRef.node(call.ref); | |
| 2928 | 78603 | allfuncs := Function.getCachedFuncs(fn_node); | |
| 2929 | |||
| 2930 |
2/2✓ Branch 1 taken 8391 times.
✓ Branch 2 taken 70212 times.
|
78603 | if listLength(allfuncs) > 1 then |
| 2931 |
6/6✓ Branch 1 taken 1050 times.
✓ Branch 2 taken 28731 times.
✓ Branch 3 taken 29781 times.
✓ Branch 4 taken 8391 times.
✓ Branch 5 taken 28731 times.
✓ Branch 6 taken 8391 times.
|
38172 | allfuncs := list(fn for fn guard not Function.isDefaultRecordConstructor(fn) in allfuncs); |
| 2932 | end if; | ||
| 2933 | 78603 | then | |
| 2934 | Function.matchFunctions(allfuncs, call.positional_args, call.named_args, context, info, vectorize, | ||
| 2935 | callPrefix = ComponentRef.stripClassScope(ComponentRef.rest(call.ref))); | ||
| 2936 | end match; | ||
| 2937 | |||
| 2938 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 78598 times.
|
78603 | if listEmpty(matchedFunctions) then |
| 2939 | // Don't show error messages for overloaded functions, it leaks | ||
| 2940 | // implementation details and usually doesn't provide any more info than | ||
| 2941 | // what the "no match found" error gives anyway. | ||
| 2942 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 3 times.
|
5 | if listLength(allfuncs) > 1 then |
| 2943 | 2 | ErrorExt.rollBack("NFCall:checkMatchingFunctions"); | |
| 2944 | 6 | Error.addSourceMessage(Error.NO_MATCHING_FUNCTION_FOUND_NFINST, | |
| 2945 | {typedString(call), Function.candidateFuncListString(allfuncs)}, info); | ||
| 2946 | |||
| 2947 | // Only show the error message for no matching functions if no other error | ||
| 2948 | // was shown. | ||
| 2949 | // functions that for some reason failed to match without giving any error. | ||
| 2950 | elseif numerr == Error.getNumErrorMessages() then | ||
| 2951 | ✗ | ErrorExt.rollBack("NFCall:checkMatchingFunctions"); | |
| 2952 | ✗ | Error.addSourceMessage(Error.NO_MATCHING_FUNCTION_FOUND_NFINST, | |
| 2953 | {typedString(call), Function.candidateFuncListString(allfuncs)}, info); | ||
| 2954 | else | ||
| 2955 | 3 | ErrorExt.delCheckpoint("NFCall:checkMatchingFunctions"); | |
| 2956 | end if; | ||
| 2957 | |||
| 2958 | 5 | fail(); | |
| 2959 | end if; | ||
| 2960 | |||
| 2961 | // If we have at least one matching function then we discard all error messages | ||
| 2962 | // about matching. We have one matching func if we reach here. | ||
| 2963 | 78598 | ErrorExt.rollBack("NFCall:checkMatchingFunctions"); | |
| 2964 | |||
| 2965 |
2/2✓ Branch 1 taken 519 times.
✓ Branch 2 taken 78079 times.
|
78598 | if listLength(matchedFunctions) > 1 then |
| 2966 | 519 | exactMatches := MatchedFunction.getExactMatches(matchedFunctions); | |
| 2967 | |||
| 2968 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 518 times.
|
519 | if listEmpty(exactMatches) then |
| 2969 | 1 | exactMatches := MatchedFunction.getExactVectorizedMatches(matchedFunctions); | |
| 2970 | end if; | ||
| 2971 | |||
| 2972 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 519 times.
|
519 | if listLength(exactMatches) > 1 then |
| 2973 | ✗ | Error.addSourceMessage(Error.AMBIGUOUS_MATCHING_FUNCTIONS_NFINST, | |
| 2974 | {typedString(call), Function.candidateFuncListString(list(mfn.func for mfn in matchedFunctions))}, info); | ||
| 2975 | ✗ | fail(); | |
| 2976 | end if; | ||
| 2977 | |||
| 2978 | 519 | matchedFunc := listHead(exactMatches); | |
| 2979 | else | ||
| 2980 | 78079 | matchedFunc := listHead(matchedFunctions); | |
| 2981 | end if; | ||
| 2982 | |||
| 2983 | // Overwrite the actual function name with the overload name for builtin functions. | ||
| 2984 |
2/2✓ Branch 1 taken 59733 times.
✓ Branch 2 taken 18865 times.
|
78598 | if Function.isBuiltin(matchedFunc.func) then |
| 2985 | 18865 | func := matchedFunc.func; | |
| 2986 | 18865 | func.path := Function.nameConsiderBuiltin(func); | |
| 2987 | 18865 | matchedFunc.func := func; | |
| 2988 | end if; | ||
| 2989 | end checkMatchingFunctions; | ||
| 2990 | |||
| 2991 | function iteratorToDAE | ||
| 2992 | input tuple<InstNode, Expression> iter; | ||
| 2993 | output DAE.ReductionIterator diter; | ||
| 2994 | protected | ||
| 2995 | InstNode iter_node; | ||
| 2996 | Expression iter_range; | ||
| 2997 | algorithm | ||
| 2998 | 598 | (iter_node, iter_range) := iter; | |
| 2999 | 598 | diter := DAE.REDUCTIONITER(InstNode.name(iter_node), Expression.toDAE(iter_range), NONE(), | |
| 3000 | Type.toDAE(InstNode.getType(iter_node))); | ||
| 3001 | end iteratorToDAE; | ||
| 3002 | |||
| 3003 | function vectorizeCall | ||
| 3004 | input NFCall base_call; | ||
| 3005 | input FunctionMatchKind mk; | ||
| 3006 | input NFInstNode.ScopeRef scope; | ||
| 3007 | input SourceInfo info; | ||
| 3008 | output NFCall vectorized_call; | ||
| 3009 | protected | ||
| 3010 | Type ty, vect_ty; | ||
| 3011 | Expression exp; | ||
| 3012 | list<tuple<InstNode, Expression>> iters; | ||
| 3013 | InstNode iter; | ||
| 3014 | Integer i; | ||
| 3015 | list<Expression> call_args; | ||
| 3016 | Subscript sub; | ||
| 3017 | algorithm | ||
| 3018 | vectorized_call := match (base_call, mk) | ||
| 3019 | case (TYPED_CALL(arguments = call_args), FunctionMatchKind.VECTORIZED()) | ||
| 3020 | algorithm | ||
| 3021 | iters := {}; | ||
| 3022 | i := 1; | ||
| 3023 | |||
| 3024 |
2/2✓ Branch 0 taken 1523 times.
✓ Branch 1 taken 1515 times.
|
3038 | for dim in mk.vectDims loop |
| 3025 | 1523 | Error.assertion(Dimension.isKnown(dim, allowExp = true), getInstanceName() + | |
| 3026 | " got unknown dimension for vectorized call", info); | ||
| 3027 | |||
| 3028 | // Create the range on which we will iterate to vectorize. | ||
| 3029 | 1523 | ty := Type.ARRAY(Type.INTEGER(), {dim}); | |
| 3030 | 1523 | exp := Expression.RANGE(ty, Expression.INTEGER(1), NONE(), Dimension.sizeExp(dim)); | |
| 3031 | |||
| 3032 | // Create the iterator. | ||
| 3033 | 1523 | iter := InstNode.newUniqueIterator(info); | |
| 3034 | 1523 | iters := (iter, exp) :: iters; | |
| 3035 | |||
| 3036 | // Now that iterator is ready apply it, as a subscript, to each argument that is supposed to be vectorized | ||
| 3037 | // Make a cref expression from the iterator | ||
| 3038 | 1523 | exp := Expression.CREF(Type.INTEGER(), ComponentRef.makeIterator(iter, Type.INTEGER())); | |
| 3039 | 1523 | sub := Subscript.INDEX(exp); | |
| 3040 | |||
| 3041 | 1523 | call_args := List.mapIndices(call_args, mk.vectorizedArgs, | |
| 3042 | function Expression.applySubscript(subscript = sub, restSubscripts = {}, applyToScope = false)); | ||
| 3043 | |||
| 3044 | i := i + 1; | ||
| 3045 | end for; | ||
| 3046 | |||
| 3047 | 1515 | vect_ty := Type.liftArrayLeftList(base_call.ty, mk.vectDims); | |
| 3048 | 1515 | base_call.arguments := call_args; | |
| 3049 | 1515 | then | |
| 3050 | TYPED_ARRAY_CONSTRUCTOR(vect_ty, base_call.var, base_call.purity, Expression.CALL(base_call), iters); | ||
| 3051 | |||
| 3052 | else | ||
| 3053 | algorithm | ||
| 3054 | ✗ | Error.addInternalError(getInstanceName() + " got unknown call", info); | |
| 3055 | ✗ | then | |
| 3056 | fail(); | ||
| 3057 | |||
| 3058 | end match; | ||
| 3059 | end vectorizeCall; | ||
| 3060 | |||
| 3061 | function isVectorized | ||
| 3062 | input NFCall call; | ||
| 3063 | output Boolean vectorized; | ||
| 3064 | algorithm | ||
| 3065 | vectorized := match call | ||
| 3066 | // A call is considered to be vectorized if the first iterator has a name | ||
| 3067 | // beginning with $. | ||
| 3068 | case TYPED_ARRAY_CONSTRUCTOR(exp = Expression.CALL()) | ||
| 3069 | ✗ | then stringGet(InstNode.name(Util.tuple21(listHead(call.iters))), 1) == 36; /* $ */ | |
| 3070 | else false; | ||
| 3071 | end match; | ||
| 3072 | end isVectorized; | ||
| 3073 | |||
| 3074 | function devectorizeCall | ||
| 3075 | "Transforms a vectorized call into a non-vectorized one. This function is | ||
| 3076 | used as a helper to output valid flat Modelica, and should probably not | ||
| 3077 | be used where e.g. correct types are required." | ||
| 3078 | input NFCall call; | ||
| 3079 | output Expression result; | ||
| 3080 | protected | ||
| 3081 | Expression exp, iter_exp; | ||
| 3082 | list<tuple<InstNode, Expression>> iters; | ||
| 3083 | InstNode iter_node; | ||
| 3084 | algorithm | ||
| 3085 | ✗ | TYPED_ARRAY_CONSTRUCTOR(exp = exp, iters = iters) := call; | |
| 3086 | |||
| 3087 | ✗ | for i in iters loop | |
| 3088 | ✗ | (iter_node, iter_exp) := i; | |
| 3089 | ✗ | exp := Expression.replaceIterator(exp, iter_node, iter_exp); | |
| 3090 | end for; | ||
| 3091 | |||
| 3092 | ✗ | result := SimplifyExp.simplify(exp); | |
| 3093 | end devectorizeCall; | ||
| 3094 | |||
| 3095 | function evaluateCallType | ||
| 3096 | "Replaces references to inputs in a call's return type with the call's | ||
| 3097 | arguments, in order to determine e.g. the sizes of output arrays." | ||
| 3098 | input output Type ty; | ||
| 3099 | input Function fn; | ||
| 3100 | input list<Expression> args; | ||
| 3101 | input Integer outputIndex = 1; | ||
| 3102 | input output ParameterTree ptree = ParameterTree.EMPTY(); | ||
| 3103 | protected | ||
| 3104 | list<Dimension> dims; | ||
| 3105 | list<Type> tys; | ||
| 3106 | Binding binding; | ||
| 3107 | Expression binding_exp; | ||
| 3108 | Type t; | ||
| 3109 | Integer output_index; | ||
| 3110 | algorithm | ||
| 3111 | ty := match ty | ||
| 3112 | case Type.ARRAY() | ||
| 3113 | algorithm | ||
| 3114 | 17373 | (dims, ptree) := List.mapFold(ty.dimensions, function evaluateCallTypeDim(fn = fn, args = args), ptree); | |
| 3115 | 17373 | ty.dimensions := dims; | |
| 3116 | then | ||
| 3117 | ty; | ||
| 3118 | |||
| 3119 | case Type.TUPLE() | ||
| 3120 | algorithm | ||
| 3121 | tys := {}; | ||
| 3122 | output_index := 1; | ||
| 3123 | |||
| 3124 |
2/2✓ Branch 0 taken 2557 times.
✓ Branch 1 taken 1131 times.
|
3688 | for t in ty.types loop |
| 3125 | 2557 | (t, ptree) := evaluateCallType(t, fn, args, output_index, ptree); | |
| 3126 | tys := t :: tys; | ||
| 3127 | 2557 | output_index := output_index + 1; | |
| 3128 | end for; | ||
| 3129 | |||
| 3130 | 1131 | ty.types := listReverseInPlace(tys); | |
| 3131 | then | ||
| 3132 | ty; | ||
| 3133 | |||
| 3134 | // A normal record output | ||
| 3135 | case Type.COMPLEX() | ||
| 3136 | guard Type.isRecord(ty) and not Function.isNonDefaultRecordConstructor(fn) | ||
| 3137 | algorithm | ||
| 3138 | 10333 | binding := Component.getBinding(InstNode.component(InstNode.fromHandle(listGet(fn.outputs, outputIndex)))); | |
| 3139 | |||
| 3140 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 10332 times.
|
10333 | if Binding.isBound(binding) then |
| 3141 | // If the output has a binding, replace inputs in it and update the type of the output. | ||
| 3142 | 1 | binding_exp := Binding.getExp(binding); | |
| 3143 | 1 | ptree := buildParameterTree(fn, args, ptree); | |
| 3144 | 1 | binding_exp := Expression.map(binding_exp, function evaluateCallTypeDimExp(ptree = ptree)); | |
| 3145 | 1 | t := Expression.typeOf(binding_exp); | |
| 3146 | else | ||
| 3147 | t := ty; | ||
| 3148 | end if; | ||
| 3149 | then | ||
| 3150 | t; | ||
| 3151 | |||
| 3152 | else ty; | ||
| 3153 | end match; | ||
| 3154 | end evaluateCallType; | ||
| 3155 | |||
| 3156 | function evaluateCallTypeDim | ||
| 3157 | input output Dimension dim; | ||
| 3158 | input Function fn; | ||
| 3159 | input list<Expression> args; | ||
| 3160 | input output ParameterTree ptree; | ||
| 3161 | algorithm | ||
| 3162 | dim := match dim | ||
| 3163 | local | ||
| 3164 | Expression exp; | ||
| 3165 | Dimension new_dim; | ||
| 3166 | |||
| 3167 | case Dimension.EXP() | ||
| 3168 | algorithm | ||
| 3169 | 2749 | ptree := buildParameterTree(fn, args, ptree); | |
| 3170 | 2749 | exp := Expression.map(dim.exp, function evaluateCallTypeDimExp(ptree = ptree)); | |
| 3171 | // size(x, i) of a resizable dimension is its expression (e.g. N), the | ||
| 3172 | // dimension of the output stays resizable instead of being evaluated | ||
| 3173 | 2749 | exp := Expression.map(exp, resizableSizeExp); | |
| 3174 | |||
| 3175 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2749 times.
|
2749 | if Expression.contains(exp, Expression.isResizableCref) then |
| 3176 | ✗ | new_dim := Dimension.fromExp(SimplifyExp.simplify(exp), Variability.NON_STRUCTURAL_PARAMETER); | |
| 3177 | else | ||
| 3178 | 2749 | ErrorExt.setCheckpoint(getInstanceName()); | |
| 3179 | try | ||
| 3180 | 2749 | Structural.markExp(exp); | |
| 3181 | 2749 | exp := Ceval.evalExp(exp); | |
| 3182 | else | ||
| 3183 | end try; | ||
| 3184 | 2749 | ErrorExt.rollBack(getInstanceName()); | |
| 3185 | 2749 | new_dim := Dimension.fromExp(exp, Variability.CONSTANT); | |
| 3186 | end if; | ||
| 3187 | then | ||
| 3188 | new_dim; | ||
| 3189 | |||
| 3190 | else dim; | ||
| 3191 | end match; | ||
| 3192 | end evaluateCallTypeDim; | ||
| 3193 | |||
| 3194 | function resizableSizeExp | ||
| 3195 | "size(x, i) -> the expression of dimension i of x if it is resizable" | ||
| 3196 | input Expression exp; | ||
| 3197 | output Expression outExp = exp; | ||
| 3198 | protected | ||
| 3199 | Integer i; | ||
| 3200 | Dimension d; | ||
| 3201 | algorithm | ||
| 3202 | () := match exp | ||
| 3203 | case Expression.SIZE(dimIndex = SOME(Expression.INTEGER(i))) algorithm | ||
| 3204 | try | ||
| 3205 | 2057 | d := Type.nthDimension(Expression.typeOf(exp.exp), i); | |
| 3206 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2057 times.
|
2057 | if Dimension.isResizable(d) then |
| 3207 | ✗ | outExp := Dimension.sizeExp(d); | |
| 3208 | end if; | ||
| 3209 | else | ||
| 3210 | end try; | ||
| 3211 | then (); | ||
| 3212 | else (); | ||
| 3213 | end match; | ||
| 3214 | end resizableSizeExp; | ||
| 3215 | |||
| 3216 | function buildParameterTree | ||
| 3217 | input Function fn; | ||
| 3218 | input list<Expression> args; | ||
| 3219 | input output ParameterTree ptree; | ||
| 3220 | protected | ||
| 3221 | Expression arg; | ||
| 3222 | list<Expression> rest_args = args; | ||
| 3223 | algorithm | ||
| 3224 |
2/2✓ Branch 1 taken 810 times.
✓ Branch 2 taken 1940 times.
|
2750 | if not ParameterTree.isEmpty(ptree) then |
| 3225 | 810 | return; | |
| 3226 | end if; | ||
| 3227 | |||
| 3228 |
2/2✓ Branch 0 taken 3207 times.
✓ Branch 1 taken 1940 times.
|
5147 | for i in fn.inputs loop |
| 3229 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3207 times.
|
3207 | arg :: rest_args := rest_args; |
| 3230 | 3207 | ptree := ParameterTree.add(ptree, InstNode.name(i), arg); | |
| 3231 | end for; | ||
| 3232 | |||
| 3233 | // TODO: Add local variable bindings. | ||
| 3234 | end buildParameterTree; | ||
| 3235 | |||
| 3236 | function evaluateCallTypeDimExp | ||
| 3237 | input Expression exp; | ||
| 3238 | input ParameterTree ptree; | ||
| 3239 | output Expression outExp; | ||
| 3240 | protected | ||
| 3241 | list<ComponentRef> cref_parts; | ||
| 3242 | ComponentRef cref; | ||
| 3243 | Option<Expression> oexp; | ||
| 3244 | algorithm | ||
| 3245 | outExp := match exp | ||
| 3246 | case Expression.CREF(cref = ComponentRef.CREF()) | ||
| 3247 | algorithm | ||
| 3248 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2854 times.
|
2854 | cref :: cref_parts := ComponentRef.toListReverse(exp.cref); |
| 3249 | 2854 | oexp := ParameterTree.getOpt(ptree, ComponentRef.nodeName(cref)); | |
| 3250 | |||
| 3251 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 2854 times.
✓ Branch 2 taken 2853 times.
✓ Branch 3 taken 1 time.
|
2854 | if isSome(oexp) then |
| 3252 | 2853 | SOME(outExp) := oexp; | |
| 3253 | 2853 | outExp := Expression.applySubscripts(ComponentRef.getSubscripts(cref), outExp); | |
| 3254 | |||
| 3255 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2853 times.
|
2856 | for cr in cref_parts loop |
| 3256 | 3 | outExp := Expression.recordElement(ComponentRef.nodeName(cr), outExp); | |
| 3257 | 3 | outExp := Expression.applySubscripts(ComponentRef.getSubscripts(cr), outExp); | |
| 3258 | end for; | ||
| 3259 | else | ||
| 3260 | outExp := exp; | ||
| 3261 | end if; | ||
| 3262 | then | ||
| 3263 | outExp; | ||
| 3264 | |||
| 3265 | else exp; | ||
| 3266 | end match; | ||
| 3267 | end evaluateCallTypeDimExp; | ||
| 3268 | |||
| 3269 | function resolvePolymorphicReturnType | ||
| 3270 | "Resolves a polymorphic type to the actual type based on the inputs of a function." | ||
| 3271 | input Function fn; | ||
| 3272 | input list<TypedArg> args; | ||
| 3273 | input Type ty; | ||
| 3274 | output Type outType; | ||
| 3275 | protected | ||
| 3276 | String name; | ||
| 3277 | Type input_ty; | ||
| 3278 | TypedArg arg; | ||
| 3279 | list<TypedArg> rest_args = args; | ||
| 3280 | algorithm | ||
| 3281 | outType := match ty | ||
| 3282 | case Type.POLYMORPHIC(name = name) | ||
| 3283 | algorithm | ||
| 3284 | // Go through the inputs until we find one with the same polymorphic | ||
| 3285 | // type as the one we're looking for. | ||
| 3286 |
2/2✓ Branch 0 taken 3601 times.
✓ Branch 1 taken 1706 times.
|
5307 | for i in fn.inputs loop |
| 3287 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3601 times.
|
3601 | arg :: rest_args := rest_args; |
| 3288 | 3601 | input_ty := InstNode.getType(i); | |
| 3289 | |||
| 3290 |
2/2✓ Branch 2 taken 1895 times.
✓ Branch 3 taken 1706 times.
|
3601 | if Type.isPolymorphicNamed(Type.arrayElementType(input_ty), name) then |
| 3291 | // Replace the type with the corresponding argument type, but | ||
| 3292 | // remove as many dimensions from it as the input has. | ||
| 3293 | // For example: T[:] and Real[2, 3] gives T = Real[3] | ||
| 3294 | 1895 | outType := Type.unliftArrayN(Type.dimensionCount(input_ty), arg.ty); | |
| 3295 | 1895 | return; | |
| 3296 | end if; | ||
| 3297 | end for; | ||
| 3298 | |||
| 3299 | // If no input with the same type could be found and the result type | ||
| 3300 | // is __Scalar, try to find some input with the type __Array and | ||
| 3301 | // assume they have the same element type. | ||
| 3302 |
2/4✓ Branch 0 taken 1706 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1706 times.
✗ Branch 4 not taken.
|
1706 | if name == "__Scalar" then |
| 3303 | 1706 | outType := resolvePolymorphicReturnType(fn, args, Type.POLYMORPHIC("__Array")); | |
| 3304 | 1706 | outType := Type.arrayElementType(outType); | |
| 3305 | 1706 | return; | |
| 3306 | end if; | ||
| 3307 | ✗ | then | |
| 3308 | fail(); | ||
| 3309 | |||
| 3310 | case Type.ARRAY(elementType = Type.POLYMORPHIC()) | ||
| 3311 | algorithm | ||
| 3312 | // For an array of polymorphic types, only resolve the polymorphic | ||
| 3313 | // type itself and keep the dimensions. | ||
| 3314 | 109 | ty.elementType := resolvePolymorphicReturnType(fn, args, ty.elementType); | |
| 3315 | then | ||
| 3316 | ty; | ||
| 3317 | |||
| 3318 | else ty; | ||
| 3319 | end match; | ||
| 3320 | end resolvePolymorphicReturnType; | ||
| 3321 | |||
| 3322 | annotation(__OpenModelica_Interface="nf_frontend"); | ||
| 3323 | end NFCall; | ||
| 3324 |