File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -116,6 +116,26 @@ drop_nulls <- function(x, i) {
116116
117117last <- function (x ) x [[length(x )]]
118118drop_last <- function (x ) x [- length(x )]
119+
120+ compile_nonreturn_statements <- function (stmts , scope ) {
121+ if (! length(stmts )) {
122+ return (" " )
123+ }
124+
125+ compiled <- lapply(stmts , function (stmt ) {
126+ stmt_f <- r2f(stmt , scope )
127+ if (! is.null(stmt_f @ value )) {
128+ stop(
129+ " all expressions except the final return must compile to a statement (no value); found: " ,
130+ deparse1(stmt ),
131+ call. = FALSE
132+ )
133+ }
134+ stmt_f
135+ })
136+
137+ str_flatten_lines(compiled )
138+ }
119139# fmt: skip
120140{
121141is_scalar_na <- function (x ) is.atomic(x ) && ! is.object(x ) && length(x ) == 1L && is.na(x )
Original file line number Diff line number Diff line change @@ -168,16 +168,12 @@ compile_internal_subroutine <- function(
168168 if (is.null(last(stmts ))) {
169169 stmts <- drop_last(stmts )
170170 }
171- if (length(stmts )) {
172- body_prefix <- lapply(stmts , function (stmt ) r2f(stmt , proc_scope ))
173- body_prefix <- str_flatten_lines(body_prefix )
174- }
171+ body_prefix <- compile_nonreturn_statements(stmts , proc_scope )
175172 } else {
176173 last_expr <- last(stmts )
177174 prefix <- drop_last(stmts )
178175
179- body_prefix <- lapply(prefix , function (stmt ) r2f(stmt , proc_scope ))
180- body_prefix <- str_flatten_lines(body_prefix )
176+ body_prefix <- compile_nonreturn_statements(prefix , proc_scope )
181177
182178 h <- new_hoist(proc_scope )
183179 expr_error <- NULL
Original file line number Diff line number Diff line change @@ -30,7 +30,8 @@ new_fortran_subroutine <- function(
3030 # declare(type(foo = integer(foo_dim_1_, foo_dim_2_)),
3131 # type(bar = integer(foo_dim_1_, 3L)))
3232 body <- substitute_declared_sizes(body )
33- body <- r2f(drop_last(body ), scope )
33+ stmts <- as.list(body )[- 1L ]
34+ body <- compile_nonreturn_statements(drop_last(stmts ), scope )
3435
3536 # check all input vars were declared
3637 # TODO: this check might be too late, because r2f() might throw cryptic errors
Original file line number Diff line number Diff line change @@ -7,3 +7,63 @@ test_that("case-sensitive variable name clashes", {
77 })
88 })
99})
10+
11+ test_that(" non-final expressions must be assigned" , {
12+ expect_error(regexp = " all expressions except the final return" , {
13+ quick(function (x ) {
14+ declare(type(x = double(1 )))
15+ x + 1
16+ x
17+ })
18+ })
19+
20+ expect_error(regexp = " all expressions except the final return" , {
21+ quick(function (x ) {
22+ declare(type(x = double(1 )))
23+ x
24+ x
25+ })
26+ })
27+
28+ expect_error(regexp = " all expressions except the final return" , {
29+ quick(function (x ) {
30+ declare(type(x = double(1 )))
31+ x <- x + 1
32+ x + 1
33+ x
34+ })
35+ })
36+ })
37+
38+ test_that(" value-returning local closures can be called as statements" , {
39+ fn <- function (x ) {
40+ declare(type(x = double(1 )))
41+
42+ apply_boundary_conditions <- function () {
43+ x <<- x + 1
44+ }
45+
46+ apply_boundary_conditions()
47+ x
48+ }
49+
50+ # r2f(fn)
51+
52+ expect_quick_identical(fn , list (1 ))
53+
54+ fn <- function (x ) {
55+ declare(type(x = double(1 )))
56+
57+ apply_boundary_conditions <- function () {
58+ x <<- x + 1
59+ x
60+ }
61+
62+ apply_boundary_conditions()
63+ x
64+ }
65+
66+ # r2f(fn)
67+
68+ expect_quick_identical(fn , list (1 ))
69+ })
You can’t perform that action at this time.
0 commit comments