#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);
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;
- overflow(n->val, t);
- } else if(isfloat[et]) {
- if(ct == CTINT)
+ // flowthrough
+ case CTINT:
+ overflow(n->val, t);
+ break;
+ }
+ } else
+ if(isfloat[et]) {
+ switch(ct) {
+ default:
+ case CTCPLX:
+ case CTINT:
n->val = toflt(n->val);
- else if(ct != CTFLT)
+ // flowthrough
+ case CTFLT:
+ overflow(n->val, t);
+ n->val.u.fval = truncfltlit(n->val.u.fval, t);
+ break;
+ }
+ } else
+ if(iscomplex[et]) {
+ switch(ct) {
+ default:
goto bad;
- overflow(n->val, t);
- n->val.u.fval = truncfltlit(n->val.u.fval, t);
- } else if(et == TSTRING && ct == CTINT && explicit)
+ 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;
{
Mpint *i;
Mpflt *f;
+ Mpcplx *c;
switch(v.ctype) {
case CTINT:
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;
}
{
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;
}
{
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;
}
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;
}
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);
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;
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)
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);
}
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):
break;
case CTINT:
case CTFLT:
+ case CTCPLX:
n->type = types[TIDEAL];
break;
case CTNIL:
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);
}
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);
}
}
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]);
}
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);
}
goto casedot;
if(c == 'e' || c == 'E')
goto casee;
+ if(c == 'i')
+ goto casei;
if(c1)
yyerror("malformed octal constant");
goto ncu;
goto casee;
if(c == 'p' || c == 'P')
goto casep;
+ if(c == 'i')
+ goto casei;
ncu:
*cp = 0;
if(!isdigit(c))
break;
}
+ if(c == 'i')
+ goto casei;
if(c != 'e' && c != 'E')
goto caseout;
*cp++ = c;
c = getc();
}
+ if(c == 'i')
+ goto casei;
goto caseout;
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);
"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,
[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",
[TBOOL] = "*runtime.BoolType",
- [TSTRING] = "*runtime.StringType",
+ [TSTRING] = "*runtime.StringType",
- [TPTR32] = "*runtime.PtrType",
- [TPTR64] = "*runtime.PtrType",
+ [TPTR32] = "*runtime.PtrType",
+ [TPTR64] = "*runtime.PtrType",
[TSTRUCT] = "*runtime.StructType",
- [TINTER] = "*runtime.InterfaceType",
+ [TINTER] = "*runtime.InterfaceType",
[TCHAN] = "*runtime.ChanType",
[TMAP] = "*runtime.MapType",
- [TARRAY] = "*runtime.ArrayType",
+ [TARRAY] = "*runtime.ArrayType",
[TFUNC] = "*runtime.FuncType",
};