R/package.R

Defines functions odin_dust_header odin_dust_package

Documented in odin_dust_package

##' Update generated code in a package that uses odin and dust to
##' provide a model. This will generate new dust code in `inst/dust`
##' and from that generate a full model in `src`, and an R interface
##' in `R/dust.R`, along with the cpp11 attributes that are needed to
##' use the model.
##'
##' @title Update package code
##'
##' @param path Path to the package root (the directory that
##'   contains `DESCRIPTION`)
##'
##' @inheritParams odin_dust
##'
##' @export
##'
##' @return The path to the package
odin_dust_package <- function(path, options = NULL) {
  re_r <- "\\.R$"
  header_cpp <- odin_dust_header("//")
  header_r <- odin_dust_header("##")

  filenames <- dir(file.path(path, "inst/odin"), re_r, full.names = TRUE)
  if (length(filenames) == 0L) {
    stop("Did not find any files in inst/odin")
  }

  dir.create(file.path(path, "inst/dust"), FALSE, TRUE)
  ## NOTE: that mixing odin and odin.dust models together is unlikely
  ## to go well, and we assume here that all models are compilable to
  ## dust.
  options <- odin_dust_options(options = options)
  if (!identical(options$gpu$compile, FALSE)) {
    stop("Can't compile gpu models into a package")
  }
  nms <- character()

  for (f in filenames) {
    ir <- odin::odin_parse_(f, options)
    dat <- with_dir(
      dirname(f),
      generate_dust(ir, options))
    code <- odin_dust_code(dat)
    dest <- file.path(path, "inst", "dust", sub(re_r, ".cpp", basename(f)))
    if (file.exists(dest)) {
      if (!isTRUE(grepl("^// Generated by odin\\.dust", readLines(dest, 1)))) {
        stop("Refusing to overwrite edited file")
      }
    }
    writeLines(c(header_cpp, code), dest)
    nms <- c(nms, dat$name)
  }

  dust::dust_package(path, quiet = !options$verbose)

  path_dust_r <- file.path(path, "R", "dust.R")
  code_r <- readLines(path_dust_r)
  code_r_transform <- sprintf('%s$set("public", "transform_variables", %s)',
                          nms, deparse_fun(odin_dust_transform_variables))
  writeLines(c(code_r, header_r, code_r_transform), path_dust_r)

  path
}


odin_dust_header <- function(comment) {
  sprintf("%s Generated by odin.dust (version %s) - do not edit",
          comment, utils::packageVersion("odin.dust"))
}
mrc-ide/odin.dust documentation built on Nov. 23, 2023, 4:54 a.m.