renjin icon indicating copy to clipboard operation
renjin copied to clipboard

getNamespaceInfo, .getNamespaceInfo, getExportedValue are not correct

Open akbertram opened this issue 5 years ago • 1 comments

  • getNamespaceInfo returns names instead of an environment
  • .getNamespaceInfo is relies on GNU R internals and needs to be replaced or updated
  • getExportedValue relies on .getNamespaceInfo

akbertram avatar Oct 24 '19 08:10 akbertram

A little more information based on a first investigation:

getNamespaceInfo(ns, which) and .getNamespaceInfo(ns, which) seem to differ only in the sense that ns can be a character string (or symbol) in the first case, whereas the second case expects ns to be an environment. This is the R 3.5.3 implementation:

getNamespaceInfo <- function(ns, which) {
    ns <- asNamespace(ns, base.OK = FALSE)
    get(which, envir = ns[[".__NAMESPACE__."]])
}

.getNamespaceInfo <- function(ns, which) {
    ns[[".__NAMESPACE__."]][[which]]
}

For getNamespaceInfo(ns, which), Renjin currently uses getNamespaceExports(ns) and getNamespaceImports(ns) to implement this function, but R uses .getNamespaceInfo(ns, "exports") and getNamespaceInfo(ns, "imports") respectively:

getNamespaceExports <- function(ns) {
    ns <- asNamespace(ns)
    names(if(isBaseNamespace(ns)) .BaseNamespaceEnv
          else .getNamespaceInfo(ns, "exports"))
}

getNamespaceImports <- function(ns) {
    ns <- asNamespace(ns)
    if (isBaseNamespace(ns)) NULL
    else .getNamespaceInfo(ns, "imports")
}

Based on the R implementation, getNamespaceImports(ns) and therefore also .getNamespaceInfo(ns, "imports") should return a list:

> ns <- asNamespace("stats")
> str(getNamespaceImports(ns))
List of 4
 $ base     : logi TRUE
 $ graphics : Named chr [1:88] "assocplot" "title" "axis.Date" "points" ...
  ..- attr(*, "names")= chr [1:88] "assocplot" "title" "axis.Date" "points" ...
 $ grDevices: Named chr [1:12] "as.graphicsAnnot" "dev.cur" "dev.flush" "dev.hold" ...
  ..- attr(*, "names")= chr [1:12] "as.graphicsAnnot" "dev.cur" "dev.flush" "dev.hold" ...
 $ utils    : Named chr [1:4] "count.fields" "flush.console" "str" "tail"
  ..- attr(*, "names")= chr [1:4] "count.fields" "flush.console" "str" "tail"

But getNamespaceExports(ns) returns the names of the (objects in the) environment returned by getNamespaceInfo(ns, "exports"):

> .getNamespaceInfo(ns, "exports")
<environment: 0xc2e468>
> getNamespaceExports(ns)
  [1] "confint.default"      "mahalanobis"          "optimize"            
  [4] "hat"                  "Box.test"             "reorder"             
  [7] "phyper"               "ar.mle"               "rhyper" 
...

The functions getNamespaceExports(ns) and getNamespaceImports(ns) are defined as primitives in Renjin and the latter actually throws a not-yet-implemented exception.

Based on all this, it seems that a proper implementation of .getNamespaceInfo(ns, which) would resolve most of the current issues.

mjkallen avatar Nov 01 '19 15:11 mjkallen