Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 69.4% 150 / 0 / 216
Functions: -% 0 / 1 / 1
Branches: 43.1% 25 / 0 / 58

OMCompiler/Compiler/FrontEnd/NFSCodeEnv.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 NFSCodeEnv
37 " file: NFSCodeEnv.mo
38 package: NFSCodeEnv
39 description: SCode flattening
40
41
42 This module flattens the SCode representation by removing all extends, imports
43 and redeclares, and fully qualifying class names.
44 "
45
46 import Absyn;
47 import AbsynUtil;
48 import BaseAvlTree;
49 import Mutable;
50 import SCode;
51 import Util;
52
53 protected
54
55 import Error;
56 import FBuiltin;
57 import List;
58 import SCodeDump;
59 import NFEnvExtends;
60 import NFSCodeFlattenRedeclare;
61 import NFSCodeLookup;
62 import NFSCodeCheck;
63 import AbsynToSCode;
64 import SCodeUtil;
65 import System;
66
67 public
68
69 type Import = Absyn.Import;
70 constant Integer tmpTickIndex = 2;
71 constant Integer extendsTickIndex = 3;
72
73 uniontype ImportTable
74 record IMPORT_TABLE
75 // Imports should not be inherited, but removing them from the environment
76 // when doing lookup through extends causes problems for the lookup later
77 // on, because for example components may have types that depends on
78 // imports. The hidden flag allows the lookup to 'hide' the imports
79 // temporarily, without actually removing them.
80 Boolean hidden "If true means that the imports are hidden.";
81 list<Import> qualifiedImports;
82 list<Import> unqualifiedImports;
83 end IMPORT_TABLE;
84 end ImportTable;
85
86 uniontype Redeclaration
87 "This uniontype stores a redeclare modifier (which might be derived from an
88 element redeclare). The RAW_MODIFIER stores a 'raw' modifier, i.e. the raw
89 element stored in the SCode representation. These are processed when they are
90 used, i.e. when replacements are done, and converted into PROCESSED_MODIFIERs
91 which are environment items ready to be replaced in the environment."
92
93 record RAW_MODIFIER
94 SCode.Element modifier;
95 end RAW_MODIFIER;
96
97 record PROCESSED_MODIFIER
98 Item modifier;
99 end PROCESSED_MODIFIER;
100 end Redeclaration;
101
102 uniontype Extends
103 record EXTENDS
104 Absyn.Path baseClass;
105 list<Redeclaration> redeclareModifiers;
106 Integer index;
107 SourceInfo info;
108 end EXTENDS;
109 end Extends;
110
111 uniontype ExtendsTable
112 record EXTENDS_TABLE
113 list<Extends> baseClasses;
114 list<SCode.Element> redeclaredElements;
115 Option<SCode.Element> classExtendsInfo;
116 end EXTENDS_TABLE;
117 end ExtendsTable;
118
119 uniontype FrameType
120 record NORMAL_SCOPE end NORMAL_SCOPE;
121 record ENCAPSULATED_SCOPE end ENCAPSULATED_SCOPE;
122 record IMPLICIT_SCOPE "This scope contains one or more iterators; they are made unique by the following index (plus their name)" Integer iterIndex; end IMPLICIT_SCOPE;
123 end FrameType;
124
125 uniontype Frame
126 record FRAME
127 Option<String> name;
128 FrameType frameType;
129 EnvTree.Tree clsAndVars;
130 ExtendsTable extendsTable;
131 ImportTable importTable;
132 Option<Mutable<Boolean>> isUsed "Used by SCodeDependency.";
133 end FRAME;
134 end Frame;
135
136 uniontype ClassType
137 record USERDEFINED end USERDEFINED;
138 record BUILTIN end BUILTIN;
139 record CLASS_EXTENDS end CLASS_EXTENDS;
140 record BASIC_TYPE end BASIC_TYPE;
141 end ClassType;
142
143 uniontype Item
144 record VAR
145 SCode.Element var;
146 Option<Mutable<Boolean>> isUsed "Used by SCodeDependency.";
147 end VAR;
148
149 record CLASS
150 SCode.Element cls;
151 Env env;
152 ClassType classType;
153 end CLASS;
154
155 record ALIAS
156 "An alias for another Item, see comment in SCodeFlattenRedeclare package."
157 String name;
158 Option<Absyn.Path> path;
159 SourceInfo info;
160 end ALIAS;
161
162 record REDECLARED_ITEM
163 Item item;
164 Env declaredEnv;
165 end REDECLARED_ITEM;
166 end Item;
167
168 encapsulated package EnvTree
169 import BaseAvlTree;
170 import NFSCodeEnv.Item;
171 extends BaseAvlTree;
172
173 redeclare type Key = String;
174 redeclare type Value = Item;
175
176 redeclare function extends keyStr
177 algorithm
178 outString := inKey;
179 end keyStr;
180
181 redeclare function extends valueStr
182 algorithm
183 outString := "$item";
184 end valueStr;
185
186 redeclare function extends keyCompare
187 algorithm
188 504425601 outResult := stringCompare(inKey1, inKey2);
189 end keyCompare;
190
191 redeclare function addConflictDefault = addConflictReplace;
192
193 annotation(__OpenModelica_Interface="util");
194 end EnvTree;
195
196 public type Env = list<Frame>;
197 public constant Env emptyEnv = {};
198 public constant String BASE_CLASS_SUFFIX = "$base";
199
200 public function newEnvironment
201 "Returns a new environment with only one frame."
202 input Option<SCode.Ident> inName;
203 output Env outEnv;
204 protected
205 Frame new_frame;
206 algorithm
207 ✗ new_frame := newFrame(inName, NORMAL_SCOPE());
208 outEnv := {new_frame};
209 end newEnvironment;
210
211 protected function openScope
212 "Open a new class scope in the environment by adding a new frame for the given
213 class."
214 input Env inEnv;
215 input SCode.Element inClass;
216 output Env outEnv;
217 protected
218 String name;
219 SCode.Encapsulated encapsulatedPrefix;
220 Frame new_frame;
221 algorithm
222
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2569199 times.
2569199 SCode.CLASS(name = name, encapsulatedPrefix = encapsulatedPrefix) := inClass;
223 5138398 new_frame := newFrame(SOME(name), getFrameType(encapsulatedPrefix));
224 outEnv := new_frame :: inEnv;
225 end openScope;
226
227 public function enterScope
228 "Enters a new scope in the environment by looking up an item in the
229 environment and appending it's frame to the environment."
230 input Env inEnv;
231 input SCode.Ident inName;
232 output Env outEnv;
233 algorithm
234 outEnv := matchcontinue inName
235 local
236 Frame cls_env;
237 Item item;
238
239 case _
240 algorithm
241 /*********************************************************************/
242 // TODO: Should we use the environment returned by lookupInClass?
243 /*********************************************************************/
244 30184 (item, _) := NFSCodeLookup.lookupInClass(inName, inEnv);
245
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 30184 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 30184 times.
30184 {cls_env} := getItemEnv(item);
246 30184 outEnv := enterFrame(cls_env, inEnv);
247 then
248 outEnv;
249
250 case _
251 algorithm
252 ✗ print("Failed to enterScope: " + inName + " in env: " + printEnvStr(inEnv) + "\n");
253 ✗ then
254 fail();
255 end matchcontinue;
256 end enterScope;
257
258 public function enterScopePath
259 input Env inEnv;
260 input Absyn.Path inPath;
261 output Env outEnv;
262 algorithm
263 outEnv := match inPath
264 local
265 Absyn.Ident name;
266 Absyn.Path path;
267 Env env;
268
269 case Absyn.QUALIFIED(name = name, path = path)
270 algorithm
271 9686 env := enterScope(inEnv, name);
272 9686 then
273 enterScopePath(env, path);
274
275 case Absyn.IDENT(name = name)
276 3181 then enterScope(inEnv, name);
277
278 case Absyn.FULLYQUALIFIED(path = path)
279 algorithm
280 ✗ env := getEnvTopScope(inEnv);
281 ✗ then
282 enterScopePath(env, path);
283
284 end match;
285 end enterScopePath;
286
287 public function enterFrame
288 input Frame inFrame;
289 input Env inEnv;
290 output Env outEnv;
291 algorithm
292 outEnv := inFrame :: inEnv;
293 end enterFrame;
294
295 public function getEnvTopScope
296 "Returns the top scope, i.e. last frame in the environment."
297 input Env inEnv;
298 output Env outEnv;
299 protected
300 Frame top_scope;
301 Env env;
302 algorithm
303 22820977 env := listReverse(inEnv);
304
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22820977 times.
22820977 top_scope :: _ := env;
305 outEnv := {top_scope};
306 end getEnvTopScope;
307
308 protected function getFrameType
309 "Returns a new FrameType given if the frame should be encapsulated or not."
310 input SCode.Encapsulated encapsulatedPrefix;
311 output FrameType outType;
312 algorithm
313 outType := match encapsulatedPrefix
314 case SCode.ENCAPSULATED() then ENCAPSULATED_SCOPE();
315 else NORMAL_SCOPE();
316 end match;
317 end getFrameType;
318
319 protected function newFrame
320 "Creates a new frame with an optional name and a frame type."
321 input Option<String> inName;
322 input FrameType inType;
323 output Frame outFrame;
324 protected
325 EnvTree.Tree tree;
326 ExtendsTable exts;
327 ImportTable imps;
328 Mutable<Boolean> is_used;
329 algorithm
330 2570743 tree := EnvTree.new();
331 exts := newExtendsTable();
332 imps := newImportTable();
333 2570743 is_used := Mutable.create(false);
334 2570743 outFrame := FRAME(inName, inType, tree, exts, imps, SOME(is_used));
335 end newFrame;
336
337 protected function newImportTable
338 "Creates a new import table."
339 output ImportTable outImports;
340 algorithm
341 outImports := IMPORT_TABLE(false, {}, {});
342 end newImportTable;
343
344 protected function newExtendsTable
345 "Creates a new extends table."
346 output ExtendsTable outExtends;
347 algorithm
348 outExtends := EXTENDS_TABLE({}, {}, NONE());
349 end newExtendsTable;
350
351 public function newItem
352 input SCode.Element inElement;
353 output Item outItem;
354 algorithm
355 outItem := match inElement
356 local
357 Env class_env;
358 Item item;
359
360 case SCode.CLASS()
361 algorithm
362 ✗ class_env := makeClassEnvironment(inElement, true);
363 ✗ item := newClassItem(inElement, class_env, USERDEFINED());
364 then
365 item;
366
367 ✗ case SCode.COMPONENT() then newVarItem(inElement, false);
368
369 end match;
370 end newItem;
371
372 public function newClassItem
373 "Creates a new class environment item."
374 input SCode.Element inClass;
375 input Env inEnv;
376 input ClassType inClassType;
377 output Item outClassItem;
378 algorithm
379 2586509 outClassItem := CLASS(inClass, inEnv, inClassType);
380 end newClassItem;
381
382 public function newVarItem
383 "Creates a new variable environment item."
384 input SCode.Element inVar;
385 input Boolean inIsUsed;
386 output Item outVarItem;
387 protected
388 Mutable<Boolean> is_used;
389 algorithm
390
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 94515 times.
94515 is_used := Mutable.create(inIsUsed);
391 94515 outVarItem := VAR(inVar, SOME(is_used));
392 end newVarItem;
393
394 public function extendEnvWithClasses
395 "Extends the environment with a list of classes."
396 input list<SCode.Element> inClasses;
397 input Env inEnv;
398 output Env outEnv;
399 algorithm
400 3298 outEnv := List.fold(inClasses, extendEnvWithClass, inEnv);
401 end extendEnvWithClasses;
402
403 protected function extendEnvWithClass
404 "Extends the environment with a class."
405 input SCode.Element inClass;
406 input Env inEnv;
407 output Env outEnv;
408 algorithm
409 193031 outEnv := extendEnvWithClassDef(inClass, inEnv);
410 end extendEnvWithClass;
411
412 public function getClassType
413 "Returns a class's type."
414 input SCode.ClassDef inClassDef;
415 output ClassType outType;
416 algorithm
417 outType := match inClassDef
418 // A builtin class.
419 case SCode.PARTS(externalDecl = SOME(SCode.EXTERNALDECL(
420 lang = SOME("builtin"))))
421 then BUILTIN();
422 // A user-defined class (i.e. not builtin).
423 else USERDEFINED();
424 end match;
425 end getClassType;
426
427 public function printClassType
428 input ClassType inClassType;
429 output String outString;
430 algorithm
431 outString := match inClassType
432 case BUILTIN() then "BUILTIN";
433 case CLASS_EXTENDS() then "CLASS_EXTENDS";
434 case USERDEFINED() then "USERDEFINED";
435 case BASIC_TYPE() then "BASIC_TYPE";
436 end match;
437 end printClassType;
438
439 public function removeExtendsFromLocalScope
440 "Removes all extends from the local scope, i.e. inserts a new empty
441 extends-table into the first frame."
442 input Env inEnv;
443 output Env outEnv;
444 protected
445 Option<String> name;
446 FrameType ty;
447 EnvTree.Tree tree;
448 ImportTable imps;
449 ExtendsTable exts;
450 Env rest;
451 Option<Mutable<Boolean>> is_used;
452 algorithm
453
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10079043 times.
10079043 FRAME(name = name, frameType = ty, clsAndVars = tree, importTable = imps,
454 isUsed = is_used) :: rest := inEnv;
455 exts := newExtendsTable();
456 10079043 outEnv := FRAME(name, ty, tree, exts, imps, is_used) :: rest;
457 end removeExtendsFromLocalScope;
458
459 public function removeExtendFromLocalScope
460 "Removes a given extends clause from the local scope."
461 input Absyn.Path inExtend;
462 input Env inEnv;
463 output Env outEnv;
464 protected
465 Option<String> name;
466 FrameType ty;
467 EnvTree.Tree tree;
468 ImportTable imps;
469 Env rest;
470 Option<Mutable<Boolean>> iu;
471 list<Extends> bcl;
472 list<SCode.Element> re;
473 Option<SCode.Element> cei;
474 algorithm
475
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 592474 times.
592474 FRAME(name = name, frameType = ty, clsAndVars = tree, extendsTable =
476 EXTENDS_TABLE(baseClasses = bcl, redeclaredElements = re, classExtendsInfo = cei),
477 importTable = imps, isUsed = iu) :: rest := inEnv;
478 592474 (bcl, _) := List.deleteMemberOnTrue(inExtend, bcl, isExtendNamed);
479 592474 outEnv := FRAME(name, ty, tree, EXTENDS_TABLE(bcl, re, cei), imps, iu) :: rest;
480 end removeExtendFromLocalScope;
481
482 protected function isExtendNamed
483 input Absyn.Path inName;
484 input Extends inExtends;
485 output Boolean outIsNamed;
486 protected
487 Absyn.Path bc;
488 algorithm
489 592476 EXTENDS(baseClass = bc) := inExtends;
490 592476 outIsNamed := AbsynUtil.pathEqual(inName, bc);
491 end isExtendNamed;
492
493 public function removeRedeclaresFromLocalScope
494 input Env inEnv;
495 output Env outEnv;
496 protected
497 Option<String> name;
498 FrameType ty;
499 EnvTree.Tree tree;
500 ImportTable imps;
501 ExtendsTable exts;
502 Env rest;
503 Option<Mutable<Boolean>> is_used;
504 list<Extends> bc;
505 Option<SCode.Element> cei;
506 algorithm
507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17460 times.
17460 FRAME(name = name, frameType = ty, clsAndVars = tree, extendsTable =
508 EXTENDS_TABLE(baseClasses = bc, classExtendsInfo = cei), importTable = imps,
509 isUsed = is_used) :: rest := inEnv;
510 17460 bc := List.map(bc, removeRedeclaresFromExtend);
511 17460 exts := EXTENDS_TABLE(bc, {}, cei);
512 17460 outEnv := FRAME(name, ty, tree, exts, imps, is_used) :: rest;
513 end removeRedeclaresFromLocalScope;
514
515 protected function removeRedeclaresFromExtend
516 input Extends inExtend;
517 output Extends outExtend;
518 protected
519 Absyn.Path bc;
520 Integer index;
521 SourceInfo info;
522 algorithm
523 12688 EXTENDS(bc, _, index, info) := inExtend;
524 12688 outExtend := EXTENDS(bc, {}, index, info);
525 end removeRedeclaresFromExtend;
526
527 public function removeClsAndVarsFromFrame
528 "Removes the classes variables from a frame."
529 input Frame inFrame;
530 output Frame outFrame;
531 output EnvTree.Tree outClsAndVars;
532 protected
533 Option<String> name;
534 FrameType ty;
535 EnvTree.Tree tree;
536 ImportTable imps;
537 ExtendsTable exts;
538 Option<Mutable<Boolean>> is_used;
539 algorithm
540 14142 FRAME(name = name, frameType = ty, clsAndVars = outClsAndVars,
541 extendsTable = exts, importTable = imps, isUsed = is_used) := inFrame;
542 14142 tree := EnvTree.new();
543 14142 outFrame := FRAME(name, ty, tree, exts, imps, is_used);
544 end removeClsAndVarsFromFrame;
545
546 public function setImportTableHidden
547 "Sets the 'hidden' flag in the import table in the local scope of the given
548 environment."
549 input Env inEnv;
550 input Boolean inHidden;
551 output Env outEnv;
552 protected
553 Option<String> name;
554 FrameType ty;
555 EnvTree.Tree tree;
556 ExtendsTable exts;
557 Env rest;
558 list<Import> qi, uqi;
559 Option<Mutable<Boolean>> is_used;
560 algorithm
561
2/2
✓ Branch 0 taken 234 times.
✓ Branch 1 taken 107679214 times.
107679448 FRAME(name = name, frameType = ty, clsAndVars = tree, extendsTable = exts,
562 importTable = IMPORT_TABLE(qualifiedImports = qi, unqualifiedImports = uqi),
563 isUsed = is_used) :: rest := inEnv;
564
2/2
✓ Branch 0 taken 84937202 times.
✓ Branch 1 taken 22742012 times.
192616416 outEnv := FRAME(name, ty, tree, exts, IMPORT_TABLE(inHidden, qi, uqi), is_used) :: rest;
565 end setImportTableHidden;
566
567 public function setImportsInItemHidden
568 "Sets the 'hidden' flag in the import table for the given items environment if
569 the item is a class. Otherwise does nothing."
570 input Item inItem;
571 input Boolean inHidden;
572 output Item outItem;
573 algorithm
574 outItem := match inItem
575 local
576 SCode.Element cls;
577 Env env;
578 ClassType cls_ty;
579
580 case CLASS(cls = cls, env = env, classType = cls_ty)
581 algorithm
582 19773292 env := setImportTableHidden(env, inHidden);
583 19773058 then
584 CLASS(cls, env, cls_ty);
585
586 else inItem;
587 end match;
588 end setImportsInItemHidden;
589
590 public function isItemUsed
591 "Checks if an item is used or not."
592 input Item inItem;
593 output Boolean isUsed;
594 algorithm
595 isUsed := match inItem
596 local
597 Mutable<Boolean> is_used;
598 Item item;
599
600 case CLASS(env = {FRAME(isUsed = SOME(is_used))})
601 338613 then Mutable.access(is_used);
602
603 case VAR(isUsed = SOME(is_used))
604 305812 then Mutable.access(is_used);
605
606 case ALIAS() then true;
607
608 2 case REDECLARED_ITEM(item = item) then isItemUsed(item);
609
610 else false;
611 end match;
612 end isItemUsed;
613
614 public function linkItemUsage
615 "'Links' two items to each other, by making them share the same isUsed
616 variable."
617 input Item inSrcItem;
618 input Item inDestItem;
619 output Item outDestItem;
620 algorithm
621 outDestItem := match(inSrcItem, inDestItem)
622 local
623 Option<Mutable<Boolean>> is_used;
624 SCode.Element elem;
625 ClassType cls_ty;
626 Option<String> name;
627 FrameType ft;
628 EnvTree.Tree cv;
629 ExtendsTable exts;
630 ImportTable imps;
631 Item item;
632 Env env;
633
634 case (VAR(isUsed = is_used), VAR(var = elem))
635 725 then VAR(elem, is_used);
636
637 case (CLASS(env = {FRAME(isUsed = is_used)}),
638 CLASS(cls = elem, classType = cls_ty, env =
639 {FRAME(name, ft, cv, exts, imps, _)}))
640 34 then CLASS(elem, {FRAME(name, ft, cv, exts, imps, is_used)}, cls_ty);
641
642 case (_, REDECLARED_ITEM(item, env))
643 algorithm
644 397239 item := linkItemUsage(inSrcItem, item);
645 397239 then
646 REDECLARED_ITEM(item, env);
647
648 else inDestItem;
649 end match;
650 end linkItemUsage;
651
652 public function isClassItem
653 input Item inItem;
654 output Boolean outIsClass;
655 algorithm
656 outIsClass := match inItem
657 local
658 Item item;
659
660 case CLASS() then true;
661 ✗ case REDECLARED_ITEM(item = item) then isClassItem(item);
662 else false;
663 end match;
664 end isClassItem;
665
666 public function isVarItem
667 input Item inItem;
668 output Boolean outIsVar;
669 algorithm
670 outIsVar := match inItem
671 local
672 Item item;
673
674 case VAR() then true;
675 ✗ case REDECLARED_ITEM(item = item) then isVarItem(item);
676 else false;
677 end match;
678 end isVarItem;
679
680 public function isClassExtendsItem
681 input Item inItem;
682 output Boolean outIsClassExtends;
683 algorithm
684 outIsClassExtends := match inItem
685 local
686 Item item;
687
688 case CLASS(classType = CLASS_EXTENDS()) then true;
689 ✗ case REDECLARED_ITEM(item = item) then isClassExtendsItem(item);
690 else false;
691 end match;
692 end isClassExtendsItem;
693
694 protected function extendEnvWithClassDef
695 "Extends the environment with a class definition."
696 input SCode.Element inClassDefElement;
697 input Env inEnv;
698 output Env outEnv;
699 algorithm
700 outEnv := match inClassDefElement
701 local
702 String cls_name, alias_name;
703 Env class_env, env;
704 SCode.ClassDef cdef;
705 ClassType cls_type;
706 SourceInfo info;
707
708 // A class extends.
709 case SCode.CLASS(classDef = SCode.CLASS_EXTENDS())
710 38783 then
711 NFEnvExtends.extendEnvWithClassExtends(inClassDefElement, inEnv);
712
713 case SCode.CLASS(name = cls_name, classDef = cdef, prefixes = SCode.PREFIXES(
714 replaceablePrefix = SCode.REPLACEABLE(_)), info = info)
715 algorithm
716 20446 class_env := makeClassEnvironment(inClassDefElement, false);
717 20446 cls_type := getClassType(cdef);
718 20446 alias_name := cls_name + BASE_CLASS_SUFFIX;
719 20446 env := extendEnvWithItem(newClassItem(inClassDefElement, class_env, cls_type),
720 inEnv, alias_name);
721 20446 env := extendEnvWithItem(ALIAS(alias_name, NONE(), info), env, cls_name);
722 then
723 env;
724
725 // A normal class.
726 case SCode.CLASS(name = cls_name, classDef = cdef)
727 algorithm
728 // Create a new environment and add the class's components to it.
729 2112860 class_env := makeClassEnvironment(inClassDefElement, false);
730 2112856 cls_type := getClassType(cdef);
731 // Add the class with it's environment to the environment.
732 2112856 env := extendEnvWithItem(newClassItem(inClassDefElement, class_env, cls_type),
733 inEnv, cls_name);
734 then
735 env;
736 end match;
737 end extendEnvWithClassDef;
738
739 public function makeClassEnvironment
740 input SCode.Element inClassDefElement;
741 input Boolean inInModifierScope;
742 output Env outClassEnv;
743 protected
744 SCode.ClassDef cdef;
745 String cls_name;
746 Env env, enclosing_env;
747 SourceInfo info;
748 algorithm
749
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2569199 times.
2569199 SCode.CLASS(name = cls_name, classDef = cdef, info = info) := inClassDefElement;
750 2569199 env := openScope(emptyEnv, inClassDefElement);
751
2/2
✓ Branch 0 taken 2172089 times.
✓ Branch 1 taken 397110 times.
2569199 enclosing_env := if inInModifierScope then emptyEnv else env;
752 2569199 outClassEnv :=
753 extendEnvWithClassComponents(cls_name, cdef, env, enclosing_env, info);
754 end makeClassEnvironment;
755
756 protected function extendEnvWithVar
757 "Extends the environment with a variable."
758 input SCode.Element inVar;
759 input Env inEnv;
760 output Env outEnv;
761 protected
762 String var_name;
763 Mutable<Boolean> is_used;
764 Absyn.TypeSpec ty;
765 SourceInfo info;
766 algorithm
767
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8085924 times.
8085924 SCode.COMPONENT(name = var_name, typeSpec = ty, info = info) := inVar;
768 8085924 is_used := Mutable.create(false);
769 8085924 outEnv := extendEnvWithItem(VAR(inVar, SOME(is_used)), inEnv, var_name);
770 end extendEnvWithVar;
771
772 public function extendEnvWithItem
773 "Extends the environment with an environment item."
774 input Item inItem;
775 input Env inEnv;
776 input String inItemName;
777 output Env outEnv;
778 protected
779 Option<String> name;
780 EnvTree.Tree tree;
781 ExtendsTable exts;
782 ImportTable imps;
783 FrameType ty;
784 Env rest;
785 Option<Mutable<Boolean>> is_used;
786 algorithm
787
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10347013 times.
10347013 FRAME(name, ty, tree, exts, imps, is_used) :: rest := inEnv;
788 10347013 tree := EnvTree.add(tree, inItemName, inItem, extendEnvWithItemConflict);
789 10347013 outEnv := FRAME(name, ty, tree, exts, imps, is_used) :: rest;
790 end extendEnvWithItem;
791
792 function extendEnvWithItemConflict
793 input Item newItem;
794 input Item oldItem;
795 input String name;
796 output Item item;
797 algorithm
798 4 item := linkItemUsage(oldItem, newItem);
799 end extendEnvWithItemConflict;
800
801 public function updateItemInEnv
802 "Updates an item in the environment by replacing an existing item."
803 input Item inItem;
804 input Env inEnv;
805 input String inItemName;
806 output Env outEnv;
807 protected
808 Option<String> name;
809 EnvTree.Tree tree;
810 ExtendsTable exts;
811 ImportTable imps;
812 FrameType ty;
813 Env rest;
814 Option<Mutable<Boolean>> is_used;
815 algorithm
816
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 67545 times.
67545 FRAME(name, ty, tree, exts, imps, is_used) :: rest := inEnv;
817 67545 tree := EnvTree.add(tree, inItemName, inItem);
818 67545 outEnv := FRAME(name, ty, tree, exts, imps, is_used) :: rest;
819 end updateItemInEnv;
820
821 protected function extendEnvWithImport
822 "Extends the environment with an import element."
823 input SCode.Element inImport;
824 input Env inEnv;
825 output Env outEnv;
826 algorithm
827 outEnv := match(inImport, inEnv)
828 local
829 Import imp;
830 Option<String> name;
831 EnvTree.Tree tree;
832 ExtendsTable exts;
833 list<Import> qual_imps, unqual_imps;
834 FrameType ty;
835 Env rest;
836 Boolean hidden;
837 Option<Mutable<Boolean>> is_used;
838
839 // Unqualified imports
840 case (SCode.IMPORT(imp = imp as Absyn.UNQUAL_IMPORT()),
841 FRAME(name, ty, tree, exts,
842 IMPORT_TABLE(hidden, qual_imps, unqual_imps), is_used) :: rest)
843 algorithm
844 unqual_imps := imp :: unqual_imps;
845
1/2
✓ Branch 0 taken 105 times.
✗ Branch 1 not taken.
210 then
846 FRAME(name, ty, tree, exts,
847 IMPORT_TABLE(hidden, qual_imps, unqual_imps), is_used) :: rest;
848
849 // Qualified imports
850 case (SCode.IMPORT(imp = imp), FRAME(name, ty, tree, exts,
851 IMPORT_TABLE(hidden, qual_imps, unqual_imps), is_used) :: rest)
852 algorithm
853 127277 imp := translateQualifiedImportToNamed(imp);
854 qual_imps := imp :: qual_imps;
855
1/2
✓ Branch 0 taken 127277 times.
✗ Branch 1 not taken.
254554 then
856 FRAME(name, ty, tree, exts,
857 IMPORT_TABLE(hidden, qual_imps, unqual_imps), is_used) :: rest;
858 end match;
859 end extendEnvWithImport;
860
861 protected function translateQualifiedImportToNamed
862 "Translates a qualified import to a named import."
863 input Import inImport;
864 output Import outImport;
865 algorithm
866 outImport := match inImport
867 local
868 Absyn.Ident name;
869 Absyn.Path path;
870
871 // Already named.
872 case Absyn.NAMED_IMPORT() then inImport;
873
874 // Get the last identifier from the import and use that as the name.
875 case Absyn.QUAL_IMPORT(path = path)
876 algorithm
877 101347 name := AbsynUtil.pathLastIdent(path);
878 101347 then
879 Absyn.NAMED_IMPORT(name, path);
880 end match;
881 end translateQualifiedImportToNamed;
882
883 public function extendEnvWithExtends
884 "Extends the environment with an extends-clause."
885 input SCode.Element inExtends;
886 input Env inEnv;
887 output Env outEnv;
888 protected
889 Absyn.Path bc;
890 SCode.Mod mods;
891 list<Redeclaration> redecls;
892 SourceInfo info;
893 Integer index;
894 algorithm
895
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1098337 times.
1098337 SCode.EXTENDS(baseClassPath = bc, modifications = mods, info = info) :=
896 inExtends;
897 1098337 redecls := NFSCodeFlattenRedeclare.extractRedeclaresFromModifier(mods);
898 1098336 index := System.tmpTickIndex(extendsTickIndex);
899 1098336 outEnv := addExtendsToEnvExtendsTable(EXTENDS(bc, redecls, index, info), inEnv);
900 end extendEnvWithExtends;
901
902 protected function addExtendsToEnvExtendsTable
903 "Adds an Extents to the environment."
904 input Extends inExtends;
905 input Env inEnv;
906 output Env outEnv;
907 protected
908 list<Extends> exts;
909 list<SCode.Element> re;
910 Option<SCode.Element> cei;
911 algorithm
912 1098336 EXTENDS_TABLE(exts, re, cei) := getEnvExtendsTable(inEnv);
913 exts := inExtends :: exts;
914 1098336 outEnv := setEnvExtendsTable(EXTENDS_TABLE(exts, re, cei), inEnv);
915 end addExtendsToEnvExtendsTable;
916
917 protected function addElementRedeclarationToEnvExtendsTable
918 input SCode.Element inRedeclare;
919 input Env inEnv;
920 output Env outEnv;
921 protected
922 list<Extends> exts;
923 list<SCode.Element> re;
924 Option<SCode.Element> cei;
925 algorithm
926 46390 EXTENDS_TABLE(exts, re, cei) := getEnvExtendsTable(inEnv);
927 re := inRedeclare :: re;
928 46390 outEnv := setEnvExtendsTable(EXTENDS_TABLE(exts, re, cei), inEnv);
929 end addElementRedeclarationToEnvExtendsTable;
930
931 protected function extendEnvWithClassComponents
932 "Extends the environment with a class's components."
933 input String inClassName;
934 input SCode.ClassDef inClassDef;
935 input Env inEnv;
936 input Env inEnclosingScope;
937 input SourceInfo inInfo;
938 output Env outEnv;
939 algorithm
940 outEnv := match inClassDef
941 local
942 list<SCode.Element> el;
943 list<SCode.Enum> enums;
944 Absyn.TypeSpec ty;
945 Env env;
946 SCode.Mod mods;
947 Absyn.Path path;
948
949 case SCode.PARTS(elementLst = el)
950 algorithm
951 1987438 env := List.fold(el, extendEnvWithElement, inEnv);
952 then
953 env;
954
955 case SCode.DERIVED(typeSpec = ty as Absyn.TPATH(path = path),
956 modifications = mods)
957 algorithm
958 501298 NFSCodeCheck.checkRecursiveShortDefinition(ty, inClassName,
959 inEnclosingScope, inInfo);
960 501297 env := extendEnvWithExtends(SCode.EXTENDS(path, SCode.PUBLIC(), mods,
961 NONE(), inInfo), inEnv);
962 then
963 env;
964
965 case SCode.ENUMERATION(enumLst = enums)
966 algorithm
967 43622 path := Absyn.IDENT(inClassName);
968 43622 env := extendEnvWithEnumLiterals(enums, path, 1, inEnv, inInfo);
969 then
970 env;
971
972 else inEnv;
973 end match;
974 end extendEnvWithClassComponents;
975
976 protected function extendEnvWithElement
977 "Extends the environment with a class element."
978 input SCode.Element inElement;
979 input Env inEnv;
980 output Env outEnv;
981 algorithm
982 outEnv := matchcontinue inElement
983 local
984 Env env;
985
986 // redeclare-as-element component
987 case SCode.COMPONENT(prefixes = SCode.PREFIXES(redeclarePrefix = SCode.REDECLARE()))
988 algorithm
989 1 env := addElementRedeclarationToEnvExtendsTable(inElement, inEnv);
990 1 env := extendEnvWithVar(inElement, env);
991 then
992 env;
993
994 // normal component
995 case SCode.COMPONENT()
996 algorithm
997 8085923 env := extendEnvWithVar(inElement, inEnv);
998 then
999 env;
1000
1001 // redeclare-as-element class
1002 case SCode.CLASS( prefixes = SCode.PREFIXES(redeclarePrefix = SCode.REDECLARE()))
1003 algorithm
1004 46389 env := addElementRedeclarationToEnvExtendsTable(inElement, inEnv);
1005 46389 env := extendEnvWithClassDef(inElement, env);
1006 then
1007 env;
1008
1009 // normal class
1010 case SCode.CLASS()
1011 algorithm
1012 1932669 env := extendEnvWithClassDef(inElement, inEnv);
1013 then
1014 env;
1015
1016 case SCode.EXTENDS()
1017 algorithm
1018 558258 env := extendEnvWithExtends(inElement, inEnv);
1019 then
1020 env;
1021
1022 case SCode.IMPORT()
1023 algorithm
1024 127382 env := extendEnvWithImport(inElement, inEnv);
1025 then
1026 env;
1027
1028 case SCode.DEFINEUNIT()
1029 then inEnv;
1030
1031 end matchcontinue;
1032 end extendEnvWithElement;
1033
1034 public function checkUniqueQualifiedImport
1035 "Checks that a qualified import is unique, because it's not allowed to have
1036 qualified imports with the same name."
1037 input Import inImport;
1038 input list<Import> inImports;
1039 input SourceInfo inInfo;
1040 algorithm
1041 () := matchcontinue inImport
1042 local
1043 Absyn.Ident name;
1044
1045 case _
1046 algorithm
1047 ✗ false := List.isMemberOnTrue(inImport, inImports,
1048 compareQualifiedImportNames);
1049 then
1050 ();
1051
1052 case Absyn.NAMED_IMPORT(name = name)
1053 algorithm
1054 ✗ Error.addSourceMessage(Error.MULTIPLE_QUALIFIED_IMPORTS_WITH_SAME_NAME,
1055 {name}, inInfo);
1056 ✗ then
1057 fail();
1058
1059 end matchcontinue;
1060 end checkUniqueQualifiedImport;
1061
1062 protected function compareQualifiedImportNames
1063 "Compares two qualified imports, returning true if they have the same import
1064 name, otherwise false."
1065 input Import inImport1;
1066 input Import inImport2;
1067 output Boolean outEqual;
1068 algorithm
1069 outEqual := match(inImport1, inImport2)
1070 local
1071 Absyn.Ident name1, name2;
1072
1073 case (Absyn.NAMED_IMPORT(name = name1), Absyn.NAMED_IMPORT(name = name2)) guard stringEqual(name1, name2)
1074 then
1075 true;
1076
1077 else false;
1078 end match;
1079 end compareQualifiedImportNames;
1080
1081 protected function extendEnvWithEnumLiterals
1082 input list<SCode.Enum> inEnum;
1083 input Absyn.Path inEnumPath;
1084 input Integer inNextValue;
1085 input Env inEnv;
1086 input SourceInfo inInfo;
1087 output Env outEnv;
1088 algorithm
1089 outEnv := match inEnum
1090 local
1091 SCode.Enum lit;
1092 list<SCode.Enum> rest_lits;
1093 Env env;
1094
1095 case lit :: rest_lits
1096 algorithm
1097 200224 env := extendEnvWithEnum(lit, inEnumPath, inNextValue, inEnv, inInfo);
1098 200224 then
1099 extendEnvWithEnumLiterals(rest_lits, inEnumPath, inNextValue + 1, env, inInfo);
1100
1101 case {} then inEnv;
1102
1103 end match;
1104 end extendEnvWithEnumLiterals;
1105
1106 protected function extendEnvWithEnum
1107 "Extends the environment with an enumeration."
1108 input SCode.Enum inEnum;
1109 input Absyn.Path inEnumPath;
1110 input Integer inValue;
1111 input Env inEnv;
1112 input SourceInfo inInfo;
1113 output Env outEnv;
1114 protected
1115 SCode.Element enum_lit;
1116 SCode.Ident lit_name;
1117 Absyn.TypeSpec ty;
1118 String index;
1119 algorithm
1120 200224 SCode.ENUM(literal = lit_name) := inEnum;
1121 200224 index := intString(inValue);
1122 200224 ty := Absyn.TPATH(Absyn.QUALIFIED("$EnumType",
1123 Absyn.QUALIFIED(index, inEnumPath)), NONE());
1124 200224 enum_lit := SCode.COMPONENT(lit_name, SCode.defaultPrefixes, SCode.ATTR({},
1125 SCode.POTENTIAL(), SCode.NON_PARALLEL(), SCode.CONST(), Absyn.BIDIR(),Absyn.NONFIELD()), ty,
1126 SCode.NOMOD(), SCode.noComment, NONE(), inInfo);
1127 200224 outEnv := extendEnvWithElement(enum_lit, inEnv);
1128 end extendEnvWithEnum;
1129
1130 public function extendEnvWithIterators
1131 "Extends the environment with a new scope and adds a list of iterators to it."
1132 input Absyn.ForIterators inIterators;
1133 input Integer iterIndex;
1134 input Env inEnv;
1135 output Env outEnv;
1136 protected
1137 Frame frame;
1138 algorithm
1139 1524 frame := newFrame(SOME("$for$"), IMPLICIT_SCOPE(iterIndex));
1140 1524 outEnv := List.fold(inIterators, extendEnvWithIterator, frame :: inEnv);
1141 end extendEnvWithIterators;
1142
1143 protected function extendEnvWithIterator
1144 "Extends the environment with an iterator."
1145 input Absyn.ForIterator inIterator;
1146 input Env inEnv;
1147 output Env outEnv;
1148 protected
1149 Absyn.Ident iter_name;
1150 SCode.Element iter;
1151 algorithm
1152 1544 Absyn.ITERATOR(name=iter_name) := inIterator;
1153 1544 iter := SCode.COMPONENT(iter_name, SCode.defaultPrefixes,
1154 SCode.ATTR({}, SCode.POTENTIAL(), SCode.NON_PARALLEL(), SCode.CONST(), Absyn.BIDIR(), Absyn.NONFIELD()),
1155 Absyn.TPATH(Absyn.IDENT(""), NONE()), SCode.NOMOD(),
1156 SCode.noComment, NONE(), Absyn.dummyInfo);
1157 1544 outEnv := extendEnvWithElement(iter, inEnv);
1158 end extendEnvWithIterator;
1159
1160 public function extendEnvWithMatch
1161 "Extends the environment with a match-expression, i.e. opens a new scope and
1162 adds the local declarations in the match to it."
1163 input Absyn.Exp inMatchExp;
1164 input Integer iterIndex;
1165 input Env inEnv;
1166 output Env outEnv;
1167 protected
1168 Frame frame;
1169 list<Absyn.ElementItem> local_decls;
1170 algorithm
1171 20 frame := newFrame(SOME("$match$"), IMPLICIT_SCOPE(iterIndex));
1172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 Absyn.MATCHEXP(localDecls = local_decls) := inMatchExp;
1173 20 outEnv := List.fold(local_decls, extendEnvWithElementItem,
1174 frame :: inEnv);
1175 end extendEnvWithMatch;
1176
1177 protected function extendEnvWithElementItem
1178 "Extends the environment with an Absyn.ElementItem."
1179 input Absyn.ElementItem inElementItem;
1180 input Env inEnv;
1181 output Env outEnv;
1182 algorithm
1183 outEnv := match inElementItem
1184 local
1185 Absyn.Element element;
1186 list<SCode.Element> el;
1187 Env env;
1188
1189 case Absyn.ELEMENTITEM(element = element)
1190 algorithm
1191 // Translate the element item to a SCode element.
1192 6 el := AbsynToSCode.translateElement(element, SCode.PROTECTED());
1193 6 env := List.fold(el, extendEnvWithElement, inEnv);
1194 then
1195 env;
1196
1197 else inEnv;
1198 end match;
1199 end extendEnvWithElementItem;
1200
1201 public function getEnvName
1202 "Returns the environment path as a string."
1203 input Env inEnv;
1204 output String outString;
1205 algorithm
1206 outString := matchcontinue inEnv
1207 local
1208 String str;
1209
1210 case _
1211 algorithm
1212 4 str := AbsynUtil.pathString(getEnvPath(inEnv));
1213 then
1214 str;
1215
1216 else "";
1217 end matchcontinue;
1218 end getEnvName;
1219
1220 public function getEnvPath
1221 "Returns the environment path. Fails for an empty environment or the top
1222 scope, which can't be represented as an Absyn.Path."
1223 input Env inEnv;
1224 output Absyn.Path outPath;
1225 algorithm
1226 outPath := match inEnv
1227 local
1228 String name;
1229 Absyn.Path path;
1230 Env rest;
1231
1232 case FRAME(frameType = IMPLICIT_SCOPE()) :: rest
1233 14609 then getEnvPath(rest);
1234
1235 case {FRAME(name = SOME(name))}
1236 104189 then Absyn.IDENT(name);
1237
1238 case {FRAME(name = SOME(name)), FRAME(name = NONE())}
1239 1496045 then Absyn.IDENT(name);
1240
1241 case FRAME(name = SOME(name)) :: rest
1242 algorithm
1243 2810139 path := getEnvPath(rest);
1244 2810139 path := AbsynUtil.joinPaths(path, Absyn.IDENT(name));
1245 then
1246 path;
1247 end match;
1248 end getEnvPath;
1249
1250 public function getScopeName
1251 "Returns the name of the innermost that has a name."
1252 input Env inEnv;
1253 output String outString;
1254 algorithm
1255 outString := match inEnv
1256 local
1257 String name;
1258 Env rest;
1259
1260 case FRAME(name = SOME(name)) :: _ then name;
1261 ✗ case _ :: rest then getScopeName(rest);
1262
1263 end match;
1264 end getScopeName;
1265
1266 public function envPrefixOf
1267 input Env inPrefixEnv;
1268 input Env inEnv;
1269 output Boolean outIsPrefix;
1270 algorithm
1271 57202 outIsPrefix := envPrefixOf2(listReverse(inPrefixEnv), listReverse(inEnv));
1272 end envPrefixOf;
1273
1274 public function envPrefixOf2
1275 "Checks if one environment is a prefix of another."
1276 input Env inPrefixEnv;
1277 input Env inEnv;
1278 output Boolean outIsPrefix;
1279 algorithm
1280 outIsPrefix := match(inPrefixEnv, inEnv)
1281 local
1282 String n1, n2;
1283 Env rest1, rest2;
1284
1285 case ({}, _) then true;
1286
1287 case (FRAME(name = NONE()) :: rest1, FRAME(name = NONE()) :: rest2)
1288 31654 then envPrefixOf2(rest1, rest2);
1289
1290 case (FRAME(name = SOME(n1)) :: rest1, FRAME(name = SOME(n2)) :: rest2) guard stringEqual(n1, n2)
1291 56942 then
1292 envPrefixOf2(rest1, rest2);
1293
1294 else false;
1295 end match;
1296 end envPrefixOf2;
1297
1298 public function envScopeNames
1299 input Env inEnv;
1300 output list<String> outNames;
1301 algorithm
1302 ✗ outNames := envScopeNames2(inEnv, {});
1303 end envScopeNames;
1304
1305 public function envScopeNames2
1306 input Env inEnv;
1307 input list<String> inAccumNames;
1308 output list<String> outNames;
1309 algorithm
1310 outNames := match inEnv
1311 local
1312 String name;
1313 Env rest_env;
1314 list<String> names;
1315
1316 case FRAME(name = SOME(name)) :: rest_env
1317 algorithm
1318 ✗ names := envScopeNames2(rest_env, name :: inAccumNames);
1319 then
1320 names;
1321
1322 case FRAME(name = NONE()) :: rest_env
1323 ✗ then envScopeNames2(rest_env, inAccumNames);
1324
1325 case {} then inAccumNames;
1326
1327 end match;
1328 end envScopeNames2;
1329
1330 public function envEqualPrefix
1331 input Env inEnv1;
1332 input Env inEnv2;
1333 output Env outPrefix;
1334 algorithm
1335 ✗ outPrefix := envEqualPrefix2(listReverse(inEnv1), listReverse(inEnv2), {});
1336 end envEqualPrefix;
1337
1338 public function envEqualPrefix2
1339 input Env inEnv1;
1340 input Env inEnv2;
1341 input Env inAccumEnv;
1342 output Env outPrefix;
1343 algorithm
1344 outPrefix := match(inEnv1, inEnv2)
1345 local
1346 String name1, name2;
1347 Env env, rest_env1, rest_env2;
1348 Frame frame;
1349
1350 case ((frame as FRAME(name = SOME(name1))) :: rest_env1, FRAME(name = SOME(name2)) :: rest_env2) guard stringEq(name1, name2)
1351 algorithm
1352 ✗ env := envEqualPrefix2(rest_env1, rest_env2, frame :: inAccumEnv);
1353 then
1354 env;
1355
1356 case (FRAME(name = NONE()) :: rest_env1, FRAME(name = NONE()) :: rest_env2)
1357 ✗ then envEqualPrefix2(rest_env1, rest_env2, inAccumEnv);
1358
1359 else inAccumEnv;
1360
1361 end match;
1362 end envEqualPrefix2;
1363
1364 public function getItemInfo
1365 "Returns the SourceInfo of an environment item."
1366 input Item inItem;
1367 output SourceInfo outInfo;
1368 algorithm
1369 outInfo := match inItem
1370 local
1371 SourceInfo info;
1372 Item item;
1373
1374 case VAR(var = SCode.COMPONENT(info = info)) then info;
1375 case CLASS(cls = SCode.CLASS(info = info)) then info;
1376 case ALIAS(info = info) then info;
1377 1 case REDECLARED_ITEM(item = item) then getItemInfo(item);
1378 end match;
1379 end getItemInfo;
1380
1381 public function itemStr
1382 "Returns more info on an environment item."
1383 input Item inItem;
1384 output String outName;
1385 algorithm
1386 outName := matchcontinue inItem
1387 local
1388 String name, alias_str;
1389 SCode.Element el;
1390 Absyn.Path path;
1391 Item item;
1392
1393 case VAR(var = el)
1394 ✗ then SCodeDump.unparseElementStr(el,SCodeDump.defaultOptions);
1395 case CLASS(cls = el)
1396 ✗ then SCodeDump.unparseElementStr(el,SCodeDump.defaultOptions);
1397 case ALIAS(name = name, path = SOME(path))
1398 algorithm
1399 ✗ alias_str := AbsynUtil.pathString(path);
1400 ✗ then
1401 "alias " + name + " -> (" + alias_str + "." + name + ")";
1402 case ALIAS(name = name, path = NONE())
1403 ✗ then "alias " + name + " -> ()";
1404 case REDECLARED_ITEM(item = item)
1405 algorithm
1406 ✗ name := itemStr(item);
1407 ✗ then
1408 "redeclared " + name;
1409
1410 else "UNHANDLED ITEM";
1411
1412
1413 end matchcontinue;
1414 end itemStr;
1415
1416 public function getItemName
1417 "Returns the name of an environment item."
1418 input Item inItem;
1419 output String outName;
1420 algorithm
1421 outName := match inItem
1422 local
1423 String name;
1424 Item item;
1425
1426 case VAR(var = SCode.COMPONENT(name = name)) then name;
1427 case CLASS(cls = SCode.CLASS(name = name)) then name;
1428 case ALIAS(name = name) then name;
1429 1230230 case REDECLARED_ITEM(item = item) then getItemName(item);
1430 end match;
1431 end getItemName;
1432
1433 public function getItemEnv
1434 "Returns the environment in an environment item."
1435 input Item inItem;
1436 output Env outEnv;
1437 algorithm
1438 outEnv := match inItem
1439 local
1440 Env env;
1441 Item item;
1442
1443 case CLASS(env = env) then env;
1444 ✗ case REDECLARED_ITEM(item = item) then getItemEnv(item);
1445
1446 end match;
1447 end getItemEnv;
1448
1449 public function getItemEnvNoFail
1450 "Returns the environment in an environment item."
1451 input Item inItem;
1452 output Env outEnv;
1453 algorithm
1454 outEnv := matchcontinue inItem
1455 local
1456 Env env;
1457 Item item;
1458 String str;
1459 Frame f;
1460
1461 case CLASS(env = env) then env;
1462 ✗ case REDECLARED_ITEM(item = item) then getItemEnvNoFail(item);
1463 else
1464 algorithm
1465 ✗ str := "NO ENV FOR ITEM: " + getItemName(inItem);
1466 ✗ f := newFrame(SOME(str), ENCAPSULATED_SCOPE());
1467 env := {f};
1468 then
1469 env;
1470
1471 end matchcontinue;
1472 end getItemEnvNoFail;
1473
1474 public function setItemEnv
1475 "Sets the environment in an environment item."
1476 input Item inItem;
1477 input Env inNewEnv;
1478 output Item outItem;
1479 algorithm
1480 outItem := match inItem
1481 local
1482 Item item;
1483 SCode.Element cls;
1484 ClassType ct;
1485
1486 case CLASS(cls, _, ct)
1487 ✗ then CLASS(cls, inNewEnv, ct);
1488 case REDECLARED_ITEM(item = item)
1489 ✗ then setItemEnv(item, inNewEnv);
1490 end match;
1491 end setItemEnv;
1492
1493 public function mergeItemEnv
1494 "Merges an environment item's environment with the given environment."
1495 input Item inItem;
1496 input Env inEnv;
1497 output Env outEnv;
1498 algorithm
1499 outEnv := match inItem
1500 local
1501 Frame cls_env;
1502 Item item;
1503
1504 11215555 case CLASS(env = {cls_env}) then enterFrame(cls_env, inEnv);
1505 ✗ case REDECLARED_ITEM(item = item) then mergeItemEnv(item, inEnv);
1506 else inEnv;
1507 end match;
1508 end mergeItemEnv;
1509
1510 public function unmergeItemEnv
1511 "Merges an environment item's environment with the given environment."
1512 input Item inItem;
1513 input Env inEnv;
1514 output Env outEnv;
1515 algorithm
1516 outEnv := match inEnv
1517 local
1518 Env env;
1519
1520 case _::env then env;
1521 else inEnv;
1522 end match;
1523 end unmergeItemEnv;
1524
1525 public function getItemPrefixes
1526 input Item inItem;
1527 output SCode.Prefixes outPrefixes;
1528 algorithm
1529 outPrefixes := match inItem
1530 local
1531 SCode.Prefixes pf;
1532 Item item;
1533
1534 case CLASS(cls = SCode.CLASS(prefixes = pf)) then pf;
1535 case VAR(var = SCode.COMPONENT(prefixes = pf)) then pf;
1536 ✗ case REDECLARED_ITEM(item = item) then getItemPrefixes(item);
1537 end match;
1538 end getItemPrefixes;
1539
1540 public function resolveRedeclaredItem
1541 input Item inItem;
1542 input Env inEnv;
1543 output Item outItem;
1544 output Env outEnv;
1545 output list<tuple<Item, Env>> outPreviousItem;
1546 algorithm
1547 (outItem, outEnv, outPreviousItem) := match inItem
1548 local
1549 Item item;
1550 Env env;
1551
1552 152 case REDECLARED_ITEM(item = item, declaredEnv = env) then (item, env, {(inItem, inEnv)});
1553
1554 else (inItem, inEnv, {});
1555
1556 end match;
1557 end resolveRedeclaredItem;
1558
1559 public function getEnvExtendsTable
1560 input Env inEnv;
1561 output ExtendsTable outExtendsTable;
1562 algorithm
1563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2705130 times.
2705130 FRAME(extendsTable = outExtendsTable) :: _ := inEnv;
1564 end getEnvExtendsTable;
1565
1566 public function getEnvExtendsFromTable
1567 input Env inEnv;
1568 output list<Extends> outExtends;
1569 algorithm
1570 17167 EXTENDS_TABLE(baseClasses = outExtends) := getEnvExtendsTable(inEnv);
1571 end getEnvExtendsFromTable;
1572
1573 public function getDerivedClassRedeclares
1574 "@author: adrpo
1575 returns the redeclares inside the extends table for the given class.
1576 The derived class should have only 1 extends"
1577 input SCode.Ident inDerivedName;
1578 input Absyn.TypeSpec inTypeSpec;
1579 input Env inEnv;
1580 output list<Redeclaration> outRedeclarations;
1581 algorithm
1582 outRedeclarations := matchcontinue inTypeSpec
1583 local
1584 Absyn.Path bc, path;
1585 list<Redeclaration> rm;
1586
1587 // only one extends!
1588 case Absyn.TPATH(path, _)
1589 algorithm
1590 ✗ {EXTENDS(baseClass = bc, redeclareModifiers = rm)} :=
1591 getEnvExtendsFromTable(inEnv);
1592 ✗ true := AbsynUtil.pathSuffixOf(path, bc);
1593 then
1594 rm;
1595
1596 case Absyn.TPATH(path, _)
1597 algorithm
1598 ✗ {EXTENDS(baseClass = bc, redeclareModifiers = rm)} :=
1599 getEnvExtendsFromTable(inEnv);
1600 ✗ false := AbsynUtil.pathSuffixOf(path, bc);
1601 ✗ print("Derived paths are not the same: " + AbsynUtil.pathString(path) + " != " + AbsynUtil.pathString(bc) + "\n");
1602 then
1603 rm;
1604
1605 // else nothing
1606 else {};
1607
1608 end matchcontinue;
1609 end getDerivedClassRedeclares;
1610
1611 public function setEnvExtendsTable
1612 input ExtendsTable inExtendsTable;
1613 input Env inEnv;
1614 output Env outEnv;
1615 protected
1616 Option<String> name;
1617 FrameType ty;
1618 EnvTree.Tree tree;
1619 ImportTable imps;
1620 Option<Mutable<Boolean>> is_used;
1621 Env rest_env;
1622 algorithm
1623
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5256690 times.
5256690 FRAME(name, ty, tree, _, imps, is_used) :: rest_env := inEnv;
1624 5256690 outEnv := FRAME(name, ty, tree, inExtendsTable, imps, is_used) :: rest_env;
1625 end setEnvExtendsTable;
1626
1627 public function setEnvClsAndVars
1628 input EnvTree.Tree inTree;
1629 input Env inEnv;
1630 output Env outEnv;
1631 protected
1632 Option<String> name;
1633 FrameType ty;
1634 ExtendsTable ext;
1635 ImportTable imps;
1636 Option<Mutable<Boolean>> is_used;
1637 Env rest_env;
1638 algorithm
1639
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5206911 times.
5206911 FRAME(name, ty, _, ext, imps, is_used) :: rest_env := inEnv;
1640 5206911 outEnv := FRAME(name, ty, inTree, ext, imps, is_used) :: rest_env;
1641 end setEnvClsAndVars;
1642
1643 public function mergePathWithEnvPath
1644 "Merges a path with the environment path."
1645 input Absyn.Path inPath;
1646 input Env inEnv;
1647 output Absyn.Path outPath;
1648 algorithm
1649 outPath := matchcontinue inEnv
1650 local
1651 Absyn.Path env_path;
1652 Absyn.Ident id;
1653
1654 // Try to merge the last identifier in the path with the environment path.
1655 case _
1656 algorithm
1657 1 env_path := getEnvPath(inEnv);
1658 1 id := AbsynUtil.pathLastIdent(inPath);
1659 1 then
1660 AbsynUtil.joinPaths(env_path, Absyn.IDENT(id));
1661
1662 // If the previous case failed (which will happen at the top-scope when
1663 // getEnvPath fails), just return the path as it is.
1664 else inPath;
1665 end matchcontinue;
1666 end mergePathWithEnvPath;
1667
1668 public function mergeTypeSpecWithEnvPath
1669 "Merges a path with the environment path."
1670 input Absyn.TypeSpec inTS;
1671 input Env inEnv;
1672 output Absyn.TypeSpec outTS;
1673 algorithm
1674 outTS := matchcontinue inTS
1675 local
1676 Absyn.Path path;
1677 Absyn.Ident id;
1678 Option<Absyn.ArrayDim> ad;
1679
1680 // Try to merge the last identifier in the path with the environment path.
1681 case Absyn.TPATH(path, ad)
1682 algorithm
1683 ✗ id := AbsynUtil.pathLastIdent(path);
1684 ✗ path := AbsynUtil.joinPaths(getEnvPath(inEnv), Absyn.IDENT(id));
1685 ✗ then
1686 Absyn.TPATH(path, ad);
1687
1688 // If the previous case failed (which will happen at the top-scope when
1689 // getEnvPath fails), just return the path as it is.
1690 else inTS;
1691
1692 end matchcontinue;
1693 end mergeTypeSpecWithEnvPath;
1694
1695 public function prefixIdentWithEnv
1696 input String inIdent;
1697 input Env inEnv;
1698 output Absyn.Path outPath;
1699 algorithm
1700 outPath := match inEnv
1701 local
1702 Absyn.Path path;
1703
1704 5350 case {FRAME(name = NONE())} then Absyn.IDENT(inIdent);
1705 else
1706 algorithm
1707 13633 path := getEnvPath(inEnv);
1708 13633 path := AbsynUtil.suffixPath(path, inIdent);
1709 then
1710 path;
1711
1712 end match;
1713 end prefixIdentWithEnv;
1714
1715 public function getRedeclarationElement
1716 input Redeclaration inRedeclare;
1717 output SCode.Element outElement;
1718 algorithm
1719 outElement := match inRedeclare
1720 local
1721 SCode.Element e;
1722 Item item;
1723
1724 case RAW_MODIFIER(modifier = e) then e;
1725 case PROCESSED_MODIFIER(modifier = CLASS(cls = e)) then e;
1726 case PROCESSED_MODIFIER(modifier = VAR(var = e)) then e;
1727 case PROCESSED_MODIFIER(modifier = REDECLARED_ITEM(item = item))
1728 ✗ then getRedeclarationElement(PROCESSED_MODIFIER(item));
1729 end match;
1730 end getRedeclarationElement;
1731
1732 public function getRedeclarationNameInfo
1733 input Redeclaration inRedeclare;
1734 output String outName;
1735 output SourceInfo outInfo;
1736 algorithm
1737 (outName, outInfo) := match inRedeclare
1738 local
1739 SCode.Element el;
1740 String name;
1741 SourceInfo info;
1742
1743 case PROCESSED_MODIFIER(modifier = ALIAS(name = name, info = info))
1744 773279 then (name, info);
1745
1746 else
1747 algorithm
1748 50195 el := getRedeclarationElement(inRedeclare);
1749 50195 (name, info) := SCodeUtil.elementNameInfo(el);
1750 then
1751 (name, info);
1752
1753 end match;
1754 end getRedeclarationNameInfo;
1755
1756 public function buildInitialEnv
1757 "Build a new environment that contains some things that can't be represented
1758 in ModelicaBuiltin or MetaModelicaBuiltin."
1759 output Env outInitialEnv;
1760 protected
1761 EnvTree.Tree tree;
1762 ExtendsTable exts;
1763 ImportTable imps;
1764 Mutable<Boolean> is_used;
1765 SCode.Program p;
1766 algorithm
1767 2193 tree := EnvTree.new();
1768 exts := newExtendsTable();
1769 imps := newImportTable();
1770 2193 is_used := Mutable.create(false);
1771
1772 2193 tree := addDummyClassToTree("String", tree);
1773 2193 tree := addDummyClassToTree("Integer", tree);
1774 2193 tree := addDummyClassToTree("spliceFunction", tree);
1775
1776 2193 outInitialEnv := {FRAME(NONE(), NORMAL_SCOPE(), tree, exts, imps, SOME(is_used))};
1777
1778 // add the builtin classes from ModelicaBuiltin.mo and MetaModelicaBuiltin.mo
1779 2193 (_,p) := FBuiltin.getInitialFunctions();
1780 2193 outInitialEnv := extendEnvWithClasses(p, outInitialEnv);
1781 end buildInitialEnv;
1782
1783 protected function addDummyClassToTree
1784 "Insert a dummy class into the EnvTree."
1785 input String inName;
1786 input EnvTree.Tree inTree;
1787 output EnvTree.Tree outTree;
1788 protected
1789 SCode.Element cls;
1790 algorithm
1791 6579 cls := SCode.CLASS(inName, SCode.defaultPrefixes, SCode.NOT_ENCAPSULATED(), SCode.NOT_PARTIAL(), SCode.R_CLASS(),
1792 SCode.PARTS({}, {}, {}, {}, {}, {}, {}, NONE()), SCode.noComment, Absyn.dummyInfo);
1793 6579 outTree := EnvTree.add(inTree, inName, CLASS(cls, emptyEnv, BUILTIN()));
1794 end addDummyClassToTree;
1795
1796 public function printEnvStr
1797 input Env inEnv;
1798 output String outString;
1799 protected
1800 Env env;
1801 algorithm
1802 ✗ env := listReverse(inEnv);
1803 ✗ outString := stringDelimitList(List.map(env, printFrameStr), "\n");
1804 end printEnvStr;
1805
1806 protected function printFrameStr
1807 input Frame inFrame;
1808 output String outString;
1809 algorithm
1810 outString := match inFrame
1811 local
1812 Option<String> name;
1813 FrameType ty;
1814 EnvTree.Tree tree;
1815 ExtendsTable exts;
1816 ImportTable imps;
1817 String name_str, ty_str, tree_str, ext_str, imp_str, out;
1818
1819 case FRAME(name, ty, tree, exts, imps, _)
1820 algorithm
1821 ✗ name_str := printFrameNameStr(name);
1822 ✗ ty_str := printFrameTypeStr(ty);
1823 ✗ tree_str := EnvTree.printTreeStr(tree);
1824 ✗ ext_str := printExtendsTableStr(exts);
1825 ✗ imp_str := printImportTableStr(imps);
1826 ✗ name_str := "<<<" + ty_str + " frame " + name_str + ">>>\n";
1827 ✗ out := name_str +
1828 "\tImports:\n" + imp_str +
1829 "\n\tExtends:\n" + ext_str +
1830 "\n\tComponents:\n" + tree_str + "\n";
1831 then
1832 out;
1833 end match;
1834 end printFrameStr;
1835
1836 protected function printFrameNameStr
1837 input Option<String> inFrame;
1838 output String outString;
1839 algorithm
1840 outString := match inFrame
1841 local
1842 String name;
1843
1844 case NONE() then "global";
1845 case SOME(name) then name;
1846 end match;
1847 end printFrameNameStr;
1848
1849 protected function printFrameTypeStr
1850 input FrameType inFrame;
1851 output String outString;
1852 algorithm
1853 outString := match inFrame
1854 case NORMAL_SCOPE() then "Normal";
1855 case ENCAPSULATED_SCOPE() then "Encapsulated";
1856 case IMPLICIT_SCOPE() then "Implicit";
1857 end match;
1858 end printFrameTypeStr;
1859
1860 public function printExtendsTableStr
1861 input ExtendsTable inExtendsTable;
1862 output String outString;
1863 protected
1864 list<Extends> bcl;
1865 list<SCode.Element> re;
1866 Option<SCode.Element> cei;
1867 algorithm
1868 ✗ EXTENDS_TABLE(baseClasses = bcl, redeclaredElements = re, classExtendsInfo = cei) := inExtendsTable;
1869 ✗ outString := stringDelimitList(List.map(bcl, printExtendsStr), "\n") +
1870 "\n\t\tRedeclare elements:\n\t\t\t" +
1871 stringDelimitList(List.map1(re, SCodeDump.unparseElementStr, SCodeDump.defaultOptions), "\n\t\t\t") +
1872 "\n\t\tClass extends:\n\t\t\t" +
1873 Util.applyOptionOrDefault(cei, function SCodeDump.unparseElementStr(options = SCodeDump.defaultOptions), "");
1874 end printExtendsTableStr;
1875
1876 public function printExtendsStr
1877 input Extends inExtends;
1878 output String outString;
1879 protected
1880 Absyn.Path bc;
1881 list<Redeclaration> mods;
1882 String mods_str;
1883 algorithm
1884 ✗ EXTENDS(baseClass = bc, redeclareModifiers = mods) := inExtends;
1885 ✗ mods_str := stringDelimitList(
1886 List.map(mods, printRedeclarationStr), "\n");
1887 ✗ outString := "\t\t" + AbsynUtil.pathString(bc) + "(" + mods_str + ")";
1888 end printExtendsStr;
1889
1890 public function printRedeclarationStr
1891 input Redeclaration inRedeclare;
1892 output String outString;
1893 algorithm
1894 outString := matchcontinue inRedeclare
1895 local String name; Absyn.Path p;
1896 case PROCESSED_MODIFIER(modifier = ALIAS(name = name, path = SOME(p)))
1897 ✗ then "ALIAS(" + AbsynUtil.pathString(p) + "." + name + ")";
1898 case PROCESSED_MODIFIER(modifier = ALIAS(name = name))
1899 ✗ then "ALIAS(" + name + ")";
1900 ✗ else SCodeDump.unparseElementStr(getRedeclarationElement(inRedeclare),SCodeDump.defaultOptions);
1901 end matchcontinue;
1902 end printRedeclarationStr;
1903
1904 protected function printImportTableStr
1905 input ImportTable inImports;
1906 output String outString;
1907 protected
1908 list<Import> qual_imps, unqual_imps;
1909 String qual_str, unqual_str;
1910 algorithm
1911 ✗ IMPORT_TABLE(qualifiedImports = qual_imps, unqualifiedImports = unqual_imps)
1912 := inImports;
1913 ✗ qual_str := stringDelimitList(
1914 List.map(qual_imps, AbsynUtil.printImportString), "\n\t\t");
1915 ✗ unqual_str := stringDelimitList(
1916 List.map(unqual_imps, AbsynUtil.printImportString), "\n\t\t");
1917 ✗ outString := "\t\t" + qual_str + unqual_str;
1918 end printImportTableStr;
1919
1920 annotation(__OpenModelica_Interface="frontend");
1921 end NFSCodeEnv;
1922