Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 83.7% 36 / 0 / 43
Functions: -% 0 / 1 / 1
Branches: 81.8% 18 / 0 / 22

OMCompiler/Compiler/FrontEnd/SCodeInstUtil.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 SCodeInstUtil
37 " file: SCodeInstUtil.mo
38 package: SCodeInstUtil
39 description: Utility functions for the SCode intermediate form for calling from the frontend"
40
41 import Absyn;
42 import SCode;
43
44 protected
45
46 import List;
47 import SCodeDump;
48 import SCodeUtil;
49
50 protected function constantBindingOrNone
51 "@author: adrpo
52 keeps the constant binding and if not returns none"
53 input Option<Absyn.Exp> inBinding;
54 output Option<Absyn.Exp> outBinding;
55 algorithm
56 outBinding := match inBinding
57 local
58 Absyn.Exp e;
59
60 // keep it
61 case SOME(e)
62
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 4 times.
9 then if listEmpty(AbsynUtil.getCrefFromExp(e, true, true)) then inBinding else NONE();
63 // else
64 else NONE();
65 end match;
66 end constantBindingOrNone;
67
68 public function removeNonConstantBindingsKeepRedeclares
69 "@author: adrpo
70 keeps the redeclares and removes all non-constant bindings!
71 if onlyRedeclare is true then bindings are removed completely!"
72 input SCode.Mod inMod;
73 input Boolean onlyRedeclares;
74 output SCode.Mod outMod;
75 algorithm
76 outMod := match inMod
77 local
78 list<SCode.SubMod> sl;
79 SCode.Final fp;
80 SCode.Each ep;
81 SourceInfo i;
82 Option<Absyn.Exp> binding;
83 Option<String> cmt;
84
85 case SCode.MOD(fp, ep, sl, binding, cmt, i)
86 algorithm
87
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
20 binding := if onlyRedeclares then NONE() else constantBindingOrNone(binding);
88 20 sl := removeNonConstantBindingsKeepRedeclaresFromSubMod(sl, onlyRedeclares);
89 20 then
90 SCode.MOD(fp, ep, sl, binding, cmt, i);
91
92 case SCode.REDECL() then inMod;
93
94 else inMod;
95
96 end match;
97 end removeNonConstantBindingsKeepRedeclares;
98
99 protected function removeNonConstantBindingsKeepRedeclaresFromSubMod
100 "@author: adrpo
101 removes the non-constant bindings in submods and keeps the redeclares"
102 input list<SCode.SubMod> inSl;
103 input Boolean onlyRedeclares;
104 output list<SCode.SubMod> outSl;
105 algorithm
106 outSl := match inSl
107 local
108 String n;
109 list<SCode.SubMod> sl,rest;
110 SCode.Mod m;
111
112 case {} then {};
113
114 case SCode.NAMEMOD(n, m)::rest
115 algorithm
116 10 m := removeNonConstantBindingsKeepRedeclares(m, onlyRedeclares);
117 10 sl := removeNonConstantBindingsKeepRedeclaresFromSubMod(rest, onlyRedeclares);
118 10 then
119 SCode.NAMEMOD(n, m)::sl;
120
121 end match;
122 end removeNonConstantBindingsKeepRedeclaresFromSubMod;
123
124 public function addRedeclareAsElementsToExtends
125 "add the redeclare-as-element elements to extends"
126 input list<SCode.Element> inElements;
127 input list<SCode.Element> redeclareElements;
128 output list<SCode.Element> outExtendsElements;
129 algorithm
130 outExtendsElements := match (inElements, redeclareElements)
131 local
132 SCode.Element el;
133 list<SCode.Element> redecls, rest, out;
134 Absyn.Path baseClassPath;
135 SCode.Visibility visibility;
136 SCode.Mod mod;
137 Option<SCode.Annotation> ann "the extends annotation";
138 SourceInfo info;
139 SCode.Mod redeclareMod;
140 list<SCode.SubMod> submods;
141
142 // empty, return the same
143 case (_, {}) then inElements;
144
145 // empty elements
146 case ({}, _) then {};
147
148 // we got some
149 case (SCode.EXTENDS(baseClassPath, visibility, mod, ann, info)::rest, redecls)
150 algorithm
151 411 submods := makeElementsIntoSubMods(SCode.NOT_FINAL(), SCode.NOT_EACH(), redecls);
152 411 redeclareMod := SCode.MOD(SCode.NOT_FINAL(), SCode.NOT_EACH(), submods, NONE(), NONE(), info);
153 411 mod := SCodeUtil.mergeSCodeMods(redeclareMod, mod);
154 411 out := addRedeclareAsElementsToExtends(rest, redecls);
155 411 then
156 SCode.EXTENDS(baseClassPath, visibility, mod, ann, info)::out;
157
158 // ignore non-extends
159 case (el::rest, redecls)
160 algorithm
161 8811 out := addRedeclareAsElementsToExtends(rest, redecls);
162 then
163 el::out;
164
165 end match;
166 end addRedeclareAsElementsToExtends;
167
168 protected function makeElementsIntoSubMods
169 "transform elements into submods with named mods"
170 input SCode.Final inFinal;
171 input SCode.Each inEach;
172 input list<SCode.Element> inElements;
173 output list<SCode.SubMod> outSubMods;
174 algorithm
175 outSubMods := match (inFinal, inEach, inElements)
176 local
177 SCode.Element el;
178 list<SCode.Element> rest;
179 SCode.Final f;
180 SCode.Each e;
181 SCode.Ident n;
182 list<SCode.SubMod> newSubMods;
183
184 // empty
185 case (_, _, {}) then {};
186
187 // class extends, error!
188 case (f, e, (el as SCode.CLASS(classDef = SCode.CLASS_EXTENDS()))::rest)
189 algorithm
190 // print an error here
191 ✗ print("- AbsynToSCode.makeElementsIntoSubMods ignoring class-extends redeclare-as-element: " + SCodeDump.unparseElementStr(el,SCodeDump.defaultOptions) + "\n");
192 // recurse
193 ✗ newSubMods := makeElementsIntoSubMods(f, e, rest);
194 then
195 newSubMods;
196
197 // component
198 case (f, e, (el as SCode.COMPONENT(name = n))::rest)
199 algorithm
200 // recurse
201 ✗ newSubMods := makeElementsIntoSubMods(f, e, rest);
202 ✗ then
203 SCode.NAMEMOD(n,SCode.REDECL(f,e,el))::newSubMods;
204
205 // class
206 case (f, e, (el as SCode.CLASS(name = n))::rest)
207 algorithm
208 // recurse
209 3559 newSubMods := makeElementsIntoSubMods(f, e, rest);
210 3559 then
211 SCode.NAMEMOD(n,SCode.REDECL(f,e,el))::newSubMods;
212
213 // rest
214 case (f, e, el::rest)
215 algorithm
216 // print an error here
217 ✗ print("- AbsynToSCode.makeElementsIntoSubMods ignoring redeclare-as-element redeclaration: " + SCodeDump.unparseElementStr(el,SCodeDump.defaultOptions) + "\n");
218 // recurse
219 ✗ newSubMods := makeElementsIntoSubMods(f, e, rest);
220 then
221 newSubMods;
222 end match;
223 end makeElementsIntoSubMods;
224
225 protected function removeReferenceInBinding
226 "@author: adrpo
227 remove the binding that contains a cref"
228 input Option<Absyn.Exp> inBinding;
229 input Absyn.ComponentRef inCref;
230 output Option<Absyn.Exp> outBinding;
231 algorithm
232 outBinding := match inBinding
233 local
234 Absyn.Exp e;
235 list<Absyn.ComponentRef> crlst1, crlst2;
236
237 // if cref is not present keep the binding!
238 case SOME(e)
239 algorithm
240 24867 crlst1 := AbsynUtil.getCrefFromExp(e, true, true);
241 24867 crlst2 := AbsynUtil.removeCrefFromCrefs(crlst1, inCref);
242
2/2
✓ Branch 2 taken 2496 times.
✓ Branch 3 taken 22371 times.
24867 then if intEq(listLength(crlst1), listLength(crlst2)) then inBinding else NONE();
243 // else
244 else NONE();
245 end match;
246 end removeReferenceInBinding;
247
248 public function removeSelfReferenceFromMod
249 "@author: adrpo
250 remove the self reference from mod!"
251 input SCode.Mod inMod;
252 input Absyn.ComponentRef inCref;
253 output SCode.Mod outMod;
254 algorithm
255 outMod := match inMod
256 local
257 list<SCode.SubMod> sl;
258 SCode.Final fp;
259 SCode.Each ep;
260 SourceInfo i;
261 Option<Absyn.Exp> binding;
262 Option<String> cmt;
263
264 case SCode.MOD(fp, ep, sl, binding, cmt, i)
265 algorithm
266 27352 binding := removeReferenceInBinding(binding, inCref);
267 27352 sl := removeSelfReferenceFromSubMod(sl, inCref);
268 27352 then
269 SCode.MOD(fp, ep, sl, binding, cmt, i);
270
271 case SCode.REDECL() then inMod;
272
273 else inMod;
274
275 end match;
276 end removeSelfReferenceFromMod;
277
278 protected function removeSelfReferenceFromSubMod
279 "@author: adrpo
280 removes the self references from a submod"
281 input list<SCode.SubMod> inSl;
282 input Absyn.ComponentRef inCref;
283 output list<SCode.SubMod> outSl;
284 algorithm
285 outSl := match inSl
286 local
287 String n;
288 list<SCode.SubMod> sl,rest;
289 SCode.Mod m;
290
291 case {} then {};
292
293 case SCode.NAMEMOD(n, m)::rest
294 algorithm
295 24857 m := removeSelfReferenceFromMod(m, inCref);
296 24857 sl := removeSelfReferenceFromSubMod(rest, inCref);
297 24857 then
298 SCode.NAMEMOD(n, m)::sl;
299
300 end match;
301 end removeSelfReferenceFromSubMod;
302
303 protected function expandEnumerationSubMod
304 input SCode.SubMod inSubMod;
305 input Boolean inChanged;
306 output SCode.SubMod outSubMod;
307 output Boolean outChanged;
308 algorithm
309 (outSubMod, outChanged) := match inSubMod
310 local
311 SCode.Mod mod, mod1;
312 SCode.Ident ident;
313 case SCode.NAMEMOD(ident=ident, mod=mod)
314 algorithm
315 986338 mod1 := expandEnumerationMod(mod);
316
3/4
✓ Branch 0 taken 986337 times.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 986337 times.
✗ Branch 3 not taken.
1972675 then
317 if referenceEq(mod, mod1) then (inSubMod, inChanged) else (SCode.NAMEMOD(ident, mod1), true);
318 ✗ else
319 (inSubMod, inChanged);
320 end match;
321 end expandEnumerationSubMod;
322
323 public function expandEnumerationMod
324 input SCode.Mod inMod;
325 output SCode.Mod outMod;
326 protected
327 SCode.Final f;
328 SCode.Each e;
329 SCode.Element el, el1;
330 list<SCode.SubMod> submod;
331 Option<Absyn.Exp> binding;
332 SourceInfo info;
333 Boolean changed;
334 Option<String> cmt;
335 algorithm
336 outMod := match inMod
337 case SCode.REDECL(f, e, el)
338 algorithm
339 637 el1 := expandEnumerationClass(el);
340
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 636 times.
637 then
341 if referenceEq(el, el1) then inMod else SCode.REDECL(f, e, el1);
342
343 case SCode.MOD(f, e, submod, binding, cmt, info)
344 algorithm
345 2532294 (submod, changed) := List.mapFold(submod, expandEnumerationSubMod, false);
346
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 2532293 times.
2532294 then if changed then SCode.MOD(f, e, submod, binding, cmt, info) else inMod;
347
348 else inMod;
349 end match;
350 end expandEnumerationMod;
351
352 public function expandEnumerationClass
353 "@author: PA, adrpo
354 this function expands the enumeration from a list into a class with components
355 if the class is not an enumeration is kept as it is"
356 input SCode.Element inElement;
357 output SCode.Element outElement;
358 algorithm
359 outElement := match inElement
360 local
361 SCode.Ident n;
362 list<SCode.Enum> l;
363 SCode.Comment cmt;
364 SourceInfo info;
365 SCode.Element c;
366 SCode.Prefixes prefixes;
367 SCode.Mod m, m1;
368 Absyn.Path p;
369 SCode.Visibility v;
370 Option<SCode.Annotation> ann;
371
372 case SCode.CLASS(name = n,restriction = SCode.R_TYPE(), prefixes = prefixes,
373 classDef = SCode.ENUMERATION(enumLst=l),cmt=cmt,info = info)
374 algorithm
375 188040 c := expandEnumeration(n, l, prefixes, cmt, info);
376 then
377 c;
378
379 case SCode.EXTENDS(baseClassPath = p, visibility = v, modifications = m, ann = ann, info = info)
380 algorithm
381
382 32720 m1 := expandEnumerationMod(m);
383
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32720 times.
32720 then
384 if referenceEq(m, m1) then inElement else SCode.EXTENDS(p, v, m1, ann, info);
385
386 else inElement;
387
388 end match;
389 end expandEnumerationClass;
390
391 public function expandEnumeration
392 "author: PA
393 This function takes an Ident and list of strings, and returns an enumeration class."
394 input SCode.Ident n;
395 input list<SCode.Enum> l;
396 input SCode.Prefixes prefixes;
397 input SCode.Comment cmt;
398 input SourceInfo info;
399 output SCode.Element outClass;
400 algorithm
401 188040 outClass :=
402 SCode.CLASS(
403 n,
404 prefixes,
405 SCode.NOT_ENCAPSULATED(),
406 SCode.NOT_PARTIAL(),
407 SCode.R_ENUMERATION(),
408 makeEnumParts(l, info),
409 cmt,
410 info);
411 end expandEnumeration;
412
413 protected function makeEnumParts
414 input list<SCode.Enum> inEnumLst;
415 input SourceInfo info;
416 output SCode.ClassDef classDef;
417 algorithm
418 188040 classDef := SCode.PARTS(makeEnumComponents(inEnumLst, info),{},{},{},{},{},{},NONE());
419 end makeEnumParts;
420
421 protected function makeEnumComponents
422 "Translates a list of Enums to a list of elements of type EnumType."
423 input list<SCode.Enum> inEnumLst;
424 input SourceInfo info;
425 output list<SCode.Element> outSCodeElementLst;
426 algorithm
427
4/4
✓ Branch 0 taken 898634 times.
✓ Branch 1 taken 188040 times.
✓ Branch 2 taken 898634 times.
✓ Branch 3 taken 188040 times.
1086674 outSCodeElementLst := list(SCodeUtil.makeEnumType(e,info) for e in inEnumLst);
428 end makeEnumComponents;
429
430 annotation(__OpenModelica_Interface="frontend_inst");
431 end SCodeInstUtil;
432