void inferApplyArgTypes(enum TOK op, Parameters *arguments, Expression *aggr, Module* from) { if (!arguments || !arguments->dim) return; /* Return if no arguments need types. */ for (size_t u = 0; 1; u++) { if (u == arguments->dim) return; Parameter *arg = arguments->tdata()[u]; if (!arg->type) break; } Dsymbol *s; AggregateDeclaration *ad; Parameter *arg = arguments->tdata()[0]; Type *taggr = aggr->type; if (!taggr) return; Type *tab = taggr->toBasetype(); switch (tab->ty) { case Tarray: case Tsarray: case Ttuple: if (arguments->dim == 2) { if (!arg->type) arg->type = Type::tsize_t; // key type arg = arguments->tdata()[1]; } if (!arg->type && tab->ty != Ttuple) arg->type = tab->nextOf(); // value type break; case Taarray: { TypeAArray *taa = (TypeAArray *)tab; if (arguments->dim == 2) { if (!arg->type) arg->type = taa->index; // key type arg = arguments->tdata()[1]; } if (!arg->type) arg->type = taa->next; // value type break; } case Tclass: ad = ((TypeClass *)tab)->sym; goto Laggr; case Tstruct: ad = ((TypeStruct *)tab)->sym; goto Laggr; Laggr: s = search_function(ad, (op == TOKforeach_reverse) ? Id::applyReverse : Id::apply); if (s) goto Lapply; // prefer opApply if (arguments->dim == 1) { if (!arg->type) { /* Look for a head() or rear() overload */ Identifier *id = (op == TOKforeach) ? Id::Fhead : Id::Ftoe; Dsymbol *s = search_function(ad, id); FuncDeclaration *fd = s ? s->isFuncDeclaration() : NULL; if (!fd) { if (s && s->isTemplateDeclaration()) break; goto Lapply; } arg->type = fd->type->nextOf(); } break; } Lapply: { /* Look for an * int opApply(int delegate(ref Type [, ...]) dg); * overload */ if (s) { FuncDeclaration *fd = s->isFuncDeclaration(); if (fd) { inferApplyArgTypesX(from, fd, arguments); break; } #if 0 TemplateDeclaration *td = s->isTemplateDeclaration(); if (td) { inferApplyArgTypesZ(td, arguments); break; } #endif } break; } case Tdelegate: { if (0 && aggr->op == TOKdelegate) { DelegateExp *de = (DelegateExp *)aggr; FuncDeclaration *fd = de->func->isFuncDeclaration(); if (fd) inferApplyArgTypesX(from, fd, arguments); } else { inferApplyArgTypesY((TypeFunction *)tab->nextOf(), arguments); } break; } default: break; // ignore error, caught later } }
int ForeachStatement::inferApplyArgTypes(Scope *sc, Dsymbol *&sapply) { if (!arguments || !arguments->dim) return 0; if (sapply) // prefer opApply { for (size_t u = 0; u < arguments->dim; u++) { Parameter *arg = (*arguments)[u]; if (arg->type) { arg->type = arg->type->semantic(loc, sc); arg->type = arg->type->addStorageClass(arg->storageClass); } } Expression *ethis; Type *tab = aggr->type->toBasetype(); if (tab->ty == Tclass || tab->ty == Tstruct) ethis = aggr; else { assert(tab->ty == Tdelegate && aggr->op == TOKdelegate); ethis = ((DelegateExp *)aggr)->e1; } /* Look for like an * int opApply(int delegate(ref Type [, ...]) dg); * overload */ FuncDeclaration *fd = sapply->isFuncDeclaration(); if (fd) { sapply = inferApplyArgTypesX(ethis, fd, arguments); } #if 0 TemplateDeclaration *td = sapply->isTemplateDeclaration(); if (td) { inferApplyArgTypesZ(td, arguments); } #endif return sapply ? 1 : 0; } /* Return if no arguments need types. */ for (size_t u = 0; u < arguments->dim; u++) { Parameter *arg = (*arguments)[u]; if (!arg->type) break; } AggregateDeclaration *ad; Parameter *arg = (*arguments)[0]; Type *taggr = aggr->type; assert(taggr); Type *tab = taggr->toBasetype(); switch (tab->ty) { case Tarray: case Tsarray: case Ttuple: if (arguments->dim == 2) { if (!arg->type) { arg->type = Type::tsize_t; // key type arg->type = arg->type->addStorageClass(arg->storageClass); } arg = (*arguments)[1]; } if (!arg->type && tab->ty != Ttuple) { arg->type = tab->nextOf(); // value type arg->type = arg->type->addStorageClass(arg->storageClass); } break; case Taarray: { TypeAArray *taa = (TypeAArray *)tab; if (arguments->dim == 2) { if (!arg->type) { arg->type = taa->index; // key type arg->type = arg->type->addStorageClass(arg->storageClass); } arg = (*arguments)[1]; } if (!arg->type) { arg->type = taa->next; // value type arg->type = arg->type->addStorageClass(arg->storageClass); } break; } case Tclass: ad = ((TypeClass *)tab)->sym; goto Laggr; case Tstruct: ad = ((TypeStruct *)tab)->sym; goto Laggr; Laggr: if (arguments->dim == 1) { if (!arg->type) { /* Look for a front() or back() overload */ Identifier *id = (op == TOKforeach) ? Id::Ffront : Id::Fback; Dsymbol *s = ad->search(Loc(), id, 0); FuncDeclaration *fd = s ? s->isFuncDeclaration() : NULL; if (fd) { // Resolve inout qualifier of front type arg->type = fd->type->nextOf(); if (arg->type) { arg->type = arg->type->substWildTo(tab->mod); arg->type = arg->type->addStorageClass(arg->storageClass); } } else if (s && s->isTemplateDeclaration()) ; else if (s && s->isDeclaration()) arg->type = ((Declaration *)s)->type; else break; } break; } break; case Tdelegate: { if (!inferApplyArgTypesY((TypeFunction *)tab->nextOf(), arguments)) return 0; break; } default: break; // ignore error, caught later } return 1; }