OMCompiler/Compiler/NFFrontEnd/NFDimension.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 NFDimension | ||
| 37 | protected | ||
| 38 | import Absyn; | ||
| 39 | import Dimension = NFDimension; | ||
| 40 | import DAE; | ||
| 41 | import Dump; | ||
| 42 | import Operator = NFOperator; | ||
| 43 | import Prefixes = NFPrefixes; | ||
| 44 | import List; | ||
| 45 | import SimplifyExp = NFSimplifyExp; | ||
| 46 | import Ceval = NFCeval; | ||
| 47 | |||
| 48 | public | ||
| 49 | import BaseModelica; | ||
| 50 | import Absyn.{Exp, Path, Subscript}; | ||
| 51 | import Class = NFClass; | ||
| 52 | import Expression = NFExpression; | ||
| 53 | import NFInstNode.InstNode; | ||
| 54 | import NFInstNode; | ||
| 55 | import Type = NFType; | ||
| 56 | import ComponentRef = NFComponentRef; | ||
| 57 | import NFPrefixes.Variability; | ||
| 58 | import Inst = NFInst; | ||
| 59 | import NFCeval.EvalTarget; | ||
| 60 | |||
| 61 | record RAW_DIM | ||
| 62 | Absyn.Subscript dim; | ||
| 63 | NFInstNode.ScopeRef scope "Weakly: the class tree owns the scope this | ||
| 64 | dimension was written in."; | ||
| 65 | end RAW_DIM; | ||
| 66 | |||
| 67 | record UNTYPED | ||
| 68 | Expression dimension; | ||
| 69 | Boolean isProcessing; | ||
| 70 | end UNTYPED; | ||
| 71 | |||
| 72 | record INTEGER | ||
| 73 | Integer size; | ||
| 74 | Variability var; | ||
| 75 | end INTEGER; | ||
| 76 | |||
| 77 | record BOOLEAN | ||
| 78 | end BOOLEAN; | ||
| 79 | |||
| 80 | record ENUM | ||
| 81 | Type enumType; | ||
| 82 | end ENUM; | ||
| 83 | |||
| 84 | record EXP | ||
| 85 | Expression exp; | ||
| 86 | Variability var; | ||
| 87 | end EXP; | ||
| 88 | |||
| 89 | record RESIZABLE | ||
| 90 | "for all symbolic purposes this is INTEGER() for codegeneration it is EXP() | ||
| 91 | invoked by using annotation(__OpenModelica_resizable=true) on a parameter" | ||
| 92 | Integer size "the actual size defined by the user"; | ||
| 93 | Option<Integer> opt_size "the optimal size determined by the backend"; | ||
| 94 | Expression exp "the full expression (parameter)"; | ||
| 95 | Variability var; | ||
| 96 | end RESIZABLE; | ||
| 97 | |||
| 98 | record UNKNOWN | ||
| 99 | end UNKNOWN; | ||
| 100 | |||
| 101 | function fromExp | ||
| 102 | input Expression exp; | ||
| 103 | input Variability var; | ||
| 104 | output Dimension dim; | ||
| 105 | algorithm | ||
| 106 | dim := match exp | ||
| 107 | local | ||
| 108 | Expression exp_simple, e1, e2; | ||
| 109 | Integer value, value_original; | ||
| 110 | Type ty; | ||
| 111 | |||
| 112 | 179261 | case Expression.INTEGER() then INTEGER(exp.value, var); | |
| 113 | |||
| 114 | case Expression.TYPENAME(ty = Type.ARRAY(elementType = ty)) | ||
| 115 | then | ||
| 116 | match ty | ||
| 117 | case Type.BOOLEAN() then BOOLEAN(); | ||
| 118 | 51 | case Type.ENUMERATION() then ENUM(ty); | |
| 119 | else | ||
| 120 | algorithm | ||
| 121 | ✗ | Error.terminate(getInstanceName() + " got invalid typename", sourceInfo()); | |
| 122 | ✗ | then | |
| 123 | fail(); | ||
| 124 | end match; | ||
| 125 | |||
| 126 | case Expression.ARRAY() | ||
| 127 | guard Expression.arrayAllEqual(exp) | ||
| 128 | ✗ | then fromExp(Expression.arrayFirstScalar(exp), var); | |
| 129 | |||
| 130 | case Expression.SUBSCRIPTED_EXP(split = true) | ||
| 131 | guard Expression.isArray(exp.exp) and Expression.arrayAllEqual(exp.exp) | ||
| 132 | 1 | then fromExp(Expression.arrayFirstScalar(exp.exp), var); | |
| 133 | |||
| 134 | else algorithm | ||
| 135 | 26305 | exp_simple := SimplifyExp.simplify(exp); | |
| 136 | then match exp_simple | ||
| 137 | // if it can be simplified to an integer its just an integer | ||
| 138 | 559 | case Expression.INTEGER(value) then INTEGER(value, var); | |
| 139 | // if it can be simplified to an integer after replacing resizables its resizable | ||
| 140 | else algorithm | ||
| 141 | 25746 | e1 := Expression.map(exp_simple, Expression.replaceResizableParameter); | |
| 142 | 25746 | e1 := SimplifyExp.simplify(e1); | |
| 143 | then match e1 | ||
| 144 | case Expression.INTEGER(value) algorithm | ||
| 145 | // if replacing the body with original yields another solution, it has already been resized | ||
| 146 | 704 | e2 := Expression.map(exp_simple, Expression.replaceResizableParameterWithOriginal); | |
| 147 | 704 | e2 := SimplifyExp.simplify(e2); | |
| 148 | then match e2 | ||
| 149 | ✗ | case Expression.INTEGER(value_original) guard(value <> value_original) then RESIZABLE(value_original, SOME(value), exp, var); | |
| 150 | 704 | else RESIZABLE(value, NONE(), exp, var); | |
| 151 | end match; | ||
| 152 | // otherwise it is just an expression | ||
| 153 | 25042 | else EXP(exp, var); | |
| 154 | end match; | ||
| 155 | end match; | ||
| 156 | end match; | ||
| 157 | end fromExp; | ||
| 158 | |||
| 159 | function fromRange | ||
| 160 | input Expression range "needs to be RANGE()"; | ||
| 161 | output Dimension dim; | ||
| 162 | protected | ||
| 163 | Integer start, step, stop; | ||
| 164 | algorithm | ||
| 165 | (start, step, stop) := match range | ||
| 166 | case Expression.RANGE(start = Expression.INTEGER(start), | ||
| 167 | step = NONE(), | ||
| 168 | stop = Expression.INTEGER(stop)) | ||
| 169 | then (start, 1, stop); | ||
| 170 | case Expression.RANGE(start = Expression.INTEGER(start), | ||
| 171 | step = SOME(Expression.INTEGER(step)), | ||
| 172 | stop = Expression.INTEGER(stop)) | ||
| 173 | then (start, step, stop); | ||
| 174 | else algorithm | ||
| 175 | ✗ | Error.terminate(getInstanceName() + " got non-range expression: " + Expression.toString(range), sourceInfo()); | |
| 176 | ✗ | then fail(); | |
| 177 | end match; | ||
| 178 | |||
| 179 | ✗ | dim := INTEGER(intDiv(stop-start, step) + 1, NFPrefixes.Variability.CONSTANT); | |
| 180 | end fromRange; | ||
| 181 | |||
| 182 | function fromInteger | ||
| 183 | input Integer n; | ||
| 184 | input Variability var = Variability.CONSTANT; | ||
| 185 | output Dimension dim = INTEGER(n, var); | ||
| 186 | end fromInteger; | ||
| 187 | |||
| 188 | function fromExpArray | ||
| 189 | input array<Expression> expl; | ||
| 190 | output Dimension dim = INTEGER(arrayLength(expl), Variability.CONSTANT); | ||
| 191 | end fromExpArray; | ||
| 192 | |||
| 193 | function fromExpList | ||
| 194 | input list<Expression> expl; | ||
| 195 | output Dimension dim = INTEGER(listLength(expl), Variability.CONSTANT); | ||
| 196 | end fromExpList; | ||
| 197 | |||
| 198 | function toRange | ||
| 199 | input Dimension dim; | ||
| 200 | output Expression range; | ||
| 201 | algorithm | ||
| 202 | 32 | range := Expression.RANGE(Type.liftArrayLeft(typeOf(dim), dim), | |
| 203 | lowerBoundExp(dim), NONE(), upperBoundExp(dim)); | ||
| 204 | end toRange; | ||
| 205 | |||
| 206 | function toDAE | ||
| 207 | input Dimension dim; | ||
| 208 | output DAE.Dimension daeDim; | ||
| 209 | algorithm | ||
| 210 | daeDim := match dim | ||
| 211 | local | ||
| 212 | Type ty; | ||
| 213 | |||
| 214 | 1040923 | case INTEGER() then DAE.DIM_INTEGER(dim.size); | |
| 215 | case BOOLEAN() then DAE.DIM_BOOLEAN(); | ||
| 216 | case ENUM(enumType = ty as Type.ENUMERATION()) | ||
| 217 | 1338 | then DAE.DIM_ENUM(ty.typePath, ty.literals, listLength(ty.literals)); | |
| 218 | 5300 | case EXP() then DAE.DIM_EXP(Expression.toDAE(dim.exp)); | |
| 219 | 2716 | case RESIZABLE() then DAE.DIM_EXP(Expression.toDAE(dim.exp)); | |
| 220 | case UNKNOWN() then DAE.DIM_UNKNOWN(); | ||
| 221 | end match; | ||
| 222 | end toDAE; | ||
| 223 | |||
| 224 | function add | ||
| 225 | input Dimension a, b; | ||
| 226 | output Dimension c; | ||
| 227 | protected | ||
| 228 | function addExp | ||
| 229 | input Expression e1; | ||
| 230 | input Expression e2; | ||
| 231 | output Expression res = Expression.BINARY(e1, Operator.OPERATOR(Type.INTEGER(), NFOperator.Op.ADD), e2); | ||
| 232 | end addExp; | ||
| 233 | function addOpt | ||
| 234 | input Option<Integer> s1; | ||
| 235 | input Option<Integer> s2; | ||
| 236 | output Option<Integer> res; | ||
| 237 | algorithm | ||
| 238 | res := match (s1, s2) | ||
| 239 | local | ||
| 240 | Integer i1, i2; | ||
| 241 | ✗ | case (SOME(i1), SOME(i2)) then SOME(i1+i2); | |
| 242 | else NONE(); | ||
| 243 | end match; | ||
| 244 | end addOpt; | ||
| 245 | algorithm | ||
| 246 | c := match (a, b) | ||
| 247 | case (UNKNOWN(),_) then UNKNOWN(); | ||
| 248 | case (_,UNKNOWN()) then UNKNOWN(); | ||
| 249 | 25172 | case (INTEGER(),INTEGER()) then INTEGER(a.size+b.size, Prefixes.variabilityMax(a.var, b.var)); | |
| 250 | 12 | case (INTEGER(),EXP()) then EXP(addExp(b.exp, Expression.INTEGER(a.size)), b.var); | |
| 251 | 5 | case (EXP(),INTEGER()) then EXP(addExp(a.exp, Expression.INTEGER(b.size)), a.var); | |
| 252 | 7 | case (EXP(),EXP()) then EXP(addExp(a.exp, b.exp), Prefixes.variabilityMax(a.var, b.var)); | |
| 253 | ✗ | case (INTEGER(),RESIZABLE()) then RESIZABLE(a.size+b.size, addOpt(SOME(a.size), b.opt_size), addExp(b.exp, Expression.INTEGER(a.size)), b.var); | |
| 254 | ✗ | case (RESIZABLE(),INTEGER()) then RESIZABLE(a.size+b.size, addOpt(a.opt_size, SOME(b.size)), addExp(a.exp, Expression.INTEGER(b.size)), a.var); | |
| 255 | ✗ | case (EXP(),RESIZABLE()) then EXP(addExp(a.exp, b.exp), Prefixes.variabilityMax(a.var, b.var)); | |
| 256 | ✗ | case (RESIZABLE(),EXP()) then EXP(addExp(a.exp, b.exp), Prefixes.variabilityMax(a.var, b.var)); | |
| 257 | ✗ | case (RESIZABLE(),RESIZABLE()) then RESIZABLE(a.size+b.size, addOpt(a.opt_size, b.opt_size), addExp(a.exp, b.exp), Prefixes.variabilityMax(a.var, b.var)); | |
| 258 | else UNKNOWN(); | ||
| 259 | end match; | ||
| 260 | end add; | ||
| 261 | |||
| 262 | function size | ||
| 263 | input Dimension dim; | ||
| 264 | input Boolean resize = false; | ||
| 265 | output Integer size; | ||
| 266 | algorithm | ||
| 267 | size := match dim | ||
| 268 | local | ||
| 269 | Type ty; | ||
| 270 | |||
| 271 | 1117021 | case INTEGER() then dim.size; | |
| 272 |
2/2✓ Branch 0 taken 3602 times.
✓ Branch 1 taken 1376 times.
|
4978 | case RESIZABLE() then if resize then Util.getOptionOrDefault(dim.opt_size, dim.size) else dim.size; |
| 273 | case BOOLEAN() then 2; | ||
| 274 | 67 | case ENUM(enumType = ty as Type.ENUMERATION()) then listLength(ty.literals); | |
| 275 | else algorithm | ||
| 276 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 54 times.
|
54 | if Flags.isSet(Flags.FAILTRACE) then |
| 277 | ✗ | Error.addCompilerWarning(getInstanceName() + " could not get size of: " + toString(dim)); | |
| 278 | end if; | ||
| 279 | 54 | then fail(); | |
| 280 | end match; | ||
| 281 | end size; | ||
| 282 | |||
| 283 | function sizes | ||
| 284 | "Returns the sizes of the given dimension sizes." | ||
| 285 | input list<Dimension> dims; | ||
| 286 | input Boolean resize = false; | ||
| 287 | output list<Integer> outSizes = list(Dimension.size(d, resize) for d in dims); | ||
| 288 | end sizes; | ||
| 289 | |||
| 290 | function sizesProduct | ||
| 291 | "Returns the product of the given dimension sizes." | ||
| 292 | input list<Dimension> dims; | ||
| 293 | input Boolean resize = false; | ||
| 294 | output Integer outSize = product(Dimension.size(d, resize) for d in dims); | ||
| 295 | end sizesProduct; | ||
| 296 | |||
| 297 | function isEqual | ||
| 298 | input Dimension dim1; | ||
| 299 | input Dimension dim2; | ||
| 300 | output Boolean isEqual; | ||
| 301 | algorithm | ||
| 302 | isEqual := match (dim1, dim2) | ||
| 303 | case (UNKNOWN(), _) then true; | ||
| 304 | case (_, UNKNOWN()) then true; | ||
| 305 | case (EXP(), _) then true; | ||
| 306 | case (_, EXP()) then true; | ||
| 307 | 6 | case (RESIZABLE(), RESIZABLE()) then isEqualResizableExp(dim1.exp, dim2.exp); | |
| 308 | 22427 | else Dimension.size(dim1) == Dimension.size(dim2); | |
| 309 | end match; | ||
| 310 | end isEqual; | ||
| 311 | |||
| 312 | function isEqualResizableExp | ||
| 313 | "resizable size expressions can be in different forms (e.g. BINARY and MULTARY)" | ||
| 314 | input Expression exp1; | ||
| 315 | input Expression exp2; | ||
| 316 | output Boolean b = Expression.isEqual(exp1, exp2) or Expression.isEqual(canonicalExp(exp1), canonicalExp(exp2)); | ||
| 317 | end isEqualResizableExp; | ||
| 318 | |||
| 319 | function canonicalExp | ||
| 320 | input output Expression exp; | ||
| 321 | algorithm | ||
| 322 | 30 | exp := SimplifyExp.simplify(SimplifyExp.combineBinaries(exp)); | |
| 323 | end canonicalExp; | ||
| 324 | |||
| 325 | function isEqualKnown | ||
| 326 | input Dimension dim1; | ||
| 327 | input Dimension dim2; | ||
| 328 | output Boolean isEqual; | ||
| 329 | algorithm | ||
| 330 | isEqual := match (dim1, dim2) | ||
| 331 | case (UNKNOWN(), _) then false; | ||
| 332 | case (_, UNKNOWN()) then false; | ||
| 333 | 884 | case (EXP(), EXP()) then Expression.isEqual(dim1.exp, dim2.exp); | |
| 334 | 8 | case (RESIZABLE(), RESIZABLE()) then isEqualResizableExp(dim1.exp, dim2.exp); | |
| 335 | case (EXP(), _) then false; | ||
| 336 | case (_, EXP()) then false; | ||
| 337 | 332265 | else Dimension.size(dim1) == Dimension.size(dim2); | |
| 338 | end match; | ||
| 339 | end isEqualKnown; | ||
| 340 | |||
| 341 | function isEqualKnownSize | ||
| 342 | "Same as isEqualKnown, but also takes the nodes and dimension indices that | ||
| 343 | the dimensions come from in order to check for equality when one dimension | ||
| 344 | is a size-expression that refers to the other dimension." | ||
| 345 | input Dimension dim1; | ||
| 346 | input InstNode node1; | ||
| 347 | input Integer index1; | ||
| 348 | input Dimension dim2; | ||
| 349 | input InstNode node2; | ||
| 350 | input Integer index2; | ||
| 351 | output Boolean isEqual; | ||
| 352 | algorithm | ||
| 353 | isEqual := match (dim1, dim2) | ||
| 354 | // dim1 is equal to dim2 if dim1 = size(node2, ...) | ||
| 355 | case (EXP(), _) guard isSizeOf(dim1, node2, index2) then true; | ||
| 356 | |||
| 357 | // dim2 is equal to dim1 if dim2 = size(node1, ...) | ||
| 358 | case (_, EXP()) guard isSizeOf(dim2, node1, index1) then true; | ||
| 359 | |||
| 360 | ✗ | case (EXP(), EXP()) then Expression.isEqual(dim1.exp, dim2.exp); | |
| 361 | ✗ | case (RESIZABLE(), RESIZABLE()) then isEqualResizableExp(dim1.exp, dim2.exp); | |
| 362 | case (UNKNOWN(), _) then false; | ||
| 363 | case (_, UNKNOWN()) then false; | ||
| 364 | 5 | else Dimension.size(dim1) == Dimension.size(dim2); | |
| 365 | end match; | ||
| 366 | end isEqualKnownSize; | ||
| 367 | |||
| 368 | function isSame | ||
| 369 | input Dimension dim1; | ||
| 370 | input Dimension dim2; | ||
| 371 | output Boolean same; | ||
| 372 | algorithm | ||
| 373 | same := match (dim1, dim2) | ||
| 374 | case (RAW_DIM(), RAW_DIM()) | ||
| 375 | ✗ | then InstNode.isSame(InstNode.borrow(dim1.scope), InstNode.borrow(dim2.scope)) and | |
| 376 | AbsynUtil.subscriptEqual(dim1.dim, dim2.dim); | ||
| 377 | ✗ | case (UNTYPED(), UNTYPED()) then Expression.isEqual(dim1.dimension, dim2.dimension); | |
| 378 | 1782 | case (INTEGER(), INTEGER()) then dim1.size == dim2.size; | |
| 379 | case (BOOLEAN(), BOOLEAN()) then true; | ||
| 380 | ✗ | case (ENUM(), ENUM()) then Type.isEqual(dim1.enumType, dim2.enumType); | |
| 381 | ✗ | case (EXP(), EXP()) then Expression.isEqual(dim1.exp, dim2.exp); | |
| 382 | ✗ | case (RESIZABLE(), RESIZABLE()) then isEqualResizableExp(dim1.exp, dim2.exp); | |
| 383 | case (UNKNOWN(), UNKNOWN()) then true; | ||
| 384 | else false; | ||
| 385 | end match; | ||
| 386 | end isSame; | ||
| 387 | |||
| 388 | function isSizeOf | ||
| 389 | "Returns true if the dimension is size(node, index)." | ||
| 390 | input Dimension dim; | ||
| 391 | input InstNode node; | ||
| 392 | input Integer index; | ||
| 393 | output Boolean res; | ||
| 394 | protected | ||
| 395 | Expression cref_exp, index_exp; | ||
| 396 | algorithm | ||
| 397 | res := match dim | ||
| 398 | case EXP(exp = Expression.SIZE(exp = cref_exp as Expression.CREF(), dimIndex = SOME(index_exp))) | ||
| 399 | ✗ | then InstNode.refEqual(ComponentRef.node(cref_exp.cref), node) and | |
| 400 | Expression.isEqual(index_exp, Expression.INTEGER(index)); | ||
| 401 | |||
| 402 | else false; | ||
| 403 | end match; | ||
| 404 | end isSizeOf; | ||
| 405 | |||
| 406 | function isResizable | ||
| 407 | input Dimension dim; | ||
| 408 | output Boolean b; | ||
| 409 | algorithm | ||
| 410 | b := match dim | ||
| 411 | case RESIZABLE() then true; | ||
| 412 | else false; | ||
| 413 | end match; | ||
| 414 | end isResizable; | ||
| 415 | |||
| 416 | function allEqualKnown | ||
| 417 | input list<Dimension> dims1; | ||
| 418 | input list<Dimension> dims2; | ||
| 419 | output Boolean allEqual = List.isEqualOnTrue(dims1, dims2, isEqualKnown); | ||
| 420 | end allEqualKnown; | ||
| 421 | |||
| 422 | function isKnown | ||
| 423 | input Dimension dim; | ||
| 424 | input Boolean allowExp = false; | ||
| 425 | output Boolean known; | ||
| 426 | algorithm | ||
| 427 | known := match dim | ||
| 428 | case INTEGER() then true; | ||
| 429 | case BOOLEAN() then true; | ||
| 430 | case ENUM() then true; | ||
| 431 | case RESIZABLE() then true; | ||
| 432 | case EXP() then allowExp; | ||
| 433 | else false; | ||
| 434 | end match; | ||
| 435 | end isKnown; | ||
| 436 | |||
| 437 | function isUnknown | ||
| 438 | input Dimension dim; | ||
| 439 | output Boolean isUnknown; | ||
| 440 | algorithm | ||
| 441 | isUnknown := match dim | ||
| 442 | case UNKNOWN() then true; | ||
| 443 | else false; | ||
| 444 | end match; | ||
| 445 | end isUnknown; | ||
| 446 | |||
| 447 | function isZero | ||
| 448 | input Dimension dim; | ||
| 449 | output Boolean isZero; | ||
| 450 | algorithm | ||
| 451 | isZero := match dim | ||
| 452 | 429269 | case INTEGER() then dim.size == 0; | |
| 453 | 11 | case ENUM() then Type.enumSize(dim.enumType) == 0; | |
| 454 | else false; | ||
| 455 | end match; | ||
| 456 | end isZero; | ||
| 457 | |||
| 458 | function isOne | ||
| 459 | input Dimension dim; | ||
| 460 | output Boolean isOne; | ||
| 461 | algorithm | ||
| 462 | isOne := match dim | ||
| 463 | 2944 | case INTEGER() then dim.size == 1; | |
| 464 | ✗ | case ENUM() then Type.enumSize(dim.enumType) == 1; | |
| 465 | else false; | ||
| 466 | end match; | ||
| 467 | end isOne; | ||
| 468 | |||
| 469 | function subscriptType | ||
| 470 | "Returns the expected type of a subscript for the given dimension." | ||
| 471 | input Dimension dim; | ||
| 472 | output Type ty; | ||
| 473 | algorithm | ||
| 474 | ty := match dim | ||
| 475 | case INTEGER() then Type.INTEGER(); | ||
| 476 | case BOOLEAN() then Type.BOOLEAN(); | ||
| 477 | 208 | case ENUM() then dim.enumType; | |
| 478 | 3487 | case EXP() then Expression.typeOf(dim.exp); | |
| 479 | 57 | case RESIZABLE() then Expression.typeOf(dim.exp); | |
| 480 | else Type.UNKNOWN(); | ||
| 481 | end match; | ||
| 482 | end subscriptType; | ||
| 483 | |||
| 484 | function toString | ||
| 485 | input Dimension dim; | ||
| 486 | output String str; | ||
| 487 | algorithm | ||
| 488 | str := match dim | ||
| 489 | local | ||
| 490 | Type ty; | ||
| 491 | |||
| 492 | ✗ | case RAW_DIM() then Dump.printSubscriptStr(dim.dim); | |
| 493 | 1611 | case INTEGER() then String(dim.size); | |
| 494 | case BOOLEAN() then "Boolean"; | ||
| 495 | ✗ | case ENUM(enumType = ty as Type.ENUMERATION()) then AbsynUtil.pathString(ty.typePath); | |
| 496 | 1 | case EXP() then Expression.toString(dim.exp); | |
| 497 | 179 | case RESIZABLE() then Expression.toString(dim.exp) + "(R)"; | |
| 498 | case UNKNOWN() then ":"; | ||
| 499 | ✗ | case UNTYPED() then Expression.toString(dim.dimension); | |
| 500 | end match; | ||
| 501 | end toString; | ||
| 502 | |||
| 503 | function hashList | ||
| 504 | input list<Dimension> dims; | ||
| 505 | output Integer hash = Util.HASH_SEED; | ||
| 506 | algorithm | ||
| 507 |
2/2✓ Branch 0 taken 143 times.
✓ Branch 1 taken 120 times.
|
263 | for dim in dims loop |
| 508 | 143 | hash := stringHashDjb2Continue(match dim case RESIZABLE() then Expression.toString(canonicalExp(dim.exp)) + "(R)"; else toString(dim); end match, hash); | |
| 509 | end for; | ||
| 510 | end hashList; | ||
| 511 | |||
| 512 | function toStringList | ||
| 513 | input list<Dimension> dims; | ||
| 514 | input Boolean brackets = true; | ||
| 515 | output String str; | ||
| 516 | algorithm | ||
| 517 |
4/4✓ Branch 0 taken 6 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6 times.
|
12 | str := stringDelimitList(list(toString(d) for d in dims), ", "); |
| 518 | |||
| 519 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if brackets then |
| 520 | 6 | str := "[" + str + "]"; | |
| 521 | end if; | ||
| 522 | end toStringList; | ||
| 523 | |||
| 524 | function toFlatString | ||
| 525 | input Dimension dim; | ||
| 526 | input BaseModelica.OutputFormat format; | ||
| 527 | output String str; | ||
| 528 | algorithm | ||
| 529 | str := match dim | ||
| 530 | 229 | case INTEGER() then String(dim.size); | |
| 531 | case BOOLEAN() then "Boolean"; | ||
| 532 | ✗ | case ENUM() then Type.toFlatString(dim.enumType, format); | |
| 533 | 1 | case EXP() then Expression.toFlatString(dim.exp, format); | |
| 534 | ✗ | case RESIZABLE() then Expression.toFlatString(dim.exp, format) + "(R)"; | |
| 535 | case UNKNOWN() then ":"; | ||
| 536 | ✗ | case UNTYPED() then Expression.toFlatString(dim.dimension, format); | |
| 537 | end match; | ||
| 538 | end toFlatString; | ||
| 539 | |||
| 540 | function toFlatStringList | ||
| 541 | input list<Dimension> dims; | ||
| 542 | input BaseModelica.OutputFormat format; | ||
| 543 | input String name = ""; | ||
| 544 | output String str; | ||
| 545 | algorithm | ||
| 546 | 223 | str := List.toStringCustom(dims, function toFlatString(format = format), name, "[", ", ", "]", false); | |
| 547 | end toFlatStringList; | ||
| 548 | |||
| 549 | function endExp | ||
| 550 | "Returns an expression for the last index in a dimension." | ||
| 551 | input Dimension dim; | ||
| 552 | input Expression subscriptedExp; | ||
| 553 | input Integer index; | ||
| 554 | output Expression sizeExp; | ||
| 555 | algorithm | ||
| 556 | sizeExp := match dim | ||
| 557 | local | ||
| 558 | Type ty; | ||
| 559 | |||
| 560 | 32 | case INTEGER() then Expression.INTEGER(dim.size); | |
| 561 | case BOOLEAN() then Expression.BOOLEAN(true); | ||
| 562 | case ENUM(enumType = ty as Type.ENUMERATION()) | ||
| 563 | 2 | then Expression.makeEnumLiteral(ty, listLength(ty.literals)); | |
| 564 | ✗ | case EXP() then dim.exp; | |
| 565 | ✗ | case RESIZABLE() then dim.exp; | |
| 566 | case UNKNOWN() | ||
| 567 | then match subscriptedExp | ||
| 568 | case Expression.CREF() | ||
| 569 | 6 | then Expression.SIZE(Expression.fromCref(ComponentRef.stripSubscripts(subscriptedExp.cref)), | |
| 570 | SOME(Expression.INTEGER(index))); | ||
| 571 | case Expression.SUBSCRIPTED_EXP() | ||
| 572 | ✗ | then Expression.SIZE(subscriptedExp.exp, SOME(Expression.INTEGER(index))); | |
| 573 | end match; | ||
| 574 | end match; | ||
| 575 | end endExp; | ||
| 576 | |||
| 577 | function sizeExp | ||
| 578 | "Returns the size of a dimension as an Expression." | ||
| 579 | input Dimension dim; | ||
| 580 | output Expression sizeExp; | ||
| 581 | algorithm | ||
| 582 | sizeExp := match dim | ||
| 583 | local | ||
| 584 | Type ty; | ||
| 585 | |||
| 586 | 89213 | case INTEGER() then Expression.INTEGER(dim.size); | |
| 587 | case BOOLEAN() then Expression.INTEGER(2); | ||
| 588 | case ENUM(enumType = ty as Type.ENUMERATION()) | ||
| 589 | ✗ | then Expression.INTEGER(listLength(ty.literals)); | |
| 590 | 251 | case EXP() then dim.exp; | |
| 591 | 687 | case RESIZABLE() then dim.exp; | |
| 592 | end match; | ||
| 593 | end sizeExp; | ||
| 594 | |||
| 595 | function lowerBoundExp | ||
| 596 | input Dimension dim; | ||
| 597 | output Expression exp; | ||
| 598 | algorithm | ||
| 599 | exp := match dim | ||
| 600 | case BOOLEAN() then Expression.BOOLEAN(false); | ||
| 601 | 1 | case ENUM() then Expression.makeEnumLiteral(dim.enumType, 1); | |
| 602 | else Expression.INTEGER(1); | ||
| 603 | end match; | ||
| 604 | end lowerBoundExp; | ||
| 605 | |||
| 606 | function expIsLowerBound | ||
| 607 | "Returns true if the expression represents the lower bound of a dimension." | ||
| 608 | input Expression exp; | ||
| 609 | output Boolean isStart; | ||
| 610 | algorithm | ||
| 611 | isStart := match exp | ||
| 612 | 493 | case Expression.INTEGER() then exp.value == 1; | |
| 613 | ✗ | case Expression.BOOLEAN() then exp.value == false; | |
| 614 | ✗ | case Expression.ENUM_LITERAL() then exp.index == 1; | |
| 615 | else false; | ||
| 616 | end match; | ||
| 617 | end expIsLowerBound; | ||
| 618 | |||
| 619 | function upperBoundExp | ||
| 620 | input Dimension dim; | ||
| 621 | output Expression exp; | ||
| 622 | algorithm | ||
| 623 | exp := match dim | ||
| 624 | local | ||
| 625 | Type ty; | ||
| 626 | |||
| 627 | 29 | case INTEGER() then Expression.INTEGER(dim.size); | |
| 628 | case BOOLEAN() then Expression.BOOLEAN(true); | ||
| 629 | case ENUM(enumType = ty as Type.ENUMERATION()) | ||
| 630 | ✗ | then Expression.makeEnumLiteral(ty, listLength(ty.literals)); | |
| 631 | ✗ | case EXP() then dim.exp; | |
| 632 | 3 | case RESIZABLE() then dim.exp; | |
| 633 | end match; | ||
| 634 | end upperBoundExp; | ||
| 635 | |||
| 636 | function expIsUpperBound | ||
| 637 | "Returns true if the expression represents the upper bound of the given dimension." | ||
| 638 | input Expression exp; | ||
| 639 | input Dimension dim; | ||
| 640 | output Boolean isEnd; | ||
| 641 | algorithm | ||
| 642 | isEnd := match (exp, dim) | ||
| 643 | local | ||
| 644 | Type ty; | ||
| 645 | |||
| 646 | 315 | case (Expression.INTEGER(), INTEGER()) then exp.value == dim.size; | |
| 647 | ✗ | case (Expression.BOOLEAN(), _) then exp.value == true; | |
| 648 | case (Expression.ENUM_LITERAL(), ENUM(enumType = ty as Type.ENUMERATION())) | ||
| 649 | ✗ | then exp.index == listLength(ty.literals); | |
| 650 | else false; | ||
| 651 | end match; | ||
| 652 | end expIsUpperBound; | ||
| 653 | |||
| 654 | function variability | ||
| 655 | input Dimension dim; | ||
| 656 | output Variability var; | ||
| 657 | algorithm | ||
| 658 | var := match dim | ||
| 659 | 39702 | case INTEGER() then dim.var; | |
| 660 | case BOOLEAN() then Variability.CONSTANT; | ||
| 661 | case ENUM() then Variability.CONSTANT; | ||
| 662 | 8 | case EXP() then dim.var; | |
| 663 | ✗ | case RESIZABLE() then dim.var; | |
| 664 | case UNKNOWN() then Variability.CONTINUOUS; | ||
| 665 | end match; | ||
| 666 | end variability; | ||
| 667 | |||
| 668 | function mapExp | ||
| 669 | input Dimension dim; | ||
| 670 | input MapFunc func; | ||
| 671 | output Dimension outDim; | ||
| 672 | |||
| 673 | partial function MapFunc | ||
| 674 | input output Expression e; | ||
| 675 | end MapFunc; | ||
| 676 | algorithm | ||
| 677 | outDim := match dim | ||
| 678 | local | ||
| 679 | Expression e1, e2; | ||
| 680 | |||
| 681 | case UNTYPED(dimension = e1) | ||
| 682 | algorithm | ||
| 683 | ✗ | e2 := Expression.map(e1, func); | |
| 684 | ✗ | then | |
| 685 | if referenceEq(e1, e2) then dim else UNTYPED(e2, dim.isProcessing); | ||
| 686 | |||
| 687 | case EXP(exp = e1) | ||
| 688 | algorithm | ||
| 689 | 1539 | e2 := Expression.map(e1, func); | |
| 690 |
1/2✓ Branch 0 taken 1539 times.
✗ Branch 1 not taken.
|
1539 | then |
| 691 | if referenceEq(e1, e2) then dim else fromExp(e2, dim.var); | ||
| 692 | |||
| 693 | case RESIZABLE(exp = e1) | ||
| 694 | algorithm | ||
| 695 | 420 | e2 := Expression.map(e1, func); | |
| 696 |
1/2✓ Branch 0 taken 420 times.
✗ Branch 1 not taken.
|
420 | then |
| 697 | if referenceEq(e1, e2) then dim else fromExp(e2, dim.var); | ||
| 698 | |||
| 699 | else dim; | ||
| 700 | end match; | ||
| 701 | end mapExp; | ||
| 702 | |||
| 703 | function foldExp<ArgT> | ||
| 704 | input Dimension dim; | ||
| 705 | input FoldFunc func; | ||
| 706 | input ArgT arg; | ||
| 707 | output ArgT outArg; | ||
| 708 | |||
| 709 | partial function FoldFunc | ||
| 710 | input Expression dim; | ||
| 711 | input output ArgT arg; | ||
| 712 | end FoldFunc; | ||
| 713 | algorithm | ||
| 714 | outArg := match dim | ||
| 715 | ✗ | case UNTYPED() then Expression.fold(dim.dimension, func, arg); | |
| 716 | 2651 | case EXP() then Expression.fold(dim.exp, func, arg); | |
| 717 | 79 | case RESIZABLE() then Expression.fold(dim.exp, func, arg); | |
| 718 | else arg; | ||
| 719 | end match; | ||
| 720 | end foldExp; | ||
| 721 | |||
| 722 | function foldExpList<ArgT> | ||
| 723 | input list<Dimension> dims; | ||
| 724 | input FoldFunc func; | ||
| 725 | input output ArgT arg; | ||
| 726 | |||
| 727 | partial function FoldFunc | ||
| 728 | input Expression dim; | ||
| 729 | input output ArgT arg; | ||
| 730 | end FoldFunc; | ||
| 731 | algorithm | ||
| 732 |
2/2✓ Branch 0 taken 153508 times.
✓ Branch 1 taken 136376 times.
|
289884 | for dim in dims loop |
| 733 | 153508 | arg := foldExp(dim, func, arg); | |
| 734 | end for; | ||
| 735 | end foldExpList; | ||
| 736 | |||
| 737 | function eval | ||
| 738 | input Dimension dim; | ||
| 739 | input EvalTarget target = NFCeval.noTarget; | ||
| 740 | output Dimension outDim; | ||
| 741 | algorithm | ||
| 742 | outDim := match dim | ||
| 743 | ✗ | case EXP() then fromExp(Ceval.evalExp(dim.exp, target), dim.var); | |
| 744 | case RESIZABLE() algorithm | ||
| 745 | ✗ | dim.exp := Ceval.evalExp(dim.exp, target); | |
| 746 | then dim; | ||
| 747 | else dim; | ||
| 748 | end match; | ||
| 749 | end eval; | ||
| 750 | |||
| 751 | function simplify | ||
| 752 | input output Dimension dim; | ||
| 753 | algorithm | ||
| 754 | dim := match dim | ||
| 755 | local | ||
| 756 | Expression simple; | ||
| 757 | case EXP() algorithm | ||
| 758 | 7818 | simple := SimplifyExp.simplify(dim.exp); | |
| 759 | 7818 | then fromExp(simple, Expression.variability(simple)); | |
| 760 | case RESIZABLE() algorithm | ||
| 761 | 1011 | dim.exp := SimplifyExp.simplify(dim.exp); | |
| 762 | then dim; | ||
| 763 | else dim; | ||
| 764 | end match; | ||
| 765 | end simplify; | ||
| 766 | |||
| 767 | function typeOf | ||
| 768 | input Dimension dim; | ||
| 769 | output Type ty; | ||
| 770 | algorithm | ||
| 771 | ty := match dim | ||
| 772 | case INTEGER() then Type.INTEGER(); | ||
| 773 | case BOOLEAN() then Type.BOOLEAN(); | ||
| 774 | ✗ | case ENUM() then dim.enumType; | |
| 775 | ✗ | case EXP() then Expression.typeOf(dim.exp); | |
| 776 | 3 | case RESIZABLE() then Expression.typeOf(dim.exp); | |
| 777 | else Type.UNKNOWN(); | ||
| 778 | end match; | ||
| 779 | end typeOf; | ||
| 780 | |||
| 781 | annotation(__OpenModelica_Interface="nf_frontend"); | ||
| 782 | end NFDimension; | ||
| 783 |