Mercurial > projects > ddmd
view dmd/IntegerExp.d @ 135:af1bebfd96a4 dmd2037
dmd 2.038
author | Eldar Insafutdinov <e.insafutdinov@gmail.com> |
---|---|
date | Mon, 13 Sep 2010 22:19:42 +0100 |
parents | e28b18c23469 |
children | 438eaa11eed4 |
line wrap: on
line source
module dmd.IntegerExp; import dmd.common; import dmd.Expression; import dmd.backend.elem; import dmd.TY; import dmd.TypeEnum; import dmd.TypeTypedef; import dmd.Global; import dmd.InterState; import dmd.MATCH; import dmd.Type; import dmd.OutBuffer; import dmd.Loc; import dmd.Scope; import dmd.IntRange; import dmd.IRState; import dmd.HdrGenState; import dmd.TOK; import dmd.Complex; import dmd.backend.dt_t; import dmd.backend.Util; import core.stdc.ctype : isprint; import std.stdio; class IntegerExp : Expression { ulong value; this(Loc loc, ulong value, Type type) { super(loc, TOK.TOKint64, IntegerExp.sizeof); //printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type.toChars() : ""); if (type && !type.isscalar()) { //printf("%s, loc = %d\n", toChars(), loc.linnum); error("integral constant must be scalar type, not %s", type.toChars()); type = Type.terror; } this.type = type; this.value = value; } this(ulong value) { super(Loc(0), TOK.TOKint64, IntegerExp.sizeof); this.type = Type.tint32; this.value = value; } override bool equals(Object o) { IntegerExp ne; if (this == o || ((cast(Expression)o).op == TOKint64 && ((ne = cast(IntegerExp)o), type.toHeadMutable().equals(ne.type.toHeadMutable())) && value == ne.value) ) return 1; return 0; } override Expression semantic(Scope sc) { if (!type) { // Determine what the type of this number is ulong number = value; if (number & 0x8000000000000000) type = Type.tuns64; else if (number & 0xFFFFFFFF80000000) type = Type.tint64; else type = Type.tint32; } else { if (!type.deco) type = type.semantic(loc, sc); } return this; } override Expression interpret(InterState istate) { version (LOG) { printf("IntegerExp.interpret() %s\n", toChars()); } return this; } override string toChars() { static if (true) { return Expression.toChars(); } else { static char buffer[value.sizeof * 3 + 1]; int len = sprintf(buffer.ptr, "%jd", value); return buffer[0..len].idup; } } override void dump(int indent) { assert(false); } override IntRange getIntRange() { IntRange ir; ir.imin = value & type.sizemask(); ir.imax = ir.imin; return ir; } override ulong toInteger() { Type t; t = type; while (t) { switch (t.ty) { case TY.Tbit: case TY.Tbool: value = (value != 0); break; case TY.Tint8: value = cast(byte) value; break; case TY.Tchar: case TY.Tuns8: value = cast(ubyte) value; break; case TY.Tint16: value = cast(short) value; break; case TY.Twchar: case TY.Tuns16: value = cast(ushort)value; break; case TY.Tint32: value = cast(int) value; break; case TY.Tdchar: case TY.Tuns32: value = cast(uint) value; break; case TY.Tint64: value = cast(long) value; break; case TY.Tuns64: value = cast(ulong) value; break; case TY.Tpointer: if (PTRSIZE == 4) value = cast(uint) value; else if (PTRSIZE == 8) value = cast(ulong) value; else assert(0); break; case TY.Tenum: { TypeEnum te = cast(TypeEnum)t; t = te.sym.memtype; continue; } case TY.Ttypedef: { TypeTypedef tt = cast(TypeTypedef)t; t = tt.sym.basetype; continue; } default: /* This can happen if errors, such as * the type is painted on like in fromConstInitializer(). */ if (!global.errors) { writef("%s %p\n", type.toChars(), type); assert(0); } break; } break; } return value; } override real toReal() { Type t; toInteger(); t = type.toBasetype(); if (t.ty == Tuns64) return cast(real)cast(ulong)value; else return cast(real)cast(long)value; } override real toImaginary() { assert(false); } override Complex!(real) toComplex() { assert(false); } override int isConst() { return 1; } override bool isBool(bool result) { int r = toInteger() != 0; return cast(bool)(result ? r : !r); } override MATCH implicitConvTo(Type t) { static if (false) { printf("IntegerExp.implicitConvTo(this=%s, type=%s, t=%s)\n", toChars(), type.toChars(), t.toChars()); } MATCH m = type.implicitConvTo(t); if (m >= MATCH.MATCHconst) return m; TY ty = type.toBasetype().ty; TY toty = t.toBasetype().ty; if (m == MATCH.MATCHnomatch && t.ty == TY.Tenum) goto Lno; switch (ty) { case TY.Tbit: case TY.Tbool: value &= 1; ty = TY.Tint32; break; case TY.Tint8: value = cast(byte)value; ty = TY.Tint32; break; case TY.Tchar: case TY.Tuns8: value &= 0xFF; ty = TY.Tint32; break; case TY.Tint16: value = cast(short)value; ty = TY.Tint32; break; case TY.Tuns16: case TY.Twchar: value &= 0xFFFF; ty = TY.Tint32; break; case TY.Tint32: value = cast(int)value; break; case TY.Tuns32: case TY.Tdchar: value &= 0xFFFFFFFF; ty = TY.Tuns32; break; default: break; } // Only allow conversion if no change in value switch (toty) { case TY.Tbit: case TY.Tbool: if ((value & 1) != value) goto Lno; goto Lyes; case TY.Tint8: if (cast(byte)value != value) goto Lno; goto Lyes; case TY.Tchar: case TY.Tuns8: //printf("value = %llu %llu\n", (dinteger_t)(unsigned char)value, value); if (cast(ubyte)value != value) goto Lno; goto Lyes; case TY.Tint16: if (cast(short)value != value) goto Lno; goto Lyes; case TY.Tuns16: if (cast(ushort)value != value) goto Lno; goto Lyes; case TY.Tint32: if (ty == TY.Tuns32) { ; } else if (cast(int)value != value) { goto Lno; } goto Lyes; case TY.Tuns32: if (ty == TY.Tint32) { } else if (cast(uint)value != value) { goto Lno; } goto Lyes; case TY.Tdchar: if (value > 0x10FFFF) { goto Lno; } goto Lyes; case TY.Twchar: if (cast(ushort)value != value) { goto Lno; } goto Lyes; case TY.Tfloat32: { /*volatile*/ float f; /// if (type.isunsigned()) { f = cast(float)value; if (f != value) { goto Lno; } } else { f = cast(float)cast(long)value; if (f != cast(long)value) { goto Lno; } } goto Lyes; } case TY.Tfloat64: { /*volatile*/ double f; /// if (type.isunsigned()) { f = cast(double)value; if (f != value) goto Lno; } else { f = cast(double)cast(long)value; if (f != cast(long)value) goto Lno; } goto Lyes; } case TY.Tfloat80: { /*volatile*/ real f; /// if (type.isunsigned()) { f = cast(real)value; if (f != value) goto Lno; } else { f = cast(real)cast(long)value; if (f != cast(long)value) goto Lno; } goto Lyes; } case TY.Tpointer: //printf("type = %s\n", type.toBasetype().toChars()); //printf("t = %s\n", t.toBasetype().toChars()); if (ty == TY.Tpointer && type.toBasetype().nextOf().ty == t.toBasetype().nextOf().ty) { /* Allow things like: * const char* P = cast(char *)3; * char* q = P; */ goto Lyes; } break; default: break; /// } return Expression.implicitConvTo(t); Lyes: //printf("MATCHconvert\n"); return MATCH.MATCHconvert; Lno: //printf("MATCHnomatch\n"); return MATCH.MATCHnomatch; } override void toCBuffer(OutBuffer buf, HdrGenState* hgs) { long v = toInteger(); if (type) { Type t = type; L1: switch (t.ty) { case TY.Tenum: { TypeEnum te = cast(TypeEnum)t; buf.printf("cast(%s)", te.sym.toChars()); t = te.sym.memtype; goto L1; } case TY.Ttypedef: { TypeTypedef tt = cast(TypeTypedef)t; buf.printf("cast(%s)", tt.sym.toChars()); t = tt.sym.basetype; goto L1; } case TY.Twchar: // BUG: need to cast(wchar) case TY.Tdchar: // BUG: need to cast(dchar) if (cast(ulong)v > 0xFF) { buf.printf("'\\U%08x'", v); break; } case TY.Tchar: if (v == '\'') buf.writestring("'\\''"); else if (isprint(cast(int)v) && v != '\\') buf.printf("'%c'", cast(int)v); else buf.printf("'\\x%02x'", cast(int)v); break; case TY.Tint8: buf.writestring("cast(byte)"); goto L2; case TY.Tint16: buf.writestring("cast(short)"); goto L2; case TY.Tint32: L2: buf.printf("%d", cast(int)v); break; case TY.Tuns8: buf.writestring("cast(ubyte)"); goto L3; case TY.Tuns16: buf.writestring("cast(ushort)"); goto L3; case TY.Tuns32: L3: buf.printf("%du", cast(uint)v); break; case TY.Tint64: //buf.printf("%jdL", v); buf.printf("%sL", v); break; case TY.Tuns64: L4: //buf.printf("%juLU", v); buf.printf("%sLU", v); break; case TY.Tbit: case TY.Tbool: buf.writestring(v ? "true" : "false"); break; case TY.Tpointer: buf.writestring("cast("); buf.writestring(t.toChars()); buf.writeByte(')'); if (PTRSIZE == 4) goto L3; else if (PTRSIZE == 8) goto L4; else assert(0); default: /* This can happen if errors, such as * the type is painted on like in fromConstInitializer(). */ if (!global.errors) { debug { writef("%s\n", t.toChars()); } assert(0); } break; } } else if (v & 0x8000000000000000L) buf.printf("0x%jx", v); else buf.printf("%jd", v); } override void toMangleBuffer(OutBuffer buf) { if (cast(long)value < 0) buf.printf("N%d", -value); else buf.printf("%d", value); } override Expression toLvalue(Scope sc, Expression e) { if (!e) e = this; else if (!loc.filename) loc = e.loc; e.error("constant %s is not an lvalue", e.toChars()); return this; } override elem* toElem(IRState* irs) { elem* e = el_long(type.totym(), value); el_setLoc(e,loc); return e; } override dt_t** toDt(dt_t** pdt) { //printf("IntegerExp.toDt() %d\n", op); uint sz = cast(uint)type.size(); if (value == 0) pdt = dtnzeros(pdt, sz); else pdt = dtnbytes(pdt, sz, cast(char*)&value); return pdt; } }