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