OMCompiler/Compiler/NFFrontEnd/NFClass.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 NFClass | ||
| 37 | |||
| 38 | import Attributes = NFAttributes; | ||
| 39 | import BaseModelica; | ||
| 40 | import NFCall.Call; | ||
| 41 | import Component = NFComponent; | ||
| 42 | import ComponentRef = NFComponentRef; | ||
| 43 | import Dimension = NFDimension; | ||
| 44 | import Expression = NFExpression; | ||
| 45 | import NFClassTree.ClassTree; | ||
| 46 | import NFInstNode.InstNode; | ||
| 47 | import NFInstNode; | ||
| 48 | import NFModifier.Modifier; | ||
| 49 | import NFSections.Sections; | ||
| 50 | import NFStatement.Statement; | ||
| 51 | import Record = NFRecord; | ||
| 52 | import Restriction = NFRestriction; | ||
| 53 | import SCode.Element; | ||
| 54 | import Type = NFType; | ||
| 55 | |||
| 56 | protected | ||
| 57 | import Absyn; | ||
| 58 | import DAE; | ||
| 59 | import AbsynUtil; | ||
| 60 | import Binding = NFBinding; | ||
| 61 | import Class = NFClass; | ||
| 62 | import ComplexType = NFComplexType; | ||
| 63 | import IOStream; | ||
| 64 | import SCode; | ||
| 65 | import SCodeUtil; | ||
| 66 | import System; | ||
| 67 | import MetaModelica.Dangerous.listReverseInPlace; | ||
| 68 | |||
| 69 | public | ||
| 70 | |||
| 71 | constant Prefixes DEFAULT_PREFIXES = Prefixes.PREFIXES( | ||
| 72 | SCode.Encapsulated.NOT_ENCAPSULATED(), | ||
| 73 | SCode.Partial.NOT_PARTIAL(), | ||
| 74 | SCode.Final.NOT_FINAL(), | ||
| 75 | Absyn.InnerOuter.NOT_INNER_OUTER(), | ||
| 76 | SCode.Replaceable.NOT_REPLACEABLE() | ||
| 77 | ); | ||
| 78 | |||
| 79 | uniontype Prefixes | ||
| 80 | record PREFIXES | ||
| 81 | SCode.Encapsulated encapsulatedPrefix; | ||
| 82 | SCode.Partial partialPrefix; | ||
| 83 | SCode.Final finalPrefix; | ||
| 84 | Absyn.InnerOuter innerOuter; | ||
| 85 | SCode.Replaceable replaceablePrefix; | ||
| 86 | end PREFIXES; | ||
| 87 | |||
| 88 | function isEqual | ||
| 89 | input Prefixes prefs1; | ||
| 90 | input Prefixes prefs2; | ||
| 91 | output Boolean isEqual = valueEq(prefs1, prefs2); | ||
| 92 | end isEqual; | ||
| 93 | |||
| 94 | function isPartial | ||
| 95 | input Prefixes prefs; | ||
| 96 | output Boolean isPartial = SCodeUtil.partialBool(prefs.partialPrefix); | ||
| 97 | end isPartial; | ||
| 98 | |||
| 99 | function isEncapsulated | ||
| 100 | input Prefixes prefs; | ||
| 101 | output Boolean isEncapsulated = SCodeUtil.encapsulatedBool(prefs.encapsulatedPrefix); | ||
| 102 | end isEncapsulated; | ||
| 103 | end Prefixes; | ||
| 104 | |||
| 105 | record NOT_INSTANTIATED end NOT_INSTANTIATED; | ||
| 106 | |||
| 107 | record PARTIAL_CLASS | ||
| 108 | ClassTree elements; | ||
| 109 | Modifier modifier; | ||
| 110 | Modifier ccMod; | ||
| 111 | Prefixes prefixes; | ||
| 112 | end PARTIAL_CLASS; | ||
| 113 | |||
| 114 | record PARTIAL_BUILTIN | ||
| 115 | Type ty; | ||
| 116 | ClassTree elements; | ||
| 117 | Modifier modifier; | ||
| 118 | Prefixes prefixes; | ||
| 119 | Restriction restriction; | ||
| 120 | end PARTIAL_BUILTIN; | ||
| 121 | |||
| 122 | record EXPANDED_CLASS | ||
| 123 | ClassTree elements; | ||
| 124 | Modifier modifier; | ||
| 125 | Modifier ccMod; | ||
| 126 | Prefixes prefixes; | ||
| 127 | Restriction restriction; | ||
| 128 | end EXPANDED_CLASS; | ||
| 129 | |||
| 130 | record EXPANDED_DERIVED | ||
| 131 | InstNode baseClass; | ||
| 132 | Modifier modifier; | ||
| 133 | Modifier ccMod; | ||
| 134 | array<Dimension> dims; | ||
| 135 | Prefixes prefixes; | ||
| 136 | Attributes attributes; | ||
| 137 | Restriction restriction; | ||
| 138 | end EXPANDED_DERIVED; | ||
| 139 | |||
| 140 | record INSTANCED_CLASS | ||
| 141 | Type ty; | ||
| 142 | ClassTree elements; | ||
| 143 | Sections sections; | ||
| 144 | Prefixes prefixes; | ||
| 145 | Restriction restriction; | ||
| 146 | end INSTANCED_CLASS; | ||
| 147 | |||
| 148 | record INSTANCED_BUILTIN | ||
| 149 | Type ty; | ||
| 150 | ClassTree elements; | ||
| 151 | Restriction restriction; | ||
| 152 | end INSTANCED_BUILTIN; | ||
| 153 | |||
| 154 | record TYPED_DERIVED | ||
| 155 | Type ty; | ||
| 156 | InstNode baseClass; | ||
| 157 | Restriction restriction; | ||
| 158 | end TYPED_DERIVED; | ||
| 159 | |||
| 160 | record DAE_TYPE | ||
| 161 | DAE.Type ty; | ||
| 162 | end DAE_TYPE; | ||
| 163 | |||
| 164 | function fromSCode | ||
| 165 | input list<SCode.Element> elements; | ||
| 166 | input Boolean isClassExtends; | ||
| 167 | input InstNode scope; | ||
| 168 | input Prefixes prefixes; | ||
| 169 | output Class cls; | ||
| 170 | protected | ||
| 171 | ClassTree tree; | ||
| 172 | algorithm | ||
| 173 | 79606 | tree := ClassTree.fromSCode(elements, isClassExtends, scope); | |
| 174 | 79604 | cls := PARTIAL_CLASS(tree, Modifier.NOMOD(), Modifier.NOMOD(), prefixes); | |
| 175 | end fromSCode; | ||
| 176 | |||
| 177 | function initImports | ||
| 178 | input output Class cls; | ||
| 179 | input InstNode parent; | ||
| 180 | algorithm | ||
| 181 | () := match cls | ||
| 182 | case PARTIAL_CLASS() | ||
| 183 | algorithm | ||
| 184 | 93243 | cls.elements := ClassTree.initImports(cls.elements, parent); | |
| 185 | then | ||
| 186 | (); | ||
| 187 | |||
| 188 | else (); | ||
| 189 | end match; | ||
| 190 | end initImports; | ||
| 191 | |||
| 192 | function fromEnumeration | ||
| 193 | input list<SCode.Enum> literals; | ||
| 194 | input Type enumType; | ||
| 195 | input Prefixes prefixes; | ||
| 196 | input InstNode enumClass; | ||
| 197 | output Class cls; | ||
| 198 | protected | ||
| 199 | ClassTree tree; | ||
| 200 | algorithm | ||
| 201 | 1179 | tree := ClassTree.fromEnumeration(literals, enumType, enumClass); | |
| 202 | 1178 | cls := PARTIAL_BUILTIN(enumType, tree, Modifier.NOMOD(), prefixes, Restriction.ENUMERATION()); | |
| 203 | end fromEnumeration; | ||
| 204 | |||
| 205 | function makeRecordConstructor | ||
| 206 | input list<InstNode> fields; | ||
| 207 | input InstNode out; | ||
| 208 | output Class cls; | ||
| 209 | protected | ||
| 210 | ClassTree tree; | ||
| 211 | algorithm | ||
| 212 | 2789 | tree := ClassTree.fromRecordConstructor(fields, out); | |
| 213 | 2789 | cls := INSTANCED_CLASS(Type.UNKNOWN(), tree, Sections.EMPTY(), | |
| 214 | DEFAULT_PREFIXES, Restriction.RECORD_CONSTRUCTOR()); | ||
| 215 | end makeRecordConstructor; | ||
| 216 | |||
| 217 | function initExpandedClass | ||
| 218 | input output Class cls; | ||
| 219 | algorithm | ||
| 220 | cls := match cls | ||
| 221 | case PARTIAL_CLASS() | ||
| 222 | 71411 | then EXPANDED_CLASS(cls.elements, cls.modifier, cls.ccMod, cls.prefixes, Restriction.UNKNOWN()); | |
| 223 | end match; | ||
| 224 | end initExpandedClass; | ||
| 225 | |||
| 226 | function getSections | ||
| 227 | input Class cls; | ||
| 228 | output Sections sections; | ||
| 229 | algorithm | ||
| 230 | sections := match cls | ||
| 231 | 70695 | case INSTANCED_CLASS() then cls.sections; | |
| 232 | 14 | case TYPED_DERIVED() then getSections(InstNode.getClass(cls.baseClass)); | |
| 233 | else Sections.EMPTY(); | ||
| 234 | end match; | ||
| 235 | end getSections; | ||
| 236 | |||
| 237 | function setSections | ||
| 238 | input Sections sections; | ||
| 239 | input output Class cls; | ||
| 240 | algorithm | ||
| 241 | cls := match cls | ||
| 242 | case INSTANCED_CLASS() | ||
| 243 | 98287 | then INSTANCED_CLASS(cls.ty, cls.elements, sections, cls.prefixes, cls.restriction); | |
| 244 | |||
| 245 | case TYPED_DERIVED() | ||
| 246 | algorithm | ||
| 247 | 2 | InstNode.classApply(cls.baseClass, setSections, sections); | |
| 248 | then | ||
| 249 | cls; | ||
| 250 | end match; | ||
| 251 | end setSections; | ||
| 252 | |||
| 253 | function lookupElement | ||
| 254 | input String name; | ||
| 255 | input Class cls; | ||
| 256 | output InstNode node; | ||
| 257 | output Boolean isImport; | ||
| 258 | algorithm | ||
| 259 | 6244448 | (node, isImport) := ClassTree.lookupElement(name, classTree(cls)); | |
| 260 | end lookupElement; | ||
| 261 | |||
| 262 | function tryLookupElement | ||
| 263 | input String name; | ||
| 264 | input Class cls; | ||
| 265 | output Option<InstNode> node; | ||
| 266 | output Boolean isImport; | ||
| 267 | protected | ||
| 268 | InstNode n; | ||
| 269 | algorithm | ||
| 270 | try | ||
| 271 | 58162 | (n, isImport) := ClassTree.lookupElement(name, classTree(cls)); | |
| 272 | node := SOME(n); | ||
| 273 | else | ||
| 274 | node := NONE(); | ||
| 275 | 55387 | isImport := false; | |
| 276 | end try; | ||
| 277 | end tryLookupElement; | ||
| 278 | |||
| 279 | function lookupComponentIndex | ||
| 280 | input String name; | ||
| 281 | input Class cls; | ||
| 282 | output Integer index; | ||
| 283 | algorithm | ||
| 284 | 175829 | index := ClassTree.lookupComponentIndex(name, classTree(cls)); | |
| 285 | end lookupComponentIndex; | ||
| 286 | |||
| 287 | function nthComponent | ||
| 288 | input Integer index; | ||
| 289 | input Class cls; | ||
| 290 | output InstNode component; | ||
| 291 | algorithm | ||
| 292 | 3584 | component := ClassTree.nthComponent(index, classTree(cls)); | |
| 293 | end nthComponent; | ||
| 294 | |||
| 295 | function getComponents | ||
| 296 | input Class cls; | ||
| 297 | output array<InstNode> comps = ClassTree.getComponents(classTree(cls)); | ||
| 298 | end getComponents; | ||
| 299 | |||
| 300 | function lookupAttributeBinding | ||
| 301 | input String name; | ||
| 302 | input Class cls; | ||
| 303 | output Binding binding; | ||
| 304 | protected | ||
| 305 | InstNode attr_node; | ||
| 306 | algorithm | ||
| 307 | try | ||
| 308 | 45652 | attr_node := ClassTree.lookupElement(name, classTree(cls)); | |
| 309 | 44104 | binding := Component.getBinding(InstNode.component(attr_node)); | |
| 310 | else | ||
| 311 | binding := NFBinding.EMPTY_BINDING; | ||
| 312 | end try; | ||
| 313 | end lookupAttributeBinding; | ||
| 314 | |||
| 315 | function lookupAttributeValue | ||
| 316 | input String name; | ||
| 317 | input Class cls; | ||
| 318 | output Option<Expression> value = Binding.typedExp(lookupAttributeBinding(name, cls)); | ||
| 319 | end lookupAttributeValue; | ||
| 320 | |||
| 321 | function isOnlyBuiltin | ||
| 322 | input Class cls; | ||
| 323 | output Boolean builtin; | ||
| 324 | algorithm | ||
| 325 | builtin := match cls | ||
| 326 | case PARTIAL_BUILTIN() then true; | ||
| 327 | case INSTANCED_BUILTIN() then true; | ||
| 328 | else false; | ||
| 329 | end match; | ||
| 330 | end isOnlyBuiltin; | ||
| 331 | |||
| 332 | function isBuiltin | ||
| 333 | input Class cls; | ||
| 334 | output Boolean isBuiltin; | ||
| 335 | algorithm | ||
| 336 | isBuiltin := match cls | ||
| 337 | case PARTIAL_BUILTIN() then true; | ||
| 338 | case INSTANCED_BUILTIN() then true; | ||
| 339 | 2371 | case EXPANDED_DERIVED() then isBuiltin(InstNode.getClass(cls.baseClass)); | |
| 340 | ✗ | case TYPED_DERIVED() then isBuiltin(InstNode.getClass(cls.baseClass)); | |
| 341 | else false; | ||
| 342 | end match; | ||
| 343 | end isBuiltin; | ||
| 344 | |||
| 345 | function classTree | ||
| 346 | input Class cls; | ||
| 347 | output ClassTree tree; | ||
| 348 | algorithm | ||
| 349 | tree := match cls | ||
| 350 | 143311 | case Class.PARTIAL_CLASS() then cls.elements; | |
| 351 | 919130 | case Class.PARTIAL_BUILTIN() then cls.elements; | |
| 352 | 2649661 | case Class.EXPANDED_CLASS() then cls.elements; | |
| 353 | 92039 | case Class.EXPANDED_DERIVED() then classTree(InstNode.getClass(cls.baseClass)); | |
| 354 | 4380522 | case Class.INSTANCED_CLASS() then cls.elements; | |
| 355 | 4152246 | case Class.INSTANCED_BUILTIN() then cls.elements; | |
| 356 | 5581 | case Class.TYPED_DERIVED() then classTree(InstNode.getClass(cls.baseClass)); | |
| 357 | else ClassTree.EMPTY_TREE(); | ||
| 358 | end match; | ||
| 359 | end classTree; | ||
| 360 | |||
| 361 | function setClassTree | ||
| 362 | input ClassTree tree; | ||
| 363 | input output Class cls; | ||
| 364 | algorithm | ||
| 365 | () := match cls | ||
| 366 | 3744 | case Class.PARTIAL_CLASS() algorithm cls.elements := tree; then (); | |
| 367 | 170792 | case Class.EXPANDED_CLASS() algorithm cls.elements := tree; then (); | |
| 368 | ✗ | case Class.PARTIAL_BUILTIN() algorithm cls.elements := tree; then (); | |
| 369 | 12 | case Class.INSTANCED_CLASS() algorithm cls.elements := tree; then (); | |
| 370 | ✗ | case Class.INSTANCED_BUILTIN() algorithm cls.elements := tree; then (); | |
| 371 | end match; | ||
| 372 | end setClassTree; | ||
| 373 | |||
| 374 | function classTreeApply | ||
| 375 | input output Class cls; | ||
| 376 | input FuncType func; | ||
| 377 | |||
| 378 | partial function FuncType | ||
| 379 | input output ClassTree tree; | ||
| 380 | end FuncType; | ||
| 381 | algorithm | ||
| 382 | () := match cls | ||
| 383 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | case Class.PARTIAL_CLASS() algorithm cls.elements := func(cls.elements); then (); |
| 384 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3976 times.
|
3976 | case Class.EXPANDED_CLASS() algorithm cls.elements := func(cls.elements); then (); |
| 385 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8475 times.
|
8475 | case Class.PARTIAL_BUILTIN() algorithm cls.elements := func(cls.elements); then (); |
| 386 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
|
48 | case Class.INSTANCED_CLASS() algorithm cls.elements := func(cls.elements); then (); |
| 387 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
|
52 | case Class.INSTANCED_BUILTIN() algorithm cls.elements := func(cls.elements); then (); |
| 388 | else (); | ||
| 389 | end match; | ||
| 390 | end classTreeApply; | ||
| 391 | |||
| 392 | function getModifier | ||
| 393 | input Class cls; | ||
| 394 | output Modifier modifier; | ||
| 395 | algorithm | ||
| 396 | modifier := match cls | ||
| 397 | 30586 | case PARTIAL_CLASS() then cls.modifier; | |
| 398 | 301388 | case EXPANDED_CLASS() then cls.modifier; | |
| 399 | 695737 | case EXPANDED_DERIVED() then cls.modifier; | |
| 400 | 862047 | case PARTIAL_BUILTIN() then cls.modifier; | |
| 401 | else Modifier.NOMOD(); | ||
| 402 | end match; | ||
| 403 | end getModifier; | ||
| 404 | |||
| 405 | function getCCModifier | ||
| 406 | input Class cls; | ||
| 407 | output Modifier modifier; | ||
| 408 | algorithm | ||
| 409 | modifier := match cls | ||
| 410 | 13230 | case PARTIAL_CLASS() then cls.ccMod; | |
| 411 | ✗ | case EXPANDED_CLASS() then cls.ccMod; | |
| 412 | ✗ | case EXPANDED_DERIVED() then cls.ccMod; | |
| 413 | else Modifier.NOMOD(); | ||
| 414 | end match; | ||
| 415 | end getCCModifier; | ||
| 416 | |||
| 417 | function setModifier | ||
| 418 | input Modifier modifier; | ||
| 419 | input output Class cls; | ||
| 420 | algorithm | ||
| 421 | () := match cls | ||
| 422 | case PARTIAL_CLASS() | ||
| 423 | algorithm | ||
| 424 | ✗ | cls.modifier := modifier; | |
| 425 | then | ||
| 426 | (); | ||
| 427 | case EXPANDED_CLASS() | ||
| 428 | algorithm | ||
| 429 | ✗ | cls.modifier := modifier; | |
| 430 | then | ||
| 431 | (); | ||
| 432 | case EXPANDED_DERIVED() | ||
| 433 | algorithm | ||
| 434 | ✗ | cls.modifier := modifier; | |
| 435 | then | ||
| 436 | (); | ||
| 437 | case PARTIAL_BUILTIN() | ||
| 438 | algorithm | ||
| 439 | ✗ | cls.modifier := modifier; | |
| 440 | then | ||
| 441 | (); | ||
| 442 | else | ||
| 443 | algorithm | ||
| 444 | ✗ | Error.terminate(getInstanceName() + " got non-modifiable class", sourceInfo()); | |
| 445 | ✗ | then | |
| 446 | fail(); | ||
| 447 | end match; | ||
| 448 | end setModifier; | ||
| 449 | |||
| 450 | function mergeModifier | ||
| 451 | input Modifier modifier; | ||
| 452 | input output Class cls; | ||
| 453 | algorithm | ||
| 454 | () := match cls | ||
| 455 | case PARTIAL_CLASS() | ||
| 456 | algorithm | ||
| 457 | 1782 | cls.modifier := Modifier.merge(modifier, cls.modifier); | |
| 458 | then | ||
| 459 | (); | ||
| 460 | case EXPANDED_CLASS() | ||
| 461 | algorithm | ||
| 462 | ✗ | cls.modifier := Modifier.merge(modifier, cls.modifier); | |
| 463 | then | ||
| 464 | (); | ||
| 465 | case EXPANDED_DERIVED() | ||
| 466 | algorithm | ||
| 467 | 4 | cls.modifier := Modifier.merge(modifier, cls.modifier); | |
| 468 | then | ||
| 469 | (); | ||
| 470 | case PARTIAL_BUILTIN() | ||
| 471 | algorithm | ||
| 472 | 8 | cls.modifier := Modifier.merge(modifier, cls.modifier); | |
| 473 | then | ||
| 474 | (); | ||
| 475 | else | ||
| 476 | algorithm | ||
| 477 | ✗ | Error.terminate(getInstanceName() + " got non-modifiable class", sourceInfo()); | |
| 478 | ✗ | then | |
| 479 | fail(); | ||
| 480 | end match; | ||
| 481 | end mergeModifier; | ||
| 482 | |||
| 483 | function isIdentical | ||
| 484 | input Class cls1; | ||
| 485 | input Class cls2; | ||
| 486 | output Boolean identical = false; | ||
| 487 | algorithm | ||
| 488 |
1/2✓ Branch 0 taken 32943 times.
✗ Branch 1 not taken.
|
32943 | if referenceEq(cls1, cls2) then |
| 489 | identical := true; | ||
| 490 | else | ||
| 491 | identical := match (cls1, cls2) | ||
| 492 | case (EXPANDED_CLASS(), EXPANDED_CLASS()) | ||
| 493 |
2/4✓ Branch 1 taken 2794 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2794 times.
|
2794 | then Prefixes.isEqual(cls1.prefixes, cls2.prefixes) and |
| 494 | ClassTree.isIdentical(cls1.elements, cls2.elements); | ||
| 495 | |||
| 496 | case (INSTANCED_BUILTIN(), INSTANCED_BUILTIN()) | ||
| 497 | algorithm | ||
| 498 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 8745 times.
|
8745 | if not Type.isEqual(cls1.ty, cls2.ty) then |
| 499 | ✗ | return; | |
| 500 | end if; | ||
| 501 | then | ||
| 502 | true; | ||
| 503 | |||
| 504 | else true; | ||
| 505 | end match; | ||
| 506 | end if; | ||
| 507 | end isIdentical; | ||
| 508 | |||
| 509 | function hasDimensions | ||
| 510 | input Class cls; | ||
| 511 | output Boolean hasDims; | ||
| 512 | algorithm | ||
| 513 | hasDims := match cls | ||
| 514 | case EXPANDED_DERIVED() | ||
| 515 |
4/6✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1 time.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 time.
|
4 | then arrayLength(cls.dims) > 0 or hasDimensions(InstNode.getClass(cls.baseClass)); |
| 516 | ✗ | case TYPED_DERIVED() then Type.isArray(cls.ty); | |
| 517 | else false; | ||
| 518 | end match; | ||
| 519 | end hasDimensions; | ||
| 520 | |||
| 521 | function getDimensions | ||
| 522 | input Class cls; | ||
| 523 | output list<Dimension> dims; | ||
| 524 | algorithm | ||
| 525 | dims := match cls | ||
| 526 | ✗ | case INSTANCED_CLASS() then Type.arrayDims(cls.ty); | |
| 527 | ✗ | case INSTANCED_BUILTIN() then Type.arrayDims(cls.ty); | |
| 528 | ✗ | case TYPED_DERIVED() then Type.arrayDims(cls.ty); | |
| 529 | else {}; | ||
| 530 | end match; | ||
| 531 | end getDimensions; | ||
| 532 | |||
| 533 | function dimensionCount | ||
| 534 | input Class cls; | ||
| 535 | output Integer count; | ||
| 536 | algorithm | ||
| 537 | count := match cls | ||
| 538 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | case EXPANDED_DERIVED() then arrayLength(cls.dims); |
| 539 | 9636 | case INSTANCED_CLASS() then Type.dimensionCount(cls.ty); | |
| 540 | 546283 | case INSTANCED_BUILTIN() then Type.dimensionCount(cls.ty); | |
| 541 | 2106 | case TYPED_DERIVED() then Type.dimensionCount(cls.ty); | |
| 542 | else 0; | ||
| 543 | end match; | ||
| 544 | end dimensionCount; | ||
| 545 | |||
| 546 | function getAttributes | ||
| 547 | input Class cls; | ||
| 548 | output Attributes attr; | ||
| 549 | algorithm | ||
| 550 | attr := match cls | ||
| 551 | ✗ | case EXPANDED_DERIVED() then cls.attributes; | |
| 552 | else NFAttributes.DEFAULT_ATTR; | ||
| 553 | end match; | ||
| 554 | end getAttributes; | ||
| 555 | |||
| 556 | function getTypeAttributes | ||
| 557 | input Class cls; | ||
| 558 | output list<Modifier> attributes = {}; | ||
| 559 | protected | ||
| 560 | array<InstNode> comps; | ||
| 561 | Modifier mod; | ||
| 562 | algorithm | ||
| 563 | try | ||
| 564 | 300282 | comps := ClassTree.getComponents(classTree(cls)); | |
| 565 | |||
| 566 |
2/2✓ Branch 1 taken 3051118 times.
✓ Branch 2 taken 299940 times.
|
3351058 | for c in comps loop |
| 567 | 3051118 | mod := Component.getModifier(InstNode.component(c)); | |
| 568 | |||
| 569 |
2/2✓ Branch 1 taken 553254 times.
✓ Branch 2 taken 2497864 times.
|
3051118 | if not Modifier.isEmpty(mod) then |
| 570 | attributes := mod :: attributes; | ||
| 571 | end if; | ||
| 572 | end for; | ||
| 573 | else | ||
| 574 | end try; | ||
| 575 | end getTypeAttributes; | ||
| 576 | |||
| 577 | function getType | ||
| 578 | input Class cls; | ||
| 579 | input InstNode clsNode; | ||
| 580 | output Type ty; | ||
| 581 | algorithm | ||
| 582 | ty := match cls | ||
| 583 | 489 | case PARTIAL_BUILTIN() then cls.ty; | |
| 584 | 56695 | case EXPANDED_DERIVED() then getType(InstNode.getClass(cls.baseClass), cls.baseClass); | |
| 585 | 448487 | case INSTANCED_CLASS() then cls.ty; | |
| 586 | 342364 | case INSTANCED_BUILTIN() then cls.ty; | |
| 587 | 10 | case TYPED_DERIVED() then cls.ty; | |
| 588 | else Type.UNKNOWN(); | ||
| 589 | end match; | ||
| 590 | end getType; | ||
| 591 | |||
| 592 | function setType | ||
| 593 | input Type ty; | ||
| 594 | input output Class cls; | ||
| 595 | algorithm | ||
| 596 | () := match cls | ||
| 597 | case PARTIAL_BUILTIN() | ||
| 598 | algorithm | ||
| 599 | ✗ | cls.ty := ty; | |
| 600 | then | ||
| 601 | (); | ||
| 602 | |||
| 603 | case EXPANDED_DERIVED() | ||
| 604 | algorithm | ||
| 605 | ✗ | InstNode.classApply(cls.baseClass, setType, ty); | |
| 606 | then | ||
| 607 | (); | ||
| 608 | |||
| 609 | case INSTANCED_CLASS() | ||
| 610 | algorithm | ||
| 611 | 2829 | cls.ty := ty; | |
| 612 | then | ||
| 613 | (); | ||
| 614 | |||
| 615 | case INSTANCED_BUILTIN() | ||
| 616 | algorithm | ||
| 617 | ✗ | cls.ty := ty; | |
| 618 | then | ||
| 619 | (); | ||
| 620 | |||
| 621 | case TYPED_DERIVED() | ||
| 622 | algorithm | ||
| 623 | ✗ | cls.ty := ty; | |
| 624 | then | ||
| 625 | (); | ||
| 626 | |||
| 627 | else (); | ||
| 628 | end match; | ||
| 629 | end setType; | ||
| 630 | |||
| 631 | function restriction | ||
| 632 | input Class cls; | ||
| 633 | output Restriction res; | ||
| 634 | algorithm | ||
| 635 | res := match cls | ||
| 636 | 795 | case PARTIAL_BUILTIN() then cls.restriction; | |
| 637 | 1111334 | case EXPANDED_CLASS() then cls.restriction; | |
| 638 | 542391 | case EXPANDED_DERIVED() then cls.restriction; | |
| 639 | 945182 | case INSTANCED_CLASS() then cls.restriction; | |
| 640 | 644198 | case INSTANCED_BUILTIN() then cls.restriction; | |
| 641 | 9 | case TYPED_DERIVED() then cls.restriction; | |
| 642 | else Restriction.UNKNOWN(); | ||
| 643 | end match; | ||
| 644 | end restriction; | ||
| 645 | |||
| 646 | function setRestriction | ||
| 647 | input Restriction res; | ||
| 648 | input output Class cls; | ||
| 649 | algorithm | ||
| 650 | () := match cls | ||
| 651 | // PARTIAL_BUILTIN is only used for predefined builtin types and not needed here. | ||
| 652 | ✗ | case EXPANDED_CLASS() algorithm cls.restriction := res; then (); | |
| 653 | ✗ | case EXPANDED_DERIVED() algorithm cls.restriction := res; then (); | |
| 654 | 12030 | case INSTANCED_CLASS() algorithm cls.restriction := res; then (); | |
| 655 | 316110 | case INSTANCED_BUILTIN() algorithm cls.restriction := res; then (); | |
| 656 | ✗ | case TYPED_DERIVED() algorithm cls.restriction := res; then (); | |
| 657 | end match; | ||
| 658 | end setRestriction; | ||
| 659 | |||
| 660 | function isConnectorClass | ||
| 661 | input Class cls; | ||
| 662 | output Boolean isConnector = Restriction.isConnector(restriction(cls)); | ||
| 663 | end isConnectorClass; | ||
| 664 | |||
| 665 | function isNonexpandableConnectorClass | ||
| 666 | input Class cls; | ||
| 667 | output Boolean isConnector = Restriction.isNonexpandableConnector(restriction(cls)); | ||
| 668 | end isNonexpandableConnectorClass; | ||
| 669 | |||
| 670 | function isExpandableConnectorClass | ||
| 671 | input Class cls; | ||
| 672 | output Boolean isConnector = Restriction.isExpandableConnector(restriction(cls)); | ||
| 673 | end isExpandableConnectorClass; | ||
| 674 | |||
| 675 | function isExternalObject | ||
| 676 | input Class cls; | ||
| 677 | output Boolean isExternalObject = Restriction.isExternalObject(restriction(cls)); | ||
| 678 | end isExternalObject; | ||
| 679 | |||
| 680 | function isFunction | ||
| 681 | input Class cls; | ||
| 682 | output Boolean isFunction = Restriction.isFunction(restriction(cls)); | ||
| 683 | end isFunction; | ||
| 684 | |||
| 685 | function isEnumeration | ||
| 686 | input Class cls; | ||
| 687 | output Boolean isEnum; | ||
| 688 | algorithm | ||
| 689 | isEnum := match cls | ||
| 690 | case PARTIAL_BUILTIN(ty = Type.ENUMERATION()) then true; | ||
| 691 | case INSTANCED_BUILTIN(ty = Type.ENUMERATION()) then true; | ||
| 692 | 8 | case EXPANDED_DERIVED() then isEnumeration(InstNode.getClass(cls.baseClass)); | |
| 693 | ✗ | case TYPED_DERIVED() then isEnumeration(InstNode.getClass(cls.baseClass)); | |
| 694 | else false; | ||
| 695 | end match; | ||
| 696 | end isEnumeration; | ||
| 697 | |||
| 698 | function isExternalFunction | ||
| 699 | input Class cls; | ||
| 700 | output Boolean isExtFunc; | ||
| 701 | algorithm | ||
| 702 | isExtFunc := match cls | ||
| 703 | local | ||
| 704 | String lang; | ||
| 705 | |||
| 706 | ✗ | case EXPANDED_DERIVED() then isExternalFunction(InstNode.getClass(cls.baseClass)); | |
| 707 |
3/4✓ Branch 0 taken 58340 times.
✓ Branch 1 taken 1960 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 58340 times.
|
60300 | case INSTANCED_CLASS(sections = Sections.EXTERNAL(language = lang)) then lang <> "builtin"; |
| 708 | 4 | case TYPED_DERIVED() then isExternalFunction(InstNode.getClass(cls.baseClass)); | |
| 709 | else false; | ||
| 710 | end match; | ||
| 711 | end isExternalFunction; | ||
| 712 | |||
| 713 | function isOverdetermined | ||
| 714 | input Class cls; | ||
| 715 | output Boolean isOverdetermined; | ||
| 716 | algorithm | ||
| 717 | try | ||
| 718 | 78247 | lookupElement("equalityConstraint", cls); | |
| 719 | // set the external flag that signals the presence of expandable connectors in the model | ||
| 720 | 17922 | System.setHasOverconstrainedConnectors(true); | |
| 721 | isOverdetermined := true; | ||
| 722 | else | ||
| 723 | isOverdetermined := false; | ||
| 724 | end try; | ||
| 725 | end isOverdetermined; | ||
| 726 | |||
| 727 | function getPrefixes | ||
| 728 | input Class cls; | ||
| 729 | output Prefixes prefs; | ||
| 730 | algorithm | ||
| 731 | prefs := match cls | ||
| 732 | 28790 | case PARTIAL_CLASS() then cls.prefixes; | |
| 733 | 9824 | case PARTIAL_BUILTIN() then cls.prefixes; | |
| 734 | 1052456 | case EXPANDED_CLASS() then cls.prefixes; | |
| 735 | 474644 | case EXPANDED_DERIVED() then cls.prefixes; | |
| 736 | 2981015 | case INSTANCED_CLASS() then cls.prefixes; | |
| 737 | 4 | case TYPED_DERIVED() then getPrefixes(InstNode.getClass(cls.baseClass)); | |
| 738 | else DEFAULT_PREFIXES; | ||
| 739 | end match; | ||
| 740 | end getPrefixes; | ||
| 741 | |||
| 742 | function setPrefixes | ||
| 743 | input Prefixes prefs; | ||
| 744 | input output Class cls; | ||
| 745 | algorithm | ||
| 746 | () := match cls | ||
| 747 | case PARTIAL_CLASS() | ||
| 748 | algorithm | ||
| 749 | ✗ | cls.prefixes := prefs; | |
| 750 | then | ||
| 751 | (); | ||
| 752 | |||
| 753 | case PARTIAL_BUILTIN() | ||
| 754 | algorithm | ||
| 755 | 3 | cls.prefixes := prefs; | |
| 756 | then | ||
| 757 | (); | ||
| 758 | |||
| 759 | case EXPANDED_CLASS() | ||
| 760 | algorithm | ||
| 761 | ✗ | cls.prefixes := prefs; | |
| 762 | then | ||
| 763 | (); | ||
| 764 | |||
| 765 | case EXPANDED_DERIVED() | ||
| 766 | algorithm | ||
| 767 | 2 | cls.prefixes := prefs; | |
| 768 | then | ||
| 769 | (); | ||
| 770 | |||
| 771 | case INSTANCED_CLASS() | ||
| 772 | algorithm | ||
| 773 | ✗ | cls.prefixes := prefs; | |
| 774 | then | ||
| 775 | (); | ||
| 776 | end match; | ||
| 777 | end setPrefixes; | ||
| 778 | |||
| 779 | function isEncapsulated | ||
| 780 | input Class cls; | ||
| 781 | output Boolean isEncapsulated = Prefixes.isEncapsulated(getPrefixes(cls)); | ||
| 782 | end isEncapsulated; | ||
| 783 | |||
| 784 | function isPartial | ||
| 785 | input Class cls; | ||
| 786 | output Boolean isPartial = Prefixes.isPartial(getPrefixes(cls)); | ||
| 787 | end isPartial; | ||
| 788 | |||
| 789 | function lastBaseClass | ||
| 790 | input output InstNode node; | ||
| 791 | protected | ||
| 792 | Class cls = InstNode.getClass(node); | ||
| 793 | algorithm | ||
| 794 | node := match cls | ||
| 795 | 290138 | case EXPANDED_DERIVED() then lastBaseClass(cls.baseClass); | |
| 796 | 4 | case TYPED_DERIVED() then lastBaseClass(cls.baseClass); | |
| 797 | else node; | ||
| 798 | end match; | ||
| 799 | end lastBaseClass; | ||
| 800 | |||
| 801 | function getDerivedComments | ||
| 802 | input Class cls; | ||
| 803 | input output list<SCode.Comment> cmts; | ||
| 804 | algorithm | ||
| 805 | cmts := match cls | ||
| 806 | 288 | case EXPANDED_DERIVED() then InstNode.getComments(cls.baseClass, cmts); | |
| 807 | ✗ | case TYPED_DERIVED() then InstNode.getComments(cls.baseClass, cmts); | |
| 808 | else | ||
| 809 | algorithm | ||
| 810 |
2/2✓ Branch 3 taken 14608 times.
✓ Branch 4 taken 38641 times.
|
91890 | for ext in ClassTree.getExtends(classTree(cls)) loop |
| 811 | 14608 | cmts := InstNode.getComments(ext, cmts); | |
| 812 | end for; | ||
| 813 | then | ||
| 814 | cmts; | ||
| 815 | |||
| 816 | end match; | ||
| 817 | end getDerivedComments; | ||
| 818 | |||
| 819 | function constrainingClassPath | ||
| 820 | "Returns the path of the constraining class for a given class, either the | ||
| 821 | declared constraining class or the path of the class itself if there's no | ||
| 822 | declared constraining class." | ||
| 823 | input InstNode clsNode; | ||
| 824 | output Absyn.Path path; | ||
| 825 | protected | ||
| 826 | InstNode cls_node = lastBaseClass(clsNode); | ||
| 827 | Prefixes prefs = getPrefixes(InstNode.getClass(cls_node)); | ||
| 828 | algorithm | ||
| 829 | path := match prefs | ||
| 830 | case Prefixes.PREFIXES(replaceablePrefix = SCode.Replaceable.REPLACEABLE( | ||
| 831 | cc = SOME(SCode.ConstrainClass.CONSTRAINCLASS(constrainingClass = path)))) then path; | ||
| 832 | 4 | else InstNode.enclosingScopePath(cls_node); | |
| 833 | end match; | ||
| 834 | end constrainingClassPath; | ||
| 835 | |||
| 836 | function hasOperator | ||
| 837 | input String name; | ||
| 838 | input Class cls; | ||
| 839 | output Boolean hasOperator; | ||
| 840 | protected | ||
| 841 | InstNode op_node; | ||
| 842 | algorithm | ||
| 843 |
2/2✓ Branch 2 taken 2 times.
✓ Branch 3 taken 9 times.
|
11 | if Restriction.isOperatorRecord(restriction(cls)) then |
| 844 | try | ||
| 845 | 2 | op_node := lookupElement(name, cls); | |
| 846 | 2 | hasOperator := SCodeUtil.isOperator(InstNode.definition(op_node)); | |
| 847 | else | ||
| 848 | hasOperator := false; | ||
| 849 | end try; | ||
| 850 | else | ||
| 851 | hasOperator := false; | ||
| 852 | end if; | ||
| 853 | end hasOperator; | ||
| 854 | |||
| 855 | function makeRecordExp | ||
| 856 | input InstNode clsNode; | ||
| 857 | input InstNode scope; | ||
| 858 | input Boolean typed; | ||
| 859 | output Expression exp; | ||
| 860 | protected | ||
| 861 | Class cls; | ||
| 862 | Type ty; | ||
| 863 | InstNode ty_node; | ||
| 864 | NFInstNode.ScopeRef ty_cell; | ||
| 865 | list<Record.Field> fields; | ||
| 866 | array<InstNode> comps; | ||
| 867 | list<Expression> args; | ||
| 868 | algorithm | ||
| 869 | 9915 | cls := InstNode.getClass(clsNode); | |
| 870 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 9915 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 9915 times.
|
9915 | ty as Type.COMPLEX(complexTy = ComplexType.RECORD(constructor = ty_cell)) := getType(cls, clsNode); |
| 871 | 9915 | ty_node := InstNode.borrow(ty_cell); | |
| 872 | 9915 | comps := ClassTree.getComponents(classTree(cls)); | |
| 873 | |||
| 874 |
2/2✓ Branch 0 taken 831 times.
✓ Branch 1 taken 9084 times.
|
9915 | if typed then |
| 875 | // Create a record expression if the instance has been typed. | ||
| 876 |
4/4✓ Branch 0 taken 1817 times.
✓ Branch 1 taken 756 times.
✓ Branch 3 taken 1817 times.
✓ Branch 4 taken 756 times.
|
5146 | args := list(Binding.getExp(Component.getImplicitBinding(InstNode.component(c), scope)) for c in comps); |
| 877 | 756 | exp := Expression.makeRecord(InstNode.fullPath(ty_node), ty, args); | |
| 878 | else | ||
| 879 | // Create a record constructor call if the instance hasn't been typed. | ||
| 880 | // Creating a record expression would skip type checking and potentially | ||
| 881 | // lead to issues like missing type casts. | ||
| 882 | args := {}; | ||
| 883 |
2/2✓ Branch 1 taken 16056 times.
✓ Branch 2 taken 607 times.
|
16663 | for c in comps loop |
| 884 | 16056 | fields := Record.collectRecordField(c, {}); | |
| 885 | |||
| 886 |
3/4✓ Branch 0 taken 16056 times.
✗ Branch 1 not taken.
✓ Branch 4 taken 15918 times.
✓ Branch 5 taken 138 times.
|
16056 | if not listEmpty(fields) and Record.Field.isInput(listHead(fields)) then |
| 887 | 15918 | args := Binding.getExp(Component.getImplicitBinding(InstNode.component(c), scope)) :: args; | |
| 888 | end if; | ||
| 889 | end for; | ||
| 890 | |||
| 891 | 607 | args := listReverseInPlace(args); | |
| 892 | 607 | exp := Expression.CALL(Call.UNTYPED_CALL(ComponentRef.fromNode(ty_node, ty), args, {}, InstNode.scopeRef(scope))); | |
| 893 | end if; | ||
| 894 | end makeRecordExp; | ||
| 895 | |||
| 896 | function toFlatStream | ||
| 897 | input Class cls; | ||
| 898 | input InstNode clsNode; | ||
| 899 | input BaseModelica.OutputFormat format; | ||
| 900 | input String indent; | ||
| 901 | input output IOStream.IOStream s; | ||
| 902 | protected | ||
| 903 | String name; | ||
| 904 | algorithm | ||
| 905 | 26 | name := Util.makeQuotedIdentifier(AbsynUtil.pathString(InstNode.scopePath(clsNode))); | |
| 906 | |||
| 907 | s := match cls | ||
| 908 | case INSTANCED_CLASS() | ||
| 909 | algorithm | ||
| 910 | 26 | s := IOStream.append(s, indent); | |
| 911 | 26 | s := IOStream.append(s, Restriction.toString(cls.restriction)); | |
| 912 | 26 | s := IOStream.append(s, " "); | |
| 913 | 26 | s := IOStream.append(s, name); | |
| 914 | 26 | s := IOStream.append(s, "\n"); | |
| 915 | |||
| 916 |
2/2✓ Branch 2 taken 69 times.
✓ Branch 3 taken 26 times.
|
121 | for comp in ClassTree.getComponents(cls.elements) loop |
| 917 | 69 | s := IOStream.append(s, InstNode.toFlatString(comp, format, indent + " ")); | |
| 918 | 69 | s := IOStream.append(s, ";\n"); | |
| 919 | end for; | ||
| 920 | |||
| 921 | 26 | s := IOStream.append(s, indent); | |
| 922 | 26 | s := IOStream.append(s, "end "); | |
| 923 | 26 | s := IOStream.append(s, name); | |
| 924 | then | ||
| 925 | s; | ||
| 926 | |||
| 927 | case INSTANCED_BUILTIN() | ||
| 928 | algorithm | ||
| 929 | ✗ | s := IOStream.append(s, indent); | |
| 930 | ✗ | s := IOStream.append(s, "INSTANCED_BUILTIN("); | |
| 931 | ✗ | s := IOStream.append(s, name); | |
| 932 | ✗ | s := IOStream.append(s, ")"); | |
| 933 | then | ||
| 934 | s; | ||
| 935 | |||
| 936 | case TYPED_DERIVED() | ||
| 937 | algorithm | ||
| 938 | ✗ | s := IOStream.append(s, indent); | |
| 939 | ✗ | s := IOStream.append(s, Restriction.toString(cls.restriction)); | |
| 940 | ✗ | s := IOStream.append(s, " "); | |
| 941 | ✗ | s := IOStream.append(s, name); | |
| 942 | ✗ | s := IOStream.append(s, " = "); | |
| 943 | ✗ | s := IOStream.append(s, Util.makeQuotedIdentifier(AbsynUtil.pathString(InstNode.scopePath(cls.baseClass)))); | |
| 944 | then | ||
| 945 | s; | ||
| 946 | |||
| 947 | ✗ | else IOStream.append(s, "UNKNOWN_CLASS(" + name + ")"); | |
| 948 | end match; | ||
| 949 | end toFlatStream; | ||
| 950 | |||
| 951 | function toFlatString | ||
| 952 | input Class cls; | ||
| 953 | input InstNode clsNode; | ||
| 954 | input BaseModelica.OutputFormat format = BaseModelica.defaultFormat; | ||
| 955 | input String indent = ""; | ||
| 956 | output String str; | ||
| 957 | protected | ||
| 958 | IOStream.IOStream s; | ||
| 959 | algorithm | ||
| 960 | 26 | s := IOStream.create(getInstanceName(), IOStream.IOStreamType.LIST()); | |
| 961 | 26 | s := toFlatStream(cls, clsNode, format, indent, s); | |
| 962 | 26 | str := IOStream.string(s); | |
| 963 | 26 | IOStream.delete(s); | |
| 964 | end toFlatString; | ||
| 965 | |||
| 966 | annotation(__OpenModelica_Interface="nf_frontend"); | ||
| 967 | end NFClass; | ||
| 968 |