# HG changeset patch # User Tomas Lindquist Olsen # Date 1218689741 -7200 # Node ID 6aee82889553f7da34a6cd121eb186cced547cd5 # Parent 337554fd34f1350a792ff6726a7bfd50ec8251fc Merged DMD 1.034, array operations are not yet implemented ;) diff -r 337554fd34f1 -r 6aee82889553 dmd/arrayop.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/arrayop.c Thu Aug 14 06:55:41 2008 +0200 @@ -0,0 +1,505 @@ + +// Copyright (c) 1999-2008 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// http://www.digitalmars.com +// License for redistribution is by either the Artistic License +// in artistic.txt, or the GNU General Public License in gnu.txt. +// See the included readme.txt for details. + +#include +#include +#include + +#if _WIN32 || IN_GCC || IN_LLVM +#include "mem.h" +#else +#include "../root/mem.h" +#endif + +#include "stringtable.h" + +#include "expression.h" +#include "statement.h" +#include "mtype.h" +#include "declaration.h" +#include "scope.h" +#include "id.h" +#include "module.h" +#include "init.h" + +// FIXME +int binary(const char *p , const char **tab, int high) +{ + assert(0); +} + +/************************************** + * Hash table of array op functions already generated or known about. + */ + +StringTable arrayfuncs; + +/*********************************** + * Construct the array operation expression. + */ + +Expression *BinExp::arrayOp(Scope *sc) +{ + // FIXME + error("array operations not yet implemented"); + fatal(); + + Expressions *arguments = new Expressions(); + + /* The expression to generate an array operation for is mangled + * into a name to use as the array operation function name. + * Mangle in the operands and operators in RPN order, and type. + */ + OutBuffer buf; + buf.writestring("_array"); + buildArrayIdent(&buf, arguments); + buf.writeByte('_'); + + /* Append deco of array element type + */ +#if DMDV2 + buf.writestring(type->toBasetype()->nextOf()->toBasetype()->mutableOf()->deco); +#else + buf.writestring(type->toBasetype()->nextOf()->toBasetype()->deco); +#endif + + size_t namelen = buf.offset; + buf.writeByte(0); + char *name = (char *)buf.extractData(); + + /* Look up name in hash table + */ + StringValue *sv = arrayfuncs.update(name, namelen); + FuncDeclaration *fd = (FuncDeclaration *)sv->ptrvalue; + if (!fd) + { + /* Some of the array op functions are written as library functions, + * presumably to optimize them with special CPU vector instructions. + * List those library functions here, in alpha order. + */ + static const char *libArrayopFuncs[] = + { + "_arrayExpSliceAddass_a", + "_arrayExpSliceAddass_d", // T[]+=T + "_arrayExpSliceAddass_f", // T[]+=T + "_arrayExpSliceAddass_g", + "_arrayExpSliceAddass_h", + "_arrayExpSliceAddass_i", + "_arrayExpSliceAddass_k", + "_arrayExpSliceAddass_s", + "_arrayExpSliceAddass_t", + "_arrayExpSliceAddass_u", + "_arrayExpSliceAddass_w", + + "_arrayExpSliceDivass_d", // T[]/=T + "_arrayExpSliceDivass_f", // T[]/=T + + "_arrayExpSliceMinSliceAssign_a", + "_arrayExpSliceMinSliceAssign_d", // T[]=T-T[] + "_arrayExpSliceMinSliceAssign_f", // T[]=T-T[] + "_arrayExpSliceMinSliceAssign_g", + "_arrayExpSliceMinSliceAssign_h", + "_arrayExpSliceMinSliceAssign_i", + "_arrayExpSliceMinSliceAssign_k", + "_arrayExpSliceMinSliceAssign_s", + "_arrayExpSliceMinSliceAssign_t", + "_arrayExpSliceMinSliceAssign_u", + "_arrayExpSliceMinSliceAssign_w", + + "_arrayExpSliceMinass_a", + "_arrayExpSliceMinass_d", // T[]-=T + "_arrayExpSliceMinass_f", // T[]-=T + "_arrayExpSliceMinass_g", + "_arrayExpSliceMinass_h", + "_arrayExpSliceMinass_i", + "_arrayExpSliceMinass_k", + "_arrayExpSliceMinass_s", + "_arrayExpSliceMinass_t", + "_arrayExpSliceMinass_u", + "_arrayExpSliceMinass_w", + + "_arrayExpSliceMulass_d", // T[]*=T + "_arrayExpSliceMulass_f", // T[]*=T + "_arrayExpSliceMulass_i", + "_arrayExpSliceMulass_k", + "_arrayExpSliceMulass_s", + "_arrayExpSliceMulass_t", + "_arrayExpSliceMulass_u", + "_arrayExpSliceMulass_w", + + "_arraySliceExpAddSliceAssign_a", + "_arraySliceExpAddSliceAssign_d", // T[]=T[]+T + "_arraySliceExpAddSliceAssign_f", // T[]=T[]+T + "_arraySliceExpAddSliceAssign_g", + "_arraySliceExpAddSliceAssign_h", + "_arraySliceExpAddSliceAssign_i", + "_arraySliceExpAddSliceAssign_k", + "_arraySliceExpAddSliceAssign_s", + "_arraySliceExpAddSliceAssign_t", + "_arraySliceExpAddSliceAssign_u", + "_arraySliceExpAddSliceAssign_w", + + "_arraySliceExpDivSliceAssign_d", // T[]=T[]/T + "_arraySliceExpDivSliceAssign_f", // T[]=T[]/T + + "_arraySliceExpMinSliceAssign_a", + "_arraySliceExpMinSliceAssign_d", // T[]=T[]-T + "_arraySliceExpMinSliceAssign_f", // T[]=T[]-T + "_arraySliceExpMinSliceAssign_g", + "_arraySliceExpMinSliceAssign_h", + "_arraySliceExpMinSliceAssign_i", + "_arraySliceExpMinSliceAssign_k", + "_arraySliceExpMinSliceAssign_s", + "_arraySliceExpMinSliceAssign_t", + "_arraySliceExpMinSliceAssign_u", + "_arraySliceExpMinSliceAssign_w", + + "_arraySliceExpMulSliceAddass_d", // T[] += T[]*T + "_arraySliceExpMulSliceAddass_f", + "_arraySliceExpMulSliceAddass_r", + + "_arraySliceExpMulSliceAssign_d", // T[]=T[]*T + "_arraySliceExpMulSliceAssign_f", // T[]=T[]*T + "_arraySliceExpMulSliceAssign_i", + "_arraySliceExpMulSliceAssign_k", + "_arraySliceExpMulSliceAssign_s", + "_arraySliceExpMulSliceAssign_t", + "_arraySliceExpMulSliceAssign_u", + "_arraySliceExpMulSliceAssign_w", + + "_arraySliceExpMulSliceMinass_d", // T[] -= T[]*T + "_arraySliceExpMulSliceMinass_f", + "_arraySliceExpMulSliceMinass_r", + + "_arraySliceSliceAddSliceAssign_a", + "_arraySliceSliceAddSliceAssign_d", // T[]=T[]+T[] + "_arraySliceSliceAddSliceAssign_f", // T[]=T[]+T[] + "_arraySliceSliceAddSliceAssign_g", + "_arraySliceSliceAddSliceAssign_h", + "_arraySliceSliceAddSliceAssign_i", + "_arraySliceSliceAddSliceAssign_k", + "_arraySliceSliceAddSliceAssign_r", // T[]=T[]+T[] + "_arraySliceSliceAddSliceAssign_s", + "_arraySliceSliceAddSliceAssign_t", + "_arraySliceSliceAddSliceAssign_u", + "_arraySliceSliceAddSliceAssign_w", + + "_arraySliceSliceAddass_a", + "_arraySliceSliceAddass_d", // T[]+=T[] + "_arraySliceSliceAddass_f", // T[]+=T[] + "_arraySliceSliceAddass_g", + "_arraySliceSliceAddass_h", + "_arraySliceSliceAddass_i", + "_arraySliceSliceAddass_k", + "_arraySliceSliceAddass_s", + "_arraySliceSliceAddass_t", + "_arraySliceSliceAddass_u", + "_arraySliceSliceAddass_w", + + "_arraySliceSliceMinSliceAssign_a", + "_arraySliceSliceMinSliceAssign_d", // T[]=T[]-T[] + "_arraySliceSliceMinSliceAssign_f", // T[]=T[]-T[] + "_arraySliceSliceMinSliceAssign_g", + "_arraySliceSliceMinSliceAssign_h", + "_arraySliceSliceMinSliceAssign_i", + "_arraySliceSliceMinSliceAssign_k", + "_arraySliceSliceMinSliceAssign_r", // T[]=T[]-T[] + "_arraySliceSliceMinSliceAssign_s", + "_arraySliceSliceMinSliceAssign_t", + "_arraySliceSliceMinSliceAssign_u", + "_arraySliceSliceMinSliceAssign_w", + + "_arraySliceSliceMinass_a", + "_arraySliceSliceMinass_d", // T[]-=T[] + "_arraySliceSliceMinass_f", // T[]-=T[] + "_arraySliceSliceMinass_g", + "_arraySliceSliceMinass_h", + "_arraySliceSliceMinass_i", + "_arraySliceSliceMinass_k", + "_arraySliceSliceMinass_s", + "_arraySliceSliceMinass_t", + "_arraySliceSliceMinass_u", + "_arraySliceSliceMinass_w", + + "_arraySliceSliceMulSliceAssign_d", // T[]=T[]*T[] + "_arraySliceSliceMulSliceAssign_f", // T[]=T[]*T[] + "_arraySliceSliceMulSliceAssign_i", + "_arraySliceSliceMulSliceAssign_k", + "_arraySliceSliceMulSliceAssign_s", + "_arraySliceSliceMulSliceAssign_t", + "_arraySliceSliceMulSliceAssign_u", + "_arraySliceSliceMulSliceAssign_w", + + "_arraySliceSliceMulass_d", // T[]*=T[] + "_arraySliceSliceMulass_f", // T[]*=T[] + "_arraySliceSliceMulass_i", + "_arraySliceSliceMulass_k", + "_arraySliceSliceMulass_s", + "_arraySliceSliceMulass_t", + "_arraySliceSliceMulass_u", + "_arraySliceSliceMulass_w", + }; + + int i = binary(name, libArrayopFuncs, sizeof(libArrayopFuncs) / sizeof(char *)); + if (i == -1) + { +#ifdef DEBUG // Make sure our array is alphabetized + for (i = 0; i < sizeof(libArrayopFuncs) / sizeof(char *); i++) + { + if (strcmp(name, libArrayopFuncs[i]) == 0) + assert(0); + } +#endif + /* Not in library, so generate it. + * Construct the function body: + * foreach (i; 0 .. p.length) for (size_t i = 0; i < p.length; i++) + * loopbody; + * return p; + */ + + Arguments *fparams = new Arguments(); + Expression *loopbody = buildArrayLoop(fparams); + Argument *p = (Argument *)fparams->data[0 /*fparams->dim - 1*/]; +#if DMDV1 + // for (size_t i = 0; i < p.length; i++) + Initializer *init = new ExpInitializer(0, new IntegerExp(0, 0, Type::tsize_t)); + Dsymbol *d = new VarDeclaration(0, Type::tsize_t, Id::p, init); + Statement *s1 = new ForStatement(0, + new DeclarationStatement(0, d), + new CmpExp(TOKlt, 0, new IdentifierExp(0, Id::p), new ArrayLengthExp(0, new IdentifierExp(0, p->ident))), + new PostExp(TOKplusplus, 0, new IdentifierExp(0, Id::p)), + new ExpStatement(0, loopbody)); +#else + // foreach (i; 0 .. p.length) + Statement *s1 = new ForeachRangeStatement(0, TOKforeach, + new Argument(0, NULL, Id::p, NULL), + new IntegerExp(0, 0, Type::tint32), + new ArrayLengthExp(0, new IdentifierExp(0, p->ident)), + new ExpStatement(0, loopbody)); +#endif + Statement *s2 = new ReturnStatement(0, new IdentifierExp(0, p->ident)); + //printf("s2: %s\n", s2->toChars()); + Statement *fbody = new CompoundStatement(0, s1, s2); + + /* Construct the function + */ + TypeFunction *ftype = new TypeFunction(fparams, type, 0, LINKc); + //printf("ftype: %s\n", ftype->toChars()); + fd = new FuncDeclaration(0, 0, Lexer::idPool(name), STCundefined, ftype); + fd->fbody = fbody; + fd->protection = PROTpublic; + fd->linkage = LINKc; + + sc->module->importedFrom->members->push(fd); + + sc = sc->push(); + sc->parent = sc->module->importedFrom; + sc->stc = 0; + sc->linkage = LINKc; + fd->semantic(sc); + sc->pop(); + } + else + { /* In library, refer to it. + */ + // LLVMDC FIXME + fd = FuncDeclaration::genCfunc(NULL, type, name); + } + sv->ptrvalue = fd; // cache symbol in hash table + } + + /* Call the function fd(arguments) + */ + Expression *ec = new VarExp(0, fd); + Expression *e = new CallExp(loc, ec, arguments); + e->type = type; + return e; +} + +/****************************************** + * Construct the identifier for the array operation function, + * and build the argument list to pass to it. + */ + +void Expression::buildArrayIdent(OutBuffer *buf, Expressions *arguments) +{ + buf->writestring("Exp"); + arguments->shift(this); +} + +void SliceExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) +{ + buf->writestring("Slice"); + arguments->shift(this); +} + +void AssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) +{ + /* Evaluate assign expressions right to left + */ + e2->buildArrayIdent(buf, arguments); + e1->buildArrayIdent(buf, arguments); + buf->writestring("Assign"); +} + +#define X(Str) \ +void Str##AssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) \ +{ \ + /* Evaluate assign expressions right to left \ + */ \ + e2->buildArrayIdent(buf, arguments); \ + e1->buildArrayIdent(buf, arguments); \ + buf->writestring(#Str); \ + buf->writestring("ass"); \ +} + +X(Add) +X(Min) +X(Mul) +X(Div) +X(Mod) +X(Xor) +X(And) +X(Or) + +#undef X + +void NegExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) +{ + e1->buildArrayIdent(buf, arguments); + buf->writestring("Neg"); +} + +void ComExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) +{ + e1->buildArrayIdent(buf, arguments); + buf->writestring("Com"); +} + +#define X(Str) \ +void Str##Exp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) \ +{ \ + /* Evaluate assign expressions left to right \ + */ \ + e1->buildArrayIdent(buf, arguments); \ + e2->buildArrayIdent(buf, arguments); \ + buf->writestring(#Str); \ +} + +X(Add) +X(Min) +X(Mul) +X(Div) +X(Mod) +X(Xor) +X(And) +X(Or) + +#undef X + +/****************************************** + * Construct the inner loop for the array operation function, + * and build the parameter list. + */ + +Expression *Expression::buildArrayLoop(Arguments *fparams) +{ + Identifier *id = Identifier::generateId("c", fparams->dim); + Argument *param = new Argument(0, type, id, NULL); + fparams->shift(param); + Expression *e = new IdentifierExp(0, id); + return e; +} + +Expression *SliceExp::buildArrayLoop(Arguments *fparams) +{ + Identifier *id = Identifier::generateId("p", fparams->dim); + Argument *param = new Argument(STCconst, type, id, NULL); + fparams->shift(param); + Expression *e = new IdentifierExp(0, id); + Expressions *arguments = new Expressions(); + Expression *index = new IdentifierExp(0, Id::p); + arguments->push(index); + e = new ArrayExp(0, e, arguments); + return e; +} + +Expression *AssignExp::buildArrayLoop(Arguments *fparams) +{ + /* Evaluate assign expressions right to left + */ + Expression *ex2 = e2->buildArrayLoop(fparams); + Expression *ex1 = e1->buildArrayLoop(fparams); + Argument *param = (Argument *)fparams->data[0]; + param->storageClass = 0; + Expression *e = new AssignExp(0, ex1, ex2); + return e; +} + +#define X(Str) \ +Expression *Str##AssignExp::buildArrayLoop(Arguments *fparams) \ +{ \ + /* Evaluate assign expressions right to left \ + */ \ + Expression *ex2 = e2->buildArrayLoop(fparams); \ + Expression *ex1 = e1->buildArrayLoop(fparams); \ + Argument *param = (Argument *)fparams->data[0]; \ + param->storageClass = 0; \ + Expression *e = new Str##AssignExp(0, ex1, ex2); \ + return e; \ +} + +X(Add) +X(Min) +X(Mul) +X(Div) +X(Mod) +X(Xor) +X(And) +X(Or) + +#undef X + +Expression *NegExp::buildArrayLoop(Arguments *fparams) +{ + Expression *ex1 = e1->buildArrayLoop(fparams); + Expression *e = new NegExp(0, ex1); + return e; +} + +Expression *ComExp::buildArrayLoop(Arguments *fparams) +{ + Expression *ex1 = e1->buildArrayLoop(fparams); + Expression *e = new ComExp(0, ex1); + return e; +} + +#define X(Str) \ +Expression *Str##Exp::buildArrayLoop(Arguments *fparams) \ +{ \ + /* Evaluate assign expressions left to right \ + */ \ + Expression *ex1 = e1->buildArrayLoop(fparams); \ + Expression *ex2 = e2->buildArrayLoop(fparams); \ + Expression *e = new Str##Exp(0, ex1, ex2); \ + return e; \ +} + +X(Add) +X(Min) +X(Mul) +X(Div) +X(Mod) +X(Xor) +X(And) +X(Or) + +#undef X + + diff -r 337554fd34f1 -r 6aee82889553 dmd/cast.c --- a/dmd/cast.c Thu Aug 14 03:09:26 2008 +0200 +++ b/dmd/cast.c Thu Aug 14 06:55:41 2008 +0200 @@ -46,6 +46,14 @@ warning("%s: implicit conversion of expression (%s) of type %s to %s can cause loss of data", loc.toChars(), toChars(), type->toChars(), t->toChars()); } +#if DMDV2 + if (match == MATCHconst && t == type->constOf()) + { + Expression *e = copy(); + e->type = t; + return e; + } +#endif return castTo(sc, t); } @@ -54,12 +62,13 @@ return e->implicitCastTo(sc, t); #if 0 +printf("ty = %d\n", type->ty); print(); type->print(); printf("to:\n"); t->print(); printf("%p %p type: %s to: %s\n", type->deco, t->deco, type->deco, t->deco); -//printf("%p %p %p\n", type->next->arrayOf(), type, t); +//printf("%p %p %p\n", type->nextOf()->arrayOf(), type, t); fflush(stdout); #endif if (!t->deco) @@ -92,6 +101,7 @@ printf("Expression::implicitConvTo(this=%s, type=%s, t=%s)\n", toChars(), type->toChars(), t->toChars()); #endif + //static int nest; if (++nest == 10) halt(); if (!type) { error("%s is not an expression", toChars()); type = Type::terror; @@ -110,16 +120,16 @@ Type *tb = t->toBasetype(); if (tb->ty == Tdelegate) { TypeDelegate *td = (TypeDelegate *)tb; - TypeFunction *tf = (TypeFunction *)td->next; + TypeFunction *tf = (TypeFunction *)td->nextOf(); if (!tf->varargs && !(tf->arguments && tf->arguments->dim) ) { - match = type->implicitConvTo(tf->next); + match = type->implicitConvTo(tf->nextOf()); if (match) return match; - if (tf->next->toBasetype()->ty == Tvoid) + if (tf->nextOf()->toBasetype()->ty == Tvoid) return MATCHconvert; } } @@ -332,6 +342,39 @@ return Expression::implicitConvTo(t); } +#if DMDV2 +MATCH StructLiteralExp::implicitConvTo(Type *t) +{ +#if 0 + printf("StructLiteralExp::implicitConvTo(this=%s, type=%s, t=%s)\n", + toChars(), type->toChars(), t->toChars()); +#endif + MATCH m = Expression::implicitConvTo(t); + if (m != MATCHnomatch) + return m; + if (type->ty == t->ty && type->ty == Tstruct && + ((TypeStruct *)type)->sym == ((TypeStruct *)t)->sym) + { + m = MATCHconst; + for (int i = 0; i < elements->dim; i++) + { Expression *e = (Expression *)elements->data[i]; + Type *te = e->type; + if (t->mod == 0) + te = te->mutableOf(); + else + { assert(t->mod == MODinvariant); + te = te->invariantOf(); + } + MATCH m2 = e->implicitConvTo(te); + //printf("\t%s => %s, match = %d\n", e->toChars(), te->toChars(), m2); + if (m2 < m) + m = m2; + } + } + return m; +} +#endif + MATCH StringExp::implicitConvTo(Type *t) { MATCH m; @@ -387,6 +430,10 @@ MATCH ArrayLiteralExp::implicitConvTo(Type *t) { MATCH result = MATCHexact; +#if 0 + printf("ArrayLiteralExp::implicitConvTo(this=%s, type=%s, t=%s)\n", + toChars(), type->toChars(), t->toChars()); +#endif Type *typeb = type->toBasetype(); Type *tb = t->toBasetype(); if ((tb->ty == Tarray || tb->ty == Tsarray) && @@ -400,7 +447,7 @@ for (int i = 0; i < elements->dim; i++) { Expression *e = (Expression *)elements->data[i]; - MATCH m = (MATCH)e->implicitConvTo(tb->next); + MATCH m = (MATCH)e->implicitConvTo(tb->nextOf()); if (m < result) result = m; // remember worst match if (result == MATCHnomatch) @@ -427,7 +474,7 @@ if (result == MATCHnomatch) break; // no need to check for worse e = (Expression *)values->data[i]; - m = (MATCH)e->implicitConvTo(tb->next); + m = (MATCH)e->implicitConvTo(tb->nextOf()); if (m < result) result = m; // remember worst match if (result == MATCHnomatch) @@ -516,10 +563,10 @@ FuncDeclaration *f; t = t->toBasetype(); - if (type->ty == Tdelegate && type->next->ty == Tfunction && - t->ty == Tdelegate && t->next->ty == Tfunction) + if (type->ty == Tdelegate && type->nextOf()->ty == Tfunction && + t->ty == Tdelegate && t->nextOf()->ty == Tfunction) { - if (func && func->overloadExactMatch(t->next)) + if (func && func->overloadExactMatch(t->nextOf())) result = MATCHexact; } } @@ -948,7 +995,7 @@ Expression *ArrayLiteralExp::castTo(Scope *sc, Type *t) { #if 0 - printf("ArrayLiteralExp::castTo(this=%s, type=%s, t=%s)\n", + printf("ArrayLiteralExp::castTo(this=%s, type=%s, => %s)\n", toChars(), type->toChars(), t->toChars()); #endif if (type == t) @@ -1016,7 +1063,6 @@ return e->Expression::castTo(sc, t); } - Expression *SymOffExp::castTo(Scope *sc, Type *t) { Type *tb; @@ -1134,7 +1180,7 @@ // Replace (ptr + int) with (ptr + (int * stride)) Type *t = Type::tptrdiff_t; - stride = t1b->next->size(); + stride = t1b->nextOf()->size(loc); if (!t->equals(t2b)) e2 = e2->castTo(sc, t); // LLVMDC: llvm uses typesafe pointer arithmetic @@ -1156,7 +1202,7 @@ Type *t = Type::tptrdiff_t; Expression *e; - stride = t2b->next->size(); + stride = t2b->nextOf()->size(loc); if (!t->equals(t1b)) e = e1->castTo(sc, t); else @@ -1327,13 +1373,17 @@ goto Lincompatible; } else if ((t1->ty == Tsarray || t1->ty == Tarray) && - e2->op == TOKnull && t2->ty == Tpointer && t2->next->ty == Tvoid) - { + e2->op == TOKnull && t2->ty == Tpointer && t2->nextOf()->ty == Tvoid) + { /* (T[n] op void*) + * (T[] op void*) + */ goto Lx1; } else if ((t2->ty == Tsarray || t2->ty == Tarray) && - e1->op == TOKnull && t1->ty == Tpointer && t1->next->ty == Tvoid) - { + e1->op == TOKnull && t1->ty == Tpointer && t1->nextOf()->ty == Tvoid) + { /* (void* op T[n]) + * (void* op T[]) + */ goto Lx2; } else if ((t1->ty == Tsarray || t1->ty == Tarray) && t1->implicitConvTo(t2)) @@ -1375,7 +1425,7 @@ /* Pick 'tightest' type */ ClassDeclaration *cd1 = tc1->sym->baseClass; - ClassDeclaration *cd2 = tc1->sym->baseClass; + ClassDeclaration *cd2 = tc2->sym->baseClass; if (cd1 && cd2) { t1 = cd1->type; @@ -1402,21 +1452,48 @@ goto Lt1; } else if (t1->ty == Tsarray && t2->ty == Tsarray && - e2->implicitConvTo(t1->next->arrayOf())) + e2->implicitConvTo(t1->nextOf()->arrayOf())) { Lx1: - t = t1->next->arrayOf(); + t = t1->nextOf()->arrayOf(); e1 = e1->castTo(sc, t); e2 = e2->castTo(sc, t); } else if (t1->ty == Tsarray && t2->ty == Tsarray && - e1->implicitConvTo(t2->next->arrayOf())) + e1->implicitConvTo(t2->nextOf()->arrayOf())) { Lx2: - t = t2->next->arrayOf(); + t = t2->nextOf()->arrayOf(); e1 = e1->castTo(sc, t); e2 = e2->castTo(sc, t); } + else if (t1->isintegral() && t2->isintegral()) + { + assert(0); + } + else if (e1->op == TOKslice && t1->ty == Tarray && + e2->implicitConvTo(t1->nextOf())) + { // T[] op T + e2 = e2->castTo(sc, t1->nextOf()); + t = t1->nextOf()->arrayOf(); + } + else if (e2->op == TOKslice && t2->ty == Tarray && + e1->implicitConvTo(t2->nextOf())) + { // T op T[] + e1 = e1->castTo(sc, t2->nextOf()); + t = t2->nextOf()->arrayOf(); + + //printf("test %s\n", e->toChars()); + e1 = e1->optimize(WANTvalue); + if (isCommutative() && e1->isConst()) + { /* Swap operands to minimize number of functions generated + */ + //printf("swap %s\n", e->toChars()); + Expression *tmp = e1; + e1 = e2; + e2 = tmp; + } + } else { Lincompatible: @@ -1446,9 +1523,10 @@ */ Expression *Expression::integralPromotions(Scope *sc) -{ Expression *e; +{ + Expression *e = this; - e = this; + //printf("integralPromotions %s %s\n", e->toChars(), e->type->toChars()); switch (type->toBasetype()->ty) { case Tvoid: diff -r 337554fd34f1 -r 6aee82889553 dmd/doc.c --- a/dmd/doc.c Thu Aug 14 03:09:26 2008 +0200 +++ b/dmd/doc.c Thu Aug 14 06:55:41 2008 +0200 @@ -775,7 +775,7 @@ { TemplateParameter *tp = (TemplateParameter *)td->origParameters->data[i]; if (i) - buf->writeByte(','); + buf->writestring(", "); tp->toCBuffer(buf, &hgs); } buf->writeByte(')'); diff -r 337554fd34f1 -r 6aee82889553 dmd/expression.c --- a/dmd/expression.c Thu Aug 14 03:09:26 2008 +0200 +++ b/dmd/expression.c Thu Aug 14 06:55:41 2008 +0200 @@ -368,6 +368,7 @@ { e->error("expression has no value"); } + } return e; } @@ -389,6 +390,26 @@ } } + +/****************************** + * Perform canThrow() on an array of Expressions. + */ + +#if DMDV2 +int arrayExpressionCanThrow(Expressions *exps) +{ + if (exps) + { + for (size_t i = 0; i < exps->dim; i++) + { Expression *e = (Expression *)exps->data[i]; + if (e && e->canThrow()) + return 1; + } + } + return 0; +} +#endif + /**************************************** * Expand tuples. */ @@ -503,10 +524,10 @@ /**************************************** * Now that we know the exact type of the function we're calling, * the arguments[] need to be adjusted: - * 1) implicitly convert argument to the corresponding parameter type - * 2) add default arguments for any missing arguments - * 3) do default promotions on arguments corresponding to ... - * 4) add hidden _arguments[] argument + * 1. implicitly convert argument to the corresponding parameter type + * 2. add default arguments for any missing arguments + * 3. do default promotions on arguments corresponding to ... + * 4. add hidden _arguments[] argument */ void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *arguments) @@ -802,6 +823,7 @@ Expression::Expression(Loc loc, enum TOK op, int size) : loc(loc) { + //printf("Expression::Expression(op = %d) this = %p\n", op, this); this->loc = loc; this->op = op; this->size = size; @@ -832,6 +854,7 @@ assert(0); } e = (Expression *)mem.malloc(size); + //printf("Expression::copy(op = %d) e = %p\n", op, e); return (Expression *)memcpy(e, this, size); } @@ -965,6 +988,8 @@ Expression *Expression::modifiableLvalue(Scope *sc, Expression *e) { + //printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type->toChars()); + // See if this expression is a modifiable lvalue (i.e. not const) return toLvalue(sc, e); } @@ -1300,7 +1325,8 @@ type = Type::tint32; } else - { type = type->semantic(loc, sc); + { if (!type->deco) + type = type->semantic(loc, sc); } return this; } @@ -1785,7 +1811,8 @@ { Expression *e; WithScopeSymbol *withsym; - // See if it was a with class + /* See if the symbol was a member of an enclosing 'with' + */ withsym = scopesym->isWithScopeSymbol(); if (withsym) { @@ -1800,7 +1827,7 @@ else { Type *t = withsym->withstate->wthis->type; if (t->ty == Tpointer) - t = t->next; + t = ((TypePointer *)t)->next; e = new TypeDotIdExp(loc, t, ident); } } @@ -2161,8 +2188,8 @@ return this; Lerr: - error("'this' is only allowed in non-static member functions, not %s", sc->parent->toChars()); - type = Type::tint32; + error("'this' is only defined in non-static member functions, not %s", sc->parent->toChars()); + type = Type::terror; return this; } @@ -2695,7 +2722,7 @@ // Convert any static arrays to dynamic arrays if (t0->ty == Tsarray) { - t0 = t0->next->arrayOf(); + t0 = ((TypeSArray *)t0)->next->arrayOf(); e = e->implicitCastTo(sc, t0); } } @@ -2906,6 +2933,8 @@ #if LOGSEMANTIC printf("StructLiteralExp::semantic('%s')\n", toChars()); #endif + if (type) + return this; // Run semantic() on each element for (size_t i = 0; i < elements->dim; i++) @@ -2986,11 +3015,17 @@ */ Expression *StructLiteralExp::getField(Type *type, unsigned offset) -{ Expression *e = NULL; +{ + //printf("StructLiteralExp::getField(this = %s, type = %s, offset = %u)\n", +// /*toChars()*/"", type->toChars(), offset); + Expression *e = NULL; int i = getFieldIndex(type, offset); if (i != -1) - { e = (Expression *)elements->data[i]; + { + //printf("\ti = %d\n", i); + assert(i < elements->dim); + e = (Expression *)elements->data[i]; if (e) { e = e->copy(); @@ -3330,7 +3365,7 @@ Dsymbol *s = cd->toParent2(); ClassDeclaration *cdn = s->isClassDeclaration(); - //printf("isNested, cdn = %s\n", cdn ? cdn->toChars() : "null"); + //printf("cd isNested, cdn = %s\n", cdn ? cdn->toChars() : "null"); if (cdn) { if (!cdthis) @@ -3485,7 +3520,7 @@ if (arg->op == TOKint64 && (long long)arg->toInteger() < 0) error("negative array index %s", arg->toChars()); arguments->data[i] = (void *) arg; - tb = tb->next->toBasetype(); + tb = ((TypeDArray *)tb)->next->toBasetype(); } } else if (tb->isscalar()) @@ -3822,6 +3857,29 @@ } +/******************************** OverExp **************************/ + +#if DMDV2 +OverExp::OverExp(OverloadSet *s) + : Expression(loc, TOKoverloadset, sizeof(OverExp)) +{ + //printf("OverExp(this = %p, '%s')\n", this, var->toChars()); + vars = s; + type = Type::tvoid; +} + +int OverExp::isLvalue() +{ + return 1; +} + +Expression *OverExp::toLvalue(Scope *sc, Expression *e) +{ + return this; +} +#endif + + /******************************** TupleExp **************************/ TupleExp::TupleExp(Loc loc, Expressions *exps) @@ -4158,6 +4216,43 @@ buf->writeByte(')'); } +/************************ TraitsExp ************************************/ +#if DMDV2 +/* + * __traits(identifier, args...) + */ + +TraitsExp::TraitsExp(Loc loc, Identifier *ident, Objects *args) + : Expression(loc, TOKtraits, sizeof(TraitsExp)) +{ + this->ident = ident; + this->args = args; +} + + +Expression *TraitsExp::syntaxCopy() +{ + return new TraitsExp(loc, ident, TemplateInstance::arraySyntaxCopy(args)); +} + + +void TraitsExp::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 = (Object *)args->data[i]; + ObjectToCBuffer(buf, hgs, oarg); + } + } + buf->writeByte(')'); +} +#endif + /************************************************************/ HaltExp::HaltExp(Loc loc) @@ -4210,7 +4305,11 @@ Expression *IsExp::semantic(Scope *sc) { Type *tded; - //printf("IsExp::semantic()\n"); + /* is(targ id tok tspec) + * is(targ id == tok2) + */ + + //printf("IsExp::semantic(%s)\n", toChars()); if (id && !(sc->flags & SCOPEstaticif)) error("can only declare type aliases within static if conditionals"); @@ -4267,6 +4366,19 @@ goto Lno; tded = targ; break; +#if DMDV2 + case TOKconst: + if (!targ->isConst()) + goto Lno; + tded = targ; + break; + + case TOKinvariant: + if (!targ->isInvariant()) + goto Lno; + tded = targ; + break; +#endif case TOKsuper: // If class or interface, get the base class and interfaces @@ -4293,11 +4405,12 @@ case TOKdelegate: if (targ->ty != Tdelegate) goto Lno; - tded = targ->next; // the underlying function type + tded = ((TypeDelegate *)targ)->next; // the underlying function type break; case TOKfunction: - { if (targ->ty != Tfunction) + { + if (targ->ty != Tfunction) goto Lno; tded = targ; @@ -4321,7 +4434,7 @@ * delegate, or pointer to function. */ if (targ->ty == Tfunction) - tded = targ->next; + tded = ((TypeFunction *)targ)->next; else if (targ->ty == Tdelegate) tded = targ->next->next; else if (targ->ty == Tpointer && targ->next->ty == Tfunction) @@ -4537,6 +4650,13 @@ if (e) return e; + if (e1->op == TOKslice) + { // T[] op= ... + typeCombine(sc); + type = e1->type; + return arrayOp(sc); + } + e1 = e1->modifiableLvalue(sc, e1); e1->checkScalar(); type = e1->type; @@ -4568,6 +4688,13 @@ if (e) return e; + if (e1->op == TOKslice) + { // T[] op= ... + typeCombine(sc); + type = e1->type; + return arrayOp(sc); + } + e1 = e1->modifiableLvalue(sc, e1); e1->checkScalar(); type = e1->type; @@ -4888,6 +5015,24 @@ eleft = NULL; eright = e1; } +#if DMDV2 + if (e1->op == TOKtuple && ident == Id::offsetof) + { /* 'distribute' the .offsetof to each of the tuple elements. + */ + TupleExp *te = (TupleExp *)e1; + Expressions *exps = new Expressions(); + exps->setDim(te->exps->dim); + for (int i = 0; i < exps->dim; i++) + { Expression *e = (Expression *)te->exps->data[i]; + e = e->semantic(sc); + e = new DotIdExp(e->loc, e, Id::offsetof); + exps->data[i] = (void *)e; + } + e = new TupleExp(loc, exps); + e = e->semantic(sc); + return e; + } +#endif if (e1->op == TOKtuple && ident == Id::length) { @@ -5048,7 +5193,7 @@ ident != Id::mangleof && ident != Id::stringof) { e = new PtrExp(loc, e1); - e->type = e1->type->next; + e->type = ((TypePointer *)e1->type)->next; return e->type->dotExp(sc, e, ident); } else @@ -5176,7 +5321,11 @@ Expression *DotVarExp::modifiableLvalue(Scope *sc, Expression *e) { - //printf("DotVarExp::modifiableLvalue(%s)\n", toChars()); +#if 0 + printf("DotVarExp::modifiableLvalue(%s)\n", toChars()); + printf("e1->type = %s\n", e1->type->toChars()); + printf("var->type = %s\n", var->type->toChars()); +#endif if (var->isCtorinit()) { // It's only modifiable if inside the right constructor @@ -5265,6 +5414,12 @@ if (t1) t1 = t1->toBasetype(); //t1->print(); + + /* Extract the following from e1: + * s: the symbol which ti should be a member of + * eleft: if not NULL, it is the 'this' pointer for ti + */ + if (e1->op == TOKdotexp) { DotExp *de = (DotExp *)e1; eleft = de->e1; @@ -5295,7 +5450,7 @@ } else if (t1 && t1->ty == Tpointer) { - t1 = t1->next->toBasetype(); + t1 = ((TypePointer *)t1)->next->toBasetype(); if (t1->ty != Tstruct) goto L1; s = t1->toDsymbol(sc); @@ -5471,6 +5626,7 @@ int i; Type *t1; int istemp; + Objects *targsi = NULL; // initial list of template arguments #if LOGSEMANTIC printf("CallExp::semantic() %s\n", toChars()); @@ -5534,8 +5690,66 @@ } } +#if DMDV2 + /* This recognizes: + * foo!(tiargs)(funcargs) + */ + if (e1->op == TOKimport && !e1->type) + { ScopeExp *se = (ScopeExp *)e1; + TemplateInstance *ti = se->sds->isTemplateInstance(); + if (ti && !ti->semanticdone) + { + /* Attempt to instantiate ti. If that works, go with it. + * If not, go with partial explicit specialization. + */ + ti->semanticTiargs(sc); + unsigned errors = global.errors; + global.gag++; + ti->semantic(sc); + global.gag--; + if (errors != global.errors) + { + /* Didn't work, go with partial explicit specialization + */ + global.errors = errors; + targsi = ti->tiargs; + e1 = new IdentifierExp(loc, ti->name); + } + } + } + + /* This recognizes: + * expr.foo!(tiargs)(funcargs) + */ + if (e1->op == TOKdotti && !e1->type) + { DotTemplateInstanceExp *se = (DotTemplateInstanceExp *)e1; + TemplateInstance *ti = se->ti; + if (!ti->semanticdone) + { + /* Attempt to instantiate ti. If that works, go with it. + * If not, go with partial explicit specialization. + */ + ti->semanticTiargs(sc); + Expression *etmp; + unsigned errors = global.errors; + global.gag++; + etmp = e1->semantic(sc); + global.gag--; + if (errors != global.errors) + { + global.errors = errors; + targsi = ti->tiargs; + e1 = new DotIdExp(loc, se->e1, ti->name); + } + else + e1 = etmp; + } + } +#endif + istemp = 0; Lagain: + //printf("Lagain: %s\n", toChars()); f = NULL; if (e1->op == TOKthis || e1->op == TOKsuper) { @@ -5804,16 +6018,16 @@ else if (t1->ty != Tfunction) { if (t1->ty == Tdelegate) - { - assert(t1->next->ty == Tfunction); - tf = (TypeFunction *)(t1->next); + { TypeDelegate *td = (TypeDelegate *)t1; + assert(td->next->ty == Tfunction); + tf = (TypeFunction *)(td->next); goto Lcheckargs; } - else if (t1->ty == Tpointer && t1->next->ty == Tfunction) + else if (t1->ty == Tpointer && ((TypePointer *)t1)->next->ty == Tfunction) { Expression *e; e = new PtrExp(loc, e1); - t1 = t1->next; + t1 = ((TypePointer *)t1)->next; e->type = t1; e1 = e; } @@ -5909,10 +6123,11 @@ { Type *t = type; int offset = 0; - - if (f->tintro->next->isBaseOf(t, &offset) && offset) - { - type = f->tintro->next; + TypeFunction *tf = (TypeFunction *)f->tintro; + + if (tf->next->isBaseOf(t, &offset) && offset) + { + type = tf->next; return castTo(sc, t); } } @@ -5974,9 +6189,7 @@ FuncDeclaration *f = dve->var->isFuncDeclaration(); if (f) - { Expression *e; - - e = new DelegateExp(loc, dve->e1, f); + { Expression *e = new DelegateExp(loc, dve->e1, f); e = e->semantic(sc); return e; } @@ -6018,7 +6231,7 @@ : UnaExp(loc, TOKstar, sizeof(PtrExp), e) { if (e->type) - type = e->type->next; + type = ((TypePointer *)e->type)->next; } PtrExp::PtrExp(Loc loc, Expression *e, Type *t) @@ -6108,7 +6321,8 @@ return e; e1->checkNoBool(); - e1->checkArithmetic(); + if (e1->op != TOKslice) + e1->checkArithmetic(); type = e1->type; } return this; @@ -6157,7 +6371,8 @@ return e; e1->checkNoBool(); - e1 = e1->checkIntegral(); + if (e1->op != TOKslice) + e1 = e1->checkIntegral(); type = e1->type; } return this; @@ -6238,7 +6453,7 @@ break; } case Tpointer: - tb = tb->next->toBasetype(); + tb = ((TypePointer *)tb)->next->toBasetype(); if (tb->ty == Tstruct) { TypeStruct *ts = (TypeStruct *)tb; @@ -6569,7 +6784,7 @@ return e; } - type = t->next->arrayOf(); + type = t->nextOf()->arrayOf(); return e; Lerror: @@ -6878,7 +7093,7 @@ index, length); } #endif - e->type = t1->next; + e->type = t1->nextOf(); break; } @@ -7199,6 +7414,20 @@ { e2 = e2->implicitCastTo(sc, e1->type); } + + /* Look for array operations + */ + if (e1->op == TOKslice && !ismemset && + (e2->op == TOKadd || e2->op == TOKmin || + e2->op == TOKmul || e2->op == TOKdiv || + e2->op == TOKmod || e2->op == TOKxor || + e2->op == TOKand || e2->op == TOKor || + e2->op == TOKtilde || e2->op == TOKneg)) + { + type = e1->type; + return arrayOp(sc); + } + type = e1->type; assert(type); return this; @@ -7234,14 +7463,23 @@ if (e) return e; - e1 = e1->modifiableLvalue(sc, e1); - Type *tb1 = e1->type->toBasetype(); Type *tb2 = e2->type->toBasetype(); + if (e1->op == TOKslice) + { + typeCombine(sc); + type = e1->type; + return arrayOp(sc); + } + else + { + e1 = e1->modifiableLvalue(sc, e1); + } + if ((tb1->ty == Tarray || tb1->ty == Tsarray) && (tb2->ty == Tarray || tb2->ty == Tsarray) && - tb1->next->equals(tb2->next) + tb1->nextOf()->equals(tb2->nextOf()) ) { type = e1->type; @@ -7263,11 +7501,7 @@ Expression *ea; Expression *ex; - char name[6+6+1]; - Identifier *id; - static int idn; - sprintf(name, "__name%d", ++idn); - id = Lexer::idPool(name); + Identifier *id = Lexer::uniqueId("__name"); v = new VarDeclaration(loc, tb1->pointerTo(), id, NULL); v->semantic(sc); @@ -7334,6 +7568,13 @@ if (e) return e; + if (e1->op == TOKslice) + { // T[] -= ... + typeCombine(sc); + type = e1->type; + return arrayOp(sc); + } + e1 = e1->modifiableLvalue(sc, e1); e1->checkScalar(); e1->checkNoBool(); @@ -7397,10 +7638,10 @@ e = this; } else if ((tb1->ty == Tarray) && - e2->implicitConvTo(tb1->next) + e2->implicitConvTo(tb1->nextOf()) ) { // Append element - e2 = e2->castTo(sc, tb1->next); + e2 = e2->castTo(sc, tb1->nextOf()); type = e1->type; e = this; } @@ -7430,6 +7671,13 @@ if (e) return e; + if (e1->op == TOKslice) + { // T[] -= ... + typeCombine(sc); + type = e1->type; + return arrayOp(sc); + } + e1 = e1->modifiableLvalue(sc, e1); e1->checkScalar(); e1->checkNoBool(); @@ -7486,6 +7734,13 @@ if (e) return e; + if (e1->op == TOKslice) + { // T[] -= ... + typeCombine(sc); + type = e1->type; + return arrayOp(sc); + } + e1 = e1->modifiableLvalue(sc, e1); e1->checkScalar(); e1->checkNoBool(); @@ -7690,7 +7945,7 @@ if ((tb1->ty == Tarray || tb1->ty == Tsarray) && (tb2->ty == Tarray || tb2->ty == Tsarray) && - tb1->next->equals(tb2->next) + tb1->nextOf()->equals(tb2->nextOf()) ) { type = e1->type; @@ -7776,17 +8031,22 @@ typeCombine(sc); // make sure pointer types are compatible type = Type::tptrdiff_t; - stride = t2->next->size(); - if (!stride) - return new IntegerExp(0, 0, Type::tptrdiff_t); - e = new DivExp(loc, this, new IntegerExp(0, stride, Type::tptrdiff_t)); - e->type = Type::tptrdiff_t; + stride = t2->nextOf()->size(); + if (stride == 0) + { + e = new IntegerExp(loc, 0, Type::tptrdiff_t); + } + else + { + e = new DivExp(loc, this, new IntegerExp(0, stride, Type::tptrdiff_t)); + e->type = Type::tptrdiff_t; + } return e; } else if (t2->isintegral()) e = scaleFactor(sc); else - { error("incompatible types for -"); + { error("incompatible types for minus"); return new IntegerExp(0); } } @@ -7864,7 +8124,7 @@ if ((tb1->ty == Tsarray || tb1->ty == Tarray) && e2->type->equals(tb1->next)) { - type = tb1->next->arrayOf(); + type = tb1->nextOf()->arrayOf(); if (tb2->ty == Tarray) { // Make e2 into [e2] e2 = new ArrayLiteralExp(e2->loc, e2); @@ -7875,7 +8135,7 @@ else if ((tb2->ty == Tsarray || tb2->ty == Tarray) && e1->type->equals(tb2->next)) { - type = tb2->next->arrayOf(); + type = tb2->nextOf()->arrayOf(); if (tb1->ty == Tarray) { // Make e1 into [e1] e1 = new ArrayLiteralExp(e1->loc, e1); @@ -7904,6 +8164,7 @@ } else { + //printf("(%s) ~ (%s)\n", e1->toChars(), e2->toChars()); error("Can only concatenate arrays, not (%s ~ %s)", e1->type->toChars(), e2->type->toChars()); type = Type::tint32; @@ -7939,8 +8200,10 @@ return e; typeCombine(sc); - e1->checkArithmetic(); - e2->checkArithmetic(); + if (e1->op != TOKslice && e2->op != TOKslice) + { e1->checkArithmetic(); + e2->checkArithmetic(); + } if (type->isfloating()) { Type *t1 = e1->type; Type *t2 = e2->type; @@ -8003,8 +8266,10 @@ return e; typeCombine(sc); - e1->checkArithmetic(); - e2->checkArithmetic(); + if (e1->op != TOKslice && e2->op != TOKslice) + { e1->checkArithmetic(); + e2->checkArithmetic(); + } if (type->isfloating()) { Type *t1 = e1->type; Type *t2 = e2->type; @@ -8068,8 +8333,10 @@ return e; typeCombine(sc); - e1->checkArithmetic(); - e2->checkArithmetic(); + if (e1->op != TOKslice && e2->op != TOKslice) + { e1->checkArithmetic(); + e2->checkArithmetic(); + } if (type->isfloating()) { type = e1->type; if (e2->type->iscomplex()) @@ -8180,8 +8447,10 @@ else { typeCombine(sc); - e1->checkIntegral(); - e2->checkIntegral(); + if (e1->op != TOKslice && e2->op != TOKslice) + { e1->checkIntegral(); + e2->checkIntegral(); + } } } return this; @@ -8211,8 +8480,10 @@ else { typeCombine(sc); - e1->checkIntegral(); - e2->checkIntegral(); + if (e1->op != TOKslice && e2->op != TOKslice) + { e1->checkIntegral(); + e2->checkIntegral(); + } } } return this; @@ -8242,8 +8513,10 @@ else { typeCombine(sc); - e1->checkIntegral(); - e2->checkIntegral(); + if (e1->op != TOKslice && e2->op != TOKslice) + { e1->checkIntegral(); + e2->checkIntegral(); + } } } return this; @@ -8414,7 +8687,7 @@ e1 = e1->implicitCastTo(sc, ta->index); // Return type is pointer to value - type = ta->next->pointerTo(); + type = ta->nextOf()->pointerTo(); } return this; } @@ -8501,6 +8774,7 @@ #endif else e = this; + //printf("CmpExp: %s\n", e->toChars()); return e; } diff -r 337554fd34f1 -r 6aee82889553 dmd/expression.h --- a/dmd/expression.h Thu Aug 14 03:09:26 2008 +0200 +++ b/dmd/expression.h Thu Aug 14 06:55:41 2008 +0200 @@ -43,7 +43,7 @@ struct BinExp; struct InterState; struct Symbol; // back end symbol - +struct OverloadSet; namespace llvm { class Constant; @@ -151,6 +151,10 @@ virtual Identifier *opId(); virtual Identifier *opId_r(); + // For array ops + virtual void buildArrayIdent(OutBuffer *buf, Expressions *arguments); + virtual Expression *buildArrayLoop(Arguments *fparams); + // Back end virtual elem *toElem(IRState *irs); virtual dt_t **toDt(dt_t **pdt); @@ -594,6 +598,19 @@ virtual llvm::Constant *toConstElem(IRState *irs); }; +#if DMDV2 +// Overload Set + +struct OverExp : Expression +{ + OverloadSet *vars; + + OverExp(OverloadSet *s); + int isLvalue(); + Expression *toLvalue(Scope *sc, Expression *e); +}; +#endif + // Function/Delegate literal struct FuncExp : Expression @@ -643,6 +660,19 @@ void toCBuffer(OutBuffer *buf, HdrGenState *hgs); }; +#if DMDV2 +struct TraitsExp : Expression +{ + Identifier *ident; + Objects *args; + + TraitsExp(Loc loc, Identifier *ident, Objects *args); + Expression *syntaxCopy(); + Expression *semantic(Scope *sc); + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); +}; +#endif + struct HaltExp : Expression { HaltExp(Loc loc); @@ -715,6 +745,7 @@ Expression *interpretCommon(InterState *istate, Expression *(*fp)(Type *, Expression *, Expression *)); Expression *interpretCommon2(InterState *istate, Expression *(*fp)(TOK, Type *, Expression *, Expression *)); Expression *interpretAssignCommon(InterState *istate, Expression *(*fp)(Type *, Expression *, Expression *), int post = 0); + Expression *arrayOp(Scope *sc); int inlineCost(InlineCostState *ics); Expression *doInline(InlineDoState *ids); @@ -887,6 +918,8 @@ Expression *semantic(Scope *sc); Expression *optimize(int result); Expression *interpret(InterState *istate); + void buildArrayIdent(OutBuffer *buf, Expressions *arguments); + Expression *buildArrayLoop(Arguments *fparams); // For operator overloading Identifier *opId(); @@ -909,6 +942,8 @@ Expression *semantic(Scope *sc); Expression *optimize(int result); Expression *interpret(InterState *istate); + void buildArrayIdent(OutBuffer *buf, Expressions *arguments); + Expression *buildArrayLoop(Arguments *fparams); // For operator overloading Identifier *opId(); @@ -984,6 +1019,8 @@ void dump(int indent); elem *toElem(IRState *irs); void scanForNestedRef(Scope *sc); + void buildArrayIdent(OutBuffer *buf, Expressions *arguments); + Expression *buildArrayLoop(Arguments *fparams); int inlineCost(InlineCostState *ics); Expression *doInline(InlineDoState *ids); @@ -1081,6 +1118,8 @@ Expression *checkToBoolean(); Expression *interpret(InterState *istate); Identifier *opId(); // For operator overloading + void buildArrayIdent(OutBuffer *buf, Expressions *arguments); + Expression *buildArrayLoop(Arguments *fparams); elem *toElem(IRState *irs); }; @@ -1090,25 +1129,33 @@ op##AssignExp(Loc loc, Expression *e1, Expression *e2); \ Expression *semantic(Scope *sc); \ Expression *interpret(InterState *istate); \ + X(void buildArrayIdent(OutBuffer *buf, Expressions *arguments);) \ + X(Expression *buildArrayLoop(Arguments *fparams);) \ \ Identifier *opId(); /* For operator overloading */ \ \ elem *toElem(IRState *irs); \ }; +#define X(a) a ASSIGNEXP(Add) ASSIGNEXP(Min) -ASSIGNEXP(Cat) ASSIGNEXP(Mul) ASSIGNEXP(Div) ASSIGNEXP(Mod) +ASSIGNEXP(And) +ASSIGNEXP(Or) +ASSIGNEXP(Xor) +#undef X + +#define X(a) + ASSIGNEXP(Shl) ASSIGNEXP(Shr) ASSIGNEXP(Ushr) -ASSIGNEXP(And) -ASSIGNEXP(Or) -ASSIGNEXP(Xor) +ASSIGNEXP(Cat) +#undef X #undef ASSIGNEXP struct AddExp : BinExp @@ -1117,6 +1164,8 @@ Expression *semantic(Scope *sc); Expression *optimize(int result); Expression *interpret(InterState *istate); + void buildArrayIdent(OutBuffer *buf, Expressions *arguments); + Expression *buildArrayLoop(Arguments *fparams); // For operator overloading int isCommutative(); @@ -1135,6 +1184,8 @@ Expression *semantic(Scope *sc); Expression *optimize(int result); Expression *interpret(InterState *istate); + void buildArrayIdent(OutBuffer *buf, Expressions *arguments); + Expression *buildArrayLoop(Arguments *fparams); // For operator overloading Identifier *opId(); @@ -1163,6 +1214,8 @@ Expression *semantic(Scope *sc); Expression *optimize(int result); Expression *interpret(InterState *istate); + void buildArrayIdent(OutBuffer *buf, Expressions *arguments); + Expression *buildArrayLoop(Arguments *fparams); // For operator overloading int isCommutative(); @@ -1178,6 +1231,8 @@ Expression *semantic(Scope *sc); Expression *optimize(int result); Expression *interpret(InterState *istate); + void buildArrayIdent(OutBuffer *buf, Expressions *arguments); + Expression *buildArrayLoop(Arguments *fparams); // For operator overloading Identifier *opId(); @@ -1192,6 +1247,8 @@ Expression *semantic(Scope *sc); Expression *optimize(int result); Expression *interpret(InterState *istate); + void buildArrayIdent(OutBuffer *buf, Expressions *arguments); + Expression *buildArrayLoop(Arguments *fparams); // For operator overloading Identifier *opId(); @@ -1248,6 +1305,8 @@ Expression *semantic(Scope *sc); Expression *optimize(int result); Expression *interpret(InterState *istate); + void buildArrayIdent(OutBuffer *buf, Expressions *arguments); + Expression *buildArrayLoop(Arguments *fparams); // For operator overloading int isCommutative(); @@ -1263,6 +1322,8 @@ Expression *semantic(Scope *sc); Expression *optimize(int result); Expression *interpret(InterState *istate); + void buildArrayIdent(OutBuffer *buf, Expressions *arguments); + Expression *buildArrayLoop(Arguments *fparams); // For operator overloading int isCommutative(); @@ -1278,6 +1339,8 @@ Expression *semantic(Scope *sc); Expression *optimize(int result); Expression *interpret(InterState *istate); + void buildArrayIdent(OutBuffer *buf, Expressions *arguments); + Expression *buildArrayLoop(Arguments *fparams); // For operator overloading int isCommutative(); @@ -1402,6 +1465,32 @@ elem *toElem(IRState *irs); }; +#if DMDV2 +/****************************************************************/ + +struct DefaultInitExp : Expression +{ + enum TOK subop; // which of the derived classes this is + + DefaultInitExp(Loc loc, enum TOK subop, int size); + virtual Expression *resolve(Loc loc, Scope *sc) = 0; + void toCBuffer(OutBuffer *buf, HdrGenState *hgs); +}; + +struct FileInitExp : DefaultInitExp +{ + FileInitExp(Loc loc); + Expression *semantic(Scope *sc); + Expression *resolve(Loc loc, Scope *sc); +}; + +struct LineInitExp : DefaultInitExp +{ + LineInitExp(Loc loc); + Expression *semantic(Scope *sc); + Expression *resolve(Loc loc, Scope *sc); +}; +#endif /****************************************************************/ diff -r 337554fd34f1 -r 6aee82889553 dmd/func.c --- a/dmd/func.c Thu Aug 14 03:09:26 2008 +0200 +++ b/dmd/func.c Thu Aug 14 06:55:41 2008 +0200 @@ -68,6 +68,9 @@ fes = NULL; introducing = 0; tintro = NULL; + /* The type given for "infer the return type" is a TypeFunction with + * NULL for the return type. + */ inferRetType = (type && type->nextOf() == NULL); scope = NULL; hasReturnExp = 0; @@ -112,7 +115,7 @@ if (isFuncLiteralDeclaration()) printf("\tFuncLiteralDeclaration()\n"); printf("sc->parent = %s\n", sc->parent->toChars()); - printf("type: %s\n", type->toChars()); + printf("type: %p, %s\n", type, type->toChars()); #endif if (type->nextOf()) @@ -281,8 +284,11 @@ vi = findVtblIndex(&cd->vtbl, cd->baseClass ? cd->baseClass->vtbl.dim : 0); switch (vi) { - case -1: // didn't find one - // This is an 'introducing' function. + case -1: + /* Didn't find one, so + * This is an 'introducing' function which gets a new + * slot in the vtbl[]. + */ // Verify this doesn't override previous final function if (cd->baseClass) @@ -632,9 +638,8 @@ // Check the 'throws' clause if (fthrows) - { int i; - - for (i = 0; i < fthrows->dim; i++) + { + for (int i = 0; i < fthrows->dim; i++) { Type *t = (Type *)fthrows->data[i]; @@ -696,9 +701,11 @@ } else if (isNested()) { - VarDeclaration *v; - - v = new ThisDeclaration(Type::tvoid->pointerTo()); + /* The 'this' for a nested function is the link to the + * enclosing function's stack frame. + * Note that nested functions and member functions are disjoint. + */ + VarDeclaration *v = new ThisDeclaration(Type::tvoid->pointerTo()); v->storage_class |= STCparameter | STCin; v->semantic(sc2); if (!sc2->insert(v)) @@ -781,11 +788,7 @@ /* Generate identifier for un-named parameter, * because we need it later on. */ - OutBuffer buf; - buf.printf("_param_%"PRIuSIZE, i); - char *name = (char *)buf.extractData(); - id = new Identifier(name, TOKidentifier); - arg->ident = id; + arg->ident = id = Identifier::generateId("_param_", i); } VarDeclaration *v = new VarDeclaration(loc, arg->type, id, NULL); //printf("declaring parameter %s of type %s\n", v->toChars(), v->type->toChars()); @@ -824,11 +827,11 @@ assert(narg->ident); VarDeclaration *v = sc2->search(0, narg->ident, NULL)->isVarDeclaration(); assert(v); - Expression *e = new VarExp(0, v); + Expression *e = new VarExp(v->loc, v); exps->data[j] = (void *)e; } assert(arg->ident); - TupleDeclaration *v = new TupleDeclaration(0, arg->ident, exps); + TupleDeclaration *v = new TupleDeclaration(loc, arg->ident, exps); //printf("declaring tuple %s\n", v->toChars()); v->isexp = 1; if (!sc2->insert(v)) @@ -1569,10 +1572,8 @@ if (f != m->lastf) // skip duplicates { - TypeFunction *tf; - m->anyf = f; - tf = (TypeFunction *)f->type; + TypeFunction *tf = (TypeFunction *)f->type; match = (MATCH) tf->callMatch(arguments); //printf("match = %d\n", match); if (match != MATCHnomatch) @@ -1910,8 +1911,16 @@ int FuncDeclaration::isWinMain() { + //printf("FuncDeclaration::isWinMain() %s\n", toChars()); +#if 0 + int x = ident == Id::WinMain && + linkage != LINKc && !isMember(); + printf("%s\n", x ? "yes" : "no"); + return x; +#else return ident == Id::WinMain && linkage != LINKc && !isMember(); +#endif } int FuncDeclaration::isDllMain() @@ -2090,7 +2099,7 @@ goto Lyes; // assume f escapes this function's scope // Look to see if any parents of f that are below this escape - for (Dsymbol *s = f->parent; s != this; s = s->parent) + for (Dsymbol *s = f->parent; s && s != this; s = s->parent) { f = s->isFuncDeclaration(); if (f && (f->isThis() || f->tookAddressOf)) @@ -2196,7 +2205,7 @@ { this->arguments = arguments; this->varargs = varargs; - //printf("CtorDeclaration() %s\n", toChars()); + //printf("CtorDeclaration(loc = %s) %s\n", loc.toChars(), toChars()); } Dsymbol *CtorDeclaration::syntaxCopy(Dsymbol *s) diff -r 337554fd34f1 -r 6aee82889553 dmd/identifier.c --- a/dmd/identifier.c Thu Aug 14 03:09:26 2008 +0200 +++ b/dmd/identifier.c Thu Aug 14 06:55:41 2008 +0200 @@ -81,15 +81,21 @@ return DYNCAST_IDENTIFIER; } -Identifier *Identifier::generateId(char *prefix) + +Identifier *Identifier::generateId(const char *prefix) +{ + static size_t i; + + return generateId(prefix, ++i); +} + +Identifier *Identifier::generateId(const char *prefix, size_t i) { OutBuffer buf; - char *id; - static unsigned i; buf.writestring(prefix); - buf.printf("%u", ++i); + buf.printf("%zu", i); - id = buf.toChars(); + char *id = buf.toChars(); buf.data = NULL; - return new Identifier(id, TOKidentifier); + return Lexer::idPool(id); } diff -r 337554fd34f1 -r 6aee82889553 dmd/identifier.h --- a/dmd/identifier.h Thu Aug 14 03:09:26 2008 +0200 +++ b/dmd/identifier.h Thu Aug 14 06:55:41 2008 +0200 @@ -1,46 +1,47 @@ - -// Compiler implementation of the D programming language -// Copyright (c) 1999-2006 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// http://www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#ifndef DMD_IDENTIFIER_H -#define DMD_IDENTIFIER_H - -#ifdef __DMC__ -#pragma once -#endif /* __DMC__ */ - -#include "root.h" - -namespace llvm -{ - class Value; -} - -struct Identifier : Object -{ - int value; - const char *string; - unsigned len; - - Identifier(const char *string, int value); - int equals(Object *o); - hash_t hashCode(); - int compare(Object *o); - void print(); - char *toChars(); -#ifdef _DH - char *toHChars(); -#endif - char *toHChars2(); - int dyncast(); - - static Identifier *generateId(char *prefix); -}; - -#endif /* DMD_IDENTIFIER_H */ + +// Compiler implementation of the D programming language +// Copyright (c) 1999-2006 by Digital Mars +// All Rights Reserved +// written by Walter Bright +// http://www.digitalmars.com +// License for redistribution is by either the Artistic License +// in artistic.txt, or the GNU General Public License in gnu.txt. +// See the included readme.txt for details. + +#ifndef DMD_IDENTIFIER_H +#define DMD_IDENTIFIER_H + +#ifdef __DMC__ +#pragma once +#endif /* __DMC__ */ + +#include "root.h" + +namespace llvm +{ + class Value; +} + +struct Identifier : Object +{ + int value; + const char *string; + unsigned len; + + Identifier(const char *string, int value); + int equals(Object *o); + hash_t hashCode(); + int compare(Object *o); + void print(); + char *toChars(); +#ifdef _DH + char *toHChars(); +#endif + char *toHChars2(); + int dyncast(); + + static Identifier *generateId(const char *prefix); + static Identifier *generateId(const char *prefix, size_t i); +}; + +#endif /* DMD_IDENTIFIER_H */ diff -r 337554fd34f1 -r 6aee82889553 dmd/mars.c --- a/dmd/mars.c Thu Aug 14 03:09:26 2008 +0200 +++ b/dmd/mars.c Thu Aug 14 06:55:41 2008 +0200 @@ -865,6 +865,7 @@ #endif if (stricmp(ext, global.mars_ext) == 0 || + stricmp(ext, global.hdr_ext) == 0 || stricmp(ext, "htm") == 0 || stricmp(ext, "html") == 0 || stricmp(ext, "xhtml") == 0) diff -r 337554fd34f1 -r 6aee82889553 dmd/module.c --- a/dmd/module.c Thu Aug 14 03:09:26 2008 +0200 +++ b/dmd/module.c Thu Aug 14 06:55:41 2008 +0200 @@ -112,6 +112,7 @@ srcfilename = FileName::defaultExt(filename, global.mars_ext); if (!srcfilename->equalsExt(global.mars_ext) && + !srcfilename->equalsExt(global.hdr_ext) && !srcfilename->equalsExt("dd")) { if (srcfilename->equalsExt("html") || diff -r 337554fd34f1 -r 6aee82889553 dmd/statement.c --- a/dmd/statement.c Thu Aug 14 03:09:26 2008 +0200 +++ b/dmd/statement.c Thu Aug 14 06:55:41 2008 +0200 @@ -1968,8 +1968,10 @@ if (arg->type) arg->type->toCBuffer(buf, arg->ident, hgs); else + { buf->writestring("auto "); buf->writestring(arg->ident->toChars()); - buf->writebyte(';'); + } + buf->writestring(" = "); } condition->toCBuffer(buf, hgs); buf->writebyte(')'); @@ -2041,6 +2043,14 @@ return (ifbody && ifbody->usesEH()) || (elsebody && elsebody->usesEH()); } +int ConditionalStatement::blockExit() +{ + int result = ifbody->blockExit(); + if (elsebody) + result |= elsebody->blockExit(); + return result; +} + void ConditionalStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { condition->toCBuffer(buf, hgs); diff -r 337554fd34f1 -r 6aee82889553 dmd/statement.h --- a/dmd/statement.h Thu Aug 14 03:09:26 2008 +0200 +++ b/dmd/statement.h Thu Aug 14 06:55:41 2008 +0200 @@ -461,6 +461,7 @@ Statement *semantic(Scope *sc); Statements *flatten(Scope *sc); int usesEH(); + int blockExit(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); }; diff -r 337554fd34f1 -r 6aee82889553 llvmdc.kdevelop.filelist --- a/llvmdc.kdevelop.filelist Thu Aug 14 03:09:26 2008 +0200 +++ b/llvmdc.kdevelop.filelist Thu Aug 14 06:55:41 2008 +0200 @@ -3,6 +3,7 @@ dmd/access.c dmd/aggregate.h dmd/array.c +dmd/arrayop.c dmd/arraytypes.h dmd/attrib.c dmd/attrib.h