%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
}
| 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 ')'
fixlbrace($2);
}
-keyval:
- expr ':' expr
- {
- $$ = nod(OKEY, $1, $3);
- }
-
-
/*
* function stuff
* all in one place to show how crappy it all is
{
$$ = list1($1);
}
-| expr
+| complitexpr
{
$$ = list1($1);
}
{
$$ = list($1, $3);
}
-| keyval_list ',' expr
+| keyval_list ',' complitexpr
{
$$ = list($1, $3);
}
int bad, i, len, nerr;
Node *l, *n, *hash[101];
NodeList *ll;
- Type *t, *f;
+ Type *t, *f, *pushtype;
Sym *s;
int32 lno;
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);
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;
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;
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;