mirror of
https://github.com/golang/go
synced 2024-11-22 06:34:40 -07:00
introduce typecheck pass before walkexpr.
not complete but compiler still works. R=ken OCL=32424 CL=32426
This commit is contained in:
parent
056940d84b
commit
9271c6402e
@ -257,8 +257,10 @@ typeinit(void)
|
|||||||
* initialize okfor
|
* initialize okfor
|
||||||
*/
|
*/
|
||||||
for(i=0; i<NTYPE; i++) {
|
for(i=0; i<NTYPE; i++) {
|
||||||
if(isint[i]) {
|
if(isint[i] || i == TIDEAL) {
|
||||||
okforeq[i] = 1;
|
okforeq[i] = 1;
|
||||||
|
okforcmp[i] = 1;
|
||||||
|
okforarith[i] = 1;
|
||||||
okforadd[i] = 1;
|
okforadd[i] = 1;
|
||||||
okforand[i] = 1;
|
okforand[i] = 1;
|
||||||
issimple[i] = 1;
|
issimple[i] = 1;
|
||||||
@ -267,26 +269,76 @@ typeinit(void)
|
|||||||
}
|
}
|
||||||
if(isfloat[i]) {
|
if(isfloat[i]) {
|
||||||
okforeq[i] = 1;
|
okforeq[i] = 1;
|
||||||
|
okforcmp[i] = 1;
|
||||||
okforadd[i] = 1;
|
okforadd[i] = 1;
|
||||||
|
okforarith[i] = 1;
|
||||||
issimple[i] = 1;
|
issimple[i] = 1;
|
||||||
minfltval[i] = mal(sizeof(*minfltval[i]));
|
minfltval[i] = mal(sizeof(*minfltval[i]));
|
||||||
maxfltval[i] = mal(sizeof(*maxfltval[i]));
|
maxfltval[i] = mal(sizeof(*maxfltval[i]));
|
||||||
}
|
}
|
||||||
switch(i) {
|
|
||||||
case TBOOL:
|
|
||||||
issimple[i] = 1;
|
|
||||||
|
|
||||||
case TPTR32:
|
|
||||||
case TPTR64:
|
|
||||||
case TINTER:
|
|
||||||
case TMAP:
|
|
||||||
case TCHAN:
|
|
||||||
case TFUNC:
|
|
||||||
okforeq[i] = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issimple[TBOOL] = 1;
|
||||||
|
|
||||||
|
okforadd[TSTRING] = 1;
|
||||||
|
|
||||||
|
okforbool[TBOOL] = 1;
|
||||||
|
|
||||||
|
okforcap[TARRAY] = 1;
|
||||||
|
//okforcap[TCHAN] = 1;
|
||||||
|
//okforcap[TMAP] = 1;
|
||||||
|
|
||||||
|
okforlen[TARRAY] = 1;
|
||||||
|
//okforlen[TCHAN] = 1;
|
||||||
|
okforlen[TMAP] = 1;
|
||||||
|
okforlen[TSTRING] = 1;
|
||||||
|
|
||||||
|
okforeq[TPTR32] = 1;
|
||||||
|
okforeq[TPTR64] = 1;
|
||||||
|
okforeq[TINTER] = 1;
|
||||||
|
okforeq[TMAP] = 1;
|
||||||
|
okforeq[TCHAN] = 1;
|
||||||
|
okforeq[TFUNC] = 1;
|
||||||
|
okforeq[TSTRING] = 1;
|
||||||
|
okforeq[TBOOL] = 1;
|
||||||
|
okforeq[TARRAY] = 1; // refined in typecheck
|
||||||
|
|
||||||
|
okforcmp[TSTRING] = 1;
|
||||||
|
|
||||||
|
for(i=0; i<nelem(okfor); i++)
|
||||||
|
okfor[i] = okfornone;
|
||||||
|
|
||||||
|
// binary
|
||||||
|
okfor[OADD] = okforadd;
|
||||||
|
okfor[OAND] = okforand;
|
||||||
|
okfor[OANDAND] = okforbool;
|
||||||
|
okfor[OANDNOT] = okforand;
|
||||||
|
okfor[ODIV] = okforarith;
|
||||||
|
okfor[OEQ] = okforeq;
|
||||||
|
okfor[OGE] = okforcmp;
|
||||||
|
okfor[OGT] = okforcmp;
|
||||||
|
okfor[OLE] = okforcmp;
|
||||||
|
okfor[OLT] = okforcmp;
|
||||||
|
okfor[OMOD] = okforarith;
|
||||||
|
okfor[OMUL] = okforarith;
|
||||||
|
okfor[ONE] = okforeq;
|
||||||
|
okfor[OOR] = okforand;
|
||||||
|
okfor[OOROR] = okforbool;
|
||||||
|
okfor[OSUB] = okforarith;
|
||||||
|
okfor[OXOR] = okforand;
|
||||||
|
okfor[OLSH] = okforand;
|
||||||
|
okfor[ORSH] = okforand;
|
||||||
|
|
||||||
|
// unary
|
||||||
|
okfor[OCOM] = okforand;
|
||||||
|
okfor[OMINUS] = okforarith;
|
||||||
|
okfor[ONOT] = okforbool;
|
||||||
|
okfor[OPLUS] = okforadd;
|
||||||
|
|
||||||
|
// special
|
||||||
|
okfor[OCAP] = okforcap;
|
||||||
|
okfor[OLEN] = okforlen;
|
||||||
|
|
||||||
mpatofix(maxintval[TINT8], "0x7f");
|
mpatofix(maxintval[TINT8], "0x7f");
|
||||||
mpatofix(minintval[TINT8], "-0x80");
|
mpatofix(minintval[TINT8], "-0x80");
|
||||||
mpatofix(maxintval[TINT16], "0x7fff");
|
mpatofix(maxintval[TINT16], "0x7fff");
|
||||||
|
@ -587,6 +587,12 @@ unary:
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case TUP(OCONV, CTINT):
|
||||||
|
case TUP(OCONV, CTFLT):
|
||||||
|
case TUP(OCONV, CTSTR):
|
||||||
|
convlit1(&nl, n->type, 1);
|
||||||
|
break;
|
||||||
|
|
||||||
case TUP(OPLUS, CTINT):
|
case TUP(OPLUS, CTINT):
|
||||||
break;
|
break;
|
||||||
case TUP(OMINUS, CTINT):
|
case TUP(OMINUS, CTINT):
|
||||||
@ -711,7 +717,7 @@ defaultlit(Node **np, Type *t)
|
|||||||
lineno = n->lineno;
|
lineno = n->lineno;
|
||||||
switch(n->val.ctype) {
|
switch(n->val.ctype) {
|
||||||
default:
|
default:
|
||||||
yyerror("defaultlit: unknown literal: %N", n);
|
yyerror("defaultlit: unknown literal: %#N", n);
|
||||||
break;
|
break;
|
||||||
case CTINT:
|
case CTINT:
|
||||||
n->type = types[TINT];
|
n->type = types[TINT];
|
||||||
|
@ -195,6 +195,7 @@ struct Node
|
|||||||
uchar funcdepth;
|
uchar funcdepth;
|
||||||
uchar builtin; // built-in name, like len or close
|
uchar builtin; // built-in name, like len or close
|
||||||
uchar walkdef;
|
uchar walkdef;
|
||||||
|
uchar typecheck;
|
||||||
|
|
||||||
// most nodes
|
// most nodes
|
||||||
Node* left;
|
Node* left;
|
||||||
@ -435,12 +436,11 @@ enum
|
|||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
Exxx,
|
Etop = 1<<1, // evaluated at statement level
|
||||||
Eyyy,
|
Elv = 1<<2, // evaluated in lvalue context
|
||||||
Etop, // evaluated at statement level
|
Erv = 1<<3, // evaluated in rvalue context
|
||||||
Elv, // evaluated in lvalue context
|
Etype = 1<<4,
|
||||||
Erv, // evaluated in rvalue context
|
Eideal = 1<<5,
|
||||||
Etype = 1<<8,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BITS 5
|
#define BITS 5
|
||||||
@ -574,6 +574,7 @@ EXTERN char* filename; // name to uniqify names
|
|||||||
EXTERN Idir* idirs;
|
EXTERN Idir* idirs;
|
||||||
|
|
||||||
EXTERN Type* types[NTYPE];
|
EXTERN Type* types[NTYPE];
|
||||||
|
EXTERN Type* idealstring;
|
||||||
EXTERN uchar simtype[NTYPE];
|
EXTERN uchar simtype[NTYPE];
|
||||||
EXTERN uchar isptr[NTYPE];
|
EXTERN uchar isptr[NTYPE];
|
||||||
EXTERN uchar isforw[NTYPE];
|
EXTERN uchar isforw[NTYPE];
|
||||||
@ -581,10 +582,17 @@ EXTERN uchar isint[NTYPE];
|
|||||||
EXTERN uchar isfloat[NTYPE];
|
EXTERN uchar isfloat[NTYPE];
|
||||||
EXTERN uchar issigned[NTYPE];
|
EXTERN uchar issigned[NTYPE];
|
||||||
EXTERN uchar issimple[NTYPE];
|
EXTERN uchar issimple[NTYPE];
|
||||||
|
|
||||||
EXTERN uchar okforeq[NTYPE];
|
EXTERN uchar okforeq[NTYPE];
|
||||||
EXTERN uchar okforadd[NTYPE];
|
EXTERN uchar okforadd[NTYPE];
|
||||||
EXTERN uchar okforand[NTYPE];
|
EXTERN uchar okforand[NTYPE];
|
||||||
EXTERN Type* idealstring;
|
EXTERN uchar okfornone[NTYPE];
|
||||||
|
EXTERN uchar okforcmp[NTYPE];
|
||||||
|
EXTERN uchar okforbool[NTYPE];
|
||||||
|
EXTERN uchar okforcap[NTYPE];
|
||||||
|
EXTERN uchar okforlen[NTYPE];
|
||||||
|
EXTERN uchar okforarith[NTYPE];
|
||||||
|
EXTERN uchar* okfor[OEND];
|
||||||
|
|
||||||
EXTERN Mpint* minintval[NTYPE];
|
EXTERN Mpint* minintval[NTYPE];
|
||||||
EXTERN Mpint* maxintval[NTYPE];
|
EXTERN Mpint* maxintval[NTYPE];
|
||||||
@ -977,6 +985,8 @@ void addrescapes(Node*);
|
|||||||
void heapmoves(void);
|
void heapmoves(void);
|
||||||
void walkdeflist(NodeList*);
|
void walkdeflist(NodeList*);
|
||||||
void walkdef(Node*);
|
void walkdef(Node*);
|
||||||
|
void typechecklist(NodeList*, int);
|
||||||
|
Node* typecheck(Node**, int);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* const.c
|
* const.c
|
||||||
|
@ -1324,7 +1324,7 @@ Nconv(Fmt *fp)
|
|||||||
fmtprint(fp, "<N>");
|
fmtprint(fp, "<N>");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fp->flags & FmtSharp) {
|
if(fp->flags & FmtSharp) {
|
||||||
exprfmt(fp, n, 0);
|
exprfmt(fp, n, 0);
|
||||||
goto out;
|
goto out;
|
||||||
@ -2123,7 +2123,6 @@ out:
|
|||||||
void
|
void
|
||||||
badtype(int o, Type *tl, Type *tr)
|
badtype(int o, Type *tl, Type *tr)
|
||||||
{
|
{
|
||||||
|
|
||||||
yyerror("illegal types for operand: %O", o);
|
yyerror("illegal types for operand: %O", o);
|
||||||
if(tl != T)
|
if(tl != T)
|
||||||
print(" %T\n", tl);
|
print(" %T\n", tl);
|
||||||
@ -2346,7 +2345,6 @@ tempname(Node *n, Type *t)
|
|||||||
n->op = ONAME;
|
n->op = ONAME;
|
||||||
n->sym = s;
|
n->sym = s;
|
||||||
n->type = t;
|
n->type = t;
|
||||||
n->etype = t->etype;
|
|
||||||
n->class = PAUTO;
|
n->class = PAUTO;
|
||||||
n->addable = 1;
|
n->addable = 1;
|
||||||
n->ullman = 1;
|
n->ullman = 1;
|
||||||
|
@ -137,6 +137,10 @@ walkdef(Node *n)
|
|||||||
}
|
}
|
||||||
n->walkdef = 2;
|
n->walkdef = 2;
|
||||||
|
|
||||||
|
if(n->type != T || n->sym == S) // builtin or no name
|
||||||
|
goto ret;
|
||||||
|
|
||||||
|
|
||||||
init = nil;
|
init = nil;
|
||||||
switch(n->op) {
|
switch(n->op) {
|
||||||
case OLITERAL:
|
case OLITERAL:
|
||||||
@ -151,8 +155,11 @@ walkdef(Node *n)
|
|||||||
}
|
}
|
||||||
e = n->defn;
|
e = n->defn;
|
||||||
n->defn = N;
|
n->defn = N;
|
||||||
if(e == N)
|
if(e == N) {
|
||||||
dump("walkdef", n);
|
lineno = n->lineno;
|
||||||
|
dump("walkdef nil defn", n);
|
||||||
|
yyerror("xxx");
|
||||||
|
}
|
||||||
walkexpr(&e, Erv, &init);
|
walkexpr(&e, Erv, &init);
|
||||||
if(e->op != OLITERAL) {
|
if(e->op != OLITERAL) {
|
||||||
yyerror("const initializer must be constant");
|
yyerror("const initializer must be constant");
|
||||||
@ -185,7 +192,7 @@ walkstmt(Node **np)
|
|||||||
NodeList *ll;
|
NodeList *ll;
|
||||||
int lno;
|
int lno;
|
||||||
Node *n;
|
Node *n;
|
||||||
|
|
||||||
n = *np;
|
n = *np;
|
||||||
if(n == N)
|
if(n == N)
|
||||||
return;
|
return;
|
||||||
@ -288,7 +295,7 @@ walkstmt(Node **np)
|
|||||||
n->op = OFALL;
|
n->op = OFALL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
*np = n;
|
*np = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,6 +320,299 @@ implicitstar(Node **nn)
|
|||||||
*nn = n;
|
*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
|
* walk the whole tree of the body of an
|
||||||
* expression or simple statement.
|
* expression or simple statement.
|
||||||
@ -351,20 +651,13 @@ walkexpr(Node **np, int top, NodeList **init)
|
|||||||
if(debug['w'] > 1 && top == Etop)
|
if(debug['w'] > 1 && top == Etop)
|
||||||
dump("walk-before", n);
|
dump("walk-before", n);
|
||||||
|
|
||||||
|
if(n->typecheck != 1)
|
||||||
|
typecheck(&n, top | typeok);
|
||||||
|
|
||||||
reswitch:
|
reswitch:
|
||||||
t = T;
|
t = T;
|
||||||
et = Txxx;
|
et = Txxx;
|
||||||
|
|
||||||
switch(n->op) {
|
|
||||||
case ONAME:
|
|
||||||
case OTYPE:
|
|
||||||
case OLITERAL:
|
|
||||||
case ONONAME:
|
|
||||||
if(n->sym != S && n->type == T)
|
|
||||||
walkdef(n);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(n->op) {
|
switch(n->op) {
|
||||||
default:
|
default:
|
||||||
dump("walk", n);
|
dump("walk", n);
|
||||||
@ -374,80 +667,6 @@ reswitch:
|
|||||||
case OTYPE:
|
case OTYPE:
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OTARRAY:
|
|
||||||
t = typ(TARRAY);
|
|
||||||
l = n->left;
|
|
||||||
r = n->right;
|
|
||||||
if(l == nil) {
|
|
||||||
t->bound = -1;
|
|
||||||
} else {
|
|
||||||
walkexpr(&l, Erv | Etype, init);
|
|
||||||
switch(l->op) {
|
|
||||||
default:
|
|
||||||
yyerror("invalid array bound %O", l->op);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OLITERAL:
|
|
||||||
if(consttype(l) == CTINT) {
|
|
||||||
t->bound = mpgetfix(l->val.u.xval);
|
|
||||||
if(t->bound < 0) {
|
|
||||||
yyerror("array bound must be non-negative");
|
|
||||||
t->bound = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OTYPE:
|
|
||||||
if(l->type == T)
|
|
||||||
break;
|
|
||||||
if(l->type->etype != TDDD)
|
|
||||||
yyerror("invalid array bound %T", l->type);
|
|
||||||
t->bound = -100;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
walkexpr(&r, Etype, init);
|
|
||||||
t->type = r->type;
|
|
||||||
n->op = OTYPE;
|
|
||||||
n->type = t;
|
|
||||||
checkwidth(t);
|
|
||||||
goto ret;
|
|
||||||
|
|
||||||
case OTMAP:
|
|
||||||
l = n->left;
|
|
||||||
r = n->right;
|
|
||||||
walkexpr(&l, Etype, init);
|
|
||||||
walkexpr(&r, Etype, init);
|
|
||||||
n->op = OTYPE;
|
|
||||||
n->type = maptype(l->type, r->type);
|
|
||||||
goto ret;
|
|
||||||
|
|
||||||
case OTCHAN:
|
|
||||||
t = typ(TCHAN);
|
|
||||||
l = n->left;
|
|
||||||
walkexpr(&l, Etype, init);
|
|
||||||
t->type = l->type;
|
|
||||||
t->chan = n->etype;
|
|
||||||
n->op = OTYPE;
|
|
||||||
n->type = t;
|
|
||||||
goto ret;
|
|
||||||
|
|
||||||
case OTSTRUCT:
|
|
||||||
n->op = OTYPE;
|
|
||||||
n->type = dostruct(n->list, TSTRUCT);
|
|
||||||
goto ret;
|
|
||||||
|
|
||||||
case OTINTER:
|
|
||||||
n->op = OTYPE;
|
|
||||||
n->type = dostruct(n->list, TINTER);
|
|
||||||
n->type = sortinter(n->type);
|
|
||||||
goto ret;
|
|
||||||
|
|
||||||
case OTFUNC:
|
|
||||||
n->op = OTYPE;
|
|
||||||
n->type = functype(n->left, n->list, n->rlist);
|
|
||||||
goto ret;
|
|
||||||
|
|
||||||
case OKEY:
|
case OKEY:
|
||||||
walkexpr(&n->left, top | typeok, init);
|
walkexpr(&n->left, top | typeok, init);
|
||||||
walkexpr(&n->right, top | typeok, init);
|
walkexpr(&n->right, top | typeok, init);
|
||||||
@ -483,7 +702,7 @@ reswitch:
|
|||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OLITERAL:
|
case OLITERAL:
|
||||||
if(top != Erv)
|
if(!(top & Erv))
|
||||||
goto nottop;
|
goto nottop;
|
||||||
n->addable = 1;
|
n->addable = 1;
|
||||||
goto ret;
|
goto ret;
|
||||||
@ -550,7 +769,7 @@ reswitch:
|
|||||||
n->op = OCALLINTER;
|
n->op = OCALLINTER;
|
||||||
if(n->left->op == OTYPE) {
|
if(n->left->op == OTYPE) {
|
||||||
n->op = OCONV;
|
n->op = OCONV;
|
||||||
if(top != Erv)
|
if(!(top & Erv))
|
||||||
goto nottop;
|
goto nottop;
|
||||||
// turn CALL(type, arg) into CONV(arg) w/ type.
|
// turn CALL(type, arg) into CONV(arg) w/ type.
|
||||||
n->type = n->left->type;
|
n->type = n->left->type;
|
||||||
@ -777,7 +996,7 @@ reswitch:
|
|||||||
walkdottype(n, init);
|
walkdottype(n, init);
|
||||||
// fall through
|
// fall through
|
||||||
case OCONV:
|
case OCONV:
|
||||||
if(top != Erv)
|
if(!(top & Erv))
|
||||||
goto nottop;
|
goto nottop;
|
||||||
walkconv(&n, init);
|
walkconv(&n, init);
|
||||||
goto ret;
|
goto ret;
|
||||||
@ -817,9 +1036,8 @@ reswitch:
|
|||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case ONOT:
|
case ONOT:
|
||||||
if(top != Erv)
|
if(!(top & Erv))
|
||||||
goto nottop;
|
goto nottop;
|
||||||
evconst(n);
|
|
||||||
if(n->op == OLITERAL)
|
if(n->op == OLITERAL)
|
||||||
goto ret;
|
goto ret;
|
||||||
walkexpr(&n->left, Erv, init);
|
walkexpr(&n->left, Erv, init);
|
||||||
@ -841,7 +1059,7 @@ reswitch:
|
|||||||
|
|
||||||
case OLSH:
|
case OLSH:
|
||||||
case ORSH:
|
case ORSH:
|
||||||
if(top != Erv)
|
if(!(top & Erv))
|
||||||
goto nottop;
|
goto nottop;
|
||||||
walkexpr(&n->left, Erv, init);
|
walkexpr(&n->left, Erv, init);
|
||||||
|
|
||||||
@ -880,7 +1098,7 @@ reswitch:
|
|||||||
case OSUB:
|
case OSUB:
|
||||||
case OMUL:
|
case OMUL:
|
||||||
case ODIV:
|
case ODIV:
|
||||||
if(top != Erv)
|
if(!(top & Erv))
|
||||||
goto nottop;
|
goto nottop;
|
||||||
walkexpr(&n->left, Erv, init);
|
walkexpr(&n->left, Erv, init);
|
||||||
|
|
||||||
@ -935,18 +1153,17 @@ reswitch:
|
|||||||
case OMINUS:
|
case OMINUS:
|
||||||
case OPLUS:
|
case OPLUS:
|
||||||
case OCOM:
|
case OCOM:
|
||||||
if(top != Erv)
|
if(!(top & Erv))
|
||||||
goto nottop;
|
goto nottop;
|
||||||
walkexpr(&n->left, Erv, init);
|
walkexpr(&n->left, Erv, init);
|
||||||
if(n->left == N)
|
if(n->left == N)
|
||||||
goto ret;
|
goto ret;
|
||||||
evconst(n);
|
|
||||||
if(n->op == OLITERAL)
|
if(n->op == OLITERAL)
|
||||||
goto ret;
|
goto ret;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OLEN:
|
case OLEN:
|
||||||
if(top != Erv)
|
if(!(top & Erv))
|
||||||
goto nottop;
|
goto nottop;
|
||||||
if(n->left == N) {
|
if(n->left == N) {
|
||||||
if(n->list == nil) {
|
if(n->list == nil) {
|
||||||
@ -981,7 +1198,7 @@ reswitch:
|
|||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OCAP:
|
case OCAP:
|
||||||
if(top != Erv)
|
if(!(top & Erv))
|
||||||
goto nottop;
|
goto nottop;
|
||||||
if(n->left == N) {
|
if(n->left == N) {
|
||||||
if(n->list == nil) {
|
if(n->list == nil) {
|
||||||
@ -1033,7 +1250,7 @@ reswitch:
|
|||||||
|
|
||||||
case TSTRING:
|
case TSTRING:
|
||||||
// right side must be an int
|
// right side must be an int
|
||||||
if(top != Erv)
|
if(!(top & Erv))
|
||||||
goto nottop;
|
goto nottop;
|
||||||
defaultlit(&n->right, types[TINT]);
|
defaultlit(&n->right, types[TINT]);
|
||||||
if(n->right->type == T)
|
if(n->right->type == T)
|
||||||
@ -1107,7 +1324,8 @@ reswitch:
|
|||||||
goto nottop;
|
goto nottop;
|
||||||
|
|
||||||
walkexpr(&n->left, top, init);
|
walkexpr(&n->left, top, init);
|
||||||
walkexpr(&n->right, Erv, init);
|
walkexpr(&n->right->left, Erv, init);
|
||||||
|
walkexpr(&n->right->right, Erv, init);
|
||||||
if(n->left == N || n->right == N)
|
if(n->left == N || n->right == N)
|
||||||
goto ret;
|
goto ret;
|
||||||
defaultlit(&n->left, T);
|
defaultlit(&n->left, T);
|
||||||
@ -1139,7 +1357,7 @@ reswitch:
|
|||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OADDR:
|
case OADDR:
|
||||||
if(top != Erv)
|
if(!(top & Erv))
|
||||||
goto nottop;
|
goto nottop;
|
||||||
defaultlit(&n->left, T);
|
defaultlit(&n->left, T);
|
||||||
if(n->left->op == OCOMPOS) {
|
if(n->left->op == OCOMPOS) {
|
||||||
@ -1225,13 +1443,13 @@ reswitch:
|
|||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OMAKE:
|
case OMAKE:
|
||||||
if(top != Erv)
|
if(!(top & Erv))
|
||||||
goto nottop;
|
goto nottop;
|
||||||
n = makecompat(n);
|
n = makecompat(n);
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case ONEW:
|
case ONEW:
|
||||||
if(top != Erv)
|
if(!(top & Erv))
|
||||||
goto nottop;
|
goto nottop;
|
||||||
if(n->list == nil) {
|
if(n->list == nil) {
|
||||||
yyerror("missing argument to new");
|
yyerror("missing argument to new");
|
||||||
@ -1295,7 +1513,7 @@ reswitch:
|
|||||||
if(n->left->type == T)
|
if(n->left->type == T)
|
||||||
goto ret;
|
goto ret;
|
||||||
et = n->left->type->etype;
|
et = n->left->type->etype;
|
||||||
if(!okforadd[et] && et != TSTRING)
|
if(!okforarith[et] && et != TSTRING)
|
||||||
goto badt;
|
goto badt;
|
||||||
t = types[TBOOL];
|
t = types[TBOOL];
|
||||||
break;
|
break;
|
||||||
@ -1308,7 +1526,7 @@ reswitch:
|
|||||||
if(n->left->type == T)
|
if(n->left->type == T)
|
||||||
goto ret;
|
goto ret;
|
||||||
et = n->left->type->etype;
|
et = n->left->type->etype;
|
||||||
if(!okforadd[et])
|
if(!okforarith[et])
|
||||||
goto badt;
|
goto badt;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1316,7 +1534,7 @@ reswitch:
|
|||||||
if(n->left->type == T)
|
if(n->left->type == T)
|
||||||
goto ret;
|
goto ret;
|
||||||
et = n->left->type->etype;
|
et = n->left->type->etype;
|
||||||
if(!okforadd[et])
|
if(!okforarith[et])
|
||||||
goto badt;
|
goto badt;
|
||||||
if(isfloat[et]) {
|
if(isfloat[et]) {
|
||||||
// TODO(rsc): Can do this more efficiently,
|
// TODO(rsc): Can do this more efficiently,
|
||||||
@ -1394,7 +1612,7 @@ nottop:
|
|||||||
if(n->diag)
|
if(n->diag)
|
||||||
goto ret;
|
goto ret;
|
||||||
n->diag = 1;
|
n->diag = 1;
|
||||||
switch(top | typeok) {
|
switch((top | typeok) & ~Eideal) {
|
||||||
default:
|
default:
|
||||||
yyerror("didn't expect %O here [top=%d]", n->op, top);
|
yyerror("didn't expect %O here [top=%d]", n->op, top);
|
||||||
break;
|
break;
|
||||||
@ -1495,7 +1713,7 @@ walkconv(Node **np, NodeList **init)
|
|||||||
Type *t;
|
Type *t;
|
||||||
Node *l;
|
Node *l;
|
||||||
Node *n;
|
Node *n;
|
||||||
|
|
||||||
n = *np;
|
n = *np;
|
||||||
t = n->type;
|
t = n->type;
|
||||||
if(t == T)
|
if(t == T)
|
||||||
@ -2846,7 +3064,7 @@ mapop(Node *n, int top, NodeList **init)
|
|||||||
if(cl > 1)
|
if(cl > 1)
|
||||||
yyerror("too many arguments to make map");
|
yyerror("too many arguments to make map");
|
||||||
|
|
||||||
if(top != Erv)
|
if(!(top & Erv))
|
||||||
goto nottop;
|
goto nottop;
|
||||||
|
|
||||||
// newmap(keysize int, valsize int,
|
// newmap(keysize int, valsize int,
|
||||||
@ -2884,7 +3102,7 @@ mapop(Node *n, int top, NodeList **init)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case OINDEX:
|
case OINDEX:
|
||||||
if(top != Erv)
|
if(!(top & Erv))
|
||||||
goto nottop;
|
goto nottop;
|
||||||
// mapaccess1(hmap map[any]any, key any) (val any);
|
// mapaccess1(hmap map[any]any, key any) (val any);
|
||||||
|
|
||||||
|
@ -133,6 +133,7 @@ fixedbugs/bug039.go:6: variable x redeclared in this block
|
|||||||
previous declaration at fixedbugs/bug039.go:5
|
previous declaration at fixedbugs/bug039.go:5
|
||||||
|
|
||||||
=========== fixedbugs/bug049.go
|
=========== fixedbugs/bug049.go
|
||||||
|
fixedbugs/bug049.go:6: invalid operation: s == nil
|
||||||
fixedbugs/bug049.go:6: illegal types for operand: EQ
|
fixedbugs/bug049.go:6: illegal types for operand: EQ
|
||||||
string
|
string
|
||||||
nil
|
nil
|
||||||
|
Loading…
Reference in New Issue
Block a user