new switch implementation
in preparation of type switch.
no functional change (yet).

R=r
OCL=25784
CL=25788
diff --git a/src/cmd/6g/gen.c b/src/cmd/6g/gen.c
index d14ad30..9bc6126 100644
--- a/src/cmd/6g/gen.c
+++ b/src/cmd/6g/gen.c
@@ -260,8 +260,8 @@
 		break;
 
 	case OFOR:
-		p1 = gbranch(AJMP, T);			// 		goto test
 		sbreak = breakpc;
+		p1 = gbranch(AJMP, T);			// 		goto test
 		breakpc = gbranch(AJMP, T);		// break:	goto done
 		scontin = continpc;
 		continpc = pc;
@@ -299,15 +299,15 @@
 		break;
 
 	case OSWITCH:
-		p1 = gbranch(AJMP, T);			// 		goto test
 		sbreak = breakpc;
+		p1 = gbranch(AJMP, T);			// 		goto test
 		breakpc = gbranch(AJMP, T);		// break:	goto done
 		patch(p1, pc);				// test:
 		if(labloop != L) {
 			labloop->op = OFOR;
 			labloop->breakpc = breakpc;
 		}
-		swgen(n);				//		switch(test) body
+		gen(n->nbody, L);			//		switch(test) body
 		patch(breakpc, pc);			// done:
 		breakpc = sbreak;
 		break;
@@ -367,279 +367,6 @@
 	lineno = lno;
 }
 
-Case*
-csort(Case *l, int(*f)(Case*, Case*))
-{
-	Case *l1, *l2, *le;
-
-	if(l == 0 || l->slink == 0)
-		return l;
-
-	l1 = l;
-	l2 = l;
-	for(;;) {
-		l2 = l2->slink;
-		if(l2 == 0)
-			break;
-		l2 = l2->slink;
-		if(l2 == 0)
-			break;
-		l1 = l1->slink;
-	}
-
-	l2 = l1->slink;
-	l1->slink = 0;
-	l1 = csort(l, f);
-	l2 = csort(l2, f);
-
-	/* set up lead element */
-	if((*f)(l1, l2) < 0) {
-		l = l1;
-		l1 = l1->slink;
-	} else {
-		l = l2;
-		l2 = l2->slink;
-	}
-	le = l;
-
-	for(;;) {
-		if(l1 == 0) {
-			while(l2) {
-				le->slink = l2;
-				le = l2;
-				l2 = l2->slink;
-			}
-			le->slink = 0;
-			break;
-		}
-		if(l2 == 0) {
-			while(l1) {
-				le->slink = l1;
-				le = l1;
-				l1 = l1->slink;
-			}
-			break;
-		}
-		if((*f)(l1, l2) < 0) {
-			le->slink = l1;
-			le = l1;
-			l1 = l1->slink;
-		} else {
-			le->slink = l2;
-			le = l2;
-			l2 = l2->slink;
-		}
-	}
-	le->slink = 0;
-	return l;
-}
-
-int
-casecmp(Case *c1, Case *c2)
-{
-	int w;
-
-	w = whatis(c1->scase);
-	if(w != whatis(c2->scase))
-		fatal("casecmp1");
-
-	switch(w) {
-	case Wlitfloat:
-		return mpcmpfltflt(c1->scase->val.u.fval, c2->scase->val.u.fval);
-	case Wlitint:
-		return mpcmpfixfix(c1->scase->val.u.xval, c2->scase->val.u.xval);
-	case Wlitstr:
-		return cmpslit(c1->scase, c2->scase);
-//	case Wlitbool:
-//	case Wlitnil:
-	}
-
-	fatal("casecmp2");
-	return 0;
-}
-
-void
-swconst(Case *sa, int nc, Node *n1, Node *tmp)
-{
-	Case *s, *sb;
-	Prog *p1, *p2, *p3;
-	int n;
-
-	// small number of cases --
-	// test them sequentially
-	if(nc < 4) {
-		for(s=sa; s!=C; s=s->slink) {
-			setlineno(s->scase);
-			memset(n1, 0, sizeof(*n1));
-			n1->op = OEQ;
-			n1->left = tmp;
-			n1->right = s->scase;
-			walktype(n1, Erv);
-			bgen(n1, 1, s->sprog);
-		}
-		return;
-	}
-
-	// large number of cases --
-	// find the middle and recur on each half
-
-	n = nc/2;
-	for(s=sa; s!=C; s=s->slink) {
-		n--;
-		if(n == 0)
-			break;
-	}
-	n = nc/2;
-	sb = s->slink;
-	s->slink = C;
-
-	p1 = gbranch(AJMP, T);			// goto midcmp
-	p2 = pc;				// low half of switch
-	swconst(sa, n, n1, tmp);
-
-	p3 = gbranch(AJMP, T);			// goto end
-	patch(p1, pc);
-
-	setlineno(s->scase);
-	memset(n1, 0, sizeof(*n1));
-	n1->op = OLE;
-	n1->left = tmp;
-	n1->right = s->scase;
-	walktype(n1, Erv);
-	bgen(n1, 1, p2);
-
-	swconst(sb, nc-n, n1, tmp);		// high half of switch
-	patch(p3, pc);
-}
-
-void
-swgen(Node *n)
-{
-	Node *c1, *c2;
-	Node n1, tmp;
-	Case *s0, *se, *s, *sa;
-	Prog *p1, *dflt;
-	int32 lno;
-	int any, nc;
-	Iter save1, save2;
-
-// botch - put most of this code in
-// walk. gen binary search for
-// sequence of constant cases
-
-	lno = setlineno(n);
-
-	p1 = gbranch(AJMP, T);
-	s0 = C;
-	se = C;
-
-	// walk thru the body placing breaks
-	// and labels into the case statements
-
-	any = 0;
-	dflt = P;
-	c1 = listfirst(&save1, &n->nbody);
-	while(c1 != N) {
-		setlineno(c1);
-		if(c1->op == OEMPTY)
-			break;
-		if(c1->op != OCASE) {
-			if(s0 == C && dflt == P)
-				yyerror("unreachable statements in a switch");
-			gen(c1, L);
-
-			any = 1;
-			if(c1->op == OFALL)
-				any = 0;
-			c1 = listnext(&save1);
-			continue;
-		}
-
-		// put in the break between cases
-		if(any)
-			patch(gbranch(AJMP, T), breakpc);
-		any = 1;
-
-		// loop over case expressions
-		c2 = listfirst(&save2, &c1->left);
-		if(c2 == N)
-			dflt = pc;
-
-		while(c2 != N) {
-			s = mal(sizeof(*s));
-			if(s0 == C)
-				s0 = s;
-			else
-				se->slink = s;
-			se = s;
-
-			s->scase = c2;		// case expression
-			s->sprog = pc;		// where to go
-
-			c2 = listnext(&save2);
-		}
-
-		c1 = listnext(&save1);
-	}
-
-	lineno = lno;
-
-	if(any)
-		patch(gbranch(AJMP, T), breakpc);
-
-	patch(p1, pc);
-
-	if(n->ntest != N)
-		if(n->ntest->ninit != N)
-			gen(n->ntest->ninit, L);
-	tempname(&tmp, n->ntest->type);
-	cgen(n->ntest, &tmp);
-
-	sa = C;		// base of constant cases
-	nc = 0;
-	for(s=s0; s!=C; s=s->slink) {
-		switch(whatis(s->scase)) {
-		case Wlitfloat:
-		case Wlitint:
-		case Wlitstr:
-//		case Wlitbool:
-//		case Wlitnil:
-			nc++;
-			if(sa == C)
-				sa = s;
-			se = s;
-			continue;
-		}
-		if(sa != C) {
-			se->slink = C;
-			sa = csort(sa, casecmp);
-			swconst(sa, nc, &n1, &tmp);
-			nc = 0;
-			sa = C;
-		}
-		setlineno(s->scase);
-		memset(&n1, 0, sizeof(n1));
-		n1.op = OEQ;
-		n1.left = &tmp;
-		n1.right = s->scase;
-		walktype(&n1, Erv);
-		bgen(&n1, 1, s->sprog);
-	}
-	if(sa != C) {
-		se->slink = C;
-		sa = csort(sa, casecmp);
-		swconst(sa, nc, &n1, &tmp);
-	}
-	if(dflt != P) {
-		patch(gbranch(AJMP, T), dflt);
-		goto ret;
-	}
-	patch(gbranch(AJMP, T), breakpc);
-
-ret:
-	lineno = lno;
-}
-
 void
 inarggen(void)
 {
diff --git a/src/cmd/6g/gg.h b/src/cmd/6g/gg.h
index a44f104..741527c 100644
--- a/src/cmd/6g/gg.h
+++ b/src/cmd/6g/gg.h
@@ -64,15 +64,6 @@
 	Sig*	link;
 };
 
-typedef	struct	Case Case;
-struct	Case
-{
-	Prog*	sprog;
-	Node*	scase;
-	Case*	slink;
-};
-#define	C	((Case*)0)
-
 typedef	struct	Pool Pool;
 struct	Pool
 {
@@ -143,8 +134,6 @@
 void	compile(Node*);
 void	proglist(void);
 void	gen(Node*, Label*);
-void	swgen(Node*);
-void	selgen(Node*);
 Node*	lookdot(Node*, Node*, int);
 void	inarggen(void);
 void	cgen_as(Node*, Node*);
diff --git a/src/cmd/gc/Makefile b/src/cmd/gc/Makefile
index 1ab4497..4237e97 100644
--- a/src/cmd/gc/Makefile
+++ b/src/cmd/gc/Makefile
@@ -21,6 +21,7 @@
 	dcl.$O\
 	export.$O\
 	walk.$O\
+	swt.$O\
 	const.$O\
 	mparith1.$O\
 	mparith2.$O\
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index 76e440d..dfd975f 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -812,8 +812,7 @@
 void	walkconv(Node*);
 void	walkas(Node*);
 void	walkbool(Node*);
-Type*	walkswitch(Node*, Type*(*)(Node*, Type*));
-int	casebody(Node*);
+void	walkswitch(Node*);
 void	walkselect(Node*);
 int	whatis(Node*);
 void	walkdot(Node*);
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index bb2c31e..aa8b01a 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -547,8 +547,11 @@
 		return;
 
 	case OCASE:
-		// the right side points to the next case
-		print("%O%J\n", n->op, n);
+		// the right side points to label of the body
+		if(n->right != N && n->right->op == OGOTO && n->right->left->op == ONAME)
+			print("%O%J GOTO %N\n", n->op, n, n->right->left);
+		else
+			print("%O%J\n", n->op, n);
 		dodump(n->left, dep+1);
 		return;
 	}
@@ -654,8 +657,8 @@
 	[OCMP]		= "CMP",
 	[OFALL]		= "FALL",
 	[OCOMPOS]	= "COMPOS",
-	[ODOTTYPE]		= "DOTTYPE",
-	[OCONV]	= "CONV",
+	[ODOTTYPE]	= "DOTTYPE",
+	[OCONV]		= "CONV",
 	[OCOM]		= "COM",
 	[OCONST]	= "CONST",
 	[OCONTINUE]	= "CONTINUE",
@@ -724,7 +727,7 @@
 	[OPRINT]	= "PRINT",
 	[OPRINTN]	= "PRINTN",
 	[OPARAM]	= "PARAM",
-	[ODCL]	= "DCL",
+	[ODCL]		= "DCL",
 	[OXXX]		= "XXX",
 };
 
diff --git a/src/cmd/gc/swt.c b/src/cmd/gc/swt.c
new file mode 100644
index 0000000..dc32665
--- /dev/null
+++ b/src/cmd/gc/swt.c
@@ -0,0 +1,333 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include	"go.h"
+
+/*
+ * walktype
+ */
+Type*
+sw0(Node *c, Type *place)
+{
+	Node *r;
+
+	if(c == N)
+		return T;
+	if(c->op != OAS) {
+		walktype(c, Erv);
+		return T;
+	}
+	walktype(c->left, Elv);
+
+	r = c->right;
+	if(c == N)
+		return T;
+
+	switch(r->op) {
+	default:
+		goto bad;
+	case ORECV:
+		// <-chan
+		walktype(r->left, Erv);
+		if(!istype(r->left->type, TCHAN))
+			goto bad;
+		break;
+	case OINDEX:
+		// map[e]
+		walktype(r->left, Erv);
+		if(!istype(r->left->type, TMAP))
+			goto bad;
+		break;
+	case ODOTTYPE:
+		// interface.(type)
+		walktype(r->left, Erv);
+		if(!istype(r->left->type, TINTER))
+			goto bad;
+		break;
+	}
+	c->type = types[TBOOL];
+	return T;
+
+bad:
+	yyerror("inappropriate assignment in a case statement");
+	return T;
+}
+
+/*
+ * return the first type
+ */
+Type*
+sw1(Node *c, Type *place)
+{
+	if(place == T)
+		return c->type;
+	return place;
+}
+
+/*
+ * return a suitable type
+ */
+Type*
+sw2(Node *c, Type *place)
+{
+	return types[TINT];	// botch
+}
+
+/*
+ * check that switch type
+ * is compat with all the cases
+ */
+Type*
+sw3(Node *c, Type *place)
+{
+	if(place == T)
+		return c->type;
+	if(c->type == T)
+		c->type = place;
+	convlit(c, place);
+	if(!ascompat(place, c->type))
+		badtype(OSWITCH, place, c->type);
+	return place;
+}
+
+/*
+ * over all cases, call paramenter function.
+ * four passes of these are used to allocate
+ * types to cases and switch
+ */
+Type*
+walkcases(Node *sw, Type*(*call)(Node*, Type*))
+{
+	Iter save;
+	Node *n;
+	Type *place;
+	int32 lno;
+
+	lno = setlineno(sw);
+	place = call(sw->ntest, T);
+
+	n = listfirst(&save, &sw->nbody->left);
+	if(n->op == OEMPTY)
+		return T;
+
+loop:
+	if(n == N) {
+		lineno = lno;
+		return place;
+	}
+
+	if(n->op != OCASE)
+		fatal("walkcases: not case %O\n", n->op);
+
+	if(n->left != N) {
+		setlineno(n->left);
+		place = call(n->left, place);
+	}
+	n = listnext(&save);
+	goto loop;
+}
+
+Node*
+newlabel()
+{
+	static int label;
+
+	label++;
+	snprint(namebuf, sizeof(namebuf), "%.6d", label);
+	return newname(lookup(namebuf));
+}
+
+/*
+ * build separate list of statements and cases
+ * make labels between cases and statements
+ * deal with fallthrough, break, unreachable statements
+ */
+void
+casebody(Node *sw)
+{
+	Iter save;
+	Node *os, *oc, *t, *c;
+	Node *cas, *stat, *def;
+	Node *go, *br;
+	int32 lno;
+
+	lno = setlineno(sw);
+	t = listfirst(&save, &sw->nbody);
+	if(t == N || t->op == OEMPTY) {
+		sw->nbody = nod(OLIST, N, N);
+		return;
+	}
+
+	cas = N;	// cases
+	stat = N;	// statements
+	def = N;	// defaults
+	os = N;		// last statement
+	oc = N;		// last case
+	br = nod(OBREAK, N, N);
+
+loop:
+
+	if(t == N) {
+		if(oc == N && os != N)
+			yyerror("first switch statement must be a case");
+
+		stat = list(stat, br);
+		cas = list(cas, def);
+
+		sw->nbody = nod(OLIST, rev(cas), rev(stat));
+//dump("case", sw->nbody->left);
+//dump("stat", sw->nbody->right);
+		lineno = lno;
+		return;
+	}
+
+	lno = setlineno(t);
+
+	switch(t->op) {
+	case OXCASE:
+		t->op = OCASE;
+		if(oc == N && os != N)
+			yyerror("first switch statement must be a case");
+
+		if(os != N && os->op == OXFALL)
+			os->op = OFALL;
+		else
+			stat = list(stat, br);
+
+		go = nod(OGOTO, newlabel(), N);
+
+		c = t->left;
+		if(c == N) {
+			if(def != N)
+				yyerror("more than one default case");
+
+			// reuse original default case
+			t->right = go;
+			def = t;
+		}
+
+		// expand multi-valued cases
+		for(; c!=N; c=c->right) {
+			if(c->op != OLIST) {
+				// reuse original case
+				t->left = c;
+				t->right = go;
+				cas = list(cas, t);
+				break;
+			}
+			cas = list(cas, nod(OCASE, c->left, go));
+		}
+		stat = list(stat, nod(OLABEL, go->left, N));
+		oc = t;
+		os = N;
+		break;
+
+	default:
+		stat = list(stat, t);
+		os = t;
+		break;
+	}
+	t = listnext(&save);
+	goto loop;
+}
+
+/*
+ * rebulid case statements into if .. goto
+ */
+void
+prepsw(Node *sw)
+{
+	Iter save;
+	Node *name, *cas;
+	Node *t, *a;
+	int bool;
+
+	bool = 0;
+	if(whatis(sw->ntest) == Wlitbool) {
+		bool = 1;		// true
+		if(sw->ntest->val.u.xval == 0)
+			bool = 2;	// false
+	}
+
+	cas = N;
+	name = N;
+	if(bool == 0) {
+		name = nod(OXXX, N, N);
+		tempname(name, sw->ntest->type);
+		cas = nod(OAS, name, sw->ntest);
+	}
+
+	t = listfirst(&save, &sw->nbody->left);
+
+loop:
+	if(t == N) {
+		sw->nbody->left = rev(cas);
+		walkstate(sw->nbody->left);
+//dump("case", sw->nbody->left);
+		return;
+	}
+
+	if(t->left == N) {
+		cas = list(cas, t->right);		// goto default
+		t = listnext(&save);
+		goto loop;
+	}
+
+	a = nod(OIF, N, N);
+	a->nbody = t->right;				// then goto l
+
+	switch(bool) {
+	default:
+		// not bool const
+		a->ntest = nod(OEQ, name, t->left);	// if name == val
+		break;
+
+	case 1:
+		// bool true
+		a->ntest = t->left;			// if val
+		break;
+
+	case 2:
+		// bool false
+		a->ntest = nod(ONOT, t->left, N);	// if !val
+		break;
+	}
+	cas = list(cas, a);
+
+	t = listnext(&save);
+	goto loop;
+}
+
+void
+walkswitch(Node *n)
+{
+	Type *t;
+
+	casebody(n);
+	if(n->ntest == N)
+		n->ntest = booltrue;
+
+	walkstate(n->ninit);
+	walktype(n->ntest, Erv);
+	walkstate(n->nbody);
+
+	// walktype
+	walkcases(n, sw0);
+
+	// find common type
+	t = n->ntest->type;
+	if(t == T)
+		t = walkcases(n, sw1);
+
+	// if that fails pick a type
+	if(t == T)
+		t = walkcases(n, sw2);
+
+	// set the type on all literals
+	if(t != T) {
+		walkcases(n, sw3);
+		convlit(n->ntest, t);
+		prepsw(n);
+	}
+}
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index 3ae0f52..d82dfd4 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -4,9 +4,6 @@
 
 #include	"go.h"
 
-static	Type*	sw1(Node*, Type*);
-static	Type*	sw2(Node*, Type*);
-static	Type*	sw3(Node*, Type*);
 static	Node*	curfn;
 
 enum
@@ -318,26 +315,7 @@
 		if(top != Etop)
 			goto nottop;
 
-		casebody(n->nbody);
-		if(n->ntest == N)
-			n->ntest = booltrue;
-		walkstate(n->ninit);
-		walktype(n->ntest, Erv);
-		walkstate(n->nbody);
-
-		// find common type
-		if(n->ntest->type == T)
-			n->ntest->type = walkswitch(n, sw1);
-
-		// if that fails pick a type
-		if(n->ntest->type == T)
-			n->ntest->type = walkswitch(n, sw2);
-
-		// set the type on all literals
-		if(n->ntest->type != T)
-			walkswitch(n, sw3);
-		walktype(n->ntest, Erv);	// BOTCH is this right
-		walktype(n->nincr, Erv);
+		walkswitch(n);
 		goto ret;
 
 	case OSELECT:
@@ -577,7 +555,6 @@
 	case OCASE:
 		if(top != Etop)
 			goto nottop;
-		walktype(n->left, Erv);
 		walkstate(n->right);
 		goto ret;
 
@@ -1251,124 +1228,11 @@
 bad:
 	if(l->type != T)
 		yyerror("invalid conversion: %T to %T", l->type, t);
-	else if(n->left->op == OLIST)
+	else
+	if(n->left->op == OLIST)
 		yyerror("invalid type for composite literal: %T", t);
 }
 
-
-/*
- * return the first type
- */
-Type*
-sw1(Node *c, Type *place)
-{
-	if(place == T)
-		return c->type;
-	return place;
-}
-
-/*
- * return a suitable type
- */
-Type*
-sw2(Node *c, Type *place)
-{
-	return types[TINT];	// botch
-}
-
-/*
- * check that switch type
- * is compat with all the cases
- */
-Type*
-sw3(Node *c, Type *place)
-{
-	if(place == T)
-		return c->type;
-	if(c->type == T)
-		c->type = place;
-	convlit(c, place);
-	if(!ascompat(place, c->type))
-		badtype(OSWITCH, place, c->type);
-	return place;
-}
-
-Type*
-walkswitch(Node *sw, Type*(*call)(Node*, Type*))
-{
-	Node *n, *c;
-	Type *place;
-	place = call(sw->ntest, T);
-
-	setlineno(sw);
-
-	n = sw->nbody;
-	if(n->op == OLIST)
-		n = n->left;
-	if(n->op == OEMPTY)
-		return T;
-
-	for(; n!=N; n=n->right) {
-		if(n->op != OCASE)
-			fatal("walkswitch: not case %O\n", n->op);
-		for(c=n->left; c!=N; c=c->right) {
-			if(c->op != OLIST) {
-				setlineno(c);
-				place = call(c, place);
-				break;
-			}
-			setlineno(c);
-			place = call(c->left, place);
-		}
-	}
-	return place;
-}
-
-int
-casebody(Node *n)
-{
-	Node *oc, *ot, *t;
-	Iter save;
-
-	/*
-	 * look to see if statements at top level have
-	 * case labels attached to them. convert the illegal
-	 * ops XFALL and XCASE into legal ops FALL and CASE.
-	 * all unconverted ops will thus be caught as illegal
-	 */
-
-	oc = N;		// last case statement
-	ot = N;		// last statement (look for XFALL)
-	t = listfirst(&save, &n);
-
-loop:
-	if(t == N) {
-		/* empty switch */
-		if(oc == N)
-			return 0;
-		return 1;
-	}
-	if(t->op == OXCASE) {
-		/* rewrite and link top level cases */
-		t->op = OCASE;
-		if(oc != N)
-			oc->right = t;
-		oc = t;
-
-		/* rewrite top fall that preceed case */
-		if(ot != N && ot->op == OXFALL)
-			ot->op = OFALL;
-	}
-
-	/* if first statement is not case */
-	if(oc == N)
-		return 0;
-
-	ot = t;
-	t = listnext(&save);
-	goto loop;
-}
-
 Node*
 selcase(Node *n, Node *var)
 {
@@ -1477,21 +1341,58 @@
 	return r;
 }
 
+/*
+ * enumerate the special cases
+ * of the case statement:
+ *	case v := <-chan		// select and switch
+ *	case v := map[]			// switch
+ *	case v := interface.(TYPE)	// switch
+ */
 Node*
 selectas(Node *name, Node *expr)
 {
 	Node *a;
 	Type *t;
 
-	if(expr == N || expr->op != ORECV)
+	if(expr == N)
 		goto bad;
-	walktype(expr->left, Erv);
-	t = expr->left->type;
-	if(t == T)
+	switch(expr->op) {
+	default:
+//dump("case", expr);
 		goto bad;
-	if(t->etype != TCHAN)
-		goto bad;
-	a = old2new(name, t->type);
+
+	case ORECV:
+		walktype(expr->left, Erv);
+		t = expr->left->type;
+		if(t == T)
+			goto bad;
+		if(t->etype != TCHAN)
+			goto bad;
+		t = t->type;
+		break;
+
+	case OINDEX:
+		walktype(expr->left, Erv);
+		walktype(expr->right, Erv);
+		t = expr->left->type;
+		if(t == T)
+			goto bad;
+		if(t->etype != TMAP)
+			goto bad;
+		t = t->type;
+		break;
+
+	case ODOTTYPE:
+		walktype(expr->left, Erv);
+		t = expr->left->type;
+		if(t == T)
+			goto bad;
+		if(t->etype != TINTER)
+			goto bad;
+		t = expr->type;
+		break;
+	}
+	a = old2new(name, t);
 	return a;
 
 bad:
@@ -1523,7 +1424,7 @@
 	oc = N;		// last case
 	def = N;	// default case
 
-	for(count=0; n!=N; n=listnext(&iter)) {
+	for(; n!=N; n=listnext(&iter)) {
 		setlineno(n);
 
 		switch(n->op) {