OMCompiler/Compiler/NFFrontEnd/NFAttributes.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 NFAttributes | ||
| 37 | |||
| 38 | import InstContext = NFInstContext; | ||
| 39 | import NFInstNode.InstNode; | ||
| 40 | import NFPrefixes.*; | ||
| 41 | import SCode; | ||
| 42 | import Restriction = NFRestriction; | ||
| 43 | |||
| 44 | protected | ||
| 45 | import Absyn; | ||
| 46 | import Class = NFClass; | ||
| 47 | import DAE; | ||
| 48 | import IOStream; | ||
| 49 | import Prefixes = NFPrefixes; | ||
| 50 | import SCodeUtil; | ||
| 51 | |||
| 52 | import Attributes = NFAttributes; | ||
| 53 | |||
| 54 | public | ||
| 55 | constant Attributes DEFAULT_ATTR = | ||
| 56 | ATTRIBUTES( | ||
| 57 | ConnectorType.NON_CONNECTOR, | ||
| 58 | Parallelism.NON_PARALLEL, | ||
| 59 | Variability.CONTINUOUS, | ||
| 60 | Direction.NONE, | ||
| 61 | InnerOuter.NOT_INNER_OUTER, | ||
| 62 | false, | ||
| 63 | false, | ||
| 64 | Replaceable.NOT_REPLACEABLE(), | ||
| 65 | false | ||
| 66 | ); | ||
| 67 | |||
| 68 | constant Attributes INPUT_ATTR = | ||
| 69 | ATTRIBUTES( | ||
| 70 | ConnectorType.NON_CONNECTOR, | ||
| 71 | Parallelism.NON_PARALLEL, | ||
| 72 | Variability.CONTINUOUS, | ||
| 73 | Direction.INPUT, | ||
| 74 | InnerOuter.NOT_INNER_OUTER, | ||
| 75 | false, | ||
| 76 | false, | ||
| 77 | Replaceable.NOT_REPLACEABLE(), | ||
| 78 | false | ||
| 79 | ); | ||
| 80 | |||
| 81 | constant Attributes OUTPUT_ATTR = | ||
| 82 | ATTRIBUTES( | ||
| 83 | ConnectorType.NON_CONNECTOR, | ||
| 84 | Parallelism.NON_PARALLEL, | ||
| 85 | Variability.CONTINUOUS, | ||
| 86 | Direction.OUTPUT, | ||
| 87 | InnerOuter.NOT_INNER_OUTER, | ||
| 88 | false, | ||
| 89 | false, | ||
| 90 | Replaceable.NOT_REPLACEABLE(), | ||
| 91 | false | ||
| 92 | ); | ||
| 93 | |||
| 94 | constant Attributes CONSTANT_ATTR = | ||
| 95 | ATTRIBUTES( | ||
| 96 | ConnectorType.NON_CONNECTOR, | ||
| 97 | Parallelism.NON_PARALLEL, | ||
| 98 | Variability.CONSTANT, | ||
| 99 | Direction.NONE, | ||
| 100 | InnerOuter.NOT_INNER_OUTER, | ||
| 101 | false, | ||
| 102 | false, | ||
| 103 | Replaceable.NOT_REPLACEABLE(), | ||
| 104 | false | ||
| 105 | ); | ||
| 106 | |||
| 107 | constant Attributes IMPL_DISCRETE_ATTR = | ||
| 108 | ATTRIBUTES( | ||
| 109 | ConnectorType.NON_CONNECTOR, | ||
| 110 | Parallelism.NON_PARALLEL, | ||
| 111 | Variability.IMPLICITLY_DISCRETE, | ||
| 112 | Direction.NONE, | ||
| 113 | InnerOuter.NOT_INNER_OUTER, | ||
| 114 | false, | ||
| 115 | false, | ||
| 116 | Replaceable.NOT_REPLACEABLE(), | ||
| 117 | false | ||
| 118 | ); | ||
| 119 | |||
| 120 | constant Attributes AUGMENTED_ATTR = | ||
| 121 | ATTRIBUTES( | ||
| 122 | ConnectorType.AUGMENTED, | ||
| 123 | Parallelism.NON_PARALLEL, | ||
| 124 | Variability.CONTINUOUS, | ||
| 125 | Direction.NONE, | ||
| 126 | InnerOuter.NOT_INNER_OUTER, | ||
| 127 | false, | ||
| 128 | false, | ||
| 129 | Replaceable.NOT_REPLACEABLE(), | ||
| 130 | false | ||
| 131 | ); | ||
| 132 | |||
| 133 | |||
| 134 | record ATTRIBUTES | ||
| 135 | ConnectorType.Type connectorType; | ||
| 136 | Parallelism parallelism; | ||
| 137 | Variability variability; | ||
| 138 | Direction direction; | ||
| 139 | InnerOuter innerOuter; | ||
| 140 | Boolean isFinal; | ||
| 141 | Boolean isRedeclare; | ||
| 142 | Replaceable isReplaceable; | ||
| 143 | Boolean isResizable; | ||
| 144 | end ATTRIBUTES; | ||
| 145 | |||
| 146 | function fromSCode | ||
| 147 | input SCode.Attributes compAttr; | ||
| 148 | input SCode.Prefixes compPrefs; | ||
| 149 | output Attributes attributes; | ||
| 150 | protected | ||
| 151 | ConnectorType.Type cty; | ||
| 152 | Parallelism par; | ||
| 153 | Variability var; | ||
| 154 | Direction dir; | ||
| 155 | InnerOuter io; | ||
| 156 | Boolean fin, redecl; | ||
| 157 | Replaceable repl; | ||
| 158 | algorithm | ||
| 159 | attributes := match (compAttr, compPrefs) | ||
| 160 | case (SCode.Attributes.ATTR( | ||
| 161 | connectorType = SCode.ConnectorType.POTENTIAL(), | ||
| 162 | parallelism = SCode.Parallelism.NON_PARALLEL(), | ||
| 163 | variability = SCode.Variability.VAR(), | ||
| 164 | direction = Absyn.Direction.BIDIR()), | ||
| 165 | SCode.Prefixes.PREFIXES( | ||
| 166 | redeclarePrefix = SCode.Redeclare.NOT_REDECLARE(), | ||
| 167 | finalPrefix = SCode.Final.NOT_FINAL(), | ||
| 168 | innerOuter = Absyn.InnerOuter.NOT_INNER_OUTER(), | ||
| 169 | replaceablePrefix = SCode.Replaceable.NOT_REPLACEABLE())) | ||
| 170 | then DEFAULT_ATTR; | ||
| 171 | |||
| 172 | else | ||
| 173 | algorithm | ||
| 174 | 347352 | cty := ConnectorType.fromSCode(compAttr.connectorType); | |
| 175 | 347352 | par := Prefixes.parallelismFromSCode(compAttr.parallelism); | |
| 176 | 347352 | var := Prefixes.variabilityFromSCode(compAttr.variability); | |
| 177 | 347352 | dir := Prefixes.directionFromSCode(compAttr.direction); | |
| 178 | 347352 | io := Prefixes.innerOuterFromSCode(compPrefs.innerOuter); | |
| 179 | 347352 | fin := SCodeUtil.finalBool(compPrefs.finalPrefix); | |
| 180 | 347352 | redecl := SCodeUtil.redeclareBool(compPrefs.redeclarePrefix); | |
| 181 | repl := Replaceable.NOT_REPLACEABLE(); | ||
| 182 |
4/4✓ Branch 0 taken 341792 times.
✓ Branch 1 taken 5560 times.
✓ Branch 2 taken 332670 times.
✓ Branch 3 taken 14682 times.
|
1021814 | then |
| 183 | Attributes.ATTRIBUTES(cty, par, var, dir, io, fin, redecl, repl, false); | ||
| 184 | end match; | ||
| 185 | end fromSCode; | ||
| 186 | |||
| 187 | function fromDerivedSCode | ||
| 188 | input SCode.Attributes scodeAttr; | ||
| 189 | output Attributes attributes; | ||
| 190 | protected | ||
| 191 | ConnectorType.Type cty; | ||
| 192 | Variability var; | ||
| 193 | Direction dir; | ||
| 194 | algorithm | ||
| 195 | attributes := match scodeAttr | ||
| 196 | case SCode.Attributes.ATTR( | ||
| 197 | connectorType = SCode.ConnectorType.POTENTIAL(), | ||
| 198 | variability = SCode.Variability.VAR(), | ||
| 199 | direction = Absyn.Direction.BIDIR()) | ||
| 200 | then DEFAULT_ATTR; | ||
| 201 | |||
| 202 | else | ||
| 203 | algorithm | ||
| 204 | 1104 | cty := ConnectorType.fromSCode(scodeAttr.connectorType); | |
| 205 | 1104 | var := Prefixes.variabilityFromSCode(scodeAttr.variability); | |
| 206 | 1104 | dir := Prefixes.directionFromSCode(scodeAttr.direction); | |
| 207 | 1104 | then | |
| 208 | ATTRIBUTES(cty, Parallelism.NON_PARALLEL, | ||
| 209 | var, dir, InnerOuter.NOT_INNER_OUTER, false, false, Replaceable.NOT_REPLACEABLE(), false); | ||
| 210 | |||
| 211 | end match; | ||
| 212 | end fromDerivedSCode; | ||
| 213 | |||
| 214 | function mergeComponentAttributes | ||
| 215 | input Attributes outerAttr; | ||
| 216 | input Attributes innerAttr; | ||
| 217 | input InstNode node; | ||
| 218 | input Restriction parentRestriction; | ||
| 219 | output Attributes attr; | ||
| 220 | protected | ||
| 221 | ConnectorType.Type cty; | ||
| 222 | Parallelism par; | ||
| 223 | Variability var; | ||
| 224 | Direction dir; | ||
| 225 | Boolean fin, redecl, resize; | ||
| 226 | Replaceable repl; | ||
| 227 | algorithm | ||
| 228 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 956641 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
956641 | if referenceEq(outerAttr, DEFAULT_ATTR) and innerAttr.connectorType == 0 then |
| 229 | attr := innerAttr; | ||
| 230 | elseif referenceEq(innerAttr, DEFAULT_ATTR) then | ||
| 231 | 609087 | cty := ConnectorType.merge(outerAttr.connectorType, innerAttr.connectorType, node); | |
| 232 | 609087 | attr := Attributes.ATTRIBUTES(cty, outerAttr.parallelism, | |
| 233 | outerAttr.variability, outerAttr.direction, innerAttr.innerOuter, outerAttr.isFinal, | ||
| 234 | innerAttr.isRedeclare, innerAttr.isReplaceable, innerAttr.isResizable); | ||
| 235 | else | ||
| 236 | 347554 | cty := ConnectorType.merge(outerAttr.connectorType, innerAttr.connectorType, node); | |
| 237 | 347554 | par := Prefixes.mergeParallelism(outerAttr.parallelism, innerAttr.parallelism, node); | |
| 238 | 347554 | var := Prefixes.variabilityMin(outerAttr.variability, innerAttr.variability); | |
| 239 | |||
| 240 |
2/2✓ Branch 1 taken 70149 times.
✓ Branch 2 taken 277405 times.
|
347554 | if Restriction.isFunction(parentRestriction) then |
| 241 | 70149 | dir := innerAttr.direction; | |
| 242 | else | ||
| 243 | 277405 | dir := Prefixes.mergeDirection(outerAttr.direction, innerAttr.direction, node); | |
| 244 | end if; | ||
| 245 | |||
| 246 |
4/4✓ Branch 0 taken 344810 times.
✓ Branch 1 taken 2743 times.
✓ Branch 2 taken 330392 times.
✓ Branch 3 taken 14418 times.
|
347553 | fin := outerAttr.isFinal or innerAttr.isFinal; |
| 247 | 347553 | redecl := innerAttr.isRedeclare; | |
| 248 | 347553 | repl := innerAttr.isReplaceable; | |
| 249 | 347553 | resize := innerAttr.isResizable; | |
| 250 |
5/6✓ Branch 0 taken 347553 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 341993 times.
✓ Branch 3 taken 5560 times.
✓ Branch 4 taken 330392 times.
✓ Branch 5 taken 17161 times.
|
1367491 | attr := Attributes.ATTRIBUTES(cty, par, var, dir, innerAttr.innerOuter, fin, redecl, repl, resize); |
| 251 | end if; | ||
| 252 | end mergeComponentAttributes; | ||
| 253 | |||
| 254 | function mergeDerivedAttributes | ||
| 255 | input Attributes outerAttr; | ||
| 256 | input Attributes innerAttr; | ||
| 257 | input InstNode node; | ||
| 258 | output Attributes attr; | ||
| 259 | protected | ||
| 260 | ConnectorType.Type cty; | ||
| 261 | Parallelism par; | ||
| 262 | Variability var; | ||
| 263 | Direction dir; | ||
| 264 | InnerOuter io; | ||
| 265 | Boolean fin, redecl, resize; | ||
| 266 | Replaceable repl; | ||
| 267 | algorithm | ||
| 268 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 693489 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
693489 | if referenceEq(innerAttr, DEFAULT_ATTR) and outerAttr.connectorType == 0 then |
| 269 | attr := outerAttr; | ||
| 270 | elseif referenceEq(outerAttr, DEFAULT_ATTR) and innerAttr.connectorType == 0 then | ||
| 271 | attr := innerAttr; | ||
| 272 | else | ||
| 273 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 70366 times.
|
70366 | Attributes.ATTRIBUTES(cty, par, var, dir, io, fin, redecl, repl, resize) := outerAttr; |
| 274 | 70366 | cty := ConnectorType.merge(cty, innerAttr.connectorType, node, isClass = true); | |
| 275 | 70366 | var := Prefixes.variabilityMin(var, innerAttr.variability); | |
| 276 | 70366 | dir := Prefixes.mergeDirection(dir, innerAttr.direction, node, allowSame = true); | |
| 277 |
3/6✓ Branch 0 taken 70365 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 70365 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 70365 times.
✗ Branch 5 not taken.
|
281460 | attr := Attributes.ATTRIBUTES(cty, par, var, dir, innerAttr.innerOuter, fin, redecl, repl, resize); |
| 278 | end if; | ||
| 279 | end mergeDerivedAttributes; | ||
| 280 | |||
| 281 | function mergeRedeclaredComponentAttributes | ||
| 282 | input Attributes origAttr; | ||
| 283 | input Attributes redeclAttr; | ||
| 284 | input InstNode node; | ||
| 285 | output Attributes attr; | ||
| 286 | protected | ||
| 287 | ConnectorType.Type cty, rcty, cty_fs, rcty_fs; | ||
| 288 | Parallelism par, rpar; | ||
| 289 | Variability var, rvar; | ||
| 290 | Direction dir, rdir; | ||
| 291 | InnerOuter io, rio; | ||
| 292 | Boolean fin, redecl, resize; | ||
| 293 | Replaceable repl; | ||
| 294 | algorithm | ||
| 295 |
1/2✓ Branch 0 taken 5561 times.
✗ Branch 1 not taken.
|
5561 | if referenceEq(origAttr, DEFAULT_ATTR) then |
| 296 | attr := redeclAttr; | ||
| 297 | elseif referenceEq(redeclAttr, DEFAULT_ATTR) then | ||
| 298 | attr := origAttr; | ||
| 299 | else | ||
| 300 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5561 times.
|
5561 | Attributes.ATTRIBUTES(cty, par, var, dir, io, _, _, _, _) := origAttr; |
| 301 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5561 times.
|
5561 | Attributes.ATTRIBUTES(rcty, rpar, rvar, rdir, rio, fin, redecl, repl, resize) := redeclAttr; |
| 302 | |||
| 303 | // If no prefix is given for one of these attributes in the redeclaration, | ||
| 304 | // then the one from the original declaration is used. The redeclare is not | ||
| 305 | // allowed to change an existing prefix on the original declaration, except | ||
| 306 | // for the variability which can be lowered (e.g. parameter -> constant) and | ||
| 307 | // final which is always taken from the redeclare (since redeclaring a final | ||
| 308 | // element isn't allowed). | ||
| 309 | |||
| 310 | 5561 | rcty_fs := intBitAnd(rcty, ConnectorType.FLOW_STREAM_MASK); | |
| 311 | 5561 | cty_fs := intBitAnd(cty, ConnectorType.FLOW_STREAM_MASK); | |
| 312 |
2/2✓ Branch 0 taken 967 times.
✓ Branch 1 taken 4594 times.
|
5561 | if rcty_fs > 0 then |
| 313 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 967 times.
|
967 | if cty_fs > 0 and rcty_fs <> cty_fs then |
| 314 | ✗ | printRedeclarePrefixError(node, ConnectorType.toString(rcty), ConnectorType.toString(cty)); | |
| 315 | end if; | ||
| 316 | end if; | ||
| 317 | |||
| 318 | 5561 | cty := intBitOr(rcty, cty_fs); | |
| 319 | |||
| 320 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5561 times.
|
5561 | if rpar <> Parallelism.NON_PARALLEL then |
| 321 | ✗ | if par <> Parallelism.NON_PARALLEL and par <> rpar then | |
| 322 | ✗ | printRedeclarePrefixError(node, Prefixes.parallelismString(rpar), Prefixes.parallelismString(par)); | |
| 323 | end if; | ||
| 324 | |||
| 325 | par := rpar; | ||
| 326 | end if; | ||
| 327 | |||
| 328 |
2/2✓ Branch 0 taken 481 times.
✓ Branch 1 taken 5080 times.
|
5561 | if rvar <> Variability.CONTINUOUS then |
| 329 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 480 times.
|
481 | if rvar > var then |
| 330 | 1 | printRedeclarePrefixError(node, Prefixes.variabilityString(rvar), Prefixes.variabilityString(var)); | |
| 331 | end if; | ||
| 332 | |||
| 333 | var := rvar; | ||
| 334 | end if; | ||
| 335 | |||
| 336 |
2/2✓ Branch 0 taken 650 times.
✓ Branch 1 taken 4910 times.
|
5560 | if rdir <> Direction.NONE then |
| 337 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 650 times.
|
650 | if dir <> Direction.NONE and rdir <> dir then |
| 338 | ✗ | printRedeclarePrefixError(node, Prefixes.directionString(rdir), Prefixes.directionString(dir)); | |
| 339 | end if; | ||
| 340 | |||
| 341 | dir := rdir; | ||
| 342 | end if; | ||
| 343 | |||
| 344 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5560 times.
|
5560 | if rio <> InnerOuter.NOT_INNER_OUTER then |
| 345 | ✗ | if io <> InnerOuter.NOT_INNER_OUTER and rio <> io then | |
| 346 | ✗ | printRedeclarePrefixError(node, Prefixes.innerOuterString(rio), Prefixes.innerOuterString(io)); | |
| 347 | end if; | ||
| 348 | |||
| 349 | io := rio; | ||
| 350 | end if; | ||
| 351 | |||
| 352 |
5/6✓ Branch 0 taken 5560 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 5559 times.
✓ Branch 4 taken 4964 times.
✓ Branch 5 taken 596 times.
|
16085 | attr := Attributes.ATTRIBUTES(cty, par, var, dir, io, fin, redecl, repl, resize); |
| 353 | end if; | ||
| 354 | end mergeRedeclaredComponentAttributes; | ||
| 355 | |||
| 356 | function mergeRedeclaredClassPrefixes | ||
| 357 | input Class.Prefixes origPrefs; | ||
| 358 | input Class.Prefixes redeclPrefs; | ||
| 359 | input InstNode node; | ||
| 360 | output Class.Prefixes prefs; | ||
| 361 | protected | ||
| 362 | SCode.Encapsulated enc; | ||
| 363 | SCode.Partial par; | ||
| 364 | SCode.Final fin; | ||
| 365 | Absyn.InnerOuter io, rio; | ||
| 366 | SCode.Replaceable repl; | ||
| 367 | algorithm | ||
| 368 |
1/2✓ Branch 0 taken 6439 times.
✗ Branch 1 not taken.
|
6439 | if referenceEq(origPrefs, NFClass.DEFAULT_PREFIXES) then |
| 369 | prefs := redeclPrefs; | ||
| 370 | else | ||
| 371 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6439 times.
|
6439 | Class.Prefixes.PREFIXES(innerOuter = io) := origPrefs; |
| 372 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6439 times.
|
6439 | Class.Prefixes.PREFIXES(enc, par, fin, rio, repl) := redeclPrefs; |
| 373 | |||
| 374 | io := match (io, rio) | ||
| 375 | case (Absyn.InnerOuter.NOT_INNER_OUTER(), _) then rio; | ||
| 376 | case (_, Absyn.InnerOuter.NOT_INNER_OUTER()) then io; | ||
| 377 | case (Absyn.InnerOuter.INNER(), Absyn.InnerOuter.INNER()) then io; | ||
| 378 | case (Absyn.InnerOuter.OUTER(), Absyn.InnerOuter.OUTER()) then io; | ||
| 379 | case (Absyn.InnerOuter.INNER_OUTER(), Absyn.InnerOuter.INNER_OUTER()) then io; | ||
| 380 | else | ||
| 381 | algorithm | ||
| 382 | ✗ | printRedeclarePrefixError(node, | |
| 383 | Prefixes.innerOuterString(Prefixes.innerOuterFromSCode(rio)), | ||
| 384 | Prefixes.innerOuterString(Prefixes.innerOuterFromSCode(io))); | ||
| 385 | ✗ | then | |
| 386 | fail(); | ||
| 387 | end match; | ||
| 388 | |||
| 389 | 6439 | prefs := Class.Prefixes.PREFIXES(enc, par, fin, io, repl); | |
| 390 | end if; | ||
| 391 | end mergeRedeclaredClassPrefixes; | ||
| 392 | |||
| 393 | function printRedeclarePrefixError | ||
| 394 | input InstNode node; | ||
| 395 | input String prefix1; | ||
| 396 | input String prefix2; | ||
| 397 | algorithm | ||
| 398 | 2 | Error.addSourceMessageAndFail(Error.REDECLARE_MISMATCHED_PREFIX, | |
| 399 | {prefix1, InstNode.name(node), prefix2}, InstNode.info(node)); | ||
| 400 | end printRedeclarePrefixError; | ||
| 401 | |||
| 402 | function checkDeclaredComponentAttributes | ||
| 403 | input output Attributes attr; | ||
| 404 | input Restriction parentRestriction; | ||
| 405 | input InstNode component; | ||
| 406 | algorithm | ||
| 407 | () := match parentRestriction | ||
| 408 | case Restriction.CONNECTOR() | ||
| 409 | algorithm | ||
| 410 | // Components of a connector may not have prefixes 'inner' or 'outer'. | ||
| 411 | 46250 | assertNotInnerOuter(attr.innerOuter, component, parentRestriction); | |
| 412 | |||
| 413 |
2/2✓ Branch 0 taken 202 times.
✓ Branch 1 taken 46048 times.
|
46250 | if parentRestriction.isExpandable then |
| 414 | // Components of an expandable connector may not have the prefix 'flow'. | ||
| 415 | 202 | assertNotFlowStream(attr.connectorType, component, parentRestriction); | |
| 416 | |||
| 417 | // Mark components in expandable connectors as potentially present. | ||
| 418 | 202 | attr.connectorType := intBitOr(attr.connectorType, ConnectorType.POTENTIALLY_PRESENT); | |
| 419 | end if; | ||
| 420 | then | ||
| 421 | (); | ||
| 422 | |||
| 423 | case Restriction.RECORD() | ||
| 424 | algorithm | ||
| 425 | // Elements of a record may not have prefixes 'input', 'output', 'inner', 'outer', 'stream', or 'flow'. | ||
| 426 | 551956 | assertNotInputOutput(attr.direction, component, parentRestriction); | |
| 427 | 551956 | assertNotInnerOuter(attr.innerOuter, component, parentRestriction); | |
| 428 | 551956 | assertNotFlowStream(attr.connectorType, component, parentRestriction); | |
| 429 | then | ||
| 430 | (); | ||
| 431 | |||
| 432 | else (); | ||
| 433 | end match; | ||
| 434 | end checkDeclaredComponentAttributes; | ||
| 435 | |||
| 436 | function invalidComponentPrefixError | ||
| 437 | input String prefix; | ||
| 438 | input InstNode node; | ||
| 439 | input Restriction restriction; | ||
| 440 | algorithm | ||
| 441 | ✗ | Error.addSourceMessage(Error.INVALID_COMPONENT_PREFIX, | |
| 442 | {prefix, InstNode.name(node), Restriction.toString(restriction)}, InstNode.info(node)); | ||
| 443 | end invalidComponentPrefixError; | ||
| 444 | |||
| 445 | function assertNotInputOutput | ||
| 446 | input Direction dir; | ||
| 447 | input InstNode node; | ||
| 448 | input Restriction restriction; | ||
| 449 | algorithm | ||
| 450 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 551956 times.
|
551956 | if dir <> Direction.NONE then |
| 451 | ✗ | invalidComponentPrefixError(Prefixes.directionString(dir), node, restriction); | |
| 452 | ✗ | fail(); | |
| 453 | end if; | ||
| 454 | end assertNotInputOutput; | ||
| 455 | |||
| 456 | function assertNotInnerOuter | ||
| 457 | input InnerOuter io; | ||
| 458 | input InstNode node; | ||
| 459 | input Restriction restriction; | ||
| 460 | algorithm | ||
| 461 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 598206 times.
|
598206 | if io <> InnerOuter.NOT_INNER_OUTER then |
| 462 | ✗ | invalidComponentPrefixError(Prefixes.innerOuterString(io), node, restriction); | |
| 463 | ✗ | fail(); | |
| 464 | end if; | ||
| 465 | end assertNotInnerOuter; | ||
| 466 | |||
| 467 | function assertNotFlowStream | ||
| 468 | input ConnectorType.Type cty; | ||
| 469 | input InstNode node; | ||
| 470 | input Restriction restriction; | ||
| 471 | algorithm | ||
| 472 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 552158 times.
|
552158 | if ConnectorType.isFlowOrStream(cty) then |
| 473 | ✗ | invalidComponentPrefixError(ConnectorType.toString(cty), node, restriction); | |
| 474 | ✗ | fail(); | |
| 475 | end if; | ||
| 476 | end assertNotFlowStream; | ||
| 477 | |||
| 478 | function updateComponentConnectorType | ||
| 479 | input output Attributes attributes; | ||
| 480 | input Restriction restriction; | ||
| 481 | input InstContext.Type context; | ||
| 482 | input InstNode component; | ||
| 483 | protected | ||
| 484 | ConnectorType.Type cty = attributes.connectorType; | ||
| 485 | algorithm | ||
| 486 |
2/2✓ Branch 1 taken 77858 times.
✓ Branch 2 taken 878539 times.
|
956397 | if ConnectorType.isConnectorType(cty) then |
| 487 |
2/2✓ Branch 1 taken 23914 times.
✓ Branch 2 taken 53944 times.
|
77858 | if Restriction.isConnector(restriction) then |
| 488 |
4/6✓ Branch 0 taken 3 times.
✓ Branch 1 taken 23911 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
|
23914 | if attributes.variability < Variability.DISCRETE and not InstContext.inRelaxed(context) and |
| 489 | not Class.isBuiltin(InstNode.getClass(component)) then | ||
| 490 | ✗ | Error.addSourceMessage(Error.INVALID_CONNECTOR_VARIABILITY, | |
| 491 | {Prefixes.variabilityString(attributes.variability), InstNode.name(component)}, InstNode.info(component)); | ||
| 492 | ✗ | fail(); | |
| 493 | end if; | ||
| 494 | |||
| 495 |
2/2✓ Branch 1 taken 41 times.
✓ Branch 2 taken 23873 times.
|
23914 | if Restriction.isExpandableConnector(restriction) then |
| 496 | 41 | cty := ConnectorType.setPresent(cty); | |
| 497 | else | ||
| 498 | 23873 | cty := intBitAnd(cty, intBitNot(ConnectorType.EXPANDABLE)); | |
| 499 | end if; | ||
| 500 | else | ||
| 501 | // The connector type might have the connector or expandable bits set | ||
| 502 | // because of a parent node, but they should be unset if the component | ||
| 503 | // itself isn't a connector. | ||
| 504 | 53944 | cty := intBitAnd(cty, | |
| 505 | intBitNot(intBitOr(ConnectorType.CONNECTOR, ConnectorType.EXPANDABLE))); | ||
| 506 | end if; | ||
| 507 | |||
| 508 | // Connector elements that are not flow/stream are potentials. | ||
| 509 |
2/2✓ Branch 1 taken 56994 times.
✓ Branch 2 taken 20864 times.
|
77858 | if not ConnectorType.isFlowOrStream(cty) then |
| 510 | 56994 | cty := ConnectorType.setPotential(cty); | |
| 511 | end if; | ||
| 512 | |||
| 513 |
2/2✓ Branch 0 taken 77857 times.
✓ Branch 1 taken 1 time.
|
77858 | if cty <> attributes.connectorType then |
| 514 | 77857 | attributes.connectorType := cty; | |
| 515 | end if; | ||
| 516 | elseif ConnectorType.isFlowOrStream(cty) and not InstContext.inRedeclared(context) then | ||
| 517 | // The Modelica specification forbids using stream outside connector | ||
| 518 | // declarations, but has no such restriction for flow. To compromise we | ||
| 519 | // print a warning for both flow and stream. | ||
| 520 | ✗ | Error.addStrictMessage(Error.CONNECTOR_PREFIX_OUTSIDE_CONNECTOR, | |
| 521 | {ConnectorType.toString(cty)}, InstNode.info(component)); | ||
| 522 | |||
| 523 | // Remove the erroneous flow/stream prefix and keep going. | ||
| 524 | ✗ | attributes.connectorType := ConnectorType.unsetFlowStream(cty); | |
| 525 | end if; | ||
| 526 | end updateComponentConnectorType; | ||
| 527 | |||
| 528 | function updateClassConnectorType | ||
| 529 | input Restriction res; | ||
| 530 | input output Attributes attrs; | ||
| 531 | algorithm | ||
| 532 |
2/2✓ Branch 1 taken 42 times.
✓ Branch 2 taken 860747 times.
|
860789 | if Restriction.isExpandableConnector(res) then |
| 533 | 42 | attrs.connectorType := ConnectorType.setExpandable(attrs.connectorType); | |
| 534 | elseif Restriction.isConnector(res) then | ||
| 535 | 24926 | attrs.connectorType := ConnectorType.setConnector(attrs.connectorType); | |
| 536 | end if; | ||
| 537 | end updateClassConnectorType; | ||
| 538 | |||
| 539 | function updateVariability | ||
| 540 | "Updates the variability based on the type of the attributes' owner (e.g. | ||
| 541 | Integer is implicitly discrete)." | ||
| 542 | input output Attributes attr; | ||
| 543 | input Class cls; | ||
| 544 | input InstNode clsNode; | ||
| 545 | input InstNode compNode; | ||
| 546 | input InstContext.Type context; | ||
| 547 | protected | ||
| 548 | Variability var = attr.variability; | ||
| 549 | algorithm | ||
| 550 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 956397 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
956397 | if referenceEq(attr, DEFAULT_ATTR) and InstNode.isDiscreteClass(clsNode) then |
| 551 | attr := NFAttributes.IMPL_DISCRETE_ATTR; | ||
| 552 | elseif var == Variability.CONTINUOUS and InstNode.isDiscreteClass(clsNode) then | ||
| 553 | 19164 | attr.variability := Variability.IMPLICITLY_DISCRETE; | |
| 554 | elseif var < Variability.CONTINUOUS and InstContext.inFunction(context) and | ||
| 555 | attr.direction <> Direction.NONE and | ||
| 556 | SCodeUtil.isEmptyMod(InstNode.getAnnotation("__OpenModelica_functionVariability", compNode)) then | ||
| 557 | // Variability prefixes on function parameters has no semantic meaning, | ||
| 558 | // remove them so we don't have to worry about accidentally evaluating | ||
| 559 | // e.g. an input declared as constant/parameter. | ||
| 560 | 7557 | attr.variability := Variability.CONTINUOUS; | |
| 561 | elseif var == Variability.PARAMETER and not Flags.isSet(Flags.NF_SCALARIZE) | ||
| 562 | and Util.getOptionOrDefault(SCodeUtil.lookupBooleanAnnotationMod(InstNode.getAnnotation("__OpenModelica_resizable", compNode)), false) then | ||
| 563 | 3 | attr.variability := Variability.NON_STRUCTURAL_PARAMETER; | |
| 564 | attr.isResizable := true; | ||
| 565 | end if; | ||
| 566 | end updateVariability; | ||
| 567 | |||
| 568 | function setConnectorType | ||
| 569 | input ConnectorType.Type cty; | ||
| 570 | input output Attributes attr; | ||
| 571 | algorithm | ||
| 572 | ✗ | attr.connectorType := cty; | |
| 573 | end setConnectorType; | ||
| 574 | |||
| 575 | function setVariability | ||
| 576 | input Variability var; | ||
| 577 | input output Attributes attr; | ||
| 578 | algorithm | ||
| 579 | ✗ | attr.variability := var; | |
| 580 | end setVariability; | ||
| 581 | |||
| 582 | function setDirection | ||
| 583 | input Direction dir; | ||
| 584 | input output Attributes attr; | ||
| 585 | algorithm | ||
| 586 | ✗ | attr.direction := dir; | |
| 587 | end setDirection; | ||
| 588 | |||
| 589 | function setInnerOuter | ||
| 590 | input InnerOuter io; | ||
| 591 | input output Attributes attr; | ||
| 592 | algorithm | ||
| 593 | ✗ | attr.innerOuter := io; | |
| 594 | end setInnerOuter; | ||
| 595 | |||
| 596 | function setFinal | ||
| 597 | input Boolean fin; | ||
| 598 | input output Attributes attr; | ||
| 599 | algorithm | ||
| 600 | ✗ | attr.isFinal := fin; | |
| 601 | end setFinal; | ||
| 602 | |||
| 603 | function setRedeclare | ||
| 604 | input Boolean redecl; | ||
| 605 | input output Attributes attr; | ||
| 606 | algorithm | ||
| 607 | ✗ | attr.isRedeclare := redecl; | |
| 608 | end setRedeclare; | ||
| 609 | |||
| 610 | function setReplaceable | ||
| 611 | input Replaceable repl; | ||
| 612 | input output Attributes attr; | ||
| 613 | algorithm | ||
| 614 | ✗ | attr.isReplaceable := repl; | |
| 615 | end setReplaceable; | ||
| 616 | |||
| 617 | function toDAE | ||
| 618 | input Attributes ina; | ||
| 619 | input Visibility vis; | ||
| 620 | output DAE.Attributes outa; | ||
| 621 | algorithm | ||
| 622 | 95638 | outa := DAE.ATTR( | |
| 623 | ConnectorType.toDAE(ina.connectorType), | ||
| 624 | parallelismToSCode(ina.parallelism), | ||
| 625 | variabilityToSCode(ina.variability), | ||
| 626 | directionToAbsyn(ina.direction), | ||
| 627 | innerOuterToAbsyn(ina.innerOuter), | ||
| 628 | visibilityToSCode(vis) | ||
| 629 | ); | ||
| 630 | end toDAE; | ||
| 631 | |||
| 632 | function toString | ||
| 633 | input Attributes attr; | ||
| 634 | input Type ty; | ||
| 635 | output String str; | ||
| 636 | algorithm | ||
| 637 |
3/4✓ Branch 0 taken 1110 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 1118 times.
✗ Branch 3 not taken.
|
3346 | str := (if attr.isRedeclare then "redeclare " else "") + |
| 638 | (if attr.isFinal then "final " else "") + | ||
| 639 | Prefixes.unparseInnerOuter(attr.innerOuter) + | ||
| 640 | Prefixes.unparseReplaceable(attr.isReplaceable) + | ||
| 641 | Prefixes.unparseParallelism(attr.parallelism) + | ||
| 642 | ConnectorType.unparse(attr.connectorType) + | ||
| 643 | Prefixes.unparseVariability(attr.variability, ty) + | ||
| 644 | Prefixes.unparseDirection(attr.direction); | ||
| 645 | end toString; | ||
| 646 | |||
| 647 | function toFlatStream | ||
| 648 | input Attributes attr; | ||
| 649 | input Type ty; | ||
| 650 | input output IOStream.IOStream s; | ||
| 651 | input Boolean isTopLevel = true; | ||
| 652 | algorithm | ||
| 653 | 955 | s := IOStream.append(s, Prefixes.unparseVariability(attr.variability, ty)); | |
| 654 | |||
| 655 |
2/2✓ Branch 0 taken 788 times.
✓ Branch 1 taken 167 times.
|
955 | if isTopLevel then |
| 656 | 167 | s := IOStream.append(s, Prefixes.unparseDirection(attr.direction)); | |
| 657 | end if; | ||
| 658 | end toFlatStream; | ||
| 659 | |||
| 660 | annotation(__OpenModelica_Interface="nf_frontend"); | ||
| 661 | end NFAttributes; | ||
| 662 | |||
| 663 |