void inferApplyArgTypesZ(TemplateDeclaration *tstart, Parameters *arguments) { for (TemplateDeclaration *td = tstart; td; td = td->overnext) { if (!td->scope) { error("forward reference to template %s", td->toChars()); return; } if (!td->onemember || !td->onemember->toAlias()->isFuncDeclaration()) { error("is not a function template"); return; } if (!td->parameters || td->parameters->dim != 1) continue; TemplateParameter *tp = td->parameters->tdata()[0]; TemplateAliasParameter *tap = tp->isTemplateAliasParameter(); if (!tap || !tap->specType || tap->specType->ty != Tfunction) continue; TypeFunction *tf = (TypeFunction *)tap->specType; if (inferApplyArgTypesY(tf, arguments) == 0) // found it return; } }
static Dsymbol *inferApplyArgTypesX(Expression *ethis, FuncDeclaration *fstart, Parameters *arguments) { struct Param3 { Parameters *arguments; int mod; MATCH match; FuncDeclaration *fd_best; FuncDeclaration *fd_ambig; static int fp(void *param, FuncDeclaration *f) { Param3 *p = (Param3 *)param; TypeFunction *tf = (TypeFunction *)f->type; MATCH m = MATCHexact; if (f->isThis()) { if (!MODimplicitConv(p->mod, tf->mod)) m = MATCHnomatch; else if (p->mod != tf->mod) m = MATCHconst; } if (!inferApplyArgTypesY(tf, p->arguments, 1)) m = MATCHnomatch; if (m > p->match) { p->fd_best = f; p->fd_ambig = NULL; p->match = m; } else if (m == p->match) p->fd_ambig = f; return 0; } }; Param3 p; p.arguments = arguments; p.mod = ethis->type->mod; p.match = MATCHnomatch; p.fd_best = NULL; p.fd_ambig = NULL; overloadApply(fstart, &Param3::fp, &p); if (p.fd_best) { inferApplyArgTypesY((TypeFunction *)p.fd_best->type, arguments); if (p.fd_ambig) { ::error(ethis->loc, "%s.%s matches more than one declaration:\n\t%s(%d):%s\nand:\n\t%s(%d):%s", ethis->toChars(), fstart->ident->toChars(), p.fd_best ->loc.filename, p.fd_best ->loc.linnum, p.fd_best ->type->toChars(), p.fd_ambig->loc.filename, p.fd_ambig->loc.linnum, p.fd_ambig->type->toChars()); p.fd_best = NULL; } } return p.fd_best; }
int fp3(void *param, FuncDeclaration *f) { Parameters *arguments = (Parameters *)param; TypeFunction *tf = (TypeFunction *)f->type; if (inferApplyArgTypesY(tf, arguments) == 1) return 0; if (arguments->dim == 0) return 1; return 0; }
static int fp(void *param, FuncDeclaration *f) { Param3 *p = (Param3 *)param; TypeFunction *tf = (TypeFunction *)f->type; MATCH m = MATCHexact; if (f->isThis()) { if (!MODimplicitConv(p->mod, tf->mod)) m = MATCHnomatch; else if (p->mod != tf->mod) m = MATCHconst; } if (!inferApplyArgTypesY(tf, p->arguments, 1)) m = MATCHnomatch; if (m > p->match) { p->fd_best = f; p->fd_ambig = NULL; p->match = m; } else if (m == p->match) p->fd_ambig = f; return 0; }
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; }