Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 0.0% 0 / 0 / 169
Functions: -% 0 / 1 / 1
Branches: 0.0% 0 / 0 / 64

OMCompiler/Compiler/Script/TotalModelDebug.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 TotalModelDebug
37 "Implements a simple heuristic based on which identifiers are used in a class,
38 that can be used instead of the usual instantiation-based saveTotalModel when
39 that approach fails."
40
41 import Absyn;
42 import SCode;
43
44 protected
45 import AbsynUtil;
46 import SCodeUtil;
47 import UnorderedSet;
48 import Util;
49 import MetaModelica.Dangerous.*;
50
51 type UseTable = UnorderedSet<String>;
52
53 public
54 function getTotalModel
55 input output SCode.Program program;
56 input Absyn.Path classPath;
57 protected
58 UseTable used;
59 Integer prev_size = 0;
60 algorithm
61 // Create a new table and add each identifier in the path of the class.
62 ✗ used := UnorderedSet.new(stringHashDjb2, stringEq);
63 ✗ analysePath(classPath, used);
64
65 // Add some identifiers which can be implicitly used.
66 ✗ UnorderedSet.add("constructor", used);
67 ✗ UnorderedSet.add("destructor", used);
68
69 // Go through the program and add identifiers used in classes that are in
70 // the table. Repeat this until no more new identifiers are found.
71 ✗ while UnorderedSet.size(used) <> prev_size loop
72 ✗ prev_size := UnorderedSet.size(used);
73 ✗ analyseProgram(program, used);
74 end while;
75
76 // Save all classes whose name is in the table.
77 ✗ program := saveElements(program, used);
78 end getTotalModel;
79
80 function analyseProgram
81 input SCode.Program program;
82 input UseTable used;
83 algorithm
84 ✗ for e in program loop
85 ✗ analyseElement(e, used);
86 end for;
87 end analyseProgram;
88
89 function analyseElements
90 input list<SCode.Element> elements;
91 input UseTable used;
92 algorithm
93 ✗ for e in elements loop
94 ✗ analyseElement(e, used);
95 end for;
96 end analyseElements;
97
98 function analyseElement
99 input SCode.Element element;
100 input UseTable used;
101 algorithm
102 () := match element
103 case SCode.Element.IMPORT()
104 algorithm
105 ✗ analyseImport(element.imp, used);
106 then
107 ();
108
109 case SCode.Element.EXTENDS()
110 algorithm
111 ✗ analysePath(element.baseClassPath, used);
112 ✗ analyseMod(element.modifications, used);
113 then
114 ();
115
116 case SCode.Element.CLASS()
117 guard UnorderedSet.contains(element.name, used)
118 algorithm
119 ✗ if SCodeUtil.isOperatorRecord(element) then
120 ✗ analyseOperatorRecord(element, used);
121 end if;
122
123 ✗ analyseClassDef(element.classDef, used);
124 ✗ analysePrefixes(element.prefixes, used);
125 ✗ analyseComment(element.cmt, used);
126 then
127 ();
128
129 case SCode.Element.COMPONENT()
130 algorithm
131 ✗ analysePrefixes(element.prefixes, used);
132 ✗ analyseAttributes(element.attributes, used);
133 ✗ analyseTypeSpec(element.typeSpec, used);
134 ✗ analyseMod(element.modifications, used);
135 ✗ analyseExpOpt(element.condition, used);
136 ✗ analyseComment(element.comment, used);
137 then
138 ();
139
140 else ();
141 end match;
142 end analyseElement;
143
144 function analyseImport
145 input Absyn.Import imp;
146 input UseTable used;
147 algorithm
148 ✗ analysePath(AbsynUtil.importPath(imp), used);
149 end analyseImport;
150
151 function analyseClassDef
152 input SCode.ClassDef def;
153 input UseTable used;
154 algorithm
155 () := match def
156 case SCode.ClassDef.PARTS()
157 algorithm
158 ✗ analyseElements(def.elementLst, used);
159 ✗ analyseEquations(def.normalEquationLst, used);
160 ✗ analyseEquations(def.initialEquationLst, used);
161 ✗ analyseAlgorithms(def.normalAlgorithmLst, used);
162 ✗ analyseAlgorithms(def.initialAlgorithmLst, used);
163
164 ✗ if isSome(def.externalDecl) then
165 ✗ analyseExternalDecl(Util.getOption(def.externalDecl), used);
166 end if;
167 then
168 ();
169
170 case SCode.ClassDef.CLASS_EXTENDS()
171 algorithm
172 ✗ analyseMod(def.modifications, used);
173 ✗ analyseClassDef(def.composition, used);
174 then
175 ();
176
177 case SCode.ClassDef.DERIVED()
178 algorithm
179 ✗ analyseTypeSpec(def.typeSpec, used);
180 ✗ analyseMod(def.modifications, used);
181 ✗ analyseAttributes(def.attributes, used);
182 then
183 ();
184
185 else ();
186 end match;
187 end analyseClassDef;
188
189 function analyseExternalDecl
190 input SCode.ExternalDecl extDecl;
191 input UseTable used;
192 algorithm
193 ✗ if isSome(extDecl.annotation_) then
194 ✗ analyseAnnotation(Util.getOption(extDecl.annotation_), used);
195 end if;
196 end analyseExternalDecl;
197
198 function analyseOperatorRecord
199 input SCode.Element element;
200 input UseTable used;
201 algorithm
202 () := match element
203 case SCode.Element.CLASS()
204 algorithm
205 ✗ UnorderedSet.add(element.name, used);
206
207 ✗ for e in SCodeUtil.getClassElements(element) loop
208 ✗ analyseOperatorRecord(e, used);
209 end for;
210 then
211 ();
212
213 else ();
214 end match;
215 end analyseOperatorRecord;
216
217 function analyseAttributes
218 input SCode.Attributes attributes;
219 input UseTable used;
220 algorithm
221 ✗ analyseDims(attributes.arrayDims, used);
222 end analyseAttributes;
223
224 function analysePrefixes
225 input SCode.Prefixes prefixes;
226 input UseTable used;
227 algorithm
228 ✗ analyseReplaceable(prefixes.replaceablePrefix, used);
229 end analysePrefixes;
230
231 function analyseReplaceable
232 input SCode.Replaceable repl;
233 input UseTable used;
234 protected
235 SCode.ConstrainClass cc;
236 algorithm
237 () := match repl
238 case SCode.Replaceable.REPLACEABLE(cc = SOME(cc))
239 algorithm
240 ✗ analyseConstrainClass(cc, used);
241 then
242 ();
243
244 else ();
245 end match;
246 end analyseReplaceable;
247
248 function analyseConstrainClass
249 input SCode.ConstrainClass cc;
250 input UseTable used;
251 algorithm
252 ✗ analysePath(cc.constrainingClass, used);
253 ✗ analyseMod(cc.modifier, used);
254 ✗ analyseComment(cc.comment, used);
255 end analyseConstrainClass;
256
257 function analyseMod
258 input SCode.Mod mod;
259 input UseTable used;
260 algorithm
261 () := match mod
262 case SCode.Mod.MOD()
263 algorithm
264 ✗ for s in mod.subModLst loop
265 ✗ analyseMod(s.mod, used);
266 end for;
267
268 ✗ analyseExpOpt(mod.binding, used);
269 then
270 ();
271
272 case SCode.Mod.REDECL()
273 algorithm
274 ✗ analyseElement(mod.element, used);
275 then
276 ();
277
278 else ();
279 end match;
280 end analyseMod;
281
282 function analyseTypeSpec
283 input Absyn.TypeSpec ty;
284 input UseTable used;
285 algorithm
286 () := match ty
287 case Absyn.TypeSpec.TPATH()
288 algorithm
289 ✗ analysePath(ty.path, used);
290
291 ✗ if isSome(ty.arrayDim) then
292 ✗ analyseDims(Util.getOption(ty.arrayDim), used);
293 end if;
294 then
295 ();
296
297 case Absyn.TypeSpec.TCOMPLEX()
298 algorithm
299 ✗ analysePath(ty.path, used);
300
301 ✗ for t in ty.typeSpecs loop
302 ✗ analyseTypeSpec(t, used);
303 end for;
304
305 ✗ if isSome(ty.arrayDim) then
306 ✗ analyseDims(Util.getOption(ty.arrayDim), used);
307 end if;
308 then
309 ();
310 end match;
311 end analyseTypeSpec;
312
313 function analysePath
314 input Absyn.Path path;
315 input UseTable used;
316 algorithm
317 ✗ for i in AbsynUtil.pathToStringList(path) loop
318 ✗ UnorderedSet.add(i, used);
319 end for;
320 end analysePath;
321
322 function analyseEquations
323 input list<SCode.Equation> eqs;
324 input UseTable used;
325 algorithm
326 ✗ for e in eqs loop
327 ✗ analyseEquation(e, used);
328 end for;
329 end analyseEquations;
330
331 function analyseEquation
332 input SCode.Equation eq;
333 input UseTable used;
334 algorithm
335 () := match eq
336 case SCode.Equation.EQ_IF()
337 algorithm
338 ✗ analyseExpList(eq.condition, used);
339
340 ✗ for b in eq.thenBranch loop
341 ✗ analyseEquations(b, used);
342 end for;
343
344 ✗ analyseEquations(eq.elseBranch, used);
345 ✗ analyseComment(eq.comment, used);
346 then
347 ();
348
349 case SCode.Equation.EQ_EQUALS()
350 algorithm
351 ✗ analyseExp(eq.expLeft, used);
352 ✗ analyseExp(eq.expRight, used);
353 ✗ analyseComment(eq.comment, used);
354 then
355 ();
356
357 case SCode.Equation.EQ_PDE()
358 algorithm
359 ✗ analyseExp(eq.expLeft, used);
360 ✗ analyseExp(eq.expRight, used);
361 ✗ analyseComment(eq.comment, used);
362 then
363 ();
364
365 case SCode.Equation.EQ_CONNECT()
366 algorithm
367 ✗ analyseCref(eq.crefLeft, used);
368 ✗ analyseCref(eq.crefRight, used);
369 ✗ analyseComment(eq.comment, used);
370 then
371 ();
372
373 case SCode.Equation.EQ_FOR()
374 algorithm
375 ✗ analyseExpOpt(eq.range, used);
376 ✗ analyseEquations(eq.eEquationLst, used);
377 ✗ analyseComment(eq.comment, used);
378 then
379 ();
380
381 case SCode.Equation.EQ_WHEN()
382 algorithm
383 ✗ analyseExp(eq.condition, used);
384 ✗ analyseEquations(eq.eEquationLst, used);
385
386 ✗ for b in eq.elseBranches loop
387 ✗ analyseExp(Util.tuple21(b), used);
388 ✗ analyseEquations(Util.tuple22(b), used);
389 end for;
390
391 ✗ analyseComment(eq.comment, used);
392 then
393 ();
394
395 case SCode.Equation.EQ_ASSERT()
396 algorithm
397 ✗ analyseExp(eq.condition, used);
398 ✗ analyseExp(eq.message, used);
399 ✗ analyseExp(eq.level, used);
400 ✗ analyseComment(eq.comment, used);
401 then
402 ();
403
404 case SCode.Equation.EQ_TERMINATE()
405 algorithm
406 ✗ analyseExp(eq.message, used);
407 ✗ analyseComment(eq.comment, used);
408 then
409 ();
410
411 case SCode.Equation.EQ_REINIT()
412 algorithm
413 ✗ analyseExp(eq.cref, used);
414 ✗ analyseExp(eq.expReinit, used);
415 ✗ analyseComment(eq.comment, used);
416 then
417 ();
418
419 case SCode.Equation.EQ_NORETCALL()
420 algorithm
421 ✗ analyseExp(eq.exp, used);
422 ✗ analyseComment(eq.comment, used);
423 then
424 ();
425 end match;
426 end analyseEquation;
427
428 function analyseAlgorithms
429 input list<SCode.AlgorithmSection> algs;
430 input UseTable used;
431 algorithm
432 ✗ for a in algs loop
433 ✗ analyseAlgorithm(a, used);
434 end for;
435 end analyseAlgorithms;
436
437 function analyseAlgorithm
438 input SCode.AlgorithmSection alg;
439 input UseTable used;
440 algorithm
441 ✗ analyseStatements(alg.statements, used);
442 end analyseAlgorithm;
443
444 function analyseStatements
445 input list<SCode.Statement> stmts;
446 input UseTable used;
447 algorithm
448 ✗ for s in stmts loop
449 ✗ analyseStatement(s, used);
450 end for;
451 end analyseStatements;
452
453 function analyseStatement
454 input SCode.Statement stmt;
455 input UseTable used;
456 algorithm
457 () := match stmt
458 case SCode.Statement.ALG_ASSIGN()
459 algorithm
460 ✗ analyseExp(stmt.assignComponent, used);
461 ✗ analyseExp(stmt.value, used);
462 ✗ analyseComment(stmt.comment, used);
463 then
464 ();
465
466 case SCode.Statement.ALG_IF()
467 algorithm
468 ✗ analyseExp(stmt.boolExpr, used);
469 ✗ analyseStatements(stmt.trueBranch, used);
470
471 ✗ for b in stmt.elseIfBranch loop
472 ✗ analyseExp(Util.tuple21(b), used);
473 ✗ analyseStatements(Util.tuple22(b), used);
474 end for;
475
476 ✗ analyseStatements(stmt.elseBranch, used);
477 ✗ analyseComment(stmt.comment, used);
478 then
479 ();
480
481 case SCode.Statement.ALG_FOR()
482 algorithm
483 ✗ analyseExpOpt(stmt.range, used);
484 ✗ analyseStatements(stmt.forBody, used);
485 ✗ analyseComment(stmt.comment, used);
486 then
487 ();
488
489 case SCode.Statement.ALG_PARFOR()
490 algorithm
491 ✗ analyseExpOpt(stmt.range, used);
492 ✗ analyseStatements(stmt.parforBody, used);
493 ✗ analyseComment(stmt.comment, used);
494 then
495 ();
496
497 case SCode.Statement.ALG_WHILE()
498 algorithm
499 ✗ analyseExp(stmt.boolExpr, used);
500 ✗ analyseStatements(stmt.whileBody, used);
501 ✗ analyseComment(stmt.comment, used);
502 then
503 ();
504
505 case SCode.Statement.ALG_WHEN_A()
506 algorithm
507 ✗ for b in stmt.branches loop
508 ✗ analyseExp(Util.tuple21(b), used);
509 ✗ analyseStatements(Util.tuple22(b), used);
510 end for;
511
512 ✗ analyseComment(stmt.comment, used);
513 then
514 ();
515
516 case SCode.Statement.ALG_ASSERT()
517 algorithm
518 ✗ analyseExp(stmt.condition, used);
519 ✗ analyseExp(stmt.message, used);
520 ✗ analyseExp(stmt.level, used);
521 ✗ analyseComment(stmt.comment, used);
522 then
523 ();
524
525 case SCode.Statement.ALG_TERMINATE()
526 algorithm
527 ✗ analyseExp(stmt.message, used);
528 ✗ analyseComment(stmt.comment, used);
529 then
530 ();
531
532 case SCode.Statement.ALG_REINIT()
533 algorithm
534 ✗ analyseExp(stmt.cref, used);
535 ✗ analyseExp(stmt.newValue, used);
536 ✗ analyseComment(stmt.comment, used);
537 then
538 ();
539
540 case SCode.Statement.ALG_NORETCALL()
541 algorithm
542 ✗ analyseExp(stmt.exp, used);
543 ✗ analyseComment(stmt.comment, used);
544 then
545 ();
546
547 case SCode.Statement.ALG_RETURN()
548 algorithm
549 ✗ analyseComment(stmt.comment, used);
550 then
551 ();
552
553 case SCode.Statement.ALG_BREAK()
554 algorithm
555 ✗ analyseComment(stmt.comment, used);
556 then
557 ();
558
559 case SCode.Statement.ALG_CONTINUE()
560 algorithm
561 ✗ analyseComment(stmt.comment, used);
562 then
563 ();
564
565 else ();
566 end match;
567 end analyseStatement;
568
569 function analyseDims = analyseSubscripts;
570
571 function analyseSubscripts
572 input list<Absyn.Subscript> subs;
573 input UseTable used;
574 algorithm
575 ✗ for s in subs loop
576 ✗ analyseSubscript(s, used);
577 end for;
578 end analyseSubscripts;
579
580 function analyseSubscript
581 input Absyn.Subscript sub;
582 input UseTable used;
583 algorithm
584 () := match sub
585 case Absyn.Subscript.SUBSCRIPT()
586 algorithm
587 ✗ analyseExp(sub.subscript, used);
588 then
589 ();
590
591 else ();
592 end match;
593 end analyseSubscript;
594
595 function analyseExpOpt
596 input Option<Absyn.Exp> exp;
597 input UseTable used;
598 algorithm
599 ✗ if isSome(exp) then
600 ✗ analyseExp(Util.getOption(exp), used);
601 end if;
602 end analyseExpOpt;
603
604 function analyseExpList
605 input list<Absyn.Exp> expl;
606 input UseTable used;
607 algorithm
608 ✗ for e in expl loop
609 ✗ analyseExp(e, used);
610 end for;
611 end analyseExpList;
612
613 function analyseExp
614 input Absyn.Exp exp;
615 input UseTable used;
616 algorithm
617 ✗ AbsynUtil.traverseExp(exp, analyseExpTraverse, used);
618 end analyseExp;
619
620 function analyseExpTraverse
621 input output Absyn.Exp exp;
622 input output UseTable used;
623 algorithm
624 () := match exp
625 case Absyn.Exp.CREF()
626 algorithm
627 ✗ analyseCref(exp.componentRef, used);
628 then
629 ();
630
631 case Absyn.Exp.CALL()
632 algorithm
633 ✗ analyseCref(exp.function_, used);
634 then
635 ();
636
637 case Absyn.Exp.PARTEVALFUNCTION()
638 algorithm
639 ✗ analyseCref(exp.function_, used);
640 then
641 ();
642
643 else ();
644 end match;
645 end analyseExpTraverse;
646
647 function analyseCref
648 input Absyn.ComponentRef cref;
649 input UseTable used;
650 input Boolean includeLast = true;
651 algorithm
652 () := match cref
653 case Absyn.ComponentRef.CREF_FULLYQUALIFIED()
654 algorithm
655 ✗ analyseCref(cref.componentRef, used, includeLast);
656 then
657 ();
658
659 case Absyn.ComponentRef.CREF_QUAL()
660 algorithm
661 ✗ UnorderedSet.add(cref.name, used);
662 ✗ analyseSubscripts(cref.subscripts, used);
663 ✗ analyseCref(cref.componentRef, used, includeLast);
664 then
665 ();
666
667 case Absyn.ComponentRef.CREF_IDENT()
668 algorithm
669 ✗ if includeLast then
670 ✗ UnorderedSet.add(cref.name, used);
671 end if;
672
673 ✗ analyseSubscripts(cref.subscripts, used);
674 then
675 ();
676
677 else ();
678 end match;
679 end analyseCref;
680
681 function analyseComment
682 input SCode.Comment comment;
683 input UseTable used;
684 algorithm
685 ✗ if isSome(comment.annotation_) then
686 ✗ analyseAnnotation(Util.getOption(comment.annotation_), used);
687 end if;
688 end analyseComment;
689
690 function analyseAnnotation
691 input SCode.Annotation ann;
692 input UseTable used;
693 algorithm
694 ✗ analyseMod(ann.modification, used);
695 end analyseAnnotation;
696
697 function saveElements
698 input list<SCode.Element> elements;
699 input UseTable used;
700 output list<SCode.Element> outElements = {};
701 algorithm
702 ✗ for e in elements loop
703 ✗ outElements := saveElement(e, used, outElements);
704 end for;
705
706 ✗ outElements := listReverseInPlace(outElements);
707 end saveElements;
708
709 function saveElement
710 input SCode.Element element;
711 input UseTable used;
712 input output list<SCode.Element> elements;
713 protected
714 SCode.Element elem = element;
715 algorithm
716 elements := match elem
717 case SCode.Element.CLASS()
718 guard UnorderedSet.contains(elem.name, used)
719 algorithm
720 ✗ elem.classDef := saveClassDef(elem.classDef, used);
721 then
722 elem :: elements;
723
724 case SCode.Element.CLASS() then elements;
725
726 case SCode.Element.EXTENDS()
727 guard AbsynUtil.pathContains(elem.baseClassPath, "Icons")
728 then elements;
729
730 else element :: elements;
731 end match;
732 end saveElement;
733
734 function saveClassDef
735 input output SCode.ClassDef def;
736 input UseTable used;
737 algorithm
738 () := match def
739 case SCode.ClassDef.PARTS()
740 algorithm
741 ✗ def.elementLst := saveElements(def.elementLst, used);
742 then
743 ();
744
745 case SCode.ClassDef.CLASS_EXTENDS()
746 algorithm
747 ✗ def.composition := saveClassDef(def.composition, used);
748 then
749 ();
750
751 else ();
752 end match;
753 end saveClassDef;
754
755 annotation(__OpenModelica_Interface="backend_tools");
756 end TotalModelDebug;
757