Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 87.2% 41 / 0 / 47
Functions: -% 0 / 1 / 1
Branches: 82.4% 28 / 0 / 34

OMCompiler/Compiler/FrontEnd/MetaUtil.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 MetaUtil
37 " file: MetaUtil.mo
38 package: MetaUtil
39 description: Different MetaModelica extension functions.
40 "
41
42 import Absyn;
43 import AbsynUtil;
44
45 protected
46
47 import Config;
48 import Error;
49 import List;
50 import MetaModelica.Dangerous;
51
52 public function createMetaClassesInProgram
53 "This function goes through a program and changes all records inside of
54 uniontype into metarecords. It also makes a copy of them outside of the
55 uniontype where they are found so that they can be used without prefixing
56 with the uniontype name."
57 input Absyn.Program inProgram;
58 output Absyn.Program outProgram = inProgram;
59 protected
60 list<Absyn.Class> classes = {}, meta_classes;
61 algorithm
62
2/2
✓ Branch 1 taken 7866 times.
✓ Branch 2 taken 294 times.
8160 if not Config.acceptMetaModelicaGrammar() then
63 7866 return;
64 end if;
65
66 () := match outProgram
67 case Absyn.PROGRAM()
68 algorithm
69
2/2
✓ Branch 0 taken 33297 times.
✓ Branch 1 taken 294 times.
33591 for c in outProgram.classes loop
70 33297 (c, meta_classes) := createMetaClasses(c);
71 33297 classes := c :: listAppend(meta_classes, classes);
72 end for;
73
74 294 outProgram.classes := Dangerous.listReverseInPlace(classes);
75 // print(Dump.unparseStr(outProgram));
76 then
77 ();
78
79 else ();
80 end match;
81 end createMetaClassesInProgram;
82
83 protected function createMetaClasses
84 "Takes a class, and if it's a uniontype it converts all records inside it into
85 metarecords and returns the updated uniontype and a list of all metarecords.
86 It then recursively applies the same operation to all subclasses."
87 input Absyn.Class inClass;
88 output Absyn.Class outClass = inClass;
89 output list<Absyn.Class> outMetaClasses = {};
90 protected
91 Absyn.ClassDef body;
92 list<Absyn.ClassPart> parts;
93 algorithm
94 () := match outClass
95 local
96 list<String> typeVars;
97 case Absyn.CLASS(restriction = Absyn.R_UNIONTYPE(),
98 body = body as Absyn.PARTS(classParts = parts))
99 algorithm
100 2623 (parts, outMetaClasses) := fixClassParts(parts, outClass.name, body.typeVars);
101 2623 body.classParts := parts;
102 2623 outClass.body := body;
103 then
104 ();
105
106 case Absyn.CLASS(restriction = Absyn.R_UNIONTYPE(),
107 body = body as Absyn.CLASS_EXTENDS(parts = parts))
108 algorithm
109 ✗ (parts, outMetaClasses) := fixClassParts(parts, outClass.name, {});
110 ✗ body.parts := parts;
111 ✗ outClass.body := body;
112 then
113 ();
114
115 else ();
116 end match;
117
118 () := match outClass
119 case Absyn.CLASS(body = body as Absyn.PARTS())
120 algorithm
121 230752 body.classParts := createMetaClassesFromClassParts(body.classParts);
122 230752 outClass.body := body;
123 then
124 ();
125
126 case Absyn.CLASS(body = body as Absyn.CLASS_EXTENDS())
127 algorithm
128 522 body.parts := createMetaClassesFromClassParts(body.parts);
129 522 outClass.body := body;
130 then
131 ();
132
133 else ();
134 end match;
135 end createMetaClasses;
136
137 protected function createMetaClassesFromClassParts
138 input list<Absyn.ClassPart> inClassParts;
139 output list<Absyn.ClassPart> outClassParts;
140 algorithm
141
4/4
✓ Branch 0 taken 560602 times.
✓ Branch 1 taken 231274 times.
✓ Branch 2 taken 560602 times.
✓ Branch 3 taken 231274 times.
791876 outClassParts := list(match p
142 case Absyn.PUBLIC()
143 algorithm
144 278693 p.contents := createMetaClassesFromElementItems(p.contents);
145 then
146 p;
147
148 case Absyn.PROTECTED()
149 algorithm
150 78633 p.contents := createMetaClassesFromElementItems(p.contents);
151 then
152 p;
153
154 else p;
155 end match for p in inClassParts);
156 end createMetaClassesFromClassParts;
157
158 protected function createMetaClassesFromElementItems
159 input list<Absyn.ElementItem> inElementItems;
160 output list<Absyn.ElementItem> outElementItems = {};
161 protected
162 Absyn.Class cls;
163 list<Absyn.Class> meta_classes;
164 list<Absyn.ElementItem> els;
165 algorithm
166
2/2
✓ Branch 1 taken 1146661 times.
✓ Branch 2 taken 357326 times.
1503987 for e in listReverse(inElementItems) loop
167 e := match e
168 case Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification =
169 Absyn.CLASSDEF(class_ = cls)))
170 algorithm
171 207750 (cls, meta_classes) := createMetaClasses(cls);
172
4/4
✓ Branch 0 taken 7735 times.
✓ Branch 1 taken 207750 times.
✓ Branch 2 taken 7735 times.
✓ Branch 3 taken 207750 times.
215485 els := list(setElementItemClass(e, c) for c in meta_classes);
173 207750 outElementItems := listAppend(els, outElementItems);
174 207750 then
175 setElementItemClass(e, cls);
176
177 else e;
178 end match;
179
180 outElementItems := e :: outElementItems;
181 end for;
182 end createMetaClassesFromElementItems;
183
184 protected function setElementItemClass
185 input Absyn.ElementItem inElementItem;
186 input Absyn.Class inClass;
187 output Absyn.ElementItem outElementItem = inElementItem;
188 algorithm
189 outElementItem := match outElementItem
190 local
191 Absyn.Element e;
192 Absyn.ElementSpec es;
193
194 case Absyn.ELEMENTITEM(element = e as Absyn.ELEMENT(specification = es as Absyn.CLASSDEF()))
195 algorithm
196 223690 es.class_ := inClass;
197 223690 e.specification := es;
198 223690 outElementItem.element := e;
199 then
200 outElementItem;
201
202 else outElementItem;
203 end match;
204 end setElementItemClass;
205
206 protected function convertElementToClass
207 input Absyn.ElementItem inElementItem;
208 output Absyn.Class outClass;
209 algorithm
210 ✗ Absyn.ELEMENTITEM(element = Absyn.ELEMENT(
211 specification = Absyn.CLASSDEF(class_ = outClass))) := inElementItem;
212 end convertElementToClass;
213
214 protected function fixClassParts
215 input list<Absyn.ClassPart> inClassParts;
216 input Absyn.Ident inClassName;
217 input list<String> typeVars;
218 output list<Absyn.ClassPart> outClassParts;
219 output list<Absyn.Class> outMetaClasses = {};
220 protected
221 list<Absyn.Class> meta_classes;
222 list<Absyn.ElementItem> els;
223 algorithm
224
4/4
✓ Branch 0 taken 2813 times.
✓ Branch 1 taken 2623 times.
✓ Branch 2 taken 2813 times.
✓ Branch 3 taken 2623 times.
5436 outClassParts := list(match p
225 case Absyn.PUBLIC()
226 algorithm
227 2733 (els, meta_classes) := fixElementItems(p.contents, inClassName, typeVars);
228 2733 p.contents := els;
229 2733 outMetaClasses := listAppend(meta_classes, outMetaClasses);
230 then
231 p;
232
233 case Absyn.PROTECTED()
234 algorithm
235 80 (els, meta_classes) := fixElementItems(p.contents, inClassName, typeVars);
236 80 p.contents := els;
237 80 outMetaClasses := listAppend(meta_classes, outMetaClasses);
238 then
239 p;
240
241 else p;
242 end match for p in inClassParts);
243 end fixClassParts;
244
245 protected function fixElementItems
246 input list<Absyn.ElementItem> inElementItems;
247 input String inName;
248 input list<String> typeVars;
249 output list<Absyn.ElementItem> outElementItems;
250 output list<Absyn.Class> outMetaClasses = {};
251 protected
252 Integer index = 0;
253 Boolean singleton = sum(if AbsynUtil.isElementItem(e) then 1 else 0 for e in inElementItems) == 1;
254 Absyn.Class c;
255 Absyn.Restriction r;
256 algorithm
257
258
4/4
✓ Branch 0 taken 13824 times.
✓ Branch 1 taken 2813 times.
✓ Branch 2 taken 13824 times.
✓ Branch 3 taken 2813 times.
16637 outElementItems := list(match e
259 local Absyn.ClassDef body;
260 case Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification =
261 Absyn.CLASSDEF(class_ = c as Absyn.CLASS(restriction = Absyn.R_RECORD()))))
262 algorithm
263 8205 body := c.body;
264 () := match body
265 case Absyn.PARTS(typeVars=_::_)
266 algorithm
267 ✗ Error.addSourceMessage(Error.METARECORD_WITH_TYPEVARS, {stringDelimitList(body.typeVars, ",")}, c.info);
268 ✗ then fail();
269 else ();
270 end match;
271 // Change the record into a metarecord and add it to the list of metaclasses.
272
2/2
✓ Branch 1 taken 7028 times.
✓ Branch 2 taken 1177 times.
15233 r := Absyn.R_METARECORD(Absyn.IDENT(inName), index, singleton, true, typeVars);
273 8205 c.restriction := r;
274 outMetaClasses := c :: outMetaClasses;
275 // Change the record into a metarecord and update the original class.
276 8205 r := Absyn.R_METARECORD(Absyn.IDENT(inName), index, singleton, false, typeVars);
277 8205 c.restriction := r;
278 8205 index := index + 1;
279 8205 then
280 setElementItemClass(e, c);
281
282 else e;
283 end match for e in inElementItems);
284 end fixElementItems;
285
286 public function transformArrayNodesToListNodes
287 input list<Absyn.Exp> inList;
288 output list<Absyn.Exp> outList;
289 algorithm
290
4/4
✓ Branch 0 taken 646 times.
✓ Branch 1 taken 327 times.
✓ Branch 2 taken 646 times.
✓ Branch 3 taken 327 times.
973 outList := list(match e
291 case Absyn.ARRAY({}) then Absyn.LIST({});
292 case Absyn.ARRAY()
293 13 then Absyn.LIST(transformArrayNodesToListNodes(e.arrayExp));
294 else e;
295 end match for e in inList);
296 end transformArrayNodesToListNodes;
297
298 annotation(__OpenModelica_Interface="frontend_dump");
299 end MetaUtil;
300