@@ -598,6 +598,7 @@ compile <- function(quiet = TRUE,
598598 include_paths <- private $ precompile_include_paths_
599599 }
600600 private $ include_paths_ <- resolve_path(include_paths )
601+ include_paths <- private $ include_paths_
601602 if (is.null(dir ) && ! is.null(private $ dir_ )) {
602603 dir <- absolute_path(private $ dir_ )
603604 } else if (! is.null(dir )) {
@@ -630,7 +631,6 @@ compile <- function(quiet = TRUE,
630631 }
631632
632633 cpp_options [[" USER_HEADER" ]] <- wsl_safe_path(absolute_path(user_header ))
633- stanc_options [[" allow-undefined" ]] <- TRUE
634634 private $ using_user_header_ <- TRUE
635635 } else if (! is.null(cpp_options [[" USER_HEADER" ]])) {
636636 if (! is.null(cpp_options [[" user_header" ]])) {
@@ -648,6 +648,7 @@ compile <- function(quiet = TRUE,
648648
649649
650650 if (! is.null(user_header )) {
651+ stanc_options [[" allow-undefined" ]] <- TRUE
651652 user_header <- absolute_path(user_header ) # As mentioned above, just absolute, not wsl_safe_path()
652653 if (! file.exists(user_header )) {
653654 stop(paste0(" User header file '" , user_header , " ' does not exist." ), call. = FALSE )
@@ -709,29 +710,18 @@ compile <- function(quiet = TRUE,
709710 if (is.null(stanc_options [[" name" ]])) {
710711 stanc_options [[" name" ]] <- paste0(self $ model_name(), " _model" )
711712 }
712- stanc_built_options <- c()
713- for (i in seq_len(length(stanc_options ))) {
714- option_name <- names(stanc_options )[i ]
715- if (isTRUE(as.logical(stanc_options [[i ]]))) {
716- stanc_built_options <- c(stanc_built_options , paste0(" --" , option_name ))
717- } else if (is.null(option_name ) || ! nzchar(option_name )) {
718- stanc_built_options <- c(stanc_built_options , paste0(" --" , stanc_options [[i ]]))
719- } else if (option_name == " name" ) { # Quoting model name mangles generated namespace
720- stanc_built_options <- c(stanc_built_options , paste0(" --" , option_name , " =" , stanc_options [[i ]]))
721- } else {
722- stanc_built_options <- c(stanc_built_options , paste0(" --" , option_name , " =" , " '" , stanc_options [[i ]], " '" ))
723- }
724- }
725- stancflags_combined <- stanc_built_options
713+ stancflags_combined <- stanc_options_to_args(stanc_options , quote_values = TRUE )
714+ stancflags_direct <- stanc_options_to_args(stanc_options )
726715 stancflags_local <- get_cmdstan_flags(" STANCFLAGS" )
727716 if (length(stancflags_local ) > 0 ) {
728717 stancflags_combined <- c(stancflags_combined , stancflags_local )
718+ stancflags_direct <- c(stancflags_direct , stancflags_local )
729719 }
730720 stanc_inc_paths <- include_paths_stanc3_args(include_paths , direct_call = TRUE )
731- stancflags_standalone <- c(" --standalone-functions" , stanc_inc_paths , stancflags_combined )
721+ stancflags_standalone <- c(" --standalone-functions" , stanc_inc_paths , stancflags_direct )
732722 self $ functions $ hpp_code <- get_standalone_hpp(temp_stan_file , stancflags_standalone )
733723 private $ model_methods_env_ <- new.env()
734- private $ model_methods_env_ $ hpp_code_ <- get_standalone_hpp(temp_stan_file , c(stanc_inc_paths , stancflags_combined ))
724+ private $ model_methods_env_ $ hpp_code_ <- get_standalone_hpp(temp_stan_file , c(stanc_inc_paths , stancflags_direct ))
735725 self $ functions $ external <- ! is.null(user_header )
736726 self $ functions $ existing_exe <- FALSE
737727
@@ -796,12 +786,8 @@ compile <- function(quiet = TRUE,
796786 )
797787 )
798788 if (is.na(run_log $ status ) || run_log $ status != 0 ) {
799- err_msg <- " An error occured during compilation! See the message above for more information."
800- if (grepl(" auto-format flag to stanc" , run_log $ stderr )) {
801- format_msg <- " \n To fix deprecated or removed syntax please see ?cmdstanr::format for an example."
802- err_msg <- paste(err_msg , format_msg )
803- }
804- stop(err_msg , call. = FALSE )
789+ stop(" An error occurred during compilation! See the message above for more information." ,
790+ call. = FALSE )
805791 }
806792 if (file.exists(exe )) {
807793 file.remove(exe )
@@ -991,17 +977,7 @@ check_syntax <- function(pedantic = FALSE,
991977 if (is.null(stanc_options [[" name" ]])) {
992978 stanc_options [[" name" ]] <- paste0(self $ model_name(), " _model" )
993979 }
994- stanc_built_options <- c()
995- for (i in seq_len(length(stanc_options ))) {
996- option_name <- names(stanc_options )[i ]
997- if (isTRUE(as.logical(stanc_options [[i ]]))) {
998- stanc_built_options <- c(stanc_built_options , paste0(" --" , option_name ))
999- } else if (is.null(option_name ) || ! nzchar(option_name )) {
1000- stanc_built_options <- c(stanc_built_options , paste0(" --" , stanc_options [[i ]]))
1001- } else {
1002- stanc_built_options <- c(stanc_built_options , paste0(" --" , option_name , " =" , stanc_options [[i ]]))
1003- }
1004- }
980+ stanc_built_options <- stanc_options_to_args(stanc_options )
1005981
1006982 withr :: with_path(
1007983 c(
@@ -1111,37 +1087,21 @@ format <- function(overwrite_file = FALSE,
11111087 max_line_length ,
11121088 lower = 1 , len = 1 , null.ok = TRUE
11131089 )
1114- stanc_options <- private $ precompile_stanc_options_
1090+ stanc_options <- as.list( private $ precompile_stanc_options_ )
11151091 stancflags_val <- include_paths_stanc3_args(
11161092 self $ include_paths(),
11171093 direct_call = TRUE
11181094 )
1119- stanc_options [" auto-format" ] <- TRUE
1095+ stanc_options [[ " auto-format" ] ] <- TRUE
11201096 if (! is.null(max_line_length )) {
1121- stanc_options [" max-line-length" ] <- max_line_length
1097+ stanc_options [[ " max-line-length" ] ] <- max_line_length
11221098 }
11231099 if (isTRUE(canonicalize )) {
1124- stanc_options [" print-canonical" ] <- TRUE
1100+ stanc_options [[ " print-canonical" ] ] <- TRUE
11251101 } else if (is.list(canonicalize ) && length(canonicalize ) > 0 ){
1126- stanc_options [" canonicalize" ] <- paste0(canonicalize , collapse = " ," )
1127- }
1128- stanc_built_options <- c()
1129- for (i in seq_len(length(stanc_options ))) {
1130- option_name <- names(stanc_options )[i ]
1131- if (isTRUE(as.logical(stanc_options [[i ]])) && ! is.numeric(stanc_options [[i ]])) {
1132- stanc_built_options <- c(stanc_built_options , paste0(" --" , option_name ))
1133- } else if (is.null(option_name ) || ! nzchar(option_name )) {
1134- stanc_built_options <- c(
1135- stanc_built_options ,
1136- paste0(" --" , stanc_options [[i ]])
1137- )
1138- } else {
1139- stanc_built_options <- c(
1140- stanc_built_options ,
1141- paste0(" --" , option_name , " =" , stanc_options [[i ]])
1142- )
1143- }
1102+ stanc_options [[" canonicalize" ]] <- paste0(canonicalize , collapse = " ," )
11441103 }
1104+ stanc_built_options <- stanc_options_to_args(stanc_options )
11451105 withr :: with_path(
11461106 c(
11471107 toolchain_PATH_env_var(),
@@ -2471,6 +2431,39 @@ assert_stan_file_exists <- function(stan_file) {
24712431 }
24722432}
24732433
2434+ # ' Turn a `stanc_options` list into `stanc` command line arguments
2435+ # '
2436+ # ' @param stanc_options (list) Named or unnamed stanc options. Logical values
2437+ # ' mark boolean flags and any other value is passed as `--name=value`.
2438+ # ' @param quote_values (logical) Single-quote option values? Only the
2439+ # ' `STANCFLAGS` string handed to Make needs quoting, because Make expands it
2440+ # ' through a shell. Arguments for direct `stanc` calls are passed to processx
2441+ # ' as separate elements and must be left unquoted (#1227).
2442+ # ' @return A character vector of arguments, one per element.
2443+ # ' @noRd
2444+ stanc_options_to_args <- function (stanc_options , quote_values = FALSE ) {
2445+ args <- c()
2446+ for (i in seq_len(length(stanc_options ))) {
2447+ option_name <- names(stanc_options )[i ]
2448+ option_value <- stanc_options [[i ]]
2449+ if (is.null(option_name ) || ! nzchar(option_name )) {
2450+ # Unnamed options are already flag names, e.g. list("allow-undefined")
2451+ args <- c(args , paste0(" --" , option_value ))
2452+ } else if (is.logical(option_value )) {
2453+ # TRUE emits a bare flag, FALSE leaves the flag out entirely
2454+ if (isTRUE(option_value )) {
2455+ args <- c(args , paste0(" --" , option_name ))
2456+ }
2457+ } else if (isTRUE(quote_values ) && option_name != " name" ) {
2458+ # Quoting the model name mangles the generated namespace
2459+ args <- c(args , paste0(" --" , option_name , " =" , " '" , option_value , " '" ))
2460+ } else {
2461+ args <- c(args , paste0(" --" , option_name , " =" , option_value ))
2462+ }
2463+ }
2464+ args
2465+ }
2466+
24742467# ' Build stanc include-path arguments
24752468# '
24762469# ' Make receives include paths through `STANCFLAGS` and needs paths containing
0 commit comments