Commit ff3a73b4 authored by Russ Cox's avatar Russ Cox

typechecking checkpoint.

started to move typechecking to another file.
can build entire tree still, but lots of work
is duplicated.  much to clean up.

R=ken
OCL=32536
CL=32543
parent 34b277f0
......@@ -281,7 +281,7 @@ cgen(Node *n, Node *res)
cgen_callret(n, res);
break;
case OCALL:
case OCALLFUNC:
cgen_call(n, 0);
cgen_callret(n, res);
break;
......@@ -404,7 +404,7 @@ agen(Node *n, Node *res)
cgen_aret(n, res);
break;
case OCALL:
case OCALLFUNC:
cgen_call(n, 0);
cgen_aret(n, res);
break;
......@@ -811,7 +811,7 @@ stkof(Node *n)
case OCALLMETH:
case OCALLINTER:
case OCALL:
case OCALLFUNC:
t = n->left->type;
if(isptr[t->etype])
t = t->type;
......
......@@ -300,7 +300,7 @@ cgen(Node *n, Node *res)
cgen_callret(n, res);
break;
case OCALL:
case OCALLFUNC:
cgen_call(n, 0);
cgen_callret(n, res);
break;
......@@ -420,7 +420,7 @@ agen(Node *n, Node *res)
cgen_aret(n, res);
break;
case OCALL:
case OCALLFUNC:
cgen_call(n, 0);
cgen_aret(n, res);
break;
......@@ -827,7 +827,7 @@ stkof(Node *n)
case OCALLMETH:
case OCALLINTER:
case OCALL:
case OCALLFUNC:
t = n->left->type;
if(isptr[t->etype])
t = t->type;
......
......@@ -306,7 +306,7 @@ cgen(Node *n, Node *res)
cgen_callret(n, res);
break;
case OCALL:
case OCALLFUNC:
cgen_call(n, 0);
cgen_callret(n, res);
break;
......@@ -447,7 +447,7 @@ agen(Node *n, Node *res)
cgen_aret(n, res);
break;
case OCALL:
case OCALLFUNC:
cgen_call(n, 0);
cgen_aret(n, res);
break;
......@@ -922,7 +922,7 @@ stkof(Node *n)
case OCALLMETH:
case OCALLINTER:
case OCALL:
case OCALLFUNC:
t = n->left->type;
if(isptr[t->etype])
t = t->type;
......
......@@ -35,6 +35,7 @@ OFILES=\
gen.$O\
obj.$O\
print.$O\
typecheck.$O\
$(LIB): $(OFILES)
ar rsc $(LIB) $(OFILES)
......
......@@ -339,6 +339,14 @@ typeinit(void)
okfor[OCAP] = okforcap;
okfor[OLEN] = okforlen;
// comparison
iscmp[OLT] = 1;
iscmp[OGT] = 1;
iscmp[OGE] = 1;
iscmp[OLE] = 1;
iscmp[OEQ] = 1;
iscmp[ONE] = 1;
mpatofix(maxintval[TINT8], "0x7f");
mpatofix(minintval[TINT8], "-0x80");
mpatofix(maxintval[TINT16], "0x7fff");
......
......@@ -89,12 +89,17 @@ convlit1(Node **np, Type *t, int explicit)
switch(n->op) {
default:
if(n->type->etype == TIDEAL) {
convlit(&n->left, t);
convlit(&n->right, t);
n->type = t;
}
return;
case OLITERAL:
break;
case OLSH:
case ORSH:
convlit1(&n->left, t, explicit);
convlit(&n->left, t);
n->type = n->left->type;
return;
}
......@@ -259,11 +264,15 @@ overflow(Val v, Type *t)
return;
switch(v.ctype) {
case CTINT:
if(!isint[t->etype])
fatal("overflow: %T integer constant", t);
if(mpcmpfixfix(v.u.xval, minintval[t->etype]) < 0
|| mpcmpfixfix(v.u.xval, maxintval[t->etype]) > 0)
yyerror("constant %B overflows %T", v.u.xval, t);
break;
case CTFLT:
if(!isfloat[t->etype])
fatal("overflow: %T floating-point constant", t);
if(mpcmpfltflt(v.u.fval, minfltval[t->etype]) < 0
|| mpcmpfltflt(v.u.fval, maxfltval[t->etype]) > 0)
yyerror("constant %#F overflows %T", v.u.fval, t);
......@@ -325,6 +334,11 @@ evconst(Node *n)
Val v;
Mpint b;
switch(n->op) {
case OMAKE:
return;
}
nl = n->left;
if(nl == N || nl->type == T)
return;
......@@ -590,6 +604,7 @@ unary:
case TUP(OCONV, CTINT):
case TUP(OCONV, CTFLT):
case TUP(OCONV, CTSTR):
case TUP(OCONV, CTNIL):
convlit1(&nl, n->type, 1);
break;
......@@ -711,6 +726,11 @@ defaultlit(Node **np, Type *t)
defaultlit(&n->left, t);
n->type = n->left->type;
return;
default:
defaultlit(&n->left, t);
defaultlit(&n->right, t);
n->type = n->left->type;
return;
}
lno = lineno;
......@@ -753,7 +773,7 @@ defaultlit(Node **np, Type *t)
* get the same type going out.
*/
void
defaultlit2(Node **lp, Node **rp)
defaultlit2(Node **lp, Node **rp, int force)
{
Node *l, *r;
......@@ -769,6 +789,8 @@ defaultlit2(Node **lp, Node **rp)
convlit(lp, r->type);
return;
}
if(!force)
return;
if(isconst(l, CTFLT) || isconst(r, CTFLT)) {
convlit(lp, types[TFLOAT]);
convlit(rp, types[TFLOAT]);
......
......@@ -528,7 +528,7 @@ funclit0(Node *t)
autodcl = dcl();
autodcl->back = autodcl;
walkexpr(&t, Etype, &t->ninit);
typecheck(&t, Etype);
funcargs(t->type);
return t;
}
......@@ -703,7 +703,7 @@ stotype(NodeList *l, int et, Type **t)
if(n->op != ODCLFIELD)
fatal("stotype: oops %N\n", n);
if(n->right != N) {
walkexpr(&n->right, Etype, &init);
typecheck(&n->right, Etype);
n->type = n->right->type;
n->right = N;
if(n->embedded && n->type != T) {
......@@ -1298,7 +1298,7 @@ xanondcl(Node *nt)
Node *n;
Type *t;
walkexpr(&nt, Etype, &nt->ninit);
typecheck(&nt, Etype);
t = nt->type;
if(nt->op != OTYPE) {
yyerror("%S is not a type", nt->sym);
......@@ -1318,7 +1318,7 @@ namedcl(Node *nn, Node *nt)
if(nn->op == OKEY)
nn = nn->left;
if(nn->sym == S) {
walkexpr(&nn, Etype, &nn->ninit);
typecheck(&nn, Etype);
yyerror("cannot mix anonymous %T with named arguments", nn->type);
return xanondcl(nn);
}
......@@ -1326,7 +1326,7 @@ namedcl(Node *nn, Node *nt)
if(nt == N)
yyerror("missing type for argument %S", nn->sym);
else {
walkexpr(&nt, Etype, &nt->ninit);
typecheck(&nt, Etype);
if(nt->op != OTYPE)
yyerror("%S is not a type", nt->sym);
else
......@@ -1650,7 +1650,7 @@ variter(NodeList *vl, Node *nt, NodeList *el)
t = T;
if(nt) {
walkexpr(&nt, Etype, &nt->ninit);
typecheck(&nt, Etype);
t = nt->type;
}
......@@ -1763,7 +1763,7 @@ unsafenmagic(Node *fn, NodeList *args)
n = nod(OLITERAL, N, N);
if(strcmp(s->name, "Sizeof") == 0) {
walkexpr(&r, Erv, &n->ninit);
typecheck(&r, Erv);
tr = r->type;
if(r->op == OLITERAL && r->val.ctype == CTSTR)
tr = types[TSTRING];
......@@ -1775,12 +1775,12 @@ unsafenmagic(Node *fn, NodeList *args)
if(strcmp(s->name, "Offsetof") == 0) {
if(r->op != ODOT && r->op != ODOTPTR)
goto no;
walkexpr(&r, Erv, &n->ninit);
typecheck(&r, Erv);
v = r->xoffset;
goto yes;
}
if(strcmp(s->name, "Alignof") == 0) {
walkexpr(&r, Erv, &n->ninit);
typecheck(&r, Erv);
tr = r->type;
if(r->op == OLITERAL && r->val.ctype == CTSTR)
tr = types[TSTRING];
......
......@@ -321,7 +321,7 @@ gen(Node *n)
cgen_callinter(n, N, 0);
break;
case OCALL:
case OCALLFUNC:
cgen_call(n, 0);
break;
......@@ -360,7 +360,7 @@ cgen_callmeth(Node *n, int proc)
if(l->op != ODOTMETH)
fatal("cgen_callmeth: not dotmethod: %N");
n->op = OCALL;
n->op = OCALLFUNC;
n->left = n->left->right;
n->left->type = l->type;
......@@ -387,7 +387,7 @@ cgen_proc(Node *n, int proc)
cgen_callinter(n->left, N, proc);
break;
case OCALL:
case OCALLFUNC:
cgen_call(n->left, proc);
break;
}
......
......@@ -343,14 +343,15 @@ enum
OCONTINUE,
OADDR,
OIND,
OCALL, OCALLMETH, OCALLINTER,
OCALL, OCALLFUNC, OCALLMETH, OCALLINTER,
OINDEX, OSLICE,
ONOT, OCOM, OPLUS, OMINUS, OSEND, ORECV,
OREGISTER, OINDREG,
OKEY, OPARAM,
OCOMPOS, OCOMPSLICE, OCOMPMAP,
OCONV, OCONVNOP,
ODOTTYPE, OTYPESW,
OCONV, OCONVNOP, OCONVRUNE, OCONVSTRB, OCONVSTRI,
OCONVA2S,
ODOTTYPE, OTYPESW, OTYPECASE,
OBAD,
OTCHAN, OTMAP, OTSTRUCT, OTINTER, OTFUNC, OTARRAY,
......@@ -440,7 +441,7 @@ enum
Elv = 1<<2, // evaluated in lvalue context
Erv = 1<<3, // evaluated in rvalue context
Etype = 1<<4,
Eideal = 1<<5,
Ecall = 1<<5,
};
#define BITS 5
......@@ -593,6 +594,7 @@ EXTERN uchar okforcap[NTYPE];
EXTERN uchar okforlen[NTYPE];
EXTERN uchar okforarith[NTYPE];
EXTERN uchar* okfor[OEND];
EXTERN uchar iscmp[OEND];
EXTERN Mpint* minintval[NTYPE];
EXTERN Mpint* maxintval[NTYPE];
......@@ -830,7 +832,6 @@ int Wconv(Fmt*);
int Zconv(Fmt*);
int lookdot0(Sym*, Type*, Type**);
Type* lookdot1(Sym*, Type*, Type*);
int adddot1(Sym*, Type*, int, Type**);
Node* adddot(Node*);
void expandmeth(Sym*, Type*);
......@@ -846,7 +847,7 @@ Type* dodcltype(Type*);
void updatetype(Type*, Type*);
void dodclconst(Node*, Node*);
void defaultlit(Node**, Type*);
void defaultlit2(Node**, Node**);
void defaultlit2(Node**, Node**, int);
int structcount(Type*);
void addmethod(Node*, Type*, int);
Node* methodname(Node*, Type*);
......
......@@ -400,7 +400,7 @@ typedclname:
typedcl:
typedclname ntype
{
walkexpr(&$2, Etype, &$2->ninit);
typecheck(&$2, Etype);
updatetype($1, $2->type);
resumecheckwidth();
}
......@@ -478,21 +478,21 @@ case:
yyerror("type switch case cannot be list");
if(n->op == OLITERAL && n->val.ctype == CTNIL) {
// case nil
$$->list = list1(nod(OTYPESW, N, N));
$$->list = list1(nod(OTYPECASE, N, N));
break;
}
// TODO: move
e = nerrors;
walkexpr(&n, Etype | Erv, &$$->ninit);
typecheck(&n, Etype | Erv);
if(n->op == OTYPE) {
n = old2new(typeswvar->right, n->type, &$$->ninit);
$$->list = list1(nod(OTYPESW, n, N));
$$->list = list1(nod(OTYPECASE, n, N));
break;
}
// maybe walkexpr found problems that keep
// maybe typecheck found problems that keep
// e from being valid even outside a type switch.
// only complain if walkexpr didn't print new errors.
// only complain if typecheck didn't print new errors.
if(nerrors == e)
yyerror("non-type case in type switch");
$$->diag = 1;
......@@ -518,6 +518,7 @@ case:
// done in casebody()
poptodcl();
$$ = nod(OXCASE, N, N);
typecheck(&$4, Erv);
$$->list = list1(nod(OAS, selectas($2, $4, &$$->ninit), $4));
}
| LDEFAULT ':'
......@@ -1143,7 +1144,7 @@ fndcl:
n = nod(OTFUNC, N, N);
n->list = $3;
n->rlist = $5;
walkexpr(&n, Etype, &n->ninit);
typecheck(&n, Etype);
$$->type = n->type;
funchdr($$);
}
......
......@@ -24,7 +24,7 @@ void
exprfmt(Fmt *f, Node *n, int prec)
{
int nprec;
nprec = 0;
if(n == nil) {
fmtprint(f, "<nil>");
......@@ -38,7 +38,7 @@ exprfmt(Fmt *f, Node *n, int prec)
case OLITERAL:
nprec = 7;
break;
case OMUL:
case ODIV:
case OMOD:
......@@ -48,14 +48,14 @@ exprfmt(Fmt *f, Node *n, int prec)
case OANDNOT:
nprec = 6;
break;
case OADD:
case OSUB:
case OOR:
case OXOR:
nprec = 5;
break;
case OEQ:
case OLT:
case OLE:
......@@ -64,15 +64,15 @@ exprfmt(Fmt *f, Node *n, int prec)
case ONE:
nprec = 4;
break;
case OSEND:
nprec = 3;
break;
case OANDAND:
nprec = 2;
break;
case OOROR:
nprec = 1;
break;
......@@ -117,7 +117,7 @@ exprfmt(Fmt *f, Node *n, int prec)
case ONONAME:
fmtprint(f, "%S", n->sym);
break;
case OTYPE:
fmtprint(f, "%T", n->type);
break;
......@@ -126,7 +126,7 @@ exprfmt(Fmt *f, Node *n, int prec)
fmtprint(f, "[]");
exprfmt(f, n->left, PFIXME);
break;
case OTMAP:
fmtprint(f, "map[");
exprfmt(f, n->left, 0);
......@@ -146,19 +146,31 @@ exprfmt(Fmt *f, Node *n, int prec)
exprfmt(f, n->left, PCHAN);
}
break;
case OTSTRUCT:
fmtprint(f, "<struct>");
break;
case OTINTER:
fmtprint(f, "<inter>");
break;
case OTFUNC:
fmtprint(f, "<func>");
break;
case OAS:
exprfmt(f, n->left, 0);
fmtprint(f, " = ");
exprfmt(f, n->right, 0);
break;
case OASOP:
exprfmt(f, n->left, 0);
fmtprint(f, " %#O= ", n->etype);
exprfmt(f, n->right, 0);
break;
case OADD:
case OANDAND:
case OANDNOT:
......@@ -182,7 +194,7 @@ exprfmt(Fmt *f, Node *n, int prec)
fmtprint(f, " %#O ", n->op);
exprfmt(f, n->right, nprec+1);
break;
case OADDR:
case OCOM:
case OIND:
......@@ -195,35 +207,35 @@ exprfmt(Fmt *f, Node *n, int prec)
fmtprint(f, " ");
exprfmt(f, n->left, 0);
break;
case OCOMPOS:
fmtprint(f, "<compos>");
break;
case ODOT:
case ODOTINTER:
case ODOTMETH:
exprfmt(f, n->left, 7);
if(n->sym == S)
if(n->right == N || n->right->sym == S)
fmtprint(f, ".<nil>");
else
fmtprint(f, ".%s", n->sym->name);
fmtprint(f, ".%s", n->right->sym->name);
break;
case ODOTTYPE:
exprfmt(f, n->left, 7);
fmtprint(f, ".(");
exprfmt(f, n->right, 0);
fmtprint(f, ")");
break;
case OINDEX:
exprfmt(f, n->left, 7);
fmtprint(f, "[");
exprfmt(f, n->right, 0);
fmtprint(f, "]");
break;
case OSLICE:
exprfmt(f, n->left, 7);
fmtprint(f, "[");
......@@ -232,8 +244,9 @@ exprfmt(Fmt *f, Node *n, int prec)
exprfmt(f, n->right->right, 0);
fmtprint(f, "]");
break;
case OCALL:
case OCALLFUNC:
case OCALLINTER:
case OCALLMETH:
exprfmt(f, n->left, 7);
......@@ -241,13 +254,13 @@ exprfmt(Fmt *f, Node *n, int prec)
exprlistfmt(f, n->list);
fmtprint(f, ")");
break;
case OCONV:
fmtprint(f, "%T(", n->type);
exprfmt(f, n->left, 0);
fmtprint(f, ")");
break;
case OCAP:
case OCLOSE:
case OCLOSED:
......
......@@ -461,7 +461,7 @@ aindex(Node *b, Type *t)
bound = -1; // open bound
init = nil;
walkexpr(&b, Erv, &init);
typecheck(&b, Erv);
if(b != nil) {
switch(consttype(b)) {
default:
......@@ -638,6 +638,7 @@ opnames[] =
[OBAD] = "BAD",
[OBLOCK] = "BLOCK",
[OBREAK] = "BREAK",
[OCALLFUNC] = "CALLFUNC",
[OCALLINTER] = "CALLINTER",
[OCALLMETH] = "CALLMETH",
[OCALL] = "CALL",
......@@ -2100,6 +2101,7 @@ ullmancalc(Node *n)
ul++;
goto out;
case OCALL:
case OCALLFUNC:
case OCALLMETH:
case OCALLINTER:
ul = UINF;
......@@ -2389,6 +2391,7 @@ saferef(Node *n, NodeList **init)
r = nod(OXXX, N, N);
*r = *n;
r->left = l;
typecheck(&r, Elv);
walkexpr(&r, Elv, init);
return r;
......@@ -2398,9 +2401,11 @@ saferef(Node *n, NodeList **init)
l = nod(OXXX, N, N);
tempname(l, ptrto(n->type));
a = nod(OAS, l, nod(OADDR, n, N));
typecheck(&a, Etop);
walkexpr(&a, Etop, init);
*init = list(*init, a);
r = nod(OIND, l, N);
typecheck(&r, Elv);
walkexpr(&r, Elv, init);
return r;
}
......@@ -2555,13 +2560,11 @@ out:
Node*
adddot(Node *n)
{
NodeList *init;
Type *t;
Sym *s;
int c, d;
init = nil;
walkexpr(&n->left, Erv, &init);
typecheck(&n->left, Erv);
t = n->left->type;
if(t == T)
goto ret;
......@@ -2589,7 +2592,6 @@ out:
n->left->right = newname(dotlist[c].field->sym);
}
ret:
n->ninit = concat(init, n->ninit);
return n;
}
......
......@@ -247,14 +247,15 @@ sw0(Node **cp, Type *place, int arg)
switch(c->op) {
default:
if(arg == Stype) {
yyerror("inappropriate case for a type switch");
yyerror("expression case in a type switch");
return T;
}
walkexpr(cp, Erv, nil);
break;
case OTYPESW:
case OTYPECASE:
if(arg != Stype)
yyerror("inappropriate type case");
yyerror("type case in an expression switch");
break;
case OAS:
yyerror("inappropriate assignment in a case statement");
......@@ -542,12 +543,14 @@ exprbsw(Case *c0, int ncase, int arg)
case Sfalse:
a = nod(OIF, N, N);
a->ntest = nod(ONOT, n->left, N); // if !val
typecheck(&a->ntest, Erv);
a->nbody = list1(n->right); // then goto l
break;
default:
a = nod(OIF, N, N);
a->ntest = nod(OEQ, exprname, n->left); // if name == val
typecheck(&a->ntest, Erv);
a->nbody = list1(n->right); // then goto l
break;
}
......@@ -566,6 +569,7 @@ exprbsw(Case *c0, int ncase, int arg)
c = c->link;
a = nod(OIF, N, N);
a->ntest = nod(OLE, exprname, c->node->left);
typecheck(&a->ntest, Erv);
a->nbody = list1(exprbsw(c0, half, arg));
a->nelse = list1(exprbsw(c->link, ncase-half, arg));
return a;
......@@ -619,6 +623,7 @@ exprswitch(Node *sw)
exprname = nod(OXXX, N, N);
tempname(exprname, sw->ntest->type);
cas = list1(nod(OAS, exprname, sw->ntest));
typechecklist(cas, Etop);
}
c0 = mkcaselist(sw, arg);
......@@ -686,6 +691,7 @@ typeone(Node *t)
b = nod(ODOTTYPE, facename, N);
b->type = t->left->left->type; // interface.(type)
a->rlist = list1(b);
typecheck(&a, Etop);
init = list(init, a);
b = nod(OIF, N, N);
......@@ -716,6 +722,7 @@ typebsw(Case *c0, int ncase)
v.ctype = CTNIL;
a = nod(OIF, N, N);
a->ntest = nod(OEQ, facename, nodlit(v));
typecheck(&a->ntest, Erv);
a->nbody = list1(n->right); // if i==nil { goto l }
cas = list(cas, a);
break;
......@@ -728,6 +735,7 @@ typebsw(Case *c0, int ncase)
case Ttypeconst:
a = nod(OIF, N, N);
a->ntest = nod(OEQ, hashname, nodintconst(c0->hash));
typecheck(&a->ntest, Erv);
a->nbody = list1(typeone(n));
cas = list(cas, a);
break;
......@@ -744,6 +752,7 @@ typebsw(Case *c0, int ncase)
c = c->link;
a = nod(OIF, N, N);
a->ntest = nod(OLE, hashname, nodintconst(c->hash));
typecheck(&a->ntest, Erv);
a->nbody = list1(typebsw(c0, half));
a->nelse = list1(typebsw(c->link, ncase-half));
return a;
......@@ -786,13 +795,16 @@ typeswitch(Node *sw)
facename = nod(OXXX, N, N);
tempname(facename, sw->ntest->right->type);
a = nod(OAS, facename, sw->ntest->right);
typecheck(&a, Etop);
cas = list(cas, a);
boolname = nod(OXXX, N, N);
tempname(boolname, types[TBOOL]);
typecheck(&boolname, Erv);
hashname = nod(OXXX, N, N);
tempname(hashname, types[TUINT32]);
typecheck(&hashname, Erv);
t = sw->ntest->right->type;
if(isnilinter(t))
......@@ -803,6 +815,7 @@ typeswitch(Node *sw)
a = nod(OCALL, a, N);
a->list = list1(facename);
a = nod(OAS, hashname, a);
typecheck(&a, Etop);
cas = list(cas, a);
c0 = mkcaselist(sw, Stype);
......@@ -861,8 +874,10 @@ walkswitch(Node *sw)
* both have inserted OBREAK statements
*/
walkstmtlist(sw->ninit);
if(sw->ntest == N)
if(sw->ntest == N) {
sw->ntest = nodbool(1);
typecheck(&sw->ntest, Erv);
}
casebody(sw);
if(sw->ntest->op == OTYPESW) {
......
// 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 void implicitstar(Node**);
static int onearg(Node*);
static int lookdot(Node*, Type*);
static int convert(Node**, Type*, int);
void
typechecklist(NodeList *l, int top)
{
for(; l; l=l->next)
typecheck(&l->n, top);
}
/*
* type check the whole tree of an expression.
* calculates expression types.
* evaluates compile time constants.
* marks variables that escape the local frame.
* rewrites n->op to be more specific in some cases.
* replaces *np with a new pointer in some cases.
* returns the final value of *np as a convenience.
*/
Node*
typecheck(Node **np, int top)
{
int et, et1, et2, op, nerr, len;
NodeList *ll;
Node *n, *l, *r;
NodeList *args;
int i, lno, ok;
Type *t;
n = *np;
if(n == N || n->typecheck == 1)
return n;
if(n->typecheck == 2)
fatal("typecheck loop");
n->typecheck = 2;
if(n->sym && n->walkdef != 1)
walkdef(n);
lno = setlineno(n);
reswitch:
ok = 0;
switch(n->op) {
default:
// until typecheck is complete, do nothing.
dump("typecheck", n);
fatal("typecheck %O", n->op);
/*
* names
*/
case OLITERAL:
ok |= Erv;
goto ret;
case ONONAME:
ok |= Elv | Erv;
goto ret;
case ONAME:
if(n->etype != 0) {
yyerror("must call builtin %S", n->sym);
goto error;
}
ok |= Erv;
if(n->class != PFUNC)
ok |= Elv;
goto ret;
/*
* types (OIND is with exprs)
*/
case OTYPE:
ok |= Etype;
if(n->type == T)
goto error;
break;
case OTARRAY:
ok |= Etype;
t = typ(TARRAY);
l = n->left;
r = n->right;
if(l == nil) {
t->bound = -1;
} else {
typecheck(&l, Erv | Etype);
switch(l->op) {
default:
yyerror("invalid array bound %#N", l);
goto error;
case OLITERAL:
if(consttype(l) == CTINT) {
t->bound = mpgetfix(l->val.u.xval);
if(t->bound < 0) {
yyerror("array bound must be non-negative");
goto error;
}
}
break;
case OTYPE:
if(l->type == T)
goto error;
if(l->type->etype != TDDD) {
yyerror("invalid array bound %T", l->type);
goto error;
}
t->bound = -100;
break;
}
}
typecheck(&r, Etype);
if(r->type == T)
goto error;
t->type = r->type;
n->op = OTYPE;
n->type = t;
n->left = N;
n->right = N;
checkwidth(t);
break;
case OTMAP:
ok |= Etype;
l = typecheck(&n->left, Etype);
r = typecheck(&n->right, Etype);
if(l->type == T || r->type == T)
goto error;
n->op = OTYPE;
n->type = maptype(l->type, r->type);
n->left = N;
n->right = N;
break;
case OTCHAN:
ok |= Etype;
l = typecheck(&n->left, Etype);
if(l->type == T)
goto error;
t = typ(TCHAN);
t->type = l->type;
t->chan = n->etype;
n->op = OTYPE;
n->type = t;
n->left = N;
n->etype = 0;
break;
case OTSTRUCT:
ok |= Etype;
n->op = OTYPE;
n->type = dostruct(n->list, TSTRUCT);
if(n->type == T)
goto error;
n->list = nil;
break;
case OTINTER:
ok |= Etype;
n->op = OTYPE;
n->type = dostruct(n->list, TINTER);
if(n->type == T)
goto error;
n->type = sortinter(n->type);
break;
case OTFUNC:
ok |= Etype;
n->op = OTYPE;
n->type = functype(n->left, n->list, n->rlist);
if(n->type == T)
goto error;
break;
/*
* type or expr
*/
case OIND:
l = typecheck(&n->left, top | Etype);
if((t = l->type) == T)
goto error;
if(l->op == OTYPE) {
ok |= Etype;
n->op = OTYPE;
n->type = ptrto(l->type);
n->left = N;
goto ret;
}
if(!isptr[t->etype]) {
yyerror("invalid indirect %#N (non-pointer type %T)", n, t);
goto error;
}
n->type = t->type;
goto ret;
/*
* arithmetic exprs
*/
case OASOP:
ok |= Etop;
l = typecheck(&n->left, Elv);
r = typecheck(&n->right, Erv);
if(l->type == T || r->type == T)
goto error;
op = n->etype;
goto arith;
case OADD:
case OAND:
case OANDAND:
case OANDNOT:
case ODIV:
case OEQ:
case OGE:
case OGT:
case OLE:
case OLT:
case OLSH:
case ORSH:
case OMOD:
case OMUL:
case ONE:
case OOR:
case OOROR:
case OSUB:
case OXOR:
ok |= Erv;
l = typecheck(&n->left, Erv);
r = typecheck(&n->right, Erv);
if(l->type == T || r->type == T)
goto error;
op = n->op;
arith:
if(op == OLSH || op == ORSH)
goto shift;
// ideal mixed with non-ideal
defaultlit2(&l, &r, 0);
n->left = l;
n->right = r;
t = l->type;
if(t->etype == TIDEAL)
t = r->type;
et = t->etype;
if(et == TIDEAL)
et = TINT;
if(t->etype != TIDEAL && !eqtype(l->type, r->type)) {
badbinary:
yyerror("invalid operation: %#N (type %T %#O %T)", n, l->type, op, r->type);
goto error;
}
if(!okfor[op][et])
goto badbinary;
// okfor allows any array == array;
// restrict to slice == nil and nil == slice.
if(l->type->etype == TARRAY && !isslice(l->type))
goto badbinary;
if(r->type->etype == TARRAY && !isslice(r->type))
goto badbinary;
if(isslice(l->type) && !isnil(l) && !isnil(r))
goto badbinary;
t = l->type;
if(iscmp[n->op])
t = types[TBOOL];
n->type = t;
goto ret;
shift:
defaultlit(&r, types[TUINT]);
n->right = r;
t = r->type;
if(!isint[t->etype] || issigned[t->etype]) {
yyerror("invalid operation: %#N (shift count type %T)", n, r->type);
goto error;
}
// no defaultlit for left
// the outer context gives the type
n->type = l->type;
goto ret;
case OCOM:
case OMINUS:
case ONOT:
case OPLUS:
ok |= Erv;
l = typecheck(&n->left, Erv);
if((t = l->type) == T)
goto error;
if(!okfor[n->op][t->etype]) {
yyerror("invalid operation: %#O %T", n->op, t);
goto error;
}
n->type = t;
goto ret;
/*
* exprs
*/
case OADDR:
l = typecheck(&n->left, Elv);
if((t = l->type) == T)
goto error;
n->type = ptrto(t);
goto ret;
case OCOMPOS:
l = typecheck(&n->right /* sic */, Etype /* TODO | Edotarray */);
if((t = l->type) == T)
goto error;
nerr = nerrors;
switch(t->etype) {
case TARRAY:
len = 0;
i = 0;
for(ll=n->list; ll; ll=ll->next) {
l = ll->n;
if(l->op == OKEY) {
typecheck(&l->left, Erv);
evconst(l->left);
i = nonnegconst(l->left);
typecheck(&l->right, Erv);
defaultlit(&l->right, t->type);
// TODO more forceful conversion of l->right
} else {
typecheck(&ll->n, Erv);
defaultlit(&ll->n, t->type);
// TODO more forceful conversion
}
i++;
if(i > len) {
len = i;
if(t->bound >= 0 && len > t->bound) {
setlineno(l);
yyerror("array index out of bounds");
t->bound = -1; // no more errors
}
}
}
if(t->bound == -100)
t->bound = len;
break;
case TMAP:
for(ll=n->list; ll; ll=ll->next) {
l = ll->n;
if(l->op != OKEY) {
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);
// TODO more forceful
}
break;
case TSTRUCT:
// fatal("compos %T", t);
;
}
if(nerr != nerrors)
goto error;
n->type = t;
goto ret;
case ODOT:
l = typecheck(&n->left, Erv);
if((t = l->type) == T)
goto error;
if(n->right->op != ONAME) {
yyerror("rhs of . must be a name"); // impossible
goto error;
}
if(isptr[t->etype]) {
t = t->type;
if(t == T)
goto error;
n->op = ODOTPTR;
}
if(!lookdot(n, t)) {
yyerror("%#N undefined (%S in type %T)", n, n->right->sym, t);
goto error;
}
switch(n->op) {
case ODOTINTER:
case ODOTMETH:
ok |= Ecall;
break;
default:
ok |= Erv;
// TODO ok |= Elv sometimes
break;
}
goto ret;
case ODOTTYPE:
typecheck(&n->left, Erv);
defaultlit(&n->left, T);
l = n->left;
if((t = l->type) == T)
goto error;
if(!isinter(t)) {
yyerror("invalid type assertion: %#N (non-interface type %T on left)", n, t);
goto error;
}
if(n->right != N) {
typecheck(&n->right, Etype);
n->type = n->right->type;
n->right = N;
if(n->type == T)
goto error;
}
goto ret;
case OINDEX:
typecheck(&n->left, Erv);
defaultlit(&n->left, T);
implicitstar(&n->left);
l = n->left;
typecheck(&n->right, Erv);
r = n->right;
if((t = l->type) == T || r->type == T)
goto error;
switch(t->etype) {
default:
yyerror("invalid operation: %#N (index of type %T)", n, t);
goto error;
case TARRAY:
ok |= Erv | Elv;
defaultlit(&n->right, types[TUINT]);
n->type = t->type;
break;
case TMAP:
ok |= Erv | Elv;
defaultlit(&n->right, t->down);
n->type = t->type;
break;
case TSTRING:
ok |= Erv;
defaultlit(&n->right, types[TUINT]);
n->type = types[TUINT8];
break;
}
goto ret;
case ORECV:
typecheck(&n->left, Erv);
defaultlit(&n->left, T);
l = n->left;
if((t = l->type) == T)
goto error;
if(t->etype != TCHAN) {
yyerror("invalid operation: %#N (recv from non-chan type %T)", n, t);
goto error;
}
if(!(t->chan & Crecv)) {
yyerror("invalid operation: %#N (recv from send-only type %T)", n, t);
goto error;
}
n->type = t->type;
ok |= Erv;
goto ret;
case OSEND:
l = typecheck(&n->left, Erv);
typecheck(&n->right, Erv);
defaultlit(&n->left, T);
l = n->left;
if((t = l->type) == T)
goto error;
if(!(t->chan & Csend)) {
yyerror("invalid operation: %#N (send to recv-only type %T)", n, t);
goto error;
}
defaultlit(&n->right, t->type);
r = n->right;
if((t = r->type) == T)
goto error;
// TODO: more aggressive
ok |= Etop | Erv;
n->type = types[TBOOL];
goto ret;
case OSLICE:
ok |= Erv;
typecheck(&n->left, top);
typecheck(&n->right->left, Erv);
typecheck(&n->right->right, Erv);
defaultlit(&n->left, T);
defaultlit(&n->right->left, types[TUINT]);
defaultlit(&n->right->right, types[TUINT]);
implicitstar(&n->left);
if(n->right->left == N || n->right->right == N) {
yyerror("missing slice bounds?");
goto error;
}
if((t = n->right->left->type) == T)
goto error;
if(!isint[t->etype]) {
yyerror("invalid array index %#N (type %T)", n->right->left, t);
goto error;
}
if((t = n->right->right->type) == T)
goto error;
if(!isint[t->etype]) {
yyerror("invalid array index %#N (type %T)", n->right->right, t);
goto error;
}
l = n->left;
if((t = l->type) == T)
goto error;
// TODO(rsc): 64-bit slice index needs to be checked
// for overflow in generated code
switch(t->etype) {
default:
yyerror("invalid operation: %#N (slice of type %T)", n, t);
goto error;
case TARRAY:
ok |= Elv;
n = arrayop(n, Erv);
break;
case TSTRING:
n = stringop(n, Erv, nil);
break;
}
goto ret;
/*
* call and call like
*/
case OCALL:
l = n->left;
if(l->op == ONAME && l->etype != 0) {
// builtin: OLEN, OCAP, etc.
n->op = l->etype;
n->left = n->right;
n->right = N;
goto reswitch;
}
l = typecheck(&n->left, Erv | Etype | Ecall);
typechecklist(n->list, Erv);
if((t = l->type) == T)
{
yyerror("skip %#N", n);
goto error;
}
if(l->op == OTYPE) {
ok |= Erv;
// turn CALL(type, arg) into CONV(arg) w/ type
n->left = N;
if(onearg(n) < 0)
goto error;
n->op = OCONV;
n->type = l->type;
goto doconv;
}
// TODO: check args
if(t->outtuple == 0) {
ok |= Etop;
goto ret;
}
if(t->outtuple == 1) {
ok |= Erv;
t = getoutargx(l->type)->type;
if(t->etype == TFIELD)
t = t->type;
n->type = t;
goto ret;
}
// multiple return
// ok |= Emulti;
n->type = getoutargx(l->type);
goto ret;
case OCAP:
case OLEN:
if(onearg(n) < 0)
goto error;
typecheck(&n->left, Erv);
defaultlit(&n->left, T);
implicitstar(&n->left);
l = n->left;
if((t = l->type) == T)
goto error;
switch(n->op) {
case OCAP:
if(!okforcap[t->etype])
goto badcall1;
break;
case OLEN:
if(!okforlen[t->etype])
goto badcall1;
break;
}
// might be constant
switch(t->etype) {
case TSTRING:
if(isconst(l, CTSTR))
nodconst(n, types[TINT], l->val.u.sval->len);
break;
case TARRAY:
if(t->bound >= 0)
nodconst(n, types[TINT], t->bound);
break;
}
n->type = types[TINT];
goto ret;
case OCLOSED:
ok |= Erv;
case OCLOSE:
ok |= Etop;
if(onearg(n) < 0)
goto error;
typecheck(&n->left, Erv);
defaultlit(&n->left, T);
l = n->left;
if((t = l->type) == T)
goto error;
if(t->etype != TCHAN) {
yyerror("invalid operation: %#N (non-chan type %T)", n, t);
goto error;
}
goto ret;
case OCONV:
doconv:
typecheck(&n->left, Erv);
defaultlit(&n->left, n->type);
if((t = n->left->type) == T)
goto error;
switch(convert(&n->left, n->type, 1)) {
case -1:
goto error;
case 0:
n = n->left;
break;
case OCONV:
break;
}
goto ret;
case OMAKE:
args = n->list;
if(args == nil) {
yyerror("missing argument to make");
goto error;
}
l = args->n;
args = args->next;
typecheck(&l, Etype);
if((t = l->type) == T)
goto error;
switch(t->etype) {
default:
badmake:
yyerror("cannot make type %T", t);
goto error;
case TARRAY:
if(!isslice(t))
goto badmake;
if(args == nil) {
yyerror("missing len argument to make(%T)", t);
goto error;
}
l = args->n;
args = args->next;
typecheck(&l, Erv);
defaultlit(&l, types[TUINT]);
r = N;
if(args != nil) {
r = args->n;
args = args->next;
typecheck(&r, Erv);
defaultlit(&r, types[TUINT]);
}
if(l->type == T || (r && r->type == T))
goto error;
if(!isint[l->type->etype]) {
yyerror("non-integer len argument to make(%T)", t);
goto error;
}
if(r && !isint[r->type->etype]) {
yyerror("non-integer cap argument to make(%T)", t);
goto error;
}
n->left = l;
n->right = r;
break;
case TMAP:
if(args != nil) {
l = args->n;
args = args->next;
typecheck(&l, Erv);
defaultlit(&l, types[TUINT]);
if(l->type == T)
goto error;
if(!isint[l->type->etype]) {
yyerror("non-integer size argument to make(%T)", t);
goto error;
}
n->left = l;
}
break;
case TCHAN:
l = N;
if(args != nil) {
l = args->n;
args = args->next;
typecheck(&l, Erv);
defaultlit(&l, types[TUINT]);
if(l->type == T)
goto error;
if(!isint[l->type->etype]) {
yyerror("non-integer buffer argument to make(%T)", t);
goto error;
}
n->left = l;
}
break;
}
if(args != nil) {
yyerror("too many arguments to make(%T)", t);
goto error;
}
n->type = t;
goto ret;
case ONEW:
args = n->list;
if(args == nil) {
yyerror("missing argument to new");
goto error;
}
l = args->n;
typecheck(&l, Etype);
if((t = l->type) == T)
goto error;
if(args->next != nil) {
yyerror("too many arguments to new(%T)", t);
goto error;
}
n->left = l;
n->type = ptrto(t);
goto ret;
case OPANIC:
case OPANICN:
case OPRINT:
case OPRINTN:
typechecklist(n->list, Erv);
goto ret;
/*
* statements
*/
case OAS:
typecheck(&n->left, Elv);
typecheck(&n->right, Erv);
goto ret;
case OAS2:
typechecklist(n->list, Elv);
typechecklist(n->rlist, Erv);
goto ret;
case OBREAK:
case OCONTINUE:
case ODCL:
case OEMPTY:
case OGOTO:
case OLABEL:
case OXFALL:
goto ret;
case ODEFER:
case OPROC:
typecheck(&n->left, Etop);
goto ret;
case OFOR:
typechecklist(n->ninit, Etop);
typecheck(&n->ntest, Erv); // TODO Ebool
typecheck(&n->nincr, Etop);
typechecklist(n->nbody, Etop);
goto ret;
case OIF:
typechecklist(n->ninit, Etop);
typecheck(&n->ntest, Erv); // TODO Ebool
typechecklist(n->nbody, Etop);
typechecklist(n->nelse, Etop);
goto ret;
case ORETURN:
typechecklist(n->list, Erv);
// TODO convert
goto ret;
case OSELECT:
typechecklist(n->ninit, Etop);
typecheck(&n->ntest, Erv);
typechecklist(n->list, Etop);
goto ret;
case OSWITCH:
typechecklist(n->ninit, Etop);
typecheck(&n->ntest, Erv);
typechecklist(n->list, Etop);
goto ret;
case OTYPECASE:
typecheck(&n->left, Elv);
goto ret;
case OTYPESW:
typecheck(&n->right, Erv);
goto ret;
case OXCASE:
typechecklist(n->list, Erv);
typechecklist(n->nbody, Etop);
goto ret;
}
ret:
evconst(n);
if(n->op == OTYPE && !(top & Etype)) {
yyerror("type %T is not an expression", n->type);
goto error;
}
if((top & (Elv|Erv|Etype)) == Etype && n->op != OTYPE) {
yyerror("%O is not a type", n->op);
goto error;
}
if((ok & Ecall) && !(top & Ecall)) {
yyerror("must call method %#N", n);
goto error;
}
/* TODO
if(n->type == T)
fatal("typecheck nil type");
*/
goto out;
badcall1:
yyerror("invalid argument %#N (type %T) for %#O", n->left, n->left->type, n->op);
goto error;
error:
n->type = T;
out:
lineno = lno;
n->typecheck = 1;
*np = n;
return n;
}
static void
implicitstar(Node **nn)
{
Type *t;
Node *n;
// insert implicit * if needed
n = *nn;
t = n->type;
if(t == T || !isptr[t->etype])
return;
t = t->type;
if(t == T)
return;
if(!isfixedarray(t))
return;
n = nod(OIND, n, N);
typecheck(&n, Erv);
*nn = n;
}
static int
onearg(Node *n)
{
if(n->left != N)
return 0;
if(n->list == nil) {
yyerror("missing argument to %#O - %#N", n->op, n);
return -1;
}
n->left = n->list->n;
if(n->list->next != nil) {
yyerror("too many arguments to %#O", n->op);
n->list = nil;
return -1;
}
n->list = nil;
return 0;
}
static Type*
lookdot1(Sym *s, Type *t, Type *f)
{
Type *r;
r = T;
for(; f!=T; f=f->down) {
if(f->sym != s)
continue;
if(r != T) {
yyerror("ambiguous DOT reference %T.%S", t, s);
break;
}
r = f;
}
return r;
}
static int
lookdot(Node *n, Type *t)
{
Type *f1, *f2, *tt, *rcvr;
Sym *s;
s = n->right->sym;
f1 = T;
if(t->etype == TSTRUCT || t->etype == TINTER)
f1 = lookdot1(s, t, t->type);
f2 = methtype(n->left->type);
if(f2 != T)
f2 = lookdot1(s, f2, f2->method);
if(f1 != T) {
if(f2 != T)
yyerror("ambiguous DOT reference %S as both field and method",
n->right->sym);
n->xoffset = f1->width;
n->type = f1->type;
if(t->etype == TINTER) {
if(isptr[n->left->type->etype]) {
n->left = nod(OIND, n->left, N); // implicitstar
typecheck(&n->left, Elv);
}
n->op = ODOTINTER;
}
return 1;
}
if(f2 != T) {
tt = n->left->type;
rcvr = getthisx(f2->type)->type->type;
if(!eqtype(rcvr, tt)) {
if(rcvr->etype == tptr && eqtype(rcvr->type, tt)) {
typecheck(&n->left, Elv);
addrescapes(n->left);
n->left = nod(OADDR, n->left, N);
typecheck(&n->left, Erv);
} else if(tt->etype == tptr && eqtype(tt->type, rcvr)) {
n->left = nod(OIND, n->left, N);
typecheck(&n->left, Erv);
} else {
// method is attached to wrong type?
fatal("method mismatch: %T for %T", rcvr, tt);
}
}
n->right = methodname(n->right, n->left->type);
n->xoffset = f2->width;
n->type = f2->type;
n->op = ODOTMETH;
return 1;
}
return 0;
}
/*
* try to convert *np to t.
* explicit means conversion like int64(n).
* not explicit means assignment, return, or function call parameter.
* return -1 for failure, 0 if OCONV node not needed, 1 if OCONV is needed.
*/
static int
convert(Node **np, Type *t, int explicit)
{
int et;
Node *n, *n1;
Type *tt;
n = *np;
if(n->type == t)
return 0;
if(eqtype(n->type, t))
return OCONV;
// XXX wtf?
convlit1(&n, t, explicit);
if(n->type == T)
return -1;
// no-op conversion
if(cvttype(t, n->type) == 1) {
nop:
if(n->op == OLITERAL) {
// can convert literal in place
n1 = nod(OXXX, N, N);
*n1 = *n;
n1->type = t;
*np = n1;
return 0;
}
return OCONV;
}
if(!explicit) {
yyerror("cannot use %#N (type %T) as type %T", n, n->type, t);
return -1;
}
// simple fix-float
if(isint[n->type->etype] || isfloat[n->type->etype])
if(isint[t->etype] || isfloat[t->etype]) {
// evconst(n); // XXX is this needed?
return OCONV;
}
// to/from interface.
// ifaceas1 will generate a good error if the conversion fails.
if(t->etype == TINTER || n->type->etype == TINTER) {
n = ifacecvt(t, n, ifaceas1(t, n->type, 0));
n->type = t;
*np = n;
return 0;
}
// to string
if(istype(t, TSTRING)) {
// integer rune
et = n->type->etype;
if(isint[et]) {
// xxx;
return OCONVRUNE;
}
// []byte and *[10]byte -> string
tt = T;
if(isptr[et] && isfixedarray(n->type->type))
tt = n->type->type->type;
else if(isslice(n->type))
tt = n->type->type;
if(tt) {
if(tt->etype == TUINT8)
return OCONVSTRB;
if(tt->etype == TINT)
return OCONVSTRI;
}
}
// convert static array to slice
if(isslice(t) && isptr[n->type->etype] && isfixedarray(n->type->type)
&& eqtype(t->type, n->type->type->type))
return OCONVA2S;
// convert to unsafe pointer
if(isptrto(t, TANY)
&& (isptr[n->type->etype] || n->type->etype == TUINTPTR))
return OCONV;
// convert from unsafe pointer
if(isptrto(n->type, TANY)
&& (isptr[t->etype] || t->etype == TUINTPTR))
return OCONV;
yyerror("cannot convert %#N (type %T) to type %T", n, n->type, t);
return -1;
}
......@@ -81,6 +81,7 @@ walk(Node *fn)
if(curfn->type->outtuple)
if(walkret(curfn->nbody))
yyerror("function ends without a return statement");
typechecklist(curfn->nbody, Etop);
walkstmtlist(curfn->nbody);
if(debug['W']) {
snprint(s, sizeof(s), "after walk %S", curfn->nname->sym);
......@@ -98,7 +99,7 @@ gettype(Node **np, NodeList **init)
{
if(debug['W'])
dump("\nbefore gettype", *np);
walkexpr(np, Erv, init);
typecheck(np, Erv);
if(debug['W'])
dump("after gettype", *np);
}
......@@ -145,7 +146,7 @@ walkdef(Node *n)
switch(n->op) {
case OLITERAL:
if(n->ntype != N) {
walkexpr(&n->ntype, Etype, &init);
typecheck(&n->ntype, Etype);
n->type = n->ntype->type;
n->ntype = N;
if(n->type == T) {
......@@ -160,7 +161,7 @@ walkdef(Node *n)
dump("walkdef nil defn", n);
yyerror("xxx");
}
walkexpr(&e, Erv, &init);
typecheck(&e, Erv);
if(e->op != OLITERAL) {
yyerror("const initializer must be constant");
goto ret;
......@@ -217,6 +218,7 @@ walkstmt(Node **np)
case OCALLMETH:
case OCALLINTER:
case OCALL:
case OCALLFUNC:
case OSEND:
case ORECV:
case OPRINT:
......@@ -299,319 +301,6 @@ walkstmt(Node **np)
*np = n;
}
void
implicitstar(Node **nn)
{
Type *t;
Node *n;
// insert implicit * if needed
n = *nn;
t = n->type;
if(t == T || !isptr[t->etype])
return;
t = t->type;
if(t == T)
return;
if(!isfixedarray(t))
return;
n = nod(OIND, n, N);
walkexpr(&n, Elv, nil);
*nn = n;
}
void
typechecklist(NodeList *l, int top)
{
for(; l; l=l->next)
typecheck(&l->n, top);
}
/*
* type check the whole tree of an expression.
* calculates expression types.
* evaluates compile time constants.
* marks variables that escape the local frame.
* rewrites n->op to be more specific in some cases.
* replaces *np with a new pointer in some cases.
* returns the final value of *np as a convenience.
*/
Node*
typecheck(Node **np, int top)
{
int et, et1, et2;
Node *n, *l, *r;
int lno, ok;
Type *t;
n = *np;
if(n == N || n->typecheck == 1)
return n;
if(n->typecheck == 2)
fatal("typecheck loop");
n->typecheck = 2;
if(n->sym && n->walkdef != 1)
walkdef(n);
lno = setlineno(n);
ok = 0;
switch(n->op) {
default:
// until typecheck is complete, do nothing.
goto ret;
dump("typecheck", n);
fatal("typecheck %O", n->op);
/*
* names
*/
case OLITERAL:
ok |= Erv;
goto ret;
case ONONAME:
ok |= Elv | Erv;
goto ret;
case ONAME:
if(n->etype != 0) {
yyerror("must call builtin %S", n->sym);
goto error;
}
ok |= Erv;
if(n->class != PFUNC)
ok |= Elv;
goto ret;
/*
* types (OIND is with exprs)
*/
case OTYPE:
ok |= Etype;
if(n->type == T)
goto error;
break;
case OTARRAY:
ok |= Etype;
t = typ(TARRAY);
l = n->left;
r = n->right;
if(l == nil) {
t->bound = -1;
} else {
typecheck(&l, Erv | Etype);
walkexpr(&l, Erv | Etype, &n->ninit); // TODO: remove
switch(l->op) {
default:
yyerror("invalid array bound %O", l->op);
goto error;
case OLITERAL:
if(consttype(l) == CTINT) {
t->bound = mpgetfix(l->val.u.xval);
if(t->bound < 0) {
yyerror("array bound must be non-negative");
goto error;
}
}
break;
case OTYPE:
if(l->type == T)
goto error;
if(l->type->etype != TDDD) {
yyerror("invalid array bound %T", l->type);
goto error;
}
t->bound = -100;
break;
}
}
typecheck(&r, Etype);
if(r->type == T)
goto error;
t->type = r->type;
n->op = OTYPE;
n->type = t;
n->left = N;
n->right = N;
checkwidth(t);
break;
case OTMAP:
ok |= Etype;
l = typecheck(&n->left, Etype);
r = typecheck(&n->right, Etype);
if(l->type == T || r->type == T)
goto error;
n->op = OTYPE;
n->type = maptype(l->type, r->type);
n->left = N;
n->right = N;
break;
case OTCHAN:
ok |= Etype;
l = typecheck(&n->left, Etype);
if(l->type == T)
goto error;
t = typ(TCHAN);
t->type = l->type;
t->chan = n->etype;
n->op = OTYPE;
n->type = t;
n->left = N;
n->etype = 0;
break;
case OTSTRUCT:
ok |= Etype;
n->op = OTYPE;
n->type = dostruct(n->list, TSTRUCT);
if(n->type == T)
goto error;
n->list = nil;
break;
case OTINTER:
ok |= Etype;
n->op = OTYPE;
n->type = dostruct(n->list, TINTER);
if(n->type == T)
goto error;
n->type = sortinter(n->type);
break;
case OTFUNC:
ok |= Etype;
n->op = OTYPE;
n->type = functype(n->left, n->list, n->rlist);
if(n->type == T)
goto error;
break;
/*
* exprs
*/
case OADD:
case OAND:
case OANDAND:
case OANDNOT:
case ODIV:
case OEQ:
case OGE:
case OGT:
case OLE:
case OLT:
case OMOD:
case OMUL:
case ONE:
case OOR:
case OOROR:
case OSUB:
case OXOR:
ok |= Erv;
l = typecheck(&n->left, Erv | Eideal);
r = typecheck(&n->right, Erv | Eideal);
if(l->type == T || r->type == T)
goto error;
et1 = l->type->etype;
et2 = r->type->etype;
if(et1 == TIDEAL || et1 == TNIL || et2 == TIDEAL || et2 == TNIL)
if(et1 != TIDEAL && et1 != TNIL || et2 != TIDEAL && et2 != TNIL) {
// ideal mixed with non-ideal
defaultlit2(&l, &r);
n->left = l;
n->right = r;
}
t = l->type;
if(t->etype == TIDEAL)
t = r->type;
et = t->etype;
if(et == TIDEAL)
et = TINT;
if(t->etype != TIDEAL && !eqtype(l->type, r->type)) {
badbinary:
yyerror("invalid operation: %#N", n);
goto error;
}
if(!okfor[n->op][et])
goto badbinary;
// okfor allows any array == array;
// restrict to slice == nil and nil == slice.
if(l->type->etype == TARRAY && !isslice(l->type))
goto badbinary;
if(r->type->etype == TARRAY && !isslice(r->type))
goto badbinary;
if(isslice(l->type) && !isnil(l) && !isnil(r))
goto badbinary;
evconst(n);
goto ret;
case OCOM:
case OMINUS:
case ONOT:
case OPLUS:
ok |= Erv;
l = typecheck(&n->left, Erv | Eideal);
walkexpr(&n->left, Erv | Eideal, &n->ninit); // TODO: remove
if((t = l->type) == T)
goto error;
if(!okfor[n->op][t->etype]) {
yyerror("invalid operation: %#O %T", n->op, t);
goto error;
}
n->type = t;
goto ret;
/*
* type or expr
*/
case OIND:
typecheck(&n->left, top | Etype);
if(n->left->op == OTYPE) {
ok |= Etype;
n->op = OTYPE;
n->type = ptrto(n->left->type);
n->left = N;
goto ret;
}
// TODO: OIND expression type checking
goto ret;
}
ret:
evconst(n);
if(n->op == OTYPE && !(top & Etype)) {
yyerror("type %T is not an expression", n->type);
goto error;
}
if((top & (Elv|Erv|Etype)) == Etype && n->op != OTYPE) {
yyerror("%O is not a type", n->op);
goto error;
}
/* TODO
if(n->type == T)
fatal("typecheck nil type");
*/
goto out;
error:
n->type = T;
out:
lineno = lno;
n->typecheck = 1;
*np = n;
return n;
}
/*
* walk the whole tree of the body of an
......@@ -651,8 +340,10 @@ walkexpr(Node **np, int top, NodeList **init)
if(debug['w'] > 1 && top == Etop)
dump("walk-before", n);
if(n->typecheck != 1)
typecheck(&n, top | typeok);
if(n->typecheck != 1) {
dump("missed typecheck", n);
fatal("missed typecheck");
}
reswitch:
t = T;
......@@ -738,13 +429,13 @@ reswitch:
case OCALLMETH:
case OCALLINTER:
case OCALLFUNC:
goto ret;
case OCALL:
if(top == Elv)
goto nottop;
if(n->type != T)
goto ret;
if(n->left == N)
goto ret;
......@@ -752,22 +443,24 @@ reswitch:
// builtin OLEN, OCAP, etc.
n->op = n->left->etype;
n->left = N;
//dump("do", n);
goto reswitch;
}
walkexpr(&n->left, Erv | Etype, init);
walkexpr(&n->left, Erv | Etype | Ecall, init);
defaultlit(&n->left, T);
t = n->left->type;
if(t == T)
goto ret;
if(n->left->op == ODOTMETH)
switch(n->left->op) {
case ODOTMETH:
n->op = OCALLMETH;
if(n->left->op == ODOTINTER)
break;
case ODOTINTER:
n->op = OCALLINTER;
if(n->left->op == OTYPE) {
break;
case OTYPE:
n->op = OCONV;
if(!(top & Erv))
goto nottop;
......@@ -784,6 +477,9 @@ reswitch:
n->left = n->list->n;
n->list = nil;
goto reswitch;
default:
n->op = OCALLFUNC;
break;
}
if(t->etype != TFUNC) {
......@@ -818,7 +514,7 @@ reswitch:
n->list = reorder1(ll);
break;
case OCALL:
case OCALLFUNC:
ll = ascompatte(n->op, getinarg(t), n->list, 0, init);
n->list = reorder1(ll);
if(isselect(n)) {
......@@ -886,6 +582,7 @@ reswitch:
switch(r->op) {
case OCALLMETH:
case OCALLINTER:
case OCALLFUNC:
case OCALL:
if(cr == 1) {
// a,b,... = fn()
......@@ -902,7 +599,6 @@ reswitch:
if(cl == 2 && cr == 1) {
// a,b = map[] - mapaccess2
walkexpr(&r->left, Erv, init);
implicitstar(&r->left);
if(!istype(r->left->type, TMAP))
break;
l = mapop(n, top, init);
......@@ -938,9 +634,11 @@ reswitch:
case I2Isame:
case E2Esame:
n->rlist = list(list1(r->left), nodbool(1));
typechecklist(n->rlist, Erv);
goto multias;
case I2E:
n->list = list(list1(n->right), nodbool(1));
typechecklist(n->rlist, Erv);
goto multias;
case I2T:
et = I2T2;
......@@ -1109,7 +807,7 @@ reswitch:
evconst(n);
if(n->op == OLITERAL)
goto ret;
defaultlit2(&n->left, &n->right);
defaultlit2(&n->left, &n->right, iscmp[n->op]);
if(n->left->type == T || n->right->type == T)
goto ret;
if(!eqtype(n->left->type, n->right->type))
......@@ -1176,7 +874,6 @@ reswitch:
}
walkexpr(&n->left, Erv, init);
defaultlit(&n->left, T);
implicitstar(&n->left);
t = n->left->type;
if(t == T)
goto ret;
......@@ -1211,7 +908,6 @@ reswitch:
}
walkexpr(&n->left, Erv, init);
defaultlit(&n->left, T);
implicitstar(&n->left);
t = n->left->type;
if(t == T)
goto ret;
......@@ -1237,7 +933,6 @@ reswitch:
goto ret;
defaultlit(&n->left, T);
implicitstar(&n->left);
t = n->left->type;
if(t == T)
......@@ -1331,7 +1026,6 @@ reswitch:
defaultlit(&n->left, T);
defaultlit(&n->right->left, types[TUINT]);
defaultlit(&n->right->right, types[TUINT]);
implicitstar(&n->left);
t = n->left->type;
if(t == T)
goto ret;
......@@ -1350,10 +1044,7 @@ reswitch:
case ODOTPTR:
case ODOTMETH:
case ODOTINTER:
if(top == Etop)
goto nottop;
defaultlit(&n->left, T);
walkdot(n, init);
walkexpr(&n->left, Erv, init);
goto ret;
case OADDR:
......@@ -1378,6 +1069,7 @@ reswitch:
tempname(nvar, ptrto(n->left->type));
nas = nod(OAS, nvar, callnew(n->left->type));
typecheck(&nas, Etop);
walkexpr(&nas, Etop, init);
*init = list(*init, nas);
......@@ -1540,6 +1232,7 @@ reswitch:
// TODO(rsc): Can do this more efficiently,
// but OSUB is wrong. Should be in back end anyway.
n = nod(OMUL, n->left, nodintconst(-1));
typecheck(&n, Erv);
walkexpr(&n, Erv, init);
goto ret;
}
......@@ -1588,6 +1281,7 @@ reswitch:
r->list = list(list1(n->left), n->right);
r = nod(OCONV, r, N);
r->type = n->left->left->type;
typecheck(&r, Erv);
walkexpr(&r, Erv, init);
n = r;
goto ret;
......@@ -1598,6 +1292,7 @@ reswitch:
break;
l = saferef(n->left, init);
r = nod(OAS, l, nod(n->etype, l, n->right));
typecheck(&r, Etop);
walkexpr(&r, Etop, init);
n = r;
goto ret;
......@@ -1612,7 +1307,7 @@ nottop:
if(n->diag)
goto ret;
n->diag = 1;
switch((top | typeok) & ~Eideal) {
switch(top | typeok) {
default:
yyerror("didn't expect %O here [top=%d]", n->op, top);
break;
......@@ -1718,6 +1413,7 @@ walkconv(Node **np, NodeList **init)
t = n->type;
if(t == T)
return;
typecheck(&n->left, Erv);
walkexpr(&n->left, Erv, init);
l = n->left;
if(l == N)
......@@ -2075,7 +1771,9 @@ walkselect(Node *sel)
tempname(on, l->left->type);
on->sym = lookup("!tmpselect!");
r->left = on;
nbod = list(n->ninit, nod(OAS, l->left, on));
on = nod(OAS, l->left, on);
typecheck(&on, Etop);
nbod = list(n->ninit, on);
n->ninit = nil;
}
break;
......@@ -2112,6 +1810,8 @@ walkselect(Node *sel)
r = nod(OCALL, on, N);
r->list = args;
r = nod(OAS, var, r);
typecheck(&r, Etop);
typechecklist(res, Etop);
sel->ninit = list1(r);
sel->nbody = res;
......@@ -2125,128 +1825,6 @@ walkselect(Node *sel)
lineno = lno;
}
Type*
lookdot1(Sym *s, Type *t, Type *f)
{
Type *r;
r = T;
for(; f!=T; f=f->down) {
if(f->sym != s)
continue;
if(r != T) {
yyerror("ambiguous DOT reference %T.%S", t, s);
break;
}
r = f;
}
return r;
}
int
lookdot(Node *n, Type *t)
{
Type *f1, *f2, *tt, *rcvr;
Sym *s;
s = n->right->sym;
f1 = T;
if(t->etype == TSTRUCT || t->etype == TINTER)
f1 = lookdot1(s, t, t->type);
f2 = methtype(n->left->type);
if(f2 != T)
f2 = lookdot1(s, f2, f2->method);
if(f1 != T) {
if(f2 != T)
yyerror("ambiguous DOT reference %S as both field and method",
n->right->sym);
n->xoffset = f1->width;
n->type = f1->type;
if(t->etype == TINTER) {
if(isptr[n->left->type->etype]) {
n->left = nod(OIND, n->left, N); // implicitstar
walkexpr(&n->left, Elv, nil);
}
n->op = ODOTINTER;
}
return 1;
}
if(f2 != T) {
tt = n->left->type;
rcvr = getthisx(f2->type)->type->type;
if(!eqtype(rcvr, tt)) {
if(rcvr->etype == tptr && eqtype(rcvr->type, tt)) {
walkexpr(&n->left, Elv, nil);
addrescapes(n->left);
n->left = nod(OADDR, n->left, N);
n->left->type = ptrto(tt);
} else if(tt->etype == tptr && eqtype(tt->type, rcvr)) {
n->left = nod(OIND, n->left, N);
n->left->type = tt->type;
} else {
// method is attached to wrong type?
fatal("method mismatch: %T for %T", rcvr, tt);
}
}
n->right = methodname(n->right, n->left->type);
n->xoffset = f2->width;
n->type = f2->type;
n->op = ODOTMETH;
return 1;
}
return 0;
}
void
walkdot(Node *n, NodeList **init)
{
Type *t;
walkexprlist(n->ninit, Etop, init);
if(n->ninit != nil) {
*init = concat(*init, n->ninit);
n->ninit = nil;
}
if(n->left == N || n->right == N)
return;
switch(n->op) {
case ODOTINTER:
case ODOTMETH:
return; // already done
}
walkexpr(&n->left, Erv, init);
if(n->right->op != ONAME) {
yyerror("rhs of . must be a name");
return;
}
t = n->left->type;
if(t == T)
return;
// as a structure field or pointer to structure field
if(isptr[t->etype]) {
t = t->type;
if(t == T)
return;
n->op = ODOTPTR;
}
if(!lookdot(n, t)) {
if(!n->diag) {
n->diag = 1;
yyerror("undefined: %T field %S", n->left->type, n->right->sym);
}
}
}
Node*
ascompatee1(int op, Node *l, Node *r, NodeList **init)
{
......@@ -2451,6 +2029,7 @@ mkdotargs(NodeList *lr0, NodeList *nn, Type *l, int fp, NodeList **init)
*r->left = *var;
r->left->type = r->right->type;
r->left->xoffset += t->width;
typecheck(&r, Etop);
walkexpr(&r, Etop, init);
lr->n = r;
t = t->down;
......@@ -2544,7 +2123,8 @@ ascompatte(int op, Type **nl, NodeList *lr, int fp, NodeList **init)
fatal("misaligned multiple return\n\t%T\n\t%T", r->type, *nl);
a = nodarg(*nl, fp);
a->type = r->type;
return list1(convas(nod(OAS, a, r), init));
nn = list1(convas(nod(OAS, a, r), init));
goto ret;
}
loop:
......@@ -2562,13 +2142,14 @@ loop:
a = nod(OAS, nodarg(l, fp), r);
a = convas(a, init);
nn = list(nn, a);
return nn;
goto ret;
}
// normal case -- make a structure of all
// remaining arguments and pass a pointer to
// it to the ddd parameter (empty interface)
return mkdotargs(lr, nn, l, fp, init);
nn = mkdotargs(lr, nn, l, fp, init);
goto ret;
}
if(l == T || r == N) {
......@@ -2580,7 +2161,7 @@ loop:
dumptypes(nl, "expected");
dumpnodetypes(lr0, "given");
}
return nn;
goto ret;
}
convlit(&r, l->type);
if(!ascompat(l->type, r->type)) {
......@@ -2598,6 +2179,11 @@ loop:
if(lr != nil)
r = lr->n;
goto loop;
ret:
for(lr=nn; lr; lr=lr->next)
lr->n->typecheck = 1;
return nn;
}
/*
......@@ -2721,7 +2307,7 @@ prcompat(NodeList *all, int fmt, int dopanic)
}
notfirst = fmt;
walkexpr(&l->n, Erv, nil);
typecheck(&l->n, Erv);
n = l->n;
if(n->op == OLITERAL) {
switch(n->val.ctype) {
......@@ -2733,6 +2319,8 @@ prcompat(NodeList *all, int fmt, int dopanic)
break;
}
}
if(n->op != OLITERAL && n->type && n->type->etype == TIDEAL)
defaultlit(&n, types[TINT64]);
defaultlit(&n, nil);
l->n = n;
if(n->type == T)
......@@ -2786,12 +2374,14 @@ prcompat(NodeList *all, int fmt, int dopanic)
on = syslook("printnl", 0);
calls = list(calls, nod(OCALL, on, N));
}
typechecklist(calls, Etop);
walkexprlist(calls, Etop, nil);
if(dopanic)
r = nodpanic(0);
else
r = nod(OEMPTY, N, N);
typecheck(&r, Etop);
walkexpr(&r, Etop, nil);
r->ninit = calls;
return r;
......@@ -2808,6 +2398,7 @@ nodpanic(int32 lineno)
args = list1(n);
n = nod(OCALL, on, N);
n->list = args;
typecheck(&n, Etop);
walkexpr(&n, Etop, nil);
return n;
}
......@@ -2871,6 +2462,7 @@ callnew(Type *t)
args = list1(r);
r = nod(OCALL, on, N);
r->list = args;
typecheck(&r, Erv);
walkexpr(&r, Erv, nil);
return r;
}
......@@ -3002,6 +2594,7 @@ stringop(Node *n, int top, NodeList **init)
break;
}
typecheck(&r, top);
walkexpr(&r, top, init);
return r;
}
......@@ -3097,6 +2690,7 @@ mapop(Node *n, int top, NodeList **init)
r = nod(OCALL, on, N);
r->list = args;
typecheck(&r, Erv);
walkexpr(&r, top, nil);
r->type = n->type;
break;
......@@ -3131,6 +2725,7 @@ mapop(Node *n, int top, NodeList **init)
r = nod(OCALL, on, N);
r->list = args;
typecheck(&r, Erv);
walkexpr(&r, Erv, nil);
r->type = t->type;
break;
......@@ -3160,6 +2755,7 @@ mapop(Node *n, int top, NodeList **init)
r = nod(OCALL, on, N);
r->list = args;
typecheck(&r, Etop);
walkexpr(&r, Etop, init);
break;
......@@ -3197,6 +2793,7 @@ mapop(Node *n, int top, NodeList **init)
r = nod(OCALL, on, N);
r->list = args;
typecheck(&r, Etop);
walkexpr(&r, Etop, init);
break;
......@@ -3224,7 +2821,9 @@ mapop(Node *n, int top, NodeList **init)
a = nod(OCALL, on, N);
a->list = args;
typecheck(&a, Erv);
n->rlist = list1(a);
typecheck(&n, Etop);
walkexpr(&n, Etop, init);
r = n;
break;
......@@ -3239,6 +2838,7 @@ mapop(Node *n, int top, NodeList **init)
tempname(a, t->down); // tmpi
r = nod(OAS, a, n->left->right); // tmpi := index
n->left->right = a; // m[tmpi]
typecheck(&r, Etop);
walkexpr(&r, Etop, init);
*init = list(*init, r);
......@@ -3246,6 +2846,7 @@ mapop(Node *n, int top, NodeList **init)
*a = *n->left; // copy of map[tmpi]
a = nod(n->etype, a, n->right); // m[tmpi] op right
r = nod(OAS, n->left, a); // map[tmpi] = map[tmpi] op right
typecheck(&r, Etop);
walkexpr(&r, Etop, init);
break;
}
......@@ -3275,13 +2876,6 @@ chanop(Node *n, int top, NodeList **init)
fatal("chanop: unknown op %O", n->op);
case OCLOSE:
cl = count(n->list);
if(cl > 1)
yyerror("too many arguments to close");
else if(cl < 1)
yyerror("missing argument to close");
n->left = n->list->n;
// closechan(hchan *chan any);
t = fixchan(n->left->type);
if(t == T)
......@@ -3295,18 +2889,12 @@ chanop(Node *n, int top, NodeList **init)
r = nod(OCALL, on, N);
r->list = args;
typecheck(&r, Etop);
walkexpr(&r, top, nil);
r->type = n->type;
break;
case OCLOSED:
cl = count(n->list);
if(cl > 1)
yyerror("too many arguments to closed");
else if(cl < 1)
yyerror("missing argument to closed");
n->left = n->list->n;
// closedchan(hchan *chan any) bool;
t = fixchan(n->left->type);
if(t == T)
......@@ -3320,6 +2908,7 @@ chanop(Node *n, int top, NodeList **init)
r = nod(OCALL, on, N);
r->list = args;
typecheck(&r, Erv);
walkexpr(&r, top, nil);
n->type = r->type;
break;
......@@ -3353,6 +2942,7 @@ chanop(Node *n, int top, NodeList **init)
r = nod(OCALL, on, N);
r->list = args;
typecheck(&r, Erv);
walkexpr(&r, top, nil);
r->type = n->type;
break;
......@@ -3385,6 +2975,7 @@ chanop(Node *n, int top, NodeList **init)
argtype(on, t->type); // any-2
r = nod(OCALL, on, N);
r->list = args;
typecheck(&r, Etop);
n->rlist->n = r;
r = n;
walkexpr(&r, Etop, init);
......@@ -3417,6 +3008,7 @@ chanop(Node *n, int top, NodeList **init)
argtype(on, t->type); // any-2
r = nod(OCALL, on, N);
r->list = args;
typecheck(&r, Erv);
walkexpr(&r, Erv, nil);
break;
......@@ -3443,6 +3035,7 @@ chanop(Node *n, int top, NodeList **init)
argtype(on, t->type); // any-2
r = nod(OCALL, on, N);
r->list = args;
typecheck(&r, Etop);
walkexpr(&r, Etop, nil);
break;
......@@ -3458,6 +3051,7 @@ chanop(Node *n, int top, NodeList **init)
argtype(on, t->type); // any-2
r = nod(OCALL, on, N);
r->list = args;
typecheck(&r, Etop);
walkexpr(&r, Etop, nil);
break;
}
......@@ -3523,6 +3117,7 @@ arrayop(Node *n, int top)
r = nod(OCALL, on, N);
r->list = args;
n->left = r;
typecheck(&n, Erv);
walkexpr(&n, top, nil);
return n;
......@@ -3571,6 +3166,7 @@ arrayop(Node *n, int top)
argtype(on, t->type); // any-1
r = nod(OCALL, on, N);
r->list = args;
typecheck(&r, Erv);
walkexpr(&r, top, nil);
r->type = t; // if t had a name, going through newarray lost it
break;
......@@ -3621,7 +3217,7 @@ arrayop(Node *n, int top)
r = nod(OCALL, on, N);
r->list = args;
walkexpr(&r, top, nil);
typecheck(&r, Erv);
break;
}
return r;
......@@ -3770,6 +3366,7 @@ ifacecvt(Type *tl, Node *n, int et)
r = nod(OCALL, on, N);
r->list = args;
typecheck(&r, Erv);
walkexpr(&r, Erv, nil);
return r;
}
......@@ -3803,6 +3400,7 @@ ifaceop(Node *n)
r->list = args;
if(n->op == ONE)
r = nod(ONOT, r, N);
typecheck(&r, Erv);
walkexpr(&r, Erv, nil);
return r;
}
......@@ -4004,14 +3602,17 @@ colas(NodeList *ll, NodeList *lr)
nr = lr->n;
switch(nr->op) {
case OCALL:
case OCALLFUNC:
if(nr->left->op == ONAME && nr->left->etype != 0)
break;
walkexpr(&nr->left, Erv | Etype, &init);
typecheck(&nr->left, Erv | Etype | Ecall);
walkexpr(&nr->left, Erv | Etype | Ecall, &init);
if(nr->left->op == OTYPE)
break;
goto call;
case OCALLMETH:
case OCALLINTER:
typecheck(&nr->left, Erv);
walkexpr(&nr->left, Erv, &init);
call:
convlit(&nr->left, types[TFUNC]);
......@@ -4054,7 +3655,7 @@ colas(NodeList *ll, NodeList *lr)
l = savel->n;
r = saver->n;
walkexpr(&r, Erv, &init);
typecheck(&r, Erv);
defaultlit(&r, T);
saver->n = r;
a = mixedoldnew(l, r->type);
......@@ -4064,6 +3665,9 @@ colas(NodeList *ll, NodeList *lr)
goto out;
multi:
typecheck(&nr, Erv);
lr->n = nr;
/*
* there is a list on the left
* and a mono on the right.
......@@ -4080,7 +3684,6 @@ multi:
if(cl != 2)
goto badt;
walkexpr(&nr->left, Erv, &init);
implicitstar(&nr->left);
t = nr->left->type;
if(!istype(t, TMAP))
goto badt;
......@@ -4124,7 +3727,7 @@ badt:
nl = ll->n;
if(nl->diag == 0) {
nl->diag = 1;
yyerror("assignment count mismatch: %d = %d", cl, cr);
yyerror("assignment count mismatch: %d = %d %#N", cl, cr, lr->n);
}
outl:
n = ll;
......@@ -4172,8 +3775,7 @@ dorange(Node *nn)
n = nod(OFOR, N, N);
init = nil;
walkexpr(&nn->right, Erv, &init);
implicitstar(&nn->right);
typecheck(&nn->right, Erv);
m = nn->right;
local = nn->etype;
......@@ -4625,6 +4227,7 @@ structlit(Node *n, Node *var, NodeList **init)
// build list of var.field = expr
a = nod(ODOT, var, newname(l->sym));
a = nod(OAS, a, r);
typecheck(&a, Etop);
walkexpr(&a, Etop, init);
if(nerr != nerrors)
return var;
......@@ -4641,6 +4244,7 @@ structlit(Node *n, Node *var, NodeList **init)
keyval:
memset(hash, 0, sizeof(hash));
a = nod(OAS, var, N);
typecheck(&a, Etop);
walkexpr(&a, Etop, init);
*init = list(*init, a);
......@@ -4660,6 +4264,7 @@ keyval:
break;
a = nod(OAS, a, r->right);
typecheck(&a, Etop);
walkexpr(&a, Etop, init);
if(nerr != nerrors)
break;
......@@ -4741,6 +4346,7 @@ arraylit(Node *n, Node *var, NodeList **init)
a = nod(OMAKE, N, N);
a->list = list(list1(typenod(t)), nodintconst(ninit));
a = nod(OAS, var, a);
typecheck(&a, Etop);
walkexpr(&a, Etop, init);
*init = list(*init, a);
} else {
......@@ -4748,6 +4354,7 @@ arraylit(Node *n, Node *var, NodeList **init)
// then clear the array
if(ninit < b) {
a = nod(OAS, var, N);
typecheck(&a, Etop);
walkexpr(&a, Etop, init);
*init = list(*init, a);
}
......@@ -4779,6 +4386,7 @@ arraylit(Node *n, Node *var, NodeList **init)
a = nod(OINDEX, var, a);
a = nod(OAS, a, r);
typecheck(&a, Etop);
walkexpr(&a, Etop, init); // add any assignments in r to top
if(nerr != nerrors)
break;
......@@ -4866,6 +4474,7 @@ maplit(Node *n, Node *var, NodeList **init)
a = nod(OMAKE, N, N);
a->list = list1(typenod(t));
a = nod(OAS, var, a);
typecheck(&a, Etop);
walkexpr(&a, Etop, init);
*init = list(*init, a);
......@@ -4884,6 +4493,7 @@ maplit(Node *n, Node *var, NodeList **init)
a = nod(OINDEX, var, r->left);
a = nod(OAS, a, r->right);
typecheck(&a, Etop);
walkexpr(&a, Etop, init);
if(nerr != nerrors)
break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment