2008-06-04 15:37:38 -06:00
|
|
|
// 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, Type *t)
|
|
|
|
{
|
|
|
|
int et;
|
|
|
|
|
2008-06-15 21:24:30 -06:00
|
|
|
if(n == N || n->op != OLITERAL || t == T)
|
2008-06-04 15:37:38 -06:00
|
|
|
return;
|
2008-06-15 21:24:30 -06:00
|
|
|
|
|
|
|
if(t->etype == TANY || isptrto(t, TANY)) {
|
|
|
|
defaultlit(n);
|
2008-06-04 15:37:38 -06:00
|
|
|
return;
|
2008-06-15 21:24:30 -06:00
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2008-06-15 21:24:30 -06:00
|
|
|
n->type = t;
|
2008-06-04 15:37:38 -06:00
|
|
|
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 *nl, *nr;
|
|
|
|
long len;
|
|
|
|
String *str;
|
|
|
|
int wl, wr;
|
|
|
|
|
|
|
|
nl = n->left;
|
|
|
|
if(nl == N)
|
|
|
|
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;
|
|
|
|
}
|
2008-06-15 21:24:30 -06:00
|
|
|
|
2008-06-04 15:37:38 -06:00
|
|
|
if(wl != wr) {
|
2008-06-15 21:24:30 -06:00
|
|
|
if(wl == Wlitfloat && wr == Wlitint)
|
|
|
|
convlit(n->right, n->left->type);
|
|
|
|
else
|
|
|
|
if(wl == Wlitint && wr == Wlitfloat)
|
|
|
|
convlit(n->left, n->right->type);
|
|
|
|
else {
|
|
|
|
yyerror("illegal combination of literals %d %d", nl->etype, nr->etype);
|
|
|
|
return;
|
|
|
|
}
|
2008-06-04 15:37:38 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
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 != T)
|
|
|
|
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;
|
|
|
|
char *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;
|
|
|
|
}
|