Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 80.8% 101 / 0 / 125
Functions: -% 0 / 1 / 1
Branches: 35.7% 10 / 0 / 28

OMCompiler/Compiler/FrontEnd/NFSCodeFlattenRedeclare.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 NFSCodeFlattenRedeclare
37 " file: NFSCodeFlattenRedeclare.mo
38 package: NFSCodeFlattenRedeclare
39 description: SCode flattening
40
41
42 This module contains redeclare-specific functions used by SCodeFlatten to
43 handle redeclares. Redeclares can be either modifiers or elements.
44
45 REDECLARE MODIFIERS:
46 Redeclare modifiers are redeclarations given as modifiers on e.g. extends
47 clauses. The redeclares are usually extracted from modifiers with the
48 extractRedeclaresFromModifier function, like in NFSCodeEnv.extendEnvWithExtends.
49 The redeclares are in the form of raw modifiers, which are simply
50 SCode.Elements. They are then replaced when needed with the replaceRedeclares
51 function, which use the function processRedeclare to turn the into Items ready
52 to be inserted in the environment. The replaced items are of the type
53 NFSCodeEnv.REDECLARED_ITEM, which contains the new item and the environment it
54 was declared in. The function NFSCodeEnv.resolveRedeclaredItem may then be used
55 to resolve a redeclared item to get the actual item and it's environment,
56 which is important to make sure that e.g. redeclared elements are instantiated
57 in the environment where they were declared.
58
59 ELEMENT REDECLARES:
60 Element redeclares are similar to redeclare modifiers, but they are declared
61 as standalone elements that redeclare an inherited element. When the
62 environment is built they are initially added to a list of elements in the
63 extends tables by NFSCodeEnv.addElementRedeclarationToEnvExtendsTable. When the
64 environment is complete and NFEnvExtends.update is used to update the extends
65 these redeclares are handled by addElementRedeclarationsToEnv, which looks up
66 which base classes the redeclared elements should be applied to. The element
67 redeclares are then added to the list of redeclarations in the correct
68 NFSCodeEnv.EXTENDS, and handled in the same way as redeclare modifiers.
69 "
70
71 public import Absyn;
72 public import AbsynUtil;
73 public import SCode;
74 public import NFSCodeEnv;
75 public import NFInstPrefix;
76 public import NFInstTypes;
77 public import NFSCodeLookup;
78
79 public type Env = NFSCodeEnv.Env;
80 public type Item = NFSCodeEnv.Item;
81 public type Extends = NFSCodeEnv.Extends;
82 public type Prefix = NFInstTypes.Prefix;
83
84 import NFSCodeEnv.EnvTree;
85
86 public uniontype Replacement
87 record REPLACED "an item got replaced"
88 SCode.Ident name;
89 Item old;
90 Item new;
91 Env env;
92 end REPLACED;
93
94 record PUSHED "the redeclares got pushed into the extends of the base classes"
95 SCode.Ident name;
96 Item redeclaredItem;
97 list<Absyn.Path> baseClasses;
98 NFSCodeEnv.ExtendsTable old;
99 NFSCodeEnv.ExtendsTable new;
100 Env env;
101 end PUSHED;
102 end Replacement;
103
104 public type Replacements = list<Replacement>;
105 public constant Replacements emptyReplacements = {};
106
107 protected import Debug;
108 protected import Error;
109 protected import Flags;
110 protected import List;
111 protected import NFSCodeCheck;
112 protected import Util;
113 protected import SCodeDump;
114 import SCodeUtil;
115
116 public function addElementRedeclarationsToEnv
117 input list<SCode.Element> inRedeclares;
118 input Env inEnv;
119 output Env outEnv;
120 algorithm
121 1456769 outEnv := List.fold(inRedeclares, addElementRedeclarationsToEnv2, inEnv);
122 end addElementRedeclarationsToEnv;
123
124 protected function addElementRedeclarationsToEnv2
125 input SCode.Element inRedeclare;
126 input Env inEnv;
127 output Env outEnv;
128 algorithm
129 outEnv := matchcontinue inEnv
130 local
131 SCode.Ident name;
132 SourceInfo info;
133 Absyn.Path env_path;
134 list<Absyn.Path> ext_pathl;
135 Env env;
136 Item item;
137
138 case _
139 algorithm
140 46390 name := SCodeUtil.elementName(inRedeclare);
141 46390 info := SCodeUtil.elementInfo(inRedeclare);
142 46390 ext_pathl := lookupElementRedeclaration(name, inEnv, info);
143 46388 env_path := NFSCodeEnv.getEnvPath(inEnv);
144 46388 item := NFSCodeEnv.ALIAS(name, SOME(env_path), info);
145 46388 env := addRedeclareToEnvExtendsTable(item, ext_pathl, inEnv, info);
146 then
147 env;
148
149 else
150 algorithm
151
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 true := Flags.isSet(Flags.FAILTRACE);
152 ✗ Debug.traceln("- NFSCodeFlattenRedeclare.addElementRedeclarationsToEnv failed for " +
153 SCodeUtil.elementName(inRedeclare) + " in " +
154 NFSCodeEnv.getEnvName(inEnv) + "\n");
155 ✗ then
156 fail();
157 end matchcontinue;
158 end addElementRedeclarationsToEnv2;
159
160 protected function lookupElementRedeclaration
161 input SCode.Ident inName;
162 input Env inEnv;
163 input SourceInfo inInfo;
164 output list<Absyn.Path> outPaths;
165 algorithm
166 outPaths := matchcontinue inInfo
167 local
168 list<Absyn.Path> paths;
169
170 case _
171 algorithm
172 46390 paths := NFSCodeLookup.lookupBaseClasses(inName, inEnv);
173 then
174 paths;
175
176 else
177 algorithm
178 2 Error.addSourceMessage(Error.REDECLARE_NONEXISTING_ELEMENT,
179 {inName}, inInfo);
180 2 then
181 fail();
182
183 end matchcontinue;
184 end lookupElementRedeclaration;
185
186 protected function addRedeclareToEnvExtendsTable
187 input Item inRedeclaredElement;
188 input list<Absyn.Path> inBaseClasses;
189 input Env inEnv;
190 input SourceInfo inInfo;
191 output Env outEnv;
192 protected
193 list<Extends> bcl;
194 list<SCode.Element> re;
195 Option<SCode.Element> cei;
196 algorithm
197 46388 NFSCodeEnv.EXTENDS_TABLE(bcl, re, cei) := NFSCodeEnv.getEnvExtendsTable(inEnv);
198 46388 bcl := addRedeclareToEnvExtendsTable2(inRedeclaredElement, inBaseClasses, bcl);
199 46388 outEnv := NFSCodeEnv.setEnvExtendsTable(NFSCodeEnv.EXTENDS_TABLE(bcl, re, cei), inEnv);
200 end addRedeclareToEnvExtendsTable;
201
202 protected function addRedeclareToEnvExtendsTable2
203 input Item inRedeclaredElement;
204 input list<Absyn.Path> inBaseClasses;
205 input list<Extends> inExtends;
206 output list<Extends> outExtends;
207 algorithm
208 outExtends := matchcontinue(inBaseClasses, inExtends)
209 local
210 Extends ex;
211 list<Extends> exl;
212 Absyn.Path bc1, bc2;
213 list<Absyn.Path> rest_bc;
214 list<NFSCodeEnv.Redeclaration> el;
215 Integer index;
216 SourceInfo info;
217 NFSCodeEnv.Redeclaration redecl;
218
219 case (bc1 :: rest_bc, NFSCodeEnv.EXTENDS(bc2, el, index, info) :: exl)
220 algorithm
221
2/2
✓ Branch 1 taken 642 times.
✓ Branch 2 taken 46388 times.
47030 true := AbsynUtil.pathEqual(bc1, bc2);
222 46388 redecl := NFSCodeEnv.PROCESSED_MODIFIER(inRedeclaredElement);
223 46388 NFSCodeCheck.checkDuplicateRedeclarations(redecl, el);
224 46388 ex := NFSCodeEnv.EXTENDS(bc2, redecl :: el, index, info);
225 46388 exl := addRedeclareToEnvExtendsTable2(inRedeclaredElement, rest_bc, exl);
226 then
227 ex :: exl;
228
229 case ({}, _) then inExtends;
230
231 case (_, ex :: exl)
232 algorithm
233 642 exl := addRedeclareToEnvExtendsTable2(inRedeclaredElement, inBaseClasses, exl);
234 then
235 ex :: exl;
236
237 end matchcontinue;
238 end addRedeclareToEnvExtendsTable2;
239
240 public function processRedeclare
241 "Processes a raw redeclare modifier into a processed form."
242 input NFSCodeEnv.Redeclaration inRedeclare;
243 input Env inEnv;
244 input NFInstTypes.Prefix inPrefix;
245 output NFSCodeEnv.Redeclaration outRedeclare;
246 algorithm
247 outRedeclare := matchcontinue inRedeclare
248 local
249
250 Item el_item, redecl_item;
251 SCode.Element el;
252 Env cls_env;
253
254 case NFSCodeEnv.RAW_MODIFIER(modifier = el as SCode.CLASS())
255 algorithm
256 397110 cls_env := NFSCodeEnv.makeClassEnvironment(el, true);
257 397110 el_item := NFSCodeEnv.newClassItem(el, cls_env, NFSCodeEnv.USERDEFINED());
258 397110 redecl_item := NFSCodeEnv.REDECLARED_ITEM(el_item, inEnv);
259 397110 then
260 NFSCodeEnv.PROCESSED_MODIFIER(redecl_item);
261
262 case NFSCodeEnv.RAW_MODIFIER(modifier = el as SCode.COMPONENT())
263 algorithm
264 726 el_item := NFSCodeEnv.newVarItem(el, true);
265 726 redecl_item := NFSCodeEnv.REDECLARED_ITEM(el_item, inEnv);
266 726 then
267 NFSCodeEnv.PROCESSED_MODIFIER(redecl_item);
268
269 case NFSCodeEnv.PROCESSED_MODIFIER() then inRedeclare;
270
271 else
272 algorithm
273 ✗ true := Flags.isSet(Flags.FAILTRACE);
274 ✗ Debug.traceln("- NFSCodeFlattenRedeclare.processRedeclare failed on " +
275 SCodeDump.unparseElementStr(NFSCodeEnv.getRedeclarationElement(inRedeclare),SCodeDump.defaultOptions) +
276 " in " + AbsynUtil.pathString(NFSCodeEnv.getEnvPath(inEnv)));
277 ✗ then
278 fail();
279 end matchcontinue;
280 end processRedeclare;
281
282 public function replaceRedeclares
283 "Replaces redeclares in the environment. This function takes a list of
284 redeclares, the item and environment of the class in which they should be
285 redeclared, and the environment in which the modified element was declared
286 (used to qualify the redeclares). The redeclares are then either replaced if
287 they can be found in the immediate local environment of the class, or pushed
288 into the correct extends clauses if they are inherited."
289 input list<NFSCodeEnv.Redeclaration> inRedeclares;
290 input Item inClassItem "The item of the class to be modified.";
291 input Env inClassEnv "The environment of the class to be modified.";
292 input Env inElementEnv "The environment in which the modified element was declared.";
293 input NFSCodeLookup.RedeclareReplaceStrategy inReplaceRedeclares;
294 output Option<Item> outItem;
295 output Option<Env> outEnv;
296 algorithm
297 (outItem, outEnv) := matchcontinue inReplaceRedeclares
298 local
299 Item item;
300 Env env;
301
302 case NFSCodeLookup.IGNORE_REDECLARES()
303 then (SOME(inClassItem), SOME(inClassEnv));
304
305 case NFSCodeLookup.INSERT_REDECLARES()
306 algorithm
307 10549335 (item, env, _) := replaceRedeclaredElementsInEnv(inRedeclares,
308 inClassItem, inClassEnv, inElementEnv, NFInstPrefix.emptyPrefix);
309 10549335 then
310 (SOME(item), SOME(env));
311
312 else (NONE(), NONE());
313 end matchcontinue;
314 end replaceRedeclares;
315
316 public function replaceRedeclaredElementsInEnv
317 "If a variable or extends clause has modifications that redeclare classes in
318 it's instance we need to replace those classes in the environment so that the
319 lookup finds the right classes. This function takes a list of redeclares from
320 an elements' modifications and applies them to the environment of the
321 elements type."
322 input list<NFSCodeEnv.Redeclaration> inRedeclares "The redeclares from the modifications.";
323 input Item inItem "The type of the element.";
324 input Env inTypeEnv "The enclosing scopes of the type.";
325 input Env inElementEnv "The environment in which the element was declared.";
326 input NFInstTypes.Prefix inPrefix;
327 output Item outItem;
328 output Env outEnv;
329 output Replacements outReplacements "what replacements where performed if any";
330 algorithm
331 (outItem, outEnv, outReplacements) :=
332 matchcontinue(inRedeclares, inItem)
333 local
334 SCode.Element cls;
335 Env env;
336 NFSCodeEnv.Frame item_env;
337 NFSCodeEnv.ClassType cls_ty;
338 list<NFSCodeEnv.Redeclaration> redecls;
339 Replacements repl;
340
341 // No redeclares!
342 case ({}, _) then (inItem, inTypeEnv, {});
343
344 case (_, NFSCodeEnv.CLASS(cls = cls, env = {item_env}, classType = cls_ty))
345 algorithm
346 // Merge the types environment with it's enclosing scopes to get the
347 // enclosing scopes of the classes we need to replace.
348 1379912 env := NFSCodeEnv.enterFrame(item_env, inTypeEnv);
349 1379912 redecls := List.map2(inRedeclares, processRedeclare, inElementEnv, inPrefix);
350 1379912 (env, repl) := List.fold(redecls, replaceRedeclaredElementInEnv, ((env, emptyReplacements)));
351
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1379911 times.
1379911 item_env :: env := env;
352 1379911 then
353 (NFSCodeEnv.CLASS(cls, {item_env}, cls_ty), env, repl);
354
355 else
356 algorithm
357
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 true := Flags.isSet(Flags.FAILTRACE);
358 ✗ Debug.trace("- NFSCodeFlattenRedeclare.replaceRedeclaredElementsInEnv failed for:\n\t");
359 ✗ Debug.traceln("redeclares: " +
360 stringDelimitList(List.map(inRedeclares, NFSCodeEnv.printRedeclarationStr), "\n---------\n") +
361 "\n\titem: " + NFSCodeEnv.itemStr(inItem) + "\n\tin scope:" + NFSCodeEnv.getEnvName(inElementEnv));
362 ✗ then
363 fail();
364 end matchcontinue;
365 end replaceRedeclaredElementsInEnv;
366
367 public function extractRedeclaresFromModifier
368 "Returns a list of redeclare elements given a redeclaration modifier."
369 input SCode.Mod inMod;
370 output list<NFSCodeEnv.Redeclaration> outRedeclares;
371 algorithm
372 outRedeclares := match inMod
373 local
374 list<SCode.SubMod> sub_mods;
375 list<NFSCodeEnv.Redeclaration> redeclares;
376
377 case SCode.MOD(subModLst = sub_mods)
378 algorithm
379 171219 redeclares := List.fold(sub_mods, extractRedeclareFromSubMod, {});
380 then
381 redeclares;
382
383 else {};
384 end match;
385 end extractRedeclaresFromModifier;
386
387 protected function extractRedeclareFromSubMod
388 "Checks a submodifier and adds the redeclare element to the list of redeclares
389 if the modifier is a redeclaration modifier."
390 input SCode.SubMod inMod;
391 input list<NFSCodeEnv.Redeclaration> inRedeclares;
392 output list<NFSCodeEnv.Redeclaration> outRedeclares;
393 algorithm
394 outRedeclares := match inMod
395 local
396 SCode.Element el;
397 NFSCodeEnv.Redeclaration redecl;
398
399 case SCode.NAMEMOD(mod = SCode.REDECL(element = el))
400 algorithm
401 23139 redecl := NFSCodeEnv.RAW_MODIFIER(el);
402 23139 NFSCodeCheck.checkDuplicateRedeclarations(redecl, inRedeclares);
403 then
404 redecl :: inRedeclares;
405
406 // Skip modifiers that are not redeclarations.
407 else inRedeclares;
408 end match;
409 end extractRedeclareFromSubMod;
410
411 protected function replaceRedeclaredElementInEnv
412 "Replaces a redeclaration in the environment."
413 input NFSCodeEnv.Redeclaration inRedeclare;
414 input tuple<Env, Replacements> inEnv;
415 output tuple<Env, Replacements> outEnv;
416 algorithm
417 outEnv := matchcontinue inRedeclare
418 local
419 SCode.Ident name, scope_name;
420 Item item;
421 SourceInfo info;
422 list<Absyn.Path> bcl;
423 tuple<Env, Replacements> envRpl;
424
425 // Try to redeclare this element in the current scope.
426 case NFSCodeEnv.PROCESSED_MODIFIER(modifier = item)
427 algorithm
428 4925631 name := NFSCodeEnv.getItemName(item);
429 // do not asume the story ends here
430 // you have to push into extends again
431 // even if you find it in the local scope!
432 4925631 envRpl := pushRedeclareIntoExtendsNoFail(name, item, inEnv);
433 4925631 then
434 replaceElementInScope(name, item, envRpl);
435
436 // If the previous case failed, see if we can find the redeclared element in
437 // any of the base classes. If so, push the redeclare into those base
438 // classes instead, i.e. add them to the list of redeclares in the
439 // appropriate extends in the extends table.
440 case NFSCodeEnv.PROCESSED_MODIFIER(modifier = item)
441 algorithm
442 1176786 name := NFSCodeEnv.getItemName(item);
443 1176786 bcl := NFSCodeLookup.lookupBaseClasses(name, Util.tuple21(inEnv));
444 1176785 then
445 pushRedeclareIntoExtends(name, item, bcl, inEnv);
446
447 // The redeclared element could not be found, show an error.
448 case NFSCodeEnv.PROCESSED_MODIFIER(modifier = item)
449 algorithm
450 1 scope_name := NFSCodeEnv.getScopeName(Util.tuple21(inEnv));
451 1 name := NFSCodeEnv.getItemName(item);
452 1 info := NFSCodeEnv.getItemInfo(item);
453 1 Error.addSourceMessage(Error.MISSING_MODIFIED_ELEMENT,
454 {name, scope_name}, info);
455 1 then
456 fail();
457
458 end matchcontinue;
459 end replaceRedeclaredElementInEnv;
460
461 protected function pushRedeclareIntoExtendsNoFail
462 "Pushes a redeclare into the given extends in the environment if it can.
463 if not just returns the same tuple<env, repl>"
464 input SCode.Ident inName;
465 input Item inRedeclare;
466 input tuple<Env, Replacements> inEnv;
467 output tuple<Env, Replacements> outEnv;
468 algorithm
469 outEnv := matchcontinue inEnv
470 local
471 list<Absyn.Path> bcl;
472 tuple<Env, Replacements> envRpl;
473
474 case _
475 algorithm
476 4925631 bcl := NFSCodeLookup.lookupBaseClasses(inName, Util.tuple21(inEnv));
477 1391942 envRpl := pushRedeclareIntoExtends(inName, inRedeclare, bcl, inEnv);
478 then
479 envRpl;
480
481 else inEnv;
482 end matchcontinue;
483 end pushRedeclareIntoExtendsNoFail;
484
485 protected function pushRedeclareIntoExtends
486 "Pushes a redeclare into the given extends in the environment."
487 input SCode.Ident inName;
488 input Item inRedeclare;
489 input list<Absyn.Path> inBaseClasses;
490 input tuple<Env, Replacements> inEnv;
491 output tuple<Env, Replacements> outEnv;
492 protected
493 list<NFSCodeEnv.Extends> exts;
494 list<SCode.Element> re;
495 Option<SCode.Element> cei;
496 NFSCodeEnv.ExtendsTable etNew, etOld;
497 Env env;
498 Replacements repl;
499 algorithm
500 2568727 (env, repl) := inEnv;
501
502
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2568727 times.
2568727 NFSCodeEnv.FRAME(extendsTable = etOld as NFSCodeEnv.EXTENDS_TABLE(exts, re, cei)) :: _ := env;
503 2568727 exts := pushRedeclareIntoExtends2(inName, inRedeclare, inBaseClasses, exts);
504 2568727 etNew := NFSCodeEnv.EXTENDS_TABLE(exts, re, cei);
505
506 2568727 env := NFSCodeEnv.setEnvExtendsTable(etNew, env);
507 2568727 repl := PUSHED(inName, inRedeclare, inBaseClasses, etOld, etNew, env)::repl;
508
509 2568727 outEnv := (env, repl);
510 // tracePushRedeclareIntoExtends(inName, inRedeclare, inBaseClasses, env, etOld, etNew);
511 end pushRedeclareIntoExtends;
512
513 protected function pushRedeclareIntoExtends2
514 "This function takes a redeclare item and a list of base class paths that the
515 redeclare item should be added to. It goes through the given list of
516 extends and pushes the redeclare into each one that's in the list of the
517 base class paths. It assumes that the list of base class paths and extends
518 are sorted in the same order."
519 input String inName;
520 input Item inRedeclare;
521 input list<Absyn.Path> inBaseClasses;
522 input list<NFSCodeEnv.Extends> inExtends;
523 output list<NFSCodeEnv.Extends> outExtends;
524 algorithm
525 outExtends := match(inBaseClasses, inExtends)
526 local
527 Absyn.Path bc1, bc2;
528 list<Absyn.Path> rest_bc;
529 NFSCodeEnv.Extends ext;
530 list<NFSCodeEnv.Extends> rest_exts;
531 list<NFSCodeEnv.Redeclaration> redecls;
532 Integer index;
533 SourceInfo info;
534 list<String> bc_strl;
535 String bcl_str, err_msg;
536
537 // See if the first base class path matches the first extends. Push the
538 // redeclare into that extends if so.
539 case (bc1 :: rest_bc, NFSCodeEnv.EXTENDS(bc2, redecls, index, info) :: rest_exts)
540 guard AbsynUtil.pathEqual(bc1, bc2)
541 algorithm
542 2568797 redecls := pushRedeclareIntoExtends3(inRedeclare, inName, redecls, {});
543 2568797 rest_exts := pushRedeclareIntoExtends2(inName, inRedeclare, rest_bc, rest_exts);
544 2568797 then
545 NFSCodeEnv.EXTENDS(bc2, redecls, index, info) :: rest_exts;
546
547 // The extends didn't match, continue with the rest of them.
548 case (rest_bc, ext :: rest_exts)
549 algorithm
550 27664 rest_exts := pushRedeclareIntoExtends2(inName, inRedeclare, rest_bc, rest_exts);
551 then
552 ext :: rest_exts;
553
554 // No more base class paths to match means we're done.
555 case ({}, _) then inExtends;
556
557 // No more extends means that we couldn't find all the base classes. This
558 // shouldn't happen.
559 case (_, {})
560 algorithm
561 ✗ bc_strl := list(AbsynUtil.pathString(p) for p in inBaseClasses);
562 ✗ bcl_str := stringDelimitList(bc_strl, ", ");
563 ✗ err_msg := "NFSCodeFlattenRedeclare.pushRedeclareIntoExtends2 couldn't find the base classes {"
564 + bcl_str + "} for " + inName;
565 ✗ Error.addMessage(Error.INTERNAL_ERROR, {err_msg});
566 ✗ then
567 fail();
568
569 end match;
570 end pushRedeclareIntoExtends2;
571
572 protected function pushRedeclareIntoExtends3
573 "Given the item and name of a redeclare, try to find the redeclare in the
574 given list of redeclares. If found, replace the redeclare in the list.
575 Otherwise, add a new redeclare to the list."
576 input Item inRedeclare;
577 input String inName;
578 input list<NFSCodeEnv.Redeclaration> inRedeclares;
579 input list<NFSCodeEnv.Redeclaration> inOutRedeclares;
580 output list<NFSCodeEnv.Redeclaration> outRedeclares;
581 algorithm
582 outRedeclares := match inRedeclares
583 local
584 Item item;
585 NFSCodeEnv.Redeclaration redecl;
586 list<NFSCodeEnv.Redeclaration> rest_redecls;
587
588 case NFSCodeEnv.PROCESSED_MODIFIER(modifier = item) :: rest_redecls
589 guard stringEqual(NFSCodeEnv.getItemName(item), inName)
590 430076 then
591 List.append_reverse(inOutRedeclares, NFSCodeEnv.PROCESSED_MODIFIER(inRedeclare) :: rest_redecls);
592
593 case redecl :: rest_redecls
594 49575372 then
595 pushRedeclareIntoExtends3(inRedeclare, inName, rest_redecls, redecl :: inOutRedeclares);
596
597 4707518 case {} then listReverse(NFSCodeEnv.PROCESSED_MODIFIER(inRedeclare) :: inOutRedeclares);
598
599 end match;
600 end pushRedeclareIntoExtends3;
601
602 public function replaceElementInScope
603 "Replaces an element in the current scope."
604 input SCode.Ident inElementName;
605 input Item inElement;
606 input tuple<Env, Replacements> inEnv;
607 output tuple<Env, Replacements> outEnv;
608 algorithm
609 outEnv := match inEnv
610 local
611 EnvTree.Tree tree;
612 Item old_item, new_item;
613 Env env;
614 Replacements repl;
615
616 case (env as NFSCodeEnv.FRAME(clsAndVars = tree) :: _, repl)
617 algorithm
618 4925631 old_item := EnvTree.get(tree, inElementName);
619 /*********************************************************************/
620 // TODO: Check if this is actually needed
621 /*********************************************************************/
622 3748845 new_item := propagateItemPrefixes(old_item, inElement);
623 3748845 new_item := NFSCodeEnv.linkItemUsage(old_item, new_item);
624 3748845 tree := EnvTree.add(tree, inElementName, new_item, EnvTree.addConflictReplace);
625 3748845 env := NFSCodeEnv.setEnvClsAndVars(tree, env);
626 3748845 repl := REPLACED(inElementName, old_item, new_item, env)::repl;
627 // traceReplaceElementInScope(inElementName, old_item, new_item, env);
628 3748845 then
629 ((env, repl));
630
631 end match;
632 end replaceElementInScope;
633
634 protected function propagateItemPrefixes
635 input Item inOriginalItem;
636 input Item inNewItem;
637 output Item outNewItem;
638 algorithm
639 outNewItem := match(inOriginalItem, inNewItem)
640 local
641 SCode.Element el1, el2;
642 Option<Mutable<Boolean>> iu2;
643 Env env1, env2;
644 NFSCodeEnv.ClassType ty2;
645 Item item;
646
647 case (NFSCodeEnv.VAR(var = el1),
648 NFSCodeEnv.VAR(var = el2, isUsed = iu2))
649 algorithm
650 725 el2 := propagateAttributesVar(el1, el2);
651 725 then
652 NFSCodeEnv.VAR(el2, iu2);
653
654 case (NFSCodeEnv.CLASS(cls = el1),
655 NFSCodeEnv.CLASS(cls = el2, env = env2, classType = ty2))
656 algorithm
657 6937 el2 := propagateAttributesClass(el1, el2);
658 6937 then
659 NFSCodeEnv.CLASS(el2, env2, ty2);
660
661 /*************************************************************************/
662 // TODO: Attributes should probably be propagated for alias items too. If
663 // the original is an alias, look up the referenced item and use those
664 // attributes. If the new item is an alias, look up the referenced item and
665 // apply the attributes to it.
666 /*************************************************************************/
667 case (NFSCodeEnv.ALIAS(), _) then inNewItem;
668 case (_, NFSCodeEnv.ALIAS()) then inNewItem;
669
670 case (NFSCodeEnv.REDECLARED_ITEM(item = item), _)
671 6924 then propagateItemPrefixes(item, inNewItem);
672
673 case (_, NFSCodeEnv.REDECLARED_ITEM(item = item, declaredEnv = env1))
674 algorithm
675 7662 item := propagateItemPrefixes(inOriginalItem, item);
676 7662 then
677 NFSCodeEnv.REDECLARED_ITEM(item, env1);
678
679 else
680 algorithm
681 ✗ Error.addMessage(Error.INTERNAL_ERROR,
682 {"NFSCodeFlattenRedeclare.propagateAttributes failed on unknown item."});
683 ✗ then
684 fail();
685 end match;
686 end propagateItemPrefixes;
687
688 public function propagateAttributesVar
689 input SCode.Element inOriginalVar;
690 input SCode.Element inNewVar;
691 output SCode.Element outNewVar;
692 protected
693 SCode.Ident name;
694 SCode.Prefixes pref1, pref2;
695 SCode.Attributes attr1, attr2;
696 Absyn.TypeSpec ty;
697 SCode.Mod mod;
698 SCode.Comment cmt;
699 Option<Absyn.Exp> cond;
700 SourceInfo info;
701 algorithm
702
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 725 times.
725 SCode.COMPONENT(prefixes = pref1, attributes = attr1) := inOriginalVar;
703
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 725 times.
725 SCode.COMPONENT(name, pref2, attr2, ty, mod, cmt, cond, info) := inNewVar;
704 725 pref2 := propagatePrefixes(pref1, pref2);
705 725 attr2 := propagateAttributes(attr1, attr2);
706 725 outNewVar := SCode.COMPONENT(name, pref2, attr2, ty, mod, cmt, cond, info);
707 end propagateAttributesVar;
708
709 public function propagateAttributesClass
710 input SCode.Element inOriginalClass;
711 input SCode.Element inNewClass;
712 output SCode.Element outNewClass;
713 protected
714 SCode.Ident name;
715 SCode.Prefixes pref1, pref2;
716 SCode.Encapsulated ep;
717 SCode.Partial pp;
718 SCode.Restriction res;
719 SCode.ClassDef cdef;
720 SourceInfo info;
721 SCode.Comment cmt;
722 algorithm
723
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6937 times.
6937 SCode.CLASS(prefixes = pref1) := inOriginalClass;
724
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6937 times.
6937 SCode.CLASS(name, pref2, ep, pp, res, cdef, cmt, info) := inNewClass;
725 6937 pref2 := propagatePrefixes(pref1, pref2);
726 6937 outNewClass := SCode.CLASS(name, pref2, ep, pp, res, cdef, cmt, info);
727 end propagateAttributesClass;
728
729 protected function propagatePrefixes
730 input SCode.Prefixes inOriginalPrefixes;
731 input SCode.Prefixes inNewPrefixes;
732 output SCode.Prefixes outNewPrefixes;
733 protected
734 SCode.Visibility vis1, vis2;
735 Absyn.InnerOuter io1, io2;
736 SCode.Redeclare rdp;
737 SCode.Final fp;
738 SCode.Replaceable rpp;
739 algorithm
740 7662 SCode.PREFIXES(visibility = vis1, innerOuter = io1) := inOriginalPrefixes;
741 7662 SCode.PREFIXES(vis2, rdp, fp, io2, rpp) := inNewPrefixes;
742 7662 io2 := propagatePrefixInnerOuter(io1, io2);
743 7662 outNewPrefixes := SCode.PREFIXES(vis2, rdp, fp, io2, rpp);
744 end propagatePrefixes;
745
746 protected function propagatePrefixInnerOuter
747 input Absyn.InnerOuter inOriginalIO;
748 input Absyn.InnerOuter inIO;
749 output Absyn.InnerOuter outIO;
750 algorithm
751 outIO := match inIO
752 case Absyn.NOT_INNER_OUTER() then inOriginalIO;
753 else inIO;
754 end match;
755 end propagatePrefixInnerOuter;
756
757 protected function propagateAttributes
758 input SCode.Attributes inOriginalAttributes;
759 input SCode.Attributes inNewAttributes;
760 output SCode.Attributes outNewAttributes;
761 protected
762 Absyn.ArrayDim dims1, dims2;
763 SCode.ConnectorType ct1, ct2;
764 SCode.Parallelism prl1,prl2;
765 SCode.Variability var1, var2;
766 Absyn.Direction dir1, dir2;
767 Absyn.IsField isf1, isf2;
768 algorithm
769 725 SCode.ATTR(dims1, ct1, prl1, var1, dir1, isf1) := inOriginalAttributes;
770 725 SCode.ATTR(dims2, ct2, prl2, var2, dir2, isf2) := inNewAttributes;
771 725 dims2 := propagateArrayDimensions(dims1, dims2);
772 725 ct2 := propagateConnectorType(ct1, ct2);
773 725 prl2 := propagateParallelism(prl1,prl2);
774 725 var2 := propagateVariability(var1, var2);
775 725 dir2 := propagateDirection(dir1, dir2);
776 725 isf2 := propagateIsField(isf1, isf2);
777 725 outNewAttributes := SCode.ATTR(dims2, ct2, prl2, var2, dir2, isf2);
778 end propagateAttributes;
779
780 protected function propagateArrayDimensions
781 input Absyn.ArrayDim inOriginalDims;
782 input Absyn.ArrayDim inNewDims;
783 output Absyn.ArrayDim outNewDims;
784 algorithm
785 outNewDims := match inNewDims
786 case {} then inOriginalDims;
787 else inNewDims;
788 end match;
789 end propagateArrayDimensions;
790
791 protected function propagateConnectorType
792 input SCode.ConnectorType inOriginalConnectorType;
793 input SCode.ConnectorType inNewConnectorType;
794 output SCode.ConnectorType outNewConnectorType;
795 algorithm
796 outNewConnectorType := match inNewConnectorType
797 case SCode.POTENTIAL() then inOriginalConnectorType;
798 else inNewConnectorType;
799 end match;
800 end propagateConnectorType;
801
802 protected function propagateParallelism
803 input SCode.Parallelism inOriginalParallelism;
804 input SCode.Parallelism inNewParallelism;
805 output SCode.Parallelism outNewParallelism;
806 algorithm
807 outNewParallelism := match inNewParallelism
808 case SCode.NON_PARALLEL() then inOriginalParallelism;
809 else inNewParallelism;
810 end match;
811 end propagateParallelism;
812
813 protected function propagateVariability
814 input SCode.Variability inOriginalVariability;
815 input SCode.Variability inNewVariability;
816 output SCode.Variability outNewVariability;
817 algorithm
818 outNewVariability := match inNewVariability
819 case SCode.VAR() then inOriginalVariability;
820 else inNewVariability;
821 end match;
822 end propagateVariability;
823
824 protected function propagateDirection
825 input Absyn.Direction inOriginalDirection;
826 input Absyn.Direction inNewDirection;
827 output Absyn.Direction outNewDirection;
828 algorithm
829 outNewDirection := match inNewDirection
830 case Absyn.BIDIR() then inOriginalDirection;
831 else inNewDirection;
832 end match;
833 end propagateDirection;
834
835 protected function propagateIsField
836 input Absyn.IsField inOriginalIsField;
837 input Absyn.IsField inNewIsField;
838 output Absyn.IsField outNewIsField;
839 algorithm
840 outNewIsField := match inNewIsField
841 case Absyn.NONFIELD() then inOriginalIsField;
842 else inNewIsField;
843 end match;
844 end propagateIsField;
845
846 protected function traceReplaceElementInScope
847 "@author: adrpo
848 good for debugging redeclares.
849 uncomment it in replaceElementInScope to activate it"
850 input SCode.Ident inElementName;
851 input Item inOldItem;
852 input Item inNewItem;
853 input Env inEnv;
854 algorithm
855 () := matchcontinue inEnv
856 case _
857 algorithm
858 ✗ print("replacing element: " + inElementName + " env: " + NFSCodeEnv.getEnvName(inEnv) + "\n\t");
859 ✗ print("Old Element:" + NFSCodeEnv.itemStr(inOldItem) +
860 " env: " + NFSCodeEnv.getEnvName(NFSCodeEnv.getItemEnvNoFail(inOldItem)) + "\n\t");
861 ✗ print("New Element:" + NFSCodeEnv.itemStr(inNewItem) +
862 " env: " + NFSCodeEnv.getEnvName(NFSCodeEnv.getItemEnvNoFail(inNewItem)) +
863 "\n===============\n");
864 then ();
865
866 else
867 algorithm
868 ✗ print("traceReplaceElementInScope failed on element: " + inElementName + "\n");
869 then ();
870 end matchcontinue;
871 end traceReplaceElementInScope;
872
873 protected function tracePushRedeclareIntoExtends
874 "@author: adrpo
875 good for debugging redeclares.
876 uncomment it in pushRedeclareIntoExtends to activate it"
877 input SCode.Ident inName;
878 input NFSCodeEnv.Item inRedeclare;
879 input list<Absyn.Path> inBaseClasses;
880 input Env inEnv;
881 input NFSCodeEnv.ExtendsTable inEtNew;
882 input NFSCodeEnv.ExtendsTable inEtOld;
883 algorithm
884 () := matchcontinue inEtOld
885 case _
886 algorithm
887 ✗ print("pushing: " + inName + " redeclare: " + NFSCodeEnv.itemStr(inRedeclare) + "\n\t");
888 ✗ print("into baseclases: " + stringDelimitList(list(AbsynUtil.pathString(p) for p in inBaseClasses), ", ") + "\n\t");
889 ✗ print("called from env: " + NFSCodeEnv.getEnvName(inEnv) + "\n");
890 ✗ print("-----------------\n");
891 then ();
892
893 else
894 algorithm
895 ✗ print("tracePushRedeclareIntoExtends failed on element: " + inName + "\n");
896 then ();
897
898 end matchcontinue;
899 end tracePushRedeclareIntoExtends;
900
901 annotation(__OpenModelica_Interface="frontend");
902 end NFSCodeFlattenRedeclare;
903