Nothing
# Import scoping, load (source-like), and run (isolated) tests.
# Written first (TDD); implementation follows.
thin <- make_cran_thinner()
test_that("imports are not visible across distinct child environments", {
thin()
# Each load runs in a fresh child env; file B must not see file A's imports.
engine <- make_engine()
parent_env <- engine$get_env()
tmp_dir <- tempfile()
dir.create(tmp_dir)
old_dir <- getwd()
setwd(tmp_dir)
on.exit({
setwd(old_dir)
unlink(tmp_dir, recursive = TRUE)
}, add = TRUE)
module_name <- paste0("mymod", sample.int(100000, 1))
module_file <- file.path(tmp_dir, paste0(module_name, ".arl"))
writeLines(c(
sprintf("(module %s", module_name),
" (export myfn)",
" (define myfn (lambda (x) (* x 2))))"
), module_file)
file_a <- file.path(tmp_dir, "file_a.arl")
writeLines(c(
sprintf("(import %s :refer :all)", module_name),
"(myfn 5)"
), file_a)
file_b <- file.path(tmp_dir, "file_b.arl")
writeLines("(myfn 5)", file_b)
engine$load_file_in_env(file_a, env = new.env(parent = parent_env))
expect_error(engine$load_file_in_env(file_b, env = new.env(parent = parent_env)), regexp = "myfn|not found|object")
})
test_that("imports are visible in the same file", {
thin()
engine <- make_engine()
parent_env <- engine$get_env()
tmp_dir <- tempfile()
dir.create(tmp_dir)
old_dir <- getwd()
setwd(tmp_dir)
on.exit({
setwd(old_dir)
unlink(tmp_dir, recursive = TRUE)
}, add = TRUE)
# Use stdlib 'list' so we don't need a temp module
path <- file.path(tmp_dir, "single.arl")
writeLines(c("(import list :refer :all)", "(cadr (list 1 2 3))"), path)
result <- engine$load_file_in_env(path, env = new.env(parent = parent_env))
expect_equal(result, 2)
})
test_that("(load path) runs in caller env - definitions visible", {
thin()
engine <- make_engine()
env <- engine$get_env()
tmp_dir <- tempfile()
dir.create(tmp_dir)
old_dir <- getwd()
setwd(tmp_dir)
on.exit({
setwd(old_dir)
unlink(tmp_dir, recursive = TRUE)
}, add = TRUE)
defs_path <- file.path(tmp_dir, "defs.arl")
writeLines("(define shared 99)", defs_path)
main_code <- sprintf('(begin (load "%s") shared)', normalizePath(defs_path, winslash = "/"))
exprs <- engine$read(main_code)
result <- engine$eval(exprs[[1]], env = env)
expect_equal(result, 99)
})
test_that("(load path) runs in caller env - imports visible to caller", {
thin()
engine <- make_engine()
env <- engine$get_env()
tmp_dir <- tempfile()
dir.create(tmp_dir)
old_dir <- getwd()
setwd(tmp_dir)
on.exit({
setwd(old_dir)
unlink(tmp_dir, recursive = TRUE)
}, add = TRUE)
with_import_path <- file.path(tmp_dir, "with_import.arl")
writeLines(c("(import list :refer :all)", "(define x (cadr (list 1 2 3)))"), with_import_path)
main_code <- sprintf('(begin (load "%s") x)', normalizePath(with_import_path, winslash = "/"))
exprs <- engine$read(main_code)
result <- engine$eval(exprs[[1]], env = env)
expect_equal(result, 2)
})
test_that("(run path) runs in child env - definitions not visible in caller", {
thin()
engine <- make_engine()
env <- engine$get_env()
tmp_dir <- tempfile()
dir.create(tmp_dir)
old_dir <- getwd()
setwd(tmp_dir)
on.exit({
setwd(old_dir)
unlink(tmp_dir, recursive = TRUE)
}, add = TRUE)
defs_path <- file.path(tmp_dir, "secret.arl")
writeLines("(define secret 42)", defs_path)
main_code <- sprintf('(begin (run "%s") secret)', normalizePath(defs_path, winslash = "/"))
exprs <- engine$read(main_code)
expect_error(engine$eval(exprs[[1]], env = env), regexp = "secret|not found|object")
})
test_that("(run path) runs in child env - imports not visible in caller", {
thin()
# Use a custom module with a unique export; the engine env already has stdlib (e.g. cadr).
engine <- make_engine()
env <- engine$get_env()
tmp_dir <- tempfile()
dir.create(tmp_dir)
old_dir <- getwd()
setwd(tmp_dir)
on.exit({
setwd(old_dir)
unlink(tmp_dir, recursive = TRUE)
}, add = TRUE)
mod_name <- paste0("runmod", sample.int(100000, 1))
mod_file <- file.path(tmp_dir, paste0(mod_name, ".arl"))
writeLines(c(
sprintf("(module %s", mod_name),
" (export uniquefn)",
" (define uniquefn (lambda (x) (+ x 1))))"
), mod_file)
run_import_path <- file.path(tmp_dir, "run_import.arl")
writeLines(sprintf("(import %s)", mod_name), run_import_path)
main_code <- sprintf('(begin (run "%s") (uniquefn 1))', normalizePath(run_import_path, winslash = "/"))
exprs <- engine$read(main_code)
expect_error(engine$eval(exprs[[1]], env = env), regexp = "uniquefn|not found|object")
})
test_that("(run path parent) uses parent for lookup and stays isolated", {
thin()
engine <- make_engine()
caller_env <- engine$get_env()
parent_env <- new.env(parent = caller_env)
parent_env$parent_value <- 7
caller_env$custom_parent <- parent_env
tmp_dir <- tempfile()
dir.create(tmp_dir)
old_dir <- getwd()
setwd(tmp_dir)
on.exit({
setwd(old_dir)
unlink(tmp_dir, recursive = TRUE)
}, add = TRUE)
defs_path <- file.path(tmp_dir, "parent_lookup.arl")
writeLines(c("(define from-run (+ parent_value 1))", "from-run"), defs_path)
main_code <- sprintf('(run "%s" custom_parent)', normalizePath(defs_path, winslash = "/"))
exprs <- engine$read(main_code)
expect_equal(engine$eval(exprs[[1]], env = caller_env), 8)
expect_false(exists("from-run", envir = caller_env, inherits = FALSE))
expect_false(exists("from-run", envir = parent_env, inherits = FALSE))
})
test_that("global module cache: same module loaded once per engine, shared across child envs", {
thin()
# Module with side effect (counter); two files each import it and call tick.
# With global cache, module runs once so counter is shared: file_a returns 1, file_b returns 2.
engine <- make_engine()
parent_env <- engine$get_env()
tmp_dir <- tempfile()
dir.create(tmp_dir)
old_dir <- getwd()
setwd(tmp_dir)
on.exit({
setwd(old_dir)
unlink(tmp_dir, recursive = TRUE)
}, add = TRUE)
mod_name <- paste0("cached", sample.int(100000, 1))
mod_file <- file.path(tmp_dir, paste0(mod_name, ".arl"))
writeLines(c(
sprintf("(module %s", mod_name),
" (export tick)",
" (define counter 0)",
" (define tick (lambda () (begin (set! counter (+ counter 1)) counter))))"
), mod_file)
file_a <- file.path(tmp_dir, "file_a.arl")
writeLines(c(sprintf("(import %s :refer :all)", mod_name), "(tick)"), file_a)
file_b <- file.path(tmp_dir, "file_b.arl")
writeLines(c(sprintf("(import %s :refer :all)", mod_name), "(tick)"), file_b)
expect_equal(engine$load_file_in_env(file_a, env = new.env(parent = parent_env)), 1)
expect_equal(engine$load_file_in_env(file_b, env = new.env(parent = parent_env)), 2)
})
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.