Mercurial > projects > ddmd
diff dmd/StructDeclaration.d @ 130:60bb0fe4563e
dmdfe 2.037 first main iteration
author | Eldar Insafutdinov <e.insafutdinov@gmail.com> |
---|---|
date | Thu, 09 Sep 2010 22:51:44 +0100 |
parents | 010eb8f0e18d |
children | 206db751bd4c |
line wrap: on
line diff
--- a/dmd/StructDeclaration.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/StructDeclaration.d Thu Sep 09 22:51:44 2010 +0100 @@ -23,7 +23,7 @@ import dmd.ThisExp; import dmd.ThisDeclaration; import dmd.TypeFunction; -import dmd.Argument; +import dmd.Parameter; import dmd.Id; import dmd.TY; import dmd.LINK; @@ -70,6 +70,7 @@ version (DMDV2) { int hasIdentityAssign; // !=0 if has identity opAssign FuncDeclaration cpctor; // generated copy-constructor, if any + FuncDeclaration eq; // bool opEquals(ref const T), if any FuncDeclarations postblits; // Array of postblit functions FuncDeclaration postblit; // aggregate postblit @@ -234,6 +235,10 @@ } } +version(DMDV1) { + /* This doesn't work for DMDV2 because (ref S) and (S) parameter + * lists will overload the same. + */ /* The TypeInfo_Struct is expecting an opEquals and opCmp with * a parameter that is a pointer to the struct. But if there * isn't one, but is an opEquals or opCmp with a value, write @@ -243,8 +248,8 @@ TypeFunction tfeqptr; { - Arguments arguments = new Arguments; - Argument arg = new Argument(STC.STCin, handle, Id.p, null); + auto arguments = new Parameters; + auto arg = new Parameter(STC.STCin, handle, Id.p, null); arguments.push(arg); tfeqptr = new TypeFunction(arguments, Type.tint32, 0, LINK.LINKd); @@ -253,8 +258,8 @@ TypeFunction tfeq; { - Arguments arguments = new Arguments; - Argument arg = new Argument(STC.STCin, type, null, null); + auto arguments = new Parameters; + auto arg = new Parameter(STC.STCin, type, null, null); arguments.push(arg); tfeq = new TypeFunction(arguments, Type.tint32, 0, LINK.LINKd); @@ -291,7 +296,39 @@ id = Id.cmp; } +} version (DMDV2) { + /* Try to find the opEquals function. Build it if necessary. + */ + TypeFunction *tfeqptr; + { // bool opEquals(const T*) const; + auto parameters = new Parameters; +version(STRUCTTHISREF) { + // bool opEquals(ref const T) const; + auto param = new Parameter(STC.STCref, type.constOf(), null, null); +} else { + // bool opEquals(const T*) const; + auto param = new Parameter(STC.STCin, type.pointerTo(), null, null); +} + + parameters.push(param); + tfeqptr = new TypeFunction(parameters, Type.tbool, 0, LINK.LINKd); + tfeqptr.mod = MOD.MODconst; + tfeqptr = cast(TypeFunction)(tfeqptr.semantic(0, sc2)); + + Dsymbol s = search_function(this, Id.eq); + FuncDeclaration fdx = s ? s.isFuncDeclaration() : null; + if (fdx) + { + eq = fdx.overloadExactMatch(tfeqptr); + if (!eq) + fdx.error("type signature should be %s not %s", tfeqptr.toChars(), fdx.type.toChars()); + } + + if (!eq) + eq = buildOpEquals(sc2); + } + dtor = buildDtor(sc2); postblit = buildPostBlit(sc2); cpctor = buildCpCtor(sc2); @@ -386,7 +423,17 @@ { assert(false); } - + +version(DMDV1) +{ + Expression cloneMembers() + { + assert(false); + } +} + +version(DMDV2) +{ /******************************************* * We need an opAssign for the struct if * it has a destructor or a postblit. @@ -436,6 +483,46 @@ return true; } + /******************************************* + * We need an opEquals for the struct if + * any fields has an opEquals. + * Generate one if a user-specified one does not exist. + */ + bool needOpEquals() + { + enum X = 0; +static if (X) printf("StructDeclaration::needOpEquals() %s\n", toChars()); + + /* If any of the fields has an opEquals, then we + * need it too. + */ + foreach (s; fields) + { + VarDeclaration v = s.isVarDeclaration(); + assert(v && v.storage_class & STC.STCfield); + if (v.storage_class & STC.STCref) + continue; + Type tv = v.type.toBasetype(); + while (tv.ty == Tsarray) + { auto ta = cast(TypeSArray)tv; + tv = tv.nextOf().toBasetype(); + } + if (tv.ty == Tstruct) + { auto ts = cast(TypeStruct)tv; + StructDeclaration sd = ts.sym; + if (sd.eq) + goto Lneed; + } + } + Ldontneed: +static if (X) printf("\tdontneed\n"); + return false; + + Lneed: +static if (X) printf("\tneed\n"); + return true; + } + /****************************************** * Build opAssign for struct. * S* opAssign(S s) { ... } @@ -449,8 +536,8 @@ FuncDeclaration fop = null; - Argument param = new Argument(STC.STCnodtor, type, Id.p, null); - Arguments fparams = new Arguments; + auto param = new Parameter(STC.STCnodtor, type, Id.p, null); + auto fparams = new Parameters; fparams.push(param); Type ftype = new TypeFunction(fparams, handle, false, LINK.LINKd); version (STRUCTTHISREF) { @@ -543,6 +630,72 @@ return fop; } + /****************************************** + * Build opEquals for struct. + * const bool opEquals(const ref S s) { ... } + */ + FuncDeclaration buildOpEquals(Scope sc) + { + if (!needOpEquals()) + return null; + //printf("StructDeclaration::buildOpEquals() %s\n", toChars()); + Loc loc = this.loc; + + auto parameters = new Parameters; +version (STRUCTTHISREF) { + // bool opEquals(ref const T) const; + auto param = new Parameter(STC.STCref, type.constOf(), Id.p, NULL); +} else { + // bool opEquals(const T*) const; + auto param = new Parameter(STC.STCin, type.pointerTo(), Id.p, NULL); +} + + parameters.push(param); + auto ftype = new TypeFunction(parameters, Type.tbool, 0, LINKd); + ftype.mod = MOD.MODconst; + ftype = cast(TypeFunction)ftype.semantic(loc, sc); + + auto fop = new FuncDeclaration(loc, 0, Id.eq, STD.STCundefined, ftype); + + Expression *e = NULL; + /* Do memberwise compare + */ + //printf("\tmemberwise compare\n"); + foreach (s; fields) + { + VarDeclaration v = s.isVarDeclaration(); + assert(v && v.storage_class & STD.STCfield); + if (v.storage_class & STC.STCref) + assert(0); // what should we do with this? + // this.v == s.v; + auto ec = new EqualExp(TOKequal, loc, + new DotVarExp(loc, new ThisExp(loc), v, 0), + new DotVarExp(loc, new IdentifierExp(loc, Id.p), v, 0)); + if (e) + e = new AndAndExp(loc, e, ec); + else + e = ec; + } + if (!e) + e = new IntegerExp(loc, 1, Type.tbool); + fop.fbody = new ReturnStatement(loc, e); + + members.push(fop); + fop.addMember(sc, this, 1); + + sc = sc.push(); + sc.stc = 0; + sc.linkage = LINK.LINKd; + + fop.semantic(sc); + + sc.pop(); + + //printf("-StructDeclaration::buildOpEquals() %s\n", toChars()); + + return fop; + } + /***************************************** * Create inclusive postblit for struct by aggregating * all the postblits in postblits[] with the postblits for @@ -664,8 +817,8 @@ { //printf("generating cpctor\n"); - Argument param = new Argument(STC.STCref, type, Id.p, null); - Arguments fparams = new Arguments; + auto param = new Parameter(STC.STCref, type, Id.p, null); + auto fparams = new Parameters; fparams.push(param); Type ftype = new TypeFunction(fparams, Type.tvoid, false, LINK.LINKd); @@ -701,7 +854,7 @@ return fcp; } - +} override void toDocBuffer(OutBuffer buf) { assert(false);