1
0
mirror of https://github.com/golang/go synced 2024-11-22 01:14:40 -07:00

new types complex, complex64 and complex128

only front-end compiler work.
best to do thin in 3 steps
1. frontend
2. backend
3. lib

R=rsc
CC=golang-dev
https://golang.org/cl/214042
This commit is contained in:
Ken Thompson 2010-02-17 22:08:30 -08:00
parent 3f09c0b0d7
commit 33d6a260c1
9 changed files with 285 additions and 56 deletions

View File

@ -18,6 +18,7 @@ Typedef typedefs[] =
"uint", TUINT, TUINT32,
"uintptr", TUINTPTR, TUINT64,
"float", TFLOAT, TFLOAT32,
"complex", TCOMPLEX, TCOMPLEX64,
0
};

View File

@ -166,8 +166,12 @@ dowidth(Type *t)
case TINT64:
case TUINT64:
case TFLOAT64:
case TCOMPLEX64:
w = 8;
break;
case TCOMPLEX128:
w = 16;
break;
case TPTR32:
w = 4;
checkwidth(t->type);
@ -385,10 +389,14 @@ typeinit(void)
isint[TUINT] = 1;
isint[TUINTPTR] = 1;
for(i=TFLOAT32; i<=TFLOAT64; i++)
isfloat[i] = 1;
isfloat[TFLOAT32] = 1;
isfloat[TFLOAT64] = 1;
isfloat[TFLOAT] = 1;
iscomplex[TCOMPLEX64] = 1;
iscomplex[TCOMPLEX128] = 1;
iscomplex[TCOMPLEX] = 1;
isptr[TPTR32] = 1;
isptr[TPTR64] = 1;
@ -425,6 +433,13 @@ typeinit(void)
minfltval[i] = mal(sizeof(*minfltval[i]));
maxfltval[i] = mal(sizeof(*maxfltval[i]));
}
if(iscomplex[i]) {
okforeq[i] = 1;
okforadd[i] = 1;
okforarith[i] = 1;
okforconst[i] = 1;
// issimple[i] = 1;
}
}
issimple[TBOOL] = 1;
@ -518,6 +533,11 @@ typeinit(void)
mpatoflt(maxfltval[TFLOAT64], "18014398509481983p970"); /* 2^53-1 p (1023-52) + 1/2 ulp */
mpatoflt(minfltval[TFLOAT64], "-18014398509481983p970");
maxfltval[TCOMPLEX64] = maxfltval[TFLOAT32];
minfltval[TCOMPLEX64] = minfltval[TFLOAT32];
maxfltval[TCOMPLEX128] = maxfltval[TFLOAT64];
minfltval[TCOMPLEX128] = minfltval[TFLOAT64];
/* for walk to use in error messages */
types[TFUNC] = functype(N, nil, nil);

View File

@ -5,6 +5,7 @@
#include "go.h"
#define TUP(x,y) (((x)<<16)|(y))
static Val tocplx(Val);
static Val toflt(Val);
static Val tostr(Val);
static Val copyval(Val);
@ -165,24 +166,51 @@ convlit1(Node **np, Type *t, int explicit)
case CTINT:
case CTFLT:
case CTCPLX:
ct = n->val.ctype;
if(isint[et]) {
if(ct == CTFLT)
switch(ct) {
default:
case CTCPLX:
case CTFLT:
n->val = toint(n->val);
else if(ct != CTINT)
goto bad;
// flowthrough
case CTINT:
overflow(n->val, t);
} else if(isfloat[et]) {
if(ct == CTINT)
break;
}
} else
if(isfloat[et]) {
switch(ct) {
default:
case CTCPLX:
case CTINT:
n->val = toflt(n->val);
else if(ct != CTFLT)
goto bad;
// flowthrough
case CTFLT:
overflow(n->val, t);
n->val.u.fval = truncfltlit(n->val.u.fval, t);
} else if(et == TSTRING && ct == CTINT && explicit)
break;
}
} else
if(iscomplex[et]) {
switch(ct) {
default:
goto bad;
case CTFLT:
case CTINT:
n->val = tocplx(n->val);
break;
case CTCPLX:
overflow(n->val, t);
break;
}
} else
if(et == TSTRING && ct == CTINT && explicit)
n->val = tostr(n->val);
else
goto bad;
break;
}
n->type = t;
return;
@ -204,6 +232,7 @@ copyval(Val v)
{
Mpint *i;
Mpflt *f;
Mpcplx *c;
switch(v.ctype) {
case CTINT:
@ -216,6 +245,36 @@ copyval(Val v)
mpmovefltflt(f, v.u.fval);
v.u.fval = f;
break;
case CTCPLX:
c = mal(sizeof(*c));
mpmovefltflt(&c->real, &v.u.cval->real);
mpmovefltflt(&c->imag, &v.u.cval->imag);
v.u.cval = c;
break;
}
return v;
}
static Val
tocplx(Val v)
{
Mpcplx *c;
switch(v.ctype) {
case CTINT:
c = mal(sizeof(*c));
mpmovefixflt(&c->real, v.u.xval);
mpmovecflt(&c->imag, 0.0);
v.ctype = CTCPLX;
v.u.cval = c;
break;
case CTFLT:
c = mal(sizeof(*c));
mpmovefltflt(&c->real, v.u.fval);
mpmovecflt(&c->imag, 0.0);
v.ctype = CTCPLX;
v.u.cval = c;
break;
}
return v;
}
@ -225,11 +284,21 @@ toflt(Val v)
{
Mpflt *f;
if(v.ctype == CTINT) {
switch(v.ctype) {
case CTINT:
f = mal(sizeof(*f));
mpmovefixflt(f, v.u.xval);
v.ctype = CTFLT;
v.u.fval = f;
break;
case CTCPLX:
f = mal(sizeof(*f));
mpmovefltflt(f, &v.u.cval->real);
if(mpcmpfltc(&v.u.cval->imag, 0) != 0)
yyerror("constant %#F truncated to real", v.u.fval);
v.ctype = CTFLT;
v.u.fval = f;
break;
}
return v;
}
@ -239,12 +308,23 @@ toint(Val v)
{
Mpint *i;
if(v.ctype == CTFLT) {
switch(v.ctype) {
case 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;
break;
case CTCPLX:
i = mal(sizeof(*i));
if(mpmovefltfix(i, &v.u.cval->real) < 0)
yyerror("constant %#F truncated to integer", v.u.fval);
if(mpcmpfltc(&v.u.cval->imag, 0) != 0)
yyerror("constant %#F truncated to real", v.u.fval);
v.ctype = CTINT;
v.u.xval = i;
break;
}
return v;
}
@ -260,15 +340,24 @@ overflow(Val v, Type *t)
case CTINT:
if(!isint[t->etype])
fatal("overflow: %T integer constant", t);
if(mpcmpfixfix(v.u.xval, minintval[t->etype]) < 0
|| mpcmpfixfix(v.u.xval, maxintval[t->etype]) > 0)
if(mpcmpfixfix(v.u.xval, minintval[t->etype]) < 0 ||
mpcmpfixfix(v.u.xval, maxintval[t->etype]) > 0)
yyerror("constant %B overflows %T", v.u.xval, t);
break;
case CTFLT:
if(!isfloat[t->etype])
fatal("overflow: %T floating-point constant", t);
if(mpcmpfltflt(v.u.fval, minfltval[t->etype]) <= 0
|| mpcmpfltflt(v.u.fval, maxfltval[t->etype]) >= 0)
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;
case CTCPLX:
if(!iscomplex[t->etype])
fatal("overflow: %T complex constant", t);
if(mpcmpfltflt(&v.u.cval->real, minfltval[t->etype]) <= 0 ||
mpcmpfltflt(&v.u.cval->real, maxfltval[t->etype]) >= 0 ||
mpcmpfltflt(&v.u.cval->imag, minfltval[t->etype]) <= 0 ||
mpcmpfltflt(&v.u.cval->imag, maxfltval[t->etype]) >= 0)
yyerror("constant %#F overflows %T", v.u.fval, t);
break;
}
@ -283,8 +372,8 @@ tostr(Val v)
switch(v.ctype) {
case CTINT:
if(mpcmpfixfix(v.u.xval, minintval[TINT]) < 0
|| mpcmpfixfix(v.u.xval, maxintval[TINT]) > 0)
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);
@ -380,7 +469,7 @@ evconst(Node *n)
if(consttype(nl) < 0)
return;
wl = nl->type->etype;
if(isint[wl] || isfloat[wl])
if(isint[wl] || isfloat[wl] || iscomplex[wl])
wl = TIDEAL;
nr = n->right;
@ -391,7 +480,7 @@ evconst(Node *n)
if(consttype(nr) < 0)
return;
wr = nr->type->etype;
if(isint[wr] || isfloat[wr])
if(isint[wr] || isfloat[wr] || iscomplex[wr])
wr = TIDEAL;
// check for compatible general types (numeric, string, etc)
@ -433,11 +522,12 @@ evconst(Node *n)
rv = nr->val;
// since wl == wr,
// the only way v.ctype != nr->val.ctype
// is when one is CTINT and the other CTFLT.
// make both CTFLT.
if(v.ctype != nr->val.ctype) {
// convert to common ideal
if(v.ctype == CTCPLX || rv.ctype == CTCPLX) {
v = tocplx(v);
rv = tocplx(rv);
}
if(v.ctype == CTFLT || rv.ctype == CTFLT) {
v = toflt(v);
rv = toflt(rv);
}
@ -515,6 +605,20 @@ evconst(Node *n)
mpdivfltflt(v.u.fval, rv.u.fval);
break;
case TUP(OADD, CTCPLX):
mpaddfltflt(&v.u.cval->real, &rv.u.cval->real);
mpaddfltflt(&v.u.cval->imag, &rv.u.cval->imag);
break;
case TUP(OSUB, CTCPLX):
mpsubfltflt(&v.u.cval->real, &rv.u.cval->real);
mpsubfltflt(&v.u.cval->imag, &rv.u.cval->imag);
break;
case TUP(OMUL, CTCPLX):
goto illegal; // TODO
case TUP(ODIV, CTCPLX):
goto illegal; // TODO
break;
case TUP(OEQ, CTNIL):
goto settrue;
case TUP(ONE, CTNIL):
@ -737,6 +841,7 @@ nodlit(Val v)
break;
case CTINT:
case CTFLT:
case CTCPLX:
n->type = types[TIDEAL];
break;
case CTNIL:
@ -815,7 +920,8 @@ defaultlit(Node **np, Type *t)
if(t != T) {
if(isint[t->etype])
n->type = t;
else if(isfloat[t->etype]) {
else
if(isfloat[t->etype]) {
n->type = t;
n->val = toflt(n->val);
}
@ -827,7 +933,25 @@ defaultlit(Node **np, Type *t)
if(t != T) {
if(isfloat[t->etype])
n->type = t;
else if(isint[t->etype]) {
else
if(isint[t->etype]) {
n->type = t;
n->val = toint(n->val);
}
}
overflow(n->val, n->type);
break;
case CTCPLX:
n->type = types[TCOMPLEX];
if(t != T) {
if(iscomplex[t->etype])
n->type = t;
else
if(isfloat[t->etype]) {
n->type = t;
n->val = toflt(n->val);
} else
if(isint[t->etype]) {
n->type = t;
n->val = toint(n->val);
}
@ -862,6 +986,11 @@ defaultlit2(Node **lp, Node **rp, int force)
}
if(!force)
return;
if(isconst(l, CTCPLX) || isconst(r, CTCPLX)) {
convlit(lp, types[TCOMPLEX]);
convlit(rp, types[TCOMPLEX]);
return;
}
if(isconst(l, CTFLT) || isconst(r, CTFLT)) {
convlit(lp, types[TFLOAT]);
convlit(rp, types[TFLOAT]);
@ -1013,22 +1142,28 @@ convconst(Node *con, Type *t, Val *val)
}
if(isfloat[tt]) {
if(con->val.ctype == CTINT) {
con->val.ctype = CTFLT;
con->val.u.fval = mal(sizeof *con->val.u.fval);
mpmovefixflt(con->val.u.fval, val->u.xval);
}
if(con->val.ctype != CTFLT)
fatal("convconst ctype=%d %T", con->val.ctype, t);
if(!isfloat[tt]) {
// easy to handle, but can it happen?
fatal("convconst CTINT %T", t);
}
con->val = toflt(con->val);
// if(con->val.ctype == CTINT) {
// con->val.ctype = CTFLT;
// con->val.u.fval = mal(sizeof *con->val.u.fval);
// mpmovefixflt(con->val.u.fval, val->u.xval);
// }
// if(con->val.ctype != CTFLT)
// fatal("convconst ctype=%d %T", con->val.ctype, t);
if(tt == TFLOAT32)
con->val.u.fval = truncfltlit(con->val.u.fval, t);
return;
}
if(iscomplex[tt]) {
con->val = tocplx(con->val);
if(tt == TCOMPLEX64) {
con->val.u.cval->real = *truncfltlit(&con->val.u.cval->real, types[TFLOAT32]);
con->val.u.cval->imag = *truncfltlit(&con->val.u.cval->imag, types[TFLOAT32]);
}
return;
}
fatal("convconst %lT constant", t);
}

View File

@ -113,6 +113,13 @@ struct Mpflt
short exp;
};
typedef struct Mpcplx Mpcplx;
struct Mpcplx
{
Mpflt real;
Mpflt imag;
};
typedef struct Val Val;
struct Val
{
@ -123,6 +130,7 @@ struct Val
short bval; // bool value CTBOOL
Mpint* xval; // int CTINT
Mpflt* fval; // float CTFLT
Mpcplx* cval; // float CTCPLX
Strlit* sval; // string CTSTR
} u;
};
@ -422,28 +430,32 @@ enum
TINT64, TUINT64,
TINT, TUINT, TUINTPTR,
TFLOAT32, // 12
TCOMPLEX64, // 12
TCOMPLEX128,
TCOMPLEX,
TFLOAT32, // 15
TFLOAT64,
TFLOAT,
TBOOL, // 15
TBOOL, // 18
TPTR32, TPTR64, // 16
TPTR32, TPTR64, // 19
TFUNC, // 18
TFUNC, // 21
TARRAY,
T_old_DARRAY,
TSTRUCT, // 21
TSTRUCT, // 24
TCHAN,
TMAP,
TINTER, // 24
TINTER, // 27
TFORW,
TFIELD,
TANY,
TSTRING,
// pseudo-types for literals
TIDEAL, // 29
TIDEAL, // 32
TNIL,
TBLANK,
@ -459,6 +471,7 @@ enum
CTINT,
CTFLT,
CTCPLX,
CTSTR,
CTBOOL,
CTNIL,
@ -668,6 +681,7 @@ EXTERN uchar isptr[NTYPE];
EXTERN uchar isforw[NTYPE];
EXTERN uchar isint[NTYPE];
EXTERN uchar isfloat[NTYPE];
EXTERN uchar iscomplex[NTYPE];
EXTERN uchar issigned[NTYPE];
EXTERN uchar issimple[NTYPE];

View File

@ -900,6 +900,8 @@ tnum:
goto casedot;
if(c == 'e' || c == 'E')
goto casee;
if(c == 'i')
goto casei;
if(c1)
yyerror("malformed octal constant");
goto ncu;
@ -911,6 +913,8 @@ dc:
goto casee;
if(c == 'p' || c == 'P')
goto casep;
if(c == 'i')
goto casei;
ncu:
*cp = 0;
@ -933,6 +937,8 @@ casedot:
if(!isdigit(c))
break;
}
if(c == 'i')
goto casei;
if(c != 'e' && c != 'E')
goto caseout;
@ -949,6 +955,8 @@ casee:
*cp++ = c;
c = getc();
}
if(c == 'i')
goto casei;
goto caseout;
casep:
@ -964,8 +972,24 @@ casep:
*cp++ = c;
c = getc();
}
if(c == 'i')
goto casei;
goto caseout;
casei:
// imaginary constant
*cp = 0;
yylval.val.u.cval = mal(sizeof(*yylval.val.u.cval));
mpmovecflt(&yylval.val.u.cval->real, 0.0);
mpatoflt(&yylval.val.u.cval->imag, lexbuf);
if(yylval.val.u.cval->imag.val.ovf) {
yyerror("overflow in imaginary constant");
mpmovecflt(&yylval.val.u.cval->real, 0.0);
}
yylval.val.ctype = CTCPLX;
DBG("lex: imaginary literal\n");
return LLITERAL;
caseout:
*cp = 0;
ungetc(c);
@ -1235,6 +1259,9 @@ static struct
"float32", LNAME, TFLOAT32, OXXX,
"float64", LNAME, TFLOAT64, OXXX,
"complex64", LNAME, TCOMPLEX64, OXXX,
"complex128", LNAME, TCOMPLEX128, OXXX,
"bool", LNAME, TBOOL, OXXX,
"byte", LNAME, TUINT8, OXXX,
"string", LNAME, TSTRING, OXXX,

View File

@ -129,6 +129,11 @@ exprfmt(Fmt *f, Node *n, int prec)
else
fmtprint(f, "false");
break;
case CTCPLX:
fmtprint(f, "%.17g+%.17gi",
mpgetflt(&n->val.u.cval->real),
mpgetflt(&n->val.u.cval->imag));
break;
case CTFLT:
fmtprint(f, "%.17g", mpgetflt(n->val.u.fval));
break;

View File

@ -447,6 +447,9 @@ structnames[] =
[TINT64] = "*runtime.Int64Type",
[TUINT64] = "*runtime.Uint64Type",
[TUINTPTR] = "*runtime.UintptrType",
[TCOMPLEX] = "*runtime.ComplexType",
[TCOMPLEX64] = "*runtime.Complex64Type",
[TCOMPLEX128] = "*runtime.Complex128Type",
[TFLOAT] = "*runtime.FloatType",
[TFLOAT32] = "*runtime.Float32Type",
[TFLOAT64] = "*runtime.Float64Type",

View File

@ -954,6 +954,9 @@ etnames[] =
[TFLOAT] = "FLOAT",
[TFLOAT32] = "FLOAT32",
[TFLOAT64] = "FLOAT64",
[TCOMPLEX] = "COMPLEX",
[TCOMPLEX64] = "COMPLEX64",
[TCOMPLEX128] = "COMPLEX128",
[TBOOL] = "BOOL",
[TPTR32] = "PTR32",
[TPTR64] = "PTR64",
@ -1453,6 +1456,11 @@ Nconv(Fmt *fp)
case CTFLT:
snprint(buf1, sizeof(buf1), "F%g", mpgetflt(n->val.u.fval));
break;
case CTCPLX:
snprint(buf1, sizeof(buf1), "(F%g+F%gi)",
mpgetflt(&n->val.u.cval->real),
mpgetflt(&n->val.u.cval->imag));
break;
case CTSTR:
snprint(buf1, sizeof(buf1), "S\"%Z\"", n->val.u.sval);
break;
@ -1665,7 +1673,14 @@ isideal(Type *t)
{
if(t == T)
return 0;
return t == idealstring || t == idealbool || t->etype == TNIL || t->etype == TIDEAL;
if(t == idealstring || t == idealbool)
return 1;
switch(t->etype) {
case TNIL:
case TIDEAL:
return 1;
}
return 0;
}
/*

View File

@ -99,6 +99,15 @@ type Float64Type commonType
// FloatType represents a float type.
type FloatType commonType
// Complex64Type represents a complex64 type.
type Complex64Type commonType
// Complex128Type represents a complex32 type.
type Complex128Type commonType
// ComplexType represents a complex type.
type ComplexType commonType
// Int16Type represents an int16 type.
type Int16Type commonType