diff dmd/ArrayScopeSymbol.d @ 0:10317f0c89a5

Initial commit
author korDen
date Sat, 24 Oct 2009 08:42:06 +0400
parents
children 4caad35a6ceb
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ArrayScopeSymbol.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,166 @@
+module dmd.ArrayScopeSymbol;
+
+import dmd.ScopeDsymbol;
+import dmd.Expression;
+import dmd.TypeTuple;
+import dmd.TupleDeclaration;
+import dmd.Scope;
+import dmd.Dsymbol;
+import dmd.Loc;
+import dmd.TOK;
+import dmd.Identifier;
+import dmd.Id;
+import dmd.TY;
+import dmd.TupleExp;
+import dmd.StringExp;
+import dmd.WANT;
+import dmd.TypeExp;
+import dmd.Type;
+import dmd.SliceExp;
+import dmd.IndexExp;
+import dmd.IntegerExp;
+import dmd.STC;
+import dmd.ExpInitializer;
+import dmd.VarDeclaration;
+import dmd.ArrayLiteralExp;
+import dmd.expression.Util;
+
+class ArrayScopeSymbol : ScopeDsymbol
+{
+    Expression exp;	// IndexExp or SliceExp
+    TypeTuple type;	// for tuple[length]
+    TupleDeclaration td;	// for tuples of objects
+    Scope sc;
+
+    this(Scope sc, Expression e)
+	{
+		super();
+		assert(e.op == TOKindex || e.op == TOKslice);
+		this.exp = e;
+		this.sc = sc;
+	}
+	
+    this(Scope sc, TypeTuple t)
+	{
+		assert(false);
+	}
+	
+    this(Scope sc, TupleDeclaration td)
+	{
+		assert(false);
+	}
+	
+    Dsymbol search(Loc loc, Identifier ident, int flags)
+	{
+		//printf("ArrayScopeSymbol.search('%s', flags = %d)\n", ident.toChars(), flags);
+		if (ident == Id.length || ident == Id.dollar)
+		{
+			VarDeclaration* pvar;
+			Expression ce;
+
+		L1:
+			if (td)
+			{   /* $ gives the number of elements in the tuple
+				 */
+				VarDeclaration v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null);
+				Expression e = new IntegerExp(Loc(0), td.objects.dim, Type.tsize_t);
+				v.init = new ExpInitializer(Loc(0), e);
+				v.storage_class |= STCstatic | STCconst;
+				v.semantic(sc);
+				return v;
+			}
+
+			if (type)
+			{   /* $ gives the number of type entries in the type tuple
+				 */
+				VarDeclaration v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null);
+				Expression e = new IntegerExp(Loc(0), type.arguments.dim, Type.tsize_t);
+				v.init = new ExpInitializer(Loc(0), e);
+				v.storage_class |= STCstatic | STCconst;
+				v.semantic(sc);
+				return v;
+			}
+
+			if (exp.op == TOKindex)
+			{   /* array[index] where index is some function of $
+				 */
+				IndexExp ie = cast(IndexExp)exp;
+
+				pvar = &ie.lengthVar;
+				ce = ie.e1;
+			}
+			else if (exp.op == TOKslice)
+			{   /* array[lwr .. upr] where lwr or upr is some function of $
+				 */
+				SliceExp se = cast(SliceExp)exp;
+
+				pvar = &se.lengthVar;
+				ce = se.e1;
+			}
+			else
+				/* Didn't find $, look in enclosing scope(s).
+				 */
+				return null;
+
+			/* If we are indexing into an array that is really a type
+			 * tuple, rewrite this as an index into a type tuple and
+			 * try again.
+			 */
+			if (ce.op == TOKtype)
+			{
+				Type t = (cast(TypeExp)ce).type;
+				if (t.ty == Ttuple)
+				{	
+					type = cast(TypeTuple)t;
+					goto L1;
+				}
+			}
+
+			/* *pvar is lazily initialized, so if we refer to $
+			 * multiple times, it gets set only once.
+			 */
+			if (!*pvar)		// if not already initialized
+			{   /* Create variable v and set it to the value of $,
+				 * which will be a constant.
+				 */
+				VarDeclaration v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null);
+
+				if (ce.op == TOKvar)
+				{	// if ce is const, get its initializer
+					ce = fromConstInitializer(WANTvalue | WANTinterpret, ce);
+				}
+
+				if (ce.op == TOKstring)
+				{	/* It is for a string literal, so the
+					 * length will be a const.
+					 */
+					Expression e = new IntegerExp(Loc(0), (cast(StringExp)ce).len, Type.tsize_t);
+					v.init = new ExpInitializer(Loc(0), e);
+					v.storage_class |= STCstatic | STCconst;
+				}
+				else if (ce.op == TOKarrayliteral)
+				{	/* It is for an array literal, so the
+					 * length will be a const.
+					 */
+					Expression e = new IntegerExp(Loc(0), (cast(ArrayLiteralExp)ce).elements.dim, Type.tsize_t);
+					v.init = new ExpInitializer(Loc(0), e);
+					v.storage_class |= STCstatic | STCconst;
+				}
+				else if (ce.op == TOKtuple)
+				{	/* It is for an expression tuple, so the
+					 * length will be a const.
+					 */
+					Expression e = new IntegerExp(Loc(0), (cast(TupleExp)ce).exps.dim, Type.tsize_t);
+					v.init = new ExpInitializer(Loc(0), e);
+					v.storage_class |= STCstatic | STCconst;
+				}
+				*pvar = v;
+			}
+			(*pvar).semantic(sc);
+			return (*pvar);
+		}
+		return null;
+	}
+
+    ArrayScopeSymbol isArrayScopeSymbol() { return this; }
+}
\ No newline at end of file