diff dmd/IsExp.d @ 0:10317f0c89a5

Initial commit
author korDen
date Sat, 24 Oct 2009 08:42:06 +0400
parents
children 427f8aa74d28
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/IsExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,323 @@
+module dmd.IsExp;
+
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.ArrayTypes;
+import dmd.Type;
+import dmd.TOK;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.HdrGenState;
+import dmd.TY;
+import dmd.TypeEnum;
+import dmd.STC;
+import dmd.TypeClass;
+import dmd.TemplateParameter;
+import dmd.BaseClass;
+import dmd.ClassDeclaration;
+import dmd.TypeStruct;
+import dmd.TypeTypedef;
+import dmd.IntegerExp;
+import dmd.AliasDeclaration;
+import dmd.Dsymbol;
+import dmd.TypeTuple;
+import dmd.TypeDelegate;
+import dmd.Declaration;
+import dmd.TypeFunction;
+import dmd.MATCH;
+import dmd.TypePointer;
+import dmd.Argument;
+
+class IsExp : Expression
+{
+	/* is(targ id tok tspec)
+     * is(targ id == tok2)
+     */
+    Type targ;
+    Identifier id;	// can be null
+    TOK tok;	// ':' or '=='
+    Type tspec;	// can be null
+    TOK tok2;	// 'struct', 'union', 'typedef', etc.
+    TemplateParameters parameters;
+
+	this(Loc loc, Type targ, Identifier id, TOK tok, Type tspec, TOK tok2, TemplateParameters parameters)
+	{
+		super(loc, TOK.TOKis, IsExp.sizeof);
+		
+		this.targ = targ;
+		this.id = id;
+		this.tok = tok;
+		this.tspec = tspec;
+		this.tok2 = tok2;
+		this.parameters = parameters;
+	}
+
+	Expression syntaxCopy()
+	{
+		assert(false);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Type tded;
+
+		/* is(targ id tok tspec)
+		 * is(targ id == tok2)
+		 */
+
+		//printf("IsExp.semantic(%s)\n", toChars());
+		if (id && !(sc.flags & SCOPE.SCOPEstaticif))
+			error("can only declare type aliases within static if conditionals");
+
+		Type t = targ.trySemantic(loc, sc);
+		if (!t)
+			goto Lno;			// errors, so condition is false
+		targ = t;
+		if (tok2 != TOK.TOKreserved)
+		{
+			switch (tok2)
+			{
+				case TOKtypedef:
+					if (targ.ty != Ttypedef)
+						goto Lno;
+					tded = (cast(TypeTypedef)targ).sym.basetype;
+					break;
+
+				case TOKstruct:
+					if (targ.ty != Tstruct)
+						goto Lno;
+					if ((cast(TypeStruct)targ).sym.isUnionDeclaration())
+						goto Lno;
+					tded = targ;
+					break;
+
+				case TOKunion:
+					if (targ.ty != Tstruct)
+						goto Lno;
+					if (!(cast(TypeStruct)targ).sym.isUnionDeclaration())
+						goto Lno;
+					tded = targ;
+					break;
+
+				case TOKclass:
+					if (targ.ty != Tclass)
+						goto Lno;
+					if ((cast(TypeClass)targ).sym.isInterfaceDeclaration())
+						goto Lno;
+					tded = targ;
+					break;
+
+				case TOKinterface:
+					if (targ.ty != Tclass)
+						goto Lno;
+					if (!(cast(TypeClass)targ).sym.isInterfaceDeclaration())
+						goto Lno;
+					tded = targ;
+					break;
+		version (DMDV2) {
+				case TOKconst:
+					if (!targ.isConst())
+						goto Lno;
+					tded = targ;
+					break;
+
+				case TOKinvariant:
+				case TOKimmutable:
+					if (!targ.isInvariant())
+						goto Lno;
+					tded = targ;
+					break;
+
+				case TOKshared:
+					if (!targ.isShared())
+						goto Lno;
+					tded = targ;
+					break;
+		}
+
+				case TOKsuper:
+					// If class or interface, get the base class and interfaces
+					if (targ.ty != Tclass)
+						goto Lno;
+					else
+					{   ClassDeclaration cd = (cast(TypeClass)targ).sym;
+						Arguments args = new Arguments;
+						args.reserve(cd.baseclasses.dim);
+						for (size_t i = 0; i < cd.baseclasses.dim; i++)
+						{	
+							BaseClass b = cast(BaseClass)cd.baseclasses.data[i];
+							args.push(cast(void*)new Argument(STCin, b.type, null, null));
+						}
+						tded = new TypeTuple(args);
+					}
+					break;
+
+				case TOKenum:
+					if (targ.ty != Tenum)
+						goto Lno;
+					tded = (cast(TypeEnum)targ).sym.memtype;
+					break;
+
+				case TOKdelegate:
+					if (targ.ty != Tdelegate)
+						goto Lno;
+					tded = (cast(TypeDelegate)targ).next;	// the underlying function type
+					break;
+
+				case TOKfunction:
+				{
+					if (targ.ty != Tfunction)
+						goto Lno;
+					tded = targ;
+
+					/* Generate tuple from function parameter types.
+					 */
+					assert(tded.ty == Tfunction);
+					Arguments params = (cast(TypeFunction)tded).parameters;
+					size_t dim = Argument.dim(params);
+					Arguments args = new Arguments;
+					args.reserve(dim);
+					for (size_t i = 0; i < dim; i++)
+					{   
+						Argument arg = Argument.getNth(params, i);
+						assert(arg && arg.type);
+						args.push(cast(void*)new Argument(arg.storageClass, arg.type, null, null));
+					}
+					tded = new TypeTuple(args);
+					break;
+				}
+				
+				case TOKreturn:
+					/* Get the 'return type' for the function,
+					 * delegate, or pointer to function.
+					 */
+					if (targ.ty == Tfunction)
+						tded = (cast(TypeFunction)targ).next;
+					else if (targ.ty == Tdelegate)
+					{   tded = (cast(TypeDelegate)targ).next;
+						tded = (cast(TypeFunction)tded).next;
+					}
+					else if (targ.ty == Tpointer &&
+						 (cast(TypePointer)targ).next.ty == Tfunction)
+					{   tded = (cast(TypePointer)targ).next;
+						tded = (cast(TypeFunction)tded).next;
+					}
+					else
+						goto Lno;
+					break;
+
+				default:
+					assert(0);
+			}
+			goto Lyes;
+		}
+		else if (id && tspec)
+		{
+			/* Evaluate to true if targ matches tspec.
+			 * If true, declare id as an alias for the specialized type.
+			 */
+
+			MATCH m;
+			assert(parameters && parameters.dim);
+
+			scope Objects dedtypes = new Objects();
+			dedtypes.setDim(parameters.dim);
+			dedtypes.zero();
+
+			m = targ.deduceType(null, tspec, parameters, dedtypes);
+			if (m == MATCHnomatch ||
+				(m != MATCHexact && tok == TOKequal))
+			{
+				goto Lno;
+			}
+			else
+			{
+				tded = cast(Type)dedtypes.data[0];
+				if (!tded)
+				tded = targ;
+
+				scope Objects tiargs = new Objects();
+				tiargs.setDim(1);
+				tiargs.data[0] = cast(void*)targ;
+
+				/* Declare trailing parameters
+				 */
+				for (int i = 1; i < parameters.dim; i++)
+				{	
+					TemplateParameter tp = cast(TemplateParameter)parameters.data[i];
+					Declaration s = null;
+
+					m = tp.matchArg(sc, tiargs, i, parameters, dedtypes, &s);
+					if (m == MATCHnomatch)
+						goto Lno;
+					s.semantic(sc);
+					if (!sc.insert(s))
+						error("declaration %s is already defined", s.toChars());
+		static if (false) {
+					Object o = cast(Object)dedtypes.data[i];
+					Dsymbol s = TemplateDeclaration.declareParameter(loc, sc, tp, o);
+		}
+					if (sc.sd)
+						s.addMember(sc, sc.sd, 1);
+				}
+
+				goto Lyes;
+			}
+		}
+		else if (id)
+		{
+			/* Declare id as an alias for type targ. Evaluate to true
+			 */
+			tded = targ;
+			goto Lyes;
+		}
+		else if (tspec)
+		{
+			/* Evaluate to true if targ matches tspec
+			 * is(targ == tspec)
+			 * is(targ : tspec)
+			 */
+			tspec = tspec.semantic(loc, sc);
+			//printf("targ  = %s\n", targ.toChars());
+			//printf("tspec = %s\n", tspec.toChars());
+			if (tok == TOKcolon)
+			{   
+				if (targ.implicitConvTo(tspec))
+					goto Lyes;
+				else
+					goto Lno;
+			}
+			else /* == */
+			{   
+				if (targ.equals(tspec))
+					goto Lyes;
+				else
+					goto Lno;
+			}
+		}
+
+	Lyes:
+		if (id)
+		{
+			Dsymbol s = new AliasDeclaration(loc, id, tded);
+			s.semantic(sc);
+			if (!sc.insert(s))
+				error("declaration %s is already defined", s.toChars());
+			if (sc.sd)
+				s.addMember(sc, sc.sd, 1);
+		}
+	//printf("Lyes\n");
+		return new IntegerExp(loc, 1, Type.tbool);
+
+	Lno:
+	//printf("Lno\n");
+		return new IntegerExp(loc, 0, Type.tbool);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+}
+