github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/src/cmd/gc/swt.c (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  #include	<u.h>
     6  #include	<libc.h>
     7  #include	"go.h"
     8  
     9  enum
    10  {
    11  	Snorm		= 0,
    12  	Strue,
    13  	Sfalse,
    14  	Stype,
    15  
    16  	Tdefault,	// default case
    17  	Texprconst,	// normal constant case
    18  	Texprvar,	// normal variable case
    19  	Ttypenil,	// case nil
    20  	Ttypeconst,	// type hashes
    21  	Ttypevar,	// interface type
    22  
    23  	Ncase	= 4,	// count needed to split
    24  };
    25  
    26  typedef	struct	Case	Case;
    27  struct	Case
    28  {
    29  	Node*	node;		// points at case statement
    30  	uint32	hash;		// hash of a type switch
    31  	uint8	type;		// type of case
    32  	uint8	diag;		// suppress multiple diagnostics
    33  	uint16	ordinal;	// position in switch
    34  	Case*	link;		// linked list to link
    35  };
    36  #define	C	((Case*)nil)
    37  
    38  void
    39  dumpcase(Case *c0)
    40  {
    41  	Case *c;
    42  
    43  	for(c=c0; c!=C; c=c->link) {
    44  		switch(c->type) {
    45  		case Tdefault:
    46  			print("case-default\n");
    47  			print("	ord=%d\n", c->ordinal);
    48  			break;
    49  		case Texprconst:
    50  			print("case-exprconst\n");
    51  			print("	ord=%d\n", c->ordinal);
    52  			break;
    53  		case Texprvar:
    54  			print("case-exprvar\n");
    55  			print("	ord=%d\n", c->ordinal);
    56  			print("	op=%O\n", c->node->left->op);
    57  			break;
    58  		case Ttypenil:
    59  			print("case-typenil\n");
    60  			print("	ord=%d\n", c->ordinal);
    61  			break;
    62  		case Ttypeconst:
    63  			print("case-typeconst\n");
    64  			print("	ord=%d\n", c->ordinal);
    65  			print("	hash=%ux\n", c->hash);
    66  			break;
    67  		case Ttypevar:
    68  			print("case-typevar\n");
    69  			print("	ord=%d\n", c->ordinal);
    70  			break;
    71  		default:
    72  			print("case-???\n");
    73  			print("	ord=%d\n", c->ordinal);
    74  			print("	op=%O\n", c->node->left->op);
    75  			print("	hash=%ux\n", c->hash);
    76  			break;
    77  		}
    78  	}
    79  	print("\n");
    80  }
    81  
    82  static int
    83  ordlcmp(Case *c1, Case *c2)
    84  {
    85  	// sort default first
    86  	if(c1->type == Tdefault)
    87  		return -1;
    88  	if(c2->type == Tdefault)
    89  		return +1;
    90  
    91  	// sort nil second
    92  	if(c1->type == Ttypenil)
    93  		return -1;
    94  	if(c2->type == Ttypenil)
    95  		return +1;
    96  
    97  	// sort by ordinal
    98  	if(c1->ordinal > c2->ordinal)
    99  		return +1;
   100  	if(c1->ordinal < c2->ordinal)
   101  		return -1;
   102  	return 0;
   103  }
   104  
   105  static int
   106  exprcmp(Case *c1, Case *c2)
   107  {
   108  	int ct, n;
   109  	Node *n1, *n2;
   110  
   111  	// sort non-constants last
   112  	if(c1->type != Texprconst)
   113  		return +1;
   114  	if(c2->type != Texprconst)
   115  		return -1;
   116  
   117  	n1 = c1->node->left;
   118  	n2 = c2->node->left;
   119  
   120  	// sort by type (for switches on interface)
   121  	ct = n1->val.ctype;
   122  	if(ct != n2->val.ctype)
   123  		return ct - n2->val.ctype;
   124  	if(!eqtype(n1->type, n2->type)) {
   125  		if(n1->type->vargen > n2->type->vargen)
   126  			return +1;
   127  		else
   128  			return -1;
   129  	}
   130  
   131  	// sort by constant value
   132  	n = 0;
   133  	switch(ct) {
   134  	case CTFLT:
   135  		n = mpcmpfltflt(n1->val.u.fval, n2->val.u.fval);
   136  		break;
   137  	case CTINT:
   138  	case CTRUNE:
   139  		n = mpcmpfixfix(n1->val.u.xval, n2->val.u.xval);
   140  		break;
   141  	case CTSTR:
   142  		n = cmpslit(n1, n2);
   143  		break;
   144  	}
   145  
   146  	return n;
   147  }
   148  
   149  static int
   150  typecmp(Case *c1, Case *c2)
   151  {
   152  
   153  	// sort non-constants last
   154  	if(c1->type != Ttypeconst)
   155  		return +1;
   156  	if(c2->type != Ttypeconst)
   157  		return -1;
   158  
   159  	// sort by hash code
   160  	if(c1->hash > c2->hash)
   161  		return +1;
   162  	if(c1->hash < c2->hash)
   163  		return -1;
   164  
   165  	// sort by ordinal so duplicate error
   166  	// happens on later case.
   167  	if(c1->ordinal > c2->ordinal)
   168  		return +1;
   169  	if(c1->ordinal < c2->ordinal)
   170  		return -1;
   171  	return 0;
   172  }
   173  
   174  static Case*
   175  csort(Case *l, int(*f)(Case*, Case*))
   176  {
   177  	Case *l1, *l2, *le;
   178  
   179  	if(l == C || l->link == C)
   180  		return l;
   181  
   182  	l1 = l;
   183  	l2 = l;
   184  	for(;;) {
   185  		l2 = l2->link;
   186  		if(l2 == C)
   187  			break;
   188  		l2 = l2->link;
   189  		if(l2 == C)
   190  			break;
   191  		l1 = l1->link;
   192  	}
   193  
   194  	l2 = l1->link;
   195  	l1->link = C;
   196  	l1 = csort(l, f);
   197  	l2 = csort(l2, f);
   198  
   199  	/* set up lead element */
   200  	if((*f)(l1, l2) < 0) {
   201  		l = l1;
   202  		l1 = l1->link;
   203  	} else {
   204  		l = l2;
   205  		l2 = l2->link;
   206  	}
   207  	le = l;
   208  
   209  	for(;;) {
   210  		if(l1 == C) {
   211  			while(l2) {
   212  				le->link = l2;
   213  				le = l2;
   214  				l2 = l2->link;
   215  			}
   216  			le->link = C;
   217  			break;
   218  		}
   219  		if(l2 == C) {
   220  			while(l1) {
   221  				le->link = l1;
   222  				le = l1;
   223  				l1 = l1->link;
   224  			}
   225  			break;
   226  		}
   227  		if((*f)(l1, l2) < 0) {
   228  			le->link = l1;
   229  			le = l1;
   230  			l1 = l1->link;
   231  		} else {
   232  			le->link = l2;
   233  			le = l2;
   234  			l2 = l2->link;
   235  		}
   236  	}
   237  	le->link = C;
   238  	return l;
   239  }
   240  
   241  static Node*
   242  newlabel(void)
   243  {
   244  	static int label;
   245  
   246  	label++;
   247  	snprint(namebuf, sizeof(namebuf), "%.6d", label);
   248  	return newname(lookup(namebuf));
   249  }
   250  
   251  /*
   252   * build separate list of statements and cases
   253   * make labels between cases and statements
   254   * deal with fallthrough, break, unreachable statements
   255   */
   256  static void
   257  casebody(Node *sw, Node *typeswvar)
   258  {
   259  	Node *n, *c, *last;
   260  	Node *def;
   261  	NodeList *cas, *stat, *l, *lc;
   262  	Node *go, *br;
   263  	int32 lno, needvar;
   264  
   265  	if(sw->list == nil)
   266  		return;
   267  
   268  	lno = setlineno(sw);
   269  
   270  	cas = nil;	// cases
   271  	stat = nil;	// statements
   272  	def = N;	// defaults
   273  	br = nod(OBREAK, N, N);
   274  
   275  	for(l=sw->list; l; l=l->next) {
   276  		n = l->n;
   277  		setlineno(n);
   278  		if(n->op != OXCASE)
   279  			fatal("casebody %O", n->op);
   280  		n->op = OCASE;
   281  		needvar = count(n->list) != 1 || n->list->n->op == OLITERAL;
   282  
   283  		go = nod(OGOTO, newlabel(), N);
   284  		if(n->list == nil) {
   285  			if(def != N)
   286  				yyerror("more than one default case");
   287  			// reuse original default case
   288  			n->right = go;
   289  			def = n;
   290  		}
   291  
   292  		if(n->list != nil && n->list->next == nil) {
   293  			// one case - reuse OCASE node.
   294  			c = n->list->n;
   295  			n->left = c;
   296  			n->right = go;
   297  			n->list = nil;
   298  			cas = list(cas, n);
   299  		} else {
   300  			// expand multi-valued cases
   301  			for(lc=n->list; lc; lc=lc->next) {
   302  				c = lc->n;
   303  				cas = list(cas, nod(OCASE, c, go));
   304  			}
   305  		}
   306  
   307  		stat = list(stat, nod(OLABEL, go->left, N));
   308  		if(typeswvar && needvar && n->nname != N) {
   309  			NodeList *l;
   310  
   311  			l = list1(nod(ODCL, n->nname, N));
   312  			l = list(l, nod(OAS, n->nname, typeswvar));
   313  			typechecklist(l, Etop);
   314  			stat = concat(stat, l);
   315  		}
   316  		stat = concat(stat, n->nbody);
   317  
   318  		// botch - shouldn't fall thru declaration
   319  		last = stat->end->n;
   320  		if(last->xoffset == n->xoffset && last->op == OXFALL) {
   321  			if(typeswvar) {
   322  				setlineno(last);
   323  				yyerror("cannot fallthrough in type switch");
   324  			}
   325  			if(l->next == nil) {
   326  				setlineno(last);
   327  				yyerror("cannot fallthrough final case in switch");
   328  			}
   329  			last->op = OFALL;
   330  		} else
   331  			stat = list(stat, br);
   332  	}
   333  
   334  	stat = list(stat, br);
   335  	if(def)
   336  		cas = list(cas, def);
   337  
   338  	sw->list = cas;
   339  	sw->nbody = stat;
   340  	lineno = lno;
   341  }
   342  
   343  static Case*
   344  mkcaselist(Node *sw, int arg)
   345  {
   346  	Node *n;
   347  	Case *c, *c1, *c2;
   348  	NodeList *l;
   349  	int ord;
   350  
   351  	c = C;
   352  	ord = 0;
   353  
   354  	for(l=sw->list; l; l=l->next) {
   355  		n = l->n;
   356  		c1 = mal(sizeof(*c1));
   357  		c1->link = c;
   358  		c = c1;
   359  
   360  		ord++;
   361  		if((uint16)ord != ord)
   362  			fatal("too many cases in switch");
   363  		c->ordinal = ord;
   364  		c->node = n;
   365  
   366  		if(n->left == N) {
   367  			c->type = Tdefault;
   368  			continue;
   369  		}
   370  
   371  		switch(arg) {
   372  		case Stype:
   373  			c->hash = 0;
   374  			if(n->left->op == OLITERAL) {
   375  				c->type = Ttypenil;
   376  				continue;
   377  			}
   378  			if(istype(n->left->type, TINTER)) {
   379  				c->type = Ttypevar;
   380  				continue;
   381  			}
   382  
   383  			c->hash = typehash(n->left->type);
   384  			c->type = Ttypeconst;
   385  			continue;
   386  
   387  		case Snorm:
   388  		case Strue:
   389  		case Sfalse:
   390  			c->type = Texprvar;
   391  			c->hash = typehash(n->left->type);
   392  			switch(consttype(n->left)) {
   393  			case CTFLT:
   394  			case CTINT:
   395  			case CTRUNE:
   396  			case CTSTR:
   397  				c->type = Texprconst;
   398  			}
   399  			continue;
   400  		}
   401  	}
   402  
   403  	if(c == C)
   404  		return C;
   405  
   406  	// sort by value and diagnose duplicate cases
   407  	switch(arg) {
   408  	case Stype:
   409  		c = csort(c, typecmp);
   410  		for(c1=c; c1!=C; c1=c1->link) {
   411  			for(c2=c1->link; c2!=C && c2->hash==c1->hash; c2=c2->link) {
   412  				if(c1->type == Ttypenil || c1->type == Tdefault)
   413  					break;
   414  				if(c2->type == Ttypenil || c2->type == Tdefault)
   415  					break;
   416  				if(!eqtype(c1->node->left->type, c2->node->left->type))
   417  					continue;
   418  				yyerrorl(c2->node->lineno, "duplicate case %T in type switch\n\tprevious case at %L", c2->node->left->type, c1->node->lineno);
   419  			}
   420  		}
   421  		break;
   422  	case Snorm:
   423  	case Strue:
   424  	case Sfalse:
   425  		c = csort(c, exprcmp);
   426  		for(c1=c; c1->link!=C; c1=c1->link) {
   427  			if(exprcmp(c1, c1->link) != 0)
   428  				continue;
   429  			setlineno(c1->link->node);
   430  			yyerror("duplicate case %N in switch\n\tprevious case at %L", c1->node->left, c1->node->lineno);
   431  		}
   432  		break;
   433  	}
   434  
   435  	// put list back in processing order
   436  	c = csort(c, ordlcmp);
   437  	return c;
   438  }
   439  
   440  static	Node*	exprname;
   441  
   442  static Node*
   443  exprbsw(Case *c0, int ncase, int arg)
   444  {
   445  	NodeList *cas;
   446  	Node *a, *n;
   447  	Case *c;
   448  	int i, half, lno;
   449  
   450  	cas = nil;
   451  	if(ncase < Ncase) {
   452  		for(i=0; i<ncase; i++) {
   453  			n = c0->node;
   454  			lno = setlineno(n);
   455  
   456  			if(assignop(n->left->type, exprname->type, nil) == OCONVIFACE ||
   457  			   assignop(exprname->type, n->left->type, nil) == OCONVIFACE)
   458  				goto snorm;
   459  
   460  			switch(arg) {
   461  			case Strue:
   462  				a = nod(OIF, N, N);
   463  				a->ntest = n->left;			// if val
   464  				a->nbody = list1(n->right);			// then goto l
   465  				break;
   466  
   467  			case Sfalse:
   468  				a = nod(OIF, N, N);
   469  				a->ntest = nod(ONOT, n->left, N);	// if !val
   470  				typecheck(&a->ntest, Erv);
   471  				a->nbody = list1(n->right);			// then goto l
   472  				break;
   473  
   474  			default:
   475  			snorm:
   476  				a = nod(OIF, N, N);
   477  				a->ntest = nod(OEQ, exprname, n->left);	// if name == val
   478  				typecheck(&a->ntest, Erv);
   479  				a->nbody = list1(n->right);			// then goto l
   480  				break;
   481  			}
   482  
   483  			cas = list(cas, a);
   484  			c0 = c0->link;
   485  			lineno = lno;
   486  		}
   487  		return liststmt(cas);
   488  	}
   489  
   490  	// find the middle and recur
   491  	c = c0;
   492  	half = ncase>>1;
   493  	for(i=1; i<half; i++)
   494  		c = c->link;
   495  	a = nod(OIF, N, N);
   496  	a->ntest = nod(OLE, exprname, c->node->left);
   497  	typecheck(&a->ntest, Erv);
   498  	a->nbody = list1(exprbsw(c0, half, arg));
   499  	a->nelse = list1(exprbsw(c->link, ncase-half, arg));
   500  	return a;
   501  }
   502  
   503  /*
   504   * normal (expression) switch.
   505   * rebulid case statements into if .. goto
   506   */
   507  static void
   508  exprswitch(Node *sw)
   509  {
   510  	Node *def;
   511  	NodeList *cas;
   512  	Node *a;
   513  	Case *c0, *c, *c1;
   514  	Type *t;
   515  	int arg, ncase;
   516  
   517  	casebody(sw, N);
   518  
   519  	arg = Snorm;
   520  	if(isconst(sw->ntest, CTBOOL)) {
   521  		arg = Strue;
   522  		if(sw->ntest->val.u.bval == 0)
   523  			arg = Sfalse;
   524  	}
   525  	walkexpr(&sw->ntest, &sw->ninit);
   526  	t = sw->type;
   527  	if(t == T)
   528  		return;
   529  
   530  	/*
   531  	 * convert the switch into OIF statements
   532  	 */
   533  	exprname = N;
   534  	cas = nil;
   535  	if(arg != Strue && arg != Sfalse) {
   536  		exprname = temp(sw->ntest->type);
   537  		cas = list1(nod(OAS, exprname, sw->ntest));
   538  		typechecklist(cas, Etop);
   539  	} else {
   540  		exprname = nodbool(arg == Strue);
   541  	}
   542  
   543  	c0 = mkcaselist(sw, arg);
   544  	if(c0 != C && c0->type == Tdefault) {
   545  		def = c0->node->right;
   546  		c0 = c0->link;
   547  	} else {
   548  		def = nod(OBREAK, N, N);
   549  	}
   550  
   551  loop:
   552  	if(c0 == C) {
   553  		cas = list(cas, def);
   554  		sw->nbody = concat(cas, sw->nbody);
   555  		sw->list = nil;
   556  		walkstmtlist(sw->nbody);
   557  		return;
   558  	}
   559  
   560  	// deal with the variables one-at-a-time
   561  	if(!okforcmp[t->etype] || c0->type != Texprconst) {
   562  		a = exprbsw(c0, 1, arg);
   563  		cas = list(cas, a);
   564  		c0 = c0->link;
   565  		goto loop;
   566  	}
   567  
   568  	// do binary search on run of constants
   569  	ncase = 1;
   570  	for(c=c0; c->link!=C; c=c->link) {
   571  		if(c->link->type != Texprconst)
   572  			break;
   573  		ncase++;
   574  	}
   575  
   576  	// break the chain at the count
   577  	c1 = c->link;
   578  	c->link = C;
   579  
   580  	// sort and compile constants
   581  	c0 = csort(c0, exprcmp);
   582  	a = exprbsw(c0, ncase, arg);
   583  	cas = list(cas, a);
   584  
   585  	c0 = c1;
   586  	goto loop;
   587  
   588  }
   589  
   590  static	Node*	hashname;
   591  static	Node*	facename;
   592  static	Node*	boolname;
   593  
   594  static Node*
   595  typeone(Node *t)
   596  {
   597  	NodeList *init;
   598  	Node *a, *b, *var;
   599  
   600  	var = t->nname;
   601  	init = nil;
   602  	if(var == N) {
   603  		typecheck(&nblank, Erv | Easgn);
   604  		var = nblank;
   605  	} else
   606  		init = list1(nod(ODCL, var, N));
   607  
   608  	a = nod(OAS2, N, N);
   609  	a->list = list(list1(var), boolname);	// var,bool =
   610  	b = nod(ODOTTYPE, facename, N);
   611  	b->type = t->left->type;		// interface.(type)
   612  	a->rlist = list1(b);
   613  	typecheck(&a, Etop);
   614  	init = list(init, a);
   615  
   616  	b = nod(OIF, N, N);
   617  	b->ntest = boolname;
   618  	b->nbody = list1(t->right);		// if bool { goto l }
   619  	a = liststmt(list(init, b));
   620  	return a;
   621  }
   622  
   623  static Node*
   624  typebsw(Case *c0, int ncase)
   625  {
   626  	NodeList *cas;
   627  	Node *a, *n;
   628  	Case *c;
   629  	int i, half;
   630  
   631  	cas = nil;
   632  
   633  	if(ncase < Ncase) {
   634  		for(i=0; i<ncase; i++) {
   635  			n = c0->node;
   636  			if(c0->type != Ttypeconst)
   637  				fatal("typebsw");
   638  			a = nod(OIF, N, N);
   639  			a->ntest = nod(OEQ, hashname, nodintconst(c0->hash));
   640  			typecheck(&a->ntest, Erv);
   641  			a->nbody = list1(n->right);
   642  			cas = list(cas, a);
   643  			c0 = c0->link;
   644  		}
   645  		return liststmt(cas);
   646  	}
   647  
   648  	// find the middle and recur
   649  	c = c0;
   650  	half = ncase>>1;
   651  	for(i=1; i<half; i++)
   652  		c = c->link;
   653  	a = nod(OIF, N, N);
   654  	a->ntest = nod(OLE, hashname, nodintconst(c->hash));
   655  	typecheck(&a->ntest, Erv);
   656  	a->nbody = list1(typebsw(c0, half));
   657  	a->nelse = list1(typebsw(c->link, ncase-half));
   658  	return a;
   659  }
   660  
   661  /*
   662   * convert switch of the form
   663   *	switch v := i.(type) { case t1: ..; case t2: ..; }
   664   * into if statements
   665   */
   666  static void
   667  typeswitch(Node *sw)
   668  {
   669  	Node *def;
   670  	NodeList *cas, *hash;
   671  	Node *a, *n;
   672  	Case *c, *c0, *c1;
   673  	int ncase;
   674  	Type *t;
   675  	Val v;
   676  
   677  	if(sw->ntest == nil)
   678  		return;
   679  	if(sw->ntest->right == nil) {
   680  		setlineno(sw);
   681  		yyerror("type switch must have an assignment");
   682  		return;
   683  	}
   684  	walkexpr(&sw->ntest->right, &sw->ninit);
   685  	if(!istype(sw->ntest->right->type, TINTER)) {
   686  		yyerror("type switch must be on an interface");
   687  		return;
   688  	}
   689  	cas = nil;
   690  
   691  	/*
   692  	 * predeclare temporary variables
   693  	 * and the boolean var
   694  	 */
   695  	facename = temp(sw->ntest->right->type);
   696  	a = nod(OAS, facename, sw->ntest->right);
   697  	typecheck(&a, Etop);
   698  	cas = list(cas, a);
   699  
   700  	casebody(sw, facename);
   701  
   702  	boolname = temp(types[TBOOL]);
   703  	typecheck(&boolname, Erv);
   704  
   705  	hashname = temp(types[TUINT32]);
   706  	typecheck(&hashname, Erv);
   707  
   708  	t = sw->ntest->right->type;
   709  	if(isnilinter(t))
   710  		a = syslook("efacethash", 1);
   711  	else
   712  		a = syslook("ifacethash", 1);
   713  	argtype(a, t);
   714  	a = nod(OCALL, a, N);
   715  	a->list = list1(facename);
   716  	a = nod(OAS, hashname, a);
   717  	typecheck(&a, Etop);
   718  	cas = list(cas, a);
   719  
   720  	c0 = mkcaselist(sw, Stype);
   721  	if(c0 != C && c0->type == Tdefault) {
   722  		def = c0->node->right;
   723  		c0 = c0->link;
   724  	} else {
   725  		def = nod(OBREAK, N, N);
   726  	}
   727  	
   728  	/*
   729  	 * insert if statement into each case block
   730  	 */
   731  	for(c=c0; c!=C; c=c->link) {
   732  		n = c->node;
   733  		switch(c->type) {
   734  
   735  		case Ttypenil:
   736  			v.ctype = CTNIL;
   737  			a = nod(OIF, N, N);
   738  			a->ntest = nod(OEQ, facename, nodlit(v));
   739  			typecheck(&a->ntest, Erv);
   740  			a->nbody = list1(n->right);		// if i==nil { goto l }
   741  			n->right = a;
   742  			break;
   743  		
   744  		case Ttypevar:
   745  		case Ttypeconst:
   746  			n->right = typeone(n);
   747  			break;
   748  		}
   749  	}
   750  
   751  	/*
   752  	 * generate list of if statements, binary search for constant sequences
   753  	 */
   754  	while(c0 != C) {
   755  		if(c0->type != Ttypeconst) {
   756  			n = c0->node;
   757  			cas = list(cas, n->right);
   758  			c0=c0->link;
   759  			continue;
   760  		}
   761  		
   762  		// identify run of constants
   763  		c1 = c = c0;
   764  		while(c->link!=C && c->link->type==Ttypeconst)
   765  			c = c->link;
   766  		c0 = c->link;
   767  		c->link = nil;
   768  
   769  		// sort by hash
   770  		c1 = csort(c1, typecmp);
   771  		
   772  		// for debugging: linear search
   773  		if(0) {
   774  			for(c=c1; c!=C; c=c->link) {
   775  				n = c->node;
   776  				cas = list(cas, n->right);
   777  			}
   778  			continue;
   779  		}
   780  
   781  		// combine adjacent cases with the same hash
   782  		ncase = 0;
   783  		for(c=c1; c!=C; c=c->link) {
   784  			ncase++;
   785  			hash = list1(c->node->right);
   786  			while(c->link != C && c->link->hash == c->hash) {
   787  				hash = list(hash, c->link->node->right);
   788  				c->link = c->link->link;
   789  			}
   790  			c->node->right = liststmt(hash);
   791  		}
   792  		
   793  		// binary search among cases to narrow by hash
   794  		cas = list(cas, typebsw(c1, ncase));
   795  	}
   796  	if(nerrors == 0) {
   797  		cas = list(cas, def);
   798  		sw->nbody = concat(cas, sw->nbody);
   799  		sw->list = nil;
   800  		walkstmtlist(sw->nbody);
   801  	}
   802  }
   803  
   804  void
   805  walkswitch(Node *sw)
   806  {
   807  	/*
   808  	 * reorder the body into (OLIST, cases, statements)
   809  	 * cases have OGOTO into statements.
   810  	 * both have inserted OBREAK statements
   811  	 */
   812  	if(sw->ntest == N) {
   813  		sw->ntest = nodbool(1);
   814  		typecheck(&sw->ntest, Erv);
   815  	}
   816  
   817  	if(sw->ntest->op == OTYPESW) {
   818  		typeswitch(sw);
   819  //dump("sw", sw);
   820  		return;
   821  	}
   822  	exprswitch(sw);
   823  	// Discard old AST elements after a walk. They can confuse racewealk.
   824  	sw->ntest = nil;
   825  	sw->list = nil;
   826  }
   827  
   828  /*
   829   * type check switch statement
   830   */
   831  void
   832  typecheckswitch(Node *n)
   833  {
   834  	int top, lno, ptr;
   835  	char *nilonly;
   836  	Type *t, *badtype, *missing, *have;
   837  	NodeList *l, *ll;
   838  	Node *ncase, *nvar;
   839  	Node *def;
   840  
   841  	lno = lineno;
   842  	typechecklist(n->ninit, Etop);
   843  	nilonly = nil;
   844  
   845  	if(n->ntest != N && n->ntest->op == OTYPESW) {
   846  		// type switch
   847  		top = Etype;
   848  		typecheck(&n->ntest->right, Erv);
   849  		t = n->ntest->right->type;
   850  		if(t != T && t->etype != TINTER)
   851  			yyerror("cannot type switch on non-interface value %lN", n->ntest->right);
   852  	} else {
   853  		// value switch
   854  		top = Erv;
   855  		if(n->ntest) {
   856  			typecheck(&n->ntest, Erv);
   857  			defaultlit(&n->ntest, T);
   858  			t = n->ntest->type;
   859  		} else
   860  			t = types[TBOOL];
   861  		if(t) {
   862  			if(!okforeq[t->etype])
   863  				yyerror("cannot switch on %lN", n->ntest);
   864  			else if(t->etype == TARRAY && !isfixedarray(t))
   865  				nilonly = "slice";
   866  			else if(t->etype == TARRAY && isfixedarray(t) && algtype1(t, nil) == ANOEQ)
   867  				yyerror("cannot switch on %lN", n->ntest);
   868  			else if(t->etype == TSTRUCT && algtype1(t, &badtype) == ANOEQ)
   869  				yyerror("cannot switch on %lN (struct containing %T cannot be compared)", n->ntest, badtype);
   870  			else if(t->etype == TFUNC)
   871  				nilonly = "func";
   872  			else if(t->etype == TMAP)
   873  				nilonly = "map";
   874  		}
   875  	}
   876  	n->type = t;
   877  
   878  	def = N;
   879  	for(l=n->list; l; l=l->next) {
   880  		ncase = l->n;
   881  		setlineno(n);
   882  		if(ncase->list == nil) {
   883  			// default
   884  			if(def != N)
   885  				yyerror("multiple defaults in switch (first at %L)", def->lineno);
   886  			else
   887  				def = ncase;
   888  		} else {
   889  			for(ll=ncase->list; ll; ll=ll->next) {
   890  				setlineno(ll->n);
   891  				typecheck(&ll->n, Erv | Etype);
   892  				if(ll->n->type == T || t == T)
   893  					continue;
   894  				setlineno(ncase);
   895  				switch(top) {
   896  				case Erv:	// expression switch
   897  					defaultlit(&ll->n, t);
   898  					if(ll->n->op == OTYPE)
   899  						yyerror("type %T is not an expression", ll->n->type);
   900  					else if(ll->n->type != T && !assignop(ll->n->type, t, nil) && !assignop(t, ll->n->type, nil)) {
   901  						if(n->ntest)
   902  							yyerror("invalid case %N in switch on %N (mismatched types %T and %T)", ll->n, n->ntest, ll->n->type, t);
   903  						else
   904  							yyerror("invalid case %N in switch (mismatched types %T and bool)", ll->n, ll->n->type);
   905  					} else if(nilonly && !isconst(ll->n, CTNIL)) {
   906  						yyerror("invalid case %N in switch (can only compare %s %N to nil)", ll->n, nilonly, n->ntest);
   907  					}
   908  					break;
   909  				case Etype:	// type switch
   910  					if(ll->n->op == OLITERAL && istype(ll->n->type, TNIL)) {
   911  						;
   912  					} else if(ll->n->op != OTYPE && ll->n->type != T) {  // should this be ||?
   913  						yyerror("%lN is not a type", ll->n);
   914  						// reset to original type
   915  						ll->n = n->ntest->right;
   916  					} else if(ll->n->type->etype != TINTER && t->etype == TINTER && !implements(ll->n->type, t, &missing, &have, &ptr)) {
   917  						if(have && !missing->broke && !have->broke)
   918  							yyerror("impossible type switch case: %lN cannot have dynamic type %T"
   919  								" (wrong type for %S method)\n\thave %S%hT\n\twant %S%hT",
   920  								n->ntest->right, ll->n->type, missing->sym, have->sym, have->type,
   921  								missing->sym, missing->type);
   922  						else if(!missing->broke)
   923  							yyerror("impossible type switch case: %lN cannot have dynamic type %T"
   924  								" (missing %S method)", n->ntest->right, ll->n->type, missing->sym);
   925  					}
   926  					break;
   927  				}
   928  			}
   929  		}
   930  		if(top == Etype && n->type != T) {
   931  			ll = ncase->list;
   932  			nvar = ncase->nname;
   933  			if(nvar != N) {
   934  				if(ll && ll->next == nil && ll->n->type != T && !istype(ll->n->type, TNIL)) {
   935  					// single entry type switch
   936  					nvar->ntype = typenod(ll->n->type);
   937  				} else {
   938  					// multiple entry type switch or default
   939  					nvar->ntype = typenod(n->type);
   940  				}
   941  			}
   942  		}
   943  		typechecklist(ncase->nbody, Etop);
   944  	}
   945  
   946  	lineno = lno;
   947  }