Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 95.6% 129 / 0 / 135
Functions: -% 0 / 1 / 1
Branches: 79.5% 70 / 0 / 88

OMCompiler/Compiler/NFFrontEnd/NFExpandableConnectors.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 NFExpandableConnectors
37
38 public
39 import FlatModel = NFFlatModel;
40 import Connections = NFConnections;
41
42 protected
43 import Array;
44 import Binding = NFBinding;
45 import ComplexType = NFComplexType;
46 import ComponentRef = NFComponentRef;
47 import Connection = NFConnection;
48 import ConnectionSets = NFConnectionSets.ConnectionSets;
49 import Connector = NFConnector;
50 import ElementSource;
51 import Error;
52 import Expression = NFExpression;
53 import MetaModelica.Dangerous.listReverseInPlace;
54 import Class = NFClass;
55 import NFClassTree.ClassTree;
56 import Component = NFComponent;
57 import NFInstNode.InstNode;
58 import NFInstNode;
59 import NFPrefixes.ConnectorType;
60 import NFPrefixes.Visibility;
61 import NFTypeCheck.MatchKind;
62 import Prefixes = NFPrefixes;
63 import TypeCheck = NFTypeCheck;
64 import Type = NFType;
65 import Typing = NFTyping;
66 import UnorderedSet;
67 import Util;
68 import Variable = NFVariable;
69
70 public
71 function elaborate
72 input output FlatModel flatModel;
73 input output Connections connections;
74 protected
75 list<Connection> expandable_conns, undeclared_conns, conns;
76 list<Variable> vars;
77 ConnectionSets.Sets csets;
78 array<list<Connector>> csets_array;
79 algorithm
80 // Sort the connections based on whether they involve expandable connectors,
81 // undeclared/potentially present connectors, or only normal connectors.
82 1573 (expandable_conns, undeclared_conns, conns) := sortConnections(connections.connections);
83
84 // Don't do anything if there aren't any expandable connectors in the model.
85
4/4
✓ Branch 0 taken 1568 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 1562 times.
✓ Branch 3 taken 6 times.
1573 if listEmpty(expandable_conns) and listEmpty(undeclared_conns) then
86 1562 return;
87 end if;
88
89 // Create a graph from the connections. Expandable connectors connect to
90 // expandable connectors, while undeclared/potentially present connectors connect
91 // to the expandable connector they belong to.
92 11 csets := ConnectionSets.emptySets(listLength(expandable_conns) + listLength(undeclared_conns));
93 11 csets := addExpandableConnectorsToSets(expandable_conns, csets);
94 11 (undeclared_conns, csets) := List.mapFold(undeclared_conns, addExpandableConnectorElementToSets, csets);
95
96 // Extract the sets of connected connectors.
97 11 csets_array := ConnectionSets.extractSets(csets);
98
99 //for set in csets_array loop
100 // print("Expandable connection set:\n");
101 // print(List.toString(set, Connector.toString, "", "{", ", ", "}", true) + "\n");
102 //end for;
103
104 // Augment the expandable connectors with the necessary elements, mark
105 // connected potentially present variables as present, and add the
106 // created variables to the flat model.
107
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
11 vars := flatModel.variables;
108
2/2
✓ Branch 1 taken 22 times.
✓ Branch 2 taken 11 times.
33 for set in csets_array loop
109 22 vars := elaborateExpandableSet(set, vars);
110 end for;
111
112 // Update the connections and put them back in the list of connections.
113 11 conns := List.fold(undeclared_conns, updateUndeclaredConnection, conns);
114 11 conns := List.fold(expandable_conns, updateExpandableConnection, conns);
115 11 connections.connections := conns;
116
117 // Update the attributes of potentially present variables so that they have
118 // the same attributes as their node. Their connector type will have changed
119 // if they've been marked as present.
120
4/4
✓ Branch 0 taken 1214 times.
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 1214 times.
✓ Branch 3 taken 11 times.
1225 vars := list(updatePotentiallyPresentVariable(v) for v in vars);
121 11 flatModel.variables := vars;
122 end elaborate;
123
124 protected
125
126 function sortConnections
127 "Sorts the connections into different categories of connectors based on
128 whether they involve expandable connectors, undeclared/potentially present
129 connector, or only normal connectors."
130 input list<Connection> conns;
131 output list<Connection> expandableConnections = {};
132 output list<Connection> undeclaredConnections = {};
133 output list<Connection> normalConnections = {};
134 protected
135 Connector c1, c2;
136 Boolean is_undeclared1, is_undeclared2, is_expandable1, is_expandable2;
137 algorithm
138
2/2
✓ Branch 0 taken 13948 times.
✓ Branch 1 taken 1573 times.
15521 for conn in conns loop
139
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13948 times.
13948 Connection.CONNECTION(lhs = c1, rhs = c2) := conn;
140
141
4/4
✓ Branch 1 taken 13942 times.
✓ Branch 2 taken 6 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 13937 times.
13948 is_undeclared1 := ConnectorType.isUndeclared(c1.cty) or ConnectorType.isPotentiallyPresent(c1.cty);
142
4/4
✓ Branch 1 taken 13894 times.
✓ Branch 2 taken 54 times.
✓ Branch 4 taken 16 times.
✓ Branch 5 taken 13878 times.
13948 is_undeclared2 := ConnectorType.isUndeclared(c2.cty) or ConnectorType.isPotentiallyPresent(c2.cty);
143 13948 is_expandable1 := ConnectorType.isExpandable(c1.cty);
144 13948 is_expandable2 := ConnectorType.isExpandable(c2.cty);
145
146
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 13938 times.
13948 if is_expandable1 or is_expandable2 then
147
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if is_expandable1 and is_expandable2 then
148 expandableConnections := conn :: expandableConnections;
149 else
150 // An expandable connector may only connect to another expandable connector.
151 ✗ Error.addSourceMessageAndFail(Error.EXPANDABLE_NON_EXPANDABLE_CONNECTION,
152 {Connector.toString(if is_expandable1 then c1 else c2),
153 Connector.toString(if is_expandable1 then c2 else c1)},
154 Connector.getInfo(c1));
155 end if;
156 elseif is_undeclared1 or is_undeclared2 then
157
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
81 if is_undeclared1 and is_undeclared2 then
158 // Both sides can't be undeclared, one must be a declared component.
159 ✗ Error.addSourceMessageAndFail(Error.UNDECLARED_CONNECTION,
160 {Connector.toString(c1), Connector.toString(c2)}, Connector.getInfo(c1));
161 else
162 undeclaredConnections := conn :: undeclaredConnections;
163 end if;
164 else
165 normalConnections := conn :: normalConnections;
166 end if;
167 end for;
168
169 1573 normalConnections := listReverseInPlace(normalConnections);
170 end sortConnections;
171
172 function addExpandableConnectorsToSets
173 input list<Connection> conns;
174 input output ConnectionSets.Sets csets;
175 protected
176 Connector c1, c2;
177 algorithm
178
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 14 times.
32 for conn in conns loop
179
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 Connection.CONNECTION(lhs = c1, rhs = c2) := conn;
180 18 csets := addConnectionToSets(c1, c2, csets);
181 18 csets := addNestedExpandableConnectorsToSets(c1, c2, csets);
182 end for;
183 end addExpandableConnectorsToSets;
184
185 function addNestedExpandableConnectorsToSets
186 input Connector c1;
187 input Connector c2;
188 input output ConnectionSets.Sets csets;
189 protected
190 list<Connector> ecl1, ecl2;
191 Option<Connector> oec;
192 list<Connection> conns = {};
193 algorithm
194 18 ecl1 := getExpandableConnectorsInConnector(c1);
195 18 ecl2 := getExpandableConnectorsInConnector(c2);
196
197
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 15 times.
18 if listEmpty(ecl1) and listEmpty(ecl2) then
198 15 return;
199 end if;
200
201
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 3 times.
11 for ec1 in ecl1 loop
202 8 (ecl2, oec) := List.deleteMemberOnTrue(ec1, ecl2, Connector.isNodeNameEqual);
203
204
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
8 if isSome(oec) then
205 8 conns := Connection.CONNECTION(ec1, Util.getOption(oec)) :: conns;
206 end if;
207 end for;
208
209 3 csets := addExpandableConnectorsToSets(conns, csets);
210 end addNestedExpandableConnectorsToSets;
211
212 function getExpandableConnectorsInConnector
213 input Connector c1;
214 output list<Connector> ecl;
215 protected
216 list<NFInstNode.ScopeRef> nodes;
217 InstNode n;
218 ComponentRef par_name, name;
219 Type ty;
220 algorithm
221 ecl := match c1
222 case Connector.CONNECTOR(name = par_name, ty = Type.COMPLEX(
223 complexTy = ComplexType.EXPANDABLE_CONNECTOR(expandableConnectors = nodes)))
224 algorithm
225 ecl := {};
226
227
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 36 times.
52 for n_ref in nodes loop
228 16 n := InstNode.borrow(n_ref);
229 16 ty := InstNode.getType(n);
230 16 name := ComponentRef.prefixCref(n, ty, {}, par_name);
231 16 ecl := Connector.fromCref(name, ty, ElementSource.createElementSource(InstNode.info(n))) :: ecl;
232 end for;
233 then
234 ecl;
235
236 else {};
237 end match;
238 end getExpandableConnectorsInConnector;
239
240 function addExpandableConnectorElementToSets
241 input output Connection conn;
242 input output ConnectionSets.Sets csets;
243 protected
244 Connector c1, c2, c, ec;
245 algorithm
246
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
81 Connection.CONNECTION(lhs = c1, rhs = c2) := conn;
247
248 // Figure out which connector to add, and create a virtual connector if necessary.
249
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 75 times.
81 if ConnectorType.isUndeclared(c1.cty) then
250 6 c1 := makeVirtualConnector(c1, c2);
251 6 conn := Connection.CONNECTION(c1, c2);
252 c := c1;
253 elseif ConnectorType.isUndeclared(c2.cty) then
254 54 c2 := makeVirtualConnector(c2, c1);
255 54 conn := Connection.CONNECTION(c1, c2);
256 c := c2;
257 else
258
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 5 times.
21 c := if ConnectorType.isPotentiallyPresent(c1.cty) then c1 else c2;
259 end if;
260
261 // Create a parent connector for the undeclared/potentially present connector, i.e. the expandable
262 // connector it should be added to. The type here is wrong, but it doesn't matter.
263 81 ec := Connector.CONNECTOR(ComponentRef.rest(c.name), c.ty, c.face, ConnectorType.EXPANDABLE, c.source);
264
265 // Add a connection between the undeclared/potentially present connector and the expandable connector.
266 81 csets := addConnectionToSets(c, ec, csets);
267 end addExpandableConnectorElementToSets;
268
269 function addConnectionToSets
270 input Connector c1;
271 input Connector c2;
272 input output ConnectionSets.Sets csets;
273 algorithm
274 // The connection sets are not used to represent actual connections here, only
275 // to keep track of which expandable connectors that are associated. So to
276 // make sure we only get one instance of each expandable connector in the sets
277 // we make sure the face of all the connectors we add is the same.
278 99 csets := ConnectionSets.merge(Connector.setOutside(c1), Connector.setOutside(c2), csets);
279 end addConnectionToSets;
280
281 function makeVirtualConnector
282 input Connector virtualConnector;
283 input Connector normalConnector;
284 output Connector newConnector;
285 protected
286 ComponentRef virtual_cref, normal_cref;
287 Type ty;
288 InstNode node;
289 algorithm
290 60 virtual_cref := virtualConnector.name;
291 60 normal_cref := normalConnector.name;
292 60 ty := normalConnector.ty;
293
294 // TODO: Update the virtual connector with the created node.
295 60 node := ComponentRef.node(normal_cref);
296 60 node := InstNode.clone(node);
297 60 node := InstNode.rename(ComponentRef.firstName(virtual_cref), node);
298 60 node := InstNode.setParent(ComponentRef.node(ComponentRef.rest(virtual_cref)), node);
299 60 node := InstNode.componentApply(node, Component.setType, ty);
300 60 virtual_cref := ComponentRef.prefixCref(node, ty, {}, ComponentRef.rest(virtual_cref));
301 // TODO: This needs more work, the new connector might be a complex connector.
302 60 newConnector := Connector.CONNECTOR(virtual_cref, ty, virtualConnector.face,
303 virtualConnector.cty, virtualConnector.source);
304 end makeVirtualConnector;
305
306 function elaborateExpandableSet
307 input list<Connector> set;
308 input output list<Variable> vars;
309 protected
310 UnorderedSet<Connector> exp_set;
311 list<Connector> exp_conns = {}, exp_set_lst;
312 algorithm
313 22 exp_set := UnorderedSet.new(hashConnector, Connector.isNodeNameEqual);
314
315
2/2
✓ Branch 0 taken 120 times.
✓ Branch 1 taken 22 times.
142 for c in set loop
316
2/2
✓ Branch 1 taken 40 times.
✓ Branch 2 taken 80 times.
120 if ConnectorType.isExpandable(c.cty) then
317 exp_conns := c :: exp_conns;
318 elseif ConnectorType.isUndeclared(c.cty) or ConnectorType.isPotentiallyPresent(c.cty) then
319 80 UnorderedSet.add(c, exp_set);
320 80 markComponentPresent(ComponentRef.node(Connector.name(c)));
321 end if;
322 end for;
323
324 22 exp_set_lst := UnorderedSet.toList(exp_set);
325
326
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 22 times.
62 for ec in exp_conns loop
327 40 vars := augmentExpandableConnector(ec, exp_set_lst, vars);
328 end for;
329 end elaborateExpandableSet;
330
331 function markComponentPresent
332 input InstNode node;
333 protected
334 Component comp;
335 ConnectorType.Type cty;
336 Class cls;
337 algorithm
338 152 comp := InstNode.component(node);
339 152 cty := Component.connectorType(comp);
340
341
2/2
✓ Branch 1 taken 80 times.
✓ Branch 2 taken 72 times.
152 if ConnectorType.isPotentiallyPresent(cty) then
342 72 cty := ConnectorType.setPresent(cty);
343 72 comp := Component.setConnectorType(cty, comp);
344 72 InstNode.updateComponent(comp, node);
345
346 // Also mark the component's children as present.
347
2/2
✓ Branch 2 taken 71 times.
✓ Branch 3 taken 1 time.
72 if Type.isComplex(Component.getType(comp)) then
348 1 cls := InstNode.getClass(Component.classInstance(comp));
349 1 ClassTree.applyComponents(Class.classTree(cls), markComponentPresent);
350 end if;
351 end if;
352 end markComponentPresent;
353
354 function augmentExpandableConnector
355 input Connector conn;
356 input list<Connector> expandableSet;
357 input output list<Variable> vars;
358 protected
359 ComponentRef exp_name, elem_name;
360 InstNode exp_node, comp_node, cls_node, node;
361 Class cls;
362 ClassTree cls_tree;
363 list<InstNode> nodes = {};
364 Type ty;
365 ComplexType complex_ty;
366 algorithm
367 40 exp_name := Connector.name(conn);
368 40 exp_node := ComponentRef.node(exp_name);
369
370
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
40 if InstNode.isName(exp_node) then
371 ✗ Error.addInternalError(
372 "Augmenting a virtual element in an expandable connector is not yet supported.",
373 Connector.getInfo(conn));
374 ✗ fail();
375 end if;
376
377 40 cls_node := InstNode.classScope(exp_node);
378 40 cls_node := InstNode.clone(cls_node);
379 40 cls := InstNode.getClass(cls_node);
380 40 cls_tree := Class.classTree(cls);
381
382 // Go through the union of elements the expandable connector should have.
383
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 40 times.
172 for c in expandableSet loop
384 132 elem_name := Connector.name(c);
385 132 node := ComponentRef.node(elem_name);
386
387 try
388 132 comp_node := ClassTree.lookupElement(InstNode.name(node), cls_tree);
389 else
390 comp_node := InstNode.EMPTY_NODE();
391 end try;
392
393
2/2
✓ Branch 1 taken 62 times.
✓ Branch 2 taken 70 times.
132 if InstNode.isEmpty(comp_node) then
394 // If the element doesn't already exist, add it to the list of elements to be
395 // added to the connector.
396 62 nodes := node :: nodes;
397 62 ty := c.ty;
398 62 elem_name := ComponentRef.prefixCref(node, ty, {}, exp_name);
399 62 vars := createVirtualVariables(elem_name, ty, ElementSource.getInfo(c.source), vars);
400 else
401 70 comp_node := InstNode.resolveInner(comp_node);
402
403
1/2
✓ Branch 1 taken 70 times.
✗ Branch 2 not taken.
70 if InstNode.isComponent(comp_node) then
404 // If the element already exists and is a potentially present component,
405 // change it to be present.
406 70 markComponentPresent(comp_node);
407 else
408 ✗ Error.addInternalError(getInstanceName() + " got non-component element", sourceInfo());
409 end if;
410 end if;
411 end for;
412
413
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 28 times.
40 if not listEmpty(nodes) then
414 12 cls_tree := ClassTree.addElementsToFlatTree(nodes, cls_tree);
415 12 cls := Class.setClassTree(cls_tree, cls);
416 end if;
417
418 // Create a normal non-expandable complex type for the augmented expandable connector.
419 40 complex_ty := Typing.makeConnectorType(cls_tree, isExpandable = false);
420 40 ty := Type.COMPLEX(InstNode.identityCell(cls_node), complex_ty);
421 40 ty := Type.liftArrayLeftList(ty, Type.arrayDims(InstNode.getType(exp_node)));
422 40 cls := Class.setType(ty, cls);
423 40 InstNode.updateClass(cls, cls_node);
424 40 InstNode.componentApply(exp_node, Component.setType, ty);
425 end augmentExpandableConnector;
426
427 function createVirtualVariables
428 input ComponentRef connectorName;
429 input Type connectorType;
430 input SourceInfo info;
431 input output list<Variable> vars;
432 protected
433 Variable var;
434 ComponentRef name;
435 Type ty;
436 algorithm
437
2/2
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 72 times.
82 if Type.isComplex(connectorType) then
438
2/2
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 10 times.
40 for comp in Type.complexComponents(connectorType) loop
439 20 ty := InstNode.getType(comp);
440 20 name := ComponentRef.prefixCref(comp, ty, {}, connectorName);
441 20 vars := createVirtualVariables(name, ty, info, vars);
442 end for;
443 else
444 72 var := Variable.VARIABLE(connectorName, connectorType, NFBinding.EMPTY_BINDING,
445 Visibility.PUBLIC, NFAttributes.AUGMENTED_ATTR, {}, {},
446 SCode.COMMENT(NONE(), SOME("variable added to expandable connector")),
447 info, NFBackendExtension.DUMMY_BACKEND_INFO);
448 vars := var :: vars;
449 end if;
450 end createVirtualVariables;
451
452 function updateUndeclaredConnection
453 input Connection conn;
454 input output list<Connection> conns;
455 algorithm
456 conns := conn :: conns;
457 end updateUndeclaredConnection;
458
459 function updateExpandableConnection
460 input Connection conn;
461 input output list<Connection> conns;
462 protected
463 Connector c1, c2;
464 Type ty1, ty2;
465 MatchKind mk;
466 Expression e1, e2;
467 algorithm
468
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 Connection.CONNECTION(lhs = c1, rhs = c2) := conn;
469 10 (c1, ty1) := updateExpandableConnector(c1);
470 10 (c2, ty2) := updateExpandableConnector(c2);
471
472 // Check that the types match now that the connectors have been augmented.
473 10 e1 := Expression.CREF(ty1, Connector.name(c1));
474 10 e2 := Expression.CREF(ty2, Connector.name(c2));
475 10 (_, _, _, mk) := TypeCheck.matchExpressions(e1, ty1, e2, ty2, NFTypeCheck.ALLOW_UNKNOWN);
476
477
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 if TypeCheck.isIncompatibleMatch(mk) then
478 ✗ Error.addSourceMessageAndFail(Error.CONNECT_TYPE_MISMATCH,
479 {Expression.toString(e1), Expression.toString(e2)}, Connector.getInfo(c1));
480 end if;
481
482 10 conns := Connection.CONNECTION(c1, c2) :: conns;
483 end updateExpandableConnection;
484
485 function updateExpandableConnector
486 input output Connector conn;
487 output Type ty;
488 protected
489 ComponentRef name;
490 algorithm
491
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 Connector.CONNECTOR(name = name, ty = ty) := conn;
492 20 name := ComponentRef.updateNodeType(name);
493 20 ty := Type.setArrayElementType(ty, Type.arrayElementType(ComponentRef.nodeType(name)));
494 20 conn := Connector.CONNECTOR(name, ty, conn.face, conn.cty, conn.source);
495 end updateExpandableConnector;
496
497 function updatePotentiallyPresentVariable
498 input output Variable var;
499 algorithm
500
2/2
✓ Branch 1 taken 1031 times.
✓ Branch 2 taken 183 times.
1214 if ConnectorType.isPotentiallyPresent(var.attributes.connectorType) then
501 183 var.attributes := Component.getAttributes(InstNode.component(ComponentRef.node(var.name)));
502 end if;
503 end updatePotentiallyPresentVariable;
504
505 function hashConnector
506 input Connector conn;
507 output Integer res;
508 algorithm
509 110 res := stringHashDjb2(ComponentRef.firstName(conn.name));
510 end hashConnector;
511
512 annotation(__OpenModelica_Interface="nf_frontend");
513 end NFExpandableConnectors;
514