Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 59.0% 627 / 0 / 1063
Functions: -% 0 / 1 / 1
Branches: 45.7% 364 / 0 / 796

OMCompiler/Compiler/FrontEnd/AbsynUtil.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 AbsynUtil
37
38 protected
39 import Absyn;
40 import Dump;
41 import Error;
42 import List;
43 import System;
44 import Util;
45 import MetaModelica.Dangerous.listReverseInPlace;
46
47 public function traverseExp<Arg>
48 " Traverses all subexpressions of an Absyn.Exp expression.
49 Takes a function and an extra argument passed through the traversal.
50 NOTE:This function was copied from Expression.traverseExpression."
51 input Absyn.Exp inExp;
52 input FuncType inFunc;
53 input Arg inArg;
54 output Absyn.Exp outExp;
55 output Arg outArg;
56
57 partial function FuncType
58 input output Absyn.Exp exp;
59 input output Arg arg;
60 end FuncType;
61 algorithm
62 547532 (outExp,outArg) := traverseExpBidir(inExp,dummyTraverseExp,inFunc,inArg);
63 end traverseExp;
64
65 public function traverseExpTopDown<Arg>
66 " Traverses all subexpressions of an Absyn.Exp expression.
67 Takes a function and an extra argument passed through the traversal."
68 input Absyn.Exp inExp;
69 input FuncType inFunc;
70 input Arg inArg;
71 output Absyn.Exp outExp;
72 output Arg outArg;
73
74 partial function FuncType
75 input output Absyn.Exp exp;
76 input output Arg arg;
77 end FuncType;
78 algorithm
79 30 (outExp,outArg) := traverseExpBidir(inExp,inFunc,dummyTraverseExp,inArg);
80 end traverseExpTopDown;
81
82 public function traverseExpList<Arg>
83 "calls traverseExp on each element in the given list"
84 input list<Absyn.Exp> inExpList;
85 input FuncType inFunc;
86 input Arg inArg;
87 output list<Absyn.Exp> outExpList;
88 output Arg outArg;
89
90 partial function FuncType
91 input output Absyn.Exp exp;
92 input output Arg arg;
93 end FuncType;
94 algorithm
95 1262 (outExpList,outArg) := traverseExpListBidir(inExpList,dummyTraverseExp,inFunc,inArg);
96 end traverseExpList;
97
98 public function traverseExpListBidir<Arg>
99 "Traverses a list of expressions, calling traverseExpBidir on each
100 expression."
101 input list<Absyn.Exp> inExpl;
102 input FuncType enterFunc;
103 input FuncType exitFunc;
104 input Arg inArg;
105 output list<Absyn.Exp> outExpl;
106 output Arg outArg;
107
108 partial function FuncType
109 input output Absyn.Exp exp;
110 input output Arg arg;
111 end FuncType;
112 algorithm
113 464730 (outExpl, outArg) := List.map2FoldCheckReferenceEq(inExpl, traverseExpBidir, enterFunc, exitFunc, inArg);
114 end traverseExpListBidir;
115
116 public function traverseExpBidir<Arg>
117 "This function takes an expression and a tuple with an enter function, an exit
118 function, and an extra argument. For each expression it encounters it calls
119 the enter function with the expression and the extra argument. It then
120 traverses all subexpressions in the expression and calls traverseExpBidir on
121 them with the updated argument. Finally it calls the exit function, again with
122 the updated argument. This means that this function is bidirectional, and can
123 be used to emulate both top-down and bottom-up traversal."
124 input Absyn.Exp inExp;
125 input FuncType enterFunc;
126 input FuncType exitFunc;
127 input Arg inArg;
128 output Absyn.Exp e;
129 output Arg arg;
130
131 partial function FuncType
132 input output Absyn.Exp exp;
133 input output Arg arg;
134 end FuncType;
135 algorithm
136
2/2
✓ Branch 0 taken 826 times.
✓ Branch 1 taken 3836819 times.
3837645 (e, arg) := enterFunc(inExp, inArg);
137 3837645 (e, arg) := traverseExpBidirSubExps(e, enterFunc, exitFunc, arg);
138
2/2
✓ Branch 0 taken 11088 times.
✓ Branch 1 taken 3826557 times.
3837645 (e, arg) := exitFunc(e, arg);
139 end traverseExpBidir;
140
141 public function traverseExpOptBidir<Arg>
142 "Same as traverseExpBidir, but with an optional expression. Calls
143 traverseExpBidir if the option is SOME(), or just returns the input if it's
144 NONE()"
145 input Option<Absyn.Exp> inExp;
146 input FuncType enterFunc;
147 input FuncType exitFunc;
148 input Arg inArg;
149 output Option<Absyn.Exp> outExp;
150 output Arg arg;
151
152 partial function FuncType
153 input output Absyn.Exp exp;
154 input output Arg arg;
155 end FuncType;
156 algorithm
157 (outExp, arg) := match inExp
158 local
159 Absyn.Exp e1,e2;
160
161 case SOME(e1)
162 algorithm
163 2869 (e2, arg) := traverseExpBidir(e1, enterFunc, exitFunc, inArg);
164
2/2
✓ Branch 0 taken 291 times.
✓ Branch 1 taken 2578 times.
3160 then
165 (if referenceEq(e1,e2) then inExp else SOME(e2), arg);
166
167 else (inExp, inArg);
168 end match;
169 end traverseExpOptBidir;
170
171 protected function traverseExpBidirSubExps<Arg>
172 "Helper function to traverseExpBidir. Traverses the subexpressions of an
173 expression and calls traverseExpBidir on them."
174 input output Absyn.Exp exp;
175 input FuncType enterFunc;
176 input FuncType exitFunc;
177 input output Arg arg;
178
179 partial function FuncType
180 input output Absyn.Exp exp;
181 input output Arg arg;
182 end FuncType;
183 algorithm
184 (exp, arg) := match exp
185 local
186 Absyn.Exp e1, e1m, e2, e2m, e3, e3m;
187 Option<Absyn.Exp> oe1, oe1m;
188 Absyn.ComponentRef cref, crefm;
189 list<tuple<Absyn.Exp, Absyn.Exp>> else_ifs1,else_ifs2;
190 list<Absyn.Exp> expl1,expl2;
191 list<list<Absyn.Exp>> mat_expl;
192 Absyn.FunctionArgs fargs1,fargs2;
193 String error_msg;
194 Absyn.Ident id, enterName, exitName;
195 list<Absyn.Case> match_cases;
196 list<Absyn.Subscript> subs;
197
198 case Absyn.INTEGER() then (exp, arg);
199 case Absyn.REAL() then (exp, arg);
200 case Absyn.STRING() then (exp, arg);
201 case Absyn.BOOL() then (exp, arg);
202
203 case Absyn.CREF(componentRef = cref)
204 algorithm
205 1277183 (crefm, arg) := traverseExpBidirCref(cref, enterFunc, exitFunc, arg);
206
2/2
✓ Branch 0 taken 3582 times.
✓ Branch 1 taken 1273601 times.
1277183 then
207 (if referenceEq(cref,crefm) then exp else Absyn.CREF(crefm), arg);
208
209 case Absyn.BINARY(exp1 = e1, exp2 = e2)
210 algorithm
211 555471 (e1m, arg) := traverseExpBidir(e1, enterFunc, exitFunc, arg);
212 555471 (e2m, arg) := traverseExpBidir(e2, enterFunc, exitFunc, arg);
213
2/2
✓ Branch 0 taken 198866 times.
✓ Branch 1 taken 356605 times.
555471 then
214 (if referenceEq(e1,e1m) and referenceEq(e2,e2m) then exp else Absyn.BINARY(e1m, exp.op, e2m), arg);
215
216 case Absyn.UNARY(exp = e1)
217 algorithm
218 167747 (e1m, arg) := traverseExpBidir(e1, enterFunc, exitFunc, arg);
219
2/2
✓ Branch 0 taken 8470 times.
✓ Branch 1 taken 159277 times.
167747 then
220 (if referenceEq(e1,e1m) then exp else Absyn.UNARY(exp.op, e1m), arg);
221
222 case Absyn.LBINARY(exp1 = e1, exp2 = e2)
223 algorithm
224 14383 (e1m, arg) := traverseExpBidir(e1, enterFunc, exitFunc, arg);
225 14383 (e2m, arg) := traverseExpBidir(e2, enterFunc, exitFunc, arg);
226
2/2
✓ Branch 0 taken 2309 times.
✓ Branch 1 taken 12074 times.
14383 then
227 (if referenceEq(e1,e1m) and referenceEq(e2,e2m) then exp else Absyn.LBINARY(e1m, exp.op, e2m), arg);
228
229 case Absyn.LUNARY(exp = e1)
230 algorithm
231 4061 (e1m, arg) := traverseExpBidir(e1, enterFunc, exitFunc, arg);
232
2/2
✓ Branch 0 taken 747 times.
✓ Branch 1 taken 3314 times.
4061 then
233 (if referenceEq(e1,e1m) then exp else Absyn.LUNARY(exp.op, e1m), arg);
234
235 case Absyn.RELATION(exp1 = e1, exp2 = e2)
236 algorithm
237 33567 (e1m, arg) := traverseExpBidir(e1, enterFunc, exitFunc, arg);
238 33567 (e2m, arg) := traverseExpBidir(e2, enterFunc, exitFunc, arg);
239
2/2
✓ Branch 0 taken 7816 times.
✓ Branch 1 taken 25751 times.
33567 then
240 (if referenceEq(e1,e1m) and referenceEq(e2,e2m) then exp else Absyn.RELATION(e1m, exp.op, e2m), arg);
241
242 case Absyn.IFEXP(ifExp = e1, trueBranch = e2, elseBranch = e3, elseIfBranch = else_ifs1)
243 algorithm
244 24363 (e1m, arg) := traverseExpBidir(e1, enterFunc, exitFunc, arg);
245 24363 (e2m, arg) := traverseExpBidir(e2, enterFunc, exitFunc, arg);
246 24363 (e3m, arg) := traverseExpBidir(e3, enterFunc, exitFunc, arg);
247 24363 (else_ifs2, arg) := List.map2FoldCheckReferenceEq(else_ifs1, traverseExpBidirElseIf, enterFunc, exitFunc, arg);
248
4/4
✓ Branch 0 taken 18770 times.
✓ Branch 1 taken 5593 times.
✓ Branch 2 taken 322 times.
✓ Branch 3 taken 18448 times.
24363 then
249 (if referenceEq(e1,e1m) and referenceEq(e2,e2m) and referenceEq(e3,e3m) and referenceEq(else_ifs1,else_ifs2) then exp else Absyn.IFEXP(e1m, e2m, e3m, else_ifs2), arg);
250
251 case Absyn.CALL(function_ = cref, functionArgs = fargs1)
252 algorithm
253 229273 (fargs2, arg) := traverseExpBidirFunctionArgs(fargs1, enterFunc, exitFunc, arg);
254
2/2
✓ Branch 0 taken 22562 times.
✓ Branch 1 taken 206711 times.
229273 then
255 (if referenceEq(fargs1,fargs2) then exp else Absyn.CALL(cref, fargs2, exp.typeVars), arg);
256
257 case Absyn.PARTEVALFUNCTION(function_ = cref, functionArgs = fargs1)
258 algorithm
259 244 (fargs2, arg) := traverseExpBidirFunctionArgs(fargs1, enterFunc, exitFunc, arg);
260
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 232 times.
244 then
261 (if referenceEq(fargs1,fargs2) then exp else Absyn.PARTEVALFUNCTION(cref, fargs2), arg);
262
263 case Absyn.ARRAY(arrayExp = expl1)
264 algorithm
265 92672 (expl2, arg) := traverseExpListBidir(expl1, enterFunc, exitFunc, arg);
266
2/2
✓ Branch 0 taken 1212 times.
✓ Branch 1 taken 91460 times.
92672 then
267 (if referenceEq(expl1,expl2) then exp else Absyn.ARRAY(expl2), arg);
268
269 case Absyn.MATRIX(matrix = mat_expl)
270 algorithm
271 2042 (mat_expl, arg) := List.map2FoldCheckReferenceEq(mat_expl, traverseExpListBidir, enterFunc, exitFunc, arg);
272 2042 then
273 (Absyn.MATRIX(mat_expl), arg);
274
275 case Absyn.RANGE(start = e1, step = oe1, stop = e2)
276 algorithm
277 10991 (e1m, arg) := traverseExpBidir(e1, enterFunc, exitFunc, arg);
278 10991 (oe1m, arg) := traverseExpOptBidir(oe1, enterFunc, exitFunc, arg);
279 10991 (e2m, arg) := traverseExpBidir(e2, enterFunc, exitFunc, arg);
280
3/4
✓ Branch 0 taken 9709 times.
✓ Branch 1 taken 1282 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9709 times.
10991 then
281 (if referenceEq(e1,e1m) and referenceEq(e2,e2m) and referenceEq(oe1,oe1m) then exp else Absyn.RANGE(e1m, oe1m, e2m), arg);
282
283 case Absyn.END() then (exp, arg);
284
285 case Absyn.TUPLE(expressions = expl1)
286 algorithm
287 136840 (expl2, arg) := traverseExpListBidir(expl1, enterFunc, exitFunc, arg);
288
2/2
✓ Branch 0 taken 53231 times.
✓ Branch 1 taken 83609 times.
136840 then
289 (if referenceEq(expl1,expl2) then exp else Absyn.TUPLE(expl2), arg);
290
291 case Absyn.AS(id = id, exp = e1)
292 algorithm
293 371 (e1m, arg) := traverseExpBidir(e1, enterFunc, exitFunc, arg);
294
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 359 times.
371 then
295 (if referenceEq(e1,e1m) then exp else Absyn.AS(id, e1m), arg);
296
297 case Absyn.CONS(head = e1, rest = e2)
298 algorithm
299 957 (e1m, arg) := traverseExpBidir(e1, enterFunc, exitFunc, arg);
300 957 (e2m, arg) := traverseExpBidir(e2, enterFunc, exitFunc, arg);
301
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 928 times.
957 then
302 (if referenceEq(e1,e1m) and referenceEq(e2,e2m) then exp else Absyn.CONS(e1m, e2m), arg);
303
304 case Absyn.MATCHEXP(inputExp = e1, cases = match_cases)
305 algorithm
306 1363 (e1, arg) := traverseExpBidir(e1, enterFunc, exitFunc, arg);
307 1363 (match_cases, arg) := List.map2FoldCheckReferenceEq(match_cases, traverseMatchCase, enterFunc, exitFunc, arg);
308 1363 then
309 (Absyn.MATCHEXP(exp.matchTy, e1, exp.localDecls, match_cases, exp.comment), arg);
310
311 case Absyn.LIST(exps = expl1)
312 algorithm
313 ✗ (expl2, arg) := traverseExpListBidir(expl1, enterFunc, exitFunc, arg);
314 ✗ then
315 (if referenceEq(expl1,expl2) then exp else Absyn.LIST(expl2), arg);
316
317 case Absyn.CODE()
318 then (exp, arg);
319
320 case Absyn.DOT()
321 algorithm
322 4 (e1, arg) := traverseExpBidir(exp.exp, enterFunc, exitFunc, arg);
323 4 (e2, arg) := traverseExpBidir(exp.index, enterFunc, exitFunc, arg);
324
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
4 then
325 (if referenceEq(exp.exp,e1) and referenceEq(exp.index,e2) then exp else Absyn.DOT(e1, e2), arg);
326
327 case Absyn.EXPRESSIONCOMMENT()
328 algorithm
329 698 (e1, arg) := traverseExpBidir(exp.exp, enterFunc, exitFunc, arg);
330
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 662 times.
698 then
331 (if referenceEq(exp.exp,e1) then exp else Absyn.EXPRESSIONCOMMENT(exp.commentsBefore, e1, exp.commentsAfter), arg);
332
333 case Absyn.SUBSCRIPTED_EXP()
334 algorithm
335 ✗ (e1, arg) := traverseExpBidir(exp.exp, enterFunc, exitFunc, arg);
336 ✗ (subs, arg) := traverseExpBidirSubs(exp.subscripts, enterFunc, exitFunc, arg);
337 ✗ then
338 (if referenceEq(exp.exp, e1) and referenceEq(exp.subscripts, subs) then exp else Absyn.SUBSCRIPTED_EXP(e1, subs), arg);
339
340 case Absyn.BREAK() then (exp, arg);
341 case Absyn.UNITFUL_LITERAL() then (exp, arg);
342
343 else
344 algorithm
345 ✗ (,,enterName) := System.dladdr(enterFunc);
346 ✗ (,,exitName) := System.dladdr(exitFunc);
347 ✗ error_msg := "in traverseExpBidirSubExps(" + enterName + ", " + exitName + ") - Unknown expression: ";
348 ✗ error_msg := error_msg + Dump.printExpStr(exp);
349 ✗ Error.addMessage(Error.INTERNAL_ERROR, {error_msg});
350 ✗ then
351 fail();
352
353 end match;
354 end traverseExpBidirSubExps;
355
356 public function traverseExpBidirCref<Arg>
357 "Helper function to traverseExpBidirSubExps. Traverses any expressions in a
358 component reference (i.e. in it's subscripts)."
359 input output Absyn.ComponentRef cref;
360 input FuncType enterFunc;
361 input FuncType exitFunc;
362 input output Arg arg;
363
364 partial function FuncType
365 input output Absyn.Exp exp;
366 input output Arg arg;
367 end FuncType;
368 algorithm
369 (cref, arg) := match cref
370 local
371 Absyn.Ident name;
372 Absyn.ComponentRef cr1,cr2;
373 list<Absyn.Subscript> subs1,subs2;
374
375 case Absyn.CREF_FULLYQUALIFIED(componentRef = cr1)
376 algorithm
377 7232 (cr2, arg) := traverseExpBidirCref(cr1, enterFunc, exitFunc, arg);
378
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 7172 times.
7232 then
379 (if referenceEq(cr1,cr2) then cref else crefMakeFullyQualified(cr2), arg);
380
381 case Absyn.CREF_QUAL(name = name, subscripts = subs1, componentRef = cr1)
382 algorithm
383 283525 (subs2, arg) := traverseExpBidirSubs(subs1, enterFunc, exitFunc, arg);
384 283525 (cr2, arg) := traverseExpBidirCref(cr1, enterFunc, exitFunc, arg);
385
2/2
✓ Branch 0 taken 613 times.
✓ Branch 1 taken 282912 times.
283525 then
386 (if referenceEq(cr1,cr2) and referenceEq(subs1,subs2) then cref else Absyn.CREF_QUAL(name, subs2, cr2), arg);
387
388 case Absyn.CREF_IDENT(name = name, subscripts = subs1)
389 algorithm
390 1275452 (subs2, arg) := traverseExpBidirSubs(subs1, enterFunc, exitFunc, arg);
391
2/2
✓ Branch 0 taken 3328 times.
✓ Branch 1 taken 1272124 times.
1275452 then
392 (if referenceEq(subs1,subs2) then cref else Absyn.CREF_IDENT(name, subs2), arg);
393
394 case Absyn.ALLWILD() then (cref, arg);
395 case Absyn.WILD() then (cref, arg);
396 end match;
397 end traverseExpBidirCref;
398
399 public function traverseExpBidirSubs<Arg>
400 "Helper function to traverseExpBidir. Traverses expressions in a list of subscripts."
401 input output list<Absyn.Subscript> subscripts;
402 input FuncType enterFunc;
403 input FuncType exitFunc;
404 input output Arg arg;
405
406 partial function FuncType
407 input output Absyn.Exp exp;
408 input output Arg arg;
409 end FuncType;
410 algorithm
411 1558977 (subscripts, arg) := List.map2FoldCheckReferenceEq(subscripts, traverseExpBidirSub, enterFunc, exitFunc, arg);
412 end traverseExpBidirSubs;
413
414 public function traverseExpBidirSub<Arg>
415 "Helper function to traverseExpBidir. Traverses expressions in a subscript."
416 input output Absyn.Subscript subscript;
417 input FuncType enterFunc;
418 input FuncType exitFunc;
419 input output Arg arg;
420
421 partial function FuncType
422 input output Absyn.Exp exp;
423 input output Arg arg;
424 end FuncType;
425 algorithm
426 (subscript, arg) := match subscript
427 local
428 Absyn.Exp e1,e2;
429
430 case Absyn.SUBSCRIPT(subscript = e1)
431 algorithm
432 196618 (e2, arg) := traverseExpBidir(e1, enterFunc, exitFunc, arg);
433
2/2
✓ Branch 0 taken 3695 times.
✓ Branch 1 taken 192923 times.
196618 then
434 (if referenceEq(e1,e2) then subscript else Absyn.SUBSCRIPT(e2), arg);
435
436 case Absyn.NOSUB() then (subscript, arg);
437 end match;
438 end traverseExpBidirSub;
439
440 public function traverseExpBidirElseIf<Arg>
441 "Helper function to traverseExpBidirSubExps. Traverses the expressions in an
442 elseif branch."
443 input tuple<Absyn.Exp, Absyn.Exp> inElseIf;
444 input FuncType enterFunc;
445 input FuncType exitFunc;
446 input Arg inArg;
447 output tuple<Absyn.Exp, Absyn.Exp> outElseIf;
448 output Arg arg;
449
450 partial function FuncType
451 input output Absyn.Exp exp;
452 input output Arg arg;
453 end FuncType;
454 protected
455 Absyn.Exp e1, e2;
456 algorithm
457 149 (e1, e2) := inElseIf;
458 149 (e1, arg) := traverseExpBidir(e1, enterFunc, exitFunc, inArg);
459 149 (e2, arg) := traverseExpBidir(e2, enterFunc, exitFunc, arg);
460 149 outElseIf := (e1, e2);
461 end traverseExpBidirElseIf;
462
463 public function traverseExpBidirFunctionArgs<Arg>
464 "Helper function to traverseExpBidirSubExps. Traverses the expressions in a
465 list of function argument."
466 input output Absyn.FunctionArgs args;
467 input FuncType enterFunc;
468 input FuncType exitFunc;
469 input output Arg arg;
470
471 partial function FuncType
472 input output Absyn.Exp exp;
473 input output Arg arg;
474 end FuncType;
475 algorithm
476 (args, arg) := match args
477 local
478 Absyn.Exp e1,e2;
479 list<Absyn.Exp> expl1,expl2;
480 list<Absyn.NamedArg> named_args1,named_args2;
481 Absyn.ForIterators iters1,iters2;
482 Absyn.ReductionIterType iterType;
483
484 case Absyn.FUNCTIONARGS(args = expl1, argNames = named_args1)
485 algorithm
486 227457 (expl2, arg) := traverseExpListBidir(expl1, enterFunc, exitFunc, arg);
487 227457 (named_args2, arg) := List.map2FoldCheckReferenceEq(named_args1, traverseExpBidirNamedArg, enterFunc, exitFunc, arg);
488
2/2
✓ Branch 0 taken 21524 times.
✓ Branch 1 taken 205933 times.
227457 then
489 (if referenceEq(expl1,expl2) and referenceEq(named_args1,named_args2) then args else Absyn.FUNCTIONARGS(expl2, named_args2), arg);
490
491 case Absyn.FOR_ITER_FARG(e1, iterType, iters1)
492 algorithm
493 2572 (e2, arg) := traverseExpBidir(e1, enterFunc, exitFunc, arg);
494 2572 (iters2, arg) := List.map2FoldCheckReferenceEq(iters1, traverseExpBidirIterator, enterFunc, exitFunc, arg);
495
2/2
✓ Branch 0 taken 1051 times.
✓ Branch 1 taken 1521 times.
2572 then
496 (if referenceEq(e1,e2) and referenceEq(iters1,iters2) then args else Absyn.FOR_ITER_FARG(e2, iterType, iters2), arg);
497 end match;
498 end traverseExpBidirFunctionArgs;
499
500 public function traverseExpBidirNamedArg<Arg>
501 "Helper function to traverseExpBidirFunctionArgs. Traverses the expressions in
502 a named function argument."
503 input Absyn.NamedArg inArg;
504 input FuncType enterFunc;
505 input FuncType exitFunc;
506 input Arg inExtra;
507 output Absyn.NamedArg outArg;
508 output Arg outExtra;
509
510 partial function FuncType
511 input output Absyn.Exp exp;
512 input output Arg arg;
513 end FuncType;
514 protected
515 Absyn.Ident name;
516 Absyn.Exp value1,value2;
517 algorithm
518 37682 Absyn.NAMEDARG(name, value1) := inArg;
519 37682 (value2, outExtra) := traverseExpBidir(value1, enterFunc, exitFunc, inExtra);
520
2/2
✓ Branch 0 taken 2724 times.
✓ Branch 1 taken 34958 times.
37682 outArg := if referenceEq(value1,value2) then inArg else Absyn.NAMEDARG(name, value2);
521 end traverseExpBidirNamedArg;
522
523 public function traverseExpBidirIterator<Arg>
524 "Helper function to traverseExpBidirFunctionArgs. Traverses the expressions in
525 an iterator."
526 input Absyn.ForIterator inIterator;
527 input FuncType enterFunc;
528 input FuncType exitFunc;
529 input Arg inArg;
530 output Absyn.ForIterator outIterator;
531 output Arg outArg;
532
533 partial function FuncType
534 input output Absyn.Exp exp;
535 input output Arg arg;
536 end FuncType;
537 protected
538 Absyn.Ident name;
539 Option<Absyn.Exp> guardExp1,guardExp2,range1,range2;
540 algorithm
541 2624 Absyn.ITERATOR(name=name, guardExp=guardExp1, range=range1) := inIterator;
542 2624 (guardExp2, outArg) := traverseExpOptBidir(guardExp1, enterFunc, exitFunc, inArg);
543 2624 (range2, outArg) := traverseExpOptBidir(range1, enterFunc, exitFunc, outArg);
544
2/2
✓ Branch 0 taken 245 times.
✓ Branch 1 taken 2379 times.
2624 outIterator := if referenceEq(guardExp1,guardExp2) and referenceEq(range1,range2) then inIterator else Absyn.ITERATOR(name, guardExp2, range2);
545 end traverseExpBidirIterator;
546
547 public function traverseMatchCase<Arg>
548 input output Absyn.Case matchCase;
549 input FuncType enterFunc;
550 input FuncType exitFunc;
551 input output Arg arg;
552
553 partial function FuncType
554 input output Absyn.Exp exp;
555 input output Arg arg;
556 end FuncType;
557 algorithm
558 (matchCase, arg) := match matchCase
559 local
560 Absyn.Exp pattern, result;
561 Absyn.Info info, resultInfo, pinfo;
562 list<Absyn.ElementItem> ldecls;
563 Absyn.ClassPart cp;
564 Option<String> cmt;
565 Option<Absyn.Exp> patternGuard;
566
567 case Absyn.CASE(pattern, patternGuard, pinfo, ldecls, cp, result, resultInfo, cmt, info)
568 algorithm
569 5279 (pattern, arg) := traverseExpBidir(pattern, enterFunc, exitFunc, arg);
570 5279 (patternGuard, arg) := traverseExpOptBidir(patternGuard, enterFunc, exitFunc, arg);
571 5279 (cp, arg) := traverseClassPartBidir(cp, enterFunc, exitFunc, arg);
572 5279 (result, arg) := traverseExpBidir(result, enterFunc, exitFunc, arg);
573 5279 then
574 (Absyn.CASE(pattern, patternGuard, pinfo, ldecls, cp, result, resultInfo, cmt, info), arg);
575
576 case Absyn.ELSE(ldecls, cp, result, resultInfo, cmt, info)
577 algorithm
578 408 (cp, arg) := traverseClassPartBidir(cp, enterFunc, exitFunc, arg);
579 408 (result, arg) := traverseExpBidir(result, enterFunc, exitFunc, arg);
580 408 then
581 (Absyn.ELSE(ldecls, cp, result, resultInfo, cmt, info), arg);
582
583 end match;
584 end traverseMatchCase;
585
586 protected function traverseClassPartBidir<Arg>
587 input output Absyn.ClassPart cp;
588 input FuncType enterFunc;
589 input FuncType exitFunc;
590 input output Arg arg;
591
592 partial function FuncType
593 input output Absyn.Exp exp;
594 input output Arg arg;
595 end FuncType;
596 algorithm
597 (cp, arg) := match cp
598 local
599 list<Absyn.AlgorithmItem> algs;
600 list<Absyn.EquationItem> eqs;
601
602 case Absyn.ALGORITHMS(algs)
603 algorithm
604 2743 (algs, arg) := List.map2FoldCheckReferenceEq(algs, traverseAlgorithmItemBidir, enterFunc, exitFunc, arg);
605 2743 then
606 (Absyn.ALGORITHMS(algs),arg);
607
608 case Absyn.EQUATIONS(eqs)
609 algorithm
610 2944 (eqs, arg) := List.map2FoldCheckReferenceEq(eqs, traverseEquationItemBidir, enterFunc, exitFunc, arg);
611 2944 then
612 (Absyn.EQUATIONS(eqs),arg);
613 end match;
614 end traverseClassPartBidir;
615
616 public function traverseEquationItemListBidir<Arg>
617 input list<Absyn.EquationItem> inEquationItems;
618 input FuncType enterFunc;
619 input FuncType exitFunc;
620 input Arg inArg;
621 output list<Absyn.EquationItem> outEquationItems;
622 output Arg outArg;
623
624 partial function FuncType
625 input output Absyn.Exp exp;
626 input output Arg arg;
627 end FuncType;
628 algorithm
629 5 (outEquationItems, outArg) := List.map2FoldCheckReferenceEq(inEquationItems, traverseEquationItemBidir, enterFunc, exitFunc, inArg);
630 end traverseEquationItemListBidir;
631
632 public function traverseAlgorithmItemListBidir<Arg>
633 input list<Absyn.AlgorithmItem> inAlgs;
634 input FuncType enterFunc;
635 input FuncType exitFunc;
636 input Arg inArg;
637 output list<Absyn.AlgorithmItem> outAlgs;
638 output Arg outArg;
639
640 partial function FuncType
641 input output Absyn.Exp exp;
642 input output Arg arg;
643 end FuncType;
644 algorithm
645 405 (outAlgs, outArg) := List.map2FoldCheckReferenceEq(inAlgs, traverseAlgorithmItemBidir, enterFunc, exitFunc, inArg);
646 end traverseAlgorithmItemListBidir;
647
648 protected function traverseAlgorithmItemBidir<Arg>
649 input output Absyn.AlgorithmItem algorithmItem;
650 input FuncType enterFunc;
651 input FuncType exitFunc;
652 input output Arg arg;
653
654 partial function FuncType
655 input output Absyn.Exp exp;
656 input output Arg arg;
657 end FuncType;
658 algorithm
659 () := match algorithmItem
660 local
661 Absyn.Algorithm alg;
662
663 case Absyn.ALGORITHMITEM(algorithm_ = alg)
664 algorithm
665 7867 (alg, arg) := traverseAlgorithmBidir(alg, enterFunc, exitFunc, arg);
666 7867 algorithmItem.algorithm_ := alg;
667 then
668 ();
669
670 case Absyn.ALGORITHMITEMCOMMENT() then ();
671 end match;
672 end traverseAlgorithmItemBidir;
673
674 protected function traverseEquationItemBidir<Arg>
675 input output Absyn.EquationItem equationItem;
676 input FuncType enterFunc;
677 input FuncType exitFunc;
678 input output Arg arg;
679
680 partial function FuncType
681 input output Absyn.Exp exp;
682 input output Arg arg;
683 end FuncType;
684 algorithm
685 () := match equationItem
686 local
687 Absyn.Equation eq;
688
689 case Absyn.EQUATIONITEM(equation_ = eq)
690 algorithm
691 48 (eq, arg) := traverseEquationBidir(eq, enterFunc, exitFunc, arg);
692 48 equationItem.equation_ := eq;
693 then
694 ();
695
696 case Absyn.EQUATIONITEMCOMMENT() then ();
697
698 end match;
699 end traverseEquationItemBidir;
700
701 public function traverseEquationBidir<Arg>
702 input output Absyn.Equation eq;
703 input FuncType enterFunc;
704 input FuncType exitFunc;
705 input output Arg arg;
706
707 partial function FuncType
708 input output Absyn.Exp exp;
709 input output Arg arg;
710 end FuncType;
711 algorithm
712 eq := match eq
713 local
714 Absyn.Exp e1, e2;
715 list<Absyn.EquationItem> eqil1, eqil2;
716 list<tuple<Absyn.Exp, list<Absyn.EquationItem>>> else_branch;
717 Absyn.ComponentRef cref1, cref2;
718 Absyn.ForIterators iters;
719 Absyn.FunctionArgs func_args;
720 Absyn.EquationItem eq1;
721
722 case Absyn.EQ_IF(ifExp = e1, equationTrueItems = eqil1, elseIfBranches = else_branch, equationElseItems = eqil2)
723 algorithm
724 2 (e1, arg) := traverseExpBidir(e1, enterFunc, exitFunc, arg);
725 2 (eqil1, arg) := traverseEquationItemListBidir(eqil1, enterFunc, exitFunc, arg);
726 2 (else_branch,arg) := List.map2FoldCheckReferenceEq(else_branch, traverseEquationBidirElse, enterFunc, exitFunc, arg);
727 2 (eqil2,arg) := traverseEquationItemListBidir(eqil2, enterFunc, exitFunc, arg);
728 2 then
729 Absyn.EQ_IF(e1, eqil1, else_branch, eqil2);
730
731 case Absyn.EQ_EQUALS(leftSide = e1, rightSide = e2)
732 algorithm
733 22 (e1, arg) := traverseExpBidir(e1, enterFunc, exitFunc, arg);
734 22 (e2, arg) := traverseExpBidir(e2, enterFunc, exitFunc, arg);
735 22 then
736 Absyn.EQ_EQUALS(e1, e2);
737
738 case Absyn.EQ_PDE(leftSide = e1, rightSide = e2, domain = cref1)
739 algorithm
740 ✗ (e1, arg) := traverseExpBidir(e1, enterFunc, exitFunc, arg);
741 ✗ (e2, arg) := traverseExpBidir(e2, enterFunc, exitFunc, arg);
742 ✗ cref1 := traverseExpBidirCref(cref1, enterFunc, exitFunc, arg);
743 ✗ then
744 Absyn.EQ_PDE(e1, e2,cref1);
745
746 case Absyn.EQ_CONNECT(connector1 = cref1, connector2 = cref2)
747 algorithm
748 ✗ (cref1, arg) := traverseExpBidirCref(cref1, enterFunc, exitFunc, arg);
749 ✗ (cref2, arg) := traverseExpBidirCref(cref2, enterFunc, exitFunc, arg);
750 ✗ then
751 Absyn.EQ_CONNECT(cref1, cref2);
752
753 case Absyn.EQ_FOR(iterators = iters, forEquations = eqil1)
754 algorithm
755 ✗ (iters, arg) := List.map2FoldCheckReferenceEq(iters, traverseExpBidirIterator, enterFunc, exitFunc, arg);
756 ✗ (eqil1, arg) := traverseEquationItemListBidir(eqil1, enterFunc, exitFunc, arg);
757 ✗ then
758 Absyn.EQ_FOR(iters, eqil1);
759
760 case Absyn.EQ_WHEN_E(whenExp = e1, whenEquations = eqil1, elseWhenEquations = else_branch)
761 algorithm
762 ✗ (e1, arg) := traverseExpBidir(e1, enterFunc, exitFunc, arg);
763 ✗ (eqil1, arg) := traverseEquationItemListBidir(eqil1, enterFunc, exitFunc, arg);
764 ✗ (else_branch, arg) := List.map2FoldCheckReferenceEq(else_branch, traverseEquationBidirElse, enterFunc, exitFunc, arg);
765 ✗ then
766 Absyn.EQ_WHEN_E(e1, eqil1, else_branch);
767
768 case Absyn.EQ_NORETCALL(functionName = cref1, functionArgs = func_args)
769 algorithm
770 22 (cref1, arg) := traverseExpBidirCref(cref1, enterFunc, exitFunc, arg);
771 22 (func_args, arg) := traverseExpBidirFunctionArgs(func_args, enterFunc, exitFunc, arg);
772 22 then
773 Absyn.EQ_NORETCALL(cref1, func_args);
774
775 case Absyn.EQ_FAILURE(equ = eq1)
776 algorithm
777 2 (eq1, arg) := traverseEquationItemBidir(eq1, enterFunc, exitFunc, arg);
778 2 then
779 Absyn.EQ_FAILURE(eq1);
780
781 end match;
782 end traverseEquationBidir;
783
784 protected function traverseEquationBidirElse<Arg>
785 input tuple<Absyn.Exp, list<Absyn.EquationItem>> inElse;
786 input FuncType enterFunc;
787 input FuncType exitFunc;
788 input Arg inArg;
789 output tuple<Absyn.Exp, list<Absyn.EquationItem>> outElse;
790 output Arg arg;
791
792 partial function FuncType
793 input output Absyn.Exp exp;
794 input output Arg arg;
795 end FuncType;
796 protected
797 Absyn.Exp e;
798 list<Absyn.EquationItem> eqil;
799 algorithm
800 ✗ (e, eqil) := inElse;
801 ✗ (e, arg) := traverseExpBidir(e, enterFunc, exitFunc, inArg);
802 ✗ (eqil, arg) := traverseEquationItemListBidir(eqil, enterFunc, exitFunc, arg);
803 ✗ outElse := (e, eqil);
804 end traverseEquationBidirElse;
805
806 protected function traverseAlgorithmBidirElse<Arg>
807 input tuple<Absyn.Exp, list<Absyn.AlgorithmItem>> inElse;
808 input FuncType enterFunc;
809 input FuncType exitFunc;
810 input Arg inArg;
811 output tuple<Absyn.Exp, list<Absyn.AlgorithmItem>> outElse;
812 output Arg arg;
813
814 partial function FuncType
815 input output Absyn.Exp exp;
816 input output Arg arg;
817 end FuncType;
818 protected
819 Absyn.Exp e;
820 list<Absyn.AlgorithmItem> algs;
821 algorithm
822 36 (e, algs) := inElse;
823 36 (e, arg) := traverseExpBidir(e, enterFunc, exitFunc, inArg);
824 36 (algs, arg) := traverseAlgorithmItemListBidir(algs, enterFunc, exitFunc, arg);
825 36 outElse := (e, algs);
826 end traverseAlgorithmBidirElse;
827
828 protected function traverseAlgorithmBidir<Arg>
829 input output Absyn.Algorithm alg;
830 input FuncType enterFunc;
831 input FuncType exitFunc;
832 input output Arg arg;
833
834 partial function FuncType
835 input output Absyn.Exp exp;
836 input output Arg arg;
837 end FuncType;
838 algorithm
839 alg := match alg
840 local
841 Absyn.Exp e1, e2;
842 list<Absyn.AlgorithmItem> algs1, algs2;
843 list<tuple<Absyn.Exp, list<Absyn.AlgorithmItem>>> else_branch;
844 Absyn.ComponentRef cref1;
845 Absyn.ForIterators iters;
846 Absyn.FunctionArgs func_args;
847
848 case Absyn.ALG_ASSIGN(e1, e2)
849 algorithm
850 7161 (e1, arg) := traverseExpBidir(e1, enterFunc, exitFunc, arg);
851 7161 (e2, arg) := traverseExpBidir(e2, enterFunc, exitFunc, arg);
852 7161 then
853 Absyn.ALG_ASSIGN(e1, e2);
854
855 case Absyn.ALG_IF(e1, algs1, else_branch, algs2)
856 algorithm
857 179 (e1, arg) := traverseExpBidir(e1, enterFunc, exitFunc, arg);
858 179 (algs1, arg) := traverseAlgorithmItemListBidir(algs1, enterFunc, exitFunc, arg);
859 179 (else_branch, arg) := List.map2FoldCheckReferenceEq(else_branch, traverseAlgorithmBidirElse, enterFunc, exitFunc, arg);
860 179 (algs2, arg) := traverseAlgorithmItemListBidir(algs2, enterFunc, exitFunc, arg);
861 179 then
862 Absyn.ALG_IF(e1, algs1, else_branch, algs2);
863
864 case Absyn.ALG_FOR(iters, algs1)
865 algorithm
866 8 (iters, arg) := List.map2FoldCheckReferenceEq(iters, traverseExpBidirIterator, enterFunc, exitFunc, arg);
867 8 (algs1, arg) := traverseAlgorithmItemListBidir(algs1, enterFunc, exitFunc, arg);
868 8 then
869 Absyn.ALG_FOR(iters, algs1);
870
871 case Absyn.ALG_PARFOR(iters, algs1)
872 algorithm
873 ✗ (iters, arg) := List.map2FoldCheckReferenceEq(iters, traverseExpBidirIterator, enterFunc, exitFunc, arg);
874 ✗ (algs1, arg) := traverseAlgorithmItemListBidir(algs1, enterFunc, exitFunc, arg);
875 ✗ then
876 Absyn.ALG_PARFOR(iters, algs1);
877
878 case Absyn.ALG_WHILE(e1, algs1)
879 algorithm
880 ✗ (e1, arg) := traverseExpBidir(e1, enterFunc, exitFunc, arg);
881 ✗ (algs1, arg) := traverseAlgorithmItemListBidir(algs1, enterFunc, exitFunc, arg);
882 ✗ then
883 Absyn.ALG_WHILE(e1, algs1);
884
885 case Absyn.ALG_WHEN_A(e1, algs1, else_branch)
886 algorithm
887 ✗ (e1, arg) := traverseExpBidir(e1, enterFunc, exitFunc, arg);
888 ✗ (algs1, arg) := traverseAlgorithmItemListBidir(algs1, enterFunc, exitFunc, arg);
889 ✗ (else_branch, arg) := List.map2FoldCheckReferenceEq(else_branch, traverseAlgorithmBidirElse, enterFunc, exitFunc, arg);
890 ✗ then
891 Absyn.ALG_WHEN_A(e1, algs1, else_branch);
892
893 case Absyn.ALG_NORETCALL(cref1, func_args)
894 algorithm
895 490 (cref1, arg) := traverseExpBidirCref(cref1, enterFunc, exitFunc, arg);
896 490 (func_args, arg) := traverseExpBidirFunctionArgs(func_args, enterFunc, exitFunc, arg);
897 490 then
898 Absyn.ALG_NORETCALL(cref1, func_args);
899
900 case Absyn.ALG_RETURN() then alg;
901 case Absyn.ALG_BREAK() then alg;
902 case Absyn.ALG_CONTINUE() then alg;
903
904 case Absyn.ALG_FAILURE(algs1)
905 algorithm
906 2 (algs1, arg) := traverseAlgorithmItemListBidir(algs1, enterFunc, exitFunc, arg);
907 2 then
908 Absyn.ALG_FAILURE(algs1);
909
910 case Absyn.ALG_TRY(algs1, algs2)
911 algorithm
912 ✗ (algs1, arg) := traverseAlgorithmItemListBidir(algs1, enterFunc, exitFunc, arg);
913 ✗ (algs2, arg) := traverseAlgorithmItemListBidir(algs2, enterFunc, exitFunc, arg);
914 ✗ then
915 Absyn.ALG_TRY(algs1, algs2);
916
917 end match;
918 end traverseAlgorithmBidir;
919
920 public function makeIdentPathFromString
921 input String s;
922 output Absyn.Path p;
923 algorithm
924 7521204 p := Absyn.IDENT(s);
925 annotation(__OpenModelica_EarlyInline = true);
926 end makeIdentPathFromString;
927
928 public function makeQualifiedPathFromStrings
929 input String s1;
930 input String s2;
931 output Absyn.Path p;
932 algorithm
933 ✗ p := Absyn.QUALIFIED(s1,Absyn.IDENT(s2));
934 annotation(__OpenModelica_EarlyInline = true);
935 end makeQualifiedPathFromStrings;
936
937 public function className
938 "Returns the class name of a Absyn.Class."
939 input Absyn.Class cl;
940 output String name;
941 algorithm
942 20 Absyn.CLASS(name = name) := cl;
943 end className;
944
945 public function isClassNamed
946 input String inName;
947 input Absyn.Class inClass;
948 output Boolean outIsNamed;
949 algorithm
950 outIsNamed := match inClass
951
4/4
✓ Branch 0 taken 64070 times.
✓ Branch 1 taken 240091 times.
✓ Branch 3 taken 20243 times.
✓ Branch 4 taken 43827 times.
304161 case Absyn.CLASS() then inName == inClass.name;
952 else false;
953 end match;
954 end isClassNamed;
955
956 public function isComponentItemNamed
957 input String name;
958 input Absyn.ComponentItem component;
959 output Boolean res = isComponentNamed(name, component.component);
960 end isComponentItemNamed;
961
962 public function isComponentNamed
963 input String name;
964 input Absyn.Component component;
965 output Boolean res = name == component.name;
966 end isComponentNamed;
967
968 public function elementSpecName
969 "The Absyn.ElementSpec type contains the name of the element, and this function
970 extracts this name."
971 input Absyn.ElementSpec inElementSpec;
972 output Absyn.Ident outIdent;
973 algorithm
974 outIdent := match inElementSpec
975 local Absyn.Ident n;
976
977 case Absyn.CLASSDEF(class_ = Absyn.CLASS(name = n)) then n;
978 case Absyn.COMPONENTS(components = {Absyn.COMPONENTITEM(component = Absyn.COMPONENT(name = n))}) then n;
979 end match;
980 end elementSpecName;
981
982 public function elementItemNames
983 input Absyn.ElementItem item;
984 output list<String> names;
985 algorithm
986 names := match item
987 12 case Absyn.ElementItem.ELEMENTITEM() then elementNames(item.element);
988 else {};
989 end match;
990 end elementItemNames;
991
992 public function elementNames
993 input Absyn.Element element;
994 output list<String> names;
995 algorithm
996 names := match element
997 12 case Absyn.Element.ELEMENT() then elementSpecNames(element.specification);
998 else {};
999 end match;
1000 end elementNames;
1001
1002 public function elementSpecNames
1003 input Absyn.ElementSpec spec;
1004 output list<String> names;
1005 algorithm
1006 names := match spec
1007 2 case Absyn.ElementSpec.CLASSDEF() then {className(spec.class_)};
1008
4/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 10 times.
20 case Absyn.ElementSpec.COMPONENTS() then list(componentName(c) for c in spec.components);
1009 else {};
1010 end match;
1011 end elementSpecNames;
1012
1013 public function isClassdef
1014 input Absyn.Element inElement;
1015 output Boolean b;
1016 algorithm
1017 b := match inElement
1018 case Absyn.ELEMENT(specification=Absyn.CLASSDEF()) then true;
1019 else false;
1020 end match;
1021 end isClassdef;
1022
1023 public function printImportString
1024 "This function takes a Absyn.Import and prints it as a flat-string."
1025 input Absyn.Import imp;
1026 output String ostring;
1027 algorithm
1028 ostring := match imp
1029 ✗ case Absyn.NAMED_IMPORT() then imp.name;
1030 2839 case Absyn.QUAL_IMPORT() then pathString(imp.path);
1031 ✗ case Absyn.UNQUAL_IMPORT() then pathString(imp.path);
1032 end match;
1033 end printImportString;
1034
1035 public function expString "returns the string of an expression if it is a string constant."
1036 input Absyn.Exp exp;
1037 output String str;
1038 algorithm
1039
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 456 times.
456 Absyn.STRING(str) := exp;
1040 end expString;
1041
1042 public function expCref "returns the componentRef of an expression if matches."
1043 input Absyn.Exp exp;
1044 output Absyn.ComponentRef cr;
1045 algorithm
1046
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 33 times.
33 Absyn.CREF(cr) := exp;
1047 end expCref;
1048
1049 public function crefExp "returns the componentRef of an expression if matches."
1050 input Absyn.ComponentRef cr;
1051 output Absyn.Exp exp;
1052 algorithm
1053 ✗ exp := Absyn.CREF(cr);
1054 annotation(__OpenModelica_EarlyInline = true);
1055 end crefExp;
1056
1057 public function pathEqual "Returns true if two paths are equal."
1058 input Absyn.Path path1;
1059 input Absyn.Path path2;
1060 output Boolean equal;
1061 algorithm
1062 equal := match (path1, path2)
1063 // fully qual vs. path
1064 3064186 case (Absyn.FULLYQUALIFIED(), _) then pathEqual(path1.path, path2);
1065 // path vs. fully qual
1066 3496407 case (_, Absyn.FULLYQUALIFIED()) then pathEqual(path1, path2.path);
1067 // ident vs. ident
1068
4/4
✓ Branch 0 taken 8691340 times.
✓ Branch 1 taken 185613 times.
✓ Branch 3 taken 4964 times.
✓ Branch 4 taken 8686376 times.
8876953 case (Absyn.IDENT(),Absyn.IDENT()) then stringEq(path1.name, path2.name);
1069 // qual ident vs. qual ident
1070 case (Absyn.QUALIFIED(),Absyn.QUALIFIED())
1071
6/6
✓ Branch 0 taken 21342484 times.
✓ Branch 1 taken 891486 times.
✓ Branch 3 taken 21300725 times.
✓ Branch 4 taken 41759 times.
✓ Branch 6 taken 806621 times.
✓ Branch 7 taken 20494104 times.
22233970 then stringEq(path1.name, path2.name) and pathEqual(path1.path, path2.path);
1072 // other return false
1073 else false;
1074 end match;
1075 end pathEqual;
1076
1077 public function pathEqualCaseInsensitive "Returns true if two paths are equal."
1078 input Absyn.Path path1;
1079 input Absyn.Path path2;
1080 output Boolean equal;
1081 algorithm
1082 equal := match (path1, path2)
1083 // fully qual vs. path
1084 ✗ case (Absyn.FULLYQUALIFIED(), _) then pathEqualCaseInsensitive(path1.path, path2);
1085 // path vs. fully qual
1086 ✗ case (_, Absyn.FULLYQUALIFIED()) then pathEqualCaseInsensitive(path1, path2.path);
1087 // ident vs. ident
1088 ✗ case (Absyn.IDENT(),Absyn.IDENT()) then stringEq(System.tolower(path1.name), System.tolower(path2.name));
1089 // qual ident vs. qual ident
1090 case (Absyn.QUALIFIED(),Absyn.QUALIFIED())
1091 ✗ then stringEq(System.tolower(path1.name), System.tolower(path2.name)) and
1092 pathEqualCaseInsensitive(path1.path, path2.path);
1093 // other return false
1094 else false;
1095 end match;
1096 end pathEqualCaseInsensitive;
1097
1098 public function typeSpecEqual
1099 "Author BZ 2009-01
1100 Check whether two type specs are equal or not."
1101 input Absyn.TypeSpec a,b;
1102 output Boolean ob;
1103 algorithm
1104 ob := match(a,b)
1105 local
1106
1107 case (Absyn.TPATH(), Absyn.TPATH())
1108
3/4
✓ Branch 1 taken 464013 times.
✓ Branch 2 taken 13 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 464013 times.
464026 then pathEqual(a.path, b.path) and optArrayDimEqual(a.arrayDim, b.arrayDim);
1109
1110 case (Absyn.TCOMPLEX(), Absyn.TCOMPLEX())
1111
3/6
✓ Branch 1 taken 5718 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5718 times.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 5718 times.
5718 then pathEqual(a.path, b.path) and
1112 List.isEqualOnTrue(a.typeSpecs, b.typeSpecs, typeSpecEqual) and
1113 optArrayDimEqual(a.arrayDim, b.arrayDim);
1114
1115 else false;
1116 end match;
1117 end typeSpecEqual;
1118
1119 public function optArrayDimEqual
1120 "Author BZ
1121 helper function for typeSpecEqual"
1122 input Option<Absyn.ArrayDim> oad1,oad2;
1123 output Boolean b;
1124 algorithm
1125 b:= match(oad1,oad2)
1126 local
1127 list<Absyn.Subscript> ad1,ad2;
1128
1129 case(SOME(ad1),SOME(ad2))
1130 ✗ then List.isEqualOnTrue(ad1,ad2,subscriptEqual);
1131 case(NONE(),NONE()) then true;
1132 else false;
1133 end match;
1134 end optArrayDimEqual;
1135
1136 public function typeSpecPathString "This function simply converts a Absyn.Path to a string."
1137 input Absyn.TypeSpec tp;
1138 output String s = pathString(typeSpecPath(tp));
1139 end typeSpecPathString;
1140
1141 public function typeSpecPath
1142 "Converts a Absyn.TypeSpec to Absyn.Path"
1143 input Absyn.TypeSpec tp;
1144 output Absyn.Path op;
1145 algorithm
1146 op := match tp
1147 5232 case Absyn.TCOMPLEX() then tp.path;
1148 798855 case Absyn.TPATH() then tp.path;
1149 end match;
1150 end typeSpecPath;
1151
1152 public function typeSpecDimensions
1153 "Returns the dimensions of a Absyn.TypeSpec."
1154 input Absyn.TypeSpec inTypeSpec;
1155 output Absyn.ArrayDim outDimensions;
1156 algorithm
1157 outDimensions := match inTypeSpec
1158 local
1159 Absyn.ArrayDim dim;
1160
1161 case Absyn.TPATH(arrayDim = SOME(dim)) then dim;
1162 case Absyn.TCOMPLEX(arrayDim = SOME(dim)) then dim;
1163 else {};
1164 end match;
1165 end typeSpecDimensions;
1166
1167 public function pathString "This function simply converts a Absyn.Path to a string."
1168 input Absyn.Path path;
1169 input String delimiter=".";
1170 input Boolean usefq=true;
1171 input Boolean reverse=false;
1172 output String s;
1173 protected
1174 Absyn.Path p1,p2;
1175 Integer count=0, len=0, dlen=stringLength(delimiter);
1176 Boolean b;
1177 algorithm
1178 // First, calculate the length of the string to be generated
1179
3/4
✓ Branch 0 taken 768557 times.
✓ Branch 1 taken 2817188 times.
✓ Branch 3 taken 15788 times.
✗ Branch 4 not taken.
3601533 p1 := if usefq then path else makeNotFullyQualified(path);
1180 () := match p1
1181 case Absyn.IDENT()
1182 algorithm
1183 // Do not allocate memory if we're just going to copy the only identifier
1184 1435645 s := p1.name;
1185 1435645 return;
1186 then ();
1187 else ();
1188 end match;
1189 p2 := p1;
1190 b := true;
1191
4/4
✓ Branch 0 taken 8134369 times.
✓ Branch 1 taken 2150336 times.
✓ Branch 2 taken 53241 times.
✓ Branch 3 taken 15552 times.
10353498 while b loop
1192 (p2,len,count,b) := match p2
1193 2165888 case Absyn.IDENT() then (p2,len+1,count+stringLength(p2.name),false);
1194 5433736 case Absyn.QUALIFIED() then (p2.path,len+1,count+stringLength(p2.name),true);
1195 587986 case Absyn.FULLYQUALIFIED() then (p2.path,len+1,count,true);
1196 end match;
1197 end while;
1198 2165888 s := pathStringWork(p1, (len-1)*dlen+count, delimiter, dlen, reverse);
1199 end pathString;
1200
1201 protected
1202
1203 function pathStringWork
1204 input Absyn.Path inPath;
1205 input Integer len;
1206 input String delimiter;
1207 input Integer dlen;
1208 input Boolean reverse;
1209 output String s="";
1210 protected
1211 Absyn.Path p=inPath;
1212 Boolean b=true;
1213 Integer count=0;
1214 // Allocate a string of the exact required length
1215 System.StringAllocator sb=System.StringAllocator(len);
1216 algorithm
1217 // Fill the string
1218
2/2
✓ Branch 0 taken 8187610 times.
✓ Branch 1 taken 2165888 times.
10353498 while b loop
1219 (p,count,b) := match p
1220 case Absyn.IDENT()
1221 algorithm
1222
2/2
✓ Branch 0 taken 498608 times.
✓ Branch 1 taken 1667280 times.
2165888 System.stringAllocatorStringCopy(sb, p.name, if reverse then len-count-stringLength(p.name) else count);
1223 2165888 then (p,count+stringLength(p.name),false);
1224 case Absyn.QUALIFIED()
1225 algorithm
1226 // In reverse order the delimiter goes to the left of the name
1227
2/2
✓ Branch 0 taken 867444 times.
✓ Branch 1 taken 4566292 times.
5433736 System.stringAllocatorStringCopy(sb, p.name, if reverse then len-count-stringLength(p.name) else count);
1228
2/2
✓ Branch 0 taken 867444 times.
✓ Branch 1 taken 4566292 times.
5433736 System.stringAllocatorStringCopy(sb, delimiter, if reverse then len-count-stringLength(p.name)-dlen else count+stringLength(p.name));
1229 5433736 then (p.path,count+stringLength(p.name)+dlen,true);
1230 case Absyn.FULLYQUALIFIED()
1231 algorithm
1232
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 587986 times.
587986 System.stringAllocatorStringCopy(sb, delimiter, if reverse then len-count-dlen else count);
1233 587986 then (p.path,count+dlen,true);
1234 end match;
1235 end while;
1236 // Return the string
1237 2165888 s := System.stringAllocatorResult(sb,s);
1238 end pathStringWork;
1239
1240 public
1241
1242 function pathStringNoQual = pathString(usefq=false);
1243
1244 function pathStringDefault
1245 input Absyn.Path path;
1246 output String s = pathString(path);
1247 end pathStringDefault;
1248
1249 public function classNameCompare
1250 input Absyn.Class c1,c2;
1251 output Integer o;
1252 algorithm
1253 ✗ o := stringCompare(c1.name, c2.name);
1254 end classNameCompare;
1255
1256 public function classNameGreater
1257 input Absyn.Class c1,c2;
1258 output Boolean b;
1259 algorithm
1260 2789 b := stringCompare(c1.name, c2.name) > 0;
1261 end classNameGreater;
1262
1263 public function pathCompare
1264 input Absyn.Path ip1;
1265 input Absyn.Path ip2;
1266 output Integer o;
1267 algorithm
1268 o := match (ip1,ip2)
1269 local
1270 Absyn.Path p1,p2;
1271 String i1,i2;
1272 27117 case (Absyn.FULLYQUALIFIED(p1),Absyn.FULLYQUALIFIED(p2)) then pathCompare(p1,p2);
1273 case (Absyn.FULLYQUALIFIED(),_) then 1;
1274 case (_,Absyn.FULLYQUALIFIED()) then -1;
1275 case (Absyn.QUALIFIED(i1,p1),Absyn.QUALIFIED(i2,p2))
1276 algorithm
1277 7073998 o := stringCompare(i1,i2);
1278
2/2
✓ Branch 0 taken 6420428 times.
✓ Branch 1 taken 653570 times.
7073998 o := if o == 0 then pathCompare(p1, p2) else o;
1279 then o;
1280 case (Absyn.QUALIFIED(),_) then 1;
1281 case (_,Absyn.QUALIFIED()) then -1;
1282 case (Absyn.IDENT(i1),Absyn.IDENT(i2))
1283 2365628 then stringCompare(i1,i2);
1284 end match;
1285 end pathCompare;
1286
1287 public function pathCompareNoQual
1288 input Absyn.Path ip1;
1289 input Absyn.Path ip2;
1290 output Integer o;
1291 algorithm
1292 o := match (ip1,ip2)
1293 local
1294 Absyn.Path p1,p2;
1295 String i1,i2;
1296 1524267 case (Absyn.FULLYQUALIFIED(p1),p2) then pathCompareNoQual(p1,p2);
1297 1887530 case (p1,Absyn.FULLYQUALIFIED(p2)) then pathCompareNoQual(p1,p2);
1298 case (Absyn.QUALIFIED(i1,p1),Absyn.QUALIFIED(i2,p2))
1299 algorithm
1300 2437145 o := stringCompare(i1,i2);
1301
2/2
✓ Branch 0 taken 2192563 times.
✓ Branch 1 taken 244582 times.
2437145 o := if o == 0 then pathCompare(p1, p2) else o;
1302 then o;
1303 case (Absyn.QUALIFIED(),_) then 1;
1304 case (_,Absyn.QUALIFIED()) then -1;
1305 case (Absyn.IDENT(i1),Absyn.IDENT(i2))
1306 309223 then stringCompare(i1,i2);
1307 end match;
1308 end pathCompareNoQual;
1309
1310 public function pathHash "Hashes a path."
1311 input Absyn.Path path;
1312 output Integer hash;
1313 algorithm
1314 4132760 hash := pathHashContinue(path, Util.HASH_SEED);
1315 end pathHash;
1316
1317 public function pathHashContinue "Hashes a path."
1318 input Absyn.Path path;
1319 input output Integer hash;
1320 algorithm
1321 hash := match path
1322 case Absyn.FULLYQUALIFIED()
1323 algorithm
1324 ✗ hash := stringHashDjb2Continue(".", hash);
1325 ✗ then pathHashContinue(path.path, hash);
1326
1327 case Absyn.QUALIFIED()
1328 algorithm
1329 9103749 hash := stringHashDjb2Continue(".", hash);
1330 9103749 hash := stringHashDjb2Continue(path.name, hash);
1331 9103749 then pathHashContinue(path.path, hash);
1332
1333 case Absyn.IDENT()
1334 algorithm
1335 4132822 hash := stringHashDjb2Continue(".", hash);
1336 4132822 hash := stringHashDjb2Continue(path.name, hash);
1337 then hash;
1338 end match;
1339 end pathHashContinue;
1340
1341 public function optPathString "Returns a path converted to string or an empty string if nothing exist"
1342 input Option<Absyn.Path> inPathOption;
1343 output String outString;
1344 algorithm
1345 outString := match inPathOption
1346 local
1347 Absyn.Path p;
1348 case NONE() then "";
1349 ✗ case SOME(p) then pathString(p);
1350 end match;
1351 end optPathString;
1352
1353 public function pathStringUnquoteReplaceDot
1354 " Changes a path to string. Uses the input string as separator.
1355 If the separtor exists in the string then it is doubled (sep _ then
1356 a_b changes to a__b) before delimiting
1357 (Replaces dots with that separator). And also unquotes each ident.
1358 "
1359 input Absyn.Path inPath;
1360 input String repStr;
1361 output String outString;
1362 protected
1363 list<String> strlst;
1364 String rep_rep;
1365 algorithm
1366 33859 rep_rep := repStr + repStr;
1367 33859 strlst := pathToStringList(inPath);
1368 33859 strlst := List.map2(strlst,System.stringReplace, repStr, rep_rep);
1369 33859 strlst := List.map(strlst,System.unquoteIdentifier);
1370 33859 outString := stringDelimitList(strlst,repStr);
1371 end pathStringUnquoteReplaceDot;
1372
1373 public function stringPath
1374 "Converts a string into a qualified path."
1375 input String str;
1376 output Absyn.Path qualifiedPath;
1377
1378 protected
1379 list<String> paths;
1380 algorithm
1381 148 paths := Util.stringSplitAtChar(str, ".");
1382 148 qualifiedPath := stringListPath(paths);
1383 end stringPath;
1384
1385 public function stringListPath
1386 "Converts a list of strings into a qualified path."
1387 input list<String> paths;
1388 output Absyn.Path qualifiedPath = stringListPathReversed(listReverse(paths));
1389 end stringListPath;
1390
1391 public function stringListPathReversed
1392 "Converts a list of strings into a qualified path, in reverse order.
1393 Ex: {'a', 'b', 'c'} => c.b.a"
1394 input list<String> inStrings;
1395 output Absyn.Path outPath;
1396 protected
1397 String id;
1398 list<String> rest_str;
1399 algorithm
1400
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 113731 times.
113731 id :: rest_str := inStrings;
1401 113731 outPath := Absyn.IDENT(id);
1402
1403
2/2
✓ Branch 0 taken 304093 times.
✓ Branch 1 taken 113731 times.
417824 for s in rest_str loop
1404 304093 outPath := Absyn.QUALIFIED(s, outPath);
1405 end for;
1406 end stringListPathReversed;
1407
1408 public function pathLastIdent
1409 "Returns the last ident (after last dot) in a path"
1410 input Absyn.Path path;
1411 output String outIdent;
1412 algorithm
1413 outIdent := match path
1414 1345624 case Absyn.QUALIFIED() then pathLastIdent(path.path);
1415 1321249 case Absyn.IDENT() then path.name;
1416 272304 case Absyn.FULLYQUALIFIED() then pathLastIdent(path.path);
1417 end match;
1418 end pathLastIdent;
1419
1420 public function pathSetLastIdent
1421 "Replaces the last identifier in the path."
1422 input Absyn.Path path;
1423 input String ident;
1424 output Absyn.Path outPath;
1425 algorithm
1426 outPath := match path
1427 8990 case Absyn.IDENT() then Absyn.IDENT(ident);
1428 case Absyn.QUALIFIED()
1429 44026 then Absyn.QUALIFIED(path.name, pathSetLastIdent(path.path, ident));
1430 case Absyn.FULLYQUALIFIED()
1431 3514 then Absyn.FULLYQUALIFIED(pathSetLastIdent(path.path, ident));
1432 end match;
1433 end pathSetLastIdent;
1434
1435 public function pathLast
1436 "Returns the last ident (after last dot) in a path"
1437 input output Absyn.Path path;
1438 algorithm
1439 path := match path
1440 42 case Absyn.QUALIFIED() then pathLast(path.path);
1441 case Absyn.IDENT() then path;
1442 ✗ case Absyn.FULLYQUALIFIED() then pathLast(path.path);
1443 end match;
1444 end pathLast;
1445
1446 public function pathFirstIdent "Returns the first ident (before first dot) in a path"
1447 input Absyn.Path path;
1448 output Absyn.Ident outIdent;
1449 algorithm
1450 outIdent := match path
1451 6391 case Absyn.FULLYQUALIFIED() then pathFirstIdent(path.path);
1452 140358 case Absyn.QUALIFIED() then path.name;
1453 870061 case Absyn.IDENT() then path.name;
1454 end match;
1455 end pathFirstIdent;
1456
1457 public function pathSetFirstIdent
1458 "Replaces the first identifier in a path."
1459 input Absyn.Path path;
1460 input String ident;
1461 output Absyn.Path outPath;
1462 algorithm
1463 outPath := match path
1464 ✗ case Absyn.IDENT() then Absyn.IDENT(ident);
1465 ✗ case Absyn.QUALIFIED() then Absyn.QUALIFIED(ident, path.path);
1466 case Absyn.FULLYQUALIFIED()
1467 ✗ then Absyn.FULLYQUALIFIED(pathSetFirstIdent(path.path, ident));
1468 end match;
1469 end pathSetFirstIdent;
1470
1471 public function pathFirstPath
1472 input Absyn.Path path;
1473 output Absyn.Path outPath;
1474 algorithm
1475 outPath := match path
1476 case Absyn.IDENT() then path;
1477 1 case Absyn.QUALIFIED() then Absyn.IDENT(path.name);
1478 ✗ case Absyn.FULLYQUALIFIED() then pathFirstPath(path.path);
1479 end match;
1480 end pathFirstPath;
1481
1482 public function pathSecondIdent
1483 input Absyn.Path inPath;
1484 output Absyn.Ident outIdent;
1485 algorithm
1486 outIdent := match inPath
1487 local
1488 Absyn.Ident n;
1489 Absyn.Path p;
1490
1491 case Absyn.QUALIFIED(path = Absyn.QUALIFIED(name = n)) then n;
1492 case Absyn.QUALIFIED(path = Absyn.IDENT(name = n)) then n;
1493 ✗ case Absyn.FULLYQUALIFIED(path = p) then pathSecondIdent(p);
1494
1495 end match;
1496 end pathSecondIdent;
1497
1498 public function pathNthIdent
1499 "Returns the n:th identifier in a path. Fails if n is out of bounds."
1500 input Absyn.Path path;
1501 input Integer n;
1502 output Absyn.Ident ident;
1503 protected
1504 Absyn.Path p = makeNotFullyQualified(path);
1505 algorithm
1506 ✗ for i in 2:n loop
1507 ✗ Absyn.QUALIFIED(path = p) := p;
1508 end for;
1509
1510 ✗ ident := pathFirstIdent(p);
1511 end pathNthIdent;
1512
1513 public function pathSetNthIdent
1514 "Replaces the n:th identifier in a path. Fails if n is out of bounds."
1515 input Absyn.Path path;
1516 input Absyn.Ident ident;
1517 input Integer n;
1518 output Absyn.Path outPath;
1519 algorithm
1520 ✗ if n == 1 then
1521 ✗ outPath := pathSetFirstIdent(path, ident);
1522 else
1523 outPath := match path
1524 case Absyn.QUALIFIED()
1525 ✗ then Absyn.QUALIFIED(path.name, pathSetNthIdent(path.path, ident, n - 1));
1526 case Absyn.FULLYQUALIFIED()
1527 ✗ then Absyn.FULLYQUALIFIED(pathSetNthIdent(path.path, ident, n));
1528 end match;
1529 end if;
1530 end pathSetNthIdent;
1531
1532 public function pathRest
1533 input Absyn.Path inPath;
1534 output Absyn.Path outPath;
1535 algorithm
1536 outPath := match inPath
1537 case Absyn.QUALIFIED(path = outPath) then outPath;
1538 ✗ case Absyn.FULLYQUALIFIED(path = outPath) then pathRest(outPath);
1539 end match;
1540 end pathRest;
1541
1542 public function pathStripSamePrefix
1543 "strips the same prefix paths and returns the stripped path. e.g pathStripSamePrefix(P.M.A, P.M.B) => A"
1544 input Absyn.Path inPath1;
1545 input Absyn.Path inPath2;
1546 output Option<Absyn.Path> outPath;
1547 protected
1548 Absyn.Path path1 = makeNotFullyQualified(inPath1), path2 = makeNotFullyQualified(inPath2);
1549 algorithm
1550
4/4
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 26 times.
✓ Branch 7 taken 1 time.
✓ Branch 8 taken 3 times.
30 while pathFirstIdent(path1) == pathFirstIdent(path2) loop
1551
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 if pathIsIdent(path1) then
1552 // The whole first path is a prefix of the second.
1553 outPath := NONE();
1554 ✗ return;
1555 end if;
1556
1557 1 path1 := pathRest(path1);
1558
1559
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 if pathIsIdent(path2) then
1560 // The whole second path is a prefix of the first.
1561 break;
1562 end if;
1563
1564 1 path2 := pathRest(path2);
1565 end while;
1566
1567 outPath := SOME(path1);
1568 end pathStripSamePrefix;
1569
1570 public function pathPrefix
1571 "Returns the prefix of a path, i.e. this.is.a.path => this.is.a"
1572 input Absyn.Path path;
1573 output Absyn.Path prefix;
1574 algorithm
1575 prefix := match path
1576 ✗ case Absyn.FULLYQUALIFIED() then pathPrefix(path.path);
1577 2016 case Absyn.QUALIFIED(path = Absyn.IDENT()) then Absyn.IDENT(path.name);
1578 4742 case Absyn.QUALIFIED() then Absyn.QUALIFIED(path.name, pathPrefix(path.path));
1579 end match;
1580 end pathPrefix;
1581
1582 public function prefixPath
1583 "Prefixes a path with an identifier."
1584 input Absyn.Ident prefix;
1585 input Absyn.Path path;
1586 output Absyn.Path outPath;
1587 algorithm
1588 35 outPath := Absyn.QUALIFIED(prefix, path);
1589 end prefixPath;
1590
1591 public function suffixPath
1592 "Adds a suffix to a path. Ex:
1593 suffixPath(a.b.c, 'd') => a.b.c.d"
1594 input Absyn.Path inPath;
1595 input Absyn.Ident inSuffix;
1596 output Absyn.Path outPath;
1597 algorithm
1598 outPath := match inPath
1599 local
1600 Absyn.Ident name;
1601 Absyn.Path path;
1602
1603 case Absyn.IDENT(name)
1604 576042 then Absyn.QUALIFIED(name, Absyn.IDENT(inSuffix));
1605
1606 case Absyn.QUALIFIED(name, path)
1607 algorithm
1608 628455 path := suffixPath(path, inSuffix);
1609 628455 then
1610 Absyn.QUALIFIED(name, path);
1611
1612 case Absyn.FULLYQUALIFIED(path)
1613 algorithm
1614 534497 path := suffixPath(path, inSuffix);
1615 534497 then
1616 Absyn.FULLYQUALIFIED(path);
1617
1618 end match;
1619 end suffixPath;
1620
1621 public function pathSuffixOf "returns true if suffix_path is a suffix of path"
1622 input Absyn.Path suffix_path;
1623 input Absyn.Path path;
1624 output Boolean res;
1625 algorithm
1626 res := match path
1627 local Absyn.Path p;
1628 case _ guard pathEqual(suffix_path,path)
1629 then true;
1630 case Absyn.FULLYQUALIFIED(path = p)
1631 532999 then pathSuffixOf(suffix_path,p);
1632 case Absyn.QUALIFIED(path = p)
1633 671467 then pathSuffixOf(suffix_path,p);
1634 else false;
1635 end match;
1636 end pathSuffixOf;
1637
1638 public function pathSuffixOfr "returns true if suffix_path is a suffix of path"
1639 input Absyn.Path path;
1640 input Absyn.Path suffix_path;
1641 output Boolean res;
1642 algorithm
1643 7280 res := pathSuffixOf(suffix_path, path);
1644 end pathSuffixOfr;
1645
1646 public function pathToStringList
1647 input Absyn.Path path;
1648 output list<String> outPaths;
1649 algorithm
1650 64170 outPaths := listReverse(pathToStringListReverse(path));
1651 end pathToStringList;
1652
1653 public function pathToStringListReverse
1654 input Absyn.Path path;
1655 input list<String> acc = {};
1656 output list<String> outPaths;
1657 algorithm
1658 outPaths := match path
1659 64172 case Absyn.IDENT() then path.name :: acc;
1660 118882 case Absyn.QUALIFIED() then pathToStringListReverse(path.path, path.name :: acc);
1661 6730 case Absyn.FULLYQUALIFIED() then pathToStringListReverse(path.path, acc);
1662 end match;
1663 end pathToStringListReverse;
1664
1665 public function addSubscriptsLast
1666 "Function for appending subscripts at end of last ident"
1667 input Absyn.ComponentRef icr;
1668 input list<Absyn.Subscript> i;
1669 output Absyn.ComponentRef ocr;
1670 algorithm
1671 ocr := match icr
1672 local
1673 list<Absyn.Subscript> subs;
1674 String id;
1675 Absyn.ComponentRef cr;
1676
1677 case Absyn.CREF_IDENT(id,subs)
1678 74694 then Absyn.CREF_IDENT(id, listAppend(subs, i));
1679
1680 case Absyn.CREF_QUAL(id,subs,cr)
1681 algorithm
1682 39180 cr := addSubscriptsLast(cr,i);
1683 39180 then
1684 Absyn.CREF_QUAL(id,subs,cr);
1685 case Absyn.CREF_FULLYQUALIFIED(cr)
1686 algorithm
1687 ✗ cr := addSubscriptsLast(cr,i);
1688 ✗ then
1689 crefMakeFullyQualified(cr);
1690 end match;
1691 end addSubscriptsLast;
1692
1693 public function crefReplaceFirst
1694 "Replaces the first part of a cref with another cref."
1695 input Absyn.ComponentRef cref;
1696 input Absyn.ComponentRef replacement;
1697 output Absyn.ComponentRef outCref;
1698 algorithm
1699 outCref := match cref
1700 case Absyn.ComponentRef.CREF_IDENT() then replacement;
1701 case Absyn.ComponentRef.CREF_QUAL()
1702 6 then joinCrefs(replacement, crefStripFirst(cref));
1703 case Absyn.ComponentRef.CREF_FULLYQUALIFIED()
1704 ✗ then Absyn.ComponentRef.CREF_FULLYQUALIFIED(crefReplaceFirst(cref.componentRef, replacement));
1705 end match;
1706 end crefReplaceFirst;
1707
1708 public function crefReplaceFirstIdent "
1709 Replaces the first part of a cref with a replacement path:
1710 (a[4].b.c[3], d.e) => d.e[4].b.c[3]
1711 (a[3], b.c.d) => b.c.d[3]
1712 "
1713 input Absyn.ComponentRef icref;
1714 input Absyn.Path replPath;
1715 output Absyn.ComponentRef outCref;
1716 algorithm
1717 outCref := match icref
1718 local
1719 list<Absyn.Subscript> subs;
1720 Absyn.ComponentRef cr,cref;
1721 case Absyn.CREF_FULLYQUALIFIED(componentRef = cr)
1722 algorithm
1723 ✗ cr := crefReplaceFirstIdent(cr,replPath);
1724 ✗ then crefMakeFullyQualified(cr);
1725 case Absyn.CREF_QUAL(componentRef = cr, subscripts = subs)
1726 algorithm
1727 45310 cref := pathToCref(replPath);
1728 45310 cref := addSubscriptsLast(cref,subs);
1729 45310 then joinCrefs(cref,cr);
1730 case Absyn.CREF_IDENT(subscripts = subs)
1731 algorithm
1732 29384 cref := pathToCref(replPath);
1733 29384 cref := addSubscriptsLast(cref,subs);
1734 then cref;
1735 end match;
1736 end crefReplaceFirstIdent;
1737
1738 public function pathPrefixOf
1739 "Returns true if prefixPath is a prefix of path, false otherwise."
1740 input Absyn.Path prefixPath;
1741 input Absyn.Path path;
1742 output Boolean isPrefix;
1743 algorithm
1744 isPrefix := match(prefixPath, path)
1745 local
1746 Absyn.Path p, p2;
1747 String id, id2;
1748 3948 case (Absyn.FULLYQUALIFIED(p), p2) then pathPrefixOf(p, p2);
1749 659 case (p, Absyn.FULLYQUALIFIED(p2)) then pathPrefixOf(p, p2);
1750
4/4
✓ Branch 0 taken 655 times.
✓ Branch 1 taken 3620 times.
✓ Branch 3 taken 131 times.
✓ Branch 4 taken 524 times.
4275 case (Absyn.IDENT(id), Absyn.IDENT(id2)) then stringEq(id, id2);
1751
4/4
✓ Branch 0 taken 1339 times.
✓ Branch 1 taken 17148 times.
✓ Branch 3 taken 531 times.
✓ Branch 4 taken 808 times.
18487 case (Absyn.IDENT(id), Absyn.QUALIFIED(name = id2)) then stringEq(id, id2);
1752 case (Absyn.QUALIFIED(id, p), Absyn.QUALIFIED(id2, p2))
1753
6/6
✓ Branch 0 taken 78224 times.
✓ Branch 1 taken 33978 times.
✓ Branch 3 taken 22510 times.
✓ Branch 4 taken 55714 times.
✓ Branch 6 taken 21320 times.
✓ Branch 7 taken 1190 times.
112202 then stringEq(id, id2) and pathPrefixOf(p, p2);
1754 else false;
1755 end match;
1756 end pathPrefixOf;
1757
1758 public function removePrefix "removes the prefix_path from path, and returns the rest of path"
1759 input Absyn.Path prefix_path;
1760 input Absyn.Path path;
1761 output Absyn.Path newPath;
1762 algorithm
1763 newPath := match(prefix_path,path)
1764 local Absyn.Path p,p2; Absyn.Ident id1,id2;
1765 // fullyqual path
1766 616559 case (p,Absyn.FULLYQUALIFIED(p2)) then removePrefix(p,p2);
1767 // qual
1768 case (Absyn.QUALIFIED(name=id1,path=p),Absyn.QUALIFIED(name=id2,path=p2))
1769 algorithm
1770
4/4
✓ Branch 0 taken 823006 times.
✓ Branch 1 taken 103286 times.
✓ Branch 3 taken 543581 times.
✓ Branch 4 taken 279425 times.
926292 true := stringEq(id1, id2);
1771 543581 then
1772 removePrefix(p,p2);
1773 // ids
1774 case(Absyn.IDENT(id1),Absyn.QUALIFIED(name=id2,path=p2))
1775 algorithm
1776
4/4
✓ Branch 0 taken 178014 times.
✓ Branch 1 taken 71398 times.
✓ Branch 3 taken 86335 times.
✓ Branch 4 taken 91679 times.
249412 true := stringEq(id1, id2);
1777 then p2;
1778 end match;
1779 end removePrefix;
1780
1781 public function removePrefixOpt
1782 "Removes prefixPath from path and returns the rest of the path, or returns
1783 NONE() if prefixPath isn't a prefix of path."
1784 input Absyn.Path prefixPath;
1785 input Absyn.Path path;
1786 output Option<Absyn.Path> outPath;
1787 algorithm
1788 outPath := match (prefixPath, path)
1789 ✗ case (_, Absyn.FULLYQUALIFIED()) then removePrefixOpt(prefixPath, path.path);
1790
1791 case (Absyn.QUALIFIED(), Absyn.QUALIFIED())
1792 guard prefixPath.name == path.name
1793 75 then removePrefixOpt(prefixPath.path, path.path);
1794
1795 case (Absyn.IDENT(), Absyn.QUALIFIED())
1796 guard prefixPath.name == path.name
1797 3 then SOME(path.path);
1798
1799 else NONE();
1800 end match;
1801 end removePrefixOpt;
1802
1803 public function removePartialPrefix
1804 "Tries to remove a given prefix from a path with removePrefix. If it fails it
1805 removes the first identifier in the prefix and tries again, until it either
1806 succeeds or reaches the end of the prefix. Ex:
1807 removePartialPrefix(A.B.C, B.C.D.E) => D.E
1808 "
1809 input Absyn.Path inPrefix;
1810 input Absyn.Path inPath;
1811 output Absyn.Path outPath;
1812 algorithm
1813 outPath := matchcontinue inPrefix
1814 37499 case _ then removePrefix(inPrefix, inPath);
1815 ✗ case Absyn.QUALIFIED() then removePrefix(inPrefix.path, inPath);
1816 ✗ case Absyn.FULLYQUALIFIED() then removePartialPrefix(inPrefix.path, inPath);
1817 else inPath;
1818 end matchcontinue;
1819 end removePartialPrefix;
1820
1821 public function getCrefsFromSubs
1822 "Author BZ 2009-08
1823 Function for getting ComponentRefs out from Subscripts"
1824 input list<Absyn.Subscript> isubs;
1825 input Boolean includeSubs "include crefs from array subscripts";
1826 input Boolean includeFunctions "note that if you say includeSubs = false then you won't get the functions from array subscripts";
1827 output list<Absyn.ComponentRef> crefs;
1828 algorithm
1829 crefs := match isubs
1830 local
1831 list<Absyn.ComponentRef> crefs1;
1832 Absyn.Exp exp;
1833 list<Absyn.Subscript> subs;
1834
1835 case {} then {};
1836
1837 597 case Absyn.NOSUB()::subs then getCrefsFromSubs(subs,includeSubs,includeFunctions);
1838
1839 case Absyn.SUBSCRIPT(exp)::subs
1840 algorithm
1841 4256 crefs1 := getCrefsFromSubs(subs,includeSubs,includeFunctions);
1842 4256 crefs := getCrefFromExp(exp,includeSubs,includeFunctions);
1843 4256 then
1844 listAppend(crefs,crefs1);
1845 end match;
1846 end getCrefsFromSubs;
1847
1848 public function getCrefFromExp
1849 "Returns a flattened list of the
1850 component references in an expression"
1851 input Absyn.Exp inExp;
1852 input Boolean includeSubs "include crefs from array subscripts";
1853 input Boolean includeFunctions "note that if you say includeSubs = false then you won't get the functions from array subscripts";
1854 output list<Absyn.ComponentRef> outComponentRefLst;
1855 algorithm
1856 outComponentRefLst := match inExp
1857 local
1858 Absyn.ComponentRef cr;
1859 list<Absyn.ComponentRef> l1,l2,res;
1860 Absyn.ComponentCondition e1,e2,e3;
1861 Absyn.FunctionArgs farg;
1862 list<Absyn.ComponentCondition> expl;
1863 list<list<Absyn.ComponentCondition>> expll;
1864 list<Absyn.Subscript> subs;
1865 list<list<Absyn.ComponentRef>> lstres1;
1866 list<list<Absyn.ComponentRef>> crefll;
1867
1868 case Absyn.INTEGER() then {};
1869 case Absyn.REAL() then {};
1870 case Absyn.STRING() then {};
1871 case Absyn.BOOL() then {};
1872 case Absyn.CREF(componentRef = Absyn.ALLWILD()) then {};
1873 case Absyn.CREF(componentRef = Absyn.WILD()) then {};
1874 case Absyn.CREF(componentRef = cr) guard not includeSubs then {cr};
1875
1876 case Absyn.CREF(componentRef = (cr))
1877 algorithm
1878 74849 subs := getSubsFromCref(cr,includeSubs,includeFunctions);
1879 74849 l1 := getCrefsFromSubs(subs,includeSubs,includeFunctions);
1880 then cr::l1;
1881
1882 case Absyn.BINARY(exp1 = e1,exp2 = e2)
1883 algorithm
1884 16433 l1 := getCrefFromExp(e1,includeSubs,includeFunctions);
1885 16433 l2 := getCrefFromExp(e2,includeSubs,includeFunctions);
1886 16433 res := listAppend(l1, l2);
1887 then
1888 res;
1889
1890 case Absyn.UNARY(exp = e1)
1891 algorithm
1892 66961 res := getCrefFromExp(e1,includeSubs,includeFunctions);
1893 then
1894 res;
1895
1896 case Absyn.LBINARY(exp1 = e1,exp2 = e2)
1897 algorithm
1898 1117 l1 := getCrefFromExp(e1,includeSubs,includeFunctions);
1899 1117 l2 := getCrefFromExp(e2,includeSubs,includeFunctions);
1900 1117 res := listAppend(l1, l2);
1901 then
1902 res;
1903
1904 case Absyn.LUNARY(exp = e1)
1905 algorithm
1906 101 res := getCrefFromExp(e1,includeSubs,includeFunctions);
1907 then
1908 res;
1909
1910 case Absyn.RELATION(exp1 = e1,exp2 = e2)
1911 algorithm
1912 1168 l1 := getCrefFromExp(e1,includeSubs,includeFunctions);
1913 1168 l2 := getCrefFromExp(e2,includeSubs,includeFunctions);
1914 1168 res := listAppend(l1, l2);
1915 then
1916 res;
1917
1918 // TODO: Handle else if-branches.
1919 case Absyn.IFEXP(ifExp = e1,trueBranch = e2,elseBranch = e3)
1920 13820 then List.flatten({
1921 getCrefFromExp(e1, includeSubs, includeFunctions),
1922 getCrefFromExp(e2, includeSubs, includeFunctions),
1923 getCrefFromExp(e3, includeSubs, includeFunctions)});
1924
1925 case Absyn.CALL(function_ = cr, functionArgs = farg)
1926 algorithm
1927 32342 res := getCrefFromFarg(farg,includeSubs,includeFunctions);
1928
1/2
✓ Branch 0 taken 32342 times.
✗ Branch 1 not taken.
32342 res := if includeFunctions then cr::res else res;
1929 then
1930 res;
1931 case Absyn.PARTEVALFUNCTION(function_ = cr, functionArgs = farg)
1932 algorithm
1933 1 res := getCrefFromFarg(farg,includeSubs,includeFunctions);
1934
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 res := if includeFunctions then cr::res else res;
1935 then
1936 res;
1937 case Absyn.ARRAY(arrayExp = expl)
1938 algorithm
1939
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 49126 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 49126 times.
49126 lstres1 := List.map2(expl, getCrefFromExp, includeSubs, includeFunctions);
1940 49126 res := List.flatten(lstres1);
1941 then
1942 res;
1943 case Absyn.MATRIX(matrix = expll)
1944 algorithm
1945
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 489 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 489 times.
489 res := List.flatten(List.flatten(List.map2List(expll, getCrefFromExp, includeSubs, includeFunctions)));
1946 then
1947 res;
1948 case Absyn.RANGE(start = e1,step = SOME(e3),stop = e2)
1949 algorithm
1950 4 l1 := getCrefFromExp(e1,includeSubs,includeFunctions);
1951 4 l2 := getCrefFromExp(e2,includeSubs,includeFunctions);
1952 4 l2 := listAppend(l1, l2);
1953 4 l1 := getCrefFromExp(e3,includeSubs,includeFunctions);
1954 4 res := listAppend(l1, l2);
1955 then
1956 res;
1957 case Absyn.RANGE(start = e1,step = NONE(),stop = e2)
1958 algorithm
1959 413 l1 := getCrefFromExp(e1,includeSubs,includeFunctions);
1960 413 l2 := getCrefFromExp(e2,includeSubs,includeFunctions);
1961 413 res := listAppend(l1, l2);
1962 then
1963 res;
1964
1965 case Absyn.END() then {};
1966
1967 case Absyn.TUPLE(expressions = expl)
1968 algorithm
1969
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3255 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3255 times.
3255 crefll := List.map2(expl,getCrefFromExp,includeSubs,includeFunctions);
1970 3255 res := List.flatten(crefll);
1971 then
1972 res;
1973
1974 case Absyn.CODE() then {};
1975
1976 ✗ case Absyn.AS(exp = e1) then getCrefFromExp(e1,includeSubs,includeFunctions);
1977
1978 case Absyn.CONS(e1,e2)
1979 algorithm
1980 ✗ l1 := getCrefFromExp(e1,includeSubs,includeFunctions);
1981 ✗ l2 := getCrefFromExp(e2,includeSubs,includeFunctions);
1982 ✗ res := listAppend(l1, l2);
1983 then
1984 res;
1985
1986 case Absyn.LIST(expl)
1987 algorithm
1988 ✗ crefll := List.map2(expl,getCrefFromExp,includeSubs,includeFunctions);
1989 ✗ res := List.flatten(crefll);
1990 then
1991 res;
1992
1993 ✗ case Absyn.MATCHEXP() then fail();
1994
1995 case Absyn.DOT()
1996 // inExp.index is only allowed to contain names to index the function call; not crefs that are evaluated in any way
1997 4 then getCrefFromExp(inExp.exp,includeSubs,includeFunctions);
1998
1999 case Absyn.EXPRESSIONCOMMENT()
2000 4 then getCrefFromExp(inExp.exp,includeSubs,includeFunctions);
2001
2002 case Absyn.SUBSCRIPTED_EXP()
2003 algorithm
2004 ✗ l1 := getCrefFromExp(inExp.exp, includeSubs, includeFunctions);
2005
2006 ✗ if includeSubs then
2007 ✗ l2 := getCrefsFromSubs(inExp.subscripts, includeSubs, includeFunctions);
2008 ✗ l1 := listAppend(l2, l1);
2009 end if;
2010 then
2011 l1;
2012
2013 case Absyn.BREAK() then {};
2014 case Absyn.UNITFUL_LITERAL() then {};
2015
2016 else
2017 algorithm
2018 ✗ Error.addInternalError(getInstanceName() + " failed " + Dump.printExpStr(inExp), sourceInfo());
2019 ✗ then fail();
2020 end match;
2021 end getCrefFromExp;
2022
2023 public function getCrefFromFarg "Returns the flattened list of all component references
2024 present in a list of function arguments."
2025 input Absyn.FunctionArgs inFunctionArgs;
2026 input Boolean includeSubs "include crefs from array subscripts";
2027 input Boolean includeFunctions "note that if you say includeSubs = false then you won't get the functions from array subscripts";
2028 output list<Absyn.ComponentRef> outComponentRefLst;
2029 algorithm
2030 outComponentRefLst := match inFunctionArgs
2031 local
2032 list<list<Absyn.ComponentRef>> l1,l2;
2033 list<Absyn.ComponentRef> fl1,fl2,fl3,res;
2034 list<Absyn.ComponentCondition> expl;
2035 list<Absyn.NamedArg> nargl;
2036 Absyn.ForIterators iterators;
2037 Absyn.Exp exp;
2038
2039 case Absyn.FUNCTIONARGS(args = expl,argNames = nargl)
2040 algorithm
2041
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 32106 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 32106 times.
32106 l1 := List.map2(expl, getCrefFromExp, includeSubs, includeFunctions);
2042 32106 fl1 := List.flatten(l1);
2043 32106 l2 := List.map2(nargl, getCrefFromNarg, includeSubs, includeFunctions);
2044 32106 fl2 := List.flatten(l2);
2045 32106 res := listAppend(fl1, fl2);
2046 then
2047 res;
2048
2049 case Absyn.FOR_ITER_FARG(exp,_,iterators)
2050 algorithm
2051
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 237 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 237 times.
237 l1 := List.map2Option(List.map(iterators,iteratorRange),getCrefFromExp,includeSubs,includeFunctions);
2052 237 l2 := List.map2Option(List.map(iterators,iteratorGuard),getCrefFromExp,includeSubs,includeFunctions);
2053 237 fl1 := List.flatten(l1);
2054 237 fl2 := List.flatten(l2);
2055 237 fl3 := getCrefFromExp(exp,includeSubs,includeFunctions);
2056 237 res := listAppend(fl1,listAppend(fl2, fl3));
2057 then
2058 res;
2059
2060 end match;
2061 end getCrefFromFarg;
2062
2063 public function iteratorName
2064 input Absyn.ForIterator iterator;
2065 output String name;
2066 algorithm
2067 ✗ Absyn.ITERATOR(name=name) := iterator;
2068 end iteratorName;
2069
2070 public function iteratorRange
2071 input Absyn.ForIterator iterator;
2072 output Option<Absyn.Exp> range;
2073 algorithm
2074 242 Absyn.ITERATOR(range=range) := iterator;
2075 end iteratorRange;
2076
2077 public function iteratorGuard
2078 input Absyn.ForIterator iterator;
2079 output Option<Absyn.Exp> guardExp;
2080 algorithm
2081 242 Absyn.ITERATOR(guardExp=guardExp) := iterator;
2082 end iteratorGuard;
2083
2084 // stefan
2085 public function getNamedFuncArgNamesAndValues
2086 "returns the names from a list of NamedArgs as a string list"
2087 input list<Absyn.NamedArg> namedArgs;
2088 output list<String> names = {};
2089 output list<Absyn.Exp> values = {};
2090 algorithm
2091
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
6 for arg in listReverse(namedArgs) loop
2092 4 names := arg.argName :: names;
2093 4 values := arg.argValue :: values;
2094 end for;
2095 end getNamedFuncArgNamesAndValues;
2096
2097 protected function getCrefFromNarg "Returns the flattened list of all component references
2098 present in a list of named function arguments."
2099 input Absyn.NamedArg inNamedArg;
2100 input Boolean includeSubs "include crefs from array subscripts";
2101 input Boolean includeFunctions "note that if you say includeSubs = false then you won't get the functions from array subscripts";
2102 output list<Absyn.ComponentRef> outComponentRefLst;
2103 algorithm
2104 213 outComponentRefLst := getCrefFromExp(inNamedArg.argValue, includeSubs, includeFunctions);
2105 end getCrefFromNarg;
2106
2107 public function joinPaths "This function joins two paths"
2108 input Absyn.Path inPath1;
2109 input Absyn.Path inPath2;
2110 output Absyn.Path outPath;
2111 algorithm
2112 outPath := match (inPath1,inPath2)
2113 local
2114 Absyn.Ident str;
2115 Absyn.Path p2,p_1,p;
2116 7658179 case (Absyn.IDENT(name = str),p2) then Absyn.QUALIFIED(str,p2);
2117 case (Absyn.QUALIFIED(name = str,path = p),p2)
2118 algorithm
2119 6184959 p_1 := joinPaths(p, p2);
2120 6184959 then
2121 Absyn.QUALIFIED(str,p_1);
2122 62632 case(Absyn.FULLYQUALIFIED(p),p2) then joinPaths(p,p2);
2123 ✗ case(p,Absyn.FULLYQUALIFIED(p2)) then joinPaths(p,p2);
2124 end match;
2125 end joinPaths;
2126
2127 public function joinPathsOpt "This function joins two paths when the first one might be NONE"
2128 input Option<Absyn.Path> inPath1;
2129 input Absyn.Path inPath2;
2130 output Absyn.Path outPath;
2131 algorithm
2132 outPath := match inPath1
2133 local Absyn.Path p;
2134 case NONE() then inPath2;
2135 ✗ case SOME(p) then joinPaths(p, inPath2);
2136 end match;
2137 end joinPathsOpt;
2138
2139 public function joinPathsOptSuffix
2140 input Absyn.Path inPath1;
2141 input Option<Absyn.Path> inPath2;
2142 output Absyn.Path outPath;
2143 algorithm
2144 outPath := match inPath2
2145 local
2146 Absyn.Path p;
2147
2148 1276038 case SOME(p) then joinPaths(inPath1, p);
2149 else inPath1;
2150 end match;
2151 end joinPathsOptSuffix;
2152
2153 public function stripLast "Returns the path given as argument to
2154 the function minus the last ident."
2155 input Absyn.Path inPath;
2156 output Absyn.Path outPath;
2157 algorithm
2158 outPath := match inPath
2159 local
2160 Absyn.Ident str;
2161 Absyn.Path p;
2162
2163 case Absyn.QUALIFIED(name = str, path = Absyn.IDENT())
2164 209509 then Absyn.IDENT(str);
2165
2166 case Absyn.QUALIFIED(name = str, path = p)
2167 algorithm
2168 187872 p := stripLast(p);
2169 187872 then
2170 Absyn.QUALIFIED(str, p);
2171
2172 case Absyn.FULLYQUALIFIED(p)
2173 algorithm
2174 56755 p := stripLast(p);
2175 56530 then
2176 Absyn.FULLYQUALIFIED(p);
2177
2178 end match;
2179 end stripLast;
2180
2181 public function crefStripLast "Returns the path given as argument to
2182 the function minus the last ident."
2183 input Absyn.ComponentRef inCref;
2184 output Absyn.ComponentRef outCref;
2185 algorithm
2186 outCref := match inCref
2187 local
2188 Absyn.Ident str;
2189 Absyn.ComponentRef c_1, c;
2190 list<Absyn.Subscript> subs;
2191
2192 ✗ case Absyn.CREF_IDENT() then fail();
2193 3384 case Absyn.CREF_QUAL(name = str,subscripts = subs, componentRef = Absyn.CREF_IDENT()) then Absyn.CREF_IDENT(str,subs);
2194 case Absyn.CREF_QUAL(name = str,subscripts = subs,componentRef = c)
2195 algorithm
2196 2204 c_1 := crefStripLast(c);
2197 2204 then
2198 Absyn.CREF_QUAL(str,subs,c_1);
2199 case Absyn.CREF_FULLYQUALIFIED(componentRef = c)
2200 algorithm
2201 ✗ c_1 := crefStripLast(c);
2202 ✗ then
2203 crefMakeFullyQualified(c_1);
2204 end match;
2205 end crefStripLast;
2206
2207 public function splitQualAndIdentPath "
2208 Author BZ 2008-04
2209 Function for splitting Absynpath into two parts,
2210 qualified part, and ident part (all_but_last, last);
2211 "
2212 input Absyn.Path inPath;
2213 output Absyn.Path outPath1;
2214 output Absyn.Path outPath2;
2215 algorithm (outPath1,outPath2) := match inPath
2216 local
2217 Absyn.Path qPath,curPath,identPath;
2218 String s1,s2;
2219
2220 case Absyn.QUALIFIED(name = s1, path = Absyn.IDENT(name = s2))
2221 9161 then (Absyn.IDENT(s1), Absyn.IDENT(s2));
2222
2223 case Absyn.QUALIFIED(name = s1, path = qPath)
2224 algorithm
2225 25118 (curPath, identPath) := splitQualAndIdentPath(qPath);
2226 25118 then
2227 (Absyn.QUALIFIED(s1, curPath), identPath);
2228
2229 case Absyn.FULLYQUALIFIED(qPath)
2230 algorithm
2231 8874 (curPath, identPath) := splitQualAndIdentPath(qPath);
2232 then
2233 (curPath, identPath);
2234 end match;
2235 end splitQualAndIdentPath;
2236
2237 public function crefToPath "This function converts a Absyn.ComponentRef to a Absyn.Path, if possible.
2238 If the component reference contains subscripts, it will silently fail."
2239 input Absyn.ComponentRef inComponentRef;
2240 output Absyn.Path outPath;
2241 algorithm
2242 outPath:=
2243 match inComponentRef
2244 local
2245 Absyn.Ident i;
2246 Absyn.Path p;
2247 Absyn.ComponentRef c;
2248 220400 case Absyn.CREF_IDENT(name = i,subscripts = {}) then Absyn.IDENT(i);
2249 case Absyn.CREF_QUAL(name = i,subscripts = {},componentRef = c)
2250 algorithm
2251 234710 p := crefToPath(c);
2252 234512 then
2253 Absyn.QUALIFIED(i,p);
2254 case Absyn.CREF_FULLYQUALIFIED(componentRef = c)
2255 algorithm
2256 5429 p := crefToPath(c);
2257 5429 then
2258 Absyn.FULLYQUALIFIED(p);
2259 end match;
2260 end crefToPath;
2261
2262 public function elementSpecToPath "This function converts a Absyn.ElementSpec to a Absyn.Path, if possible.
2263 If the Absyn.ElementSpec is not EXTENDS, it will silently fail."
2264 input Absyn.ElementSpec inElementSpec;
2265 output Absyn.Path outPath;
2266 algorithm
2267
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 Absyn.EXTENDS(path = outPath) := inElementSpec;
2268 end elementSpecToPath;
2269
2270 public function crefToPathIgnoreSubs
2271 "Converts a Absyn.ComponentRef to a Absyn.Path, ignoring any subscripts."
2272 input Absyn.ComponentRef inComponentRef;
2273 output Absyn.Path outPath;
2274 algorithm
2275 outPath := match inComponentRef
2276 local
2277 Absyn.Ident i;
2278 Absyn.Path p;
2279 Absyn.ComponentRef c;
2280
2281 250087 case Absyn.CREF_IDENT(name = i) then Absyn.IDENT(i);
2282
2283 case Absyn.CREF_QUAL(name = i, componentRef = c)
2284 algorithm
2285 79908 p := crefToPathIgnoreSubs(c);
2286 79908 then
2287 Absyn.QUALIFIED(i, p);
2288
2289 case Absyn.CREF_FULLYQUALIFIED(componentRef = c)
2290 algorithm
2291 1340 p := crefToPathIgnoreSubs(c);
2292 1340 then
2293 Absyn.FULLYQUALIFIED(p);
2294 end match;
2295 end crefToPathIgnoreSubs;
2296
2297 public function crefToTypeSpec
2298 "Converts a ComponentRef to a TypeSpec, treating subscripts on the last
2299 identifier as dimensions and failing if any other identifier is subscripted."
2300 input Absyn.ComponentRef cref;
2301 output Absyn.TypeSpec ty;
2302 protected
2303 list<Absyn.Subscript> subs;
2304 Absyn.Path path;
2305 algorithm
2306 ✗ subs := crefGetLastSubs(cref);
2307 ✗ path := crefToPath(crefStripLastSubs(cref));
2308 ✗ ty := Absyn.TypeSpec.TPATH(path, if listEmpty(subs) then NONE() else SOME(subs));
2309 end crefToTypeSpec;
2310
2311 public function pathToCref "This function converts a Absyn.Path to a Absyn.ComponentRef."
2312 input Absyn.Path inPath;
2313 output Absyn.ComponentRef outComponentRef;
2314 algorithm
2315 outComponentRef:=
2316 match inPath
2317 local
2318 Absyn.Ident i;
2319 Absyn.ComponentRef c;
2320 Absyn.Path p;
2321 375615 case Absyn.IDENT(name = i) then Absyn.CREF_IDENT(i,{});
2322 case Absyn.QUALIFIED(name = i,path = p)
2323 algorithm
2324 512630 c := pathToCref(p);
2325 512630 then
2326 Absyn.CREF_QUAL(i,{},c);
2327 case Absyn.FULLYQUALIFIED(p)
2328 algorithm
2329 29289 c := pathToCref(p);
2330 29289 then crefMakeFullyQualified(c);
2331 end match;
2332 end pathToCref;
2333
2334 public function pathToCrefWithSubs
2335 "This function converts a Absyn.Path to a Absyn.ComponentRef, and applies the given
2336 subscripts to the last identifier."
2337 input Absyn.Path inPath;
2338 input list<Absyn.Subscript> inSubs;
2339 output Absyn.ComponentRef outComponentRef;
2340 algorithm
2341 outComponentRef := match inPath
2342 local
2343 Absyn.Ident i;
2344 Absyn.ComponentRef c;
2345 Absyn.Path p;
2346
2347 301050 case Absyn.IDENT(name = i) then Absyn.CREF_IDENT(i, inSubs);
2348
2349 case Absyn.QUALIFIED(name = i, path = p)
2350 algorithm
2351 9854 c := pathToCrefWithSubs(p, inSubs);
2352 9854 then
2353 Absyn.CREF_QUAL(i, {}, c);
2354
2355 case Absyn.FULLYQUALIFIED(p)
2356 algorithm
2357 3180 c := pathToCrefWithSubs(p, inSubs);
2358 3180 then
2359 crefMakeFullyQualified(c);
2360 end match;
2361 end pathToCrefWithSubs;
2362
2363 public function crefLastIdent
2364 "Returns the last identifier in a component reference."
2365 input Absyn.ComponentRef cref;
2366 output Absyn.Ident outIdent;
2367 algorithm
2368 outIdent := match cref
2369 ✗ case Absyn.CREF_IDENT() then cref.name;
2370 ✗ case Absyn.CREF_QUAL() then crefLastIdent(cref.componentRef);
2371 ✗ case Absyn.CREF_FULLYQUALIFIED() then crefLastIdent(cref.componentRef);
2372 end match;
2373 end crefLastIdent;
2374
2375 public function crefFirstIdentNoSubs
2376 "Returns the basename of the component reference, but fails if it encounters
2377 any subscripts."
2378 input Absyn.ComponentRef cref;
2379 output Absyn.Ident outIdent;
2380 algorithm
2381 outIdent := match cref
2382 ✗ case Absyn.CREF_IDENT(subscripts = {}) then cref.name;
2383 ✗ case Absyn.CREF_QUAL(subscripts = {}) then cref.name;
2384 ✗ case Absyn.CREF_FULLYQUALIFIED() then crefFirstIdentNoSubs(cref.componentRef);
2385 end match;
2386 end crefFirstIdentNoSubs;
2387
2388 public function crefIsIdent
2389 "Returns true if the component reference is a simple identifier, otherwise false."
2390 input Absyn.ComponentRef inComponentRef;
2391 output Boolean outIsIdent;
2392 algorithm
2393 outIsIdent := match inComponentRef
2394 case Absyn.CREF_IDENT() then true;
2395 else false;
2396 end match;
2397 end crefIsIdent;
2398
2399 public function crefIsQual
2400 "Returns true if the component reference is a qualified identifier, otherwise false."
2401 input Absyn.ComponentRef inComponentRef;
2402 output Boolean outIsQual;
2403 algorithm
2404 outIsQual := match inComponentRef
2405 case Absyn.CREF_QUAL() then true;
2406 case Absyn.CREF_FULLYQUALIFIED() then true;
2407 else false;
2408 end match;
2409 end crefIsQual;
2410
2411 public function crefFirstSubs
2412 "Returns the subscripts on the first part of an Absyn.ComponentRef."
2413 input Absyn.ComponentRef cref;
2414 output list<Absyn.Subscript> subscripts;
2415 algorithm
2416 subscripts := match cref
2417 395165 case Absyn.ComponentRef.CREF_IDENT() then cref.subscripts;
2418 86727 case Absyn.ComponentRef.CREF_QUAL() then cref.subscripts;
2419 ✗ case Absyn.ComponentRef.CREF_FULLYQUALIFIED() then crefFirstSubs(cref.componentRef);
2420 end match;
2421 end crefFirstSubs;
2422
2423 public function crefLastSubs "Return the last subscripts of an Absyn.ComponentRef"
2424 input Absyn.ComponentRef cref;
2425 output list<Absyn.Subscript> subscripts;
2426 algorithm
2427 subscripts := match cref
2428 760142 case Absyn.CREF_IDENT() then cref.subscripts;
2429 ✗ case Absyn.CREF_QUAL() then crefLastSubs(cref.componentRef);
2430 2881 case Absyn.CREF_FULLYQUALIFIED() then crefLastSubs(cref.componentRef);
2431 end match;
2432 end crefLastSubs;
2433
2434 public function crefSetFirstSubs
2435 "Sets the subscripts of the first part of an Absyn.ComponentRef."
2436 input output Absyn.ComponentRef cref;
2437 input list<Absyn.Subscript> subscripts;
2438 algorithm
2439 () := match cref
2440 case Absyn.ComponentRef.CREF_IDENT()
2441 algorithm
2442 ✗ cref.subscripts := subscripts;
2443 then
2444 ();
2445
2446 case Absyn.ComponentRef.CREF_QUAL()
2447 algorithm
2448 ✗ cref.subscripts := subscripts;
2449 then
2450 ();
2451
2452 case Absyn.ComponentRef.CREF_FULLYQUALIFIED()
2453 algorithm
2454 ✗ cref.componentRef := crefSetFirstSubs(cref.componentRef, subscripts);
2455 then
2456 ();
2457 end match;
2458 end crefSetFirstSubs;
2459
2460 public function crefSetLastSubs
2461 input output Absyn.ComponentRef cref;
2462 input list<Absyn.Subscript> inSubscripts;
2463 algorithm
2464 () := match cref
2465 case Absyn.CREF_IDENT()
2466 algorithm
2467 80126 cref.subscripts := inSubscripts;
2468 then
2469 ();
2470
2471 case Absyn.CREF_QUAL()
2472 algorithm
2473 2074 cref.componentRef := crefSetLastSubs(cref.componentRef, inSubscripts);
2474 then
2475 ();
2476
2477 case Absyn.CREF_FULLYQUALIFIED()
2478 algorithm
2479 68 cref.componentRef := crefSetLastSubs(cref.componentRef, inSubscripts);
2480 then
2481 ();
2482
2483 end match;
2484 end crefSetLastSubs;
2485
2486 public function crefHasSubscripts "This function finds if a cref has subscripts"
2487 input Absyn.ComponentRef cref;
2488 output Boolean hasSubscripts;
2489 algorithm
2490 hasSubscripts := match cref
2491 3965 case Absyn.CREF_IDENT() then not listEmpty(cref.subscripts);
2492 3981 case Absyn.CREF_QUAL(subscripts = {}) then crefHasSubscripts(cref.componentRef);
2493 ✗ case Absyn.CREF_FULLYQUALIFIED() then crefHasSubscripts(cref.componentRef);
2494 case Absyn.WILD() then false;
2495 case Absyn.ALLWILD() then false;
2496 else true;
2497 end match;
2498 end crefHasSubscripts;
2499
2500 public function getSubsFromCref "
2501 Author: BZ, 2009-09
2502 Extract subscripts of crefs."
2503 input Absyn.ComponentRef cr;
2504 input Boolean includeSubs "include crefs from array subscripts";
2505 input Boolean includeFunctions "note that if you say includeSubs = false then you won't get the functions from array subscripts";
2506 output list<Absyn.Subscript> subscripts;
2507 algorithm
2508 subscripts := match cr
2509 local
2510 list<Absyn.Subscript> subs2;
2511 Absyn.ComponentRef child;
2512
2513 case Absyn.CREF_IDENT(_,subs2) then subs2;
2514
2515 case Absyn.CREF_QUAL(_,subs2,child)
2516 algorithm
2517 43730 subscripts := getSubsFromCref(child, includeSubs, includeFunctions);
2518 43730 subscripts := List.unionOnTrue(subscripts,subs2, subscriptEqual);
2519 then
2520 subscripts;
2521
2522 case Absyn.CREF_FULLYQUALIFIED(child)
2523 algorithm
2524 1010 subscripts := getSubsFromCref(child, includeSubs, includeFunctions);
2525 then
2526 subscripts;
2527 end match;
2528 end getSubsFromCref;
2529
2530 public function getString
2531 input Absyn.Exp exp;
2532 output String str;
2533 algorithm
2534 str := match exp
2535 ✗ case Absyn.EXPRESSIONCOMMENT() then getString(exp.exp);
2536 case Absyn.STRING(str) then str;
2537 end match;
2538 end getString;
2539
2540 public function stripCommentExpressions
2541 "Strips comment expressions from the given expression. If onlyComments is
2542 false it also strips parentheses (represented by tuples)."
2543 input output Absyn.Exp exp;
2544 input Boolean onlyComments = false;
2545 algorithm
2546
2/2
✓ Branch 0 taken 112248 times.
✓ Branch 1 taken 45 times.
224541 (exp,_) := traverseExp(exp, stripCommentExpressionsHelper, onlyComments);
2547 end stripCommentExpressions;
2548
2549 protected function stripCommentExpressionsHelper
2550 input output Absyn.Exp exp;
2551 input output Boolean onlyComments;
2552 protected
2553 Absyn.Exp e;
2554 algorithm
2555 exp := match exp
2556 case Absyn.TUPLE({e}) guard not onlyComments then e;
2557 683 case Absyn.EXPRESSIONCOMMENT() then exp.exp;
2558 else exp;
2559 end match;
2560 end stripCommentExpressionsHelper;
2561
2562 public function crefGetLastIdent
2563 "Gets the last ident in a Absyn.ComponentRef"
2564 input Absyn.ComponentRef cref;
2565 output Absyn.Ident ident;
2566 algorithm
2567 ident := match cref
2568 1692 case Absyn.CREF_IDENT() then cref.name;
2569 2794 case Absyn.CREF_QUAL() then crefGetLastIdent(cref.componentRef);
2570 ✗ case Absyn.CREF_FULLYQUALIFIED() then crefGetLastIdent(cref.componentRef);
2571 end match;
2572 end crefGetLastIdent;
2573
2574 public function crefGetLastSubs
2575 "Gets the last subscripts in a Absyn.ComponentRef"
2576 input Absyn.ComponentRef cref;
2577 output list<Absyn.Subscript> subscripts;
2578 algorithm
2579 subscripts := match cref
2580 ✗ case Absyn.CREF_IDENT() then cref.subscripts;
2581 ✗ case Absyn.CREF_QUAL() then crefGetLastSubs(cref.componentRef);
2582 ✗ case Absyn.CREF_FULLYQUALIFIED() then crefGetLastSubs(cref.componentRef);
2583 end match;
2584 end crefGetLastSubs;
2585
2586 public function crefStripLastSubs "Strips the last subscripts of a Absyn.ComponentRef"
2587 input output Absyn.ComponentRef cref;
2588 algorithm
2589 () := match cref
2590 case Absyn.CREF_IDENT()
2591 algorithm
2592 760142 cref.subscripts := {};
2593 then
2594 ();
2595
2596 case Absyn.CREF_QUAL()
2597 algorithm
2598 ✗ cref.componentRef := crefStripLastSubs(cref.componentRef);
2599 then
2600 ();
2601
2602 case Absyn.CREF_FULLYQUALIFIED()
2603 algorithm
2604 2881 cref.componentRef := crefStripLastSubs(cref.componentRef);
2605 then
2606 ();
2607 end match;
2608 end crefStripLastSubs;
2609
2610 public function joinCrefs "This function joins two ComponentRefs."
2611 input Absyn.ComponentRef inComponentRef1;
2612 input Absyn.ComponentRef inComponentRef2;
2613 output Absyn.ComponentRef outComponentRef;
2614 algorithm
2615 outComponentRef:=
2616 match (inComponentRef1,inComponentRef2)
2617 local
2618 Absyn.Ident id;
2619 list<Absyn.Subscript> sub;
2620 Absyn.ComponentRef cr2,cr_1,cr;
2621 case (Absyn.CREF_IDENT(name = id,subscripts = sub),cr2)
2622 algorithm
2623
2/4
✓ Branch 0 taken 324578 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 324578 times.
✗ Branch 3 not taken.
324578 failure(Absyn.CREF_FULLYQUALIFIED() := cr2);
2624 324578 then Absyn.CREF_QUAL(id,sub,cr2);
2625 case (Absyn.CREF_QUAL(name = id,subscripts = sub,componentRef = cr),cr2)
2626 algorithm
2627 146119 cr_1 := joinCrefs(cr, cr2);
2628 146119 then
2629 Absyn.CREF_QUAL(id,sub,cr_1);
2630 case (Absyn.CREF_FULLYQUALIFIED(componentRef = cr),cr2)
2631 algorithm
2632 9135 cr_1 := joinCrefs(cr, cr2);
2633 9135 then
2634 crefMakeFullyQualified(cr_1);
2635 end match;
2636 end joinCrefs;
2637
2638 public function crefFirstIdent "Returns first ident from a Absyn.ComponentRef"
2639 input Absyn.ComponentRef inCref;
2640 output Absyn.Ident outIdent;
2641 algorithm
2642 outIdent := match inCref
2643 1325427 case Absyn.CREF_IDENT() then inCref.name;
2644 492297 case Absyn.CREF_QUAL() then inCref.name;
2645 9595 case Absyn.CREF_FULLYQUALIFIED() then crefFirstIdent(inCref.componentRef);
2646 end match;
2647 end crefFirstIdent;
2648
2649 public function crefSetFirstIdent
2650 input output Absyn.ComponentRef cref;
2651 input Absyn.Ident ident;
2652 algorithm
2653 () := match cref
2654 case Absyn.CREF_IDENT()
2655 algorithm
2656 1 cref.name := ident;
2657 then
2658 ();
2659
2660 case Absyn.CREF_QUAL()
2661 algorithm
2662 ✗ cref.name := ident;
2663 then
2664 ();
2665
2666 case Absyn.CREF_FULLYQUALIFIED()
2667 algorithm
2668 ✗ cref.componentRef := crefSetFirstIdent(cref.componentRef, ident);
2669 then
2670 ();
2671
2672 else ();
2673 end match;
2674 end crefSetFirstIdent;
2675
2676 public function crefSecondIdent
2677 input Absyn.ComponentRef cref;
2678 output Absyn.Ident ident;
2679 algorithm
2680 ident := match cref
2681 ✗ case Absyn.CREF_QUAL() then crefFirstIdent(cref.componentRef);
2682 ✗ case Absyn.CREF_FULLYQUALIFIED() then crefSecondIdent(cref.componentRef);
2683 end match;
2684 end crefSecondIdent;
2685
2686 public function crefFirstCref
2687 "Returns the first part of a cref."
2688 input Absyn.ComponentRef inCref;
2689 output Absyn.ComponentRef outCref;
2690 algorithm
2691 outCref := match inCref
2692 181310 case Absyn.CREF_QUAL() then Absyn.CREF_IDENT(inCref.name, inCref.subscripts);
2693 ✗ case Absyn.CREF_FULLYQUALIFIED() then crefFirstCref(inCref.componentRef);
2694 else inCref;
2695 end match;
2696 end crefFirstCref;
2697
2698 public function crefStripFirst "Strip the first ident from a Absyn.ComponentRef"
2699 input Absyn.ComponentRef inComponentRef;
2700 output Absyn.ComponentRef outComponentRef;
2701 algorithm
2702 outComponentRef:=
2703 match inComponentRef
2704 local Absyn.ComponentRef cr;
2705 case Absyn.CREF_QUAL(componentRef = cr) then cr;
2706 ✗ case Absyn.CREF_FULLYQUALIFIED(componentRef = cr) then crefStripFirst(cr);
2707 end match;
2708 end crefStripFirst;
2709
2710 public function crefIsFullyQualified
2711 input Absyn.ComponentRef inCref;
2712 output Boolean outIsFullyQualified;
2713 algorithm
2714 outIsFullyQualified := match inCref
2715 case Absyn.CREF_FULLYQUALIFIED() then true;
2716 else false;
2717 end match;
2718 end crefIsFullyQualified;
2719
2720 public function crefMakeFullyQualified
2721 "Makes a component reference fully qualified unless it already is."
2722 input Absyn.ComponentRef inComponentRef;
2723 output Absyn.ComponentRef outComponentRef;
2724 algorithm
2725 outComponentRef := match inComponentRef
2726 case Absyn.CREF_FULLYQUALIFIED() then inComponentRef;
2727 46132 else Absyn.CREF_FULLYQUALIFIED(inComponentRef);
2728 end match;
2729 end crefMakeFullyQualified;
2730
2731 public function restrString "Maps a class restriction to the corresponding string for printing"
2732 input Absyn.Restriction inRestriction;
2733 output String outString;
2734 algorithm
2735 outString:=
2736 match inRestriction
2737 case Absyn.R_CLASS() then "CLASS";
2738 case Absyn.R_OPTIMIZATION() then "OPTIMIZATION";
2739 case Absyn.R_MODEL() then "MODEL";
2740 case Absyn.R_RECORD() then "RECORD";
2741 case Absyn.R_BLOCK() then "BLOCK";
2742 case Absyn.R_CONNECTOR() then "CONNECTOR";
2743 case Absyn.R_EXP_CONNECTOR() then "EXPANDABLE CONNECTOR";
2744 case Absyn.R_TYPE() then "TYPE";
2745 case Absyn.R_PACKAGE() then "PACKAGE";
2746 case Absyn.R_FUNCTION(Absyn.FR_NORMAL_FUNCTION(Absyn.PURE())) then "PURE FUNCTION";
2747 case Absyn.R_FUNCTION(Absyn.FR_NORMAL_FUNCTION(Absyn.IMPURE())) then "IMPURE FUNCTION";
2748 case Absyn.R_FUNCTION(Absyn.FR_NORMAL_FUNCTION(Absyn.NO_PURITY())) then "FUNCTION";
2749 case Absyn.R_FUNCTION(Absyn.FR_OPERATOR_FUNCTION()) then "OPERATOR FUNCTION";
2750 case Absyn.R_PREDEFINED_INTEGER() then "PREDEFINED_INT";
2751 case Absyn.R_PREDEFINED_REAL() then "PREDEFINED_REAL";
2752 case Absyn.R_PREDEFINED_STRING() then "PREDEFINED_STRING";
2753 case Absyn.R_PREDEFINED_BOOLEAN() then "PREDEFINED_BOOL";
2754 // BTH
2755 case Absyn.R_PREDEFINED_CLOCK() then "PREDEFINED_CLOCK";
2756
2757 /* MetaModelica restriction */
2758 case Absyn.R_UNIONTYPE() then "UNIONTYPE";
2759 else "* Unknown restriction *";
2760 end match;
2761 end restrString;
2762
2763 public function lastClassname "Returns the path (=name) of the last class in a program"
2764 input Absyn.Program inProgram;
2765 output Absyn.Path outPath;
2766 protected
2767 list<Absyn.Class> lst;
2768 Absyn.Ident id;
2769 algorithm
2770 1260 Absyn.PROGRAM(classes = lst) := inProgram;
2771 1260 Absyn.CLASS(name = id) := List.last(lst);
2772 1259 outPath := Absyn.IDENT(id);
2773 end lastClassname;
2774
2775 public function classFilename
2776 "Retrieves the filename where the class is stored."
2777 input Absyn.Class inClass;
2778 output String outFilename;
2779 algorithm
2780 9422 Absyn.CLASS(info = SOURCEINFO(fileName = outFilename)) := inClass;
2781 end classFilename;
2782
2783 public function setClassFilename
2784 "Sets the filename where the class is stored. The elements that were stored in
2785 the same file as the class are updated too, since they are stored in the new
2786 file as well. Elements that come from another file, like the classes of a
2787 package stored with a folder structure, keep their filename."
2788 input Absyn.Class inClass;
2789 input String fileName;
2790 output Absyn.Class outClass;
2791 algorithm
2792 outClass := match inClass
2793 local
2794 SourceInfo info;
2795 Absyn.Class cl;
2796 String old_filename;
2797 case cl as Absyn.CLASS(info=info as SOURCEINFO(fileName = old_filename))
2798 guard not stringEq(old_filename, fileName)
2799 algorithm
2800 1 info.fileName := fileName;
2801 1 cl.info := info;
2802 1 cl.body := setClassDefFilename(cl.body, old_filename, fileName);
2803 then cl;
2804 else inClass;
2805 end match;
2806 end setClassFilename;
2807
2808 protected function setClassDefFilename
2809 "Helper to setClassFilename, updates the filename of the elements that were
2810 stored in the given file."
2811 input output Absyn.ClassDef body;
2812 input String oldFilename;
2813 input String newFilename;
2814 algorithm
2815 () := match body
2816 case Absyn.PARTS()
2817 algorithm
2818
4/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1 time.
3 body.classParts := list(setClassPartFilename(part, oldFilename, newFilename)
2819 for part in body.classParts);
2820 then ();
2821
2822 case Absyn.CLASS_EXTENDS()
2823 algorithm
2824 ✗ body.parts := list(setClassPartFilename(part, oldFilename, newFilename)
2825 for part in body.parts);
2826 then ();
2827
2828 else ();
2829 end match;
2830 end setClassDefFilename;
2831
2832 protected function setClassPartFilename
2833 "Helper to setClassDefFilename."
2834 input output Absyn.ClassPart part;
2835 input String oldFilename;
2836 input String newFilename;
2837 algorithm
2838 () := match part
2839 case Absyn.PUBLIC()
2840 algorithm
2841
4/4
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 1 time.
3 part.contents := list(setElementItemFilename(e, oldFilename, newFilename)
2842 for e in part.contents);
2843 then ();
2844
2845 case Absyn.PROTECTED()
2846 algorithm
2847 ✗ part.contents := list(setElementItemFilename(e, oldFilename, newFilename)
2848 for e in part.contents);
2849 then ();
2850
2851 else ();
2852 end match;
2853 end setClassPartFilename;
2854
2855 protected function setElementItemFilename
2856 "Helper to setClassPartFilename."
2857 input output Absyn.ElementItem item;
2858 input String oldFilename;
2859 input String newFilename;
2860 algorithm
2861 () := match item
2862 case Absyn.ELEMENTITEM()
2863 algorithm
2864 1 item.element := setElementFilename(item.element, oldFilename, newFilename);
2865 then ();
2866
2867 else ();
2868 end match;
2869 end setElementItemFilename;
2870
2871 protected function setElementFilename
2872 "Helper to setElementItemFilename, only updates elements that were stored in
2873 the old file."
2874 input output Absyn.Element element;
2875 input String oldFilename;
2876 input String newFilename;
2877 algorithm
2878 () := match element
2879 local
2880 SourceInfo info;
2881
2882 case Absyn.ELEMENT(info = info as SOURCEINFO())
2883 guard stringEq(info.fileName, oldFilename)
2884 algorithm
2885 1 info.fileName := newFilename;
2886 1 element.info := info;
2887 1 element.specification := setElementSpecFilename(element.specification, newFilename);
2888 then ();
2889
2890 case Absyn.DEFINEUNIT(info = info as SOURCEINFO())
2891 guard stringEq(info.fileName, oldFilename)
2892 algorithm
2893 ✗ info.fileName := newFilename;
2894 ✗ element.info := info;
2895 then ();
2896
2897 case Absyn.TEXT(info = info as SOURCEINFO())
2898 guard stringEq(info.fileName, oldFilename)
2899 algorithm
2900 ✗ info.fileName := newFilename;
2901 ✗ element.info := info;
2902 then ();
2903
2904 else ();
2905 end match;
2906 end setElementFilename;
2907
2908 protected function setElementSpecFilename
2909 "Helper to setElementFilename."
2910 input output Absyn.ElementSpec spec;
2911 input String newFilename;
2912 algorithm
2913 () := match spec
2914 local
2915 SourceInfo info;
2916
2917 case Absyn.CLASSDEF()
2918 algorithm
2919 ✗ spec.class_ := setClassFilename(spec.class_, newFilename);
2920 then ();
2921
2922 case Absyn.IMPORT(info = info as SOURCEINFO())
2923 algorithm
2924 ✗ info.fileName := newFilename;
2925 ✗ spec.info := info;
2926 then ();
2927
2928 else ();
2929 end match;
2930 end setElementSpecFilename;
2931
2932 public function setClassName "author: BZ
2933 Sets the name of the class"
2934 input Absyn.Class inClass;
2935 input String newName;
2936 output Absyn.Class outClass = inClass;
2937 algorithm
2938 outClass := match outClass
2939 case Absyn.CLASS()
2940 algorithm
2941 6 outClass.name := newName;
2942 then
2943 outClass;
2944 end match;
2945 end setClassName;
2946
2947 public function setClassBody
2948 input Absyn.Class inClass;
2949 input Absyn.ClassDef inBody;
2950 output Absyn.Class outClass = inClass;
2951 algorithm
2952 outClass := match outClass
2953 case Absyn.CLASS()
2954 algorithm
2955 9 outClass.body := inBody;
2956 then
2957 outClass;
2958 end match;
2959 end setClassBody;
2960
2961 public function crefEqual " Checks if the name of a Absyn.ComponentRef is
2962 equal to the name of another Absyn.ComponentRef, including subscripts.
2963 See also crefEqualNoSubs."
2964 input Absyn.ComponentRef cref1;
2965 input Absyn.ComponentRef cref2;
2966 output Boolean equal;
2967 algorithm
2968 equal := match (cref1, cref2)
2969 case (Absyn.CREF_IDENT(), Absyn.CREF_IDENT())
2970
6/6
✓ Branch 0 taken 499210 times.
✓ Branch 1 taken 1997 times.
✓ Branch 3 taken 498690 times.
✓ Branch 4 taken 520 times.
✓ Branch 6 taken 24 times.
✓ Branch 7 taken 498666 times.
501207 then stringEq(cref1.name, cref2.name) and
2971 subscriptsEqual(cref1.subscripts, cref2.subscripts);
2972
2973 case (Absyn.CREF_QUAL(), Absyn.CREF_QUAL())
2974
8/8
✓ Branch 0 taken 141335 times.
✓ Branch 1 taken 20222 times.
✓ Branch 3 taken 140851 times.
✓ Branch 4 taken 484 times.
✓ Branch 6 taken 140850 times.
✓ Branch 7 taken 1 time.
✓ Branch 9 taken 3290 times.
✓ Branch 10 taken 137560 times.
161557 then stringEq(cref1.name, cref2.name) and
2975 subscriptsEqual(cref1.subscripts, cref2.subscripts) and
2976 crefEqual(cref1.componentRef, cref2.componentRef);
2977
2978 case (Absyn.CREF_FULLYQUALIFIED(), Absyn.CREF_FULLYQUALIFIED())
2979 ✗ then crefEqual(cref1.componentRef, cref2.componentRef);
2980
2981 else false;
2982 end match;
2983 end crefEqual;
2984
2985 public function crefFirstEqual
2986 "@author: adrpo
2987 a.b, a -> true
2988 b.c, a -> false"
2989 input Absyn.ComponentRef iCr1;
2990 input Absyn.ComponentRef iCr2;
2991 output Boolean outBoolean;
2992 algorithm
2993 ✗ outBoolean := stringEq(crefFirstIdent(iCr1),crefFirstIdent(iCr2));
2994 end crefFirstEqual;
2995
2996 public function subscriptEqual
2997 input Absyn.Subscript inSubscript1;
2998 input Absyn.Subscript inSubscript2;
2999 output Boolean outIsEqual;
3000 algorithm
3001 outIsEqual := match(inSubscript1, inSubscript2)
3002 local
3003 Absyn.Exp e1, e2;
3004
3005 case (Absyn.NOSUB(), Absyn.NOSUB()) then true;
3006 27250 case (Absyn.SUBSCRIPT(e1), Absyn.SUBSCRIPT(e2)) then expEqual(e1, e2);
3007 else false;
3008 end match;
3009 end subscriptEqual;
3010
3011 public function subscriptsEqual
3012 "Checks if two subscript lists are equal."
3013 input list<Absyn.Subscript> inSubList1;
3014 input list<Absyn.Subscript> inSubList2;
3015 output Boolean outIsEqual;
3016 algorithm
3017 639541 outIsEqual := List.isEqualOnTrue(inSubList1, inSubList2, subscriptEqual);
3018 end subscriptsEqual;
3019
3020 public function crefEqualNoSubs
3021 "Checks if the name of a Absyn.ComponentRef is equal to the name
3022 of another Absyn.ComponentRef without checking subscripts.
3023 See also crefEqual."
3024 input Absyn.ComponentRef cr1;
3025 input Absyn.ComponentRef cr2;
3026 output Boolean equal;
3027 algorithm
3028 equal := match (cr1,cr2)
3029 case (Absyn.CREF_IDENT(), Absyn.CREF_IDENT())
3030 ✗ then stringEq(cr1.name, cr2.name);
3031 case (Absyn.CREF_QUAL(), Absyn.CREF_QUAL())
3032 ✗ then stringEq(cr1.name, cr2.name) and crefEqualNoSubs(cr1.componentRef, cr2.componentRef);
3033 case (Absyn.CREF_FULLYQUALIFIED(), Absyn.CREF_FULLYQUALIFIED())
3034 ✗ then crefEqualNoSubs(cr1.componentRef, cr2.componentRef);
3035 else false;
3036 end match;
3037 end crefEqualNoSubs;
3038
3039 public function crefCompare
3040 input Absyn.ComponentRef cr1;
3041 input Absyn.ComponentRef cr2;
3042 output Integer comp;
3043 protected
3044 String name;
3045 Absyn.ComponentRef cr;
3046 list<Absyn.Subscript> subs;
3047 algorithm
3048
2/2
✓ Branch 0 taken 13395 times.
✓ Branch 1 taken 23 times.
13418 if referenceEq(cr1, cr2) then
3049 comp := 0;
3050 13395 return;
3051 end if;
3052
3053 23 comp := Util.intCompare(valueConstructor(cr1), valueConstructor(cr2));
3054
3055
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 if comp <> 0 then
3056 ✗ return;
3057 end if;
3058
3059 comp := match cr1
3060 case Absyn.ComponentRef.CREF_FULLYQUALIFIED()
3061 algorithm
3062 ✗ Absyn.ComponentRef.CREF_FULLYQUALIFIED(cr) := cr2;
3063 ✗ then
3064 crefCompare(cr1.componentRef, cr);
3065
3066 case Absyn.ComponentRef.CREF_QUAL()
3067 algorithm
3068 ✗ Absyn.ComponentRef.CREF_QUAL(name, subs, cr) := cr2;
3069 ✗ comp := stringCompare(cr1.name, name);
3070
3071 ✗ if comp == 0 then
3072 ✗ comp := List.compare(cr1.subscripts, subs, subscriptCompare);
3073 end if;
3074 ✗ then
3075 if comp == 0 then crefCompare(cr1.componentRef, cr) else comp;
3076
3077 case Absyn.ComponentRef.CREF_IDENT()
3078 algorithm
3079
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23 times.
23 Absyn.ComponentRef.CREF_IDENT(name, subs) := cr2;
3080 23 comp := stringCompare(cr1.name, name);
3081
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 16 times.
23 then
3082 if comp == 0 then List.compare(cr1.subscripts, subs, subscriptCompare) else comp;
3083
3084 else 0;
3085 end match;
3086 end crefCompare;
3087
3088 public function subscriptCompare
3089 input Absyn.Subscript sub1;
3090 input Absyn.Subscript sub2;
3091 output Integer comp;
3092 protected
3093 Absyn.Exp exp;
3094 algorithm
3095 if referenceEq(sub1, sub2) then
3096 comp := 0;
3097 end if;
3098
3099 ✗ comp := Util.intCompare(valueConstructor(sub1), valueConstructor(sub2));
3100
3101 ✗ if comp <> 0 then
3102 ✗ return;
3103 end if;
3104
3105 comp := match sub1
3106 case Absyn.Subscript.NOSUB() then 0;
3107 case Absyn.Subscript.SUBSCRIPT()
3108 algorithm
3109 ✗ Absyn.Subscript.SUBSCRIPT(exp) := sub2;
3110 ✗ then
3111 // TODO: Implement compare for Absyn.Exp instead of converting to strings.
3112 stringCompare(Dump.printExpStr(sub1.subscript), Dump.printExpStr(exp));
3113 end match;
3114 end subscriptCompare;
3115
3116 public function isPackageRestriction "checks if the provided parameter is a package or not"
3117 input Absyn.Restriction inRestriction;
3118 output Boolean outIsPackage;
3119 algorithm
3120 outIsPackage := match inRestriction
3121 case Absyn.R_PACKAGE() then true;
3122 else false;
3123 end match;
3124 end isPackageRestriction;
3125
3126 public function isFunctionRestriction "checks if restriction is a function or not"
3127 input Absyn.Restriction inRestriction;
3128 output Boolean outIsFunction;
3129 algorithm
3130 outIsFunction := match inRestriction
3131 case Absyn.R_FUNCTION() then true;
3132 else false;
3133 end match;
3134 end isFunctionRestriction;
3135
3136 public function expEqual "Returns true if two expressions are equal"
3137 input Absyn.Exp exp1;
3138 input Absyn.Exp exp2;
3139 output Boolean equal;
3140 algorithm
3141 equal := match (exp1, exp2)
3142 // real vs. integer
3143 case (Absyn.INTEGER(), Absyn.REAL())
3144 ✗ then realEq(intReal(exp1.value), stringReal(exp2.value));
3145
3146 case (Absyn.REAL(), Absyn.INTEGER())
3147 ✗ then realEq(intReal(exp2.value), stringReal(exp1.value));
3148
3149 // anything else, exact match!
3150 318737 else valueEq(exp1, exp2);
3151 end match;
3152 end expEqual;
3153
3154 public function getClassName "author: adrpo
3155 gets the name of the class."
3156 input Absyn.Class inClass;
3157 output String outName;
3158 algorithm
3159 1253345 Absyn.CLASS(name=outName) := inClass;
3160 end getClassName;
3161
3162 public type IteratorIndexedCref = tuple<Absyn.ComponentRef, Integer>;
3163
3164 public function findIteratorIndexedCrefs
3165 "Find all crefs in an expression which are subscripted with the given
3166 iterator, and return a list of cref-Integer tuples, where the cref is the
3167 index of the subscript."
3168 input Absyn.Exp inExp;
3169 input String inIterator;
3170 input list<IteratorIndexedCref> inCrefs = {};
3171 output list<IteratorIndexedCref> outCrefs;
3172 algorithm
3173 21 (_, outCrefs) := traverseExp(inExp,
3174 function findIteratorIndexedCrefs_traverser(inIterator = inIterator), {});
3175 21 outCrefs := List.fold(outCrefs,
3176 function List.unionEltOnTrue(inCompFunc = iteratorIndexedCrefsEqual), inCrefs);
3177 end findIteratorIndexedCrefs;
3178
3179 protected function findIteratorIndexedCrefs_traverser
3180 "Traversal function used by deduceReductionIterationRange. Used to find crefs
3181 which are subscripted by a given iterator."
3182 input Absyn.Exp inExp;
3183 input list<IteratorIndexedCref> inCrefs;
3184 input String inIterator;
3185 output Absyn.Exp outExp = inExp;
3186 output list<IteratorIndexedCref> outCrefs;
3187 algorithm
3188 outCrefs := match inExp
3189 case Absyn.CREF()
3190 45 then getIteratorIndexedCrefs(inExp.componentRef, inIterator, inCrefs);
3191
3192 else inCrefs;
3193 end match;
3194 end findIteratorIndexedCrefs_traverser;
3195
3196 protected function iteratorIndexedCrefsEqual
3197 "Checks whether two cref-index pairs are equal."
3198 input IteratorIndexedCref inCref1;
3199 input IteratorIndexedCref inCref2;
3200 output Boolean outEqual;
3201 protected
3202 Absyn.ComponentRef cr1, cr2;
3203 Integer idx1, idx2;
3204 algorithm
3205 2 (cr1, idx1) := inCref1;
3206 2 (cr2, idx2) := inCref2;
3207
3/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 1 time.
2 outEqual := idx1 == idx2 and crefEqual(cr1, cr2);
3208 end iteratorIndexedCrefsEqual;
3209
3210 protected function getIteratorIndexedCrefs
3211 "Checks if the given component reference is subscripted by the given iterator.
3212 Only cases where a subscript consists of only the iterator is considered.
3213 If so it adds a cref-index pair to the list, where the cref is the subscripted
3214 cref without subscripts, and the index is the subscripted dimension. E.g. for
3215 iterator i:
3216 a[i] => (a, 1), b[1, i] => (b, 2), c[i+1] => (), d[2].e[i] => (d[2].e, 1)"
3217 input Absyn.ComponentRef inCref;
3218 input String inIterator;
3219 input list<IteratorIndexedCref> inCrefs;
3220 output list<IteratorIndexedCref> outCrefs = inCrefs;
3221 protected
3222 list<tuple<Absyn.ComponentRef, Integer>> crefs;
3223 algorithm
3224 outCrefs := match inCref
3225 local
3226 list<Absyn.Subscript> subs;
3227 Integer idx;
3228 String name, id;
3229 Absyn.ComponentRef cref;
3230
3231 case Absyn.CREF_IDENT(name = id, subscripts = subs)
3232 algorithm
3233 // For each subscript, check if the subscript consists of only the
3234 // iterator we're looking for.
3235 idx := 1;
3236
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 49 times.
71 for sub in subs loop
3237 () := match sub
3238 case Absyn.SUBSCRIPT(subscript = Absyn.CREF(componentRef =
3239 Absyn.CREF_IDENT(name = name, subscripts = {})))
3240 algorithm
3241
3/4
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 18 times.
✓ Branch 4 taken 4 times.
22 if name == inIterator then
3242 18 outCrefs := (Absyn.CREF_IDENT(id, {}), idx) :: outCrefs;
3243 end if;
3244 then
3245 ();
3246
3247 else ();
3248 end match;
3249
3250 22 idx := idx + 1;
3251 end for;
3252 then
3253 outCrefs;
3254
3255 case Absyn.CREF_QUAL(name = id, subscripts = subs, componentRef = cref)
3256 algorithm
3257 4 crefs := getIteratorIndexedCrefs(cref, inIterator, {});
3258
3259 // Append the prefix from the qualified cref to any matches, and add
3260 // them to the result list.
3261
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
7 for cr in crefs loop
3262 3 (cref, idx) := cr;
3263 3 outCrefs := (Absyn.CREF_QUAL(id, subs, cref), idx) :: outCrefs;
3264 end for;
3265 4 then
3266 getIteratorIndexedCrefs(Absyn.CREF_IDENT(id, subs), inIterator, outCrefs);
3267
3268 case Absyn.CREF_FULLYQUALIFIED(componentRef = cref)
3269 algorithm
3270 1 crefs := getIteratorIndexedCrefs(cref, inIterator, {});
3271
3272 // Make any matches fully qualified, and add them to the result list.
3273
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
2 for cr in crefs loop
3274 1 (cref, idx) := cr;
3275 1 outCrefs := (Absyn.CREF_FULLYQUALIFIED(cref), idx) :: outCrefs;
3276 end for;
3277 then
3278 outCrefs;
3279
3280 else inCrefs;
3281 end match;
3282 end getIteratorIndexedCrefs;
3283
3284 public function getFileNameFromInfo
3285 input SourceInfo inInfo;
3286 output String inFileName;
3287 algorithm
3288 ✗ SOURCEINFO(fileName = inFileName) := inInfo;
3289 end getFileNameFromInfo;
3290
3291 public function isOuter
3292 "@author: adrpo
3293 this function returns true if the given Absyn.InnerOuter
3294 is one of Absyn.INNER_OUTER() or Absyn.OUTER()"
3295 input Absyn.InnerOuter io;
3296 output Boolean isItAnOuter;
3297 algorithm
3298 isItAnOuter := match io
3299 case Absyn.INNER_OUTER() then true;
3300 case Absyn.OUTER() then true;
3301 else false;
3302 end match;
3303 end isOuter;
3304
3305 public function isInner
3306 "@author: adrpo
3307 this function returns true if the given Absyn.InnerOuter
3308 is one of Absyn.INNER_OUTER() or Absyn.INNER()"
3309 input Absyn.InnerOuter io;
3310 output Boolean isItAnInner;
3311 algorithm
3312 isItAnInner := match io
3313 case Absyn.INNER_OUTER() then true;
3314 case Absyn.INNER() then true;
3315 else false;
3316 end match;
3317 end isInner;
3318
3319 public function isOnlyInner
3320 "Returns true if the Absyn.InnerOuter is Absyn.INNER, false otherwise."
3321 input Absyn.InnerOuter inIO;
3322 output Boolean outOnlyInner;
3323 algorithm
3324 outOnlyInner := match inIO
3325 case Absyn.INNER() then true;
3326 else false;
3327 end match;
3328 end isOnlyInner;
3329
3330 public function isOnlyOuter
3331 "Returns true if the Absyn.InnerOuter is Absyn.OUTER, false otherwise."
3332 input Absyn.InnerOuter inIO;
3333 output Boolean outOnlyOuter;
3334 algorithm
3335 outOnlyOuter := match inIO
3336 case Absyn.OUTER() then true;
3337 else false;
3338 end match;
3339 end isOnlyOuter;
3340
3341 public function isInnerOuter
3342 input Absyn.InnerOuter inIO;
3343 output Boolean outIsInnerOuter;
3344 algorithm
3345 outIsInnerOuter := match inIO
3346 case Absyn.INNER_OUTER() then true;
3347 else false;
3348 end match;
3349 end isInnerOuter;
3350
3351 public function isNotInnerOuter
3352 input Absyn.InnerOuter inIO;
3353 output Boolean outIsNotInnerOuter;
3354 algorithm
3355 outIsNotInnerOuter := match inIO
3356 case Absyn.NOT_INNER_OUTER() then true;
3357 else false;
3358 end match;
3359 end isNotInnerOuter;
3360
3361 public function innerOuterEqual "Returns true if two Absyn.InnerOuter's are equal"
3362 input Absyn.InnerOuter io1;
3363 input Absyn.InnerOuter io2;
3364 output Boolean res;
3365 algorithm
3366 res := match(io1,io2)
3367 case(Absyn.INNER(),Absyn.INNER()) then true;
3368 case(Absyn.OUTER(),Absyn.OUTER()) then true;
3369 case(Absyn.INNER_OUTER(),Absyn.INNER_OUTER()) then true;
3370 case(Absyn.NOT_INNER_OUTER(),Absyn.NOT_INNER_OUTER()) then true;
3371 else false;
3372 end match;
3373 end innerOuterEqual;
3374
3375 public function makeFullyQualified
3376 "Makes a path fully qualified unless it already is."
3377 input Absyn.Path inPath;
3378 output Absyn.Path outPath;
3379 algorithm
3380 outPath := match inPath
3381 case Absyn.FULLYQUALIFIED() then inPath;
3382 24057984 else Absyn.FULLYQUALIFIED(inPath);
3383 end match;
3384 end makeFullyQualified;
3385
3386 public function makeNotFullyQualified
3387 "Makes a path not fully qualified unless it already is."
3388 input Absyn.Path inPath;
3389 output Absyn.Path outPath;
3390 algorithm
3391 outPath := match inPath
3392 local Absyn.Path path;
3393 case Absyn.FULLYQUALIFIED(path) then path;
3394 else inPath;
3395 end match;
3396 end makeNotFullyQualified;
3397
3398 public function importEqual "Compares two import elements. "
3399 input Absyn.Import im1;
3400 input Absyn.Import im2;
3401 output Boolean outBoolean;
3402 algorithm
3403 outBoolean := match (im1,im2)
3404 case (Absyn.NAMED_IMPORT(), Absyn.NAMED_IMPORT())
3405 ✗ then stringEq(im1.name, im2.name) and pathEqual(im1.path, im2.path);
3406
3407 case (Absyn.QUAL_IMPORT(), Absyn.QUAL_IMPORT())
3408 154429 then pathEqual(im1.path, im2.path);
3409
3410 case (Absyn.UNQUAL_IMPORT(), Absyn.UNQUAL_IMPORT())
3411 ✗ then pathEqual(im1.path, im2.path);
3412
3413 else false;
3414 end match;
3415 end importEqual;
3416
3417 public function canonIfExp "Transforms an if-expression to canonical form (without else-if branches)"
3418 input Absyn.Exp inExp;
3419 output Absyn.Exp outExp;
3420 algorithm
3421 outExp := match inExp
3422 local
3423 Absyn.Exp cond,tb,eb,ei_cond,ei_tb,e;
3424 list<tuple<Absyn.Exp,Absyn.Exp>> eib;
3425
3426 case Absyn.IFEXP(elseIfBranch={}) then inExp;
3427 case Absyn.IFEXP(ifExp=cond,trueBranch=tb,elseBranch=eb,elseIfBranch=(ei_cond,ei_tb)::eib)
3428 algorithm
3429 100 e := canonIfExp(Absyn.IFEXP(ei_cond,ei_tb,eb,eib));
3430 100 then Absyn.IFEXP(cond,tb,e,{});
3431 end match;
3432 end canonIfExp;
3433
3434 public function onlyLiteralsInAnnotationMod
3435 "@author: adrpo
3436 This function checks if a modification only contains literal expressions"
3437 input list<Absyn.ElementArg> inMod;
3438 output Boolean onlyLiterals;
3439 algorithm
3440 onlyLiterals := matchcontinue inMod
3441 local
3442 list<Absyn.ElementArg> dive, rest;
3443 Absyn.EqMod eqMod;
3444
3445 case {} then true;
3446
3447 // skip "interaction" annotation!
3448 case Absyn.MODIFICATION(path = Absyn.IDENT(name = "interaction")) :: rest
3449 ✗ then onlyLiteralsInAnnotationMod(rest);
3450
3451
3452 // search inside, some(exp)
3453 case Absyn.MODIFICATION(modification = SOME(Absyn.CLASSMOD(dive, eqMod))) :: rest
3454
5/6
✓ Branch 1 taken 238 times.
✓ Branch 2 taken 50 times.
✓ Branch 4 taken 238 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 77 times.
✓ Branch 8 taken 161 times.
288 then onlyLiteralsInEqMod(eqMod) and
3455 onlyLiteralsInAnnotationMod(dive) and
3456 onlyLiteralsInAnnotationMod(rest);
3457
3458 ✗ case _ :: rest then onlyLiteralsInAnnotationMod(rest);
3459
3460 // failed above, return false
3461 else false;
3462 end matchcontinue;
3463 end onlyLiteralsInAnnotationMod;
3464
3465 public function onlyLiteralsInEqMod
3466 "@author: adrpo
3467 This function checks if an optional expression only contains literal expressions"
3468 input Absyn.EqMod eqMod;
3469 output Boolean onlyLiterals;
3470 algorithm
3471 onlyLiterals := match eqMod
3472 local
3473
3474 case Absyn.NOMOD() then true;
3475
3476 // search inside, some(exp)
3477 300 case Absyn.EQMOD() then onlyLiteralsInExp(eqMod.exp);
3478
3479 end match;
3480 end onlyLiteralsInEqMod;
3481
3482 public function onlyLiteralsInExp
3483 "Checks if an expression only contains literal expressions."
3484 input Absyn.Exp exp;
3485 output Boolean onlyLiterals;
3486 protected
3487 list<Absyn.Exp> lst;
3488 algorithm
3489
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 380 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 380 times.
380 (_, lst::{}) := traverseExpBidir(exp, onlyLiteralsInExpEnter, onlyLiteralsInExpExit, {}::{});
3490 380 onlyLiterals := listEmpty(lst);
3491 end onlyLiteralsInExp;
3492
3493 protected function onlyLiteralsInExpEnter
3494 "@author: adrpo
3495 Visitor function for checking if Absyn.Exp contains only literals, NO CREFS!
3496 It returns an empty list if it doesn't contain any crefs!"
3497 input Absyn.Exp inExp;
3498 input list<list<Absyn.Exp>> inLst;
3499 output Absyn.Exp outExp;
3500 output list<list<Absyn.Exp>> outLst;
3501 algorithm
3502 (outExp,outLst) := match (inExp,inLst)
3503 local
3504 Boolean b;
3505 Absyn.Exp e;
3506 list<Absyn.Exp> lst;
3507 list<list<Absyn.Exp>> rest;
3508 String name;
3509
3510 // first handle all graphic enumerations!
3511 // FillPattern.*, Smooth.*, TextAlignment.*, etc!
3512 case (e as Absyn.CREF(Absyn.CREF_QUAL(name=name)), lst::rest)
3513 algorithm
3514 110 b := listMember(name,{
3515 "LinePattern",
3516 "Arrow",
3517 "FillPattern",
3518 "BorderPattern",
3519 "TextStyle",
3520 "Smooth",
3521 "TextAlignment"});
3522 110 lst := List.consOnTrue(not b,e,lst);
3523 then (inExp, lst::rest);
3524
3525 // crefs, add to list
3526 case (Absyn.CREF(), lst::rest) then (inExp,(inExp::lst)::rest);
3527
3528 // anything else, return the same!
3529 else (inExp,inLst);
3530
3531 end match;
3532 end onlyLiteralsInExpEnter;
3533
3534 protected function onlyLiteralsInExpExit
3535 "@author: adrpo
3536 Visitor function for checking if Absyn.Exp contains only literals, NO CREFS!
3537 It returns an empty list if it doesn't contain any crefs!"
3538 input Absyn.Exp inExp;
3539 input list<list<Absyn.Exp>> inLst;
3540 output Absyn.Exp outExp;
3541 output list<list<Absyn.Exp>> outLst;
3542 algorithm
3543 (outExp,outLst) := match (inExp,inLst)
3544 local
3545 list<list<Absyn.Exp>> lst;
3546
3547 // first handle DynamicSelect; pop the stack (ignore any crefs inside DynamicSelect)
3548 case (Absyn.CALL(function_ = Absyn.CREF_IDENT(name = "DynamicSelect")), lst)
3549 then (inExp, lst);
3550
3551 // anything else, return the same!
3552 else (inExp,inLst);
3553
3554 end match;
3555 end onlyLiteralsInExpExit;
3556
3557 public function makeCons
3558 input Absyn.Exp e1;
3559 input Absyn.Exp e2;
3560 output Absyn.Exp e;
3561 algorithm
3562 397 e := Absyn.CONS(e1,e2);
3563 annotation(__OpenModelica_EarlyInline = true);
3564 end makeCons;
3565
3566 public function crefIdent
3567 input Absyn.ComponentRef cr;
3568 output String str;
3569 algorithm
3570
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 55 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 55 times.
55 Absyn.CREF_IDENT(str,{}) := cr;
3571 end crefIdent;
3572
3573 public function unqotePathIdents
3574 input Absyn.Path inPath;
3575 output Absyn.Path path;
3576 algorithm
3577 1295 path := stringListPath(List.map(pathToStringList(inPath), System.unquoteIdentifier));
3578 end unqotePathIdents;
3579
3580 public function unqualifyCref
3581 "If the given component reference is fully qualified this function removes the
3582 fully qualified qualifier, otherwise does nothing."
3583 input Absyn.ComponentRef inCref;
3584 output Absyn.ComponentRef outCref;
3585 algorithm
3586 outCref := match inCref
3587 3180 case Absyn.CREF_FULLYQUALIFIED() then inCref.componentRef;
3588 else inCref;
3589 end match;
3590 end unqualifyCref;
3591
3592 public function pathIsFullyQualified
3593 input Absyn.Path inPath;
3594 output Boolean outIsQualified;
3595 algorithm
3596 outIsQualified := match inPath
3597 case Absyn.FULLYQUALIFIED() then true;
3598 else false;
3599 end match;
3600 end pathIsFullyQualified;
3601
3602 public function pathIsIdent
3603 input Absyn.Path inPath;
3604 output Boolean outIsIdent;
3605 algorithm
3606 outIsIdent := match inPath
3607 case Absyn.IDENT() then true;
3608 else false;
3609 end match;
3610 end pathIsIdent;
3611
3612 public function pathIsQual
3613 input Absyn.Path inPath;
3614 output Boolean outIsQual;
3615 algorithm
3616 outIsQual := match inPath
3617 case Absyn.QUALIFIED() then true;
3618 else false;
3619 end match;
3620 end pathIsQual;
3621
3622 public function withinEqual
3623 input Absyn.Within within1;
3624 input Absyn.Within within2;
3625 output Boolean b;
3626 algorithm
3627 b := match (within1,within2)
3628 case (Absyn.TOP(),Absyn.TOP()) then true;
3629 1251774 case (Absyn.WITHIN(),Absyn.WITHIN()) then pathEqual(within1.path, within2.path);
3630 else false;
3631 end match;
3632 end withinEqual;
3633
3634 public function withinEqualCaseInsensitive
3635 input Absyn.Within within1;
3636 input Absyn.Within within2;
3637 output Boolean b;
3638 algorithm
3639 b := match (within1,within2)
3640 case (Absyn.TOP(),Absyn.TOP()) then true;
3641 ✗ case (Absyn.WITHIN(),Absyn.WITHIN()) then pathEqualCaseInsensitive(within1.path,within2.path);
3642 else false;
3643 end match;
3644 end withinEqualCaseInsensitive;
3645
3646 public function withinString
3647 input Absyn.Within w1;
3648 output String str;
3649 algorithm
3650 str := match w1
3651 case Absyn.TOP() then "within ;";
3652 ✗ case Absyn.WITHIN() then "within " + pathString(w1.path) + ";";
3653 end match;
3654 end withinString;
3655
3656 public function joinWithinPath
3657 input Absyn.Within within_;
3658 input Absyn.Path path;
3659 output Absyn.Path outPath;
3660 algorithm
3661 outPath := match within_
3662 case Absyn.TOP() then path;
3663 188101 case Absyn.WITHIN() then joinPaths(within_.path,path);
3664 end match;
3665 end joinWithinPath;
3666
3667 public function innerOuterStr
3668 input Absyn.InnerOuter io;
3669 output String str;
3670 algorithm
3671 str := match io
3672 case Absyn.INNER_OUTER() then "inner outer";
3673 case Absyn.INNER() then "inner";
3674 case Absyn.OUTER() then "outer";
3675 case Absyn.NOT_INNER_OUTER() then "";
3676 end match;
3677 end innerOuterStr;
3678
3679 public function subscriptExpOpt
3680 input Absyn.Subscript inSub;
3681 output Option<Absyn.Exp> outExpOpt;
3682 algorithm
3683 outExpOpt := match inSub
3684 ✗ case Absyn.SUBSCRIPT() then SOME(inSub.subscript);
3685 case Absyn.NOSUB() then NONE();
3686 end match;
3687 end subscriptExpOpt;
3688
3689 public function crefInsertSubscriptLstLst
3690 input Absyn.Exp inExp;
3691 input list<list<Absyn.Subscript>> inLst;
3692 output Absyn.Exp outExp;
3693 output list<list<Absyn.Subscript>> outLst;
3694 algorithm
3695 (outExp,outLst) := matchcontinue(inExp,inLst)
3696 local
3697 Absyn.ComponentRef cref,cref2;
3698 list<list<Absyn.Subscript>> subs;
3699 case (Absyn.CREF(componentRef=cref),subs)
3700 algorithm
3701 ✗ cref2 := crefInsertSubscriptLstLst2(cref,subs);
3702 ✗ then
3703 (Absyn.CREF(cref2),subs);
3704 else (inExp,inLst);
3705 end matchcontinue;
3706 end crefInsertSubscriptLstLst;
3707
3708 public function crefInsertSubscriptLstLst2
3709 "Helper function to crefInsertSubscriptLstLst"
3710 input Absyn.ComponentRef inCref;
3711 input list<list<Absyn.Subscript>> inSubs;
3712 output Absyn.ComponentRef outCref;
3713 algorithm
3714 outCref := matchcontinue(inCref,inSubs)
3715 local
3716 Absyn.ComponentRef cref, cref2;
3717 Absyn.Ident n;
3718 list<list<Absyn.Subscript>> subs;
3719 list<Absyn.Subscript> s;
3720 case (cref,{})
3721 then cref;
3722 case (Absyn.CREF_IDENT(name = n), {s})
3723 ✗ then Absyn.CREF_IDENT(n,s);
3724 case (Absyn.CREF_QUAL(name = n, componentRef = cref), s::subs)
3725 algorithm
3726 ✗ cref2 := crefInsertSubscriptLstLst2(cref, subs);
3727 ✗ then
3728 Absyn.CREF_QUAL(n,s,cref2);
3729 case (Absyn.CREF_FULLYQUALIFIED(componentRef = cref), subs)
3730 algorithm
3731 ✗ cref2 := crefInsertSubscriptLstLst2(cref, subs);
3732 ✗ then
3733 crefMakeFullyQualified(cref2);
3734 end matchcontinue;
3735 end crefInsertSubscriptLstLst2;
3736
3737 public function isCref
3738 input Absyn.Exp exp;
3739 output Boolean b;
3740 algorithm
3741 b := match exp
3742 case Absyn.CREF() then true;
3743 else false;
3744 end match;
3745 end isCref;
3746
3747 public function isTuple
3748 input Absyn.Exp exp;
3749 output Boolean b;
3750 algorithm
3751 b := match exp
3752 case Absyn.TUPLE(__) then true;
3753 else false;
3754 end match;
3755 end isTuple;
3756
3757 public function allFieldsAreCrefs
3758 "@author: johti
3759 Returns true if all fields are crefs"
3760 input list<Absyn.Exp> expLst;
3761 output Boolean b;
3762 algorithm
3763 ✗ b := List.all(expLst, complexIsCref);
3764 end allFieldsAreCrefs;
3765
3766 public function complexIsCref
3767 " @author: johti
3768 Returns true if everything contained
3769 in the tuple or a cons cell is a constant reference."
3770 input Absyn.Exp inExp;
3771 output Boolean b;
3772 algorithm
3773 b := match inExp
3774 ✗ case Absyn.TUPLE(__) then allFieldsAreCrefs(inExp.expressions);
3775 ✗ case Absyn.CONS(__) then complexIsCref(inExp.head) and complexIsCref(inExp.rest);
3776 ✗ case _ then isCref(inExp);
3777 end match;
3778 end complexIsCref;
3779
3780 public function isDerCref
3781 input Absyn.Exp exp;
3782 output Boolean b;
3783 algorithm
3784 b := match exp
3785 case Absyn.CALL(function_ = Absyn.CREF_IDENT("der",{}),
3786 functionArgs = Absyn.FUNCTIONARGS({Absyn.CREF()},{})) then true;
3787 else false;
3788 end match;
3789 end isDerCref;
3790
3791 public function isDerCrefFail
3792 input Absyn.Exp exp;
3793 algorithm
3794 ✗ Absyn.CALL(function_ = Absyn.CREF_IDENT("der",{}),
3795 functionArgs = Absyn.FUNCTIONARGS({Absyn.CREF()},{})) := exp;
3796 end isDerCrefFail;
3797
3798 public function getExpsFromArrayDim
3799 "author: adrpo
3800 returns all the expressions from array dimension as a list
3801 also returns if we have unknown dimensions in the array dimension"
3802 input Absyn.ArrayDim inAd;
3803 output Boolean hasUnknownDimensions;
3804 output list<Absyn.Exp> outExps;
3805 algorithm
3806 323508 (hasUnknownDimensions, outExps) := getExpsFromArrayDim_tail(inAd, {});
3807 end getExpsFromArrayDim;
3808
3809 public function getExpsFromArrayDimOpt
3810 "author: adrpo
3811 returns all the expressions from array dimension as a list
3812 also returns if we have unknown dimensions in the array dimension"
3813 input Option<Absyn.ArrayDim> inAdO;
3814 output Boolean hasUnknownDimensions;
3815 output list<Absyn.Exp> outExps;
3816 algorithm
3817 (hasUnknownDimensions, outExps) := match inAdO
3818 local Absyn.ArrayDim ad;
3819
3820 372 case NONE() then (false, {});
3821 ✗ case SOME(ad) then getExpsFromArrayDim_tail(ad, {});
3822 end match;
3823 end getExpsFromArrayDimOpt;
3824
3825 public function getExpsFromArrayDim_tail
3826 "author: adrpo
3827 returns all the expressions from array dimension as a list
3828 also returns if we have unknown dimensions in the array dimension"
3829 input Absyn.ArrayDim inAd;
3830 input list<Absyn.Exp> inAccumulator;
3831 output Boolean hasUnknownDimensions;
3832 output list<Absyn.Exp> outExps;
3833 algorithm
3834 (hasUnknownDimensions, outExps) := match(inAd, inAccumulator)
3835 local
3836 list<Absyn.Subscript> rest;
3837 Absyn.Exp e;
3838 list<Absyn.Exp> exps, acc;
3839 Boolean b;
3840
3841 // handle empty list
3842 323508 case ({}, acc) then (false, listReverse(acc));
3843
3844 // handle Absyn.SUBSCRIPT
3845 case (Absyn.SUBSCRIPT(e)::rest, acc)
3846 algorithm
3847 48414 (b, exps) := getExpsFromArrayDim_tail(rest, e::acc);
3848 then
3849 (b, exps);
3850
3851 // handle Absyn.NOSUB
3852 case (Absyn.NOSUB()::rest, acc)
3853 algorithm
3854 1701 (_, exps) := getExpsFromArrayDim_tail(rest, acc);
3855 1701 then
3856 (true, exps);
3857 end match;
3858 end getExpsFromArrayDim_tail;
3859
3860 public function isInputOrOutput
3861 "@author: adrpo
3862 returns true if the given direction is input or output"
3863 input Absyn.Direction direction;
3864 output Boolean isIorO "input or output only";
3865 algorithm
3866 isIorO := match direction
3867 case Absyn.INPUT() then true;
3868 case Absyn.OUTPUT() then true;
3869 case Absyn.INPUT_OUTPUT() then true;
3870 case Absyn.BIDIR() then false;
3871 end match;
3872 end isInputOrOutput;
3873
3874 public function isInput
3875 input Absyn.Direction inDirection;
3876 output Boolean outIsInput;
3877 algorithm
3878 outIsInput := match inDirection
3879 case Absyn.INPUT() then true;
3880 case Absyn.INPUT_OUTPUT() then true;
3881 else false;
3882 end match;
3883 end isInput;
3884
3885 public function isOutput
3886 input Absyn.Direction inDirection;
3887 output Boolean outIsOutput;
3888 algorithm
3889 outIsOutput := match inDirection
3890 case Absyn.OUTPUT() then true;
3891 case Absyn.INPUT_OUTPUT() then true;
3892 else false;
3893 end match;
3894 end isOutput;
3895
3896 public function directionEqual
3897 input Absyn.Direction inDirection1;
3898 input Absyn.Direction inDirection2;
3899 output Boolean outEqual;
3900 algorithm
3901 outEqual := match(inDirection1, inDirection2)
3902 case (Absyn.BIDIR(), Absyn.BIDIR()) then true;
3903 case (Absyn.INPUT(), Absyn.INPUT()) then true;
3904 case (Absyn.OUTPUT(), Absyn.OUTPUT()) then true;
3905 case (Absyn.INPUT_OUTPUT(), Absyn.INPUT_OUTPUT()) then true;
3906 else false;
3907 end match;
3908 end directionEqual;
3909
3910 public function isFieldEqual
3911 input Absyn.IsField isField1;
3912 input Absyn.IsField isField2;
3913 output Boolean outEqual;
3914 algorithm
3915 outEqual := match(isField1, isField2)
3916 case (Absyn.NONFIELD(), Absyn.NONFIELD()) then true;
3917 case (Absyn.FIELD(), Absyn.FIELD()) then true;
3918 else false;
3919 end match;
3920 end isFieldEqual;
3921
3922 public function pathLt
3923 input Absyn.Path path1;
3924 input Absyn.Path path2;
3925 output Boolean lt;
3926 algorithm
3927 130363 lt := stringCompare(pathString(path1),pathString(path2)) < 0;
3928 end pathLt;
3929
3930 public function pathGe
3931 input Absyn.Path path1;
3932 input Absyn.Path path2;
3933 output Boolean ge;
3934 algorithm
3935 130363 ge := not pathLt(path1,path2);
3936 end pathGe;
3937
3938 public function getShortClass "Strips out long class definitions"
3939 input output Absyn.Class cl;
3940 algorithm
3941 () := match cl
3942 ✗ case Absyn.CLASS(body=Absyn.PARTS()) then fail();
3943 ✗ case Absyn.CLASS(body=Absyn.CLASS_EXTENDS()) then fail();
3944 case Absyn.CLASS()
3945 algorithm
3946 ✗ cl.body := stripClassDefComment(cl.body);
3947 then
3948 ();
3949 end match;
3950 end getShortClass;
3951
3952 protected function stripClassDefComment
3953 "Strips out class definition comments."
3954 input output Absyn.ClassDef cl;
3955 algorithm
3956 () := match cl
3957 ✗ case Absyn.PARTS() algorithm cl.comment := NONE(); then ();
3958 ✗ case Absyn.DERIVED() algorithm cl.comment := NONE(); then ();
3959 ✗ case Absyn.ENUMERATION() algorithm cl.comment := NONE(); then ();
3960 ✗ case Absyn.OVERLOAD() algorithm cl.comment := NONE(); then ();
3961 ✗ case Absyn.CLASS_EXTENDS() algorithm cl.comment := NONE(); then ();
3962 ✗ case Absyn.PDER() algorithm cl.comment := NONE(); then ();
3963 else ();
3964 end match;
3965 end stripClassDefComment;
3966
3967 public function getFunctionInterface "Strips out the parts of a function definition that are not needed for the interface"
3968 input output Absyn.Class cl;
3969 protected
3970 Absyn.ClassDef def;
3971 list<Absyn.ElementItem> elts;
3972 algorithm
3973 () := match cl
3974 case Absyn.CLASS(restriction = Absyn.R_FUNCTION(), body = def as Absyn.PARTS())
3975 algorithm
3976 ✗ elts as _ :: _ := List.fold(listReverse(def.classParts), getFunctionInterfaceParts, {});
3977 ✗ cl.body := Absyn.PARTS(def.typeVars, def.classAttrs, {Absyn.PUBLIC(elts)}, {}, NONE());
3978 ✗ cl.commentsBeforeEnd := {};
3979 ✗ cl.commentsAfterEnd := {};
3980 then
3981 ();
3982 end match;
3983 end getFunctionInterface;
3984
3985 protected function getFunctionInterfaceParts
3986 input Absyn.ClassPart part;
3987 input list<Absyn.ElementItem> elts;
3988 output list<Absyn.ElementItem> oelts;
3989 algorithm
3990 oelts := match (part,elts)
3991 local
3992 list<Absyn.ElementItem> elts1,elts2;
3993 case (Absyn.PUBLIC(elts1),elts2)
3994 algorithm
3995 ✗ elts1 := List.filterOnTrue(elts1,filterAnnotationItem);
3996 ✗ then listAppend(elts1,elts2);
3997 else elts;
3998 end match;
3999 end getFunctionInterfaceParts;
4000
4001 protected function filterAnnotationItem
4002 input Absyn.ElementItem elt;
4003 output Boolean outB;
4004 algorithm
4005 outB := match elt
4006 case Absyn.ELEMENTITEM() then true;
4007 else false;
4008 end match;
4009 end filterAnnotationItem;
4010
4011 public function filterNestedClasses
4012 "Filter outs the nested classes from the class if any."
4013 input output Absyn.Class cl;
4014 protected
4015 Absyn.ClassDef def;
4016 algorithm
4017 () := match cl
4018 case Absyn.CLASS(body = def as Absyn.PARTS())
4019 algorithm
4020 ✗ def.classParts := List.fold(listReverse(def.classParts), filterNestedClassesParts, {});
4021 ✗ cl.body := def;
4022 then
4023 ();
4024
4025 else ();
4026 end match;
4027 end filterNestedClasses;
4028
4029 protected function filterNestedClassesParts
4030 "Helper funciton for filterNestedClassesParts."
4031 input Absyn.ClassPart classPart;
4032 input list<Absyn.ClassPart> inClassParts;
4033 output list<Absyn.ClassPart> outClassPart;
4034 algorithm
4035 outClassPart := match (classPart, inClassParts)
4036 local
4037 list<Absyn.ClassPart> classParts;
4038 list<Absyn.ElementItem> elts;
4039 case (Absyn.PUBLIC(elts), classParts)
4040 algorithm
4041 ✗ classPart.contents := List.filterOnFalse(elts, isElementItemClass);
4042 then classPart::classParts;
4043 case (Absyn.PROTECTED(elts), classParts)
4044 algorithm
4045 ✗ classPart.contents := List.filterOnFalse(elts, isElementItemClass);
4046 then classPart::classParts;
4047 else classPart::inClassParts;
4048 end match;
4049 end filterNestedClassesParts;
4050
4051 public function getExternalDecl
4052 "@author: adrpo
4053 returns the Absyn.EXTERNAL form parts if there is any.
4054 if there is none, it fails!"
4055 input Absyn.Class inCls;
4056 output Absyn.ClassPart outExternal;
4057 protected
4058 list<Absyn.ClassPart> class_parts;
4059 algorithm
4060
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 Absyn.CLASS(body = Absyn.PARTS(classParts = class_parts)) := inCls;
4061 4 outExternal := List.find(class_parts, isExternalPart);
4062 end getExternalDecl;
4063
4064 public function isExternalPart
4065 input Absyn.ClassPart inClassPart;
4066 output Boolean outFound;
4067 algorithm
4068 outFound := match inClassPart
4069 case Absyn.EXTERNAL() then true;
4070 else false;
4071 end match;
4072 end isExternalPart;
4073
4074 public function isParts
4075 input Absyn.ClassDef cl;
4076 output Boolean b;
4077 algorithm
4078 b := match cl
4079 case Absyn.PARTS() then true;
4080 else false;
4081 end match;
4082 end isParts;
4083
4084 public function makeClassElement "Makes a class into an Absyn.ElementItem"
4085 input Absyn.Class cl;
4086 output Absyn.ElementItem el;
4087 protected
4088 Absyn.Info info;
4089 Boolean fp;
4090 algorithm
4091 1251774 Absyn.CLASS(finalPrefix = fp, info = info) := cl;
4092
1/2
✓ Branch 1 taken 1251774 times.
✗ Branch 2 not taken.
2503548 el := Absyn.ELEMENTITEM(Absyn.ELEMENT(fp,NONE(),Absyn.NOT_INNER_OUTER(),Absyn.CLASSDEF(false,cl),info,NONE()));
4093 end makeClassElement;
4094
4095 public function componentName
4096 input Absyn.ComponentItem c;
4097 output String name;
4098 algorithm
4099 14433 Absyn.COMPONENTITEM(component=Absyn.COMPONENT(name=name)) := c;
4100 end componentName;
4101
4102 public function expContainsInitial
4103 "@author:
4104 returns true if expression contains initial()"
4105 input Absyn.Exp inExp;
4106 output Boolean hasInitial;
4107 algorithm
4108 hasInitial := matchcontinue inExp
4109 local Boolean b;
4110 case _
4111 algorithm
4112 115 (_, b) := traverseExp(inExp, isInitialTraverseHelper, false);
4113 then
4114 b;
4115 else false;
4116 end matchcontinue;
4117 end expContainsInitial;
4118
4119 protected function isInitialTraverseHelper
4120 "@author:
4121 returns true if expression is initial()"
4122 input Absyn.Exp inExp;
4123 input Boolean inBool;
4124 output Absyn.Exp outExp;
4125 output Boolean outBool;
4126 algorithm
4127 (outExp,outBool) := match inExp
4128 local Absyn.Exp e; Boolean b;
4129
4130 // make sure we don't have not initial()
4131 case Absyn.UNARY(Absyn.NOT(), _) then (inExp,inBool);
4132 // we have initial
4133 case e
4134 algorithm
4135 665 b := isInitial(e);
4136 then (e, b);
4137 else (inExp,inBool);
4138 end match;
4139 end isInitialTraverseHelper;
4140
4141 public function isInitial
4142 "@author:
4143 returns true if expression is initial()"
4144 input Absyn.Exp inExp;
4145 output Boolean hasReinit;
4146 algorithm
4147 hasReinit := match inExp
4148 case Absyn.CALL(function_ = Absyn.CREF_IDENT("initial", _)) then true;
4149 case Absyn.CALL(function_ = Absyn.CREF_FULLYQUALIFIED(Absyn.CREF_IDENT("initial", _))) then true;
4150 else false;
4151 end match;
4152 end isInitial;
4153
4154 public function importPath
4155 "Return the path of the given import."
4156 input Absyn.Import inImport;
4157 output Absyn.Path outPath;
4158 algorithm
4159 outPath := match inImport
4160 local
4161 Absyn.Path path;
4162
4163 case Absyn.NAMED_IMPORT(path = path) then path;
4164 case Absyn.QUAL_IMPORT(path = path) then path;
4165 case Absyn.UNQUAL_IMPORT(path = path) then path;
4166 case Absyn.GROUP_IMPORT(prefix = path) then path;
4167
4168 end match;
4169 end importPath;
4170
4171 public function setImportPath
4172 input output Absyn.Import imp;
4173 input Absyn.Path path;
4174 algorithm
4175 () := match imp
4176 ✗ case Absyn.NAMED_IMPORT() algorithm imp.path := path; then ();
4177 ✗ case Absyn.QUAL_IMPORT() algorithm imp.path := path; then ();
4178 ✗ case Absyn.UNQUAL_IMPORT() algorithm imp.path := path; then ();
4179 ✗ case Absyn.GROUP_IMPORT() algorithm imp.prefix := path; then ();
4180 end match;
4181 end setImportPath;
4182
4183 public function importName
4184 "Returns the import name of a named or qualified import."
4185 input Absyn.Import inImport;
4186 output Absyn.Ident outName;
4187 algorithm
4188 outName := match inImport
4189 // Named import has a given name, 'import D = A.B.C' => D.
4190 942 case Absyn.NAMED_IMPORT() then inImport.name;
4191 // Qualified import uses the last identifier, 'import A.B.C' => C.
4192 11597 case Absyn.QUAL_IMPORT() then pathLastIdent(inImport.path);
4193 end match;
4194 end importName;
4195
4196 public function mergeAnnotationsList
4197 input Absyn.Annotation oldAnnotation;
4198 input list<Absyn.Annotation> newAnnotations;
4199 output Absyn.Annotation outAnnotation = oldAnnotation;
4200 algorithm
4201
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 54 times.
106 for ann in newAnnotations loop
4202 52 outAnnotation := mergeAnnotations(ann, outAnnotation);
4203 end for;
4204 end mergeAnnotationsList;
4205
4206 public function mergeAnnotations
4207 "Merges an old annotation with a new. If mergeSubMods is true it merges the
4208 annotations recursively, otherwise it only merges the first level of the
4209 annotation. Example:
4210 mergeAnnotations(a(x = 1, y = 2), a(x = 3)) =>
4211 mergeSubMods = false: a(x = 3)
4212 mergeSubMods = true: a(x = 3, y = 2)
4213
4214 If mergeEqMods is true it tries to concatenate binding equation expression
4215 such as Icon/Diagram graphics arrays, otherwise the new binding overwrites
4216 the old one.
4217 "
4218 input Absyn.Annotation oldAnnotation;
4219 input Absyn.Annotation newAnnotation;
4220 input Boolean mergeSubMods = false;
4221 input Boolean mergeEqMods = false;
4222 output Absyn.Annotation outAnnotation;
4223 algorithm
4224 outAnnotation := match (oldAnnotation, newAnnotation)
4225 case (Absyn.ANNOTATION(elementArgs = {}), _) then newAnnotation;
4226 case (_, Absyn.ANNOTATION(elementArgs = {})) then oldAnnotation;
4227 52 else Absyn.ANNOTATION(mergeAnnotations2(oldAnnotation.elementArgs, newAnnotation.elementArgs,
4228 mergeSubMods, mergeEqMods));
4229 end match;
4230 end mergeAnnotations;
4231
4232 protected function mergeAnnotations2
4233 input list<Absyn.ElementArg> oldArgs;
4234 input list<Absyn.ElementArg> newArgs;
4235 input Boolean mergeSubMods = false;
4236 input Boolean mergeEqMods = false;
4237 output list<Absyn.ElementArg> outArgs = oldArgs;
4238 protected
4239 Boolean found;
4240 list<Absyn.ElementArg> new_args = {};
4241 algorithm
4242
2/2
✓ Branch 0 taken 216 times.
✓ Branch 1 taken 207 times.
423 for arg in newArgs loop
4243 // Try to merge the annotation with an existing one.
4244
1/4
✗ Branch 2 not taken.
✓ Branch 3 taken 216 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
216 (outArgs, found) := List.findAndMap(outArgs,
4245 function isModificationOfPath(path = elementArgName(arg)),
4246 if mergeSubMods then
4247 function mergeAnnotations3(newArg = arg, mergeEqMods = mergeEqMods) else
4248 function subModsInSameOrder(newmod = arg));
4249
4250
2/2
✓ Branch 0 taken 71 times.
✓ Branch 1 taken 145 times.
216 if not found then
4251 new_args := arg :: new_args;
4252 end if;
4253 end for;
4254
4255 // Add any completely new annotations to the end of the list.
4256 207 outArgs := listAppend(outArgs, listReverseInPlace(new_args)) annotation(__OpenModelica_DisableListAppendWarning = true);
4257 end mergeAnnotations2;
4258
4259 protected function mergeAnnotations3
4260 input Absyn.ElementArg oldArg;
4261 input Absyn.ElementArg newArg;
4262 input Boolean mergeEqMods;
4263 output Absyn.ElementArg outArg;
4264 protected
4265 list<Absyn.ElementArg> old_args, new_args;
4266 Absyn.EqMod old_eq, new_eq;
4267 Option<String> cmt;
4268 algorithm
4269 outArg := match (oldArg, newArg)
4270 case (Absyn.ElementArg.MODIFICATION(modification = NONE()), _) then newArg;
4271 case (_, Absyn.ElementArg.MODIFICATION(modification = NONE())) then oldArg;
4272 case (Absyn.ElementArg.MODIFICATION(modification = SOME(Absyn.Modification.CLASSMOD(old_args, old_eq))),
4273 Absyn.ElementArg.MODIFICATION(modification = SOME(Absyn.Modification.CLASSMOD(new_args, new_eq))))
4274 algorithm
4275 ✗ new_eq := mergeAnnotationEqMods(old_eq, new_eq, mergeEqMods);
4276 ✗ new_args := mergeAnnotations2(old_args, new_args, true, mergeEqMods);
4277 ✗ cmt := if isSome(newArg.comment) then newArg.comment else oldArg.comment;
4278 ✗ then
4279 Absyn.ElementArg.MODIFICATION(false, Absyn.NON_EACH(), oldArg.path,
4280 SOME(Absyn.Modification.CLASSMOD(new_args, new_eq)), cmt, oldArg.info);
4281 else newArg;
4282 end match;
4283 end mergeAnnotations3;
4284
4285 protected function mergeAnnotationEqMods
4286 input Absyn.EqMod oldEq;
4287 input Absyn.EqMod newEq;
4288 input Boolean mergeExpressions = false;
4289 output Absyn.EqMod outEq;
4290 protected
4291 Absyn.Exp new_exp, old_exp;
4292 algorithm
4293 outEq := match (oldEq, newEq)
4294 case (Absyn.EqMod.NOMOD(), _) then newEq;
4295 case (_, Absyn.EqMod.NOMOD()) then oldEq;
4296 case (Absyn.EqMod.EQMOD(exp = old_exp), Absyn.EqMod.EQMOD(exp = new_exp))
4297 guard mergeExpressions
4298 algorithm
4299 new_exp := match (old_exp, new_exp)
4300 case (Absyn.Exp.ARRAY(arrayExp = Absyn.Exp.CALL() :: _),
4301 Absyn.Exp.ARRAY(arrayExp = Absyn.Exp.CALL() :: _))
4302 ✗ then Absyn.Exp.ARRAY(listAppend(old_exp.arrayExp, new_exp.arrayExp));
4303 else new_exp;
4304 end match;
4305 ✗ then
4306 Absyn.EqMod.EQMOD(new_exp, newEq.info);
4307 else newEq;
4308 end match;
4309 end mergeAnnotationEqMods;
4310
4311 public function mergeCommentAnnotation
4312 "Merges an annotation into a Absyn.Comment option."
4313 input Absyn.Annotation inAnnotation;
4314 input Option<Absyn.Comment> inComment;
4315 output Option<Absyn.Comment> outComment;
4316 algorithm
4317 outComment := match inComment
4318 local
4319 Absyn.Annotation ann;
4320 Option<String> cmt;
4321
4322 // No comment, create a new one.
4323 case NONE()
4324 ✗ then SOME(Absyn.COMMENT(SOME(inAnnotation), NONE()));
4325
4326 // A comment without annotation, insert the annotation.
4327 case SOME(Absyn.COMMENT(annotation_ = NONE(), comment = cmt))
4328 ✗ then SOME(Absyn.COMMENT(SOME(inAnnotation), cmt));
4329
4330 // A comment with annotation, merge the annotations.
4331 case SOME(Absyn.COMMENT(annotation_ = SOME(ann), comment = cmt))
4332 ✗ then SOME(Absyn.COMMENT(SOME(mergeAnnotations(ann, inAnnotation)), cmt));
4333
4334 end match;
4335 end mergeCommentAnnotation;
4336
4337 public function mergeModifiers
4338 "Merges two modifiers, with the outer modifiers overwriting the inner one."
4339 input Absyn.Modification outerMod;
4340 input Absyn.Modification innerMod;
4341 output Absyn.Modification outMod;
4342 algorithm
4343 19 outMod := Absyn.Modification.CLASSMOD(
4344 mergeAnnotations2(innerMod.elementArgLst, outerMod.elementArgLst),
4345 mergeEqMods(outerMod.eqMod, innerMod.eqMod)
4346 );
4347 end mergeModifiers;
4348
4349 public function mergeEqMods
4350 input Absyn.EqMod outerEqMod;
4351 input Absyn.EqMod innerEqMod;
4352 output Absyn.EqMod outEqMod;
4353 algorithm
4354 outEqMod := match outerEqMod
4355 case Absyn.EqMod.EQMOD() then outerEqMod;
4356 else innerEqMod;
4357 end match;
4358 end mergeEqMods;
4359
4360 function isModificationOfPath
4361 "returns true or false if the given path is in the list of modifications"
4362 input Absyn.ElementArg mod;
4363 input Absyn.Path path;
4364 output Boolean yes;
4365 algorithm
4366 yes := match (mod,path)
4367 local
4368 String id1,id2;
4369
4/4
✓ Branch 0 taken 237 times.
✓ Branch 1 taken 222 times.
✓ Branch 3 taken 9 times.
✓ Branch 4 taken 228 times.
459 case (Absyn.MODIFICATION(path = Absyn.IDENT(name = id1)),Absyn.IDENT(name = id2)) then id1==id2;
4370 else false;
4371 end match;
4372 end isModificationOfPath;
4373
4374 function subModsInSameOrder
4375 input Absyn.ElementArg oldmod;
4376 input Absyn.ElementArg newmod;
4377 output Absyn.ElementArg mod;
4378 algorithm
4379 mod := match (oldmod,newmod)
4380 local
4381 list<Absyn.ElementArg> args1,args2,res;
4382 Absyn.ElementArg arg2;
4383 Absyn.EqMod eq2;
4384 Absyn.Path p;
4385
4386 // mod1 or mod2 has no submods
4387 case (_, Absyn.MODIFICATION(modification=NONE())) then newmod;
4388 case (Absyn.MODIFICATION(modification=NONE()), _) then newmod;
4389 // mod1
4390 case (Absyn.MODIFICATION(modification=SOME(Absyn.CLASSMOD(args1,_))), arg2 as Absyn.MODIFICATION(modification=SOME(Absyn.CLASSMOD(args2,eq2))))
4391 algorithm
4392 // Delete all items from args2 that are not in args1
4393 res := {};
4394
2/2
✓ Branch 0 taken 107 times.
✓ Branch 1 taken 136 times.
243 for arg1 in args1 loop
4395
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
107 Absyn.MODIFICATION(path=p) := arg1;
4396
2/2
✓ Branch 3 taken 83 times.
✓ Branch 4 taken 24 times.
107 if List.any(args2, function isModificationOfPath(path=p)) then
4397 res := arg1::res;
4398 end if;
4399 end for;
4400 136 res := listReverse(res);
4401 // Merge the annotations
4402 136 res := mergeAnnotations2(res, args2);
4403 272 arg2.modification := SOME(Absyn.CLASSMOD(res,eq2));
4404 then arg2;
4405 end match;
4406 end subModsInSameOrder;
4407
4408 public function annotationToElementArgs
4409 input Absyn.Annotation ann;
4410 output list<Absyn.ElementArg> args;
4411 algorithm
4412 9050 Absyn.ANNOTATION(args) := ann;
4413 end annotationToElementArgs;
4414
4415 public function pathToTypeSpec
4416 input Absyn.Path inPath;
4417 output Absyn.TypeSpec outTypeSpec;
4418 algorithm
4419 ✗ outTypeSpec := Absyn.TPATH(inPath, NONE());
4420 end pathToTypeSpec;
4421
4422 public function typeSpecString
4423 input Absyn.TypeSpec inTs;
4424 output String outStr;
4425 algorithm
4426 ✗ outStr := Dump.unparseTypeSpec(inTs);
4427 end typeSpecString;
4428
4429 public function crefString
4430 input Absyn.ComponentRef inCr;
4431 output String outStr;
4432 algorithm
4433 928 outStr := Dump.printComponentRefStr(inCr);
4434 end crefString;
4435
4436 public function typeSpecStringNoQualNoDims
4437 input Absyn.TypeSpec inTs;
4438 output String outStr;
4439 algorithm
4440 outStr := match inTs
4441 local
4442 Absyn.Ident str1,str2;
4443 Absyn.Path path;
4444 list<Absyn.TypeSpec> typeSpecLst;
4445
4446 case Absyn.TPATH(path = path)
4447 ✗ then pathString(makeNotFullyQualified(path));
4448
4449 case Absyn.TCOMPLEX(path = path,typeSpecs = typeSpecLst)
4450 algorithm
4451 ✗ str1 := pathString(makeNotFullyQualified(path));
4452 ✗ str2 := typeSpecStringNoQualNoDimsLst(typeSpecLst);
4453 ✗ then
4454 stringAppendList({str1,"<",str2,">"});
4455
4456 end match;
4457 end typeSpecStringNoQualNoDims;
4458
4459 public function typeSpecStringNoQualNoDimsLst
4460 input list<Absyn.TypeSpec> inTypeSpecLst;
4461 output String outString;
4462 algorithm
4463 ✗ outString := List.toStringCustom(inTypeSpecLst, typeSpecStringNoQualNoDims,
4464 "", "", ", ", "", false);
4465 end typeSpecStringNoQualNoDimsLst;
4466
4467 public function crefStringIgnoreSubs
4468 input Absyn.ComponentRef inCr;
4469 output String outStr;
4470 protected
4471 Absyn.Path p;
4472 algorithm
4473 ✗ p := crefToPathIgnoreSubs(inCr);
4474 ✗ outStr := pathString(makeNotFullyQualified(p));
4475 end crefStringIgnoreSubs;
4476
4477 public function importString
4478 input Absyn.Import inImp;
4479 output String outStr;
4480 algorithm
4481 ✗ outStr := Dump.unparseImportStr(inImp);
4482 end importString;
4483
4484 public function refString
4485 "@author: adrpo
4486 full Absyn.Ref -> string
4487 cref/path full qualified, type dims, subscripts in crefs"
4488 input Absyn.Ref inRef;
4489 output String outStr;
4490 algorithm
4491 outStr := match inRef
4492 ✗ case Absyn.RCR() then crefString(inRef.cr);
4493 ✗ case Absyn.RTS() then typeSpecString(inRef.ts);
4494 ✗ case Absyn.RIM() then importString(inRef.im);
4495 end match;
4496 end refString;
4497
4498 public function refStringBrief
4499 "@author: adrpo
4500 brief Absyn.Ref -> string
4501 no cref/path full qualified, no type dims, no subscripts in crefs"
4502 input Absyn.Ref inRef;
4503 output String outStr;
4504 algorithm
4505 outStr := match inRef
4506 ✗ case Absyn.RCR() then crefStringIgnoreSubs(inRef.cr);
4507 ✗ case Absyn.RTS() then typeSpecStringNoQualNoDims(inRef.ts);
4508 ✗ case Absyn.RIM() then importString(inRef.im);
4509 end match;
4510 end refStringBrief;
4511
4512 public function getArrayDimOptAsList
4513 input Option<Absyn.ArrayDim> inArrayDim;
4514 output Absyn.ArrayDim outArrayDim;
4515 algorithm
4516 outArrayDim := match inArrayDim
4517 local Absyn.ArrayDim ad;
4518 case SOME(ad) then ad;
4519 else {};
4520 end match;
4521 end getArrayDimOptAsList;
4522
4523 public function removeCrefFromCrefs
4524 "Removes a variable from a variable list"
4525 input list<Absyn.ComponentRef> inAbsynComponentRefLst;
4526 input Absyn.ComponentRef inComponentRef;
4527 output list<Absyn.ComponentRef> outAbsynComponentRefLst;
4528 algorithm
4529 outAbsynComponentRefLst := matchcontinue (inAbsynComponentRefLst,inComponentRef)
4530 local
4531 String n1,n2;
4532 list<Absyn.ComponentRef> rest;
4533 Absyn.ComponentRef cr1,cr2;
4534 case ({},_) then {};
4535 case ((cr1 :: rest),cr2)
4536 algorithm
4537
3/4
✓ Branch 0 taken 2504 times.
✓ Branch 1 taken 2543 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2543 times.
5047 Absyn.CREF_IDENT(name = n1,subscripts = {}) := cr1;
4538
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2543 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2543 times.
2543 Absyn.CREF_IDENT(name = n2,subscripts = {}) := cr2;
4539
4/4
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 2501 times.
✓ Branch 3 taken 13 times.
✓ Branch 4 taken 29 times.
2543 true := stringEq(n1, n2);
4540 13 then
4541
4542 removeCrefFromCrefs(rest, cr2);
4543 case ((cr1 :: rest),cr2) // If modifier like on comp like: T t(x=t.y) => t.y must be removed
4544 algorithm
4545
2/2
✓ Branch 0 taken 2530 times.
✓ Branch 1 taken 2504 times.
5034 Absyn.CREF_QUAL(name = n1) := cr1;
4546
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2504 times.
2504 Absyn.CREF_IDENT(name = n2) := cr2;
4547
3/4
✓ Branch 0 taken 2487 times.
✓ Branch 1 taken 17 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2487 times.
2504 true := stringEq(n1, n2);
4548 2487 then
4549 removeCrefFromCrefs(rest, cr2);
4550
4551 case ((cr1 :: rest),cr2)
4552 algorithm
4553 2547 rest := removeCrefFromCrefs(rest, cr2);
4554 then
4555 (cr1 :: rest);
4556 end matchcontinue;
4557 end removeCrefFromCrefs;
4558
4559 public function lookupClassAnnotation
4560 "Looks up the modifier for a specific annotation in the given class."
4561 input Absyn.Class cls;
4562 input String name;
4563 output Option<Absyn.Modification> outMod;
4564 algorithm
4565 3079 outMod := lookupClassDefAnnotation(cls.body, name);
4566 end lookupClassAnnotation;
4567
4568 public function lookupClassDefAnnotation
4569 "Looks up the modifier for a specific annotation in the given class definition."
4570 input Absyn.ClassDef cdef;
4571 input String name;
4572 output Option<Absyn.Modification> outMod = NONE();
4573 protected
4574 Absyn.Annotation ann;
4575 algorithm
4576 outMod := match cdef
4577 3065 case Absyn.PARTS() then List.findSome(cdef.ann, function lookupAnnotation(name = name));
4578 ✗ case Absyn.CLASS_EXTENDS() then List.findSome(cdef.ann, function lookupAnnotation(name = name));
4579 14 case Absyn.DERIVED() then lookupCommentOptAnnotation(cdef.comment, name);
4580 ✗ case Absyn.ENUMERATION() then lookupCommentOptAnnotation(cdef.comment, name);
4581 ✗ case Absyn.OVERLOAD() then lookupCommentOptAnnotation(cdef.comment, name);
4582 ✗ case Absyn.PDER() then lookupCommentOptAnnotation(cdef.comment, name);
4583 else NONE();
4584 end match;
4585 end lookupClassDefAnnotation;
4586
4587 function lookupCommentOptAnnotation
4588 "Looks up the modifier for a specific annotation in the given optional comment."
4589 input Option<Absyn.Comment> cmt;
4590 input String name;
4591 output Option<Absyn.Modification> outMod;
4592 protected
4593 Absyn.Annotation ann;
4594 algorithm
4595 outMod := match cmt
4596 5 case SOME(Absyn.COMMENT(annotation_ = SOME(ann))) then lookupAnnotation(ann, name);
4597 else NONE();
4598 end match;
4599 end lookupCommentOptAnnotation;
4600
4601 function lookupAnnotation
4602 "Looks up the modifier for a specific annotation."
4603 input Absyn.Annotation ann;
4604 input String name;
4605 output Option<Absyn.Modification> outMod = NONE();
4606 algorithm
4607
2/2
✓ Branch 0 taken 1777 times.
✓ Branch 1 taken 893 times.
2670 for m in ann.elementArgs loop
4608 outMod := match m
4609 case Absyn.MODIFICATION()
4610 guard pathFirstIdent(m.path) == name
4611 488 then m.modification;
4612
4613 else outMod;
4614 end match;
4615
4616
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1777 times.
✓ Branch 2 taken 1289 times.
✓ Branch 3 taken 488 times.
1777 if isSome(outMod) then
4617 break;
4618 end if;
4619 end for;
4620 end lookupAnnotation;
4621
4622 public function getNamedAnnotationInClass<T>
4623 "Retrieve e.g. the documentation annotation as a string from the class passed as argument."
4624 input Absyn.Class inClass;
4625 input Absyn.Path id;
4626 input ModFunc f;
4627 output Option<T> outString;
4628 partial function ModFunc
4629 input Option<Absyn.Modification> mod;
4630 output T docStr;
4631 end ModFunc;
4632 algorithm
4633 outString := matchcontinue inClass
4634 local
4635 list<Absyn.ElementArg> annlst;
4636 list<Absyn.Annotation> ann;
4637
4638 case Absyn.CLASS(body = Absyn.PARTS(ann = ann))
4639 algorithm
4640 19459 annlst := List.flatten(List.map(ann,annotationToElementArgs));
4641 19459 then
4642 getNamedAnnotationStr(annlst,id,f);
4643
4644 case Absyn.CLASS(body = Absyn.CLASS_EXTENDS(ann = ann))
4645 algorithm
4646 ✗ annlst := List.flatten(List.map(ann,annotationToElementArgs));
4647 ✗ then
4648 getNamedAnnotationStr(annlst,id,f);
4649
4650 case Absyn.CLASS(body = Absyn.DERIVED(comment = SOME(Absyn.COMMENT(SOME(Absyn.ANNOTATION(annlst)),_))))
4651 17 then getNamedAnnotationStr(annlst,id,f);
4652
4653 case Absyn.CLASS(body = Absyn.ENUMERATION(comment = SOME(Absyn.COMMENT(SOME(Absyn.ANNOTATION(annlst)),_))))
4654 ✗ then getNamedAnnotationStr(annlst,id,f);
4655
4656 case Absyn.CLASS(body = Absyn.OVERLOAD(comment = SOME(Absyn.COMMENT(SOME(Absyn.ANNOTATION(annlst)),_))))
4657 ✗ then getNamedAnnotationStr(annlst,id,f);
4658
4659 else NONE();
4660
4661 end matchcontinue;
4662 end getNamedAnnotationInClass;
4663
4664 protected function getNamedAnnotationStr<T>
4665 "Helper function to getNamedAnnotationInElementitemlist."
4666 input list<Absyn.ElementArg> inAbsynElementArgLst;
4667 input Absyn.Path id;
4668 input ModFunc f;
4669 output Option<T> outString;
4670 partial function ModFunc
4671 input Option<Absyn.Modification> mod;
4672 output T docStr;
4673 end ModFunc;
4674 algorithm
4675 outString := matchcontinue (inAbsynElementArgLst, id)
4676 local
4677 T str;
4678 Option<Absyn.Modification> mod;
4679 list<Absyn.ElementArg> xs;
4680 Absyn.Ident id1,id2;
4681 Absyn.Path rest;
4682
4683 case (((Absyn.MODIFICATION(path = Absyn.IDENT(name = id1),modification = mod)) :: _), Absyn.IDENT(id2))
4684 algorithm
4685
4/4
✓ Branch 0 taken 2300 times.
✓ Branch 1 taken 27790 times.
✓ Branch 3 taken 1569 times.
✓ Branch 4 taken 731 times.
30090 true := stringEq(id1, id2);
4686
2/2
✓ Branch 0 taken 601 times.
✓ Branch 1 taken 968 times.
1569 str := f(mod);
4687 then
4688 SOME(str);
4689
4690 case (((Absyn.MODIFICATION(path = Absyn.IDENT(name = id1),modification = SOME(Absyn.CLASSMOD(elementArgLst=xs)))) :: _), Absyn.QUALIFIED(name=id2,path=rest))
4691 algorithm
4692
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
15 true := stringEq(id1, id2);
4693 7 then getNamedAnnotationStr(xs,rest,f);
4694
4695 28533 case ((_ :: xs), _) then getNamedAnnotationStr(xs,id,f);
4696 end matchcontinue;
4697 end getNamedAnnotationStr;
4698
4699 public function transformAnnotationArg
4700 "Looks up an ElementArg in an annotation and applies a function to it.
4701 If the ElementArg doesn't exist it will be created if insert = true,
4702 otherwise the function will fail."
4703 input output Absyn.Annotation ann;
4704 input Absyn.Path path;
4705 input Func func;
4706 input Boolean insert = true;
4707
4708 partial function Func
4709 input output Absyn.ElementArg arg;
4710 end Func;
4711 algorithm
4712 ✗ ann.elementArgs := transformAnnotationInArgs(ann.elementArgs, path, func, insert);
4713 end transformAnnotationArg;
4714
4715 function transformAnnotationInArgs
4716 input output list<Absyn.ElementArg> args;
4717 input Absyn.Path path;
4718 input Fn fn;
4719 input Boolean insert = true;
4720
4721 partial function Fn
4722 input output Absyn.ElementArg arg;
4723 end Fn;
4724 protected
4725 String name;
4726 Boolean found;
4727 Absyn.ElementArg arg;
4728
4729 function is_named
4730 input Absyn.ElementArg arg;
4731 input String name;
4732 output Boolean result;
4733 protected
4734 String arg_name;
4735 algorithm
4736 result := match arg
4737 ✗ case Absyn.ElementArg.MODIFICATION(path = Absyn.Path.IDENT(name = arg_name)) then name == arg_name;
4738 else false;
4739 end match;
4740 end is_named;
4741
4742 function apply_fn
4743 input output Absyn.ElementArg arg;
4744 input Absyn.Path path;
4745 input Fn fn;
4746 input Boolean insert;
4747 protected
4748 Absyn.Modification mod;
4749 algorithm
4750 ✗ if pathIsIdent(path) then
4751 ✗ arg := fn(arg);
4752 else
4753 () := match arg
4754 case Absyn.ElementArg.MODIFICATION()
4755 algorithm
4756 ✗ if isSome(arg.modification) then
4757 ✗ SOME(mod) := arg.modification;
4758 elseif insert then
4759 mod := Absyn.Modification.CLASSMOD({}, Absyn.EqMod.NOMOD());
4760 else
4761 ✗ fail();
4762 end if;
4763
4764 ✗ mod.elementArgLst := transformAnnotationInArgs(mod.elementArgLst, pathRest(path), fn, insert);
4765 ✗ arg.modification := SOME(mod);
4766 then
4767 ();
4768 end match;
4769 end if;
4770 end apply_fn;
4771 algorithm
4772 ✗ name := pathFirstIdent(path);
4773 ✗ (args, found) := List.findAndMap(args, function is_named(name = name),
4774 function apply_fn(path = path, fn = fn, insert = insert));
4775
4776 ✗ if not found then
4777 ✗ if insert then
4778 ✗ arg := Absyn.ElementArg.MODIFICATION(false, Absyn.Each.NON_EACH(), Absyn.IDENT(name), NONE(), NONE(), Absyn.dummyInfo);
4779 ✗ arg := apply_fn(arg, path, fn, insert);
4780 args := arg :: args;
4781 else
4782 ✗ fail();
4783 end if;
4784 end if;
4785 end transformAnnotationInArgs;
4786
4787 public function mapCrefParts
4788 "This function splits each part of a cref into CREF_IDENTs and applies the
4789 given function to each part. If the given cref is a qualified cref then the
4790 map function is expected to also return Absyn.CREF_IDENT, so that the split cref
4791 can be reconstructed. Otherwise the map function is free to return whatever
4792 it wants."
4793 input Absyn.ComponentRef inCref;
4794 input MapFunc inMapFunc;
4795 output Absyn.ComponentRef outCref;
4796
4797 partial function MapFunc
4798 input Absyn.ComponentRef inCref;
4799 output Absyn.ComponentRef outCref;
4800 end MapFunc;
4801 algorithm
4802 outCref := match inCref
4803 local
4804 Absyn.Ident name;
4805 list<Absyn.Subscript> subs;
4806 Absyn.ComponentRef rest_cref;
4807 Absyn.ComponentRef cref;
4808
4809 case Absyn.CREF_QUAL(name, subs, rest_cref)
4810 algorithm
4811 ✗ cref := Absyn.CREF_IDENT(name, subs);
4812 ✗ Absyn.CREF_IDENT(name, subs) := inMapFunc(cref);
4813 ✗ rest_cref := mapCrefParts(rest_cref, inMapFunc);
4814 ✗ then
4815 Absyn.CREF_QUAL(name, subs, rest_cref);
4816
4817 case Absyn.CREF_FULLYQUALIFIED(cref)
4818 algorithm
4819 ✗ cref := mapCrefParts(cref, inMapFunc);
4820 ✗ then
4821 Absyn.CREF_FULLYQUALIFIED(cref);
4822
4823 ✗ else inMapFunc(inCref);
4824 end match;
4825 end mapCrefParts;
4826
4827 public function opEqual
4828 input Absyn.Operator op1;
4829 input Absyn.Operator op2;
4830 output Boolean isEqual;
4831 algorithm
4832 ✗ isEqual := valueEq(op1, op2);
4833 end opEqual;
4834
4835 public function opIsElementWise
4836 input Absyn.Operator op;
4837 output Boolean isElementWise;
4838 algorithm
4839 isElementWise := match op
4840 case Absyn.ADD_EW() then true;
4841 case Absyn.SUB_EW() then true;
4842 case Absyn.MUL_EW() then true;
4843 case Absyn.DIV_EW() then true;
4844 case Absyn.POW_EW() then true;
4845 case Absyn.UPLUS_EW() then true;
4846 case Absyn.UMINUS_EW() then true;
4847 else false;
4848 end match;
4849 end opIsElementWise;
4850
4851 public function dummyTraverseExp<Arg>
4852 input Absyn.Exp inExp;
4853 input Arg inArg;
4854 output Absyn.Exp outExp;
4855 output Arg outArg;
4856 algorithm
4857 outExp := inExp;
4858 outArg := inArg;
4859 end dummyTraverseExp;
4860
4861 public function getDefineUnitsInElements "retrives defineunit definitions in elements"
4862 input list<Absyn.ElementItem> elts;
4863 output list<Absyn.Element> outElts = {};
4864 algorithm
4865 ✗ for i in elts loop
4866 outElts := match i
4867 case Absyn.ELEMENTITEM(element = Absyn.DEFINEUNIT()) then i.element :: outElts;
4868 else outElts;
4869 end match;
4870 end for;
4871
4872 ✗ outElts := listReverseInPlace(outElts);
4873 end getDefineUnitsInElements;
4874
4875 public function getClassPartsInClass
4876 input Absyn.Class cls;
4877 output list<Absyn.ClassPart> parts;
4878 protected
4879 Absyn.ClassDef cdef = cls.body;
4880 algorithm
4881 parts := match cdef
4882 80390 case Absyn.ClassDef.PARTS() then cdef.classParts;
4883 ✗ case Absyn.ClassDef.CLASS_EXTENDS() then cdef.parts;
4884 else {};
4885 end match;
4886 end getClassPartsInClass;
4887
4888 public function setClassPartsInClass
4889 input list<Absyn.ClassPart> parts;
4890 input output Absyn.Class cls;
4891 protected
4892 Absyn.ClassDef cdef = cls.body;
4893 algorithm
4894 () := match cdef
4895 12 case Absyn.ClassDef.PARTS() algorithm cdef.classParts := parts; then ();
4896 ✗ case Absyn.ClassDef.CLASS_EXTENDS() algorithm cdef.parts := parts; then ();
4897 end match;
4898
4899 12 cls.body := cdef;
4900 end setClassPartsInClass;
4901
4902 public function getElementItemsInElement
4903 "Returns the public and protected elements in a class."
4904 input Absyn.Element element;
4905 output list<Absyn.ElementItem> outElements;
4906 protected
4907 Absyn.Class cls;
4908 algorithm
4909 outElements := match element
4910 case Absyn.Element.ELEMENT(specification = Absyn.ElementSpec.CLASSDEF(class_ = cls))
4911 1 then getElementItemsInClass(cls);
4912 else {};
4913 end match;
4914 end getElementItemsInElement;
4915
4916 public function getElementItemsInClass
4917 "Returns the public and protected elements in a class."
4918 input Absyn.Class inClass;
4919 output list<Absyn.ElementItem> outElements = getElementItemsInClassDef(inClass.body);
4920 end getElementItemsInClass;
4921
4922 public function getElementItemsInClassDef
4923 "Returns the public and protected elements in a class definition."
4924 input Absyn.ClassDef classDef;
4925 output list<Absyn.ElementItem> outElements;
4926 algorithm
4927 outElements := match classDef
4928 case Absyn.ClassDef.PARTS()
4929 130 then List.mapFlat(classDef.classParts, getElementItemsInClassPart);
4930
4931 case Absyn.ClassDef.CLASS_EXTENDS()
4932 ✗ then List.mapFlat(classDef.parts, getElementItemsInClassPart);
4933
4934 else {};
4935 end match;
4936 end getElementItemsInClassDef;
4937
4938 public function getElementItemsInClassPart
4939 "Returns the public and protected elements in a class part."
4940 input Absyn.ClassPart inClassPart;
4941 output list<Absyn.ElementItem> outElements;
4942 algorithm
4943 outElements := match inClassPart
4944 80861 case Absyn.PUBLIC() then inClassPart.contents;
4945 225 case Absyn.PROTECTED() then inClassPart.contents;
4946 else {};
4947 end match;
4948 end getElementItemsInClassPart;
4949
4950 public function traverseClassComponents<ArgT>
4951 input Absyn.Class inClass;
4952 input FuncType inFunc;
4953 input ArgT inArg;
4954 output Absyn.Class outClass = inClass;
4955 output ArgT outArg;
4956
4957 partial function FuncType
4958 input output list<Absyn.ComponentItem> components;
4959 input output ArgT arg;
4960 output Boolean outContinue;
4961 end FuncType;
4962 algorithm
4963 outClass := match outClass
4964 local
4965 Absyn.ClassDef body;
4966
4967 case Absyn.CLASS()
4968 algorithm
4969 2 (body, outArg) := traverseClassDef(outClass.body,
4970 function traverseClassPartComponents(inFunc = inFunc), inArg);
4971
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
4 if not referenceEq(body, outClass.body) then outClass.body := body; end if;
4972 then
4973 outClass;
4974
4975 end match;
4976 end traverseClassComponents;
4977
4978 protected function traverseListGeneric<T, ArgT>
4979 input list<T> inList;
4980 input FuncType inFunc;
4981 input ArgT inArg;
4982 output list<T> outList = {};
4983 output ArgT outArg = inArg;
4984 output Boolean outContinue = true;
4985
4986 partial function FuncType
4987 input T inElement;
4988 input ArgT inArg;
4989 output T outElement;
4990 output ArgT outArg;
4991 output Boolean outContinue;
4992 end FuncType;
4993 protected
4994 Boolean eq, changed = false;
4995 T e, new_e;
4996 list<T> rest_e = inList;
4997 algorithm
4998
2/2
✓ Branch 0 taken 156 times.
✓ Branch 1 taken 4 times.
160 while not listEmpty(rest_e) loop
4999 156 e :: rest_e := rest_e;
5000
1/2
✓ Branch 0 taken 156 times.
✗ Branch 1 not taken.
156 (new_e, outArg, outContinue) := inFunc(e, outArg);
5001 eq := referenceEq(new_e, e);
5002
2/2
✓ Branch 0 taken 116 times.
✓ Branch 1 taken 40 times.
156 outList := (if eq then e else new_e) :: outList;
5003 156 changed := changed or not eq;
5004
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 114 times.
156 if not outContinue then break; end if;
5005 end while;
5006
5007
2/2
✓ Branch 0 taken 116 times.
✓ Branch 1 taken 2 times.
118 if changed then
5008 116 outList := List.append_reverse(outList, rest_e);
5009 else
5010 outList := inList;
5011 end if;
5012 end traverseListGeneric;
5013
5014 protected function traverseClassPartComponents<ArgT>
5015 input Absyn.ClassPart inClassPart;
5016 input FuncType inFunc;
5017 input ArgT inArg;
5018 output Absyn.ClassPart outClassPart = inClassPart;
5019 output ArgT outArg = inArg;
5020 output Boolean outContinue = true;
5021
5022 partial function FuncType
5023 input list<Absyn.ComponentItem> inComponents;
5024 input ArgT inArg;
5025 output list<Absyn.ComponentItem> outComponents;
5026 output ArgT outArg;
5027 output Boolean outContinue;
5028 end FuncType;
5029 algorithm
5030 () := match outClassPart
5031 local
5032 list<Absyn.ElementItem> items;
5033
5034 case Absyn.PUBLIC()
5035 algorithm
5036 2 (items, outArg, outContinue) :=
5037 traverseListGeneric(outClassPart.contents,
5038 function traverseElementItemComponents(inFunc = inFunc), inArg);
5039 2 outClassPart.contents := items;
5040 then
5041 ();
5042
5043 case Absyn.PROTECTED()
5044 algorithm
5045 ✗ (items, outArg, outContinue) :=
5046 traverseListGeneric(outClassPart.contents,
5047 function traverseElementItemComponents(inFunc = inFunc), inArg);
5048 ✗ outClassPart.contents := items;
5049 then
5050 ();
5051
5052 else ();
5053 end match;
5054 end traverseClassPartComponents;
5055
5056 protected function traverseElementItemComponents<ArgT>
5057 input Absyn.ElementItem inItem;
5058 input FuncType inFunc;
5059 input ArgT inArg;
5060 output Absyn.ElementItem outItem;
5061 output ArgT outArg;
5062 output Boolean outContinue;
5063
5064 partial function FuncType
5065 input list<Absyn.ComponentItem> inComponents;
5066 input ArgT inArg;
5067 output list<Absyn.ComponentItem> outComponents;
5068 output ArgT outArg;
5069 output Boolean outContinue;
5070 end FuncType;
5071 algorithm
5072 (outItem, outArg, outContinue) := match inItem
5073 local
5074 Absyn.Element elem;
5075
5076 case Absyn.ELEMENTITEM()
5077 algorithm
5078 3 (elem, outArg, outContinue) := traverseElementComponents(inItem.element,
5079 inFunc, inArg);
5080
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
3 outItem := if referenceEq(elem, inItem.element) then inItem else Absyn.ELEMENTITEM(elem);
5081 3 then
5082 (outItem, outArg, outContinue);
5083
5084 else (inItem, inArg, true);
5085 end match;
5086 end traverseElementItemComponents;
5087
5088 protected function traverseElementComponents<ArgT>
5089 input Absyn.Element inElement;
5090 input FuncType inFunc;
5091 input ArgT inArg;
5092 output Absyn.Element outElement = inElement;
5093 output ArgT outArg;
5094 output Boolean outContinue;
5095
5096 partial function FuncType
5097 input list<Absyn.ComponentItem> inComponents;
5098 input ArgT inArg;
5099 output list<Absyn.ComponentItem> outComponents;
5100 output ArgT outArg;
5101 output Boolean outContinue;
5102 end FuncType;
5103 algorithm
5104 (outElement, outArg, outContinue) := match outElement
5105 local
5106 Absyn.ElementSpec spec;
5107
5108 case Absyn.ELEMENT()
5109 algorithm
5110 3 (spec, outArg, outContinue) := traverseElementSpecComponents(
5111 outElement.specification, inFunc, inArg);
5112
5113
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
3 if not referenceEq(spec, outElement.specification) then
5114 2 outElement.specification := spec;
5115 end if;
5116 3 then
5117 (outElement, outArg, outContinue);
5118
5119 else (inElement, inArg, true);
5120 end match;
5121 end traverseElementComponents;
5122
5123 protected function traverseElementSpecComponents<ArgT>
5124 input Absyn.ElementSpec inSpec;
5125 input FuncType inFunc;
5126 input ArgT inArg;
5127 output Absyn.ElementSpec outSpec = inSpec;
5128 output ArgT outArg;
5129 output Boolean outContinue;
5130
5131 partial function FuncType
5132 input list<Absyn.ComponentItem> inComponents;
5133 input ArgT inArg;
5134 output list<Absyn.ComponentItem> outComponents;
5135 output ArgT outArg;
5136 output Boolean outContinue;
5137 end FuncType;
5138 algorithm
5139 (outSpec, outArg, outContinue) := match outSpec
5140 local
5141 list<Absyn.ComponentItem> comps;
5142
5143 case Absyn.COMPONENTS()
5144 algorithm
5145
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 (comps, outArg, outContinue) := inFunc(outSpec.components, inArg);
5146
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if not referenceEq(comps, outSpec.components) then
5147 2 outSpec.components := comps;
5148 end if;
5149 then
5150 (outSpec, outArg, outContinue);
5151
5152 else (inSpec, inArg, true);
5153 end match;
5154 end traverseElementSpecComponents;
5155
5156 protected function traverseClassDef<ArgT>
5157 input Absyn.ClassDef inClassDef;
5158 input FuncType inFunc;
5159 input ArgT inArg;
5160 output Absyn.ClassDef outClassDef = inClassDef;
5161 output ArgT outArg = inArg;
5162 output Boolean outContinue = true;
5163
5164 partial function FuncType
5165 input Absyn.ClassPart inPart;
5166 input ArgT inArg;
5167 output Absyn.ClassPart outPart;
5168 output ArgT outArg;
5169 output Boolean outContinue;
5170 end FuncType;
5171 algorithm
5172 () := match outClassDef
5173 local
5174 list<Absyn.ClassPart> parts;
5175
5176 case Absyn.PARTS()
5177 algorithm
5178 59 (parts, outArg, outContinue) :=
5179 traverseListGeneric(outClassDef.classParts, inFunc, inArg);
5180 59 outClassDef.classParts := parts;
5181 then
5182 ();
5183
5184 case Absyn.CLASS_EXTENDS()
5185 algorithm
5186 ✗ (parts, outArg, outContinue) :=
5187 traverseListGeneric(outClassDef.parts, inFunc, inArg);
5188 ✗ outClassDef.parts := parts;
5189 then
5190 ();
5191
5192 else ();
5193 end match;
5194 end traverseClassDef;
5195
5196 public function isEmptyMod
5197 input Absyn.Modification inMod;
5198 output Boolean outIsEmpty;
5199 algorithm
5200 outIsEmpty := match inMod
5201 case Absyn.CLASSMOD({}, Absyn.NOMOD()) then true;
5202 case Absyn.CLASSMOD({}, Absyn.EQMOD(exp = Absyn.TUPLE(expressions = {}))) then true;
5203 else false;
5204 end match;
5205 end isEmptyMod;
5206
5207 public function isEmptySubMod
5208 input Absyn.ElementArg inSubMod;
5209 output Boolean outIsEmpty;
5210 algorithm
5211 outIsEmpty := match inSubMod
5212 local
5213 Absyn.Modification mod;
5214
5215 case Absyn.MODIFICATION(finalPrefix = true) then false;
5216 case Absyn.MODIFICATION(modification = NONE()) then true;
5217 20 case Absyn.MODIFICATION(modification = SOME(mod)) then isEmptyMod(mod);
5218 else false;
5219 end match;
5220 end isEmptySubMod;
5221
5222 function isEmptyEqMod
5223 input Absyn.EqMod eqMod;
5224 output Boolean isEmpty;
5225 algorithm
5226 isEmpty := match eqMod
5227 case Absyn.EqMod.NOMOD() then true;
5228 else false;
5229 end match;
5230 end isEmptyEqMod;
5231
5232 public function elementArgName
5233 input Absyn.ElementArg inArg;
5234 output Absyn.Path outName;
5235 algorithm
5236 outName := match inArg
5237 local
5238 Absyn.ElementSpec e;
5239 case Absyn.MODIFICATION(path = outName) then outName;
5240 6 case Absyn.REDECLARATION(elementSpec = e) then makeIdentPathFromString(elementSpecName(e));
5241 end match;
5242 end elementArgName;
5243
5244 public function elementArgEqualName
5245 input Absyn.ElementArg inArg1;
5246 input Absyn.ElementArg inArg2;
5247 output Boolean outEqual = pathEqual(elementArgName(inArg1), elementArgName(inArg2));
5248 end elementArgEqualName;
5249
5250 public function optMsg
5251 "Creates a Absyn.Msg based on a boolean value."
5252 input Boolean inShowMessage;
5253 input SourceInfo inInfo;
5254 output Absyn.Msg outMsg;
5255 algorithm
5256
2/2
✓ Branch 0 taken 580901 times.
✓ Branch 1 taken 493306 times.
1074207 outMsg := if inShowMessage then Absyn.MSG(inInfo) else Absyn.NO_MSG();
5257 annotation(__OpenModelica_EarlyInline = true);
5258 end optMsg;
5259
5260 public function makeSubscript
5261 input Absyn.Exp inExp;
5262 output Absyn.Subscript outSubscript;
5263 algorithm
5264 ✗ outSubscript := Absyn.SUBSCRIPT(inExp);
5265 end makeSubscript;
5266
5267 public function makeIntegerSubscript
5268 input Integer n;
5269 output Absyn.Subscript sub;
5270 algorithm
5271 20 sub := Absyn.SUBSCRIPT(Absyn.INTEGER(n));
5272 end makeIntegerSubscript;
5273
5274 public function crefExplode
5275 "Splits a cref into parts."
5276 input Absyn.ComponentRef inCref;
5277 input list<Absyn.ComponentRef> inAccum = {};
5278 output list<Absyn.ComponentRef> outCrefParts;
5279 algorithm
5280 outCrefParts := match inCref
5281 362618 case Absyn.CREF_QUAL() then crefExplode(inCref.componentRef, crefFirstCref(inCref) :: inAccum);
5282 2881 case Absyn.CREF_FULLYQUALIFIED() then crefExplode(inCref.componentRef, inAccum);
5283 578833 else listReverse(inCref :: inAccum);
5284 end match;
5285 end crefExplode;
5286
5287 public function traverseExpShallow<ArgT>
5288 "Calls the given function on each subexpression (non-recursively) of the given
5289 expression, sending in the extra argument to each call."
5290 input Absyn.Exp inExp;
5291 input ArgT inArg;
5292 input FuncT inFunc;
5293 output Absyn.Exp outExp = inExp;
5294
5295 partial function FuncT
5296 input Absyn.Exp inExp;
5297 input ArgT inArg;
5298 output Absyn.Exp outExp;
5299 end FuncT;
5300 algorithm
5301 () := match outExp
5302 local
5303
5304 case Absyn.BINARY()
5305 algorithm
5306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12234 times.
12234 outExp.exp1 := inFunc(outExp.exp1, inArg);
5307
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12234 times.
12234 outExp.exp2 := inFunc(outExp.exp2, inArg);
5308 then
5309 ();
5310
5311 case Absyn.UNARY()
5312 algorithm
5313
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 outExp.exp := inFunc(outExp.exp, inArg);
5314 then
5315 ();
5316
5317 case Absyn.LBINARY()
5318 algorithm
5319 ✗ outExp.exp1 := inFunc(outExp.exp1, inArg);
5320 ✗ outExp.exp2 := inFunc(outExp.exp2, inArg);
5321 then
5322 ();
5323
5324 case Absyn.LUNARY()
5325 algorithm
5326 ✗ outExp.exp := inFunc(outExp.exp, inArg);
5327 then
5328 ();
5329
5330 case Absyn.RELATION()
5331 algorithm
5332 ✗ outExp.exp1 := inFunc(outExp.exp1, inArg);
5333 ✗ outExp.exp2 := inFunc(outExp.exp2, inArg);
5334 then
5335 ();
5336
5337 case Absyn.IFEXP()
5338 algorithm
5339 ✗ outExp.ifExp := inFunc(outExp.ifExp, inArg);
5340 ✗ outExp.trueBranch := inFunc(outExp.trueBranch, inArg);
5341 ✗ outExp.elseBranch := inFunc(outExp.elseBranch, inArg);
5342 ✗ outExp.elseIfBranch := list((inFunc(Util.tuple21(e), inArg),
5343 inFunc(Util.tuple22(e), inArg)) for e in outExp.elseIfBranch);
5344 then
5345 ();
5346
5347 case Absyn.CALL()
5348 algorithm
5349 46 outExp.functionArgs := traverseExpShallowFuncArgs(outExp.functionArgs,
5350 inArg, inFunc);
5351 then
5352 ();
5353
5354 case Absyn.PARTEVALFUNCTION()
5355 algorithm
5356 ✗ outExp.functionArgs := traverseExpShallowFuncArgs(outExp.functionArgs,
5357 inArg, inFunc);
5358 then
5359 ();
5360
5361 case Absyn.ARRAY()
5362 algorithm
5363
5/6
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6 times.
12 outExp.arrayExp := list(inFunc(e, inArg) for e in outExp.arrayExp);
5364 then
5365 ();
5366
5367 case Absyn.MATRIX()
5368 algorithm
5369 ✗ outExp.matrix := list(list(inFunc(e, inArg) for e in lst) for lst in
5370 outExp.matrix);
5371 then
5372 ();
5373
5374 case Absyn.RANGE()
5375 algorithm
5376
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1013 times.
1013 outExp.start := inFunc(outExp.start, inArg);
5377 1013 outExp.step := Util.applyOption1(outExp.step, inFunc, inArg);
5378
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1013 times.
1013 outExp.stop := inFunc(outExp.stop, inArg);
5379 then
5380 ();
5381
5382 case Absyn.TUPLE()
5383 algorithm
5384 ✗ outExp.expressions := list(inFunc(e, inArg) for e in outExp.expressions);
5385 then
5386 ();
5387
5388 case Absyn.AS()
5389 algorithm
5390 ✗ outExp.exp := inFunc(outExp.exp, inArg);
5391 then
5392 ();
5393
5394 case Absyn.CONS()
5395 algorithm
5396 ✗ outExp.head := inFunc(outExp.head, inArg);
5397 ✗ outExp.rest := inFunc(outExp.rest, inArg);
5398 then
5399 ();
5400
5401 case Absyn.LIST()
5402 algorithm
5403 ✗ outExp.exps := list(inFunc(e, inArg) for e in outExp.exps);
5404 then
5405 ();
5406
5407 case Absyn.DOT()
5408 algorithm
5409 ✗ outExp.exp := inFunc(outExp.exp, inArg);
5410 ✗ outExp.index := inFunc(outExp.index, inArg);
5411 then
5412 ();
5413
5414 case Absyn.EXPRESSIONCOMMENT()
5415 algorithm
5416 ✗ outExp.exp := inFunc(outExp.exp, inArg);
5417 then
5418 ();
5419
5420 case Absyn.SUBSCRIPTED_EXP()
5421 algorithm
5422 ✗ outExp.exp := inFunc(outExp.exp, inArg);
5423 ✗ outExp.subscripts := list(traverseExpShallowSub(s, inArg, inFunc) for s in outExp.subscripts);
5424 then
5425 ();
5426
5427 else ();
5428 end match;
5429 end traverseExpShallow;
5430
5431 protected function traverseExpShallowFuncArgs<ArgT>
5432 input Absyn.FunctionArgs inArgs;
5433 input ArgT inArg;
5434 input FuncT inFunc;
5435 output Absyn.FunctionArgs outArgs = inArgs;
5436
5437 partial function FuncT
5438 input Absyn.Exp inExp;
5439 input ArgT inArg;
5440 output Absyn.Exp outExp;
5441 end FuncT;
5442 algorithm
5443 outArgs := match outArgs
5444 case Absyn.FUNCTIONARGS()
5445 algorithm
5446
5/6
✓ Branch 0 taken 64 times.
✓ Branch 1 taken 46 times.
✓ Branch 2 taken 64 times.
✓ Branch 3 taken 46 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 64 times.
156 outArgs.args := list(inFunc(arg, inArg) for arg in outArgs.args);
5447 then
5448 outArgs;
5449
5450 case Absyn.FOR_ITER_FARG()
5451 algorithm
5452 ✗ outArgs.exp := inFunc(outArgs.exp, inArg);
5453 ✗ outArgs.iterators := list(traverseExpShallowIterator(it, inArg, inFunc)
5454 for it in outArgs.iterators);
5455 then
5456 outArgs;
5457
5458 end match;
5459 end traverseExpShallowFuncArgs;
5460
5461 protected function traverseExpShallowIterator<ArgT>
5462 input Absyn.ForIterator inIterator;
5463 input ArgT inArg;
5464 input FuncT inFunc;
5465 output Absyn.ForIterator outIterator;
5466
5467 partial function FuncT
5468 input Absyn.Exp inExp;
5469 input ArgT inArg;
5470 output Absyn.Exp outExp;
5471 end FuncT;
5472 protected
5473 String name;
5474 Option<Absyn.Exp> guard_exp, range_exp;
5475 algorithm
5476 ✗ Absyn.ITERATOR(name, guard_exp, range_exp) := inIterator;
5477 ✗ guard_exp := Util.applyOption1(guard_exp, inFunc, inArg);
5478 ✗ range_exp := Util.applyOption1(range_exp, inFunc, inArg);
5479 ✗ outIterator := Absyn.ITERATOR(name, guard_exp, range_exp);
5480 end traverseExpShallowIterator;
5481
5482 public function traverseExpShallowSub<ArgT>
5483 input output Absyn.Subscript sub;
5484 input ArgT inArg;
5485 input FuncT inFunc;
5486
5487 partial function FuncT
5488 input Absyn.Exp inExp;
5489 input ArgT inArg;
5490 output Absyn.Exp outExp;
5491 end FuncT;
5492 algorithm
5493 () := match sub
5494 case Absyn.Subscript.SUBSCRIPT()
5495 algorithm
5496 ✗ sub.subscript := inFunc(sub.subscript, inArg);
5497 then
5498 ();
5499
5500 else ();
5501 end match;
5502 end traverseExpShallowSub;
5503
5504 public function isElementItemClass
5505 input Absyn.ElementItem inElement;
5506 output Boolean outIsClass;
5507 algorithm
5508 outIsClass := match inElement
5509 case Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = Absyn.CLASSDEF())) then true;
5510 else false;
5511 end match;
5512 end isElementItemClass;
5513
5514 public function isElementItemExtends
5515 input Absyn.ElementItem item;
5516 output Boolean isExtends;
5517 algorithm
5518 isExtends := match item
5519 case Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = Absyn.EXTENDS())) then true;
5520 else false;
5521 end match;
5522 end isElementItemExtends;
5523
5524 public function isElementItem
5525 input Absyn.ElementItem inElement;
5526 output Boolean outIsClass;
5527 algorithm
5528 outIsClass := match inElement
5529 case Absyn.ELEMENTITEM() then true;
5530 else false;
5531 end match;
5532 end isElementItem;
5533
5534 public function isAlgorithmItem
5535 input Absyn.AlgorithmItem inAlg;
5536 output Boolean outIsClass;
5537 algorithm
5538 outIsClass := match inAlg
5539 case Absyn.ALGORITHMITEM() then true;
5540 else false;
5541 end match;
5542 end isAlgorithmItem;
5543
5544 public function isElementItemClassNamed
5545 input String inName;
5546 input Absyn.ElementItem inElement;
5547 output Boolean outIsNamed;
5548 algorithm
5549 outIsNamed := match inElement
5550 local
5551 String name;
5552
5553 case Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = Absyn.CLASSDEF(
5554
4/4
✓ Branch 0 taken 149933 times.
✓ Branch 1 taken 767750 times.
✓ Branch 3 taken 70061 times.
✓ Branch 4 taken 79872 times.
917683 class_ = Absyn.CLASS(name = name)))) then name == inName;
5555 else false;
5556 end match;
5557 end isElementItemClassNamed;
5558
5559 public function isElementItemNamed
5560 input String name;
5561 input Absyn.ElementItem element;
5562 output Boolean res;
5563 algorithm
5564 res := match element
5565 30 case Absyn.ELEMENTITEM() then isElementNamed(name, element.element);
5566 else false;
5567 end match;
5568 end isElementItemNamed;
5569
5570 public function isElementNamed
5571 input String name;
5572 input Absyn.Element element;
5573 output Boolean res;
5574 algorithm
5575 res := match element
5576 113 case Absyn.Element.ELEMENT() then isElementSpecNamed(name, element.specification);
5577 else false;
5578 end match;
5579 end isElementNamed;
5580
5581 public function isElementSpecNamed
5582 input String name;
5583 input Absyn.ElementSpec elementSpec;
5584 output Boolean res;
5585 algorithm
5586 res := match elementSpec
5587 21 case Absyn.ElementSpec.CLASSDEF() then isClassNamed(name, elementSpec.class_);
5588 case Absyn.ElementSpec.COMPONENTS()
5589 92 then List.any(elementSpec.components, function isComponentItemNamed(name = name));
5590 else false;
5591 end match;
5592 end isElementSpecNamed;
5593
5594 public function isEmptyClassPart
5595 input Absyn.ClassPart inClassPart;
5596 output Boolean outIsEmpty;
5597 algorithm
5598 outIsEmpty := match inClassPart
5599 case Absyn.PUBLIC(contents = {}) then true;
5600 case Absyn.PROTECTED(contents = {}) then true;
5601 case Absyn.CONSTRAINTS(contents = {}) then true;
5602 case Absyn.EQUATIONS(contents = {}) then true;
5603 case Absyn.INITIALEQUATIONS(contents = {}) then true;
5604 case Absyn.ALGORITHMS(contents = {}) then true;
5605 case Absyn.INITIALALGORITHMS(contents = {}) then true;
5606 else false;
5607 end match;
5608 end isEmptyClassPart;
5609
5610 public function isInvariantExpNoTraverse "For use with traverseExp"
5611 input output Absyn.Exp e;
5612 input output Boolean b;
5613 algorithm
5614 ✗ if not b then
5615 ✗ return;
5616 end if;
5617 b := match e
5618 case Absyn.INTEGER() then true;
5619 case Absyn.REAL() then true;
5620 case Absyn.UNITFUL_LITERAL() then true;
5621 case Absyn.STRING() then true;
5622 case Absyn.BOOL() then true;
5623 case Absyn.BINARY() then true;
5624 case Absyn.UNARY() then true;
5625 case Absyn.LBINARY() then true;
5626 case Absyn.LUNARY() then true;
5627 case Absyn.RELATION() then true;
5628 case Absyn.IFEXP() then true;
5629 // case Absyn.CREF(Absyn.CREF_FULLYQUALIFIED()) then true;
5630 case Absyn.CALL(function_=Absyn.CREF_FULLYQUALIFIED()) then true;
5631 case Absyn.PARTEVALFUNCTION(function_=Absyn.CREF_FULLYQUALIFIED()) then true;
5632 case Absyn.ARRAY() then true;
5633 case Absyn.MATRIX() then true;
5634 case Absyn.RANGE() then true;
5635 case Absyn.CONS() then true;
5636 case Absyn.LIST() then true;
5637 case Absyn.BREAK() then true;
5638 else false;
5639 end match;
5640 end isInvariantExpNoTraverse;
5641
5642 function pathPartCount
5643 "Returns the number of parts a path consists of, e.g. A.B.C gives 3."
5644 input Absyn.Path path;
5645 input Integer partsAccum = 0;
5646 output Integer parts;
5647 algorithm
5648 parts := match path
5649 24 case Absyn.IDENT() then partsAccum + 1;
5650 34 case Absyn.QUALIFIED() then pathPartCount(path.path, partsAccum + 1);
5651 ✗ case Absyn.FULLYQUALIFIED() then pathPartCount(path.path, partsAccum);
5652 end match;
5653 end pathPartCount;
5654
5655 public function getAnnotationsFromConstraintClass
5656 input Option<Absyn.ConstrainClass> inCC;
5657 output list<Absyn.ElementArg> elementArgs;
5658 algorithm
5659 elementArgs := match inCC
5660 case SOME(Absyn.CONSTRAINCLASS(comment = SOME(Absyn.COMMENT(annotation_ = SOME(Absyn.ANNOTATION(elementArgs))))))
5661 then elementArgs;
5662 else {};
5663 end match;
5664 end getAnnotationsFromConstraintClass;
5665
5666 public function getAnnotationsFromItems
5667 input list<Absyn.ComponentItem> inComponentItems;
5668 input list<Absyn.ElementArg> ccAnnotations;
5669 output list<list<Absyn.ElementArg>> outLst = {};
5670 protected
5671 list<Absyn.ElementArg> annotations;
5672 algorithm
5673
2/2
✓ Branch 1 taken 164 times.
✓ Branch 2 taken 163 times.
327 for comp in listReverse(inComponentItems) loop
5674 annotations := match comp
5675 case Absyn.COMPONENTITEM(comment = SOME(Absyn.COMMENT(annotation_ =
5676 SOME(Absyn.ANNOTATION(annotations)))))
5677 111 then listAppend(annotations, ccAnnotations);
5678 else ccAnnotations;
5679 end match;
5680
5681 outLst := annotations :: outLst;
5682 end for;
5683 end getAnnotationsFromItems;
5684
5685 public function stripGraphicsAndInteractionModification
5686 " This function strips out the `graphics\' modification from an Absyn.ElementArg
5687 list and return two lists, one with the other modifications and the
5688 second with the `graphics\' modification"
5689 input list<Absyn.ElementArg> inAbsynElementArgLst;
5690 output list<Absyn.ElementArg> outAbsynElementArgLst1;
5691 output list<Absyn.ElementArg> outAbsynElementArgLst2;
5692 algorithm
5693 (outAbsynElementArgLst1,outAbsynElementArgLst2) := matchcontinue inAbsynElementArgLst
5694 local
5695 Absyn.ElementArg mod;
5696 list<Absyn.ElementArg> rest,l1,l2;
5697
5698 // handle empty
5699 141 case {} then ({},{});
5700
5701 // adrpo: remove interaction annotations as we don't handle them currently
5702 case Absyn.MODIFICATION(path = Absyn.IDENT(name = "interaction")) :: rest
5703 algorithm
5704 ✗ (l1,l2) := stripGraphicsAndInteractionModification(rest);
5705 then
5706 (l1,l2);
5707
5708 // adrpo: remove empty annotations, to handle bad Dymola annotations, for example: Diagram(graphics)
5709 case Absyn.MODIFICATION(modification = NONE(), path = Absyn.IDENT(name = "graphics")) :: rest
5710 algorithm
5711 ✗ (l1,l2) := stripGraphicsAndInteractionModification(rest);
5712 then
5713 (l1,l2);
5714
5715 // add graphics to the second tuple
5716 case (mod as Absyn.MODIFICATION(modification = SOME(_), path = Absyn.IDENT(name = "graphics"))) :: rest
5717 algorithm
5718 18 (l1,l2) := stripGraphicsAndInteractionModification(rest);
5719 18 then
5720 (l1,mod::l2);
5721
5722 // add choice to the second tuple
5723 case (mod as Absyn.MODIFICATION(modification = SOME(_), path = Absyn.IDENT(name = "choice"))) :: rest
5724 algorithm
5725 ✗ (l1,l2) := stripGraphicsAndInteractionModification(rest);
5726 ✗ then
5727 (l1,mod::l2);
5728
5729 // collect in the first tuple
5730 case (mod as Absyn.MODIFICATION()) :: rest
5731 algorithm
5732 233 (l1,l2) := stripGraphicsAndInteractionModification(rest);
5733 233 then
5734 ((mod :: l1),l2);
5735
5736 end matchcontinue;
5737 end stripGraphicsAndInteractionModification;
5738
5739 public function traverseClasses<Arg>
5740 " This function traverses all classes of a program and applies a function
5741 to each class. The function takes the Absyn.Class, Absyn.Path option
5742 and an additional argument and returns an updated class and the
5743 additional values. The Absyn.Path option contains the path to the class
5744 that is traversed.
5745 inputs: (Absyn.Program,
5746 Absyn.Path option,
5747 ((Absyn.Class Absyn.Path option \'a) => (Absyn.Class Absyn.Path option \'a)), /* rel-ation to apply */
5748 \'a, /* extra value passed to re-lation */
5749 bool) /* true = traverse protected elements */
5750 outputs: (Absyn.Program Absyn.Path option \'a)"
5751 input Absyn.Program inProgram;
5752 input Option<Absyn.Path> inPath;
5753 input FuncType inFunc;
5754 input Arg inArg;
5755 input Boolean inVisitProtected;
5756 output tuple<Absyn.Program, Option<Absyn.Path>, Arg> outTpl;
5757
5758 partial function FuncType
5759 input output tuple<Absyn.Class, Option<Absyn.Path>, Arg> tpl;
5760 end FuncType;
5761 algorithm
5762 outTpl := match inProgram
5763 local
5764 list<Absyn.Class> classes;
5765 Option<Absyn.Path> pa;
5766 Arg arg;
5767 Absyn.Program p;
5768
5769 case p as Absyn.PROGRAM()
5770 algorithm
5771 ✗ (classes,pa,arg) := traverseClasses2(p.classes, inPath, inFunc, inArg, inVisitProtected);
5772 ✗ p.classes := classes;
5773 ✗ then
5774 (p,pa,arg);
5775 end match;
5776 end traverseClasses;
5777
5778 protected function traverseClasses2<Arg>
5779 " Helperfunction to traverseClasses."
5780 input list<Absyn.Class> inClasses;
5781 input Option<Absyn.Path> inPath;
5782 input FuncType inFunc;
5783 input Arg inArg "extra argument";
5784 input Boolean inVisitProtected "visit protected elements";
5785 output tuple<list<Absyn.Class>, Option<Absyn.Path>, Arg> outTpl;
5786
5787 partial function FuncType
5788 input output tuple<Absyn.Class, Option<Absyn.Path>, Arg> tpl;
5789 end FuncType;
5790 algorithm
5791 outTpl := matchcontinue (inClasses, inPath, inFunc, inArg, inVisitProtected)
5792 local
5793 Option<Absyn.Path> pa,pa_3;
5794 FuncType visitor;
5795 Arg args,args_1,args_2,args_3;
5796 Absyn.Class class_1,class_2,class_;
5797 list<Absyn.Class> classes_1,classes;
5798 Boolean traverse_prot;
5799
5800 ✗ case ({},pa,_,args,_) then (({},pa,args));
5801
5802 case ((class_ :: classes),pa,visitor,args,traverse_prot)
5803 algorithm
5804 ✗ (class_1,_,args_1) := visitor((class_,pa,args));
5805 ✗ (class_2,_,args_2) := traverseInnerClass(class_1, pa, visitor, args_1, traverse_prot);
5806 ✗ (classes_1,pa_3,args_3) := traverseClasses2(classes, pa, visitor, args_2, traverse_prot);
5807 ✗ then
5808 (((class_2 :: classes_1),pa_3,args_3));
5809
5810 /* Visitor failed, but class contains inner classes after traversal, i.e. those inner classes didn't fail, and thus
5811 the class must be included also */
5812 case ((class_ :: classes),pa,visitor,args,traverse_prot)
5813 algorithm
5814 ✗ (class_2,_,args_2) := traverseInnerClass(class_, pa, visitor, args, traverse_prot);
5815 ✗ true := classHasLocalClasses(class_2);
5816 ✗ (classes_1,pa_3,args_3) := traverseClasses2(classes, pa, visitor, args_2, traverse_prot);
5817 ✗ then
5818 (((class_2 :: classes_1),pa_3,args_3));
5819
5820 /* Visitor failed, remove class */
5821 case ((_ :: classes),pa,visitor,args,traverse_prot)
5822 algorithm
5823 ✗ (classes_1,pa_3,args_3) := traverseClasses2(classes, pa, visitor, args, traverse_prot);
5824 ✗ then
5825 ((classes_1,pa_3,args_3));
5826
5827 case ((class_ :: _),_,_,_,_)
5828 algorithm
5829 ✗ print("-traverse_classes2 failed on class:");
5830 ✗ print(AbsynUtil.className(class_));
5831 ✗ print("\n");
5832 ✗ then
5833 fail();
5834
5835 end matchcontinue;
5836 end traverseClasses2;
5837
5838 protected function classHasLocalClasses
5839 "Returns true if class contains a local class"
5840 input Absyn.Class cl;
5841 output Boolean res;
5842 algorithm
5843 res := match cl
5844 local
5845 list<Absyn.ClassPart> parts;
5846
5847 // A class with parts.
5848 case Absyn.CLASS(body= Absyn.PARTS(classParts = parts))
5849 ✗ then partsHasLocalClass(parts);
5850
5851 // An extended class with parts: model extends M end M;
5852 case Absyn.CLASS(body= Absyn.CLASS_EXTENDS(parts = parts))
5853 ✗ then partsHasLocalClass(parts);
5854
5855 end match;
5856 end classHasLocalClasses;
5857
5858 protected function partsHasLocalClass
5859 "Help function to classHasLocalClass"
5860 input list<Absyn.ClassPart> inParts;
5861 output Boolean res;
5862 algorithm
5863 res := match inParts
5864 local
5865 list<Absyn.ElementItem> elts;
5866 list<Absyn.ClassPart> parts;
5867
5868 case Absyn.PUBLIC(elts) :: _ guard eltsHasLocalClass(elts)
5869 then
5870 true;
5871
5872 case Absyn.PROTECTED(elts) :: _ guard eltsHasLocalClass(elts)
5873 then
5874 true;
5875
5876 ✗ case _ :: parts then partsHasLocalClass(parts);
5877 else false;
5878 end match;
5879 end partsHasLocalClass;
5880
5881 protected function eltsHasLocalClass
5882 "help function to partsHasLocalClass"
5883 input list<Absyn.ElementItem> inElts;
5884 output Boolean res;
5885 algorithm
5886 res := match inElts
5887 local
5888 list<Absyn.ElementItem> elts;
5889
5890 case Absyn.ELEMENTITEM(Absyn.ELEMENT(specification=Absyn.CLASSDEF())) :: _ then true;
5891 ✗ case _ :: elts then eltsHasLocalClass(elts);
5892 else false;
5893 end match;
5894 end eltsHasLocalClass;
5895
5896 protected function traverseInnerClass<Arg>
5897 " Helperfunction to traverseClasses2. This function traverses all inner classes of a class."
5898 input Absyn.Class inClass;
5899 input Option<Absyn.Path> path;
5900 input FuncType visitor;
5901 input Arg arg "extra value";
5902 input Boolean visitProtected "if true, traverse protected elts";
5903 output tuple<Absyn.Class, Option<Absyn.Path>, Arg> outTpl;
5904
5905 partial function FuncType
5906 input tuple<Absyn.Class, Option<Absyn.Path>, Arg> inTpl;
5907 output tuple<Absyn.Class, Option<Absyn.Path>, Arg> outTpl;
5908 end FuncType;
5909 protected
5910 Absyn.Class cls = inClass;
5911 Absyn.ClassDef cdef = inClass.body;
5912 Absyn.Path pa;
5913 Option<Absyn.Path> opt_pa;
5914 list<Absyn.ClassPart> parts;
5915 Arg args;
5916 algorithm
5917 (cdef, opt_pa, args) := matchcontinue(cdef, path)
5918 /* a class with parts */
5919 case (Absyn.PARTS(), SOME(pa))
5920 algorithm
5921 ✗ pa := AbsynUtil.joinPaths(pa, Absyn.IDENT(cls.name));
5922 ✗ (parts, opt_pa, args) := traverseInnerClassParts(cdef.classParts, SOME(pa), visitor, arg, visitProtected);
5923 ✗ cdef.classParts := parts;
5924 then
5925 (cdef, opt_pa, args);
5926
5927 case (Absyn.PARTS(), NONE())
5928 algorithm
5929 ✗ (parts, opt_pa, args) := traverseInnerClassParts(cdef.classParts, SOME(Absyn.IDENT(cls.name)), visitor, arg, visitProtected);
5930 ✗ cdef.classParts := parts;
5931 then
5932 (cdef, opt_pa, args);
5933
5934 case (Absyn.PARTS(), opt_pa)
5935 algorithm
5936 ✗ (parts, opt_pa, args) := traverseInnerClassParts(cdef.classParts, opt_pa, visitor, arg, visitProtected);
5937 ✗ cdef.classParts := parts;
5938 then
5939 (cdef, opt_pa, args);
5940
5941 /* adrpo: handle also an extended class with parts: model extends M end M; */
5942 case (Absyn.CLASS_EXTENDS(), SOME(pa))
5943 algorithm
5944 ✗ pa := AbsynUtil.joinPaths(pa, Absyn.IDENT(cls.name));
5945 ✗ (parts, opt_pa, args) := traverseInnerClassParts(cdef.parts, SOME(pa), visitor, arg, visitProtected);
5946 ✗ cdef.parts := parts;
5947 then
5948 (cdef, opt_pa, args);
5949
5950 case (Absyn.CLASS_EXTENDS(), NONE())
5951 algorithm
5952 ✗ (parts, opt_pa, args) := traverseInnerClassParts(cdef.parts, SOME(Absyn.IDENT(cls.name)), visitor, arg, visitProtected);
5953 ✗ cdef.parts := parts;
5954 then
5955 (cdef, opt_pa, args);
5956
5957 case (Absyn.CLASS_EXTENDS(), opt_pa)
5958 algorithm
5959 ✗ (parts, opt_pa, args) := traverseInnerClassParts(cdef.parts, opt_pa, visitor, arg, visitProtected);
5960 ✗ cdef.parts := parts;
5961 then
5962 (cdef, opt_pa, args);
5963
5964 /* otherwise */
5965 ✗ else (cdef, path, arg);
5966 end matchcontinue;
5967
5968 ✗ cls.body := cdef;
5969 ✗ outTpl := (cls, opt_pa, args);
5970 end traverseInnerClass;
5971
5972 protected function traverseInnerClassParts<Arg>
5973 "Helper function to traverseInnerClass"
5974 input list<Absyn.ClassPart> inClassParts;
5975 input Option<Absyn.Path> inPath;
5976 input FuncType visitor;
5977 input Arg inArg "extra argument";
5978 input Boolean visitProtected "visist protected elts";
5979 output tuple<list<Absyn.ClassPart>, Option<Absyn.Path>, Arg> outTpl;
5980
5981 partial function FuncType
5982 input output tuple<Absyn.Class, Option<Absyn.Path>, Arg> tpl;
5983 end FuncType;
5984 protected
5985 list<Absyn.ClassPart> parts = {};
5986 list<Absyn.ElementItem> elts;
5987 Arg arg = inArg;
5988 algorithm
5989 ✗ parts := list(
5990 match p
5991 case Absyn.PUBLIC()
5992 algorithm
5993 ✗ (elts, _, arg) := traverseInnerClassElements(p.contents, inPath, visitor, arg, visitProtected);
5994 ✗ then
5995 Absyn.PUBLIC(elts);
5996
5997 case Absyn.PROTECTED()
5998 guard visitProtected
5999 algorithm
6000 ✗ (elts, _, arg) := traverseInnerClassElements(p.contents, inPath, visitor, arg, true);
6001 ✗ then
6002 Absyn.PROTECTED(elts);
6003
6004 else p;
6005 end match
6006 for p in inClassParts);
6007
6008 ✗ outTpl := (parts, inPath, arg);
6009 end traverseInnerClassParts;
6010
6011 protected function traverseInnerClassElements<Arg>
6012 "Helper function to traverseInnerClassParts"
6013 input list<Absyn.ElementItem> inElements;
6014 input Option<Absyn.Path> inPath;
6015 input FuncType visitor;
6016 input Arg inArg;
6017 input Boolean visitProtected "visit protected elts";
6018 output tuple<list<Absyn.ElementItem>, Option<Absyn.Path>, Arg> outTpl;
6019
6020 partial function FuncType
6021 input output tuple<Absyn.Class, Option<Absyn.Path>, Arg> tpl;
6022 end FuncType;
6023 protected
6024 list<Absyn.ElementItem> elts = {};
6025 Absyn.Element el;
6026 Arg arg = inArg;
6027 Absyn.ElementSpec spec;
6028 Absyn.Class cl;
6029 algorithm
6030 ✗ for e in inElements loop
6031 elts := match e
6032 case Absyn.ELEMENTITEM(element = el as Absyn.ELEMENT(specification = spec))
6033 algorithm
6034 ✗ (spec, _, arg) := traverseInnerClassElementspec(spec, inPath, visitor, arg, visitProtected);
6035 ✗ el.specification := spec;
6036 ✗ e.element := el;
6037 then
6038 e :: elts;
6039
6040 /* Visitor failed in elementspec, but inner classes succeeded, include class */
6041 case Absyn.ELEMENTITEM(element = el as Absyn.ELEMENT(specification = spec as Absyn.CLASSDEF()))
6042 algorithm
6043 ✗ (cl, _, arg) := traverseInnerClass(spec.class_, inPath, visitor, arg, visitProtected);
6044 ✗ spec.class_ := cl;
6045 ✗ el.specification := spec;
6046 ✗ e.element := el;
6047 then
6048 e :: elts;
6049
6050 /* Visitor failed in elementspec, remove class */
6051 case Absyn.ELEMENTITEM(element = Absyn.ELEMENT())
6052 then elts;
6053
6054 else e :: elts;
6055 end match;
6056 end for;
6057
6058 ✗ elts := listReverseInPlace(elts);
6059 ✗ outTpl := (elts, inPath, arg);
6060 end traverseInnerClassElements;
6061
6062
6063 protected function traverseInnerClassElementspec<Arg>
6064 " Helperfunction to traverseInnerClassElements"
6065 input Absyn.ElementSpec inElementSpec;
6066 input Option<Absyn.Path> inPath;
6067 input FuncType visitor;
6068 input Arg inArg;
6069 input Boolean visitProtected "visit protected elts";
6070 output tuple<Absyn.ElementSpec, Option<Absyn.Path>, Arg> outTpl;
6071 partial function FuncType
6072 input output tuple<Absyn.Class, Option<Absyn.Path>, Arg> tpl;
6073 end FuncType;
6074 algorithm
6075 outTpl := match(inElementSpec, inPath, inArg)
6076 local
6077 Absyn.Class cl;
6078 Option<Absyn.Path> pa;
6079 Arg args;
6080 Boolean repl;
6081
6082 case (Absyn.CLASSDEF(repl, cl),pa,args)
6083 algorithm
6084 ✗ (cl,_,args) := visitor((cl,pa,args));
6085 ✗ (cl,pa,args) := traverseInnerClass(cl, pa, visitor, args, visitProtected);
6086 ✗ then
6087 ((Absyn.CLASSDEF(repl, cl),pa,args));
6088
6089 ✗ case (Absyn.EXTENDS(),pa,args) then ((inElementSpec,pa,args));
6090 ✗ case (Absyn.IMPORT(),pa,args) then ((inElementSpec,pa,args));
6091 ✗ case (Absyn.COMPONENTS(),pa,args) then ((inElementSpec,pa,args));
6092 end match;
6093 end traverseInnerClassElementspec;
6094
6095 public function getTypeSpecFromElementItemOpt
6096 "@auhtor: johti
6097 Get the typespec path in an Absyn.ElementItem if it has one"
6098 input Absyn.ElementItem inElementItem;
6099 output Option<Absyn.TypeSpec> outTypeSpec;
6100 algorithm
6101 outTypeSpec := match inElementItem
6102 local
6103 Absyn.TypeSpec ty_spec;
6104 case Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = Absyn.COMPONENTS(typeSpec = ty_spec)))
6105 then SOME(ty_spec);
6106 else NONE();
6107 end match;
6108 end getTypeSpecFromElementItemOpt;
6109
6110 public function getElementSpecificationFromElementItemOpt
6111 "@auhtor: johti
6112 Get a Absyn.ComponentItem from an Absyn.ElementItem if it has one"
6113 input Absyn.ElementItem inElementItem;
6114 output Option<Absyn.ElementSpec> outSpec;
6115 algorithm
6116 outSpec := match inElementItem
6117 local
6118 Absyn.ElementSpec spec;
6119 case Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = spec)) then SOME(spec);
6120 else NONE();
6121 end match;
6122 end getElementSpecificationFromElementItemOpt;
6123
6124 public function getComponentItemsFromElement
6125 input Absyn.Element element;
6126 output list<Absyn.ComponentItem> items;
6127 algorithm
6128 items := match element
6129 case Absyn.Element.ELEMENT(specification = Absyn.ElementSpec.COMPONENTS(components = items)) then items;
6130 else {};
6131 end match;
6132 end getComponentItemsFromElement;
6133
6134 public function getComponentItemsFromElementSpec
6135 "@auhtor: johti
6136 Get the componentItems from a given elemSpec otherwise returns an empty list"
6137 input Absyn.ElementSpec elemSpec;
6138 output list<Absyn.ComponentItem> componentItems;
6139 algorithm
6140 componentItems := match elemSpec
6141 ✗ case Absyn.COMPONENTS() then elemSpec.components;
6142 else {};
6143 end match;
6144 end getComponentItemsFromElementSpec;
6145
6146 public function getComponentItemsFromElementItem
6147 "@author: johti
6148 Get the componentItems from a given elementItem"
6149 input Absyn.ElementItem inElementItem;
6150 output list<Absyn.ComponentItem> componentItems;
6151 algorithm
6152 componentItems := match getElementSpecificationFromElementItemOpt(inElementItem)
6153 local Absyn.ElementSpec elementSpec;
6154 ✗ case SOME(elementSpec) then getComponentItemsFromElementSpec(elementSpec);
6155 else {};
6156 end match;
6157 end getComponentItemsFromElementItem;
6158
6159 public function getDirection
6160 "@author johti
6161 Get the direction if one exists otherwise returns Absyn.BIDIR()"
6162 input Absyn.ElementItem elementItem;
6163 output Absyn.Direction oDirection;
6164 algorithm
6165 oDirection := match elementItem
6166 case Absyn.ELEMENTITEM(element =
6167 Absyn.ELEMENT(specification =
6168 Absyn.COMPONENTS(attributes =
6169 Absyn.ATTR(direction = oDirection))))
6170 then oDirection;
6171
6172 else Absyn.BIDIR();
6173 end match;
6174 end getDirection;
6175
6176 function isNamedPathIdent
6177 input Absyn.Path path;
6178 input String name;
6179 output Boolean res;
6180 algorithm
6181 res := match path
6182
3/4
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 1066 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 38 times.
1104 case Absyn.IDENT() then path.name == name;
6183 else false;
6184 end match;
6185 end isNamedPathIdent;
6186
6187 function isUniontype
6188 " @author johti17: Returns true if the class is of type uniontype
6189 "
6190 input Absyn.Class cls;
6191 output Boolean b;
6192 algorithm
6193 b := match cls.restriction
6194 case Absyn.R_UNIONTYPE(__) then true;
6195 else false;
6196 end match;
6197 end isUniontype;
6198
6199 public function traverseClassElements<ArgT>
6200 input output Absyn.Class cls;
6201 input FuncType func;
6202 input output ArgT arg;
6203
6204 partial function FuncType
6205 input output Absyn.Element element;
6206 input output ArgT arg;
6207 output Boolean outContinue;
6208 end FuncType;
6209 protected
6210 Absyn.ClassDef body;
6211 algorithm
6212 57 (body, arg) := traverseClassDefElements(cls.body, func, arg);
6213
6214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57 times.
57 if not referenceEq(body, cls.body) then
6215 57 cls.body := body;
6216 end if;
6217 end traverseClassElements;
6218
6219 public function traverseClassDefElements<ArgT>
6220 input output Absyn.ClassDef classDef;
6221 input FuncType func;
6222 input output ArgT arg;
6223
6224 partial function FuncType
6225 input output Absyn.Element element;
6226 input output ArgT arg;
6227 output Boolean outContinue;
6228 end FuncType;
6229 algorithm
6230 57 (classDef, arg) := traverseClassDef(classDef,
6231 function traverseClassPartElements(inFunc = func), arg);
6232 end traverseClassDefElements;
6233
6234 protected function traverseClassPartElements<ArgT>
6235 input Absyn.ClassPart inClassPart;
6236 input FuncType inFunc;
6237 input ArgT inArg;
6238 output Absyn.ClassPart outClassPart = inClassPart;
6239 output ArgT outArg = inArg;
6240 output Boolean outContinue = true;
6241
6242 partial function FuncType
6243 input Absyn.Element inElement;
6244 input ArgT inArg;
6245 output Absyn.Element outElement;
6246 output ArgT outArg;
6247 output Boolean outContinue;
6248 end FuncType;
6249 algorithm
6250 () := match outClassPart
6251 local
6252 list<Absyn.ElementItem> items;
6253
6254 case Absyn.PUBLIC()
6255 algorithm
6256 57 (items, outArg, outContinue) :=
6257 traverseListGeneric(outClassPart.contents,
6258 function traverseElementItem(inFunc = inFunc), inArg);
6259 57 outClassPart.contents := items;
6260 then
6261 ();
6262
6263 case Absyn.PROTECTED()
6264 algorithm
6265 ✗ (items, outArg, outContinue) :=
6266 traverseListGeneric(outClassPart.contents,
6267 function traverseElementItem(inFunc = inFunc), inArg);
6268 ✗ outClassPart.contents := items;
6269 then
6270 ();
6271
6272 else ();
6273 end match;
6274 end traverseClassPartElements;
6275
6276 protected function traverseElementItem<ArgT>
6277 input Absyn.ElementItem inItem;
6278 input FuncType inFunc;
6279 input ArgT inArg;
6280 output Absyn.ElementItem outItem;
6281 output ArgT outArg;
6282 output Boolean outContinue;
6283
6284 partial function FuncType
6285 input Absyn.Element inElement;
6286 input ArgT inArg;
6287 output Absyn.Element outElement;
6288 output ArgT outArg;
6289 output Boolean outContinue;
6290 end FuncType;
6291 algorithm
6292 (outItem, outArg, outContinue) := match inItem
6293 local
6294 Absyn.Element elem;
6295
6296 case Absyn.ELEMENTITEM()
6297 algorithm
6298
1/2
✓ Branch 0 taken 94 times.
✗ Branch 1 not taken.
94 (elem, outArg, outContinue) := inFunc(inItem.element, inArg);
6299
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 39 times.
94 outItem := if referenceEq(elem, inItem.element) then inItem else Absyn.ELEMENTITEM(elem);
6300 then
6301 (outItem, outArg, outContinue);
6302
6303 else (inItem, inArg, true);
6304 end match;
6305 end traverseElementItem;
6306
6307 public function elementSpec
6308 input Absyn.Element el;
6309 output Absyn.ElementSpec elSpec;
6310 algorithm
6311 ✗ Absyn.ELEMENT(specification = elSpec) := el;
6312 end elementSpec;
6313
6314 public function isClassOrComponentElementSpec
6315 "The Absyn.ElementSpec type contains the name of the element, and this function
6316 extracts this name."
6317 input Absyn.ElementSpec inElementSpec;
6318 output Boolean yes = false;
6319 algorithm
6320 yes := match inElementSpec
6321 case Absyn.CLASSDEF(class_ = Absyn.CLASS()) then true;
6322 case Absyn.COMPONENTS(components = {Absyn.COMPONENTITEM()}) then true;
6323 else false;
6324 end match;
6325 end isClassOrComponentElementSpec;
6326
6327 public function isPartial
6328 "Return true if Class is a partial."
6329 input Absyn.Class inClass;
6330 output Boolean outBoolean;
6331 algorithm
6332 6289 Absyn.CLASS(partialPrefix = outBoolean) := inClass;
6333 end isPartial;
6334
6335 public function isNotPartial
6336 "Return true if Class is a partial."
6337 input Absyn.Class inClass;
6338 output Boolean outBoolean;
6339 algorithm
6340 5510 outBoolean := not isPartial(inClass);
6341 end isNotPartial;
6342
6343 public function crefIsWild
6344 input Absyn.ComponentRef cref;
6345 output Boolean wild;
6346 algorithm
6347 wild := match cref
6348 case Absyn.WILD() then true;
6349 case Absyn.ALLWILD() then true;
6350 else false;
6351 end match;
6352 end crefIsWild;
6353
6354 public function makeCall
6355 input Absyn.ComponentRef name;
6356 input list<Absyn.Exp> posArgs;
6357 input list<Absyn.NamedArg> namedArgs = {};
6358 output Absyn.Exp callExp;
6359 algorithm
6360 ✗ callExp := Absyn.Exp.CALL(name, Absyn.FunctionArgs.FUNCTIONARGS(posArgs, namedArgs), {});
6361 end makeCall;
6362
6363 public function setClassCommentsAfterEnd
6364 input output Absyn.Class cl;
6365 input list<String> comments;
6366 algorithm
6367 74719 cl.commentsAfterEnd := comments;
6368 end setClassCommentsAfterEnd;
6369
6370 public function pathReplaceFirst
6371 "Replaces the first identifier of a path with another path. Ex:
6372 pathReplaceFirst(A.B.C, X.Y.Z) => X.Y.Z.B.C"
6373 input Absyn.Path path;
6374 input Absyn.Path prefix;
6375 output Absyn.Path outPath;
6376 algorithm
6377 outPath := match path
6378 case Absyn.Path.IDENT() then prefix;
6379 3 case Absyn.Path.QUALIFIED() then joinPaths(prefix, path.path);
6380 ✗ case Absyn.Path.FULLYQUALIFIED() then Absyn.Path.FULLYQUALIFIED(pathReplaceFirst(path.path, prefix));
6381 end match;
6382 end pathReplaceFirst;
6383
6384 function pathContains
6385 input Absyn.Path path;
6386 input Absyn.Ident name;
6387 output Boolean res;
6388 algorithm
6389 res := match path
6390
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 15 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
18 case Absyn.Path.IDENT() then path.name == name;
6391 case Absyn.Path.QUALIFIED()
6392
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
4 then path.name == name or pathContains(path.path, name);
6393 ✗ case Absyn.Path.FULLYQUALIFIED() then pathContains(path.path, name);
6394 end match;
6395 end pathContains;
6396
6397 function getClassAnnotation
6398 "Returns the optional annotation for a class. Some classes may have multiple
6399 annotations because Modelica 2 allowed it, in that case only the first
6400 annotation is returned."
6401 input Absyn.Class cls;
6402 output Option<Absyn.Annotation> outAnnotation;
6403 algorithm
6404 4 outAnnotation := getClassDefAnnotation(cls.body);
6405 end getClassAnnotation;
6406
6407 function getClassDefAnnotation
6408 "Returns the optional annotation for a class definition."
6409 input Absyn.ClassDef def;
6410 output Option<Absyn.Annotation> outAnnotation;
6411 algorithm
6412 outAnnotation := match def
6413 4 case Absyn.ClassDef.PARTS() guard not listEmpty(def.ann) then SOME(listHead(def.ann));
6414 ✗ case Absyn.ClassDef.DERIVED() then getCommentOptAnnotation(def.comment);
6415 ✗ case Absyn.ClassDef.ENUMERATION() then getCommentOptAnnotation(def.comment);
6416 ✗ case Absyn.ClassDef.OVERLOAD() then getCommentOptAnnotation(def.comment);
6417 ✗ case Absyn.ClassDef.CLASS_EXTENDS() guard not listEmpty(def.ann) then SOME(listHead(def.ann));
6418 ✗ case Absyn.ClassDef.PDER() then getCommentOptAnnotation(def.comment);
6419 else NONE();
6420 end match;
6421 end getClassDefAnnotation;
6422
6423 function setClassAnnotation
6424 "Overwrites the annotation for a class with a given annotation. If the class
6425 has multiple annotations only the first is overwritten, similarly to how
6426 getClassAnnotation ignores other annotations than the first."
6427 input output Absyn.Class cls;
6428 input Option<Absyn.Annotation> ann;
6429 algorithm
6430 1 cls.body := setClassDefAnnotation(cls.body, ann);
6431 end setClassAnnotation;
6432
6433 function setClassDefAnnotation
6434 "Overwrites the annotation for a class definition with a given annotation."
6435 input output Absyn.ClassDef cdef;
6436 input Option<Absyn.Annotation> ann;
6437 algorithm
6438 () := match cdef
6439 case Absyn.ClassDef.PARTS()
6440 algorithm
6441
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if not listEmpty(cdef.ann) then
6442 1 cdef.ann := listRest(cdef.ann);
6443 end if;
6444
6445
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
1 if isSome(ann) then
6446 2 cdef.ann := Util.getOption(ann) :: cdef.ann;
6447 end if;
6448 then
6449 ();
6450
6451 case Absyn.ClassDef.DERIVED()
6452 algorithm
6453 ✗ cdef.comment := setCommentAnnotation(cdef.comment, ann);
6454 then
6455 ();
6456
6457 case Absyn.ClassDef.ENUMERATION()
6458 algorithm
6459 ✗ cdef.comment := setCommentAnnotation(cdef.comment, ann);
6460 then
6461 ();
6462
6463 case Absyn.ClassDef.OVERLOAD()
6464 algorithm
6465 ✗ cdef.comment := setCommentAnnotation(cdef.comment, ann);
6466 then
6467 ();
6468
6469 case Absyn.ClassDef.CLASS_EXTENDS()
6470 algorithm
6471 ✗ if not listEmpty(cdef.ann) then
6472 ✗ cdef.ann := listRest(cdef.ann);
6473 end if;
6474
6475 ✗ if isSome(ann) then
6476 ✗ cdef.ann := Util.getOption(ann) :: cdef.ann;
6477 end if;
6478 then
6479 ();
6480
6481 case Absyn.ClassDef.PDER()
6482 algorithm
6483 ✗ cdef.comment := setCommentAnnotation(cdef.comment, ann);
6484 then
6485 ();
6486
6487 else ();
6488 end match;
6489 end setClassDefAnnotation;
6490
6491 function setCommentString
6492 "Overwrites the comment string in an optional comment."
6493 input output Option<Absyn.Comment> comment;
6494 input Option<String> commentString;
6495 protected
6496 Option<Absyn.Annotation> ann;
6497 Option<String> str;
6498 algorithm
6499
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
4 if isSome(comment) then
6500 ✗ SOME(Absyn.COMMENT(ann, str)) := comment;
6501 ✗ comment := if isSome(ann) or isSome(str) then SOME(Absyn.COMMENT(ann, commentString)) else NONE();
6502 elseif isSome(commentString) then
6503 4 comment := SOME(Absyn.COMMENT(NONE(), commentString));
6504 end if;
6505 end setCommentString;
6506
6507 function setCommentAnnotation
6508 "Overwrites the annotation in an optional comment."
6509 input output Option<Absyn.Comment> comment;
6510 input Option<Absyn.Annotation> ann;
6511 protected
6512 Option<Absyn.Annotation> old_ann;
6513 Option<String> str;
6514 algorithm
6515 ✗ if isSome(comment) then
6516 ✗ SOME(Absyn.COMMENT(old_ann, str)) := comment;
6517 ✗ comment := if isSome(ann) or isSome(str) then SOME(Absyn.COMMENT(ann, str)) else NONE();
6518 elseif isSome(ann) then
6519 ✗ comment := SOME(Absyn.COMMENT(ann, NONE()));
6520 end if;
6521 end setCommentAnnotation;
6522
6523 function mapAnnotationBinding
6524 "Updates the binding expression for the element specificed by the given path
6525 in an annotation using the given function. found will be true if the element
6526 was found and updated, otherwise false."
6527 input output Absyn.Annotation ann;
6528 input Absyn.Path path;
6529 input MapFunc func;
6530 output Boolean found;
6531
6532 partial function MapFunc
6533 input output Absyn.Exp exp;
6534 end MapFunc;
6535 protected
6536 list<Absyn.ElementArg> args = ann.elementArgs;
6537 algorithm
6538 1 (args, found) := List.findMap(args, function mapAnnotationBindingInArg(path = path, func = func));
6539
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 ann.elementArgs := args;
6540 end mapAnnotationBinding;
6541
6542 function mapAnnotationBindingInArg
6543 "Helper function to mapAnnotationBinding."
6544 input output Absyn.ElementArg arg;
6545 input Absyn.Path path;
6546 input MapFunc func;
6547 output Boolean found = false;
6548
6549 partial function MapFunc
6550 input output Absyn.Exp exp;
6551 end MapFunc;
6552 protected
6553 Absyn.Modification mod;
6554 list<Absyn.ElementArg> mod_args;
6555 Absyn.EqMod mod_eq;
6556 Absyn.Path rest_path;
6557 Integer arg_path_len;
6558 algorithm
6559 () := match arg
6560 case Absyn.ElementArg.MODIFICATION(modification = SOME(mod))
6561 algorithm
6562
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 if pathPrefixOf(arg.path, path) then
6563 3 arg_path_len := pathPartCount(arg.path);
6564
6565
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 2 times.
3 if arg_path_len == pathPartCount(path) then
6566 1 mod_eq := mapAnnotationBindingInEqMod(mod.eqMod, func);
6567 1 mod.eqMod := mod_eq;
6568 1 found := true;
6569 else
6570 2 rest_path := Util.foldcallN(arg_path_len, AbsynUtil.pathRest, path);
6571 2 (mod_args, found) := List.findMap(mod.elementArgLst,
6572 function mapAnnotationBindingInArg(path = rest_path, func = func));
6573 2 mod.elementArgLst := mod_args;
6574 end if;
6575
6576
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if found then
6577 3 arg.modification := SOME(mod);
6578 end if;
6579 end if;
6580 then
6581 ();
6582
6583 else ();
6584 end match;
6585 end mapAnnotationBindingInArg;
6586
6587 function mapAnnotationBindingInEqMod
6588 "Helper function to mapAnnotationBinding."
6589 input output Absyn.EqMod eqMod;
6590 input MapFunc func;
6591
6592 partial function MapFunc
6593 input output Absyn.Exp exp;
6594 end MapFunc;
6595 algorithm
6596 () := match eqMod
6597 case Absyn.EqMod.EQMOD()
6598 algorithm
6599
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 eqMod.exp := func(eqMod.exp);
6600 then
6601 ();
6602
6603 else ();
6604 end match;
6605 end mapAnnotationBindingInEqMod;
6606
6607 public function createChoiceArray
6608 "translates
6609 choices(choice(mod1),choice(mod2),choice(mod3)) -> choices(choice={\"mod1\", \"mod2\", \"mod3\"})
6610 choices(choice = mod1, choice = mod2, choice = mod3) -> choices(choice={\"mod1\", \"mod2\", \"mod3\"})"
6611 input Absyn.ElementArg inChoices;
6612 output Absyn.ElementArg outChoices = inChoices;
6613 protected
6614 Absyn.ElementArg choices;
6615 list<Absyn.ElementArg> choice, acc = {}, args;
6616 Absyn.ElementArg c, el;
6617 // info2/cmt2/fp2/ep2 are assigned inside a match arm nested in a for loop;
6618 // the surrounding `if not listEmpty(choiceArray)` guarantees the loop took
6619 // a bound arm at runtime, but Rust's flow analysis can't see this. Default
6620 // the bindings so codegen produces compilable Rust.
6621 Absyn.Info info1, info2 = Absyn.dummyInfo;
6622 Option<String> cmt1, cmt2 = NONE();
6623 Boolean fp1, fp2 = false;
6624 Absyn.Each ep1, ep2 = Absyn.NON_EACH();
6625 list<String> choiceArray = {};
6626 String s;
6627 Absyn.Exp e;
6628 algorithm
6629 outChoices := match inChoices
6630 case Absyn.MODIFICATION(
6631 finalPrefix = fp1,
6632 eachPrefix = ep1,
6633 path = Absyn.IDENT("choices"),
6634 modification = SOME(Absyn.CLASSMOD(choice, Absyn.NOMOD())),
6635 comment = cmt1,
6636 info = info1)
6637 algorithm
6638
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 for m in choice loop
6639 (choiceArray, acc) := match m
6640 // if is a choice, remember it and put it in an array of strings
6641 case Absyn.MODIFICATION(fp2, ep2, Absyn.IDENT("choice"), SOME(Absyn.CLASSMOD({el}, Absyn.NOMOD())), cmt2, info2)
6642 algorithm
6643 ✗ s := Dump.unparseElementArgStr(el);
6644 then
6645 (s::choiceArray, acc);
6646 // if is a choice, remember it and put it in an array of strings
6647 case Absyn.MODIFICATION(fp2, ep2, Absyn.IDENT("choice"), SOME(Absyn.CLASSMOD({}, Absyn.EQMOD(exp = e))), cmt2, info2)
6648 algorithm
6649 ✗ s := Dump.printExpStr(e);
6650 then
6651 (s::choiceArray, acc);
6652 // otherwise put it in any other arguments except choice
6653 else
6654 (choiceArray, m::acc);
6655 end match;
6656 end for;
6657
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if not listEmpty(choiceArray) then
6658 ✗ e := Absyn.ARRAY(list(Absyn.STRING(s) for s in listReverse(choiceArray)));
6659 ✗ c := Absyn.MODIFICATION(fp2, ep2, Absyn.IDENT("choice"), SOME(Absyn.CLASSMOD({}, Absyn.EQMOD(e, info2))), cmt2, info2);
6660 ✗ args := listReverse(c::acc);
6661 else
6662 3 args := listReverse(acc);
6663 end if;
6664
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
9 choices := Absyn.MODIFICATION(fp1, ep1, Absyn.IDENT("choices"), SOME(Absyn.CLASSMOD(args, Absyn.NOMOD())), cmt1, info1);
6665 then
6666 choices;
6667 else then inChoices;
6668 end match;
6669 end createChoiceArray;
6670
6671 function mapCrefExps
6672 "Applies a function to the expressions in an Absyn.ComponentRef, i.e. in its subscripts."
6673 input output Absyn.ComponentRef cref;
6674 input Func func;
6675
6676 partial function Func
6677 input output Absyn.Exp exp;
6678 end Func;
6679 algorithm
6680 () := match cref
6681 case Absyn.ComponentRef.CREF_IDENT()
6682 algorithm
6683 ✗ cref.subscripts := list(mapSubscriptExp(s, func) for s in cref.subscripts);
6684 then
6685 ();
6686
6687 case Absyn.ComponentRef.CREF_QUAL()
6688 algorithm
6689 ✗ cref.subscripts := list(mapSubscriptExp(s, func) for s in cref.subscripts);
6690 then
6691 ();
6692
6693 case Absyn.ComponentRef.CREF_FULLYQUALIFIED()
6694 algorithm
6695 ✗ cref.componentRef := mapCrefExps(cref.componentRef, func);
6696 then
6697 ();
6698
6699 else ();
6700 end match;
6701 end mapCrefExps;
6702
6703 function mapSubscriptExp
6704 input output Absyn.Subscript sub;
6705 input Func func;
6706
6707 partial function Func
6708 input output Absyn.Exp exp;
6709 end Func;
6710 algorithm
6711 () := match sub
6712 case Absyn.Subscript.SUBSCRIPT()
6713 algorithm
6714 ✗ sub.subscript := func(sub.subscript);
6715 then
6716 ();
6717
6718 else ();
6719 end match;
6720 end mapSubscriptExp;
6721
6722 function getElementConstrainingClass
6723 input Absyn.Element element;
6724 output Option<Absyn.ConstrainClass> cc;
6725 algorithm
6726 cc := match element
6727 138 case Absyn.Element.ELEMENT() then element.constrainClass;
6728 else NONE();
6729 end match;
6730 end getElementConstrainingClass;
6731
6732 function isElementReplaceable
6733 input Absyn.Element element;
6734 output Boolean res;
6735 protected
6736 Absyn.RedeclareKeywords redecl;
6737 algorithm
6738 res := match element
6739 case Absyn.Element.ELEMENT(redeclareKeywords = SOME(redecl))
6740 then match redecl
6741 case Absyn.RedeclareKeywords.REPLACEABLE() then true;
6742 case Absyn.RedeclareKeywords.REDECLARE_REPLACEABLE() then true;
6743 else false;
6744 end match;
6745
6746 else false;
6747 end match;
6748 end isElementReplaceable;
6749
6750 function isElementRedeclare
6751 input Absyn.Element element;
6752 output Boolean res;
6753 protected
6754 Absyn.RedeclareKeywords redecl;
6755 algorithm
6756 res := match element
6757 case Absyn.Element.ELEMENT(redeclareKeywords = SOME(redecl))
6758 then match redecl
6759 case Absyn.RedeclareKeywords.REDECLARE() then true;
6760 else false;
6761 end match;
6762
6763 else false;
6764 end match;
6765 end isElementRedeclare;
6766
6767 function isModel
6768 input Absyn.Class cls;
6769 output Boolean res;
6770 algorithm
6771 res := match cls
6772 case Absyn.Class.CLASS(restriction = Absyn.Restriction.R_MODEL()) then true;
6773 else false;
6774 end match;
6775 end isModel;
6776
6777 function isBlock
6778 input Absyn.Class cls;
6779 output Boolean res;
6780 algorithm
6781 res := match cls
6782 case Absyn.Class.CLASS(restriction = Absyn.Restriction.R_BLOCK()) then true;
6783 else false;
6784 end match;
6785 end isBlock;
6786
6787 function isConnector
6788 input Absyn.Class cls;
6789 output Boolean res;
6790 algorithm
6791 res := match cls
6792 case Absyn.Class.CLASS(restriction = Absyn.Restriction.R_CONNECTOR()) then true;
6793 else false;
6794 end match;
6795 end isConnector;
6796
6797 function isExpandableConnector
6798 input Absyn.Class cls;
6799 output Boolean res;
6800 algorithm
6801 res := match cls
6802 case Absyn.Class.CLASS(restriction = Absyn.Restriction.R_EXP_CONNECTOR()) then true;
6803 else false;
6804 end match;
6805 end isExpandableConnector;
6806
6807 function eachBool
6808 input Absyn.Each eachPrefix;
6809 output Boolean res;
6810 algorithm
6811 res := match eachPrefix
6812 case Absyn.Each.EACH() then true;
6813 else false;
6814 end match;
6815 end eachBool;
6816
6817 function getElementAnnotation
6818 "Returns the annotation of an element. The name argument is used to select a
6819 component when there are multiple components in one element, in other cases
6820 it's ignored."
6821 input Absyn.Element element;
6822 input String name;
6823 output Option<Absyn.Annotation> outAnnotation;
6824 algorithm
6825 outAnnotation := match element
6826 4 case Absyn.Element.ELEMENT() then getElementSpecAnnotation(element.specification, name);
6827 else NONE();
6828 end match;
6829 end getElementAnnotation;
6830
6831 function getElementSpecAnnotation
6832 input Absyn.ElementSpec spec;
6833 input String name;
6834 output Option<Absyn.Annotation> outAnnotation;
6835 algorithm
6836 outAnnotation := match spec
6837 3 case Absyn.ElementSpec.CLASSDEF() then getClassAnnotation(spec.class_);
6838 ✗ case Absyn.ElementSpec.EXTENDS() then spec.annotationOpt;
6839 ✗ case Absyn.ElementSpec.IMPORT() then getCommentOptAnnotation(spec.comment);
6840 1 case Absyn.ElementSpec.COMPONENTS() then getComponentItemsAnnotation(spec.components, name);
6841 else NONE();
6842 end match;
6843 end getElementSpecAnnotation;
6844
6845 function getComponentItemsAnnotation
6846 input list<Absyn.ComponentItem> items;
6847 input String name;
6848 output Option<Absyn.Annotation> outAnnotation;
6849 protected
6850 Option<Absyn.ComponentItem> oi;
6851 Absyn.ComponentItem i;
6852 algorithm
6853 1 oi := List.findOption(items, function isComponentItemNamed(name = name));
6854
6855
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
1 if isSome(oi) then
6856 1 SOME(i) := oi;
6857 1 outAnnotation := getCommentOptAnnotation(i.comment);
6858 else
6859 outAnnotation := NONE();
6860 end if;
6861 end getComponentItemsAnnotation;
6862
6863 function getCommentOptAnnotation
6864 input Option<Absyn.Comment> commentOpt;
6865 output Option<Absyn.Annotation> outAnnotation;
6866 algorithm
6867
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 2 times.
3 if isSome(commentOpt) then
6868 1 SOME(Absyn.Comment.COMMENT(annotation_ = outAnnotation)) := commentOpt;
6869 else
6870 outAnnotation := NONE();
6871 end if;
6872 end getCommentOptAnnotation;
6873
6874 function getCommentOptComment
6875 input Option<Absyn.Comment> commentOpt;
6876 output Option<String> outComment;
6877 algorithm
6878
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
4 if isSome(commentOpt) then
6879 ✗ SOME(Absyn.Comment.COMMENT(comment = outComment)) := commentOpt;
6880 else
6881 outComment := NONE();
6882 end if;
6883 end getCommentOptComment;
6884
6885 function setElementAnnotation
6886 "Sets the annotation on an element. The name argument is used to select a
6887 component when there are multiple components in one element, in other cases
6888 it's ignored."
6889 input output Absyn.Element element;
6890 input String name;
6891 input Option<Absyn.Annotation> inAnnotation;
6892 algorithm
6893 () := match element
6894 case Absyn.Element.ELEMENT()
6895 algorithm
6896 ✗ element.specification := setElementSpecAnnotation(element.specification, name, inAnnotation);
6897 then
6898 ();
6899
6900 else ();
6901 end match;
6902 end setElementAnnotation;
6903
6904 function setElementSpecAnnotation
6905 input output Absyn.ElementSpec spec;
6906 input String name;
6907 input Option<Absyn.Annotation> inAnnotation;
6908 algorithm
6909 () := match spec
6910 case Absyn.ElementSpec.CLASSDEF()
6911 algorithm
6912 ✗ spec.class_ := setClassAnnotation(spec.class_, inAnnotation);
6913 then
6914 ();
6915
6916 case Absyn.ElementSpec.EXTENDS()
6917 algorithm
6918 ✗ spec.annotationOpt := inAnnotation;
6919 then
6920 ();
6921
6922 case Absyn.ElementSpec.IMPORT()
6923 algorithm
6924 ✗ spec.comment := setCommentAnnotation(spec.comment, inAnnotation);
6925 then
6926 ();
6927
6928 case Absyn.ElementSpec.COMPONENTS()
6929 algorithm
6930 ✗ spec.components := List.findAndMap(spec.components,
6931 function isComponentItemNamed(name = name),
6932 function setComponentItemAnnotation(inAnnotation = inAnnotation));
6933 then
6934 ();
6935
6936 else ();
6937 end match;
6938 end setElementSpecAnnotation;
6939
6940 function setComponentItemAnnotation
6941 input output Absyn.ComponentItem item;
6942 input Option<Absyn.Annotation> inAnnotation;
6943 algorithm
6944 ✗ item.comment := setCommentAnnotation(item.comment, inAnnotation);
6945 end setComponentItemAnnotation;
6946
6947 function isImpure
6948 input Absyn.FunctionPurity purity;
6949 input Boolean defaultImpure = false; // No prefix = impure if true, otherwise = pure.
6950 output Boolean isImpure;
6951 algorithm
6952 isImpure := match purity
6953 case Absyn.FunctionPurity.IMPURE() then true;
6954 case Absyn.FunctionPurity.NO_PURITY() then defaultImpure;
6955 else false;
6956 end match;
6957 end isImpure;
6958
6959 function purityEqual
6960 input Absyn.FunctionPurity purity1;
6961 input Absyn.FunctionPurity purity2;
6962 input Boolean defaultImpure = false; // No prefix = impure if true, otherwise = pure.
6963 output Boolean isEqual;
6964 algorithm
6965
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
62 if valueConstructor(purity1) == valueConstructor(purity2) then
6966 isEqual := true;
6967 elseif defaultImpure then
6968 isEqual := match (purity1, purity2)
6969 case (Absyn.FunctionPurity.NO_PURITY(), Absyn.FunctionPurity.IMPURE()) then true;
6970 case (Absyn.FunctionPurity.IMPURE(), Absyn.FunctionPurity.NO_PURITY()) then true;
6971 else false;
6972 end match;
6973 else
6974 isEqual := match (purity1, purity2)
6975 case (Absyn.FunctionPurity.NO_PURITY(), Absyn.FunctionPurity.PURE()) then true;
6976 case (Absyn.FunctionPurity.PURE(), Absyn.FunctionPurity.NO_PURITY()) then true;
6977 else false;
6978 end match;
6979 end if;
6980 end purityEqual;
6981
6982 function isElementSection
6983 input Absyn.ClassPart part;
6984 output Boolean res;
6985 algorithm
6986 res := match part
6987 case Absyn.ClassPart.PUBLIC() then true;
6988 case Absyn.ClassPart.PROTECTED() then true;
6989 else false;
6990 end match;
6991 end isElementSection;
6992
6993 function isEquationSection
6994 input Absyn.ClassPart part;
6995 output Boolean res;
6996 algorithm
6997 res := match part
6998 case Absyn.ClassPart.EQUATIONS() then true;
6999 case Absyn.ClassPart.INITIALEQUATIONS() then true;
7000 else false;
7001 end match;
7002 end isEquationSection;
7003
7004 function isAlgorithmSection
7005 input Absyn.ClassPart part;
7006 output Boolean res;
7007 algorithm
7008 res := match part
7009 case Absyn.ClassPart.ALGORITHMS() then true;
7010 case Absyn.ClassPart.INITIALALGORITHMS() then true;
7011 else false;
7012 end match;
7013 end isAlgorithmSection;
7014
7015 function getEquationItemsInPart
7016 input Absyn.ClassPart part;
7017 output list<Absyn.EquationItem> eqs;
7018 algorithm
7019 eqs := match part
7020 10 case Absyn.ClassPart.EQUATIONS() then part.contents;
7021 7 case Absyn.ClassPart.INITIALEQUATIONS() then part.contents;
7022 else {};
7023 end match;
7024 end getEquationItemsInPart;
7025
7026 function setEquationItemsInPart
7027 input list<Absyn.EquationItem> eqs;
7028 input output Absyn.ClassPart part;
7029 algorithm
7030 () := match part
7031 8 case Absyn.ClassPart.EQUATIONS() algorithm part.contents := eqs; then ();
7032 ✗ case Absyn.ClassPart.INITIALEQUATIONS() algorithm part.contents := eqs; then ();
7033 end match;
7034 end setEquationItemsInPart;
7035
7036 function setElementType
7037 "Sets the type of a component or short class definition. If the element
7038 contains multiple components the type is only changed if
7039 allowMultipleComponents = true, otherwise the function will fail."
7040 input output Absyn.Element element;
7041 input Absyn.TypeSpec typeSpec;
7042 input Boolean allowMultipleComponents = false;
7043 algorithm
7044 () := match element
7045 case Absyn.Element.ELEMENT()
7046 algorithm
7047 ✗ element.specification := setElementSpecType(element.specification, typeSpec, allowMultipleComponents);
7048 then
7049 ();
7050
7051 else ();
7052 end match;
7053 end setElementType;
7054
7055 function setElementSpecType
7056 input output Absyn.ElementSpec spec;
7057 input Absyn.TypeSpec typeSpec;
7058 input Boolean allowMultipleComponents = false;
7059 algorithm
7060 () := match spec
7061 case Absyn.ElementSpec.CLASSDEF()
7062 algorithm
7063 ✗ spec.class_ := setClassType(spec.class_, typeSpec);
7064 then
7065 ();
7066
7067 case Absyn.ElementSpec.COMPONENTS()
7068 guard allowMultipleComponents or listLength(spec.components) == 1
7069 algorithm
7070 ✗ spec.typeSpec := typeSpec;
7071 then
7072 ();
7073 end match;
7074 end setElementSpecType;
7075
7076 function setClassType
7077 input output Absyn.Class cls;
7078 input Absyn.TypeSpec typeSpec;
7079 algorithm
7080 ✗ cls.body := setClassDefType(cls.body, typeSpec);
7081 end setClassType;
7082
7083 function setClassDefType
7084 input output Absyn.ClassDef cdef;
7085 input Absyn.TypeSpec typeSpec;
7086 algorithm
7087 () := match cdef
7088 case Absyn.ClassDef.DERIVED()
7089 algorithm
7090 ✗ cdef.typeSpec := typeSpec;
7091 then
7092 ();
7093 end match;
7094 end setClassDefType;
7095
7096 function isLiteralExp
7097 input Absyn.Exp exp;
7098 output Boolean literal;
7099 algorithm
7100 literal := match exp
7101 case Absyn.Exp.INTEGER() then true;
7102 case Absyn.Exp.REAL() then true;
7103 case Absyn.Exp.STRING() then true;
7104 case Absyn.Exp.BOOL() then true;
7105 227 case Absyn.Exp.ARRAY() then List.all(exp.arrayExp, isLiteralExp);
7106
7107 case Absyn.Exp.MATRIX()
7108 algorithm
7109 literal := true;
7110 ✗ for row in exp.matrix loop
7111 ✗ literal := literal and List.all(row, isLiteralExp);
7112 if not literal then
7113 break;
7114 end if;
7115 end for;
7116 then
7117 literal;
7118
7119 case Absyn.Exp.RANGE()
7120 ✗ then isLiteralExp(exp.start) and
7121 Util.applyOptionOrDefault(exp.step, isLiteralExp, true) and
7122 isLiteralExp(exp.stop);
7123
7124 else false;
7125 end match;
7126 end isLiteralExp;
7127
7128 function enumLiteralName
7129 input Absyn.EnumLiteral literal;
7130 output String name = literal.literal;
7131 end enumLiteralName;
7132
7133 public function elementItemClass
7134 input Absyn.ElementItem item;
7135 output Absyn.Class cls;
7136 algorithm
7137
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 79871 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 79871 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 79871 times.
79871 Absyn.ElementItem.ELEMENTITEM(element = Absyn.Element.ELEMENT(specification =
7138 Absyn.ElementSpec.CLASSDEF(class_ = cls))) := item;
7139 end elementItemClass;
7140
7141 function classDefStringComment
7142 input Absyn.ClassDef def;
7143 output String comment;
7144 algorithm
7145 comment := match def
7146 case Absyn.ClassDef.PARTS(comment = SOME(comment)) then comment;
7147 case Absyn.ClassDef.DERIVED(comment = SOME(Absyn.Comment.COMMENT(comment = SOME(comment)))) then comment;
7148 case Absyn.ClassDef.ENUMERATION(comment = SOME(Absyn.Comment.COMMENT(comment = SOME(comment)))) then comment;
7149 case Absyn.ClassDef.OVERLOAD(comment = SOME(Absyn.Comment.COMMENT(comment = SOME(comment)))) then comment;
7150 case Absyn.ClassDef.CLASS_EXTENDS(comment = SOME(comment)) then comment;
7151 case Absyn.ClassDef.PDER(comment = SOME(Absyn.Comment.COMMENT(comment = SOME(comment)))) then comment;
7152 else "";
7153 end match;
7154 end classDefStringComment;
7155
7156 function appendEquation
7157 input Absyn.EquationItem eq;
7158 input Boolean isInitial = false;
7159 input output Absyn.Class cls;
7160 protected
7161 list<Absyn.ClassPart> parts;
7162 Boolean found;
7163
7164 function append_eq
7165 input Absyn.EquationItem eq;
7166 input Boolean isInitial;
7167 input output Absyn.ClassPart part;
7168 output Boolean found;
7169 algorithm
7170 found := match part
7171 case Absyn.ClassPart.EQUATIONS()
7172 guard not isInitial
7173 algorithm
7174 1 part.contents := List.appendElt(eq, part.contents);
7175 then
7176 true;
7177
7178 case Absyn.ClassPart.INITIALEQUATIONS()
7179 guard isInitial
7180 algorithm
7181 1 part.contents := List.appendElt(eq, part.contents);
7182 then
7183 true;
7184
7185 else false;
7186 end match;
7187 end append_eq;
7188 algorithm
7189 4 parts := listReverse(getClassPartsInClass(cls));
7190
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
6 (parts, found) := List.findMap(parts, function append_eq(eq = eq, isInitial = isInitial));
7191
7192
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if not found then
7193
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
4 parts := if isInitial then Absyn.ClassPart.INITIALEQUATIONS({eq}) :: parts else
7194 Absyn.ClassPart.EQUATIONS({eq}) :: parts;
7195 end if;
7196
7197 4 cls := setClassPartsInClass(listReverse(parts), cls);
7198 end appendEquation;
7199
7200 public function forIteratorEqual
7201 input Absyn.ForIterator iter1;
7202 input Absyn.ForIterator iter2;
7203 output Boolean equal = iter1.name == iter2.name and
7204 Util.optionEqual(iter1.guardExp, iter2.guardExp, expEqual) and
7205 Util.optionEqual(iter1.range, iter2.range, expEqual);
7206 end forIteratorEqual;
7207
7208 public function functionArgsEqual
7209 input Absyn.FunctionArgs args1;
7210 input Absyn.FunctionArgs args2;
7211 output Boolean equal;
7212 protected
7213 function named_arg_equal
7214 input Absyn.NamedArg arg1;
7215 input Absyn.NamedArg arg2;
7216 output Boolean equal = arg1.argName == arg2.argName and expEqual(arg1.argValue, arg2.argValue);
7217 end named_arg_equal;
7218 algorithm
7219 equal := match (args1, args2)
7220 case (Absyn.FunctionArgs.FUNCTIONARGS(), Absyn.FunctionArgs.FUNCTIONARGS())
7221 ✗ then List.isEqualOnTrue(args1.args, args2.args, expEqual) and
7222 List.isEqualOnTrue(args1.argNames, args2.argNames, named_arg_equal);
7223
7224 case (Absyn.FunctionArgs.FOR_ITER_FARG(), Absyn.FunctionArgs.FOR_ITER_FARG())
7225 ✗ then expEqual(args1.exp, args2.exp) and
7226 valueEq(args1.iterType, args2.iterType) and
7227 List.isEqualOnTrue(args1.iterators, args2.iterators, forIteratorEqual);
7228
7229 else false;
7230 end match;
7231 end functionArgsEqual;
7232
7233 public function commentEqual
7234 input Absyn.Comment cmt1;
7235 input Absyn.Comment cmt2;
7236 output Boolean equal = Util.optionEqual(cmt1.comment, cmt2.comment, stringEq) and
7237 Util.optionEqual(cmt1.annotation_, cmt2.annotation_, annotationEqual);
7238 end commentEqual;
7239
7240 public function annotationEqual
7241 input Absyn.Annotation ann1;
7242 input Absyn.Annotation ann2;
7243 output Boolean equal = List.isEqualOnTrue(ann1.elementArgs, ann2.elementArgs, elementArgEqual);
7244 end annotationEqual;
7245
7246 public function elementArgEqual
7247 input Absyn.ElementArg arg1;
7248 input Absyn.ElementArg arg2;
7249 output Boolean equal;
7250 algorithm
7251 equal := match (arg1, arg2)
7252 case (Absyn.ElementArg.MODIFICATION(), Absyn.ElementArg.MODIFICATION())
7253
5/10
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
✓ Branch 3 taken 1 time.
✗ Branch 4 not taken.
✓ Branch 6 taken 1 time.
✗ Branch 7 not taken.
✓ Branch 9 taken 1 time.
✗ Branch 10 not taken.
✗ Branch 12 not taken.
✓ Branch 13 taken 1 time.
1 then arg1.finalPrefix == arg2.finalPrefix and
7254 valueEq(arg1.eachPrefix, arg2.eachPrefix) and
7255 pathEqual(arg1.path, arg2.path) and
7256 Util.optionEqual(arg1.modification, arg2.modification, modEqual) and
7257 Util.optionEqual(arg1.comment, arg2.comment, stringEq);
7258
7259 case (Absyn.ElementArg.ELEMENTARGCOMMENT(), Absyn.ElementArg.ELEMENTARGCOMMENT())
7260 ✗ then arg1.comment == arg2.comment;
7261
7262 case (Absyn.ElementArg.INHERITANCEBREAK(), Absyn.ElementArg.INHERITANCEBREAK())
7263 ✗ then equationEqual(arg1.cnct, arg2.cnct);
7264
7265 // REDECLARATION not yet implemented, since this is only used for annotations so far.
7266
7267 else
7268 algorithm
7269 ✗ Error.terminate(getInstanceName() + " got unknown element.", sourceInfo());
7270 ✗ then
7271 fail();
7272
7273 end match;
7274 end elementArgEqual;
7275
7276 public function modEqual
7277 input Absyn.Modification mod1;
7278 input Absyn.Modification mod2;
7279 output Boolean equal = eqModEqual(mod1.eqMod, mod2.eqMod) and
7280 List.isEqualOnTrue(mod1.elementArgLst, mod2.elementArgLst, elementArgEqual);
7281 end modEqual;
7282
7283 public function eqModEqual
7284 input Absyn.EqMod eqMod1;
7285 input Absyn.EqMod eqMod2;
7286 output Boolean equal;
7287 algorithm
7288 equal := match (eqMod1, eqMod2)
7289 case (Absyn.EqMod.NOMOD(), Absyn.EqMod.NOMOD()) then true;
7290 1 case (Absyn.EqMod.EQMOD(), Absyn.EqMod.EQMOD()) then expEqual(eqMod1.exp, eqMod2.exp);
7291 else false;
7292 end match;
7293 end eqModEqual;
7294
7295 public function equationItemEqual
7296 input Absyn.EquationItem eq1;
7297 input Absyn.EquationItem eq2;
7298 input Boolean shallow = false "Ignore the equations inside the equations being checked if true";
7299 input Boolean ignoreComment = true "Include comments/annotations in the comparison if true";
7300 output Boolean equal;
7301 algorithm
7302 equal := match (eq1, eq2)
7303 case (Absyn.EquationItem.EQUATIONITEM(), Absyn.EquationItem.EQUATIONITEM())
7304
6/6
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 10 times.
✓ Branch 6 taken 1 time.
✓ Branch 7 taken 1 time.
27 then equationEqual(eq1.equation_, eq2.equation_, shallow) and
7305 (ignoreComment or Util.optionEqual(eq1.comment, eq2.comment, commentEqual));
7306
7307 case (Absyn.EquationItem.EQUATIONITEMCOMMENT(), Absyn.EquationItem.EQUATIONITEMCOMMENT())
7308 ✗ then eq1.comment == eq2.comment;
7309
7310 else false;
7311 end match;
7312 end equationItemEqual;
7313
7314 public function equationItemsEqual
7315 input list<Absyn.EquationItem> eql1;
7316 input list<Absyn.EquationItem> eql2;
7317 input Boolean shallow = false "Ignore the equations inside the equations being checked if true";
7318 input Boolean ignoreComment = true "Include comments/annotations in the comparison if true";
7319 output Boolean equal = List.isEqualOnTrue(eql1, eql2,
7320 function equationItemEqual(shallow = shallow, ignoreComment = ignoreComment));
7321 end equationItemsEqual;
7322
7323 public function equationEqual
7324 input Absyn.Equation eq1;
7325 input Absyn.Equation eq2;
7326 input Boolean shallow = false "Ignore the equations inside the equations being checked if true";
7327 input Boolean ignoreComment = true "Include comments/annotations in the comparison if true";
7328 output Boolean equal;
7329 protected
7330 Absyn.Exp e1, e2;
7331 list<Absyn.EquationItem> eql1, eql2;
7332 list<tuple<Absyn.Exp, list<Absyn.EquationItem>>> branches;
7333 Absyn.ComponentRef cr1, cr2;
7334 Absyn.ForIterators iters;
7335 Absyn.FunctionArgs args;
7336 Absyn.EquationItem eq;
7337
7338 function branch_eq
7339 input tuple<Absyn.Exp, list<Absyn.EquationItem>> branch1;
7340 input tuple<Absyn.Exp, list<Absyn.EquationItem>> branch2;
7341 input Boolean shallow;
7342 input Boolean ignoreComment;
7343 output Boolean equal = expEqual(Util.tuple21(branch1), Util.tuple21(branch2)) and
7344 (shallow or equationItemsEqual(Util.tuple22(branch1), Util.tuple22(branch2), false, ignoreComment));
7345 end branch_eq;
7346 algorithm
7347
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 20 times.
27 if valueConstructor(eq1) <> valueConstructor(eq2) then
7348 equal := false;
7349 7 return;
7350 end if;
7351
7352 equal := match eq1
7353 case Absyn.Equation.EQ_IF()
7354 algorithm
7355
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 Absyn.Equation.EQ_IF(e1, eql1, branches, eql2) := eq2;
7356
12/16
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 time.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✓ Branch 9 taken 1 time.
✓ Branch 11 taken 1 time.
✓ Branch 12 taken 1 time.
✓ Branch 15 taken 2 times.
✗ Branch 16 not taken.
✓ Branch 17 taken 1 time.
✓ Branch 18 taken 1 time.
✓ Branch 20 taken 1 time.
✗ Branch 21 not taken.
5 then
7357 expEqual(eq1.ifExp, e1) and
7358 (shallow or equationItemsEqual(eq1.equationTrueItems, eql1)) and
7359 List.isEqualOnTrue(eq1.elseIfBranches, branches, function branch_eq(shallow = shallow, ignoreComment = ignoreComment)) and
7360 (shallow or equationItemsEqual(eq1.equationElseItems, eql2, false, ignoreComment));
7361
7362 case Absyn.Equation.EQ_EQUALS()
7363 algorithm
7364
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 Absyn.Equation.EQ_EQUALS(e1, e2) := eq2;
7365
4/4
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 6 times.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 10 times.
17 then
7366 expEqual(eq1.leftSide, e1) and expEqual(eq1.rightSide, e2);
7367
7368 case Absyn.Equation.EQ_PDE()
7369 algorithm
7370 ✗ Absyn.Equation.EQ_PDE(e1, e2, cr1) := eq2;
7371 ✗ then
7372 expEqual(eq1.leftSide, e1) and expEqual(eq1.rightSide, e2) and crefEqual(eq1.domain, cr1);
7373
7374 case Absyn.Equation.EQ_CONNECT()
7375 algorithm
7376 ✗ Absyn.Equation.EQ_CONNECT(cr1, cr2) := eq2;
7377 ✗ then
7378 crefEqual(eq1.connector1, cr1) and crefEqual(eq1.connector2, cr2);
7379
7380 case Absyn.Equation.EQ_FOR()
7381 algorithm
7382 ✗ Absyn.Equation.EQ_FOR(iters, eql1) := eq2;
7383 ✗ then
7384 List.isEqualOnTrue(eq1.iterators, iters, forIteratorEqual) and
7385 (shallow or equationItemsEqual(eq1.forEquations, eql1, false, ignoreComment));
7386
7387 case Absyn.Equation.EQ_WHEN_E()
7388 algorithm
7389 ✗ Absyn.Equation.EQ_WHEN_E(e1, eql1, branches) := eq2;
7390 ✗ then
7391 expEqual(eq1.whenExp, e1) and
7392 equationItemsEqual(eq1.whenEquations, eql1) and
7393 List.isEqualOnTrue(eq1.elseWhenEquations, branches, function branch_eq(shallow = shallow, ignoreComment = ignoreComment));
7394
7395 case Absyn.Equation.EQ_NORETCALL()
7396 algorithm
7397 ✗ Absyn.Equation.EQ_NORETCALL(cr1, args) := eq2;
7398 ✗ then
7399 crefEqual(eq1.functionName, cr1) and functionArgsEqual(eq1.functionArgs, args);
7400
7401 case Absyn.Equation.EQ_FAILURE()
7402 algorithm
7403 ✗ Absyn.Equation.EQ_FAILURE(eq) := eq2;
7404 ✗ then
7405 shallow or equationItemEqual(eq1.equ, eq, false, ignoreComment);
7406
7407 else
7408 algorithm
7409 ✗ Error.terminate(getInstanceName() + " got unknown equation.", sourceInfo());
7410 ✗ then
7411 fail();
7412
7413 end match;
7414 end equationEqual;
7415
7416 annotation(__OpenModelica_Interface="frontend_dump");
7417 end AbsynUtil;
7418