Rev 40900 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
### merge version called from namespace imports code. Hope to avoid using generic.mergeMethodsTable2 <- function(table, newtable, envir, metaname) {old <- objects(table, all=TRUE)mm <- 1for( what in old) {mm = get(what, envir =table)if(is(mm, "MethodDefinition")) {mm = length(mm@defined)break}}new = objects(newtable, all=TRUE)## check that signature length doesn't changecanStore <- TRUEfor(what in new) {obj <- get(what, envir = newtable)if(is(obj, "MethodDefinition") &&length(obj@defined) != mm) {canStore <- FALSEbreak}}if(canStore) {for(what in new)assign(what, get(what, envir = newtable), envir = table)table}else { # rats! have to get the generic functionf <- gsub(".__T__(.*):([^:]+)", "\\1", metaname)package <- gsub(".__T__(.*):([^:]+(.*))", "\\2", metaname)generic <- getGeneric(f, TRUE, envir, package).mergeMethodsTable(generic, table, newtable, TRUE)table}}## action on attach, detach to merge methods tables.mergeMethodsTable <- function(generic, table, newtable, add = TRUE) {fenv <- environment(generic)signature <- generic@signatureif(!exists(".SigLength", envir = fenv, inherits = FALSE)).setupMethodsTables(generic)n <- get(".SigLength", envir = fenv)anySig <- rep("ANY", n)anyLabel <- .sigLabel(anySig)newMethods <- objects(newtable, all=TRUE)for(what in newMethods) {obj <- get(what, envir = newtable)if(is.primitive(obj))sig <- anySig ## Assert doesn't need to be a signature obj., won't change nselse if(is(obj, "MethodDefinition"))sig <- obj@definedelsestop(gettextf("Invalid object in meta table of methods for \"%s\", label \"%s\", had class \"%s\"",generic@generic, what, class(obj)))ns <- length(sig)if(ns == n) {}else {if(ns < n) {sig <- new("signature", generic, c(sig@.Data, rep("ANY", n-ns)))obj@defined <- sigobj@target <- sigwhat <- .sigLabel(sig)ns <- n}else if(add) { # and ns > nsignames <- generic@signaturelength(signames) <- ns.resetTable(table, ns, signames)assign(".SigLength", ns, envir = fenv)n <- ns}}if(add)assign(what, obj, envir = table)else if(exists(what, envir = table, inherits = FALSE) &&!all(obj@defined == "ANY") ) # remove methods, but not the defaultremove(list = what, envir = table)## else warning?}}.mlistAddToTable <- function(generic, mlist, table = new.env(TRUE, fenv), add = TRUE) {fenv <- environment(generic)signature <- generic@signatureif(!exists(".SigLength", envir = fenv, inherits = FALSE)).setupMethodsTables(generic)n <- get(".SigLength", envir = fenv, inherits = FALSE).storeMlist(table, rep("ANY", n), mlist, 1, add, fenv)## check for more args in the mlist than in the tablenNow <- get(".SigLength", envir = fenv, inherits = FALSE)if(nNow > n) {length(signature) <- nNow.resetTable(table, nNow, signature)}table}.storeMlist <- function(table, sig, mlist, i, add, fenv) {## the methods slot is a list named by class, with elements either## method definitions or mlistsm <- mlist@methodsclasses <- names(m)for(j in seq_along(m)) {el <- m[[j]]sig[[i]] <- classes[[j]]if(is(el, "MethodDefinition") || is.primitive(el)) {if(add)assign(.sigLabel(sig), el, envir = table)elseremove(list = .sigLabel(sig), envir = table)}else if(is(el,"MethodsList")) {i1 <- i+1if(i1 >= length(sig)) {## a reset of the labels will be neededassign(".SigLength", i1, envir = fenv)sig <- c(sig, rep("ANY", i1-length(sig)))}Recall(table, sig, el, i1, add, fenv)}elsestop("Invalid mlist element for signature \"", classes[[j]], "\" at level ", i,"( should be methods list or method, had class \"",class(el), "\")")}table}.cacheMethodInTable <- function(fdef, sig, def,table = get(".AllMTable", envir = fenv)) {## store method in cache table.## called from setMethod()## also Called from cacheMethod (from as(),## as<-())fenv <- environment(fdef)if(!exists(".AllMTable", envir = fenv, inherits = FALSE)).setupMethodsTables(fdef)sig <- .matchSigLength(sig, fdef, fenv, TRUE)label <- .sigLabel(sig)if(is.null(def)) {if(exists(label, envir = table, inherits = FALSE)) # remove the method (convention for setMethod)remove(list = label, envir = table)}elseassign(label, def, envir = table)}.resetTable <- function(table, n, signames) {## after updating a methods table, the maximum no. of arguments in## the signature increased to n. Reassign any objects whose label## does not match n classes from the defined slotanyLabel <- rep("ANY", n); seqN <- 1:nlabels <- objects(table, all.names = TRUE)for(what in labels) {method <- get(what, envir = table)if(is.primitive(method)) # stored as default ?label <- anyLabelelse if(is(method, "MethodDefinition"))label <- method@definedelsestop("Invalid object in methods table (\"", what,"\"), expected a method, got an object of class \"",class(method), "\"")if(length(label) < n) {label@.Data <- ifelse(seqN>length(label), anyLabel, label@.Data)label@names <- signamesmethod@defined <- method@target <- label}newLabel <- .sigLabel(label)if(!identical(what, newLabel)) {assign(newLabel, method, envir = table)remove(list=what, envir = table)}}}### the tag associated with a method signature.### Should eventually use the same C code as dispatch, for consistency.sigLabel <- function(sig)## TODO: should include package; i.e., class:package#class:...## BUT: not until defined, target slots have classes with package attributepaste(sig, collapse = "#").findInheritedMethods <-function(classes, fdef, mtable = NULL,table = get(".MTable", envir = environment(fdef)),excluded = NULL, useInherited, verbose = FALSE,returnAll = !(doMtable || doExcluded) ){## classes is a list of the class(x) for each arg in generic## signature, with "missing" for missing argsif(!is.environment(table)) {if(is(fdef, "standardGeneric"))stop("Invalid or unset methods table in generic function \"", fdef@generic,"\"")elsestop("Trying to find a methods table in a non-generic function")}hasGroup <- length(fdef@group) > 0if(hasGroup)groupGenerics <- .getAllGroups(list(fdef))doMtable <- is.environment(mtable)doExcluded <- length(excluded) > 0nargs <- length(classes)if(verbose)cat(sprintf("* .findInheritedMethods(): nargs=%d, returnAll=%s\n",nargs, returnAll))methods <- list()if(!missing(useInherited) && length(useInherited) < nargs)useInherited <- rep(useInherited, length = nargs)if(hasGroup && !doExcluded) {## first try for an exact match in a group generic## If this matches & is cached, it then will be treated as a non-inherited method## so no further calls here should occur.#### doExcluded is the findNextMethod case; we don't regard group methods as## inherited in the nextMethod sense, since they have the same signaturelabel <- .sigLabel(classes)direct <- .getGroupMethods(label, groupGenerics, FALSE)##M doExcluded must be FALSE here##M if(doExcluded && length(direct) > 0)##M direct <- direct[is.na(match(names(direct), excluded))]if(length(direct) > 0 && doMtable) {assign(label, direct[[1]], envir = mtable)if(verbose) cat("* found (and cached) direct group method for", label,"\n")return(direct)##M ## else must be returnAll, so include the group direct method##M methods <- direct}## else, continue because we may want all defined methods}def <- getClass(classes[[1]], .Force = TRUE)labels <-if(missing(useInherited) || useInherited[[1]])c(classes[[1]], names(def@contains), "ANY")else classes[[1]]if(nargs > 1) {classDefs <- vector("list", nargs)classDefs[[1]] <- deffor(i in 2:nargs) {cc <- classDefs[[i]] <- getClass(classes[[i]], .Force = TRUE)allLabels <- if(missing(useInherited) || useInherited[[i]])c(cc@className, names(cc@contains), "ANY") else cc@classNamelabels <- outerLabels(labels, allLabels)}}if(!returnAll)labels <- labels[-1] # drop exact matchlabels <- unique(labels) # only needed while contains slot can have duplicates(!)allMethods <- objects(table, all.names=TRUE)found <- match(labels, allMethods, 0) > 0for(label in labels[found])methods[[label]] <- get(label, envir = table)if(hasGroup) {## add the group methods recursively found but each time## only those not already included in found.groupmethods <- .getGroupMethods(labels, groupGenerics, found)fromGroup <- c(rep(FALSE, length(methods)), rep(TRUE, length(groupmethods)))methods <- c(methods, groupmethods)}elsefromGroup <- rep(FALSE, length(methods))if(verbose) cat("*", length(methods), "preliminary methods:",substr(deparse(names(methods)), 2, 1e6), "\n")## remove default if its not the only methodif(length(methods) > 1 && !returnAll) {defaultLabel <- paste(rep("ANY", nargs), collapse = "#")i <- match(defaultLabel, names(methods), 0)if(i > 0) {methods <- methods[-i]fromGroup <- fromGroup[-i]}}if(doExcluded)methods <- methods[is.na(match(names(methods), as.character(excluded)))]if(length(methods) > 1 && !returnAll) {if(nargs == 1)classDefs <- list(def)## else, defined beforeif(verbose) cat("* getting best methods, reducing from remaining preliminary",length(methods),"ones\n")methods <- .getBestMethods(methods, classDefs, fromGroup, verbose = verbose)if(length(methods) > 1)warning(gettextf(paste("Ambiguous method selection for \"%s\", target \"%s\"","(the first of the signatures shown will be used)\n%s\n"),fdef@generic, .sigLabel(classes),paste(" ", names(methods), collapse = "\n")))methods <- methods[1]}if(doMtable && length(methods)>0) {tlabel <- .sigLabel(classes)m <- methods[[1]]if(is(m, "MethodDefinition")) { # else, a primitivem@target <- .newSignature(classes, fdef@signature)methods[[1]] <- m}assign(tlabel, m, envir = mtable)}methods}.newSignature <- function(classes, names) {## a simple version to deal with boostrapping stagei <- seq_len(min(length(classes), length(names)))value <- as.character(classes)[i]class(value) <- getClass("signature")@classNamevalue@names <- as.character(names)[i]value}.findNextFromTable <- function(method, f, optional, envir, prev = character()) {fdef <- getGeneric(f)env <- environment(fdef)target <- method@targetn <- get(".SigLength", envir = env)defined <- method@definedm <- length(defined)if(m > n)length(defined) <- nelse if(n > m)## will only really need this to be a signature when the elements## have package attribute--see .sigLabeldefined <- new("signature", fdef, c(defined@.Data, rep("ANY", n-m)))excluded <- c(prev, .sigLabel(defined))methods <- .findInheritedMethods(defined, fdef, mtable = NULL, excluded = excluded)if(length(methods)==0) # use default method, maybe recursively.methods <- list(finalDefaultMethod(fdef@default)) #todo: put a label on it?if(length(methods)>1)warning("found ", length(methods), " equally good next methods") #todo: better message## excluded slot is a list, but with methods tables, elements are just labelsnew("MethodWithNext", method, nextMethod = methods[[1]], excluded =as.list(excluded))}## get the classes of the args.InheritForDispatch <- function(classes, fdef, mtable) {methods <- .findInheritedMethods(classes, fdef, mtable)if(length(methods)==1)return(methods[[1]]) # the methodelse if(length(methods)==0) {cnames <- paste("\"", sapply(classes, as.character), "\"", sep = "", collapse = ", ")stop("unable to find an inherited method for function \"", fdef@generic,"\", for signature ", cnames)}elsestop("Internal error in finding inherited methods; didn't return a unique method")}.findMethodInTable <- function(signature, table, fdef = NULL) {allMethods <- objects(table, all.names=TRUE)if(is(fdef, "genericFunction"))signature <- .matchSigLength(signature, fdef, environment(fdef), FALSE)label <- .sigLabel(signature)found <- match(label, allMethods, 0)if(found>0)get(label, envir = table)elseNULL}## inheritance distances: 0 for the class, 1 for immediate contains, 2 for other contains## and 3 for ANY.inhDistances <- function(classDef) {contains <- classDef@containsallNames <- unique(names(contains)) # bug allows duplicates in containsdist <- rep(2, length(allNames))for(i in seq_along(dist)) {ci <- contains[[i]]dist[[i]] <- ci@distance}dist <- c(0, dist, NA)names(dist) <- c(classDef@className, allNames, "ANY")dist}.getBestMethods <- function(methods, classDefs, fromGroup, verbose = FALSE) {n <- length(methods)dist <- rep(0, n)nArg <- length(classDefs)defClasses <- matrix("ANY", nArg, n)for(j in 1:n) {cl <- methods[[j]]@defined@.DatadefClasses[seq_along(cl), j] <- cl}containsDist <- lapply(classDefs, .inhDistances)maxDist <- max(unlist(containsDist), na.rm = TRUE) + 1if(verbose) { cat("** individual arguments' distances:\n"); print(containsDist) }## add up the inheritance distances for each argument (row of defClasses)for(i in 1:nArg) {ihi <- containsDist[[i]]ihi[is.na(ihi)] <- maxDistcli <- defClasses[i,]dist <- dist + ihi[match(cli, names(ihi))]}if(verbose) cat("** final methods' distances: (",paste(formatC(dist), collapse= ", "), ")\n", sep='')best <- dist == min(dist)## of the least distance methods, choose direct, rather than group## methods, unless all the best methods are from group genericsif(!all(fromGroup[best]))best <- best & !fromGroupmethods[best]}# add objects to the generic function's environment that allow# table-based dispatch of methods.setupMethodsTables <- function(generic,initialize = !exists(".Methods", envir = env, inherits = FALSE)) {env <- environment(generic)if(initialize)mlist <- generic@defaultelsemlist <- get(".Methods", envir = env, inherits = FALSE)if(initialize || !exists(".SigLength", envir = env, inherits = FALSE)) {nsig <- 1## check that groups of generics agree on .SigLength; otherwise## labels won't matchfor(gp in generic@group) {gpDef <- getGeneric(gp)if(is(gpDef, "genericFunction")) {.getMethodsTable(gpDef) # force initializationnsig <- max(nsig, get(".SigLength", envir = environment(gpDef)))}}assign(".SigLength", nsig, envir = env)}argSyms <- lapply(generic@signature, as.name)assign(".SigArgs", argSyms, envir = env)mtable <- .mlistAddToTable(generic, mlist)assign(".MTable", mtable, envir = env).resetInheritedMethods(env, mtable)if(is(generic, "groupGenericFunction")) {for(gp in generic@groupMembers) {gpDef <- getGeneric(gp)if(is(gpDef, "genericFunction")).getMethodsTable(gpDef) # force initialization w. group methods}}}.updateMethodsInTable <- function(generic, where, attach) {fenv <- environment(generic)reset <- identical(attach, "reset")if(!exists(".MTable", envir = fenv, inherits = FALSE)).setupMethodsTables(generic)mtable <- get(".MTable", envir = fenv)if(!reset) {env <- as.environment(where)tname <- .TableMetaName(generic@generic, generic@package)if(exists(tname, envir = env, inherits = FALSE)) {.mergeMethodsTable(generic, mtable, get(tname, envir = env), attach)}else {warning(gettextf("Couldn't find methods table for \"%s\", package \"%s\" may be out of date",generic@generic, generic@package))metaName <- mlistMetaName(generic)if(exists(metaName, envir = env, inherits = FALSE)).mlistAddToTable(generic, get(metaName, envir = env), mtable, attach)elsewarning("Methods list for generic \"", generic@generic,"\" not found")}}if(length(generic@group)>0) {groups <- as.list(generic@group)generics <- vector("list", length(groups))for(i in seq_along(groups))generics[[i]] <- getGeneric(groups[[i]]).checkGroupSigLength(groups, generics)}else if(is(generic, "groupGenericFunction")).checkGroupSigLength(list(generic@generic), list(generic)).resetInheritedMethods(fenv, mtable)mtable}.resetInheritedMethods <- function(fenv, mtable) {allObjects <- character()direct <- objects(mtable, all=TRUE)if(exists(".AllMTable", envir = fenv, inherits = FALSE)) {## remove all inherited methods. Note that code (e.g. setMethod) that asigns## a new method to mtable is responsible for copying it to allTable as well.allTable <- get(".AllMTable", envir = fenv)allObjects <- objects(allTable, all=TRUE)remove(list= allObjects[is.na(match(allObjects, direct))], envir = allTable)}else {allTable <- new.env(TRUE, fenv)assign(".AllMTable", allTable, envir = fenv)}## check for missing direct objects; usually a non-existent AllMTable?if(any(is.na(match(direct, allObjects)))) {direct <- objects(mtable, all=TRUE)for(what in direct)assign(what, get(what, envir = mtable), envir = allTable)}}.UseMethodsTables <- TRUE.UsingMethodsTables <- function(onOff = .UseMethodsTables, where = .methodsNamespace){prev <- .UseMethodsTablesif(nargs()) {onOff <- as.logical(onOff) # TRUE, FALSE or NAif(!is.na(onOff)).assignOverBinding(".UseMethodsTables", onOff, where = where, FALSE)elsestop(gettextf(".UsingMethodsTables: 'onOff' is not TRUE or FALSE"))}prev}## In the following, consider separate "compute" and "print" functions/methods:## Wish: alternative to 'classes' allow "wild-card signature", e.g.,## showMethods("coerce", signature = c("dgeMatrix", "*")).showMethodsTable <- function(generic, includeDefs = FALSE, inherited = FALSE,classes = NULL, showEmpty = TRUE, printTo = stdout()){cf <- function(...) cat(file = printTo, sep = "", ...)sigString <- function(sig) paste(sig@names, "=\"", as.character(sig), "\"",sep = "", collapse = ", ")qs <- function(what) paste('"', what, '"', collapse = ", ", sep = "")doFun <- function(func, pkg) cf("Function: ", func, " (package ", pkg, ")\n")env <- environment(generic)signature <- generic@signaturetable <- get(if(inherited) ".AllMTable" else ".MTable", envir = env)f <- generic@genericp <- packageSlot(f)if(is.null(p)) p <- "base"deflt <- new("signature", generic, "ANY")labels <- objects(table, all = TRUE)if(!is.null(classes) && length(labels) > 0) {sigL <- strsplit(labels, split = "#")keep <- !sapply(sigL, function(x, y) all(is.na(match(x, y))), classes)labels <- labels[keep]}if(length(labels) == 0) {if(showEmpty) {doFun(f,p)cf("<No methods>\n\n")}return(invisible())}## else: non-empty methods listdoFun(f,p)for(what in labels) {m <- get(what, envir = table)if( is(m, "MethodDefinition")) {t <- m@targetif(length(t) == 0)t <- defltd <- m@definedif(length(d) == 0)d <- defltcf(sigString(t), "\n")if(!identical(t, d))cf(" (inherited from: ", sigString(d), ")\n")if(!.identC(m@generic, f) && length(m@generic) == 1 && nchar(m@generic)>0)cf(" (definition from function \"", m@generic, "\")\n")}if(includeDefs) {if(is(m, "MethodDefinition"))m <- m@.Datacat(deparse(m), sep="\n", "\n", file = printTo)}}cat("\n", file = printTo)}## temporary switch for tablesuseMTable <- function(onOff = NA).Call("R_set_method_dispatch", as.logical(onOff), PACKAGE = "methods")## get all the group generic functions, in breadth-first order since## direct group inheritance is closer than indirect (all existing## groups are mutually exclusive, but multiple group membership is## allowed).getAllGroups <- function(funs) {start <- length(funs)for(i in seq_along(funs)) {groups <- funs[[i]]@groupfuns <- c(funs, lapply(groups,function(what) {f <- getGeneric(what)if(!is.function(f))stop("Failed to find expected group generic function: ",what)f}))}# now the next generations recusivelyif(length(funs) > start) {nmore <- length(funs) - startmore <- Recall(funs[(start+1):length(funs)])## did we add any groups?if(length(more) > nmore)funs <- c(funs, more[(nmore+1):length(more)])}funs}.getGroupMethods <- function(labels, generics, found) {methods <- list()for(i in seq_along(generics)) {gen <- generics[[i]]if(!is(gen,"genericFunction"))stop("Invalid group generic function in search for inherited method (class \"",class(gen), "\"")table <- .getMethodsTable(gen)allMethods <- objects(table, all.names = TRUE)## TODO: possible for .SigLength to differ between group &## members. Requires expanding labels to max. lengthnewFound <- rep(FALSE, length(found))newFound[!found] <- (match(labels[!found], allMethods, 0)>0)found <- found | newFoundfor(what in labels[newFound])methods[[what]] <- get(what, envir = table)}methods}.getMethodsTable <- function(fdef, env = environment(fdef),check = TRUE, inherited = FALSE){name <- if(inherited) ".AllMTable" else ".MTable"if(check && !exists(name, envir = env, inherits = FALSE)).setupMethodsTables(fdef)get(name, envir = env)}.getGenericSigLength <- function(fdef, env = environment(fdef), check = TRUE) {if(check && !exists(".SigLength", envir = env, inherits = FALSE)).setupMethodsTables(fdef)get(".SigLength", envir = env)}.checkGroupSigLength <- function(gnames, generics = lapply(gnames, getGeneric)) {funs <- gnamesrecall <- FALSEfor(i in seq_along(gnames)) {what <- gnames[[i]]fdef <- generics[[i]]if(!is(fdef, "groupGenericFunction")) {warning("Trying to check signature length of group generic \"",what, "\", but it is not a group generic")next}if(length(fdef@group) > 0) {# push up the check one levelgnames[[i]] <- fdef@groupgenerics[[i]] <- lapply(fdef@group, getGeneric)recall <- TRUEnext}funs <- c(funs, getGroupMembers(fdef, TRUE, FALSE))}if(recall)return(Recall(unlist(gnames, FALSE), unlist(generics, FALSE)))funs <- unique(funs)fdefs <- lapply(funs, function(x) {if(is.character(x) && length(x) == 1) getGeneric(x)else x})## now compare the sig lengthssigs <- rep(0,length(funs))for(i in seq_along(sigs)) {what <- funs[[i]]fdef <- fdefs[[i]]if(is.null(fdef))next # getGroupMembers returns NULL if member is not definedif(!is(fdef, "genericFunction"))warning("Trying to check signature length of generic \"",what, "\", but it is not a generic function: i = ", i,", funs = ", paste(unlist(funs), collapse = ", "),"; gnames = ",paste(as.character(gnames), collapse = ", "))else {ev <- environment(fdef)if(!exists(".SigLength", envir = ev, inherits = FALSE)).setupMethodsTables(fdef)sigs[i] <- get(".SigLength", envir = ev)}}n <- max(sigs)reset <- sigs < n & sigs > 0 # all the sigs for defined funs & less than max.if(any(reset)) {funs <- funs[reset]fdefs <- fdefs[reset]for(fdef in fdefs) {.resetSigLength(fdef, n)}}funs}## a simplified outer of pasteouterLabels <- function(labels, new) {## WARNING: This code incorporates the definition of .sigLabel## and so must change if that does (e.g. to include package)n <- length(labels)m <- length(new)paste(labels[rep(1:n, rep(m,n))], new[rep(1:m,n)], sep ="#")}.matchSigLength <- function(sig, fdef, fenv, reset = FALSE) {nargs <- .getGenericSigLength(fdef, fenv, TRUE)n <- length(sig)if(n < nargs)sig <- c(as.character(sig), rep("ANY", nargs - n))else if(n > nargs) { #reset table?if(all(sig[(nargs+1):n] == "ANY"))length(sig) <- nargselse {while(sig[[n]] == "ANY")n <- n-1if(reset).resetSigLength(fdef, n)length(sig) <- n}}sig}.resetSigLength <- function(fdef, n) {fenv <- environment(fdef)assign(".SigLength", n, envir = fenv)mtable <- .getMethodsTable(fdef, fenv, check = FALSE)signames <- fdef@signaturelength(signames) <- n.resetTable(mtable, n, signames).resetInheritedMethods(fenv, mtable)}.TableMetaName <- function(name, package)methodsPackageMetaName("T", paste(name, package, sep=":")).TableMetaPrefix <- function()methodsPackageMetaName("T","").addToMetaTable <- function(fdef, signature, definition, where, nSig) {return()}# the real version..addToMetaTable <- function(fdef, signature, definition, where,nSig = .getGenericSigLength(fdef, fenv)) {# TODO: nSig should be a slot in the tabletname <- .TableMetaName(fdef@generic, fdef@package)where <- as.environment(where)if(exists(tname, envir =where, inherits = FALSE)) {table <- get(tname, envir = where)if(length(signature) > nSig).resetTable(table, length(signature), fdef@signature[seq_along(signature)])}else {table <- new.env(TRUE, environment(fdef))assign(tname, table, envir = where)}assign(.sigLabel(signature), definition, envir = table)}.makeGenericTables <- function(where) {generics <- .getGenerics(where)mtables <- .getGenerics(where, FALSE)for(i in seq_along(generics)) {name <- generics[[i]]mtable <- get(mtables[[i]], envir = where)generic <- .getGeneric(name, where = where)if(is.null(generic)) {warning(gettextf("Could not find generic function \"%s\" to initialize cached methods",name))next}table <- .getMethodsTable(generic).mergeMethodsTable(generic, table, mtable)assign(.TableMetaName(generic@generic, generic@package), table, envir = where)}}.assignMethodsMetaTable <- function(mlist, generic, where, overwrite = TRUE) {tname <- .TableMetaName(generic@generic, generic@package)if(overwrite || !exists(tname, envir = where, inherits = FALSE)) {table <- .mlistAddToTable(generic, mlist)assign(tname, table, envir = where)}}.getGenericSigArgs <- function(fdef, env = environment(fdef), check = TRUE) {if(check && !exists(".SigLength", envir = env, inherits = FALSE)).setupMethodsTables(fdef)n <- get(".SigLength", envir = env)args <- get(".SigArgs", envir = env)length(args) <- nargs}## the most simple part of listFromMethods() below; not yet exportedtableNames <- function(generic, where, table) {fdef <- getGeneric(generic)if(missing(table))table <-if(missing(where)) .getMethodsTable(fdef)else get(.TableMetaName(fdef@generic, fdef@package),envir = as.environment(where), inherits = FALSE)objects(table, all.names=TRUE)}listFromMethods <- function(generic, where, table) {fdef <- getGeneric(generic)if(missing(table))table <-if(missing(where)) .getMethodsTable(fdef)else get(.TableMetaName(fdef@generic, fdef@package),envir = as.environment(where), inherits = FALSE)fev <- environment(fdef)nSigArgs <- .getGenericSigLength(fdef, fev)names <- objects(table, all=TRUE)methods <- lapply(names, function(x)get(x, envir = table))if(nSigArgs > 1) {n <- length(names)sigs <- vector("list", n)namesCon <- textConnection(names)for(i in seq_len(n))sigs[[i]] <- scan(namesCon, "", sep ="#", nmax = nSigArgs, quiet=TRUE)}elsesigs <- as.list(names)new("LinearMethodsList", classes=sigs, methods=methods,arguments = .getGenericSigArgs(fdef, fev), generic = fdef)}