Mercurial > projects > ddmd
changeset 17:ddae60498573
Implemented mixin statements, DefaultInitExps, FileInitExps, LineInitExps and __traits.
author | Robert Clipsham <robert@octarineparrot.com> |
---|---|
date | Mon, 05 Apr 2010 03:24:08 +0100 |
parents | 5c9b78899f5d |
children | f2413c9183d1 |
files | dmd/ClassDeclaration.d dmd/CompileStatement.d dmd/DefaultInitExp.d dmd/Dsymbol.d dmd/FileInitExp.d dmd/FuncDeclaration.d dmd/LineInitExp.d dmd/TraitsExp.d dmd/expression/Util.d |
diffstat | 9 files changed, 593 insertions(+), 114 deletions(-) [+] |
line wrap: on
line diff
--- a/dmd/ClassDeclaration.d Sun Apr 04 22:41:11 2010 +0100 +++ b/dmd/ClassDeclaration.d Mon Apr 05 03:24:08 2010 +0100 @@ -71,7 +71,7 @@ struct Param { - int isf(FuncDeclaration fd2) + int isf(void*, FuncDeclaration fd2) { //printf("param = %p, fd = %p %s\n", param, fd, fd.toChars()); return fd is fd2; @@ -908,7 +908,7 @@ { Dsymbol s2 = cast(Dsymbol)os.a.data[i]; FuncDeclaration f2 = s2.isFuncDeclaration(); - if (f2 && overloadApply(f2, &p.isf)) + if (f2 && overloadApply(f2, &p.isf, &p)) return false; } return true; @@ -917,7 +917,7 @@ { FuncDeclaration fdstart = s.isFuncDeclaration(); //printf("%s fdstart = %p\n", s.kind(), fdstart); - return !overloadApply(fdstart, &p.isf); + return !overloadApply(fdstart, &p.isf, &p); } } } @@ -1882,4 +1882,4 @@ ///ClassDeclaration isClassDeclaration() { return cast(ClassDeclaration)this; } /// huh? ClassDeclaration isClassDeclaration() { return this; } -} \ No newline at end of file +}
--- a/dmd/CompileStatement.d Sun Apr 04 22:41:11 2010 +0100 +++ b/dmd/CompileStatement.d Mon Apr 05 03:24:08 2010 +0100 @@ -7,34 +7,71 @@ import dmd.OutBuffer; import dmd.HdrGenState; import dmd.ArrayTypes; +import dmd.TOK; +import dmd.WANT; +import dmd.ParseStatementFlags; +import dmd.Parser; +import dmd.CompoundStatement; +import dmd.StringExp; class CompileStatement : Statement { - Expression exp; + Expression exp; - this(Loc loc, Expression exp) + this(Loc loc, Expression exp) { - assert(false); super(loc); + this.exp = exp; } - Statement syntaxCopy() + Statement syntaxCopy() { - assert(false); + Expression e = exp.syntaxCopy(); + CompileStatement es = new CompileStatement(loc, e); + return es; + } + + void toCBuffer(OutBuffer buf, HdrGenState* hgs) + { + buf.writestring("mixin("); + exp.toCBuffer(buf, hgs); + buf.writestring(");"); + if (!hgs.FLinit.init) + buf.writenl(); } - void toCBuffer(OutBuffer buf, HdrGenState* hgs) + Statements flatten(Scope sc) { - assert(false); + //printf("CompileStatement::flatten() %s\n", exp->toChars()); + exp = exp.semantic(sc); + exp = resolveProperties(sc, exp); + exp = exp.optimize(WANT.WANTvalue | WANT.WANTinterpret); + if (exp.op != TOK.TOKstring) + { error("argument to mixin must be a string, not (%s)", exp.toChars()); + return null; + } + StringExp se = cast(StringExp)exp; + se = se.toUTF8(sc); + Parser p = new Parser(sc.module_, cast(ubyte *)se.string_, se.len, 0); + p.loc = loc; + p.nextToken(); + + Statements a = new Statements(); + while (p.token.value != TOK.TOKeof) + { + Statement s = p.parseStatement(ParseStatementFlags.PSsemi | ParseStatementFlags.PScurlyscope); + a.push(cast(void*)s); + } + return a; } - Statements flatten(Scope sc) + Statement semantic(Scope sc) { - assert(false); + //printf("CompileStatement::semantic() %s\n", exp->toChars()); + Statements a = flatten(sc); + if (!a) + return null; + Statement s = new CompoundStatement(loc, a); + return s.semantic(sc); } - - Statement semantic(Scope sc) - { - assert(false); - } -} \ No newline at end of file +}
--- a/dmd/DefaultInitExp.d Sun Apr 04 22:41:11 2010 +0100 +++ b/dmd/DefaultInitExp.d Mon Apr 05 03:24:08 2010 +0100 @@ -6,25 +6,23 @@ import dmd.Scope; import dmd.HdrGenState; import dmd.TOK; +import dmd.Token; -class DefaultInitExp : Expression -{ - TOK subop; - - this(Loc loc, TOK subop, int size) - { - assert(false); - super(loc, subop, size); - } - - Expression resolve(Loc loc, Scope sc) - { - assert(false); - } - - void toCBuffer(OutBuffer buf, HdrGenState* hgs) - { - assert(false); - } -} - +class DefaultInitExp : Expression +{ + TOK subop; + + this(Loc loc, TOK subop, int size) + { + super(loc, subop, size); + this.subop = subop; + } + + abstract Expression resolve(Loc loc, Scope sc); + + void toCBuffer(OutBuffer buf, HdrGenState* hgs) + { + buf.writestring(Token.toChars(subop)); + } +} +
--- a/dmd/Dsymbol.d Sun Apr 04 22:41:11 2010 +0100 +++ b/dmd/Dsymbol.d Mon Apr 05 03:24:08 2010 +0100 @@ -90,6 +90,22 @@ return cast(Type)o; } +/*********************** + * Try to get arg as a type. + */ + +Type getType(Object o) +{ + Type t = isType(o); + if (!t) + { Expression e = isExpression(o); + if (e) + t = e.type; + } + return t; +} + + Dsymbol getDsymbol(Object oarg) { Dsymbol sa;
--- a/dmd/FileInitExp.d Sun Apr 04 22:41:11 2010 +0100 +++ b/dmd/FileInitExp.d Mon Apr 05 03:24:08 2010 +0100 @@ -4,24 +4,32 @@ import dmd.Loc; import dmd.Scope; import dmd.DefaultInitExp; +import dmd.StringExp; import dmd.TOK; +import dmd.Util; +import dmd.Type; + +class FileInitExp : DefaultInitExp +{ + this(Loc loc) + { + super(loc, TOK.TOKfile, this.sizeof); + } -class FileInitExp : DefaultInitExp -{ - this(Loc loc) - { - assert(false); - super(loc, TOK.init, 0); - } - - Expression semantic(Scope sc) - { - assert(false); - } - - Expression resolve(Loc loc, Scope sc) - { - assert(false); - } -} - + Expression semantic(Scope sc) + { + type = Type.tchar.invariantOf().arrayOf(); + return this; + } + + Expression resolve(Loc loc, Scope sc) + { + //printf("FileInitExp::resolve() %s\n", toChars()); + string s = loc.filename ? loc.filename : sc.module_.ident.toChars(); + Expression e = new StringExp(loc, s); + e = e.semantic(sc); + e = e.castTo(sc, type); + return e; + } +} +
--- a/dmd/FuncDeclaration.d Sun Apr 04 22:41:11 2010 +0100 +++ b/dmd/FuncDeclaration.d Mon Apr 05 03:24:08 2010 +0100 @@ -1659,7 +1659,7 @@ Param1 p; p.t = t; p.f = null; - overloadApply(this, &p.fp1); + overloadApply(this, &p.fp1, &p); return p.f; }
--- a/dmd/LineInitExp.d Sun Apr 04 22:41:11 2010 +0100 +++ b/dmd/LineInitExp.d Mon Apr 05 03:24:08 2010 +0100 @@ -4,23 +4,27 @@ import dmd.Loc; import dmd.Scope; import dmd.DefaultInitExp; +import dmd.IntegerExp; import dmd.TOK; +import dmd.Type; + +class LineInitExp : DefaultInitExp +{ + this(Loc loc) + { + super(loc, TOK.TOKline, this.sizeof); + } -class LineInitExp : DefaultInitExp -{ - this(Loc loc) - { - assert(false); - super(loc, TOK.init, 0); - } - - Expression semantic(Scope sc) - { - assert(false); - } - - Expression resolve(Loc loc, Scope sc) - { - assert(false); - } -} \ No newline at end of file + Expression semantic(Scope sc) + { + type = Type.tint32; + return this; + } + + Expression resolve(Loc loc, Scope sc) + { + Expression e = new IntegerExp(loc, loc.linnum, Type.tint32); + e = e.castTo(sc, type); + return e; + } +}
--- a/dmd/TraitsExp.d Sun Apr 04 22:41:11 2010 +0100 +++ b/dmd/TraitsExp.d Mon Apr 05 03:24:08 2010 +0100 @@ -8,32 +8,448 @@ import dmd.Scope; import dmd.HdrGenState; import dmd.TOK; +import dmd.TY; +import dmd.STC; +import dmd.WANT; +import dmd.Id; +import dmd.Global; +import dmd.Lexer; +import dmd.ArrayLiteralExp; +import dmd.VarExp; +import dmd.StringExp; +import dmd.DotIdExp; +import dmd.DotVarExp; +import dmd.IntegerExp; +import dmd.TupleExp; +import dmd.Type; +import dmd.Dsymbol; +import dmd.DsymbolExp; +import dmd.ScopeDsymbol; +import dmd.FuncDeclaration; +import dmd.ClassDeclaration; +import dmd.TemplateDeclaration; +import dmd.TemplateInstance; +import dmd.TypeClass; +import dmd.Util; +import dmd.expression.Util; -class TraitsExp : Expression -{ - Identifier ident; - - Objects args; - - this(Loc loc, Identifier ident, Objects args) - { - assert(false); - super(loc, TOK.init, 0); - } - - Expression syntaxCopy() - { - assert(false); - } - - Expression semantic(Scope sc) - { - assert(false); - } - - void toCBuffer(OutBuffer buf, HdrGenState* hgs) - { - assert(false); - } -} - +import core.stdc.string : strcmp; + +/************************************************ + * Delegate to be passed to overloadApply() that looks + * for virtual functions. + */ + +struct Pvirtuals +{ + Expression e1; + Expressions exps; + int fpvirtuals(void* param, FuncDeclaration f) + { Pvirtuals p = *cast(Pvirtuals*)param; + + if (f.isVirtual()) + { Expression e; + + if (p.e1.op == TOK.TOKdotvar) + { DotVarExp dve = cast(DotVarExp)p.e1; + e = new DotVarExp(Loc(0), dve.e1, f); + } + else + e = new DsymbolExp(Loc(0), f); + p.exps.push(cast(void*)e); + } + return 0; + } +} + + + +class TraitsExp : Expression +{ + Identifier ident; + + Objects args; + + this(Loc loc, Identifier ident, Objects args) + { + super(loc, TOK.TOKtraits, this.sizeof); + this.ident = ident; + this.args = args; + } + + Expression syntaxCopy() + { + return new TraitsExp(loc, ident, TemplateInstance.arraySyntaxCopy(args)); + } + + Expression semantic(Scope sc) + { + version (LOGSEMANTIC) { + printf("TraitsExp.semantic() %s\n", toChars()); + } + if (ident != Id.compiles && ident != Id.isSame) + TemplateInstance.semanticTiargs(loc, sc, args, 1); + size_t dim = args ? args.dim : 0; + Object o; + FuncDeclaration f; + + string ISTYPE(string cond) + { + return ` + for (size_t i = 0; i < dim; i++) + { Type t = getType(cast(Object)args.data[i]); + if (!t) + goto Lfalse; + if (!(`~cond~`)) + goto Lfalse; + } + if (!dim) + goto Lfalse; + goto Ltrue; + `; + } + + string ISDSYMBOL(string cond) + { + return `for (size_t i = 0; i < dim; i++) + { Dsymbol s = getDsymbol(cast(Object)args.data[i]); + if (!s) + goto Lfalse; + if (!(`~cond~`)) + goto Lfalse; + } + if (!dim) + goto Lfalse; + goto Ltrue;`; + } + + if (ident == Id.isArithmetic) + { + mixin(ISTYPE(`t.isintegral() || t.isfloating()`)); + } + else if (ident == Id.isFloating) + { + mixin(ISTYPE(q{t.isfloating()})); + } + else if (ident == Id.isIntegral) + { + mixin(ISTYPE(q{t.isintegral()})); + } + else if (ident == Id.isScalar) + { + mixin(ISTYPE(q{t.isscalar()})); + } + else if (ident == Id.isUnsigned) + { + mixin(ISTYPE(q{t.isunsigned()})); + } + else if (ident == Id.isAssociativeArray) + { + mixin(ISTYPE(q{t.toBasetype().ty == TY.Taarray})); + } + else if (ident == Id.isStaticArray) + { + mixin(ISTYPE(q{t.toBasetype().ty == TY.Tsarray})); + } + else if (ident == Id.isAbstractClass) + { + mixin(ISTYPE(q{t.toBasetype().ty == TY.Tclass && (cast(TypeClass)t.toBasetype()).sym.isAbstract()})); + } + else if (ident == Id.isFinalClass) + { + mixin(ISTYPE(q{t.toBasetype().ty == TY.Tclass && (cast(TypeClass)t.toBasetype()).sym.storage_class & STC.STCfinal})); + } + else if (ident == Id.isAbstractFunction) + { + mixin(ISDSYMBOL(q{(f = s.isFuncDeclaration()) !is null && f.isAbstract()})); + } + else if (ident == Id.isVirtualFunction) + { + mixin(ISDSYMBOL(q{(f = s.isFuncDeclaration()) !is null && f.isVirtual()})); + } + else if (ident == Id.isFinalFunction) + { + mixin(ISDSYMBOL(q{(f = s.isFuncDeclaration()) !is null && f.isFinal()})); + } + else if (ident == Id.hasMember || + ident == Id.getMember || + ident == Id.getVirtualFunctions) + { + if (dim != 2) + goto Ldimerror; + Object o_ = cast(Object)args.data[0]; + Expression e = isExpression(cast(Object)args.data[1]); + if (!e) + { error("expression expected as second argument of __traits %s", ident.toChars()); + goto Lfalse; + } + e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret); + if (e.op != TOKstring) + { error("string expected as second argument of __traits %s instead of %s", ident.toChars(), e.toChars()); + goto Lfalse; + } + StringExp se = cast(StringExp)e; + se = se.toUTF8(sc); + if (se.sz != 1) + { error("string must be chars"); + goto Lfalse; + } + Identifier id = Lexer.idPool(fromStringz(cast(char*)se.string_)); + + Type t = isType(o_); + e = isExpression(o_); + Dsymbol s = isDsymbol(o_); + if (t) + e = typeDotIdExp(loc, t, id); + else if (e) + e = new DotIdExp(loc, e, id); + else if (s) + { e = new DsymbolExp(loc, s); + e = new DotIdExp(loc, e, id); + } + else + { error("invalid first argument"); + goto Lfalse; + } + + if (ident == Id.hasMember) + { /* Take any errors as meaning it wasn't found + */ + e = e.trySemantic(sc); + if (!e) + { if (global.gag) + global.errors++; + goto Lfalse; + } + else + goto Ltrue; + } + else if (ident == Id.getMember) + { + e = e.semantic(sc); + return e; + } + else if (ident == Id.getVirtualFunctions) + { + uint errors = global.errors; + Expression ex = e; + e = e.semantic(sc); + if (errors < global.errors) + error("%s cannot be resolved", ex.toChars()); + + /* Create tuple of virtual function overloads of e + */ + //e.dump(0); + Expressions exps = new Expressions(); + FuncDeclaration f_; + if (e.op == TOKvar) + { VarExp ve = cast(VarExp)e; + f_ = ve.var.isFuncDeclaration(); + } + else if (e.op == TOKdotvar) + { DotVarExp dve = cast(DotVarExp)e; + f_ = dve.var.isFuncDeclaration(); + } + else + f_ = null; + Pvirtuals p; + p.exps = exps; + p.e1 = e; + overloadApply(f_, &p.fpvirtuals, &p); + + TupleExp tup = new TupleExp(loc, exps); + return tup.semantic(sc); + } + else + assert(0); + } + else if (ident == Id.classInstanceSize) + { + if (dim != 1) + goto Ldimerror; + Object o_ = cast(Object)args.data[0]; + Dsymbol s = getDsymbol(o_); + ClassDeclaration cd; + if (!s || (cd = s.isClassDeclaration()) is null) + { + error("first argument is not a class"); + goto Lfalse; + } + return new IntegerExp(loc, cd.structsize, Type.tsize_t); + } + else if (ident == Id.allMembers || ident == Id.derivedMembers) + { + if (dim != 1) + goto Ldimerror; + Object o_ = cast(Object)args.data[0]; + Dsymbol s = getDsymbol(o_); + ScopeDsymbol sd; + if (!s) + { + error("argument has no members"); + goto Lfalse; + } + if ((sd = s.isScopeDsymbol()) is null) + { + error("%s %s has no members", s.kind(), s.toChars()); + goto Lfalse; + } + Expressions exps = new Expressions; + while (1) + { size_t dim_ = ScopeDsymbol.dim(sd.members); + for (size_t i = 0; i < dim_; i++) + { + Dsymbol sm = ScopeDsymbol.getNth(sd.members, i); + //printf("\t[%i] %s %s\n", i, sm.kind(), sm.toChars()); + if (sm.ident) + { + //printf("\t%s\n", sm.ident.toChars()); + auto str = sm.ident.toChars(); + + /* Skip if already present in exps[] + */ + for (size_t j = 0; j < exps.dim; j++) + { StringExp se2 = cast(StringExp)exps.data[j]; + if (strcmp(toStringz(str), cast(char*)se2.string_) == 0) + goto Lnext; + } + + StringExp se = new StringExp(loc, str); + exps.push(cast(void*)se); + } +Lnext: + ; + } + ClassDeclaration cd = sd.isClassDeclaration(); + if (cd && cd.baseClass && ident == Id.allMembers) + sd = cd.baseClass; // do again with base class + else + break; + } + Expression e = new ArrayLiteralExp(loc, exps); + e = e.semantic(sc); + return e; + } + else if (ident == Id.compiles) + { + /* Determine if all the objects - types, expressions, or symbols - + * compile without error + */ + if (!dim) + goto Lfalse; + + for (size_t i = 0; i < dim; i++) + { Object o_ = cast(Object)args.data[i]; + Expression e; + + uint errors = global.errors; + global.gag++; + + Type t = isType(o_); + if (t) + { Dsymbol s; + t.resolve(loc, sc, &e, &t, &s); + if (t) + t.semantic(loc, sc); + else if (e) + e.semantic(sc); + } + else + { e = isExpression(o); + if (e) + e.semantic(sc); + } + + global.gag--; + if (errors != global.errors) + { if (global.gag == 0) + global.errors = errors; + goto Lfalse; + } + } + goto Ltrue; + } + else if (ident == Id.isSame) + { /* Determine if two symbols are the same + */ + if (dim != 2) + goto Ldimerror; + TemplateInstance.semanticTiargs(loc, sc, args, 0); + Object o1 = cast(Object)args.data[0]; + Object o2 = cast(Object)args.data[1]; + Dsymbol s1 = getDsymbol(o1); + Dsymbol s2 = getDsymbol(o2); + + static if (0) { + printf("o1: %p\n", o1); + printf("o2: %p\n", o2); + if (!s1) + { Expression ea = isExpression(o1); + if (ea) + printf("%s\n", ea.toChars()); + Type ta = isType(o1); + if (ta) + printf("%s\n", ta.toChars()); + goto Lfalse; + } + else + printf("%s %s\n", s1.kind(), s1.toChars()); + } + if (!s1 && !s2) + { Expression ea1 = isExpression(o1); + Expression ea2 = isExpression(o2); + if (ea1 && ea2 && ea1.equals(ea2)) + goto Ltrue; + } + + if (!s1 || !s2) + goto Lfalse; + + s1 = s1.toAlias(); + s2 = s2.toAlias(); + + if (s1 == s2) + goto Ltrue; + else + goto Lfalse; + } + else + { error("unrecognized trait %s", ident.toChars()); + goto Lfalse; + } + + return null; + +Lnottype: + error("%s is not a type", o/*.toChars()*/); // BUG: o is Object, no member toChars() + goto Lfalse; + +Ldimerror: + error("wrong number of arguments %d", dim); + goto Lfalse; + + +Lfalse: + return new IntegerExp(loc, 0, Type.tbool); + +Ltrue: + return new IntegerExp(loc, 1, Type.tbool); + } + + void toCBuffer(OutBuffer buf, HdrGenState* hgs) + { + buf.writestring("__traits("); + buf.writestring(ident.toChars()); + if (args) + { + for (int i = 0; i < args.dim; i++) + { + buf.writeByte(','); + Object oarg = cast(Object)args.data[i]; + ObjectToCBuffer(buf, hgs, oarg); + } + } + buf.writeByte(')'); + } +} +
--- a/dmd/expression/Util.d Sun Apr 04 22:41:11 2010 +0100 +++ b/dmd/expression/Util.d Mon Apr 05 03:24:08 2010 +0100 @@ -129,7 +129,7 @@ * 1 done */ -int overloadApply(FuncDeclaration fstart, int delegate(FuncDeclaration) dg) +int overloadApply(FuncDeclaration fstart, int delegate(void*, FuncDeclaration) dg, void* param) { FuncDeclaration f; Declaration d; @@ -141,7 +141,7 @@ if (fa) { - if (overloadApply(fa.funcalias, dg)) + if (overloadApply(fa.funcalias, dg, param)) return 1; next = fa.overnext; } @@ -166,7 +166,7 @@ d.error("is aliased to a function"); break; // BUG: should print error message? } - if (dg(f)) + if (dg(param, f)) return 1; next = f.overnext; @@ -186,7 +186,7 @@ Expression ethis; Expressions arguments; - int fp2(FuncDeclaration f) + int fp2(void*, FuncDeclaration f) { MATCH match; @@ -250,7 +250,7 @@ Type t; // type to match FuncDeclaration f; // return value - int fp1(FuncDeclaration f) + int fp1(void*, FuncDeclaration f) { if (t.equals(f.type)) { @@ -283,7 +283,7 @@ p.m = m; p.ethis = ethis; p.arguments = arguments; - overloadApply(fstart, &p.fp2); + overloadApply(fstart, &p.fp2, &p); } void templateResolve(Match* m, TemplateDeclaration td, Scope sc, Loc loc, Objects targsi, Expression ethis, Expressions arguments) @@ -1258,7 +1258,7 @@ * analogous to func.overloadResolveX(). */ - int fp3(FuncDeclaration f) + int fp3(void*, FuncDeclaration f) { TypeFunction tf = cast(TypeFunction)f.type; if (inferApplyArgTypesY(tf, arguments) == 1) @@ -1277,7 +1277,7 @@ { Param3 p3; p3.arguments = arguments; - overloadApply(fstart, &p3.fp3); + overloadApply(fstart, &p3.fp3, cast(void*)arguments); } /******************************