Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 38.3% 74 / 0 / 193
Functions: -% 0 / 1 / 1
Branches: 32.5% 41 / 0 / 126

OMCompiler/Compiler/FFrontEnd/FNode.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 FNode
37 " file: FNode.mo
38 package: FNode
39 description: A node structure to hold Modelica constructs
40
41
42 This module builds nodes out of SCode
43 "
44
45 // public imports
46 public
47 import Absyn;
48 import AbsynUtil;
49 import DAE;
50 import SCode;
51 import FCore;
52 import Mutable;
53 import MutableWeak;
54
55 // protected imports
56 protected
57 import Error;
58 import List;
59 import FGraph;
60 import Config;
61 import Flags;
62 import SCodeUtil;
63
64 public
65 type Name = FCore.Name;
66 type Names = FCore.Names;
67 type Id = FCore.Id;
68 type Seq = FCore.Seq;
69 type Next = FCore.Next;
70 type Node = FCore.Node;
71 type Data = FCore.Data;
72 type Kind = FCore.Kind;
73 type Ref = FCore.Ref;
74 type Refs = FCore.Refs;
75 import FCore.RefTree;
76 type Children = FCore.Children;
77 type Parents = FCore.Parents;
78 type Scope = FCore.Scope;
79 type ImportTable = FCore.ImportTable;
80 type Graph = FCore.Graph;
81 type Extra = FCore.Extra;
82 type Visited = FCore.Visited;
83 type Import = FCore.Import;
84
85 constant Name extendsPrefix = "$ext_" "prefix of the extends node";
86
87 constant Name topNodeName = "$top";
88
89 // these names are used mostly for edges in the graph
90 // the edges are saved inside the AvlTree ("name", Ref)
91 constant Name tyNodeName = "$ty" "type node";
92 constant Name ftNodeName = "$ft" "function types node";
93 constant Name refNodeName = "$ref" "reference node";
94 constant Name modNodeName = "$mod" "modifier node";
95 constant Name bndNodeName = "$bnd" "binding node";
96 constant Name cndNodeName = "$cnd" "conditional component condition";
97 constant Name dimsNodeName = "$dims" "dimensions node";
98 constant Name tydimsNodeName = "$tydims" "type dimensions node";
99 constant Name subsNodeName = "$subs" "cref subscripts";
100 constant Name ccNodeName = "$cc" "constrain class node";
101 constant Name eqNodeName = "$eq" "equation";
102 constant Name ieqNodeName = "$ieq" "initial equation";
103 constant Name alNodeName = "$al" "algorithm";
104 constant Name ialNodeName = "$ial" "initial algorithm";
105 constant Name optNodeName = "$opt" "optimization node";
106 constant Name edNodeName = "$ed" "external declaration node";
107 constant Name forNodeName = "$for" "scope for for-iterators";
108 constant Name matchNodeName = "$match" "scope for match exps";
109 constant Name cloneNodeName = "$clone" "clone of the reference node";
110 constant Name origNodeName = "$original" "the original of the clone";
111 constant Name feNodeName = "$functionEvaluation" "a node for function evaluation";
112 constant Name duNodeName = "$definedUnits" "a node for storing defined units";
113 constant Name veNodeName = "$ve" "a node for storing references to instance component";
114 constant Name imNodeName = "$imp" "an node holding the import table";
115 constant Name itNodeName = "$it" "an node holding the instance information DAE.Var";
116 constant Name assertNodeName = "$assert" "an assersion node";
117 constant Name statusNodeName = "$status" "an status node";
118
119 public function toRef
120 "@author: adrpo
121 turns a node into a ref"
122 input Node inNode;
123 output Ref outRef;
124 algorithm
125 27966932 outRef := Mutable.create(inNode);
126 end toRef;
127
128 public function fromRef
129 "@author: adrpo
130 turns a ref into a node"
131 input Ref inRef;
132 output Node outNode;
133 algorithm
134 209680179 outNode := Mutable.access(inRef);
135 end fromRef;
136
137 public function updateRef
138 "@author: adrpo
139 sets a node into a ref"
140 input Ref inRef;
141 input Node inNode;
142 output Ref outRef;
143 algorithm
144 20873866 Mutable.update(inRef, inNode);
145 outRef := inRef;
146 end updateRef;
147
148 public function id
149 input Node inNode;
150 output Id id;
151 algorithm
152 ✗ FCore.N(id = id) := inNode;
153 end id;
154
155 public function parents
156 "The parents as owning references. They are stored weakly (see FCore.Node.N),
157 so this upgrades; it fails if a parent is already gone, which would mean the
158 node outlived the graph that owns it.
159
160 Rebuilds the list, so prefer originalParent/contextualParent — every caller
161 so far wants only one end of it."
162 input Node inNode;
163 output Parents p;
164 protected
165 FCore.WeakParents w;
166 algorithm
167 ✗ FCore.N(parents = w) := inNode;
168 ✗ p := list(MutableWeak.upgrade(r) for r in w);
169 end parents;
170
171 public function originalParent
172 "The original parent (the last one), without rebuilding the parent list."
173 input Node inNode;
174 output Ref r;
175 protected
176 FCore.WeakParents w;
177 algorithm
178 ✗ FCore.N(parents = w) := inNode;
179 ✗ r := MutableWeak.upgrade(List.last(w));
180 end originalParent;
181
182 public function refOriginalParent
183 input Ref inRef;
184 output Ref r;
185 algorithm
186 ✗ r := originalParent(fromRef(inRef));
187 end refOriginalParent;
188
189 public function contextualParent
190 "The contextual parent (the first one), without rebuilding the parent list."
191 input Node inNode;
192 output Ref r;
193 protected
194 FCore.WeakParents w;
195 algorithm
196 ✗ FCore.N(parents = w) := inNode;
197 ✗ r := MutableWeak.upgrade(listHead(w));
198 end contextualParent;
199
200 public function hasParents
201 input Node inNode;
202 output Boolean b;
203 protected
204 FCore.WeakParents w;
205 algorithm
206 // Deliberately does not upgrade: only the count matters here.
207 ✗ FCore.N(parents = w) := inNode;
208 ✗ b := not listEmpty(w);
209 end hasParents;
210
211 public function refParents
212 input Ref inRef;
213 output Parents p;
214 algorithm
215 ✗ p := parents(fromRef(inRef));
216 end refParents;
217
218 public function refPushParents
219 input Ref inRef;
220 input Parents inParents;
221 output Ref outRef;
222 protected
223 Name n;
224 Id i;
225 FCore.WeakParents p;
226 Children c;
227 Data d;
228 algorithm
229 ✗ FCore.N(n, i, p, c, d) := fromRef(inRef);
230 ✗ p := listAppend(list(MutableWeak.downgrade(r) for r in inParents), p);
231 ✗ outRef := updateRef(inRef, FCore.N(n, i, p, c, d));
232 end refPushParents;
233
234 public function setParents
235 input Node inNode;
236 input Parents inParents;
237 output Node outNode;
238 protected
239 Name n;
240 Id i;
241 FCore.WeakParents p;
242 Children c;
243 Data d;
244 algorithm
245 ✗ FCore.N(n, i, p, c, d) := inNode;
246 ✗ outNode := FCore.N(n, i, list(MutableWeak.downgrade(r) for r in inParents), c, d);
247 end setParents;
248
249 public function target
250 "returns a target from a REF node"
251 input Node inNode;
252 output Ref outRef;
253 algorithm
254 ✗ outRef::_ := targetScope(inNode);
255 end target;
256
257 public function targetScope
258 "returns the target scope from a REF node"
259 input Node inNode;
260 output Scope outScope;
261 algorithm
262 outScope := match inNode
263 case FCore.N(data = FCore.REF(target = outScope)) then outScope;
264 end match;
265 end targetScope;
266
267 public function new
268 input Name inName;
269 input Id inId;
270 input Parents inParents;
271 input Data inData;
272 output Node node;
273 algorithm
274
4/4
✓ Branch 0 taken 12301446 times.
✓ Branch 1 taken 12304869 times.
✓ Branch 2 taken 12301446 times.
✓ Branch 3 taken 12304869 times.
24606315 node := FCore.N(inName, inId, list(MutableWeak.downgrade(r) for r in inParents), RefTree.new(), inData);
275 end new;
276
277 public function addImport
278 "add import to the import table"
279 input SCode.Element inImport;
280 input ImportTable inImportTable;
281 output ImportTable outImportTable;
282 algorithm
283 outImportTable := match(inImport, inImportTable)
284 local
285 Import imp;
286 list<Import> qual_imps, unqual_imps;
287 SourceInfo info;
288 Boolean hidden;
289
290 // Unqualified imports
291 case (SCode.IMPORT(imp = imp as Absyn.UNQUAL_IMPORT()),
292 FCore.IMPORT_TABLE(hidden, qual_imps, unqual_imps))
293 algorithm
294 5 unqual_imps := List.unionElt(imp, unqual_imps);
295
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
10 then
296 FCore.IMPORT_TABLE(hidden, qual_imps, unqual_imps);
297
298 // Qualified imports
299 case (SCode.IMPORT(imp = imp, info = info),
300 FCore.IMPORT_TABLE(hidden, qual_imps, unqual_imps))
301 algorithm
302 76633 imp := translateQualifiedImportToNamed(imp);
303 76633 checkUniqueQualifiedImport(imp, qual_imps, info);
304 76633 qual_imps := List.unionElt(imp, qual_imps);
305
1/2
✓ Branch 0 taken 76633 times.
✗ Branch 1 not taken.
153266 then
306 FCore.IMPORT_TABLE(hidden, qual_imps, unqual_imps);
307 end match;
308 end addImport;
309
310 protected function translateQualifiedImportToNamed
311 "Translates a qualified import to a named import."
312 input Import inImport;
313 output Import outImport;
314 algorithm
315 outImport := match inImport
316 local
317 Name name;
318 Absyn.Path path;
319
320 // Already named.
321 case Absyn.NAMED_IMPORT() then inImport;
322
323 // Get the last identifier from the import and use that as the name.
324 case Absyn.QUAL_IMPORT(path = path)
325 algorithm
326 76633 name := AbsynUtil.pathLastIdent(path);
327 76633 then
328 Absyn.NAMED_IMPORT(name, path);
329 end match;
330 end translateQualifiedImportToNamed;
331
332 protected function checkUniqueQualifiedImport
333 "Checks that a qualified import is unique, because it's not allowed to have
334 qualified imports with the same name."
335 input Import inImport;
336 input list<Import> inImports;
337 input SourceInfo inInfo;
338 algorithm
339 () := matchcontinue inImport
340 local
341 Name name;
342
343 case _
344 algorithm
345
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 76633 times.
76633 false := List.isMemberOnTrue(inImport, inImports,
346 compareQualifiedImportNames);
347 then
348 ();
349
350 case Absyn.NAMED_IMPORT(name = name)
351 algorithm
352 ✗ Error.addSourceMessage(Error.MULTIPLE_QUALIFIED_IMPORTS_WITH_SAME_NAME,
353 {name}, inInfo);
354 ✗ then
355 fail();
356
357 end matchcontinue;
358 end checkUniqueQualifiedImport;
359
360 protected function compareQualifiedImportNames
361 "Compares two qualified imports, returning true if they have the same import
362 name, otherwise false."
363 input Import inImport1;
364 input Import inImport2;
365 output Boolean outEqual;
366 algorithm
367 outEqual := match(inImport1, inImport2)
368 local
369 Name name1, name2;
370
371 case (Absyn.NAMED_IMPORT(name = name1), Absyn.NAMED_IMPORT(name = name2)) guard stringEqual(name1, name2)
372 then
373 true;
374
375 else false;
376 end match;
377 end compareQualifiedImportNames;
378
379 public function addChildRef
380 input Ref inParentRef;
381 input Name inName;
382 input Ref inChildRef;
383 input Boolean checkDuplicate = false;
384 protected
385 Name n;
386 Integer i;
387 FCore.WeakParents p;
388 Children c;
389 Data d;
390 Ref parent;
391 algorithm
392 12105153 FCore.N(n, i, p, c, d) := fromRef(inParentRef);
393
2/2
✓ Branch 0 taken 3794477 times.
✓ Branch 1 taken 8310676 times.
15899630 c := RefTree.add(c, inName, inChildRef,
394 if checkDuplicate then printElementConflictError else RefTree.addConflictReplace);
395 12105153 parent := updateRef(inParentRef, FCore.N(n, i, p, c, d));
396 end addChildRef;
397
398 protected function printElementConflictError
399 input Ref newRef;
400 input Ref oldRef;
401 input RefTree.Key name;
402 output Ref dummy;
403 protected
404 SourceInfo info1, info2;
405 algorithm
406
1/2
✓ Branch 1 taken 603 times.
✗ Branch 2 not taken.
603 if Config.acceptMetaModelicaGrammar() then
407 dummy := newRef;
408 else
409 ✗ info1 := SCodeUtil.elementInfo(FNode.getElementFromRef(newRef));
410 ✗ info2 := SCodeUtil.elementInfo(FNode.getElementFromRef(oldRef));
411 ✗ Error.addMultiSourceMessage(Error.DOUBLE_DECLARATION_OF_ELEMENTS, {name}, {info2, info1});
412 ✗ fail();
413 end if;
414 end printElementConflictError;
415
416 public function addImportToRef
417 input Ref ref;
418 input SCode.Element imp;
419 protected
420 Name n;
421 Integer id;
422 FCore.WeakParents p;
423 Children c;
424 ImportTable it;
425 Ref r;
426 algorithm
427
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 76638 times.
76638 FCore.N(n, id, p, c, FCore.IM(it)) := fromRef(ref);
428 76638 it := addImport(imp, it);
429 76638 r := updateRef(ref, FCore.N(n, id, p, c, FCore.IM(it)));
430 end addImportToRef;
431
432 public function addTypesToRef
433 input Ref ref;
434 input list<DAE.Type> inTys;
435 protected
436 Name n;
437 Integer id;
438 FCore.WeakParents p;
439 Children c;
440 list<DAE.Type> tys;
441 Ref r;
442 algorithm
443
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 45272 times.
45272 FCore.N(n, id, p, c, FCore.FT(tys)) := fromRef(ref);
444 45272 tys := List.unique(listAppend(inTys, tys));
445 // A type-only instantiation cannot run the body analysis that marks a
446 // function no-return, so it yields a returning variant, while a full
447 // instantiation yields the no-return variant. Both would otherwise be kept
448 // here (they differ only in the NoReturn marker), leaving two types for a
449 // single function and breaking single-type function lookups. Drop the
450 // returning variant when a no-return variant of the same function is present.
451
6/6
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 45293 times.
✓ Branch 3 taken 45302 times.
✓ Branch 4 taken 45272 times.
✓ Branch 5 taken 45293 times.
✓ Branch 6 taken 45272 times.
90574 tys := list(t for t guard not isReturningFunctionWithNoReturnVariant(t, tys) in tys);
452 // update the child
453 45272 r := updateRef(ref, FCore.N(n, id, p, c, FCore.FT(tys)));
454 end addTypesToRef;
455
456 protected function isReturningFunctionWithNoReturnVariant
457 "True if ty is a returning function type for which the list also holds an
458 otherwise identical no-return function type."
459 input DAE.Type ty;
460 input list<DAE.Type> tys;
461 output Boolean b;
462 algorithm
463 b := match ty
464 case DAE.T_FUNCTION(functionAttributes = DAE.FUNCTION_ATTRIBUTES(noReturn = DAE.NoReturn.RETURNS))
465 45198 then List.isMemberOnTrue(ty, tys, isNoReturnVariantOf);
466 else false;
467 end match;
468 end isReturningFunctionWithNoReturnVariant;
469
470 protected function isNoReturnVariantOf
471 "True if cand is a no-return function type equal to the given returning
472 function type apart from the NoReturn marker."
473 input DAE.Type returning;
474 input DAE.Type cand;
475 output Boolean b;
476 algorithm
477 b := match (returning, cand)
478 local
479 list<DAE.FuncArg> fargs1, fargs2;
480 DAE.Type ret1, ret2;
481 Absyn.Path path1, path2;
482 DAE.FunctionAttributes attr1, attr2;
483 case (DAE.T_FUNCTION(fargs1, ret1, attr1, path1),
484 DAE.T_FUNCTION(fargs2, ret2, attr2 as DAE.FUNCTION_ATTRIBUTES(noReturn = DAE.NoReturn.NORETURN), path2))
485
4/8
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 9 times.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 9 times.
9 then AbsynUtil.pathEqual(path1, path2) and valueEq(ret1, ret2)
486 and valueEq(fargs1, fargs2) and functionAttributesEqualModNoReturn(attr1, attr2);
487 else false;
488 end match;
489 end isNoReturnVariantOf;
490
491 protected function functionAttributesEqualModNoReturn
492 "Compares two function attribute records ignoring their NoReturn marker."
493 input DAE.FunctionAttributes a1;
494 input DAE.FunctionAttributes a2;
495 output Boolean equal;
496 algorithm
497 equal := match (a1, a2)
498 local
499 DAE.InlineType inl1, inl2;
500 Boolean omp1, omp2, fp1, fp2;
501 DAE.Purity pu1, pu2;
502 DAE.FunctionBuiltin bi1, bi2;
503 DAE.FunctionParallelism par1, par2;
504 case (DAE.FUNCTION_ATTRIBUTES(inl1, omp1, pu1, fp1, bi1, par1, _),
505 DAE.FUNCTION_ATTRIBUTES(inl2, omp2, pu2, fp2, bi2, par2, _))
506
10/20
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 9 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 9 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 9 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 9 times.
✗ Branch 14 not taken.
✓ Branch 15 taken 9 times.
✗ Branch 16 not taken.
✓ Branch 18 taken 9 times.
✗ Branch 19 not taken.
✓ Branch 21 taken 9 times.
✗ Branch 22 not taken.
✗ Branch 24 not taken.
✓ Branch 25 taken 9 times.
45 then valueEq(inl1, inl2) and valueEq(omp1, omp2) and valueEq(pu1, pu2)
507 and valueEq(fp1, fp2) and valueEq(bi1, bi2) and valueEq(par1, par2);
508 end match;
509 end functionAttributesEqualModNoReturn;
510
511 public function addIteratorsToRef
512 input Ref ref;
513 input Absyn.ForIterators inIterators;
514 protected
515 Name n;
516 Integer id;
517 FCore.WeakParents p;
518 Children c;
519 Absyn.ForIterators it;
520 Ref r;
521 algorithm
522 ✗ FCore.N(n, id, p, c, FCore.FS(it)) := fromRef(ref);
523 // update the child
524 ✗ r := updateRef(ref, FCore.N(n, id, p, c, FCore.FS(listAppend(it, inIterators))));
525 end addIteratorsToRef;
526
527 public function addDefinedUnitToRef
528 input Ref ref;
529 input SCode.Element du;
530 protected
531 Name n;
532 Integer id;
533 FCore.WeakParents p;
534 Children c;
535 Ref r;
536 list<SCode.Element> dus;
537 algorithm
538 ✗ FCore.N(n, id, p, c, FCore.DU(dus)) := fromRef(ref);
539 ✗ r := updateRef(ref, FCore.N(n, id, p, c, FCore.DU(du::dus)));
540 end addDefinedUnitToRef;
541
542 public function name
543 input Node n;
544 output String name;
545 algorithm
546 name := match n
547 local String s;
548 case FCore.N(name = s) then s;
549 end match;
550 end name;
551
552 public function refName
553 input Ref r;
554 output String n;
555 algorithm
556 39622205 n := name(fromRef(r));
557 end refName;
558
559 public function data
560 input Node n;
561 output Data d;
562 algorithm
563 d := match n
564 case FCore.N(data = d) then d;
565 end match;
566 end data;
567
568 public function refData
569 input Ref r;
570 output Data outData;
571 algorithm
572 6752881 outData := data(fromRef(r));
573 end refData;
574
575 public function top
576 "@author: adrpo
577 return the top node ref"
578 input Ref inRef;
579 output Ref outTop;
580 algorithm
581 outTop := inRef;
582 ✗ while hasParents(fromRef(outTop)) loop
583 ✗ outTop := refOriginalParent(outTop);
584 end while;
585 end top;
586
587 public function children
588 input Node inNode;
589 output Children outChildren;
590 algorithm
591 54554594 FCore.N(children = outChildren) := inNode;
592 end children;
593
594 public function hasChild
595 input Node inNode;
596 input Name inName;
597 output Boolean b;
598 algorithm
599 b := matchcontinue inName
600
601 case _
602 algorithm
603 ✗ childFromNode(inNode, inName);
604 then
605 true;
606
607 else false;
608
609 end matchcontinue;
610 end hasChild;
611
612 public function refHasChild
613 input Ref inRef;
614 input Name inName;
615 output Boolean b;
616 algorithm
617 ✗ b := hasChild(fromRef(inRef), inName);
618 end refHasChild;
619
620 public function setChildren
621 input Node inNode;
622 input Children inChildren;
623 output Node outNode;
624 protected
625 Name n;
626 Id i;
627 FCore.WeakParents p;
628 Children c;
629 Data d;
630 algorithm
631 1692 FCore.N(n, i, p, c, d) := inNode;
632 1692 outNode := FCore.N(n, i, p, inChildren, d);
633 end setChildren;
634
635 public function setData
636 input Node inNode;
637 input Data inData;
638 output Node outNode;
639 protected
640 Name n;
641 Id i;
642 FCore.WeakParents p;
643 Children c;
644 algorithm
645 3638387 FCore.N(n, i, p, c, _) := inNode;
646 3638387 outNode := FCore.N(n, i, p, c, inData);
647 end setData;
648
649 public function child
650 input Ref inParentRef;
651 input Name inName;
652 output Ref outChildRef;
653 algorithm
654 40099670 outChildRef := childFromNode(fromRef(inParentRef), inName);
655 end child;
656
657 public function childFromNode
658 input Node inNode;
659 input Name inName;
660 output Ref outChildRef;
661 protected
662 Children c;
663 algorithm
664 40102328 c := children(inNode);
665 40102328 outChildRef := RefTree.get(c, inName);
666 end childFromNode;
667
668 public function element2Data
669 input SCode.Element inElement;
670 input Kind inKind;
671 output Data outData;
672 output DAE.Var outVar;
673 algorithm
674 (outData, outVar) := match inElement
675 local
676 String n;
677 SCode.Visibility vis;
678 SCode.ConnectorType ct;
679 Absyn.InnerOuter io;
680 SCode.Parallelism prl;
681 SCode.Variability var;
682 Absyn.Direction dir;
683 Data nd;
684 DAE.Var i;
685
686 // a component
687 case SCode.COMPONENT(n,SCode.PREFIXES(vis,_,_,io,_),
688 SCode.ATTR(_,ct,prl,var,dir),
689 _,_,_,_,_)
690 algorithm
691 1194991 nd := FCore.CO(inElement, DAE.NOMOD(), inKind, FCore.VAR_UNTYPED());
692 1194991 i := DAE.TYPES_VAR(
693 n,
694 DAE.ATTR(DAEUtil.toConnectorTypeNoState(ct),prl,var,dir,io,vis),
695 DAE.T_UNKNOWN_DEFAULT,
696 DAE.UNBOUND(),false,NONE());
697 then
698 (nd, i);
699
700 end match;
701 end element2Data;
702
703 public function dataStr
704 input Data inData;
705 output String outStr;
706 algorithm
707 outStr := match inData
708 local
709 Name n;
710 String m;
711
712 case FCore.TOP() then "TOP";
713 case FCore.IT(_) then "I";
714 case FCore.CL(e = SCode.CLASS(classDef = SCode.CLASS_EXTENDS())) then "CE";
715 case FCore.CL() then "C";
716 case FCore.CO() then "c";
717 case FCore.EX() then "E";
718 case FCore.DU(_) then "U";
719 case FCore.FT(_) then "FT";
720 case FCore.AL(_, _) then "ALG";
721 case FCore.EQ(_, _) then "EQ";
722 case FCore.OT(_, _) then "OPT";
723 case FCore.ED(_) then "ED";
724 case FCore.FS(_) then "FS";
725 case FCore.FI(_) then "FI";
726 case FCore.MS(_) then "MS";
727 case FCore.MO(_) then "M";
728 case FCore.EXP(name=n) then n;
729 case FCore.DIMS(name=n) then n;
730 case FCore.CR(_) then "r";
731 case FCore.CC(_) then "CC";
732 case FCore.ND(_) then "ND";
733 case FCore.REF(_) then "REF";
734 case FCore.VR() then "VR";
735 case FCore.IM(_) then "IM";
736 ✗ case FCore.ASSERT(m) then "assert(" + m + ")";
737
738 else "UKNOWN NODE DATA";
739
740 end match;
741 end dataStr;
742
743 public function toStr
744 input Node inNode;
745 output String outStr;
746 algorithm
747 outStr := matchcontinue inNode
748 local
749 Id i;
750 FCore.WeakParents p;
751 Data d;
752
753 case FCore.N(_, i, p, _, d)
754 algorithm
755 ✗ outStr :=
756 "[i:" + intString(i) + "] " +
757 "[p:" + stringDelimitList(List.map(List.map(List.map(list(MutableWeak.upgrade(w) for w in p), fromRef), id), intString), ", ") + "] " +
758 "[n:" + name(inNode) + "] " +
759 "[d:" + dataStr(d) + "]";
760 then
761 outStr;
762
763 else "Unhandled node!";
764
765 end matchcontinue;
766 end toStr;
767
768 public function toPathStr
769 "returns the path from top to this node"
770 input Node inNode;
771 output String outStr;
772 algorithm
773 outStr := matchcontinue inNode
774 local
775 FCore.WeakParents p;
776 Ref nr;
777 String s;
778
779 // top node
780 case FCore.N(_, _, {}, _, _)
781 algorithm
782 ✗ outStr := name(inNode);
783 then
784 outStr;
785
786 case FCore.N(_, _, p, _, _)
787 algorithm
788 // The contextual parent is the first one; upgrade just that, rather
789 // than the whole list.
790 ✗ nr := MutableWeak.upgrade(listHead(p));
791 ✗ true := hasParents(fromRef(nr));
792 ✗ s := toPathStr(fromRef(nr));
793 ✗ outStr := s + "." + name(inNode);
794 then
795 outStr;
796
797 case FCore.N(_, _, p, _, _)
798 algorithm
799 ✗ nr := MutableWeak.upgrade(listHead(p));
800 ✗ false := hasParents(fromRef(nr));
801 ✗ outStr := "." + name(inNode);
802 then
803 outStr;
804 end matchcontinue;
805 end toPathStr;
806
807 public function scopeStr
808 "note that this function returns the scopes in reverse"
809 input Scope sc;
810 output String s;
811 algorithm
812 ✗ s := stringDelimitList(List.map(listReverse(sc), refName), "/");
813 end scopeStr;
814
815 public function isImplicitScope
816 "anything that is not top, class or a component is an implicit scope!"
817 input Node inNode;
818 output Boolean b;
819 algorithm
820 b := match inNode
821 case FCore.N(data = FCore.TOP()) then false;
822 case FCore.N(data = FCore.CL()) then false;
823 case FCore.N(data = FCore.CO()) then false;
824 case FCore.N(data = FCore.CC()) then false;
825 case FCore.N(data = FCore.FS()) then false;
826 case FCore.N(data = FCore.MS()) then false;
827 case FCore.N(data = FCore.VR()) then false;
828 else true;
829 end match;
830 end isImplicitScope;
831
832 public function isRefImplicitScope
833 "anything that is not a class or a component is an implicit scope!"
834 input Ref inRef;
835 output Boolean b;
836 algorithm
837 ✗ b := isImplicitScope(fromRef(inRef));
838 end isRefImplicitScope;
839
840 public function isEncapsulated
841 input Node inNode;
842 output Boolean b;
843 algorithm
844 b := match inNode
845 case FCore.N(data = FCore.CL(e = SCode.CLASS(encapsulatedPrefix = SCode.ENCAPSULATED()))) then true;
846 case FCore.N(data = FCore.CO()) guard boolEq(Config.acceptMetaModelicaGrammar(), false) and boolNot(Flags.isSet(Flags.GRAPH_INST))
847 then true;
848 else false;
849 end match;
850 end isEncapsulated;
851
852 public function isReference
853 input Node inNode;
854 output Boolean b;
855 algorithm
856 b := match inNode
857 case FCore.N(data = FCore.REF()) then true;
858 else false;
859 end match;
860 end isReference;
861
862 public function isUserDefined
863 input Node inNode;
864 output Boolean b;
865 algorithm
866 b := match inNode
867 local Ref p;
868 case FCore.N(data = FCore.CL(kind = FCore.USERDEFINED())) then true;
869 case FCore.N(data = FCore.CO(kind = FCore.USERDEFINED())) then true;
870 // any parent is userdefined?
871 case _ guard hasParents(inNode)
872 algorithm
873 ✗ b := isRefUserDefined(contextualParent(inNode));
874 then
875 b;
876 else false;
877 end match;
878 end isUserDefined;
879
880 public function isTop
881 input Node inNode;
882 output Boolean b;
883 algorithm
884 b := match inNode
885 case FCore.N(data = FCore.TOP()) then true;
886 else false;
887 end match;
888 end isTop;
889
890 public function isExtends
891 input Node inNode;
892 output Boolean b;
893 algorithm
894 b := match inNode
895 case FCore.N(data = FCore.EX()) then true;
896 else false;
897 end match;
898 end isExtends;
899
900 public function isDerived
901 input Node inNode;
902 output Boolean b;
903 algorithm
904 b := match inNode
905 local SCode.Element e;
906 ✗ case FCore.N(data = FCore.CL(e = e)) then SCodeUtil.isDerivedClass(e);
907 else false;
908 end match;
909 end isDerived;
910
911 public function isClass
912 input Node inNode;
913 output Boolean b;
914 algorithm
915 b := match inNode
916 case FCore.N(data = FCore.CL()) then true;
917 else false;
918 end match;
919 end isClass;
920
921 public function isInstance
922 input Node inNode;
923 output Boolean b;
924 algorithm
925 b := match inNode
926 case FCore.N(data = FCore.CL(status = FCore.CLS_INSTANCE(_))) then true;
927 else false;
928 end match;
929 end isInstance;
930
931 public function isRedeclare
932 input Node inNode;
933 output Boolean b;
934 algorithm
935 b := match inNode
936 case FCore.N(data = FCore.CL(e = SCode.CLASS(prefixes = SCode.PREFIXES(redeclarePrefix = SCode.REDECLARE())))) then true;
937 case FCore.N(data = FCore.CO(e = SCode.COMPONENT(prefixes = SCode.PREFIXES(redeclarePrefix = SCode.REDECLARE())))) then true;
938 else false;
939 end match;
940 end isRedeclare;
941
942 public function isClassExtends
943 input Node inNode;
944 output Boolean b;
945 algorithm
946 b := match inNode
947 case FCore.N(data = FCore.CL(e = SCode.CLASS(classDef = SCode.CLASS_EXTENDS()))) then true;
948 else false;
949 end match;
950 end isClassExtends;
951
952 public function isComponent
953 input Node inNode;
954 output Boolean b;
955 algorithm
956 b := match inNode
957 case FCore.N(data = FCore.CO()) then true;
958 else false;
959 end match;
960 end isComponent;
961
962 public function isConstrainClass
963 input Node inNode;
964 output Boolean b;
965 algorithm
966 b := match inNode
967 case FCore.N(data = FCore.CC()) then true;
968 else false;
969 end match;
970 end isConstrainClass;
971
972 public function isCref
973 input Node inNode;
974 output Boolean b;
975 algorithm
976 b := match inNode
977 case FCore.N(data = FCore.CR()) then true;
978 else false;
979 end match;
980 end isCref;
981
982 public function isBasicType
983 input Node inNode;
984 output Boolean b;
985 algorithm
986 b := match inNode
987 case FCore.N(data = FCore.CL(kind = FCore.BASIC_TYPE())) then true;
988 else false;
989 end match;
990 end isBasicType;
991
992 public function isBuiltin
993 input Node inNode;
994 output Boolean b;
995 algorithm
996 b := match inNode
997 case FCore.N(data = FCore.CL(kind = FCore.BUILTIN())) then true;
998 case FCore.N(data = FCore.CO(kind = FCore.BUILTIN())) then true;
999 else false;
1000 end match;
1001 end isBuiltin;
1002
1003 public function isFunction
1004 input Node inNode;
1005 output Boolean b;
1006 algorithm
1007 b := match inNode
1008 local
1009 SCode.Element e;
1010 case FCore.N(data = FCore.CL(e = e)) guard SCodeUtil.isFunction(e) or SCodeUtil.isOperator(e)
1011 then true;
1012 else false;
1013 end match;
1014 end isFunction;
1015
1016 public function isRecord
1017 input Node inNode;
1018 output Boolean b = false;
1019 algorithm
1020 b := match inNode
1021 local
1022 SCode.Element e;
1023 case FCore.N(data = FCore.CL(e = e)) guard SCodeUtil.isRecord(e)
1024 then true;
1025 else false;
1026 end match;
1027 end isRecord;
1028
1029 public function isSection
1030 input Node inNode;
1031 output Boolean b;
1032 algorithm
1033 b := match inNode
1034 case FCore.N(data = FCore.AL()) then true;
1035 case FCore.N(data = FCore.EQ()) then true;
1036 else false;
1037 end match;
1038 end isSection;
1039
1040 public function isMod
1041 input Node inNode;
1042 output Boolean b;
1043 algorithm
1044 b := match inNode
1045 case FCore.N(data = FCore.MO()) then true;
1046 else false;
1047 end match;
1048 end isMod;
1049
1050 public function isModHolder
1051 input Node inNode;
1052 output Boolean b;
1053 algorithm
1054 b := match inNode
1055 local Name n;
1056 ✗ case FCore.N(name = n, data = FCore.MO()) then stringEq(n, modNodeName);
1057 else false;
1058 end match;
1059 end isModHolder;
1060
1061 public function isClone
1062 "a node is a clone if its parent is a version node"
1063 input Node inNode;
1064 output Boolean b;
1065 algorithm
1066 b := match inNode
1067 local FCore.WeakRef r;
1068 case FCore.N(parents = r::_)
1069 algorithm
1070 ✗ b := isRefVersion(MutableWeak.upgrade(r));
1071 then b;
1072 else false;
1073 end match;
1074 end isClone;
1075
1076 public function isVersion
1077 input Node inNode;
1078 output Boolean b;
1079 algorithm
1080 b := match inNode
1081 case FCore.N(data = FCore.VR()) then true;
1082 else false;
1083 end match;
1084 end isVersion;
1085
1086 public function isDims
1087 input Node inNode;
1088 output Boolean b;
1089 algorithm
1090 b := match inNode
1091 case FCore.N(data = FCore.DIMS()) then true;
1092 else false;
1093 end match;
1094 end isDims;
1095
1096 public function isIn
1097 input Node inNode;
1098 input FunctionRefIs inFunctionRefIs;
1099 output Boolean b;
1100 partial function FunctionRefIs
1101 input Ref inRef;
1102 output Boolean is;
1103 end FunctionRefIs;
1104 algorithm
1105 b := match inFunctionRefIs
1106 local
1107 Scope s;
1108 Boolean b1, b2;
1109
1110 case _
1111 algorithm
1112 ✗ s := originalScope(toRef(inNode));
1113 ✗ b1 := List.applyAndFold(s, boolOr, inFunctionRefIs, false);
1114 ✗ s := contextualScope(toRef(inNode));
1115 ✗ b2 := List.applyAndFold(s, boolOr, inFunctionRefIs, false);
1116 ✗ b := boolOr(b1, b2);
1117 then
1118 b;
1119
1120 end match;
1121 end isIn;
1122
1123 public function nonImplicitRefFromScope
1124 "@author: adrpo
1125 returns the first NON implicit
1126 reference from the given scope!"
1127 input Scope inScope;
1128 output Ref outRef;
1129 algorithm
1130 outRef := match inScope
1131 local
1132 Ref r;
1133 Scope rest;
1134
1135 ✗ case {} then fail();
1136
1137 case r::_ guard not isRefImplicitScope(r)
1138 then
1139 r;
1140
1141 case _::rest
1142 ✗ then
1143 nonImplicitRefFromScope(rest);
1144 end match;
1145 end nonImplicitRefFromScope;
1146
1147 public function namesUpToParentName
1148 "@author: adrpo
1149 returns the names of parents up
1150 to the given name. if the name
1151 is not found up to the top the
1152 empty list is returned.
1153 note that for A.B.C.D.E.F searching for B from F will give you
1154 {C, D, E, F}"
1155 input Ref inRef;
1156 input Name inName;
1157 output Names outNames;
1158 algorithm
1159 ✗ outNames := namesUpToParentName_dispatch(inRef, inName, {});
1160 end namesUpToParentName;
1161
1162 protected function namesUpToParentName_dispatch
1163 "@author: adrpo
1164 returns the names of parents up
1165 to the given name. if the name
1166 is not found up to the top the
1167 empty list is returned.
1168 note that for A.B.C.D.E.F searching for B from F will give you
1169 {C, D, E, F}"
1170 input Ref inRef;
1171 input Name inName;
1172 input Names acc;
1173 output Names outNames;
1174 algorithm
1175 outNames := match(inRef, inName)
1176 local
1177 Ref r;
1178 Name name;
1179
1180 // bah, error!
1181 case (r, _) guard isRefTop(r)
1182 then
1183 {};
1184
1185 // we're done, return
1186 case (r, _) guard stringEq(inName, refName(r))
1187 then
1188 acc;
1189
1190 // up the parent
1191 case (r, name)
1192 ✗ then
1193 namesUpToParentName_dispatch(refOriginalParent(r), name, refName(r) :: acc);
1194
1195 end match;
1196 end namesUpToParentName_dispatch;
1197
1198 public function getModifierTarget
1199 "@author: adrpo
1200 returns the target of the modifer"
1201 input Ref inRef;
1202 output Ref outRef;
1203 algorithm
1204 outRef := matchcontinue inRef
1205 local
1206 Ref r;
1207
1208 // bah, error!
1209 case r guard isRefTop(r)
1210 then
1211 fail();
1212
1213 // we're done, return
1214 case r guard isRefModHolder(r)
1215 algorithm
1216 // get his parent
1217 ✗ r := refOriginalParent(r);
1218 ✗ r::_ := refRefTargetScope(r);
1219 then
1220 r;
1221
1222 // up the parent
1223 ✗ else getModifierTarget(refOriginalParent(inRef));
1224
1225 end matchcontinue;
1226 end getModifierTarget;
1227
1228 public function originalScope
1229 "@author:
1230 return the scope from this ref to the top as a list of references.
1231 NOTE:
1232 the starting point reference is included and
1233 the scope is returned reversed, from leafs
1234 to top"
1235 input Ref inRef;
1236 output Scope outScope;
1237 algorithm
1238 3167495 outScope := originalScope_dispatch(inRef, {});
1239 end originalScope;
1240
1241 public function originalScope_dispatch
1242 "@author:
1243 return the scope from this ref to the top as a list of references.
1244 NOTE:
1245 the starting point reference is included and
1246 the scope is returned reversed, from leafs
1247 to top"
1248 input Ref inRef;
1249 input Scope inAcc;
1250 output Scope outScope;
1251 algorithm
1252 outScope := match inAcc
1253 local
1254 Scope acc;
1255 Ref r;
1256
1257 // top
1258 case acc guard isTop(fromRef(inRef))
1259 3167495 then
1260 listReverse(inRef::acc);
1261
1262 // not top
1263 case acc
1264 algorithm
1265 ✗ r := refOriginalParent(inRef);
1266 ✗ then
1267 originalScope_dispatch(r, inRef::acc);
1268
1269 end match;
1270 end originalScope_dispatch;
1271
1272 public function original
1273 "@author:
1274 return the original parent from the parents (the last one)"
1275 input Parents inParents;
1276 output Ref outOriginal;
1277 algorithm
1278 ✗ outOriginal := List.last(inParents);
1279 end original;
1280
1281 public function contextualScope
1282 "@author:
1283 return the scope from this ref to the top as a list of references.
1284 NOTE:
1285 the starting point reference is included and
1286 the scope is returned reversed, from leafs
1287 to top"
1288 input Ref inRef;
1289 output Scope outScope;
1290 algorithm
1291 ✗ outScope := contextualScope_dispatch(inRef, {});
1292 end contextualScope;
1293
1294 public function contextualScope_dispatch
1295 "@author:
1296 return the scope from this ref to the top as a list of references.
1297 NOTE:
1298 the starting point reference is included and
1299 the scope is returned reversed, from leafs
1300 to top"
1301 input Ref inRef;
1302 input Scope inAcc;
1303 output Scope outScope;
1304 algorithm
1305 outScope := match inAcc
1306 local
1307 Scope acc;
1308 Ref r;
1309
1310 // top
1311 case acc guard isTop(fromRef(inRef))
1312 ✗ then
1313 listReverse(inRef::acc);
1314
1315 // not top
1316 case acc
1317 algorithm
1318 ✗ r := contextualParent(fromRef(inRef));
1319 ✗ then
1320 contextualScope_dispatch(r, inRef::acc);
1321
1322 end match;
1323 end contextualScope_dispatch;
1324
1325 public function contextual
1326 "@author:
1327 return the contextual parent from the parents (the first one)"
1328 input Parents inParents;
1329 output Ref outContextual;
1330 algorithm
1331 ✗ outContextual := listHead(inParents);
1332 end contextual;
1333
1334 public function lookupRef
1335 "@author: adrpo
1336 lookup a reference based on given scope names
1337 NOTE:
1338 inRef/outRef could be in a totally different graph"
1339 input Ref inRef;
1340 input Scope inScope;
1341 output Ref outRef;
1342 algorithm
1343 outRef := match inScope
1344 local
1345 Scope s;
1346 Ref r;
1347
1348 // for the top, return itself
1349 case {_} then inRef;
1350
1351 case s
1352 algorithm
1353 // print("Searching for scope: " + toPathStr(fromRef(listHead(s))) + " in " + toPathStr(fromRef(inRef)) + "\n");
1354 // reverse and remove top
1355 ✗ _::s := listReverse(s);
1356 ✗ r := lookupRef_dispatch(inRef, s);
1357 then
1358 r;
1359 end match;
1360 end lookupRef;
1361
1362 public function lookupRef_dispatch
1363 "@author: adrpo
1364 lookup a reference based on given scope names
1365 NOTE:
1366 inRef/outRef could be in a totally different graph"
1367 input Ref inRef;
1368 input Scope inScope;
1369 output Ref outRef;
1370 algorithm
1371 outRef := match inScope
1372 local
1373 Ref r;
1374 Scope rest;
1375 Name n;
1376
1377 case {} then inRef;
1378
1379 case r::rest
1380 algorithm
1381 ✗ n := name(fromRef(r));
1382 // print("Lookup child: " + n + " in " + toPathStr(fromRef(inRef)) + "\n");
1383 ✗ r := child(inRef, n);
1384 ✗ r := lookupRef_dispatch(r, rest);
1385 then
1386 r;
1387
1388 end match;
1389 end lookupRef_dispatch;
1390
1391 public function filter
1392 "@author: adrpo
1393 filter the children of the given
1394 reference by the given filter"
1395 input Ref inRef;
1396 input Filter inFilter;
1397 output Refs filtered;
1398 partial function Filter
1399 input Ref inRef;
1400 output Boolean select;
1401 end Filter;
1402 protected
1403 Children c;
1404 algorithm
1405 3750 c := children(fromRef(inRef));
1406 3750 filtered := RefTree.fold(c, function filter_work(filter = inFilter), {});
1407 3750 filtered := listReverse(filtered);
1408 end filter;
1409
1410 protected function filter_work
1411 input Name name;
1412 input Ref ref;
1413 input Filter filter;
1414 input Refs accum;
1415 output Refs refs = accum;
1416
1417 partial function Filter
1418 input Ref inRef;
1419 output Boolean select;
1420 end Filter;
1421 algorithm
1422
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8770 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 8770 times.
8770 if filter(ref) then
1423 refs := ref :: refs;
1424 end if;
1425 end filter_work;
1426
1427 public function isRefExtends
1428 input Ref inRef;
1429 output Boolean b;
1430 algorithm
1431 ✗ b := isExtends(fromRef(inRef));
1432 end isRefExtends;
1433
1434 public function isRefDerived
1435 input Ref inRef;
1436 output Boolean b;
1437 algorithm
1438 ✗ b := isDerived(fromRef(inRef));
1439 end isRefDerived;
1440
1441 public function isRefComponent
1442 input Ref inRef;
1443 output Boolean b;
1444 algorithm
1445 8770 b := isComponent(fromRef(inRef));
1446 end isRefComponent;
1447
1448 public function isRefConstrainClass
1449 input Ref inRef;
1450 output Boolean b;
1451 algorithm
1452 ✗ b := isConstrainClass(fromRef(inRef));
1453 end isRefConstrainClass;
1454
1455 public function isRefClass
1456 input Ref inRef;
1457 output Boolean b;
1458 algorithm
1459 2804216 b := isClass(fromRef(inRef));
1460 end isRefClass;
1461
1462 public function isRefInstance
1463 input Ref inRef;
1464 output Boolean b;
1465 algorithm
1466 200908 b := isInstance(fromRef(inRef));
1467 end isRefInstance;
1468
1469 public function isRefRedeclare
1470 input Ref inRef;
1471 output Boolean b;
1472 algorithm
1473 ✗ b := isRedeclare(fromRef(inRef));
1474 end isRefRedeclare;
1475
1476 public function isRefClassExtends
1477 input Ref inRef;
1478 output Boolean b;
1479 algorithm
1480 ✗ b := isClassExtends(fromRef(inRef));
1481 end isRefClassExtends;
1482
1483 public function isRefCref
1484 input Ref inRef;
1485 output Boolean b;
1486 algorithm
1487 ✗ b := isCref(fromRef(inRef));
1488 end isRefCref;
1489
1490 public function isRefReference
1491 input Ref inRef;
1492 output Boolean b;
1493 algorithm
1494 ✗ b := isReference(fromRef(inRef));
1495 end isRefReference;
1496
1497 public function isRefUserDefined
1498 input Ref inRef;
1499 output Boolean b;
1500 algorithm
1501 ✗ b := isUserDefined(fromRef(inRef));
1502 end isRefUserDefined;
1503
1504 public function isRefTop
1505 input Ref inRef;
1506 output Boolean b;
1507 algorithm
1508 23390762 b := isTop(fromRef(inRef));
1509 end isRefTop;
1510
1511 public function isRefBasicType
1512 input Ref inRef;
1513 output Boolean b;
1514 algorithm
1515 40331 b := isBasicType(fromRef(inRef));
1516 end isRefBasicType;
1517
1518 public function isRefBuiltin
1519 input Ref inRef;
1520 output Boolean b;
1521 algorithm
1522 23325 b := isBuiltin(fromRef(inRef));
1523 end isRefBuiltin;
1524
1525 public function isRefFunction
1526 input Ref inRef;
1527 output Boolean b;
1528 algorithm
1529 ✗ b := isFunction(fromRef(inRef));
1530 end isRefFunction;
1531
1532 public function isRefRecord
1533 input Ref inRef;
1534 output Boolean b;
1535 algorithm
1536 ✗ b := isRecord(fromRef(inRef));
1537 end isRefRecord;
1538
1539 public function isRefSection
1540 input Ref inRef;
1541 output Boolean b;
1542 algorithm
1543 ✗ b := isSection(fromRef(inRef));
1544 end isRefSection;
1545
1546 public function isRefMod
1547 input Ref inRef;
1548 output Boolean b;
1549 algorithm
1550 ✗ b := isMod(fromRef(inRef));
1551 end isRefMod;
1552
1553 public function isRefModHolder
1554 input Ref inRef;
1555 output Boolean b;
1556 algorithm
1557 ✗ b := isModHolder(fromRef(inRef));
1558 end isRefModHolder;
1559
1560 public function isRefClone
1561 input Ref inRef;
1562 output Boolean b;
1563 algorithm
1564 ✗ b := isClone(fromRef(inRef));
1565 end isRefClone;
1566
1567 public function isRefVersion
1568 input Ref inRef;
1569 output Boolean b;
1570 algorithm
1571 ✗ b := isVersion(fromRef(inRef));
1572 end isRefVersion;
1573
1574 public function isRefDims
1575 input Ref inRef;
1576 output Boolean b;
1577 algorithm
1578 ✗ b := isDims(fromRef(inRef));
1579 end isRefDims;
1580
1581 public function isRefIn
1582 input Ref inRef;
1583 input FunctionRefIs inFunctionRefIs;
1584 output Boolean b;
1585 partial function FunctionRefIs
1586 input Ref inRef;
1587 output Boolean is;
1588 end FunctionRefIs;
1589 algorithm
1590 ✗ b := isIn(fromRef(inRef), inFunctionRefIs);
1591 end isRefIn;
1592
1593 public function dfs
1594 "@author: adrpo
1595 return all refs as given by
1596 depth first search"
1597 input Ref inRef;
1598 output Refs outRefs;
1599 algorithm
1600 outRefs := match inRef
1601 local
1602 Refs refs;
1603 Children c;
1604
1605 case _
1606 algorithm
1607 ✗ c := children(fromRef(inRef));
1608 ✗ refs := RefTree.listValues(c);
1609 ✗ refs := List.flatten(List.map(refs, dfs));
1610 refs := inRef::refs;
1611 then
1612 refs;
1613
1614 end match;
1615 end dfs;
1616
1617 public function apply1
1618 "@author: adrpo
1619 apply a function on all the subtree pointed by given ref.
1620 the order of application is dfs."
1621 input Ref inRef;
1622 input Apply inApply;
1623 input ExtraArg inExtraArg;
1624 output ExtraArg outExtraArg;
1625 partial function Apply
1626 input Name name;
1627 input Ref inRef;
1628 input ExtraArg inExtraArg;
1629 output ExtraArg outExtraArg;
1630 end Apply;
1631 replaceable type ExtraArg subtypeof Any;
1632 algorithm
1633 29048 outExtraArg := RefTree.fold(children(fromRef(inRef)), inApply, inExtraArg);
1634
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29048 times.
29048 outExtraArg := inApply(refName(inRef), inRef, outExtraArg);
1635 end apply1;
1636
1637 public function hasImports
1638 input Node inNode;
1639 output Boolean b;
1640 algorithm
1641 b := match inNode
1642 local list<Import> qi, uqi;
1643
1644 case _
1645 algorithm
1646 ✗ FCore.IMPORT_TABLE(_, qi, uqi) := importTable(fromRef(refImport(toRef(inNode))));
1647 ✗ b := boolOr(not listEmpty(qi), not listEmpty(uqi));
1648 then
1649 b;
1650
1651 else false;
1652 end match;
1653 end hasImports;
1654
1655 public function imports
1656 input Node inNode;
1657 output list<Import> outQualifiedImports;
1658 output list<Import> outUnQualifiedImports;
1659 algorithm
1660 (outQualifiedImports, outUnQualifiedImports) := match inNode
1661 local list<Import> qi, uqi;
1662 case _
1663 algorithm
1664 9778753 FCore.IMPORT_TABLE(_, qi, uqi) := importTable(fromRef(refImport(toRef(inNode))));
1665 then
1666 (qi, uqi);
1667 else ({}, {});
1668 end match;
1669 end imports;
1670
1671 public function derivedRef
1672 input Ref inRef;
1673 output Refs outRefs;
1674 algorithm
1675 outRefs := match inRef
1676 local case _ guard isRefDerived(inRef)
1677 ✗ then
1678 {child(inRef, refNodeName)};
1679
1680 else {};
1681
1682 end match;
1683 end derivedRef;
1684
1685
1686 public function extendsRefs
1687 input Ref inRef;
1688 output Refs outRefs;
1689 algorithm
1690 outRefs := match inRef
1691 local
1692 Refs refs, rd;
1693
1694 case _ guard isRefClass(inRef) // we have a class
1695 algorithm
1696 // get the derived ref
1697 ✗ rd := derivedRef(inRef);
1698 // get the extends
1699 ✗ refs := filter(inRef, isRefExtends);
1700 ✗ refs := List.flatten(List.map1(refs, filter, isRefReference));
1701 ✗ refs := listAppend(rd,refs);
1702 then
1703 refs;
1704
1705 else {};
1706
1707 end match;
1708 end extendsRefs;
1709
1710 public function cloneRef
1711 "@author: adrpo
1712 clone a node ref entire subtree
1713 the clone will have 2 parents
1714 {inParentRef, originalParentRef}"
1715 input Name inName;
1716 input Ref inRef;
1717 input Ref inParentRef;
1718 input Graph inGraph;
1719 output Graph outGraph;
1720 output Ref outRef;
1721 algorithm
1722 (outGraph, outRef) := match inGraph
1723 local
1724 Graph g;
1725 Ref r;
1726
1727 case g
1728 algorithm
1729 ✗ (g, r) := clone(fromRef(inRef), inParentRef, g);
1730 ✗ addChildRef(inParentRef, inName, r);
1731 ✗ then
1732 (g, r);
1733
1734 end match;
1735 end cloneRef;
1736
1737 public function clone
1738 "@author: adrpo
1739 clone a node entire subtree
1740 the clone will have 2 parents
1741 {inParentRef, originalParentRef}"
1742 input Node inNode;
1743 input Ref inParentRef;
1744 input Graph inGraph;
1745 output Graph outGraph;
1746 output Ref outRef;
1747 algorithm
1748 (outGraph, outRef) := match(inNode, inGraph)
1749 local
1750 Node n;
1751 Graph g;
1752 Ref r;
1753 Name name;
1754 Id id;
1755 FCore.WeakParents parents;
1756 Children children;
1757 Data data;
1758
1759 case (FCore.N(name, id, parents, children, data), g)
1760 algorithm
1761 // add parent
1762 ✗ parents := MutableWeak.downgrade(inParentRef)::parents;
1763 // create node clone
1764 ✗ (g, n as FCore.N(name, id, parents, _, data)) :=
1765 FGraph.node(g, name, list(MutableWeak.upgrade(p) for p in parents), data);
1766 // make the reference to the new node
1767 ✗ r := toRef(n);
1768 // clone children
1769 ✗ (g, children) := cloneTree(children, r, g);
1770 // set the children in the new node
1771 ✗ r := updateRef(r, FCore.N(name, id, parents, children, data));
1772 then
1773 (g, r);
1774
1775 end match;
1776 end clone;
1777
1778 public function cloneTree
1779 "@author: adrpo
1780 clone a node entire subtree
1781 the clone will have 2 parents
1782 {inParentRef, originalParentRef}"
1783 input Children inChildren;
1784 input Ref inParentRef;
1785 input Graph inGraph;
1786 output Graph outGraph;
1787 output Children outChildren;
1788 algorithm
1789 ✗ (outChildren, outGraph) :=
1790 RefTree.mapFold(inChildren, function cloneChild(parentRef = inParentRef), inGraph);
1791 end cloneTree;
1792
1793 protected function cloneChild
1794 input Name name;
1795 input Ref parentRef;
1796 input Ref inRef;
1797 input Graph inGraph;
1798 output Ref ref;
1799 output Graph graph;
1800 algorithm
1801 ✗ (graph, ref) := cloneRef(name, inRef, parentRef, inGraph);
1802 end cloneChild;
1803
1804 public function copyRef
1805 "@author: adrpo
1806 copy a node ref entire subtree
1807 this is like clone but the parents are kept as they are"
1808 input Ref inRef;
1809 input Graph inGraph;
1810 output Graph outGraph;
1811 output Ref outRef;
1812 algorithm
1813 (outGraph, outRef) := match inGraph
1814 local
1815 Graph g;
1816 Ref r;
1817
1818 case g
1819 algorithm
1820 // first copy the entire tree as it is
1821 // generating new array references
1822 29048 r := copyRefNoUpdate(inRef);
1823 // then update all array references
1824 // in the tree to their new places
1825 29048 (g, r) := updateRefs(r, g);
1826 then
1827 (g, r);
1828
1829 end match;
1830 end copyRef;
1831
1832 public function updateRefs
1833 "@author: adrpo
1834 update all parent and node data references in the graph"
1835 input Ref inRef;
1836 input Graph inGraph;
1837 output Graph outGraph;
1838 output Ref outRef;
1839 algorithm
1840 (outGraph, outRef) := match inGraph
1841 local
1842 Graph g;
1843 Ref r;
1844
1845 case g
1846 algorithm
1847 // for each node in the tree
1848 // update all refs from the node parents or node data
1849
1/2
✓ Branch 2 taken 29048 times.
✗ Branch 3 not taken.
29048 (r, g) := apply1(inRef, updateRefInGraph, (inRef, g));
1850 then
1851 (g, r);
1852
1853 end match;
1854 end updateRefs;
1855
1856 protected function updateRefInGraph
1857 input Name name;
1858 input Ref inRef;
1859 input tuple<Ref, Graph> inTopRefAndGraph;
1860 output tuple<Ref, Graph> outTopRefAndGraph;
1861 algorithm
1862 outTopRefAndGraph := match inTopRefAndGraph
1863 local
1864 Ref t;
1865 Graph g;
1866 Name n;
1867 Id i;
1868 FCore.WeakParents p;
1869 Children c;
1870 Data d;
1871
1872 case (t, g)
1873 algorithm
1874 // print("Updating references in node: " + toStr(fromRef(inRef)) + " / [" + toPathStr(fromRef(inRef)) + "]\n");
1875 3167495 FCore.N(n, i, p, c, d) := fromRef(inRef);
1876
4/4
✓ Branch 0 taken 3138447 times.
✓ Branch 1 taken 3167495 times.
✓ Branch 2 taken 3138447 times.
✓ Branch 3 taken 3167495 times.
6305942 p := list(MutableWeak.downgrade(lookupRefFromRef(t, MutableWeak.upgrade(w))) for w in p);
1877 3167495 d := updateRefInData(d, t);
1878 3167495 updateRef(inRef, FCore.N(n, i, p, c, d));
1879 3167495 then
1880 ((t, g));
1881
1882 end match;
1883 end updateRefInGraph;
1884
1885 public function lookupRefFromRef
1886 "@author: adrpo
1887 lookup a reference based on old reference in a different graph"
1888 input Ref inRef;
1889 input Ref inOldRef;
1890 output Ref outRef;
1891 algorithm
1892 outRef := match inOldRef
1893 local
1894 Ref r;
1895 Scope s;
1896 case _
1897 algorithm
1898 // get the original scope from the old ref
1899 3167495 s := originalScope(inOldRef);
1900 3167495 r := lookupRef(inRef, s);
1901 then
1902 r;
1903 end match;
1904 end lookupRefFromRef;
1905
1906 protected function updateRefInData
1907 "@author: adrpo
1908 update references in the node data currently just REF and CLONE hold other references.
1909 if you add more nodes in FCore that have references in them you need to update this function too!"
1910 input Data inData;
1911 input Ref inRef;
1912 output Data outData;
1913 algorithm
1914 outData := match inData
1915 local
1916 Scope sc;
1917
1918 case FCore.REF(sc)
1919 algorithm
1920 ✗ sc := List.map1r(sc, lookupRefFromRef, inRef);
1921 ✗ then
1922 FCore.REF(sc);
1923
1924 else inData;
1925
1926 end match;
1927 end updateRefInData;
1928
1929 public function copyRefNoUpdate
1930 "@author: adrpo
1931 copy a node ref entire subtree"
1932 input Ref inRef;
1933 output Ref outRef = copy(fromRef(inRef));
1934 end copyRefNoUpdate;
1935
1936 protected function copy
1937 "@author: adrpo
1938 copy a node entire subtree.
1939 this is like clone but the parents are kept as they are"
1940 input Node inNode;
1941 output Ref outRef;
1942 protected
1943 Node node = inNode;
1944 algorithm
1945 outRef := match node
1946 case FCore.N()
1947 algorithm
1948 // copy children
1949 5854262 node.children := RefTree.map(node.children, copyChild);
1950 5854262 then
1951 toRef(node);
1952 end match;
1953 end copy;
1954
1955 protected function copyChild
1956 input Name name;
1957 input Ref inRef;
1958 output Ref ref = copyRefNoUpdate(inRef);
1959 end copyChild;
1960
1961 public function getElement
1962 "@author: adrpo
1963 get element from the node data"
1964 input Node inNode;
1965 output SCode.Element outElement;
1966 algorithm
1967 outElement := match inNode
1968 local
1969 SCode.Element e;
1970 case FCore.N(data = FCore.CL(e = e)) then e;
1971 case FCore.N(data = FCore.CO(e = e)) then e;
1972 end match;
1973 end getElement;
1974
1975 public function getElementFromRef
1976 "@author: adrpo
1977 get element from the ref"
1978 input Ref inRef;
1979 output SCode.Element outElement;
1980 algorithm
1981 ✗ outElement := getElement(fromRef(inRef));
1982 end getElementFromRef;
1983
1984 public function isImplicitRefName
1985 "returns true if the node ref is a for-loop scope or a valueblock scope.
1986 This is indicated by the name of the frame."
1987 input Ref r;
1988 output Boolean b;
1989 algorithm
1990 b := match r
1991
1992 case _ guard not isRefTop(r)
1993 4116674 then
1994 FCore.isImplicitScope(refName(r));
1995
1996 else false;
1997
1998 end match;
1999 end isImplicitRefName;
2000
2001 public function refInstVar
2002 "@author: adrpo
2003 get the DAE.Var from the child node named itNodeName of this reference"
2004 input Ref inRef;
2005 output DAE.Var v;
2006 protected
2007 Ref r;
2008 algorithm
2009 4555633 r := refInstance(inRef);
2010
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3284553 times.
3284553 FCore.IT(i = v) := refData(r);
2011 end refInstVar;
2012
2013 public function refInstance
2014 input Ref inRef;
2015 output Ref r;
2016 algorithm
2017 6364469 r := child(inRef, itNodeName);
2018 end refInstance;
2019
2020 public function isRefRefUnresolved
2021 input Ref inRef;
2022 output Boolean b;
2023 algorithm
2024 b := matchcontinue inRef
2025
2026 case _
2027 algorithm
2028 ✗ refRef(inRef); // node exists
2029 ✗ b := listEmpty(refRefTargetScope(inRef)); // with non empty scope
2030 then
2031 b;
2032
2033 else true;
2034
2035 end matchcontinue;
2036 end isRefRefUnresolved;
2037
2038 public function isRefRefResolved
2039 input Ref inRef;
2040 output Boolean b;
2041 algorithm
2042 ✗ b := not isRefRefUnresolved(inRef);
2043 end isRefRefResolved;
2044
2045 public function refRef
2046 input Ref inRef;
2047 output Ref r;
2048 algorithm
2049 5113917 r := child(inRef, refNodeName);
2050 end refRef;
2051
2052 public function refRefTargetScope
2053 input Ref inRef;
2054 output Scope sc;
2055 protected
2056 Ref r;
2057 algorithm
2058 3284366 r := refRef(inRef);
2059 3284366 sc := targetScope(fromRef(r));
2060 end refRefTargetScope;
2061
2062 public function refImport
2063 input Ref inRef;
2064 output Ref r;
2065 algorithm
2066 9778753 r := child(inRef, imNodeName);
2067 end refImport;
2068
2069 public function importTable
2070 "returns the import table from a IM node"
2071 input Node inNode;
2072 output ImportTable it;
2073 algorithm
2074 it := match inNode
2075 case FCore.N(data = FCore.IM(i = it)) then it;
2076 end match;
2077 end importTable;
2078
2079 public function mkExtendsName
2080 input Absyn.Path inPath;
2081 output Name outName;
2082 algorithm
2083 ✗ outName := extendsPrefix + AbsynUtil.pathString(inPath);
2084 end mkExtendsName;
2085
2086 public function scopeHashWork
2087 input Scope scope;
2088 input output Integer hash;
2089 algorithm
2090 ✗ for r in scope loop
2091 ✗ hash := 31*hash + stringHashDjb2(FNode.refName(r));
2092 end for;
2093 end scopeHashWork;
2094
2095 public function scopePathEq
2096 input Scope scope1,scope2;
2097 output Boolean eq;
2098 algorithm
2099 ✗ eq := min(FNode.refName(r1)==FNode.refName(r2) threaded for r1 in scope1, r2 in scope2);
2100 end scopePathEq;
2101
2102 annotation(__OpenModelica_Interface="frontend");
2103 end FNode;
2104