Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 73.4% 243 / 0 / 331
Functions: -% 0 / 1 / 1
Branches: 62.5% 70 / 0 / 112

OMCompiler/Compiler/NFFrontEnd/NFInstNode.mo
Line Branch Exec Source
1 /*
2 * This file is part of OpenModelica.
3 *
4 * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC),
5 * c/o Linköpings universitet, Department of Computer and Information Science,
6 * SE-58183 Linköping, Sweden.
7 *
8 * All rights reserved.
9 *
10 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR
11 * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8.
12 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES
13 * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL
14 * VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
15 *
16 * The OpenModelica software and the OSMC (Open Source Modelica Consortium)
17 * Public License (OSMC-PL) are obtained from OSMC, either from the above
18 * address, from the URLs:
19 * http://www.openmodelica.org or
20 * https://github.com/OpenModelica/ or
21 * http://www.ida.liu.se/projects/OpenModelica,
22 * and in the OpenModelica distribution.
23 *
24 * GNU AGPL version 3 is obtained from:
25 * https://www.gnu.org/licenses/licenses.html#GPL
26 *
27 * This program is distributed WITHOUT ANY WARRANTY; without
28 * even the implied warranty of MERCHANTABILITY or FITNESS
29 * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
30 * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
31 *
32 * See the full OSMC Public License conditions for more details.
33 *
34 */
35
36 encapsulated package NFInstNode
37
38 import BaseModelica;
39 import Binding = NFBinding;
40 import Component = NFComponent;
41 import Class = NFClass;
42 import SCode;
43 import Absyn;
44 import AbsynUtil;
45 import Type = NFType;
46 import NFFunction.Function;
47 import Sections = NFSections;
48 import Pointer;
49 import Mutable;
50 import MutableWeak;
51 import PointerWeak;
52 import Error;
53 import Prefixes = NFPrefixes;
54 import Visibility = NFPrefixes.Visibility;
55 import AccessLevel = NFPrefixes.AccessLevel;
56 import NFModifier.Modifier;
57 import SCodeDump;
58 import DAE;
59 import Expression = NFExpression;
60 import Global;
61
62 protected
63 import List;
64 import ConvertDAE = NFConvertDAE;
65 import Restriction = NFRestriction;
66 import NFClassTree.ClassTree;
67 import SCodeUtil;
68 import IOStream;
69 import Variable = NFVariable;
70 import UnorderedMap;
71
72 public
73 uniontype InstNodeType
74 record NORMAL_CLASS
75 "An element with no specific characteristics."
76 end NORMAL_CLASS;
77
78 record BASE_CLASS
79 "A base class extended by another class."
80 ScopeRef parent "The extending class, weakly; see
81 InstNode.CLASS_NODE.parentScope.";
82 SCode.Element definition "The extends clause definition.";
83 InstNodeType ty "The original node type before the class was extended.";
84 end BASE_CLASS;
85
86 record DERIVED_CLASS
87 "A short class definition."
88 InstNodeType ty "The base node type not considering that it's a derived class.";
89 end DERIVED_CLASS;
90
91 record BUILTIN_CLASS
92 "A builtin element."
93 end BUILTIN_CLASS;
94
95 record TOP_SCOPE
96 "The unnamed class containing all the top-level classes."
97 InstNode annotationScope;
98 UnorderedMap<String, InstNode> generatedInners;
99 MutableWeak.Roots roots "The identity cells of every node under this scope.
100 A node refers to its own scope weakly, and a cref outlives the node value
101 it was made from, so the tree owns the cells rather than the values do.";
102 end TOP_SCOPE;
103
104 record ROOT_CLASS
105 "The root of the instance tree, i.e. the class that the instantiation starts from."
106 ScopeRef parent "The parent of the class, e.g. when instantiating a function
107 in a component where the component is the parent. Weakly:
108 the class tree owns it.";
109 Option<Absyn.Path> context "Used by getModelInstance to add context to instances.";
110 end ROOT_CLASS;
111
112 record NORMAL_COMP
113 end NORMAL_COMP;
114
115 record REDECLARED_COMP
116 ScopeRef parent "The parent of the replaced component, weakly.";
117 end REDECLARED_COMP;
118
119 record REDECLARED_CLASS
120 ScopeRef parent "Weakly: the class tree owns it.";
121 InstNodeType originalType;
122 Option<InstNode> originalNode;
123 Integer confidence "instance level of the redeclare, see Inst.classConfidence";
124 end REDECLARED_CLASS;
125
126 record GENERATED_INNER
127 "A generated inner element due to a missing outer."
128 end GENERATED_INNER;
129
130 record IMPLICIT_SCOPE
131 "An implicit scope that's ignored when e.g. constructing a scope path. Not
132 used by implicit scope nodes since those have no node type (they're
133 implicitly implicit), but by e.g. the annotation scope."
134 end IMPLICIT_SCOPE;
135 end InstNodeType;
136
137 uniontype NodeHandle
138 "A stored reference to a node. `CELL` is the weak edge; `VALUE` is for a node
139 that has no identity cell -- the builtin constants, which are immutable
140 globals and so cannot be on a cycle, and which a constant's serialized form
141 in a .interface.mo can express while a weak reference cannot."
142
143 record CELL
144 MutableWeak<InstNode> cell;
145 end CELL;
146
147 record VALUE
148 InstNode node;
149 end VALUE;
150 end NodeHandle;
151
152 type ScopeRef = InstNode
153 "How a reference to an enclosing scope is stored. The Rust port stores a weak
154 handle instead -- see NFInstNode.rust.mo -- because a scope owns the nodes in
155 it, so a strong reference back would close the cycle. Read one with
156 `fromCell` or `borrow`, make one with `identityCell`.";
157
158 constant ScopeRef NO_SCOPE = InstNode.EMPTY_NODE();
159
160 constant Integer NUMBER_OF_CACHES = 3;
161
162 type PackageCacheState = enumeration(
163 NOT_INITIALIZED,
164 PROCESSING,
165 EXPANDED,
166 PARTIALLY_INSTANTIATED,
167 INSTANTIATED
168 );
169
170 uniontype CachedData
171
172 record NO_CACHE end NO_CACHE;
173
174 record PACKAGE
175 NodeHandle instance "Weakly: this is a cache of the node it hangs off, so
176 the node's own scope owns it.";
177 PackageCacheState state;
178 end PACKAGE;
179
180 record FUNCTION
181 list<Function> funcs;
182 Boolean typed;
183 Boolean specialBuiltin;
184 end FUNCTION;
185
186 record PARTIAL_DAE_TYPE
187 DAE.Type ty;
188 end PARTIAL_DAE_TYPE;
189
190 function empty
191 output array<CachedData> cache = arrayCreate(NUMBER_OF_CACHES, NO_CACHE());
192 end empty;
193
194 function initFunc
195 input array<CachedData> caches;
196 protected
197 CachedData func_cache;
198 algorithm
199 26693 func_cache := getFuncCache(caches);
200 func_cache := match func_cache
201 case NO_CACHE() then FUNCTION({}, false, false);
202 case FUNCTION() then func_cache;
203 end match;
204
205 26693 setFuncCache(caches, func_cache);
206 end initFunc;
207
208 function addFunc
209 input Function fn;
210 input Boolean specialBuiltin;
211 input array<CachedData> caches;
212 protected
213 CachedData func_cache;
214 algorithm
215 27857 func_cache := getFuncCache(caches);
216 func_cache := match func_cache
217
2/2
✓ Branch 0 taken 336 times.
✓ Branch 1 taken 100 times.
772 case NO_CACHE() then FUNCTION({fn}, false, specialBuiltin);
218 // Append to end so the error messages are ordered properly.
219
4/4
✓ Branch 0 taken 27321 times.
✓ Branch 1 taken 100 times.
✓ Branch 2 taken 24261 times.
✓ Branch 3 taken 3060 times.
51682 case FUNCTION() then FUNCTION(listAppend(func_cache.funcs,{fn}), false,
220 func_cache.specialBuiltin or specialBuiltin);
221 else
222 algorithm
223 ✗ Error.terminate(getInstanceName() + ": Invalid cache for function", sourceInfo());
224 ✗ then
225 fail();
226 end match;
227
228 27857 setFuncCache(caches, func_cache);
229 end addFunc;
230
231 function getFuncCache
232 input array<CachedData> in_caches;
233 output CachedData out_cache = arrayGet(in_caches, 1);
234 end getFuncCache;
235
236 function setFuncCache
237 input array<CachedData> in_caches;
238 input CachedData in_cache;
239 algorithm
240 102066 arrayUpdate(in_caches, 1, in_cache);
241 end setFuncCache;
242
243 function getPackageCache
244 input array<CachedData> in_caches;
245 output CachedData out_cache = arrayGet(in_caches, 2);
246 end getPackageCache;
247
248 // The builtin nodes share literal cache arrays that are shorter than
249 // NUMBER_OF_CACHES and must not be written to, hence the length checks.
250 function getTypeCache
251 input array<CachedData> in_caches;
252 output CachedData out_cache = if arrayLength(in_caches) >= 3 then arrayGet(in_caches, 3) else NO_CACHE();
253 end getTypeCache;
254
255 function setTypeCache
256 input array<CachedData> in_caches;
257 input CachedData in_cache;
258 algorithm
259
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6186 times.
6186 if arrayLength(in_caches) >= 3 then
260 6186 arrayUpdate(in_caches, 3, in_cache);
261 end if;
262 end setTypeCache;
263
264 function clearTypeCache
265 input array<CachedData> in_caches;
266 algorithm
267 () := match getTypeCache(in_caches)
268 114 case PARTIAL_DAE_TYPE() algorithm arrayUpdate(in_caches, 3, NO_CACHE()); then ();
269 else ();
270 end match;
271 end clearTypeCache;
272
273 function setPackageCache
274 input array<CachedData> in_caches;
275 input CachedData in_cache;
276 output array<CachedData> out_caches = arrayUpdate(in_caches, 2, in_cache);
277 end setPackageCache;
278
279 function clearPackageCache
280 input array<CachedData> in_caches;
281 output array<CachedData> out_caches = arrayUpdate(in_caches, 2, NO_CACHE());
282 end clearPackageCache;
283 end CachedData;
284
285 uniontype InstNode
286 record CLASS_NODE
287 String name;
288 SCode.Element definition;
289 Visibility visibility;
290 Pointer<Class> cls;
291 array<CachedData> caches;
292 ScopeRef parentScope "The enclosing scope's identity.
293 Weak: a scope owns the nodes in it.";
294 InstNodeType nodeType;
295 end CLASS_NODE;
296
297 record COMPONENT_NODE
298 String name;
299 Option<SCode.Element> definition;
300 Visibility visibility;
301 Pointer<Component> component;
302 ScopeRef parent "The instance that this component is
303 part of; see CLASS_NODE.parentScope.";
304 InstNodeType nodeType;
305 end COMPONENT_NODE;
306
307 record INNER_OUTER_NODE
308 "A node representing an outer element, with a reference to the corresponding inner."
309 InstNode innerNode;
310 InstNode outerNode;
311 end INNER_OUTER_NODE;
312
313 record REF_NODE
314 Integer index;
315 end REF_NODE;
316
317 record NAME_NODE
318 String name;
319 end NAME_NODE;
320
321 record IMPLICIT_SCOPE
322 InstNode parentScope;
323 list<InstNode> locals;
324 end IMPLICIT_SCOPE;
325
326 record ITERATOR_NODE
327 Expression exp;
328 end ITERATOR_NODE;
329
330 record VAR_NODE
331 "This is an extension for better use in the backend. Not used in the Frontend.
332 NOTE: Map and traversal functions are not allowed to follow the variable
333 pointer, it would create cyclic behaviour! Var->cref->pointer->Var"
334 String name;
335 PointerWeak<Variable> varPointer "Weak, which is what stops the
336 `Var -> cref -> pointer -> Var` loop the note above warns about. The
337 backend's `VariablePointers` owns every variable.";
338 end VAR_NODE;
339
340 record EMPTY_NODE end EMPTY_NODE;
341
342 function new
343 input SCode.Element definition;
344 input InstNode parent;
345 output InstNode node;
346 algorithm
347 node := match definition
348 1324 case SCode.CLASS() then newClass(definition, parent);
349 5563 case SCode.COMPONENT() then newComponent(definition, parent);
350 end match;
351 end new;
352
353 function newClass
354 input SCode.Element definition;
355 input InstNode parent;
356 input InstNodeType nodeType = NORMAL_CLASS();
357 output InstNode node;
358 protected
359 String name;
360 SCode.Visibility vis;
361 algorithm
362
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 995601 times.
995601 SCode.CLASS(name = name, prefixes = SCode.PREFIXES(visibility = vis)) := definition;
363 995601 node := CLASS_NODE(name, definition, Prefixes.visibilityFromSCode(vis),
364 Pointer.create(Class.NOT_INSTANTIATED()), CachedData.empty(),
365 identityCell(parent), nodeType);
366 end newClass;
367
368 function newComponent
369 input SCode.Element definition;
370 input InstNode parent = EMPTY_NODE();
371 output InstNode node;
372 protected
373 String name;
374 SCode.Visibility vis;
375 algorithm
376
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 269741 times.
269741 SCode.COMPONENT(name = name, prefixes = SCode.PREFIXES(visibility = vis)) := definition;
377 539482 node := COMPONENT_NODE(name, SOME(definition), Prefixes.visibilityFromSCode(vis),
378 Pointer.create(Component.new(definition)),
379 identityCell(parent), InstNodeType.NORMAL_COMP());
380 end newComponent;
381
382 function newExtends
383 input SCode.Element definition;
384 input InstNode parent;
385 output InstNode node;
386 protected
387 Absyn.Path base_path;
388 String name;
389 SCode.Visibility vis;
390 algorithm
391
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44932 times.
44932 SCode.Element.EXTENDS(baseClassPath = base_path, visibility = vis) := definition;
392 44932 name := AbsynUtil.pathLastIdent(base_path);
393 44932 node := CLASS_NODE(name, definition, Prefixes.visibilityFromSCode(vis),
394 Pointer.create(Class.NOT_INSTANTIATED()), CachedData.empty(),
395 identityCell(parent),
396 InstNodeType.BASE_CLASS(identityCell(parent), definition, nodeType(parent)));
397 end newExtends;
398
399 function newIterator
400 input String name;
401 input Type ty;
402 input SourceInfo info;
403 output InstNode iterator;
404 algorithm
405 6389 iterator := fromComponent(name, Component.newIterator(ty, info), EMPTY_NODE());
406 end newIterator;
407
408 function newUniqueIterator
409 input SourceInfo info = Absyn.dummyInfo;
410 input Type ty = Type.INTEGER();
411 output InstNode iterator;
412 algorithm
413 2451 iterator := newIterator("$i" + String(System.tmpTickIndex(Global.iteratorIndex)), ty, info);
414 end newUniqueIterator;
415
416 function newIndexedIterator
417 input Integer index;
418 input String name = "i";
419 input SourceInfo info = Absyn.dummyInfo;
420 input Type ty = Type.INTEGER();
421 output InstNode iterator;
422 algorithm
423 1770 iterator := newIterator("$" + name + String(index), ty, info);
424 end newIndexedIterator;
425
426 function fromComponent
427 input String name;
428 input Component component;
429 input InstNode parent;
430 output InstNode node;
431 algorithm
432 23710 node := COMPONENT_NODE(name, NONE(), Visibility.PUBLIC, Pointer.create(component),
433 identityCell(parent), InstNodeType.NORMAL_COMP());
434 end fromComponent;
435
436 function isClass
437 input InstNode node;
438 output Boolean isClass;
439 algorithm
440 isClass := match node
441 case CLASS_NODE() then true;
442 ✗ case INNER_OUTER_NODE() then isClass(node.innerNode);
443 else false;
444 end match;
445 end isClass;
446
447 function isBaseClass
448 input InstNode node;
449 output Boolean isBaseClass;
450 algorithm
451 isBaseClass := match node
452 case CLASS_NODE(nodeType = InstNodeType.BASE_CLASS()) then true;
453 else false;
454 end match;
455 end isBaseClass;
456
457 function isUserdefinedClass
458 input InstNode node;
459 output Boolean isUserdefined;
460 protected
461 InstNodeType ty;
462 algorithm
463 isUserdefined := match node
464 case CLASS_NODE(nodeType = ty)
465 then match ty
466 case InstNodeType.NORMAL_CLASS() then true;
467 case InstNodeType.BASE_CLASS() then true;
468 case InstNodeType.DERIVED_CLASS() then true;
469 16 case InstNodeType.REDECLARED_CLASS() then isUserdefinedClass(borrow(ty.parent));
470 else false;
471 end match;
472 else false;
473 end match;
474 end isUserdefinedClass;
475
476 function isDerivedClass
477 input InstNode node;
478 output Boolean isDerived;
479 algorithm
480 isDerived := match node
481 case CLASS_NODE(nodeType = InstNodeType.DERIVED_CLASS()) then true;
482 else false;
483 end match;
484 end isDerivedClass;
485
486 function makeRootClass
487 input output InstNode node;
488 input InstNode parent = EMPTY_NODE();
489 input Option<Absyn.Path> context = NONE();
490 algorithm
491 32663 node := setNodeType(InstNodeType.ROOT_CLASS(scopeRef(parent), context), node);
492 end makeRootClass;
493
494 function isRootClass
495 input InstNode node;
496 output Boolean res;
497 algorithm
498 res := match node
499 case CLASS_NODE(nodeType = InstNodeType.ROOT_CLASS()) then true;
500 else false;
501 end match;
502 end isRootClass;
503
504 function rootClassContext
505 input InstNode node;
506 output Option<Absyn.Path> context;
507 algorithm
508 context := match node
509 case CLASS_NODE(nodeType = InstNodeType.ROOT_CLASS(context = context)) then context;
510 else NONE();
511 end match;
512 end rootClassContext;
513
514 function isFunction
515 input InstNode node;
516 output Boolean isFunc;
517 algorithm
518 isFunc := match node
519 15 case CLASS_NODE() then Class.isFunction(Pointer.access(node.cls));
520 814 case COMPONENT_NODE() then Class.isFunction(getClass(node));
521 else false;
522 end match;
523 end isFunction;
524
525 function isComponent
526 input InstNode node;
527 output Boolean isComponent;
528 algorithm
529 isComponent := match node
530 case COMPONENT_NODE() then true;
531 ✗ case INNER_OUTER_NODE() then isComponent(node.innerNode);
532 else false;
533 end match;
534 end isComponent;
535
536 function isIterator
537 input InstNode node;
538 output Boolean iterator;
539 algorithm
540 iterator := match node
541 1097848 case COMPONENT_NODE() then Component.isIterator(Pointer.access(node.component));
542 else false;
543 end match;
544 end isIterator;
545
546 function isRef
547 input InstNode node;
548 output Boolean isRef;
549 algorithm
550 isRef := match node
551 case REF_NODE() then true;
552 else false;
553 end match;
554 end isRef;
555
556 function isVar
557 "True for a backend VAR_NODE, which names a variable by pointer."
558 input InstNode node;
559 output Boolean isVar;
560 algorithm
561 isVar := match node
562 case VAR_NODE() then true;
563 else false;
564 end match;
565 end isVar;
566
567 function varPointer
568 input InstNode node;
569 output PointerWeak<Variable> varPointer;
570 algorithm
571
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 182583 times.
182583 VAR_NODE(varPointer = varPointer) := node;
572 end varPointer;
573
574 function isEmpty
575 input InstNode node;
576 output Boolean isEmpty;
577 algorithm
578 isEmpty := match node
579 case EMPTY_NODE() then true;
580 else false;
581 end match;
582 end isEmpty;
583
584 function isImplicit
585 input InstNode node;
586 output Boolean isImplicit;
587 algorithm
588 isImplicit := match node
589 case IMPLICIT_SCOPE() then true;
590 else false;
591 end match;
592 end isImplicit;
593
594 function isName
595 input InstNode node;
596 output Boolean isName;
597 algorithm
598 isName := match node
599 case NAME_NODE() then true;
600 else false;
601 end match;
602 end isName;
603
604 function isConnector
605 input InstNode node;
606 output Boolean isConnector;
607 algorithm
608 isConnector := match node
609 217723 case COMPONENT_NODE() then Component.isConnector(component(node));
610 case NAME_NODE() then true;
611 else false;
612 end match;
613 end isConnector;
614
615 function isExpandableConnector
616 input InstNode node;
617 output Boolean isConnector;
618 algorithm
619 isConnector := match node
620 ✗ case COMPONENT_NODE() then Component.isExpandableConnector(component(node));
621 else false;
622 end match;
623 end isExpandableConnector;
624
625 function hasParentExpandableConnector
626 "@author: adrpo
627 returns true if itself or any of the parents are expandable connectors"
628 input InstNode node;
629 output Boolean b = isExpandableConnector(node);
630 protected
631 InstNode p;
632 algorithm
633 p := node;
634 ✗ while not isEmpty(p) loop
635 ✗ p := parent(p);
636 ✗ b := boolOr(b, isExpandableConnector(p));
637 if b then
638 break;
639 end if;
640 end while;
641 end hasParentExpandableConnector;
642
643 function isOperator
644 input InstNode node;
645 output Boolean op;
646 algorithm
647 op := match node
648 ✗ case CLASS_NODE() then SCodeUtil.isOperator(node.definition);
649 ✗ case INNER_OUTER_NODE() then isOperator(node.innerNode);
650 else false;
651 end match;
652 end isOperator;
653
654 function name
655 input InstNode node;
656 output String name;
657 algorithm
658 name := match node
659 4698902 case CLASS_NODE() then node.name;
660 21536652 case COMPONENT_NODE() then node.name;
661 11 case INNER_OUTER_NODE() then name(node.innerNode);
662 5535376 case VAR_NODE() then node.name;
663 // For bug catching, these names should never be used.
664 ✗ case REF_NODE() then "$REF[" + String(node.index) + "]";
665 1837 case NAME_NODE() then node.name;
666 case IMPLICIT_SCOPE() then "$IMPLICIT";
667 ✗ case ITERATOR_NODE() then "$ITERATOR(" + Expression.toString(node.exp) + ")";
668 case EMPTY_NODE() then "$EMPTY";
669 end match;
670 end name;
671
672 function isNamed
673 input InstNode node;
674 input String name;
675 output Boolean res;
676 algorithm
677 res := match node
678
3/4
✓ Branch 0 taken 690 times.
✓ Branch 1 taken 51932 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 690 times.
52622 case CLASS_NODE() then node.name == name;
679
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 case COMPONENT_NODE() then node.name == name;
680 ✗ case INNER_OUTER_NODE() then isNamed(node.innerNode, name);
681 ✗ case VAR_NODE() then node.name == name;
682 ✗ case NAME_NODE() then node.name == name;
683 else false;
684 end match;
685 end isNamed;
686
687 function className
688 input InstNode node;
689 output String name;
690 algorithm
691
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 191307 times.
191307 CLASS_NODE(name = name) := node;
692 end className;
693
694 function scopeName
695 "Returns the name of a scope, which in the case of a component is the name
696 of the component's type, and for a class simply the name of the class."
697 input InstNode node;
698 output String outName = name(classScope(explicitScope(node)));
699 end scopeName;
700
701 function typeName
702 "Returns the type of node the given node is as a string."
703 input InstNode node;
704 output String name;
705 algorithm
706 name := match node
707 case CLASS_NODE() then "class";
708 case COMPONENT_NODE() then "component";
709 ✗ case INNER_OUTER_NODE() then typeName(node.innerNode);
710 case REF_NODE() then "ref node";
711 case NAME_NODE() then "name node";
712 case IMPLICIT_SCOPE() then "implicit scope";
713 case EMPTY_NODE() then "empty node";
714 case VAR_NODE() then "var node";
715 end match;
716 end typeName;
717
718 function rename
719 "Renaming makes a copy, so the copy gets an identity of its own: any handle
720 already naming the old node keeps pointing at the old cell, which still
721 holds the old name. Doing it here rather than at each call site is what
722 lets `NodeHandle.CELL` cache the name -- a rename can no longer be seen
723 through a handle that was made before it."
724 input String name;
725 input output InstNode node;
726 algorithm
727 6618 node := reidentify(node);
728
729 () := match node
730 case CLASS_NODE()
731 algorithm
732 24 node.name := name;
733 then
734 ();
735
736 case COMPONENT_NODE()
737 algorithm
738 6545 node.name := name;
739 then
740 ();
741
742 case NAME_NODE()
743 algorithm
744 ✗ node.name := name;
745 then
746 ();
747
748 case VAR_NODE()
749 algorithm
750 49 node.name := name;
751 then
752 ();
753 end match;
754 end rename;
755
756 function reidentify
757 "A fresh identity, for a node that is a copy of another rather than an
758 update of it. Nothing to do here; see NFInstNode.rust.mo."
759 input output InstNode node;
760 end reidentify;
761
762 function identityCell
763 "The scope reference a child stores to name this node as its parent. The
764 Rust port has to publish the node into its cell here; see
765 NFInstNode.rust.mo."
766 input InstNode node;
767 output ScopeRef identity = node;
768 end identityCell;
769
770 function scopeRef
771 "As `identityCell`, for a reference to a scope that is not this node's
772 parent: it must not replace the snapshot the node's children read. The
773 node itself here; see NFInstNode.rust.mo."
774 input InstNode node;
775 output ScopeRef scope = node;
776 end scopeRef;
777
778 function handle
779 "A weak handle for an edge that is not a parent edge. The node itself here;
780 see NFInstNode.rust.mo."
781 input InstNode node;
782 output NodeHandle hnd = NodeHandle.VALUE(node);
783 end handle;
784
785 function republish
786 "As `handle`, where the edge is an update of the same node rather than a
787 different one. Identical here; the Rust port has to replace the published
788 snapshot."
789 input InstNode node;
790 output NodeHandle hnd = handle(node);
791 end republish;
792
793 function handleName
794 "The name of the node a handle refers to. Resolving the node is the whole
795 cost of a weak edge, and `ComponentRef.isEqual`/`hashContinue` want only
796 the name, so the Rust port caches it in the handle -- see
797 NFInstNode.rust.mo."
798 input NodeHandle hnd;
799 output String name = InstNode.name(fromHandle(hnd));
800 end handleName;
801
802 function fromHandle
803 input NodeHandle hnd;
804 output InstNode node;
805 algorithm
806 node := match hnd
807 ✗ case NodeHandle.CELL() then MutableWeak.value(hnd.cell);
808 2863840 case NodeHandle.VALUE() then hnd.node;
809 end match;
810 end fromHandle;
811
812 function borrow
813 "The node a scope reference names, without taking ownership of it."
814 input ScopeRef cell;
815 output InstNode node = cell;
816 end borrow;
817
818 function fromCell
819 "The node a scope reference names. In the Rust port the scope may be gone,
820 and this owns what it hands back; see NFInstNode.rust.mo."
821 input ScopeRef cell;
822 output InstNode node = cell;
823 end fromCell;
824
825 function parent
826 input InstNode node;
827 output InstNode parent;
828 algorithm
829 parent := match node
830 2119542 case CLASS_NODE() then fromCell(node.parentScope);
831 3459877 case COMPONENT_NODE() then fromCell(node.parent);
832 1917 case IMPLICIT_SCOPE() then node.parentScope;
833 else EMPTY_NODE();
834 end match;
835 end parent;
836
837 function borrowParent
838 "As `parent`, without taking ownership of the parent."
839 input InstNode node;
840 output InstNode parent;
841 algorithm
842 parent := match node
843 3280075 case CLASS_NODE() then borrow(node.parentScope);
844 12701 case COMPONENT_NODE() then borrow(node.parent);
845 ✗ case IMPLICIT_SCOPE() then node.parentScope;
846 else EMPTY_NODE();
847 end match;
848 end borrowParent;
849
850 function explicitParent
851 input InstNode node;
852 output InstNode parentNode = explicitScope(parent(node));
853 end explicitParent;
854
855 function classParent
856 input InstNode node;
857 output InstNode parent;
858 protected
859 ScopeRef p;
860 algorithm
861
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 191537 times.
191537 CLASS_NODE(parentScope = p) := node;
862 191537 parent := fromCell(p);
863 end classParent;
864
865 function instanceParent
866 "Returns the parent of the node in the instance tree."
867 input InstNode node;
868 output InstNode parent;
869 protected
870 ScopeRef rdcl_scope;
871 algorithm
872 parent := match node
873 302838 case CLASS_NODE() then getDerivedNode(parent(getDerivedNode(node)));
874 case COMPONENT_NODE(nodeType = InstNodeType.REDECLARED_COMP(parent = rdcl_scope))
875 517 then getDerivedNode(fromCell(rdcl_scope));
876 193026 case COMPONENT_NODE() then getDerivedNode(parent(getDerivedNode(node)));
877 ✗ case IMPLICIT_SCOPE() then getDerivedNode(parent(getDerivedNode(node)));
878 else EMPTY_NODE();
879 end match;
880 end instanceParent;
881
882 function borrowInstanceParent
883 "As `instanceParent`, without taking ownership of a component's parent:
884 for walking up past scopes that are not kept."
885 input InstNode node;
886 output InstNode parent;
887 protected
888 ScopeRef rdcl_scope;
889 algorithm
890 parent := match node
891 case COMPONENT_NODE(nodeType = InstNodeType.REDECLARED_COMP(parent = rdcl_scope))
892 4162 then getDerivedNode(borrow(rdcl_scope));
893 1523888 case COMPONENT_NODE() then getDerivedNode(borrow(node.parent));
894 ✗ else instanceParent(node);
895 end match;
896 end borrowInstanceParent;
897
898 function rootParent
899 input InstNode node;
900 output InstNode parent;
901 algorithm
902 parent := match node
903 693489 case CLASS_NODE() then rootTypeParent(node.nodeType, node);
904 ✗ else parent(node);
905 end match;
906 end rootParent;
907
908 function rootTypeParent
909 input InstNodeType nodeType;
910 input InstNode node;
911 output InstNode parent;
912 algorithm
913 parent := match nodeType
914 598 case InstNodeType.ROOT_CLASS() guard not isEmpty(borrow(nodeType.parent)) then borrow(nodeType.parent);
915 693489 case InstNodeType.DERIVED_CLASS() then rootTypeParent(nodeType.ty, node);
916 692891 else parent(node);
917 end match;
918 end rootTypeParent;
919
920 function parentScope
921 "Returns the parent scope of a node. In the case of a class this is simply
922 the enclosing class. In the case of a component it is the enclosing class of
923 the component's type."
924 input InstNode node;
925 input Boolean ignoreRedeclare = false;
926 output InstNode scope;
927 protected
928 InstNode orig_node;
929 ScopeRef rdcl_scope;
930 algorithm
931 scope := match node
932 case CLASS_NODE(nodeType = InstNodeType.DERIVED_CLASS())
933 algorithm
934 1413 scope := Class.lastBaseClass(node);
935
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1413 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1413 times.
1413 then
936 if isBuiltin(scope) then
937 // Builtin types like Real do not have a parent set, go to the top scope instead.
938 topScope(fromCell(node.parentScope))
939 elseif referenceEq(node, scope) then
940 // lastBaseClass above might return the same node if the class has
941 // been flattened, go directly to the parent to avoid an infinite loop.
942 fromCell(node.parentScope)
943 else
944 parentScope(scope);
945
946 case CLASS_NODE(nodeType = InstNodeType.REDECLARED_CLASS(originalNode = SOME(orig_node)))
947 guard ignoreRedeclare
948 ✗ then parentScope(orig_node);
949
950 case CLASS_NODE(nodeType = InstNodeType.REDECLARED_CLASS(parent = rdcl_scope))
951 guard ignoreRedeclare
952 ✗ then fromCell(rdcl_scope);
953
954 2778021 case CLASS_NODE() then fromCell(node.parentScope);
955 457656 case COMPONENT_NODE() then parentScope(Component.classInstance(Pointer.access(node.component)));
956 56428 case IMPLICIT_SCOPE() then node.parentScope;
957 end match;
958 end parentScope;
959
960 function enclosingScopePath
961 "Returns the enclosing scopes of a node as a path."
962 input InstNode node;
963 input Boolean ignoreRedeclare = false;
964 input Boolean ignoreBaseClass = false;
965 output Absyn.Path path;
966 algorithm
967
4/4
✓ Branch 1 taken 329 times.
✓ Branch 2 taken 167 times.
✓ Branch 3 taken 329 times.
✓ Branch 4 taken 167 times.
496 path := AbsynUtil.stringListPath(
968 list(InstNode.name(n) for n in enclosingScopeList(node, ignoreRedeclare, ignoreBaseClass)));
969 end enclosingScopePath;
970
971 function enclosingScopeList
972 "Returns the enclosing scopes of a node as a list of nodes."
973 input InstNode node;
974 input Boolean ignoreRedeclare = false;
975 input Boolean ignoreBaseClass = false;
976 output list<InstNode> res = {};
977 protected
978 InstNode scope = node;
979 algorithm
980
2/2
✓ Branch 1 taken 329 times.
✓ Branch 2 taken 165 times.
494 while not isTopScope(scope) loop
981 res := scope :: res;
982 329 scope := enclosingScope(scope, ignoreRedeclare, ignoreBaseClass);
983
984
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 327 times.
329 if isEmpty(scope) then
985 break;
986 end if;
987
988 327 scope := classScope(scope);
989 end while;
990 end enclosingScopeList;
991
992 function enclosingScope
993 input InstNode node;
994 input Boolean ignoreRedeclare = false;
995 input Boolean ignoreBaseClass = false;
996 output InstNode scope;
997 protected
998 InstNode orig_node;
999 ScopeRef rdcl_scope;
1000 algorithm
1001 scope := match node
1002 case CLASS_NODE(nodeType = InstNodeType.REDECLARED_CLASS(originalNode = SOME(orig_node)))
1003 guard ignoreRedeclare
1004 1 then enclosingScope(orig_node, ignoreRedeclare, ignoreBaseClass);
1005
1006 case CLASS_NODE(nodeType = InstNodeType.REDECLARED_CLASS(parent = rdcl_scope))
1007 guard ignoreRedeclare
1008 ✗ then fromCell(rdcl_scope);
1009
1010
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 329 times.
329 case CLASS_NODE() then if ignoreBaseClass then getDerivedNode(fromCell(node.parentScope)) else fromCell(node.parentScope);
1011 ✗ case COMPONENT_NODE() then enclosingScope(classScope(node), ignoreRedeclare, ignoreBaseClass);
1012 ✗ case IMPLICIT_SCOPE() then node.parentScope;
1013 end match;
1014 end enclosingScope;
1015
1016 function classScope
1017 input InstNode node;
1018 output InstNode scope;
1019 algorithm
1020 scope := match node
1021 case COMPONENT_NODE()
1022 764011 then Component.classInstance(Pointer.access(node.component));
1023 else node;
1024 end match;
1025 end classScope;
1026
1027 function libraryScope
1028 "Returns the top-level class the given node belongs to."
1029 input InstNode node;
1030 output InstNode lib;
1031 algorithm
1032 lib := match node
1033 case CLASS_NODE() guard isTopScope(fromCell(node.parentScope)) then node;
1034 828 else libraryScope(parentScope(node));
1035 end match;
1036 end libraryScope;
1037
1038 function topScope
1039 input InstNode node;
1040 output InstNode topScope;
1041 algorithm
1042 topScope := match node
1043 case CLASS_NODE(nodeType = InstNodeType.TOP_SCOPE()) then node;
1044
1045 // Walking past the top means a parent cell no longer holds its node.
1046 // Without this the tail call is a loop and the compiler simply hangs.
1047 case EMPTY_NODE()
1048 algorithm
1049 ✗ Error.addInternalError(getInstanceName() +
1050 " walked past the top scope: a parent cell lost its node", sourceInfo());
1051 ✗ then fail();
1052
1053 191689 else topScope(parent(node));
1054 end match;
1055 end topScope;
1056
1057 function annotationScope
1058 input InstNode node;
1059 output InstNode annScope;
1060 algorithm
1061 annScope := match node
1062 case CLASS_NODE(nodeType = InstNodeType.TOP_SCOPE(annotationScope = annScope)) then annScope;
1063 6915 else annotationScope(parentScope(node));
1064 end match;
1065 end annotationScope;
1066
1067 function isTopScope
1068 input InstNode node;
1069 output Boolean res;
1070 algorithm
1071 res := match node
1072 case CLASS_NODE(nodeType = InstNodeType.TOP_SCOPE()) then true;
1073 else false;
1074 end match;
1075 end isTopScope;
1076
1077 function topComponent
1078 input InstNode node;
1079 output InstNode topComponent;
1080 algorithm
1081 topComponent := match node
1082 case COMPONENT_NODE() guard isEmpty(fromCell(node.parent)) then node;
1083 ✗ case COMPONENT_NODE() then topComponent(fromCell(node.parent));
1084 end match;
1085 end topComponent;
1086
1087 function setParent
1088 input InstNode parent;
1089 input output InstNode node;
1090 algorithm
1091 () := match node
1092 case CLASS_NODE()
1093 algorithm
1094 520342 node.parentScope := identityCell(parent);
1095 then
1096 ();
1097
1098 case COMPONENT_NODE()
1099 algorithm
1100 60 node.parent := identityCell(parent);
1101 then
1102 ();
1103
1104 case IMPLICIT_SCOPE()
1105 algorithm
1106 ✗ node.parentScope := parent;
1107 then
1108 ();
1109 end match;
1110 end setParent;
1111
1112 function setOrphanParent
1113 "Sets the parent of a node if the node lacks a parent, otherwise does nothing."
1114 input InstNode parent;
1115 input output InstNode node;
1116 algorithm
1117 () := match node
1118 case CLASS_NODE() guard isEmpty(fromCell(node.parentScope))
1119 algorithm
1120 ✗ node.parentScope := identityCell(parent);
1121 then
1122 ();
1123
1124 case COMPONENT_NODE() guard isEmpty(fromCell(node.parent))
1125 algorithm
1126 ✗ node.parent := identityCell(parent);
1127 then
1128 ();
1129
1130 else ();
1131 end match;
1132 end setOrphanParent;
1133
1134 function getClass
1135 input InstNode node;
1136 output Class cls;
1137 algorithm
1138 cls := match node
1139 29200040 case CLASS_NODE() then Pointer.access(node.cls);
1140 case COMPONENT_NODE()
1141 1959412 then getClass(Component.classInstance(Pointer.access(node.component)));
1142 end match;
1143 end getClass;
1144
1145 function getDerivedClass
1146 input InstNode node;
1147 output Class cls;
1148 algorithm
1149 cls := match node
1150 ✗ case CLASS_NODE() then getClass(getDerivedNode(node));
1151 case COMPONENT_NODE()
1152 ✗ then getClass(getDerivedNode(Component.classInstance(Pointer.access(node.component))));
1153 end match;
1154 end getDerivedClass;
1155
1156 function getDerivedNode
1157 input InstNode node;
1158 input Boolean recursive = true;
1159 output InstNode derived;
1160 algorithm
1161 derived := match node
1162 1924567 case CLASS_NODE() then getDerivedNode2(node, node.nodeType, recursive);
1163 else node;
1164 end match;
1165 end getDerivedNode;
1166
1167 function getDerivedNode2
1168 input InstNode node;
1169 input InstNodeType ty;
1170 input Boolean recursive;
1171 output InstNode derived;
1172 algorithm
1173 derived := match ty
1174 case InstNodeType.BASE_CLASS()
1175
2/2
✓ Branch 0 taken 787144 times.
✓ Branch 1 taken 515 times.
787659 then if recursive then getDerivedNode(fromCell(ty.parent)) else fromCell(ty.parent);
1176 236 case InstNodeType.DERIVED_CLASS() then getDerivedNode2(node, ty.ty, recursive);
1177 else node;
1178 end match;
1179 end getDerivedNode2;
1180
1181 function updateClass
1182 input Class cls;
1183 input output InstNode node;
1184 algorithm
1185 node := match node
1186 case CLASS_NODE()
1187 algorithm
1188 6211899 Pointer.update(node.cls, cls);
1189 6211899 CachedData.clearTypeCache(node.caches);
1190 then
1191 node;
1192 end match;
1193 end updateClass;
1194
1195 function component
1196 input InstNode node;
1197 output Component component;
1198 algorithm
1199 component := match node
1200 54851233 case COMPONENT_NODE() then Pointer.access(node.component);
1201 case VAR_NODE() then Component.WILD();
1202 case NAME_NODE() then Component.WILD();
1203 end match;
1204 end component;
1205
1206 function updateComponent
1207 input Component component;
1208 input output InstNode node;
1209 algorithm
1210 node := match node
1211 case COMPONENT_NODE()
1212 algorithm
1213 5955434 Pointer.update(node.component, component);
1214 then
1215 node;
1216 end match;
1217 end updateComponent;
1218
1219 function replaceComponent
1220 input Component component;
1221 input output InstNode node;
1222 algorithm
1223 () := match node
1224 case COMPONENT_NODE()
1225 algorithm
1226 342 node.component := Pointer.create(component);
1227 then
1228 ();
1229 end match;
1230 end replaceComponent;
1231
1232 function replaceClass
1233 input Class cls;
1234 input output InstNode node;
1235 algorithm
1236 () := match node
1237 case CLASS_NODE()
1238 algorithm
1239 2783803 node.cls := Pointer.create(cls);
1240 then
1241 ();
1242 end match;
1243 end replaceClass;
1244
1245 function nodeType
1246 input InstNode node;
1247 output InstNodeType nodeType;
1248 algorithm
1249 nodeType := match node
1250 4215108 case CLASS_NODE() then node.nodeType;
1251 2573767 case COMPONENT_NODE() then node.nodeType;
1252 end match;
1253 end nodeType;
1254
1255 function derivedNodeType
1256 input InstNode node;
1257 output InstNodeType ty;
1258 algorithm
1259 ty := match node
1260 case CLASS_NODE(nodeType = InstNodeType.DERIVED_CLASS(ty = ty)) then ty;
1261 2076548 else nodeType(node);
1262 end match;
1263 end derivedNodeType;
1264
1265 function setNodeType
1266 input InstNodeType nodeType;
1267 input output InstNode node;
1268 algorithm
1269 () := match node
1270 case CLASS_NODE()
1271 algorithm
1272 2383589 node.nodeType := nodeType;
1273 2383589 CachedData.clearTypeCache(node.caches);
1274 then
1275 ();
1276
1277 case COMPONENT_NODE()
1278 algorithm
1279 5578 node.nodeType := nodeType;
1280 then
1281 ();
1282
1283 else ();
1284 end match;
1285 end setNodeType;
1286
1287 function definition
1288 input InstNode node;
1289 output SCode.Element definition;
1290 algorithm
1291 definition := match node
1292 7693635 case CLASS_NODE() then node.definition;
1293 case COMPONENT_NODE(definition = SOME(definition)) then definition;
1294 else algorithm
1295 1096 Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for non class/component node: " + toString(node)});
1296 484 then fail();
1297 end match;
1298 end definition;
1299
1300 function classDefinition
1301 input InstNode node;
1302 output SCode.Element definition;
1303 algorithm
1304 definition := match node
1305 23761 case CLASS_NODE() then node.definition;
1306 ✗ case COMPONENT_NODE() then classDefinition(Component.classInstance(Pointer.access(node.component)));
1307 else algorithm
1308 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for non class/component node: " + toString(node)});
1309 ✗ then fail();
1310 end match;
1311 end classDefinition;
1312
1313 function extendsDefinition
1314 input InstNode node;
1315 output Option<SCode.Element> definition;
1316 protected
1317 InstNodeType ty;
1318 algorithm
1319 2076549 ty := derivedNodeType(node);
1320
1321 definition := match ty
1322 284156 case InstNodeType.BASE_CLASS() then SOME(ty.definition);
1323 else NONE();
1324 end match;
1325 end extendsDefinition;
1326
1327 function setDefinition
1328 input SCode.Element definition;
1329 input output InstNode node;
1330 algorithm
1331 () := match node
1332 case CLASS_NODE()
1333 algorithm
1334 28 node.definition := definition;
1335 then
1336 ();
1337
1338 case COMPONENT_NODE()
1339 algorithm
1340 17 node.definition := SOME(definition);
1341 then
1342 ();
1343
1344 end match;
1345 end setDefinition;
1346
1347 function setComponentDirection
1348 "creates new component!"
1349 input Prefixes.Direction direction;
1350 input output InstNode node;
1351 algorithm
1352 node := match node
1353 case COMPONENT_NODE() algorithm
1354 32 node.component := Pointer.create(Component.setDirection(direction, Pointer.access(node.component)));
1355 then node;
1356
1357 else algorithm
1358 ✗ Error.addMessage(Error.INTERNAL_ERROR,{getInstanceName() + " failed for non component node: " + toString(node)});
1359 ✗ then fail();
1360 end match;
1361 end setComponentDirection;
1362
1363 function info
1364 input InstNode node;
1365 output SourceInfo info;
1366 algorithm
1367 info := matchcontinue node
1368 local
1369 InstNodeType ty;
1370 case CLASS_NODE(nodeType = ty as InstNodeType.BASE_CLASS())
1371 5271 then SCodeUtil.elementInfo(ty.definition);
1372 1037325 case CLASS_NODE() then SCodeUtil.elementInfo(node.definition);
1373 646379 case COMPONENT_NODE() then Component.info(Pointer.access(node.component));
1374 1 case COMPONENT_NODE() then info(fromCell(node.parent));
1375 else Absyn.dummyInfo;
1376 end matchcontinue;
1377 end info;
1378
1379 function getType
1380 input InstNode node;
1381 output Type ty;
1382 protected
1383 Variable var;
1384 algorithm
1385 ty := match node
1386 1219398 case CLASS_NODE() then Class.getType(Pointer.access(node.cls), node);
1387 1973847 case COMPONENT_NODE() then Component.getType(Pointer.access(node.component));
1388 case VAR_NODE() algorithm
1389 488 var := Pointer.access(PointerWeak.upgrade(node.varPointer));
1390 488 then var.ty;
1391 case NAME_NODE() then Type.UNKNOWN();
1392 end match;
1393 end getType;
1394
1395 function classApply<ArgT>
1396 input output InstNode node;
1397 input FuncType func;
1398 input ArgT arg;
1399
1400 partial function FuncType
1401 input ArgT arg;
1402 input output Class cls;
1403 end FuncType;
1404 algorithm
1405 () := match node
1406 case CLASS_NODE()
1407 algorithm
1408
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2791 times.
2791 Pointer.update(node.cls, func(arg, Pointer.access(node.cls)));
1409 then
1410 ();
1411 end match;
1412 end classApply;
1413
1414 function componentApply<ArgT>
1415 input output InstNode node;
1416 input FuncType func;
1417 input ArgT arg;
1418
1419 partial function FuncType
1420 input ArgT arg;
1421 input output Component node;
1422 end FuncType;
1423 algorithm
1424 () := match node
1425 case COMPONENT_NODE()
1426 algorithm
1427
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4578520 times.
4578520 Pointer.update(node.component, func(arg, Pointer.access(node.component)));
1428 then
1429 ();
1430 end match;
1431 end componentApply;
1432
1433 function scopeList
1434 "The instances enclosing a node, outermost first. They are borrowed: see
1435 `borrow`."
1436 input InstNode node;
1437 input Boolean includeRoot = false "Whether to include the root class name or not.";
1438 input list<InstNode> accumScopes = {};
1439 output list<InstNode> scopes;
1440 algorithm
1441 scopes := match node
1442 local
1443 InstNode parent;
1444 ScopeRef rdcl_scope;
1445
1446 2040033 case CLASS_NODE() then scopeListClass(node, node.nodeType, includeRoot, accumScopes);
1447 case COMPONENT_NODE() guard isEmpty(borrow(node.parent)) then accumScopes;
1448 case COMPONENT_NODE(nodeType = InstNodeType.REDECLARED_COMP(parent = rdcl_scope))
1449 3426 then scopeList(borrow(rdcl_scope), includeRoot, node :: accumScopes);
1450 677163 case COMPONENT_NODE() then scopeList(borrow(node.parent), includeRoot, node :: accumScopes);
1451 ✗ case IMPLICIT_SCOPE() then scopeList(node.parentScope, includeRoot, accumScopes);
1452 else accumScopes;
1453 end match;
1454 end scopeList;
1455
1456 function scopeListClass
1457 input InstNode clsNode;
1458 input InstNodeType ty;
1459 input Boolean includeRoot;
1460 input list<InstNode> accumScopes = {};
1461 output list<InstNode> scopes;
1462 algorithm
1463 scopes := match ty
1464 case InstNodeType.NORMAL_CLASS()
1465 468128 then scopeList(borrowParent(clsNode), includeRoot, clsNode :: accumScopes);
1466 case InstNodeType.BASE_CLASS()
1467 322850 then scopeList(borrow(ty.parent), includeRoot, accumScopes);
1468 case InstNodeType.DERIVED_CLASS()
1469 4750 then scopeListClass(clsNode, ty.ty, includeRoot, accumScopes);
1470 case InstNodeType.BUILTIN_CLASS()
1471 then clsNode :: accumScopes;
1472 case InstNodeType.TOP_SCOPE()
1473 then accumScopes;
1474 case InstNodeType.ROOT_CLASS()
1475
2/2
✓ Branch 0 taken 4697 times.
✓ Branch 1 taken 1033810 times.
1043204 then if includeRoot then
1476 scopeList(borrowParent(clsNode), includeRoot, clsNode :: accumScopes)
1477 else
1478 accumScopes;
1479 case InstNodeType.REDECLARED_CLASS()
1480 596 then scopeList(borrow(ty.parent), includeRoot, getDerivedNode(clsNode) :: accumScopes);
1481 case InstNodeType.IMPLICIT_SCOPE()
1482 136 then scopeList(borrowParent(clsNode), includeRoot, accumScopes);
1483 else
1484 algorithm
1485 ✗ Error.terminate(getInstanceName() + " got unknown node type", sourceInfo());
1486 ✗ then
1487 fail();
1488 end match;
1489 end scopeListClass;
1490
1491 function getAnnotation
1492 input String name;
1493 input InstNode node;
1494 output SCode.Mod mod;
1495 output InstNode scope = node;
1496 protected
1497 Option<SCode.Annotation> ann;
1498 algorithm
1499
2/2
✓ Branch 1 taken 1533318 times.
✓ Branch 2 taken 384091 times.
1917409 while InstNode.isComponent(scope) loop
1500 1533318 ann := SCodeUtil.commentAnnotation(Component.comment(InstNode.component(scope)));
1501
1502
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1533318 times.
✓ Branch 2 taken 738871 times.
✓ Branch 3 taken 794447 times.
1533318 if isSome(ann) then
1503 738871 mod := SCodeUtil.lookupAnnotation(Util.getOption(ann), name);
1504
1505
2/2
✓ Branch 1 taken 5268 times.
✓ Branch 2 taken 733603 times.
738871 if not SCodeUtil.isEmptyMod(mod) then
1506 5268 scope := instanceParent(scope);
1507 5268 return;
1508 end if;
1509 end if;
1510
1511 1528050 scope := borrowInstanceParent(scope);
1512 end while;
1513
1514 mod := SCode.Mod.NOMOD();
1515 end getAnnotation;
1516
1517 type ScopeType = enumeration(
1518 RELATIVE "Stops at a root class and doesn't include the root",
1519 INCLUDING_ROOT "Stops at a root class and includes the root",
1520 FULL "Stops at the top scope"
1521 );
1522
1523 function rootPath
1524 input InstNode node;
1525 input Boolean ignoreBaseClass = false "Ignore that a class is a base class if true.";
1526 output Absyn.Path path = scopePath(node, ScopeType.INCLUDING_ROOT, ignoreBaseClass);
1527 end rootPath;
1528
1529 function fullPath
1530 input InstNode node;
1531 input Boolean ignoreBaseClass = false "Ignore that a class is a base class if true.";
1532 output Absyn.Path path = scopePath(node, ScopeType.FULL, ignoreBaseClass);
1533 end fullPath;
1534
1535 function scopePath
1536 input InstNode node;
1537 input ScopeType scopeType = ScopeType.RELATIVE;
1538 input Boolean ignoreBaseClass = false "Ignore that a class is a base class if true.";
1539 output Absyn.Path path;
1540 algorithm
1541 path := match node
1542 local
1543 InstNodeType it;
1544
1545 case CLASS_NODE(nodeType = it)
1546 then
1547 match it
1548 case InstNodeType.BASE_CLASS() guard not ignoreBaseClass
1549 4767 then scopePath(fromCell(it.parent), scopeType);
1550 55148 else scopePath2(fromCell(node.parentScope), scopeType, Absyn.IDENT(node.name));
1551 end match;
1552
1553 32 case COMPONENT_NODE() then scopePath2(fromCell(node.parent), scopeType, Absyn.IDENT(node.name));
1554 ✗ case IMPLICIT_SCOPE() then scopePath(node.parentScope, scopeType);
1555
1556 // For debugging.
1557 ✗ else Absyn.IDENT(name(node));
1558 end match;
1559 end scopePath;
1560
1561 function scopePath2
1562 input InstNode node;
1563 input ScopeType scopeType;
1564 input Absyn.Path accumPath;
1565 output Absyn.Path path;
1566 algorithm
1567 path := match node
1568 259325 case CLASS_NODE() then scopePathClass(node, node.nodeType, scopeType, accumPath);
1569 14032 case COMPONENT_NODE() then scopePath2(fromCell(node.parent), scopeType, Absyn.QUALIFIED(node.name, accumPath));
1570 else accumPath;
1571 end match;
1572 end scopePath2;
1573
1574 function scopePathClass
1575 input InstNode node;
1576 input InstNodeType ty;
1577 input ScopeType scopeType;
1578 input Absyn.Path accumPath;
1579 output Absyn.Path path;
1580 algorithm
1581 path := match ty
1582 case InstNodeType.NORMAL_CLASS()
1583 186139 then scopePath2(classParent(node), scopeType, Absyn.QUALIFIED(className(node), accumPath));
1584 case InstNodeType.BASE_CLASS()
1585 12574 then scopePath2(fromCell(ty.parent), scopeType, accumPath);
1586 case InstNodeType.DERIVED_CLASS()
1587 ✗ then scopePathClass(node, ty.ty, scopeType, accumPath);
1588 case InstNodeType.BUILTIN_CLASS()
1589 ✗ then Absyn.QUALIFIED(className(node), accumPath);
1590 case InstNodeType.TOP_SCOPE()
1591 then accumPath;
1592 case InstNodeType.ROOT_CLASS()
1593
4/4
✓ Branch 0 taken 5126 times.
✓ Branch 1 taken 1395 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 1393 times.
6521 then if scopeType == ScopeType.FULL then
1594 scopePath2(classParent(node), scopeType, Absyn.QUALIFIED(className(node), accumPath))
1595 elseif scopeType == ScopeType.INCLUDING_ROOT then
1596 Absyn.QUALIFIED(className(node), accumPath)
1597 else
1598 accumPath;
1599 case InstNodeType.REDECLARED_CLASS()
1600 40 then scopePath2(fromCell(ty.parent), scopeType, Absyn.QUALIFIED(className(node), accumPath));
1601 case InstNodeType.IMPLICIT_SCOPE()
1602 272 then scopePath2(classParent(node), scopeType, accumPath);
1603 else
1604 algorithm
1605 ✗ Error.terminate(getInstanceName() + " got unknown node type", sourceInfo());
1606 ✗ then
1607 fail();
1608 end match;
1609 end scopePathClass;
1610
1611 function isInput
1612 input InstNode node;
1613 output Boolean isInput;
1614 algorithm
1615 isInput := match node
1616 218736 case COMPONENT_NODE() then Component.isInput(Pointer.access(node.component));
1617 else false;
1618 end match;
1619 end isInput;
1620
1621 function isOutput
1622 input InstNode node;
1623 output Boolean isOutput;
1624 algorithm
1625 isOutput := match node
1626 19868 case COMPONENT_NODE() then Component.isOutput(Pointer.access(node.component));
1627 else false;
1628 end match;
1629 end isOutput;
1630
1631 function isInner
1632 input InstNode node;
1633 output Boolean isInner;
1634 algorithm
1635 isInner := match node
1636 2365 case COMPONENT_NODE() then Component.isInner(Pointer.access(node.component));
1637 case CLASS_NODE()
1638 3 then AbsynUtil.isInner(SCodeUtil.prefixesInnerOuter(SCodeUtil.elementPrefixes(node.definition)));
1639 ✗ case INNER_OUTER_NODE() then isInner(node.outerNode);
1640 else false;
1641 end match;
1642 end isInner;
1643
1644 function isOuter
1645 input InstNode node;
1646 output Boolean isOuter;
1647 algorithm
1648 isOuter := match node
1649 952976 case COMPONENT_NODE() then Component.isOuter(Pointer.access(node.component));
1650 case CLASS_NODE()
1651 520342 then AbsynUtil.isOuter(SCodeUtil.prefixesInnerOuter(SCodeUtil.elementPrefixes(node.definition)));
1652 ✗ case INNER_OUTER_NODE() then isOuter(node.outerNode);
1653 else false;
1654 end match;
1655 end isOuter;
1656
1657 function isOnlyOuter
1658 input InstNode node;
1659 output Boolean isOuter;
1660 algorithm
1661 isOuter := match node
1662 18474907 case COMPONENT_NODE() then Component.isOnlyOuter(Pointer.access(node.component));
1663 case CLASS_NODE()
1664 1794 then AbsynUtil.isOnlyOuter(SCodeUtil.prefixesInnerOuter(SCodeUtil.elementPrefixes(node.definition)));
1665 8028 case INNER_OUTER_NODE() then isOnlyOuter(node.outerNode);
1666 else false;
1667 end match;
1668 end isOnlyOuter;
1669
1670 function isInnerOuterNode
1671 input InstNode node;
1672 output Boolean isIO;
1673 algorithm
1674 isIO := match node
1675 case INNER_OUTER_NODE() then true;
1676 else false;
1677 end match;
1678 end isInnerOuterNode;
1679
1680 function isGeneratedInner
1681 input InstNode node;
1682 output Boolean isInner;
1683 algorithm
1684 isInner := match node
1685 case CLASS_NODE(nodeType = InstNodeType.GENERATED_INNER()) then true;
1686 case COMPONENT_NODE(nodeType = InstNodeType.GENERATED_INNER()) then true;
1687 else false;
1688 end match;
1689 end isGeneratedInner;
1690
1691 function resolveInner
1692 input InstNode node;
1693 output InstNode innerNode;
1694 algorithm
1695 innerNode := match node
1696 5229 case INNER_OUTER_NODE() then node.innerNode;
1697 else node;
1698 end match;
1699 end resolveInner;
1700
1701 function resolveOuter
1702 input InstNode node;
1703 output InstNode outerNode;
1704 algorithm
1705 outerNode := match node
1706 5809 case INNER_OUTER_NODE() then node.outerNode;
1707 else node;
1708 end match;
1709 end resolveOuter;
1710
1711 function cacheInitFunc
1712 input output InstNode node;
1713 algorithm
1714 () := match node
1715 26693 case CLASS_NODE() algorithm CachedData.initFunc(node.caches); then ();
1716 ✗ else algorithm Error.terminate(getInstanceName() + " got node without cache", sourceInfo()); then fail();
1717 end match;
1718 end cacheInitFunc;
1719
1720 function cacheAddFunc
1721 input output InstNode node;
1722 input Function fn;
1723 input Boolean specialBuiltin;
1724 algorithm
1725 () := match node
1726 27857 case CLASS_NODE() algorithm CachedData.addFunc(fn, specialBuiltin, node.caches); then ();
1727 ✗ else algorithm Error.terminate(getInstanceName() + " got node without cache", sourceInfo()); then fail();
1728 end match;
1729 end cacheAddFunc;
1730
1731 function newFuncCache
1732 "overwrites the old cache. use only for entirely new inst nodes from cloning!"
1733 input output InstNode node;
1734 input CachedData in_func_cache;
1735 algorithm
1736 () := match node
1737 48 case CLASS_NODE() algorithm node.caches := arrayCreate(1, in_func_cache); then ();
1738 ✗ else algorithm Error.terminate(getInstanceName() + " got node without cache", sourceInfo()); then fail();
1739 end match;
1740 end newFuncCache;
1741
1742 function getFuncCache
1743 input InstNode inNode;
1744 output CachedData func_cache;
1745 algorithm
1746 func_cache := match inNode
1747 642480 case CLASS_NODE() then CachedData.getFuncCache(inNode.caches);
1748 ✗ else algorithm Error.terminate(getInstanceName() + " got node without cache", sourceInfo()); then fail();
1749 end match;
1750 end getFuncCache;
1751
1752 function setFuncCache
1753 input output InstNode node;
1754 input CachedData in_func_cache;
1755 algorithm
1756 () := match node
1757 47516 case CLASS_NODE() algorithm CachedData.setFuncCache(node.caches, in_func_cache); then ();
1758 ✗ else algorithm Error.terminate(getInstanceName() + " got node without cache", sourceInfo()); then fail();
1759 end match;
1760 end setFuncCache;
1761
1762 function getPackageCache
1763 input InstNode inNode;
1764 output CachedData pack_cache;
1765 algorithm
1766 pack_cache := match inNode
1767 1083977 case CLASS_NODE() then CachedData.getPackageCache(inNode.caches);
1768 ✗ else algorithm Error.terminate(getInstanceName() + " got node without cache", sourceInfo()); then fail();
1769 end match;
1770 end getPackageCache;
1771
1772 function setPackageCache
1773 input output InstNode node;
1774 input InstNode packageNode;
1775 input PackageCacheState state;
1776 algorithm
1777 () := match node
1778 56402 case CLASS_NODE() algorithm CachedData.setPackageCache(node.caches, CachedData.PACKAGE(handle(packageNode), state)); then ();
1779 ✗ else algorithm Error.terminate(getInstanceName() + " got node without cache", sourceInfo()); then fail();
1780 end match;
1781 end setPackageCache;
1782
1783 function clearPackageCache
1784 input output InstNode node;
1785 algorithm
1786 () := match node
1787 1790 case CLASS_NODE() algorithm CachedData.clearPackageCache(node.caches); then ();
1788 ✗ else algorithm Error.terminate(getInstanceName() + " got node without cache", sourceInfo()); then fail();
1789 end match;
1790 end clearPackageCache;
1791
1792 function openImplicitScope
1793 input output InstNode scope;
1794 algorithm
1795 scope := match scope
1796 case IMPLICIT_SCOPE() then scope;
1797 4093 else IMPLICIT_SCOPE(scope, {});
1798 end match;
1799 end openImplicitScope;
1800
1801 function explicitScope
1802 "Returns the first parent of the node that's not an implicit scope, or the
1803 node itself if it's not an implicit scope."
1804 input InstNode node;
1805 output InstNode scope;
1806 algorithm
1807 scope := match node
1808 16115 case IMPLICIT_SCOPE() then explicitScope(node.parentScope);
1809 else node;
1810 end match;
1811 end explicitScope;
1812
1813 function addIterator
1814 input InstNode iterator;
1815 input output InstNode scope;
1816 algorithm
1817 scope := match scope
1818 4169 case IMPLICIT_SCOPE() then IMPLICIT_SCOPE(scope, iterator :: scope.locals);
1819 end match;
1820 end addIterator;
1821
1822 function refEqual
1823 "Returns true if two nodes references the same class or component,
1824 otherwise false."
1825 input InstNode node1;
1826 input InstNode node2;
1827 output Boolean refEqual;
1828 algorithm
1829 refEqual := match (node1, node2)
1830 case (CLASS_NODE(), CLASS_NODE())
1831 537567 then referenceEq(Pointer.access(node1.cls), Pointer.access(node2.cls));
1832 case (COMPONENT_NODE(), COMPONENT_NODE())
1833 6988724 then referenceEq(Pointer.access(node1.component), Pointer.access(node2.component));
1834 case (VAR_NODE(), VAR_NODE())
1835 259 then referenceEq(Pointer.access(PointerWeak.upgrade(node1.varPointer)), Pointer.access(PointerWeak.upgrade(node2.varPointer)));
1836 // Other nodes like ref nodes might be equal, but we neither know nor care.
1837 else false;
1838 end match;
1839 end refEqual;
1840
1841 function refCompare
1842 input InstNode node1;
1843 input InstNode node2;
1844 output Integer res;
1845 algorithm
1846 res := match (node1, node2)
1847 case (CLASS_NODE(), CLASS_NODE())
1848 ✗ then Util.referenceCompare(Pointer.access(node1.cls), Pointer.access(node2.cls));
1849 case (COMPONENT_NODE(), COMPONENT_NODE())
1850 ✗ then Util.referenceCompare(Pointer.access(node1.component), Pointer.access(node2.component));
1851 case (CLASS_NODE(), COMPONENT_NODE())
1852 ✗ then Util.referenceCompare(Pointer.access(node1.cls), Pointer.access(node2.component));
1853 case (COMPONENT_NODE(), CLASS_NODE())
1854 ✗ then Util.referenceCompare(Pointer.access(node1.component), Pointer.access(node2.cls));
1855 end match;
1856 end refCompare;
1857
1858 function nameEqual
1859 input InstNode node1;
1860 input InstNode node2;
1861 output Boolean equal = InstNode.name(node1) == InstNode.name(node2);
1862 end nameEqual;
1863
1864 function isSame
1865 input InstNode node1;
1866 input InstNode node2;
1867 output Boolean same = false;
1868 protected
1869 InstNode n1 = resolveOuter(node1);
1870 InstNode n2 = resolveOuter(node2);
1871 algorithm
1872
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 43146 times.
43146 if referenceEq(n1, n2) then
1873 same := true;
1874 ✗ return;
1875 end if;
1876
1877 try
1878 43146 same := referenceEq(definition(node1), definition(node2));
1879 else
1880 same := false;
1881 end try;
1882 end isSame;
1883
1884 function checkIdentical
1885 input InstNode node1;
1886 input InstNode node2;
1887 protected
1888 InstNode n1 = resolveOuter(node1);
1889 InstNode n2 = resolveOuter(node2);
1890 algorithm
1891
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33042 times.
33042 if referenceEq(n1, n2) then
1892 ✗ return;
1893 end if;
1894
1895 () := matchcontinue (n1, n2)
1896 case (CLASS_NODE(), CLASS_NODE())
1897 guard Class.isIdentical(getClass(n1), getClass(n2)) then ();
1898 case (COMPONENT_NODE(), COMPONENT_NODE())
1899 guard Component.isIdentical(component(n1), component(n2)) then ();
1900 else
1901 algorithm
1902 ✗ Error.addMultiSourceMessage(Error.DUPLICATE_ELEMENTS_NOT_IDENTICAL,
1903 {toString(n1), toString(n2)},
1904 {InstNode.info(n1), InstNode.info(n2)});
1905 ✗ then
1906 fail();
1907 end matchcontinue;
1908 end checkIdentical;
1909
1910 function toString
1911 input InstNode node;
1912 output String name;
1913 algorithm
1914 name := match node
1915 220 case COMPONENT_NODE() then Component.toString(node.name, Pointer.access(node.component));
1916 ✗ case CLASS_NODE() then SCodeDump.unparseElementStr(node.definition);
1917 392 else name(node);
1918 end match;
1919 end toString;
1920
1921 function toFlatString
1922 input InstNode node;
1923 input BaseModelica.OutputFormat format;
1924 input String indent;
1925 output String name;
1926 algorithm
1927 name := match node
1928 108 case COMPONENT_NODE() then Component.toFlatString(node.name, Pointer.access(node.component), format, indent);
1929 26 case CLASS_NODE() then Class.toFlatString(Pointer.access(node.cls), node, format, indent);
1930 ✗ else name(node);
1931 end match;
1932 end toFlatString;
1933
1934 function toFlatStream
1935 input InstNode node;
1936 input BaseModelica.OutputFormat format;
1937 input String indent;
1938 input output IOStream.IOStream s;
1939 algorithm
1940 s := match node
1941 ✗ case COMPONENT_NODE() then Component.toFlatStream(node.name, Pointer.access(node.component), format, indent, s);
1942 ✗ case CLASS_NODE() then Class.toFlatStream(Pointer.access(node.cls), node, format, indent, s);
1943 ✗ else IOStream.append(s, toFlatString(node, format, indent));
1944 end match;
1945 end toFlatStream;
1946
1947 function isRedeclare
1948 input InstNode node;
1949 output Boolean isRedeclare;
1950 algorithm
1951 isRedeclare := match node
1952 21397 case CLASS_NODE() then SCodeUtil.isElementRedeclare(definition(node));
1953 255616 case COMPONENT_NODE() then Component.isRedeclare(Pointer.access(node.component));
1954 else false;
1955 end match;
1956 end isRedeclare;
1957
1958 function isRedeclared
1959 input InstNode node;
1960 output Boolean redeclared;
1961 algorithm
1962 redeclared := match nodeType(node)
1963 case InstNodeType.REDECLARED_COMP() then true;
1964 case InstNodeType.REDECLARED_CLASS() then true;
1965 else false;
1966 end match;
1967 end isRedeclared;
1968
1969 function getRedeclaredNode
1970 input InstNode node;
1971 output InstNode outNode;
1972 algorithm
1973 outNode := match node
1974 case InstNode.CLASS_NODE(nodeType = InstNodeType.REDECLARED_CLASS(originalNode = SOME(outNode))) then outNode;
1975 else node;
1976 end match;
1977 end getRedeclaredNode;
1978
1979 function isReplaceable
1980 input InstNode node;
1981 output Boolean repl;
1982 protected
1983 SCode.Element elem;
1984 algorithm
1985 repl := match node
1986 ✗ case CLASS_NODE() then SCodeUtil.isElementReplaceable(node.definition);
1987 5560 case COMPONENT_NODE(definition = SOME(elem)) then SCodeUtil.isElementReplaceable(elem);
1988 else false;
1989 end match;
1990 end isReplaceable;
1991
1992 function isProtectedBaseClass
1993 input InstNode node;
1994 output Boolean isProtected;
1995 algorithm
1996 isProtected := match node
1997 case CLASS_NODE(nodeType = InstNodeType.BASE_CLASS(definition =
1998 SCode.Element.EXTENDS(visibility = SCode.Visibility.PROTECTED())))
1999 then true;
2000
2001 else false;
2002 end match;
2003 end isProtectedBaseClass;
2004
2005 function visibility
2006 input InstNode node;
2007 output Visibility vis;
2008 algorithm
2009 vis := match node
2010 ✗ case CLASS_NODE() then node.visibility;
2011 254478 case COMPONENT_NODE() then node.visibility;
2012 else Visibility.PUBLIC;
2013 end match;
2014 end visibility;
2015
2016 function isProtected
2017 input InstNode node;
2018 output Boolean isProtected;
2019 algorithm
2020 isProtected := match node
2021 case CLASS_NODE(visibility = Visibility.PROTECTED) then true;
2022 case COMPONENT_NODE(visibility = Visibility.PROTECTED) then true;
2023 else false;
2024 end match;
2025 end isProtected;
2026
2027 function isInheritedProtected
2028 input InstNode node;
2029 output Boolean isProtected;
2030 algorithm
2031 isProtected := match node
2032 case CLASS_NODE()
2033
2/4
✓ Branch 0 taken 124848 times.
✗ Branch 1 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 124848 times.
124848 then node.visibility == Visibility.PROTECTED or isInheritedProtected(instanceParent(node));
2034 case COMPONENT_NODE()
2035
4/4
✓ Branch 0 taken 64792 times.
✓ Branch 1 taken 2343 times.
✓ Branch 4 taken 1461 times.
✓ Branch 5 taken 63331 times.
67135 then node.visibility == Visibility.PROTECTED or isInheritedProtected(instanceParent(node));
2036 else false;
2037 end match;
2038 end isInheritedProtected;
2039
2040 function isPublic
2041 input InstNode node;
2042 output Boolean isPublic = not isProtected(node);
2043 end isPublic;
2044
2045 function protectClass
2046 input output InstNode cls;
2047 algorithm
2048 () := match cls
2049 case CLASS_NODE(visibility = Visibility.PUBLIC)
2050 algorithm
2051 1 cls.visibility := Visibility.PROTECTED;
2052 then
2053 ();
2054
2055 else ();
2056 end match;
2057 end protectClass;
2058
2059 function protectComponent
2060 input output InstNode comp;
2061 algorithm
2062 () := match comp
2063 case COMPONENT_NODE(visibility = Visibility.PUBLIC)
2064 algorithm
2065 2 comp.visibility := Visibility.PROTECTED;
2066 then
2067 ();
2068
2069 else ();
2070 end match;
2071 end protectComponent;
2072
2073 function protect
2074 input output InstNode node;
2075 algorithm
2076 () := match node
2077 case COMPONENT_NODE(visibility = Visibility.PUBLIC)
2078 algorithm
2079 32 node.visibility := Visibility.PROTECTED;
2080 then
2081 ();
2082
2083 case CLASS_NODE(visibility = Visibility.PUBLIC)
2084 algorithm
2085 ✗ node.visibility := Visibility.PROTECTED;
2086 then
2087 ();
2088
2089 else ();
2090 end match;
2091 end protect;
2092
2093 function isEncapsulated
2094 input InstNode node;
2095 output Boolean enc;
2096 algorithm
2097 enc := match node
2098 2276287 case CLASS_NODE() then Class.isEncapsulated(Pointer.access(node.cls));
2099 454248 case COMPONENT_NODE() then Class.isEncapsulated(getClass(node));
2100 else false;
2101 end match;
2102 end isEncapsulated;
2103
2104 function getModifier
2105 input InstNode node;
2106 output Modifier mod;
2107 algorithm
2108 mod := match node
2109 157258 case CLASS_NODE() then Class.getModifier(Pointer.access(node.cls));
2110 5557 case COMPONENT_NODE() then Component.getModifier(Pointer.access(node.component));
2111 else Modifier.NOMOD();
2112 end match;
2113 end getModifier;
2114
2115 function mergeModifier
2116 input Modifier mod;
2117 input output InstNode node;
2118 algorithm
2119 () := match node
2120 case CLASS_NODE()
2121 algorithm
2122 ✗ Pointer.update(node.cls, Class.mergeModifier(mod, Pointer.access(node.cls)));
2123 then
2124 ();
2125
2126 case COMPONENT_NODE()
2127 algorithm
2128 ✗ Pointer.update(node.component, Component.mergeModifier(mod, Pointer.access(node.component)));
2129 then
2130 ();
2131
2132 else ();
2133 end match;
2134 end mergeModifier;
2135
2136 function setModifier
2137 input Modifier mod;
2138 input output InstNode node;
2139 algorithm
2140 () := match node
2141 case CLASS_NODE()
2142 algorithm
2143 ✗ Pointer.update(node.cls, Class.setModifier(mod, Pointer.access(node.cls)));
2144 then
2145 ();
2146
2147 case COMPONENT_NODE()
2148 algorithm
2149 5557 Pointer.update(node.component, Component.mergeModifier(mod, Pointer.access(node.component)));
2150 then
2151 ();
2152
2153 else ();
2154 end match;
2155 end setModifier;
2156
2157 function toPartialDAEType
2158 "Returns the DAE type for a class, without the list of variables filled in.
2159 The result is cached: converting the crefs of a scalarized array asks for the
2160 same class type once per element, and building the path is not cheap."
2161 input InstNode clsNode;
2162 output DAE.Type outType;
2163 algorithm
2164 outType := match clsNode
2165 local
2166 Class cls;
2167 ClassInf.State state;
2168 Restriction res;
2169
2170 case CLASS_NODE()
2171 algorithm
2172 2492650 cls := Pointer.access(clsNode.cls);
2173 then
2174 match cls
2175 149165 case Class.DAE_TYPE() then stripDAETypeVars(cls.ty);
2176
2177 else
2178 match CachedData.getTypeCache(clsNode.caches)
2179 local DAE.Type cached;
2180 case CachedData.PARTIAL_DAE_TYPE(ty = cached) then cached;
2181
2182 else
2183 algorithm
2184 6186 res := Class.restriction(cls);
2185 6186 state := Restriction.toDAE(res, fullPath(clsNode));
2186
2/2
✓ Branch 1 taken 6183 times.
✓ Branch 2 taken 3 times.
12369 outType := DAE.Type.T_COMPLEX(state, {}, NONE(), Restriction.isExternalRecord(res));
2187 6186 CachedData.setTypeCache(clsNode.caches, CachedData.PARTIAL_DAE_TYPE(outType));
2188 then
2189 outType;
2190 end match;
2191
2192 end match;
2193 end match;
2194 end toPartialDAEType;
2195
2196 function stripDAETypeVars
2197 input output DAE.Type ty;
2198 algorithm
2199 () := match ty
2200 case DAE.Type.T_COMPLEX()
2201 algorithm
2202 149165 ty.varLst := {};
2203 then
2204 ();
2205
2206 else ();
2207 end match;
2208 end stripDAETypeVars;
2209
2210 function toFullDAEType
2211 "Returns the DAE type for a class, with the list of variables filled in."
2212 input InstNode clsNode;
2213 output DAE.Type outType;
2214 algorithm
2215 outType := match clsNode
2216 local
2217 Class cls;
2218 list<DAE.Var> vars;
2219 ClassInf.State state;
2220 Restriction res;
2221
2222 case CLASS_NODE()
2223 algorithm
2224 71081 cls := Pointer.access(clsNode.cls);
2225 then
2226 match cls
2227 56693 case Class.DAE_TYPE() then cls.ty;
2228
2229 else
2230 algorithm
2231 14388 res := Class.restriction(cls);
2232 14388 state := Restriction.toDAE(res, fullPath(clsNode));
2233 14388 vars := ConvertDAE.makeTypeVars(clsNode);
2234
2/2
✓ Branch 1 taken 14381 times.
✓ Branch 2 taken 7 times.
28769 outType := DAE.Type.T_COMPLEX(state, vars, NONE(), Restriction.isExternalRecord(res));
2235 14388 Pointer.update(clsNode.cls, Class.DAE_TYPE(outType));
2236 then
2237 outType;
2238 end match;
2239 end match;
2240 end toFullDAEType;
2241
2242 function isBuiltin
2243 input InstNode node;
2244 output Boolean isBuiltin;
2245 algorithm
2246 isBuiltin := match node
2247 60697 case CLASS_NODE() then isBuiltinNodeType(node.nodeType);
2248 else false;
2249 end match;
2250 end isBuiltin;
2251
2252 function isBuiltinNodeType
2253 input InstNodeType nodeType;
2254 output Boolean isBuiltin;
2255 algorithm
2256 isBuiltin := match nodeType
2257 case InstNodeType.BUILTIN_CLASS() then true;
2258 3130 case InstNodeType.BASE_CLASS() then isBuiltinNodeType(nodeType.ty);
2259 else false;
2260 end match;
2261 end isBuiltinNodeType;
2262
2263 function isPartial
2264 input InstNode node;
2265 output Boolean isPartial;
2266 algorithm
2267 isPartial := match node
2268 1271846 case CLASS_NODE() then Class.isPartial(Pointer.access(node.cls));
2269 else false;
2270 end match;
2271 end isPartial;
2272
2273 function clone
2274 input output InstNode node;
2275 algorithm
2276 () := match node
2277 local
2278 Class cls;
2279 Component comp;
2280
2281 case CLASS_NODE()
2282 algorithm
2283 517797 cls := Pointer.access(node.cls);
2284 517797 cls := Class.classTreeApply(cls, ClassTree.clone);
2285 517797 node.cls := Pointer.create(cls);
2286 517797 node.caches := CachedData.empty();
2287 then
2288 ();
2289
2290 case COMPONENT_NODE()
2291 algorithm
2292 60 comp := Pointer.access(node.component);
2293 60 comp := Component.setClassInstance(InstNode.clone(Component.classInstance(comp)), comp);
2294 60 node.component := Pointer.create(comp);
2295 then
2296 ();
2297
2298 else ();
2299 end match;
2300
2301 517857 node := reidentify(node);
2302 end clone;
2303
2304 function cloneComponent
2305 input InstNode component;
2306 input InstNode newParent;
2307 output InstNode outComponent = cloneComponentInScope(component, identityCell(newParent));
2308 end cloneComponent;
2309
2310 function cloneComponentInScope
2311 "As `cloneComponent`, given the parent's `identityCell`: taking it once for
2312 all of a parent's components publishes the parent once."
2313 input InstNode component;
2314 input ScopeRef parent;
2315 output InstNode outComponent;
2316 algorithm
2317 outComponent := match component
2318 case COMPONENT_NODE()
2319 16983265 then
2320 COMPONENT_NODE(component.name, component.definition, component.visibility,
2321 Pointer.create(Pointer.access(component.component)),
2322 parent, component.nodeType);
2323
2324 else component;
2325 end match;
2326 end cloneComponentInScope;
2327
2328 function getComments
2329 input InstNode node;
2330 input list<SCode.Comment> accumCmts = {};
2331 output list<SCode.Comment> cmts;
2332 algorithm
2333 cmts := match node
2334 local
2335 SCode.Comment cmt;
2336 Class cls;
2337
2338 case CLASS_NODE(definition = SCode.CLASS(cmt = cmt))
2339 38929 then cmt :: Class.getDerivedComments(Pointer.access(node.cls), accumCmts);
2340
2341 else accumCmts;
2342 end match;
2343 end getComments;
2344
2345 function copyInstancePtr
2346 input InstNode srcNode;
2347 input output InstNode dstNode;
2348 algorithm
2349 () := match (srcNode, dstNode)
2350 case (COMPONENT_NODE(), COMPONENT_NODE())
2351 algorithm
2352 5561 dstNode.component := srcNode.component;
2353 then
2354 ();
2355
2356 case (CLASS_NODE(), CLASS_NODE())
2357 algorithm
2358 ✗ dstNode.cls := srcNode.cls;
2359 then
2360 ();
2361
2362 end match;
2363 end copyInstancePtr;
2364
2365 function isRecord
2366 input InstNode node;
2367 output Boolean isRec;
2368 algorithm
2369 isRec := match node
2370 200747 case CLASS_NODE() then Restriction.isRecord(Class.restriction(Pointer.access(node.cls)));
2371 134729 case COMPONENT_NODE() then isRecord(Component.classInstance(Pointer.access(node.component)));
2372 else false;
2373 end match;
2374 end isRecord;
2375
2376 function isModel
2377 input InstNode node;
2378 output Boolean isModel;
2379 algorithm
2380 isModel := match node
2381 127938 case CLASS_NODE() then Restriction.isModel(Class.restriction(Pointer.access(node.cls)));
2382 ✗ case COMPONENT_NODE() then isModel(Component.classInstance(Pointer.access(node.component)));
2383 else false;
2384 end match;
2385 end isModel;
2386
2387 function isEnumerationType
2388 input InstNode node;
2389 output Boolean isEnum = isClass(node) and Class.isEnumeration(getClass(resolveInner(node)));
2390 end isEnumerationType;
2391
2392 function hasBinding
2393 input InstNode node;
2394 output Boolean hasBinding;
2395 algorithm
2396 hasBinding := match node
2397 case COMPONENT_NODE()
2398
4/4
✓ Branch 2 taken 13374 times.
✓ Branch 3 taken 13291 times.
✓ Branch 6 taken 13280 times.
✓ Branch 7 taken 94 times.
26665 then Component.hasBinding(Pointer.access(node.component)) or hasBinding(instanceParent(node));
2399 else false;
2400 end match;
2401 end hasBinding;
2402
2403 function getBindingExpOpt
2404 input InstNode node;
2405 output Option<Expression> binding_exp;
2406 algorithm
2407 binding_exp := match node
2408 local
2409 Variable var;
2410 InstNode scope;
2411
2412 case COMPONENT_NODE() algorithm
2413 1149 scope := instanceParent(node);
2414 try
2415 1149 binding_exp := Binding.getExpOpt(Component.getImplicitBinding(Pointer.access(node.component), scope));
2416 else
2417 ✗ binding_exp := getBindingExpOpt(scope);
2418 end try;
2419 then binding_exp;
2420 case VAR_NODE() algorithm
2421 937 var := Pointer.access(PointerWeak.upgrade(node.varPointer));
2422 937 then Binding.getExpOpt(var.binding);
2423 else NONE();
2424 end match;
2425 end getBindingExpOpt;
2426
2427 function getSections
2428 input InstNode node;
2429 output Sections sections;
2430 protected
2431 Class cls = InstNode.getClass(node);
2432 algorithm
2433 sections := match cls
2434 89191 case Class.INSTANCED_CLASS() then cls.sections;
2435 1 case Class.TYPED_DERIVED() then getSections(cls.baseClass);
2436
2437 else
2438 algorithm
2439 ✗ Error.terminate(getInstanceName() + " did not get an instanced class", sourceInfo());
2440 ✗ then fail();
2441 end match;
2442 end getSections;
2443
2444 function hash
2445 "Returns the hash of an InstNode's name."
2446 input InstNode node;
2447 output Integer hash = stringHashDjb2(name(node));
2448 end hash;
2449
2450 function hashContinue
2451 "Returns the hash of an InstNode's name."
2452 input InstNode node;
2453 input output Integer hash;
2454 algorithm
2455 17 hash := stringHashDjb2Continue(name(node), hash);
2456 end hashContinue;
2457
2458 function dimensionCount
2459 input InstNode node;
2460 output Integer count;
2461 algorithm
2462 count := match node
2463 722570 case COMPONENT_NODE() then Component.dimensionCount(Pointer.access(node.component));
2464 558694 case CLASS_NODE() then Class.dimensionCount(Pointer.access(node.cls));
2465 else 0;
2466 end match;
2467 end dimensionCount;
2468
2469 function isClockType
2470 input InstNode node;
2471 output Boolean clock;
2472 algorithm
2473 clock := match node
2474 case CLASS_NODE(name = "Clock", nodeType = InstNodeType.BUILTIN_CLASS()) then true;
2475 else false;
2476 end match;
2477 end isClockType;
2478
2479 function restriction
2480 input InstNode node;
2481 output Restriction res;
2482 algorithm
2483 res := match node
2484 743767 case CLASS_NODE() then Class.restriction(Pointer.access(node.cls));
2485 ✗ case COMPONENT_NODE() then restriction(Component.classInstance(Pointer.access(node.component)));
2486 ✗ case INNER_OUTER_NODE() then restriction(node.innerNode);
2487 else Restriction.UNKNOWN();
2488 end match;
2489 end restriction;
2490
2491 function isExtends
2492 input InstNode node;
2493 output Boolean res;
2494 algorithm
2495 res := match node
2496 case CLASS_NODE(definition = SCode.Element.EXTENDS()) then true;
2497 case CLASS_NODE(nodeType = InstNodeType.BASE_CLASS(definition = SCode.Element.EXTENDS())) then true;
2498 else false;
2499 end match;
2500 end isExtends;
2501
2502 function isDiscreteClass
2503 input InstNode clsNode;
2504 output Boolean isDiscrete;
2505 protected
2506 InstNode base_node;
2507 Class cls;
2508 array<InstNode> exts;
2509 algorithm
2510 416560 base_node := Class.lastBaseClass(clsNode);
2511 416560 cls := InstNode.getClass(base_node);
2512
2513 isDiscrete := match cls
2514 case Class.EXPANDED_CLASS(restriction = Restriction.TYPE())
2515 algorithm
2516 17044 exts := ClassTree.getExtends(cls.elements);
2517
2/2
✓ Branch 0 taken 16690 times.
✓ Branch 1 taken 354 times.
17044 then
2518 if arrayLength(exts) == 1 then isDiscreteClass(exts[1]) else false;
2519
2520 399516 else Type.isDiscrete(Class.getType(cls, base_node));
2521 end match;
2522 end isDiscreteClass;
2523
2524 function clearGeneratedInners
2525 input InstNode node;
2526 protected
2527 UnorderedMap<String, InstNode> inners;
2528 algorithm
2529
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 2512 times.
2512 InstNodeType.TOP_SCOPE(generatedInners = inners) := nodeType(InstNode.topScope(node));
2530 2512 UnorderedMap.clear(inners);
2531 end clearGeneratedInners;
2532
2533 function scopeRoots
2534 "The identity cells this node's tree owns; see TOP_SCOPE.roots. Pass it to
2535 MutableWeak.useRoots before adding nodes to a tree built by an earlier run."
2536 input InstNode node;
2537 output MutableWeak.Roots roots;
2538 algorithm
2539
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 2512 times.
2512 InstNodeType.TOP_SCOPE(roots = roots) := nodeType(InstNode.topScope(node));
2540 end scopeRoots;
2541
2542 function getAccessLevel
2543 input InstNode node;
2544 output Option<AccessLevel> access = NONE();
2545 protected
2546 InstNode scope;
2547 SCode.Mod access_mod;
2548 Option<Absyn.Exp> access_exp;
2549 algorithm
2550 12330 scope := classScope(parent(resolveInner(node)));
2551
2552
2/2
✓ Branch 1 taken 73201 times.
✓ Branch 2 taken 12330 times.
85531 while isClass(scope) loop
2553 73201 access_mod := SCodeUtil.lookupElementAnnotation(definition(scope), "Protection");
2554 73201 access_mod := SCodeUtil.lookupModInMod("access", access_mod);
2555 73201 access_exp := SCodeUtil.getModifierBinding(access_mod);
2556
2557
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 73201 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 73201 times.
73201 if isSome(access_exp) then
2558 ✗ access := Prefixes.accessLevelFromAbsyn(Util.getOption(access_exp));
2559
2560 ✗ if isSome(access) then
2561 ✗ return;
2562 end if;
2563 end if;
2564
2565 73201 scope := parent(scope);
2566 end while;
2567 end getAccessLevel;
2568 end InstNode;
2569
2570 annotation(__OpenModelica_Interface="nf_frontend");
2571 end NFInstNode;
2572