Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

Changeset 295

Show
Ignore:
Timestamp:
12/15/09 23:46:13 (15 years ago)
Author:
walter
Message:

prefer opApply to range

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/src/opover.c

    r269 r295  
    578578        if (arguments->dim == 2) 
    579579        { 
    580580        if (!arg->type) 
    581581            arg->type = taa->index; // key type 
    582582        arg = (Parameter *)arguments->data[1]; 
    583583        } 
    584584        if (!arg->type) 
    585585        arg->type = taa->next;      // value type 
    586586        break; 
    587587    } 
    588588 
    589589    case Tclass: 
    590590        ad = ((TypeClass *)tab)->sym; 
    591591        goto Laggr; 
    592592 
    593593    case Tstruct: 
    594594        ad = ((TypeStruct *)tab)->sym; 
    595595        goto Laggr; 
    596596 
    597597    Laggr: 
     598        Dsymbol *s = search_function(ad, 
     599            (op == TOKforeach_reverse) ? Id::applyReverse 
     600                           : Id::apply); 
     601        if (s) 
     602        goto Lapply;            // prefer opApply 
     603 
    598604        if (arguments->dim == 1) 
    599605        { 
    600606        if (!arg->type) 
    601607        { 
    602608            /* Look for a head() or rear() overload 
    603609             */ 
    604610            Identifier *id = (op == TOKforeach) ? Id::Fhead : Id::Ftoe; 
    605611            Dsymbol *s = search_function(ad, id); 
    606612            FuncDeclaration *fd = s ? s->isFuncDeclaration() : NULL; 
    607613            if (!fd) 
    608614            {   if (s && s->isTemplateDeclaration()) 
    609615                break; 
    610616            goto Lapply; 
    611617            } 
    612618            arg->type = fd->type->nextOf(); 
    613619        } 
    614620        break; 
    615621        } 
    616622 
    617623    Lapply: 
    618624    {   /* Look for an 
    619625         *  int opApply(int delegate(ref Type [, ...]) dg); 
    620626         * overload 
    621627         */ 
    622         Dsymbol *s = search_function(ad, 
    623             (op == TOKforeach_reverse) ? Id::applyReverse 
    624                            : Id::apply); 
    625628        if (s) 
    626629        { 
    627630        FuncDeclaration *fd = s->isFuncDeclaration(); 
    628631        if (fd)  
    629632        {   inferApplyArgTypesX(fd, arguments); 
    630633            break; 
    631634        } 
    632635#if 0 
    633636        TemplateDeclaration *td = s->isTemplateDeclaration(); 
    634637        if (td) 
    635638        {   inferApplyArgTypesZ(td, arguments); 
    636639            break; 
    637640        } 
    638641#endif 
    639642        } 
    640643        break; 
    641644    } 
    642645 
    643646    case Tdelegate: 
    644647    { 
  • trunk/src/statement.c

    r273 r295  
    12901290 
    12911291    this->func = NULL; 
    12921292} 
    12931293 
    12941294Statement *ForeachStatement::syntaxCopy() 
    12951295{ 
    12961296    Parameters *args = Parameter::arraySyntaxCopy(arguments); 
    12971297    Expression *exp = aggr->syntaxCopy(); 
    12981298    ForeachStatement *s = new ForeachStatement(loc, op, args, exp, 
    12991299    body ? body->syntaxCopy() : NULL); 
    13001300    return s; 
    13011301} 
    13021302 
    13031303Statement *ForeachStatement::semantic(Scope *sc) 
    13041304{ 
    13051305    //printf("ForeachStatement::semantic() %p\n", this); 
    13061306    ScopeDsymbol *sym; 
    13071307    Statement *s = this; 
    13081308    size_t dim = arguments->dim; 
    13091309    TypeAArray *taa = NULL; 
     1310    Dsymbol *sapply = NULL; 
    13101311 
    13111312    Type *tn = NULL; 
    13121313    Type *tnv = NULL; 
    13131314 
    13141315    func = sc->func; 
    13151316    if (func->fes) 
    13161317    func = func->fes->func; 
    13171318 
    13181319    aggr = aggr->semantic(sc); 
    13191320    aggr = resolveProperties(sc, aggr); 
    13201321    aggr = aggr->optimize(WANTvalue); 
    13211322    if (!aggr->type) 
    13221323    { 
    13231324    error("invalid foreach aggregate %s", aggr->toChars()); 
    13241325    return this; 
    13251326    } 
    13261327 
    13271328    inferApplyArgTypes(op, arguments, aggr); 
    13281329 
    13291330    /* Check for inference errors 
     
    14211422        st->push(new ExpStatement(loc, de)); 
    14221423 
    14231424        st->push(body->syntaxCopy()); 
    14241425        s = new CompoundStatement(loc, st); 
    14251426        s = new ScopeStatement(loc, s); 
    14261427        statements->push(s); 
    14271428    } 
    14281429 
    14291430    s = new UnrolledLoopStatement(loc, statements); 
    14301431    s = s->semantic(sc); 
    14311432    return s; 
    14321433    } 
    14331434 
    14341435    sym = new ScopeDsymbol(); 
    14351436    sym->parent = sc->scopesym; 
    14361437    sc = sc->push(sym); 
    14371438 
    14381439    sc->noctor++; 
    14391440 
    14401441Lagain: 
     1442    Identifier *idapply = (op == TOKforeach_reverse) 
     1443            ? Id::applyReverse : Id::apply; 
     1444    sapply = NULL; 
    14411445    switch (tab->ty) 
    14421446    { 
    14431447    case Tarray: 
    14441448    case Tsarray: 
    14451449        if (!checkForArgTypes()) 
    14461450        return this; 
    14471451 
    14481452        if (dim < 1 || dim > 2) 
    14491453        { 
    14501454        error("only one or two arguments for array foreach"); 
    14511455        break; 
    14521456        } 
    14531457 
    14541458        /* Look for special case of parsing char types out of char type 
    14551459         * array. 
    14561460         */ 
    14571461        tn = tab->nextOf()->toBasetype(); 
    14581462        if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar) 
    14591463        {   Parameter *arg; 
    14601464 
     
    16031607        if (dim < 1 || dim > 2) 
    16041608        { 
    16051609        error("only one or two arguments for associative array foreach"); 
    16061610        break; 
    16071611        } 
    16081612#if SARRAYVALUE 
    16091613        /* This only works if Key or Value is a static array. 
    16101614         */ 
    16111615        tab = taa->getImpl()->type; 
    16121616        goto Lagain; 
    16131617#else 
    16141618        if (op == TOKforeach_reverse) 
    16151619        { 
    16161620        error("no reverse iteration on associative arrays"); 
    16171621        } 
    16181622        goto Lapply; 
    16191623#endif 
    16201624    case Tclass: 
    16211625    case Tstruct: 
    16221626#if DMDV2 
     1627        /* Prefer using opApply, if it exists 
     1628         */ 
     1629        if (dim != 1)   // only one argument allowed with ranges 
     1630        goto Lapply; 
     1631 
     1632        sapply = search_function((AggregateDeclaration *)tab->toDsymbol(sc), idapply); 
     1633        if (sapply) 
     1634        goto Lapply; 
     1635 
    16231636    {   /* Look for range iteration, i.e. the properties 
    16241637         * .empty, .next, .retreat, .head and .rear 
    16251638         *    foreach (e; aggr) { ... } 
    16261639         * translates to: 
    16271640         *    for (auto __r = aggr[]; !__r.empty; __r.next) 
    16281641         *    {   auto e = __r.head; 
    16291642         *        ... 
    16301643         *    } 
    16311644         */ 
    1632         if (dim != 1)   // only one argument allowed with ranges 
    1633         goto Lapply; 
    16341645        AggregateDeclaration *ad = (tab->ty == Tclass) 
    16351646            ? (AggregateDeclaration *)((TypeClass  *)tab)->sym 
    16361647            : (AggregateDeclaration *)((TypeStruct *)tab)->sym; 
    16371648        Identifier *idhead; 
    16381649        Identifier *idnext; 
    16391650        if (op == TOKforeach) 
    16401651        {   idhead = Id::Fhead; 
    16411652        idnext = Id::Fnext; 
    16421653        } 
    16431654        else 
    16441655        {   idhead = Id::Ftoe; 
    16451656        idnext = Id::Fretreat; 
    16461657        } 
    16471658        Dsymbol *shead = search_function(ad, idhead); 
    16481659        if (!shead) 
    16491660        goto Lapply; 
    16501661 
    16511662        /* Generate a temporary __r and initialize it with the aggregate. 
    16521663         */ 
    16531664        Identifier *id = Identifier::generateId("__r"); 
     
    16821693        ve->storage_class |= arg->storageClass & (STCin | STCout | STCref | STC_TYPECTOR); 
    16831694 
    16841695        DeclarationExp *de = new DeclarationExp(loc, ve); 
    16851696 
    16861697        Statement *body = new CompoundStatement(loc, 
    16871698        new DeclarationStatement(loc, de), this->body); 
    16881699 
    16891700        s = new ForStatement(loc, init, condition, increment, body); 
    16901701#if 0 
    16911702        printf("init: %s\n", init->toChars()); 
    16921703        printf("condition: %s\n", condition->toChars()); 
    16931704        printf("increment: %s\n", increment->toChars()); 
    16941705        printf("body: %s\n", body->toChars()); 
    16951706#endif 
    16961707        s = s->semantic(sc); 
    16971708        break; 
    16981709    } 
    16991710#endif 
    17001711    case Tdelegate: 
    17011712    Lapply: 
    1702     {   FuncDeclaration *fdapply; 
    1703         Parameters *args; 
     1713    { 
    17041714        Expression *ec; 
    17051715        Expression *e; 
    1706         FuncLiteralDeclaration *fld; 
    17071716        Parameter *a; 
    1708         Type *t; 
    1709         Expression *flde; 
    1710         Identifier *id; 
    1711         Type *tret; 
    17121717 
    17131718        if (!checkForArgTypes()) 
    17141719        {   body = body->semantic(sc); 
    17151720        return this; 
    17161721        } 
    17171722 
    1718         tret = func->type->nextOf(); 
     1723        Type *tret = func->type->nextOf(); 
    17191724 
    17201725        // Need a variable to hold value from any return statements in body. 
    17211726        if (!sc->func->vresult && tret && tret != Type::tvoid) 
    1722         {   VarDeclaration *v; 
    1723  
    1724         v = new VarDeclaration(loc, tret, Id::result, NULL); 
     1727        { 
     1728        VarDeclaration *v = new VarDeclaration(loc, tret, Id::result, NULL); 
    17251729        v->noauto = 1; 
    17261730        v->semantic(sc); 
    17271731        if (!sc->insert(v)) 
    17281732            assert(0); 
    17291733        v->parent = sc->func; 
    17301734        sc->func->vresult = v; 
    17311735        } 
    17321736 
    17331737        /* Turn body into the function literal: 
    17341738         *  int delegate(ref T arg) { body } 
    17351739         */ 
    1736         args = new Parameters(); 
     1740        Parameters *args = new Parameters(); 
    17371741        for (size_t i = 0; i < dim; i++) 
    17381742        {   Parameter *arg = (Parameter *)arguments->data[i]; 
     1743        Identifier *id; 
    17391744 
    17401745        arg->type = arg->type->semantic(loc, sc); 
    17411746        if (arg->storageClass & STCref) 
    17421747            id = arg->ident; 
    17431748        else 
    17441749        {   // Make a copy of the ref argument so it isn't 
    17451750            // a reference. 
    1746             VarDeclaration *v; 
    1747             Initializer *ie; 
    17481751 
    17491752            id = Lexer::uniqueId("__applyArg", i); 
    1750  
    1751             ie = new ExpInitializer(0, new IdentifierExp(0, id)); 
    1752             v = new VarDeclaration(0, arg->type, arg->ident, ie); 
     1753            Initializer *ie = new ExpInitializer(0, new IdentifierExp(0, id)); 
     1754            VarDeclaration *v = new VarDeclaration(0, arg->type, arg->ident, ie); 
    17531755            s = new DeclarationStatement(0, v); 
    17541756            body = new CompoundStatement(loc, s, body); 
    17551757        } 
    17561758        a = new Parameter(STCref, arg->type, id, NULL); 
    17571759        args->push(a); 
    17581760        } 
    1759         t = new TypeFunction(args, Type::tint32, 0, LINKd); 
    1760         fld = new FuncLiteralDeclaration(loc, 0, t, TOKdelegate, this); 
     1761        Type *t = new TypeFunction(args, Type::tint32, 0, LINKd); 
     1762        FuncLiteralDeclaration *fld = new FuncLiteralDeclaration(loc, 0, t, TOKdelegate, this); 
    17611763        fld->fbody = body; 
    1762         flde = new FuncExp(loc, fld); 
     1764        Expression *flde = new FuncExp(loc, fld); 
    17631765        flde = flde->semantic(sc); 
    17641766        fld->tookAddressOf = 0; 
    17651767 
    17661768        // Resolve any forward referenced goto's 
    1767         for (int i = 0; i < gotos.dim; i++) 
     1769        for (size_t i = 0; i < gotos.dim; i++) 
    17681770        {   CompoundStatement *cs = (CompoundStatement *)gotos.data[i]; 
    17691771        GotoStatement *gs = (GotoStatement *)cs->statements->data[0]; 
    17701772 
    17711773        if (!gs->label->statement) 
    17721774        {   // 'Promote' it to this scope, and replace with a return 
    17731775            cases.push(gs); 
    17741776            s = new ReturnStatement(0, new IntegerExp(cases.dim + 1)); 
    17751777            cs->statements->data[0] = (void *)s; 
    17761778        } 
    17771779        } 
    17781780 
    17791781        if (tab->ty == Taarray) 
    17801782        { 
    17811783        // Check types 
    17821784        Parameter *arg = (Parameter *)arguments->data[0]; 
    17831785        if (dim == 2) 
    17841786        { 
    17851787            if (arg->storageClass & STCref) 
    17861788            error("foreach: index cannot be ref"); 
    17871789            if (!arg->type->equals(taa->index)) 
    17881790            error("foreach: index must be type %s, not %s", taa->index->toChars(), arg->type->toChars()); 
    17891791            arg = (Parameter *)arguments->data[1]; 
    17901792        } 
    17911793        if (!arg->type->equals(taa->nextOf())) 
    17921794            error("foreach: value must be type %s, not %s", taa->nextOf()->toChars(), arg->type->toChars()); 
    17931795 
    17941796        /* Call: 
    17951797         *  _aaApply(aggr, keysize, flde) 
    17961798         */ 
     1799        FuncDeclaration *fdapply; 
    17971800        if (dim == 2) 
    17981801            fdapply = FuncDeclaration::genCfunc(Type::tindex, "_aaApply2"); 
    17991802        else 
    18001803            fdapply = FuncDeclaration::genCfunc(Type::tindex, "_aaApply"); 
    18011804        ec = new VarExp(0, fdapply); 
    18021805        Expressions *exps = new Expressions(); 
    18031806        exps->push(aggr); 
    18041807        size_t keysize = taa->index->size(); 
    18051808        keysize = (keysize + (PTRSIZE-1)) & ~(PTRSIZE-1); 
    18061809        exps->push(new IntegerExp(0, keysize, Type::tsize_t)); 
    18071810        exps->push(flde); 
    18081811        e = new CallExp(loc, ec, exps); 
    18091812        e->type = Type::tindex; // don't run semantic() on e 
    18101813        } 
    18111814        else if (tab->ty == Tarray || tab->ty == Tsarray) 
    18121815        { 
    18131816        /* Call: 
    18141817         *  _aApply(aggr, flde) 
    18151818         */ 
    18161819        static char fntab[9][3] = 
     
    18211824        char fdname[7+1+2+ sizeof(dim)*3 + 1]; 
    18221825        int flag; 
    18231826 
    18241827        switch (tn->ty) 
    18251828        { 
    18261829            case Tchar:     flag = 0; break; 
    18271830            case Twchar:    flag = 3; break; 
    18281831            case Tdchar:    flag = 6; break; 
    18291832            default:        assert(0); 
    18301833        } 
    18311834        switch (tnv->ty) 
    18321835        { 
    18331836            case Tchar:     flag += 0; break; 
    18341837            case Twchar:    flag += 1; break; 
    18351838            case Tdchar:    flag += 2; break; 
    18361839            default:        assert(0); 
    18371840        } 
    18381841        const char *r = (op == TOKforeach_reverse) ? "R" : ""; 
    18391842        int j = sprintf(fdname, "_aApply%s%.*s%zd", r, 2, fntab[flag], dim); 
    18401843        assert(j < sizeof(fdname)); 
    1841         fdapply = FuncDeclaration::genCfunc(Type::tindex, fdname); 
     1844        FuncDeclaration *fdapply = FuncDeclaration::genCfunc(Type::tindex, fdname); 
    18421845 
    18431846        ec = new VarExp(0, fdapply); 
    18441847        Expressions *exps = new Expressions(); 
    18451848        if (tab->ty == Tsarray) 
    18461849           aggr = aggr->castTo(sc, tn->arrayOf()); 
    18471850        exps->push(aggr); 
    18481851        exps->push(flde); 
    18491852        e = new CallExp(loc, ec, exps); 
    18501853        e->type = Type::tindex; // don't run semantic() on e 
    18511854        } 
    18521855        else if (tab->ty == Tdelegate) 
    18531856        { 
    18541857        /* Call: 
    18551858         *  aggr(flde) 
    18561859         */ 
    18571860        Expressions *exps = new Expressions(); 
    18581861        exps->push(flde); 
    18591862        e = new CallExp(loc, aggr, exps); 
    18601863        e = e->semantic(sc); 
    18611864        if (e->type != Type::tint32) 
    18621865            error("opApply() function for %s must return an int", tab->toChars()); 
    18631866        } 
    18641867        else 
    18651868        { 
    18661869        assert(tab->ty == Tstruct || tab->ty == Tclass); 
    1867         Identifier *idapply = (op == TOKforeach_reverse) 
    1868                 ? Id::applyReverse : Id::apply; 
    1869         Dsymbol *sapply = search_function((AggregateDeclaration *)tab->toDsymbol(sc), idapply); 
    18701870            Expressions *exps = new Expressions(); 
     1871        if (!sapply) 
     1872            sapply = search_function((AggregateDeclaration *)tab->toDsymbol(sc), idapply); 
    18711873#if 0 
    18721874        TemplateDeclaration *td; 
    18731875        if (sapply && 
    18741876            (td = sapply->isTemplateDeclaration()) != NULL) 
    18751877        {   /* Call: 
    18761878             *  aggr.apply!(fld)() 
    18771879             */ 
    18781880            Objects *tiargs = new Objects(); 
    18791881            tiargs->push(fld); 
    18801882            ec = new DotTemplateInstanceExp(loc, aggr, idapply, tiargs); 
    18811883        } 
    18821884        else 
    18831885#endif 
    18841886        { 
    18851887            /* Call: 
    18861888             *  aggr.apply(flde) 
    18871889             */ 
    18881890            ec = new DotIdExp(loc, aggr, idapply); 
    18891891            exps->push(flde); 
    18901892        } 
  • trunk/src/template.c

    r294 r295  
    37363736    __except (__ehfilter(GetExceptionInformation())) 
    37373737    { 
    37383738        global.gag = 0;            // ensure error message gets printed 
    37393739        error("recursive expansion"); 
    37403740        fatal(); 
    37413741    } 
    37423742#endif 
    37433743    } 
    37443744 
    37453745  Laftersemantic: 
    37463746    sc2->pop(); 
    37473747 
    37483748    scope->pop(); 
    37493749 
    37503750    // Give additional context info if error occurred during instantiation 
    37513751    if (global.errors != errorsave) 
    37523752    { 
    37533753    error("error instantiating"); 
    37543754    if (tinst) 
    37553755    {   tinst->printInstantiationTrace(); 
    3756         fatal(); 
    37573756    } 
    37583757    errors = 1; 
    37593758    if (global.gag) 
    37603759        tempdecl->instances.remove(tempdecl_instance_idx); 
    37613760    } 
    37623761 
    37633762#if LOG 
    37643763    printf("-TemplateInstance::semantic('%s', this=%p)\n", toChars(), this); 
    37653764#endif 
    37663765} 
    37673766 
    37683767 
    37693768void TemplateInstance::semanticTiargs(Scope *sc) 
    37703769{ 
    37713770    //printf("+TemplateInstance::semanticTiargs() %s\n", toChars()); 
    37723771    if (semantictiargsdone) 
    37733772    return; 
    37743773    semantictiargsdone = 1; 
    37753774    semanticTiargs(loc, sc, tiargs, 0); 
    37763775}