| // 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; |
| } |