Skip to content

Commit 2756b9c

Browse files
committed
Preserve long fill lengths
1 parent ff65a37 commit 2756b9c

4 files changed

Lines changed: 47 additions & 7 deletions

File tree

R/classes.R

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,14 @@ Variable := new_class(
339339
# storage (0/1) rather than Fortran LOGICAL.
340340
logical_as_int = prop_bool(default = FALSE),
341341

342+
# Fortran kind for integer variables. User-facing R integers remain c_int;
343+
# pointer-sized compiler locals opt into c_ptrdiff_t explicitly.
344+
integer_kind = prop_enum(
345+
c("c_int", "c_ptrdiff_t"),
346+
default = "c_int",
347+
exact = TRUE
348+
),
349+
342350
# TRUE when the variable is available via host association and should not
343351
# be redeclared in the local scope.
344352
host_associated = prop_bool(default = FALSE),
@@ -350,7 +358,13 @@ Variable := new_class(
350358

351359
validator = function(self) {
352360
if (isTRUE(self@logical_as_int) && !identical(self@mode, "logical")) {
353-
"`logical_as_int` can only be TRUE when `mode` is 'logical'"
361+
return("`logical_as_int` can only be TRUE when `mode` is 'logical'")
362+
}
363+
if (
364+
!identical(self@integer_kind, "c_int") &&
365+
!identical(self@mode, "integer")
366+
) {
367+
"`integer_kind` can only differ from 'c_int' when `mode` is 'integer'"
354368
}
355369
}
356370
)

R/manifest.R

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,11 @@ var_storage_bytes <- function(var) {
7373
switch(
7474
var@mode,
7575
double = 8,
76-
integer = 4,
76+
integer = if (identical(var@integer_kind, "c_ptrdiff_t")) {
77+
.Machine$sizeof.pointer
78+
} else {
79+
4
80+
},
7781
complex = 16,
7882
logical = 4,
7983
raw = 1,
@@ -196,7 +200,7 @@ iso_c_binding_symbols <- function(
196200
switch(
197201
var@mode,
198202
double = "c_double",
199-
integer = "c_int",
203+
integer = var@integer_kind,
200204
complex = "c_double_complex",
201205
logical = if (isTRUE(logical_is_c_int(var))) "c_int",
202206
raw = "c_int8_t",
@@ -262,7 +266,7 @@ emit_decl_line <- function(
262266
type <- switch(
263267
var@mode,
264268
double = "real(c_double)",
265-
integer = "integer(c_int)",
269+
integer = glue("integer({var@integer_kind})"),
266270
complex = "complex(c_double_complex)",
267271
logical = if (logical_as_int(var)) "integer(c_int)" else "logical",
268272
raw = "integer(c_int8_t)",
@@ -371,7 +375,7 @@ r2f.scope <- function(scope, include_errors = FALSE) {
371375
type <- switch(
372376
var@mode,
373377
double = "real(c_double)",
374-
integer = "integer(c_int)",
378+
integer = glue("integer({var@integer_kind})"),
375379
complex = "complex(c_double_complex)",
376380
logical = if (logical_as_int(var)) "integer(c_int)" else "logical",
377381
raw = "integer(c_int8_t)",

R/r2f-constructors.R

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,16 @@ r2f_handlers[["c"]] <- function(args, scope = NULL, ...) {
6060
call. = FALSE
6161
)
6262
}
63-
spread_var <- spread_var %||% scope_unique_var(scope, "integer")
63+
spread_var <- spread_var %||%
64+
scope_unique_var(
65+
scope,
66+
"integer",
67+
integer_kind = "c_ptrdiff_t"
68+
)
6469
ff[[j]] <- Fortran(
65-
glue("({ff[[j]]}, {spread_var}=1, int({len_f}))"),
70+
glue(
71+
"({ff[[j]]}, {spread_var}=1_c_ptrdiff_t, int({len_f}, kind=c_ptrdiff_t))"
72+
),
6673
ff[[j]]@value
6774
)
6875
}

tests/testthat/test-recycling.R

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,21 @@ test_that("fill constructors spread inside c()", {
237237
expect_quick_identical(logical_fill, list(c(TRUE, FALSE)))
238238
})
239239

240+
test_that("symbolic fill spreading preserves pointer-sized lengths", {
241+
fn <- function(x) {
242+
declare(type(x = double(NA)))
243+
c(numeric(length(x)), 1)
244+
}
245+
fsub <- as.character(r2f(fn))
246+
expect_match(fsub, "integer(c_ptrdiff_t) :: tmp1_", fixed = TRUE)
247+
expect_match(
248+
fsub,
249+
"tmp1_=1_c_ptrdiff_t, int(x__len_, kind=c_ptrdiff_t)",
250+
fixed = TRUE
251+
)
252+
expect_quick_identical(fn, list(c(2, 4, 6)))
253+
})
254+
240255
test_that("fill constructors materialize where an array is required", {
241256
# A fill reaching c() through an expression is a real array, not a
242257
# scalar literal with claimed dims (which emitted one element where the

0 commit comments

Comments
 (0)