github.com/gocuntian/go@v0.0.0-20160610041250-fee02d270bf8/src/cmd/compile/internal/gc/swt.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package gc 6 7 import ( 8 "sort" 9 "strconv" 10 ) 11 12 const ( 13 // expression switch 14 switchKindExpr = iota // switch a {...} or switch 5 {...} 15 switchKindTrue // switch true {...} or switch {...} 16 switchKindFalse // switch false {...} 17 18 // type switch 19 switchKindType // switch a.(type) {...} 20 ) 21 22 const ( 23 caseKindDefault = iota // default: 24 25 // expression switch 26 caseKindExprConst // case 5: 27 caseKindExprVar // case x: 28 29 // type switch 30 caseKindTypeNil // case nil: 31 caseKindTypeConst // case time.Time: (concrete type, has type hash) 32 caseKindTypeVar // case io.Reader: (interface type) 33 ) 34 35 const binarySearchMin = 4 // minimum number of cases for binary search 36 37 // An exprSwitch walks an expression switch. 38 type exprSwitch struct { 39 exprname *Node // node for the expression being switched on 40 kind int // kind of switch statement (switchKind*) 41 } 42 43 // A typeSwitch walks a type switch. 44 type typeSwitch struct { 45 hashname *Node // node for the hash of the type of the variable being switched on 46 facename *Node // node for the concrete type of the variable being switched on 47 okname *Node // boolean node used for comma-ok type assertions 48 } 49 50 // A caseClause is a single case clause in a switch statement. 51 type caseClause struct { 52 node *Node // points at case statement 53 ordinal int // position in switch 54 hash uint32 // hash of a type switch 55 typ uint8 // type of case 56 } 57 58 // typecheckswitch typechecks a switch statement. 59 func typecheckswitch(n *Node) { 60 lno := lineno 61 typecheckslice(n.Ninit.Slice(), Etop) 62 63 var nilonly string 64 var top int 65 var t *Type 66 67 if n.Left != nil && n.Left.Op == OTYPESW { 68 // type switch 69 top = Etype 70 n.Left.Right = typecheck(n.Left.Right, Erv) 71 t = n.Left.Right.Type 72 if t != nil && !t.IsInterface() { 73 Yyerror("cannot type switch on non-interface value %v", Nconv(n.Left.Right, FmtLong)) 74 } 75 } else { 76 // expression switch 77 top = Erv 78 if n.Left != nil { 79 n.Left = typecheck(n.Left, Erv) 80 n.Left = defaultlit(n.Left, nil) 81 t = n.Left.Type 82 } else { 83 t = Types[TBOOL] 84 } 85 if t != nil { 86 switch { 87 case !okforeq[t.Etype]: 88 Yyerror("cannot switch on %v", Nconv(n.Left, FmtLong)) 89 case t.IsSlice(): 90 nilonly = "slice" 91 case t.IsArray() && !t.IsComparable(): 92 Yyerror("cannot switch on %v", Nconv(n.Left, FmtLong)) 93 case t.IsStruct(): 94 if f := t.IncomparableField(); f != nil { 95 Yyerror("cannot switch on %v (struct containing %v cannot be compared)", Nconv(n.Left, FmtLong), f.Type) 96 } 97 case t.Etype == TFUNC: 98 nilonly = "func" 99 case t.IsMap(): 100 nilonly = "map" 101 } 102 } 103 } 104 105 n.Type = t 106 107 var def, niltype *Node 108 for _, ncase := range n.List.Slice() { 109 setlineno(n) 110 if ncase.List.Len() == 0 { 111 // default 112 if def != nil { 113 Yyerror("multiple defaults in switch (first at %v)", def.Line()) 114 } else { 115 def = ncase 116 } 117 } else { 118 ls := ncase.List.Slice() 119 for i1, n1 := range ls { 120 setlineno(n1) 121 ls[i1] = typecheck(ls[i1], Erv|Etype) 122 n1 = ls[i1] 123 if n1.Type == nil || t == nil { 124 continue 125 } 126 setlineno(ncase) 127 switch top { 128 // expression switch 129 case Erv: 130 ls[i1] = defaultlit(ls[i1], t) 131 n1 = ls[i1] 132 switch { 133 case n1.Op == OTYPE: 134 Yyerror("type %v is not an expression", n1.Type) 135 case n1.Type != nil && assignop(n1.Type, t, nil) == 0 && assignop(t, n1.Type, nil) == 0: 136 if n.Left != nil { 137 Yyerror("invalid case %v in switch on %v (mismatched types %v and %v)", n1, n.Left, n1.Type, t) 138 } else { 139 Yyerror("invalid case %v in switch (mismatched types %v and bool)", n1, n1.Type) 140 } 141 case nilonly != "" && !isnil(n1): 142 Yyerror("invalid case %v in switch (can only compare %s %v to nil)", n1, nilonly, n.Left) 143 case t.IsInterface() && !n1.Type.IsInterface() && !n1.Type.IsComparable(): 144 Yyerror("invalid case %v in switch (incomparable type)", Nconv(n1, FmtLong)) 145 } 146 147 // type switch 148 case Etype: 149 var missing, have *Field 150 var ptr int 151 switch { 152 case n1.Op == OLITERAL && n1.Type.IsKind(TNIL): 153 // case nil: 154 if niltype != nil { 155 Yyerror("multiple nil cases in type switch (first at %v)", niltype.Line()) 156 } else { 157 niltype = ncase 158 } 159 case n1.Op != OTYPE && n1.Type != nil: // should this be ||? 160 Yyerror("%v is not a type", Nconv(n1, FmtLong)) 161 // reset to original type 162 n1 = n.Left.Right 163 ls[i1] = n1 164 case !n1.Type.IsInterface() && t.IsInterface() && !implements(n1.Type, t, &missing, &have, &ptr): 165 if have != nil && !missing.Broke && !have.Broke { 166 Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (wrong type for %v method)\n\thave %v%v\n\twant %v%v", Nconv(n.Left.Right, FmtLong), n1.Type, missing.Sym, have.Sym, Tconv(have.Type, FmtShort), missing.Sym, Tconv(missing.Type, FmtShort)) 167 } else if !missing.Broke { 168 Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (missing %v method)", Nconv(n.Left.Right, FmtLong), n1.Type, missing.Sym) 169 } 170 } 171 } 172 } 173 } 174 175 if top == Etype && n.Type != nil { 176 ll := ncase.List 177 if ncase.Rlist.Len() != 0 { 178 nvar := ncase.Rlist.First() 179 if ll.Len() == 1 && ll.First().Type != nil && !ll.First().Type.IsKind(TNIL) { 180 // single entry type switch 181 nvar.Name.Param.Ntype = typenod(ll.First().Type) 182 } else { 183 // multiple entry type switch or default 184 nvar.Name.Param.Ntype = typenod(n.Type) 185 } 186 187 nvar = typecheck(nvar, Erv|Easgn) 188 ncase.Rlist.SetIndex(0, nvar) 189 } 190 } 191 192 typecheckslice(ncase.Nbody.Slice(), Etop) 193 } 194 195 lineno = lno 196 } 197 198 // walkswitch walks a switch statement. 199 func walkswitch(sw *Node) { 200 // convert switch {...} to switch true {...} 201 if sw.Left == nil { 202 sw.Left = Nodbool(true) 203 sw.Left = typecheck(sw.Left, Erv) 204 } 205 206 if sw.Left.Op == OTYPESW { 207 var s typeSwitch 208 s.walk(sw) 209 } else { 210 var s exprSwitch 211 s.walk(sw) 212 } 213 } 214 215 // walk generates an AST implementing sw. 216 // sw is an expression switch. 217 // The AST is generally of the form of a linear 218 // search using if..goto, although binary search 219 // is used with long runs of constants. 220 func (s *exprSwitch) walk(sw *Node) { 221 casebody(sw, nil) 222 223 cond := sw.Left 224 sw.Left = nil 225 226 s.kind = switchKindExpr 227 if Isconst(cond, CTBOOL) { 228 s.kind = switchKindTrue 229 if !cond.Val().U.(bool) { 230 s.kind = switchKindFalse 231 } 232 } 233 234 cond = walkexpr(cond, &sw.Ninit) 235 t := sw.Type 236 if t == nil { 237 return 238 } 239 240 // convert the switch into OIF statements 241 var cas []*Node 242 if s.kind == switchKindTrue || s.kind == switchKindFalse { 243 s.exprname = Nodbool(s.kind == switchKindTrue) 244 } else if consttype(cond) >= 0 { 245 // leave constants to enable dead code elimination (issue 9608) 246 s.exprname = cond 247 } else { 248 s.exprname = temp(cond.Type) 249 cas = []*Node{Nod(OAS, s.exprname, cond)} 250 typecheckslice(cas, Etop) 251 } 252 253 // enumerate the cases, and lop off the default case 254 cc := caseClauses(sw, s.kind) 255 sw.List.Set(nil) 256 var def *Node 257 if len(cc) > 0 && cc[0].typ == caseKindDefault { 258 def = cc[0].node.Right 259 cc = cc[1:] 260 } else { 261 def = Nod(OBREAK, nil, nil) 262 } 263 264 // handle the cases in order 265 for len(cc) > 0 { 266 // deal with expressions one at a time 267 if !okforcmp[t.Etype] || cc[0].typ != caseKindExprConst { 268 a := s.walkCases(cc[:1]) 269 cas = append(cas, a) 270 cc = cc[1:] 271 continue 272 } 273 274 // do binary search on runs of constants 275 var run int 276 for run = 1; run < len(cc) && cc[run].typ == caseKindExprConst; run++ { 277 } 278 279 // sort and compile constants 280 sort.Sort(caseClauseByExpr(cc[:run])) 281 a := s.walkCases(cc[:run]) 282 cas = append(cas, a) 283 cc = cc[run:] 284 } 285 286 // handle default case 287 if nerrors == 0 { 288 cas = append(cas, def) 289 sw.Nbody.Set(append(cas, sw.Nbody.Slice()...)) 290 walkstmtlist(sw.Nbody.Slice()) 291 } 292 } 293 294 // walkCases generates an AST implementing the cases in cc. 295 func (s *exprSwitch) walkCases(cc []*caseClause) *Node { 296 if len(cc) < binarySearchMin { 297 // linear search 298 var cas []*Node 299 for _, c := range cc { 300 n := c.node 301 lno := setlineno(n) 302 303 a := Nod(OIF, nil, nil) 304 if (s.kind != switchKindTrue && s.kind != switchKindFalse) || assignop(n.Left.Type, s.exprname.Type, nil) == OCONVIFACE || assignop(s.exprname.Type, n.Left.Type, nil) == OCONVIFACE { 305 a.Left = Nod(OEQ, s.exprname, n.Left) // if name == val 306 a.Left = typecheck(a.Left, Erv) 307 } else if s.kind == switchKindTrue { 308 a.Left = n.Left // if val 309 } else { 310 // s.kind == switchKindFalse 311 a.Left = Nod(ONOT, n.Left, nil) // if !val 312 a.Left = typecheck(a.Left, Erv) 313 } 314 a.Nbody.Set1(n.Right) // goto l 315 316 cas = append(cas, a) 317 lineno = lno 318 } 319 return liststmt(cas) 320 } 321 322 // find the middle and recur 323 half := len(cc) / 2 324 a := Nod(OIF, nil, nil) 325 mid := cc[half-1].node.Left 326 le := Nod(OLE, s.exprname, mid) 327 if Isconst(mid, CTSTR) { 328 // Search by length and then by value; see exprcmp. 329 lenlt := Nod(OLT, Nod(OLEN, s.exprname, nil), Nod(OLEN, mid, nil)) 330 leneq := Nod(OEQ, Nod(OLEN, s.exprname, nil), Nod(OLEN, mid, nil)) 331 a.Left = Nod(OOROR, lenlt, Nod(OANDAND, leneq, le)) 332 } else { 333 a.Left = le 334 } 335 a.Left = typecheck(a.Left, Erv) 336 a.Nbody.Set1(s.walkCases(cc[:half])) 337 a.Rlist.Set1(s.walkCases(cc[half:])) 338 return a 339 } 340 341 // casebody builds separate lists of statements and cases. 342 // It makes labels between cases and statements 343 // and deals with fallthrough, break, and unreachable statements. 344 func casebody(sw *Node, typeswvar *Node) { 345 if sw.List.Len() == 0 { 346 return 347 } 348 349 lno := setlineno(sw) 350 351 var cas []*Node // cases 352 var stat []*Node // statements 353 var def *Node // defaults 354 br := Nod(OBREAK, nil, nil) 355 356 for i, n := range sw.List.Slice() { 357 setlineno(n) 358 if n.Op != OXCASE { 359 Fatalf("casebody %v", n.Op) 360 } 361 n.Op = OCASE 362 needvar := n.List.Len() != 1 || n.List.First().Op == OLITERAL 363 364 jmp := Nod(OGOTO, newCaseLabel(), nil) 365 if n.List.Len() == 0 { 366 if def != nil { 367 Yyerror("more than one default case") 368 } 369 // reuse original default case 370 n.Right = jmp 371 def = n 372 } 373 374 if n.List.Len() == 1 { 375 // one case -- reuse OCASE node 376 n.Left = n.List.First() 377 n.Right = jmp 378 n.List.Set(nil) 379 cas = append(cas, n) 380 } else { 381 // expand multi-valued cases 382 for _, n1 := range n.List.Slice() { 383 cas = append(cas, Nod(OCASE, n1, jmp)) 384 } 385 } 386 387 stat = append(stat, Nod(OLABEL, jmp.Left, nil)) 388 if typeswvar != nil && needvar && n.Rlist.Len() != 0 { 389 l := []*Node{ 390 Nod(ODCL, n.Rlist.First(), nil), 391 Nod(OAS, n.Rlist.First(), typeswvar), 392 } 393 typecheckslice(l, Etop) 394 stat = append(stat, l...) 395 } 396 stat = append(stat, n.Nbody.Slice()...) 397 398 // botch - shouldn't fall through declaration 399 last := stat[len(stat)-1] 400 if last.Xoffset == n.Xoffset && last.Op == OXFALL { 401 if typeswvar != nil { 402 setlineno(last) 403 Yyerror("cannot fallthrough in type switch") 404 } 405 406 if i+1 >= sw.List.Len() { 407 setlineno(last) 408 Yyerror("cannot fallthrough final case in switch") 409 } 410 411 last.Op = OFALL 412 } else { 413 stat = append(stat, br) 414 } 415 } 416 417 stat = append(stat, br) 418 if def != nil { 419 cas = append(cas, def) 420 } 421 422 sw.List.Set(cas) 423 sw.Nbody.Set(stat) 424 lineno = lno 425 } 426 427 // nSwitchLabel is the number of switch labels generated. 428 // This should be per-function, but it is a global counter for now. 429 var nSwitchLabel int 430 431 func newCaseLabel() *Node { 432 label := strconv.Itoa(nSwitchLabel) 433 nSwitchLabel++ 434 return newname(Lookup(label)) 435 } 436 437 // caseClauses generates a slice of caseClauses 438 // corresponding to the clauses in the switch statement sw. 439 // Kind is the kind of switch statement. 440 func caseClauses(sw *Node, kind int) []*caseClause { 441 var cc []*caseClause 442 for _, n := range sw.List.Slice() { 443 c := new(caseClause) 444 cc = append(cc, c) 445 c.ordinal = len(cc) 446 c.node = n 447 448 if n.Left == nil { 449 c.typ = caseKindDefault 450 continue 451 } 452 453 if kind == switchKindType { 454 // type switch 455 switch { 456 case n.Left.Op == OLITERAL: 457 c.typ = caseKindTypeNil 458 case n.Left.Type.IsInterface(): 459 c.typ = caseKindTypeVar 460 default: 461 c.typ = caseKindTypeConst 462 c.hash = typehash(n.Left.Type) 463 } 464 } else { 465 // expression switch 466 switch consttype(n.Left) { 467 case CTFLT, CTINT, CTRUNE, CTSTR: 468 c.typ = caseKindExprConst 469 default: 470 c.typ = caseKindExprVar 471 } 472 } 473 } 474 475 if cc == nil { 476 return nil 477 } 478 479 // sort by value and diagnose duplicate cases 480 if kind == switchKindType { 481 // type switch 482 sort.Sort(caseClauseByType(cc)) 483 for i, c1 := range cc { 484 if c1.typ == caseKindTypeNil || c1.typ == caseKindDefault { 485 break 486 } 487 for _, c2 := range cc[i+1:] { 488 if c2.typ == caseKindTypeNil || c2.typ == caseKindDefault || c1.hash != c2.hash { 489 break 490 } 491 if Eqtype(c1.node.Left.Type, c2.node.Left.Type) { 492 yyerrorl(c2.node.Lineno, "duplicate case %v in type switch\n\tprevious case at %v", c2.node.Left.Type, c1.node.Line()) 493 } 494 } 495 } 496 } else { 497 // expression switch 498 sort.Sort(caseClauseByExpr(cc)) 499 for i, c1 := range cc { 500 if i+1 == len(cc) { 501 break 502 } 503 c2 := cc[i+1] 504 if exprcmp(c1, c2) != 0 { 505 continue 506 } 507 setlineno(c2.node) 508 Yyerror("duplicate case %v in switch\n\tprevious case at %v", c1.node.Left, c1.node.Line()) 509 } 510 } 511 512 // put list back in processing order 513 sort.Sort(caseClauseByOrd(cc)) 514 return cc 515 } 516 517 // walk generates an AST that implements sw, 518 // where sw is a type switch. 519 // The AST is generally of the form of a linear 520 // search using if..goto, although binary search 521 // is used with long runs of concrete types. 522 func (s *typeSwitch) walk(sw *Node) { 523 cond := sw.Left 524 sw.Left = nil 525 526 if cond == nil { 527 sw.List.Set(nil) 528 return 529 } 530 if cond.Right == nil { 531 setlineno(sw) 532 Yyerror("type switch must have an assignment") 533 return 534 } 535 536 cond.Right = walkexpr(cond.Right, &sw.Ninit) 537 if !cond.Right.Type.IsInterface() { 538 Yyerror("type switch must be on an interface") 539 return 540 } 541 542 var cas []*Node 543 544 // predeclare temporary variables and the boolean var 545 s.facename = temp(cond.Right.Type) 546 547 a := Nod(OAS, s.facename, cond.Right) 548 a = typecheck(a, Etop) 549 cas = append(cas, a) 550 551 s.okname = temp(Types[TBOOL]) 552 s.okname = typecheck(s.okname, Erv) 553 554 s.hashname = temp(Types[TUINT32]) 555 s.hashname = typecheck(s.hashname, Erv) 556 557 // set up labels and jumps 558 casebody(sw, s.facename) 559 560 cc := caseClauses(sw, switchKindType) 561 sw.List.Set(nil) 562 var def *Node 563 if len(cc) > 0 && cc[0].typ == caseKindDefault { 564 def = cc[0].node.Right 565 cc = cc[1:] 566 } else { 567 def = Nod(OBREAK, nil, nil) 568 } 569 var typenil *Node 570 if len(cc) > 0 && cc[0].typ == caseKindTypeNil { 571 typenil = cc[0].node.Right 572 cc = cc[1:] 573 } 574 575 // For empty interfaces, do: 576 // if e._type == nil { 577 // do nil case if it exists, otherwise default 578 // } 579 // h := e._type.hash 580 // Use a similar strategy for non-empty interfaces. 581 582 // Get interface descriptor word. 583 typ := Nod(OITAB, s.facename, nil) 584 585 // Check for nil first. 586 i := Nod(OIF, nil, nil) 587 i.Left = Nod(OEQ, typ, nodnil()) 588 if typenil != nil { 589 // Do explicit nil case right here. 590 i.Nbody.Set1(typenil) 591 } else { 592 // Jump to default case. 593 lbl := newCaseLabel() 594 i.Nbody.Set1(Nod(OGOTO, lbl, nil)) 595 // Wrap default case with label. 596 blk := Nod(OBLOCK, nil, nil) 597 blk.List.Set([]*Node{Nod(OLABEL, lbl, nil), def}) 598 def = blk 599 } 600 i.Left = typecheck(i.Left, Erv) 601 cas = append(cas, i) 602 603 if !cond.Right.Type.IsEmptyInterface() { 604 // Load type from itab. 605 typ = NodSym(ODOTPTR, typ, nil) 606 typ.Type = Ptrto(Types[TUINT8]) 607 typ.Typecheck = 1 608 typ.Xoffset = int64(Widthptr) // offset of _type in runtime.itab 609 typ.Bounded = true // guaranteed not to fault 610 } 611 // Load hash from type. 612 h := NodSym(ODOTPTR, typ, nil) 613 h.Type = Types[TUINT32] 614 h.Typecheck = 1 615 h.Xoffset = int64(2 * Widthptr) // offset of hash in runtime._type 616 h.Bounded = true // guaranteed not to fault 617 a = Nod(OAS, s.hashname, h) 618 a = typecheck(a, Etop) 619 cas = append(cas, a) 620 621 // insert type equality check into each case block 622 for _, c := range cc { 623 n := c.node 624 switch c.typ { 625 case caseKindTypeVar, caseKindTypeConst: 626 n.Right = s.typeone(n) 627 default: 628 Fatalf("typeSwitch with bad kind: %d", c.typ) 629 } 630 } 631 632 // generate list of if statements, binary search for constant sequences 633 for len(cc) > 0 { 634 if cc[0].typ != caseKindTypeConst { 635 n := cc[0].node 636 cas = append(cas, n.Right) 637 cc = cc[1:] 638 continue 639 } 640 641 // identify run of constants 642 var run int 643 for run = 1; run < len(cc) && cc[run].typ == caseKindTypeConst; run++ { 644 } 645 646 // sort by hash 647 sort.Sort(caseClauseByType(cc[:run])) 648 649 // for debugging: linear search 650 if false { 651 for i := 0; i < run; i++ { 652 n := cc[i].node 653 cas = append(cas, n.Right) 654 } 655 continue 656 } 657 658 // combine adjacent cases with the same hash 659 ncase := 0 660 for i := 0; i < run; i++ { 661 ncase++ 662 hash := []*Node{cc[i].node.Right} 663 for j := i + 1; j < run && cc[i].hash == cc[j].hash; j++ { 664 hash = append(hash, cc[j].node.Right) 665 } 666 cc[i].node.Right = liststmt(hash) 667 } 668 669 // binary search among cases to narrow by hash 670 cas = append(cas, s.walkCases(cc[:ncase])) 671 cc = cc[ncase:] 672 } 673 674 // handle default case 675 if nerrors == 0 { 676 cas = append(cas, def) 677 sw.Nbody.Set(append(cas, sw.Nbody.Slice()...)) 678 sw.List.Set(nil) 679 walkstmtlist(sw.Nbody.Slice()) 680 } 681 } 682 683 // typeone generates an AST that jumps to the 684 // case body if the variable is of type t. 685 func (s *typeSwitch) typeone(t *Node) *Node { 686 var name *Node 687 var init []*Node 688 if t.Rlist.Len() == 0 { 689 name = nblank 690 nblank = typecheck(nblank, Erv|Easgn) 691 } else { 692 name = t.Rlist.First() 693 init = []*Node{Nod(ODCL, name, nil)} 694 a := Nod(OAS, name, nil) 695 a = typecheck(a, Etop) 696 init = append(init, a) 697 } 698 699 a := Nod(OAS2, nil, nil) 700 a.List.Set([]*Node{name, s.okname}) // name, ok = 701 b := Nod(ODOTTYPE, s.facename, nil) 702 b.Type = t.Left.Type // interface.(type) 703 a.Rlist.Set1(b) 704 a = typecheck(a, Etop) 705 init = append(init, a) 706 707 c := Nod(OIF, nil, nil) 708 c.Left = s.okname 709 c.Nbody.Set1(t.Right) // if ok { goto l } 710 711 return liststmt(append(init, c)) 712 } 713 714 // walkCases generates an AST implementing the cases in cc. 715 func (s *typeSwitch) walkCases(cc []*caseClause) *Node { 716 if len(cc) < binarySearchMin { 717 var cas []*Node 718 for _, c := range cc { 719 n := c.node 720 if c.typ != caseKindTypeConst { 721 Fatalf("typeSwitch walkCases") 722 } 723 a := Nod(OIF, nil, nil) 724 a.Left = Nod(OEQ, s.hashname, Nodintconst(int64(c.hash))) 725 a.Left = typecheck(a.Left, Erv) 726 a.Nbody.Set1(n.Right) 727 cas = append(cas, a) 728 } 729 return liststmt(cas) 730 } 731 732 // find the middle and recur 733 half := len(cc) / 2 734 a := Nod(OIF, nil, nil) 735 a.Left = Nod(OLE, s.hashname, Nodintconst(int64(cc[half-1].hash))) 736 a.Left = typecheck(a.Left, Erv) 737 a.Nbody.Set1(s.walkCases(cc[:half])) 738 a.Rlist.Set1(s.walkCases(cc[half:])) 739 return a 740 } 741 742 type caseClauseByOrd []*caseClause 743 744 func (x caseClauseByOrd) Len() int { return len(x) } 745 func (x caseClauseByOrd) Swap(i, j int) { x[i], x[j] = x[j], x[i] } 746 func (x caseClauseByOrd) Less(i, j int) bool { 747 c1, c2 := x[i], x[j] 748 switch { 749 // sort default first 750 case c1.typ == caseKindDefault: 751 return true 752 case c2.typ == caseKindDefault: 753 return false 754 755 // sort nil second 756 case c1.typ == caseKindTypeNil: 757 return true 758 case c2.typ == caseKindTypeNil: 759 return false 760 } 761 762 // sort by ordinal 763 return c1.ordinal < c2.ordinal 764 } 765 766 type caseClauseByExpr []*caseClause 767 768 func (x caseClauseByExpr) Len() int { return len(x) } 769 func (x caseClauseByExpr) Swap(i, j int) { x[i], x[j] = x[j], x[i] } 770 func (x caseClauseByExpr) Less(i, j int) bool { 771 return exprcmp(x[i], x[j]) < 0 772 } 773 774 func exprcmp(c1, c2 *caseClause) int { 775 // sort non-constants last 776 if c1.typ != caseKindExprConst { 777 return +1 778 } 779 if c2.typ != caseKindExprConst { 780 return -1 781 } 782 783 n1 := c1.node.Left 784 n2 := c2.node.Left 785 786 // sort by type (for switches on interface) 787 ct := n1.Val().Ctype() 788 if ct > n2.Val().Ctype() { 789 return +1 790 } 791 if ct < n2.Val().Ctype() { 792 return -1 793 } 794 if !Eqtype(n1.Type, n2.Type) { 795 if n1.Type.Vargen > n2.Type.Vargen { 796 return +1 797 } else { 798 return -1 799 } 800 } 801 802 // sort by constant value to enable binary search 803 switch ct { 804 case CTFLT: 805 return n1.Val().U.(*Mpflt).Cmp(n2.Val().U.(*Mpflt)) 806 case CTINT, CTRUNE: 807 return n1.Val().U.(*Mpint).Cmp(n2.Val().U.(*Mpint)) 808 case CTSTR: 809 // Sort strings by length and then by value. 810 // It is much cheaper to compare lengths than values, 811 // and all we need here is consistency. 812 // We respect this sorting in exprSwitch.walkCases. 813 a := n1.Val().U.(string) 814 b := n2.Val().U.(string) 815 if len(a) < len(b) { 816 return -1 817 } 818 if len(a) > len(b) { 819 return +1 820 } 821 if a == b { 822 return 0 823 } 824 if a < b { 825 return -1 826 } 827 return +1 828 } 829 830 return 0 831 } 832 833 type caseClauseByType []*caseClause 834 835 func (x caseClauseByType) Len() int { return len(x) } 836 func (x caseClauseByType) Swap(i, j int) { x[i], x[j] = x[j], x[i] } 837 func (x caseClauseByType) Less(i, j int) bool { 838 c1, c2 := x[i], x[j] 839 switch { 840 // sort non-constants last 841 case c1.typ != caseKindTypeConst: 842 return false 843 case c2.typ != caseKindTypeConst: 844 return true 845 846 // sort by hash code 847 case c1.hash != c2.hash: 848 return c1.hash < c2.hash 849 } 850 851 // sort by ordinal 852 return c1.ordinal < c2.ordinal 853 }