aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2010-10-21 23:17:20 -0400
committerRuss Cox <rsc@golang.org>2010-10-21 23:17:20 -0400
commit8ffc4ec5d0c3d17d633c277ba5102da838834f03 (patch)
tree1b0db1b4c859d8021acbfa0595e228c71083e2f1
parente5bd12ea90bd5a5727f51ade05c87962ca390670 (diff)
downloadgo-8ffc4ec5d0c3d17d633c277ba5102da838834f03.tar.gz
go-8ffc4ec5d0c3d17d633c277ba5102da838834f03.zip
gc: implement new composite literal spec
R=ken2 CC=golang-dev https://golang.org/cl/2350041
-rw-r--r--src/cmd/gc/go.y27
-rw-r--r--src/cmd/gc/typecheck.c78
2 files changed, 72 insertions, 33 deletions
diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y
index 8a98d24017..7960a22640 100644
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -52,7 +52,7 @@ static void fixlbrace(int);
%type <node> stmt ntype
%type <node> arg_type
%type <node> case caseblock
-%type <node> compound_stmt dotname embed expr
+%type <node> compound_stmt dotname embed expr complitexpr
%type <node> expr_or_type
%type <node> fndcl fnliteral
%type <node> for_body for_header for_stmt if_header if_stmt non_dcl_stmt
@@ -889,6 +889,20 @@ pexpr_no_paren:
}
| fnliteral
+keyval:
+ expr ':' complitexpr
+ {
+ $$ = nod(OKEY, $1, $3);
+ }
+
+complitexpr:
+ expr
+| '{' braced_keyval_list '}'
+ {
+ $$ = nod(OCOMPLIT, N, N);
+ $$->list = $2;
+ }
+
pexpr:
pexpr_no_paren
| '(' expr_or_type ')'
@@ -1094,13 +1108,6 @@ interfacetype:
fixlbrace($2);
}
-keyval:
- expr ':' expr
- {
- $$ = nod(OKEY, $1, $3);
- }
-
-
/*
* function stuff
* all in one place to show how crappy it all is
@@ -1552,7 +1559,7 @@ keyval_list:
{
$$ = list1($1);
}
-| expr
+| complitexpr
{
$$ = list1($1);
}
@@ -1560,7 +1567,7 @@ keyval_list:
{
$$ = list($1, $3);
}
-| keyval_list ',' expr
+| keyval_list ',' complitexpr
{
$$ = list($1, $3);
}
diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c
index 89cd1d6591..43cf4a7c36 100644
--- a/src/cmd/gc/typecheck.c
+++ b/src/cmd/gc/typecheck.c
@@ -1776,7 +1776,7 @@ typecheckcomplit(Node **np)
int bad, i, len, nerr;
Node *l, *n, *hash[101];
NodeList *ll;
- Type *t, *f;
+ Type *t, *f, *pushtype;
Sym *s;
int32 lno;
@@ -1784,11 +1784,38 @@ typecheckcomplit(Node **np)
lno = lineno;
memset(hash, 0, sizeof hash);
+ if(n->right == N) {
+ if(n->list != nil)
+ setlineno(n->list->n);
+ yyerror("missing type in composite literal");
+ goto error;
+ }
+
setlineno(n->right);
l = typecheck(&n->right /* sic */, Etype);
if((t = l->type) == T)
goto error;
nerr = nerrors;
+
+ // can omit type on composite literal values if the outer
+ // composite literal is array, slice, or map, and the
+ // element type is itself a struct, array, slice, or map.
+ pushtype = T;
+ if(t->etype == TARRAY || t->etype == TMAP) {
+ pushtype = t->type;
+ if(pushtype != T) {
+ switch(pushtype->etype) {
+ case TSTRUCT:
+ case TARRAY:
+ case TMAP:
+ break;
+ default:
+ pushtype = T;
+ break;
+ }
+ }
+ }
+
switch(t->etype) {
default:
yyerror("invalid type for composite literal: %T", t);
@@ -1801,27 +1828,22 @@ typecheckcomplit(Node **np)
for(ll=n->list; ll; ll=ll->next) {
l = ll->n;
setlineno(l);
- if(l->op == OKEY) {
- typecheck(&l->left, Erv);
- evconst(l->left);
- i = nonnegconst(l->left);
- if(i < 0) {
- yyerror("array index must be non-negative integer constant");
- i = -(1<<30); // stay negative for a while
- }
- typecheck(&l->right, Erv);
- defaultlit(&l->right, t->type);
- l->right = assignconv(l->right, t->type, "array index");
- } else {
- typecheck(&ll->n, Erv);
- defaultlit(&ll->n, t->type);
- ll->n = assignconv(ll->n, t->type, "array index");
- ll->n = nod(OKEY, nodintconst(i), ll->n);
- ll->n->left->type = types[TINT];
- ll->n->left->typecheck = 1;
+ if(l->op != OKEY) {
+ l = nod(OKEY, nodintconst(i), l);
+ l->left->type = types[TINT];
+ l->left->typecheck = 1;
+ ll->n = l;
+ }
+
+ typecheck(&l->left, Erv);
+ evconst(l->left);
+ i = nonnegconst(l->left);
+ if(i < 0) {
+ yyerror("array index must be non-negative integer constant");
+ i = -(1<<30); // stay negative for a while
}
if(i >= 0)
- indexdup(ll->n->left, hash, nelem(hash));
+ indexdup(l->left, hash, nelem(hash));
i++;
if(i > len) {
len = i;
@@ -1831,6 +1853,12 @@ typecheckcomplit(Node **np)
t->bound = -1; // no more errors
}
}
+
+ if(l->right->op == OCOMPLIT && l->right->right == N && pushtype != T)
+ l->right->right = typenod(pushtype);
+ typecheck(&l->right, Erv);
+ defaultlit(&l->right, t->type);
+ l->right = assignconv(l->right, t->type, "array index");
}
if(t->bound == -100)
t->bound = len;
@@ -1848,13 +1876,17 @@ typecheckcomplit(Node **np)
yyerror("missing key in map literal");
continue;
}
+
typecheck(&l->left, Erv);
- typecheck(&l->right, Erv);
defaultlit(&l->left, t->down);
- defaultlit(&l->right, t->type);
l->left = assignconv(l->left, t->down, "map key");
- l->right = assignconv(l->right, t->type, "map value");
keydup(l->left, hash, nelem(hash));
+
+ if(l->right->op == OCOMPLIT && l->right->right == N && pushtype != T)
+ l->right->right = typenod(pushtype);
+ typecheck(&l->right, Erv);
+ defaultlit(&l->right, t->type);
+ l->right = assignconv(l->right, t->type, "map value");
}
n->op = OMAPLIT;
break;