-
Notifications
You must be signed in to change notification settings - Fork 299
/
NFComponentRef.mo
809 lines (712 loc) · 21.8 KB
/
NFComponentRef.mo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
/*
* This file is part of OpenModelica.
*
* Copyright (c) 1998-2014, Open Source Modelica Consortium (OSMC),
* c/o Linköpings universitet, Department of Computer and Information Science,
* SE-58183 Linköping, Sweden.
*
* All rights reserved.
*
* THIS PROGRAM IS PROVIDED UNDER THE TERMS OF GPL VERSION 3 LICENSE OR
* THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.2.
* ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES
* RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GPL VERSION 3,
* ACCORDING TO RECIPIENTS CHOICE.
*
* The OpenModelica software and the Open Source Modelica
* Consortium (OSMC) Public License (OSMC-PL) are obtained
* from OSMC, either from the above address,
* from the URLs: http://www.ida.liu.se/projects/OpenModelica or
* http://www.openmodelica.org, and in the OpenModelica distribution.
* GNU version 3 is obtained from: http://www.gnu.org/copyleft/gpl.html.
*
* This program is distributed WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
* IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
*
* See the full OSMC Public License conditions for more details.
*
*/
encapsulated uniontype NFComponentRef
protected
import NFComponent.Component;
import Absyn;
import DAE;
import Subscript = NFSubscript;
import Type = NFType;
import NFInstNode.InstNode;
import NFInstNode.InstNodeType;
import Dimension = NFDimension;
import Expression = NFExpression;
import NFPrefixes.Variability;
import System;
import NFClass.Class;
import List;
import Prefixes = NFPrefixes;
import ComponentRef = NFComponentRef;
public
type Origin = enumeration(
CREF "From an Absyn cref.",
SCOPE "From prefixing the cref with its scope.",
ITERATOR "From an iterator."
);
record CREF
InstNode node;
list<Subscript> subscripts;
Type ty "The type of the node, without taking subscripts into account.";
Origin origin;
ComponentRef restCref;
end CREF;
record EMPTY end EMPTY;
record WILD end WILD;
function fromNode
input InstNode node;
input Type ty;
input list<Subscript> subs = {};
input Origin origin = Origin.CREF;
output ComponentRef cref = CREF(node, subs, ty, origin, EMPTY());
end fromNode;
function prefixCref
input InstNode node;
input Type ty;
input list<Subscript> subs;
input ComponentRef restCref;
output ComponentRef cref = CREF(node, subs, ty, Origin.CREF, restCref);
end prefixCref;
function prefixScope
input InstNode node;
input Type ty;
input list<Subscript> subs;
input ComponentRef restCref;
output ComponentRef cref = CREF(node, subs, ty, Origin.SCOPE, restCref);
end prefixScope;
function fromAbsyn
input InstNode node;
input list<Absyn.Subscript> subs;
input ComponentRef restCref = EMPTY();
output ComponentRef cref;
protected
list<Subscript> sl;
algorithm
sl := list(Subscript.RAW_SUBSCRIPT(s) for s in subs);
cref := CREF(node, sl, Type.UNKNOWN(), Origin.CREF, restCref);
end fromAbsyn;
function fromAbsynCref
input Absyn.ComponentRef acref;
output ComponentRef cref;
algorithm
cref := match acref
case Absyn.ComponentRef.CREF_IDENT()
then CREF(InstNode.NAME_NODE(acref.name),
list(Subscript.RAW_SUBSCRIPT(s) for s in acref.subscripts),
Type.UNKNOWN(), Origin.CREF, EMPTY());
case Absyn.ComponentRef.CREF_QUAL()
then CREF(InstNode.NAME_NODE(acref.name),
list(Subscript.RAW_SUBSCRIPT(s) for s in acref.subscripts),
Type.UNKNOWN(), Origin.CREF, fromAbsynCref(acref.componentRef));
case Absyn.ComponentRef.CREF_FULLYQUALIFIED()
then fromAbsynCref(acref.componentRef);
case Absyn.ComponentRef.WILD() then WILD();
case Absyn.ComponentRef.ALLWILD() then WILD();
end match;
end fromAbsynCref;
function fromBuiltin
input InstNode node;
input Type ty;
output ComponentRef cref = CREF(node, {}, ty, Origin.SCOPE, EMPTY());
end fromBuiltin;
function makeIterator
input InstNode node;
input Type ty;
output ComponentRef cref = CREF(node, {}, ty, Origin.ITERATOR, EMPTY());
end makeIterator;
function isEmpty
input ComponentRef cref;
output Boolean isEmpty;
algorithm
isEmpty := match cref
case EMPTY() then true;
else false;
end match;
end isEmpty;
function isSimple
input ComponentRef cref;
output Boolean isSimple;
algorithm
isSimple := match cref
case CREF(restCref = EMPTY()) then true;
else false;
end match;
end isSimple;
function isIterator
input ComponentRef cref;
output Boolean isIterator;
algorithm
isIterator := match cref
case CREF(origin = Origin.ITERATOR) then true;
else false;
end match;
end isIterator;
function node
input ComponentRef cref;
output InstNode node;
algorithm
CREF(node = node) := cref;
end node;
function nodeType
input ComponentRef cref;
output Type ty;
algorithm
CREF(ty = ty) := cref;
end nodeType;
function firstName
input ComponentRef cref;
output String name;
algorithm
name := match cref
case CREF() then InstNode.name(cref.node);
else "";
end match;
end firstName;
function rest
input ComponentRef cref;
output ComponentRef restCref;
algorithm
CREF(restCref = restCref) := cref;
end rest;
function firstNonScope
input ComponentRef cref;
output ComponentRef first;
protected
ComponentRef rest_cr = rest(cref);
algorithm
first := match rest_cr
case CREF(origin = Origin.SCOPE) then cref;
case EMPTY() then cref;
else firstNonScope(rest_cr);
end match;
end firstNonScope;
function append
input output ComponentRef cref;
input ComponentRef restCref;
algorithm
cref := match cref
case CREF()
algorithm
cref.restCref := append(cref.restCref, restCref);
then
cref;
case EMPTY() then restCref;
end match;
end append;
function getComponentType
"Returns the type of the component the given cref refers to, without taking
subscripts into account."
input ComponentRef cref;
output Type ty;
algorithm
ty := match cref
case CREF() then cref.ty;
else Type.UNKNOWN();
end match;
end getComponentType;
function getSubscriptedType
"Returns the type of a cref, with the subscripts taken into account."
input ComponentRef cref;
output Type ty;
algorithm
ty := match cref
case CREF()
then getSubscriptedType2(cref.restCref, Type.subscript(cref.ty, cref.subscripts));
case EMPTY() then Type.UNKNOWN();
case WILD() then Type.ANY();
end match;
end getSubscriptedType;
function getSubscriptedType2
input ComponentRef restCref;
input Type accumTy;
output Type ty;
algorithm
ty := match restCref
case CREF(origin = Origin.CREF)
algorithm
ty := Type.liftArrayLeftList(accumTy,
Type.arrayDims(Type.subscript(restCref.ty, restCref.subscripts)));
then
getSubscriptedType2(restCref.restCref, ty);
else accumTy;
end match;
end getSubscriptedType2;
function nodeVariability
"Returns the variability of the component node the cref refers to."
input ComponentRef cref;
output Variability var;
algorithm
var := match cref
case CREF() then Component.variability(InstNode.component(cref.node));
else Variability.CONTINUOUS;
end match;
end nodeVariability;
function subscriptsVariability
input ComponentRef cref;
input output Variability var = Variability.CONSTANT;
algorithm
() := match cref
case CREF(origin = Origin.CREF)
algorithm
for sub in cref.subscripts loop
var := Prefixes.variabilityMax(var, Subscript.variability(sub));
end for;
then
();
else ();
end match;
end subscriptsVariability;
function variability
"Returns the variability of the cref, with the variability of the subscripts
taken into account."
input ComponentRef cref;
output Variability var = Prefixes.variabilityMax(nodeVariability(cref),
subscriptsVariability(cref));
end variability;
function addSubscript
input Subscript subscript;
input output ComponentRef cref;
algorithm
() := match cref
case CREF()
algorithm
cref.subscripts := listAppend(cref.subscripts, {subscript});
then
();
end match;
end addSubscript;
function applySubscripts
input list<Subscript> subscripts;
input output ComponentRef cref;
algorithm
({}, cref) := applySubscripts2(subscripts, cref);
end applySubscripts;
function applySubscripts2
input output list<Subscript> subscripts;
input output ComponentRef cref;
algorithm
(subscripts, cref) := match cref
local
ComponentRef rest_cref;
list<Subscript> cref_subs;
case CREF(origin = Origin.CREF, subscripts = cref_subs)
algorithm
(subscripts, rest_cref) := applySubscripts2(subscripts, cref.restCref);
if not listEmpty(subscripts) then
(cref_subs, subscripts) :=
Subscript.mergeList(subscripts, cref_subs, Type.dimensionCount(cref.ty));
end if;
then
(subscripts, CREF(cref.node, cref_subs, cref.ty, cref.origin, rest_cref));
else (subscripts, cref);
end match;
end applySubscripts2;
function hasSubscripts
input ComponentRef cref;
output Boolean hasSubscripts;
algorithm
hasSubscripts := match cref
case CREF()
then not listEmpty(cref.subscripts) or hasSubscripts(cref.restCref);
else false;
end match;
end hasSubscripts;
function getSubscripts
input ComponentRef cref;
output list<Subscript> subscripts;
algorithm
subscripts := match cref
case CREF() then cref.subscripts;
else {};
end match;
end getSubscripts;
function setSubscripts
"Sets the subscripts of the first part of a cref."
input list<Subscript> subscripts;
input output ComponentRef cref;
algorithm
() := match cref
case CREF()
algorithm
cref.subscripts := subscripts;
then
();
end match;
end setSubscripts;
function setSubscriptsList
"Sets the subscripts of each part of a cref to the corresponding list of subscripts."
input list<list<Subscript>> subscripts;
input output ComponentRef cref;
algorithm
cref := match (subscripts, cref)
local
list<Subscript> subs;
list<list<Subscript>> rest_subs;
ComponentRef rest_cref;
case (subs :: rest_subs, CREF())
algorithm
rest_cref := setSubscriptsList(rest_subs, cref.restCref);
then
CREF(cref.node, subs, cref.ty, cref.origin, rest_cref);
case ({}, _) then cref;
end match;
end setSubscriptsList;
function subscriptsAll
"Returns all subscripts of a cref in reverse order.
Ex: a[1, 2].b[4].c[6, 3] => {{6,3}, {4}, {1,2}}"
input ComponentRef cref;
input list<list<Subscript>> accumSubs = {};
output list<list<Subscript>> subscripts;
algorithm
subscripts := match cref
case CREF() then subscriptsAll(cref.restCref, cref.subscripts :: accumSubs);
else accumSubs;
end match;
end subscriptsAll;
function subscriptsN
"Returns the subscripts of the N first parts of a cref in reverse order.
Fails if the cref has fewer than N parts."
input ComponentRef cref;
input Integer n;
output list<list<Subscript>> subscripts = {};
protected
list<Subscript> subs;
ComponentRef rest = cref;
algorithm
for i in 1:n loop
CREF(subscripts = subs, restCref = rest) := rest;
subscripts := subs :: subscripts;
end for;
end subscriptsN;
function transferSubscripts
"Copies subscripts from one cref to another, overwriting any subscripts on
the destination cref."
input ComponentRef srcCref;
input ComponentRef dstCref;
output ComponentRef cref;
algorithm
cref := match (srcCref, dstCref)
case (EMPTY(), _) then dstCref;
case (_, EMPTY()) then dstCref;
case (_, CREF(origin = Origin.ITERATOR)) then dstCref;
case (CREF(), CREF(origin = Origin.CREF))
algorithm
dstCref.restCref := transferSubscripts(srcCref, dstCref.restCref);
then
dstCref;
case (CREF(), CREF()) guard referenceEq(srcCref.node, dstCref.node)
algorithm
cref := transferSubscripts(srcCref.restCref, dstCref.restCref);
then
CREF(dstCref.node, srcCref.subscripts, dstCref.ty, dstCref.origin, cref);
case (CREF(), CREF())
then transferSubscripts(srcCref.restCref, dstCref);
else
algorithm
Error.assertion(false, getInstanceName() + " failed", sourceInfo());
then
fail();
end match;
end transferSubscripts;
function foldSubscripts<ArgT>
input ComponentRef cref;
input FuncT func;
input output ArgT arg;
partial function FuncT
input Subscript subscript;
input output ArgT arg;
end FuncT;
algorithm
arg := match cref
case CREF(origin = Origin.CREF)
algorithm
for sub in cref.subscripts loop
arg := func(sub, arg);
end for;
then
foldSubscripts(cref.restCref, func, arg);
else arg;
end match;
end foldSubscripts;
function compare
input ComponentRef cref1;
input ComponentRef cref2;
output Integer comp;
algorithm
comp := match (cref1, cref2)
case (CREF(), CREF())
algorithm
comp := stringCompare(InstNode.name(cref1.node), InstNode.name(cref2.node));
if comp <> 0 then
return;
end if;
comp := Subscript.compareList(cref1.subscripts, cref2.subscripts);
if comp <> 0 then
return;
end if;
then
compare(cref1.restCref, cref2.restCref);
case (EMPTY(), EMPTY()) then 0;
case (_, EMPTY()) then 1;
case (EMPTY(), _) then -1;
end match;
end compare;
function isEqual
input ComponentRef cref1;
input ComponentRef cref2;
output Boolean isEqual;
algorithm
if referenceEq(cref1, cref2) then
isEqual := true;
return;
end if;
isEqual := match (cref1, cref2)
case (CREF(), CREF())
then InstNode.name(cref1.node) == InstNode.name(cref2.node) and
Subscript.isEqualList(cref1.subscripts, cref2.subscripts) and
isEqual(cref1.restCref, cref2.restCref);
case (EMPTY(), EMPTY()) then true;
case (WILD(), WILD()) then true;
else false;
end match;
end isEqual;
function isPrefix
input ComponentRef cref1;
input ComponentRef cref2;
output Boolean isPrefix;
algorithm
if referenceEq(cref1, cref2) then
isPrefix := true;
return;
end if;
isPrefix := match (cref1, cref2)
case (CREF(), CREF())
then
if InstNode.name(cref1.node) == InstNode.name(cref2.node) then
isEqual(cref1.restCref, cref2.restCref)
else isEqual(cref1, cref2.restCref);
else false;
end match;
end isPrefix;
function toDAE
input ComponentRef cref;
output DAE.ComponentRef dcref;
algorithm
dcref := match cref
case CREF()
algorithm
dcref := DAE.ComponentRef.CREF_IDENT(InstNode.name(cref.node), Type.toDAE(cref.ty),
list(Subscript.toDAE(s) for s in cref.subscripts));
then
toDAE_impl(cref.restCref, dcref);
case WILD() then DAE.ComponentRef.WILD();
end match;
end toDAE;
function toDAE_impl
input ComponentRef cref;
input DAE.ComponentRef accumCref;
output DAE.ComponentRef dcref;
algorithm
dcref := match cref
local
Type ty;
DAE.Type dty;
case EMPTY() then accumCref;
case CREF()
algorithm
// If the type is unknown here it's likely because the cref part is
// from a scope prefix, which the typing doesn't bother typing since
// that introduces cycles in the typing. We could patch the crefs
// after the typing, but the new frontend doesn't use these types anyway.
// So instead we just fetch the type of the node if the type is unknown.
ty := if Type.isUnknown(cref.ty) then InstNode.getType(cref.node) else cref.ty;
dty := Type.toDAE(ty, makeTypeVars = false);
dcref := DAE.ComponentRef.CREF_QUAL(InstNode.name(cref.node), dty,
list(Subscript.toDAE(s) for s in cref.subscripts), accumCref);
then
toDAE_impl(cref.restCref, dcref);
end match;
end toDAE_impl;
function toString
input ComponentRef cref;
output String str;
algorithm
str := match cref
case CREF(restCref = EMPTY())
then InstNode.name(cref.node) + Subscript.toStringList(cref.subscripts);
case CREF()
algorithm
str := toString(cref.restCref);
then
str + "." + InstNode.name(cref.node) + Subscript.toStringList(cref.subscripts);
case WILD() then "_";
else "EMPTY_CREF";
end match;
end toString;
function listToString
input list<ComponentRef> crs;
output String str;
algorithm
str := "{" + stringDelimitList(List.map(crs, toString), ",") + "}";
end listToString;
function hash
input ComponentRef cref;
input Integer mod;
output Integer hash = System.stringHashDjb2Mod(toString(cref), mod);
end hash;
function toPath
input ComponentRef cref;
output Absyn.Path path;
algorithm
path := match cref
case CREF()
then toPath_impl(cref.restCref, Absyn.IDENT(InstNode.name(cref.node)));
end match;
end toPath;
function toPath_impl
input ComponentRef cref;
input Absyn.Path accumPath;
output Absyn.Path path;
algorithm
path := match cref
case CREF()
then toPath_impl(cref.restCref,
Absyn.QUALIFIED(InstNode.name(cref.node), accumPath));
else accumPath;
end match;
end toPath_impl;
function fromNodeList
input list<InstNode> nodes;
output ComponentRef cref = ComponentRef.EMPTY();
algorithm
for n in nodes loop
cref := CREF(n, {}, InstNode.getType(n), Origin.SCOPE, cref);
end for;
end fromNodeList;
function scalarize
input ComponentRef cref;
output list<ComponentRef> crefs;
algorithm
crefs := match cref
local
list<Dimension> dims;
list<list<Subscript>> subs;
case CREF(ty = Type.ARRAY())
algorithm
dims := Type.arrayDims(cref.ty);
subs := Subscript.scalarizeList(cref.subscripts, dims);
subs := List.combination(subs);
then
list(setSubscripts(s, cref) for s in subs);
else {cref};
end match;
end scalarize;
function isPackageConstant
input ComponentRef cref;
output Boolean isPkgConst;
algorithm
isPkgConst := match cref
case CREF(node = InstNode.CLASS_NODE()) then InstNode.isUserdefinedClass(cref.node);
case CREF(origin = Origin.CREF) then isPackageConstant(cref.restCref);
else false;
end match;
end isPackageConstant;
function stripSubscripts
"Strips the subscripts from the last name in a cref, e.g. a[2].b[3] => a[2].b"
input ComponentRef cref;
output ComponentRef strippedCref;
algorithm
strippedCref := match cref
case CREF()
then CREF(cref.node, {}, cref.ty, cref.origin, cref.restCref);
else cref;
end match;
end stripSubscripts;
function stripSubscriptsAll
"Strips all subscripts from a cref."
input ComponentRef cref;
output ComponentRef strippedCref;
algorithm
strippedCref := match cref
case CREF()
then CREF(cref.node, {}, cref.ty, cref.origin, stripSubscriptsAll(cref.restCref));
else cref;
end match;
end stripSubscriptsAll;
function simplifySubscripts
input output ComponentRef cref;
algorithm
cref := match cref
local
list<Subscript> subs;
case CREF(subscripts = {}, origin = Origin.CREF)
algorithm
cref.restCref := simplifySubscripts(cref.restCref);
then
cref;
case CREF(origin = Origin.CREF)
algorithm
subs := list(Subscript.simplify(s) for s in cref.subscripts);
then
CREF(cref.node, subs, cref.ty, cref.origin, simplifySubscripts(cref.restCref));
else cref;
end match;
end simplifySubscripts;
function isDeleted
input ComponentRef cref;
output Boolean isDeleted;
algorithm
isDeleted := match cref
local
InstNode node;
case CREF(node = node, origin = Origin.CREF)
then InstNode.isComponent(node) and Component.isDeleted(InstNode.component(node));
else false;
end match;
end isDeleted;
function isFromCref
input ComponentRef cref;
output Boolean fromCref;
algorithm
fromCref := match cref
case CREF(origin = Origin.CREF) then true;
case WILD() then true;
else false;
end match;
end isFromCref;
function toListReverse
input ComponentRef cref;
input list<ComponentRef> accum = {};
output list<ComponentRef> crefs;
algorithm
crefs := match cref
case CREF(origin = Origin.CREF)
then toListReverse(cref.restCref, cref :: accum);
else accum;
end match;
end toListReverse;
function depth
input ComponentRef cref;
output Integer d = 0;
algorithm
d := match cref
case CREF(restCref = EMPTY())
then d + 1;
case CREF()
algorithm
d := 1 + depth(cref.restCref);
then
d;
case WILD() then 0;
else "EMPTY_CREF" then 0;
end match;
end depth;
annotation(__OpenModelica_Interface="frontend");
end NFComponentRef;