1
0
mirror of https://github.com/golang/go synced 2024-11-12 00:30:22 -07:00

gc: implement new composite literal spec

R=ken2
CC=golang-dev
https://golang.org/cl/2350041
This commit is contained in:
Russ Cox 2010-10-21 23:17:20 -04:00
parent e5bd12ea90
commit 8ffc4ec5d0
2 changed files with 72 additions and 33 deletions

View File

@ -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);
}

View File

@ -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;