Skip to content

Commit 8d6d93d

Browse files
authored
Merge pull request #154 from stan-dev/compat
Allow deprecated syntax for specified versions of specified packages
2 parents e03b02a + 9750fd7 commit 8d6d93d

4 files changed

Lines changed: 26203 additions & 8 deletions

File tree

DESCRIPTION

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ Authors@R:
2828
person(given = "Stefan",
2929
family = "Siegert",
3030
role = "ctb"),
31-
person(given = "Visruth",
32-
family = "Srimath Kandali",
33-
role = "ctb"),
31+
person(given = "Visruth",
32+
family = "Srimath Kandali",
33+
role = "ctb"),
3434
person(given = "Trustees of",
3535
family = "Columbia University",
3636
role = "cph"))
@@ -45,7 +45,7 @@ BugReports: https://github.com/stan-dev/rstantools/issues
4545
Encoding: UTF-8
4646
LazyData: true
4747
SystemRequirements: pandoc
48-
Imports: desc, stats, utils, Rcpp (>= 0.12.16), RcppParallel (>= 5.0.1)
48+
Imports: desc, stats, utils, Rcpp (>= 0.12.16), RcppParallel (>= 5.0.1), QuickJSR
4949
Suggests:
5050
rstan (>= 2.17.2),
5151
usethis (>= 1.5.1),

R/rstan_config.R

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,27 @@
3939
#'
4040
rstan_config <- function(pkgdir = ".") {
4141
pkgdir <- .check_pkgdir(pkgdir) # check if package root directory
42+
pkg_dcf <- read.dcf(file.path(pkgdir, "DESCRIPTION"))
43+
pkg_name <- pkg_dcf[1, "Package"]
44+
pkg_ver <- pkg_dcf[1, "Version"]
45+
4246
# get stan model files
4347
stan_files <- list.files(file.path(pkgdir, "inst", "stan"),
4448
full.names = TRUE,
4549
pattern = "(\\.stan$)|(\\.stanfunctions$)")
4650
if (length(stan_files) != 0) {
51+
is_excepted <- isTRUE(stanc_exceptions[[pkg_name]] == pkg_ver) && (utils::packageVersion("StanHeaders") >= "2.36")
52+
53+
if (is_excepted) {
54+
.update_deprecations(pkg_name, stan_files)
55+
}
56+
4757
# add R & src folders in case run from configure[.win] script
4858
.add_standir(pkgdir, "R", msg = FALSE, warn = FALSE)
4959
.add_standir(pkgdir, "src", msg = FALSE, warn = FALSE)
5060
# convert all .stan files to .cc/.hpp pairs
51-
sapply(stan_files, .make_cc, pkgdir = pkgdir)
61+
sapply(stan_files, .make_cc, pkgdir = pkgdir, pkg_name = pkg_name,
62+
is_excepted = is_excepted)
5263
# update package Makevars
5364
acc <- .setup_Makevars(pkgdir, add = TRUE)
5465
## .add_Makevars(pkgdir)
@@ -65,7 +76,7 @@ rstan_config <- function(pkgdir = ".") {
6576
# register exported modules as native routines
6677
Rcpp::compileAttributes(pkgdir)
6778
# update R/stanmodels.R with current set of models
68-
stanmodels <- .update_stanmodels(pkgdir)
79+
stanmodels <- .update_stanmodels(pkgdir, pkg_name, is_excepted)
6980
acc <- acc | .add_stanfile(stanmodels, pkgdir, "R", "stanmodels.R")
7081
invisible(acc)
7182
}
@@ -167,7 +178,7 @@ rstan_config <- function(pkgdir = ".") {
167178
# If the .stan file has a functions block but no parameters block, then there
168179
# is no module definition but the functions are compiled and exported to the
169180
# package's namespace.
170-
.make_cc <- function(file_name, pkgdir) {
181+
.make_cc <- function(file_name, pkgdir, pkg_name, is_excepted) {
171182
model_name <- sub("[.]stan$", "", basename(file_name)) # model name
172183
## path to src/stan_files
173184
## stan_path <- file.path(pkgdir, "src", "stan_files")
@@ -221,6 +232,7 @@ rstan_config <- function(pkgdir = ".") {
221232
cat("#include <exporter.h>",
222233
eigen_incl,
223234
"#include <stan/math/prim/meta.hpp>",
235+
"#include <stan/services/util/create_rng.hpp>",
224236
file = file.path(pkgdir, "src",
225237
paste(pkgname, "types.h", sep = "_")),
226238
sep = "\n")
@@ -245,6 +257,9 @@ rstan_config <- function(pkgdir = ".") {
245257
if (utils::packageVersion('StanHeaders') >= "2.34") {
246258
cppcode <- gsub("boost::ecuyer1988", "stan::rng_t", cppcode, fixed = TRUE)
247259
}
260+
if (is_excepted && !is.null(cpp_pre_process[[pkg_name]])) {
261+
cppcode <- cpp_pre_process[[pkg_name]](cppcode)
262+
}
248263
# Stan header file
249264
hdr_name <- .stan_prefix(model_name, ".h")
250265
# get license file (if any)
@@ -316,7 +331,7 @@ rstan_config <- function(pkgdir = ".") {
316331
}
317332

318333
# rewrites stanmodels.R reflecting current list of stan files
319-
.update_stanmodels <- function(pkgdir) {
334+
.update_stanmodels <- function(pkgdir, pkg_name, is_excepted) {
320335
model_names <- list.files(file.path(pkgdir, "inst", "stan"),
321336
pattern = "*.stan$")
322337
only_functions <- sapply(model_names, FUN = function(nm) {
@@ -354,6 +369,25 @@ rstan_config <- function(pkgdir = ".") {
354369
stanmodels[(model_line+2):load_line],
355370
load_module,
356371
stanmodels[(load_line+2):nlines])
372+
# disbayes does not need stanc exception, but uses a variable name ('mips') that
373+
# gets mangled by stanc which rstan 2.32 does not support
374+
if (!is.null(cpp_pre_process[[pkg_name]]) && (is_excepted || pkg_name == "disbayes")) {
375+
process_fun <- c("process_fun <- ", deparse(cpp_pre_process[[pkg_name]]))
376+
377+
process_text <- c(
378+
"process_fun <- ", deparse(cpp_pre_process[[pkg_name]]),
379+
"stanfit$model_code <- process_fun(stanfit$model_code)",
380+
"stanfit$model_cpp$model_cppcode <- process_fun(stanfit$model_cpp$model_cppcode)"
381+
)
382+
383+
insert_loc <- grep("# create stanmodel object$", stanmodels)
384+
nlines <- length(stanmodels)
385+
stanmodels <- c(
386+
stanmodels[1:(insert_loc-1)],
387+
process_text,
388+
stanmodels[insert_loc:nlines]
389+
)
390+
}
357391
}
358392
stanmodels
359393
}
@@ -402,3 +436,25 @@ rstan_config <- function(pkgdir = ".") {
402436
# Update model code with type declarations
403437
gsub("auto", rtn_type, cpp_lines[decl_line], fixed = TRUE)
404438
}
439+
440+
.update_deprecations <- function(pkg_name, stan_files) {
441+
post_process <- stan_post_process[[pkg_name]]
442+
if (is.null(post_process)) {
443+
post_process <- function(x) x
444+
}
445+
ctx <- QuickJSR::JSContext$new(stack_size = 4 * 1024 * 1024)
446+
ctx$source(system.file("stanc.2.32.js", package = "rstantools", mustWork = TRUE))
447+
stanc_process <- utils::getFromNamespace("stanc_process", "rstan")
448+
sapply(stan_files, function(stanfile) {
449+
model_code <- stanc_process(stanfile)
450+
model_code <- ctx$call("stanc", "dummy", model_code, as.array("print-canonical"))$result
451+
452+
# Only overwrite Stan file if stanc succeeded
453+
if (!is.null(model_code)) {
454+
model_code <- post_process(model_code)
455+
writeLines(model_code, con = stanfile)
456+
}
457+
invisible(NULL)
458+
})
459+
invisible(NULL)
460+
}

R/stanc_exceptions.R

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
stanc_exceptions <- list(
2+
AovBay = "0.1.0",
3+
baggr = "0.8.2",
4+
BayesPET = "0.1.0",
5+
bbmix = "1.0.0",
6+
bclogit = "1.1",
7+
BINtools = "0.2.0",
8+
bmgarch = "2.1.0",
9+
bmggum = "0.1.0",
10+
BoundIRT = "0.5.0",
11+
BRRAT = "0.0.2",
12+
bsynth = "1.0",
13+
bws = "0.1.0",
14+
CARME = "0.1.1",
15+
cbq = "0.2.0.4",
16+
cloneRate = "0.2.3",
17+
CNVRG = "1.0.0",
18+
DCPO = "0.5.3",
19+
densEstBayes = "1.0-2.2",
20+
EcoEnsemble = "1.2.0",
21+
EpiPvr = "0.0.1",
22+
fcirt = "0.2.1",
23+
FlexReg = "1.4.2",
24+
glmmPen = "1.5.4.8",
25+
HHBayes = "0.1.1",
26+
hmde = "1.4.0",
27+
imt = "1.0.0",
28+
imuGAP = "0.1.0",
29+
MetaStan = "1.0.0",
30+
morseTKTD = "0.1.3",
31+
multipleDL = "1.0.0",
32+
networkscaleup = "0.2-2",
33+
phacking = "0.2.1",
34+
postlink = "0.1.0",
35+
psBayesborrow = "1.1.0",
36+
publipha = "0.1.2",
37+
SLGP = "1.0.2",
38+
survstan = "0.0.7.1",
39+
trialr = "0.1.6",
40+
truncnormbayes = "0.0.3",
41+
WhiteLabRt = "1.0.1",
42+
YPPE = "1.0.1",
43+
zoid = "1.3.1"
44+
)
45+
46+
# Additional deprecations not covered by 2.32 stanc3 canonicalise
47+
stan_post_process <- list(
48+
publipha = function(model_code) {
49+
model_code <- gsub("real \\b(lower|upper)\\b", "real \\1_par", model_code)
50+
model_code <- gsub("normal_(cdf|lccdf|lcdf)\\((-)?\\b(upper|lower)\\b(,| \\|)", "normal_\\1(\\2\\3_par |", model_code)
51+
model_code
52+
},
53+
survstan = function(model_code) {
54+
model_code <- gsub("\\boffset\\b", "offset_par", model_code)
55+
model_code
56+
},
57+
cbq = function(model_code) {
58+
model_code <- gsub("\\boffset\\b", "offset_par", model_code)
59+
model_code
60+
}
61+
)
62+
63+
cpp_pre_process <- list(
64+
survstan = function(cpp_code) {
65+
cpp_code <- gsub("offset_par", "offset", cpp_code, fixed = TRUE)
66+
cpp_code
67+
},
68+
cbq = function(cpp_code) {
69+
cpp_code <- gsub("offset_par", "offset", cpp_code, fixed = TRUE)
70+
cpp_code
71+
},
72+
# rstan 2.32 does not account for new stanc mangling
73+
disbayes = function(cpp_code) {
74+
cpp_code <- gsub("_stan_mips", "mips", cpp_code, fixed = TRUE)
75+
cpp_code
76+
}
77+
)

inst/stanc.2.32.js

Lines changed: 26062 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)