mirror of
https://github.com/golang/go
synced 2024-11-21 20:54:45 -07:00
make 6g constants behave as ken proposes. (i hope.)
various bug fixes and tests involving constants. test/const1.go is the major new test case. R=ken OCL=26216 CL=26224
This commit is contained in:
parent
9b5d82327b
commit
8f194bf5ff
@ -146,11 +146,11 @@ cgen(Node *n, Node *res)
|
|||||||
case ONOT:
|
case ONOT:
|
||||||
p1 = gbranch(AJMP, T);
|
p1 = gbranch(AJMP, T);
|
||||||
p2 = pc;
|
p2 = pc;
|
||||||
gmove(booltrue, res);
|
gmove(nodbool(1), res);
|
||||||
p3 = gbranch(AJMP, T);
|
p3 = gbranch(AJMP, T);
|
||||||
patch(p1, pc);
|
patch(p1, pc);
|
||||||
bgen(n, 1, p2);
|
bgen(n, 1, p2);
|
||||||
gmove(boolfalse, res);
|
gmove(nodbool(0), res);
|
||||||
patch(p3, pc);
|
patch(p3, pc);
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
@ -408,7 +408,7 @@ agen(Node *n, Node *res)
|
|||||||
if(nr->addable)
|
if(nr->addable)
|
||||||
goto irad;
|
goto irad;
|
||||||
if(nl->addable) {
|
if(nl->addable) {
|
||||||
if(whatis(nr) != Wlitint) {
|
if(!isconst(nr, CTINT)) {
|
||||||
regalloc(&n1, nr->type, N);
|
regalloc(&n1, nr->type, N);
|
||||||
cgen(nr, &n1);
|
cgen(nr, &n1);
|
||||||
}
|
}
|
||||||
@ -423,7 +423,7 @@ agen(Node *n, Node *res)
|
|||||||
irad:
|
irad:
|
||||||
regalloc(&n3, types[tptr], res);
|
regalloc(&n3, types[tptr], res);
|
||||||
agen(nl, &n3);
|
agen(nl, &n3);
|
||||||
if(whatis(nr) != Wlitint) {
|
if(!isconst(nr, CTINT)) {
|
||||||
regalloc(&n1, nr->type, N);
|
regalloc(&n1, nr->type, N);
|
||||||
cgen(nr, &n1);
|
cgen(nr, &n1);
|
||||||
}
|
}
|
||||||
@ -438,7 +438,7 @@ agen(Node *n, Node *res)
|
|||||||
fatal("index is zero width");
|
fatal("index is zero width");
|
||||||
|
|
||||||
// constant index
|
// constant index
|
||||||
if(whatis(nr) == Wlitint) {
|
if(isconst(nr, CTINT)) {
|
||||||
v = mpgetfix(nr->val.u.xval);
|
v = mpgetfix(nr->val.u.xval);
|
||||||
if(isslice(nl->type)) {
|
if(isslice(nl->type)) {
|
||||||
|
|
||||||
@ -618,7 +618,7 @@ bgen(Node *n, int true, Prog *to)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(n == N)
|
if(n == N)
|
||||||
n = booltrue;
|
n = nodbool(1);
|
||||||
|
|
||||||
nl = n->left;
|
nl = n->left;
|
||||||
nr = n->right;
|
nr = n->right;
|
||||||
|
@ -345,15 +345,6 @@ nodconst(Node *n, Type *t, vlong v)
|
|||||||
case TFLOAT64:
|
case TFLOAT64:
|
||||||
case TFLOAT80:
|
case TFLOAT80:
|
||||||
fatal("nodconst: bad type %T", t);
|
fatal("nodconst: bad type %T", t);
|
||||||
|
|
||||||
case TPTR32:
|
|
||||||
case TPTR64:
|
|
||||||
case TUINT8:
|
|
||||||
case TUINT16:
|
|
||||||
case TUINT32:
|
|
||||||
case TUINT64:
|
|
||||||
n->val.ctype = CTUINT;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1102,8 +1093,6 @@ naddr(Node *n, Addr *a)
|
|||||||
a->dval = mpgetflt(n->val.u.fval);
|
a->dval = mpgetflt(n->val.u.fval);
|
||||||
break;
|
break;
|
||||||
case CTINT:
|
case CTINT:
|
||||||
case CTSINT:
|
|
||||||
case CTUINT:
|
|
||||||
a->sym = S;
|
a->sym = S;
|
||||||
a->type = D_CONST;
|
a->type = D_CONST;
|
||||||
a->offset = mpgetfix(n->val.u.xval);
|
a->offset = mpgetfix(n->val.u.xval);
|
||||||
@ -2057,7 +2046,7 @@ oindex:
|
|||||||
}
|
}
|
||||||
|
|
||||||
w = n->type->width;
|
w = n->type->width;
|
||||||
if(whatis(r) == Wlitint)
|
if(isconst(r, CTINT))
|
||||||
goto oindex_const;
|
goto oindex_const;
|
||||||
|
|
||||||
switch(w) {
|
switch(w) {
|
||||||
|
@ -5,6 +5,16 @@
|
|||||||
#include "go.h"
|
#include "go.h"
|
||||||
#define TUP(x,y) (((x)<<16)|(y))
|
#define TUP(x,y) (((x)<<16)|(y))
|
||||||
|
|
||||||
|
static Val toflt(Val);
|
||||||
|
static Val toint(Val);
|
||||||
|
static Val tostr(Val);
|
||||||
|
static void overflow(Val, Type*);
|
||||||
|
static Val copyval(Val);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* truncate float literal fv to 32-bit or 64-bit precision
|
||||||
|
* according to type.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
truncfltlit(Mpflt *fv, Type *t)
|
truncfltlit(Mpflt *fv, Type *t)
|
||||||
{
|
{
|
||||||
@ -33,12 +43,28 @@ truncfltlit(Mpflt *fv, Type *t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* convert n, if literal, to type t.
|
||||||
|
* implicit conversion.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
convlit1(Node *n, Type *t, int conv)
|
convlit(Node *n, Type *t)
|
||||||
{
|
{
|
||||||
int et, wt;
|
convlit1(n, t, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if(n == N || t == T)
|
/*
|
||||||
|
* convert n, if literal, to type t.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
convlit1(Node *n, Type *t, int explicit)
|
||||||
|
{
|
||||||
|
int et, ct;
|
||||||
|
|
||||||
|
if(n == N || t == T || n->type == T)
|
||||||
|
return;
|
||||||
|
et = t->etype;
|
||||||
|
if(et == TIDEAL || et == TNIL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch(n->op) {
|
switch(n->op) {
|
||||||
@ -53,17 +79,37 @@ convlit1(Node *n, Type *t, int conv)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
et = t->etype;
|
// avoided repeated calculations, errors
|
||||||
wt = whatis(n);
|
if(eqtype(n->type, t, 0)) {
|
||||||
|
n->type = t;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch(wt) {
|
ct = consttype(n);
|
||||||
|
if(ct < 0)
|
||||||
|
goto bad;
|
||||||
|
|
||||||
|
if(et == TINTER) {
|
||||||
|
if(ct == CTNIL) {
|
||||||
|
n->type = t;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
defaultlit(n, T);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if already has non-ideal type, cannot change implicitly
|
||||||
|
if(n->type->etype != TIDEAL && n->type->etype != TNIL && !explicit)
|
||||||
|
goto bad;
|
||||||
|
|
||||||
|
switch(ct) {
|
||||||
default:
|
default:
|
||||||
goto bad1;
|
goto bad;
|
||||||
|
|
||||||
case Wlitnil:
|
case CTNIL:
|
||||||
switch(et) {
|
switch(et) {
|
||||||
default:
|
default:
|
||||||
goto bad1;
|
goto bad;
|
||||||
|
|
||||||
case TPTR32:
|
case TPTR32:
|
||||||
case TPTR64:
|
case TPTR64:
|
||||||
@ -76,450 +122,577 @@ convlit1(Node *n, Type *t, int conv)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Wlitstr:
|
case CTSTR:
|
||||||
if(isnilinter(t)) {
|
case CTBOOL:
|
||||||
defaultlit(n);
|
if(et != n->type->etype)
|
||||||
return;
|
goto bad;
|
||||||
}
|
break;
|
||||||
if(et == TSTRING)
|
|
||||||
break;
|
|
||||||
goto bad1;
|
|
||||||
|
|
||||||
case Wlitbool:
|
case CTINT:
|
||||||
if(isnilinter(t)) {
|
case CTFLT:
|
||||||
defaultlit(n);
|
ct = n->val.ctype;
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(et == TBOOL)
|
|
||||||
break;
|
|
||||||
goto bad1;
|
|
||||||
|
|
||||||
case Wlitint:
|
|
||||||
if(isnilinter(t)) {
|
|
||||||
defaultlit(n);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(isint[et]) {
|
if(isint[et]) {
|
||||||
// int to int
|
if(ct == CTFLT)
|
||||||
if(mpcmpfixfix(n->val.u.xval, minintval[et]) < 0)
|
n->val = toint(n->val);
|
||||||
goto bad2;
|
else if(ct != CTINT)
|
||||||
if(mpcmpfixfix(n->val.u.xval, maxintval[et]) > 0)
|
goto bad;
|
||||||
goto bad2;
|
overflow(n->val, t);
|
||||||
break;
|
} else if(isfloat[et]) {
|
||||||
}
|
if(ct == CTINT)
|
||||||
if(isfloat[et]) {
|
n->val = toflt(n->val);
|
||||||
// int to float
|
else if(ct != CTFLT)
|
||||||
Mpint *xv;
|
goto bad;
|
||||||
Mpflt *fv;
|
overflow(n->val, t);
|
||||||
|
truncfltlit(n->val.u.fval, t);
|
||||||
xv = n->val.u.xval;
|
} else if(et == TSTRING && ct == CTINT && explicit)
|
||||||
if(mpcmpfixflt(xv, minfltval[et]) < 0)
|
n->val = tostr(n->val);
|
||||||
goto bad2;
|
else
|
||||||
if(mpcmpfixflt(xv, maxfltval[et]) > 0)
|
goto bad;
|
||||||
goto bad2;
|
|
||||||
fv = mal(sizeof(*n->val.u.fval));
|
|
||||||
n->val.u.fval = fv;
|
|
||||||
mpmovefixflt(fv, xv);
|
|
||||||
n->val.ctype = CTFLT;
|
|
||||||
truncfltlit(fv, t);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(!conv)
|
|
||||||
goto bad1;
|
|
||||||
|
|
||||||
// only done as string(CONST)
|
|
||||||
if(et == TSTRING) {
|
|
||||||
Rune rune;
|
|
||||||
int l;
|
|
||||||
String *s;
|
|
||||||
|
|
||||||
rune = mpgetfix(n->val.u.xval);
|
|
||||||
l = runelen(rune);
|
|
||||||
s = mal(sizeof(*s)+l);
|
|
||||||
s->len = l;
|
|
||||||
runetochar((char*)(s->s), &rune);
|
|
||||||
|
|
||||||
n->val.u.sval = s;
|
|
||||||
n->val.ctype = CTSTR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
goto bad1;
|
|
||||||
|
|
||||||
case Wlitfloat:
|
|
||||||
if(isnilinter(t)) {
|
|
||||||
defaultlit(n);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(isint[et]) {
|
|
||||||
// float to int
|
|
||||||
Mpflt *fv;
|
|
||||||
|
|
||||||
fv = n->val.u.fval;
|
|
||||||
if(mpcmpfltfix(fv, minintval[et]) < 0)
|
|
||||||
goto bad2;
|
|
||||||
if(mpcmpfltfix(fv, maxintval[et]) > 0)
|
|
||||||
goto bad2;
|
|
||||||
if(floor(mpgetflt(fv)) != mpgetflt(fv))
|
|
||||||
goto bad3;
|
|
||||||
n->val.u.xval = mal(sizeof(*n->val.u.xval));
|
|
||||||
mpmovefltfix(n->val.u.xval, fv);
|
|
||||||
n->val.ctype = CTINT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(isfloat[et]) {
|
|
||||||
// float to float
|
|
||||||
Mpflt *fv;
|
|
||||||
|
|
||||||
fv = n->val.u.fval;
|
|
||||||
if(mpcmpfltflt(fv, minfltval[et]) < 0)
|
|
||||||
goto bad2;
|
|
||||||
if(mpcmpfltflt(fv, maxfltval[et]) > 0)
|
|
||||||
goto bad2;
|
|
||||||
truncfltlit(fv, t);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
goto bad1;
|
|
||||||
}
|
}
|
||||||
n->type = t;
|
n->type = t;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bad1:
|
bad:
|
||||||
yyerror("illegal conversion of %W to %T", wt, t);
|
if(n->type->etype == TIDEAL)
|
||||||
return;
|
defaultlit(n, T);
|
||||||
|
yyerror("cannot convert %T constant to %T", n->type, t);
|
||||||
bad2:
|
n->type = T;
|
||||||
yyerror("overflow converting constant to %T", t);
|
n->diag = 1;
|
||||||
return;
|
|
||||||
|
|
||||||
bad3:
|
|
||||||
yyerror("cannot convert non-integer constant to %T", t);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static Val
|
||||||
convlit(Node *n, Type *t)
|
copyval(Val v)
|
||||||
{
|
{
|
||||||
convlit1(n, t, 0);
|
Mpint *i;
|
||||||
|
Mpflt *f;
|
||||||
|
|
||||||
|
switch(v.ctype) {
|
||||||
|
case CTINT:
|
||||||
|
i = mal(sizeof(*i));
|
||||||
|
mpmovefixfix(i, v.u.xval);
|
||||||
|
v.u.xval = i;
|
||||||
|
break;
|
||||||
|
case CTFLT:
|
||||||
|
f = mal(sizeof(*f));
|
||||||
|
mpmovefltflt(f, v.u.fval);
|
||||||
|
v.u.fval = f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Val
|
||||||
|
toflt(Val v)
|
||||||
|
{
|
||||||
|
Mpflt *f;
|
||||||
|
|
||||||
|
if(v.ctype == CTINT) {
|
||||||
|
f = mal(sizeof(*f));
|
||||||
|
mpmovefixflt(f, v.u.xval);
|
||||||
|
v.ctype = CTFLT;
|
||||||
|
v.u.fval = f;
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Val
|
||||||
|
toint(Val v)
|
||||||
|
{
|
||||||
|
Mpint *i;
|
||||||
|
|
||||||
|
if(v.ctype == CTFLT) {
|
||||||
|
i = mal(sizeof(*i));
|
||||||
|
if(mpmovefltfix(i, v.u.fval) < 0)
|
||||||
|
yyerror("constant %#F truncated to integer", v.u.fval);
|
||||||
|
v.ctype = CTINT;
|
||||||
|
v.u.xval = i;
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
overflow(Val v, Type *t)
|
||||||
|
{
|
||||||
|
// v has already been converted
|
||||||
|
// to appropriate form for t.
|
||||||
|
if(t == T || t->etype == TIDEAL)
|
||||||
|
return;
|
||||||
|
switch(v.ctype) {
|
||||||
|
case CTINT:
|
||||||
|
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(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);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Val
|
||||||
|
tostr(Val v)
|
||||||
|
{
|
||||||
|
Rune rune;
|
||||||
|
int l;
|
||||||
|
String *s;
|
||||||
|
|
||||||
|
switch(v.ctype) {
|
||||||
|
case CTINT:
|
||||||
|
if(mpcmpfixfix(v.u.xval, minintval[TINT]) < 0
|
||||||
|
|| mpcmpfixfix(v.u.xval, maxintval[TINT]) > 0)
|
||||||
|
yyerror("overflow in int -> string");
|
||||||
|
rune = mpgetfix(v.u.xval);
|
||||||
|
l = runelen(rune);
|
||||||
|
s = mal(sizeof(*s)+l);
|
||||||
|
s->len = l;
|
||||||
|
runetochar((char*)s->s, &rune);
|
||||||
|
v.ctype = CTSTR;
|
||||||
|
v.u.sval = s;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CTFLT:
|
||||||
|
yyerror("no float -> string");
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
consttype(Node *n)
|
||||||
|
{
|
||||||
|
if(n == N || n->op != OLITERAL)
|
||||||
|
return -1;
|
||||||
|
return n->val.ctype;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
isconst(Node *n, int ct)
|
||||||
|
{
|
||||||
|
return consttype(n) == ct;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if n is constant, rewrite as OLITERAL node.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
evconst(Node *n)
|
evconst(Node *n)
|
||||||
{
|
{
|
||||||
Node *nl, *nr;
|
Node *nl, *nr;
|
||||||
int32 len;
|
int32 len;
|
||||||
String *str;
|
String *str;
|
||||||
int wl, wr;
|
int wl, wr, lno;
|
||||||
Mpint *xval;
|
Val v;
|
||||||
Mpflt *fval;
|
|
||||||
|
|
||||||
xval = nil;
|
|
||||||
fval = nil;
|
|
||||||
|
|
||||||
nl = n->left;
|
nl = n->left;
|
||||||
if(nl == N)
|
if(nl == N || nl->type == T)
|
||||||
return;
|
return;
|
||||||
|
if(consttype(nl) < 0)
|
||||||
wl = whatis(nl);
|
|
||||||
switch(wl) {
|
|
||||||
default:
|
|
||||||
return;
|
return;
|
||||||
|
wl = nl->type->etype;
|
||||||
case Wlitint:
|
if(isint[wl] || isfloat[wl])
|
||||||
case Wlitfloat:
|
wl = TIDEAL;
|
||||||
case Wlitbool:
|
|
||||||
case Wlitstr:
|
|
||||||
case Wlitnil:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
nr = n->right;
|
nr = n->right;
|
||||||
if(nr == N)
|
if(nr == N)
|
||||||
goto unary;
|
goto unary;
|
||||||
|
if(nr->type == T)
|
||||||
wr = whatis(nr);
|
|
||||||
switch(wr) {
|
|
||||||
default:
|
|
||||||
return;
|
return;
|
||||||
|
if(consttype(nr) < 0)
|
||||||
|
return;
|
||||||
|
wr = nr->type->etype;
|
||||||
|
if(isint[wr] || isfloat[wr])
|
||||||
|
wr = TIDEAL;
|
||||||
|
|
||||||
case Wlitint:
|
// check for compatible general types (numeric, string, etc)
|
||||||
case Wlitfloat:
|
if(wl != wr)
|
||||||
case Wlitbool:
|
goto illegal;
|
||||||
case Wlitstr:
|
|
||||||
case Wlitnil:
|
// check for compatible types.
|
||||||
|
switch(n->op) {
|
||||||
|
default:
|
||||||
|
// ideal const mixes with anything but otherwise must match.
|
||||||
|
if(nl->type->etype != TIDEAL)
|
||||||
|
defaultlit(nr, nl->type);
|
||||||
|
if(nr->type->etype != TIDEAL)
|
||||||
|
defaultlit(nl, nr->type);
|
||||||
|
if(nl->type->etype != nr->type->etype)
|
||||||
|
goto illegal;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OLSH:
|
||||||
|
case ORSH:
|
||||||
|
// right must be unsigned.
|
||||||
|
// left can be ideal.
|
||||||
|
defaultlit(nr, types[TUINT]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(wl != wr) {
|
// copy numeric value to avoid modifying
|
||||||
if(wl == Wlitfloat && wr == Wlitint) {
|
// n->left, in case someone still refers to it (e.g. iota).
|
||||||
xval = nr->val.u.xval;
|
v = nl->val;
|
||||||
nr->val.u.fval = mal(sizeof(*nr->val.u.fval));
|
if(wl == TIDEAL)
|
||||||
mpmovefixflt(nr->val.u.fval, xval);
|
v = copyval(v);
|
||||||
nr->val.ctype = CTFLT;
|
|
||||||
wr = whatis(nr);
|
// since wl == wr,
|
||||||
} else
|
// the only way v.ctype != nr->val.ctype
|
||||||
if(wl == Wlitint && wr == Wlitfloat) {
|
// is when one is CTINT and the other CTFLT.
|
||||||
xval = nl->val.u.xval;
|
// make both CTFLT.
|
||||||
nl->val.u.fval = mal(sizeof(*nl->val.u.fval));
|
if(v.ctype != nr->val.ctype) {
|
||||||
mpmovefixflt(nl->val.u.fval, xval);
|
v = toflt(v);
|
||||||
nl->val.ctype = CTFLT;
|
nr->val = toflt(nr->val);
|
||||||
wl = whatis(nl);
|
}
|
||||||
} else {
|
|
||||||
yyerror("illegal combination of literals %O %W, %W", n->op, wl, wr);
|
// run op
|
||||||
return;
|
switch(TUP(n->op, v.ctype)) {
|
||||||
|
default:
|
||||||
|
illegal:
|
||||||
|
yyerror("illegal constant expression %T %O %T",
|
||||||
|
nl->type, n->op, nr->type);
|
||||||
|
n->diag = 1;
|
||||||
|
return;
|
||||||
|
|
||||||
|
case TUP(OADD, CTINT):
|
||||||
|
mpaddfixfix(v.u.xval, nr->val.u.xval);
|
||||||
|
break;
|
||||||
|
case TUP(OSUB, CTINT):
|
||||||
|
mpsubfixfix(v.u.xval, nr->val.u.xval);
|
||||||
|
break;
|
||||||
|
case TUP(OMUL, CTINT):
|
||||||
|
mpmulfixfix(v.u.xval, nr->val.u.xval);
|
||||||
|
break;
|
||||||
|
case TUP(ODIV, CTINT):
|
||||||
|
if(mpcmpfixc(nr->val.u.xval, 0) == 0) {
|
||||||
|
yyerror("division by zero");
|
||||||
|
mpmovecfix(v.u.xval, 1);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
mpdivfixfix(v.u.xval, nr->val.u.xval);
|
||||||
|
|
||||||
// dance to not modify left side
|
|
||||||
// this is because iota will reuse it
|
|
||||||
if(wl == Wlitint) {
|
|
||||||
xval = mal(sizeof(*xval));
|
|
||||||
mpmovefixfix(xval, nl->val.u.xval);
|
|
||||||
} else
|
|
||||||
if(wl == Wlitfloat) {
|
|
||||||
fval = mal(sizeof(*fval));
|
|
||||||
mpmovefltflt(fval, nl->val.u.fval);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(TUP(n->op, wl)) {
|
|
||||||
default:
|
|
||||||
yyerror("illegal literal %O %W", n->op, wl);
|
|
||||||
return;
|
|
||||||
|
|
||||||
case TUP(OADD, Wlitint):
|
|
||||||
mpaddfixfix(xval, nr->val.u.xval);
|
|
||||||
break;
|
break;
|
||||||
case TUP(OSUB, Wlitint):
|
case TUP(OMOD, CTINT):
|
||||||
mpsubfixfix(xval, nr->val.u.xval);
|
if(mpcmpfixc(nr->val.u.xval, 0) == 0) {
|
||||||
break;
|
yyerror("division by zero");
|
||||||
case TUP(OMUL, Wlitint):
|
mpmovecfix(v.u.xval, 1);
|
||||||
mpmulfixfix(xval, nr->val.u.xval);
|
break;
|
||||||
break;
|
}
|
||||||
case TUP(ODIV, Wlitint):
|
mpmodfixfix(v.u.xval, nr->val.u.xval);
|
||||||
mpdivfixfix(xval, nr->val.u.xval);
|
|
||||||
break;
|
|
||||||
case TUP(OMOD, Wlitint):
|
|
||||||
mpmodfixfix(xval, nr->val.u.xval);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TUP(OLSH, Wlitint):
|
case TUP(OLSH, CTINT):
|
||||||
mplshfixfix(xval, nr->val.u.xval);
|
mplshfixfix(v.u.xval, nr->val.u.xval);
|
||||||
break;
|
break;
|
||||||
case TUP(ORSH, Wlitint):
|
case TUP(ORSH, CTINT):
|
||||||
mprshfixfix(xval, nr->val.u.xval);
|
mprshfixfix(v.u.xval, nr->val.u.xval);
|
||||||
break;
|
break;
|
||||||
case TUP(OOR, Wlitint):
|
case TUP(OOR, CTINT):
|
||||||
mporfixfix(xval, nr->val.u.xval);
|
mporfixfix(v.u.xval, nr->val.u.xval);
|
||||||
break;
|
break;
|
||||||
case TUP(OAND, Wlitint):
|
case TUP(OAND, CTINT):
|
||||||
mpandfixfix(xval, nr->val.u.xval);
|
mpandfixfix(v.u.xval, nr->val.u.xval);
|
||||||
break;
|
break;
|
||||||
case TUP(OANDNOT, Wlitint):
|
case TUP(OANDNOT, CTINT):
|
||||||
mpandnotfixfix(xval, nr->val.u.xval);
|
mpandnotfixfix(v.u.xval, nr->val.u.xval);
|
||||||
break;
|
break;
|
||||||
case TUP(OXOR, Wlitint):
|
case TUP(OXOR, CTINT):
|
||||||
mpxorfixfix(xval, nr->val.u.xval);
|
mpxorfixfix(v.u.xval, nr->val.u.xval);
|
||||||
|
break;
|
||||||
|
case TUP(OADD, CTFLT):
|
||||||
|
mpaddfltflt(v.u.fval, nr->val.u.fval);
|
||||||
|
break;
|
||||||
|
case TUP(OSUB, CTFLT):
|
||||||
|
mpsubfltflt(v.u.fval, nr->val.u.fval);
|
||||||
|
break;
|
||||||
|
case TUP(OMUL, CTFLT):
|
||||||
|
mpmulfltflt(v.u.fval, nr->val.u.fval);
|
||||||
|
break;
|
||||||
|
case TUP(ODIV, CTFLT):
|
||||||
|
if(mpcmpfltc(nr->val.u.fval, 0) == 0) {
|
||||||
|
yyerror("division by zero");
|
||||||
|
mpmovecflt(v.u.fval, 1.0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mpdivfltflt(v.u.fval, nr->val.u.fval);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TUP(OADD, Wlitfloat):
|
case TUP(OEQ, CTNIL):
|
||||||
mpaddfltflt(fval, nr->val.u.fval);
|
|
||||||
break;
|
|
||||||
case TUP(OSUB, Wlitfloat):
|
|
||||||
mpsubfltflt(fval, nr->val.u.fval);
|
|
||||||
break;
|
|
||||||
case TUP(OMUL, Wlitfloat):
|
|
||||||
mpmulfltflt(fval, nr->val.u.fval);
|
|
||||||
break;
|
|
||||||
case TUP(ODIV, Wlitfloat):
|
|
||||||
mpdivfltflt(fval, nr->val.u.fval);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TUP(OEQ, Wlitnil):
|
|
||||||
goto settrue;
|
goto settrue;
|
||||||
case TUP(ONE, Wlitnil):
|
case TUP(ONE, CTNIL):
|
||||||
goto setfalse;
|
goto setfalse;
|
||||||
|
|
||||||
case TUP(OEQ, Wlitint):
|
case TUP(OEQ, CTINT):
|
||||||
if(mpcmpfixfix(xval, nr->val.u.xval) == 0)
|
if(mpcmpfixfix(v.u.xval, nr->val.u.xval) == 0)
|
||||||
goto settrue;
|
goto settrue;
|
||||||
goto setfalse;
|
goto setfalse;
|
||||||
case TUP(ONE, Wlitint):
|
case TUP(ONE, CTINT):
|
||||||
if(mpcmpfixfix(xval, nr->val.u.xval) != 0)
|
if(mpcmpfixfix(v.u.xval, nr->val.u.xval) != 0)
|
||||||
goto settrue;
|
goto settrue;
|
||||||
goto setfalse;
|
goto setfalse;
|
||||||
case TUP(OLT, Wlitint):
|
case TUP(OLT, CTINT):
|
||||||
if(mpcmpfixfix(xval, nr->val.u.xval) < 0)
|
if(mpcmpfixfix(v.u.xval, nr->val.u.xval) < 0)
|
||||||
goto settrue;
|
goto settrue;
|
||||||
goto setfalse;
|
goto setfalse;
|
||||||
case TUP(OLE, Wlitint):
|
case TUP(OLE, CTINT):
|
||||||
if(mpcmpfixfix(xval, nr->val.u.xval) <= 0)
|
if(mpcmpfixfix(v.u.xval, nr->val.u.xval) <= 0)
|
||||||
goto settrue;
|
goto settrue;
|
||||||
goto setfalse;
|
goto setfalse;
|
||||||
case TUP(OGE, Wlitint):
|
case TUP(OGE, CTINT):
|
||||||
if(mpcmpfixfix(xval, nr->val.u.xval) >= 0)
|
if(mpcmpfixfix(v.u.xval, nr->val.u.xval) >= 0)
|
||||||
goto settrue;
|
goto settrue;
|
||||||
goto setfalse;
|
goto setfalse;
|
||||||
case TUP(OGT, Wlitint):
|
case TUP(OGT, CTINT):
|
||||||
if(mpcmpfixfix(xval, nr->val.u.xval) > 0)
|
if(mpcmpfixfix(v.u.xval, nr->val.u.xval) > 0)
|
||||||
goto settrue;
|
goto settrue;
|
||||||
goto setfalse;
|
goto setfalse;
|
||||||
|
|
||||||
case TUP(OEQ, Wlitfloat):
|
case TUP(OEQ, CTFLT):
|
||||||
if(mpcmpfltflt(fval, nr->val.u.fval) == 0)
|
if(mpcmpfltflt(v.u.fval, nr->val.u.fval) == 0)
|
||||||
goto settrue;
|
goto settrue;
|
||||||
goto setfalse;
|
goto setfalse;
|
||||||
case TUP(ONE, Wlitfloat):
|
case TUP(ONE, CTFLT):
|
||||||
if(mpcmpfltflt(fval, nr->val.u.fval) != 0)
|
if(mpcmpfltflt(v.u.fval, nr->val.u.fval) != 0)
|
||||||
goto settrue;
|
goto settrue;
|
||||||
goto setfalse;
|
goto setfalse;
|
||||||
case TUP(OLT, Wlitfloat):
|
case TUP(OLT, CTFLT):
|
||||||
if(mpcmpfltflt(fval, nr->val.u.fval) < 0)
|
if(mpcmpfltflt(v.u.fval, nr->val.u.fval) < 0)
|
||||||
goto settrue;
|
goto settrue;
|
||||||
goto setfalse;
|
goto setfalse;
|
||||||
case TUP(OLE, Wlitfloat):
|
case TUP(OLE, CTFLT):
|
||||||
if(mpcmpfltflt(fval, nr->val.u.fval) <= 0)
|
if(mpcmpfltflt(v.u.fval, nr->val.u.fval) <= 0)
|
||||||
goto settrue;
|
goto settrue;
|
||||||
goto setfalse;
|
goto setfalse;
|
||||||
case TUP(OGE, Wlitfloat):
|
case TUP(OGE, CTFLT):
|
||||||
if(mpcmpfltflt(fval, nr->val.u.fval) >= 0)
|
if(mpcmpfltflt(v.u.fval, nr->val.u.fval) >= 0)
|
||||||
goto settrue;
|
goto settrue;
|
||||||
goto setfalse;
|
goto setfalse;
|
||||||
case TUP(OGT, Wlitfloat):
|
case TUP(OGT, CTFLT):
|
||||||
if(mpcmpfltflt(fval, nr->val.u.fval) > 0)
|
if(mpcmpfltflt(v.u.fval, nr->val.u.fval) > 0)
|
||||||
goto settrue;
|
goto settrue;
|
||||||
goto setfalse;
|
goto setfalse;
|
||||||
|
|
||||||
case TUP(OEQ, Wlitstr):
|
case TUP(OEQ, CTSTR):
|
||||||
if(cmpslit(nl, nr) == 0)
|
if(cmpslit(nl, nr) == 0)
|
||||||
goto settrue;
|
goto settrue;
|
||||||
goto setfalse;
|
goto setfalse;
|
||||||
case TUP(ONE, Wlitstr):
|
case TUP(ONE, CTSTR):
|
||||||
if(cmpslit(nl, nr) != 0)
|
if(cmpslit(nl, nr) != 0)
|
||||||
goto settrue;
|
goto settrue;
|
||||||
goto setfalse;
|
goto setfalse;
|
||||||
case TUP(OLT, Wlitstr):
|
case TUP(OLT, CTSTR):
|
||||||
if(cmpslit(nl, nr) < 0)
|
if(cmpslit(nl, nr) < 0)
|
||||||
goto settrue;
|
goto settrue;
|
||||||
goto setfalse;
|
goto setfalse;
|
||||||
case TUP(OLE, Wlitstr):
|
case TUP(OLE, CTSTR):
|
||||||
if(cmpslit(nl, nr) <= 0)
|
if(cmpslit(nl, nr) <= 0)
|
||||||
goto settrue;
|
goto settrue;
|
||||||
goto setfalse;
|
goto setfalse;
|
||||||
case TUP(OGE, Wlitstr):
|
case TUP(OGE, CTSTR):
|
||||||
if(cmpslit(nl, nr) >= 0l)
|
if(cmpslit(nl, nr) >= 0l)
|
||||||
goto settrue;
|
goto settrue;
|
||||||
goto setfalse;
|
goto setfalse;
|
||||||
case TUP(OGT, Wlitstr):
|
case TUP(OGT, CTSTR):
|
||||||
if(cmpslit(nl, nr) > 0)
|
if(cmpslit(nl, nr) > 0)
|
||||||
goto settrue;
|
goto settrue;
|
||||||
goto setfalse;
|
goto setfalse;
|
||||||
case TUP(OADD, Wlitstr):
|
case TUP(OADD, CTSTR):
|
||||||
len = nl->val.u.sval->len + nr->val.u.sval->len;
|
len = v.u.sval->len + nr->val.u.sval->len;
|
||||||
str = mal(sizeof(*str) + len);
|
str = mal(sizeof(*str) + len);
|
||||||
str->len = len;
|
str->len = len;
|
||||||
memcpy(str->s, nl->val.u.sval->s, nl->val.u.sval->len);
|
memcpy(str->s, v.u.sval->s, v.u.sval->len);
|
||||||
memcpy(str->s+nl->val.u.sval->len, nr->val.u.sval->s, nr->val.u.sval->len);
|
memcpy(str->s+v.u.sval->len, nr->val.u.sval->s, nr->val.u.sval->len);
|
||||||
str->len = len;
|
str->len = len;
|
||||||
nl->val.u.sval = str;
|
v.u.sval = str;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TUP(OOROR, Wlitbool):
|
case TUP(OOROR, CTBOOL):
|
||||||
if(nl->val.u.bval || nr->val.u.bval)
|
if(v.u.bval || nr->val.u.bval)
|
||||||
goto settrue;
|
goto settrue;
|
||||||
goto setfalse;
|
goto setfalse;
|
||||||
case TUP(OANDAND, Wlitbool):
|
case TUP(OANDAND, CTBOOL):
|
||||||
if(nl->val.u.bval && nr->val.u.bval)
|
if(v.u.bval && nr->val.u.bval)
|
||||||
|
goto settrue;
|
||||||
|
goto setfalse;
|
||||||
|
case TUP(OEQ, CTBOOL):
|
||||||
|
if(v.u.bval == nr->val.u.bval)
|
||||||
|
goto settrue;
|
||||||
|
goto setfalse;
|
||||||
|
case TUP(ONE, CTBOOL):
|
||||||
|
if(v.u.bval != nr->val.u.bval)
|
||||||
goto settrue;
|
goto settrue;
|
||||||
goto setfalse;
|
goto setfalse;
|
||||||
}
|
}
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
settrue:
|
|
||||||
*n = *booltrue;
|
|
||||||
return;
|
|
||||||
|
|
||||||
setfalse:
|
|
||||||
*n = *boolfalse;
|
|
||||||
return;
|
|
||||||
|
|
||||||
unary:
|
unary:
|
||||||
if(wl == Wlitint) {
|
// copy numeric value to avoid modifying
|
||||||
xval = mal(sizeof(*xval));
|
// nl, in case someone still refers to it (e.g. iota).
|
||||||
mpmovefixfix(xval, nl->val.u.xval);
|
v = nl->val;
|
||||||
} else
|
if(wl == TIDEAL)
|
||||||
if(wl == Wlitfloat) {
|
v = copyval(v);
|
||||||
fval = mal(sizeof(*fval));
|
|
||||||
mpmovefltflt(fval, nl->val.u.fval);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(TUP(n->op, wl)) {
|
switch(TUP(n->op, v.ctype)) {
|
||||||
default:
|
default:
|
||||||
yyerror("illegal combination of literals %O %d", n->op, wl);
|
yyerror("illegal constant expression %O %T %d", n->op, nl->type, v.ctype);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case TUP(OPLUS, Wlitint):
|
case TUP(OPLUS, CTINT):
|
||||||
break;
|
break;
|
||||||
case TUP(OMINUS, Wlitint):
|
case TUP(OMINUS, CTINT):
|
||||||
mpnegfix(xval);
|
mpnegfix(v.u.xval);
|
||||||
break;
|
break;
|
||||||
case TUP(OCOM, Wlitint):
|
case TUP(OCOM, CTINT):
|
||||||
mpcomfix(xval);
|
mpcomfix(v.u.xval);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TUP(OPLUS, Wlitfloat):
|
case TUP(OPLUS, CTFLT):
|
||||||
break;
|
break;
|
||||||
case TUP(OMINUS, Wlitfloat):
|
case TUP(OMINUS, CTFLT):
|
||||||
mpnegflt(fval);
|
mpnegflt(v.u.fval);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TUP(ONOT, Wlitbool):
|
case TUP(ONOT, CTBOOL):
|
||||||
if(nl->val.u.bval)
|
if(!v.u.bval)
|
||||||
goto settrue;
|
goto settrue;
|
||||||
goto setfalse;
|
goto setfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret:
|
ret:
|
||||||
|
// rewrite n in place.
|
||||||
*n = *nl;
|
*n = *nl;
|
||||||
|
n->val = v;
|
||||||
|
|
||||||
// second half of dance
|
// lose type name if any:
|
||||||
if(wl == Wlitint) {
|
// type T int
|
||||||
n->val.u.xval = xval;
|
// const A T = 1;
|
||||||
} else
|
// A+0 has type int, not T.
|
||||||
if(wl == Wlitfloat) {
|
n->type = types[n->type->etype];
|
||||||
n->val.u.fval = fval;
|
|
||||||
truncfltlit(fval, n->type);
|
// check range.
|
||||||
|
lno = lineno;
|
||||||
|
lineno = n->lineno;
|
||||||
|
overflow(v, n->type);
|
||||||
|
lineno = lno;
|
||||||
|
|
||||||
|
// truncate precision for non-ideal float.
|
||||||
|
if(v.ctype == CTFLT && n->type->etype != TIDEAL)
|
||||||
|
truncfltlit(v.u.fval, n->type);
|
||||||
|
return;
|
||||||
|
|
||||||
|
settrue:
|
||||||
|
*n = *nodbool(1);
|
||||||
|
return;
|
||||||
|
|
||||||
|
setfalse:
|
||||||
|
*n = *nodbool(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node*
|
||||||
|
nodlit(Val v)
|
||||||
|
{
|
||||||
|
Node *n;
|
||||||
|
|
||||||
|
n = nod(OLITERAL, N, N);
|
||||||
|
n->val = v;
|
||||||
|
switch(v.ctype) {
|
||||||
|
default:
|
||||||
|
fatal("nodlit ctype %d", v.ctype);
|
||||||
|
case CTSTR:
|
||||||
|
n->type = types[TSTRING];
|
||||||
|
break;
|
||||||
|
case CTBOOL:
|
||||||
|
n->type = types[TBOOL];
|
||||||
|
break;
|
||||||
|
case CTINT:
|
||||||
|
case CTFLT:
|
||||||
|
n->type = types[TIDEAL];
|
||||||
|
break;
|
||||||
|
case CTNIL:
|
||||||
|
n->type = types[TNIL];
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
defaultlit(Node *n)
|
defaultlit(Node *n, Type *t)
|
||||||
{
|
{
|
||||||
|
int lno;
|
||||||
|
|
||||||
if(n == N)
|
if(n == N)
|
||||||
return;
|
return;
|
||||||
if(n->type != T)
|
if(n->type == T || n->type->etype != TIDEAL)
|
||||||
return;
|
|
||||||
if(n->op != OLITERAL)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
switch(n->op) {
|
||||||
|
case OLITERAL:
|
||||||
|
break;
|
||||||
|
case OLSH:
|
||||||
|
case ORSH:
|
||||||
|
defaultlit(n->left, t);
|
||||||
|
n->type = n->left->type;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lno = 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:
|
||||||
case CTSINT:
|
|
||||||
case CTUINT:
|
|
||||||
n->type = types[TINT];
|
n->type = types[TINT];
|
||||||
|
if(t != T) {
|
||||||
|
if(isint[t->etype])
|
||||||
|
n->type = t;
|
||||||
|
else if(isfloat[t->etype]) {
|
||||||
|
n->type = t;
|
||||||
|
n->val = toflt(n->val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
overflow(n->val, n->type);
|
||||||
break;
|
break;
|
||||||
case CTFLT:
|
case CTFLT:
|
||||||
n->type = types[TFLOAT];
|
n->type = types[TFLOAT];
|
||||||
break;
|
if(t != T) {
|
||||||
case CTBOOL:
|
if(isfloat[t->etype])
|
||||||
n->type = types[TBOOL];
|
n->type = t;
|
||||||
break;
|
else if(isint[t->etype]) {
|
||||||
case CTSTR:
|
n->type = t;
|
||||||
n->type = types[TSTRING];
|
n->val = toint(n->val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
overflow(n->val, n->type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
lineno = lno;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* defaultlit on both nodes simultaneously;
|
||||||
|
* if they're both ideal going in they better
|
||||||
|
* get the same type going out.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
defaultlit2(Node *l, Node *r)
|
||||||
|
{
|
||||||
|
if(l->type == T || r->type == T)
|
||||||
|
return;
|
||||||
|
if(l->type->etype != TIDEAL && l->type->etype != TNIL) {
|
||||||
|
convlit(r, l->type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(r->type->etype != TIDEAL && r->type->etype != TNIL) {
|
||||||
|
convlit(l, r->type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(isconst(l, CTFLT) || isconst(r, CTFLT)) {
|
||||||
|
convlit(l, types[TFLOAT]);
|
||||||
|
convlit(r, types[TFLOAT]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
convlit(l, types[TINT]);
|
||||||
|
convlit(r, types[TINT]);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -23,6 +23,8 @@ dodclvar(Node *n, Type *t)
|
|||||||
if(n == N)
|
if(n == N)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if(t != T && (t->etype == TIDEAL || t->etype == TNIL))
|
||||||
|
fatal("dodclvar %T", t);
|
||||||
for(; n->op == OLIST; n = n->right)
|
for(; n->op == OLIST; n = n->right)
|
||||||
dodclvar(n->left, t);
|
dodclvar(n->left, t);
|
||||||
|
|
||||||
@ -1284,7 +1286,7 @@ fninit(Node *n)
|
|||||||
r = list(r, a);
|
r = list(r, a);
|
||||||
|
|
||||||
// (4)
|
// (4)
|
||||||
a = nod(OAS, done, booltrue);
|
a = nod(OAS, done, nodbool(1));
|
||||||
r = list(r, a);
|
r = list(r, a);
|
||||||
|
|
||||||
// (5)
|
// (5)
|
||||||
@ -1460,7 +1462,7 @@ loop:
|
|||||||
a = nod(OAS, v, N);
|
a = nod(OAS, v, N);
|
||||||
if(t == T) {
|
if(t == T) {
|
||||||
gettype(e, a);
|
gettype(e, a);
|
||||||
defaultlit(e);
|
defaultlit(e, T);
|
||||||
dodclvar(v, e->type);
|
dodclvar(v, e->type);
|
||||||
} else
|
} else
|
||||||
dodclvar(v, t);
|
dodclvar(v, t);
|
||||||
@ -1475,7 +1477,7 @@ loop:
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* declare constants from grammar
|
* declare constants from grammar
|
||||||
* new_name_list [type] [= expr_list]
|
* new_name_list [[type] = expr_list]
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
constiter(Node *vv, Type *t, Node *cc)
|
constiter(Node *vv, Type *t, Node *cc)
|
||||||
@ -1483,9 +1485,14 @@ constiter(Node *vv, Type *t, Node *cc)
|
|||||||
Iter viter, citer;
|
Iter viter, citer;
|
||||||
Node *v, *c;
|
Node *v, *c;
|
||||||
|
|
||||||
if(cc == N)
|
if(cc == N) {
|
||||||
|
if(t != T)
|
||||||
|
yyerror("constdcl cannot have type without expr");
|
||||||
cc = lastconst;
|
cc = lastconst;
|
||||||
|
t = lasttype;
|
||||||
|
}
|
||||||
lastconst = cc;
|
lastconst = cc;
|
||||||
|
lasttype = t;
|
||||||
vv = rev(vv);
|
vv = rev(vv);
|
||||||
cc = rev(treecopy(cc));
|
cc = rev(treecopy(cc));
|
||||||
|
|
||||||
@ -1499,7 +1506,7 @@ loop:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(v == N || c == N) {
|
if(v == N || c == N) {
|
||||||
yyerror("shape error in var dcl");
|
yyerror("shape error in const dcl");
|
||||||
iota += 1;
|
iota += 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1507,6 +1514,8 @@ loop:
|
|||||||
gettype(c, N);
|
gettype(c, N);
|
||||||
if(t != T)
|
if(t != T)
|
||||||
convlit(c, t);
|
convlit(c, t);
|
||||||
|
if(t == T)
|
||||||
|
lasttype = c->type;
|
||||||
dodclconst(v, c);
|
dodclconst(v, c);
|
||||||
|
|
||||||
v = listnext(&viter);
|
v = listnext(&viter);
|
||||||
@ -1587,5 +1596,6 @@ yes:
|
|||||||
mpmovecfix(val.u.xval, v);
|
mpmovecfix(val.u.xval, v);
|
||||||
n = nod(OLITERAL, N, N);
|
n = nod(OLITERAL, N, N);
|
||||||
n->val = val;
|
n->val = val;
|
||||||
|
n->type = types[TINT];
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ dumpexportconst(Sym *s)
|
|||||||
|
|
||||||
Bprint(bout, "\t");
|
Bprint(bout, "\t");
|
||||||
Bprint(bout, "const %lS", s);
|
Bprint(bout, "const %lS", s);
|
||||||
if(t != T)
|
if(t != T && t->etype != TIDEAL)
|
||||||
Bprint(bout, " %#T", t);
|
Bprint(bout, " %#T", t);
|
||||||
Bprint(bout, " = ");
|
Bprint(bout, " = ");
|
||||||
|
|
||||||
@ -118,8 +118,6 @@ dumpexportconst(Sym *s)
|
|||||||
default:
|
default:
|
||||||
fatal("dumpexportconst: unknown ctype: %S", s);
|
fatal("dumpexportconst: unknown ctype: %S", s);
|
||||||
case CTINT:
|
case CTINT:
|
||||||
case CTSINT:
|
|
||||||
case CTUINT:
|
|
||||||
Bprint(bout, "%B\n", n->val.u.xval);
|
Bprint(bout, "%B\n", n->val.u.xval);
|
||||||
break;
|
break;
|
||||||
case CTBOOL:
|
case CTBOOL:
|
||||||
@ -343,18 +341,14 @@ mypackage(Node *ss)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
importconst(Node *ss, Type *t, Val *v)
|
importconst(Node *ss, Type *t, Node *n)
|
||||||
{
|
{
|
||||||
Node *n;
|
|
||||||
Sym *s;
|
Sym *s;
|
||||||
|
|
||||||
if(!exportname(ss->sym->name) && !mypackage(ss))
|
if(!exportname(ss->sym->name) && !mypackage(ss))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
n = nod(OLITERAL, N, N);
|
convlit(n, t);
|
||||||
n->val = *v;
|
|
||||||
n->type = t;
|
|
||||||
|
|
||||||
s = importsym(ss, LACONST);
|
s = importsym(ss, LACONST);
|
||||||
if(s->oconst != N) {
|
if(s->oconst != N) {
|
||||||
// TODO: check if already the same.
|
// TODO: check if already the same.
|
||||||
@ -363,7 +357,7 @@ importconst(Node *ss, Type *t, Val *v)
|
|||||||
|
|
||||||
dodclconst(newname(s), n);
|
dodclconst(newname(s), n);
|
||||||
|
|
||||||
if(debug['e'])
|
if(debug['E'])
|
||||||
print("import const %S\n", s);
|
print("import const %S\n", s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,7 +379,7 @@ importvar(Node *ss, Type *t, int ctxt)
|
|||||||
checkwidth(t);
|
checkwidth(t);
|
||||||
addvar(newname(s), t, ctxt);
|
addvar(newname(s), t, ctxt);
|
||||||
|
|
||||||
if(debug['e'])
|
if(debug['E'])
|
||||||
print("import var %S %lT\n", s, t);
|
print("import var %S %lT\n", s, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -410,7 +404,7 @@ importtype(Node *ss, Type *t)
|
|||||||
s->otype->sym = s;
|
s->otype->sym = s;
|
||||||
checkwidth(s->otype);
|
checkwidth(s->otype);
|
||||||
|
|
||||||
if(debug['e'])
|
if(debug['E'])
|
||||||
print("import type %S %lT\n", s, t);
|
print("import type %S %lT\n", s, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,6 +371,10 @@ enum
|
|||||||
TFORWSTRUCT,
|
TFORWSTRUCT,
|
||||||
TFORWINTER,
|
TFORWINTER,
|
||||||
|
|
||||||
|
// pseudo-types for literals
|
||||||
|
TIDEAL,
|
||||||
|
TNIL,
|
||||||
|
|
||||||
NTYPE,
|
NTYPE,
|
||||||
};
|
};
|
||||||
enum
|
enum
|
||||||
@ -378,35 +382,12 @@ enum
|
|||||||
CTxxx,
|
CTxxx,
|
||||||
|
|
||||||
CTINT,
|
CTINT,
|
||||||
CTSINT,
|
|
||||||
CTUINT,
|
|
||||||
CTFLT,
|
CTFLT,
|
||||||
|
|
||||||
CTSTR,
|
CTSTR,
|
||||||
CTBOOL,
|
CTBOOL,
|
||||||
CTNIL,
|
CTNIL,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
/* indications for whatis() */
|
|
||||||
Wnil = 0,
|
|
||||||
Wtnil,
|
|
||||||
|
|
||||||
Wtfloat,
|
|
||||||
Wtint,
|
|
||||||
Wtbool,
|
|
||||||
Wtstr,
|
|
||||||
|
|
||||||
Wlitfloat,
|
|
||||||
Wlitint,
|
|
||||||
Wlitbool,
|
|
||||||
Wlitstr,
|
|
||||||
Wlitnil,
|
|
||||||
|
|
||||||
Wtunkn,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
/* types of channel */
|
/* types of channel */
|
||||||
@ -518,10 +499,9 @@ EXTERN int dclcontext; // PEXTERN/PAUTO
|
|||||||
EXTERN int importflag;
|
EXTERN int importflag;
|
||||||
EXTERN int inimportsys;
|
EXTERN int inimportsys;
|
||||||
|
|
||||||
EXTERN Node* booltrue;
|
|
||||||
EXTERN Node* boolfalse;
|
|
||||||
EXTERN uint32 iota;
|
EXTERN uint32 iota;
|
||||||
EXTERN Node* lastconst;
|
EXTERN Node* lastconst;
|
||||||
|
EXTERN Type* lasttype;
|
||||||
EXTERN int32 vargen;
|
EXTERN int32 vargen;
|
||||||
EXTERN int32 exportgen;
|
EXTERN int32 exportgen;
|
||||||
EXTERN int32 maxarg;
|
EXTERN int32 maxarg;
|
||||||
@ -594,7 +574,7 @@ void mpdivfixfix(Mpint *a, Mpint *b);
|
|||||||
void mpmodfixfix(Mpint *a, Mpint *b);
|
void mpmodfixfix(Mpint *a, Mpint *b);
|
||||||
void mpatofix(Mpint *a, char *s);
|
void mpatofix(Mpint *a, char *s);
|
||||||
void mpatoflt(Mpflt *a, char *s);
|
void mpatoflt(Mpflt *a, char *s);
|
||||||
void mpmovefltfix(Mpint *a, Mpflt *b);
|
int mpmovefltfix(Mpint *a, Mpflt *b);
|
||||||
void mpmovefixflt(Mpflt *a, Mpint *b);
|
void mpmovefixflt(Mpflt *a, Mpint *b);
|
||||||
int Bconv(Fmt*);
|
int Bconv(Fmt*);
|
||||||
|
|
||||||
@ -611,7 +591,7 @@ void mpdivmodfixfix(Mpint *q, Mpint *r, Mpint *n, Mpint *d);
|
|||||||
void mpdivfract(Mpint *a, Mpint *b);
|
void mpdivfract(Mpint *a, Mpint *b);
|
||||||
void mpnegfix(Mpint *a);
|
void mpnegfix(Mpint *a);
|
||||||
void mpandfixfix(Mpint *a, Mpint *b);
|
void mpandfixfix(Mpint *a, Mpint *b);
|
||||||
void mpnotandfixfix(Mpint *a, Mpint *b);
|
void mpandnotfixfix(Mpint *a, Mpint *b);
|
||||||
void mplshfixfix(Mpint *a, Mpint *b);
|
void mplshfixfix(Mpint *a, Mpint *b);
|
||||||
void mporfixfix(Mpint *a, Mpint *b);
|
void mporfixfix(Mpint *a, Mpint *b);
|
||||||
void mprshfixfix(Mpint *a, Mpint *b);
|
void mprshfixfix(Mpint *a, Mpint *b);
|
||||||
@ -651,6 +631,7 @@ void fatal(char*, ...);
|
|||||||
void linehist(char*, int32);
|
void linehist(char*, int32);
|
||||||
int32 setlineno(Node*);
|
int32 setlineno(Node*);
|
||||||
Node* nod(int, Node*, Node*);
|
Node* nod(int, Node*, Node*);
|
||||||
|
Node* nodlit(Val);
|
||||||
Node* list(Node*, Node*);
|
Node* list(Node*, Node*);
|
||||||
Type* typ(int);
|
Type* typ(int);
|
||||||
Dcl* dcl(void);
|
Dcl* dcl(void);
|
||||||
@ -680,9 +661,10 @@ void argtype(Node*, Type*);
|
|||||||
int eqargs(Type*, Type*);
|
int eqargs(Type*, Type*);
|
||||||
uint32 typehash(Type*, int);
|
uint32 typehash(Type*, int);
|
||||||
void frame(int);
|
void frame(int);
|
||||||
Node* literal(int32);
|
|
||||||
Node* dobad(void);
|
Node* dobad(void);
|
||||||
Node* nodintconst(int32);
|
Node* nodintconst(int64);
|
||||||
|
Node* nodnil(void);
|
||||||
|
Node* nodbool(int);
|
||||||
void ullmancalc(Node*);
|
void ullmancalc(Node*);
|
||||||
void badtype(int, Type*, Type*);
|
void badtype(int, Type*, Type*);
|
||||||
Type* ptrto(Type*);
|
Type* ptrto(Type*);
|
||||||
@ -735,7 +717,8 @@ void dodclvar(Node*, Type*);
|
|||||||
Type* dodcltype(Type*);
|
Type* dodcltype(Type*);
|
||||||
void updatetype(Type*, Type*);
|
void updatetype(Type*, Type*);
|
||||||
void dodclconst(Node*, Node*);
|
void dodclconst(Node*, Node*);
|
||||||
void defaultlit(Node*);
|
void defaultlit(Node*, Type*);
|
||||||
|
void defaultlit2(Node*, Node*);
|
||||||
int listcount(Node*);
|
int listcount(Node*);
|
||||||
void addmethod(Node*, Type*, int);
|
void addmethod(Node*, Type*, int);
|
||||||
Node* methodname(Node*, Type*);
|
Node* methodname(Node*, Type*);
|
||||||
@ -806,7 +789,7 @@ void doimport6(Node*, Node*);
|
|||||||
void doimport7(Node*, Node*);
|
void doimport7(Node*, Node*);
|
||||||
void doimport8(Node*, Val*, Node*);
|
void doimport8(Node*, Val*, Node*);
|
||||||
void doimport9(Sym*, Node*);
|
void doimport9(Sym*, Node*);
|
||||||
void importconst(Node *ss, Type *t, Val *v);
|
void importconst(Node *ss, Type *t, Node *v);
|
||||||
void importmethod(Sym *s, Type *t);
|
void importmethod(Sym *s, Type *t);
|
||||||
void importtype(Node *ss, Type *t);
|
void importtype(Node *ss, Type *t);
|
||||||
void importvar(Node *ss, Type *t, int ctxt);
|
void importvar(Node *ss, Type *t, int ctxt);
|
||||||
@ -826,7 +809,6 @@ void walkas(Node*);
|
|||||||
void walkbool(Node*);
|
void walkbool(Node*);
|
||||||
void walkswitch(Node*);
|
void walkswitch(Node*);
|
||||||
void walkselect(Node*);
|
void walkselect(Node*);
|
||||||
int whatis(Node*);
|
|
||||||
void walkdot(Node*);
|
void walkdot(Node*);
|
||||||
Node* ascompatee(int, Node**, Node**);
|
Node* ascompatee(int, Node**, Node**);
|
||||||
Node* ascompatet(int, Node**, Type**, int);
|
Node* ascompatet(int, Node**, Type**, int);
|
||||||
@ -871,6 +853,8 @@ void convlit(Node*, Type*);
|
|||||||
void evconst(Node*);
|
void evconst(Node*);
|
||||||
int cmpslit(Node *l, Node *r);
|
int cmpslit(Node *l, Node *r);
|
||||||
int smallintconst(Node*);
|
int smallintconst(Node*);
|
||||||
|
int consttype(Node*);
|
||||||
|
int isconst(Node*, int);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* gen.c/gsubr.c/obj.c
|
* gen.c/gsubr.c/obj.c
|
||||||
|
@ -73,7 +73,7 @@
|
|||||||
%type <type> indcl fnlitdcl dotdotdot
|
%type <type> indcl fnlitdcl dotdotdot
|
||||||
%type <val> oliteral
|
%type <val> oliteral
|
||||||
|
|
||||||
%type <val> hidden_constant
|
%type <node> hidden_constant
|
||||||
%type <node> hidden_dcl hidden_structdcl
|
%type <node> hidden_dcl hidden_structdcl
|
||||||
%type <type> hidden_type hidden_type1 hidden_type2
|
%type <type> hidden_type hidden_type1 hidden_type2
|
||||||
%type <node> hidden_structdcl_list ohidden_structdcl_list hidden_structdcl_list_r
|
%type <node> hidden_structdcl_list ohidden_structdcl_list hidden_structdcl_list_r
|
||||||
@ -447,12 +447,12 @@ simple_stmt:
|
|||||||
}
|
}
|
||||||
| expr LINC
|
| expr LINC
|
||||||
{
|
{
|
||||||
$$ = nod(OASOP, $1, literal(1));
|
$$ = nod(OASOP, $1, nodintconst(1));
|
||||||
$$->etype = OADD;
|
$$->etype = OADD;
|
||||||
}
|
}
|
||||||
| expr LDEC
|
| expr LDEC
|
||||||
{
|
{
|
||||||
$$ = nod(OASOP, $1, literal(1));
|
$$ = nod(OASOP, $1, nodintconst(1));
|
||||||
$$->etype = OSUB;
|
$$->etype = OSUB;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -822,10 +822,22 @@ uexpr:
|
|||||||
pexpr:
|
pexpr:
|
||||||
LLITERAL
|
LLITERAL
|
||||||
{
|
{
|
||||||
$$ = nod(OLITERAL, N, N);
|
$$ = nodlit($1);
|
||||||
$$->val = $1;
|
}
|
||||||
if($1.ctype == CTSTR)
|
| LNIL
|
||||||
$$->type = types[TSTRING];
|
{
|
||||||
|
Val v;
|
||||||
|
|
||||||
|
v.ctype = CTNIL;
|
||||||
|
$$ = nodlit(v);
|
||||||
|
}
|
||||||
|
| LTRUE
|
||||||
|
{
|
||||||
|
$$ = nodbool(1);
|
||||||
|
}
|
||||||
|
| LFALSE
|
||||||
|
{
|
||||||
|
$$ = nodbool(0);
|
||||||
}
|
}
|
||||||
| laconst
|
| laconst
|
||||||
{
|
{
|
||||||
@ -833,22 +845,9 @@ pexpr:
|
|||||||
$$->val = $1->oconst->val;
|
$$->val = $1->oconst->val;
|
||||||
$$->type = $1->oconst->type;
|
$$->type = $1->oconst->type;
|
||||||
}
|
}
|
||||||
| LNIL
|
|
||||||
{
|
|
||||||
$$ = nod(OLITERAL, N, N);
|
|
||||||
$$->val.ctype = CTNIL;
|
|
||||||
}
|
|
||||||
| LTRUE
|
|
||||||
{
|
|
||||||
$$ = booltrue;
|
|
||||||
}
|
|
||||||
| LFALSE
|
|
||||||
{
|
|
||||||
$$ = boolfalse;
|
|
||||||
}
|
|
||||||
| LIOTA
|
| LIOTA
|
||||||
{
|
{
|
||||||
$$ = literal(iota);
|
$$ = nodintconst(iota);
|
||||||
$$->iota = 1; // flag to reevaluate on copy
|
$$->iota = 1; // flag to reevaluate on copy
|
||||||
}
|
}
|
||||||
| name
|
| name
|
||||||
@ -1828,11 +1827,11 @@ hidden_import:
|
|||||||
}
|
}
|
||||||
| LCONST hidden_pkg_importsym '=' hidden_constant
|
| LCONST hidden_pkg_importsym '=' hidden_constant
|
||||||
{
|
{
|
||||||
importconst($2, T, &$4);
|
importconst($2, types[TIDEAL], $4);
|
||||||
}
|
}
|
||||||
| LCONST hidden_pkg_importsym hidden_type '=' hidden_constant
|
| LCONST hidden_pkg_importsym hidden_type '=' hidden_constant
|
||||||
{
|
{
|
||||||
importconst($2, $3, &$5);
|
importconst($2, $3, $5);
|
||||||
}
|
}
|
||||||
| LTYPE hidden_pkg_importsym hidden_type
|
| LTYPE hidden_pkg_importsym hidden_type
|
||||||
{
|
{
|
||||||
@ -1870,11 +1869,7 @@ hidden_type1:
|
|||||||
}
|
}
|
||||||
| '[' LLITERAL ']' hidden_type
|
| '[' LLITERAL ']' hidden_type
|
||||||
{
|
{
|
||||||
Node *n;
|
$$ = aindex(nodlit($2), $4);
|
||||||
|
|
||||||
n = nod(OLITERAL, N, N);
|
|
||||||
n->val = $2;
|
|
||||||
$$ = aindex(n, $4);
|
|
||||||
}
|
}
|
||||||
| LMAP '[' hidden_type ']' hidden_type
|
| LMAP '[' hidden_type ']' hidden_type
|
||||||
{
|
{
|
||||||
@ -1978,15 +1973,18 @@ hidden_funres:
|
|||||||
|
|
||||||
hidden_constant:
|
hidden_constant:
|
||||||
LLITERAL
|
LLITERAL
|
||||||
|
{
|
||||||
|
$$ = nodlit($1);
|
||||||
|
}
|
||||||
| '-' LLITERAL
|
| '-' LLITERAL
|
||||||
{
|
{
|
||||||
$$ = $2;
|
$$ = nodlit($2);
|
||||||
switch($$.ctype){
|
switch($$->val.ctype){
|
||||||
case CTINT:
|
case CTINT:
|
||||||
mpnegfix($$.u.xval);
|
mpnegfix($$->val.u.xval);
|
||||||
break;
|
break;
|
||||||
case CTFLT:
|
case CTFLT:
|
||||||
mpnegflt($$.u.fval);
|
mpnegflt($$->val.u.fval);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
yyerror("bad negated constant");
|
yyerror("bad negated constant");
|
||||||
@ -1994,11 +1992,11 @@ hidden_constant:
|
|||||||
}
|
}
|
||||||
| LTRUE
|
| LTRUE
|
||||||
{
|
{
|
||||||
$$ = booltrue->val;
|
$$ = nodbool(1);
|
||||||
}
|
}
|
||||||
| LFALSE
|
| LFALSE
|
||||||
{
|
{
|
||||||
$$ = boolfalse->val;
|
$$ = nodbool(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
hidden_importsym:
|
hidden_importsym:
|
||||||
|
@ -58,7 +58,6 @@ mainlex(int argc, char *argv[])
|
|||||||
fmtinstall('L', Lconv); // line number
|
fmtinstall('L', Lconv); // line number
|
||||||
fmtinstall('B', Bconv); // big numbers
|
fmtinstall('B', Bconv); // big numbers
|
||||||
fmtinstall('F', Fconv); // big float numbers
|
fmtinstall('F', Fconv); // big float numbers
|
||||||
fmtinstall('W', Wconv); // whatis numbers (Wlitint)
|
|
||||||
|
|
||||||
lexinit();
|
lexinit();
|
||||||
lineno = 1;
|
lineno = 1;
|
||||||
@ -115,13 +114,14 @@ usage:
|
|||||||
print("flags:\n");
|
print("flags:\n");
|
||||||
print(" -I DIR search for packages in DIR\n");
|
print(" -I DIR search for packages in DIR\n");
|
||||||
print(" -d print declarations\n");
|
print(" -d print declarations\n");
|
||||||
|
print(" -e no limit on number of errors printed\n");
|
||||||
print(" -f print stack frame structure\n");
|
print(" -f print stack frame structure\n");
|
||||||
|
print(" -h panic on an error\n");
|
||||||
print(" -k name specify package name\n");
|
print(" -k name specify package name\n");
|
||||||
print(" -o file specify output file\n");
|
print(" -o file specify output file\n");
|
||||||
print(" -p print the assembly language\n");
|
print(" -p print the assembly language\n");
|
||||||
print(" -w print the parse tree after typing\n");
|
print(" -w print the parse tree after typing\n");
|
||||||
print(" -x print lex tokens\n");
|
print(" -x print lex tokens\n");
|
||||||
print(" -h panic on an error\n");
|
|
||||||
myexit(0);
|
myexit(0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1276,20 +1276,12 @@ lexinit(void)
|
|||||||
/* for walk to use in error messages */
|
/* for walk to use in error messages */
|
||||||
types[TFUNC] = functype(N, N, N);
|
types[TFUNC] = functype(N, N, N);
|
||||||
|
|
||||||
|
/* types used in front end */
|
||||||
|
types[TNIL] = typ(TNIL);
|
||||||
|
types[TIDEAL] = typ(TIDEAL);
|
||||||
|
|
||||||
/* pick up the backend typedefs */
|
/* pick up the backend typedefs */
|
||||||
belexinit(LBASETYPE);
|
belexinit(LBASETYPE);
|
||||||
|
|
||||||
booltrue = nod(OLITERAL, N, N);
|
|
||||||
booltrue->val.u.bval = 1;
|
|
||||||
booltrue->val.ctype = CTBOOL;
|
|
||||||
booltrue->type = types[TBOOL];
|
|
||||||
booltrue->addable = 1;
|
|
||||||
|
|
||||||
boolfalse = nod(OLITERAL, N, N);
|
|
||||||
boolfalse->val.u.bval = 0;
|
|
||||||
boolfalse->val.ctype = CTBOOL;
|
|
||||||
boolfalse->type = types[TBOOL];
|
|
||||||
boolfalse->addable = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct
|
struct
|
||||||
|
@ -154,10 +154,22 @@ mpmovefixflt(Mpflt *a, Mpint *b)
|
|||||||
mpnorm(a);
|
mpnorm(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
// convert (truncate) b to a.
|
||||||
|
// return -1 (but still convert) if b was non-integer.
|
||||||
|
int
|
||||||
mpmovefltfix(Mpint *a, Mpflt *b)
|
mpmovefltfix(Mpint *a, Mpflt *b)
|
||||||
{
|
{
|
||||||
mpmovecfix(a, mpgetflt(b));
|
Mpflt f;
|
||||||
|
*a = b->val;
|
||||||
|
mpshiftfix(a, b->exp);
|
||||||
|
if(b->exp < 0) {
|
||||||
|
f.val = *a;
|
||||||
|
f.exp = 0;
|
||||||
|
mpnorm(&f);
|
||||||
|
if(mpcmpfltflt(b, &f) != 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -303,7 +315,7 @@ bad:
|
|||||||
//
|
//
|
||||||
// fixed point input
|
// fixed point input
|
||||||
// required syntax is [+-][0[x]]d*
|
// required syntax is [+-][0[x]]d*
|
||||||
//
|
//
|
||||||
void
|
void
|
||||||
mpatofix(Mpint *a, char *as)
|
mpatofix(Mpint *a, char *as)
|
||||||
{
|
{
|
||||||
@ -422,8 +434,20 @@ Fconv(Fmt *fp)
|
|||||||
{
|
{
|
||||||
char buf[500];
|
char buf[500];
|
||||||
Mpflt *fvp, fv;
|
Mpflt *fvp, fv;
|
||||||
|
double d;
|
||||||
|
|
||||||
fvp = va_arg(fp->args, Mpflt*);
|
fvp = va_arg(fp->args, Mpflt*);
|
||||||
|
if(fp->flags & FmtSharp) {
|
||||||
|
// alternate form - decimal for error messages.
|
||||||
|
// for well in range, convert to double and use print's %g
|
||||||
|
if(-900 < fvp->exp && fvp->exp < 900) {
|
||||||
|
d = mpgetflt(fvp);
|
||||||
|
return fmtprint(fp, "%g", d);
|
||||||
|
}
|
||||||
|
// TODO(rsc): for well out of range, print
|
||||||
|
// an approximation like 1.234e1000
|
||||||
|
}
|
||||||
|
|
||||||
if(sigfig(fvp) == 0) {
|
if(sigfig(fvp) == 0) {
|
||||||
snprint(buf, sizeof(buf), "0p+0");
|
snprint(buf, sizeof(buf), "0p+0");
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -159,6 +159,7 @@ mpneg(Mpint *a)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// shift left by s (or right by -s)
|
||||||
void
|
void
|
||||||
mpshiftfix(Mpint *a, int s)
|
mpshiftfix(Mpint *a, int s)
|
||||||
{
|
{
|
||||||
|
@ -29,7 +29,7 @@ yyerror(char *fmt, ...)
|
|||||||
*(int*)0 = 0;
|
*(int*)0 = 0;
|
||||||
|
|
||||||
nerrors++;
|
nerrors++;
|
||||||
if(nerrors >= 10)
|
if(nerrors >= 10 && !debug['e'])
|
||||||
fatal("too many errors");
|
fatal("too many errors");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -351,7 +351,7 @@ dobad(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Node*
|
Node*
|
||||||
nodintconst(int32 v)
|
nodintconst(int64 v)
|
||||||
{
|
{
|
||||||
Node *c;
|
Node *c;
|
||||||
|
|
||||||
@ -360,11 +360,34 @@ nodintconst(int32 v)
|
|||||||
c->val.u.xval = mal(sizeof(*c->val.u.xval));
|
c->val.u.xval = mal(sizeof(*c->val.u.xval));
|
||||||
mpmovecfix(c->val.u.xval, v);
|
mpmovecfix(c->val.u.xval, v);
|
||||||
c->val.ctype = CTINT;
|
c->val.ctype = CTINT;
|
||||||
c->type = types[TINT];
|
c->type = types[TIDEAL];
|
||||||
ullmancalc(c);
|
ullmancalc(c);
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node*
|
||||||
|
nodnil(void)
|
||||||
|
{
|
||||||
|
Node *c;
|
||||||
|
|
||||||
|
c = nodintconst(0);
|
||||||
|
c->val.ctype = CTNIL;
|
||||||
|
c->type = types[TNIL];
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node*
|
||||||
|
nodbool(int b)
|
||||||
|
{
|
||||||
|
Node *c;
|
||||||
|
|
||||||
|
c = nodintconst(0);
|
||||||
|
c->val.ctype = CTBOOL;
|
||||||
|
c->val.u.bval = b;
|
||||||
|
c->type = types[TBOOL];
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
Node*
|
Node*
|
||||||
rev(Node *na)
|
rev(Node *na)
|
||||||
{
|
{
|
||||||
@ -437,19 +460,17 @@ aindex(Node *b, Type *t)
|
|||||||
|
|
||||||
bound = -1; // open bound
|
bound = -1; // open bound
|
||||||
walktype(b, Erv);
|
walktype(b, Erv);
|
||||||
switch(whatis(b)) {
|
if(b != nil) {
|
||||||
default: // variable bound
|
switch(consttype(b)) {
|
||||||
yyerror("array bound must be an integer expression");
|
default:
|
||||||
break;
|
yyerror("array bound must be an integer expression");
|
||||||
|
break;
|
||||||
case Wnil: // open bound
|
case CTINT:
|
||||||
break;
|
bound = mpgetfix(b->val.u.xval);
|
||||||
|
if(bound < 0)
|
||||||
case Wlitint: // fixed bound
|
yyerror("array bound must be non negative");
|
||||||
bound = mpgetfix(b->val.u.xval);
|
break;
|
||||||
if(bound < 0)
|
}
|
||||||
yyerror("array bound must be non negative");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// fixed array
|
// fixed array
|
||||||
@ -569,64 +590,6 @@ dump(char *s, Node *n)
|
|||||||
dodump(n, 1);
|
dodump(n, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
whatis(Node *n)
|
|
||||||
{
|
|
||||||
Type *t;
|
|
||||||
|
|
||||||
if(n == N)
|
|
||||||
return Wnil;
|
|
||||||
|
|
||||||
if(n->op == OLITERAL) {
|
|
||||||
switch(n->val.ctype) {
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
case CTINT:
|
|
||||||
case CTSINT:
|
|
||||||
case CTUINT:
|
|
||||||
return Wlitint;
|
|
||||||
case CTFLT:
|
|
||||||
return Wlitfloat;
|
|
||||||
case CTBOOL:
|
|
||||||
return Wlitbool;
|
|
||||||
case CTSTR:
|
|
||||||
return Wlitstr;
|
|
||||||
case CTNIL:
|
|
||||||
return Wlitnil; // not used
|
|
||||||
}
|
|
||||||
return Wtunkn;
|
|
||||||
}
|
|
||||||
|
|
||||||
t = n->type;
|
|
||||||
if(t == T)
|
|
||||||
return Wtnil;
|
|
||||||
|
|
||||||
switch(t->etype) {
|
|
||||||
case TINT:
|
|
||||||
case TINT8:
|
|
||||||
case TINT16:
|
|
||||||
case TINT32:
|
|
||||||
case TINT64:
|
|
||||||
case TUINT:
|
|
||||||
case TUINT8:
|
|
||||||
case TUINT16:
|
|
||||||
case TUINT32:
|
|
||||||
case TUINT64:
|
|
||||||
case TUINTPTR:
|
|
||||||
return Wtint;
|
|
||||||
case TFLOAT:
|
|
||||||
case TFLOAT32:
|
|
||||||
case TFLOAT64:
|
|
||||||
case TFLOAT80:
|
|
||||||
return Wtfloat;
|
|
||||||
case TBOOL:
|
|
||||||
return Wtbool;
|
|
||||||
case TSTRING:
|
|
||||||
return Wtstr;
|
|
||||||
}
|
|
||||||
return Wtunkn;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
s%,%,\n%g
|
s%,%,\n%g
|
||||||
s%\n+%\n%g
|
s%\n+%\n%g
|
||||||
@ -1013,6 +976,8 @@ basicnames[] =
|
|||||||
[TANY] = "any",
|
[TANY] = "any",
|
||||||
[TDDD] = "...",
|
[TDDD] = "...",
|
||||||
[TSTRING] = "string",
|
[TSTRING] = "string",
|
||||||
|
[TNIL] = "nil",
|
||||||
|
[TIDEAL] = "ideal",
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -1302,8 +1267,6 @@ Nconv(Fmt *fp)
|
|||||||
snprint(buf1, sizeof(buf1), "LITERAL-ctype=%d", n->val.ctype);
|
snprint(buf1, sizeof(buf1), "LITERAL-ctype=%d", n->val.ctype);
|
||||||
break;
|
break;
|
||||||
case CTINT:
|
case CTINT:
|
||||||
case CTSINT:
|
|
||||||
case CTUINT:
|
|
||||||
snprint(buf1, sizeof(buf1), "I%B", n->val.u.xval);
|
snprint(buf1, sizeof(buf1), "I%B", n->val.u.xval);
|
||||||
break;
|
break;
|
||||||
case CTFLT:
|
case CTFLT:
|
||||||
@ -1363,7 +1326,7 @@ treecopy(Node *n)
|
|||||||
|
|
||||||
case OLITERAL:
|
case OLITERAL:
|
||||||
if(n->iota) {
|
if(n->iota) {
|
||||||
m = literal(iota);
|
m = nodintconst(iota);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
m = nod(OXXX, N, N);
|
m = nod(OXXX, N, N);
|
||||||
@ -1416,34 +1379,6 @@ Zconv(Fmt *fp)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char*
|
|
||||||
wnames[] =
|
|
||||||
{
|
|
||||||
[Wnil] = "Wnil",
|
|
||||||
[Wtnil] = "Wtnil",
|
|
||||||
|
|
||||||
[Wtfloat] = "Wtfloat",
|
|
||||||
[Wtint] = "Wtint",
|
|
||||||
[Wtbool] = "Wtbool",
|
|
||||||
[Wtstr] = "Wtstr",
|
|
||||||
|
|
||||||
[Wlitfloat] = "float constant",
|
|
||||||
[Wlitint] = "int constant",
|
|
||||||
[Wlitbool] = "bool",
|
|
||||||
[Wlitstr] = "string",
|
|
||||||
[Wlitnil] = "nil",
|
|
||||||
};
|
|
||||||
|
|
||||||
int
|
|
||||||
Wconv(Fmt *fp)
|
|
||||||
{
|
|
||||||
int w;
|
|
||||||
|
|
||||||
w = va_arg(fp->args, int);
|
|
||||||
if(w < 0 || w >= nelem(wnames) || wnames[w] == nil)
|
|
||||||
return fmtprint(fp, "W-%d", w);
|
|
||||||
return fmtstrcpy(fp, wnames[w]);
|
|
||||||
}
|
|
||||||
int
|
int
|
||||||
isnil(Node *n)
|
isnil(Node *n)
|
||||||
{
|
{
|
||||||
@ -2043,18 +1978,6 @@ ptrto(Type *t)
|
|||||||
return t1;
|
return t1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node*
|
|
||||||
literal(int32 v)
|
|
||||||
{
|
|
||||||
Node *n;
|
|
||||||
|
|
||||||
n = nod(OLITERAL, N, N);
|
|
||||||
n->val.u.xval = mal(sizeof(*n->val.u.xval));
|
|
||||||
n->val.ctype = CTINT;
|
|
||||||
mpmovecfix(n->val.u.xval, v);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
frame(int context)
|
frame(int context)
|
||||||
{
|
{
|
||||||
|
@ -448,7 +448,7 @@ walkswitch(Node *sw)
|
|||||||
*/
|
*/
|
||||||
walkstate(sw->ninit);
|
walkstate(sw->ninit);
|
||||||
if(sw->ntest == N)
|
if(sw->ntest == N)
|
||||||
sw->ntest = booltrue;
|
sw->ntest = nodbool(1);
|
||||||
casebody(sw);
|
casebody(sw);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -466,7 +466,7 @@ walkswitch(Node *sw)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
arg = Snorm;
|
arg = Snorm;
|
||||||
if(whatis(sw->ntest) == Wlitbool) {
|
if(isconst(sw->ntest, CTBOOL)) {
|
||||||
arg = Strue;
|
arg = Strue;
|
||||||
if(sw->ntest->val.u.xval == 0)
|
if(sw->ntest->val.u.xval == 0)
|
||||||
arg = Sfalse;
|
arg = Sfalse;
|
||||||
@ -523,10 +523,10 @@ iscaseconst(Node *t)
|
|||||||
{
|
{
|
||||||
if(t == N || t->left == N)
|
if(t == N || t->left == N)
|
||||||
return 0;
|
return 0;
|
||||||
switch(whatis(t->left)) {
|
switch(consttype(t->left)) {
|
||||||
case Wlitfloat:
|
case CTFLT:
|
||||||
case Wlitint:
|
case CTINT:
|
||||||
case Wlitstr:
|
case CTSTR:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -616,19 +616,23 @@ csort(Case *l, int(*f)(Case*, Case*))
|
|||||||
int
|
int
|
||||||
casecmp(Case *c1, Case *c2)
|
casecmp(Case *c1, Case *c2)
|
||||||
{
|
{
|
||||||
int w;
|
int ct;
|
||||||
|
Node *n1, *n2;
|
||||||
|
|
||||||
w = whatis(c1->node->left);
|
n1 = c1->node->left;
|
||||||
if(w != whatis(c2->node->left))
|
n2 = c2->node->left;
|
||||||
|
|
||||||
|
ct = n1->val.ctype;
|
||||||
|
if(ct != n2->val.ctype)
|
||||||
fatal("casecmp1");
|
fatal("casecmp1");
|
||||||
|
|
||||||
switch(w) {
|
switch(ct) {
|
||||||
case Wlitfloat:
|
case CTFLT:
|
||||||
return mpcmpfltflt(c1->node->left->val.u.fval, c2->node->left->val.u.fval);
|
return mpcmpfltflt(n1->val.u.fval, n2->val.u.fval);
|
||||||
case Wlitint:
|
case CTINT:
|
||||||
return mpcmpfixfix(c1->node->left->val.u.xval, c2->node->left->val.u.xval);
|
return mpcmpfixfix(n1->val.u.xval, n2->val.u.xval);
|
||||||
case Wlitstr:
|
case CTSTR:
|
||||||
return cmpslit(c1->node->left, c2->node->left);
|
return cmpslit(n1, n2);
|
||||||
}
|
}
|
||||||
|
|
||||||
fatal("casecmp2");
|
fatal("casecmp2");
|
||||||
|
@ -356,7 +356,7 @@ loop:
|
|||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
walktype(n->left, Erv);
|
walktype(n->left, Erv);
|
||||||
convlit(n->left, types[TFUNC]);
|
defaultlit(n->left, T);
|
||||||
|
|
||||||
t = n->left->type;
|
t = n->left->type;
|
||||||
if(t == T)
|
if(t == T)
|
||||||
@ -367,11 +367,8 @@ loop:
|
|||||||
if(n->left->op == ODOTINTER)
|
if(n->left->op == ODOTINTER)
|
||||||
n->op = OCALLINTER;
|
n->op = OCALLINTER;
|
||||||
|
|
||||||
if(isptr[t->etype])
|
|
||||||
t = t->type;
|
|
||||||
|
|
||||||
if(t->etype != TFUNC) {
|
if(t->etype != TFUNC) {
|
||||||
yyerror("call of a non-function %T", t);
|
yyerror("call of a non-function: %T", t);
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,7 +403,9 @@ loop:
|
|||||||
n->right = reorder1(l);
|
n->right = reorder1(l);
|
||||||
if(isselect(n)) {
|
if(isselect(n)) {
|
||||||
// clear output bool - special prob with selectsend
|
// clear output bool - special prob with selectsend
|
||||||
r = ascompatte(n->op, getoutarg(t), &boolfalse, 0);
|
Node *b;
|
||||||
|
b = nodbool(0);
|
||||||
|
r = ascompatte(n->op, getoutarg(t), &b, 0);
|
||||||
n->right = list(n->right, r);
|
n->right = list(n->right, r);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -586,7 +585,7 @@ loop:
|
|||||||
if(l == N)
|
if(l == N)
|
||||||
goto ret;
|
goto ret;
|
||||||
walktype(l, Erv);
|
walktype(l, Erv);
|
||||||
|
|
||||||
// structure literal
|
// structure literal
|
||||||
if(t->etype == TSTRUCT) {
|
if(t->etype == TSTRUCT) {
|
||||||
indir(n, structlit(n, N));
|
indir(n, structlit(n, N));
|
||||||
@ -623,6 +622,9 @@ loop:
|
|||||||
case ONOT:
|
case ONOT:
|
||||||
if(top != Erv)
|
if(top != Erv)
|
||||||
goto nottop;
|
goto nottop;
|
||||||
|
evconst(n);
|
||||||
|
if(n->op == OLITERAL)
|
||||||
|
goto ret;
|
||||||
walktype(n->left, Erv);
|
walktype(n->left, Erv);
|
||||||
if(n->left == N || n->left->type == T)
|
if(n->left == N || n->left->type == T)
|
||||||
goto ret;
|
goto ret;
|
||||||
@ -634,15 +636,11 @@ loop:
|
|||||||
goto nottop;
|
goto nottop;
|
||||||
walktype(n->left, Elv);
|
walktype(n->left, Elv);
|
||||||
l = n->left;
|
l = n->left;
|
||||||
if(l->op != OINDEX) {
|
if(l->op == OINDEX && istype(l->left->type, TMAP))
|
||||||
if(n->etype == OLSH || n->etype == ORSH)
|
indir(n, mapop(n, top));
|
||||||
goto shft;
|
if(n->etype == OLSH || n->etype == ORSH)
|
||||||
goto com;
|
goto shft;
|
||||||
}
|
goto com;
|
||||||
if(!istype(l->left->type, TMAP))
|
|
||||||
goto com;
|
|
||||||
indir(n, mapop(n, top));
|
|
||||||
goto ret;
|
|
||||||
|
|
||||||
case OLSH:
|
case OLSH:
|
||||||
case ORSH:
|
case ORSH:
|
||||||
@ -657,14 +655,14 @@ loop:
|
|||||||
evconst(n);
|
evconst(n);
|
||||||
if(n->op == OLITERAL)
|
if(n->op == OLITERAL)
|
||||||
goto ret;
|
goto ret;
|
||||||
if(n->left->type == T)
|
// do NOT defaultlit n->left.
|
||||||
convlit(n->left, types[TINT]);
|
// let parent defaultlit or convlit instead.
|
||||||
if(n->right->type == T)
|
defaultlit(n->right, types[TUINT]);
|
||||||
convlit(n->right, types[TUINT]);
|
|
||||||
if(n->left->type == T || n->right->type == T)
|
if(n->left->type == T || n->right->type == T)
|
||||||
goto ret;
|
goto ret;
|
||||||
if(issigned[n->right->type->etype])
|
if(issigned[n->right->type->etype])
|
||||||
goto badt;
|
goto badt;
|
||||||
|
// check of n->left->type happens in second switch.
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OMOD:
|
case OMOD:
|
||||||
@ -695,8 +693,7 @@ loop:
|
|||||||
evconst(n);
|
evconst(n);
|
||||||
if(n->op == OLITERAL)
|
if(n->op == OLITERAL)
|
||||||
goto ret;
|
goto ret;
|
||||||
convlit(n->left, n->right->type);
|
defaultlit2(n->left, n->right);
|
||||||
convlit(n->right, n->left->type);
|
|
||||||
if(n->left->type == T || n->right->type == T)
|
if(n->left->type == T || n->right->type == T)
|
||||||
goto ret;
|
goto ret;
|
||||||
if(!eqtype(n->left->type, n->right->type, 0))
|
if(!eqtype(n->left->type, n->right->type, 0))
|
||||||
@ -749,6 +746,7 @@ loop:
|
|||||||
if(top != Erv)
|
if(top != Erv)
|
||||||
goto nottop;
|
goto nottop;
|
||||||
walktype(n->left, Erv);
|
walktype(n->left, Erv);
|
||||||
|
defaultlit(n->left, T);
|
||||||
implicitstar(&n->left);
|
implicitstar(&n->left);
|
||||||
t = n->left->type;
|
t = n->left->type;
|
||||||
if(t == T)
|
if(t == T)
|
||||||
@ -757,7 +755,7 @@ loop:
|
|||||||
default:
|
default:
|
||||||
goto badt;
|
goto badt;
|
||||||
case TSTRING:
|
case TSTRING:
|
||||||
if(whatis(n->left) == Wlitstr)
|
if(isconst(n->left, CTSTR))
|
||||||
nodconst(n, types[TINT], n->left->val.u.sval->len);
|
nodconst(n, types[TINT], n->left->val.u.sval->len);
|
||||||
break;
|
break;
|
||||||
case TMAP:
|
case TMAP:
|
||||||
@ -774,8 +772,8 @@ loop:
|
|||||||
if(top != Erv)
|
if(top != Erv)
|
||||||
goto nottop;
|
goto nottop;
|
||||||
walktype(n->left, Erv);
|
walktype(n->left, Erv);
|
||||||
|
defaultlit(n->left, T);
|
||||||
implicitstar(&n->left);
|
implicitstar(&n->left);
|
||||||
evconst(n);
|
|
||||||
t = n->left->type;
|
t = n->left->type;
|
||||||
if(t == T)
|
if(t == T)
|
||||||
goto ret;
|
goto ret;
|
||||||
@ -800,7 +798,7 @@ loop:
|
|||||||
if(n->left == N || n->right == N)
|
if(n->left == N || n->right == N)
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
defaultlit(n->left);
|
defaultlit(n->left, T);
|
||||||
implicitstar(&n->left);
|
implicitstar(&n->left);
|
||||||
|
|
||||||
t = n->left->type;
|
t = n->left->type;
|
||||||
@ -809,17 +807,16 @@ loop:
|
|||||||
|
|
||||||
switch(t->etype) {
|
switch(t->etype) {
|
||||||
default:
|
default:
|
||||||
|
defaultlit(n->right, T);
|
||||||
goto badt;
|
goto badt;
|
||||||
|
|
||||||
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;
|
||||||
if(n->right->type == T) {
|
defaultlit(n->right, types[TINT]);
|
||||||
convlit(n->right, types[TINT]);
|
if(n->right->type == T)
|
||||||
if(n->right->type == T)
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(!isint[n->right->type->etype])
|
if(!isint[n->right->type->etype])
|
||||||
goto badt;
|
goto badt;
|
||||||
indir(n, stringop(n, top));
|
indir(n, stringop(n, top));
|
||||||
@ -827,11 +824,9 @@ loop:
|
|||||||
|
|
||||||
case TMAP:
|
case TMAP:
|
||||||
// right side must be map type
|
// right side must be map type
|
||||||
if(n->right->type == T) {
|
defaultlit(n->right, t->down);
|
||||||
convlit(n->right, t->down);
|
if(n->right->type == T)
|
||||||
if(n->right->type == T)
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(!eqtype(n->right->type, t->down, 0))
|
if(!eqtype(n->right->type, t->down, 0))
|
||||||
goto badt;
|
goto badt;
|
||||||
n->type = t->type;
|
n->type = t->type;
|
||||||
@ -841,14 +836,11 @@ loop:
|
|||||||
|
|
||||||
case TARRAY:
|
case TARRAY:
|
||||||
// right side must be an int
|
// right side must be an int
|
||||||
if(n->right->type == T) {
|
defaultlit(n->right, types[TINT]);
|
||||||
convlit(n->right, types[TINT]);
|
if(n->right->type == T)
|
||||||
if(n->right->type == T)
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(!isint[n->right->type->etype])
|
if(!isint[n->right->type->etype])
|
||||||
goto badt;
|
goto badt;
|
||||||
|
|
||||||
n->type = t->type;
|
n->type = t->type;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -871,7 +863,7 @@ loop:
|
|||||||
case OSEND:
|
case OSEND:
|
||||||
if(top == Elv)
|
if(top == Elv)
|
||||||
goto nottop;
|
goto nottop;
|
||||||
walktype(n->left, Erv); // chan
|
walktype(n->left, Erv); // chan
|
||||||
walktype(n->right, Erv); // e
|
walktype(n->right, Erv); // e
|
||||||
indir(n, chanop(n, top));
|
indir(n, chanop(n, top));
|
||||||
goto ret;
|
goto ret;
|
||||||
@ -897,7 +889,9 @@ loop:
|
|||||||
walktype(n->right, Erv);
|
walktype(n->right, Erv);
|
||||||
if(n->left == N || n->right == N)
|
if(n->left == N || n->right == N)
|
||||||
goto ret;
|
goto ret;
|
||||||
convlit(n->left, types[TSTRING]);
|
defaultlit(n->left, T);
|
||||||
|
defaultlit(n->right->left, types[TUINT]);
|
||||||
|
defaultlit(n->right->right, types[TUINT]);
|
||||||
implicitstar(&n->left);
|
implicitstar(&n->left);
|
||||||
t = n->left->type;
|
t = n->left->type;
|
||||||
if(t == T)
|
if(t == T)
|
||||||
@ -919,12 +913,14 @@ loop:
|
|||||||
case ODOTINTER:
|
case ODOTINTER:
|
||||||
if(top == Etop)
|
if(top == Etop)
|
||||||
goto nottop;
|
goto nottop;
|
||||||
|
defaultlit(n->left, T);
|
||||||
walkdot(n);
|
walkdot(n);
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OADDR:
|
case OADDR:
|
||||||
if(top != Erv)
|
if(top != Erv)
|
||||||
goto nottop;
|
goto nottop;
|
||||||
|
defaultlit(n->left, T);
|
||||||
if(n->left->op == OCOMPOS && n->left->type != T) {
|
if(n->left->op == OCOMPOS && n->left->type != T) {
|
||||||
// turn &Point(1, 2) or &[]int(1, 2) or &[...]int(1, 2) into allocation.
|
// turn &Point(1, 2) or &[]int(1, 2) or &[...]int(1, 2) into allocation.
|
||||||
// initialize with
|
// initialize with
|
||||||
@ -968,13 +964,13 @@ loop:
|
|||||||
yyerror("cannot take address of function");
|
yyerror("cannot take address of function");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
walktype(n->left, Elv);
|
|
||||||
addrescapes(n->left);
|
|
||||||
if(n->left == N)
|
if(n->left == N)
|
||||||
goto ret;
|
goto ret;
|
||||||
|
walktype(n->left, Elv);
|
||||||
t = n->left->type;
|
t = n->left->type;
|
||||||
if(t == T)
|
if(t == T)
|
||||||
goto ret;
|
goto ret;
|
||||||
|
addrescapes(n->left);
|
||||||
n->type = ptrto(t);
|
n->type = ptrto(t);
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
@ -984,6 +980,7 @@ loop:
|
|||||||
if(top == Elv) // even if n is lvalue, n->left is rvalue
|
if(top == Elv) // even if n is lvalue, n->left is rvalue
|
||||||
top = Erv;
|
top = Erv;
|
||||||
walktype(n->left, top);
|
walktype(n->left, top);
|
||||||
|
defaultlit(n->left, T);
|
||||||
if(n->left == N)
|
if(n->left == N)
|
||||||
goto ret;
|
goto ret;
|
||||||
t = n->left->type;
|
t = n->left->type;
|
||||||
@ -1041,12 +1038,8 @@ loop:
|
|||||||
case ONE:
|
case ONE:
|
||||||
if(n->left->type == T)
|
if(n->left->type == T)
|
||||||
goto ret;
|
goto ret;
|
||||||
if(isslice(n->left->type)) {
|
|
||||||
t = types[TBOOL];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
et = n->left->type->etype;
|
et = n->left->type->etype;
|
||||||
if(!okforeq[et])
|
if(!okforeq[et] && !isslice(n->left->type))
|
||||||
goto badt;
|
goto badt;
|
||||||
if(isinter(n->left->type)) {
|
if(isinter(n->left->type)) {
|
||||||
indir(n, ifaceop(T, n, n->op));
|
indir(n, ifaceop(T, n, n->op));
|
||||||
@ -1085,18 +1078,14 @@ loop:
|
|||||||
et = n->left->type->etype;
|
et = n->left->type->etype;
|
||||||
if(!okforadd[et])
|
if(!okforadd[et])
|
||||||
goto badt;
|
goto badt;
|
||||||
if(!isfloat[et])
|
if(isfloat[et]) {
|
||||||
break;
|
// TODO(rsc): Can do this more efficiently,
|
||||||
|
// but OSUB is wrong. Should be in back end anyway.
|
||||||
l = nod(OLITERAL, N, N);
|
indir(n, nod(OMUL, n->left, nodintconst(-1)));
|
||||||
l->val.u.fval = mal(sizeof(*l->val.u.fval));
|
walktype(n, Erv);
|
||||||
l->val.ctype = CTFLT;
|
goto ret;
|
||||||
mpmovecflt(l->val.u.fval, 0.0);
|
}
|
||||||
|
break;
|
||||||
l = nod(OSUB, l, n->left);
|
|
||||||
indir(n, l);
|
|
||||||
walktype(n, Erv);
|
|
||||||
goto ret;
|
|
||||||
|
|
||||||
case OLSH:
|
case OLSH:
|
||||||
case ORSH:
|
case ORSH:
|
||||||
@ -1109,17 +1098,27 @@ loop:
|
|||||||
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(!okforand[et])
|
if(et != TIDEAL && !okforand[et])
|
||||||
goto badt;
|
goto badt;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(t == T)
|
if(t == T) {
|
||||||
t = n->left->type;
|
t = n->left->type;
|
||||||
|
// throw away name:
|
||||||
|
// type MyInt int
|
||||||
|
// var x MyInt = 0;
|
||||||
|
// -x has type int, not MyInt.
|
||||||
|
if(t != T)
|
||||||
|
t = types[t->etype];
|
||||||
|
}
|
||||||
n->type = t;
|
n->type = t;
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
nottop:
|
nottop:
|
||||||
|
if(n->diag)
|
||||||
|
goto ret;
|
||||||
|
n->diag = 1;
|
||||||
switch(top) {
|
switch(top) {
|
||||||
default:
|
default:
|
||||||
yyerror("didn't expect %O here", n->op);
|
yyerror("didn't expect %O here", n->op);
|
||||||
@ -1137,6 +1136,9 @@ nottop:
|
|||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
badt:
|
badt:
|
||||||
|
if(n->diag)
|
||||||
|
goto ret;
|
||||||
|
n->diag = 1;
|
||||||
if(n->right == N) {
|
if(n->right == N) {
|
||||||
if(n->left == N) {
|
if(n->left == N) {
|
||||||
badtype(n->op, T, T);
|
badtype(n->op, T, T);
|
||||||
@ -1160,14 +1162,13 @@ void
|
|||||||
walkbool(Node *n)
|
walkbool(Node *n)
|
||||||
{
|
{
|
||||||
walktype(n, Erv);
|
walktype(n, Erv);
|
||||||
|
defaultlit(n, T);
|
||||||
addtotop(n);
|
addtotop(n);
|
||||||
if(n != N && n->type != T)
|
if(n != N && n->type != T)
|
||||||
if(!eqtype(n->type, types[TBOOL], 0))
|
if(!eqtype(n->type, types[TBOOL], 0))
|
||||||
yyerror("IF and FOR require a boolean type");
|
yyerror("IF and FOR require a boolean type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
walkconv(Node *n)
|
walkconv(Node *n)
|
||||||
{
|
{
|
||||||
@ -1182,12 +1183,15 @@ walkconv(Node *n)
|
|||||||
if(l == N)
|
if(l == N)
|
||||||
return;
|
return;
|
||||||
walktype(l, Erv);
|
walktype(l, Erv);
|
||||||
|
if(l->type == T)
|
||||||
convlit1(l, t, 1);
|
return;
|
||||||
|
|
||||||
// if using .(T), interface assertion.
|
// if using .(T), interface assertion.
|
||||||
if(n->op == ODOTTYPE) {
|
if(n->op == ODOTTYPE) {
|
||||||
// interface conversion
|
// interface conversion
|
||||||
|
defaultlit(l, T);
|
||||||
|
if(!isinter(l->type))
|
||||||
|
yyerror("type assertion requires interface on left, have %T", l->type);
|
||||||
et = ifaceas(n->type, l->type, 1);
|
et = ifaceas(n->type, l->type, 1);
|
||||||
if(et != Inone) {
|
if(et != Inone) {
|
||||||
indir(n, ifaceop(n->type, l, et));
|
indir(n, ifaceop(n->type, l, et));
|
||||||
@ -1197,6 +1201,9 @@ walkconv(Node *n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// otherwise, conversion.
|
// otherwise, conversion.
|
||||||
|
convlit1(l, t, 1);
|
||||||
|
if(l->type == T)
|
||||||
|
return;
|
||||||
|
|
||||||
// nil conversion
|
// nil conversion
|
||||||
if(eqtype(t, l->type, 0)) {
|
if(eqtype(t, l->type, 0)) {
|
||||||
@ -1208,7 +1215,6 @@ walkconv(Node *n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// simple fix-float
|
// simple fix-float
|
||||||
if(l->type != T)
|
|
||||||
if(isint[l->type->etype] || isfloat[l->type->etype])
|
if(isint[l->type->etype] || isfloat[l->type->etype])
|
||||||
if(isint[t->etype] || isfloat[t->etype]) {
|
if(isint[t->etype] || isfloat[t->etype]) {
|
||||||
evconst(n);
|
evconst(n);
|
||||||
@ -1324,6 +1330,7 @@ recv:
|
|||||||
a = c->left; // nil elem
|
a = c->left; // nil elem
|
||||||
a = nod(OLITERAL, N, N);
|
a = nod(OLITERAL, N, N);
|
||||||
a->val.ctype = CTNIL;
|
a->val.ctype = CTNIL;
|
||||||
|
a->type = types[TNIL];
|
||||||
|
|
||||||
r = a;
|
r = a;
|
||||||
a = c->left; // chan
|
a = c->left; // chan
|
||||||
@ -1797,7 +1804,7 @@ mkdotargs(Node *r, Node *rr, Iter *saver, Node *nn, Type *l, int fp)
|
|||||||
st = typ(TSTRUCT); // generated structure
|
st = typ(TSTRUCT); // generated structure
|
||||||
ft = T; // last field
|
ft = T; // last field
|
||||||
while(r != N) {
|
while(r != N) {
|
||||||
defaultlit(r);
|
defaultlit(r, T);
|
||||||
|
|
||||||
// generate the next structure field
|
// generate the next structure field
|
||||||
t = typ(TFIELD);
|
t = typ(TFIELD);
|
||||||
@ -1968,7 +1975,7 @@ prcompat(Node *n, int fmt)
|
|||||||
Node *on;
|
Node *on;
|
||||||
Type *t;
|
Type *t;
|
||||||
Iter save;
|
Iter save;
|
||||||
int w, notfirst;
|
int notfirst, et;
|
||||||
|
|
||||||
r = N;
|
r = N;
|
||||||
l = listfirst(&save, &n);
|
l = listfirst(&save, &n);
|
||||||
@ -1989,49 +1996,42 @@ loop:
|
|||||||
r = list(r, nod(OCALL, on, N));
|
r = list(r, nod(OCALL, on, N));
|
||||||
}
|
}
|
||||||
|
|
||||||
w = whatis(l);
|
walktype(l, Erv);
|
||||||
switch(w) {
|
if(l->op == OLITERAL) {
|
||||||
default:
|
switch(l->val.ctype) {
|
||||||
if(l->type == T)
|
case CTINT:
|
||||||
goto out;
|
defaultlit(l, types[TINT64]);
|
||||||
if(isinter(l->type)) {
|
break;
|
||||||
on = syslook("printinter", 1);
|
case CTFLT:
|
||||||
argtype(on, l->type); // any-1
|
defaultlit(l, types[TFLOAT64]);
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(isptr[l->type->etype]
|
|
||||||
|| l->type->etype == TCHAN
|
|
||||||
|| l->type->etype == TMAP
|
|
||||||
|| l->type->etype == TFUNC) {
|
|
||||||
on = syslook("printpointer", 1);
|
|
||||||
argtype(on, l->type); // any-1
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(isslice(l->type)) {
|
|
||||||
on = syslook("printarray", 1);
|
|
||||||
argtype(on, l->type); // any-1
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if(l->type == T)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
et = l->type->etype;
|
||||||
|
if(isinter(l->type)) {
|
||||||
|
on = syslook("printinter", 1);
|
||||||
|
argtype(on, l->type); // any-1
|
||||||
|
} else if(isptr[et] || et == TCHAN || et == TMAP || et == TFUNC) {
|
||||||
|
on = syslook("printpointer", 1);
|
||||||
|
argtype(on, l->type); // any-1
|
||||||
|
} else if(isslice(l->type)) {
|
||||||
|
on = syslook("printarray", 1);
|
||||||
|
argtype(on, l->type); // any-1
|
||||||
|
} else if(isint[et]) {
|
||||||
|
on = syslook("printint", 0);
|
||||||
|
} else if(isfloat[et]) {
|
||||||
|
on = syslook("printfloat", 0);
|
||||||
|
} else if(et == TBOOL) {
|
||||||
|
on = syslook("printbool", 0);
|
||||||
|
} else if(et == TSTRING) {
|
||||||
|
on = syslook("printstring", 0);
|
||||||
|
} else {
|
||||||
badtype(OPRINT, l->type, T);
|
badtype(OPRINT, l->type, T);
|
||||||
l = listnext(&save);
|
l = listnext(&save);
|
||||||
goto loop;
|
goto loop;
|
||||||
|
|
||||||
case Wlitint:
|
|
||||||
case Wtint:
|
|
||||||
on = syslook("printint", 0);
|
|
||||||
break;
|
|
||||||
case Wlitfloat:
|
|
||||||
case Wtfloat:
|
|
||||||
on = syslook("printfloat", 0);
|
|
||||||
break;
|
|
||||||
case Wlitbool:
|
|
||||||
case Wtbool:
|
|
||||||
on = syslook("printbool", 0);
|
|
||||||
break;
|
|
||||||
case Wlitstr:
|
|
||||||
case Wtstr:
|
|
||||||
on = syslook("printstring", 0);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
t = *getinarg(on->type);
|
t = *getinarg(on->type);
|
||||||
@ -2538,6 +2538,7 @@ chanop(Node *n, int top)
|
|||||||
goto shape;
|
goto shape;
|
||||||
|
|
||||||
// chanrecv2(hchan *chan any) (elem any, pres bool);
|
// chanrecv2(hchan *chan any) (elem any, pres bool);
|
||||||
|
defaultlit(n->right->left, T);
|
||||||
t = fixchan(n->right->left->type);
|
t = fixchan(n->right->left->type);
|
||||||
if(t == T)
|
if(t == T)
|
||||||
break;
|
break;
|
||||||
@ -2560,7 +2561,7 @@ chanop(Node *n, int top)
|
|||||||
goto recv2;
|
goto recv2;
|
||||||
|
|
||||||
// chanrecv1(hchan *chan any) (elem any);
|
// chanrecv1(hchan *chan any) (elem any);
|
||||||
|
defaultlit(n->left, T);
|
||||||
t = fixchan(n->left->type);
|
t = fixchan(n->left->type);
|
||||||
if(t == T)
|
if(t == T)
|
||||||
break;
|
break;
|
||||||
@ -2588,6 +2589,7 @@ chanop(Node *n, int top)
|
|||||||
if(a == N) {
|
if(a == N) {
|
||||||
a = nod(OLITERAL, N, N);
|
a = nod(OLITERAL, N, N);
|
||||||
a->val.ctype = CTNIL;
|
a->val.ctype = CTNIL;
|
||||||
|
a->type = types[TNIL];
|
||||||
} else
|
} else
|
||||||
a = nod(OADDR, a, N);
|
a = nod(OADDR, a, N);
|
||||||
|
|
||||||
@ -3072,7 +3074,7 @@ colas(Node *nl, Node *nr)
|
|||||||
|
|
||||||
while(l != N) {
|
while(l != N) {
|
||||||
walktype(r, Erv);
|
walktype(r, Erv);
|
||||||
defaultlit(r);
|
defaultlit(r, T);
|
||||||
a = old2new(l, r->type);
|
a = old2new(l, r->type);
|
||||||
n = list(n, a);
|
n = list(n, a);
|
||||||
|
|
||||||
@ -3215,9 +3217,9 @@ ary:
|
|||||||
hk = nod(OXXX, N, N); // hidden key
|
hk = nod(OXXX, N, N); // hidden key
|
||||||
tempname(hk, types[TINT]); // maybe TINT32
|
tempname(hk, types[TINT]); // maybe TINT32
|
||||||
|
|
||||||
n->ninit = nod(OAS, hk, literal(0));
|
n->ninit = nod(OAS, hk, nodintconst(0));
|
||||||
n->ntest = nod(OLT, hk, nod(OLEN, m, N));
|
n->ntest = nod(OLT, hk, nod(OLEN, m, N));
|
||||||
n->nincr = nod(OASOP, hk, literal(1));
|
n->nincr = nod(OASOP, hk, nodintconst(1));
|
||||||
n->nincr->etype = OADD;
|
n->nincr->etype = OADD;
|
||||||
|
|
||||||
if(local)
|
if(local)
|
||||||
@ -3250,9 +3252,10 @@ map:
|
|||||||
r = nod(OCALL, on, r);
|
r = nod(OCALL, on, r);
|
||||||
n->ninit = r;
|
n->ninit = r;
|
||||||
|
|
||||||
r = nod(OINDEX, hk, literal(0));
|
r = nod(OINDEX, hk, nodintconst(0));
|
||||||
a = nod(OLITERAL, N, N);
|
a = nod(OLITERAL, N, N);
|
||||||
a->val.ctype = CTNIL;
|
a->val.ctype = CTNIL;
|
||||||
|
a->type = types[TNIL];
|
||||||
r = nod(ONE, r, a);
|
r = nod(ONE, r, a);
|
||||||
n->ntest = r;
|
n->ntest = r;
|
||||||
|
|
||||||
@ -3678,19 +3681,14 @@ loop:
|
|||||||
* the current function returns. mark any local vars
|
* the current function returns. mark any local vars
|
||||||
* as needing to move to the heap.
|
* as needing to move to the heap.
|
||||||
*/
|
*/
|
||||||
static char *pnames[] = {
|
|
||||||
[PAUTO] "auto",
|
|
||||||
[PPARAM] "param",
|
|
||||||
[PPARAMOUT] "param_out",
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
void
|
||||||
addrescapes(Node *n)
|
addrescapes(Node *n)
|
||||||
{
|
{
|
||||||
char buf[100];
|
char buf[100];
|
||||||
switch(n->op) {
|
switch(n->op) {
|
||||||
default:
|
default:
|
||||||
dump("addrescapes", n);
|
// probably a type error already.
|
||||||
|
// dump("addrescapes", n);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ONAME:
|
case ONAME:
|
||||||
@ -3702,8 +3700,6 @@ addrescapes(Node *n)
|
|||||||
break;
|
break;
|
||||||
case PAUTO:
|
case PAUTO:
|
||||||
case PPARAM:
|
case PPARAM:
|
||||||
if(debug['E'])
|
|
||||||
print("%L %s %S escapes %p\n", n->lineno, pnames[n->class], n->sym, n);
|
|
||||||
// if func param, need separate temporary
|
// if func param, need separate temporary
|
||||||
// to hold heap pointer.
|
// to hold heap pointer.
|
||||||
if(n->class == PPARAM) {
|
if(n->class == PPARAM) {
|
||||||
|
@ -235,7 +235,7 @@ func str(val int64) string { // do it here rather than with fmt to avoid depend
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Errstr(errno int64) string {
|
func Errstr(errno int64) string {
|
||||||
if errno < 0 || errno >= len(error) {
|
if errno < 0 || errno >= int64(len(error)) {
|
||||||
return "Error " + str(errno)
|
return "Error " + str(errno)
|
||||||
}
|
}
|
||||||
return error[errno]
|
return error[errno]
|
||||||
|
@ -285,7 +285,7 @@ func str(val int64) string { // do it here rather than with fmt to avoid depend
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Errstr(errno int64) string {
|
func Errstr(errno int64) string {
|
||||||
if errno < 0 || errno >= len(error) {
|
if errno < 0 || errno >= int64(len(error)) {
|
||||||
return "Error " + str(errno)
|
return "Error " + str(errno)
|
||||||
}
|
}
|
||||||
return error[errno]
|
return error[errno]
|
||||||
|
@ -14,6 +14,9 @@ const (
|
|||||||
c1 = chuge >> 100;
|
c1 = chuge >> 100;
|
||||||
c3div2 = 3/2;
|
c3div2 = 3/2;
|
||||||
c1e3 = 1e3;
|
c1e3 = 1e3;
|
||||||
|
|
||||||
|
ctrue = true;
|
||||||
|
cfalse = !ctrue;
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -111,4 +114,7 @@ func floats() {
|
|||||||
func main() {
|
func main() {
|
||||||
ints();
|
ints();
|
||||||
floats();
|
floats();
|
||||||
|
|
||||||
|
assert(ctrue == true, "ctrue == true");
|
||||||
|
assert(cfalse == false, "cfalse == false");
|
||||||
}
|
}
|
||||||
|
79
test/const1.go
Normal file
79
test/const1.go
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
// errchk $G -e $F.go
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
type I interface {}
|
||||||
|
const (
|
||||||
|
// assume all types behave similarly to int8/uint8
|
||||||
|
Int8 int8 = 101;
|
||||||
|
Minus1 int8 = -1;
|
||||||
|
Uint8 uint8 = 102;
|
||||||
|
Const = 103;
|
||||||
|
|
||||||
|
Float32 float32 = 104.5;
|
||||||
|
Float float = 105.5;
|
||||||
|
ConstFloat = 106.5;
|
||||||
|
Big float64 = 1e300;
|
||||||
|
|
||||||
|
String = "abc";
|
||||||
|
Bool = true;
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
a1 = Int8 * 100; // ERROR "overflows"
|
||||||
|
a2 = Int8 * -1; // OK
|
||||||
|
a3 = Int8 * 1000; // ERROR "overflows"
|
||||||
|
a4 = Int8 * int8(1000); // ERROR "overflows"
|
||||||
|
a5 = int8(Int8 * 1000); // ERROR "overflows"
|
||||||
|
a6 = int8(Int8 * int8(1000)); // ERROR "overflows"
|
||||||
|
a7 = Int8 - 2*Int8 - 2*Int8; // ERROR "overflows"
|
||||||
|
a8 = Int8 * Const / 100; // ERROR "overflows"
|
||||||
|
a9 = Int8 * (Const / 100); // OK
|
||||||
|
|
||||||
|
b1 = Uint8 * Uint8; // ERROR "overflows"
|
||||||
|
b2 = Uint8 * -1; // ERROR "overflows"
|
||||||
|
b3 = Uint8 - Uint8; // OK
|
||||||
|
b4 = Uint8 - Uint8 - Uint8; // ERROR "overflows"
|
||||||
|
b5 = uint8(^0); // ERROR "overflows"
|
||||||
|
b6 = ^uint8(0); // ERROR "overflows"
|
||||||
|
b7 = uint8(Minus1); // ERROR "overflows"
|
||||||
|
b8 = uint8(int8(-1)); // ERROR "overflows"
|
||||||
|
b8a = uint8(-1); // ERROR "overflows"
|
||||||
|
b9 byte = (1<<10) >> 8; // OK
|
||||||
|
b10 byte = (1<<10); // ERROR "overflows"
|
||||||
|
b11 byte = (byte(1)<<10) >> 8; // ERROR "overflows"
|
||||||
|
b12 byte = 1000; // ERROR "overflows"
|
||||||
|
b13 byte = byte(1000); // ERROR "overflows"
|
||||||
|
b14 byte = byte(100) * byte(100); // ERROR "overflows"
|
||||||
|
b15 byte = byte(100) * 100; // ERROR "overflows"
|
||||||
|
b16 byte = byte(0) * 1000; // ERROR "overflows"
|
||||||
|
b16a byte = 0 * 1000; // OK
|
||||||
|
b17 byte = byte(0) * byte(1000); // ERROR "overflows"
|
||||||
|
b18 byte = Uint8/0; // ERROR "division by zero"
|
||||||
|
|
||||||
|
c1 float64 = Big;
|
||||||
|
c2 float64 = Big*Big; // ERROR "overflows"
|
||||||
|
c3 float64 = float64(Big)*Big; // ERROR "overflows"
|
||||||
|
c4 = Big*Big; // ERROR "overflows"
|
||||||
|
c5 = Big/0; // ERROR "division by zero"
|
||||||
|
)
|
||||||
|
|
||||||
|
func f(int);
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
f(Int8); // ERROR "convert"
|
||||||
|
f(Minus1); // ERROR "convert"
|
||||||
|
f(Uint8); // ERROR "convert"
|
||||||
|
f(Const); // OK
|
||||||
|
f(Float32); // ERROR "convert"
|
||||||
|
f(Float); // ERROR "convert"
|
||||||
|
f(ConstFloat); // ERROR "truncate"
|
||||||
|
f(ConstFloat - 0.5); // OK
|
||||||
|
f(Big); // ERROR "convert"
|
||||||
|
f(String); // ERROR "convert"
|
||||||
|
f(Bool); // ERROR "convert"
|
||||||
|
}
|
12
test/const2.go
Normal file
12
test/const2.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// errchk $G $D/$F.go
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
const (
|
||||||
|
A int = 1;
|
||||||
|
B byte; // ERROR "type without expr"
|
||||||
|
)
|
29
test/const3.go
Normal file
29
test/const3.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// $G $D/$F.go && $L $F.$A && ./$A.out
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type T int
|
||||||
|
func (t T) String() string {
|
||||||
|
return fmt.Sprintf("T%d", t);
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
A T = 1<<(1<<iota);
|
||||||
|
B;
|
||||||
|
C;
|
||||||
|
D;
|
||||||
|
E;
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s := fmt.Sprintf("%v %v %v %v %v", A, B, C, D, E);
|
||||||
|
if s != "T2 T4 T16 T256 T65536" {
|
||||||
|
panicln("type info didn't propagate in const: got", s);
|
||||||
|
}
|
||||||
|
}
|
53
test/convert.go
Normal file
53
test/convert.go
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
// $G $D/$F.go && $L $F.$A && ./$A.out
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
func typeof(x interface{}) string {
|
||||||
|
val, typ, indir := sys.Reflect(x);
|
||||||
|
return typ;
|
||||||
|
}
|
||||||
|
|
||||||
|
func f() int {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
func g() int {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
type T func() int
|
||||||
|
|
||||||
|
var m = map[string] T {
|
||||||
|
"f": f
|
||||||
|
}
|
||||||
|
|
||||||
|
type A int
|
||||||
|
type B int
|
||||||
|
|
||||||
|
var a A = 1;
|
||||||
|
var b B = 2;
|
||||||
|
var x int;
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
want := typeof(g);
|
||||||
|
if t := typeof(f); t != want {
|
||||||
|
panicln("type of f is", t, "want", want);
|
||||||
|
}
|
||||||
|
|
||||||
|
want = typeof(x);
|
||||||
|
if t := typeof(+a); t != want {
|
||||||
|
panicln("type of +a is", t, "want", want);
|
||||||
|
}
|
||||||
|
if t := typeof(a+0); t != want {
|
||||||
|
panicln("type of a+0 is", t, "want", want);
|
||||||
|
}
|
||||||
|
if t := typeof(a+b); t != want {
|
||||||
|
panicln("type of a+b is", t, "want", want);
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,8 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// ! errchk $G -e $D/$F.go
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
// explicit conversions are okay, even if they overflow
|
// explicit conversions are okay, even if they overflow
|
||||||
@ -20,10 +22,10 @@ var s string;
|
|||||||
var bad1 string = 1; // ERROR "conver|incompatible"
|
var bad1 string = 1; // ERROR "conver|incompatible"
|
||||||
var bad2 = s + 1; // ERROR "conver|incompatible"
|
var bad2 = s + 1; // ERROR "conver|incompatible"
|
||||||
var bad3 = s + 'a'; // ERROR "conver|incompatible"
|
var bad3 = s + 'a'; // ERROR "conver|incompatible"
|
||||||
var bad4 = "a" + 1; // ERROR "literals|incompatible"
|
var bad4 = "a" + 1; // ERROR "literals|incompatible|convert"
|
||||||
var bad5 = "a" + 'a'; // ERROR "literals|incompatible"
|
var bad5 = "a" + 'a'; // ERROR "literals|incompatible|convert"
|
||||||
|
|
||||||
var bad6 int = 1.5; // ERROR "convert"
|
var bad6 int = 1.5; // ERROR "convert|truncate"
|
||||||
var bad7 int = 1e100; // ERROR "overflow"
|
var bad7 int = 1e100; // ERROR "overflow"
|
||||||
var bad8 float32 = 1e200; // ERROR "overflow"
|
var bad8 float32 = 1e200; // ERROR "overflow"
|
||||||
|
|
||||||
|
@ -63,11 +63,11 @@ pr -n -t $SOURCEFILE | grep '// ERROR' | while read line; do
|
|||||||
mv -f $TMPTMP $TMPALL
|
mv -f $TMPTMP $TMPALL
|
||||||
if test -z "$errmsg"; then
|
if test -z "$errmsg"; then
|
||||||
bug
|
bug
|
||||||
echo 1>&2 "errchk: $SOURCEFILE: missing expected error message on line $lineno: '$regexp'"
|
echo 1>&2 "errchk: $SOURCEFILE:$lineno: missing expected error: '$regexp'"
|
||||||
echo 1 > $TMPSTAT
|
echo 1 > $TMPSTAT
|
||||||
elif ! echo "$errmsg" | egrep -q "$regexp"; then
|
elif ! echo "$errmsg" | egrep -q "$regexp"; then
|
||||||
bug
|
bug
|
||||||
echo 1>&2 "errchk: $SOURCEFILE: error message on line $lineno does not match '$regexp'"
|
echo 1>&2 "errchk: $SOURCEFILE:$lineno: error message does not match '$regexp'"
|
||||||
echo 1>&2 $errmsg
|
echo 1>&2 $errmsg
|
||||||
echo 1 > $TMPSTAT
|
echo 1 > $TMPSTAT
|
||||||
fi
|
fi
|
||||||
|
@ -33,13 +33,14 @@ func main() {
|
|||||||
f = f3div2;
|
f = f3div2;
|
||||||
assert(f == f3div2, "f == f3div2");
|
assert(f == f3div2, "f == f3div2");
|
||||||
|
|
||||||
i = f3div2; // BUG: probably shouldn't compile
|
i = f3div2; // ERROR "truncate"
|
||||||
assert(i == c3div2, "i == c3div2 from f3div2");
|
assert(i == c3div2, "i == c3div2 from f3div2");
|
||||||
assert(i != f3div2, "i != f3div2"); // BUG: certainly shouldn't fail
|
assert(i != f3div2, "i != f3div2"); // ERROR "truncate"
|
||||||
|
|
||||||
const g float64 = 1.0;
|
const g float64 = 1.0;
|
||||||
i = g; // BUG: shouldn't compile
|
i = g; // ERROR "convert"
|
||||||
|
|
||||||
const h float64 = 3.14;
|
const h float64 = 3.14;
|
||||||
i = h; // BUG: certainly shouldn't compile
|
i = h; // ERROR "convert"
|
||||||
|
i = int(h); // ERROR "truncate"
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,6 @@
|
|||||||
package main
|
package main
|
||||||
func main() {
|
func main() {
|
||||||
var x int64 = 0;
|
var x int64 = 0;
|
||||||
println(x != nil); // ERROR "illegal|incompatible"
|
println(x != nil); // ERROR "illegal|incompatible|nil constant"
|
||||||
println(0 != nil); // ERROR "illegal|incompatible"
|
println(0 != nil); // ERROR "illegal|incompatible|nil constant"
|
||||||
}
|
}
|
||||||
|
@ -32,17 +32,12 @@ pc: xxx
|
|||||||
|
|
||||||
|
|
||||||
=========== ./convlit.go
|
=========== ./convlit.go
|
||||||
BUG: errchk: ./convlit.go: missing expected error message on line 16: 'conver|incompatible'
|
BUG: errchk: ./convlit.go: unmatched error messages:
|
||||||
errchk: ./convlit.go: missing expected error message on line 22: 'convert'
|
|
||||||
errchk: ./convlit.go: missing expected error message on line 23: 'overflow'
|
|
||||||
errchk: ./convlit.go: missing expected error message on line 24: 'overflow'
|
|
||||||
errchk: ./convlit.go: unmatched error messages:
|
|
||||||
==================================================
|
==================================================
|
||||||
./convlit.go:8: cannot convert non-integer constant to int
|
./convlit.go:8: constant 1.5 truncated to integer
|
||||||
./convlit.go:11: overflow converting constant to int
|
./convlit.go:11: constant 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 overflows int
|
||||||
./convlit.go:12: overflow converting constant to float
|
./convlit.go:12: constant 34911850510716223476646871064527264675788468424693128821036252992306087892081078460155404277013793117885253p+2968 overflows float
|
||||||
./convlit.go:8: cannot convert non-integer constant to int
|
./convlit.go:9: constant 1.5 truncated to integer
|
||||||
./convlit.go:8: fatal error: too many errors
|
|
||||||
==================================================
|
==================================================
|
||||||
|
|
||||||
=========== ./helloworld.go
|
=========== ./helloworld.go
|
||||||
@ -116,7 +111,7 @@ bugs/bug108.go:4: stupid shift: 1025
|
|||||||
BUG: errchk: command succeeded unexpectedly: 6g bugs/bug108.go
|
BUG: errchk: command succeeded unexpectedly: 6g bugs/bug108.go
|
||||||
|
|
||||||
=========== bugs/bug115.go
|
=========== bugs/bug115.go
|
||||||
bugs/bug115.go:8: overflow converting constant to uint
|
bugs/bug115.go:8: constant -1 overflows uint
|
||||||
BUG: bug115 should compile
|
BUG: bug115 should compile
|
||||||
|
|
||||||
=========== bugs/bug117.go
|
=========== bugs/bug117.go
|
||||||
@ -129,7 +124,9 @@ BUG: should compile
|
|||||||
BUG: errchk: command succeeded unexpectedly: 6g bugs/bug125.go
|
BUG: errchk: command succeeded unexpectedly: 6g bugs/bug125.go
|
||||||
|
|
||||||
=========== bugs/bug131.go
|
=========== bugs/bug131.go
|
||||||
BUG: should not compile
|
bugs/bug131.go:7: cannot convert uint64 constant to int64
|
||||||
|
bugs/bug131.go:7: illegal types for operand: AS
|
||||||
|
int64
|
||||||
|
|
||||||
=========== bugs/bug132.go
|
=========== bugs/bug132.go
|
||||||
BUG: compilation succeeds incorrectly
|
BUG: compilation succeeds incorrectly
|
||||||
@ -138,12 +135,11 @@ BUG: compilation succeeds incorrectly
|
|||||||
BUG: should not compile
|
BUG: should not compile
|
||||||
|
|
||||||
=========== bugs/bug138.go
|
=========== bugs/bug138.go
|
||||||
bugs/bug138.go:8: overflow converting constant to uint
|
bugs/bug138.go:8: constant -1 overflows uint
|
||||||
bugs/bug138.go:8: illegal combination of literals CONV 7
|
|
||||||
BUG should compile
|
BUG should compile
|
||||||
|
|
||||||
=========== fixedbugs/bug016.go
|
=========== fixedbugs/bug016.go
|
||||||
fixedbugs/bug016.go:7: overflow converting constant to uint
|
fixedbugs/bug016.go:7: constant -3 overflows uint
|
||||||
|
|
||||||
=========== fixedbugs/bug027.go
|
=========== fixedbugs/bug027.go
|
||||||
hi
|
hi
|
||||||
@ -177,7 +173,7 @@ fixedbugs/bug039.go:6: variable x redeclared in this block
|
|||||||
fixedbugs/bug041.go:5: export of incomplete type t
|
fixedbugs/bug041.go:5: export of incomplete type t
|
||||||
|
|
||||||
=========== fixedbugs/bug049.go
|
=========== fixedbugs/bug049.go
|
||||||
fixedbugs/bug049.go:6: illegal conversion of nil to string
|
fixedbugs/bug049.go:6: cannot convert nil constant to string
|
||||||
|
|
||||||
=========== fixedbugs/bug050.go
|
=========== fixedbugs/bug050.go
|
||||||
fixedbugs/bug050.go:3: package statement must be first
|
fixedbugs/bug050.go:3: package statement must be first
|
||||||
@ -187,7 +183,7 @@ sys.6:1 fixedbugs/bug050.go:3: syntax error near package
|
|||||||
fixedbugs/bug051.go:10: expression must be a constant
|
fixedbugs/bug051.go:10: expression must be a constant
|
||||||
|
|
||||||
=========== fixedbugs/bug062.go
|
=========== fixedbugs/bug062.go
|
||||||
fixedbugs/bug062.go:6: illegal conversion of nil to string
|
fixedbugs/bug062.go:6: cannot convert nil constant to string
|
||||||
fixedbugs/bug062.go:6: illegal types for operand: AS
|
fixedbugs/bug062.go:6: illegal types for operand: AS
|
||||||
string
|
string
|
||||||
|
|
||||||
@ -210,9 +206,13 @@ fixedbugs/bug072.go:6: bug: undefined
|
|||||||
fixedbugs/bug073.go:8: illegal types for operand: LSH
|
fixedbugs/bug073.go:8: illegal types for operand: LSH
|
||||||
int
|
int
|
||||||
int
|
int
|
||||||
|
fixedbugs/bug073.go:8: illegal types for operand: AS
|
||||||
|
int
|
||||||
fixedbugs/bug073.go:9: illegal types for operand: RSH
|
fixedbugs/bug073.go:9: illegal types for operand: RSH
|
||||||
int
|
int
|
||||||
int
|
int
|
||||||
|
fixedbugs/bug073.go:9: illegal types for operand: AS
|
||||||
|
int
|
||||||
|
|
||||||
=========== fixedbugs/bug074.go
|
=========== fixedbugs/bug074.go
|
||||||
fixedbugs/bug074.go:6: invalid type for composite literal: string
|
fixedbugs/bug074.go:6: invalid type for composite literal: string
|
||||||
@ -227,18 +227,6 @@ fixedbugs/bug083.dir/bug1.go:9: syntax error near t0
|
|||||||
=========== fixedbugs/bug086.go
|
=========== fixedbugs/bug086.go
|
||||||
fixedbugs/bug086.go:5: function ends without a return statement
|
fixedbugs/bug086.go:5: function ends without a return statement
|
||||||
|
|
||||||
=========== fixedbugs/bug090.go
|
|
||||||
fixedbugs/bug090.go:32: cannot convert non-integer constant to int
|
|
||||||
fixedbugs/bug090.go:32: illegal types for operand: AS
|
|
||||||
int
|
|
||||||
fixedbugs/bug090.go:34: cannot convert non-integer constant to int
|
|
||||||
fixedbugs/bug090.go:34: illegal types for operand: CALL
|
|
||||||
bool
|
|
||||||
fixedbugs/bug090.go:40: cannot convert non-integer constant to int
|
|
||||||
fixedbugs/bug090.go:40: illegal types for operand: AS
|
|
||||||
int
|
|
||||||
float64
|
|
||||||
|
|
||||||
=========== fixedbugs/bug091.go
|
=========== fixedbugs/bug091.go
|
||||||
fixedbugs/bug091.go:15: c: undefined
|
fixedbugs/bug091.go:15: c: undefined
|
||||||
fixedbugs/bug091.go:15: illegal types for operand: AS
|
fixedbugs/bug091.go:15: illegal types for operand: AS
|
||||||
|
Loading…
Reference in New Issue
Block a user