# HG changeset patch # User Robert Clipsham # Date 1270516864 -3600 # Node ID 01cadcfa4842421cf6852835b9dc8be1759cd020 # Parent f2413c9183d18f6af93441091ebb8175cf04a92e Implemented CompileExp, ConditionalDeclaration, ModAssignExp, parsingmixin statements, TemplateAliasParameters, TemplateMixins, TypeDArray. diff -r f2413c9183d1 -r 01cadcfa4842 dmd/CompileExp.d --- a/dmd/CompileExp.d Mon Apr 05 19:16:14 2010 +0100 +++ b/dmd/CompileExp.d Tue Apr 06 02:21:04 2010 +0100 @@ -7,23 +7,51 @@ import dmd.Scope; import dmd.HdrGenState; import dmd.TOK; +import dmd.PREC; +import dmd.WANT; +import dmd.StringExp; +import dmd.Type; +import dmd.Parser; -class CompileExp : UnaExp -{ - this(Loc loc, Expression e) - { - assert(false); - super(loc, TOK.init, 0, null); - } - - Expression semantic(Scope sc) - { - assert(false); - } - - void toCBuffer(OutBuffer buf, HdrGenState* hgs) - { - assert(false); - } -} - +import dmd.expression.Util; + +class CompileExp : UnaExp +{ + this(Loc loc, Expression e) + { + super(loc, TOK.TOKmixin, this.sizeof, e); + } + + Expression semantic(Scope sc) + { + version (LOGSEMANTIC) { + printf("CompileExp.semantic('%s')\n", toChars()); + } + UnaExp.semantic(sc); + e1 = resolveProperties(sc, e1); + e1 = e1.optimize(WANT.WANTvalue | WANT.WANTinterpret); + if (e1.op != TOK.TOKstring) + { error("argument to mixin must be a string, not (%s)", e1.toChars()); + type = Type.terror; + return this; + } + StringExp se = cast(StringExp)e1; + se = se.toUTF8(sc); + Parser p = new Parser(sc.module_, cast(ubyte*)se.string_, se.len, 0); + p.loc = loc; + p.nextToken(); + //printf("p.loc.linnum = %d\n", p.loc.linnum); + Expression e = p.parseExpression(); + if (p.token.value != TOK.TOKeof) + error("incomplete mixin expression (%s)", se.toChars()); + return e.semantic(sc); + } + + void toCBuffer(OutBuffer buf, HdrGenState* hgs) + { + buf.writestring("mixin("); + expToCBuffer(buf, hgs, e1, PREC.PREC_assign); + buf.writeByte(')'); + } +} + diff -r f2413c9183d1 -r 01cadcfa4842 dmd/ConditionalDeclaration.d --- a/dmd/ConditionalDeclaration.d Mon Apr 05 19:16:14 2010 +0100 +++ b/dmd/ConditionalDeclaration.d Tue Apr 06 02:21:04 2010 +0100 @@ -17,31 +17,59 @@ this(Condition condition, Array decl, Array elsedecl) { super(decl); - //printf("ConditionalDeclaration::ConditionalDeclaration()\n"); + //printf("ConditionalDeclaration.ConditionalDeclaration()\n"); this.condition = condition; this.elsedecl = elsedecl; } Dsymbol syntaxCopy(Dsymbol s) { - assert(false); + ConditionalDeclaration dd; + + assert(!s); + dd = new ConditionalDeclaration(condition.syntaxCopy(), + Dsymbol.arraySyntaxCopy(decl), + Dsymbol.arraySyntaxCopy(elsedecl)); + return dd; } bool oneMember(Dsymbol* ps) { - assert(false); + //printf("ConditionalDeclaration.oneMember(), inc = %d\n", condition.inc); + if (condition.inc) + { + Array d = condition.include(null, null) ? decl : elsedecl; + return Dsymbol.oneMembers(d, ps); + } + *ps = null; + return true; } void emitComment(Scope sc) { - assert(false); + //printf("ConditionalDeclaration.emitComment(sc = %p)\n", sc); + if (condition.inc) + { + AttribDeclaration.emitComment(sc); + } + else if (sc.docbuf) + { + /* If generating doc comment, be careful because if we're inside + * a template, then include(NULL, NULL) will fail. + */ + Array d = decl ? decl : elsedecl; + for (uint i = 0; i < d.dim; i++) + { Dsymbol s = cast(Dsymbol)d.data[i]; + s.emitComment(sc); + } + } } // Decide if 'then' or 'else' code should be included Array include(Scope sc, ScopeDsymbol sd) { - //printf("ConditionalDeclaration::include()\n"); + //printf("ConditionalDeclaration.include()\n"); assert(condition); return condition.include(sc, sd) ? decl : elsedecl; } @@ -65,7 +93,7 @@ for (uint i = 0; i < d.dim; i++) { Dsymbol s = cast(Dsymbol)d.data[i]; - //printf("ConditionalDeclaration::addComment %s\n", s->toChars()); + //printf("ConditionalDeclaration::addComment %s\n", s.toChars()); s.addComment(comment); } } @@ -76,6 +104,42 @@ void toCBuffer(OutBuffer buf, HdrGenState* hgs) { - assert(false); + condition.toCBuffer(buf, hgs); + if (decl || elsedecl) + { + buf.writenl(); + buf.writeByte('{'); + buf.writenl(); + if (decl) + { + for (uint i = 0; i < decl.dim; i++) + { + Dsymbol s = cast(Dsymbol)decl.data[i]; + + buf.writestring(" "); + s.toCBuffer(buf, hgs); + } } -} \ No newline at end of file + buf.writeByte('}'); + if (elsedecl) + { + buf.writenl(); + buf.writestring("else"); + buf.writenl(); + buf.writeByte('{'); + buf.writenl(); + for (uint i = 0; i < elsedecl.dim; i++) + { + Dsymbol s = cast(Dsymbol)elsedecl.data[i]; + + buf.writestring(" "); + s.toCBuffer(buf, hgs); + } + buf.writeByte('}'); + } + } + else + buf.writeByte(':'); + buf.writenl(); + } +} diff -r f2413c9183d1 -r 01cadcfa4842 dmd/ModAssignExp.d --- a/dmd/ModAssignExp.d Mon Apr 05 19:16:14 2010 +0100 +++ b/dmd/ModAssignExp.d Tue Apr 06 02:21:04 2010 +0100 @@ -17,13 +17,12 @@ { this(Loc loc, Expression e1, Expression e2) { - assert(false); - super(loc, TOK.init, 0, e1, e2); + super(loc, TOK.TOKmodass, this.sizeof, e1, e2); } Expression semantic(Scope sc) { - assert(false); + return commonSemanticAssign(sc); } Expression interpret(InterState* istate) @@ -50,4 +49,4 @@ { assert(false); } -} \ No newline at end of file +} diff -r f2413c9183d1 -r 01cadcfa4842 dmd/Parser.d --- a/dmd/Parser.d Mon Apr 05 19:16:14 2010 +0100 +++ b/dmd/Parser.d Tue Apr 06 02:21:04 2010 +0100 @@ -46,6 +46,7 @@ import dmd.AssertExp; import dmd.CompileExp; import dmd.FileExp; +import dmd.TemplateMixin; import dmd.TemplateParameter; import dmd.TemplateTypeParameter; import dmd.TypeidExp; @@ -1075,10 +1076,96 @@ Lerr: return tpl; } - + +/****************************************** + * Parse template mixin. + * mixin Foo; + * mixin Foo!(args); + * mixin a.b.c!(args).Foo!(args); + * mixin Foo!(args) identifier; + * mixin typeof(expr).identifier!(args); + */ + Dsymbol parseMixin() { - assert(false); + TemplateMixin tm; + Identifier id; + Type tqual; + Objects tiargs; + Array idents; + + //printf("parseMixin()\n"); + nextToken(); + tqual = null; + if (token.value == TOK.TOKdot) + { + id = Id.empty; + } + else + { + if (token.value == TOK.TOKtypeof) + { + tqual = parseTypeof(); + check(TOKdot); + } + if (token.value != TOK.TOKidentifier) + { + error("identifier expected, not %s", token.toChars()); + id = Id.empty; + } + else + id = token.ident; + nextToken(); + } + + idents = new Array(); + while (1) + { + tiargs = null; + if (token.value == TOK.TOKnot) + { + nextToken(); + if (token.value == TOK.TOKlparen) + tiargs = parseTemplateArgumentList(); + else + tiargs = parseTemplateArgument(); + } + + if (token.value != TOK.TOKdot) + break; + + if (tiargs) + { TemplateInstance tempinst = new TemplateInstance(loc, id); + tempinst.tiargs = tiargs; + id = cast(Identifier)tempinst; + tiargs = null; + } + idents.push(cast(void*)id); + + nextToken(); + if (token.value != TOK.TOKidentifier) + { error("identifier expected following '.' instead of '%s'", token.toChars()); + break; + } + id = token.ident; + nextToken(); + } + idents.push(cast(void*)id); + + if (token.value == TOK.TOKidentifier) + { + id = token.ident; + nextToken(); + } + else + id = null; + + tm = new TemplateMixin(loc, id, tqual, idents, tiargs); + if (token.value != TOK.TOKsemicolon) + error("';' expected after mixin"); + nextToken(); + + return tm; } /****************************************** @@ -6024,4 +6111,4 @@ s.addComment(combineComments(blockComment, token.lineComment)); token.lineComment = null; } -} \ No newline at end of file +} diff -r f2413c9183d1 -r 01cadcfa4842 dmd/TemplateAliasParameter.d --- a/dmd/TemplateAliasParameter.d Mon Apr 05 19:16:14 2010 +0100 +++ b/dmd/TemplateAliasParameter.d Tue Apr 06 02:21:04 2010 +0100 @@ -11,22 +11,54 @@ import dmd.OutBuffer; import dmd.HdrGenState; import dmd.Dsymbol; +import dmd.WANT; +import dmd.Expression; +import dmd.TypeIdentifier; +import dmd.Initializer; +import dmd.ExpInitializer; +import dmd.AliasDeclaration; +import dmd.VarDeclaration; +import dmd.TemplateDeclaration; +import dmd.STC; +import dmd.Util; import dmd.templates.Util; +Object aliasParameterSemantic(Loc loc, Scope sc, Object o) +{ + if (o) + { + Expression ea = isExpression(o); + Type ta = isType(o); + if (ta) + { Dsymbol s = ta.toDsymbol(sc); + if (s) + o = s; + else + o = ta.semantic(loc, sc); + } + else if (ea) + { + ea = ea.semantic(sc); + o = ea.optimize(WANT.WANTvalue | WANT.WANTinterpret); + } + } + return o; +} + class TemplateAliasParameter : TemplateParameter { - /* Syntax: - * specType ident : specAlias = defaultAlias - */ + /* Syntax: + * specType ident : specAlias = defaultAlias + */ - Type specType; - Object specAlias; - Object defaultAlias; + Type specType; + Object specAlias; + Object defaultAlias; - static Dsymbol sdummy; + static Dsymbol sdummy; - this(Loc loc, Identifier ident, Type specType, Object specAlias, Object defaultAlias) + this(Loc loc, Identifier ident, Type specType, Object specAlias, Object defaultAlias) { super(loc, ident); @@ -35,12 +67,12 @@ this.defaultAlias = defaultAlias; } - TemplateAliasParameter isTemplateAliasParameter() + TemplateAliasParameter isTemplateAliasParameter() { return this; } - - TemplateParameter syntaxCopy() + + TemplateParameter syntaxCopy() { TemplateAliasParameter tp = new TemplateAliasParameter(loc, ident, specType, specAlias, defaultAlias); if (tp.specType) @@ -49,49 +81,186 @@ tp.defaultAlias = objectSyntaxCopy(defaultAlias); return tp; } - - void declareParameter(Scope sc) + + void declareParameter(Scope sc) { - assert(false); + TypeIdentifier ti = new TypeIdentifier(loc, ident); + sparam = new AliasDeclaration(loc, ident, ti); + if (!sc.insert(sparam)) + error(loc, "parameter '%s' multiply defined", ident.toChars()); } - - void semantic(Scope) + + void semantic(Scope sc) { - assert(false); + if (specType) + { + specType = specType.semantic(loc, sc); + } + specAlias = aliasParameterSemantic(loc, sc, specAlias); + static if (0) { // Don't do semantic() until instantiation + if (defaultAlias) + defaultAlias = defaultAlias.semantic(loc, sc); + } + } + + void print(Object oarg, Object oded) + { + printf(" %s\n", ident.toChars()); + + Dsymbol sa = isDsymbol(oded); + assert(sa); + + printf("\tArgument alias: %s\n", sa.toChars()); } - - void print(Object oarg, Object oded) + + void toCBuffer(OutBuffer buf, HdrGenState* hgs) { - assert(false); + buf.writestring("alias "); + if (specType) + { HdrGenState hg; + specType.toCBuffer(buf, ident, &hg); + } + else + buf.writestring(ident.toChars()); + if (specAlias) + { + buf.writestring(" : "); + ObjectToCBuffer(buf, hgs, specAlias); + } + if (defaultAlias) + { + buf.writestring(" = "); + ObjectToCBuffer(buf, hgs, defaultAlias); + } } - - void toCBuffer(OutBuffer buf, HdrGenState* hgs) + + Object specialization() + { + return specAlias; + } + + Object defaultArg(Loc loc, Scope sc) + { + Object o = aliasParameterSemantic(loc, sc, defaultAlias); + return o; + } + + bool overloadMatch(TemplateParameter tp) { - assert(false); + TemplateAliasParameter tap = tp.isTemplateAliasParameter(); + + if (tap) + { + if (specAlias != tap.specAlias) + goto Lnomatch; + + return true; // match + } + +Lnomatch: + return false; } - - Object specialization() + + MATCH matchArg(Scope sc, Objects tiargs, int i, TemplateParameters parameters, Objects dedtypes, Declaration* psparam, int flags) { - assert(false); - } - - Object defaultArg(Loc loc, Scope sc) - { - assert(false); - } - - bool overloadMatch(TemplateParameter) - { - assert(false); + Object sa; + Object oarg; + Expression ea; + Dsymbol s; + + //printf("TemplateAliasParameter.matchArg()\n"); + + if (i < tiargs.dim) + oarg = cast(Object)tiargs.data[i]; + else + { // Get default argument instead + oarg = defaultArg(loc, sc); + if (!oarg) + { assert(i < dedtypes.dim); + // It might have already been deduced + oarg = cast(Object)dedtypes.data[i]; + if (!oarg) + goto Lnomatch; + } + } + + sa = getDsymbol(oarg); + if (sa) + { + /* specType means the alias must be a declaration with a type + * that matches specType. + */ + if (specType) + { Declaration d = (cast(Dsymbol)sa).isDeclaration(); + if (!d) + goto Lnomatch; + if (!d.type.equals(specType)) + goto Lnomatch; + } + } + else + { + sa = oarg; + ea = isExpression(oarg); + if (ea) + { if (specType) + { + if (!ea.type.equals(specType)) + goto Lnomatch; + } + } + else + goto Lnomatch; + } + if (specAlias) + { + if (sa == sdummy) + goto Lnomatch; + if (sa != specAlias) + goto Lnomatch; + } + else if (dedtypes.data[i]) + { // Must match already deduced symbol + Object s_ = cast(Object)dedtypes.data[i]; + + if (!sa || s_ != sa) + goto Lnomatch; + } + dedtypes.data[i] = cast(void*)sa; + + s = isDsymbol(sa); + if (s) + *psparam = new AliasDeclaration(loc, ident, s); + else + { + assert(ea); + + // Declare manifest constant + Initializer init = new ExpInitializer(loc, ea); + VarDeclaration v = new VarDeclaration(loc, null, ident, init); + v.storage_class = STC.STCmanifest; + v.semantic(sc); + *psparam = v; + } + return MATCHexact; + +Lnomatch: + *psparam = null; + //printf("\tm = %d\n", MATCHnomatch); + return MATCHnomatch; } - - MATCH matchArg(Scope sc, Objects tiargs, int i, TemplateParameters parameters, Objects dedtypes, Declaration* psparam, int flags) + + void* dummyArg() { - assert(false); + Object s; + + s = specAlias; + if (!s) + { + if (!sdummy) + sdummy = new Dsymbol(); + s = sdummy; + } + return cast(void*)s; } - - void* dummyArg() - { - assert(false); - } -} \ No newline at end of file +} diff -r f2413c9183d1 -r 01cadcfa4842 dmd/TemplateMixin.d --- a/dmd/TemplateMixin.d Mon Apr 05 19:16:14 2010 +0100 +++ b/dmd/TemplateMixin.d Tue Apr 06 02:21:04 2010 +0100 @@ -10,72 +10,492 @@ import dmd.Scope; import dmd.OutBuffer; import dmd.HdrGenState; +import dmd.DYNCAST; +import dmd.AggregateDeclaration; +import dmd.TemplateDeclaration; +import dmd.Expression; +import dmd.DsymbolTable; +import dmd.PROT; +import dmd.ScopeDsymbol; +import dmd.Global; +import dmd.Util; + +extern(C++) void util_progress(); class TemplateMixin : TemplateInstance { - Array idents; - Type tqual; + Array idents; + Type tqual; - this(Loc loc, Identifier ident, Type tqual, Array idents, Objects tiargs) - { - assert(false); - super(loc, ident); - } - - Dsymbol syntaxCopy(Dsymbol s) + this(Loc loc, Identifier ident, Type tqual, Array idents, Objects tiargs) { - assert(false); - } - - void semantic(Scope sc) - { - assert(false); - } - - void semantic2(Scope sc) - { - assert(false); - } - - void semantic3(Scope sc) - { - assert(false); + super(loc, cast(Identifier)idents.data[idents.dim - 1]); + //printf("TemplateMixin(ident = '%s')\n", ident ? ident.toChars() : ""); + this.ident = ident; + this.tqual = tqual; + this.idents = idents; + this.tiargs = tiargs ? tiargs : new Objects(); } - - void inlineScan() - { - assert(false); - } - - string kind() - { - assert(false); - } - - bool oneMember(Dsymbol* ps) + + Dsymbol syntaxCopy(Dsymbol s) { - assert(false); - } - - bool hasPointers() - { - assert(false); - } - - string toChars() - { - assert(false); - } - - void toCBuffer(OutBuffer buf, HdrGenState* hgs) - { - assert(false); + TemplateMixin tm; + + Array ids = new Array(); + ids.setDim(idents.dim); + for (int i = 0; i < idents.dim; i++) + { // Matches TypeQualified.syntaxCopyHelper() + Identifier id = cast(Identifier)idents.data[i]; + if (id.dyncast() == DYNCAST.DYNCAST_DSYMBOL) + { + TemplateInstance ti = cast(TemplateInstance)id; + + ti = cast(TemplateInstance)ti.syntaxCopy(null); + id = cast(Identifier)ti; + } + ids.data[i] = cast(void*)id; + } + + tm = new TemplateMixin(loc, ident, + cast(Type)(tqual ? tqual.syntaxCopy() : null), + ids, tiargs); + TemplateInstance.syntaxCopy(tm); + return tm; } - void toObjFile(int multiobj) // compile to .obj file + void semantic(Scope sc) { - assert(false); + version (LOG) { + printf("+TemplateMixin.semantic('%s', this=%p)\n", toChars(), this); + fflush(stdout); + } + if (semanticRun && + // This for when a class/struct contains mixin members, and + // is done over because of forward references + (!parent || !toParent().isAggregateDeclaration())) + { + version (LOG) { + printf("\tsemantic done\n"); + } + return; + } + if (!semanticRun) + semanticRun = 1; + version (LOG) { + printf("\tdo semantic\n"); + } + util_progress(); + + Scope scx = null; + if (scope_) + { sc = scope_; + scx = scope_; // save so we don't make redundant copies + scope_ = null; + } + + // Follow qualifications to find the TemplateDeclaration + if (!tempdecl) + { Dsymbol s; + int i; + Identifier id; + + if (tqual) + { s = tqual.toDsymbol(sc); + i = 0; + } + else + { + i = 1; + id = cast(Identifier)idents.data[0]; + switch (id.dyncast()) + { + case DYNCAST.DYNCAST_IDENTIFIER: + s = sc.search(loc, id, null); + break; + + case DYNCAST.DYNCAST_DSYMBOL: + { + TemplateInstance ti = cast(TemplateInstance)id; + ti.semantic(sc); + s = ti; + break; + } + default: + assert(0); + } + } + + for (; i < idents.dim; i++) + { + if (!s) + break; + id = cast(Identifier)idents.data[i]; + s = s.searchX(loc, sc, id); + } + if (!s) + { + error("is not defined"); + inst = this; + return; + } + tempdecl = s.toAlias().isTemplateDeclaration(); + if (!tempdecl) + { + error("%s isn't a template", s.toChars()); + inst = this; + return; + } + } + + // Look for forward reference + assert(tempdecl); + for (TemplateDeclaration td = tempdecl; td; td = td.overnext) + { + if (!td.semanticRun) + { + /* Cannot handle forward references if mixin is a struct member, + * because addField must happen during struct's semantic, not + * during the mixin semantic. + * runDeferred will re-run mixin's semantic outside of the struct's + * semantic. + */ + semanticRun = 0; + AggregateDeclaration ad = toParent().isAggregateDeclaration(); + if (ad) + ad.sizeok = 2; + else + { + // Forward reference + //printf("forward reference - deferring\n"); + scope_ = scx ? scx : new Scope(sc); + scope_.setNoFree(); + scope_.module_.addDeferredSemantic(this); + } + return; + } + } + + // Run semantic on each argument, place results in tiargs[] + semanticTiargs(sc); + + tempdecl = findBestMatch(sc); + if (!tempdecl) + { inst = this; + return; // error recovery + } + + if (!ident) + ident = genIdent(); + + inst = this; + parent = sc.parent; + + /* Detect recursive mixin instantiations. + */ + for (Dsymbol s = parent; s; s = s.parent) + { + //printf("\ts = '%s'\n", s.toChars()); + TemplateMixin tm = s.isTemplateMixin(); + if (!tm || tempdecl != tm.tempdecl) + continue; + + /* Different argument list lengths happen with variadic args + */ + if (tiargs.dim != tm.tiargs.dim) + continue; + + for (int i = 0; i < tiargs.dim; i++) + { Object o = cast(Object)tiargs.data[i]; + Type ta = isType(o); + Expression ea = isExpression(o); + Dsymbol sa = isDsymbol(o); + Object tmo = cast(Object)tm.tiargs.data[i]; + if (ta) + { + Type tmta = isType(tmo); + if (!tmta) + goto Lcontinue; + if (!ta.equals(tmta)) + goto Lcontinue; + } + else if (ea) + { Expression tme = isExpression(tmo); + if (!tme || !ea.equals(tme)) + goto Lcontinue; + } + else if (sa) + { + Dsymbol tmsa = isDsymbol(tmo); + if (sa != tmsa) + goto Lcontinue; + } + else + assert(0); + } + error("recursive mixin instantiation"); + return; + +Lcontinue: + continue; + } + + + // Copy the syntax trees from the TemplateDeclaration + members = Dsymbol.arraySyntaxCopy(tempdecl.members); + if (!members) + return; + + symtab = new DsymbolTable(); + + for (Scope sce = sc; 1; sce = sce.enclosing) + { + ScopeDsymbol sds = cast(ScopeDsymbol)sce.scopesym; + if (sds) + { + sds.importScope(this, PROT.PROTpublic); + break; + } + } + + version (LOG) { + printf("\tcreate scope for template parameters '%s'\n", toChars()); + } + Scope scy = sc; + scy = sc.push(this); + scy.parent = this; + + argsym = new ScopeDsymbol(); + argsym.parent = scy.parent; + Scope argscope = scy.push(argsym); + + uint errorsave = global.errors; + + // Declare each template parameter as an alias for the argument type + declareParameters(argscope); + + // Add members to enclosing scope, as well as this scope + for (uint i = 0; i < members.dim; i++) + { Dsymbol s; + + s = cast(Dsymbol)members.data[i]; + s.addMember(argscope, this, i); + //sc.insert(s); + //printf("sc.parent = %p, sc.scopesym = %p\n", sc.parent, sc.scopesym); + //printf("s.parent = %s\n", s.parent.toChars()); + } + + // Do semantic() analysis on template instance members + version (LOG) { + printf("\tdo semantic() on template instance members '%s'\n", toChars()); + } + Scope sc2; + sc2 = argscope.push(this); + sc2.offset = sc.offset; + + + static int nest; + //printf("%d\n", nest); + if (++nest > 500) + { + global.gag = 0; // ensure error message gets printed + error("recursive expansion"); + fatal(); + } + + for (int i = 0; i < members.dim; i++) + { + Dsymbol s = cast(Dsymbol)members.data[i]; + s.semantic(sc2); + } + + nest--; + + sc.offset = sc2.offset; + + /* The problem is when to parse the initializer for a variable. + * Perhaps VarDeclaration.semantic() should do it like it does + * for initializers inside a function. + */ + // if (sc.parent.isFuncDeclaration()) + + semantic2(sc2); + + if (sc.func) + { + semantic3(sc2); + } + + // Give additional context info if error occurred during instantiation + if (global.errors != errorsave) + { + error("error instantiating"); + } + + sc2.pop(); + + argscope.pop(); + + // if (!isAnonymous()) + { + scy.pop(); + } + version (LOG) { + printf("-TemplateMixin.semantic('%s', this=%p)\n", toChars(), this); + } } - TemplateMixin isTemplateMixin() { return this; } -} \ No newline at end of file + void semantic2(Scope sc) + { + int i; + + if (semanticRun >= 2) + return; + semanticRun = 2; + version (LOG) { + printf("+TemplateMixin.semantic2('%s')\n", toChars()); + } + if (members) + { + assert(sc); + sc = sc.push(argsym); + sc = sc.push(this); + for (i = 0; i < members.dim; i++) + { + Dsymbol s = cast(Dsymbol)members.data[i]; + version (LOG) { + printf("\tmember '%s', kind = '%s'\n", s.toChars(), s.kind()); + } + s.semantic2(sc); + } + sc = sc.pop(); + sc.pop(); + } + version (LOG) { + printf("-TemplateMixin.semantic2('%s')\n", toChars()); + } + } + + void semantic3(Scope sc) + { + int i; + + if (semanticRun >= 3) + return; + semanticRun = 3; + version (LOG) { + printf("TemplateMixin.semantic3('%s')\n", toChars()); + } + if (members) + { + sc = sc.push(argsym); + sc = sc.push(this); + for (i = 0; i < members.dim; i++) + { + Dsymbol s = cast(Dsymbol)members.data[i]; + s.semantic3(sc); + } + sc = sc.pop(); + sc.pop(); + } + } + + void inlineScan() + { + TemplateInstance.inlineScan(); + } + + string kind() + { + return "mixin"; + } + + bool oneMember(Dsymbol* ps) + { + return Dsymbol.oneMember(ps); + } + + bool hasPointers() + { + //printf("TemplateMixin.hasPointers() %s\n", toChars()); + for (size_t i = 0; i < members.dim; i++) + { + Dsymbol s = cast(Dsymbol)members.data[i]; + //printf(" s = %s %s\n", s.kind(), s.toChars()); + if (s.hasPointers()) + { + return 1; + } + } + return 0; + } + + string toChars() + { + OutBuffer buf; + HdrGenState hgs; + string s; + + TemplateInstance.toCBuffer(buf, &hgs); + s = buf.toChars(); + buf.data = null; + return s; + } + + void toCBuffer(OutBuffer buf, HdrGenState* hgs) + { + buf.writestring("mixin "); + + for (int i = 0; i < idents.dim; i++) + { Identifier id = cast(Identifier)idents.data[i]; + + if (i) + buf.writeByte('.'); + buf.writestring(id.toChars()); + } + buf.writestring("!("); + if (tiargs) + { + for (int i = 0; i < tiargs.dim; i++) + { if (i) + buf.writebyte(','); + Object oarg = cast(Object)tiargs.data[i]; + Type t = isType(oarg); + Expression e = isExpression(oarg); + Dsymbol s = isDsymbol(oarg); + if (t) + t.toCBuffer(buf, null, hgs); + else if (e) + e.toCBuffer(buf, hgs); + else if (s) + { + string p = s.ident ? s.ident.toChars() : s.toChars(); + buf.writestring(p); + } + else if (!oarg) + { + buf.writestring("null"); + } + else + { + assert(0); + } + } + } + buf.writebyte(')'); + if (ident) + { + buf.writebyte(' '); + buf.writestring(ident.toChars()); + } + buf.writebyte(';'); + buf.writenl(); + } + + void toObjFile(int multiobj) // compile to .obj file + { + //printf("TemplateMixin.toObjFile('%s')\n", toChars()); + TemplateInstance.toObjFile(multiobj); + } + + TemplateMixin isTemplateMixin() { return this; } +} diff -r f2413c9183d1 -r 01cadcfa4842 dmd/TypeDArray.d --- a/dmd/TypeDArray.d Mon Apr 05 19:16:14 2010 +0100 +++ b/dmd/TypeDArray.d Tue Apr 06 02:21:04 2010 +0100 @@ -161,7 +161,8 @@ int isString() { - assert(false); + TY nty = next.toBasetype().ty; + return nty == TY.Tchar || nty == TY.Twchar || nty == TY.Tdchar; } bool isZeroInit(Loc loc)