Mercurial > projects > ddmd
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