Mercurial > projects > ddmd
diff dmd/DotIdExp.d @ 0:10317f0c89a5
Initial commit
author | korDen |
---|---|
date | Sat, 24 Oct 2009 08:42:06 +0400 |
parents | |
children | 2e2a5c3f943a |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/DotIdExp.d Sat Oct 24 08:42:06 2009 +0400 @@ -0,0 +1,373 @@ +module dmd.DotIdExp; + +import dmd.Expression; +import dmd.Identifier; +import dmd.IntegerExp; +import dmd.Type; +import dmd.TY; +import dmd.ScopeExp; +import dmd.StringExp; +import dmd.PtrExp; +import dmd.TypePointer; +import dmd.Dsymbol; +import dmd.EnumMember; +import dmd.VarDeclaration; +import dmd.ThisExp; +import dmd.DotVarExp; +import dmd.VarExp; +import dmd.CommaExp; +import dmd.FuncDeclaration; +import dmd.OverloadSet; +import dmd.OverExp; +import dmd.TypeExp; +import dmd.TupleDeclaration; +import dmd.ScopeDsymbol; +import dmd.Import; +import dmd.Id; +import dmd.TupleExp; +import dmd.ArrayTypes; +import dmd.UnaExp; +import dmd.OutBuffer; +import dmd.Loc; +import dmd.Scope; +import dmd.TOK; +import dmd.HdrGenState; +import dmd.ClassDeclaration; +import dmd.StructDeclaration; +import dmd.AggregateDeclaration; +import dmd.DotExp; +import dmd.Global; +import dmd.IdentifierExp; +import dmd.CallExp; +import dmd.PREC; + +import dmd.expression.Util; + +class DotIdExp : UnaExp +{ + Identifier ident; + + this(Loc loc, Expression e, Identifier ident) + { + super(loc, TOK.TOKdot, DotIdExp.sizeof, e); + this.ident = ident; + } + + Expression semantic(Scope sc) + { + Expression e; + Expression eleft; + Expression eright; + +version (LOGSEMANTIC) { + printf("DotIdExp.semantic(this = %p, '%s')\n", this, toChars()); + //printf("e1.op = %d, '%s'\n", e1.op, Token.toChars(e1.op)); +} + + //{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; } + +static if (false) { + /* Don't do semantic analysis if we'll be converting + * it to a string. + */ + if (ident == Id.stringof) + { + char *s = e1.toChars(); + e = new StringExp(loc, s, strlen(s), 'c'); + e = e.semantic(sc); + return e; + } +} + + /* Special case: rewrite this.id and super.id + * to be classtype.id and baseclasstype.id + * if we have no this pointer. + */ + if ((e1.op == TOK.TOKthis || e1.op == TOK.TOKsuper) && !hasThis(sc)) + { + ClassDeclaration cd; + StructDeclaration sd; + AggregateDeclaration ad; + + ad = sc.getStructClassScope(); + if (ad) + { + cd = ad.isClassDeclaration(); + if (cd) + { + if (e1.op == TOK.TOKthis) + { + e = typeDotIdExp(loc, cd.type, ident); + return e.semantic(sc); + } + else if (cd.baseClass && e1.op == TOK.TOKsuper) + { + e = typeDotIdExp(loc, cd.baseClass.type, ident); + return e.semantic(sc); + } + } + else + { + sd = ad.isStructDeclaration(); + if (sd) + { + if (e1.op == TOK.TOKthis) + { + e = typeDotIdExp(loc, sd.type, ident); + return e.semantic(sc); + } + } + } + } + } + + UnaExp.semantic(sc); + + if (e1.op == TOK.TOKdotexp) + { + DotExp de = cast(DotExp)e1; + eleft = de.e1; + eright = de.e2; + } + else + { + e1 = resolveProperties(sc, e1); + eleft = null; + eright = e1; + } + +version (DMDV2) { + if (e1.op == TOK.TOKtuple && ident == Id.offsetof) + { + /* 'distribute' the .offsetof to each of the tuple elements. + */ + TupleExp te = cast(TupleExp)e1; + Expressions exps = new Expressions(); + exps.setDim(te.exps.dim); + for (int i = 0; i < exps.dim; i++) + { + Expression ee = cast(Expression)te.exps.data[i]; + ee = ee.semantic(sc); + ee = new DotIdExp(e.loc, ee, Id.offsetof); + exps.data[i] = cast(void*)ee; + } + e = new TupleExp(loc, exps); + e = e.semantic(sc); + return e; + } +} + + if (e1.op == TOK.TOKtuple && ident == Id.length) + { + TupleExp te = cast(TupleExp)e1; + e = new IntegerExp(loc, te.exps.dim, Type.tsize_t); + return e; + } + + if (e1.op == TOK.TOKdottd) + { + error("template %s does not have property %s", e1.toChars(), ident.toChars()); + return e1; + } + + if (!e1.type) + { + error("expression %s does not have property %s", e1.toChars(), ident.toChars()); + return e1; + } + + Type t1b = e1.type.toBasetype(); + + if (eright.op == TOK.TOKimport) // also used for template alias's + { + ScopeExp ie = cast(ScopeExp)eright; + + /* Disable access to another module's private imports. + * The check for 'is sds our current module' is because + * the current module should have access to its own imports. + */ + Dsymbol s = ie.sds.search(loc, ident, + (ie.sds.isModule() && ie.sds != sc.module_) ? 1 : 0); + if (s) + { + s = s.toAlias(); + checkDeprecated(sc, s); + + EnumMember em = s.isEnumMember(); + if (em) + { + e = em.value; + e = e.semantic(sc); + return e; + } + + VarDeclaration v = s.isVarDeclaration(); + if (v) + { + //printf("DotIdExp. Identifier '%s' is a variable, type '%s'\n", toChars(), v.type.toChars()); + if (v.inuse) + { + error("circular reference to '%s'", v.toChars()); + type = Type.tint32; + return this; + } + type = v.type; + if (v.needThis()) + { + if (!eleft) + eleft = new ThisExp(loc); + e = new DotVarExp(loc, eleft, v); + e = e.semantic(sc); + } + else + { + e = new VarExp(loc, v); + if (eleft) + { + e = new CommaExp(loc, eleft, e); + e.type = v.type; + } + } + return e.deref(); + } + + FuncDeclaration f = s.isFuncDeclaration(); + if (f) + { + //printf("it's a function\n"); + if (f.needThis()) + { + if (!eleft) + eleft = new ThisExp(loc); + e = new DotVarExp(loc, eleft, f); + e = e.semantic(sc); + } + else + { + e = new VarExp(loc, f, 1); + if (eleft) + { e = new CommaExp(loc, eleft, e); + e.type = f.type; + } + } + return e; + } +version (DMDV2) { + OverloadSet o = s.isOverloadSet(); + if (o) + { + //printf("'%s' is an overload set\n", o.toChars()); + return new OverExp(o); + } +} + + Type t = s.getType(); + if (t) + { + return new TypeExp(loc, t); + } + + TupleDeclaration tup = s.isTupleDeclaration(); + if (tup) + { + if (eleft) + error("cannot have e.tuple"); + e = new TupleExp(loc, tup); + e = e.semantic(sc); + return e; + } + + ScopeDsymbol sds = s.isScopeDsymbol(); + if (sds) + { + //printf("it's a ScopeDsymbol\n"); + e = new ScopeExp(loc, sds); + e = e.semantic(sc); + if (eleft) + e = new DotExp(loc, eleft, e); + return e; + } + + Import imp = s.isImport(); + if (imp) + { + ScopeExp iee = new ScopeExp(loc, imp.pkg); + return iee.semantic(sc); + } + + // BUG: handle other cases like in IdentifierExp.semantic() +version (DEBUG) { + printf("s = '%s', kind = '%s'\n", s.toChars(), s.kind()); +} + assert(0); + } + else if (ident is Id.stringof_) + { + string ss = ie.toChars(); + e = new StringExp(loc, ss, 'c'); + e = e.semantic(sc); + return e; + } + error("undefined identifier %s", toChars()); + type = Type.tvoid; + return this; + } + else if (t1b.ty == TY.Tpointer && + ident !is Id.init_ && ident !is Id.__sizeof && + ident !is Id.alignof_ && ident !is Id.offsetof && + ident !is Id.mangleof_ && ident !is Id.stringof_) + { /* Rewrite: + * p.ident + * as: + * (*p).ident + */ + e = new PtrExp(loc, e1); + e.type = (cast(TypePointer)t1b).next; + return e.type.dotExp(sc, e, ident); + } +///version (DMDV2) { + else if (t1b.ty == TY.Tarray || + t1b.ty == TY.Tsarray || + t1b.ty == TY.Taarray) + { + /* If ident is not a valid property, rewrite: + * e1.ident + * as: + * .ident(e1) + */ + uint errors = global.errors; + global.gag++; + e = e1.type.dotExp(sc, e1, ident); + global.gag--; + if (errors != global.errors) // if failed to find the property + { + global.errors = errors; + e = new DotIdExp(loc, new IdentifierExp(loc, Id.empty), ident); + e = new CallExp(loc, e, e1); + } + e = e.semantic(sc); + return e; + } +///} + else + { + e = e1.type.dotExp(sc, e1, ident); + e = e.semantic(sc); + return e; + } + } + + void toCBuffer(OutBuffer buf, HdrGenState* hgs) + { + //printf("DotIdExp.toCBuffer()\n"); + expToCBuffer(buf, hgs, e1, PREC.PREC_primary); + buf.writeByte('.'); + buf.writestring(ident.toChars()); + } + + void dump(int i) + { + assert(false); + } +} +