Mercurial > projects > ddmd
view dmd/IsExp.d @ 178:e3afd1303184
Many small bugs fixed
Made all classes derive from TObject to detect memory leaks (functionality is disabled for now)
Began work on overriding backend memory allocations (to avoid memory leaks)
author | korDen |
---|---|
date | Sun, 17 Oct 2010 07:42:00 +0400 |
parents | af1bebfd96a4 |
children | b0d41ff5e0df |
line wrap: on
line source
module dmd.IsExp; import dmd.common; 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.Parameter; import dmd.Token; 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) { register(); super(loc, TOK.TOKis, IsExp.sizeof); this.targ = targ; this.id = id; this.tok = tok; this.tspec = tspec; this.tok2 = tok2; this.parameters = parameters; } override Expression syntaxCopy() { // This section is identical to that in TemplateDeclaration.syntaxCopy() TemplateParameters p = null; if (parameters) { p = new TemplateParameters(); p.setDim(parameters.dim); for (int i = 0; i < p.dim; i++) { auto tp = parameters[i]; p[i] = tp.syntaxCopy(); } } return new IsExp(loc, targ.syntaxCopy(), id, tok, tspec ? tspec.syntaxCopy() : null, tok2, p); } override Expression semantic(Scope sc) { Type tded; /* is(targ id tok tspec) * is(targ id : tok2) * 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.isImmutable()) goto Lno; tded = targ; break; case TOKshared: if (!targ.isShared()) goto Lno; tded = targ; break; case TOKwild: if (!targ.isWild()) 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; auto args = new Parameters; args.reserve(cd.baseclasses.dim); foreach (b; cd.baseclasses) { args.push(new Parameter(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); auto params = (cast(TypeFunction)tded).parameters; size_t dim = Parameter.dim(params); auto args = new Parameters; args.reserve(dim); for (size_t i = 0; i < dim; i++) { auto arg = Parameter.getNth(params, i); assert(arg && arg.type); args.push(new Parameter(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. */ assert(parameters && parameters.dim); scope dedtypes = new Objects(); dedtypes.setDim(parameters.dim); dedtypes.zero(); MATCH m = targ.deduceType(null, tspec, parameters, dedtypes); if (m == MATCHnomatch || (m != MATCHexact && tok == TOKequal)) { goto Lno; } else { tded = cast(Type)dedtypes[0]; if (!tded) tded = targ; scope Objects tiargs = new Objects(); tiargs.setDim(1); tiargs[0] = targ; /* Declare trailing parameters */ for (int i = 1; i < parameters.dim; i++) { auto tp = parameters[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, true); } 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, true); } //printf("Lyes\n"); return new IntegerExp(loc, 1, Type.tbool); Lno: //printf("Lno\n"); return new IntegerExp(loc, 0, Type.tbool); } override void toCBuffer(OutBuffer buf, HdrGenState* hgs) { buf.writestring("is("); targ.toCBuffer(buf, id, hgs); if (tok2 != TOKreserved) { buf.printf(" %s %s", Token.toChars(tok), Token.toChars(tok2)); } else if (tspec) { if (tok == TOKcolon) buf.writestring(" : "); else buf.writestring(" == "); tspec.toCBuffer(buf, null, hgs); } version (DMDV2) { if (parameters) { // First parameter is already output, so start with second for (int i = 1; i < parameters.dim; i++) { buf.writeByte(','); auto tp = parameters[i]; tp.toCBuffer(buf, hgs); } } } buf.writeByte(')'); } }