Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 65.4% 17 / 0 / 26
Functions: -% 0 / 1 / 1
Branches: 28.6% 4 / 0 / 14

OMCompiler/Compiler/FFrontEnd/FCore.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 FCore
37 " file: FCore.mo
38 package: FCore
39 description: Structures to hold Modelica constructs
40
41
42 This module holds types used in FNode, FGraph and all the other F* packages
43 "
44
45
46 public
47 import Absyn;
48 import AbsynUtil;
49 import AvlSetCR;
50 import AvlTreePathFunction;
51 import DAE;
52 import Mutable;
53 import MutableWeak;
54 import SCode;
55
56 protected
57 import Config;
58
59 // ************************ FNode structures ***************************
60 // ************************ FNode structures ***************************
61 // ************************ FNode structures ***************************
62 // ************************ FNode structures ***************************
63
64 public
65 type Name = String "an identifier is just a string";
66 type Names = list<Name> "list of names";
67 type Import = Absyn.Import;
68 type Id = Integer;
69 type Seq = Integer;
70 type Next = Seq;
71
72 constant ImportTable emptyImportTable = IMPORT_TABLE(false, {}, {});
73
74 uniontype ImportTable
75 record IMPORT_TABLE
76 // Imports should not be inherited, but removing them from the node
77 // when doing lookup through extends causes problems for the lookup later
78 // on, because for example components may have types that depends on
79 // imports. The hidden flag allows the lookup to 'hide' the imports
80 // temporarily, without actually removing them.
81 Boolean hidden "If true means that the imports are hidden.";
82 list<Import> qualifiedImports;
83 list<Import> unqualifiedImports;
84 end IMPORT_TABLE;
85 end ImportTable;
86
87 type Ref = Mutable<Node> "one mutable slot; a node's identity is its cell";
88 type WeakRef = MutableWeak<Node> "a parent, held without owning it";
89
90 uniontype Node
91 record N
92 Name name "node name, class/component/extends name, etc. see also *NodeName in above";
93 Id id "Unique node id";
94 WeakParents parents "A node can have several parents depending on the context.
95 Held weakly: a parent owns its children, so owning the
96 parent back would make the graph unreclaimable by
97 reference counting. The graph is rooted at the top node,
98 which keeps every parent alive while it is reachable.";
99 Children children "List of uniquely named classes and variables";
100 Data data "More data for this node, Class, Var, etc";
101 end N;
102 end Node;
103
104 public uniontype ModScope
105 "Used to know where a modifier came from, for error reporting."
106 record MS_COMPONENT
107 String name;
108 end MS_COMPONENT;
109
110 record MS_EXTENDS
111 Absyn.Path path;
112 end MS_EXTENDS;
113
114 record MS_DERIVED
115 Absyn.Path path;
116 end MS_DERIVED;
117
118 record MS_CLASS_EXTENDS
119 String name;
120 end MS_CLASS_EXTENDS;
121
122 record MS_CONSTRAINEDBY
123 Absyn.Path path;
124 end MS_CONSTRAINEDBY;
125
126 end ModScope;
127
128 uniontype Data
129 record TOP "top"
130 end TOP;
131
132 record IT
133 DAE.Var i "instantiated component";
134 end IT;
135
136 record IM "import"
137 ImportTable i "imports";
138 end IM;
139
140 record CL "class"
141 SCode.Element e;
142 DAE.Prefix pre;
143 DAE.Mod mod "modification";
144 Kind kind "usedefined, builtin, basic type";
145 Status status "if it is untyped, typed or fully instantiated (dae)";
146 end CL;
147
148 record CO "component"
149 SCode.Element e;
150 DAE.Mod mod "modification";
151 Kind kind "usedefined, builtin, basic type";
152 Status status "if it is untyped, typed or fully instantiated (dae)";
153 end CO;
154
155 record EX "extends"
156 SCode.Element e;
157 DAE.Mod mod "modification";
158 end EX;
159
160 record DU "units"
161 list<SCode.Element> els;
162 end DU;
163
164 record FT "function type nodes"
165 list<DAE.Type> tys "list since several types with the same name can exist in the same scope (overloading)";
166 end FT;
167
168 record AL "algorithm section"
169 Name name "al or ial (initial)";
170 list<SCode.AlgorithmSection> a;
171 end AL;
172
173 record EQ "equation section"
174 Name name "eq or ieq (initial)";
175 list<SCode.Equation> e;
176 end EQ;
177
178 record OT "optimization"
179 list<SCode.ConstraintSection> constrainLst;
180 list<Absyn.NamedArg> clsAttrs;
181 end OT;
182
183 record ED "external declaration"
184 SCode.ExternalDecl ed;
185 end ED;
186
187 record FS "for iterators scope"
188 Absyn.ForIterators fis;
189 end FS;
190
191 record FI "for iterator"
192 Absyn.ForIterator fi;
193 end FI;
194
195 record MS "match scope"
196 Absyn.Exp e;
197 end MS;
198
199 record MO "mod"
200 SCode.Mod m;
201 end MO;
202
203 record EXP "binding, condition, array dim, etc"
204 String name "what is the expression for";
205 Absyn.Exp e;
206 end EXP;
207
208 record CR "component reference"
209 Absyn.ComponentRef r;
210 end CR;
211
212 record DIMS "dimensions"
213 String name "what are the dimensions for, type or component";
214 Absyn.ArrayDim dims;
215 end DIMS;
216
217 record CC "constrainedby class"
218 SCode.ConstrainClass cc;
219 end CC;
220
221 record REF "reference node"
222 Scope target;
223 end REF;
224
225 record ND "no data"
226 Option<ScopeType> scopeType;
227 end ND;
228
229 record VR "version node, contains the node that decided the generation of the clone"
230 Scope source;
231 DAE.Prefix p;
232 DAE.Mod m;
233 Option<ScopeType> scopeType;
234 end VR;
235
236 record ASSERT "an assertion node, to be used in places
237 where we want to assert things in the graph.
238 for example if we looked up A.B from A.B.C.D
239 but could not find C then we add an assertion
240 node. we have just a message here but might
241 add new info later on."
242 String message;
243 end ASSERT;
244
245 record STATUS "status node"
246 Boolean isInstantiating;
247 end STATUS;
248
249 end Data;
250
251 type Refs = list<Ref>;
252 type Parents = Refs "as handed out by FNode.parents, already upgraded";
253 type WeakParents = list<WeakRef> "as stored in a node; see Node.N.parents";
254 type Scope = Refs;
255 type Children = RefTree.Tree;
256
257 public constant Scope emptyScope = {} "empty scope";
258
259 encapsulated package RefTree
260 import BaseAvlTree;
261 import FCore.Name;
262 import FCore.Ref;
263 import FCore.Node;
264 extends BaseAvlTree;
265
266 redeclare type Key = Name;
267 redeclare type Value = Ref;
268
269 redeclare function extends keyStr
270 algorithm
271 outString := inKey;
272 end keyStr;
273
274 redeclare function extends valueStr
275 algorithm
276 ✗ Node.N(name = outString) := Mutable.access(inValue);
277 end valueStr;
278
279 redeclare function extends keyCompare
280 algorithm
281 321736621 outResult := stringCompare(inKey1, inKey2);
282 end keyCompare;
283 end RefTree;
284
285 uniontype Kind
286 record USERDEFINED end USERDEFINED;
287 record BUILTIN end BUILTIN;
288 record BASIC_TYPE end BASIC_TYPE;
289 end Kind;
290
291 public uniontype Status
292 "Used to distinguish between different phases of the instantiation of a component
293 A component is first added to environment untyped. It can thereafter be instantiated to get its type
294 and finally instantiated to produce the DAE. These three states are indicated by this datatype."
295
296 record VAR_UNTYPED "Untyped variables, initially added to env"
297 end VAR_UNTYPED;
298
299 record VAR_TYPED "Typed variables, when instantiation to get type has been performed"
300 end VAR_TYPED;
301
302 record VAR_DAE "Typed variables that also have been instantiated to generate dae. Required to distinguish
303 between typed variables without DAE to know when to skip multiply declared dae elements"
304 end VAR_DAE;
305
306 record VAR_DELETED "A conditional variable that was deleted."
307 end VAR_DELETED;
308
309 record CLS_UNTYPED "just added to the env"
310 end CLS_UNTYPED;
311
312 record CLS_PARTIAL "partially instantiated"
313 end CLS_PARTIAL;
314
315 record CLS_FULL "fully instantiated"
316 end CLS_FULL;
317
318 record CLS_INSTANCE "a class that was generated for a component"
319 String instanceOf;
320 end CLS_INSTANCE;
321
322 end Status;
323
324 // ************************ FVisit structures ***************************
325 // ************************ FVisit structures ***************************
326 // ************************ FVisit structures ***************************
327 // ************************ FVisit structures ***************************
328
329 uniontype Visit "Visit Node Info"
330 record VN "Visit Node Info"
331 Ref ref "which node it is";
332 Seq seq "order in which was visited";
333 end VN;
334 end Visit;
335
336 uniontype Visited "Visited structure is an AvlTree Id <-> Visit"
337 record V
338 VAvlTree tree;
339 Next next "the next visit node id";
340 end V;
341 end Visited;
342
343 public type VAvlKey = Id;
344 public type VAvlValue = Visit;
345
346 uniontype VAvlTree "The binary tree data structure for visited"
347 record VAVLTREENODE
348 Option<VAvlTreeValue> value "Value" ;
349 Integer height "heigth of tree, used for balancing";
350 Option<VAvlTree> left "left subtree" ;
351 Option<VAvlTree> right "right subtree" ;
352 end VAVLTREENODE;
353 end VAvlTree;
354
355 uniontype VAvlTreeValue "Each node in the binary tree can have a value associated with it."
356 record VAVLTREEVALUE
357 VAvlKey key "Key" ;
358 VAvlValue value "Value" ;
359 end VAVLTREEVALUE;
360 end VAvlTreeValue;
361
362 constant VAvlTree emptyVAvlTree = VAVLTREENODE(NONE(),0,NONE(),NONE());
363
364 // ************************ FGraph structures ***************************
365 // ************************ FGraph structures ***************************
366 // ************************ FGraph structures ***************************
367 // ************************ FGraph structures ***************************
368
369
370 constant Absyn.Path dummyTopModel = Absyn.IDENT("$EMPTY");
371 constant Extra dummyExtra = EXTRA(dummyTopModel);
372
373 constant String recordConstructorSuffix = "$recordconstructor";
374
375 constant String forScopeName="$for loop scope$" "a unique scope used in for equations";
376 constant String forIterScopeName="$foriter loop scope$" "a unique scope used in for iterators";
377 constant String parForScopeName="$pafor loop scope$" "a unique scope used in parfor loops";
378 constant String parForIterScopeName="$parforiter loop scope$" "a unique scope used in parfor iterators";
379 constant String matchScopeName="$match scope$" "a unique scope used by match expressions";
380 constant String caseScopeName="$case scope$" "a unique scope used by match expressions; to be removed when local decls are deprecated";
381 constant String patternTypeScope="$pattern type scope$" "a scope for specializing pattern types";
382 constant list<String> implicitScopeNames={forScopeName,forIterScopeName,parForScopeName,parForIterScopeName,matchScopeName,caseScopeName,patternTypeScope};
383
384 uniontype Extra "propagate more info into env if needed"
385 record EXTRA "propagate more info into env if needed"
386 Absyn.Path topModel;
387 end EXTRA;
388 end Extra;
389
390 uniontype Graph "graph"
391
392 record G "graph"
393 Top top "the top node";
394 Scope scope "current scope";
395 end G;
396
397 record EG "empty graph"
398 Name name;
399 end EG;
400
401 end Graph;
402
403 uniontype Top
404 record GTOP
405 Name name "name of the graph";
406 Ref node "the top node";
407 Extra extra "extra information";
408 end GTOP;
409 end Top;
410
411 public constant Id firstId = 0;
412
413 // ************************ Cache structures ***************************
414 // ************************ Cache structures ***************************
415 // ************************ Cache structures ***************************
416 // ************************ Cache structures ***************************
417
418 public type StructuralParameters = tuple<AvlSetCR.Tree,list<list<DAE.ComponentRef>>>;
419 public uniontype Cache
420 record CACHE
421 Option<Graph> initialGraph "and the initial environment";
422 Mutable<AvlTreePathFunction.Tree> functions "set of Option<DAE.Function>; NONE() means instantiation started; SOME() means it's finished";
423 StructuralParameters evaluatedParams "ht of prefixed crefs and a stack of evaluated but not yet prefix crefs";
424 Absyn.Path modelName "name of the model being instantiated";
425 end CACHE;
426
427 record NO_CACHE "no cache" end NO_CACHE;
428 end Cache;
429
430 public uniontype ScopeType
431 record FUNCTION_SCOPE end FUNCTION_SCOPE;
432 record CLASS_SCOPE end CLASS_SCOPE;
433 record PARALLEL_SCOPE end PARALLEL_SCOPE;
434 end ScopeType;
435
436 // ************************ functions ***************************
437
438
439 public function next
440 input Next inext;
441 output Next onext;
442 algorithm
443 ✗ onext := inext + 1;
444 end next;
445
446 public function emptyCache
447 "returns an empty cache"
448 output Cache cache;
449 protected
450 Mutable<AvlTreePathFunction.Tree> instFuncs;
451 StructuralParameters ht;
452 algorithm
453 669974 instFuncs := Mutable.create(AvlTreePathFunction.Tree.EMPTY());
454 ht := (AvlSetCR.EMPTY(),{});
455 669974 cache := CACHE(NONE(),instFuncs,ht,Absyn.IDENT("##UNDEFINED##"));
456 end emptyCache;
457
458
459 public function noCache "returns an empty cache"
460 output Cache cache;
461 algorithm
462 cache := NO_CACHE();
463 end noCache;
464
465 public function addEvaluatedCref
466 input Cache cache;
467 input SCode.Variability var;
468 input DAE.ComponentRef cr;
469 output Cache ocache;
470 algorithm
471 ocache := match (cache, var)
472 local
473 Option<Graph> initialGraph;
474 Mutable<AvlTreePathFunction.Tree> functions;
475 AvlSetCR.Tree ht;
476 list<list<DAE.ComponentRef>> st;
477 list<DAE.ComponentRef> crs;
478 Absyn.Path p;
479
480 case (CACHE(initialGraph,functions,(ht,crs::st),p), SCode.PARAM())
481 52319 then CACHE(initialGraph,functions,(ht,(cr::crs)::st),p);
482
483 case (CACHE(initialGraph,functions,(ht,{}),p), SCode.PARAM())
484 1680 then CACHE(initialGraph,functions,(ht,{cr}::{}),p);
485
486 else cache;
487
488 end match;
489 end addEvaluatedCref;
490
491 public function getEvaluatedParams
492 input Cache cache;
493 output AvlSetCR.Tree ht;
494 algorithm
495
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1560 times.
1560 CACHE(evaluatedParams=(ht,_)) := cache;
496 end getEvaluatedParams;
497
498 public function printNumStructuralParameters
499 input Cache cache;
500 protected
501 list<DAE.ComponentRef> crs;
502 algorithm
503 ✗ CACHE(evaluatedParams=(_,crs::_)) := cache;
504 ✗ print("printNumStructuralParameters: " + intString(listLength(crs)) + "\n");
505 end printNumStructuralParameters;
506
507 public function setCacheClassName
508 input Cache inCache;
509 input Absyn.Path p;
510 output Cache outCache;
511 algorithm
512 outCache := match inCache
513 local
514 Mutable<AvlTreePathFunction.Tree> ef;
515 StructuralParameters ht;
516 Option<Graph> igraph;
517
518 case CACHE(igraph,ef,ht,_)
519 1104 then CACHE(igraph,ef,ht,p);
520 else inCache;
521 end match;
522 end setCacheClassName;
523
524 public function isImplicitScope
525 input Name inName;
526 output Boolean isImplicit;
527 algorithm
528 isImplicit := matchcontinue inName
529
530 local
531 Name id;
532
533 4491525 case id then stringGet(id,1) == 36; // "$"
534
535 else false;
536
537 end matchcontinue;
538 end isImplicitScope;
539
540 public function getCachedInstFunc
541 "returns the function in the set"
542 input Cache inCache;
543 input Absyn.Path path;
544 output DAE.Function func;
545 algorithm
546 func := match inCache
547 local
548 Mutable<AvlTreePathFunction.Tree> ef;
549 case CACHE(functions=ef)
550 algorithm
551
3/4
✗ Branch 2 not taken.
✓ Branch 3 taken 71730 times.
✓ Branch 4 taken 66 times.
✓ Branch 5 taken 71664 times.
131522 SOME(func) := AvlTreePathFunction.get(Mutable.access(ef),path);
552 then func;
553 end match;
554 end getCachedInstFunc;
555
556 public function checkCachedInstFuncGuard
557 "succeeds if the FQ function is in the set of functions"
558 input Cache inCache;
559 input Absyn.Path path;
560 algorithm
561 () := match inCache
562 local
563 Mutable<AvlTreePathFunction.Tree> ef;
564 case CACHE(functions=ef) algorithm
565 39458 AvlTreePathFunction.get(Mutable.access(ef),path);
566 then ();
567 end match;
568 end checkCachedInstFuncGuard;
569
570 public function getFunctionTree
571 "Selector function"
572 input Cache cache;
573 output AvlTreePathFunction.Tree ft;
574 algorithm
575 ft := match cache
576 local
577 Mutable<AvlTreePathFunction.Tree> ef;
578 60320 case CACHE(functions = ef) then Mutable.access(ef);
579 else AvlTreePathFunction.Tree.EMPTY();
580 end match;
581 end getFunctionTree;
582
583 public function addCachedInstFuncGuard
584 "adds the FQ path to the set of instantiated functions as NONE().
585 This guards against recursive functions."
586 input Cache cache;
587 input Absyn.Path func "fully qualified function name";
588 output Cache outCache;
589 algorithm
590 outCache := matchcontinue(cache,func)
591 local
592 Mutable<AvlTreePathFunction.Tree> ef;
593
594 // Don't overwrite SOME() with NONE()
595 case (_, _)
596 algorithm
597 6849 checkCachedInstFuncGuard(cache, func);
598 // print("Func quard [there]: " + AbsynUtil.pathString(func) + "\n");
599 then cache;
600
601 case (CACHE(functions=ef),Absyn.FULLYQUALIFIED(_))
602 algorithm
603 6043 Mutable.update(ef,AvlTreePathFunction.add(Mutable.access(ef),func,NONE()));
604 // print("Func quard [new]: " + AbsynUtil.pathString(func) + "\n");
605 then cache;
606
607 // Non-FQ paths mean aliased functions; do not add these to the cache
608 case (_,_)
609 algorithm
610 // print("Func quard [unqual]: " + AbsynUtil.pathString(func) + "\n");
611 then (cache);
612
613 end matchcontinue;
614 end addCachedInstFuncGuard;
615
616 public function addDaeFunction
617 "adds the list<DAE.Function> to the set of instantiated functions"
618 input Cache inCache;
619 input list<DAE.Function> funcs "fully qualified function name";
620 output Cache outCache;
621 algorithm
622 outCache := match inCache
623 local
624 Mutable<AvlTreePathFunction.Tree> ef;
625
626 case CACHE(_,ef,_,_)
627 algorithm
628 13983 Mutable.update(ef,AvlTreePathFunction.addDaeFunction(funcs, Mutable.access(ef)));
629 then inCache;
630 else inCache;
631
632 end match;
633 end addDaeFunction;
634
635 public function addDaeExtFunction
636 "adds the external functions in list<DAE.Function> to the set of instantiated functions"
637 input Cache inCache;
638 input list<DAE.Function> funcs "fully qualified function name";
639 output Cache outCache;
640 algorithm
641 outCache := match inCache
642 local
643 Mutable<AvlTreePathFunction.Tree> ef;
644
645 case CACHE(_,ef,_,_)
646 algorithm
647 33843 Mutable.update(ef,AvlTreePathFunction.addDaeExtFunction(funcs, Mutable.access(ef)));
648 then inCache;
649 else inCache;
650
651 end match;
652 end addDaeExtFunction;
653
654 public function setCachedFunctionTree
655 input Cache inCache;
656 input AvlTreePathFunction.Tree inFunctions;
657 algorithm
658 () := match inCache
659 case CACHE()
660 algorithm
661 1227 Mutable.update(inCache.functions, inFunctions);
662 then ();
663 else ();
664 end match;
665 end setCachedFunctionTree;
666
667 public function isTyped
668 "author BZ 2008-06
669 This function checks wheter an InstStatus is typed or not.
670 Currently used by Inst.updateComponentsInEnv."
671 input Status is;
672 output Boolean b;
673 algorithm
674 b := match is
675 case VAR_UNTYPED() then false;
676 else true;
677 end match;
678 end isTyped;
679
680 public function isDeletedComp
681 "Returns true if the status indicates a deleted conditional component,
682 otherwise false."
683 input Status status;
684 output Boolean isDeleted;
685 algorithm
686 isDeleted := match status
687 case VAR_DELETED() then true;
688 else false;
689 end match;
690 end isDeletedComp;
691
692 public function getCachedInitialGraph "get the initial environment from the cache"
693 input Cache cache;
694 output Graph g;
695 algorithm
696 g := match cache
697 case CACHE(initialGraph = SOME(g)) then g;
698 end match;
699 end getCachedInitialGraph;
700
701 public function setCachedInitialGraph "set the initial environment in the cache"
702 input output Cache cache;
703 input Graph g;
704 algorithm
705 cache := match cache
706
707 case CACHE()
708 algorithm
709 2196 cache.initialGraph := SOME(g);
710 then cache;
711 else cache;
712
713 end match;
714 end setCachedInitialGraph;
715
716 public function getRecordConstructorName
717 "@author: adrpo
718 adds suffix FCore.recordConstructorSuffix ($recordconstructor)
719 to the given name. does not do it for MetaModelica"
720 input Name inName;
721 output Name outName;
722 algorithm
723 ✗ outName := if Config.acceptMetaModelicaGrammar() then inName else inName + recordConstructorSuffix;
724 end getRecordConstructorName;
725
726 public function getRecordConstructorPath
727 input Absyn.Path inPath;
728 output Absyn.Path outPath;
729 protected
730 Name lastId;
731 algorithm
732 ✗ if Config.acceptMetaModelicaGrammar() then
733 outPath := inPath;
734 else
735 ✗ lastId := AbsynUtil.pathLastIdent(inPath);
736 ✗ lastId := getRecordConstructorName(lastId);
737 ✗ outPath := AbsynUtil.pathSetLastIdent(inPath, lastId);
738 end if;
739 end getRecordConstructorPath;
740
741 annotation(__OpenModelica_Interface="frontend_dump");
742 end FCore;
743