diff -uNr dmd-0.169/dmd/src/dmd/attrib.c dmd-0.170/dmd/src/dmd/attrib.c --- dmd-0.169/dmd/src/dmd/attrib.c 2006-07-14 16:16:34.000000000 +0200 +++ dmd-0.170/dmd/src/dmd/attrib.c 2006-10-16 01:11:34.000000000 +0200 @@ -1,4 +1,5 @@ +// Compiler implementation of the D programming language // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright @@ -26,6 +27,7 @@ #include "expression.h" #include "dsymbol.h" #include "aggregate.h" +#include "module.h" extern void obj_includelib(char *name); diff -uNr dmd-0.169/dmd/src/dmd/cast.c dmd-0.170/dmd/src/dmd/cast.c --- dmd-0.169/dmd/src/dmd/cast.c 2006-09-20 22:10:44.000000000 +0200 +++ dmd-0.170/dmd/src/dmd/cast.c 2006-10-16 23:15:30.000000000 +0200 @@ -314,7 +314,7 @@ if (t->ty == Tpointer || t->ty == Tarray || t->ty == Taarray || t->ty == Tclass || t->ty == Tdelegate) - return MATCHconvert; + return committed ? MATCHconvert : MATCHexact; } return Expression::implicitConvTo(t); } @@ -570,6 +570,7 @@ Type *tb; //printf("NullExp::castTo(t = %p)\n", t); + committed = 1; e = this; tb = t->toBasetype(); type = type->toBasetype(); @@ -886,6 +887,10 @@ type = t; return this; } + if (tb->ty == Tpointer && typeb->ty == Tsarray) + { + type = typeb->next->pointerTo(); + } L1: return Expression::castTo(sc, t); } diff -uNr dmd-0.169/dmd/src/dmd/class.c dmd-0.170/dmd/src/dmd/class.c --- dmd-0.169/dmd/src/dmd/class.c 2006-10-07 19:05:22.000000000 +0200 +++ dmd-0.170/dmd/src/dmd/class.c 2006-10-15 20:04:58.000000000 +0200 @@ -418,8 +418,14 @@ if (cd) t = cd->type; else if (fd) - { t = new TypePointer(Type::tvoid); - t = t->semantic(0, sc); + { AggregateDeclaration *ad = fd->isMember2(); + if (ad) + t = ad->handle; + else + { + t = new TypePointer(Type::tvoid); + t = t->semantic(0, sc); + } } else assert(0); @@ -886,7 +892,7 @@ tc = NULL; if (!tc || !tc->sym->isInterfaceDeclaration()) { - //error("base type must be interface, not %s", b->type->toChars()); + error("base type must be interface, not %s", b->type->toChars()); baseclasses.remove(i); continue; } diff -uNr dmd-0.169/dmd/src/dmd/delegatize.c dmd-0.170/dmd/src/dmd/delegatize.c --- dmd-0.169/dmd/src/dmd/delegatize.c 2006-09-10 13:06:00.000000000 +0200 +++ dmd-0.170/dmd/src/dmd/delegatize.c 2006-10-16 01:14:00.000000000 +0200 @@ -1,4 +1,5 @@ +// Compiler implementation of the D programming language // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright @@ -12,10 +13,12 @@ #include "mars.h" #include "expression.h" +#include "statement.h" #include "mtype.h" #include "utf.h" #include "declaration.h" #include "aggregate.h" +#include "scope.h" /******************************************** * Convert from expression to delegate that returns the expression, diff -uNr dmd-0.169/dmd/src/dmd/dsymbol.c dmd-0.170/dmd/src/dmd/dsymbol.c --- dmd-0.169/dmd/src/dmd/dsymbol.c 2006-10-05 17:00:58.000000000 +0200 +++ dmd-0.170/dmd/src/dmd/dsymbol.c 2006-10-16 01:08:16.000000000 +0200 @@ -26,6 +26,7 @@ #include "id.h" #include "scope.h" #include "init.h" +#include "import.h" /****************************** Dsymbol ******************************/ diff -uNr dmd-0.169/dmd/src/dmd/expression.c dmd-0.170/dmd/src/dmd/expression.c --- dmd-0.169/dmd/src/dmd/expression.c 2006-10-07 15:38:06.000000000 +0200 +++ dmd-0.170/dmd/src/dmd/expression.c 2006-10-16 23:14:00.000000000 +0200 @@ -265,6 +265,11 @@ e = e->semantic(sc); } } + + else if (e->op == TOKdotexp) + { + e->error("expression has no value"); + } } return e; } @@ -769,7 +774,6 @@ else if (!loc.filename) loc = e->loc; error("%s is not an lvalue", e->toChars()); -*(char*)0=0; return this; } @@ -1915,6 +1919,7 @@ NullExp::NullExp(Loc loc) : Expression(loc, TOKnull, sizeof(NullExp)) { + committed = 0; } Expression *NullExp::semantic(Scope *sc) @@ -3708,8 +3713,6 @@ UnaExp::semantic(sc); - e1 = resolveProperties(sc, e1); - if (e1->op == TOKdotexp) { DotExp *de = (DotExp *)e1; @@ -3718,6 +3721,7 @@ } else { + e1 = resolveProperties(sc, e1); eleft = NULL; eright = e1; } @@ -3961,6 +3965,9 @@ goto L1; } +#ifdef DEBUG + printf("2: "); +#endif error("this for %s needs to be type %s not type %s", var->toChars(), ad->toChars(), t->toChars()); } @@ -4192,6 +4199,9 @@ e1 = e1->semantic(sc); goto L10; } +#ifdef DEBUG + printf("3: "); +#endif error("this for %s needs to be type %s not type %s", func->toChars(), ad->toChars(), t->toChars()); } @@ -4299,6 +4309,13 @@ } #endif + if (e1->op == TOKdelegate) + { DelegateExp *de = (DelegateExp *)e1; + + e1 = new DotVarExp(de->loc, de->e1, de->func); + return semantic(sc); + } + /* Transform: * array.id(args) into id(array,args) * aa.remove(arg) into delete aa[arg] @@ -4470,6 +4487,9 @@ ue->e1 = ue->e1->semantic(sc); goto L10; } +#ifdef DEBUG + printf("1: "); +#endif error("this for %s needs to be type %s not type %s", f->toChars(), ad->toChars(), t->toChars()); } @@ -5382,6 +5402,7 @@ { #if LOGSEMANTIC printf("DotExp::semantic('%s')\n", toChars()); + if (type) printf("\ttype = %s\n", type->toChars()); #endif e1 = e1->semantic(sc); e2 = e2->semantic(sc); diff -uNr dmd-0.169/dmd/src/dmd/expression.h dmd-0.170/dmd/src/dmd/expression.h --- dmd-0.169/dmd/src/dmd/expression.h 2006-10-05 17:01:12.000000000 +0200 +++ dmd-0.170/dmd/src/dmd/expression.h 2006-10-16 23:14:00.000000000 +0200 @@ -40,6 +40,8 @@ struct HdrGenState; struct BinExp; +enum TOK; + // Back end struct IRState; struct dt_t; @@ -55,7 +57,7 @@ Expression *resolveProperties(Scope *sc, Expression *e); void accessCheck(Loc loc, Scope *sc, Expression *e, Declaration *d); Dsymbol *search_function(AggregateDeclaration *ad, Identifier *funcid); -void inferApplyArgTypes(Array *arguments, Type *taggr); +void inferApplyArgTypes(enum TOK op, Array *arguments, Expression *aggr); void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs); void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs); @@ -267,6 +269,8 @@ struct NullExp : Expression { + unsigned char committed; // !=0 if type is committed + NullExp(Loc loc); Expression *semantic(Scope *sc); int isBool(int result); diff -uNr dmd-0.169/dmd/src/dmd/func.c dmd-0.170/dmd/src/dmd/func.c --- dmd-0.169/dmd/src/dmd/func.c 2006-09-30 17:21:00.000000000 +0200 +++ dmd-0.170/dmd/src/dmd/func.c 2006-10-10 19:26:58.000000000 +0200 @@ -315,12 +315,29 @@ } // This is an 'introducing' function. - // Append to end of vtbl[] - //printf("\tintroducing function\n"); - introducing = 1; - vi = cd->vtbl.dim; - cd->vtbl.push(this); - vtblIndex = vi; + if (isFinal()) + { + // Verify this doesn't override previous final function + if (cd->baseClass) + { Dsymbol *s = cd->baseClass->search(loc, ident, 0); + if (s) + { + FuncDeclaration *f = s->isFuncDeclaration(); + f = f->overloadExactMatch(type); + if (f && f->isFinal()) + error("cannot override final function %s", f->toPrettyChars()); + } + } + } + else + { + // Append to end of vtbl[] + //printf("\tintroducing function\n"); + introducing = 1; + vi = cd->vtbl.dim; + cd->vtbl.push(this); + vtblIndex = vi; + } L1: ; diff -uNr dmd-0.169/dmd/src/dmd/identifier.c dmd-0.170/dmd/src/dmd/identifier.c --- dmd-0.169/dmd/src/dmd/identifier.c 2006-02-15 00:07:28.000000000 +0100 +++ dmd-0.170/dmd/src/dmd/identifier.c 2006-10-16 01:10:40.000000000 +0200 @@ -1,5 +1,6 @@ -// Copyright (c) 1999-2005 by Digital Mars +// Compiler implementation of the D programming language +// Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright // www.digitalmars.com @@ -14,6 +15,7 @@ #include "identifier.h" #include "mars.h" #include "lexer.h" +#include "id.h" Identifier::Identifier(const char *string, int value) { diff -uNr dmd-0.169/dmd/src/dmd/idgen.c dmd-0.170/dmd/src/dmd/idgen.c --- dmd-0.169/dmd/src/dmd/idgen.c 2006-10-07 19:06:26.000000000 +0200 +++ dmd-0.170/dmd/src/dmd/idgen.c 2006-10-12 11:56:52.000000000 +0200 @@ -183,6 +183,7 @@ // For foreach { "apply", "opApply" }, + { "applyReverse", "opApplyReverse" }, // For pragma's { "lib" }, diff -uNr dmd-0.169/dmd/src/dmd/import.c dmd-0.170/dmd/src/dmd/import.c --- dmd-0.169/dmd/src/dmd/import.c 2006-10-05 17:01:54.000000000 +0200 +++ dmd-0.170/dmd/src/dmd/import.c 2006-10-16 01:10:10.000000000 +0200 @@ -18,6 +18,9 @@ #include "module.h" #include "scope.h" #include "hdrgen.h" +#include "mtype.h" +#include "declaration.h" +#include "id.h" /********************************* Import ****************************/ diff -uNr dmd-0.169/dmd/src/dmd/lexer.c dmd-0.170/dmd/src/dmd/lexer.c --- dmd-0.169/dmd/src/dmd/lexer.c 2006-09-19 19:42:24.000000000 +0200 +++ dmd-0.170/dmd/src/dmd/lexer.c 2006-10-14 14:13:38.000000000 +0200 @@ -428,6 +428,42 @@ } } +/********************************** + * Determine if string is a valid Identifier. + * Placed here because of commonality with Lexer functionality. + * Returns: + * 0 invalid + */ + +int Lexer::isValidIdentifier(char *p) +{ + size_t len; + size_t idx; + + if (!p || !*p) + goto Linvalid; + + if (isdigit(*p)) + goto Linvalid; + + len = strlen(p); + idx = 0; + while (p[idx]) + { dchar_t dc; + + char *q = utf_decodeChar((unsigned char *)p, len, &idx, &dc); + if (q) + goto Linvalid; + + if (!((dc >= 0x80 && isUniAlpha(dc)) || isalnum(dc) || dc == '_')) + goto Linvalid; + } + return 1; + +Linvalid: + return 0; +} + /**************************** * Turn next token in buffer into a token. */ @@ -2518,6 +2554,7 @@ { "with", TOKwith }, { "asm", TOKasm }, { "foreach", TOKforeach }, + { "foreach_reverse", TOKforeach_reverse }, { "scope", TOKscope }, { "on_scope_exit", TOKon_scope_exit }, { "on_scope_failure", TOKon_scope_failure }, diff -uNr dmd-0.169/dmd/src/dmd/lexer.h dmd-0.170/dmd/src/dmd/lexer.h --- dmd-0.169/dmd/src/dmd/lexer.h 2006-10-05 17:05:40.000000000 +0200 +++ dmd-0.170/dmd/src/dmd/lexer.h 2006-10-14 14:11:10.000000000 +0200 @@ -136,7 +136,7 @@ TOKif, TOKelse, TOKwhile, TOKfor, TOKdo, TOKswitch, TOKcase, TOKdefault, TOKbreak, TOKcontinue, TOKwith, TOKsynchronized, TOKreturn, TOKgoto, TOKtry, TOKcatch, TOKfinally, - TOKasm, TOKforeach, + TOKasm, TOKforeach, TOKforeach_reverse, TOKscope, TOKon_scope_exit, TOKon_scope_failure, TOKon_scope_success, @@ -273,6 +273,7 @@ unsigned decodeUTF(); void getDocComment(Token *t, unsigned lineComment); + static int isValidIdentifier(char *p); static unsigned char *combineComments(unsigned char *c1, unsigned char *c2); }; diff -uNr dmd-0.169/dmd/src/dmd/mangle.c dmd-0.170/dmd/src/dmd/mangle.c --- dmd-0.169/dmd/src/dmd/mangle.c 2006-09-26 21:00:10.000000000 +0200 +++ dmd-0.170/dmd/src/dmd/mangle.c 2006-10-16 01:11:08.000000000 +0200 @@ -1,4 +1,5 @@ +// Compiler implementation of the D programming language // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright @@ -21,6 +22,7 @@ #include "attrib.h" #include "template.h" #include "id.h" +#include "module.h" char *Declaration::mangle() #if __DMC__ diff -uNr dmd-0.169/dmd/src/dmd/mars.c dmd-0.170/dmd/src/dmd/mars.c --- dmd-0.169/dmd/src/dmd/mars.c 2006-10-05 17:00:04.000000000 +0200 +++ dmd-0.170/dmd/src/dmd/mars.c 2006-10-17 01:07:06.000000000 +0200 @@ -36,6 +36,7 @@ #include "id.h" #include "cond.h" #include "expression.h" +#include "lexer.h" void getenv_setargv(const char *envvar, int *pargc, char** *pargv); @@ -59,7 +60,7 @@ copyright = "Copyright (c) 1999-2006 by Digital Mars"; written = "written by Walter Bright"; - version = "v0.169"; + version = "v0.170"; global.structalign = 8; memset(¶ms, 0, sizeof(Param)); @@ -403,7 +404,7 @@ goto Lerror; DebugCondition::setGlobalLevel((int)level); } - else if (isalpha(p[7]) || p[7] == '_') + else if (Lexer::isValidIdentifier(p + 7)) DebugCondition::addGlobalIdent(p + 7); else goto Lerror; @@ -429,7 +430,7 @@ goto Lerror; VersionCondition::setGlobalLevel((int)level); } - else if (isalpha(p[9]) || p[9] == '_') + else if (Lexer::isValidIdentifier(p + 9)) VersionCondition::addGlobalIdent(p + 9); else goto Lerror; diff -uNr dmd-0.169/dmd/src/dmd/module.c dmd-0.170/dmd/src/dmd/module.c --- dmd-0.169/dmd/src/dmd/module.c 2006-10-05 17:01:44.000000000 +0200 +++ dmd-0.170/dmd/src/dmd/module.c 2006-10-14 14:14:04.000000000 +0200 @@ -31,6 +31,7 @@ #include "import.h" #include "dsymbol.h" #include "hdrgen.h" +#include "lexer.h" #define MARS 1 #include "html.h" @@ -570,13 +571,10 @@ { dst = modules; - for (char* p = this->ident->toChars(); *p; p++) - { - if (*p != '_' && !isalnum(*p)) - { error("has non-identifier characters in filename, use module declaration instead"); - break; - } - } + /* Check to see if module name is a valid identifier + */ + if (!Lexer::isValidIdentifier(this->ident->toChars())) + error("has non-identifier characters in filename, use module declaration instead"); } // Update global list of modules diff -uNr dmd-0.169/dmd/src/dmd/mtype.c dmd-0.170/dmd/src/dmd/mtype.c --- dmd-0.169/dmd/src/dmd/mtype.c 2006-10-07 19:06:04.000000000 +0200 +++ dmd-0.170/dmd/src/dmd/mtype.c 2006-10-16 02:01:44.000000000 +0200 @@ -676,6 +676,17 @@ return next->reliesOnTident(); } +/******************************** + * We've mistakenly parsed this as a type. + * Redo it as an Expression. + * NULL if cannot. + */ + +Expression *Type::toExpression() +{ + return NULL; +} + /* ============================= TypeBasic =========================== */ TypeBasic::TypeBasic(TY ty) @@ -1736,6 +1747,18 @@ return next->isZeroInit(); } + +Expression *TypeSArray::toExpression() +{ + Expression *e = next->toExpression(); + if (e) + { Expressions *arguments = new Expressions(); + arguments->push(dim); + e = new ArrayExp(dim->loc, e, arguments); + } + return e; +} + /***************************** TypeDArray *****************************/ TypeDArray::TypeDArray(Type *t) @@ -3186,6 +3209,18 @@ return this; } +Expression *TypeIdentifier::toExpression() +{ + Expression *e = new IdentifierExp(loc, ident); + for (int i = 0; i < idents.dim; i++) + { + Identifier *id = (Identifier *)idents.data[i]; + e = new DotIdExp(loc, e, id); + } + + return e; +} + /***************************** TypeInstance *****************************/ TypeInstance::TypeInstance(Loc loc, TemplateInstance *tempinst) diff -uNr dmd-0.169/dmd/src/dmd/mtype.h dmd-0.170/dmd/src/dmd/mtype.h --- dmd-0.169/dmd/src/dmd/mtype.h 2006-10-07 19:05:40.000000000 +0200 +++ dmd-0.170/dmd/src/dmd/mtype.h 2006-10-16 01:58:00.000000000 +0200 @@ -235,6 +235,7 @@ virtual TypeInfoDeclaration *getTypeInfoDeclaration(); virtual int builtinTypeInfo(); virtual Type *reliesOnTident(); + virtual Expression *toExpression(); static void error(Loc loc, const char *format, ...); @@ -310,6 +311,7 @@ dt_t **toDtElem(dt_t **pdt, Expression *e); MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Array *atypes); TypeInfoDeclaration *getTypeInfoDeclaration(); + Expression *toExpression(); type *toCtype(); type *toCParamtype(); @@ -462,6 +464,7 @@ Type *semantic(Loc loc, Scope *sc); MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Array *atypes); Type *reliesOnTident(); + Expression *toExpression(); }; /* Similar to TypeIdentifier, but with a TemplateInstance as the root diff -uNr dmd-0.169/dmd/src/dmd/opover.c dmd-0.170/dmd/src/dmd/opover.c --- dmd-0.169/dmd/src/dmd/opover.c 2006-10-05 14:12:10.000000000 +0200 +++ dmd-0.170/dmd/src/dmd/opover.c 2006-10-12 21:51:14.000000000 +0200 @@ -1,3 +1,5 @@ + +// Compiler implementation of the D programming language // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright @@ -35,6 +37,7 @@ static Expression *build_overload(Loc loc, Scope *sc, Expression *ethis, Expression *earg, Identifier *id); static void inferApplyArgTypesX(FuncDeclaration *fstart, Array *arguments); +static int inferApplyArgTypesY(TypeFunction *tf, Array *arguments); static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expressions *arguments); /******************************** Expression **************************/ @@ -484,7 +487,7 @@ * them from the aggregate type. */ -void inferApplyArgTypes(Array *arguments, Type *taggr) +void inferApplyArgTypes(enum TOK op, Array *arguments, Expression *aggr) { if (!arguments || !arguments->dim) return; @@ -503,6 +506,7 @@ FuncDeclaration *fd; Argument *arg = (Argument *)arguments->data[0]; + Type *taggr = aggr->type; Type *tab = taggr->toBasetype(); switch (tab->ty) { @@ -562,7 +566,9 @@ * int opApply(int delegate(inout Type [, ...]) dg); * overload */ - Dsymbol *s = search_function(ad, Id::apply); + Dsymbol *s = search_function(ad, + (op == TOKforeach_reverse) ? Id::applyReverse + : Id::apply); if (s) { fd = s->isFuncDeclaration(); @@ -571,6 +577,23 @@ } break; } + + case Tdelegate: + { + if (0 && aggr->op == TOKdelegate) + { DelegateExp *de = (DelegateExp *)aggr; + + fd = de->func->isFuncDeclaration(); + if (fd) + inferApplyArgTypesX(fd, arguments); + } + else + { + inferApplyArgTypesY((TypeFunction *)tab->next, arguments); + } + break; + } + default: break; // ignore error, caught later } @@ -603,40 +626,10 @@ next = f->overnext; TypeFunction *tf = (TypeFunction *)f->type; - if (!tf->arguments || tf->arguments->dim != 1) - continue; - Argument *p = (Argument *)tf->arguments->data[0]; - if (p->type->ty != Tdelegate) + if (inferApplyArgTypesY(tf, arguments) == 1) continue; - tf = (TypeFunction *)p->type->next; - assert(tf->ty == Tfunction); - - /* We now have tf, the type of the delegate. Match it against - * the arguments, filling in missing argument types. - */ - if (!tf->arguments || tf->varargs) - continue; // not enough parameters - unsigned nparams = tf->arguments->dim; - if (arguments->dim != nparams) - continue; // not enough parameters - - for (unsigned u = 0; u < nparams; u++) - { - p = (Argument *)arguments->data[u]; - Argument *tp = (Argument *)tf->arguments->data[u]; - if (p->type) - { if (!p->type->equals(tp->type)) - { - /* Cannot resolve argument types. Indicate an - * error by setting the number of arguments to 0. - */ - arguments->dim = 0; - return; - } - continue; - } - p->type = tp->type; - } + if (arguments->dim == 0) + return; } else if ((a = d->isAliasDeclaration()) != NULL) { @@ -654,6 +647,60 @@ } } +/****************************** + * Infer arguments from type of function. + * Returns: + * 0 match for this function + * 1 no match for this function + */ + +static int inferApplyArgTypesY(TypeFunction *tf, Array *arguments) +{ unsigned nparams; + Argument *p; + + if (!tf->arguments || tf->arguments->dim != 1) + goto Lnomatch; + p = (Argument *)tf->arguments->data[0]; + if (p->type->ty != Tdelegate) + goto Lnomatch; + tf = (TypeFunction *)p->type->next; + assert(tf->ty == Tfunction); + + /* We now have tf, the type of the delegate. Match it against + * the arguments, filling in missing argument types. + */ + if (!tf->arguments || tf->varargs) + goto Lnomatch; // not enough parameters + nparams = tf->arguments->dim; + if (arguments->dim != nparams) + goto Lnomatch; // not enough parameters + + for (unsigned u = 0; u < nparams; u++) + { + p = (Argument *)arguments->data[u]; + Argument *tp = (Argument *)tf->arguments->data[u]; + if (p->type) + { if (!p->type->equals(tp->type)) + { + /* Cannot resolve argument types. Indicate an + * error by setting the number of arguments to 0. + */ + arguments->dim = 0; + goto Lmatch; + } + continue; + } + p->type = tp->type; + } + Lmatch: + return 0; + + Lnomatch: + return 1; +} + +/************************************** + */ static void templateResolve(Match *m, TemplateDeclaration *td, Scope *sc, Loc loc, Objects *targsi, Expressions *arguments) { diff -uNr dmd-0.169/dmd/src/dmd/parse.c dmd-0.170/dmd/src/dmd/parse.c --- dmd-0.169/dmd/src/dmd/parse.c 2006-09-15 00:26:00.000000000 +0200 +++ dmd-0.170/dmd/src/dmd/parse.c 2006-10-16 01:53:32.000000000 +0200 @@ -1,4 +1,5 @@ +// Compiler implementation of the D programming language // Copyright (c) 1999-2006 by Digital Mars // All Rights Reserved // written by Walter Bright @@ -2601,7 +2602,9 @@ } case TOKforeach: + case TOKforeach_reverse: { + enum TOK op = token.value; Array *arguments; Statement *d; @@ -2654,7 +2657,7 @@ aggr = parseExpression(); check(TOKrparen); body = parseStatement(0); - s = new ForeachStatement(loc, arguments, aggr, body); + s = new ForeachStatement(loc, op, arguments, aggr, body); break; } @@ -4664,21 +4667,9 @@ { Type *index = ((TypeAArray *)t)->index; - if (index->ty == Tident) - { - TypeIdentifier *ti = (TypeIdentifier *)index; - int i; - Expression *e; - Identifier *id = ti->ident; - - e = new IdentifierExp(loc, id); - for (i = 0; i < ti->idents.dim; i++) - { - id = (Identifier *)ti->idents.data[i]; - e = new DotIdExp(loc, e, id); - } - - arguments = new Expressions(); + Expression *e = index->toExpression(); + if (e) + { arguments = new Expressions(); arguments->push(e); t = new TypeDArray(t->next); } diff -uNr dmd-0.169/dmd/src/dmd/statement.c dmd-0.170/dmd/src/dmd/statement.c --- dmd-0.169/dmd/src/dmd/statement.c 2006-10-05 17:01:36.000000000 +0200 +++ dmd-0.170/dmd/src/dmd/statement.c 2006-10-12 21:13:04.000000000 +0200 @@ -874,10 +874,11 @@ /******************************** ForeachStatement ***************************/ -ForeachStatement::ForeachStatement(Loc loc, Array *arguments, +ForeachStatement::ForeachStatement(Loc loc, enum TOK op, Array *arguments, Expression *aggr, Statement *body) : Statement(loc) { + this->op = op; this->arguments = arguments; this->aggr = aggr; this->body = body; @@ -892,7 +893,7 @@ { Array *args = Argument::arraySyntaxCopy(arguments); Expression *exp = aggr->syntaxCopy(); - ForeachStatement *s = new ForeachStatement(loc, args, exp, body->syntaxCopy()); + ForeachStatement *s = new ForeachStatement(loc, op, args, exp, body->syntaxCopy()); return s; } @@ -915,7 +916,7 @@ aggr = aggr->semantic(sc); aggr = resolveProperties(sc, aggr); - inferApplyArgTypes(arguments, aggr->type); + inferApplyArgTypes(op, arguments, aggr); /* Check for inference errors */ @@ -1039,8 +1040,15 @@ error("only one or two arguments for associative array foreach"); break; } + if (op == TOKforeach_reverse) + { + error("no reverse iteration on associative arrays"); + } + goto Lapply; + case Tclass: case Tstruct: + case Tdelegate: Lapply: { FuncDeclaration *fdapply; Expressions *args; @@ -1157,7 +1165,7 @@ "wc","cc","wd", "dc","dw","dd" }; - char fdname[10 + 1]; + char fdname[11 + 1]; int flag; switch (tn->ty) @@ -1174,7 +1182,8 @@ case Tdchar: flag += 2; break; default: assert(0); } - int j = sprintf(fdname, "_aApply%.*s%d", 2, fntab[flag], dim); + const char *r = (op == TOKforeach_reverse) ? "R" : ""; + int j = sprintf(fdname, "_aApply%s%.*s%d", r, 2, fntab[flag], dim); assert(j < sizeof(fdname)); fdapply = FuncDeclaration::genCfunc(Type::tindex, fdname); @@ -1187,12 +1196,26 @@ e = new CallExp(loc, ec, args); e->type = Type::tindex; // don't run semantic() on e } + else if (tab->ty == Tdelegate) + { + /* Call: + * aggr(flde) + */ + args = new Expressions(); + args->push(flde); + e = new CallExp(loc, aggr, args); + e = e->semantic(sc); + if (e->type != Type::tint32) + error("opApply() function for %s must return an int", tab->toChars()); + } else { /* Call: * aggr.apply(flde) */ - ec = new DotIdExp(loc, aggr, Id::apply); + ec = new DotIdExp(loc, aggr, + (op == TOKforeach_reverse) ? Id::applyReverse + : Id::apply); args = new Expressions(); args->push(flde); e = new CallExp(loc, ec, args); @@ -1269,7 +1292,8 @@ void ForeachStatement::toCBuffer(OutBuffer *buf, HdrGenState *hgs) { - buf->writestring("foreach ("); + buf->writestring(Token::toChars(op)); + buf->writestring(" ("); int i; for (int i = 0; i < arguments->dim; i++) { diff -uNr dmd-0.169/dmd/src/dmd/statement.h dmd-0.170/dmd/src/dmd/statement.h --- dmd-0.169/dmd/src/dmd/statement.h 2006-10-05 17:01:26.000000000 +0200 +++ dmd-0.170/dmd/src/dmd/statement.h 2006-10-12 11:50:18.000000000 +0200 @@ -44,6 +44,8 @@ struct TryCatchStatement; struct HdrGenState; +enum TOK; + // Back end struct IRState; struct Blockx; @@ -248,6 +250,7 @@ struct ForeachStatement : Statement { + enum TOK op; // TOKforeach or TOKforeach_reverse Array *arguments; // array of Argument*'s Expression *aggr; Statement *body; @@ -260,7 +263,7 @@ Array cases; // put breaks, continues, gotos and returns here Array gotos; // forward referenced goto's go here - ForeachStatement(Loc loc, Array *arguments, Expression *aggr, Statement *body); + ForeachStatement(Loc loc, enum TOK op, Array *arguments, Expression *aggr, Statement *body); Statement *syntaxCopy(); Statement *semantic(Scope *sc); int hasBreak(); diff -uNr dmd-0.169/dmd/src/dmd/template.h dmd-0.170/dmd/src/dmd/template.h --- dmd-0.169/dmd/src/dmd/template.h 2006-10-06 16:41:20.000000000 +0200 +++ dmd-0.170/dmd/src/dmd/template.h 2006-10-16 01:12:02.000000000 +0200 @@ -28,6 +28,7 @@ struct TemplateValueParameter; struct TemplateAliasParameter; struct Type; +struct TypeTypeof; struct Scope; struct Expression; struct AliasDeclaration; diff -uNr dmd-0.169/dmd/src/dmd/utf.h dmd-0.170/dmd/src/dmd/utf.h --- dmd-0.169/dmd/src/dmd/utf.h 2006-10-05 17:02:46.000000000 +0200 +++ dmd-0.170/dmd/src/dmd/utf.h 2006-10-14 13:55:38.000000000 +0200 @@ -21,4 +21,6 @@ char *utf_validateString(unsigned char *s, unsigned len); +extern int isUniAlpha(dchar_t); + #endif diff -uNr dmd-0.169/dmd/src/phobos/internal/aApply.d dmd-0.170/dmd/src/phobos/internal/aApply.d --- dmd-0.169/dmd/src/phobos/internal/aApply.d 2006-10-08 01:06:30.000000000 +0200 +++ dmd-0.170/dmd/src/phobos/internal/aApply.d 2006-10-17 02:36:12.000000000 +0200 @@ -1,6 +1,30 @@ -//_ aApply.d -// Copyright (c) 2004 by Digital Mars -// Written by Walter Bright + +/** + * Part of the D programming language runtime library. + */ + +/* + * Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com + * Written by Walter Bright + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, in both source and binary form, subject to the following + * restrictions: + * + * o The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * o Altered source versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * o This notice may not be removed or altered from any source + * distribution. + */ /* This code handles decoding UTF strings for foreach loops. * There are 6 combinations of conversions between char, wchar, @@ -12,7 +36,6 @@ //debug=apply; /********************************************** - * 'apply' for associative arrays - to support foreach */ // dg is D, but _aApplycd() is C diff -uNr dmd-0.169/dmd/src/phobos/internal/aApplyR.d dmd-0.170/dmd/src/phobos/internal/aApplyR.d --- dmd-0.169/dmd/src/phobos/internal/aApplyR.d 1970-01-01 01:00:00.000000000 +0100 +++ dmd-0.170/dmd/src/phobos/internal/aApplyR.d 2006-10-17 02:36:12.000000000 +0200 @@ -0,0 +1,953 @@ + +/** + * Part of the D programming language runtime library. + */ + +/* + * Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com + * Written by Walter Bright + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, in both source and binary form, subject to the following + * restrictions: + * + * o The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * o Altered source versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * o This notice may not be removed or altered from any source + * distribution. + */ + +/* This code handles decoding UTF strings for foreach_reverse loops. + * There are 6 combinations of conversions between char, wchar, + * and dchar, and 2 of each of those. + */ + +import std.utf; + +debug=apply; + +/**********************************************/ +/* 1 argument versions */ + +// dg is D, but _aApplyRcd() is C +extern (D) typedef int delegate(void *) dg_t; + +extern (C) int _aApplyRcd1(char[] aa, dg_t dg) +{ int result; + + debug(apply) printf("_aApplyRcd1(), len = %d\n", aa.length); + for (size_t i = aa.length; i != 0; ) + { dchar d; + + i--; + d = aa[i]; + if (d & 0x80) + { char c = cast(char)d; + uint j; + uint m = 0x3F; + d = 0; + while ((c & 0xC0) != 0xC0) + { if (i == 0) + throw new std.utf.UtfException("Invalid UTF-8 sequence", 0); + i--; + d |= (c & 0x3F) << j; + j += 6; + m >>= 1; + c = aa[i]; + } + d |= (c & m) << j; + } + result = dg(cast(void *)&d); + if (result) + break; + } + return result; +} + +unittest +{ + debug(apply) printf("_aApplyRcd1.unittest\n"); + + char[] s = "hello"; + int i; + + foreach_reverse(dchar d; s) + { + switch (i) + { + case 0: assert(d == 'o'); break; + case 1: assert(d == 'l'); break; + case 2: assert(d == 'l'); break; + case 3: assert(d == 'e'); break; + case 4: assert(d == 'h'); break; + } + i++; + } + assert(i == 5); + + s = "a\u1234\U00100456b"; + i = 0; + foreach_reverse(dchar d; s) + { + //printf("i = %d, d = %x\n", i, d); + switch (i) + { + case 0: assert(d == 'b'); break; + case 1: assert(d == '\U00100456'); break; + case 2: assert(d == '\u1234'); break; + case 3: assert(d == 'a'); break; + } + i++; + } + assert(i == 4); +} + +/*****************************/ + +extern (C) int _aApplyRwd1(wchar[] aa, dg_t dg) +{ int result; + + debug(apply) printf("_aApplyRwd1(), len = %d\n", aa.length); + for (size_t i = aa.length; i != 0; ) + { dchar d; + + i--; + d = aa[i]; + if (d >= 0xDC00 && d <= 0xDFFF) + { if (i == 0) + throw new std.utf.UtfException("Invalid UTF-16 sequence", 0); + i--; + d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00); + } + result = dg(cast(void *)&d); + if (result) + break; + } + return result; +} + +unittest +{ + debug(apply) printf("_aApplyRwd1.unittest\n"); + + wchar[] s = "hello"; + int i; + + foreach_reverse(dchar d; s) + { + switch (i) + { + case 0: assert(d == 'o'); break; + case 1: assert(d == 'l'); break; + case 2: assert(d == 'l'); break; + case 3: assert(d == 'e'); break; + case 4: assert(d == 'h'); break; + } + i++; + } + assert(i == 5); + + s = "a\u1234\U00100456b"; + i = 0; + foreach_reverse(dchar d; s) + { + //printf("i = %d, d = %x\n", i, d); + switch (i) + { + case 0: assert(d == 'b'); break; + case 1: assert(d == '\U00100456'); break; + case 2: assert(d == '\u1234'); break; + case 3: assert(d == 'a'); break; + } + i++; + } + assert(i == 4); +} + +/*****************************/ + +extern (C) int _aApplyRcw1(char[] aa, dg_t dg) +{ int result; + + debug(apply) printf("_aApplyRcw1(), len = %d\n", aa.length); + for (size_t i = aa.length; i != 0; ) + { dchar d; + wchar w; + + i--; + w = aa[i]; + if (w & 0x80) + { char c = cast(char)w; + uint j; + uint m = 0x3F; + d = 0; + while ((c & 0xC0) != 0xC0) + { if (i == 0) + throw new std.utf.UtfException("Invalid UTF-8 sequence", 0); + i--; + d |= (c & 0x3F) << j; + j += 6; + m >>= 1; + c = aa[i]; + } + d |= (c & m) << j; + + if (d <= 0xFFFF) + w = cast(wchar) d; + else + { + w = (((d - 0x10000) >> 10) & 0x3FF) + 0xD800; + result = dg(cast(void *)&w); + if (result) + break; + w = ((d - 0x10000) & 0x3FF) + 0xDC00; + } + } + result = dg(cast(void *)&w); + if (result) + break; + } + return result; +} + +unittest +{ + debug(apply) printf("_aApplyRcw1.unittest\n"); + + char[] s = "hello"; + int i; + + foreach_reverse(wchar d; s) + { + switch (i) + { + case 0: assert(d == 'o'); break; + case 1: assert(d == 'l'); break; + case 2: assert(d == 'l'); break; + case 3: assert(d == 'e'); break; + case 4: assert(d == 'h'); break; + } + i++; + } + assert(i == 5); + + s = "a\u1234\U00100456b"; + i = 0; + foreach_reverse(wchar d; s) + { + //printf("i = %d, d = %x\n", i, d); + switch (i) + { + case 0: assert(d == 'b'); break; + case 1: assert(d == 0xDBC1); break; + case 2: assert(d == 0xDC56); break; + case 3: assert(d == 0x1234); break; + case 4: assert(d == 'a'); break; + } + i++; + } + assert(i == 5); +} + +/*****************************/ + +extern (C) int _aApplyRwc1(wchar[] aa, dg_t dg) +{ int result; + + debug(apply) printf("_aApplyRwc1(), len = %d\n", aa.length); + for (size_t i = aa.length; i != 0; ) + { dchar d; + char c; + + i--; + d = aa[i]; + if (d >= 0xDC00 && d <= 0xDFFF) + { if (i == 0) + throw new std.utf.UtfException("Invalid UTF-16 sequence", 0); + i--; + d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00); + } + + if (d & ~0x7F) + { + char[4] buf; + char[] b; + + b = std.utf.toUTF8(buf, d); + foreach (char c2; b) + { + result = dg(cast(void *)&c2); + if (result) + return result; + } + continue; + } + c = cast(char)d; + result = dg(cast(void *)&c); + if (result) + break; + } + return result; +} + +unittest +{ + debug(apply) printf("_aApplyRwc1.unittest\n"); + + wchar[] s = "hello"; + int i; + + foreach_reverse(char d; s) + { + switch (i) + { + case 0: assert(d == 'o'); break; + case 1: assert(d == 'l'); break; + case 2: assert(d == 'l'); break; + case 3: assert(d == 'e'); break; + case 4: assert(d == 'h'); break; + } + i++; + } + assert(i == 5); + + s = "a\u1234\U00100456b"; + i = 0; + foreach_reverse(char d; s) + { + //printf("i = %d, d = %x\n", i, d); + switch (i) + { + case 0: assert(d == 'b'); break; + case 1: assert(d == 0xF4); break; + case 2: assert(d == 0x80); break; + case 3: assert(d == 0x91); break; + case 4: assert(d == 0x96); break; + case 5: assert(d == 0xE1); break; + case 6: assert(d == 0x88); break; + case 7: assert(d == 0xB4); break; + case 8: assert(d == 'a'); break; + } + i++; + } + assert(i == 9); +} + +/*****************************/ + +extern (C) int _aApplyRdc1(dchar[] aa, dg_t dg) +{ int result; + + debug(apply) printf("_aApplyRdc1(), len = %d\n", aa.length); + for (size_t i = aa.length; i != 0;) + { dchar d = aa[--i]; + char c; + + if (d & ~0x7F) + { + char[4] buf; + char[] b; + + b = std.utf.toUTF8(buf, d); + foreach (char c2; b) + { + result = dg(cast(void *)&c2); + if (result) + return result; + } + continue; + } + else + { + c = cast(char)d; + } + result = dg(cast(void *)&c); + if (result) + break; + } + return result; +} + +unittest +{ + debug(apply) printf("_aApplyRdc1.unittest\n"); + + dchar[] s = "hello"; + int i; + + foreach_reverse(char d; s) + { + switch (i) + { + case 0: assert(d == 'o'); break; + case 1: assert(d == 'l'); break; + case 2: assert(d == 'l'); break; + case 3: assert(d == 'e'); break; + case 4: assert(d == 'h'); break; + } + i++; + } + assert(i == 5); + + s = "a\u1234\U00100456b"; + i = 0; + foreach_reverse(char d; s) + { + //printf("i = %d, d = %x\n", i, d); + switch (i) + { + case 0: assert(d == 'b'); break; + case 1: assert(d == 0xF4); break; + case 2: assert(d == 0x80); break; + case 3: assert(d == 0x91); break; + case 4: assert(d == 0x96); break; + case 5: assert(d == 0xE1); break; + case 6: assert(d == 0x88); break; + case 7: assert(d == 0xB4); break; + case 8: assert(d == 'a'); break; + } + i++; + } + assert(i == 9); +} + +/*****************************/ + +extern (C) int _aApplyRdw1(dchar[] aa, dg_t dg) +{ int result; + + debug(apply) printf("_aApplyRdw1(), len = %d\n", aa.length); + for (size_t i = aa.length; i != 0; ) + { dchar d = aa[--i]; + wchar w; + + if (d <= 0xFFFF) + w = cast(wchar) d; + else + { + w = (((d - 0x10000) >> 10) & 0x3FF) + 0xD800; + result = dg(cast(void *)&w); + if (result) + break; + w = ((d - 0x10000) & 0x3FF) + 0xDC00; + } + result = dg(cast(void *)&w); + if (result) + break; + } + return result; +} + +unittest +{ + debug(apply) printf("_aApplyRdw1.unittest\n"); + + dchar[] s = "hello"; + int i; + + foreach_reverse(wchar d; s) + { + switch (i) + { + case 0: assert(d == 'o'); break; + case 1: assert(d == 'l'); break; + case 2: assert(d == 'l'); break; + case 3: assert(d == 'e'); break; + case 4: assert(d == 'h'); break; + } + i++; + } + assert(i == 5); + + s = "a\u1234\U00100456b"; + i = 0; + foreach_reverse(wchar d; s) + { + //printf("i = %d, d = %x\n", i, d); + switch (i) + { + case 0: assert(d == 'b'); break; + case 1: assert(d == 0xDBC1); break; + case 2: assert(d == 0xDC56); break; + case 3: assert(d == 0x1234); break; + case 4: assert(d == 'a'); break; + } + i++; + } + assert(i == 5); +} + + +/****************************************************************************/ +/* 2 argument versions */ + +// dg is D, but _aApplyRcd2() is C +extern (D) typedef int delegate(void *, void *) dg2_t; + +extern (C) int _aApplyRcd2(char[] aa, dg2_t dg) +{ int result; + size_t i; + size_t len = aa.length; + + debug(apply) printf("_aApplyRcd2(), len = %d\n", len); + for (i = len; i != 0; ) + { dchar d; + + i--; + d = aa[i]; + if (d & 0x80) + { char c = cast(char)d; + uint j; + uint m = 0x3F; + d = 0; + while ((c & 0xC0) != 0xC0) + { if (i == 0) + throw new std.utf.UtfException("Invalid UTF-8 sequence", 0); + i--; + d |= (c & 0x3F) << j; + j += 6; + m >>= 1; + c = aa[i]; + } + d |= (c & m) << j; + } + result = dg(&i, cast(void *)&d); + if (result) + break; + } + return result; +} + +unittest +{ + debug(apply) printf("_aApplyRcd2.unittest\n"); + + char[] s = "hello"; + int i; + + foreach_reverse(k, dchar d; s) + { + assert(k == 4 - i); + switch (i) + { + case 0: assert(d == 'o'); break; + case 1: assert(d == 'l'); break; + case 2: assert(d == 'l'); break; + case 3: assert(d == 'e'); break; + case 4: assert(d == 'h'); break; + } + i++; + } + assert(i == 5); + + s = "a\u1234\U00100456b"; + i = 0; + foreach_reverse(k, dchar d; s) + { + //printf("i = %d, k = %d, d = %x\n", i, k, d); + switch (i) + { + case 0: assert(d == 'b'); assert(k == 8); break; + case 1: assert(d == '\U00100456'); assert(k == 4); break; + case 2: assert(d == '\u1234'); assert(k == 1); break; + case 3: assert(d == 'a'); assert(k == 0); break; + } + i++; + } + assert(i == 4); +} + +/*****************************/ + +extern (C) int _aApplyRwd2(wchar[] aa, dg2_t dg) +{ int result; + + debug(apply) printf("_aApplyRwd2(), len = %d\n", aa.length); + for (size_t i = aa.length; i != 0; ) + { dchar d; + + i--; + d = aa[i]; + if (d >= 0xDC00 && d <= 0xDFFF) + { if (i == 0) + throw new std.utf.UtfException("Invalid UTF-16 sequence", 0); + i--; + d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00); + } + result = dg(&i, cast(void *)&d); + if (result) + break; + } + return result; +} + +unittest +{ + debug(apply) printf("_aApplyRwd2.unittest\n"); + + wchar[] s = "hello"; + int i; + + foreach_reverse(k, dchar d; s) + { + //printf("i = %d, k = %d, d = %x\n", i, k, d); + assert(k == 4 - i); + switch (i) + { + case 0: assert(d == 'o'); break; + case 1: assert(d == 'l'); break; + case 2: assert(d == 'l'); break; + case 3: assert(d == 'e'); break; + case 4: assert(d == 'h'); break; + } + i++; + } + assert(i == 5); + + s = "a\u1234\U00100456b"; + i = 0; + foreach_reverse(k, dchar d; s) + { + //printf("i = %d, k = %d, d = %x\n", i, k, d); + switch (i) + { + case 0: assert(k == 4); assert(d == 'b'); break; + case 1: assert(k == 2); assert(d == '\U00100456'); break; + case 2: assert(k == 1); assert(d == '\u1234'); break; + case 3: assert(k == 0); assert(d == 'a'); break; + } + i++; + } + assert(i == 4); +} + +/*****************************/ + +extern (C) int _aApplyRcw2(char[] aa, dg2_t dg) +{ int result; + + debug(apply) printf("_aApplyRcw2(), len = %d\n", aa.length); + for (size_t i = aa.length; i != 0; ) + { dchar d; + wchar w; + + i--; + w = aa[i]; + if (w & 0x80) + { char c = cast(char)w; + uint j; + uint m = 0x3F; + d = 0; + while ((c & 0xC0) != 0xC0) + { if (i == 0) + throw new std.utf.UtfException("Invalid UTF-8 sequence", 0); + i--; + d |= (c & 0x3F) << j; + j += 6; + m >>= 1; + c = aa[i]; + } + d |= (c & m) << j; + + if (d <= 0xFFFF) + w = cast(wchar) d; + else + { + w = (((d - 0x10000) >> 10) & 0x3FF) + 0xD800; + result = dg(&i, cast(void *)&w); + if (result) + break; + w = ((d - 0x10000) & 0x3FF) + 0xDC00; + } + } + result = dg(&i, cast(void *)&w); + if (result) + break; + } + return result; +} + +unittest +{ + debug(apply) printf("_aApplyRcw2.unittest\n"); + + char[] s = "hello"; + int i; + + foreach_reverse(k, wchar d; s) + { + //printf("i = %d, k = %d, d = %x\n", i, k, d); + assert(k == 4 - i); + switch (i) + { + case 0: assert(d == 'o'); break; + case 1: assert(d == 'l'); break; + case 2: assert(d == 'l'); break; + case 3: assert(d == 'e'); break; + case 4: assert(d == 'h'); break; + } + i++; + } + assert(i == 5); + + s = "a\u1234\U00100456b"; + i = 0; + foreach_reverse(k, wchar d; s) + { + //printf("i = %d, k = %d, d = %x\n", i, k, d); + switch (i) + { + case 0: assert(k == 8); assert(d == 'b'); break; + case 1: assert(k == 4); assert(d == 0xDBC1); break; + case 2: assert(k == 4); assert(d == 0xDC56); break; + case 3: assert(k == 1); assert(d == 0x1234); break; + case 4: assert(k == 0); assert(d == 'a'); break; + } + i++; + } + assert(i == 5); +} + +/*****************************/ + +extern (C) int _aApplyRwc2(wchar[] aa, dg2_t dg) +{ int result; + + debug(apply) printf("_aApplyRwc2(), len = %d\n", aa.length); + for (size_t i = aa.length; i != 0; ) + { dchar d; + char c; + + i--; + d = aa[i]; + if (d >= 0xDC00 && d <= 0xDFFF) + { if (i == 0) + throw new std.utf.UtfException("Invalid UTF-16 sequence", 0); + i--; + d = ((aa[i] - 0xD7C0) << 10) + (d - 0xDC00); + } + + if (d & ~0x7F) + { + char[4] buf; + char[] b; + + b = std.utf.toUTF8(buf, d); + foreach (char c2; b) + { + result = dg(&i, cast(void *)&c2); + if (result) + return result; + } + continue; + } + c = cast(char)d; + result = dg(&i, cast(void *)&c); + if (result) + break; + } + return result; +} + +unittest +{ + debug(apply) printf("_aApplyRwc2.unittest\n"); + + wchar[] s = "hello"; + int i; + + foreach_reverse(k, char d; s) + { + //printf("i = %d, k = %d, d = %x\n", i, k, d); + assert(k == 4 - i); + switch (i) + { + case 0: assert(d == 'o'); break; + case 1: assert(d == 'l'); break; + case 2: assert(d == 'l'); break; + case 3: assert(d == 'e'); break; + case 4: assert(d == 'h'); break; + } + i++; + } + assert(i == 5); + + s = "a\u1234\U00100456b"; + i = 0; + foreach_reverse(k, char d; s) + { + //printf("i = %d, k = %d, d = %x\n", i, k, d); + switch (i) + { + case 0: assert(k == 4); assert(d == 'b'); break; + case 1: assert(k == 2); assert(d == 0xF4); break; + case 2: assert(k == 2); assert(d == 0x80); break; + case 3: assert(k == 2); assert(d == 0x91); break; + case 4: assert(k == 2); assert(d == 0x96); break; + case 5: assert(k == 1); assert(d == 0xE1); break; + case 6: assert(k == 1); assert(d == 0x88); break; + case 7: assert(k == 1); assert(d == 0xB4); break; + case 8: assert(k == 0); assert(d == 'a'); break; + } + i++; + } + assert(i == 9); +} + +/*****************************/ + +extern (C) int _aApplyRdc2(dchar[] aa, dg2_t dg) +{ int result; + + debug(apply) printf("_aApplyRdc2(), len = %d\n", aa.length); + for (size_t i = aa.length; i != 0; ) + { dchar d = aa[--i]; + char c; + + if (d & ~0x7F) + { + char[4] buf; + char[] b; + + b = std.utf.toUTF8(buf, d); + foreach (char c2; b) + { + result = dg(&i, cast(void *)&c2); + if (result) + return result; + } + continue; + } + else + { c = cast(char)d; + } + result = dg(&i, cast(void *)&c); + if (result) + break; + } + return result; +} + +unittest +{ + debug(apply) printf("_aApplyRdc2.unittest\n"); + + dchar[] s = "hello"; + int i; + + foreach_reverse(k, char d; s) + { + //printf("i = %d, k = %d, d = %x\n", i, k, d); + assert(k == 4 - i); + switch (i) + { + case 0: assert(d == 'o'); break; + case 1: assert(d == 'l'); break; + case 2: assert(d == 'l'); break; + case 3: assert(d == 'e'); break; + case 4: assert(d == 'h'); break; + } + i++; + } + assert(i == 5); + + s = "a\u1234\U00100456b"; + i = 0; + foreach_reverse(k, char d; s) + { + //printf("i = %d, k = %d, d = %x\n", i, k, d); + switch (i) + { + case 0: assert(k == 3); assert(d == 'b'); break; + case 1: assert(k == 2); assert(d == 0xF4); break; + case 2: assert(k == 2); assert(d == 0x80); break; + case 3: assert(k == 2); assert(d == 0x91); break; + case 4: assert(k == 2); assert(d == 0x96); break; + case 5: assert(k == 1); assert(d == 0xE1); break; + case 6: assert(k == 1); assert(d == 0x88); break; + case 7: assert(k == 1); assert(d == 0xB4); break; + case 8: assert(k == 0); assert(d == 'a'); break; + } + i++; + } + assert(i == 9); +} + +/*****************************/ + +extern (C) int _aApplyRdw2(dchar[] aa, dg2_t dg) +{ int result; + + debug(apply) printf("_aApplyRdw2(), len = %d\n", aa.length); + for (size_t i = aa.length; i != 0; ) + { dchar d = aa[--i]; + wchar w; + + if (d <= 0xFFFF) + w = cast(wchar) d; + else + { + w = (((d - 0x10000) >> 10) & 0x3FF) + 0xD800; + result = dg(&i, cast(void *)&w); + if (result) + break; + w = ((d - 0x10000) & 0x3FF) + 0xDC00; + } + result = dg(&i, cast(void *)&w); + if (result) + break; + } + return result; +} + +unittest +{ + debug(apply) printf("_aApplyRdw2.unittest\n"); + + dchar[] s = "hello"; + int i; + + foreach_reverse(k, wchar d; s) + { + //printf("i = %d, k = %d, d = %x\n", i, k, d); + assert(k == 4 - i); + switch (i) + { + case 0: assert(d == 'o'); break; + case 1: assert(d == 'l'); break; + case 2: assert(d == 'l'); break; + case 3: assert(d == 'e'); break; + case 4: assert(d == 'h'); break; + } + i++; + } + assert(i == 5); + + s = "a\u1234\U00100456b"; + i = 0; + foreach_reverse(k, wchar d; s) + { + //printf("i = %d, k = %d, d = %x\n", i, k, d); + switch (i) + { + case 0: assert(k == 3); assert(d == 'b'); break; + case 1: assert(k == 2); assert(d == 0xDBC1); break; + case 2: assert(k == 2); assert(d == 0xDC56); break; + case 3: assert(k == 1); assert(d == 0x1234); break; + case 4: assert(k == 0); assert(d == 'a'); break; + } + i++; + } + assert(i == 5); +} + + diff -uNr dmd-0.169/dmd/src/phobos/internal/cast.d dmd-0.170/dmd/src/phobos/internal/cast.d --- dmd-0.169/dmd/src/phobos/internal/cast.d 2006-10-08 01:06:30.000000000 +0200 +++ dmd-0.170/dmd/src/phobos/internal/cast.d 2006-10-17 02:36:12.000000000 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 by Digital Mars, www.digitalmars.com + * Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com * Written by Walter Bright * * This software is provided 'as-is', without any express or implied @@ -25,13 +25,44 @@ import object; import std.c.stdio; +extern (C): + +/****************************************** + * Given a pointer: + * If it is an Object, return that Object. + * If it is an interface, return the Object implementing the interface. + * If it is null, return null. + * Else, undefined crash + */ + +Object _d_toObject(void* p) +{ Object o; + + if (p) + { + o = cast(Object)p; + ClassInfo oc = o.classinfo; + Interface *pi = **cast(Interface ***)p; + + /* Interface.offset lines up with ClassInfo.name.ptr, + * so we rely on pointers never being less than 64K, + * and Objects never being greater. + */ + if (pi.offset < 0x10000) + { + //printf("\tpi.offset = %d\n", pi.offset); + o = cast(Object)(p - pi.offset); + } + } + return o; +} + + /************************************* * Attempts to cast Object o to class c. * Returns o if successful, null if not. */ -extern (C): - Object _d_interface_cast(void* p, ClassInfo c) { Object o; diff -uNr dmd-0.169/dmd/src/phobos/internal/gc/gc.d dmd-0.170/dmd/src/phobos/internal/gc/gc.d --- dmd-0.169/dmd/src/phobos/internal/gc/gc.d 2006-10-08 01:06:32.000000000 +0200 +++ dmd-0.170/dmd/src/phobos/internal/gc/gc.d 2006-10-17 02:36:12.000000000 +0200 @@ -512,7 +512,7 @@ } else { - newdata = null; + newdata = p.data; } p.data = newdata; @@ -609,7 +609,7 @@ } else { - newdata = null; + newdata = p.data; } p.data = newdata; @@ -714,7 +714,7 @@ } else { - newdata = null; + newdata = p.data; } p.data = newdata; diff -uNr dmd-0.169/dmd/src/phobos/internal/mars.h dmd-0.170/dmd/src/phobos/internal/mars.h --- dmd-0.169/dmd/src/phobos/internal/mars.h 2006-10-08 01:06:30.000000000 +0200 +++ dmd-0.170/dmd/src/phobos/internal/mars.h 2006-10-17 02:36:12.000000000 +0200 @@ -64,6 +64,18 @@ char *msg; } Exception; +typedef struct Array +{ + size_t length; + void *ptr; +} Array; + +struct Delegate +{ + void *thisptr; + void (*funcptr)(); +}; + void _d_monitorenter(Object *h); void _d_monitorexit(Object *h); void _d_monitorrelease(Object *h); diff -uNr dmd-0.169/dmd/src/phobos/internal/monitor.c dmd-0.170/dmd/src/phobos/internal/monitor.c --- dmd-0.169/dmd/src/phobos/internal/monitor.c 2006-10-08 01:06:30.000000000 +0200 +++ dmd-0.170/dmd/src/phobos/internal/monitor.c 2006-10-17 02:36:12.000000000 +0200 @@ -1,25 +1,58 @@ -// Copyright (c) 2000-2006 by Digital Mars -// All Rights Reserved -// written by Walter Bright +// D programming language runtime library +// Public Domain +// written by Walter Bright, Digital Mars // www.digitalmars.com +// This is written in C because nobody has written a pthreads interface +// to D yet. #include #include #include -/* =============================== Win32 ============================ */ - #if _WIN32 +#elif linux +#define USE_PTHREADS 1 +#else +#endif +#if _WIN32 #include +#endif + +#if USE_PTHREADS +#include +#endif #include "mars.h" -static CRITICAL_SECTION _monitor_critsec; +// This is what the monitor reference in Object points to +typedef struct Monitor +{ + Array delegates; // for the notification system + +#if _WIN32 + CRITICAL_SECTION mon; +#endif + +#if USE_PTHREADS + pthread_mutex_t mon; +#endif +} Monitor; + +#define MONPTR(h) (&((Monitor *)(h)->monitor)->mon) + static volatile int inited; +void _d_notify_release(Object *); + +/* =============================== Win32 ============================ */ + +#if _WIN32 + +static CRITICAL_SECTION _monitor_critsec; + void _STI_monitor_staticctor() { if (!inited) @@ -40,15 +73,15 @@ { //printf("_d_monitorenter(%p), %p\n", h, h->monitor); if (!h->monitor) - { CRITICAL_SECTION *cs; + { Monitor *cs; - cs = (CRITICAL_SECTION *)calloc(sizeof(CRITICAL_SECTION), 1); + cs = (Monitor *)calloc(sizeof(Monitor), 1); assert(cs); EnterCriticalSection(&_monitor_critsec); if (!h->monitor) // if, in the meantime, another thread didn't set it { h->monitor = (void *)cs; - InitializeCriticalSection(cs); + InitializeCriticalSection(&cs->mon); cs = NULL; } LeaveCriticalSection(&_monitor_critsec); @@ -56,7 +89,7 @@ free(cs); } //printf("-_d_monitorenter(%p)\n", h); - EnterCriticalSection((CRITICAL_SECTION *)h->monitor); + EnterCriticalSection(MONPTR(h)); //printf("-_d_monitorenter(%p)\n", h); } @@ -64,7 +97,7 @@ { //printf("_d_monitorexit(%p)\n", h); assert(h->monitor); - LeaveCriticalSection((CRITICAL_SECTION *)h->monitor); + LeaveCriticalSection(MONPTR(h)); } /*************************************** @@ -74,12 +107,15 @@ void _d_monitorrelease(Object *h) { if (h->monitor) - { DeleteCriticalSection((CRITICAL_SECTION *)h->monitor); + { + _d_notify_release(h); + + DeleteCriticalSection(MONPTR(h)); // We can improve this by making a free list of monitors free((void *)h->monitor); - h->monitor = 0; + h->monitor = NULL; } } @@ -87,17 +123,12 @@ /* =============================== linux ============================ */ -#if linux +#if USE_PTHREADS // Includes attribute fixes from David Friedman's GDC port -#include - -#include "mars.h" - static pthread_mutex_t _monitor_critsec; static pthread_mutexattr_t _monitors_attr; -static volatile int inited; void _STI_monitor_staticctor() { @@ -123,15 +154,15 @@ { //printf("_d_monitorenter(%p), %p\n", h, h->monitor); if (!h->monitor) - { pthread_mutex_t *cs; + { Monitor *cs; - cs = (pthread_mutex_t *)calloc(sizeof(pthread_mutex_t), 1); + cs = (Monitor *)calloc(sizeof(Monitor), 1); assert(cs); pthread_mutex_lock(&_monitor_critsec); if (!h->monitor) // if, in the meantime, another thread didn't set it { h->monitor = (void *)cs; - pthread_mutex_init(cs, & _monitors_attr); + pthread_mutex_init(&cs->mon, & _monitors_attr); cs = NULL; } pthread_mutex_unlock(&_monitor_critsec); @@ -139,7 +170,7 @@ free(cs); } //printf("-_d_monitorenter(%p)\n", h); - pthread_mutex_lock((pthread_mutex_t *)h->monitor); + pthread_mutex_lock(MONPTR(h)); //printf("-_d_monitorenter(%p)\n", h); } @@ -147,7 +178,7 @@ { //printf("+_d_monitorexit(%p)\n", h); assert(h->monitor); - pthread_mutex_unlock((pthread_mutex_t *)h->monitor); + pthread_mutex_unlock(MONPTR(h)); //printf("-_d_monitorexit(%p)\n", h); } @@ -158,12 +189,15 @@ void _d_monitorrelease(Object *h) { if (h->monitor) - { pthread_mutex_destroy((pthread_mutex_t *)h->monitor); + { + _d_notify_release(h); + + pthread_mutex_destroy(MONPTR(h)); // We can improve this by making a free list of monitors free((void *)h->monitor); - h->monitor = 0; + h->monitor = NULL; } } diff -uNr dmd-0.169/dmd/src/phobos/internal/object.d dmd-0.170/dmd/src/phobos/internal/object.d --- dmd-0.169/dmd/src/phobos/internal/object.d 2006-10-08 01:06:30.000000000 +0200 +++ dmd-0.170/dmd/src/phobos/internal/object.d 2006-10-17 02:36:12.000000000 +0200 @@ -1,5 +1,6 @@ /** + * Part of the D programming language runtime library. * Forms the symbols available to all D programs. Includes * Object, which is the root of the class object heirarchy. * @@ -34,12 +35,17 @@ module object; +import std.outofmemory; + extern (C) { /// C's printf function. int printf(char *, ...); int memcmp(void *, void *, size_t); void* memcpy(void *, void *, size_t); + void* calloc(size_t, size_t); + void* realloc(void*, size_t); + void free(void*); } /// Standard boolean type. @@ -72,6 +78,15 @@ alias uint hash_t; } +/* ************************* + * Internal struct pointed to by the hidden .monitor member. + */ +struct Monitor +{ + void delegate(Object)[] delegates; + + /* More stuff goes here defined by internal/monitor.c */ +} /****************** * All D class objects inherit from Object. @@ -124,21 +139,114 @@ { return this is o; } + + /* ** + * Call delegate dg, passing this to it, when this object gets destroyed. + * Use extreme caution, as the list of delegates is stored in a place + * not known to the gc. Thus, if any objects pointed to by one of these + * delegates gets freed by the gc, calling the delegate will cause a + * crash. + * This is only for use by library developers, as it will need to be + * redone if weak pointers are added or a moving gc is developed. + */ + final void notifyRegister(void delegate(Object) dg) + { + printf("notifyRegister(dg = %llx, o = %p)\n", dg, this); + synchronized (this) + { + Monitor* m = cast(Monitor*)(cast(void**)this)[1]; + foreach (inout x; m.delegates) + { + if (!x || x == dg) + { x = dg; + return; + } + } + + // Increase size of delegates[] + auto len = m.delegates.length; + auto startlen = len; + if (len == 0) + { + len = 4; + auto p = calloc((void delegate(Object)).sizeof, len); + if (!p) + _d_OutOfMemory(); + m.delegates = (cast(void delegate(Object)*)p)[0 .. len]; + } + else + { + len += len + 4; + auto p = realloc(m.delegates.ptr, (void delegate(Object)).sizeof * len); + if (!p) + _d_OutOfMemory(); + m.delegates = (cast(void delegate(Object)*)p)[0 .. len]; + m.delegates[startlen .. len] = null; + } + m.delegates[startlen] = dg; + } + } + + /* ** + * Remove delegate dg from the notify list. + * This is only for use by library developers, as it will need to be + * redone if weak pointers are added or a moving gc is developed. + */ + final void notifyUnRegister(void delegate(Object) dg) + { + synchronized (this) + { + Monitor* m = cast(Monitor*)(cast(void**)this)[1]; + foreach (inout x; m.delegates) + { + if (x == dg) + x = null; + } + } + } +} + +extern (C) void _d_notify_release(Object o) +{ + printf("_d_notify_release(o = %p)\n", o); + Monitor* m = cast(Monitor*)(cast(void**)o)[1]; + if (m.delegates.length) + { + auto dgs = m.delegates; + synchronized (o) + { + dgs = m.delegates; + m.delegates = null; + } + + foreach (dg; dgs) + { + if (dg) + { printf("calling dg = %llx (%p)\n", dg, o); + dg(o); + } + } + + free(dgs.ptr); + } } + /** * Information about an interface. + * A pointer to this appears as the first entry in the interface's vtbl[]. */ struct Interface { - ClassInfo classinfo; /// .classinfo for this interface + ClassInfo classinfo; /// .classinfo for this interface (not for containing class) void *[] vtbl; - int offset; // offset to Interface 'this' from Object 'this' + int offset; /// offset to Interface 'this' from Object 'this' } /** * Runtime type information about a class. Can be retrieved for any class type * or instance by using the .classinfo property. + * A pointer to this appears as the first entry in the class's vtbl[]. */ class ClassInfo : Object { diff -uNr dmd-0.169/dmd/src/phobos/linux.mak dmd-0.170/dmd/src/phobos/linux.mak --- dmd-0.169/dmd/src/phobos/linux.mak 2006-10-08 01:06:30.000000000 +0200 +++ dmd-0.170/dmd/src/phobos/linux.mak 2006-10-17 02:36:10.000000000 +0200 @@ -57,7 +57,7 @@ process.o syserror.o \ socket.o socketstream.o stdarg.o stdio.o format.o \ perf.o openrj.o uni.o trace.o boxer.o \ - demangle.o cover.o bitarray.o \ + demangle.o cover.o bitarray.o aApplyR.o \ ti_wchar.o ti_uint.o ti_short.o ti_ushort.o \ ti_byte.o ti_ubyte.o ti_long.o ti_ulong.o ti_ptr.o \ ti_float.o ti_double.o ti_real.o ti_delegate.o \ @@ -129,7 +129,7 @@ internal/memset.d internal/arraycast.d internal/aaA.d internal/adi.d \ internal/dmain2.d internal/cast.d internal/qsort.d internal/deh2.d \ internal/cmath2.d internal/obj.d internal/mars.h internal/aApply.d \ - internal/object.d internal/trace.d internal/qsort2.d + internal/aApplyR.d internal/object.d internal/trace.d internal/qsort2.d SRC_STD_WIN= std/windows/registry.d \ std/windows/iunknown.d std/windows/charset.d @@ -227,6 +227,9 @@ aApply.o : internal/aApply.d $(DMD) -c $(DFLAGS) internal/aApply.d +aApplyR.o : internal/aApplyR.d + $(DMD) -c $(DFLAGS) internal/aApplyR.d + adi.o : internal/adi.d $(DMD) -c $(DFLAGS) internal/adi.d diff -uNr dmd-0.169/dmd/src/phobos/object.d dmd-0.170/dmd/src/phobos/object.d --- dmd-0.169/dmd/src/phobos/object.d 2006-10-08 01:06:30.000000000 +0200 +++ dmd-0.170/dmd/src/phobos/object.d 2006-10-17 02:36:10.000000000 +0200 @@ -21,6 +21,9 @@ hash_t toHash(); int opCmp(Object o); int opEquals(Object o); + + final void notifyRegister(void delegate(Object) dg); + final void notifyUnRegister(void delegate(Object) dg); } struct Interface diff -uNr dmd-0.169/dmd/src/phobos/std/gc.d dmd-0.170/dmd/src/phobos/std/gc.d --- dmd-0.169/dmd/src/phobos/std/gc.d 2006-10-08 01:06:30.000000000 +0200 +++ dmd-0.170/dmd/src/phobos/std/gc.d 2006-10-17 02:36:10.000000000 +0200 @@ -93,11 +93,12 @@ * disable() temporarilly disables garbage collection cycle, enable() * then reenables them. * - * This is used for brief time - critical sections of code, so the amount of time it will take is predictable. - If the collector runs out of memory while it is disabled, it will throw an - OutOfMemory exception. The disable() function calls can be nested, but must be - matched with corresponding enable() calls. + * This is used for brief time critical sections of code, so the amount of time + * it will take is predictable. + * If the collector runs out of memory while it is disabled, it will throw an + * std.outofmemory.OutOfMemoryException. + * The disable() function calls can be nested, but must be + * matched with corresponding enable() calls. * By default collections are enabled. */ diff -uNr dmd-0.169/dmd/src/phobos/std/math.d dmd-0.170/dmd/src/phobos/std/math.d --- dmd-0.169/dmd/src/phobos/std/math.d 2006-10-08 01:06:30.000000000 +0200 +++ dmd-0.170/dmd/src/phobos/std/math.d 2006-10-17 02:36:10.000000000 +0200 @@ -498,7 +498,7 @@ assert(isPosZero(atanh(0.0))); assert(isNegZero(atanh(-0.0))); assert(isnan(atanh(real.nan))); - assert(isNegZero(atanh(-real.infinity))); + assert(isnan(atanh(-real.infinity))); } /***************************************** diff -uNr dmd-0.169/dmd/src/phobos/std/outofmemory.d dmd-0.170/dmd/src/phobos/std/outofmemory.d --- dmd-0.169/dmd/src/phobos/std/outofmemory.d 2006-10-08 01:06:30.000000000 +0200 +++ dmd-0.170/dmd/src/phobos/std/outofmemory.d 2006-10-17 02:36:10.000000000 +0200 @@ -1,10 +1,25 @@ +/** + * Macros: + * WIKI=Phobos/StdOutOfMemory + * Copyright: + * Placed into public domain. + * www.digitalmars.com + */ + module std.outofmemory; +/****** + * This exception is thrown when out of memory errors happen. + */ + class OutOfMemoryException : Exception { static char[] s = "Out of memory"; + /** + * Default constructor + */ this() { super(s); @@ -23,3 +38,6 @@ OutOfMemoryException.classinfo.init; } +static this() +{ +} diff -uNr dmd-0.169/dmd/src/phobos/std/path.d dmd-0.170/dmd/src/phobos/std/path.d --- dmd-0.169/dmd/src/phobos/std/path.d 2006-10-08 01:06:30.000000000 +0200 +++ dmd-0.170/dmd/src/phobos/std/path.d 2006-10-17 02:36:10.000000000 +0200 @@ -978,7 +978,8 @@ * if it could not be expanded. * For Windows, expandTilde() merely returns its argument inputPath. * - * Throws: std.OutOfMemory if there is not enough memory to perform + * Throws: std.outofmemory.OutOfMemoryException if there is not enough + * memory to perform * the database lookup for the ~user syntax. * * Examples: diff -uNr dmd-0.169/dmd/src/phobos/std/zlib.d dmd-0.170/dmd/src/phobos/std/zlib.d --- dmd-0.169/dmd/src/phobos/std/zlib.d 2006-10-08 01:06:30.000000000 +0200 +++ dmd-0.170/dmd/src/phobos/std/zlib.d 2006-10-17 02:36:10.000000000 +0200 @@ -342,7 +342,7 @@ body { void[] destbuf; - void[] tmpbuf; + ubyte[512] tmpbuf; int err; if (!inited) @@ -351,8 +351,8 @@ /* may be zs.avail_out+ * zs.avail_out is set nonzero by deflate in previous compress() */ - tmpbuf = new void[zs.avail_out]; - zs.next_out = cast(ubyte*) tmpbuf; + //tmpbuf = new void[zs.avail_out]; + zs.next_out = tmpbuf; zs.avail_out = tmpbuf.length; while( (err = deflate(&zs, mode)) != Z_STREAM_END) @@ -364,7 +364,7 @@ else if(zs.avail_out == 0) { destbuf ~= tmpbuf; - zs.next_out = cast(ubyte*) tmpbuf; + zs.next_out = tmpbuf; zs.avail_out = tmpbuf.length; continue; } diff -uNr dmd-0.169/dmd/src/phobos/std.ddoc dmd-0.170/dmd/src/phobos/std.ddoc --- dmd-0.169/dmd/src/phobos/std.ddoc 2006-10-08 01:06:30.000000000 +0200 +++ dmd-0.170/dmd/src/phobos/std.ddoc 2006-10-17 02:36:10.000000000 +0200 @@ -128,6 +128,7 @@ $(LI std.mmfile) $(LI std.openrj) $(LI std.outbuffer) + $(LI std.outofmemory) $(LI std.path) $(LI std.process) $(LI std.random) diff -uNr dmd-0.169/dmd/src/phobos/unittest.d dmd-0.170/dmd/src/phobos/unittest.d --- dmd-0.169/dmd/src/phobos/unittest.d 2006-10-08 01:06:30.000000000 +0200 +++ dmd-0.170/dmd/src/phobos/unittest.d 2006-10-17 02:36:10.000000000 +0200 @@ -114,6 +114,9 @@ std.file.exists("foo"); + foreach_reverse (dchar d; "hello"c) { ; } + foreach_reverse (k, dchar d; "hello"c) { ; } + printf("Success\n!"); return 0; } diff -uNr dmd-0.169/dmd/src/phobos/win32.mak dmd-0.170/dmd/src/phobos/win32.mak --- dmd-0.169/dmd/src/phobos/win32.mak 2006-10-08 01:06:30.000000000 +0200 +++ dmd-0.170/dmd/src/phobos/win32.mak 2006-10-17 02:36:10.000000000 +0200 @@ -73,7 +73,7 @@ socket.obj socketstream.obj loader.obj stdarg.obj format.obj stdio.obj \ perf.obj openrj.obj uni.obj winsock.obj oldsyserror.obj \ errno.obj boxer.obj cstream.obj charset.obj \ - gamma.obj demangle.obj cover.obj bitarray.obj \ + gamma.obj demangle.obj cover.obj bitarray.obj aApplyR.obj \ ti_Aa.obj ti_Ag.obj ti_C.obj ti_int.obj ti_char.obj \ ti_wchar.obj ti_uint.obj ti_short.obj ti_ushort.obj \ ti_byte.obj ti_ubyte.obj ti_long.obj ti_ulong.obj ti_ptr.obj \ @@ -105,6 +105,7 @@ $(DOC)\std_intrinsic.html \ $(DOC)\std_mmfile.html \ $(DOC)\std_openrj.html \ + $(DOC)\std_outofmemory.html \ $(DOC)\std_process.html \ $(DOC)\std_regexp.html \ $(DOC)\std_socket.html \ @@ -179,7 +180,7 @@ internal\memset.d internal\arraycast.d internal\aaA.d internal\adi.d \ internal\dmain2.d internal\cast.d internal\qsort.d internal\deh2.d \ internal\cmath2.d internal\obj.d internal\mars.h internal\aApply.d \ - internal\object.d internal\trace.d internal\qsort2.d + internal\aApplyR.d internal\object.d internal\trace.d internal\qsort2.d SRC_STD_WIN= std\windows\registry.d \ std\windows\iunknown.d std\windows\syserror.d std\windows\charset.d @@ -265,6 +266,9 @@ aApply.obj : internal\aApply.d $(DMD) -c $(DFLAGS) internal\aApply.d +aApplyR.obj : internal\aApplyR.d + $(DMD) -c $(DFLAGS) internal\aApplyR.d + adi.obj : internal\adi.d $(DMD) -c $(DFLAGS) internal\adi.d @@ -693,6 +697,9 @@ $(DOC)\std_outbuffer.html : std.ddoc std\outbuffer.d $(DMD) -c -o- $(DFLAGS) -Df$(DOC)\std_outbuffer.html std.ddoc std\outbuffer.d +$(DOC)\std_outofmemory.html : std.ddoc std\outofmemory.d + $(DMD) -c -o- $(DFLAGS) -Df$(DOC)\std_outofmemory.html std.ddoc std\outofmemory.d + $(DOC)\std_path.html : std.ddoc std\path.d $(DMD) -c -o- $(DFLAGS) -Df$(DOC)\std_path.html std.ddoc std\path.d