1 | // +build ignore |
---|---|
2 | |
3 | package main |
4 | |
5 | // This file is the input to TestSwitches in switch_test.go. |
6 | // Each multiway conditional with constant or type cases (Switch) |
7 | // discovered by Switches is printed, and compared with the |
8 | // comments. |
9 | // |
10 | // The body of each case is printed as the value of its first |
11 | // instruction. |
12 | |
13 | // -------- Value switches -------- |
14 | |
15 | func SimpleSwitch(x, y int) { |
16 | // switch x { |
17 | // case 1:int: print(1:int) |
18 | // case 2:int: print(23:int) |
19 | // case 3:int: print(23:int) |
20 | // case 4:int: print(3:int) |
21 | // default: x == y |
22 | // } |
23 | switch x { |
24 | case 1: |
25 | print(1) |
26 | case 2, 3: |
27 | print(23) |
28 | fallthrough |
29 | case 4: |
30 | print(3) |
31 | default: |
32 | print(4) |
33 | case y: |
34 | print(5) |
35 | } |
36 | print(6) |
37 | } |
38 | |
39 | func four() int { return 4 } |
40 | |
41 | // A non-constant case makes a switch "impure", but its pure |
42 | // cases form two separate switches. |
43 | func SwitchWithNonConstantCase(x int) { |
44 | // switch x { |
45 | // case 1:int: print(1:int) |
46 | // case 2:int: print(23:int) |
47 | // case 3:int: print(23:int) |
48 | // default: four() |
49 | // } |
50 | |
51 | // switch x { |
52 | // case 5:int: print(5:int) |
53 | // case 6:int: print(6:int) |
54 | // default: print("done":string) |
55 | // } |
56 | switch x { |
57 | case 1: |
58 | print(1) |
59 | case 2, 3: |
60 | print(23) |
61 | case four(): |
62 | print(3) |
63 | case 5: |
64 | print(5) |
65 | case 6: |
66 | print(6) |
67 | } |
68 | print("done") |
69 | } |
70 | |
71 | // Switches may be found even where the source |
72 | // program doesn't have a switch statement. |
73 | |
74 | func ImplicitSwitches(x, y int) { |
75 | // switch x { |
76 | // case 1:int: print(12:int) |
77 | // case 2:int: print(12:int) |
78 | // default: x < 5:int |
79 | // } |
80 | if x == 1 || 2 == x || x < 5 { |
81 | print(12) |
82 | } |
83 | |
84 | // switch x { |
85 | // case 3:int: print(34:int) |
86 | // case 4:int: print(34:int) |
87 | // default: x == y |
88 | // } |
89 | if x == 3 || 4 == x || x == y { |
90 | print(34) |
91 | } |
92 | |
93 | // Not a switch: no consistent variable. |
94 | if x == 5 || y == 6 { |
95 | print(56) |
96 | } |
97 | |
98 | // Not a switch: only one constant comparison. |
99 | if x == 7 || x == y { |
100 | print(78) |
101 | } |
102 | } |
103 | |
104 | func IfElseBasedSwitch(x int) { |
105 | // switch x { |
106 | // case 1:int: print(1:int) |
107 | // case 2:int: print(2:int) |
108 | // default: print("else":string) |
109 | // } |
110 | if x == 1 { |
111 | print(1) |
112 | } else if x == 2 { |
113 | print(2) |
114 | } else { |
115 | print("else") |
116 | } |
117 | } |
118 | |
119 | func GotoBasedSwitch(x int) { |
120 | // switch x { |
121 | // case 1:int: print(1:int) |
122 | // case 2:int: print(2:int) |
123 | // default: print("else":string) |
124 | // } |
125 | if x == 1 { |
126 | goto L1 |
127 | } |
128 | if x == 2 { |
129 | goto L2 |
130 | } |
131 | print("else") |
132 | L1: |
133 | print(1) |
134 | goto end |
135 | L2: |
136 | print(2) |
137 | end: |
138 | } |
139 | |
140 | func SwitchInAForLoop(x int) { |
141 | // switch x { |
142 | // case 1:int: print(1:int) |
143 | // case 2:int: print(2:int) |
144 | // default: print("head":string) |
145 | // } |
146 | loop: |
147 | for { |
148 | print("head") |
149 | switch x { |
150 | case 1: |
151 | print(1) |
152 | break loop |
153 | case 2: |
154 | print(2) |
155 | break loop |
156 | } |
157 | } |
158 | } |
159 | |
160 | // This case is a switch in a for-loop, both constructed using goto. |
161 | // As before, the default case points back to the block containing the |
162 | // switch, but that's ok. |
163 | func SwitchInAForLoopUsingGoto(x int) { |
164 | // switch x { |
165 | // case 1:int: print(1:int) |
166 | // case 2:int: print(2:int) |
167 | // default: print("head":string) |
168 | // } |
169 | loop: |
170 | print("head") |
171 | if x == 1 { |
172 | goto L1 |
173 | } |
174 | if x == 2 { |
175 | goto L2 |
176 | } |
177 | goto loop |
178 | L1: |
179 | print(1) |
180 | goto end |
181 | L2: |
182 | print(2) |
183 | end: |
184 | } |
185 | |
186 | func UnstructuredSwitchInAForLoop(x int) { |
187 | // switch x { |
188 | // case 1:int: print(1:int) |
189 | // case 2:int: x == 1:int |
190 | // default: print("end":string) |
191 | // } |
192 | for { |
193 | if x == 1 { |
194 | print(1) |
195 | return |
196 | } |
197 | if x == 2 { |
198 | continue |
199 | } |
200 | break |
201 | } |
202 | print("end") |
203 | } |
204 | |
205 | func CaseWithMultiplePreds(x int) { |
206 | for { |
207 | if x == 1 { |
208 | print(1) |
209 | return |
210 | } |
211 | loop: |
212 | // This block has multiple predecessors, |
213 | // so can't be treated as a switch case. |
214 | if x == 2 { |
215 | goto loop |
216 | } |
217 | break |
218 | } |
219 | print("end") |
220 | } |
221 | |
222 | func DuplicateConstantsAreNotEliminated(x int) { |
223 | // switch x { |
224 | // case 1:int: print(1:int) |
225 | // case 1:int: print("1a":string) |
226 | // case 2:int: print(2:int) |
227 | // default: return |
228 | // } |
229 | if x == 1 { |
230 | print(1) |
231 | } else if x == 1 { // duplicate => unreachable |
232 | print("1a") |
233 | } else if x == 2 { |
234 | print(2) |
235 | } |
236 | } |
237 | |
238 | // Interface values (created by comparisons) are not constants, |
239 | // so ConstSwitch.X is never of interface type. |
240 | func MakeInterfaceIsNotAConstant(x interface{}) { |
241 | if x == "foo" { |
242 | print("foo") |
243 | } else if x == 1 { |
244 | print(1) |
245 | } |
246 | } |
247 | |
248 | func ZeroInitializedVarsAreConstants(x int) { |
249 | // switch x { |
250 | // case 0:int: print(1:int) |
251 | // case 2:int: print(2:int) |
252 | // default: print("end":string) |
253 | // } |
254 | var zero int // SSA construction replaces zero with 0 |
255 | if x == zero { |
256 | print(1) |
257 | } else if x == 2 { |
258 | print(2) |
259 | } |
260 | print("end") |
261 | } |
262 | |
263 | // -------- Select -------- |
264 | |
265 | // NB, potentially fragile reliance on register number. |
266 | func SelectDesugarsToSwitch(ch chan int) { |
267 | // switch t1 { |
268 | // case 0:int: extract t0 #2 |
269 | // case 1:int: println(0:int) |
270 | // case 2:int: println(1:int) |
271 | // default: println("default":string) |
272 | // } |
273 | select { |
274 | case x := <-ch: |
275 | println(x) |
276 | case <-ch: |
277 | println(0) |
278 | case ch <- 1: |
279 | println(1) |
280 | default: |
281 | println("default") |
282 | } |
283 | } |
284 | |
285 | // NB, potentially fragile reliance on register number. |
286 | func NonblockingSelectDefaultCasePanics(ch chan int) { |
287 | // switch t1 { |
288 | // case 0:int: extract t0 #2 |
289 | // case 1:int: println(0:int) |
290 | // case 2:int: println(1:int) |
291 | // default: make interface{} <- string ("blocking select m...":string) |
292 | // } |
293 | select { |
294 | case x := <-ch: |
295 | println(x) |
296 | case <-ch: |
297 | println(0) |
298 | case ch <- 1: |
299 | println(1) |
300 | } |
301 | } |
302 | |
303 | // -------- Type switches -------- |
304 | |
305 | // NB, reliance on fragile register numbering. |
306 | func SimpleTypeSwitch(x interface{}) { |
307 | // switch x.(type) { |
308 | // case t3 int: println(x) |
309 | // case t7 bool: println(x) |
310 | // case t10 string: println(t10) |
311 | // default: println(x) |
312 | // } |
313 | switch y := x.(type) { |
314 | case nil: |
315 | println(y) |
316 | case int, bool: |
317 | println(y) |
318 | case string: |
319 | println(y) |
320 | default: |
321 | println(y) |
322 | } |
323 | } |
324 | |
325 | // NB, potentially fragile reliance on register number. |
326 | func DuplicateTypesAreNotEliminated(x interface{}) { |
327 | // switch x.(type) { |
328 | // case t1 string: println(1:int) |
329 | // case t5 interface{}: println(t5) |
330 | // case t9 int: println(3:int) |
331 | // default: return |
332 | // } |
333 | switch y := x.(type) { |
334 | case string: |
335 | println(1) |
336 | case interface{}: |
337 | println(y) |
338 | case int: |
339 | println(3) // unreachable! |
340 | } |
341 | } |
342 | |
343 | // NB, potentially fragile reliance on register number. |
344 | func AdHocTypeSwitch(x interface{}) { |
345 | // switch x.(type) { |
346 | // case t1 int: println(t1) |
347 | // case t5 string: println(t5) |
348 | // default: print("default":string) |
349 | // } |
350 | if i, ok := x.(int); ok { |
351 | println(i) |
352 | } else if s, ok := x.(string); ok { |
353 | println(s) |
354 | } else { |
355 | print("default") |
356 | } |
357 | } |
358 |
Members