"  (define square (lambda (x) (* x x)))"
"  (define cube (lambda (x) (* x x x)))"
"import with no modifiers imports all exports"
"import :refer imports only specified symbols"
"not found|could not find|object .* not found"
"import :refer errors on names not in module exports"
"import :refer :all imports all exports"
"import :as with :refer combines correctly"
"(import testmod :as m :refer (square))"
"import :rename renames specified symbols"
"(import testmod :rename ((square sq)))"
"import :rename errors on names not in module exports"
"(import testmod :rename ((nonexistent foo)))"
"import :refer + :rename composes correctly"
"(import testmod :refer (square cube) :rename ((square sq)))"
"  (defmacro my-when (test . body) `(if ,test (begin ,@body) #nil))"
"(import macmod3 :rename ((mw3 my-when3)))"
"import with empty :refer imports nothing unqualified"
"import with path string supports modifiers"
"proxy-based imports are accessible via scoping but not in ls(env)"
"reference semantics: module bindings are locked"
"parser: math/inc produces (module-ref math inc)"
"parser: a/b/c produces nested module-ref"
"parser: bare / stays as division symbol"
"parser: round-trip math/inc -> write -> math/inc"
"parser: round-trip a/b/c -> write -> a/b/c"
"parser: R infix operators %/% are not split"
"qualified access: import :refer then mod/sym resolves"
"qualified access: import :as then alias/sym resolves"

import with path string supports modifiers

<arl_error/error/condition>
Error: Module not found: D:	emp\2026_02_23_11_20_16_15377\Rtmp4WUrHm\filee18443476fd/pathmod.arl

test_that("engine$load_file_in_env evaluates source into environment", {
writeLines(c("(define foo 42)", "(define bar (+ foo 1))"), path)
expect_equal(get("foo", envir = env), 42)
expect_equal(get("bar", envir = env), 43)
test_that("(load ...) evaluates file in current environment", {
path_for_arl <- normalizePath(path, winslash = "/", mustWork = FALSE)
exprs <- engine$read(paste0("(load \"", path_for_arl, "\")"))
expect_equal(get("foo", envir = env), 7)
test_that("(load path env) evaluates file in the provided environment", {
target_env <- new.env(parent = caller_env)
exprs <- engine$read(paste0("(load \"", path_for_arl, "\" target-env)"))
expect_equal(get("scoped-value", envir = target_env), 11)
expect_false(exists("scoped-value", envir = caller_env, inherits = FALSE))
test_that("(load ...) does not resolve stdlib by name", {
# load should NOT do stdlib lookup; that's import's job
engine$eval(engine$read("(load \"control\")")[[1]], env = env),
test_that("(load ...) re-evaluates on each call", {
writeLines("(set! counter (+ counter 1))", path)
expr <- engine$read(paste0("(load \"", path_for_arl, "\")"))[[1]]
expect_equal(get("counter", envir = env), 1L)
expect_equal(get("counter", envir = env), 2L)
test_that("stdlib modules register macros", {
expect_true(engine_field(engine, "macro_expander")$is_macro(as.symbol("when"), env = env))
expect_true(engine_field(engine, "macro_expander")$is_macro(as.symbol("unless"), env = env))
expect_true(engine_field(engine, "macro_expander")$is_macro(as.symbol("let"), env = env))
expect_true(engine_field(engine, "macro_expander")$is_macro(as.symbol("->"), env = env))
expect_true(engine_field(engine, "macro_expander")$is_macro(as.symbol("try-catch"), env = env))
test_that("(import ...) loads module exports into environment", {
module_name <- paste0("math", sample.int(100000, 1))
module_file <- file.path(tmp_dir, paste0(module_name, ".arl"))
exprs <- engine$read(sprintf("(import %s :refer :all)", module_name))
expect_equal(engine$eval(exprs[[1]], env = env), 9)
test_that("(import ...) does not re-evaluate loaded modules", {
module_name <- paste0("counter", sample.int(100000, 1))
"  (define tick (lambda () (begin (set! counter (+ counter 1)) counter))))"
expect_equal(engine$eval(exprs[[1]], env = env), 1)
expect_equal(engine$eval(exprs[[1]], env = env), 2)
expect_equal(engine$eval(engine$read("(tick)")[[1]], env = env), 3)
test_that("(import ...) errors on missing modules and exports", {
missing_name <- paste0("missing", sample.int(100000, 1))
exprs <- engine$read(sprintf("(import %s)", missing_name))
expect_error(engine$eval(exprs[[1]], env = env), "Module not found")
module_name <- paste0("bad", sample.int(100000, 1))
exprs <- engine$read(sprintf("(import %s)", module_name))
expect_error(engine$eval(exprs[[1]], env = env), "not defined or imported")
test_that("(import \"path\") loads module by path and attaches exports", {
"  (define double (lambda (x) (* x 2))))"
exprs <- engine$read(sprintf('(import "%s" :refer :all)', module_file))
expect_equal(engine$eval(exprs[[1]], env = env), 14)
test_that("second (import \"path\") does not reload module", {
"  (define getn (lambda () (begin (set! n (+ n 1)) n))))"
expect_equal(engine$eval(engine$read("(getn)")[[1]], env = env), 1)
expect_equal(engine$eval(engine$read("(getn)")[[1]], env = env), 2)
test_that("relative import paths resolve from importing file's directory", {
dir.create(file.path(tmp_dir, "lib"), recursive = TRUE)
# lib/helper.arl - a module in a subdirectory
# lib/main.arl - imports sibling via relative path
on.exit(unlink(tmp_dir, recursive = TRUE), add = TRUE)
# CWD is NOT the lib directory — relative path must resolve from file, not CWD
main_path <- normalizePath(file.path(tmp_dir, "lib", "main.arl"),
expect_equal(get("main-val", envir = env), 99)
test_that("(import symbol) is module name, (import \"string\") is path", {
expect_silent(engine$eval(engine$read("(import control :refer :all)")[[1]], env = env))
missing_path <- tempfile(fileext = ".arl")
engine$eval(engine$read(sprintf('(import "%s")', missing_path))[[1]], env = env),