44passByReference <- function (fun ,
55 refArgs = character (),
66 blockRefArgs = character ()) {
7+ # The format from an NFinternals object is a named list of TRUE/FALSE values,
8+ # so convert that to a character vector of names for the TRUE ones.
79 if (is.list(refArgs ))
810 refArgs <- names(refArgs )[ unlist(lapply(refArgs , isTRUE )) ]
911
@@ -16,17 +18,22 @@ passByReference <- function(fun,
1618 if ((length(refArgs )== 0 ) & length(blockRefArgs )== 0 )
1719 return (fun )
1820
21+ # fun can be a function or the body of a function.
1922 passedAsFunction <- is.function(fun )
2023 code <- if (passedAsFunction )
2124 body(fun )
2225 else
2326 fun
2427
28+ # Helper to create a substitution list from argument names
29+ # e.g. ("x", "_suffix") -> list(x = as.name("x_suffix"))
2530 args_2_subList <- function (args , suffix )
2631 args | >
2732 lapply(function (x ) as.name(paste0(x , suffix ))) | >
2833 structure(names = args )
2934
35+ # Helper to create lines of code for active bindings
36+ # e.g. nCompiler::createRef("x_suffix", x) # either createRef or createBlockRef
3037 subList_2_lines <- function (subList ,
3138 fun_name ) {
3239 lines <- list ()
@@ -41,12 +48,17 @@ passByReference <- function(fun,
4148 lines
4249 }
4350
51+ # From "x", create lines like
52+ # nCompiler::createRef("x_Ref__", x)
4453 subList <- args_2_subList(refArgs , " _Ref__" )
4554 refArg_activeBinding_lines <- subList_2_lines(subList , " createRef" )
4655
56+ # From "y", create lines like
57+ # nCompiler::createBlockRef("y_BlockRef__", y)
4758 blockSubList <- args_2_subList(blockRefArgs , " _BlockRef__" )
4859 blockRefArg_activeBinding_lines <- subList_2_lines(blockSubList , " createBlockRef" )
4960
61+ # In the original code, replace x with x_Ref__, y with y_BlockRef__, etc.
5062 code <-
5163 eval(
5264 substitute(
@@ -56,6 +68,7 @@ passByReference <- function(fun,
5668 )
5769 )
5870
71+ # Wrap in braces if not already
5972 if (code [[1 ]] != ' {' )
6073 code <- substitute({CODE }, list (CODE = code ))
6174
@@ -102,8 +115,7 @@ createRef <- function(innerName,
102115createBlockRef <- function (innerName ,
103116 outerCode ,
104117 env ,
105- innerEnv ,
106- dummyName = ' DUMMY_FOR_CREATE_BLOCK_REF_' ) {
118+ innerEnv ) {
107119 # There is potential for more elaborate error-trapping.
108120 # E.g. we could determine the sizes (or net length) of outerCode (assignment target)
109121 # and check that v matches it.
@@ -117,19 +129,18 @@ createBlockRef <- function(innerName,
117129 stop(" A block reference argument must be passed as a variable name, e.g. `x`, or an indexed block of a variable, e.g. `x[1:4, 2:3]` or `x[1:4, ]`." )
118130 }
119131 outerLen <- eval(substitute(length(OC ), list (OC = outerCode )), envir = env )
120- outer_dummy_assign_code <- substitute(L <- R ,
121- list (L = outerCode ,
122- R = as.name(dummyName )))
132+ assignment_code <- substitute(L <- NULL ,
133+ list (L = outerCode ))
123134 binding <-
124135 function (v )
125136 if (missing(v ))
126137 eval(outerCode , env )
127138 else {
128139 if (outerLen != length(v ))
129140 stop(" blockRef assignment must match in length." )
130- assign( dummyName , v , env )
131- on.exit(rm( list = dummyName , envir = env ) )
132- eval( outer_dummy_assign_code , env )
141+ assignment_code [[ 3 ]] <<- v
142+ eval( assignment_code , env )
143+ assignment_code [[ 3 ]] <<- NULL
133144 v
134145 }
135146 makeActiveBinding(innerName , binding , innerEnv )
0 commit comments