@@ -1147,15 +1147,15 @@ r2f_handlers[["cbind"]] <- function(e, scope) {
11471147 ncols <- eval(ncols , scope @ sizes )
11481148}
11491149
1150- r2f_handlers [[" <-" ]] <- function (args , scope , ... ) {
1150+ r2f_handlers [[" <-" ]] <- function (args , scope , ... , hoist = NULL ) {
11511151 target <- args [[1 ]]
11521152 if (is.call(target )) {
11531153 # given a call like `foo(x) <- y`, dispatch to `foo<-`
11541154 target_callable <- target [[1 ]]
11551155 stopifnot(is.symbol(target_callable ))
11561156 name <- as.symbol(paste0(as.character(target_callable ), " <-" ))
11571157 handler <- get_r2f_handler(name )
1158- return (handler(args , scope , ... )) # new hoist target
1158+ return (handler(args , scope , ... , hoist = hoist )) # new hoist target
11591159 }
11601160
11611161 # It sure seems like it's be nice if the Fortran() constructor
@@ -1166,6 +1166,37 @@ r2f_handlers[["<-"]] <- function(args, scope, ...) {
11661166
11671167 rhs <- args [[2 ]]
11681168
1169+ # Fall-through assignment: `a <- b <- expr` (or `a <- (b <- expr)`).
1170+ # R evaluates this right-to-left and returns the assigned value, i.e.
1171+ # `a <- (b <- expr)` is equivalent to `b <- expr; a <- b`.
1172+ rhs_unwrapped <- rhs
1173+ while (is_call(rhs_unwrapped , " (" ) && length(rhs_unwrapped ) == 2L ) {
1174+ rhs_unwrapped <- rhs_unwrapped [[2L ]]
1175+ }
1176+ if (
1177+ (is_call(rhs_unwrapped , " <-" ) || is_call(rhs_unwrapped , " =" )) &&
1178+ length(rhs_unwrapped ) == 3L &&
1179+ is.symbol(rhs_unwrapped [[2L ]])
1180+ ) {
1181+ inner_target <- rhs_unwrapped [[2L ]]
1182+ inner_rhs <- rhs_unwrapped [[3L ]]
1183+
1184+ inner_stmt <- r2f(
1185+ call(" <-" , inner_target , inner_rhs ),
1186+ scope ,
1187+ ... ,
1188+ hoist = hoist
1189+ )
1190+ outer_stmt <- r2f(
1191+ call(" <-" , target , inner_target ),
1192+ scope ,
1193+ ... ,
1194+ hoist = hoist
1195+ )
1196+
1197+ return (Fortran(str_flatten_lines(inner_stmt , outer_stmt )))
1198+ }
1199+
11691200 # Local closure definition: `f <- function(i) ...`
11701201 if (is_function_call(rhs )) {
11711202 scope [[name ]] <- as_local_closure(
@@ -1182,15 +1213,21 @@ r2f_handlers[["<-"]] <- function(args, scope, ...) {
11821213 is.symbol(rhs [[1L ]]) &&
11831214 inherits(scope [[as.character(rhs [[1L ]])]], LocalClosure )
11841215 ) {
1185- return (compile_closure_call_assignment(name , rhs , scope , ... ))
1216+ return (compile_closure_call_assignment(
1217+ name ,
1218+ rhs ,
1219+ scope ,
1220+ ... ,
1221+ hoist = hoist
1222+ ))
11861223 }
11871224
11881225 # Targeted higher-order lowering: `out <- sapply(seq_along(x), f)`
11891226 if (is_sapply_call(rhs )) {
1190- return (compile_sapply_assignment(name , rhs , scope , ... ))
1227+ return (compile_sapply_assignment(name , rhs , scope , ... , hoist = hoist ))
11911228 }
11921229
1193- value <- r2f(rhs , scope , ... )
1230+ value <- r2f(rhs , scope , ... , hoist = hoist )
11941231
11951232 # immutable / copy-on-modify usage of Variable()
11961233 var <- get0(name , scope , inherits = FALSE )
0 commit comments