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) {
......
This diff is collapsed.
This diff is collapsed.
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