Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 81.4% 158 / 0 / 194
Functions: -% 0 / 1 / 1
Branches: 54.9% 89 / 0 / 162

OMCompiler/Compiler/FrontEnd/NFSCodeLookup.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 NFSCodeLookup
37 " file: NFSCodeLookup.mo
38 package: NFSCodeLookup
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 public import Absyn;
47 public import AbsynUtil;
48 public import ErrorTypes;
49 public import NFInstPrefix;
50 public import SCode;
51 public import NFSCodeEnv;
52
53 protected
54 import Config;
55 import Debug;
56 import Error;
57 import Flags;
58 import List;
59 import NFEnvExtends;
60 import NFSCodeFlattenImports;
61 import NFSCodeFlattenRedeclare;
62
63 import NFSCodeEnv.EnvTree;
64
65 public type Env = NFSCodeEnv.Env;
66 public type Item = NFSCodeEnv.Item;
67 public type Extends = NFSCodeEnv.Extends;
68 public type Frame = NFSCodeEnv.Frame;
69 public type FrameType = NFSCodeEnv.FrameType;
70 public type Import = Absyn.Import;
71
72 public uniontype RedeclareReplaceStrategy
73 record INSERT_REDECLARES end INSERT_REDECLARES;
74 record IGNORE_REDECLARES end IGNORE_REDECLARES;
75 end RedeclareReplaceStrategy;
76
77 public uniontype LookupStrategy
78 record NO_BUILTIN_TYPES end NO_BUILTIN_TYPES;
79 record LOOKUP_ANY end LOOKUP_ANY;
80 end LookupStrategy;
81
82 // Default parts of the declarations for builtin elements and types.
83 public constant SCode.Prefixes BUILTIN_PREFIXES = SCode.PREFIXES(
84 SCode.PUBLIC(), SCode.NOT_REDECLARE(), SCode.NOT_FINAL(),
85 Absyn.NOT_INNER_OUTER(), SCode.NOT_REPLACEABLE());
86
87 public constant SCode.Attributes BUILTIN_ATTRIBUTES = SCode.ATTR(
88 {}, SCode.POTENTIAL(), SCode.NON_PARALLEL(), SCode.VAR(), Absyn.BIDIR(), Absyn.NONFIELD());
89
90 public constant SCode.Attributes BUILTIN_CONST_ATTRIBUTES = SCode.ATTR(
91 {}, SCode.POTENTIAL(), SCode.NON_PARALLEL(), SCode.CONST(), Absyn.BIDIR(), Absyn.NONFIELD());
92
93 public constant SCode.ClassDef BUILTIN_EMPTY_CLASS = SCode.PARTS(
94 {}, {}, {}, {}, {}, {}, {}, NONE());
95
96
97 // Metatypes used to define the builtin types.
98 public constant SCode.Element BUILTIN_REALTYPE = SCode.CLASS(
99 "$RealType", BUILTIN_PREFIXES, SCode.NOT_ENCAPSULATED(), SCode.NOT_PARTIAL(),
100 SCode.R_PREDEFINED_REAL(), BUILTIN_EMPTY_CLASS, SCode.noComment, Absyn.dummyInfo);
101
102 public constant SCode.Element BUILTIN_INTEGERTYPE = SCode.CLASS(
103 "$IntegerType", BUILTIN_PREFIXES, SCode.NOT_ENCAPSULATED(), SCode.NOT_PARTIAL(),
104 SCode.R_PREDEFINED_INTEGER(), BUILTIN_EMPTY_CLASS, SCode.noComment, Absyn.dummyInfo);
105
106 public constant SCode.Element BUILTIN_BOOLEANTYPE = SCode.CLASS(
107 "$BooleanType", BUILTIN_PREFIXES, SCode.NOT_ENCAPSULATED(), SCode.NOT_PARTIAL(),
108 SCode.R_PREDEFINED_BOOLEAN(), BUILTIN_EMPTY_CLASS, SCode.noComment, Absyn.dummyInfo);
109
110 public constant SCode.Element BUILTIN_STRINGTYPE = SCode.CLASS(
111 "$StringType", BUILTIN_PREFIXES, SCode.NOT_ENCAPSULATED(), SCode.NOT_PARTIAL(),
112 SCode.R_PREDEFINED_STRING(), BUILTIN_EMPTY_CLASS, SCode.noComment, Absyn.dummyInfo);
113
114 public constant SCode.Element BUILTIN_ENUMTYPE = SCode.CLASS(
115 "$EnumType", BUILTIN_PREFIXES, SCode.NOT_ENCAPSULATED(), SCode.NOT_PARTIAL(),
116 SCode.R_PREDEFINED_ENUMERATION(), BUILTIN_EMPTY_CLASS, SCode.noComment, Absyn.dummyInfo);
117
118 public constant Item BUILTIN_REALTYPE_ITEM =
119 NFSCodeEnv.VAR(BUILTIN_REALTYPE, NONE());
120 public constant Item BUILTIN_INTEGERTYPE_ITEM =
121 NFSCodeEnv.VAR(BUILTIN_INTEGERTYPE, NONE());
122 public constant Item BUILTIN_BOOLEANTYPE_ITEM =
123 NFSCodeEnv.VAR(BUILTIN_BOOLEANTYPE, NONE());
124 public constant Item BUILTIN_STRINGTYPE_ITEM =
125 NFSCodeEnv.VAR(BUILTIN_STRINGTYPE, NONE());
126 public constant Item BUILTIN_ENUMTYPE_ITEM =
127 NFSCodeEnv.VAR(BUILTIN_ENUMTYPE, NONE());
128
129 public constant Absyn.TypeSpec BUILTIN_REALTYPE_SPEC =
130 Absyn.TPATH(Absyn.IDENT("$RealType"), NONE());
131 public constant Absyn.TypeSpec BUILTIN_INTEGERTYPE_SPEC =
132 Absyn.TPATH(Absyn.IDENT("$IntegerType"), NONE());
133 public constant Absyn.TypeSpec BUILTIN_BOOLEANTYPE_SPEC =
134 Absyn.TPATH(Absyn.IDENT("$BooleanType"), NONE());
135 public constant Absyn.TypeSpec BUILTIN_STRINGTYPE_SPEC =
136 Absyn.TPATH(Absyn.IDENT("$StringType"), NONE());
137 public constant Absyn.TypeSpec BUILTIN_ENUMTYPE_SPEC =
138 Absyn.TPATH(Absyn.IDENT("$EnumType"), NONE());
139 public constant Absyn.TypeSpec BUILTIN_STATESELECT_SPEC =
140 Absyn.TPATH(Absyn.IDENT("StateSelect"), NONE());
141
142 // Parts of the builtin types.
143 // Generic elements:
144 public constant SCode.Element BUILTIN_ATTR_QUANTITY = SCode.COMPONENT(
145 "quantity", BUILTIN_PREFIXES, BUILTIN_ATTRIBUTES, BUILTIN_STRINGTYPE_SPEC,
146 SCode.NOMOD(), SCode.noComment, NONE(), Absyn.dummyInfo);
147
148 public constant SCode.Element BUILTIN_ATTR_UNIT = SCode.COMPONENT(
149 "unit", BUILTIN_PREFIXES, BUILTIN_ATTRIBUTES, BUILTIN_STRINGTYPE_SPEC,
150 SCode.NOMOD(), SCode.noComment, NONE(), Absyn.dummyInfo);
151
152 public constant SCode.Element BUILTIN_ATTR_DISPLAYUNIT = SCode.COMPONENT(
153 "displayUnit", BUILTIN_PREFIXES, BUILTIN_ATTRIBUTES, BUILTIN_STRINGTYPE_SPEC,
154 SCode.NOMOD(), SCode.noComment, NONE(), Absyn.dummyInfo);
155
156 public constant SCode.Element BUILTIN_ATTR_FIXED = SCode.COMPONENT(
157 "fixed", BUILTIN_PREFIXES, BUILTIN_ATTRIBUTES, BUILTIN_BOOLEANTYPE_SPEC,
158 SCode.NOMOD(), SCode.noComment, NONE(), Absyn.dummyInfo);
159
160 public constant SCode.Element BUILTIN_ATTR_STATESELECT = SCode.COMPONENT(
161 "stateSelect", BUILTIN_PREFIXES, BUILTIN_ATTRIBUTES, BUILTIN_STATESELECT_SPEC,
162 SCode.NOMOD(), SCode.noComment, NONE(), Absyn.dummyInfo);
163
164 // Real-specific elements:
165 public constant SCode.Element BUILTIN_REAL_MIN = SCode.COMPONENT(
166 "min", BUILTIN_PREFIXES, BUILTIN_ATTRIBUTES, BUILTIN_REALTYPE_SPEC,
167 SCode.NOMOD(), SCode.noComment, NONE(), Absyn.dummyInfo);
168
169 public constant SCode.Element BUILTIN_REAL_MAX = SCode.COMPONENT(
170 "max", BUILTIN_PREFIXES, BUILTIN_ATTRIBUTES, BUILTIN_REALTYPE_SPEC,
171 SCode.NOMOD(), SCode.noComment, NONE(), Absyn.dummyInfo);
172
173 public constant SCode.Element BUILTIN_REAL_START = SCode.COMPONENT(
174 "start", BUILTIN_PREFIXES, BUILTIN_ATTRIBUTES, BUILTIN_REALTYPE_SPEC,
175 SCode.NOMOD(), SCode.noComment, NONE(), Absyn.dummyInfo);
176
177 public constant SCode.Element BUILTIN_REAL_NOMINAL = SCode.COMPONENT(
178 "nominal", BUILTIN_PREFIXES, BUILTIN_ATTRIBUTES, BUILTIN_REALTYPE_SPEC,
179 SCode.NOMOD(), SCode.noComment, NONE(), Absyn.dummyInfo);
180
181 // Integer-specific elements:
182 public constant SCode.Element BUILTIN_INTEGER_MIN = SCode.COMPONENT(
183 "min", BUILTIN_PREFIXES, BUILTIN_ATTRIBUTES, BUILTIN_INTEGERTYPE_SPEC,
184 SCode.NOMOD(), SCode.noComment, NONE(), Absyn.dummyInfo);
185
186 public constant SCode.Element BUILTIN_INTEGER_MAX = SCode.COMPONENT(
187 "max", BUILTIN_PREFIXES, BUILTIN_ATTRIBUTES, BUILTIN_INTEGERTYPE_SPEC,
188 SCode.NOMOD(), SCode.noComment, NONE(), Absyn.dummyInfo);
189
190 public constant SCode.Element BUILTIN_INTEGER_START = SCode.COMPONENT(
191 "start", BUILTIN_PREFIXES, BUILTIN_ATTRIBUTES, BUILTIN_INTEGERTYPE_SPEC,
192 SCode.NOMOD(), SCode.noComment, NONE(), Absyn.dummyInfo);
193
194 // Boolean-specific elements:
195 public constant SCode.Element BUILTIN_BOOLEAN_START = SCode.COMPONENT(
196 "start", BUILTIN_PREFIXES, BUILTIN_ATTRIBUTES, BUILTIN_BOOLEANTYPE_SPEC,
197 SCode.NOMOD(), SCode.noComment, NONE(), Absyn.dummyInfo);
198
199 // String-specific elements:
200 public constant SCode.Element BUILTIN_STRING_START = SCode.COMPONENT(
201 "start", BUILTIN_PREFIXES, BUILTIN_ATTRIBUTES, BUILTIN_STRINGTYPE_SPEC,
202 SCode.NOMOD(), SCode.noComment, NONE(), Absyn.dummyInfo);
203
204 // StateSelect-specific elements:
205 public constant SCode.Element BUILTIN_ENUM_MIN = SCode.COMPONENT(
206 "min", BUILTIN_PREFIXES, BUILTIN_ATTRIBUTES, BUILTIN_ENUMTYPE_SPEC,
207 SCode.NOMOD(), SCode.noComment, NONE(), Absyn.dummyInfo);
208
209 public constant SCode.Element BUILTIN_ENUM_MAX = SCode.COMPONENT(
210 "max", BUILTIN_PREFIXES, BUILTIN_ATTRIBUTES, BUILTIN_ENUMTYPE_SPEC,
211 SCode.NOMOD(), SCode.noComment, NONE(), Absyn.dummyInfo);
212
213 public constant SCode.Element BUILTIN_ENUM_START = SCode.COMPONENT(
214 "start", BUILTIN_PREFIXES, BUILTIN_ATTRIBUTES, BUILTIN_ENUMTYPE_SPEC,
215 SCode.NOMOD(), SCode.noComment, NONE(), Absyn.dummyInfo);
216
217 public constant SCode.Element BUILTIN_STATESELECT_NEVER = SCode.COMPONENT(
218 "never", BUILTIN_PREFIXES, BUILTIN_CONST_ATTRIBUTES, BUILTIN_ENUMTYPE_SPEC,
219 SCode.NOMOD(), SCode.noComment, NONE(), Absyn.dummyInfo);
220
221 public constant SCode.Element BUILTIN_STATESELECT_AVOID = SCode.COMPONENT(
222 "avoid", BUILTIN_PREFIXES, BUILTIN_CONST_ATTRIBUTES, BUILTIN_ENUMTYPE_SPEC,
223 SCode.NOMOD(), SCode.noComment, NONE(), Absyn.dummyInfo);
224
225 public constant SCode.Element BUILTIN_STATESELECT_DEFAULT = SCode.COMPONENT(
226 "default", BUILTIN_PREFIXES, BUILTIN_CONST_ATTRIBUTES, BUILTIN_ENUMTYPE_SPEC,
227 SCode.NOMOD(), SCode.noComment, NONE(), Absyn.dummyInfo);
228
229 public constant SCode.Element BUILTIN_STATESELECT_PREFER = SCode.COMPONENT(
230 "prefer", BUILTIN_PREFIXES, BUILTIN_CONST_ATTRIBUTES, BUILTIN_ENUMTYPE_SPEC,
231 SCode.NOMOD(), SCode.noComment, NONE(), Absyn.dummyInfo);
232
233 public constant SCode.Element BUILTIN_STATESELECT_ALWAYS = SCode.COMPONENT(
234 "always", BUILTIN_PREFIXES, BUILTIN_CONST_ATTRIBUTES, BUILTIN_ENUMTYPE_SPEC,
235 SCode.NOMOD(), SCode.noComment, NONE(), Absyn.dummyInfo);
236
237
238 // Environments for the builtin types:
239 public constant Env BUILTIN_REAL_ENV = {NFSCodeEnv.FRAME(SOME("Real"),
240 NFSCodeEnv.NORMAL_SCOPE(),
241 NFSCodeEnv.EnvTree.Tree.NODE("nominal",
242 NFSCodeEnv.VAR(BUILTIN_REAL_NOMINAL, NONE()), 3,
243 NFSCodeEnv.EnvTree.Tree.NODE("max",
244 NFSCodeEnv.VAR(BUILTIN_REAL_MAX, NONE()), 2,
245 NFSCodeEnv.EnvTree.Tree.NODE("fixed",
246 NFSCodeEnv.VAR(BUILTIN_ATTR_FIXED, NONE()), 1,
247 NFSCodeEnv.EnvTree.Tree.LEAF("displayUnit",
248 NFSCodeEnv.VAR(BUILTIN_ATTR_DISPLAYUNIT, NONE())),
249 NFSCodeEnv.EnvTree.Tree.EMPTY()),
250 NFSCodeEnv.EnvTree.Tree.LEAF("min",
251 NFSCodeEnv.VAR(BUILTIN_REAL_MIN, NONE()))),
252 NFSCodeEnv.EnvTree.Tree.NODE("start",
253 NFSCodeEnv.VAR(BUILTIN_REAL_START, NONE()), 2,
254 NFSCodeEnv.EnvTree.Tree.LEAF("quantity",
255 NFSCodeEnv.VAR(BUILTIN_ATTR_QUANTITY, NONE())),
256 NFSCodeEnv.EnvTree.Tree.NODE("stateSelect",
257 NFSCodeEnv.VAR(BUILTIN_ATTR_STATESELECT, NONE()), 1,
258 NFSCodeEnv.EnvTree.Tree.EMPTY(),
259 NFSCodeEnv.EnvTree.Tree.LEAF("unit",
260 NFSCodeEnv.VAR(BUILTIN_ATTR_UNIT, NONE()))))),
261 NFSCodeEnv.EXTENDS_TABLE({}, {}, NONE()), NFSCodeEnv.IMPORT_TABLE(false, {}, {}), NONE())};
262
263 public constant Env BUILTIN_INTEGER_ENV = {NFSCodeEnv.FRAME(SOME("Integer"),
264 NFSCodeEnv.NORMAL_SCOPE(),
265 NFSCodeEnv.EnvTree.Tree.NODE("quantity",
266 NFSCodeEnv.VAR(BUILTIN_ATTR_QUANTITY, NONE()), 2,
267 NFSCodeEnv.EnvTree.Tree.NODE("max",
268 NFSCodeEnv.VAR(BUILTIN_INTEGER_MAX, NONE()), 1,
269 NFSCodeEnv.EnvTree.Tree.LEAF("fixed",
270 NFSCodeEnv.VAR(BUILTIN_ATTR_FIXED, NONE())),
271 NFSCodeEnv.EnvTree.Tree.LEAF("min",
272 NFSCodeEnv.VAR(BUILTIN_INTEGER_MIN, NONE()))),
273 NFSCodeEnv.EnvTree.Tree.LEAF("start",
274 NFSCodeEnv.VAR(BUILTIN_INTEGER_START, NONE()))),
275 NFSCodeEnv.EXTENDS_TABLE({}, {}, NONE()), NFSCodeEnv.IMPORT_TABLE(false, {}, {}), NONE())};
276
277 public constant Env BUILTIN_BOOLEAN_ENV = {NFSCodeEnv.FRAME(SOME("Boolean"),
278 NFSCodeEnv.NORMAL_SCOPE(),
279 NFSCodeEnv.EnvTree.Tree.NODE("quantity",
280 NFSCodeEnv.VAR(BUILTIN_ATTR_QUANTITY, NONE()), 1,
281 NFSCodeEnv.EnvTree.Tree.LEAF("fixed",
282 NFSCodeEnv.VAR(BUILTIN_ATTR_FIXED, NONE())),
283 NFSCodeEnv.EnvTree.Tree.LEAF("start",
284 NFSCodeEnv.VAR(BUILTIN_BOOLEAN_START, NONE()))),
285 NFSCodeEnv.EXTENDS_TABLE({}, {}, NONE()), NFSCodeEnv.IMPORT_TABLE(false, {}, {}), NONE())};
286
287 public constant Env BUILTIN_STRING_ENV = {NFSCodeEnv.FRAME(SOME("String"),
288 NFSCodeEnv.NORMAL_SCOPE(),
289 NFSCodeEnv.EnvTree.Tree.NODE("quantity",
290 NFSCodeEnv.VAR(BUILTIN_ATTR_QUANTITY, NONE()), 2,
291 NFSCodeEnv.EnvTree.Tree.EMPTY(),
292 NFSCodeEnv.EnvTree.Tree.LEAF("start",
293 NFSCodeEnv.VAR(BUILTIN_STRING_START, NONE()))),
294 NFSCodeEnv.EXTENDS_TABLE({}, {}, NONE()), NFSCodeEnv.IMPORT_TABLE(false, {}, {}), NONE())};
295
296 public constant Env BUILTIN_STATESELECT_ENV = {NFSCodeEnv.FRAME(SOME("StateSelect"),
297 NFSCodeEnv.NORMAL_SCOPE(),
298 NFSCodeEnv.EnvTree.Tree.NODE("max",
299 NFSCodeEnv.VAR(BUILTIN_ENUM_MAX, NONE()), 3,
300 NFSCodeEnv.EnvTree.Tree.NODE("default",
301 NFSCodeEnv.VAR(BUILTIN_STATESELECT_DEFAULT, NONE()), 2,
302 NFSCodeEnv.EnvTree.Tree.NODE("avoid",
303 NFSCodeEnv.VAR(BUILTIN_STATESELECT_AVOID, NONE()), 1,
304 NFSCodeEnv.EnvTree.Tree.LEAF("always",
305 NFSCodeEnv.VAR(BUILTIN_STATESELECT_ALWAYS, NONE())),
306 NFSCodeEnv.EnvTree.Tree.EMPTY()),
307 NFSCodeEnv.EnvTree.Tree.LEAF("fixed",
308 NFSCodeEnv.VAR(BUILTIN_ATTR_FIXED, NONE()))),
309 NFSCodeEnv.EnvTree.Tree.NODE("never",
310 NFSCodeEnv.VAR(BUILTIN_STATESELECT_NEVER, NONE()), 2,
311 NFSCodeEnv.EnvTree.Tree.LEAF("min",
312 NFSCodeEnv.VAR(BUILTIN_ENUM_MIN, NONE())),
313 NFSCodeEnv.EnvTree.Tree.NODE("quantity",
314 NFSCodeEnv.VAR(BUILTIN_ATTR_QUANTITY, NONE()), 1,
315 NFSCodeEnv.EnvTree.Tree.LEAF("prefer",
316 NFSCodeEnv.VAR(BUILTIN_STATESELECT_PREFER, NONE())),
317 NFSCodeEnv.EnvTree.Tree.LEAF("start",
318 NFSCodeEnv.VAR(BUILTIN_ENUM_START, NONE()))))),
319 NFSCodeEnv.EXTENDS_TABLE({}, {}, NONE()), NFSCodeEnv.IMPORT_TABLE(false, {}, {}), NONE())};
320
321 // The builtin types:
322 public constant Item BUILTIN_REAL = NFSCodeEnv.CLASS(
323 SCode.CLASS("Real", SCode.defaultPrefixes,
324 SCode.NOT_ENCAPSULATED(), SCode.NOT_PARTIAL(), SCode.R_TYPE(),
325 SCode.PARTS({}, {}, {}, {}, {}, {}, {}, NONE()),
326 SCode.noComment, Absyn.dummyInfo), BUILTIN_REAL_ENV, NFSCodeEnv.BASIC_TYPE());
327
328 public constant Item BUILTIN_INTEGER = NFSCodeEnv.CLASS(
329 SCode.CLASS("Integer", SCode.defaultPrefixes,
330 SCode.NOT_ENCAPSULATED(), SCode.NOT_PARTIAL(), SCode.R_TYPE(),
331 SCode.PARTS({}, {}, {}, {}, {}, {}, {}, NONE()),
332 SCode.noComment, Absyn.dummyInfo), BUILTIN_INTEGER_ENV, NFSCodeEnv.BASIC_TYPE());
333
334 public constant Item BUILTIN_BOOLEAN = NFSCodeEnv.CLASS(
335 SCode.CLASS("Boolean", SCode.defaultPrefixes,
336 SCode.NOT_ENCAPSULATED(), SCode.NOT_PARTIAL(), SCode.R_TYPE(),
337 SCode.PARTS({}, {}, {}, {}, {}, {}, {}, NONE()),
338 SCode.noComment, Absyn.dummyInfo), BUILTIN_BOOLEAN_ENV, NFSCodeEnv.BASIC_TYPE());
339
340 public constant Item BUILTIN_STRING = NFSCodeEnv.CLASS(
341 SCode.CLASS("String", SCode.defaultPrefixes,
342 SCode.NOT_ENCAPSULATED(), SCode.NOT_PARTIAL(), SCode.R_TYPE(),
343 SCode.PARTS({}, {}, {}, {}, {}, {}, {}, NONE()),
344 SCode.noComment, Absyn.dummyInfo), BUILTIN_STRING_ENV, NFSCodeEnv.BASIC_TYPE());
345
346 public constant Item BUILTIN_STATESELECT = NFSCodeEnv.CLASS(
347 SCode.CLASS("StateSelect", SCode.defaultPrefixes,
348 SCode.NOT_ENCAPSULATED(), SCode.NOT_PARTIAL(), SCode.R_CLASS(),
349 SCode.ENUMERATION({
350 SCode.ENUM("never", SCode.noComment),
351 SCode.ENUM("avoid", SCode.noComment),
352 SCode.ENUM("default", SCode.noComment),
353 SCode.ENUM("prefer", SCode.noComment),
354 SCode.ENUM("always", SCode.noComment)}),
355 SCode.noComment, Absyn.dummyInfo), BUILTIN_STATESELECT_ENV, NFSCodeEnv.BASIC_TYPE());
356
357 public constant Item BUILTIN_EXTERNALOBJECT = NFSCodeEnv.CLASS(
358 SCode.CLASS("ExternalObject", SCode.defaultPrefixes,
359 SCode.NOT_ENCAPSULATED(), SCode.PARTIAL(), SCode.R_CLASS(),
360 SCode.PARTS({}, {}, {}, {}, {}, {}, {}, NONE()),
361 SCode.noComment, Absyn.dummyInfo), NFSCodeEnv.emptyEnv, NFSCodeEnv.BASIC_TYPE());
362
363 public constant Item BUILTIN_CLOCK = NFSCodeEnv.CLASS(
364 SCode.CLASS("Clock", SCode.defaultPrefixes,
365 SCode.NOT_ENCAPSULATED(), SCode.PARTIAL(), SCode.R_CLASS(),
366 SCode.PARTS({}, {}, {}, {}, {}, {}, {}, NONE()),
367 SCode.noComment, Absyn.dummyInfo), NFSCodeEnv.emptyEnv, NFSCodeEnv.BASIC_TYPE());
368
369 public function lookupSimpleName
370 "Looks up a simple identifier in the environment and returns the environment
371 item, the path, and the enclosing scope of the name."
372 input Absyn.Ident inName;
373 input Env inEnv;
374 output Item outItem;
375 output Absyn.Path outPath;
376 output Env outEnv;
377 algorithm
378
8/14
✗ Branch 1 not taken.
✓ Branch 2 taken 950572 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 950572 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 950572 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 950572 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 950572 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 950572 times.
✓ Branch 16 taken 949712 times.
✓ Branch 17 taken 860 times.
977932 (SOME(outItem), SOME(outPath), SOME(outEnv)) :=
379 lookupSimpleName2(inName, inEnv, {});
380 end lookupSimpleName;
381
382 protected function lookupSimpleName2
383 "Helper function to lookupSimpleName. Looks up a simple identifier in the
384 environment."
385 input Absyn.Ident inName;
386 input Env inEnv;
387 input list<String> inVisitedScopes;
388 output Option<Item> outItem;
389 output Option<Absyn.Path> outPath;
390 output Option<Env> outEnv;
391 algorithm
392 (outItem, outPath, outEnv) := matchcontinue inEnv
393 local
394 FrameType frame_type;
395 Env rest_env;
396 Option<Item> opt_item;
397 Option<Absyn.Path> opt_path;
398 Option<Env> opt_env;
399 String scope_name;
400
401 // Check the local scope.
402 case _
403 algorithm
404 1840861 (opt_item, opt_path, opt_env) :=
405 lookupInLocalScope(inName, inEnv, inVisitedScopes);
406 then
407 (opt_item, opt_path, opt_env);
408
409 // If not found in the local scope, check the next frame unless the current
410 // frame is encapsulated.
411 case NFSCodeEnv.FRAME(name = SOME(scope_name), frameType = frame_type) ::
412 rest_env
413 algorithm
414 862929 frameNotEncapsulated(frame_type);
415 861675 (opt_item, opt_path, opt_env) :=
416 lookupSimpleName2(inName, rest_env, scope_name :: inVisitedScopes);
417 then
418 (opt_item, opt_path, opt_env);
419
420 // If the current frame is encapsulated, check for builtin types and
421 // functions in the top scope.
422 case NFSCodeEnv.FRAME(frameType = NFSCodeEnv.ENCAPSULATED_SCOPE()) ::
423 rest_env
424 algorithm
425 1254 rest_env := NFSCodeEnv.getEnvTopScope(rest_env);
426 1254 (opt_item, opt_path, opt_env) := lookupSimpleName2(inName, rest_env, {});
427 352 checkBuiltinItem(opt_item);
428 314 then
429 (opt_item, opt_path, opt_env);
430
431 end matchcontinue;
432 end lookupSimpleName2;
433
434 public function frameNotEncapsulated
435 "Fails if the frame type is encapsulated, otherwise succeeds."
436 input FrameType frameType;
437 algorithm
438 () := match frameType
439 1254 case NFSCodeEnv.ENCAPSULATED_SCOPE() then fail();
440 else ();
441 end match;
442 end frameNotEncapsulated;
443
444 protected function checkBuiltinItem
445 input Option<Item> inItem;
446 algorithm
447 () := match inItem
448 local
449
450 case SOME(NFSCodeEnv.CLASS(classType = NFSCodeEnv.BUILTIN())) then ();
451 case NONE() then ();
452 end match;
453 end checkBuiltinItem;
454
455 public function lookupInLocalScope
456 "Looks up a simple identifier in the environment. Returns SOME(item) if an
457 item is found, NONE() if a partial match was found (for example when the name
458 matches the import name of an import, but the imported class couldn't be
459 found), or fails if no match is found."
460 input Absyn.Ident inName;
461 input Env inEnv;
462 input list<String> inVisitedScopes;
463 output Option<Item> outItem;
464 output Option<Absyn.Path> outPath;
465 output Option<Env> outEnv;
466 algorithm
467 (outItem, outPath, outEnv) := matchcontinue inEnv
468 local
469 Env rest_env, env;
470 Item item;
471 Option<Item> opt_item;
472 Option<Absyn.Path> opt_path;
473 list<Import> imps;
474 Absyn.Path path;
475 Option<Env> opt_env;
476
477 // Look among the locally declared components.
478 case _
479 algorithm
480 89749411 (item, env) := lookupInClass(inName, inEnv);
481 143377226 then
482 (SOME(item), SOME(Absyn.IDENT(inName)), SOME(env));
483
484 // Look among the inherited components.
485 case _
486 algorithm
487 18060798 (opt_item, opt_path, opt_env) :=
488 lookupInBaseClasses(inName, inEnv, INSERT_REDECLARES(), inVisitedScopes);
489 then
490 (opt_item, opt_path, opt_env);
491
492 // Look among the qualified imports.
493 case NFSCodeEnv.FRAME(importTable =
494 NFSCodeEnv.IMPORT_TABLE(hidden = false, qualifiedImports = imps)) :: _
495 algorithm
496 959991 (opt_item, opt_path, opt_env) :=
497 lookupInQualifiedImports(inName, imps, inEnv);
498 then
499 (opt_item, opt_path, opt_env);
500
501 // Look among the unqualified imports.
502 case NFSCodeEnv.FRAME(importTable =
503 NFSCodeEnv.IMPORT_TABLE(hidden = false, unqualifiedImports = imps)) :: _
504 algorithm
505 909576 (item, path, env) :=
506 lookupInUnqualifiedImports(inName, imps, inEnv);
507 26 then
508 (SOME(item), SOME(path), SOME(env));
509
510 // Look in the next scope only if the current scope is an implicit scope
511 // (for example a for or match/matchcontinue scope).
512 case NFSCodeEnv.FRAME(frameType = NFSCodeEnv.IMPLICIT_SCOPE()) :: rest_env
513 algorithm
514 16585 (opt_item, opt_path, opt_env) :=
515 lookupInLocalScope(inName, rest_env, inVisitedScopes);
516 then
517 (opt_item, opt_path, opt_env);
518
519 end matchcontinue;
520 end lookupInLocalScope;
521
522 public function lookupInClass
523 input Absyn.Ident inName;
524 input Env inEnv;
525 output Item outItem;
526 output Env outEnv;
527 protected
528 EnvTree.Tree tree;
529 algorithm
530
2/2
✓ Branch 0 taken 610 times.
✓ Branch 1 taken 106605953 times.
106606563 NFSCodeEnv.FRAME(clsAndVars = tree) :: _ := inEnv;
531 106605953 outItem := EnvTree.get(tree, inName);
532 82881170 (outItem, outEnv) := resolveAlias(outItem, inEnv);
533 end lookupInClass;
534
535 public function resolveAlias
536 "Resolved an alias by looking up the aliased item recursively in the
537 environment until a non-alias item is found."
538 input Item inItem;
539 input Env inEnv;
540 output Item outItem;
541 output Env outEnv;
542 algorithm
543 (outItem, outEnv) := match(inItem, inEnv)
544 local
545 String name;
546 Item item;
547 Absyn.Path path;
548 Env env;
549 EnvTree.Tree tree;
550
551 case (NFSCodeEnv.ALIAS(name = name, path = NONE()),
552 NFSCodeEnv.FRAME(clsAndVars = tree) :: _)
553 algorithm
554 2595380 item := EnvTree.get(tree, name);
555 2595380 (item, env) := resolveAlias(item, inEnv);
556 then
557 (item, env);
558
559 case (NFSCodeEnv.ALIAS(name = name, path = SOME(path)), _)
560 algorithm
561 3181 env := NFSCodeEnv.getEnvTopScope(inEnv);
562 3181 env := NFSCodeEnv.enterScopePath(env, path);
563
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3181 times.
3181 NFSCodeEnv.FRAME(clsAndVars = tree) :: _ := env;
564 3181 item := EnvTree.get(tree, name);
565 3181 (item, env) := resolveAlias(item, env);
566 then
567 (item, env);
568
569 else (inItem, inEnv);
570 end match;
571 end resolveAlias;
572
573 protected function lookupInBaseClasses
574 "Looks up an identifier by following the extends clauses in a scope."
575 input Absyn.Ident inName;
576 input Env inEnv;
577 input RedeclareReplaceStrategy inReplaceRedeclares;
578 input list<String> inVisitedScopes;
579 output Option<Item> outItem;
580 output Option<Absyn.Path> outPath;
581 output Option<Env> outEnv;
582 protected
583 Env env;
584 list<Extends> bcl;
585 algorithm
586
4/4
✓ Branch 0 taken 273 times.
✓ Branch 1 taken 18117864 times.
✓ Branch 3 taken 8051100 times.
✓ Branch 4 taken 10066764 times.
18118137 NFSCodeEnv.FRAME(extendsTable =
587 NFSCodeEnv.EXTENDS_TABLE(baseClasses = bcl as _ :: _)) :: _ := inEnv;
588 // Remove the extends, base class names should not be inherited.
589 10066764 env := NFSCodeEnv.removeExtendsFromLocalScope(inEnv);
590 // Unhide the imports in case they've been hidden so we can find the base
591 // classes.
592 10066764 env := NFSCodeEnv.setImportTableHidden(env, false);
593 10066764 (outItem, outPath, outEnv) :=
594 lookupInBaseClasses2(inName, bcl, env, inEnv, inReplaceRedeclares, inVisitedScopes);
595 end lookupInBaseClasses;
596
597 protected function lookupInBaseClasses2
598 "Helper function to lookupInBaseClasses. Tries to find an identifier by
599 looking in the extended classes in a scope."
600 input Absyn.Ident inName;
601 input list<Extends> inBaseClasses;
602 input Env inEnv;
603 input Env inEnvWithExtends;
604 input RedeclareReplaceStrategy inReplaceRedeclares;
605 input list<String> inVisitedScopes;
606 output Option<Item> outItem;
607 output Option<Absyn.Path> outPath;
608 output Option<Env> outEnv;
609 algorithm
610 (outItem, outPath, outEnv) :=
611 matchcontinue inBaseClasses
612 local
613 Extends ext;
614 list<Extends> rest_ext;
615 Option<Item> item;
616 Option<Absyn.Path> path;
617 Option<Env> env;
618
619 case ext :: _
620 algorithm
621 10551616 (item, path, env) := lookupInBaseClasses3(inName, ext, inEnv,
622 inEnvWithExtends, inReplaceRedeclares, inVisitedScopes);
623 then
624 (item, path, env);
625
626 case _ :: rest_ext
627 algorithm
628 9312484 (item, path, env) := lookupInBaseClasses2(inName, rest_ext, inEnv,
629 inEnvWithExtends, inReplaceRedeclares, inVisitedScopes);
630 then
631 (item, path, env);
632
633 end matchcontinue;
634 end lookupInBaseClasses2;
635
636 public function lookupInBaseClasses3
637 "Helper function to lookupInBaseClasses2. Looks up an identifier in the given
638 extended class."
639 input Absyn.Ident inName;
640 input Extends inBaseClass;
641 input Env inEnv;
642 input Env inEnvWithExtends;
643 input RedeclareReplaceStrategy inReplaceRedeclares;
644 input list<String> inVisitedScopes;
645 output Option<Item> outItem;
646 output Option<Absyn.Path> outPath;
647 output Option<Env> outEnv;
648 algorithm
649 (outItem, outPath, outEnv) := match inBaseClass
650 local
651 Absyn.Path bc, path;
652 Item item;
653 Env env;
654 list<NFSCodeEnv.Redeclaration> redecls;
655 SourceInfo info;
656 Option<Absyn.Path> opt_path;
657 Option<Item> opt_item;
658 Option<Env> opt_env;
659
660 case NFSCodeEnv.EXTENDS(baseClass = bc as Absyn.QUALIFIED(name = "$E"),
661 info = info)
662 algorithm
663 ✗ NFEnvExtends.printExtendsError(bc, inEnvWithExtends, info);
664 ✗ then
665 (NONE(), NONE(), NONE());
666
667 // Look in the first base class.
668 case NFSCodeEnv.EXTENDS(baseClass = bc, redeclareModifiers = redecls, info = info)
669 algorithm
670 // Find the base class.
671 10551618 (item, path, env) := lookupBaseClassName(bc, inEnv, info);
672
2/2
✓ Branch 1 taken 789 times.
✓ Branch 2 taken 10550829 times.
10551618 true := checkVisitedScopes(inVisitedScopes, inEnv, path);
673 // Hide the imports to make sure that we don't find the name via them
674 // (imports are not inherited).
675 10550829 item := NFSCodeEnv.setImportsInItemHidden(item, true);
676 // Look in the base class.
677 10550595 (opt_item, opt_env) := NFSCodeFlattenRedeclare.replaceRedeclares(redecls,
678 item, env, inEnvWithExtends, inReplaceRedeclares);
679 10550595 (opt_item, opt_path, opt_env) :=
680 lookupInBaseClasses4(Absyn.IDENT(inName), opt_item, opt_env);
681 then
682 (opt_item, opt_path, opt_env);
683
684 end match;
685 end lookupInBaseClasses3;
686
687 protected function checkVisitedScopes
688 "Checks if we are trying to look up a base class that we are coming from when
689 going up in the environment, to avoid infinite loops."
690 input list<String> inVisitedScopes;
691 input Env inEnv;
692 input Absyn.Path inBaseClass;
693 output Boolean outRes;
694 algorithm
695 outRes := matchcontinue inVisitedScopes
696 local
697 Absyn.Path env_path, visited_path, bc_path;
698
699 case {} then true;
700
701 case _
702 algorithm
703 612237 env_path := NFSCodeEnv.getEnvPath(inEnv);
704 612237 bc_path := AbsynUtil.removePrefix(env_path, inBaseClass);
705 91377 visited_path := AbsynUtil.stringListPath(inVisitedScopes);
706
2/2
✓ Branch 1 taken 90588 times.
✓ Branch 2 taken 789 times.
91377 true := AbsynUtil.pathPrefixOf(visited_path, bc_path);
707 then
708 false;
709
710 else true;
711 end matchcontinue;
712 end checkVisitedScopes;
713
714 protected function lookupInBaseClasses4
715 "Helper function to lookupInBaseClasses3. Tries to find the name in the given
716 item."
717 input Absyn.Path inName;
718 input Option<Item> inItem;
719 input Option<Env> inEnv;
720 output Option<Item> outItem;
721 output Option<Absyn.Path> outPath;
722 output Option<Env> outEnv;
723 algorithm
724 (outItem, outPath, outEnv) := match(inItem, inEnv)
725 local
726 Item item;
727 Absyn.Path path;
728 Env env;
729
730 // If the item and env is NONE it means that an error occured (hopefully a
731 // user error), and we should stop searching.
732 case (NONE(), NONE()) then (NONE(), NONE(), NONE());
733
734 // Otherwise, try to find the name in the given item. If the name can not be
735 // found we fail, so that we can continue to look in other base classes.
736 case (SOME(item), SOME(env))
737 algorithm
738 10550595 (item, path, env) := lookupNameInItem(inName, item, env);
739 1239134 then
740 (SOME(item), SOME(path), SOME(env));
741
742 end match;
743 end lookupInBaseClasses4;
744
745 public function lookupInQualifiedImports
746 "Looks up a name through the qualified imports in a scope. If it finds the
747 name it returns the item, path, and environment for the name. It can also find
748 a partial match, in which case it returns NONE() to signal that the lookup
749 shouldn't look further. This can happen if the have an 'import A.B' and an
750 element 'B.C', but C is not in A.B. Finally it can also fail to find anything,
751 in which case it simply fails as normal."
752 input Absyn.Ident inName;
753 input list<Import> inImports;
754 input Env inEnv;
755 output Option<Item> outItem;
756 output Option<Absyn.Path> outPath;
757 output Option<Env> outEnv;
758 algorithm
759 (outItem, outPath, outEnv) := matchcontinue inImports
760 local
761 Absyn.Ident name;
762 Absyn.Path path;
763 Item item;
764 list<Import> rest_imps;
765 Option<Item> opt_item;
766 Option<Absyn.Path> opt_path;
767 Option<Env> opt_env;
768 Env env;
769
770 // No match, search the rest of the list of imports.
771 case Absyn.NAMED_IMPORT(name = name) :: rest_imps
772 algorithm
773
4/4
✓ Branch 0 taken 100874 times.
✓ Branch 1 taken 249390 times.
✓ Branch 3 taken 50415 times.
✓ Branch 4 taken 50459 times.
350264 false := stringEqual(inName, name);
774 299849 (opt_item, opt_path, opt_env) :=
775 lookupInQualifiedImports(inName, rest_imps, inEnv);
776 then
777 (opt_item, opt_path, opt_env);
778
779 // Match, look up the fully qualified import path.
780 case Absyn.NAMED_IMPORT(name = name, path = path) :: _
781 algorithm
782
4/4
✓ Branch 0 taken 64407 times.
✓ Branch 1 taken 243588 times.
✓ Branch 3 taken 13992 times.
✓ Branch 4 taken 50415 times.
307995 true := stringEqual(inName, name);
783 50415 (item, path, env) := lookupFullyQualified(path, inEnv);
784 50415 then
785 (SOME(item), SOME(path), SOME(env));
786
787 // Partial match, return NONE(). This is when only part of the import path
788 // can be found, in which case we should stop looking further.
789 case Absyn.NAMED_IMPORT(name = name) :: _
790 algorithm
791
3/4
✓ Branch 0 taken 13992 times.
✓ Branch 1 taken 243588 times.
✓ Branch 3 taken 13992 times.
✗ Branch 4 not taken.
257580 true := stringEqual(inName, name);
792 ✗ then
793 (NONE(), NONE(), NONE());
794
795 end matchcontinue;
796 end lookupInQualifiedImports;
797
798 public function lookupInUnqualifiedImports
799 "Looks up a name through the qualified imports in a scope. If it finds the
800 name it returns the item, path, and environment for the name, otherwise it
801 fails."
802 input Absyn.Ident inName;
803 input list<Import> inImports;
804 input Env inEnv;
805 output Item outItem;
806 output Absyn.Path outPath;
807 output Env outEnv;
808 algorithm
809 (outItem, outPath, outEnv) := matchcontinue inImports
810 local
811 Item item;
812 Absyn.Path path, path2;
813 list<Import> rest_imps;
814 Env env;
815
816 // For each unqualified import we have to look up the package the import
817 // points to, and then look among the public member of the package for the
818 // name we are looking for.
819 case Absyn.UNQUAL_IMPORT(path = path) :: _
820 algorithm
821 // Look up the import path.
822 105 (item, path, env) := lookupFullyQualified(path, inEnv);
823 // Look up the name among the public member of the found package.
824 105 (item, path2, env) := lookupNameInItem(Absyn.IDENT(inName), item, env);
825 // Combine the paths for the name and the package it was found in.
826 26 path := joinPaths(path, path2);
827 26 then
828 (item, path, env);
829
830 // No match, continue with the rest of the imports.
831 case _ :: rest_imps
832 algorithm
833 79 (item, path, env) :=
834 lookupInUnqualifiedImports(inName, rest_imps, inEnv);
835 then
836 (item, path, env);
837 end matchcontinue;
838 end lookupInUnqualifiedImports;
839
840 public function lookupFullyQualified
841 "Looks up a fully qualified path in the environment, returning the
842 environment item, path and environment of the name if found."
843 input Absyn.Path inName;
844 input Env inEnv;
845 output Item outItem;
846 output Absyn.Path outPath;
847 output Env outEnv;
848 protected
849 Env env;
850 algorithm
851 19814172 env := NFSCodeEnv.getEnvTopScope(inEnv);
852 19814172 (outItem, outPath, outEnv) := lookupNameInPackage(inName, env);
853 19814172 outPath := AbsynUtil.makeFullyQualified(outPath);
854 end lookupFullyQualified;
855
856 public function lookupNameInPackage
857 "Looks up a name inside the environment of a package, returning the
858 environment item, path and environment of the name if found."
859 input Absyn.Path inName;
860 input Env inEnv;
861 output Item outItem;
862 output Absyn.Path outPath;
863 output Env outEnv;
864 algorithm
865 (outItem, outPath, outEnv) := match(inName, inEnv)
866 local
867 Absyn.Ident name;
868 Absyn.Path path, new_path;
869 Env env;
870 Item item;
871
872 // Simple name, look in the local scope.
873 case (Absyn.IDENT(name = name), _)
874 algorithm
875
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 23763025 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 23763025 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 23763025 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 23763025 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 23763025 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 23763025 times.
39681845 (SOME(item), SOME(path), SOME(env)) := lookupInLocalScope(name, inEnv, {});
876 23763025 env := NFSCodeEnv.setImportTableHidden(env, false);
877 23763025 then
878 (item, path, env);
879
880 // Qualified name.
881 case (Absyn.QUALIFIED(name = name, path = path), _ :: _)
882 algorithm
883 // Look up the name in the local scope.
884
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 48137813 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 48137813 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 48137813 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 48137813 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 48137813 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 48137813 times.
48137813 (SOME(item), SOME(new_path), SOME(env)) :=
885 lookupInLocalScope(name, inEnv, {});
886 48137813 env := NFSCodeEnv.setImportTableHidden(env, false);
887 // Look for the rest of the path in the found item.
888 48137813 (item, path, env) := lookupNameInItem(path, item, env);
889 48137813 path := joinPaths(new_path, path);
890 48137813 then
891 (item, path, env);
892
893 end match;
894 end lookupNameInPackage;
895
896 public function lookupCrefInPackage
897 "Looks up a component reference inside the environment of a package, returning
898 the environment item, path and environment of the reference if found."
899 input Absyn.ComponentRef inCref;
900 input Env inEnv;
901 output Item outItem;
902 output Absyn.ComponentRef outCref;
903 algorithm
904 (outItem, outCref) := matchcontinue inCref
905 local
906 Absyn.Ident name;
907 Absyn.Path new_path;
908 list<Absyn.Subscript> subs;
909 Absyn.ComponentRef cref, cref_rest;
910 Item item;
911 Env env;
912
913 // Simple identifier, look in the local scope.
914 case Absyn.CREF_IDENT(name = name, subscripts = subs)
915 algorithm
916
4/8
✗ Branch 1 not taken.
✓ Branch 2 taken 56705 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 56705 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 56705 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 56705 times.
56973 (SOME(item), SOME(new_path), _) := lookupInLocalScope(name, inEnv, {});
917 56705 cref := AbsynUtil.pathToCrefWithSubs(new_path, subs);
918 then
919 (item, cref);
920
921 // Qualified identifier, what we get back is not fully qualified
922 case Absyn.CREF_QUAL(name = name, subscripts = subs,
923 componentRef = cref_rest)
924 algorithm
925 // Look in the local scope.
926
6/12
✗ Branch 1 not taken.
✓ Branch 2 taken 12696 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 12696 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12696 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 12696 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 12696 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 12696 times.
14015 (SOME(item), SOME(new_path), SOME(env)) :=
927 lookupInLocalScope(name, inEnv, {});
928 // Look for the rest of the reference in the found item.
929 12696 (item, cref_rest) := lookupCrefInItem(cref_rest, item, env);
930 // not fully qualified
931
2/4
✓ Branch 0 taken 12696 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12696 times.
✗ Branch 3 not taken.
12696 failure(Absyn.CREF_FULLYQUALIFIED(_) := cref_rest);
932 12696 cref := AbsynUtil.pathToCrefWithSubs(new_path, subs);
933 12696 cref := AbsynUtil.joinCrefs(cref, cref_rest);
934 12696 then
935 (item, cref);
936
937 // Qualified identifier, what we get back is fully qualified, i.e. from import!
938 case Absyn.CREF_QUAL(name = name,
939 componentRef = cref_rest)
940 algorithm
941 // Look in the local scope.
942
0/12
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
1319 (SOME(item), SOME(_), SOME(env)) :=
943 lookupInLocalScope(name, inEnv, {});
944 // Look for the rest of the reference in the found item, fully qualified
945 ✗ (item, cref_rest as Absyn.CREF_FULLYQUALIFIED(_)) := lookupCrefInItem(cref_rest, item, env);
946 cref := cref_rest;
947 then
948 (item, cref);
949
950 end matchcontinue;
951 end lookupCrefInPackage;
952
953 public function lookupNameInItem
954 "Looks up a name inside of an item, which can be either a variable or a
955 class."
956 input Absyn.Path inName;
957 input Item inItem;
958 input Env inEnv;
959 output Item outItem;
960 output Absyn.Path outPath;
961 output Env outEnv;
962 algorithm
963 (outItem, outPath, outEnv) := match(inItem, inEnv)
964 local
965 Item item;
966 Absyn.Path path;
967 Frame class_env;
968 Env env, type_env;
969 Absyn.TypeSpec type_spec;
970 SCode.Mod mods;
971 list<NFSCodeEnv.Redeclaration> redeclares;
972 SourceInfo info;
973
974 // A variable.
975 case (NFSCodeEnv.VAR(var = SCode.COMPONENT(typeSpec = type_spec,
976 modifications = mods, info = info)), env)
977 algorithm
978 //env = NFSCodeEnv.setImportTableHidden(env, false);
979 // Look up the variable type.
980 ✗ (item, _, type_env) := lookupTypeSpec(type_spec, env, info);
981 // Apply redeclares to the type and look for the name inside the type.
982 ✗ redeclares := NFSCodeFlattenRedeclare.extractRedeclaresFromModifier(mods);
983 ✗ (item, type_env, _) := NFSCodeFlattenRedeclare.replaceRedeclaredElementsInEnv(
984 redeclares, item, type_env, inEnv, NFInstPrefix.emptyPrefix);
985 54 (item, path, env) := lookupNameInItem(inName, item, type_env);
986 then
987 (item, path, env);
988
989 // A class.
990 case (NFSCodeEnv.CLASS(env = {class_env}), _)
991 algorithm
992 // Look in the class's environment.
993 68005486 env := NFSCodeEnv.enterFrame(class_env, inEnv);
994 68005486 (item, path, env) := lookupNameInPackage(inName, env);
995 then
996 (item, path, env);
997
998 case (NFSCodeEnv.REDECLARED_ITEM(item = item, declaredEnv = env), _)
999 algorithm
1000 54 (item, path, env) := lookupNameInItem(inName, item, env);
1001 then
1002 (item, path, env);
1003
1004 end match;
1005 end lookupNameInItem;
1006
1007 public function lookupCrefInItem
1008 "Looks up a component reference inside of an item, which can be either a
1009 variable or a class."
1010 input Absyn.ComponentRef inCref;
1011 input Item inItem;
1012 input Env inEnv;
1013 output Item outItem;
1014 output Absyn.ComponentRef outCref;
1015 algorithm
1016 (outItem, outCref) := match inItem
1017 local
1018 Item item;
1019 Absyn.ComponentRef cref;
1020 Frame class_env;
1021 Env env, type_env;
1022 Absyn.TypeSpec type_spec;
1023 SCode.Mod mods;
1024 list<NFSCodeEnv.Redeclaration> redeclares;
1025 SourceInfo info;
1026
1027 // A variable.
1028 case NFSCodeEnv.VAR(var = SCode.COMPONENT(typeSpec = type_spec,
1029 modifications = mods, info = info))
1030 algorithm
1031 // Look up the variable's type.
1032 43518 (item, _, type_env) := lookupTypeSpec(type_spec, inEnv, info);
1033 // Apply redeclares to the type and look for the name inside the type.
1034 43518 redeclares := NFSCodeFlattenRedeclare.extractRedeclaresFromModifier(mods);
1035 43518 (item, type_env, _) := NFSCodeFlattenRedeclare.replaceRedeclaredElementsInEnv(
1036 redeclares, item, type_env, inEnv, NFInstPrefix.emptyPrefix);
1037 43608 (item, cref) := lookupCrefInItem(inCref, item, type_env);
1038 then
1039 (item, cref);
1040
1041 // A class.
1042 case NFSCodeEnv.CLASS(env = {class_env})
1043 algorithm
1044 // Look in the class's environment.
1045 69401 env := NFSCodeEnv.enterFrame(class_env, inEnv);
1046 69401 (item, cref) := lookupCrefInPackage(inCref, env);
1047 then
1048 (item, cref);
1049
1050 case NFSCodeEnv.REDECLARED_ITEM(item = item, declaredEnv = env)
1051 algorithm
1052 90 (item, cref) := lookupCrefInItem(inCref, item, env);
1053 then
1054 (item, cref);
1055
1056 end match;
1057 end lookupCrefInItem;
1058
1059 public function lookupBaseClasses
1060 "Looks up the given name, and returns a list of all the base classes in the
1061 current scope that the name was found in."
1062 input SCode.Ident inName;
1063 input Env inEnv;
1064 output list<Absyn.Path> outBaseClasses;
1065 protected
1066 list<Extends> bcl;
1067 algorithm
1068
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6148807 times.
✓ Branch 3 taken 2425 times.
✓ Branch 4 taken 6146382 times.
6148807 NFSCodeEnv.FRAME(extendsTable =
1069 NFSCodeEnv.EXTENDS_TABLE(baseClasses = bcl as _ :: _)) :: _ := inEnv;
1070 6146382 (_, outBaseClasses) :=
1071 List.fold22(bcl, lookupBaseClasses2, inName, inEnv, {}, {});
1072
2/2
✓ Branch 0 taken 3531267 times.
✓ Branch 1 taken 2615115 times.
6146382 false := listEmpty(outBaseClasses);
1073 2615115 outBaseClasses := listReverse(outBaseClasses);
1074 end lookupBaseClasses;
1075
1076 protected function lookupBaseClasses2
1077 "Helper function to lookupBaseClasses. Tries to find a name in the given base
1078 class, and appends the base class path to the given list if found. Otherwise
1079 returns the unchanged list."
1080 input Extends inBaseClass;
1081 input SCode.Ident inName;
1082 input Env inEnv;
1083 input output list<Item> items;
1084 input output list<Absyn.Path> bcl;
1085 algorithm
1086 (items, bcl) := matchcontinue inBaseClass
1087 local
1088 Absyn.Path bc;
1089 SourceInfo info;
1090 Env env;
1091 Item item;
1092
1093 case NFSCodeEnv.EXTENDS(baseClass = bc,
1094 info = info)
1095 algorithm
1096 // Look up the base class.
1097 9222463 (item, _, env) := lookupBaseClassName(bc, inEnv, info);
1098
1099 // Hide the imports to make sure that we don't find the name via them
1100 // (imports are not inherited).
1101 9222463 item := NFSCodeEnv.setImportsInItemHidden(item, true);
1102
1103 // Note that we don't need to apply any redeclares here, since no part
1104 // of the base class path may be replaceable. The element we're looking
1105 // for may have been replaced, but that doesn't matter since we only
1106 // want to check if it can be found or not.
1107
1108 // Check if we can find the name in the base class. If so, add the base
1109 // class path to the list.
1110 9222463 (item, _, _) := lookupNameInItem(Absyn.IDENT(inName), item, env);
1111 then
1112 (item :: items, bc :: bcl);
1113
1114 6607278 else (items, bcl);
1115
1116 end matchcontinue;
1117 end lookupBaseClasses2;
1118
1119 public function lookupInheritedName
1120 "Looks up an inherited name by searching the extends in the local scope."
1121 input SCode.Ident inName;
1122 input Env inEnv;
1123 output Item outItem;
1124 output Env outEnv;
1125 algorithm
1126
6/10
✗ Branch 1 not taken.
✓ Branch 2 taken 56079 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 56079 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 56079 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 56079 times.
✓ Branch 11 taken 17297 times.
✓ Branch 12 taken 38782 times.
56081 (SOME(outItem), _, SOME(outEnv)) :=
1127 lookupInBaseClasses(inName, inEnv, INSERT_REDECLARES(), {});
1128 end lookupInheritedName;
1129
1130 public function lookupInheritedNameAndBC
1131 input SCode.Ident inName;
1132 input Env inEnv;
1133 output list<Item> outItems;
1134 output list<Absyn.Path> outBaseClasses;
1135 protected
1136 list<Extends> bcl;
1137 algorithm
1138 ✗ NFSCodeEnv.FRAME(extendsTable =
1139 NFSCodeEnv.EXTENDS_TABLE(baseClasses = bcl as _ :: _)) :: _ := inEnv;
1140 ✗ (outItems, outBaseClasses) :=
1141 List.fold22(bcl, lookupBaseClasses2, inName, inEnv, {}, {});
1142 ✗ outBaseClasses := listReverse(outBaseClasses);
1143 ✗ outItems := listReverse(outItems);
1144 end lookupInheritedNameAndBC;
1145
1146 public function lookupRedeclaredClassByItem
1147 input Item inItem;
1148 input Env inEnv;
1149 input SourceInfo inInfo;
1150 output Item outItem;
1151 output Env outEnv;
1152 algorithm
1153 (outItem, outEnv) := matchcontinue inItem
1154 local
1155 SCode.Ident name;
1156 Item item;
1157 Env env;
1158 SCode.Redeclare rdp;
1159 SCode.Replaceable rpp;
1160
1161 case NFSCodeEnv.CLASS(cls = SCode.CLASS(name = name))
1162 algorithm
1163
4/8
✗ Branch 1 not taken.
✓ Branch 2 taken 1058 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1058 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1058 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1058 times.
1058 (SOME(item), _, SOME(env)) := lookupInBaseClasses(name, inEnv,
1164 IGNORE_REDECLARES(), {});
1165 1058 SCode.PREFIXES(redeclarePrefix = rdp, replaceablePrefix = rpp) :=
1166 NFSCodeEnv.getItemPrefixes(item);
1167 1058 (item, env) := lookupRedeclaredClass2(item, rdp, rpp, env, inInfo);
1168 then
1169 (item, env);
1170
1171 // No error message is output if the previous case fails. This is because
1172 // lookupInBaseClasses is used by NFSCodeEnv.extendEnvWithClassExtends when
1173 // adding the redeclaration to the environment, and lookupRedeclaredClass2
1174 // outputs its own errors.
1175 else
1176 algorithm
1177 ✗ true := Flags.isSet(Flags.FAILTRACE);
1178 ✗ Debug.traceln("- NFSCodeLookup.lookupRedeclaredClassByItem failed on " +
1179 NFSCodeEnv.getItemName(inItem) + " in " +
1180 NFSCodeEnv.getEnvName(inEnv));
1181 ✗ then
1182 fail();
1183 end matchcontinue;
1184 end lookupRedeclaredClassByItem;
1185
1186 protected function lookupRedeclaredClass2
1187 input Item inItem;
1188 input SCode.Redeclare inRedeclarePrefix;
1189 input SCode.Replaceable inReplaceablePrefix;
1190 input Env inEnv;
1191 input SourceInfo inInfo;
1192 output Item outItem;
1193 output Env outEnv;
1194 algorithm
1195 (outItem, outEnv) :=
1196 matchcontinue(inItem, inRedeclarePrefix, inReplaceablePrefix)
1197 local
1198 SCode.Ident name;
1199 Item item;
1200 Env env;
1201 SourceInfo info;
1202 SCode.Redeclare rdp;
1203 SCode.Replaceable rpp;
1204
1205 // Replaceable element which is not a redeclaration => return the element.
1206 case (_, SCode.NOT_REDECLARE(), SCode.REPLACEABLE())
1207 1058 then (inItem, inEnv);
1208
1209 // Replaceable element which is a redeclaration => continue.
1210 case (NFSCodeEnv.CLASS(cls = SCode.CLASS(name = name)), SCode.REDECLARE(), SCode.REPLACEABLE())
1211 algorithm
1212
4/8
✗ Branch 1 not taken.
✓ Branch 2 taken 200 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 200 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 200 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 200 times.
200 (SOME(item), _, SOME(env)) := lookupInBaseClasses(name, inEnv,
1213 IGNORE_REDECLARES(), {});
1214 200 SCode.PREFIXES(redeclarePrefix = rdp, replaceablePrefix = rpp) :=
1215 NFSCodeEnv.getItemPrefixes(item);
1216 200 (item, env) := lookupRedeclaredClass2(item, rdp, rpp, env, inInfo);
1217 then
1218 (item, env);
1219
1220 case (NFSCodeEnv.REDECLARED_ITEM(item, env), _, _)
1221 algorithm
1222 ✗ (item, env) := lookupRedeclaredClass2(item, inRedeclarePrefix,
1223 inReplaceablePrefix, env, inInfo);
1224 then
1225 (item, env);
1226
1227 // Non-replaceable element => error.
1228 case (NFSCodeEnv.CLASS(cls = SCode.CLASS(name = name, info = info)), _, SCode.NOT_REPLACEABLE())
1229 algorithm
1230 ✗ Error.addSourceMessage(Error.ERROR_FROM_HERE, {}, inInfo);
1231 ✗ Error.addSourceMessage(Error.REDECLARE_NON_REPLACEABLE, {name}, info);
1232 ✗ then
1233 fail();
1234
1235 // Redeclaration of class to component => error.
1236 case (NFSCodeEnv.VAR(var = SCode.COMPONENT(name = name, info = info)), _, _)
1237 algorithm
1238 ✗ Error.addSourceMessage(Error.ERROR_FROM_HERE, {}, inInfo);
1239 ✗ Error.addSourceMessage(Error.INVALID_REDECLARE_AS,
1240 {"component", name, "a class"}, info);
1241 ✗ then
1242 fail();
1243
1244 else
1245 algorithm
1246 ✗ true := Flags.isSet(Flags.FAILTRACE);
1247 ✗ Debug.traceln("- NFSCodeLookup.lookupRedeclaredClass2 failed on " +
1248 NFSCodeEnv.getItemName(inItem) + " in " +
1249 NFSCodeEnv.getEnvName(inEnv));
1250 ✗ then
1251 fail();
1252 end matchcontinue;
1253 end lookupRedeclaredClass2;
1254
1255 public function lookupBuiltinType
1256 "Checks if a name references a builtin type, and returns an environment item
1257 for that type or fails."
1258 input Absyn.Ident inName;
1259 output Item outItem;
1260 algorithm
1261 outItem := match inName
1262 case "Real" then BUILTIN_REAL;
1263 case "Integer" then BUILTIN_INTEGER;
1264 case "Boolean" then BUILTIN_BOOLEAN;
1265 case "String" then BUILTIN_STRING;
1266 case "StateSelect" then BUILTIN_STATESELECT;
1267 case "ExternalObject" then BUILTIN_EXTERNALOBJECT;
1268 case "Clock"
1269 algorithm
1270
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 454 times.
454 true := Config.synchronousFeaturesAllowed();
1271 then BUILTIN_CLOCK;
1272 case "$RealType" then BUILTIN_REALTYPE_ITEM;
1273 case "$IntegerType" then BUILTIN_INTEGERTYPE_ITEM;
1274 case "$BooleanType" then BUILTIN_BOOLEANTYPE_ITEM;
1275 case "$StringType" then BUILTIN_STRINGTYPE_ITEM;
1276 case "$EnumType" then BUILTIN_ENUMTYPE_ITEM;
1277 end match;
1278 end lookupBuiltinType;
1279
1280 protected function lookupBuiltinName
1281 input Absyn.Path inName;
1282 output Item outItem;
1283 output Env outEnv;
1284 algorithm
1285 (outItem, outEnv) := match inName
1286 local
1287 Absyn.Ident id;
1288 Item item;
1289
1290 // A builtin type.
1291 case Absyn.IDENT(name = id)
1292 algorithm
1293 598490 item := lookupBuiltinType(id);
1294 then
1295 (item, NFSCodeEnv.emptyEnv);
1296
1297 // Builtin type StateSelect. The only builtin type that can be qualified,
1298 // i.e. StateSelect.always.
1299 case Absyn.QUALIFIED(name = "StateSelect", path = Absyn.IDENT(id))
1300 algorithm
1301 ✗ (item, _) := lookupInClass(id, BUILTIN_STATESELECT_ENV);
1302 then
1303 (item, BUILTIN_STATESELECT_ENV);
1304
1305 end match;
1306 end lookupBuiltinName;
1307
1308 protected function lookupName
1309 "Looks up a simple or qualified name in the environment and returns the
1310 environment item corresponding to the name, the path for the name and
1311 optionally the enclosing scope of the name if the name references a class.
1312 This function doesn't know what kind of thing the name references, so to get
1313 meaningful error messages you should use one of the lookup****Name below
1314 instead."
1315 input Absyn.Path inName;
1316 input Env inEnv;
1317 input LookupStrategy inLookupStrategy;
1318 input SourceInfo inInfo;
1319 input Option<ErrorTypes.Message> inErrorType;
1320 output Item outItem;
1321 output Absyn.Path outName;
1322 output Env outEnv;
1323 algorithm
1324 (outItem, outName, outEnv) :=
1325 matchcontinue(inName, inLookupStrategy, inErrorType)
1326 local
1327 Absyn.Ident id;
1328 Item item;
1329 Absyn.Path path, new_path;
1330 Env env;
1331 String name_str, env_str;
1332 ErrorTypes.Message error_id;
1333
1334 // Builtin types.
1335 case (_, LOOKUP_ANY(), _)
1336 algorithm
1337 20456651 (item, env) := lookupBuiltinName(inName);
1338 84968 then
1339 (item, inName, env);
1340
1341 // Simple name.
1342 case (Absyn.IDENT(name = id), _, _)
1343 algorithm
1344 649834 (item, new_path, env) := lookupSimpleName(id, inEnv);
1345 then
1346 (item, new_path, env);
1347
1348 // Qualified name.
1349 case (Absyn.QUALIFIED(name = id, path = path), _, _)
1350 algorithm
1351 // Look up the first identifier.
1352 94510 (item, new_path, env) := lookupSimpleName(id, inEnv);
1353 // Look up the rest of the name in the environment of the first
1354 // identifier.
1355 94510 (item, path, env) := lookupNameInItem(path, item, env);
1356 94508 path := joinPaths(new_path, path);
1357 94508 then
1358 (item, path, env);
1359
1360 case (Absyn.FULLYQUALIFIED(path = path), _, _)
1361 algorithm
1362 19763651 (item, path, env) := lookupFullyQualified(path, inEnv);
1363 then
1364 (item, path, env);
1365
1366 case (_, _, SOME(error_id))
1367 algorithm
1368 2 name_str := AbsynUtil.pathString(inName);
1369 2 env_str := NFSCodeEnv.getEnvName(inEnv);
1370 2 Error.addSourceMessage(error_id, {name_str, env_str}, inInfo);
1371 2 then
1372 fail();
1373
1374 end matchcontinue;
1375 end lookupName;
1376
1377 protected function joinPaths
1378 "Joins two paths, like AbsynUtil.joinPaths but not with quite the same behaviour.
1379 If the second path is fully qualified it just returns the cref, because then
1380 it has been looked up through an import and already points directly at the
1381 class. If the first path is fully qualified it joins the paths, and return a
1382 fully qualified path. Otherwise it has the same behaviour as AbsynUtil.joinPaths,
1383 i.e. it simply joins the paths."
1384 input Absyn.Path inPath1;
1385 input Absyn.Path inPath2;
1386 output Absyn.Path outPath;
1387 algorithm
1388 outPath := match(inPath1, inPath2)
1389 local
1390 Absyn.Ident id;
1391 Absyn.Path path;
1392
1393 // The second path is fully qualified, return only that path.
1394 case (_, Absyn.FULLYQUALIFIED()) then inPath2;
1395
1396 // Neither of the paths are fully qualified, just join them.
1397 48232347 case (Absyn.IDENT(name = id), _) then Absyn.QUALIFIED(id, inPath2);
1398 case (Absyn.QUALIFIED(name = id, path = path), _)
1399 algorithm
1400 47567 path := joinPaths(path, inPath2);
1401 47567 then
1402 Absyn.QUALIFIED(id, path);
1403
1404 // The first path is fully qualified, merge it with the second path and
1405 // return the result as a fully qualified path.
1406 case (Absyn.FULLYQUALIFIED(path = path), _)
1407 algorithm
1408 23525 path := joinPaths(path, inPath2);
1409 23525 then
1410 AbsynUtil.makeFullyQualified(path);
1411 end match;
1412 end joinPaths;
1413
1414 public function lookupNameSilent
1415 "Looks up a name, but doesn't print an error message if it fails."
1416 input Absyn.Path inName;
1417 input Env inEnv;
1418 input SourceInfo inInfo;
1419 output Item outItem;
1420 output Absyn.Path outName;
1421 output Env outEnv;
1422 algorithm
1423 522245 (outItem, outName, outEnv) := lookupName(inName, inEnv,
1424 LOOKUP_ANY(), inInfo, NONE());
1425 end lookupNameSilent;
1426
1427 public function lookupNameSilentNoBuiltin
1428 input Absyn.Path inName;
1429 input Env inEnv;
1430 input SourceInfo inInfo;
1431 output Item outItem;
1432 output Absyn.Path outName;
1433 output Env outEnv;
1434 algorithm
1435 136312 (outItem, outName, outEnv) := lookupName(inName, inEnv,
1436 NO_BUILTIN_TYPES(), inInfo, NONE());
1437 end lookupNameSilentNoBuiltin;
1438
1439 public function lookupClassName
1440 "Calls lookupName with the 'Class not found' error message."
1441 input Absyn.Path inName;
1442 input Env inEnv;
1443 input SourceInfo inInfo;
1444 output Item outItem;
1445 output Absyn.Path outName;
1446 output Env outEnv;
1447 algorithm
1448 157491 (outItem, outName, outEnv) := lookupName(inName, inEnv, LOOKUP_ANY(),
1449 inInfo, SOME(Error.LOOKUP_ERROR));
1450 end lookupClassName;
1451
1452 public function lookupBaseClassName
1453 "Calls lookupName with the 'Baseclass not found' error message."
1454 input Absyn.Path inName;
1455 input Env inEnv;
1456 input SourceInfo inInfo;
1457 output Item outItem;
1458 output Absyn.Path outName;
1459 output Env outEnv;
1460 algorithm
1461 (outItem, outName, outEnv) := match(inName, inEnv)
1462 local
1463 Absyn.Ident id;
1464 Env env;
1465 Item item;
1466 Absyn.Path path;
1467
1468 // Special case for the baseclass of a class extends. Should be looked up
1469 // among the inherited elements of the enclosing class.
1470 case (Absyn.QUALIFIED(name = "$ce", path = path as Absyn.IDENT(name = id)), _ :: env)
1471 algorithm
1472 16734 (item, env) := lookupInheritedName(id, env);
1473 16734 then
1474 (item, path, env);
1475
1476 // The extends was marked as erroneous in the qualifying phase, print an error.
1477 case (Absyn.QUALIFIED(name = "$E"), _)
1478 algorithm
1479 2 NFEnvExtends.printExtendsError(inName, inEnv, inInfo);
1480 2 then
1481 fail();
1482
1483 // Normal baseclass.
1484 else
1485 algorithm
1486 19776915 (item, path, env) := lookupName(inName, inEnv, LOOKUP_ANY(), inInfo,
1487 SOME(Error.LOOKUP_BASECLASS_ERROR));
1488 then
1489 (item, path, env);
1490
1491 end match;
1492 end lookupBaseClassName;
1493
1494 public function lookupVariableName
1495 "Calls lookupName with the 'Variable not found' error message."
1496 input Absyn.Path inName;
1497 input Env inEnv;
1498 input SourceInfo inInfo;
1499 output Item outItem;
1500 output Absyn.Path outName;
1501 output Env outEnv;
1502 algorithm
1503 ✗ (outItem, outName, outEnv) := lookupName(inName, inEnv, NO_BUILTIN_TYPES(),
1504 inInfo, SOME(Error.LOOKUP_VARIABLE_ERROR));
1505 end lookupVariableName;
1506
1507 public function lookupFunctionName
1508 "Calls lookupName with the 'Function not found' error message."
1509 input Absyn.Path inName;
1510 input Env inEnv;
1511 input SourceInfo inInfo;
1512 output Item outItem;
1513 output Absyn.Path outName;
1514 output Env outEnv;
1515 algorithm
1516 ✗ (outItem, outName, outEnv) := lookupName(inName, inEnv,
1517 NO_BUILTIN_TYPES(), inInfo, SOME(Error.LOOKUP_FUNCTION_ERROR));
1518 end lookupFunctionName;
1519
1520 protected function crefStripEnvPrefix
1521 "Removes the entire environment prefix from the given component reference, or
1522 returns the unchanged reference. This is done because models might import
1523 local packages, for example:
1524
1525 package P
1526 import myP = InsideP;
1527
1528 package InsideP
1529 function f end f;
1530 end InsideP;
1531
1532 constant c = InsideP.f();
1533 end P;
1534
1535 package P2
1536 extends P;
1537 end P2;
1538
1539 When P2 is instantiated all elements from P will be brought into P2's scope
1540 due to the extends. The binding of c will still point to P.InsideP.f though, so
1541 the lookup will try to instantiate P which might fail if P is a partial
1542 package or for other reasons. This is really a bug in Lookup (it shouldn't
1543 need to instantiate the whole package just to find a function), but to work
1544 around this problem for now this function will remove the environment prefix
1545 when InsideP.f is looked up in P, so that it resolves to InsideP.f and not
1546 P.InsideP.f. This allows P2 to find it in the local scope instead, since the
1547 InsideP package has been inherited from P."
1548 input Absyn.ComponentRef inCref;
1549 input Env inEnv;
1550 output Absyn.ComponentRef outCref;
1551 algorithm
1552 outCref := matchcontinue inEnv
1553 local
1554 Absyn.Path env_path;
1555 Absyn.ComponentRef cref1, cref2;
1556
1557 case _
1558 algorithm
1559
1/2
✓ Branch 1 taken 231649 times.
✗ Branch 2 not taken.
231649 false := Flags.isSet(Flags.STRIP_PREFIX);
1560 then inCref;
1561
1562 case _
1563 algorithm
1564 // Don't do this if -d=newInst is used, it messed up the new
1565 // instantiation which handles this correctly.
1566
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 231649 times.
231649 false := Flags.isSet(Flags.SCODE_INST);
1567 231649 env_path := NFSCodeEnv.getEnvPath(inEnv);
1568 231649 cref1 := AbsynUtil.unqualifyCref(inCref);
1569 // try to strip as much as possible
1570 231649 cref2 := crefStripEnvPrefix2(cref1, env_path);
1571 // check if we really did anything, fail if we did nothing!
1572
2/2
✓ Branch 1 taken 507 times.
✓ Branch 2 taken 2046 times.
2553 false := AbsynUtil.crefEqual(cref1, cref2);
1573 then
1574 cref2;
1575
1576 else inCref;
1577 end matchcontinue;
1578 end crefStripEnvPrefix;
1579
1580 protected function crefStripEnvPrefix2
1581 input Absyn.ComponentRef inCref;
1582 input Absyn.Path inEnvPath;
1583 output Absyn.ComponentRef outCref;
1584 algorithm
1585 outCref := matchcontinue(inCref, inEnvPath)
1586 local
1587 Absyn.Ident id1, id2;
1588 Absyn.ComponentRef cref;
1589 Absyn.Path env_path;
1590
1591 case (Absyn.CREF_QUAL(name = id1, subscripts = {}, componentRef = cref),
1592 Absyn.QUALIFIED(name = id2, path = env_path))
1593 algorithm
1594
4/4
✓ Branch 0 taken 17939 times.
✓ Branch 1 taken 52686 times.
✓ Branch 3 taken 16581 times.
✓ Branch 4 taken 1358 times.
70625 true := stringEqual(id1, id2);
1595 16581 then
1596 crefStripEnvPrefix2(cref, env_path);
1597
1598 case (Absyn.CREF_QUAL(name = id1, subscripts = {}, componentRef = cref),
1599 Absyn.IDENT(name = id2))
1600 algorithm
1601
4/4
✓ Branch 0 taken 307 times.
✓ Branch 1 taken 2246 times.
✓ Branch 3 taken 306 times.
✓ Branch 4 taken 1 time.
2553 true := stringEqual(id1, id2);
1602 then
1603 cref;
1604
1605 // adrpo: leave it as stripped as you can if you can't match it above!
1606 case (Absyn.CREF_QUAL(name = id1, subscripts = {}),
1607 Absyn.IDENT(name = id2))
1608 algorithm
1609
3/4
✓ Branch 0 taken 306 times.
✓ Branch 1 taken 2246 times.
✓ Branch 3 taken 306 times.
✗ Branch 4 not taken.
2552 false := stringEqual(id1, id2);
1610 then
1611 inCref;
1612 end matchcontinue;
1613 end crefStripEnvPrefix2;
1614
1615 public function lookupComponentRef
1616 "Look up a component reference in the environment and returns it fully
1617 qualified."
1618 input Absyn.ComponentRef inCref;
1619 input Env inEnv;
1620 input SourceInfo inInfo;
1621 output Absyn.ComponentRef outCref;
1622 algorithm
1623 outCref := matchcontinue inCref
1624 local
1625 Absyn.ComponentRef cref;
1626
1627 // Special case for StateSelect, do nothing.
1628 case Absyn.CREF_QUAL(name = "StateSelect", subscripts = {},
1629 componentRef = Absyn.CREF_IDENT())
1630 then inCref;
1631
1632 // Wildcard.
1633 case Absyn.WILD() then inCref;
1634
1635 // All other component references.
1636 case _
1637 algorithm
1638 // First look up all subscripts, because all subscripts should be found
1639 // in the enclosing scope of the component reference.
1640 234315 cref := NFSCodeFlattenImports.flattenComponentRefSubs(inCref, inEnv, inInfo);
1641 // Then look up the component reference itself.
1642 234315 (cref,_) := lookupComponentRef2(cref, inEnv);
1643 231649 cref := crefStripEnvPrefix(cref, inEnv);
1644 then
1645 cref;
1646
1647 else inCref;
1648
1649 end matchcontinue;
1650 end lookupComponentRef;
1651
1652 protected function lookupComponentRef2
1653 "Helper function to lookupComponentRef. Does the actual look up of the
1654 component reference."
1655 input Absyn.ComponentRef inCref;
1656 input Env inEnv;
1657 output Absyn.ComponentRef outCref;
1658 output Env outEnv;
1659 algorithm
1660 (outCref, outEnv) := match inCref
1661 local
1662 Absyn.ComponentRef cref, rest_cref;
1663 Absyn.Ident name;
1664 list<Absyn.Subscript> subs;
1665 Absyn.Path path, new_path;
1666 Env env;
1667 Item item;
1668
1669 // A simple name.
1670 case Absyn.CREF_IDENT(name, subs)
1671 algorithm
1672 175950 (_, path, env) := lookupSimpleName(name, inEnv);
1673 174944 cref := AbsynUtil.pathToCrefWithSubs(path, subs);
1674 174944 then
1675 (cref, env);
1676
1677 // A qualified name.
1678 case Absyn.CREF_QUAL(name, subs, rest_cref)
1679 algorithm
1680 // Lookup the first identifier.
1681 56778 (item, new_path, env) := lookupSimpleName(name, inEnv);
1682 56705 cref := AbsynUtil.pathToCrefWithSubs(new_path, subs);
1683
1684 // Lookup the rest of the cref in the enclosing scope of the first
1685 // identifier.
1686 56705 (item, rest_cref) := lookupCrefInItem(rest_cref, item, env);
1687 56705 cref := joinCrefs(cref, rest_cref);
1688 56705 then
1689 (cref, env);
1690
1691 // A fully qualified name.
1692 case Absyn.CREF_FULLYQUALIFIED(componentRef = cref)
1693 algorithm
1694 1587 cref := lookupCrefFullyQualified(cref, inEnv);
1695 ✗ env := NFSCodeEnv.getEnvTopScope(inEnv);
1696 then
1697 (cref, env);
1698
1699 end match;
1700 end lookupComponentRef2;
1701
1702 public function lookupCrefFullyQualified
1703 input Absyn.ComponentRef inCref;
1704 input Env inEnv;
1705 output Absyn.ComponentRef outCref;
1706 protected
1707 Env env;
1708 algorithm
1709 1587 env := NFSCodeEnv.getEnvTopScope(inEnv);
1710 1587 (_, outCref) := lookupCrefInPackage(inCref, inEnv);
1711 ✗ outCref := AbsynUtil.crefMakeFullyQualified(outCref);
1712 end lookupCrefFullyQualified;
1713
1714 public function joinCrefs
1715 "Joins two component references. If the second cref is fully qualified it just
1716 returns the cref, because then it has been looked up through an import and
1717 already points directly at the class. Otherwise it just calls AbsynUtil.joinCrefs."
1718 input Absyn.ComponentRef inCref1;
1719 input Absyn.ComponentRef inCref2;
1720 output Absyn.ComponentRef outCref;
1721 algorithm
1722 outCref := match inCref2
1723 case Absyn.CREF_FULLYQUALIFIED() then inCref2;
1724 56705 else AbsynUtil.joinCrefs(inCref1, inCref2);
1725 end match;
1726 end joinCrefs;
1727
1728 public function lookupTypeSpec
1729 "Looks up a type specification and returns the environment item and enclosing
1730 scopes of the type."
1731 input Absyn.TypeSpec inTypeSpec;
1732 input Env inEnv;
1733 input SourceInfo inInfo;
1734 output Item outItem;
1735 output Absyn.TypeSpec outTypeSpec;
1736 output Env outTypeEnv;
1737 algorithm
1738 (outItem, outTypeSpec, outTypeEnv) := match inTypeSpec
1739 local
1740 Absyn.Path path, newpath;
1741 Absyn.Ident name;
1742 Item item;
1743 Env env;
1744 SCode.Element cls;
1745 Option<Absyn.ArrayDim> ad;
1746
1747 // A normal type.
1748 case Absyn.TPATH(path, ad)
1749 algorithm
1750 104018 (item, newpath, env) := lookupClassName(path, inEnv, inInfo);
1751 104016 then
1752 (item, Absyn.TPATH(newpath, ad), env);
1753
1754 // A MetaModelica type such as list or tuple.
1755 case Absyn.TCOMPLEX(path = Absyn.IDENT(name = name))
1756 algorithm
1757 67 cls := makeDummyMetaType(name);
1758 67 then
1759 (NFSCodeEnv.CLASS(cls, NFSCodeEnv.emptyEnv, NFSCodeEnv.BASIC_TYPE()),
1760 inTypeSpec,
1761 NFSCodeEnv.emptyEnv);
1762
1763 end match;
1764 end lookupTypeSpec;
1765
1766 protected function makeDummyMetaType
1767 input String inTypeName;
1768 output SCode.Element outClass;
1769 algorithm
1770 67 outClass :=
1771 SCode.CLASS(
1772 inTypeName,
1773 SCode.defaultPrefixes,
1774 SCode.NOT_ENCAPSULATED(), SCode.NOT_PARTIAL(), SCode.R_TYPE(),
1775 SCode.PARTS({}, {}, {}, {}, {}, {}, {}, NONE()), SCode.noComment, Absyn.dummyInfo);
1776 end makeDummyMetaType;
1777
1778 public function qualifyPath
1779 "Qualifies a path by looking up a path in the environment, and merging the
1780 resulting path with it's environment."
1781 input Absyn.Path inPath;
1782 input Env inEnv;
1783 input SourceInfo inInfo;
1784 input Option<ErrorTypes.Message> inErrorType;
1785 output Absyn.Path outPath;
1786 algorithm
1787 outPath := matchcontinue inPath
1788 local
1789 Absyn.Ident id;
1790 Absyn.Path path;
1791 Env env;
1792
1793 // Never fully qualify builtin types.
1794 case Absyn.IDENT(name = id)
1795 algorithm
1796 ✗ lookupBuiltinType(id);
1797 then
1798 inPath;
1799
1800 case _
1801 algorithm
1802 ✗ (_, path, env) := lookupName(inPath, inEnv, NO_BUILTIN_TYPES(),
1803 inInfo, inErrorType);
1804 ✗ path := NFSCodeEnv.mergePathWithEnvPath(path, env);
1805 ✗ path := AbsynUtil.makeFullyQualified(path);
1806 then
1807 path;
1808
1809 else
1810 algorithm
1811 ✗ true := Flags.isSet(Flags.FAILTRACE);
1812 ✗ Debug.traceln("- NFSCodeLookup.qualifyPath failed on " +
1813 AbsynUtil.pathString(inPath) + " in " +
1814 NFSCodeEnv.getEnvName(inEnv));
1815 ✗ then
1816 fail();
1817 end matchcontinue;
1818 end qualifyPath;
1819
1820 annotation(__OpenModelica_Interface="frontend");
1821 end NFSCodeLookup;
1822