| 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