Mercurial > projects > ddmd
changeset 8:d42cd5917df4
wysiwyg strings, alias this, templates, TypeSlice implementation
author | dkoroskin <> |
---|---|
date | Mon, 14 Dec 2009 17:43:43 +0300 |
parents | 89cc05dbdae1 |
children | 661073dd5661 |
files | dmd/AliasThis.d dmd/InExp.d dmd/Lexer.d dmd/TemplateDeclaration.d dmd/TypeSlice.d |
diffstat | 5 files changed, 270 insertions(+), 15 deletions(-) [+] |
line wrap: on
line diff
--- a/dmd/AliasThis.d Mon Dec 14 14:50:03 2009 +0300 +++ b/dmd/AliasThis.d Mon Dec 14 17:43:43 2009 +0300 @@ -6,6 +6,7 @@ import dmd.Scope; import dmd.OutBuffer; import dmd.HdrGenState; +import dmd.AggregateDeclaration; class AliasThis : Dsymbol { @@ -14,17 +15,38 @@ this(Loc loc, Identifier ident) { - assert(false); + super(null); // it's anonymous (no identifier) + this.loc = loc; + this.ident = ident; } - Dsymbol syntaxCopy(Dsymbol) + Dsymbol syntaxCopy(Dsymbol s) { - assert(false); + assert(!s); + /* Since there is no semantic information stored here, + * we don't need to copy it. + */ + return this; } void semantic(Scope sc) { - assert(false); + Dsymbol parent = sc.parent; + if (parent) + parent = parent.pastMixin(); + AggregateDeclaration ad = null; + if (parent) + ad = parent.isAggregateDeclaration(); + if (ad) + { + if (ad.aliasthis) + error("there can be only one alias this"); + assert(ad.members); + Dsymbol s = ad.search(loc, ident, 0); + ad.aliasthis = s; + } + else + error("alias this can only appear in struct or class declaration, not %s", parent ? parent.toChars() : "nowhere"); } string kind()
--- a/dmd/InExp.d Mon Dec 14 14:50:03 2009 +0300 +++ b/dmd/InExp.d Mon Dec 14 17:43:43 2009 +0300 @@ -6,7 +6,12 @@ import dmd.Scope; import dmd.IRState; import dmd.BinExp; -import dmd.TOK; +import dmd.TOK; +import dmd.Type; +import dmd.TY; +import dmd.TypeAArray; + +import dmd.expression.util.arrayTypeCompatible; import dmd.backend.elem; @@ -14,18 +19,47 @@ { this(Loc loc, Expression e1, Expression e2) { - assert(false); - super(loc, TOK.init, 0, e1, e2); + super(loc, TOKin, InExp.sizeof, e1, e2); } Expression semantic(Scope sc) { - assert(false); + if (type) + return this; + + super.semanticp(sc); + + Expression e = op_overload(sc); + if (e) + return e; + + //type = Type.tboolean; + Type t2b = e2.type.toBasetype(); + if (t2b.ty != TY.Taarray) + { + error("rvalue of in expression must be an associative array, not %s", e2.type.toChars()); + type = Type.terror; + } + else + { + TypeAArray ta = cast(TypeAArray)t2b; + + // Special handling for array keys + if (!arrayTypeCompatible(e1.loc, e1.type, ta.index)) + { + // Convert key to type of key + e1 = e1.implicitCastTo(sc, ta.index); + } + + // Return type is pointer to value + type = ta.nextOf().pointerTo(); + } + return this; } int isBit() { - assert(false); + return 0; } Identifier opId()
--- a/dmd/Lexer.d Mon Dec 14 14:50:03 2009 +0300 +++ b/dmd/Lexer.d Mon Dec 14 17:43:43 2009 +0300 @@ -1561,6 +1561,64 @@ TOK wysiwygStringConstant(Token* t, int tc) { + uint c; + Loc start = loc; + + p++; + stringbuffer.reset(); + while (true) + { + c = *p++; + switch (c) + { + case '\n': + loc.linnum++; + break; + + case '\r': + if (*p == '\n') + continue; // ignore + c = '\n'; // treat EndOfLine as \n character + loc.linnum++; + break; + + case 0: + case 0x1A: + error("unterminated string constant starting at %s", start.toChars()); + t.ustring = "".ptr; + t.len = 0; + t.postfix = 0; + return TOKstring; + + case '"': + case '`': + if (c == tc) + { + t.len = stringbuffer.offset; + stringbuffer.writeByte(0); + char* tmp = cast(char*)GC.malloc(stringbuffer.offset); + memcpy(tmp, stringbuffer.data, stringbuffer.offset); + t.ustring = tmp; + stringPostfix(t); + return TOKstring; + } + break; + + default: + if (c & 0x80) + { p--; + uint u = decodeUTF(); + p++; + if (u == PS || u == LS) + loc.linnum++; + stringbuffer.writeUTF8(u); + continue; + } + break; + } + stringbuffer.writeByte(c); + } + assert(false); } @@ -1575,9 +1633,59 @@ assert(false); } + /************************************** + * Lex delimited strings: + * q{ foo(xxx) } // " foo(xxx) " + * q{foo(} // "foo(" + * q{{foo}"}"} // "{foo}"}"" + * Input: + * p is on the q + */ TOK tokenStringConstant(Token* t) { - assert(false); + uint nest = 1; + Loc start = loc; + ubyte* pstart = ++p; + + while (true) + { + Token tok; + + scan(&tok); + switch (tok.value) + { + case TOKlcurly: + nest++; + continue; + + case TOKrcurly: + if (--nest == 0) + goto Ldone; + continue; + + case TOKeof: + goto Lerror; + + default: + continue; + } + } + + Ldone: + t.len = p - 1 - pstart; + char* tmp = cast(char*)GC.malloc(t.len + 1); + memcpy(tmp, pstart, t.len); + tmp[t.len] = 0; + t.ustring = tmp; + stringPostfix(t); + return TOKstring; + + Lerror: + error("unterminated token string constant starting at %s", start.toChars()); + t.ustring = "".ptr; + t.len = 0; + t.postfix = 0; + return TOKstring; } } TOK escapeStringConstant(Token* t, int wide)
--- a/dmd/TemplateDeclaration.d Mon Dec 14 14:50:03 2009 +0300 +++ b/dmd/TemplateDeclaration.d Mon Dec 14 17:43:43 2009 +0300 @@ -246,9 +246,55 @@ */ } + /********************************** + * Overload existing TemplateDeclaration 'this' with the new one 's'. + * Return !=0 if successful; i.e. no conflict. + */ bool overloadInsert(Dsymbol s) { - assert(false); + TemplateDeclaration f; + + version (LOG) { + printf("TemplateDeclaration.overloadInsert('%s')\n", s.toChars()); + } + f = s.isTemplateDeclaration(); + if (!f) + return false; + + for (TemplateDeclaration f2 = this; f2; f2 = f2.overnext) + { + static if (false) { + // Conflict if TemplateParameter's match + // Will get caught anyway later with TemplateInstance, but + // should check it now. + if (f.parameters.dim != f2.parameters.dim) + goto Lcontinue; + + for (int i = 0; i < f.parameters.dim; i++) + { + TemplateParameter p1 = cast(TemplateParameter)f.parameters.data[i]; + TemplateParameter p2 = cast(TemplateParameter)f2.parameters.data[i]; + + if (!p1.overloadMatch(p2)) + goto Lcontinue; + } + + version (LOG) { + printf("\tfalse: conflict\n"); + } + return false; + + Lcontinue: + ; + } + } + + f.overroot = this; + ///*pf = f; + version (LOG) { + printf("\ttrue: no conflict\n"); + } + return true; } void toCBuffer(OutBuffer buf, HdrGenState* hgs)
--- a/dmd/TypeSlice.d Mon Dec 14 14:50:03 2009 +0300 +++ b/dmd/TypeSlice.d Mon Dec 14 17:43:43 2009 +0300 @@ -10,6 +10,12 @@ import dmd.OutBuffer; import dmd.HdrGenState; import dmd.TY; +import dmd.TypeTuple; +import dmd.WANT; +import dmd.ArrayTypes; +import dmd.Argument; + +import dmd.type.Util; class TypeSlice : TypeNext { @@ -18,8 +24,10 @@ this(Type next, Expression lwr, Expression upr) { - super(TY.init, null); - assert(false); + super(TY.Tslice, next); + //printf("TypeSlice[%s .. %s]\n", lwr.toChars(), upr.toChars()); + this.lwr = lwr; + this.upr = upr; } version (DumbClone) { @@ -32,12 +40,49 @@ Type syntaxCopy() { - assert(false); + Type t = new TypeSlice(next.syntaxCopy(), lwr.syntaxCopy(), upr.syntaxCopy()); + t.mod = mod; + return t; } Type semantic(Loc loc, Scope sc) { - assert(false); + //printf("TypeSlice.semantic() %s\n", toChars()); + next = next.semantic(loc, sc); + transitive(); + //printf("next: %s\n", next.toChars()); + + Type tbn = next.toBasetype(); + if (tbn.ty != Ttuple) + { + error(loc, "can only slice tuple types, not %s", tbn.toChars()); + return Type.terror; + } + TypeTuple tt = cast(TypeTuple)tbn; + + lwr = semanticLength(sc, tbn, lwr); + lwr = lwr.optimize(WANTvalue); + ulong i1 = lwr.toUInteger(); + + upr = semanticLength(sc, tbn, upr); + upr = upr.optimize(WANTvalue); + ulong i2 = upr.toUInteger(); + + if (!(i1 <= i2 && i2 <= tt.arguments.dim)) + { + error(loc, "slice [%ju..%ju] is out of range of [0..%u]", i1, i2, tt.arguments.dim); + return Type.terror; + } + + Arguments args = new Arguments; + args.reserve(cast(size_t)(i2 - i1)); + for (size_t i = cast(size_t)i1; i < cast(size_t)i2; i++) + { + Argument arg = cast(Argument)tt.arguments.data[i]; + args.push(cast(void*)arg); + } + + return new TypeTuple(args); } void resolve(Loc loc, Scope sc, Expression* pe, Type* pt, Dsymbol* ps)