Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 70.0% 156 / 0 / 223
Functions: -% 0 / 1 / 1
Branches: 50.0% 47 / 0 / 94

OMCompiler/Compiler/FrontEnd/InnerOuter.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 InnerOuter
37 " file: InnerOuter.mo
38 package: InnerOuter
39 description: Instance hierarchy and functionality to deal with Inner/Outer definitions"
40
41
42 import Absyn;
43 import DAE.Connect;
44 import ConnectionGraph;
45 import DAE;
46 import FCore;
47 import FNode;
48 import SCode;
49 import UnitAbsyn;
50 import HashSet;
51
52 protected import Array;
53 protected import ComponentReference;
54 protected import ComponentReferenceBasics;
55 protected import ConnectUtil;
56 protected import DAEUtil;
57 protected import Debug;
58 protected import ElementSource;
59 protected import Error;
60 protected import ErrorExt;
61 protected import Flags;
62 protected import InstSection;
63 protected import List;
64 protected import Lookup;
65 protected import Mod;
66 protected import PrefixUtil;
67 protected import Util;
68 protected import BaseHashSet;
69 protected import FGraph;
70
71 public
72 type Cache = FCore.Cache;
73
74 uniontype InstResult
75 record INST_RESULT
76 Cache outCache;
77 FCore.Graph outEnv;
78 UnitAbsyn.InstStore outStore;
79 DAE.DAElist outDae;
80 Connect.Sets outSets;
81 DAE.Type outType;
82 ConnectionGraph.ConnectionGraph outGraph;
83 end INST_RESULT;
84 end InstResult;
85
86 uniontype InstInner
87 record INST_INNER
88 DAE.Prefix innerPrefix "the prefix of the inner. we need it to prefix the outer variables with it!";
89 SCode.Ident name;
90 Absyn.InnerOuter io;
91 String fullName "full inner component name";
92 Absyn.Path typePath "the type of the inner";
93 String scope "the scope of the inner";
94 Option<InstResult> instResult;
95 list<DAE.ComponentRef> outers "which outers are referencing this inner";
96 Option<SCode.Element> innerElement "class or component";
97 end INST_INNER;
98 end InstInner;
99
100 uniontype OuterPrefix
101 record OUTER
102 DAE.ComponentRef outerComponentRef "the prefix of this outer + component name";
103 DAE.ComponentRef innerComponentRef "the coresponding prefix for this outer + component name";
104 end OUTER;
105 end OuterPrefix;
106
107 type OuterPrefixes = list<OuterPrefix>;
108
109 constant OuterPrefixes emptyOuterPrefixes = {} "empty outer prefixes";
110
111 public
112 type Key = DAE.ComponentRef "the prefix + '.' + the component name";
113 type Value = InstInner "the inputs of the instantiation function and the results";
114
115 uniontype TopInstance "a top instance is an instance of a model thar resides at top level"
116 record TOP_INSTANCE
117 Option<Absyn.Path> path "top model path";
118 InstHierarchyHashTable ht "hash table with fully qualified components";
119 OuterPrefixes outerPrefixes "the outer prefixes help us prefix the outer components with the correct prefix of inner component directly";
120 HashSet.HashSet sm "Set of synchronous SM states (fully qualified components)";
121 end TOP_INSTANCE;
122 end TopInstance;
123
124 type InstHierarchy = list<TopInstance>;
125
126 constant InstHierarchy emptyInstHierarchy = {}
127 "an empty instance hierarchy";
128
129 public function handleInnerOuterEquations
130 "Author: BZ, 2008-12
131 Depending on the inner outer declaration we do
132 different things for dae declared for a variable.
133 If it is an outer variable, we remove all equations
134 (will be declared again in the inner part).
135 If it is InnerOuter declared, we rename all the crefs
136 in this equation to unique vars, while we want to keep
137 them with this prefix for the inner part of the innerouter."
138 input Absyn.InnerOuter io;
139 input DAE.DAElist inDae;
140 input InstHierarchy inIH;
141 input ConnectionGraph.ConnectionGraph inGraphNew;
142 input ConnectionGraph.ConnectionGraph inGraph;
143 output DAE.DAElist odae;
144 output InstHierarchy outIH;
145 output ConnectionGraph.ConnectionGraph outGraph;
146 algorithm
147 (odae,outIH,outGraph) := matchcontinue(io,inDae,inIH,inGraphNew,inGraph)
148 local
149 DAE.DAElist dae1,dae2,dae;
150 ConnectionGraph.ConnectionGraph graphNew,graph;
151 InstHierarchy ih;
152 // is an outer, remove equations
153 // outer components do NOT change the connection graph!
154 case (Absyn.OUTER(),dae,ih,_,graph)
155 algorithm
156 697 (odae,_) := DAEUtil.splitDAEIntoVarsAndEquations(dae);
157 then
158 (odae,ih,graph);
159 // is both an inner and an outer,
160 // rename inner vars in the equations to unique names
161 // innerouter component change the connection graph
162 case (Absyn.INNER_OUTER(),dae,ih,_,graph)
163 algorithm
164 4 (dae1,dae2) := DAEUtil.splitDAEIntoVarsAndEquations(dae);
165 // rename variables in the equations and algs.
166 // inner vars from dae1 are kept with the same name.
167 4 dae2 := DAEUtil.nameUniqueOuterVars(dae2);
168
169 4 dae := DAEUtil.joinDaes(dae1,dae2);
170 // adrpo: TODO! FIXME: here we should do a difference of graphNew-graph
171 // and rename the new equations added with unique vars.
172 then
173 (dae,ih,graph);
174 // is an inner do nothing
175 case (Absyn.INNER(),dae,ih,graphNew,_) then (dae,ih,graphNew);
176 // is not an inner nor an outer
177 case (Absyn.NOT_INNER_OUTER (),dae,ih,graphNew,_) then (dae,ih,graphNew);
178 // something went totally wrong!
179 else
180 algorithm
181 ✗ print("- InnerOuter.handleInnerOuterEquations failed!\n");
182 ✗ then fail();
183 end matchcontinue;
184 end handleInnerOuterEquations;
185
186 public function changeInnerOuterInOuterConnect
187 "changes inner to outer and outer to inner where needed"
188 input output Connect.Sets sets;
189 algorithm
190 159882 sets.outerConnects := List.map(sets.outerConnects, changeInnerOuterInOuterConnect2);
191 end changeInnerOuterInOuterConnect;
192
193 protected function changeInnerOuterInOuterConnect2
194 "@author: adrpo
195 changes inner to outer and outer to inner where needed"
196 input Connect.OuterConnect inOC;
197 output Connect.OuterConnect outOC;
198 algorithm
199 outOC := matchcontinue inOC
200 local
201 DAE.ComponentRef cr1,cr2,ncr1,ncr2;
202 Absyn.InnerOuter io1,io2;
203 Connect.Face f1,f2;
204 DAE.Prefix scope;
205 DAE.ElementSource source "the origin of the element";
206
207 // the left hand side is an outer!
208 case Connect.OUTERCONNECT(scope,cr1,io1,f1,cr2,io2,f2,source)
209 algorithm
210
2/2
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 8 times.
22 (_,true) := innerOuterBooleans(io1);
211 8 ncr1 := PrefixUtil.prefixToCref(scope);
212 // fprintln(Flags.IOS, "changeInnerOuterInOuterConnect: changing left: " +
213 // ComponentReferenceBasics.printComponentRefStr(cr1) + " to inner");
214
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 false := ComponentReferenceBasics.crefFirstCrefLastCrefEqual(ncr1,cr1);
215 8 then
216 Connect.OUTERCONNECT(scope,cr1,Absyn.INNER(),f1,cr2,io2,f2,source);
217
218 // the right hand side is an outer!
219 case Connect.OUTERCONNECT(scope,cr1,io1,f1,cr2,io2,f2,source)
220 algorithm
221
2/2
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 2 times.
14 (_,true) := innerOuterBooleans(io2);
222 2 ncr2 := PrefixUtil.prefixToCref(scope);
223 // fprintln(Flags.IOS, "changeInnerOuterInOuterConnect: changing right: " +
224 // ComponentReferenceBasics.printComponentRefStr(cr2) + " to inner");
225
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 false := ComponentReferenceBasics.crefFirstCrefLastCrefEqual(ncr2,cr2);
226 2 then
227 Connect.OUTERCONNECT(scope,cr1,io1,f1,cr2,Absyn.INNER(),f2,source);
228
229 // none of left or right hand side are outer
230 else inOC;
231 end matchcontinue;
232 end changeInnerOuterInOuterConnect2;
233
234 public function retrieveOuterConnections
235 "Moves outerConnections to connection sets
236 author PA:
237 This function moves the connections put in outerConnects to the connection
238 set, if a corresponding innner component can be found in the environment.
239 If not, they are kept in the outerConnects for use higher up in the instance
240 hierarchy."
241 input FCore.Cache inCache;
242 input FCore.Graph inEnv;
243 input InstHierarchy inIH;
244 input DAE.Prefix inPrefix;
245 input Connect.Sets inSets;
246 input Boolean inTopCall;
247 input ConnectionGraph.ConnectionGraph inCGraph;
248 output Connect.Sets outSets;
249 output list<Connect.OuterConnect> outInnerOuterConnects;
250 output ConnectionGraph.ConnectionGraph outCGraph;
251 protected
252 list<Connect.OuterConnect> oc;
253 algorithm
254 898893 Connect.SETS(outerConnects = oc) := inSets;
255 898893 (oc, outSets, outInnerOuterConnects, outCGraph) :=
256 retrieveOuterConnections2(inCache, inEnv, inIH, inPrefix, oc, inSets, inTopCall, inCGraph);
257
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 898893 times.
898893 outSets.outerConnects := oc;
258 end retrieveOuterConnections;
259
260 protected function removeInnerPrefixFromCref
261 "@author: adrpo
262 This function will strip the given prefix from the component references."
263 input DAE.Prefix inPrefix;
264 input DAE.ComponentRef inCref;
265 output DAE.ComponentRef outCref;
266 algorithm
267 outCref := matchcontinue inPrefix
268 local
269 DAE.ComponentRef crefPrefix, crOuter;
270
271 // no prefix to strip, return the cref!
272 case DAE.NOPRE() then inCref;
273
274 // we have a prefix, remove it from the cref
275 case _
276 algorithm
277 // transform prefix into cref
278 ✗ crefPrefix := PrefixUtil.prefixToCref(inPrefix);
279 // remove the prefix from the component reference
280 ✗ crOuter := ComponentReference.crefStripPrefix(inCref, crefPrefix);
281 then
282 crOuter;
283
284 // something went wrong, print a failtrace and then
285 else
286 algorithm
287 //true = Flags.isSet(Flags.FAILTRACE);
288 //Debug.traceln("- InnerOuter.removeInnerPrefixFromCref failed on prefix: " + PrefixUtil.printPrefixStr(inPrefix) +
289 // " cref: " + ComponentReferenceBasics.printComponentRefStr(inCref));
290 then
291 inCref;
292 end matchcontinue;
293 end removeInnerPrefixFromCref;
294
295 protected function retrieveOuterConnections2
296 "help function to retrieveOuterConnections"
297 input FCore.Cache inCache;
298 input FCore.Graph inEnv;
299 input InstHierarchy inIH;
300 input DAE.Prefix inPrefix;
301 input list<Connect.OuterConnect> inOuterConnects;
302 input Connect.Sets inSets;
303 input Boolean inTopCall;
304 input ConnectionGraph.ConnectionGraph inCGraph;
305 output list<Connect.OuterConnect> outOuterConnects;
306 output Connect.Sets outSets;
307 output list<Connect.OuterConnect> outInnerOuterConnects;
308 output ConnectionGraph.ConnectionGraph outCGraph;
309 algorithm
310 (outOuterConnects, outSets, outInnerOuterConnects, outCGraph) :=
311 matchcontinue(inOuterConnects, inSets, inTopCall, inCGraph)
312 local
313 DAE.ComponentRef cr1, cr2;
314 Absyn.InnerOuter io1, io2;
315 Connect.Face f1, f2;
316 Connect.OuterConnect oc;
317 list<Connect.OuterConnect> rest_oc, ioc;
318 Boolean inner1, inner2, outer1, outer2, added;
319 DAE.Prefix scope;
320 DAE.ElementSource source "the origin of the element";
321 SourceInfo info;
322 Connect.Sets sets;
323 ConnectionGraph.ConnectionGraph graph;
324
325 // handle empty
326 898893 case ({}, _, _, _) then (inOuterConnects, inSets, {}, inCGraph);
327
328 // an inner only outer connect
329 case(Connect.OUTERCONNECT(scope, cr1, io1, f1, cr2, io2, f2,
330 source as DAE.SOURCE(info = info)) :: rest_oc, sets, _, graph)
331 algorithm
332 27 (inner1, outer1) := lookupVarInnerOuterAttr(inCache, inEnv, inIH, cr1, cr2);
333
334
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 7 times.
20 true := inner1;
335
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
7 false := outer1;
336
337 // remove the prefixes so we can find it in the DAE
338 4 cr1 := removeInnerPrefixFromCref(inPrefix, cr1);
339 4 cr2 := removeInnerPrefixFromCref(inPrefix, cr2);
340
341 4 (sets, added) := ConnectUtil.addOuterConnectToSets(cr1, cr2, io1, io2, f1, f2, sets, info);
342
343 // if no connection set available (added = false), create new one
344 4 (sets, graph) := addOuterConnectIfEmpty(inCache, inEnv, inIH, inPrefix, sets,
345 added, cr1, io1, f1, cr2, io2, f2, info, graph);
346
347 4 (rest_oc, sets, ioc, graph) :=
348 retrieveOuterConnections2(inCache, inEnv, inIH, inPrefix, rest_oc, sets, inTopCall, graph);
349
350 // if is also outer, then keep it also in the outer connects
351 rest_oc := if outer1 then Connect.OUTERCONNECT(scope, cr1, io1, f1, cr2, io2, f2, source) :: rest_oc else rest_oc;
352 4 then
353 (rest_oc, sets, ioc, graph);
354
355 // this case is for innerouter declarations, since we do not have them in environment we need to treat them in a special way
356 case(Connect.OUTERCONNECT(_, cr1, io1, f1, cr2, io2, f2,
357 DAE.SOURCE(info = info)) :: rest_oc, sets, true, graph)
358 algorithm
359 6 (inner1, outer1) := innerOuterBooleans(io1);
360 6 (inner2, outer2) := innerOuterBooleans(io2);
361
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 true := boolOr(inner1, inner2); // for inner outer we set Absyn.INNER()
362
2/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
6 false := boolOr(outer1, outer2);
363
364 6 io1 := convertInnerOuterInnerToOuter(io1); // we need to change from inner to outer to be able to join sets in: addOuterConnectToSets
365 6 io2 := convertInnerOuterInnerToOuter(io2);
366
367 6 (sets, added) := ConnectUtil.addOuterConnectToSets(cr1, cr2, io1, io2, f1, f2, sets, info);
368 // If no connection set available (added = false), create new one
369 6 (sets, graph) := addOuterConnectIfEmpty(inCache, inEnv, inIH, inPrefix, sets,
370 added, cr1, io1, f1, cr2, io2, f2, info, graph);
371 6 (rest_oc, sets, ioc, graph) :=
372 retrieveOuterConnections2(inCache, inEnv, inIH, inPrefix, rest_oc, sets, true, graph);
373 then
374 (rest_oc, sets, ioc, graph);
375
376 // just keep the outer connects the same if we don't find them in the same scope
377 case(oc :: rest_oc, sets, _, graph)
378 algorithm
379 17 (rest_oc, sets, ioc, graph) :=
380 retrieveOuterConnections2(inCache, inEnv, inIH, inPrefix, rest_oc, sets, inTopCall, graph);
381 17 then
382 (oc :: rest_oc, sets, ioc, graph);
383 end matchcontinue;
384 end retrieveOuterConnections2;
385
386 protected function convertInnerOuterInnerToOuter
387 "Author: BZ, 2008-12
388 Change from Absyn.INNER => Absyn.OUTER,
389 this to be able to use normal functions
390 for the innerouter declared variables/connections."
391 input Absyn.InnerOuter io;
392 output Absyn.InnerOuter oio;
393 algorithm
394 oio := match io
395 case Absyn.INNER() then Absyn.OUTER();
396 else io;
397 end match;
398 end convertInnerOuterInnerToOuter;
399
400 protected function addOuterConnectIfEmpty
401 "help function to retrieveOuterConnections2
402 author PA.
403 Adds a new connectionset if inner component
404 found but no connection set refering to the
405 inner component. In that is case the outer
406 connection (from inside sub-components) forms
407 a connection set of their own."
408 input FCore.Cache inCache;
409 input FCore.Graph inEnv;
410 input InstHierarchy inIH;
411 input DAE.Prefix pre;
412 input Connect.Sets inSets;
413 input Boolean added "if true, this function does nothing";
414 input DAE.ComponentRef cr1;
415 input Absyn.InnerOuter iio1;
416 input Connect.Face f1;
417 input DAE.ComponentRef cr2;
418 input Absyn.InnerOuter iio2;
419 input Connect.Face f2;
420 input SourceInfo info;
421 input ConnectionGraph.ConnectionGraph inCGraph;
422 output Connect.Sets outSets;
423 output ConnectionGraph.ConnectionGraph outCGraph;
424 algorithm
425 (outSets, outCGraph) := match(inCache, inEnv, inIH, inSets, added, iio1, iio2, inCGraph)
426 local
427 SCode.Variability vt1,vt2;
428 DAE.Type t1,t2;
429 DAE.ConnectorType ct;
430 InstHierarchy ih;
431 Connect.SetTrie sets;
432 Integer sc;
433 list<Connect.SetConnection> cl;
434 list<Connect.OuterConnect> oc;
435 FCore.Cache cache;
436 FCore.Graph env;
437 Absyn.InnerOuter io1,io2;
438 ConnectionGraph.ConnectionGraph graph;
439
440 // if it was added, return the same
441 case(_, _, _, _, true, _, _, _)
442 then (inSets, inCGraph);
443
444 // if it was not added, add it (search for both components)
445 case(cache, env, ih, Connect.SETS(sets, sc, cl, oc), false, io1, io2, graph)
446 algorithm
447 10 (cache,DAE.ATTR(connectorType = ct, variability = vt1),t1,_,_,_,_,_,_) := Lookup.lookupVar(cache,env,cr1);
448 10 (cache,DAE.ATTR(variability = vt2),t2,_,_,_,_,_,_) := Lookup.lookupVar(cache,env,cr2);
449 10 io1 := removeOuter(io1);
450 10 io2 := removeOuter(io2);
451 10 (cache,env,ih, Connect.SETS(sets = sets, setCount = sc, connections = cl),_, graph) :=
452 InstSection.connectComponents(
453 cache,env,ih,
454 Connect.SETS(sets, sc, cl, {}),
455 pre,cr1,f1,t1,vt1,cr2,f2,t2,vt2,ct,io1,io2,
456 graph,info);
457 // TODO: take care of dae, can contain asserts from connections
458 10 then
459 (Connect.SETS(sets, sc, cl, oc), graph);
460
461 // This can fail, for innerouter, the inner part is not declared in env so instead the call to addOuterConnectIfEmptyNoEnv will succed.
462 else
463 algorithm
464 //print("Failed lookup: " + ComponentReferenceBasics.printComponentRefStr(cr1) + "\n");
465 //print("Failed lookup: " + ComponentReferenceBasics.printComponentRefStr(cr2) + "\n");
466 // print("#FAILURE# in: addOuterConnectIfEmpty:__ " + ComponentReferenceBasics.printComponentRefStr(cr1) + " " + ComponentReferenceBasics.printComponentRefStr(cr2) + "\n");
467 then fail();
468
469 end match;
470 end addOuterConnectIfEmpty;
471
472 protected function removeOuter
473 "Removes outer attribute, keeping inner"
474 input Absyn.InnerOuter io;
475 output Absyn.InnerOuter outIo;
476 algorithm
477 outIo := match io
478 case Absyn.OUTER() then Absyn.NOT_INNER_OUTER();
479 case Absyn.INNER() then Absyn.INNER();
480 case Absyn.INNER_OUTER() then Absyn.INNER();
481 case Absyn.NOT_INNER_OUTER() then Absyn.NOT_INNER_OUTER();
482 end match;
483 end removeOuter;
484
485 protected function lookupVarInnerOuterAttr
486 "searches for two variables in env and retrieves
487 its inner and outer attributes in form of booleans.
488 adrpo: Make sure that there are no error messages displayed!"
489 input FCore.Cache cache;
490 input FCore.Graph env;
491 input InstHierarchy inIH;
492 input DAE.ComponentRef cr1;
493 input DAE.ComponentRef cr2;
494 output Boolean isInner;
495 output Boolean isOuter;
496 algorithm
497 (isInner,isOuter) := matchcontinue cr2
498 local
499 Absyn.InnerOuter io,io1,io2;
500 Boolean isInner1,isInner2,isOuter1,isOuter2;
501 // Search for both
502 case _
503 algorithm
504 27 ErrorExt.setCheckpoint("lookupVarInnerOuterAttr");
505 27 (_,DAE.ATTR(innerOuter=io1),_,_,_,_,_,_,_) := Lookup.lookupVar(cache,env,cr1);
506 17 (_,DAE.ATTR(innerOuter=io2),_,_,_,_,_,_,_) := Lookup.lookupVar(cache,env,cr2);
507 10 (isInner1,isOuter1) := innerOuterBooleans(io1);
508 10 (isInner2,isOuter2) := innerOuterBooleans(io2);
509 10 isInner := isInner1 or isInner2;
510
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
10 isOuter := isOuter1 or isOuter2;
511 10 ErrorExt.rollBack("lookupVarInnerOuterAttr");
512 then
513 (isInner,isOuter);
514 // try to find var cr1 (lookup can fail for one of them)
515 case _
516 algorithm
517 17 (_,DAE.ATTR(innerOuter=io),_,_,_,_,_,_,_) := Lookup.lookupVar(cache,env,cr1);
518 7 (isInner,isOuter) := innerOuterBooleans(io);
519 7 ErrorExt.rollBack("lookupVarInnerOuterAttr");
520 7 then
521 (isInner,isOuter);
522 // ..else try cr2 (lookup can fail for one of them)
523 case _
524 algorithm
525 10 (_,DAE.ATTR(innerOuter=io),_,_,_,_,_,_,_) := Lookup.lookupVar(cache,env,cr2);
526 3 (isInner,isOuter) := innerOuterBooleans(io);
527 3 ErrorExt.rollBack("lookupVarInnerOuterAttr");
528 3 then (isInner,isOuter);
529 // failure
530 else
531 algorithm
532 7 ErrorExt.rollBack("lookupVarInnerOuterAttr");
533 7 then fail();
534 end matchcontinue;
535 end lookupVarInnerOuterAttr;
536
537 protected function innerOuterBooleans
538 "Returns inner outer information as two booleans"
539 input Absyn.InnerOuter io;
540 output Boolean inner1;
541 output Boolean outer1;
542 algorithm
543 (inner1,outer1) := match io
544 case Absyn.INNER() then (true,false);
545 case Absyn.OUTER() then (false,true);
546 case Absyn.INNER_OUTER() then (true,true);
547 case Absyn.NOT_INNER_OUTER() then (false,false);
548 end match;
549 end innerOuterBooleans;
550
551 public function outerConnection "Returns true if either Absyn.InnerOuter is OUTER."
552 input Absyn.InnerOuter io1;
553 input Absyn.InnerOuter io2;
554 output Boolean isOuter;
555 algorithm
556 isOuter := match(io1,io2)
557 case(Absyn.OUTER(),_) then true;
558 case(_,Absyn.OUTER()) then true;
559 case(Absyn.INNER_OUTER(),_) then true;
560 case(_,Absyn.INNER_OUTER()) then true;
561 else false;
562 end match;
563 end outerConnection;
564
565 protected function lookupInnerInIH
566 "@author: adrpo
567 Given an instance hierarchy and a component name find the
568 modification of the inner component with the same name"
569 input TopInstance inTIH;
570 input DAE.Prefix inPrefix;
571 input SCode.Ident inComponentIdent;
572 output InstInner outInstInner;
573 algorithm
574 outInstInner := matchcontinue(inTIH, inPrefix, inComponentIdent)
575 local
576 SCode.Ident name;
577 DAE.Prefix prefix;
578 InstHierarchyHashTable ht;
579 DAE.ComponentRef cref;
580 InstInner instInner;
581
582 // no prefix, this is an error!
583 // disabled as this is used in Interactive.getComponents
584 // and makes mosfiles/interactive_api_attributes.mos to fail!
585 case (TOP_INSTANCE(), DAE.PREFIX(compPre = DAE.NOCOMPPRE()), _)
586 ✗ then lookupInnerInIH(inTIH, DAE.NOPRE(), inComponentIdent);
587
588 // no prefix, this is an error!
589 // disabled as this is used in Interactive.getComponents
590 // and makes mosfiles/interactive_api_attributes.mos to fail!
591 case (TOP_INSTANCE(), DAE.NOPRE(), name)
592 algorithm
593 // fprintln(Flags.INNER_OUTER, "Error: outer component: " + name + " defined at the top level!");
594 // fprintln(Flags.INNER_OUTER, "InnerOuter.lookupInnerInIH : looking for: " + PrefixUtil.printPrefixStr(DAE.NOPRE()) + "/" + name + " REACHED TOP LEVEL!");
595 // TODO! add warning!
596 ✗ then emptyInstInner(DAE.NOPRE(), name);
597
598 // we have a prefix, remove the last cref from the prefix and search!
599 case (TOP_INSTANCE(_, ht, _, _), _, name)
600 algorithm
601 // back one step in the instance hierarchy
602
603 // fprintln(Flags.INNER_OUTER, "InnerOuter.lookupInnerInIH : looking for: " + PrefixUtil.printPrefixStr(inPrefix) + "/" + name);
604
605 1190 prefix := PrefixUtil.prefixStripLast(inPrefix);
606
607 // fprintln(Flags.INNER_OUTER, "InnerOuter.lookupInnerInIH : stripping and looking for: " + PrefixUtil.printPrefixStr(prefix) + "/" + name);
608
609 // put the name as the last prefix
610 1190 (_,cref) := PrefixUtil.prefixCref(FCore.emptyCache(), FGraph.empty(), emptyInstHierarchy, prefix, ComponentReferenceBasics.makeCrefIdent(name, DAE.T_UNKNOWN_DEFAULT, {}));
611
612 // search in instance hierarchy
613 1190 instInner := get(cref, ht);
614
615 // isInner = AbsynUtil.isInner(io);
616 // instInner = if_(isInner, instInner, emptyInstInner(inPrefix, name));
617 // fprintln(Flags.INNER_OUTER, "InnerOuter.lookupInnerInIH : Looking up: " +
618 // ComponentReferenceBasics.printComponentRefStr(cref) + " FOUND with innerPrefix: " +
619 // PrefixUtil.printPrefixStr(innerPrefix));
620 then
621 instInner;
622
623 // we have a prefix, search recursively as there was a failure before!
624 case (TOP_INSTANCE(_, ht, _, _), _, name)
625 algorithm
626 // back one step in the instance hierarchy
627 // fprintln(Flags.INNER_OUTER, "InnerOuter.lookupInnerInIH : looking for: " + PrefixUtil.printPrefixStr(inPrefix) + "/" + name);
628
629 491 prefix := PrefixUtil.prefixStripLast(inPrefix);
630
631 // fprintln(Flags.INNER_OUTER, "InnerOuter.lookupInnerInIH : stripping and looking for: " + PrefixUtil.printPrefixStr(prefix) + "/" + name);
632
633 // put the name as the last prefix
634 491 (_,cref) := PrefixUtil.prefixCref(FCore.emptyCache(), FGraph.empty(), emptyInstHierarchy, prefix, ComponentReferenceBasics.makeCrefIdent(name, DAE.T_UNKNOWN_DEFAULT, {}));
635
636 // search in instance hierarchy we had a failure
637
2/2
✓ Branch 0 taken 491 times.
✓ Branch 1 taken 491 times.
982 failure(get(cref, ht));
638
639 // fprintln(Flags.INNER_OUTER, "InnerOuter.lookupInnerInIH : Couldn't find: " + ComponentReferenceBasics.printComponentRefStr(cref) + " going deeper");
640
641 // call recursively to back one more step!
642 491 instInner := lookupInnerInIH(inTIH, prefix, name);
643 then
644 instInner;
645
646 // if we fail return nothing
647 case (TOP_INSTANCE(), prefix, name)
648 algorithm
649 // fprintln(Flags.INNER_OUTER, "InnerOuter.lookupInnerInIH : looking for: " + PrefixUtil.printPrefixStr(prefix) + "/" + name + " NOT FOUND!");
650 // dumpInstHierarchyHashTable(ht);
651 ✗ then
652 emptyInstInner(prefix, name);
653 end matchcontinue;
654 end lookupInnerInIH;
655
656 public function modificationOnOuter "
657 Author BZ, 2008-11
658 According to specification modifiers on outer elements is not allowed."
659 input FCore.Cache cache;
660 input FCore.Graph env;
661 input InstHierarchy ih;
662 input DAE.Prefix prefix;
663 input String componentName;
664 input DAE.ComponentRef cr;
665 input DAE.Mod inMod;
666 input Absyn.InnerOuter io;
667 input Boolean impl;
668 input SourceInfo inInfo;
669 output Boolean modd;
670 algorithm
671 modd := matchcontinue(inMod, io)
672 local
673 String s1,s2,s;
674 // if we don't have the same modification on inner report error!
675 case(DAE.MOD(), Absyn.OUTER())
676 algorithm
677 ✗ s1 := ComponentReferenceBasics.printComponentRefStr(cr);
678 ✗ s2 := Mod.prettyPrintMod(inMod, 0);
679 ✗ s := s1 + " " + s2;
680 ✗ Error.addSourceMessage(Error.OUTER_MODIFICATION, {s}, inInfo);
681 then
682 true;
683
684 else false;
685
686 end matchcontinue;
687 end modificationOnOuter;
688
689 public function switchInnerToOuterInGraph
690 "function switchInnerToOuterInGraph switches the inner to outer attributes of
691 a component in the Env."
692 input FCore.Graph inEnv;
693 input DAE.ComponentRef inCr;
694 output FCore.Graph outEnv;
695 algorithm
696 outEnv := match(inEnv,inCr)
697 local
698 DAE.ComponentRef cr;
699 FCore.Ref r;
700 FCore.Node n;
701 // handle nothingness
702 case (FCore.EG(_), _) then inEnv;
703 case (FCore.G(scope = {}), _) then inEnv;
704 // only need to handle top frame!
705 case (_, cr)
706 algorithm
707 45 r := FGraph.lastScopeRef(inEnv);
708 45 n := FNode.fromRef(r);
709 45 n := switchInnerToOuterInNode(n, cr);
710 45 r := FNode.updateRef(r, n);
711 then
712 inEnv;
713 end match;
714 end switchInnerToOuterInGraph;
715
716 protected function switchInnerToOuterInNode "
717 function switchInnerToOuterInFrame
718 switches the inner to outer attributes of a component in the Frame."
719 input FCore.Node inNode;
720 input DAE.ComponentRef inCr;
721 output FCore.Node outNode = inNode;
722 algorithm
723 () := match outNode
724 case FCore.N()
725 algorithm
726 90 outNode.children := FNode.RefTree.map(outNode.children,
727 function switchInnerToOuterInChild(cr = inCr));
728 then
729 ();
730
731 else ();
732 end match;
733 end switchInnerToOuterInNode;
734
735 protected function switchInnerToOuterInChild
736 input FCore.Name name;
737 input DAE.ComponentRef cr;
738 input FCore.Ref inRef;
739 output FCore.Ref ref;
740 protected
741 FCore.Node n;
742 algorithm
743 1329 n := FNode.fromRef(inRef);
744 1329 n := switchInnerToOuterInChildrenValue(n, cr);
745 1329 ref := FNode.updateRef(inRef, n);
746 end switchInnerToOuterInChild;
747
748 protected function switchInnerToOuterInChildrenValue "
749 function switchInnerToOuterInChildrenValue
750 switches the inner to outer attributes of a component in the RefTree."
751 input FCore.Node inNode;
752 input DAE.ComponentRef inCr;
753 output FCore.Node outNode;
754 algorithm
755 outNode := matchcontinue inNode
756 local
757 FCore.Ref r;
758 FCore.Node node;
759
760 DAE.Ident name;
761 DAE.Attributes attributes;
762 SCode.Visibility visibility;
763 DAE.Type ty;
764 DAE.Binding binding;
765 Boolean bndsrc;
766
767 DAE.ConnectorType ct;
768 SCode.Parallelism parallelism "parallelism";
769 SCode.Variability variability "variability" ;
770 Absyn.Direction direction "direction" ;
771 Option<DAE.Const> cnstForRange;
772
773 // inner
774 case node
775 algorithm
776 // get the instance child
777 1329 r := FNode.childFromNode(node, FNode.itNodeName);
778
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1311 times.
1311 FCore.IT(DAE.TYPES_VAR(name, attributes, ty, binding, bndsrc, cnstForRange)) := FNode.refData(r);
779
1/2
✓ Branch 0 taken 1311 times.
✗ Branch 1 not taken.
1311 DAE.ATTR(ct, parallelism, variability, direction, Absyn.INNER(), visibility) := attributes;
780 ✗ attributes := DAE.ATTR(ct, parallelism, variability, direction, Absyn.OUTER(), visibility);
781 // update the ref
782 ✗ r := FNode.updateRef(r, FNode.setData(FNode.fromRef(r),FCore.IT(DAE.TYPES_VAR(name, attributes, ty, binding, bndsrc, cnstForRange))));
783 // env = switchInnerToOuterInGraph(env, inCr);
784 then
785 node;
786
787 // inner outer
788 case node
789 algorithm
790 // get the instance child
791 1329 r := FNode.childFromNode(node, FNode.itNodeName);
792
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1311 times.
1311 FCore.IT(DAE.TYPES_VAR(name, attributes, ty, binding, bndsrc, cnstForRange)) := FNode.refData(r);
793
1/2
✓ Branch 0 taken 1311 times.
✗ Branch 1 not taken.
1311 DAE.ATTR(ct, parallelism, variability, direction, Absyn.INNER_OUTER(), visibility) := attributes;
794 ✗ attributes := DAE.ATTR(ct, parallelism, variability, direction, Absyn.OUTER(), visibility);
795 // update the ref
796 ✗ r := FNode.updateRef(r, FNode.setData(FNode.fromRef(r),FCore.IT(DAE.TYPES_VAR(name, attributes, ty, binding, bndsrc, cnstForRange))));
797 // env = switchInnerToOuterInGraph(env, inCr);
798 then
799 node;
800
801 // leave unchanged
802 case _ then inNode;
803
804 end matchcontinue;
805 end switchInnerToOuterInChildrenValue;
806
807
808 ///////////////////////////////////////////////////
809 /// instance hieararchy for inner/outer
810 /// add furher functions before this
811 ///////////////////////////////////////////////////
812
813
814 protected function emptyInstInner
815 input DAE.Prefix innerPrefix;
816 input String name;
817 output InstInner outInstInner;
818 annotation(__OpenModelica_EarlyInline = true);
819 algorithm
820 ✗ outInstInner := INST_INNER(innerPrefix, name, Absyn.NOT_INNER_OUTER(), "", Absyn.IDENT(""), "", NONE(), {}, NONE());
821 end emptyInstInner;
822
823 public function lookupInnerVar
824 "@author: adrpo
825 This function lookups the result of instatiation of the inner
826 component given an instance hierarchy a prefix and a component name."
827 input Cache inCache;
828 input FCore.Graph inEnv;
829 input InstHierarchy inIH;
830 input DAE.Prefix inPrefix;
831 input SCode.Ident inIdent;
832 input Absyn.InnerOuter io;
833 output InstInner outInstInner;
834 algorithm
835 outInstInner := matchcontinue (inIH, inPrefix, inIdent)
836 local
837 String n;
838 DAE.Prefix pre;
839 TopInstance tih;
840 InstInner instInner;
841
842 // adrpo: if component is an outer or an inner/outer we need to
843 // lookup the modification of the inner component and use it
844 // when we instantiate the outer component
845 case (tih::_, pre, n)
846 algorithm
847 // is component an outer or an inner/outer?
848 //true = AbsynUtil.isOuter(io); // is outer
849 //false = AbsynUtil.isInner(io); // and is not inner
850 // search the instance hierarchy for the inner component
851 699 instInner := lookupInnerInIH(tih, pre, n);
852 then
853 instInner;
854
855 // failure in case we look for anything else but outer!
856 case (_, pre, n)
857 algorithm
858
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 true := Flags.isSet(Flags.FAILTRACE);
859 ✗ Debug.traceln("InnerOuter.lookupInnerVar failed on component: " + PrefixUtil.printPrefixStr(pre) + "/" + n);
860 ✗ then
861 fail();
862 end matchcontinue;
863 end lookupInnerVar;
864
865 public function updateInstHierarchy
866 "@author: adrpo
867 This function updates the instance hierarchy by adding
868 the INNER components to it with the given prefix"
869 input InstHierarchy inIH;
870 input DAE.Prefix inPrefix;
871 input Absyn.InnerOuter inInnerOuter;
872 input InstInner inInstInner;
873 output InstHierarchy outIH;
874 algorithm
875 outIH := match(inIH, inInstInner)
876 local
877 TopInstance tih;
878 InstHierarchy restIH, ih;
879 DAE.ComponentRef cref;
880 SCode.Ident name;
881 InstHierarchyHashTable ht;
882 Option<Absyn.Path> pathOpt;
883 OuterPrefixes outerPrefixes;
884 DAE.ComponentRef cref_;
885 HashSet.HashSet sm;
886
887 /* only add inner elements
888 case(ih,inPrefix,inInnerOuter,inInstInner as INST_INNER(name=name))
889 algorithm
890 false = AbsynUtil.isInner(inInnerOuter);
891 // prefix the name!
892 (_,cref) = PrefixUtil.prefixCref(FCore.emptyCache(),{},emptyInstHierarchy,inPrefix, ComponentReferenceBasics.makeCrefIdent(name, DAE.T_UNKNOWN_DEFAULT, {}));
893 // print ("InnerOuter.updateInstHierarchy jumping over non-inner: " + ComponentReferenceBasics.printComponentRefStr(cref) + "\n");
894 then
895 ih;*/
896
897 // no hashtable, create one!
898 case({}, INST_INNER())
899 algorithm
900 // print ("InnerOuter.updateInstHierarchy creating an empty hash table! \n");
901 36 ht := emptyInstHierarchyHashTable();
902 36 sm := HashSet.emptyHashSet();
903 36 tih := TOP_INSTANCE(NONE(), ht, emptyOuterPrefixes, sm);
904 36 ih := updateInstHierarchy({tih}, inPrefix, inInnerOuter, inInstInner);
905 then
906 ih;
907
908 // add to the hierarchy
909 case((TOP_INSTANCE(pathOpt, ht, outerPrefixes, sm))::restIH, INST_INNER(name=name))
910 algorithm
911 // prefix the name!
912 738 cref_ := ComponentReferenceBasics.makeCrefIdent(name, DAE.T_UNKNOWN_DEFAULT, {});
913 738 (_,cref) := PrefixUtil.prefixCref(FCore.emptyCache(), FGraph.empty(), emptyInstHierarchy, inPrefix, cref_);
914 // add to hashtable!
915 // fprintln(Flags.FAILTRACE, "InnerOuter.updateInstHierarchy adding: " + PrefixUtil.printPrefixStr(inPrefix) + "/" + name + " to IH");
916 738 ht := add((cref,inInstInner), ht);
917 738 then
918 TOP_INSTANCE(pathOpt, ht, outerPrefixes, sm)::restIH;
919
920 // failure
921 case(_, INST_INNER())
922 algorithm
923 // prefix the name!
924 //(_,cref) = PrefixUtil.prefixCref(FCore.emptyCache(),{},emptyInstHierarchy,inPrefix, ComponentReferenceBasics.makeCrefIdent("UNKNOWN", DAE.T_UNKNOWN_DEFAULT, {}));
925 // fprintln(Flags.INNER_OUTER, "InnerOuter.updateInstHierarchy failure for: " +
926 // PrefixUtil.printPrefixStr(inPrefix) + "/" + name);
927 then
928 fail();
929 end match;
930 end updateInstHierarchy;
931
932 public function updateSMHierarchy
933 "@author: BTH
934 Add State Machine state to collection of State Machine states in instance hierarchy."
935 input DAE.ComponentRef smState;
936 input InstHierarchy inIH;
937 output InstHierarchy outIH;
938 algorithm
939 outIH := match (smState, inIH)
940 local
941 TopInstance tih;
942 InstHierarchy restIH, ih;
943 DAE.ComponentRef cref;
944 SCode.Ident name;
945 InstHierarchyHashTable ht;
946 Option<Absyn.Path> pathOpt;
947 OuterPrefixes outerPrefixes;
948 HashSet.HashSet sm;
949 HashSet.HashSet sm2;
950
951 // no hashtable, create one!
952 case(_,{})
953 algorithm
954 4 ht := emptyInstHierarchyHashTable();
955 4 sm := HashSet.emptyHashSet();
956 //sm = Debug.bcallret2(true, BaseHashSet.add, smState, sm, sm);
957 4 sm2 := BaseHashSet.add(smState, sm);
958 // FIXME what to put for emptyOuterPrefixes
959 4 tih := TOP_INSTANCE(NONE(), ht, emptyOuterPrefixes, sm2);
960
961 ih := {tih};
962 then
963 ih;
964
965 // add to the hierarchy
966 case (cref,TOP_INSTANCE(pathOpt, ht, outerPrefixes, sm)::restIH)
967 algorithm
968 // add to hashtable!
969 36 sm := BaseHashSet.add(cref, sm); // add((cref,inInstInner), ht);
970 36 then
971 TOP_INSTANCE(pathOpt, ht, outerPrefixes, sm)::restIH;
972
973 // failure
974 case (DAE.CREF_IDENT(ident=name),_)
975 algorithm
976 ✗ true := Flags.isSet(Flags.INSTANCE);
977 ✗ Debug.traceln("InnerOuter.updateSMHierarchy failure for: " + name);
978 ✗ then
979 fail();
980 end match;
981 end updateSMHierarchy;
982
983
984 public function addClassIfInner
985 input SCode.Element inClass;
986 input DAE.Prefix inPrefix;
987 input FCore.Graph inScope;
988 input InstHierarchy inIH;
989 output InstHierarchy outIH;
990 algorithm
991 outIH := matchcontinue inClass
992 local
993 String name, scopeName;
994 Absyn.InnerOuter io;
995
996 // add inner or innerouter
997 case SCode.CLASS(name = name, prefixes = SCode.PREFIXES(innerOuter = io))
998 algorithm
999
1/2
✓ Branch 1 taken 8064891 times.
✗ Branch 2 not taken.
8064891 true := AbsynUtil.isInner(io);
1000 ✗ scopeName := FGraph.getGraphNameStr(inScope);
1001 // add to instance hierarchy
1002 ✗ outIH := updateInstHierarchy(inIH, inPrefix, io,
1003 INST_INNER(
1004 inPrefix, // prefix
1005 name, // class name
1006 io,
1007 name,
1008 Absyn.IDENT(name),
1009 scopeName,
1010 NONE(),
1011 {},
1012 SOME(inClass)));
1013 then
1014 outIH;
1015
1016 // do nothing if not inner
1017 else inIH;
1018
1019 end matchcontinue;
1020 end addClassIfInner;
1021
1022 public function addOuterPrefixToIH
1023 "@author: adrpo
1024 This function remembers the outer prefix with the correct prefix of the inner"
1025 input InstHierarchy inIH;
1026 input DAE.ComponentRef inOuterComponentRef;
1027 input DAE.ComponentRef inInnerComponentRef;
1028 output InstHierarchy outIH;
1029 algorithm
1030 outIH := matchcontinue inIH
1031 local
1032 TopInstance tih;
1033 InstHierarchy restIH, ih;
1034 InstHierarchyHashTable ht;
1035 Option<Absyn.Path> pathOpt;
1036 OuterPrefixes outerPrefixes;
1037 HashSet.HashSet sm;
1038
1039 // no hashtable, create one!
1040 case {}
1041 algorithm
1042 // create an empty table and add the crefs to it.
1043 ✗ ht := emptyInstHierarchyHashTable();
1044 ✗ sm := HashSet.emptyHashSet();
1045 ✗ tih := TOP_INSTANCE(NONE(), ht, {OUTER(ComponentReference.crefStripSubs(inOuterComponentRef), inInnerComponentRef)}, sm);
1046 ih := {tih};
1047 then
1048 ih;
1049
1050 // add to the top instance
1051 case (TOP_INSTANCE(pathOpt, ht, outerPrefixes, sm))::restIH
1052 algorithm
1053 // fprintln(Flags.INNER_OUTER, "InnerOuter.addOuterPrefix adding: outer cref: " +
1054 // ComponentReferenceBasics.printComponentRefStr(inOuterComponentRef) + " refers to inner cref: " +
1055 // ComponentReferenceBasics.printComponentRefStr(inInnerComponentRef) + " to IH");
1056 693 outerPrefixes := List.unionElt(OUTER(ComponentReference.crefStripSubs(inOuterComponentRef), inInnerComponentRef), outerPrefixes);
1057 693 then
1058 TOP_INSTANCE(pathOpt, ht, outerPrefixes, sm)::restIH;
1059
1060 // failure
1061 else
1062 algorithm
1063 ✗ true := Flags.isSet(Flags.FAILTRACE);
1064 ✗ Debug.traceln("InnerOuter.addOuterPrefix failed to add: outer cref: " +
1065 ComponentReferenceBasics.printComponentRefStr(inOuterComponentRef) + " refers to inner cref: " +
1066 ComponentReferenceBasics.printComponentRefStr(inInnerComponentRef) + " to IH");
1067 ✗ then
1068 fail();
1069 end matchcontinue;
1070 end addOuterPrefixToIH;
1071
1072 public function prefixOuterCrefWithTheInnerPrefix
1073 "@author: adrpo
1074 This function searches for outer crefs and prefixes them with the inner prefix"
1075 input InstHierarchy inIH;
1076 input DAE.ComponentRef inOuterComponentRef;
1077 input DAE.Prefix inPrefix;
1078 output DAE.ComponentRef outInnerComponentRef;
1079 algorithm
1080 outInnerComponentRef := match inIH
1081 local
1082 DAE.ComponentRef outerCrefPrefix, fullCref, innerCref, innerCrefPrefix;
1083 OuterPrefixes outerPrefixes;
1084
1085 // we have no outer references, fail so prefixing can happen in the calling function
1086 case {}
1087 32908 then
1088 fail();
1089
1090 // we have some outer references, search for our prefix + cref in them
1091 case {TOP_INSTANCE(_, _, outerPrefixes as _::_, _)}
1092 algorithm
1093 104474 (_,fullCref) := PrefixUtil.prefixCref(FCore.emptyCache(), FGraph.empty(), emptyInstHierarchy, inPrefix, inOuterComponentRef);
1094
1095 // this will fail if we don't find it so prefixing can happen in the calling function
1096 104474 (outerCrefPrefix, innerCrefPrefix) := searchForInnerPrefix(fullCref, inOuterComponentRef, outerPrefixes);
1097
1098 1625 innerCref := changeOuterReferenceToInnerReference(fullCref, outerCrefPrefix, innerCrefPrefix);
1099
1100 // fprintln(Flags.FAILTRACE, "- InnerOuter.prefixOuterCrefWithTheInnerPrefix replaced cref " + ComponentReferenceBasics.printComponentRefStr(fullCref) + " with cref: " + ComponentReferenceBasics.printComponentRefStr(innerCref));
1101 then
1102 innerCref;
1103
1104 // failure
1105 else
1106 algorithm
1107 // true = Flags.isSet(Flags.FAILTRACE);
1108 // Debug.traceln("- InnerOuter.prefixOuterCrefWithTheInnerPrefix failed to find prefix of inner for outer: prefix/cref " + PrefixUtil.printPrefixStr(inPrefix) + "/" + ComponentReferenceBasics.printComponentRefStr(inOuterComponentRef));
1109 then
1110 fail();
1111 end match;
1112 end prefixOuterCrefWithTheInnerPrefix;
1113
1114 protected function changeOuterReferenceToInnerReference
1115 "@author: adrpo
1116 This function replaces the outer prefix with the inner prefix in the full cref"
1117 input DAE.ComponentRef inFullCref;
1118 input DAE.ComponentRef inOuterCrefPrefix;
1119 input DAE.ComponentRef inInnerCrefPrefix;
1120 output DAE.ComponentRef outInnerCref;
1121 algorithm
1122 outInnerCref := match(inFullCref, inOuterCrefPrefix, inInnerCrefPrefix)
1123 local
1124 DAE.ComponentRef ifull, ocp, icp, ic;
1125 list<DAE.ComponentRef> eifull, eocp, eicp, epre, erest, esuffix;
1126
1127 // The full cref might contain subscripts that we wish to keep, so we use
1128 // the inner and outer prefix to extract the relevant parts of the full cref.
1129 //
1130 // E.g. if we have a full cref a.b.c.d.e.f.g, an outer prefix a.b.c.d.e and
1131 // an inner prefix a.d.e, then we want a, d.e and f.g, resulting in a.d.e.f.g.
1132 case (ifull, ocp, icp)
1133 algorithm
1134 // print("F:" + ComponentReferenceBasics.printComponentRefStr(ifull) + "\n" + "I:" + ComponentReferenceBasics.printComponentRefStr(icp) + "\n" + "O:" + ComponentReferenceBasics.printComponentRefStr(ocp) + "\n");
1135 // Explode the crefs to lists so that they are easier to work with.
1136 1625 eifull := ComponentReference.explode(ifull);
1137 1625 eicp := ComponentReference.explode(icp);
1138
1139 // Split the full cref so that we get the part that is equal to the
1140 // outer prefix and the rest of the suffix.
1141 1625 (eocp, esuffix) := List.split(eifull, ComponentReference.identifierCount(ocp));
1142
1143 // Extract the common prefix of the outer and inner prefix.
1144 1625 (epre, erest) := List.splitEqualPrefix(eocp, eicp, ComponentReferenceBasics.crefFirstIdentEqual);
1145
1146 // remove the common prefix from the inner!
1147 1625 (_, eicp) := List.splitEqualPrefix(eicp, epre, ComponentReferenceBasics.crefFirstIdentEqual);
1148
1149 // Extract the common suffix of the outer and inner prefix.
1150 1625 (erest, _) := List.splitEqualPrefix(listReverse(erest), listReverse(eicp), ComponentReferenceBasics.crefFirstIdentEqual);
1151
1152 // Combine the parts into a new cref.
1153 1625 erest := List.append_reverse(erest, esuffix);
1154 1625 eifull := listAppend(epre, erest);
1155 1625 ic := ComponentReference.implode(eifull);
1156 // print("C:" + ComponentReferenceBasics.printComponentRefStr(ic) + "\n");
1157 then
1158 ic;
1159
1160 end match;
1161 end changeOuterReferenceToInnerReference;
1162
1163 protected function searchForInnerPrefix
1164 "@author: adrpo
1165 search in the outer prefixes and retrieve the outer/inner crefs"
1166 input DAE.ComponentRef fullCref;
1167 input DAE.ComponentRef inOuterCref;
1168 input OuterPrefixes outerPrefixes;
1169 output DAE.ComponentRef outerCrefPrefix;
1170 output DAE.ComponentRef innerCrefPrefix;
1171 protected
1172 DAE.ComponentRef cr;
1173 Boolean b1 = false, b2 = false;
1174 algorithm
1175 // print("L:" + intString(listLength(outerPrefixes)) + "\n");
1176
2/2
✓ Branch 0 taken 4402740 times.
✓ Branch 1 taken 102849 times.
4505589 for op in outerPrefixes loop
1177 4402740 OUTER(outerComponentRef = outerCrefPrefix) := op;
1178 4402740 b1 := ComponentReferenceBasics.crefPrefixOfIgnoreSubscripts(outerCrefPrefix, fullCref);
1179
2/2
✓ Branch 0 taken 4401115 times.
✓ Branch 1 taken 1625 times.
4402740 if not b1
1180 then
1181 4401115 cr := ComponentReference.crefStripLastIdent(outerCrefPrefix);
1182
5/6
✓ Branch 2 taken 291082 times.
✓ Branch 3 taken 4110033 times.
✓ Branch 7 taken 720 times.
✓ Branch 8 taken 290362 times.
✓ Branch 10 taken 720 times.
✗ Branch 11 not taken.
4401115 b2 := ComponentReferenceBasics.crefLastIdent(outerCrefPrefix) == ComponentReferenceBasics.crefFirstIdent(inOuterCref)
1183 and ComponentReferenceBasics.crefPrefixOfIgnoreSubscripts(cr, fullCref);
1184 end if;
1185
1186
2/2
✓ Branch 0 taken 1625 times.
✓ Branch 1 taken 4401115 times.
4402740 if b1 or b2
1187 then
1188 1625 OUTER(innerComponentRef = innerCrefPrefix) := op;
1189
1/2
✓ Branch 0 taken 1625 times.
✗ Branch 1 not taken.
1625 return;
1190 end if;
1191 end for;
1192
1193 102849 fail();
1194 end searchForInnerPrefix;
1195
1196 protected function printInnerDefStr
1197 input InstInner inInstInner;
1198 output String outStr;
1199 algorithm
1200 outStr := match inInstInner
1201 local
1202 String fullName "full inner component name";
1203 Absyn.Path typePath "the type of the inner";
1204 String scope "the scope of the inner";
1205 list<DAE.ComponentRef> outers "which outers are referencing this inner";
1206 String str, strOuters;
1207
1208 case INST_INNER(_, _, _, fullName, typePath, scope, _, outers, _)
1209 algorithm
1210 ✗ outers := List.uniqueOnTrue(outers, ComponentReferenceBasics.crefEqualNoStringCompare);
1211 ✗ strOuters := if listEmpty(outers)
1212 then ""
1213 else (" Referenced by 'outer' components: {" +
1214 stringDelimitList(List.map(outers, ComponentReferenceBasics.printComponentRefStr), ", ") + "}");
1215 ✗ str := AbsynUtil.pathString(typePath) + " " + fullName + "; defined in scope: " + scope + "." + strOuters;
1216 then
1217 str;
1218 end match;
1219 end printInnerDefStr;
1220
1221 public function getExistingInnerDeclarations
1222 "@author: adrpo
1223 This function retrieves all the existing inner declarations as a string"
1224 input InstHierarchy inIH;
1225 input FCore.Graph inEnv;
1226 output String innerDeclarations;
1227 algorithm
1228 innerDeclarations := match inIH
1229 local
1230 InstHierarchyHashTable ht;
1231 list<InstInner> inners;
1232 String str;
1233
1234 // we have no inner components yet
1235 case {}
1236 2 then
1237 "There are no 'inner' components defined in the model in any of the parent scopes of 'outer' component's scope: " + FGraph.printGraphPathStr(inEnv) + "." ;
1238
1239 // get the list of components
1240 case (TOP_INSTANCE(_, ht, _, _))::_
1241 algorithm
1242 ✗ inners := getInnersFromInstHierarchyHashTable(ht);
1243 ✗ str := stringDelimitList(List.map(inners, printInnerDefStr), "\n ");
1244 then
1245 str;
1246 end match;
1247 end getExistingInnerDeclarations;
1248
1249 protected function getInnersFromInstHierarchyHashTable
1250 "@author: adrpo
1251 Returns all the inners defined in the hashtable."
1252 input InstHierarchyHashTable t;
1253 output list<InstInner> inners;
1254 algorithm
1255 ✗ inners := List.map(hashTableList(t),getValue);
1256 end getInnersFromInstHierarchyHashTable;
1257
1258 protected function getValue
1259 input tuple<Key,Value> tpl;
1260 output InstInner v;
1261 algorithm
1262 v := match tpl
1263 case (_,v) then v;
1264 end match;
1265 end getValue;
1266
1267 /////////////////////////////////////////////////////////////////
1268 // hash table implementation for InnerOuter instance hierarchy //
1269 /////////////////////////////////////////////////////////////////
1270
1271 protected function hashFunc
1272 "author: PA
1273 Calculates a hash value for DAE.ComponentRef"
1274 input Key k;
1275 output Integer res;
1276 algorithm
1277 3164 res := stringHashDjb2(ComponentReferenceBasics.printComponentRefStr(k));
1278 end hashFunc;
1279
1280 protected function keyEqual
1281 input Key key1;
1282 input Key key2;
1283 output Boolean res;
1284 algorithm
1285 4188 res := ComponentReferenceBasics.crefEqualNoStringCompare(key1,key2);
1286 end keyEqual;
1287
1288 protected function dumpInstHierarchyHashTable ""
1289 input InstHierarchyHashTable t;
1290 algorithm
1291 ✗ print("InstHierarchyHashTable:\n");
1292 ✗ print(stringDelimitList(List.map(hashTableList(t),dumpTuple),"\n"));
1293 ✗ print("\n");
1294 end dumpInstHierarchyHashTable;
1295
1296 protected function dumpTuple
1297 input tuple<Key,Value> tpl;
1298 output String str;
1299 algorithm
1300 str := match tpl
1301 local
1302 Key k; case (k,_)
1303 algorithm
1304 ✗ str := "{" +
1305 ComponentReference.crefStr(k) +
1306 " opaque InstInner for now, implement printing. " + "}\n";
1307 then str;
1308 end match;
1309 end dumpTuple;
1310
1311 /* end of InstHierarchyHashTable instance specific code */
1312
1313 /* Generic hashtable code below!! */
1314 public
1315 uniontype InstHierarchyHashTable
1316 record HASHTABLE
1317 array<list<tuple<Key,Integer>>> hashTable " hashtable to translate Key to array indx" ;
1318 ValueArray valueArr "Array of values" ;
1319 Integer bucketSize "bucket size" ;
1320 Integer numberOfEntries "number of entries in hashtable" ;
1321 end HASHTABLE;
1322 end InstHierarchyHashTable;
1323
1324 uniontype ValueArray
1325 "array of values are expandable, to amortize the
1326 cost of adding elements in a more efficient manner"
1327 record VALUE_ARRAY
1328 Integer numberOfElements "number of elements in hashtable" ;
1329 array<Option<tuple<Key,Value>>> valueArray "array of values";
1330 end VALUE_ARRAY;
1331 end ValueArray;
1332
1333 protected function emptyInstHierarchyHashTable
1334 "author: PA
1335 Returns an empty InstHierarchyHashTable.
1336 Using the bucketsize 100 and array size 10."
1337 output InstHierarchyHashTable hashTable;
1338 protected
1339 array<list<tuple<Key,Integer>>> arr;
1340 array<Option<tuple<Key,Value>>> emptyarr;
1341 algorithm
1342 40 arr := arrayCreate(1000, {});
1343 40 emptyarr := arrayCreate(100, NONE());
1344 40 hashTable := HASHTABLE(arr,VALUE_ARRAY(0,emptyarr),1000,0);
1345 end emptyInstHierarchyHashTable;
1346
1347 protected function add
1348 "author: PA
1349 Add a Key-Value tuple to hashtable.
1350 If the Key-Value tuple already exists, the function updates the Value."
1351 input tuple<Key,Value> entry;
1352 input InstHierarchyHashTable hashTable;
1353 output InstHierarchyHashTable outHashTable;
1354 algorithm
1355 outHashTable :=
1356 matchcontinue (entry,hashTable)
1357 local
1358 Integer hval,indx,newpos,n,n_1,bsize;
1359 ValueArray varr_1,varr;
1360 list<tuple<Key,Integer>> indexes;
1361 array<list<tuple<Key,Integer>>> hashvec_1,hashvec;
1362 tuple<Key,Value> v,newv;
1363 Key key;
1364 /* Adding when not existing previously */
1365 case ((v as (key,_)),(HASHTABLE(hashvec,varr,bsize,_)))
1366 algorithm
1367
2/2
✓ Branch 0 taken 738 times.
✓ Branch 1 taken 44 times.
782 failure(get(key, hashTable));
1368 44 hval := hashFunc(key);
1369 44 indx := intMod(hval, bsize);
1370 44 newpos := valueArrayLength(varr);
1371 44 varr_1 := valueArrayAdd(varr, v);
1372 44 indexes := hashvec[indx + 1];
1373 88 hashvec_1 := arrayUpdate(hashvec, indx + 1, ((key,newpos) :: indexes));
1374 44 n_1 := valueArrayLength(varr_1);
1375 // print("Added NEW to IH: key:" + ComponentReferenceBasics.printComponentRefStr(key) + " value: " + printInnerDefStr(value) + "\n");
1376 44 then HASHTABLE(hashvec_1,varr_1,bsize,n_1);
1377
1378 /* adding when already present => Updating value */
1379 case ((newv as (key,_)),(HASHTABLE(hashvec,varr,bsize,n)))
1380 algorithm
1381 694 (_,indx) := get1(key, hashTable);
1382 //print("adding when present, indx =" );print(intString(indx));print("\n");
1383 694 varr_1 := valueArraySetnth(varr, indx, newv);
1384 // print("Updated NEW to IH: key:" + ComponentReferenceBasics.printComponentRefStr(key) + " value: " + printInnerDefStr(value) + "\n");
1385 694 then HASHTABLE(hashvec,varr_1,bsize,n);
1386 else
1387 algorithm
1388 ✗ print("- InnerOuter.add failed\n");
1389 ✗ then
1390 fail();
1391 end matchcontinue;
1392 end add;
1393
1394 public function get
1395 "author: PA
1396 Returns a Value given a Key and a InstHierarchyHashTable."
1397 input Key key;
1398 input InstHierarchyHashTable hashTable;
1399 output Value value;
1400 algorithm
1401 2426 (value,_):= get1(key,hashTable);
1402 end get;
1403
1404 protected function get1 "help function to get"
1405 input Key key;
1406 input InstHierarchyHashTable hashTable;
1407 output Value value;
1408 output Integer indx;
1409 algorithm
1410 (value, indx) := match hashTable
1411 local
1412 Integer hval,hashindx,bsize;
1413 list<tuple<Key,Integer>> indexes;
1414 Value v;
1415 array<list<tuple<Key,Integer>>> hashvec;
1416 ValueArray varr;
1417 Key k;
1418
1419 case HASHTABLE(hashvec,varr,bsize,_)
1420 algorithm
1421 3120 hval := hashFunc(key);
1422 hashindx := intMod(hval, bsize);
1423 3120 indexes := hashvec[hashindx + 1];
1424 3120 indx := get2(key, indexes);
1425 2094 (k, v) := valueArrayNth(varr, indx);
1426
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2094 times.
2094 true := keyEqual(k, key);
1427
2/2
✓ Branch 0 taken 694 times.
✓ Branch 1 taken 1400 times.
2094 then
1428 (v,indx);
1429 end match;
1430 end get1;
1431
1432 protected function get2
1433 "author: PA
1434 Helper function to get"
1435 input Key key;
1436 input list<tuple<Key,Integer>> keyIndices;
1437 output Integer index;
1438 algorithm
1439 index := matchcontinue keyIndices
1440 local
1441 Key key2;
1442 list<tuple<Key,Integer>> xs;
1443 case (key2,index) :: _
1444 algorithm
1445
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2094 times.
2094 true := keyEqual(key, key2);
1446 then
1447 index;
1448 case _ :: xs
1449 algorithm
1450 ✗ index := get2(key, xs);
1451 then
1452 index;
1453 end matchcontinue;
1454 end get2;
1455
1456 protected function hashTableList "returns the entries in the hashTable as a list of tuple<Key,Value>"
1457 input InstHierarchyHashTable hashTable;
1458 output list<tuple<Key,Value>> tplLst;
1459 algorithm
1460 tplLst := match hashTable
1461 local ValueArray varr;
1462 case HASHTABLE(valueArr = varr) algorithm
1463 ✗ tplLst := valueArrayList(varr);
1464 then tplLst;
1465 end match;
1466 end hashTableList;
1467
1468 protected function valueArrayList
1469 "author: PA
1470 Transforms a ValueArray to a tuple<Key,Value> list"
1471 input ValueArray valueArray;
1472 output list<tuple<Key,Value>> tplLst;
1473 algorithm
1474 tplLst := matchcontinue valueArray
1475 local
1476 array<Option<tuple<Key,Value>>> arr;
1477 tuple<Key,Value> elt;
1478 Integer lastpos,n;
1479 list<tuple<Key,Value>> lst;
1480 case VALUE_ARRAY(numberOfElements = 0) then {};
1481 case VALUE_ARRAY(numberOfElements = 1,valueArray = arr)
1482 algorithm
1483 ✗ SOME(elt) := arr[0 + 1];
1484 then
1485 {elt};
1486 case VALUE_ARRAY(numberOfElements = n,valueArray = arr)
1487 algorithm
1488 ✗ lastpos := n - 1;
1489 ✗ lst := valueArrayList2(arr, 0, lastpos);
1490 then
1491 lst;
1492 end matchcontinue;
1493 end valueArrayList;
1494
1495 protected function valueArrayList2 "Helper function to valueArrayList"
1496 input array<Option<tuple<Key,Value>>> inVarOptionArray1;
1497 input Integer inInteger2;
1498 input Integer inInteger3;
1499 output list<tuple<Key,Value>> outVarLst;
1500 algorithm
1501 outVarLst := matchcontinue (inVarOptionArray1,inInteger2,inInteger3)
1502 local
1503 tuple<Key,Value> v;
1504 array<Option<tuple<Key,Value>>> arr;
1505 Integer pos,lastpos,pos_1;
1506 list<tuple<Key,Value>> res;
1507 case (arr,pos,lastpos) guard pos == lastpos
1508 algorithm
1509 ✗ SOME(v) := arr[pos + 1];
1510 then
1511 {v};
1512 case (arr,pos,lastpos)
1513 algorithm
1514 ✗ pos_1 := pos + 1;
1515 ✗ SOME(v) := arr[pos + 1];
1516 ✗ res := valueArrayList2(arr, pos_1, lastpos);
1517 then
1518 (v :: res);
1519 case (arr,pos,lastpos)
1520 algorithm
1521 ✗ pos_1 := pos + 1;
1522 ✗ NONE() := arr[pos + 1];
1523 ✗ res := valueArrayList2(arr, pos_1, lastpos);
1524 then
1525 (res);
1526 end matchcontinue;
1527 end valueArrayList2;
1528
1529 protected function valueArrayLength
1530 "author: PA
1531 Returns the number of elements in the ValueArray"
1532 input ValueArray valueArray;
1533 output Integer size;
1534 algorithm
1535 size := match valueArray
1536 case VALUE_ARRAY(numberOfElements = size) then size;
1537 end match;
1538 end valueArrayLength;
1539
1540 protected function valueArrayAdd
1541 "author: PA
1542 Adds an entry last to the ValueArray, increasing
1543 array size if no space left by factor 1.4"
1544 input ValueArray valueArray;
1545 input tuple<Key,Value> entry;
1546 output ValueArray outValueArray;
1547 algorithm
1548 outValueArray := matchcontinue valueArray
1549 local
1550 Integer n_1,n,size,expandsize,expandsize_1;
1551 array<Option<tuple<Key,Value>>> arr_1,arr,arr_2;
1552 Real rsize,rexpandsize;
1553 case VALUE_ARRAY(numberOfElements = n,valueArray = arr) guard n < arrayLength(arr)
1554 algorithm
1555 44 n_1 := n + 1;
1556 44 arr_1 := arrayUpdate(arr, n + 1, SOME(entry));
1557 44 then
1558 VALUE_ARRAY(n_1,arr_1);
1559
1560 case VALUE_ARRAY(numberOfElements = n,valueArray = arr) guard n < arrayLength(arr)
1561 algorithm
1562 size := arrayLength(arr);
1563 ✗ rsize := intReal(size);
1564 ✗ rexpandsize := rsize * 0.4;
1565 ✗ expandsize := realInt(rexpandsize);
1566 expandsize_1 := intMax(expandsize, 1);
1567 ✗ arr_1 := Array.expand(expandsize_1, arr,NONE());
1568 ✗ n_1 := n + 1;
1569 ✗ arr_2 := arrayUpdate(arr_1, n + 1, SOME(entry));
1570 ✗ then
1571 VALUE_ARRAY(n_1,arr_2);
1572 else
1573 algorithm
1574 ✗ print("-InstHierarchyHashTable.valueArrayAdd failed\n");
1575 ✗ then
1576 fail();
1577 end matchcontinue;
1578 end valueArrayAdd;
1579
1580 protected function valueArraySetnth
1581 "author: PA
1582 Set the n:th variable in the ValueArray to value."
1583 input ValueArray valueArray;
1584 input Integer pos;
1585 input tuple<Key,Value> entry;
1586 output ValueArray outValueArray;
1587 algorithm
1588 outValueArray := matchcontinue valueArray
1589 local
1590 array<Option<tuple<Key,Value>>> arr;
1591 case VALUE_ARRAY(_,arr) guard pos < arrayLength(arr)
1592 algorithm
1593 694 arrayUpdate(arr, pos + 1, SOME(entry));
1594 then
1595 valueArray;
1596 else
1597 algorithm
1598 ✗ print("-InstHierarchyHashTable.valueArraySetnth failed\n");
1599 ✗ then
1600 fail();
1601 end matchcontinue;
1602 end valueArraySetnth;
1603
1604 protected function valueArrayClearnth
1605 "author: PA
1606 Clears the n:th variable in the ValueArray (set to NONE())."
1607 input ValueArray valueArray;
1608 input Integer pos;
1609 output ValueArray outValueArray;
1610 algorithm
1611 outValueArray := matchcontinue valueArray
1612 local
1613 array<Option<tuple<Key,Value>>> arr;
1614 case VALUE_ARRAY(_,arr) guard pos < arrayLength(arr)
1615 algorithm
1616 ✗ arrayUpdate(arr, pos + 1,NONE());
1617 then
1618 valueArray;
1619 else
1620 algorithm
1621 ✗ print("-InstHierarchyHashTable.valueArrayClearnth failed\n");
1622 ✗ then
1623 fail();
1624 end matchcontinue;
1625 end valueArrayClearnth;
1626
1627 protected function valueArrayNth
1628 "author: PA
1629 Retrieve the n:th Vale from ValueArray, index from 0..n-1."
1630 input ValueArray valueArray;
1631 input Integer pos;
1632 output Key key;
1633 output Value value;
1634 algorithm
1635 (key, value) := match valueArray
1636 local
1637 Key k;
1638 Value v;
1639 Integer n;
1640 array<Option<tuple<Key,Value>>> arr;
1641
1642 case VALUE_ARRAY(numberOfElements = n,valueArray = arr)
1643 algorithm
1644
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2094 times.
2094 true := (pos < n);
1645
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 2094 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2094 times.
✓ Branch 5 taken 2094 times.
✗ Branch 6 not taken.
2094 SOME((k,v)) := arr[pos + 1];
1646 then
1647 (k, v);
1648
1649 end match;
1650 end valueArrayNth;
1651
1652 annotation(__OpenModelica_Interface="frontend");
1653 end InnerOuter;
1654