added key:val extension to
structure and array literals

R=r
OCL=29190
CL=29190
diff --git a/src/cmd/6g/gen.c b/src/cmd/6g/gen.c
index 61d2518..1b7505e 100644
--- a/src/cmd/6g/gen.c
+++ b/src/cmd/6g/gen.c
@@ -786,6 +786,10 @@
 		goto yes;
 	}
 
+	if(nr->op == OCOMPMAP) {
+		goto yes;
+	}
+
 	if(nr->type == T ||
 	   !eqtype(nl->type, nr->type))
 		goto no;
diff --git a/src/cmd/gc/Makefile b/src/cmd/gc/Makefile
index 0fc15de..e5cabbb 100644
--- a/src/cmd/gc/Makefile
+++ b/src/cmd/gc/Makefile
@@ -19,6 +19,7 @@
 	lex.$O\
 	subr.$O\
 	dcl.$O\
+	sinit.$O\
 	export.$O\
 	walk.$O\
 	swt.$O\
diff --git a/src/cmd/gc/const.c b/src/cmd/gc/const.c
index 50b5823..5dbacec 100644
--- a/src/cmd/gc/const.c
+++ b/src/cmd/gc/const.c
@@ -773,3 +773,26 @@
 	}
 	return 0;
 }
+
+long
+nonnegconst(Node *n)
+{
+	if(n->op == OLITERAL)
+	switch(simtype[n->type->etype]) {
+	case TINT8:
+	case TUINT8:
+	case TINT16:
+	case TUINT16:
+	case TINT32:
+	case TUINT32:
+	case TINT64:
+	case TUINT64:
+	case TIDEAL:
+		// check negative and 2^31
+		if(mpcmpfixfix(n->val.u.xval, minintval[TUINT32]) < 0
+		|| mpcmpfixfix(n->val.u.xval, maxintval[TINT32]) > 0)
+			break;
+		return mpgetfix(n->val.u.xval);
+	}
+	return -1;
+}
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c
index 6025b42..67a53df 100644
--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -1322,238 +1322,6 @@
 	return 0;
 }
 
-/*
- * the init code (thru initfix) reformats the
- *	var = ...
- * statements, rewriting the automatic
- * variables with the static variables.
- * this allows the code generator to
- * generate DATA statements instead
- * of assignment statements.
- * it is quadradic, may need to change.
- * it is extremely fragile knowing exactly
- * how the code from (struct|array|map)lit
- * will look. ideally the lit routines could
- * write the code in this form, but ...
- */
-
-static	Node*	xxx;
-
-void
-initlin(Node* n)
-{
-	if(n == N)
-		return;
-	initlin(n->ninit);
-	switch(n->op) {
-	default:
-		print("o = %O\n", n->op);
-		n->ninit = N;
-		xxx = list(xxx, n);
-		break;
-
-	case OCALL:
-		// call to mapassign1
-		if(n->left->op != ONAME ||
-		   n->right->op != OLIST ||
-		   n->right->left->op != OAS ||
-		   n->right->right->op != OLIST ||
-		   n->right->right->left->op != OAS ||
-		   n->right->right->right->op != OAS ||
-		   strcmp(n->left->sym->name, "mapassign1") != 0)
-			dump("o=call", n);
-		n->ninit = N;
-		xxx = list(xxx, n);
-		break;
-
-	case OAS:
-		n->ninit = N;
-		xxx = list(xxx, n);
-		break;
-
-	case OLIST:
-		initlin(n->left);
-		initlin(n->right);
-		break;
-	}
-}
-
-int
-inittmp(Node *n)
-{
-	if(n != N)
-	if(n->op == ONAME)
-	if(n->sym != S)
-	if(n->class == PAUTO)
-	if(strcmp(n->sym->name, "!tmpname!") == 0)
-		return 1;
-	return 0;
-}
-
-int
-sametmp(Node *n1, Node *n2)
-{
-	if(inittmp(n1))
-	if(n1->xoffset == n2->xoffset)
-		return 1;
-	return 0;
-}
-
-int
-indsametmp(Node *n1, Node *n2)
-{
-	if(n1->op == OIND)
-	if(inittmp(n1->left))
-	if(n1->left->xoffset == n2->xoffset)
-		return 1;
-	return 0;
-}
-
-Node*
-slicerewrite(Node *n)
-{
-	Iter param;
-	Node *a, *wid, *nel;
-	Type *t;
-	int b;
-
-	if(n == N || n->op != OCALL || !isslice(n->type) ||
-	   n->left == N || n->left->sym == S ||
-	   strcmp(n->left->sym->name, "newarray") != 0)
-		goto no;
-
-	// call to newarray - find width and nel
-	wid = N;
-	nel = N;
-	a = listfirst(&param, &n->right);
-	while(a != N) {
-		if(a->op == OAS &&
-		   a->left != N && a->right != N &&
-		   a->left->op == OINDREG && a->right->op == OLITERAL &&
-		   a->left->sym != S) {
-			if(strcmp(a->left->sym->name, "nel") == 0)
-				nel = a->right;
-			if(strcmp(a->left->sym->name, "width") == 0)
-				wid = a->right;
-		}
-		a = listnext(&param);
-	}
-	if(wid == N || nel == N)
-		goto no;
-
-	b = mpgetfix(nel->val.u.xval);
-	if(b == 0)
-		goto no;
-
-	t = shallow(n->type);
-	t->bound = b;
-	a = staticname(t);
-	a = nod(OCOMPSLICE, a, N);
-	a->type = n->type;
-	return a;
-
-no:
-	return N;
-}
-
-int
-initsub(Node *n, Node *nam)
-{
-	Iter iter, param;
-	Node *r, *w;
-	int any;
-
-	any = 0;
-	r = listfirst(&iter, &xxx);
-	while(r != N) {
-		switch(r->op) {
-		case OAS:
-		case OEMPTY:
-			if(r->left != N)
-			switch(r->left->op) {
-			case ONAME:
-				if(sametmp(r->left, nam)) {
-					any = 1;
-					w = slicerewrite(r->right);
-					r->left = n;
-					if(w != N) {
-						n = w->left;	// from now on use fixed array
-						r->right = w;
-						break;
-					}
-				}
-				break;
-			case ODOT:
-				if(sametmp(r->left->left, nam)) {
-					any = 1;
-					r->left->left = n;
-				}
-				if(indsametmp(r->left->left, nam)) {
-					any = 1;
-					r->left->left->left = n;
-				}
-				break;
-			case OINDEX:
-				if(sametmp(r->left->left, nam)) {
-					any = 1;
-					r->left->left = n;
-				}
-				if(indsametmp(r->left->left, nam)) {
-					any = 1;
-					r->left->left->left = n;
-				}
-				break;
-			}
-			break;
-		case OCALL:
-			// call to mapassign1
-			// look through the parameters
-			w = listfirst(&param, &r->right);
-			while(w != N) {
-				if(sametmp(w->right, nam)) {
-					any = 1;
-					w->right = n;
-				}
-				if(indsametmp(w->right, nam)) {
-					any = 1;
-					w->right->left = n;
-				}
-				w = listnext(&param);
-			}
-			break;
-		}
-		r = listnext(&iter);
-	}
-	return any;
-}
-
-Node*
-initfix(Node* n)
-{
-	Iter iter;
-	Node *r;
-
-//dump("prelin", n);
-
-	xxx = N;
-	initlin(n);
-	xxx = rev(xxx);
-
-//dump("preinitfix", xxx);
-	// look for the copy-out reference
-	r = listfirst(&iter, &xxx);
-	while(r != N) {
-		if(r->op == OAS)
-		if(inittmp(r->right)) {
-			if(initsub(r->left, r->right))
-				r->op = OEMPTY;
-		}
-		r = listnext(&iter);
-	}
-//dump("postinitfix", xxx);
-	return xxx;
-}
-
 void
 fninit(Node *n)
 {
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index 856b986..4d4ff3e 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -850,6 +850,12 @@
 Node*	unsafenmagic(Node*, Node*);
 
 /*
+ * sinit.c
+ */
+
+Node*	initfix(Node*);
+
+/*
  *	export.c
  */
 void	renameimports(void);
@@ -939,6 +945,7 @@
 void	evconst(Node*);
 int	cmpslit(Node *l, Node *r);
 int	smallintconst(Node*);
+long	nonnegconst(Node*);
 int	consttype(Node*);
 int	isconst(Node*, int);
 
diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y
index 7dc6352..0841d5d 100644
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -1786,12 +1786,20 @@
 		$$ = rev($1);
 	}
 
+/*
+ * list of combo of keyval and val
+ */
 keyval_list_r:
 	keyval
+|	expr
 |	keyval_list_r ',' keyval
 	{
 		$$ = nod(OLIST, $1, $3);
 	}
+|	keyval_list_r ',' expr
+	{
+		$$ = nod(OLIST, $1, $3);
+	}
 
 /*
  * have to spell this out using _r lists to avoid yacc conflict
@@ -1804,10 +1812,6 @@
 	{
 		$$ = rev($1);
 	}
-|	expr_list_r ocomma
-	{
-		$$ = rev($1);
-	}
 
 
 /*
diff --git a/src/cmd/gc/sinit.c b/src/cmd/gc/sinit.c
new file mode 100644
index 0000000..2567151
--- /dev/null
+++ b/src/cmd/gc/sinit.c
@@ -0,0 +1,346 @@
+// 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"
+
+static struct
+{
+	Node*	list;
+	Node*	mapname;
+	Type*	type;
+} xxx;
+
+/*
+ * the init code (thru initfix) reformats the
+ *	var = ...
+ * statements, rewriting the automatic
+ * variables with the static variables.
+ * this allows the code generator to
+ * generate DATA statements instead
+ * of assignment statements.
+ * it is quadradic, may need to change.
+ * it is extremely fragile knowing exactly
+ * how the code from (struct|array|map)lit
+ * will look. ideally the lit routines could
+ * write the code in this form, but ...
+ */
+
+void
+initlin(Node* n)
+{
+	if(n == N)
+		return;
+	initlin(n->ninit);
+	switch(n->op) {
+	default:
+		print("o = %O\n", n->op);
+		n->ninit = N;
+		xxx.list = list(xxx.list, n);
+		break;
+
+	case OCALL:
+		// call to mapassign1
+		if(n->left->op != ONAME ||
+		   n->right->op != OLIST ||
+		   n->right->left->op != OAS ||
+		   n->right->right->op != OLIST ||
+		   n->right->right->left->op != OAS ||
+		   n->right->right->right->op != OAS ||
+		   strcmp(n->left->sym->name, "mapassign1") != 0)
+			dump("o=call", n);
+		n->ninit = N;
+		xxx.list = list(xxx.list, n);
+		break;
+
+	case OAS:
+		n->ninit = N;
+		xxx.list = list(xxx.list, n);
+		break;
+
+	case OLIST:
+		initlin(n->left);
+		initlin(n->right);
+		break;
+	}
+}
+
+int
+inittmp(Node *n)
+{
+	if(n != N)
+	if(n->op == ONAME)
+	if(n->sym != S)
+	if(n->class == PAUTO)
+	if(strcmp(n->sym->name, "!tmpname!") == 0)
+		return 1;
+	return 0;
+}
+
+int
+sametmp(Node *n1, Node *n2)
+{
+	if(inittmp(n1))
+	if(n1->xoffset == n2->xoffset)
+		return 1;
+	return 0;
+}
+
+int
+indsametmp(Node *n1, Node *n2)
+{
+	if(n1->op == OIND)
+	if(inittmp(n1->left))
+	if(n1->left->xoffset == n2->xoffset)
+		return 1;
+	return 0;
+}
+
+Node*
+findarg(Node *n, char *arg, char *fn)
+{
+	Iter param;
+	Node *a;
+
+	if(n == N || n->op != OCALL ||
+	   n->left == N || n->left->sym == S ||
+	   strcmp(n->left->sym->name, fn) != 0)
+		return N;
+
+	a = listfirst(&param, &n->right);
+	while(a != N) {
+		if(a->op == OAS &&
+		   a->left != N && a->right != N &&
+		   a->left->op == OINDREG &&
+		   a->left->sym != S)
+			if(strcmp(a->left->sym->name, arg) == 0)
+				return a->right;
+		a = listnext(&param);
+	}
+	return N;
+}
+
+Node*
+slicerewrite(Node *n)
+{
+	Node *nel;
+	Type *t;
+	int b;
+	Node *a;
+
+	// call to newarray - find nel argument
+	nel = findarg(n, "nel", "newarray");
+	if(nel == N || !isslice(n->type))
+		goto no;
+
+	b = mpgetfix(nel->val.u.xval);
+	t = shallow(n->type);
+	t->bound = b;
+
+	// special hack for zero-size array
+	// invent an l-value to point at
+	if(b == 0)
+		a = staticname(types[TBOOL]);
+	else
+		a = staticname(t);
+
+	a = nod(OCOMPSLICE, a, N);
+	a->type = n->type;
+	return a;
+
+no:
+	return N;
+}
+
+Node*
+maprewrite(Node *n)
+{
+	Node *nel;
+	Type *ta, *tb;
+	Node *a;
+
+	// call to newarray - find nel argument
+	nel = findarg(n, "hint", "newmap");
+	if(nel == N)
+		goto no;
+	ta = n->type;
+	if(ta->etype != TMAP)
+		goto no;
+
+	// create a new type from map[index]value
+	//	[0]struct { a index; b value) }
+
+	tb = typ(TFIELD);
+	tb->type = ta->down;
+	tb->sym = lookup("key");
+	tb->nname = newname(tb->sym);
+	tb->down = typ(TFIELD);
+	tb->down->type = ta->type;
+	tb->down->sym = lookup("val");
+	tb->down->nname = newname(tb->down->sym);
+
+	ta = typ(TSTRUCT);
+	ta->type = tb;
+
+	tb = typ(TARRAY);
+	tb->type = ta;
+	tb->bound = 0;
+
+	dowidth(tb);
+
+	a = staticname(tb);
+	a = nod(OCOMPMAP, a, N);
+	a->type = n->type;
+
+	// save stuff for this iteration
+	xxx.mapname = a->left;
+	xxx.type = tb;
+
+	return a;
+
+no:
+	return N;
+}
+
+// convert the call to mapassign1
+// into static[i].key = k, static[i].val = v
+Node*
+mapindex(Node *n)
+{
+	Node *index, *val, *key, *a, *b;
+
+	// pull all the primatives
+	key = findarg(n, "key", "mapassign1");
+	val = findarg(n, "val", "mapassign1");
+	index = nodintconst(xxx.type->bound);
+	xxx.type->bound++;
+	dowidth(xxx.type);
+
+	// build tree
+	a = nod(OINDEX, xxx.mapname, index);
+	a = nod(ODOT, a, newname(lookup("key")));
+	a = nod(OAS, a, key);
+
+	b = nod(OINDEX, xxx.mapname, index);
+	b = nod(ODOT, b, newname(lookup("val")));
+	b = nod(OAS, b, val);
+
+	a = nod(OLIST, a, b);
+	walktype(a, Etop);
+
+	return a;
+}
+
+// for a copy out reference, A = B,
+// look through the whole structure
+// and substitute references of B to A.
+// some rewrite goes on also.
+int
+initsub(Node *n, Node *nam)
+{
+	Iter iter;
+	Node *r, *w;
+	int any;
+
+	any = 0;
+	r = listfirst(&iter, &xxx.list);
+	while(r != N) {
+		switch(r->op) {
+		case OAS:
+		case OEMPTY:
+			if(r->left != N)
+			switch(r->left->op) {
+			case ONAME:
+				if(sametmp(r->left, nam)) {
+					any = 1;
+					r->left = n;
+
+					w = slicerewrite(r->right);
+					if(w != N) {
+						n = w->left;	// from now on use fixed array
+						r->right = w;
+						break;
+					}
+
+					w = maprewrite(r->right);
+					if(w != N) {
+						n = w->left;	// from now on use fixed array
+						r->right = w;
+						break;
+					}
+				}
+				break;
+			case ODOT:
+				if(sametmp(r->left->left, nam)) {
+					any = 1;
+					r->left->left = n;
+				}
+				if(indsametmp(r->left->left, nam)) {
+					any = 1;
+					r->left->left->left = n;
+				}
+				break;
+			case OINDEX:
+				if(sametmp(r->left->left, nam)) {
+					any = 1;
+					r->left->left = n;
+				}
+				if(indsametmp(r->left->left, nam)) {
+					any = 1;
+					r->left->left->left = n;
+				}
+				break;
+			}
+			break;
+		case OCALL:
+			// call to mapassign1
+			// look through the parameters
+			w = findarg(r, "hmap", "mapassign1");
+			if(w == N)
+				break;
+			if(sametmp(w, nam)) {
+				any = 1;
+				*r = *mapindex(r);
+			}
+			if(indsametmp(w, nam)) {
+fatal("indirect map index");
+				any = 1;
+				w->right->left = n;
+			}
+			break;
+		}
+		r = listnext(&iter);
+	}
+	return any;
+}
+
+Node*
+initfix(Node* n)
+{
+	Iter iter;
+	Node *r;
+
+//dump("prelin", n);
+
+	xxx.list = N;
+	initlin(n);
+	xxx.list = rev(xxx.list);
+
+return xxx.list;
+if(debug['A'])
+dump("preinitfix", xxx.list);
+
+	// look for the copy-out reference
+	r = listfirst(&iter, &xxx.list);
+	while(r != N) {
+		if(r->op == OAS)
+		if(inittmp(r->right)) {
+			if(initsub(r->left, r->right))
+				r->op = OEMPTY;
+		}
+		r = listnext(&iter);
+	}
+if(debug['A'])
+dump("postinitfix", xxx.list);
+	return xxx.list;
+}
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index 0f160a8..b1c1c2d 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -637,7 +637,7 @@
 			break;
 		}
 		indir(n, r);
-		walktype(l, Erv);
+//		walktype(l, Erv);
 		goto ret;
 
 	case ORETURN:
@@ -988,7 +988,7 @@
 				goto badlit;
 			}
 
-			walktype(n->left->left, Erv);
+//			walktype(n->left->left, Erv);
 			indir(n, nvar);
 			goto ret;
 		}
@@ -3911,6 +3911,7 @@
 	Iter savel, saver;
 	Type *l, *t;
 	Node *r, *a;
+	int mixflag;
 
 	t = n->type;
 	if(t->etype != TSTRUCT)
@@ -3921,30 +3922,66 @@
 		tempname(var, t);
 	}
 
-	l = structfirst(&savel, &n->type);
 	r = listfirst(&saver, &n->left);
 	if(r != N && r->op == OEMPTY)
 		r = N;
 
-loop:
+	mixflag = 0;
+	if(r != N && r->op == OKEY) {
+		a = nod(OAS, var, N);
+		addtop = list(addtop, a);
+		goto loop2;
+	}
+	l = structfirst(&savel, &n->type);
+
+loop1:
+	// assignment to every field
 	if(l == T || r == N) {
 		if(l != T)
 			yyerror("struct literal expect expr of type %T", l);
 		if(r != N)
 			yyerror("struct literal too many expressions");
+		if(mixflag)
+			yyerror("mixture of field:value initializers");
 		return var;
 	}
+	if(r->op == OKEY) {
+		mixflag = 1;
+		goto incr1;
+	}
 
 	// build list of var.field = expr
-
 	a = nod(ODOT, var, newname(l->sym));
 	a = nod(OAS, a, r);
-	walktype(a, Etop);	// add any assignments in r to addtop
+	walktype(a, Etop);
 	addtop = list(addtop, a);
 
+incr1:
 	l = structnext(&savel);
 	r = listnext(&saver);
-	goto loop;
+	goto loop1;
+
+loop2:
+	// assignment to field:value elements
+	if(r == N) {
+		if(mixflag)
+			yyerror("mixture of field:value initializers");
+		return var;
+	}
+	if(r->op != OKEY) {
+		mixflag = 1;
+		goto incr2;
+	}
+
+	// build list of var.field = expr
+	a = nod(ODOT, var, newname(r->left->sym));
+	a = nod(OAS, a, r->right);
+	walktype(a, Etop);
+	addtop = list(addtop, a);
+
+incr2:
+	r = listnext(&saver);
+	goto loop2;
 }
 
 Node*
@@ -3953,19 +3990,28 @@
 	Iter saver;
 	Type *t;
 	Node *r, *a;
-	int ninit, b;
+	long ninit, b;
 
 	t = n->type;
 	if(t->etype != TARRAY)
 		fatal("arraylit: not array");
 
-	// count initializers
+	// find max index
 	ninit = 0;
+	b = 0;
+
 	r = listfirst(&saver, &n->left);
 	if(r != N && r->op == OEMPTY)
 		r = N;
+
 	while(r != N) {
-		ninit++;
+		b++;
+		if(r->op == OKEY) {
+			evconst(r->left);
+			b = nonnegconst(r->left);
+		}
+		if(b > ninit)
+			ninit = b;
 		r = listnext(&saver);
 	}
 
@@ -3998,18 +4044,28 @@
 		}
 	}
 
-	ninit = 0;
+	b = 0;
 	r = listfirst(&saver, &n->left);
 	if(r != N && r->op == OEMPTY)
 		r = N;
 	while(r != N) {
 		// build list of var[c] = expr
-		a = nodintconst(ninit);
+		if(r->op == OKEY) {
+			b = nonnegconst(r->left);
+			if(b < 0) {
+				yyerror("array index must be non-negative integer");
+				break;
+			}
+			r = r->right;
+		}
+		a = nodintconst(b);
 		a = nod(OINDEX, var, a);
 		a = nod(OAS, a, r);
+
 		walktype(a, Etop);	// add any assignments in r to addtop
 		addtop = list(addtop, a);
-		ninit++;
+		b++;
+
 		r = listnext(&saver);
 	}
 	return var;
@@ -4041,24 +4097,24 @@
 		r = N;
 
 loop:
-	if(r == N) {
-		return var;
+	while(r != N) {
+		if(r == N)
+			break;
+
+		if(r->op != OKEY) {
+			yyerror("map literal must have key:value pairs");
+			break;
+		}
+
+		// build list of var[c] = expr
+		a = nod(OINDEX, var, r->left);
+		a = nod(OAS, a, r->right);
+		walktype(a, Etop);	// add any assignments in r to addtop
+		addtop = list(addtop, a);
+
+		r = listnext(&saver);
 	}
-
-	if(r->op != OKEY) {
-		yyerror("map literal must have key:value pairs");
-		return var;
-	}
-
-	// build list of var[c] = expr
-
-	a = nod(OINDEX, var, r->left);
-	a = nod(OAS, a, r->right);
-	walktype(a, Etop);	// add any assignments in r to addtop
-	addtop = list(addtop, a);
-
-	r = listnext(&saver);
-	goto loop;
+	return var;
 }
 
 /*