blob: ff1f5221d079ebc3e2b720ec667ea46561c8d1e4 [file] [log] [blame]
// 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.
#include "go.h"
#define TUP(x,y) (((x)<<16)|(y))
void
convlit(Node *n, Node *t)
{
int et;
if(n->op != OLITERAL)
return;
if(t == N)
return;
n->type = t;
et = t->etype;
switch(whatis(n)) {
case Wlitint:
if(isptrto(t, TSTRING)) {
Rune rune;
int l;
String *s;
rune = n->val.vval;
l = runelen(rune);
s = mal(sizeof(*s)+l);
s->len = l;
runetochar((char*)(s->s), &rune);
n->val.sval = s;
n->val.ctype = CTSTR;
break;
}
if(isint[et]) {
if(n->val.vval < minintval[et])
goto bad2;
if(n->val.vval > maxintval[et])
goto bad2;
break;
}
if(isfloat[et]) {
if(n->val.vval < minfloatval[et])
goto bad2;
if(n->val.vval > maxfloatval[et])
goto bad2;
n->val.dval = n->val.vval;
n->val.ctype = CTFLT;
break;
}
goto bad1;
case Wlitfloat:
if(isint[et]) {
if(n->val.dval < minintval[et])
goto bad2;
if(n->val.dval > maxintval[et])
goto bad2;
n->val.vval = n->val.dval;
n->val.ctype = CTINT;
break;
}
if(isfloat[et]) {
if(n->val.dval < minfloatval[et])
goto bad2;
if(n->val.dval > maxfloatval[et])
goto bad2;
break;
}
goto bad1;
}
return;
bad1:
yyerror("illegal conversion of constant to %T", t);
return;
bad2:
yyerror("overflow converting constant to %T", t);
return;
}
void
evconst(Node *n)
{
Node *t, *nl, *nr;
long len;
String *str;
int wl, wr;
nl = n->left;
if(nl == N)
return;
switch(n->op) {
case OCONV:
t = n->type;
*n = *nl;
n->type = t;
return;
}
wl = whatis(nl);
switch(wl) {
default:
return;
case Wlitint:
case Wlitfloat:
case Wlitbool:
case Wlitstr:
break;
}
nr = n->right;
if(nr == N)
goto unary;
wr = whatis(nr);
switch(wr) {
default:
return;
case Wlitint:
case Wlitfloat:
case Wlitbool:
case Wlitstr:
break;
}
if(wl != wr) {
yyerror("illegal combination of literals %d %d", nl->etype, nr->etype);
return;
}
switch(TUP(n->op, wl)) {
default:
yyerror("illegal combination of literals %O %d", n->op, wl);
return;
case TUP(OADD, Wlitint):
nl->val.vval += nr->val.vval;
break;
case TUP(OSUB, Wlitint):
nl->val.vval -= nr->val.vval;
break;
case TUP(OMUL, Wlitint):
nl->val.vval *= nr->val.vval;
break;
case TUP(ODIV, Wlitint):
nl->val.vval /= nr->val.vval;
break;
case TUP(OMOD, Wlitint):
nl->val.vval %= nr->val.vval;
break;
case TUP(OLSH, Wlitint):
nl->val.vval <<= nr->val.vval;
break;
case TUP(ORSH, Wlitint):
nl->val.vval >>= nr->val.vval;
break;
case TUP(OOR, Wlitint):
nl->val.vval |= nr->val.vval;
break;
case TUP(OAND, Wlitint):
nl->val.vval &= nr->val.vval;
break;
case TUP(OADD, Wlitfloat):
nl->val.dval += nr->val.dval;
break;
case TUP(OSUB, Wlitfloat):
nl->val.dval -= nr->val.dval;
break;
case TUP(OMUL, Wlitfloat):
nl->val.dval *= nr->val.dval;
break;
case TUP(ODIV, Wlitfloat):
nl->val.dval /= nr->val.dval;
break;
case TUP(OEQ, Wlitint):
if(nl->val.vval == nr->val.vval)
goto settrue;
goto setfalse;
case TUP(ONE, Wlitint):
if(nl->val.vval != nr->val.vval)
goto settrue;
goto setfalse;
case TUP(OLT, Wlitint):
if(nl->val.vval < nr->val.vval)
goto settrue;
goto setfalse;
case TUP(OLE, Wlitint):
if(nl->val.vval <= nr->val.vval)
goto settrue;
goto setfalse;
case TUP(OGE, Wlitint):
if(nl->val.vval >= nr->val.vval)
goto settrue;
goto setfalse;
case TUP(OGT, Wlitint):
if(nl->val.vval > nr->val.vval)
goto settrue;
goto setfalse;
case TUP(OEQ, Wlitfloat):
if(nl->val.dval == nr->val.dval)
goto settrue;
goto setfalse;
case TUP(ONE, Wlitfloat):
if(nl->val.dval != nr->val.dval)
goto settrue;
goto setfalse;
case TUP(OLT, Wlitfloat):
if(nl->val.dval < nr->val.dval)
goto settrue;
goto setfalse;
case TUP(OLE, Wlitfloat):
if(nl->val.dval <= nr->val.dval)
goto settrue;
goto setfalse;
case TUP(OGE, Wlitfloat):
if(nl->val.dval >= nr->val.dval)
goto settrue;
goto setfalse;
case TUP(OGT, Wlitfloat):
if(nl->val.dval > nr->val.dval)
goto settrue;
goto setfalse;
case TUP(OEQ, Wlitstr):
if(cmpslit(nl, nr) == 0)
goto settrue;
goto setfalse;
case TUP(ONE, Wlitstr):
if(cmpslit(nl, nr) != 0)
goto settrue;
goto setfalse;
case TUP(OLT, Wlitstr):
if(cmpslit(nl, nr) < 0)
goto settrue;
goto setfalse;
case TUP(OLE, Wlitstr):
if(cmpslit(nl, nr) <= 0)
goto settrue;
goto setfalse;
case TUP(OGE, Wlitstr):
if(cmpslit(nl, nr) >= 0l)
goto settrue;
goto setfalse;
case TUP(OGT, Wlitstr):
if(cmpslit(nl, nr) > 0)
goto settrue;
goto setfalse;
case TUP(OADD, Wlitstr):
len = nl->val.sval->len + nr->val.sval->len;
str = mal(sizeof(*str) + len);
str->len = len;
memcpy(str->s, nl->val.sval->s, nl->val.sval->len);
memcpy(str->s+nl->val.sval->len, nr->val.sval->s, nr->val.sval->len);
str->len = len;
nl->val.sval = str;
break;
case TUP(OOROR, Wlitbool):
if(nl->val.vval || nr->val.vval)
goto settrue;
goto setfalse;
case TUP(OANDAND, Wlitbool):
if(nl->val.vval && nr->val.vval)
goto settrue;
goto setfalse;
}
*n = *nl;
return;
settrue:
*n = *booltrue;
return;
setfalse:
*n = *boolfalse;
return;
unary:
switch(TUP(n->op, wl)) {
default:
yyerror("illegal combination of literals %O %d", n->op, wl);
return;
case TUP(OPLUS, Wlitint):
nl->val.vval = +nl->val.vval;
break;
case TUP(OMINUS, Wlitint):
nl->val.vval = -nl->val.vval;
break;
case TUP(OCOM, Wlitint):
nl->val.vval = ~nl->val.vval;
break;
case TUP(OPLUS, Wlitfloat):
nl->val.dval = +nl->val.dval;
break;
case TUP(OMINUS, Wlitfloat):
nl->val.dval = -nl->val.dval;
break;
case TUP(ONOT, Wlitbool):
if(nl->val.vval)
goto settrue;
goto setfalse;
}
*n = *nl;
}
void
defaultlit(Node *n)
{
if(n == N)
return;
if(n->type != N)
return;
if(n->op != OLITERAL)
return;
switch(n->val.ctype) {
default:
yyerror("defaultlit: unknown literal: %N", n);
break;
case CTINT:
case CTSINT:
case CTUINT:
n->type = types[TINT32];
break;
case CTFLT:
n->type = types[TFLOAT64];
break;
case CTBOOL:
n->type = types[TBOOL];
break;
case CTSTR:
n->type = types[TSTRING];
break;
}
}
int
cmpslit(Node *l, Node *r)
{
long l1, l2, i, m;
uchar *s1, *s2;
l1 = l->val.sval->len;
l2 = r->val.sval->len;
s1 = l->val.sval->s;
s2 = r->val.sval->s;
m = l1;
if(l2 < m)
m = l2;
for(i=0; i<m; i++) {
if(s1[i] == s2[i])
continue;
if(s1[i] > s2[i])
return +1;
return -1;
}
if(l1 == l2)
return 0;
if(l1 > l2)
return +1;
return -1;
}