Mercurial > projects > ddmd
diff dmd/IntegerExp.d @ 0:10317f0c89a5
Initial commit
author | korDen |
---|---|
date | Sat, 24 Oct 2009 08:42:06 +0400 |
parents | |
children | 1628b221808d |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/IntegerExp.d Sat Oct 24 08:42:06 2009 +0400 @@ -0,0 +1,549 @@ +module dmd.IntegerExp; + +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; + +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; + } + + int 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; + } + + 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; + } + + Expression interpret(InterState* istate) + { + assert(false); + } + + 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; +} + } + + void dump(int indent) + { + assert(false); + } + + IntRange getIntRange() + { + assert(false); + } + + 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) + { + ///type.print(); + assert(0); + } + break; + } + break; + } + return value; + } + + 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; + } + + real toImaginary() + { + assert(false); + } + + Complex!(real) toComplex() + { + assert(false); + } + + int isConst() + { + return 1; + } + + bool isBool(bool result) + { + return result ? value != 0 : value == 0; + } + + 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; + } + + 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); + break; + + case TY.Tuns64: + L4: + buf.printf("%juLU", 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); + } + + void toMangleBuffer(OutBuffer buf) + { + assert(false); + } + + 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; + } + + elem* toElem(IRState* irs) + { + elem* e = el_long(type.totym(), value); + el_setLoc(e,loc); + return e; + } + + 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; + } +} +