Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 74.6% 185 / 0 / 248
Functions: -% 0 / 1 / 1
Branches: 64.0% 110 / 0 / 172

OMCompiler/Compiler/FFrontEnd/FGraph.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 FGraph
37 " file: FGraph.mo
38 package: FGraph
39 description: Graph of program
40
41
42 "
43
44 // public imports
45 public
46 import Absyn;
47 import AbsynUtil;
48 import SCode;
49 import DAE;
50 import ClassInf;
51 import FCore;
52 import FNode;
53 import InnerOuter;
54 import FCore.RefTree;
55
56 protected
57 import List;
58 import Util;
59 import System;
60 import Debug;
61 import FGraphBuildEnv;
62 import Global;
63 import Config;
64 import PrefixUtil;
65 import Flags;
66 import SCodeDump;
67 import MetaModelica.Dangerous;
68 import Mod;
69 import Error;
70 import ComponentReference;
71 import Types;
72 import SCodeUtil;
73
74 public
75 type Name = FCore.Name;
76 type Id = FCore.Id;
77 type Seq = FCore.Seq;
78 type Next = FCore.Next;
79 type Node = FCore.Node;
80 type Data = FCore.Data;
81 type Kind = FCore.Kind;
82 type Ref = FCore.Ref;
83 type Refs = FCore.Refs;
84 type Children = FCore.Children;
85 type Parents = FCore.Parents;
86 type Scope = FCore.Scope;
87 type Top = FCore.Top;
88 type Graph = FCore.Graph;
89 type Extra = FCore.Extra;
90 type Visited = FCore.Visited;
91 type Status = FCore.Status;
92
93 constant FCore.Graph emptyGraph = FCore.EG("empty");
94
95 public function top
96 "get the top node ref from the graph"
97 input Graph inGraph;
98 output Ref outRef;
99 algorithm
100 outRef := match inGraph
101 49812 case FCore.G() then inGraph.top.node;
102 end match;
103 end top;
104
105 public function extra
106 "get the extra from the graph"
107 input Graph inGraph;
108 output Extra outExtra;
109 algorithm
110 outExtra := match inGraph
111 ✗ case FCore.G() then inGraph.top.extra;
112 end match;
113 end extra;
114
115 public function currentScope
116 "get the top current scope from the graph"
117 input Graph inGraph;
118 output Scope outScope;
119 algorithm
120 outScope := match inGraph
121 case FCore.G(scope = outScope) then outScope;
122 case FCore.EG(_) then {};
123 end match;
124 end currentScope;
125
126 public function lastScopeRef
127 "get the last ref from the current scope the graph"
128 input Graph inGraph;
129 output Ref outRef;
130 algorithm
131 37999851 outRef := listHead(currentScope(inGraph));
132 end lastScopeRef;
133
134 public function setLastScopeRef
135 input Ref inRef;
136 input Graph inGraph;
137 output Graph outGraph = inGraph;
138 algorithm
139 outGraph := match outGraph
140 case FCore.G()
141 algorithm
142 ✗ outGraph.scope := inRef :: listRest(outGraph.scope);
143 then
144 outGraph;
145
146 else outGraph;
147 end match;
148 end setLastScopeRef;
149
150 public function stripLastScopeRef
151 "remove the last ref from the current scope the graph"
152 input Graph inGraph;
153 output Graph outGraph;
154 output Ref outRef;
155 protected
156 Top t;
157 Scope s;
158 algorithm
159
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 5792092 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5792092 times.
5792092 FCore.G(t, outRef::s) := inGraph;
160 // strip the last scope ref
161 5792092 outGraph := FCore.G(t, s);
162 end stripLastScopeRef;
163
164 public function topScope
165 "remove all the scopes, leave just the top one from the graph scopes"
166 input Graph inGraph;
167 output Graph outGraph;
168 algorithm
169 // leave only the top scope
170 outGraph := match inGraph
171 466614 case FCore.G() then FCore.G(inGraph.top, {inGraph.top.node});
172 end match;
173 end topScope;
174
175 public function empty
176 "make an empty graph"
177 output Graph outGraph;
178 algorithm
179 outGraph := emptyGraph;
180 end empty;
181
182 public function new
183 "make a new graph"
184 input Name inGraphName;
185 input Absyn.Path inPath;
186 output Graph outGraph;
187 protected
188 Node n;
189 Scope s;
190 Ref nr;
191 Id id;
192 Top top;
193 algorithm
194 3423 id := System.tmpTickIndex(Global.fgraph_nextId);
195 3423 n := FNode.new(FNode.topNodeName, id, {}, FCore.TOP());
196 3423 nr := FNode.toRef(n);
197 s := {nr};
198 3423 top := FCore.GTOP(inGraphName,nr,FCore.EXTRA(inPath));
199 3423 outGraph := FCore.G(top,s);
200 end new;
201
202 public function node
203 "make a new node in the graph"
204 input Graph inGraph;
205 input Name inName;
206 input Parents inParents;
207 input Data inData;
208 output Graph outGraph;
209 output Node outNode;
210 algorithm
211 (outGraph, outNode) := match inGraph
212 local
213 Integer i;
214 Graph g;
215 Node n;
216
217 case g
218 algorithm
219 12301446 i := System.tmpTickIndex(Global.fgraph_nextId);
220 12301446 n := FNode.new(inName, i, inParents, inData);
221 // uncomment this if unique node id's are not unique!
222 /*
223 b = (id == i);
224 Debug.bcall1(true, print, "Next: " + intString(id) + " <-> " + intString(i) + " node: " + FNode.toStr(n) + "\n");
225 // true = b;
226 */
227 then
228 (g, n);
229
230 end match;
231 end node;
232
233 public function clone
234 "@author: adrpo
235 clone a graph. everything is copied except visited information and refs (which will be new)"
236 input Graph inGraph;
237 output Graph outGraph;
238 algorithm
239 outGraph := match inGraph
240 local
241 Graph g;
242 Top t;
243 Ref nt;
244 Scope s;
245 case FCore.G(t, s)
246 algorithm
247 // make a new top
248 29048 nt := FNode.toRef(FNode.fromRef(t.node));
249 // make new graph
250 // g = FCore.G(t, s);
251 // deep copy the top, clone the entire subtree, update references
252 29048 (g, nt) := FNode.copyRef(nt, inGraph);
253 // update scope references
254 29048 s := List.map1r(s, FNode.lookupRefFromRef, nt);
255 29048 t := FCore.GTOP(t.name, nt, t.extra);
256 29048 g := FCore.G(t, s);
257 then g;
258
259 end match;
260 end clone;
261
262 public function updateComp
263 "This function updates a component already added to the graph, but
264 that prior to the update did not have any binding. I.e this function is
265 called in the second stage of instantiation with declare before use."
266 input Graph inGraph;
267 input DAE.Var inVar;
268 input FCore.Status instStatus;
269 input Graph inTargetGraph;
270 output Graph outGraph;
271 algorithm
272 outGraph := matchcontinue (inGraph, inVar)
273 local
274 Ref pr, r;
275 Name n;
276 Id id;
277 FCore.WeakParents p;
278 Children c;
279 SCode.Element e;
280 DAE.Var v;
281 DAE.Mod m;
282 Kind k;
283 Graph g;
284
285 // update in the current frame
286 case (g, v as DAE.TYPES_VAR(name = n))
287 algorithm
288 709602 pr := lastScopeRef(g);
289 709602 r := FNode.child(pr, n);
290
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 616965 times.
616965 FCore.N(n, id, p, c, FCore.CO(e, m, k, _)) := FNode.fromRef(r);
291 616965 r := FNode.updateRef(r, FCore.N(n, id, p, c, FCore.CO(e, m, k, instStatus)));
292 // update the target scope
293 616965 r := updateSourceTargetScope(r, currentScope(inTargetGraph));
294 616965 r := updateInstance(r, v);
295 then
296 g;
297
298 // if not found update in the parent frame
299 case (g, v)
300 algorithm
301 92637 pr := lastScopeRef(g);
302
1/2
✓ Branch 1 taken 92637 times.
✗ Branch 2 not taken.
92637 true := FNode.isImplicitRefName(pr);
303 ✗ (g, _) := stripLastScopeRef(g);
304 ✗ g := updateComp(g, v, instStatus, inTargetGraph);
305 then
306 g;
307
308 // do NOT fail!
309 else inGraph;
310
311 end matchcontinue;
312 end updateComp;
313
314 public function updateSourceTargetScope
315 "update the class scope in the source"
316 input Ref inRef;
317 input Scope inTargetScope;
318 output Ref outRef;
319 algorithm
320 outRef := matchcontinue inRef
321 local
322 Ref r;
323
324 // update the target scope of the node, hopefully existing
325 case r
326 algorithm
327 1829551 r := FNode.refRef(r);
328 1829551 r := FNode.updateRef(r, FNode.setData(FNode.fromRef(r), FCore.REF(inTargetScope)));
329 then
330 inRef;
331
332 // create one and update it
333 case r
334 algorithm
335 ✗ Error.addCompilerWarning("FNode.updateSourceTargetScope: node does not yet have a reference child: " + FNode.toPathStr(FNode.fromRef(r)) +
336 " target scope: " + FNode.scopeStr(inTargetScope) + "\n");
337 then
338 inRef;
339
340 end matchcontinue;
341 end updateSourceTargetScope;
342
343 public function updateInstance
344 "update the class scope in the source"
345 input Ref inRef;
346 input DAE.Var inVar;
347 output Ref outRef;
348 algorithm
349 outRef := matchcontinue inRef
350 local
351 Ref r;
352
353 // update the instance node
354 case r
355 algorithm
356 1808836 r := FNode.refInstance(r);
357 1808836 r := FNode.updateRef(r, FNode.setData(FNode.fromRef(r), FCore.IT(inVar)));
358 then
359 inRef;
360
361 else
362 algorithm
363 ✗ Error.addCompilerError("FGraph.updateInstance failed for node: " + FNode.toPathStr(FNode.fromRef(inRef)) + " variable:" + TypesDump.printVarStr(inVar));
364 ✗ then
365 fail();
366
367 end matchcontinue;
368 end updateInstance;
369
370 protected function updateVarAndMod
371 "update the component data"
372 input Graph inGraph;
373 input DAE.Var inVar;
374 input DAE.Mod inMod;
375 input FCore.Status instStatus;
376 input Graph inTargetGraph;
377 output Graph outGraph;
378 algorithm
379 outGraph := matchcontinue (inGraph, inVar)
380 local
381 Ref pr, r;
382 Name n;
383 Id id;
384 FCore.WeakParents p;
385 Children c;
386 SCode.Element e;
387 DAE.Var v;
388 Kind k;
389 Graph g;
390
391 // update in the current frame
392 case (g, v as DAE.TYPES_VAR(name = n))
393 algorithm
394 1191871 pr := lastScopeRef(g);
395 1191871 r := FNode.child(pr, n);
396
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1191871 times.
1191871 FCore.N(n, id, p, c, FCore.CO(e, _, k, _)) := FNode.fromRef(r);
397 1191871 r := FNode.updateRef(r, FCore.N(n, id, p, c, FCore.CO(e, inMod, k, instStatus)));
398 1191871 r := updateSourceTargetScope(r, currentScope(inTargetGraph));
399 1191871 r := updateInstance(r, v);
400 then
401 g;
402
403 // if not found update in the parent frame
404 case (g, v)
405 algorithm
406 ✗ pr := lastScopeRef(g);
407 ✗ true := FNode.isImplicitRefName(pr);
408 ✗ (g, _) := stripLastScopeRef(g);
409 ✗ g := updateVarAndMod(g, v, inMod, instStatus, inTargetGraph);
410 then
411 g;
412
413 // do NOT fail!
414 else inGraph;
415
416 end matchcontinue;
417 end updateVarAndMod;
418
419 public function updateClass
420 "This function updates a class element in the graph"
421 input Graph inGraph;
422 input SCode.Element inElement;
423 input DAE.Prefix inPrefix;
424 input DAE.Mod inMod;
425 input FCore.Status instStatus;
426 input Graph inTargetGraph;
427 output Graph outGraph;
428 algorithm
429 outGraph := matchcontinue (inGraph, inElement)
430 local
431 Ref pr, r;
432 Name n;
433 Id id;
434 FCore.WeakParents p;
435 Children c;
436 SCode.Element e;
437 Kind k;
438 Graph g;
439
440 // update in the current frame
441 case (g, e as SCode.CLASS(name = n))
442 algorithm
443 8304 pr := lastScopeRef(g);
444 8304 r := FNode.child(pr, n);
445
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8304 times.
8304 FCore.N(n, id, p, c, FCore.CL(_, _, _, k, _)) := FNode.fromRef(r);
446 8304 r := FNode.updateRef(r, FCore.N(n, id, p, c, FCore.CL(e, inPrefix, inMod, k, instStatus)));
447 // r = updateSourceTargetScope(r, currentScope(inTargetGraph));
448 then
449 g;
450
451 // if not found update in the parent frame
452 case (g, e)
453 algorithm
454 ✗ pr := lastScopeRef(g);
455 ✗ true := FNode.isImplicitRefName(pr);
456 ✗ (g, _) := stripLastScopeRef(g);
457 ✗ g := updateClass(g, e, inPrefix, inMod, instStatus, inTargetGraph);
458 then
459 g;
460 end matchcontinue;
461 end updateClass;
462
463 public function updateClassElement
464 "This function updates a class element in the given parent ref"
465 input Ref inRef;
466 input SCode.Element inElement;
467 input DAE.Prefix inPrefix;
468 input DAE.Mod inMod;
469 input FCore.Status instStatus;
470 input Graph inTargetGraph;
471 output Ref outRef;
472 algorithm
473 outRef := match (inRef, inElement)
474 local
475 Ref r;
476 Name n;
477 Id id;
478 FCore.WeakParents p;
479 Children c;
480 SCode.Element e;
481 Kind k;
482
483 case (r, e as SCode.CLASS(name = n))
484 algorithm
485
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20715 times.
20715 FCore.N(_, id, p, c, FCore.CL(_, _, _, k, _)) := FNode.fromRef(r);
486 20715 r := FNode.updateRef(r, FCore.N(n, id, p, c, FCore.CL(e, inPrefix, inMod, k, instStatus)));
487 then
488 r;
489
490 end match;
491 end updateClassElement;
492
493 public function addForIterator
494 "Adds a for loop iterator to the graph."
495 input Graph inGraph;
496 input String name;
497 input DAE.Type ty;
498 input DAE.Binding binding;
499 input SCode.Variability variability;
500 input Option<DAE.Const> constOfForIteratorRange;
501 output Graph outGraph;
502 algorithm
503 outGraph := match inGraph
504 local
505 Graph g;
506 Ref r;
507 SCode.Element c;
508 DAE.Var v;
509
510 case g
511 algorithm
512 7544 c := SCode.COMPONENT(
513 name,
514 SCode.defaultPrefixes,
515 SCode.ATTR({}, SCode.POTENTIAL(), SCode.NON_PARALLEL(), SCode.CONST(), Absyn.BIDIR(), Absyn.NONFIELD()),
516 Absyn.TPATH(Absyn.IDENT(""), NONE()), SCode.NOMOD(),
517 SCode.noComment, NONE(), Absyn.dummyInfo);
518 7544 v := DAE.TYPES_VAR(
519 name,
520 DAE.ATTR(DAE.NON_CONNECTOR(), SCode.NON_PARALLEL(), variability, Absyn.BIDIR(), Absyn.NOT_INNER_OUTER(), SCode.PUBLIC()),
521 ty,
522 binding,
523 false,
524 constOfForIteratorRange);
525 7544 r := lastScopeRef(g);
526 7544 g := FGraphBuildEnv.mkCompNode(c, r, FCore.BUILTIN(), g);
527 // update the var too!
528 7544 g := updateVarAndMod(g, v, DAE.NOMOD(), FCore.VAR_UNTYPED(), empty());
529 then
530 g;
531
532 end match;
533 end addForIterator;
534
535 public function printGraphPathStr "Retrive the graph current scope path as a string"
536 input Graph inGraph;
537 output String outString;
538 algorithm
539 outString := matchcontinue inGraph
540 local
541 String str;
542 Scope s;
543
544 case FCore.G(scope = s as _::_::_)
545 algorithm
546 // remove top
547
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 188184 times.
188184 _::s := listReverse(s);
548 188184 str := stringDelimitList(List.map(s, FNode.refName), ".");
549 then
550 str;
551
552 else "<global scope>";
553
554 end matchcontinue;
555 end printGraphPathStr;
556
557 public function openNewScope
558 "Opening a new scope in the graph means adding a new node in the current scope."
559 input Graph inGraph;
560 input SCode.Encapsulated encapsulatedPrefix;
561 input Option<Name> inName;
562 input Option<FCore.ScopeType> inScopeType;
563 output Graph outGraph;
564 algorithm
565 outGraph := matchcontinue(inGraph, inName)
566 local
567 Graph g;
568 Name n;
569 Node no;
570 Ref r, p;
571
572 // else open a new scope!
573 case (g, SOME(n))
574 algorithm
575 5164 p := lastScopeRef(g);
576 5164 (g, no) := node(g, n, {p}, FCore.ND(inScopeType));
577 5164 r := FNode.toRef(no);
578 // FNode.addChildRef(p, n, r);
579 5164 g := pushScopeRef(g, r);
580 then
581 g;
582
583 else
584 algorithm
585 ✗ Error.addCompilerError("FGraph.openNewScope: failed to open new scope in scope: " + getGraphNameStr(inGraph) + " name: " + Util.getOptionOrDefault(inName, "") + "\n");
586 ✗ then
587 fail();
588
589 end matchcontinue;
590 end openNewScope;
591
592 public function openScope
593 "Opening a new scope in the graph means adding a new node in the current scope."
594 input Graph inGraph;
595 input SCode.Encapsulated encapsulatedPrefix;
596 input Name inName;
597 input Option<FCore.ScopeType> inScopeType;
598 output Graph outGraph;
599 protected
600 Ref p;
601 algorithm
602 2689483 p := lastScopeRef(inGraph);
603 outGraph := matchcontinue(inGraph, inName)
604 local
605 Graph g;
606 Name n;
607 Node no;
608 Ref r;
609
610 // see if we have it as a class instance
611 case (g, n)
612 algorithm
613 2689483 r := FNode.child(p, n);
614
4/4
✓ Branch 1 taken 1781 times.
✓ Branch 2 taken 2450044 times.
✓ Branch 3 taken 2424230 times.
✓ Branch 4 taken 25814 times.
2451825 FCore.CL(status = FCore.CLS_INSTANCE(_)) := FNode.refData(r);
615 25814 FNode.addChildRef(p, n, r);
616 25814 g := pushScopeRef(g, r);
617 then
618 g;
619
620 // see if we have a child with the same name!
621 case (g, n)
622 algorithm
623 2663669 r := FNode.child(p, n);
624 2426011 r := FNode.copyRefNoUpdate(r);
625 // FNode.addChildRef(p, n, r);
626 2426011 g := pushScopeRef(g, r);
627 then
628 g;
629
630 // else open a new scope!
631 case (g, n)
632 algorithm
633 237658 (g, no) := node(g, n, {p}, FCore.ND(inScopeType));
634 237658 r := FNode.toRef(no);
635 // FNode.addChildRef(p, n, r);
636 237658 g := pushScopeRef(g, r);
637 then
638 g;
639
640 else
641 algorithm
642 ✗ Error.addCompilerError("FGraph.openScope: failed to open new scope in scope: " + getGraphNameStr(inGraph) + " name: " + inName + "\n");
643 ✗ then
644 fail();
645
646 end matchcontinue;
647 end openScope;
648
649 public function inForLoopScope "returns true if environment has a frame that is a for loop"
650 input Graph inGraph;
651 output Boolean res;
652 algorithm
653 res := matchcontinue inGraph
654 local
655 String name;
656
657 case _
658 algorithm
659 1797 name := FNode.refName(listHead(currentScope(inGraph)));
660
4/4
✓ Branch 0 taken 823 times.
✓ Branch 1 taken 974 times.
✓ Branch 3 taken 771 times.
✓ Branch 4 taken 52 times.
1797 true := stringEq(name, FCore.forScopeName);
661 then true;
662
663 else false;
664
665 end matchcontinue;
666 end inForLoopScope;
667
668 public function inForOrParforIterLoopScope "returns true if environment has a frame that is a for iterator 'loop'"
669 input Graph inGraph;
670 output Boolean res;
671 algorithm
672 res := matchcontinue inGraph
673 local String name;
674
675 case _
676 algorithm
677 82316 name := FNode.refName(listHead(currentScope(inGraph)));
678
7/8
✓ Branch 0 taken 1344 times.
✓ Branch 1 taken 80972 times.
✓ Branch 3 taken 135 times.
✓ Branch 4 taken 1209 times.
✓ Branch 5 taken 26 times.
✓ Branch 6 taken 81081 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 26 times.
82316 true := stringEq(name, FCore.forIterScopeName) or stringEq(name, FCore.parForIterScopeName);
679 then true;
680
681 else false;
682 end matchcontinue;
683 end inForOrParforIterLoopScope;
684
685 public function getScopePath
686 "get the current scope as a path from the graph"
687 input Graph inGraph;
688 output Option<Absyn.Path> outPath;
689 algorithm
690 outPath := matchcontinue inGraph
691 local
692 Absyn.Path p;
693 Ref r;
694
695 case _
696 algorithm
697
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 3168060 times.
✓ Branch 3 taken 2586115 times.
✓ Branch 4 taken 581945 times.
3168060 {r} := currentScope(inGraph);
698
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 581945 times.
581945 true := FNode.isRefTop(r);
699 then
700 NONE();
701
702 case _
703 algorithm
704 2586115 p := getGraphName(inGraph);
705 then
706 SOME(p);
707
708 end matchcontinue;
709 end getScopePath;
710
711 public function getGraphNameStr
712 "Returns the FQ name of the environment."
713 input Graph inGraph;
714 output String outString;
715 algorithm
716 outString := matchcontinue inGraph
717 case _
718 114335 then
719 AbsynUtil.pathString(getGraphName(inGraph));
720 else ".";
721 end matchcontinue;
722 end getGraphNameStr;
723
724 public function getGraphName
725 "Returns the FQ name of the environment."
726 input Graph inGraph;
727 output Absyn.Path outPath;
728 protected
729 Absyn.Path p;
730 Scope s;
731 Ref r;
732 algorithm
733
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 7483349 times.
7483351 r::s := currentScope(inGraph);
734 7483349 p := AbsynUtil.makeIdentPathFromString(FNode.refName(r));
735
2/2
✓ Branch 0 taken 19416705 times.
✓ Branch 1 taken 7483349 times.
26900054 for r in s loop
736 19416705 p := Absyn.QUALIFIED(FNode.refName(r), p);
737 end for;
738
2/2
✓ Branch 0 taken 24221 times.
✓ Branch 1 taken 7459128 times.
7483349 Absyn.QUALIFIED(_, outPath) := p;
739 end getGraphName;
740
741 public function getGraphNameNoImplicitScopes
742 "Returns the FQ name of the environment."
743 input Graph inGraph;
744 output Absyn.Path outPath;
745 protected
746 Scope s;
747 algorithm
748
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
5 _::s := listReverse(currentScope(inGraph));
749
10/10
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 5 times.
✓ Branch 6 taken 8 times.
✓ Branch 7 taken 10 times.
✓ Branch 8 taken 18 times.
✓ Branch 9 taken 5 times.
✓ Branch 10 taken 10 times.
✓ Branch 11 taken 5 times.
41 outPath := AbsynUtil.stringListPath(list(str for str guard stringGet(str,1)<>36 /* "$" */ in list(FNode.refName(n) for n in s)));
750 end getGraphNameNoImplicitScopes;
751
752 public function pushScopeRef
753 "@author:adrpo
754 push the given ref as first element in the graph scope list"
755 input output Graph graph;
756 input Ref inRef;
757 algorithm
758 () := match graph
759 case FCore.G()
760 algorithm
761 7081500 graph.scope := inRef::graph.scope;
762 then ();
763 end match;
764 end pushScopeRef;
765
766 public function pushScope
767 "@author:adrpo
768 put the given scope in the graph scope at the begining (listAppend(inScope, currentScope(graph)))"
769 input output Graph graph;
770 input Scope inScope;
771 algorithm
772 () := match graph
773 case FCore.G()
774 algorithm
775 2794 graph.scope := listAppend(inScope, graph.scope);
776 then ();
777 end match;
778 end pushScope;
779
780 public function setScope
781 "@author:adrpo
782 replaces the graph scope with the given scope"
783 input output Graph graph;
784 input Scope inScope;
785 algorithm
786 () := match graph
787 case FCore.G()
788 algorithm
789 8210222 graph.scope := inScope;
790 then ();
791 end match;
792 end setScope;
793
794 public function restrictionToScopeType
795 input SCode.Restriction inRestriction;
796 output Option<FCore.ScopeType> outType;
797 algorithm
798 outType := match inRestriction
799 case SCode.R_FUNCTION(SCode.FR_PARALLEL_FUNCTION()) then SOME(FCore.PARALLEL_SCOPE());
800 case SCode.R_FUNCTION(SCode.FR_KERNEL_FUNCTION()) then SOME(FCore.PARALLEL_SCOPE());
801 case SCode.R_FUNCTION(_) then SOME(FCore.FUNCTION_SCOPE());
802 else SOME(FCore.CLASS_SCOPE());
803 end match;
804 end restrictionToScopeType;
805
806 public function scopeTypeToRestriction
807 "Converts a ScopeType to a Restriction. Restriction is much more expressive
808 than ScopeType, so the returned Restriction is more of a rough indication of
809 what the original Restriction was."
810 input FCore.ScopeType inScopeType;
811 output SCode.Restriction outRestriction;
812 algorithm
813 outRestriction := match inScopeType
814 case FCore.PARALLEL_SCOPE() then SCode.R_FUNCTION(SCode.FR_PARALLEL_FUNCTION());
815 case FCore.FUNCTION_SCOPE() then SCode.R_FUNCTION(SCode.FR_NORMAL_FUNCTION(Absyn.FunctionPurity.NO_PURITY()));
816 else SCode.R_CLASS();
817 end match;
818 end scopeTypeToRestriction;
819
820 public function isTopScope "Returns true if we are in the top-most scope"
821 input Graph graph;
822 output Boolean isTop;
823 algorithm
824 isTop := matchcontinue graph
825
826 case _
827 algorithm
828
2/2
✓ Branch 2 taken 60005 times.
✓ Branch 3 taken 469 times.
60474 true := FNode.isRefTop(lastScopeRef(graph));
829 then
830 true;
831
832 else false;
833
834 end matchcontinue;
835 end isTopScope;
836
837 public function crefStripGraphScopePrefix
838 "Removes the entire environment prefix from the given component reference, or
839 returns the unchanged reference. This is done because models might import
840 local packages, for example:
841
842 package P
843 import myP = InsideP;
844
845 package InsideP
846 function f end f;
847 end InsideP;
848
849 constant c = InsideP.f();
850 end P;
851
852 package P2
853 extends P;
854 end P2;
855
856 When P2 is instantiated all elements from P will be brought into P2's scope
857 due to the extends. The binding of c will still point to P.InsideP.f though, so
858 the lookup will try to instantiate P which might fail if P is a partial
859 package or for other reasons. This is really a bug in Lookup (it shouldn't
860 need to instantiate the whole package just to find a function), but to work
861 around this problem for now this function will remove the environment prefix
862 when InsideP.f is looked up in P, so that it resolves to InsideP.f and not
863 P.InsideP.f. This allows P2 to find it in the local scope instead, since the
864 InsideP package has been inherited from P."
865 input Absyn.ComponentRef inCref;
866 input Graph inEnv;
867 input Boolean stripPartial;
868 output Absyn.ComponentRef outCref;
869 algorithm
870 outCref := matchcontinue stripPartial
871 local
872 Absyn.Path env_path;
873 Absyn.ComponentRef cref1, cref2;
874
875 case _
876 algorithm
877
1/2
✓ Branch 1 taken 451394 times.
✗ Branch 2 not taken.
451394 false := Flags.isSet(Flags.STRIP_PREFIX);
878 then
879 inCref;
880
881 case _
882 algorithm
883
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 451394 times.
✓ Branch 3 taken 5591 times.
✓ Branch 4 taken 445803 times.
451394 SOME(env_path) := getScopePath(inEnv);
884 445803 cref1 := AbsynUtil.unqualifyCref(inCref);
885 445803 env_path := AbsynUtil.makeNotFullyQualified(env_path);
886 // try to strip as much as possible
887 445803 cref2 := crefStripGraphScopePrefix2(cref1, env_path, stripPartial);
888 // check if we really did anything, fail if we did nothing!
889
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1135 times.
1135 false := AbsynUtil.crefEqual(cref1, cref2);
890 then
891 cref2;
892
893 else inCref;
894 end matchcontinue;
895 end crefStripGraphScopePrefix;
896
897 protected function crefStripGraphScopePrefix2
898 input Absyn.ComponentRef inCref;
899 input Absyn.Path inEnvPath;
900 input Boolean stripPartial;
901 output Absyn.ComponentRef outCref;
902 algorithm
903 outCref := matchcontinue(inCref, inEnvPath, stripPartial)
904 local
905 Absyn.Ident id1, id2;
906 Absyn.ComponentRef cref;
907 Absyn.Path env_path;
908
909 case (Absyn.CREF_QUAL(name = id1, subscripts = {}, componentRef = cref),
910 Absyn.QUALIFIED(name = id2, path = env_path), _)
911 algorithm
912
4/4
✓ Branch 0 taken 105963 times.
✓ Branch 1 taken 39480 times.
✓ Branch 3 taken 93862 times.
✓ Branch 4 taken 12101 times.
145443 true := stringEqual(id1, id2);
913 93862 then
914 crefStripGraphScopePrefix2(cref, env_path, stripPartial);
915
916 case (Absyn.CREF_QUAL(name = id1, subscripts = {}, componentRef = cref),
917 Absyn.IDENT(name = id2), _)
918 algorithm
919
4/4
✓ Branch 0 taken 2270 times.
✓ Branch 1 taken 355 times.
✓ Branch 3 taken 1135 times.
✓ Branch 4 taken 1135 times.
2625 true := stringEqual(id1, id2);
920 then
921 cref;
922
923 // adrpo: leave it as stripped as you can if you can't match it above and we have true for stripPartial
924 case (Absyn.CREF_QUAL(name = id1, subscripts = {}),
925 env_path, true)
926 algorithm
927 ✗ false := stringEqual(id1, AbsynUtil.pathFirstIdent(env_path));
928 then
929 inCref;
930 end matchcontinue;
931 end crefStripGraphScopePrefix2;
932
933 public function pathStripGraphScopePrefix
934 "same as pathStripGraphScopePrefix"
935 input Absyn.Path inPath;
936 input Graph inEnv;
937 input Boolean stripPartial;
938 output Absyn.Path outPath;
939 algorithm
940 outPath := matchcontinue stripPartial
941 local
942 Absyn.Path env_path;
943 Absyn.Path path1, path2;
944
945 case _
946 algorithm
947
1/2
✓ Branch 1 taken 335341 times.
✗ Branch 2 not taken.
335341 false := Flags.isSet(Flags.STRIP_PREFIX);
948 then inPath;
949
950 case _
951 algorithm
952
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 335341 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 335341 times.
335341 SOME(env_path) := getScopePath(inEnv);
953 335341 path1 := AbsynUtil.makeNotFullyQualified(inPath);
954 335341 env_path := AbsynUtil.makeNotFullyQualified(env_path);
955 // try to strip as much as possible
956 335341 path2 := pathStripGraphScopePrefix2(path1, env_path, stripPartial);
957 // check if we really did anything, fail if we did nothing!
958 ✗ false := AbsynUtil.pathEqual(path1, path2);
959 then
960 path2;
961
962 else inPath;
963 end matchcontinue;
964 end pathStripGraphScopePrefix;
965
966 protected function pathStripGraphScopePrefix2
967 input Absyn.Path inPath;
968 input Absyn.Path inEnvPath;
969 input Boolean stripPartial;
970 output Absyn.Path outPath;
971 algorithm
972 outPath := match(inPath, inEnvPath, stripPartial)
973 local
974 Absyn.Ident id1, id2;
975 Absyn.Path path;
976 Absyn.Path env_path;
977
978 case (Absyn.QUALIFIED(name = id1, path = path),
979 Absyn.QUALIFIED(name = id2, path = env_path), _) guard stringEqual(id1, id2)
980 87809 then
981 pathStripGraphScopePrefix2(path, env_path, stripPartial);
982
983 case (Absyn.QUALIFIED(name = id1, path = path),
984 Absyn.IDENT(name = id2), _) guard stringEqual(id1, id2)
985 then
986 path;
987
988 // adrpo: leave it as stripped as you can if you can't match it above and stripPartial is true
989 case (Absyn.QUALIFIED(name = id1), env_path, true) guard not stringEqual(id1, AbsynUtil.pathFirstIdent(env_path))
990 then
991 inPath;
992 end match;
993 end pathStripGraphScopePrefix2;
994
995 public function mkComponentNode "This function adds a component to the graph."
996 input Graph inGraph;
997 input DAE.Var inVar;
998 input SCode.Element inVarEl;
999 input DAE.Mod inMod;
1000 input Status instStatus;
1001 input Graph inCompGraph;
1002 output Graph outGraph;
1003 algorithm
1004 outGraph := matchcontinue (inGraph,inVar,inVarEl,inMod,instStatus,inCompGraph)
1005 local
1006 DAE.Var v;
1007 Name n;
1008 SCode.Element c;
1009 Graph g, cg;
1010 DAE.Mod m;
1011 Ref r;
1012 FCore.Status i;
1013
1014 // Graph of component
1015 case (_, DAE.TYPES_VAR(name = n),c,_,_,_)
1016 algorithm
1017 // maks sure the element name and the DAE.TYPES_VAR name is the same!
1018
2/4
✓ Branch 1 taken 1184327 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1184327 times.
✗ Branch 6 not taken.
1184327 false := stringEq(n, SCodeUtil.elementName(c));
1019 ✗ Error.addCompilerError("FGraph.mkComponentNode: The component name: " + SCodeUtil.elementName(c) + " is not the same as its DAE.TYPES_VAR: " + n + "\n");
1020 ✗ then
1021 fail();
1022
1023 // Graph of component
1024 case (g, v as DAE.TYPES_VAR(name = n),c,m,i,cg)
1025 algorithm
1026 // make sure the element name and the DAE.TYPES_VAR name is the same!
1027
2/4
✓ Branch 1 taken 1184327 times.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 1184327 times.
1184327 true := stringEq(n, SCodeUtil.elementName(c));
1028 1184327 r := lastScopeRef(g);
1029 1184327 g := FGraphBuildEnv.mkCompNode(c, r, FCore.USERDEFINED(), g);
1030 // update the var too!
1031 1184327 g := updateVarAndMod(g, v, m, i, cg);
1032 then
1033 g;
1034
1035 end matchcontinue;
1036 end mkComponentNode;
1037
1038 public function mkClassNode
1039 "This function adds a class definition to the environment.
1040 Enumeration are expanded from a list into a class with components"
1041 input Graph inGraph;
1042 input SCode.Element inClass;
1043 input DAE.Prefix inPrefix;
1044 input DAE.Mod inMod;
1045 input Boolean checkDuplicate = false;
1046 output Graph outGraph;
1047 algorithm
1048 outGraph := matchcontinue (inGraph, inClass)
1049 local
1050 Name n;
1051 Graph g;
1052 Ref r;
1053
1054 // already there as class instance, do nothing!
1055 case (g, SCode.CLASS(name = n))
1056 algorithm
1057 8065015 r := lastScopeRef(g);
1058 8065015 r := FNode.child(r, n);
1059
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 26137 times.
✓ Branch 3 taken 26137 times.
✗ Branch 4 not taken.
26137 FCore.CL(status = FCore.CLS_INSTANCE(_)) := FNode.refData(r);
1060 then
1061 g;
1062
1063 case (g, SCode.CLASS())
1064 algorithm
1065 8065015 r := lastScopeRef(g);
1066 8065015 g := FGraphBuildEnv.mkClassNode(inClass, inPrefix, inMod, r,
1067 FCore.USERDEFINED(), g, checkDuplicate);
1068 then
1069 g;
1070
1071 end matchcontinue;
1072 end mkClassNode;
1073
1074 public function mkTypeNode
1075 "This function adds a class definition to the environment.
1076 Enumeration are expanded from a list into a class with components"
1077 input Graph inGraph;
1078 input Name inName;
1079 input DAE.Type inType;
1080 output Graph outGraph;
1081 algorithm
1082 outGraph := match inGraph
1083 local
1084 Graph g;
1085 Ref r;
1086
1087 case g
1088 algorithm
1089 69018 r := lastScopeRef(g);
1090 69018 g := FGraphBuildEnv.mkTypeNode({inType}, r, inName, g);
1091 then
1092 g;
1093
1094 end match;
1095 end mkTypeNode;
1096
1097 public function mkImportNode
1098 "This function adds a class definition to the environment.
1099 Enumeration are expanded from a list into a class with components"
1100 input Graph inGraph;
1101 input SCode.Element inImport;
1102 output Graph outGraph;
1103 algorithm
1104 outGraph := match inGraph
1105 local
1106 Graph g;
1107 Ref r;
1108
1109 case g
1110 algorithm
1111 76638 r := lastScopeRef(g);
1112 76638 g := FGraphBuildEnv.mkElementNode(inImport, r, FCore.USERDEFINED(), g);
1113 then
1114 g;
1115
1116 end match;
1117 end mkImportNode;
1118
1119 public function mkDefunitNode
1120 "This function adds a class definition to the environment.
1121 Enumeration are expanded from a list into a class with components"
1122 input Graph inGraph;
1123 input SCode.Element inDu;
1124 output Graph outGraph;
1125 algorithm
1126 outGraph := match inGraph
1127 local
1128 Graph g;
1129 Ref r;
1130
1131 case g
1132 algorithm
1133 ✗ r := lastScopeRef(g);
1134 ✗ g := FGraphBuildEnv.mkElementNode(inDu, r, FCore.USERDEFINED(), g);
1135 then
1136 g;
1137
1138 end match;
1139 end mkDefunitNode;
1140
1141 public function classInfToScopeType
1142 input ClassInf.State inState;
1143 output Option<FCore.ScopeType> outType;
1144 algorithm
1145 outType := match inState
1146 case ClassInf.FUNCTION() then SOME(FCore.FUNCTION_SCOPE());
1147 else SOME(FCore.CLASS_SCOPE());
1148 end match;
1149 end classInfToScopeType;
1150
1151 public function isEmpty
1152 "returns true if empty graph"
1153 input Graph inGraph;
1154 output Boolean b;
1155 algorithm
1156 b := match inGraph
1157 case FCore.EG(_) then true;
1158 else false;
1159 end match;
1160 end isEmpty;
1161
1162 public function isNotEmpty
1163 "returns true if not empty graph"
1164 input Graph inGraph;
1165 output Boolean b;
1166 algorithm
1167 75525 b := not isEmpty(inGraph);
1168 end isNotEmpty;
1169
1170 public function isEmptyScope
1171 input Graph graph;
1172 output Boolean isEmpty;
1173 algorithm
1174 try
1175 220723 isEmpty := RefTree.isEmpty(FNode.children(FNode.fromRef(lastScopeRef(graph))));
1176 else
1177 isEmpty := true;
1178 end try;
1179 end isEmptyScope;
1180
1181 public function printGraphStr
1182 "prints the graph"
1183 input Graph inGraph;
1184 output String s;
1185 algorithm
1186 s := "NOT IMPLEMENTED YET";
1187 end printGraphStr;
1188
1189 public function inFunctionScope
1190 input Graph inGraph;
1191 output Boolean inFunction;
1192 algorithm
1193 inFunction := match inGraph
1194 local
1195 Scope s;
1196
1197 case FCore.G(scope = s) guard checkScopeType(s, SOME(FCore.FUNCTION_SCOPE())) or
1198 checkScopeType(s, SOME(FCore.PARALLEL_SCOPE()))
1199 then
1200 true;
1201
1202 else false;
1203
1204 end match;
1205 end inFunctionScope;
1206
1207 public function getScopeName " Returns the name of a scope, if no name exist, the function fails."
1208 input Graph inGraph;
1209 output Name name;
1210 algorithm
1211 name := match inGraph
1212 local Ref r;
1213 case _
1214 algorithm
1215 ✗ r := lastScopeRef(inGraph);
1216 // not top
1217 ✗ false := FNode.isRefTop(r);
1218 ✗ name := FNode.refName(r);
1219 then
1220 name;
1221 end match;
1222 end getScopeName;
1223
1224 public function checkScopeType
1225 input Scope inScope;
1226 input Option<FCore.ScopeType> inScopeType;
1227 output Boolean yes;
1228 algorithm
1229 yes := matchcontinue inScope
1230 local
1231 Ref r;
1232 Scope rest;
1233 SCode.Restriction restr;
1234 Option<FCore.ScopeType> st;
1235
1236 case {} then false;
1237
1238 // classes
1239 case r::_
1240 algorithm
1241
2/2
✓ Branch 1 taken 821712 times.
✓ Branch 2 taken 1981288 times.
2803000 true := FNode.isRefClass(r);
1242 1981288 restr := SCodeUtil.getClassRestriction(FNode.getElement(FNode.fromRef(r)));
1243
2/2
✓ Branch 2 taken 1632744 times.
✓ Branch 3 taken 348544 times.
1981288 true := valueEq(restrictionToScopeType(restr), inScopeType);
1244 then
1245 true;
1246
1247 // FCore.ND(scopeType)
1248 case r::_
1249 algorithm
1250
2/2
✓ Branch 1 taken 2247891 times.
✓ Branch 2 taken 206565 times.
2454456 FCore.N(data = FCore.ND(st)) := FNode.fromRef(r);
1251
1/2
✓ Branch 1 taken 206565 times.
✗ Branch 2 not taken.
206565 true := valueEq(st, inScopeType);
1252 then
1253 true;
1254
1255 case _::rest
1256 2454456 then
1257 checkScopeType(rest, inScopeType);
1258
1259 end matchcontinue;
1260 end checkScopeType;
1261
1262 public function lastScopeRestriction
1263 input Graph inGraph;
1264 output SCode.Restriction outRestriction;
1265 protected
1266 Scope s;
1267 algorithm
1268
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1028 times.
1028 FCore.G(scope = s) := inGraph;
1269 1028 outRestriction := getScopeRestriction(s);
1270 end lastScopeRestriction;
1271
1272 public function getScopeRestriction
1273 input Scope inScope;
1274 output SCode.Restriction outRestriction;
1275 algorithm
1276 outRestriction := matchcontinue inScope
1277 local
1278 Ref r;
1279 FCore.ScopeType st;
1280
1281 case r :: _ guard(FNode.isRefClass(r))
1282 963 then SCodeUtil.getClassRestriction(FNode.getElement(FNode.fromRef(r)));
1283
1284 case r :: _
1285 algorithm
1286
4/6
✓ Branch 1 taken 65 times.
✓ Branch 2 taken 188 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 188 times.
✓ Branch 5 taken 188 times.
✗ Branch 6 not taken.
253 FCore.N(data = FCore.ND(SOME(st))) := FNode.fromRef(r);
1287 ✗ then
1288 scopeTypeToRestriction(st);
1289
1290 318 else getScopeRestriction(listRest(inScope));
1291
1292 end matchcontinue;
1293 end getScopeRestriction;
1294
1295 public function getGraphPathNoImplicitScope
1296 "This function returns all partially instantiated parents as an Absyn.Path
1297 option I.e. it collects all identifiers of each frame until it reaches
1298 the topmost unnamed frame. If the environment is only the topmost frame,
1299 NONE() is returned."
1300 input Graph inGraph;
1301 output Option<Absyn.Path> outAbsynPathOption;
1302 algorithm
1303 123062 outAbsynPathOption := getGraphPathNoImplicitScope_dispatch(currentScope(inGraph));
1304 end getGraphPathNoImplicitScope;
1305
1306 protected function getGraphPathNoImplicitScope_dispatch
1307 "This function returns all partially instantiated parents as an Absyn.Path
1308 option I.e. it collects all identifiers of each frame until it reaches
1309 the topmost unnamed frame. If the environment is only the topmost frame,
1310 NONE() is returned."
1311 input Scope inScope;
1312 output Option<Absyn.Path> outAbsynPathOption;
1313 protected
1314 Option<Absyn.Path> opath;
1315 algorithm
1316 outAbsynPathOption := matchcontinue inScope
1317 local
1318 Name id;
1319 Absyn.Path path,path_1;
1320 Scope rest;
1321 Ref ref;
1322
1323 case ref :: rest
1324 guard
1325 not FNode.isRefTop(ref)
1326 algorithm
1327 368823 id := FNode.refName(ref);
1328
2/2
✓ Branch 1 taken 48629 times.
✓ Branch 2 taken 320194 times.
368823 if isImplicitScope(id) then
1329 48629 opath := getGraphPathNoImplicitScope_dispatch(rest);
1330 else
1331 320194 opath := getGraphPathNoImplicitScope_dispatch(rest);
1332
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 320194 times.
✓ Branch 2 taken 108217 times.
✓ Branch 3 taken 211977 times.
320194 if isSome(opath) then
1333 211977 SOME(path) := opath;
1334 211977 path_1 := AbsynUtil.joinPaths(path, Absyn.IDENT(id));
1335 opath := SOME(path_1);
1336 else
1337 108217 opath := SOME(Absyn.IDENT(id));
1338 end if;
1339 end if;
1340 then
1341 opath;
1342
1343 else NONE();
1344
1345 end matchcontinue;
1346 end getGraphPathNoImplicitScope_dispatch;
1347
1348 public function isImplicitScope
1349 input Name inName;
1350 output Boolean isImplicit;
1351 algorithm
1352 368823 isImplicit := FCore.isImplicitScope(inName);
1353 end isImplicitScope;
1354
1355 public function joinScopePath "Used to join an Graph scope with an Absyn.Path (probably an IDENT)"
1356 input Graph inGraph;
1357 input Absyn.Path inPath;
1358 output Absyn.Path outPath;
1359 protected
1360 Option<Absyn.Path> opath;
1361 Absyn.Path envPath;
1362 algorithm
1363 37420 opath := getScopePath(inGraph);
1364
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 37420 times.
✓ Branch 2 taken 36273 times.
✓ Branch 3 taken 1147 times.
37420 if isSome(opath) then
1365 36273 SOME(envPath) := opath;
1366 36273 outPath := AbsynUtil.joinPaths(envPath,inPath);
1367 else
1368 outPath := inPath;
1369 end if;
1370 end joinScopePath;
1371
1372 public function splitGraphScope
1373 "splits out the for loop scope from the graph scope"
1374 input Graph inGraph;
1375 output Graph outRealGraph;
1376 output Scope outForScope;
1377 algorithm
1378 2794 (outRealGraph, outForScope) := splitGraphScope_dispatch(inGraph, {});
1379 end splitGraphScope;
1380
1381 public function splitGraphScope_dispatch
1382 "splits out the for loop scope from the graph scope"
1383 input Graph inGraph;
1384 input Scope inAcc;
1385 output Graph outRealGraph;
1386 output Scope outForScope;
1387 algorithm
1388 (outRealGraph, outForScope) := match inGraph
1389 local
1390 Graph g;
1391 Ref r;
1392 Scope s;
1393
1394 ✗ case FCore.EG(_) then (inGraph, listReverse(inAcc));
1395
1396 case FCore.G(scope = r::_)
1397 algorithm
1398
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2794 times.
2794 if FNode.isImplicitRefName(r) then
1399 ✗ (g, _) := stripLastScopeRef(inGraph);
1400 ✗ (g, s) := splitGraphScope_dispatch(g, r::inAcc);
1401 else
1402 g := inGraph;
1403 2794 s := listReverse(inAcc);
1404 end if;
1405 2794 then
1406 (g, s);
1407
1408 end match;
1409 end splitGraphScope_dispatch;
1410
1411 public function getVariablesFromGraphScope
1412 "@author: adrpo
1413 returns the a list with all the variables names in the given graph from the last graph scope"
1414 input Graph inGraph;
1415 output list<Name> variables;
1416 algorithm
1417 variables := match inGraph
1418 local
1419 list<Name> lst;
1420 Ref r;
1421
1422 // empty case
1423 case FCore.EG(_) then {};
1424
1425 // some graph, no scope
1426 case FCore.G(scope = {}) then {};
1427
1428 // some graph
1429 case FCore.G(scope = r::_)
1430 algorithm
1431 3750 lst := List.map(FNode.filter(r, FNode.isRefComponent), FNode.refName);
1432 then
1433 lst;
1434
1435 end match;
1436 end getVariablesFromGraphScope;
1437
1438 public function removeComponentsFromScope
1439 "@author:adrpo
1440 remove the children of the last ref"
1441 input Graph inGraph;
1442 output Graph outGraph;
1443 protected
1444 Ref r;
1445 Node n;
1446 algorithm
1447 1692 r := lastScopeRef(inGraph);
1448 1692 r := FNode.copyRefNoUpdate(r);
1449 1692 n := FNode.fromRef(r);
1450 1692 n := FNode.setChildren(n, RefTree.new());
1451 1692 r := FNode.updateRef(r, n);
1452 1692 (outGraph, _) := stripLastScopeRef(inGraph);
1453 1692 outGraph := pushScopeRef(outGraph, r);
1454 end removeComponentsFromScope;
1455
1456 public function cloneLastScopeRef
1457 input Graph inGraph;
1458 output Graph outGraph;
1459 protected
1460 Ref r;
1461 algorithm
1462 ✗ (outGraph, r) := stripLastScopeRef(inGraph);
1463 ✗ r := FNode.copyRefNoUpdate(r);
1464 ✗ outGraph := pushScopeRef(outGraph, r);
1465 end cloneLastScopeRef;
1466
1467 public function updateScope
1468 input Graph inGraph;
1469 output Graph outGraph;
1470 algorithm
1471 outGraph := match inGraph
1472 case _ then inGraph;
1473 end match;
1474 end updateScope;
1475
1476 public function mkVersionNode
1477 "@author: adrpo
1478 THE MOST IMPORTANT FUNCTION IN THE COMPILER :)
1479 This function works like this:
1480 From source scope:
1481 A.B.C.D
1482 we lookup a target scope
1483 X.Y.Z.W
1484 to be used for a component, derived class, or extends
1485 We get back X.Y.Z + CLASS(W) via lookup.
1486 We build X.Y.Z.W_newVersion and return it.
1487 The newVersion name is generated by mkVersionName based on
1488 the source scope, the element name, prefix and modifiers.
1489 The newVersion scope is only created if there are non emtpy
1490 modifiers given to this functions"
1491 input Graph inSourceEnv;
1492 input Name inSourceName;
1493 input DAE.Prefix inPrefix;
1494 input DAE.Mod inMod;
1495 input Graph inTargetClassEnv;
1496 input SCode.Element inTargetClass;
1497 input InnerOuter.InstHierarchy inIH;
1498 output Graph outVersionedTargetClassEnv;
1499 output SCode.Element outVersionedTargetClass;
1500 output InnerOuter.InstHierarchy outIH;
1501 algorithm
1502 (outVersionedTargetClassEnv, outVersionedTargetClass, outIH) := matchcontinue inIH
1503 local
1504 Graph gclass;
1505 Ref classRef, sourceRef, targetClassParentRef;
1506 DAE.Prefix crefPrefix;
1507 SCode.Element c;
1508 Name targetClassName, newTargetClassName;
1509 InnerOuter.InstHierarchy ih;
1510
1511 /*
1512 case (_, _, _, _, _, _, _)
1513 algorithm
1514 c = inTargetClass;
1515 gclass = inTargetClassEnv;
1516 targetClassName = SCodeUtil.elementName(c);
1517
1518 (newTargetClassName, crefPrefix) = mkVersionName(inSourceEnv, inSourceName, inPrefix, inMod, inTargetClassEnv, targetClassName);
1519
1520 // get the last scope from target
1521 targetClassParentRef = lastScopeRef(inTargetClassEnv);
1522 classRef = FNode.child(targetClassParentRef, newTargetClassName);
1523 c = FNode.getElementFromRef(classRef);
1524 then
1525 (inTargetClassEnv, c, inIH);*/
1526
1527 case _
1528 algorithm
1529 c := inTargetClass;
1530 gclass := inTargetClassEnv;
1531 20715 targetClassName := SCodeUtil.elementName(c);
1532
1533 20715 (newTargetClassName, crefPrefix) := mkVersionName(inSourceEnv, inSourceName, inPrefix, inMod, inTargetClassEnv, targetClassName);
1534
1535 // get the last item in the source env
1536 20715 sourceRef := FNode.child(lastScopeRef(inSourceEnv), inSourceName);
1537
1538 // get the last scope from target
1539 20715 targetClassParentRef := lastScopeRef(inTargetClassEnv);
1540 // get the class from class env
1541 20715 classRef := FNode.child(targetClassParentRef, targetClassName);
1542 // clone the class
1543 20715 classRef := FNode.copyRefNoUpdate(classRef);
1544
1545 // check if the name of the class already exists!
1546 // failure(_ = FNode.child(targetClassParentRef, newTargetClassName));
1547
1548 // change class name (so unqualified references to the same class reach the original element
1549
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20715 times.
20715 FCore.CL(e = c) := FNode.refData(classRef);
1550 20715 c := SCodeUtil.setClassName(newTargetClassName, c);
1551 20715 classRef := updateClassElement(classRef, c, crefPrefix, inMod, FCore.CLS_INSTANCE(targetClassName) /* FCore.CLS_UNTYPED() */, empty());
1552 // parent the classRef
1553 20715 FNode.addChildRef(targetClassParentRef, newTargetClassName, classRef);
1554 // update the source target scope
1555 41430 sourceRef := updateSourceTargetScope(sourceRef, classRef :: currentScope(gclass));
1556
1557 // we never need to add the instance as inner!
1558 ih := inIH; // ih = InnerOuter.addClassIfInner(c, crefPrefix, gclass, inIH);
1559
1560 /*
1561 print("Instance1: CL(" + getGraphNameStr(inSourceEnv) + ").CO(" +
1562 inSourceName + ").CL(" + getGraphNameStr(inTargetClassEnv) + "." +
1563 targetClassName + SCodeDump.printModStr(Mod.unelabMod(inMod), SCodeDump.defaultOptions) + ")\n\t" +
1564 newTargetClassName + "\n");*/
1565 then
1566 (gclass, c, ih);
1567
1568 else
1569 algorithm
1570 c := inTargetClass;
1571 ✗ targetClassName := SCodeUtil.elementName(c);
1572 ✗ (newTargetClassName,_) := mkVersionName(inSourceEnv, inSourceName, inPrefix, inMod, inTargetClassEnv, targetClassName);
1573
1574 ✗ Error.addCompilerWarning(
1575 "FGraph.mkVersionNode: failed to create version node:\n" +
1576 "Instance: CL(" + getGraphNameStr(inSourceEnv) + ").CO(" +
1577 inSourceName + ").CL(" + getGraphNameStr(inTargetClassEnv) + "." +
1578 targetClassName + SCodeDump.printModStr(Mod.unelabMod(inMod), SCodeDump.defaultOptions) + ")\n\t" +
1579 newTargetClassName + "\n");
1580 then
1581 (inTargetClassEnv, inTargetClass, inIH);
1582
1583 end matchcontinue;
1584 end mkVersionNode;
1585
1586 public function createVersionScope
1587 input Graph inSourceEnv;
1588 input Name inSourceName;
1589 input DAE.Prefix inPrefix;
1590 input DAE.Mod inMod;
1591 input Graph inTargetClassEnv;
1592 input SCode.Element inTargetClass;
1593 input InnerOuter.InstHierarchy inIH;
1594 output Graph outVersionedTargetClassEnv;
1595 output SCode.Element outVersionedTargetClass;
1596 output InnerOuter.InstHierarchy outIH;
1597 algorithm
1598 (outVersionedTargetClassEnv, outVersionedTargetClass, outIH) := matchcontinue inMod
1599 local
1600 Graph gclass;
1601 SCode.Element c;
1602
1603 /*
1604 case (_, _, _, _, _, _, _)
1605 algorithm
1606 print(AbsynUtil.pathString(PrefixUtil.prefixToPath(inPrefix)) + " S:" + getGraphNameStr(inSourceEnv) + "/" + inSourceName + " ||| " + "T:" + getGraphNameStr(inTargetClassEnv) + "/" + SCodeUtil.elementName(inTargetClass) + "\n");
1607 then
1608 fail();*/
1609
1610 // case (_, _, _, _, _, _, _) then (inTargetClassEnv, inTargetClass, inIH);
1611
1612 // don't do this if there is no modifications on the class
1613 // TODO! FIXME! wonder if we can skip this if it has only a binding, not an actual type modifier
1614 301894 case DAE.NOMOD() then (inTargetClassEnv, inTargetClass, inIH);
1615 218830 case DAE.MOD(subModLst={}) then (inTargetClassEnv, inTargetClass, inIH);
1616
1617 // don't do this for MetaModelica, target class is builtin or builtin type, functions
1618 case _
1619 algorithm
1620
7/8
✓ Branch 1 taken 40331 times.
✓ Branch 2 taken 24 times.
✓ Branch 4 taken 23324 times.
✓ Branch 5 taken 17007 times.
✓ Branch 7 taken 20715 times.
✓ Branch 8 taken 2609 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 20715 times.
40355 true := Config.acceptMetaModelicaGrammar() or
1621 isTargetClassBuiltin(inTargetClassEnv, inTargetClass) or
1622 inFunctionScope(inSourceEnv) or
1623 SCodeUtil.isOperatorRecord(inTargetClass);
1624 19640 then
1625 (inTargetClassEnv, inTargetClass, inIH);
1626
1627 // or OpenModelica scripting stuff
1628 case _
1629 algorithm
1630
3/4
✓ Branch 2 taken 1268 times.
✓ Branch 3 taken 19348 times.
✓ Branch 7 taken 1268 times.
✗ Branch 8 not taken.
20715 true := stringEq(AbsynUtil.pathFirstIdent(getGraphName(inTargetClassEnv)), "OpenModelica");
1631 ✗ then
1632 (inTargetClassEnv, inTargetClass, inIH);
1633
1634 // need to create a new version of the class
1635 case _
1636 algorithm
1637 20715 (gclass, c, outIH) := mkVersionNode(inSourceEnv, inSourceName, inPrefix, inMod, inTargetClassEnv, inTargetClass, inIH);
1638 then
1639 (gclass, c, outIH);
1640
1641 end matchcontinue;
1642 end createVersionScope;
1643
1644 public function isTargetClassBuiltin
1645 input Graph inGraph;
1646 input SCode.Element inClass;
1647 output Boolean yes;
1648 algorithm
1649 yes := matchcontinue inClass
1650 local Ref r;
1651 case _
1652 algorithm
1653 40331 r := FNode.child(lastScopeRef(inGraph), SCodeUtil.elementName(inClass));
1654
4/4
✓ Branch 1 taken 23325 times.
✓ Branch 2 taken 17006 times.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 23324 times.
40331 yes := FNode.isRefBasicType(r) or FNode.isRefBuiltin(r);
1655 then
1656 yes;
1657
1658 else false;
1659 end matchcontinue;
1660 end isTargetClassBuiltin;
1661
1662 public function mkVersionName
1663 input Graph inSourceEnv;
1664 input Name inSourceName;
1665 input DAE.Prefix inPrefix;
1666 input DAE.Mod inMod;
1667 input Graph inTargetClassEnv;
1668 input Name inTargetClassName;
1669 output Name outName;
1670 output DAE.Prefix outCrefPrefix;
1671 algorithm
1672 (outName, outCrefPrefix) := match inTargetClassName
1673 local
1674 DAE.Prefix crefPrefix;
1675 Name name;
1676
1677 case _
1678 algorithm
1679 20715 crefPrefix := PrefixUtil.prefixAdd(inSourceName,{},{},inPrefix,SCode.CONST(),ClassInf.UNKNOWN(Absyn.IDENT("")), Absyn.dummyInfo); // variability doesn't matter
1680
1681 // name = inTargetClassName + "$" + ComponentReferenceBasics.printComponentRefStr(PrefixUtil.prefixToCref(crefPrefix));
1682 20715 name := inTargetClassName + "$" + AbsynUtil.pathString(AbsynUtil.stringListPath(listReverse(AbsynUtil.pathToStringList(PrefixUtil.prefixToPath(crefPrefix)))), "$", usefq=false)
1683 ; // + "$" + AbsynUtil.pathString2NoLeadingDot(getGraphName(inSourceEnv), "$");
1684 // name = "'$" + inTargetClassName + "@" + AbsynUtil.pathString(AbsynUtil.stringListPath(listReverse(AbsynUtil.pathToStringList(PrefixUtil.prefixToPath(crefPrefix))))) + "'";
1685 // name = "'$" + getGraphNameStr(inSourceEnv) + "." + AbsynUtil.pathString(AbsynUtil.stringListPath(listReverse(AbsynUtil.pathToStringList(PrefixUtil.prefixToPath(crefPrefix))))) + "'";
1686 // name = "$'" + getGraphNameStr(inSourceEnv) + "." +
1687 // AbsynUtil.pathString(AbsynUtil.stringListPath(listReverse(AbsynUtil.pathToStringList(PrefixUtil.prefixToPath(crefPrefix))))) +
1688 // SCodeDump.printModStr(Mod.unelabMod(inMod), SCodeDump.defaultOptions);
1689 then
1690 (name, crefPrefix);
1691
1692 end match;
1693 end mkVersionName;
1694
1695 public function getClassPrefix
1696 input FCore.Graph inEnv;
1697 input Name inClassName;
1698 output DAE.Prefix outPrefix;
1699 algorithm
1700 outPrefix := matchcontinue inClassName
1701 local
1702 DAE.Prefix p;
1703 Ref r;
1704
1705 case _
1706 algorithm
1707 ✗ r := FNode.child(lastScopeRef(inEnv), inClassName);
1708 ✗ FCore.CL(pre = p) := FNode.refData(r);
1709 then
1710 p;
1711
1712 else DAE.NOPRE();
1713
1714 end matchcontinue;
1715 end getClassPrefix;
1716
1717 public function isInstance
1718 input FCore.Graph inEnv;
1719 input FCore.Name inName;
1720 output Boolean yes;
1721 algorithm
1722 yes := matchcontinue inName
1723
1724 case _
1725 algorithm
1726 ✗ FCore.CL(status = FCore.CLS_INSTANCE(_)) := FNode.refData(FNode.child(lastScopeRef(inEnv), inName));
1727 then
1728 true;
1729
1730 else false;
1731
1732 end matchcontinue;
1733 end isInstance;
1734
1735 public function getInstanceOriginalName
1736 input FCore.Graph inEnv;
1737 input FCore.Name inName;
1738 output FCore.Name outName;
1739 algorithm
1740 outName := matchcontinue inName
1741
1742 case _
1743 algorithm
1744
3/4
✗ Branch 3 not taken.
✓ Branch 4 taken 3514 times.
✓ Branch 5 taken 992 times.
✓ Branch 6 taken 2522 times.
3514 FCore.CL(status = FCore.CLS_INSTANCE(outName)) := FNode.refData(FNode.child(lastScopeRef(inEnv), inName));
1745 then
1746 outName;
1747
1748 else inName;
1749
1750 end matchcontinue;
1751 end getInstanceOriginalName;
1752
1753 public function graphPrefixOf
1754 "note that A.B.C is not prefix of A.B.C,
1755 only A.B is a prefix of A.B.C"
1756 input Graph inPrefixEnv;
1757 input Graph inEnv;
1758 output Boolean outIsPrefix;
1759 algorithm
1760 1 outIsPrefix := graphPrefixOf2(listReverse(currentScope(inPrefixEnv)), listReverse(currentScope(inEnv)));
1761 end graphPrefixOf;
1762
1763 public function graphPrefixOf2
1764 "Checks if one environment is a prefix of another.
1765 note that A.B.C is not prefix of A.B.C,
1766 only A.B is a prefix of A.B.C"
1767 input Scope inPrefixEnv;
1768 input Scope inEnv;
1769 output Boolean outIsPrefix;
1770 algorithm
1771 outIsPrefix := match(inPrefixEnv, inEnv)
1772 local
1773 Scope rest1, rest2;
1774 Ref r1, r2;
1775
1776 case ({}, _::_) then true;
1777
1778 case (r1 :: rest1, r2 :: rest2) guard stringEq(FNode.refName(r1), FNode.refName(r2))
1779 2 then
1780 graphPrefixOf2(rest1, rest2);
1781
1782 else false;
1783
1784 end match;
1785 end graphPrefixOf2;
1786
1787 public function setStatus
1788 input Graph inEnv;
1789 input Name inName;
1790 input FCore.Data inStatus;
1791 output Graph outEnv;
1792 algorithm
1793 outEnv := matchcontinue inEnv
1794 local
1795 Graph g;
1796 Node n;
1797 Ref ref, refParent;
1798
1799 case g
1800 algorithm
1801 ✗ refParent := lastScopeRef(g);
1802 ✗ if FNode.refHasChild(refParent, inName) then
1803 ✗ ref := FNode.child(refParent, inName);
1804 ✗ if FNode.refHasChild(ref, FNode.statusNodeName) then
1805 // child exists and has a status node
1806 ✗ ref := FNode.child(ref, FNode.statusNodeName);
1807 ✗ n := FNode.setData(FNode.fromRef(ref), inStatus);
1808 ✗ ref := FNode.updateRef(ref, n);
1809 else
1810 // child exists but has no status node
1811 ✗ (g, n) := node(g, FNode.statusNodeName, {ref}, inStatus);
1812 ✗ FNode.addChildRef(ref, FNode.statusNodeName, FNode.toRef(n));
1813 end if;
1814 //else child does not exist, do nothing, is an import or extends
1815 end if;
1816 then
1817 g;
1818
1819 // did we fail for some weird reson?
1820 case g
1821 algorithm
1822 ✗ print("FGraph.setStatus failed on: " + getGraphNameStr(g) + " element: " + inName + "\n");
1823 then
1824 g;
1825
1826 end matchcontinue;
1827 end setStatus;
1828
1829 public function getStatus
1830 input Graph inEnv;
1831 input Name inName;
1832 output FCore.Data outStatus;
1833 algorithm
1834 outStatus := match inEnv
1835 local
1836 Graph g;
1837 Ref ref, refParent;
1838 FCore.Data s;
1839
1840 // child exists and has a status node
1841 case g
1842 algorithm
1843 ✗ refParent := lastScopeRef(g);
1844 ✗ true := FNode.refHasChild(refParent, inName);
1845 ✗ ref := FNode.child(refParent, inName);
1846 ✗ true := FNode.refHasChild(ref, FNode.statusNodeName);
1847 ✗ ref := FNode.child(ref, FNode.statusNodeName);
1848 ✗ s := FNode.refData(ref);
1849 then
1850 s;
1851
1852 // we can fail here with no problem, there is no status node!
1853 case _
1854 algorithm
1855 // print("FGraph.getStatus failed on: " + getGraphNameStr(g) + " element: " + inName + "\n");
1856 then
1857 fail();
1858
1859 end match;
1860 end getStatus;
1861
1862 public function selectScope
1863 "return the environment pointed by the path if it exists, else fails"
1864 input Graph inEnv;
1865 input Absyn.Path inPath;
1866 output Graph outEnv;
1867 algorithm
1868 outEnv := match inPath
1869 local
1870 Graph env;
1871 list<String> pl;
1872 Integer lp, le, diff;
1873 Scope cs;
1874 Absyn.Path p;
1875
1876 case _
1877 algorithm
1878 74956 p := AbsynUtil.stripLast(inPath);
1879
2/2
✓ Branch 2 taken 20830 times.
✓ Branch 3 taken 233 times.
45187 true := AbsynUtil.pathPrefixOf(p, getGraphName(inEnv));
1880 233 pl := AbsynUtil.pathToStringList(p);
1881 233 lp := listLength(pl);
1882 233 cs := currentScope(inEnv);
1883 233 le := listLength(cs) - 1;
1884 233 diff := le - lp;
1885 233 cs := List.stripN(cs, diff);
1886 233 env := setScope(inEnv, cs);
1887 // print("F: " + AbsynUtil.pathString(inPath) + "\n"); print("E: " + getGraphNameStr(inEnv) + "\n"); print("R: " + getGraphNameStr(env) + "\n");
1888 then
1889 env;
1890
1891 end match;
1892 end selectScope;
1893
1894 public function makeScopePartial
1895 input Graph inEnv;
1896 output Graph outEnv = inEnv;
1897 protected
1898 Node node;
1899 Data data;
1900 SCode.Element el;
1901 algorithm
1902 try
1903 ✗ node := FNode.fromRef(lastScopeRef(inEnv));
1904 node := match node
1905 case FCore.N(data = data as FCore.CL(e = el))
1906 algorithm
1907 ✗ el := SCodeUtil.makeClassPartial(el);
1908 ✗ data.e := el;
1909 ✗ node.data := data;
1910 then
1911 node;
1912
1913 else node;
1914 end match;
1915 ✗ outEnv := setLastScopeRef(FNode.toRef(node), outEnv);
1916 else
1917 end try;
1918 end makeScopePartial;
1919
1920 public function isPartialScope
1921 input Graph inEnv;
1922 output Boolean outIsPartial;
1923 protected
1924 SCode.Element el;
1925 algorithm
1926 try
1927
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 403750 times.
403750 FCore.N(data = FCore.CL(e = el)) := FNode.fromRef(lastScopeRef(inEnv));
1928 403750 outIsPartial := SCodeUtil.isPartial(el);
1929 else
1930 outIsPartial := false;
1931 end try;
1932 end isPartialScope;
1933
1934 annotation(__OpenModelica_Interface="frontend");
1935 end FGraph;
1936