Mercurial > projects > ddmd
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); + } +} +