2 This module contains compiler support for switch...case statements
4 Copyright: Copyright Digital Mars 2000 - 2019.
5 License: Distributed under the
6 $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
7 (See accompanying file LICENSE)
8 Source: $(DRUNTIMESRC core/internal/_switch_.d)
10 module core
.internal
.switch_
;
13 Support for switch statements switching on strings.
15 caseLabels = sorted array of strings generated by compiler. Note the
16 strings are sorted by length first, and then lexicographically.
17 condition = string to look up in table
19 index of match in caseLabels, a negative integer if not found
21 int __switch(T
, caseLabels
...)(/*in*/ const scope T
[] condition
) pure nothrow @safe @nogc
23 // This closes recursion for other cases.
24 static if (caseLabels
.length
== 0)
28 else static if (caseLabels
.length
== 1)
30 return __cmp(condition
, caseLabels
[0]) == 0 ?
0 : int.min
;
32 // To be adjusted after measurements
33 // Compile-time inlined binary search.
34 else static if (caseLabels
.length
< 7)
37 enum mid
= cast(int)caseLabels
.length
/ 2;
38 if (condition
.length
== caseLabels
[mid
].length
)
40 r
= __cmp(condition
, caseLabels
[mid
]);
41 if (r
== 0) return mid
;
45 // Equivalent to (but faster than) condition.length > caseLabels[$ / 2].length ? 1 : -1
46 r
= ((condition
.length
> caseLabels
[mid
].length
) << 1) - 1;
51 // Search the left side
52 return __switch
!(T
, caseLabels
[0 .. mid
])(condition
);
56 // Search the right side
57 return __switch
!(T
, caseLabels
[mid
+ 1 .. $])(condition
) + mid
+ 1;
62 // Need immutable array to be accessible in pure code, but case labels are
63 // currently coerced to the switch condition type (e.g. const(char)[]).
64 pure @trusted nothrow @nogc asImmutable(scope const(T
[])[] items
)
66 assert(__ctfe
); // only @safe for CTFE
67 immutable T
[][caseLabels
.length
] result
= cast(immutable)(items
[]);
70 static immutable T
[][caseLabels
.length
] cases
= asImmutable([caseLabels
]);
72 // Run-time binary search in a static array of labels.
73 return __switchSearch
!T(cases
[], condition
);
77 // binary search in sorted string cases, also see `__switch`.
78 private int __switchSearch(T
)(/*in*/ const scope T
[][] cases
, /*in*/ const scope T
[] condition
) pure nothrow @safe @nogc
81 size_t high
= cases
.length
;
85 auto mid
= (low
+ high
) / 2;
87 if (condition
.length
== cases
[mid
].length
)
89 r
= __cmp(condition
, cases
[mid
]);
90 if (r
== 0) return cast(int) mid
;
94 // Generates better code than "expr ? 1 : -1" on dmd and gdc, same with ldc
95 r
= ((condition
.length
> cases
[mid
].length
) << 1) - 1;
98 if (r
> 0) low
= mid
+ 1;
109 static void testSwitch(T
)()
111 switch (cast(T
[]) "c")
118 static int bug5381(immutable(T
)[] s
)
122 case "unittest": return 1;
123 case "D_Version2": return 2;
124 case "nonenone": return 3;
125 case "none": return 4;
126 case "all": return 5;
131 int rc
= bug5381("unittest");
134 rc
= bug5381("D_Version2");
137 rc
= bug5381("nonenone");
140 rc
= bug5381("none");
146 rc
= bug5381("nonerandom");
149 static int binarySearch(immutable(T
)[] s
)
153 static foreach (i
; 0 .. 16)
154 case i
.stringof
: return i
;
158 static foreach (i
; 0 .. 16)
159 assert(binarySearch(i
.stringof
) == i
);
160 assert(binarySearch("") == -1);
161 assert(binarySearch("sth.") == -1);
162 assert(binarySearch(null) == -1);
164 static int bug16739(immutable(T
)[] s
)
168 case "\u0100": return 1;
173 assert(bug16739("\u0100") == 1);
174 assert(bug16739("a") == 2);
175 assert(bug16739("foo") == 3);
183 Compiler lowers final switch default case to this (which is a runtime error)
184 Old implementation is in core/exception.d
186 void __switch_error()(string file
= __FILE__
, size_t line
= __LINE__
)
188 import core
.exception
: __switch_errorT
;
189 __switch_errorT(file
, line
);