| // +build ignore |
| |
| package main |
| |
| // This file is the input to TestSwitches in switch_test.go. |
| // Each multiway conditional with constant or type cases (Switch) |
| // discovered by Switches is printed, and compared with the |
| // comments. |
| // |
| // The body of each case is printed as the value of its first |
| // instruction. |
| |
| // -------- Value switches -------- |
| |
| func SimpleSwitch(x, y int) { |
| // switch x { |
| // case 1:int: print(1:int) |
| // case 2:int: print(23:int) |
| // case 3:int: print(23:int) |
| // case 4:int: print(3:int) |
| // default: x == y |
| // } |
| switch x { |
| case 1: |
| print(1) |
| case 2, 3: |
| print(23) |
| fallthrough |
| case 4: |
| print(3) |
| default: |
| print(4) |
| case y: |
| print(5) |
| } |
| print(6) |
| } |
| |
| func four() int { return 4 } |
| |
| // A non-constant case makes a switch "impure", but its pure |
| // cases form two separate switches. |
| func SwitchWithNonConstantCase(x int) { |
| // switch x { |
| // case 1:int: print(1:int) |
| // case 2:int: print(23:int) |
| // case 3:int: print(23:int) |
| // default: four() |
| // } |
| |
| // switch x { |
| // case 5:int: print(5:int) |
| // case 6:int: print(6:int) |
| // default: print("done":string) |
| // } |
| switch x { |
| case 1: |
| print(1) |
| case 2, 3: |
| print(23) |
| case four(): |
| print(3) |
| case 5: |
| print(5) |
| case 6: |
| print(6) |
| } |
| print("done") |
| } |
| |
| // Switches may be found even where the source |
| // program doesn't have a switch statement. |
| |
| func ImplicitSwitches(x, y int) { |
| // switch x { |
| // case 1:int: print(12:int) |
| // case 2:int: print(12:int) |
| // default: x < 5:int |
| // } |
| if x == 1 || 2 == x || x < 5 { |
| print(12) |
| } |
| |
| // switch x { |
| // case 3:int: print(34:int) |
| // case 4:int: print(34:int) |
| // default: x == y |
| // } |
| if x == 3 || 4 == x || x == y { |
| print(34) |
| } |
| |
| // Not a switch: no consistent variable. |
| if x == 5 || y == 6 { |
| print(56) |
| } |
| |
| // Not a switch: only one constant comparison. |
| if x == 7 || x == y { |
| print(78) |
| } |
| } |
| |
| func IfElseBasedSwitch(x int) { |
| // switch x { |
| // case 1:int: print(1:int) |
| // case 2:int: print(2:int) |
| // default: print("else":string) |
| // } |
| if x == 1 { |
| print(1) |
| } else if x == 2 { |
| print(2) |
| } else { |
| print("else") |
| } |
| } |
| |
| func GotoBasedSwitch(x int) { |
| // switch x { |
| // case 1:int: print(1:int) |
| // case 2:int: print(2:int) |
| // default: print("else":string) |
| // } |
| if x == 1 { |
| goto L1 |
| } |
| if x == 2 { |
| goto L2 |
| } |
| print("else") |
| L1: |
| print(1) |
| goto end |
| L2: |
| print(2) |
| end: |
| } |
| |
| func SwitchInAForLoop(x int) { |
| // switch x { |
| // case 1:int: print(1:int) |
| // case 2:int: print(2:int) |
| // default: print("head":string) |
| // } |
| loop: |
| for { |
| print("head") |
| switch x { |
| case 1: |
| print(1) |
| break loop |
| case 2: |
| print(2) |
| break loop |
| } |
| } |
| } |
| |
| // This case is a switch in a for-loop, both constructed using goto. |
| // As before, the default case points back to the block containing the |
| // switch, but that's ok. |
| func SwitchInAForLoopUsingGoto(x int) { |
| // switch x { |
| // case 1:int: print(1:int) |
| // case 2:int: print(2:int) |
| // default: print("head":string) |
| // } |
| loop: |
| print("head") |
| if x == 1 { |
| goto L1 |
| } |
| if x == 2 { |
| goto L2 |
| } |
| goto loop |
| L1: |
| print(1) |
| goto end |
| L2: |
| print(2) |
| end: |
| } |
| |
| func UnstructuredSwitchInAForLoop(x int) { |
| // switch x { |
| // case 1:int: print(1:int) |
| // case 2:int: x == 1:int |
| // default: print("end":string) |
| // } |
| for { |
| if x == 1 { |
| print(1) |
| return |
| } |
| if x == 2 { |
| continue |
| } |
| break |
| } |
| print("end") |
| } |
| |
| func CaseWithMultiplePreds(x int) { |
| for { |
| if x == 1 { |
| print(1) |
| return |
| } |
| loop: |
| // This block has multiple predecessors, |
| // so can't be treated as a switch case. |
| if x == 2 { |
| goto loop |
| } |
| break |
| } |
| print("end") |
| } |
| |
| func DuplicateConstantsAreNotEliminated(x int) { |
| // switch x { |
| // case 1:int: print(1:int) |
| // case 1:int: print("1a":string) |
| // case 2:int: print(2:int) |
| // default: return |
| // } |
| if x == 1 { |
| print(1) |
| } else if x == 1 { // duplicate => unreachable |
| print("1a") |
| } else if x == 2 { |
| print(2) |
| } |
| } |
| |
| // Interface values (created by comparisons) are not constants, |
| // so ConstSwitch.X is never of interface type. |
| func MakeInterfaceIsNotAConstant(x interface{}) { |
| if x == "foo" { |
| print("foo") |
| } else if x == 1 { |
| print(1) |
| } |
| } |
| |
| func ZeroInitializedVarsAreConstants(x int) { |
| // switch x { |
| // case 0:int: print(1:int) |
| // case 2:int: print(2:int) |
| // default: print("end":string) |
| // } |
| var zero int // SSA construction replaces zero with 0 |
| if x == zero { |
| print(1) |
| } else if x == 2 { |
| print(2) |
| } |
| print("end") |
| } |
| |
| // -------- Select -------- |
| |
| // NB, potentially fragile reliance on register number. |
| func SelectDesugarsToSwitch(ch chan int) { |
| // switch t1 { |
| // case 0:int: extract t0 #2 |
| // case 1:int: println(0:int) |
| // case 2:int: println(1:int) |
| // default: println("default":string) |
| // } |
| select { |
| case x := <-ch: |
| println(x) |
| case <-ch: |
| println(0) |
| case ch <- 1: |
| println(1) |
| default: |
| println("default") |
| } |
| } |
| |
| // NB, potentially fragile reliance on register number. |
| func NonblockingSelectDefaultCasePanics(ch chan int) { |
| // switch t1 { |
| // case 0:int: extract t0 #2 |
| // case 1:int: println(0:int) |
| // case 2:int: println(1:int) |
| // default: make interface{} <- string ("blocking select m...":string) |
| // } |
| select { |
| case x := <-ch: |
| println(x) |
| case <-ch: |
| println(0) |
| case ch <- 1: |
| println(1) |
| } |
| } |
| |
| // -------- Type switches -------- |
| |
| // NB, reliance on fragile register numbering. |
| func SimpleTypeSwitch(x interface{}) { |
| // switch x.(type) { |
| // case t3 int: println(x) |
| // case t7 bool: println(x) |
| // case t10 string: println(t10) |
| // default: println(x) |
| // } |
| switch y := x.(type) { |
| case nil: |
| println(y) |
| case int, bool: |
| println(y) |
| case string: |
| println(y) |
| default: |
| println(y) |
| } |
| } |
| |
| // NB, potentially fragile reliance on register number. |
| func DuplicateTypesAreNotEliminated(x interface{}) { |
| // switch x.(type) { |
| // case t1 string: println(1:int) |
| // case t5 interface{}: println(t5) |
| // case t9 int: println(3:int) |
| // default: return |
| // } |
| switch y := x.(type) { |
| case string: |
| println(1) |
| case interface{}: |
| println(y) |
| case int: |
| println(3) // unreachable! |
| } |
| } |
| |
| // NB, potentially fragile reliance on register number. |
| func AdHocTypeSwitch(x interface{}) { |
| // switch x.(type) { |
| // case t1 int: println(t1) |
| // case t5 string: println(t5) |
| // default: print("default":string) |
| // } |
| if i, ok := x.(int); ok { |
| println(i) |
| } else if s, ok := x.(string); ok { |
| println(s) |
| } else { |
| print("default") |
| } |
| } |