tests/testthat/test-engine-api.R

# Tests for Engine public API methods.

# =============================================================================
# define()
# =============================================================================

thin <- make_cran_thinner()

test_that("define() binds a value visible to Arl code", {
  thin()
  engine <- make_engine(load_prelude = FALSE)
  engine$define("my_val", 42)
  expect_equal(engine$eval_text("my_val"), 42)
})

test_that("define() works with complex R objects", {
  thin()
  engine <- make_engine(load_prelude = FALSE)
  engine$define("df", mtcars)
  expect_equal(engine$eval_text("(nrow df)"), nrow(mtcars))
  expect_equal(engine$eval_text("(median ($ df \"mpg\"))"), median(mtcars$mpg))
})

test_that("define() returns engine invisibly for chaining", {
  thin()
  engine <- make_engine(load_prelude = FALSE)
  result <- engine$define("x", 10)$define("y", 20)$eval_text("(+ x y)")
  expect_equal(result, 30)
})

test_that("define() validates name argument", {
  thin()
  engine <- make_engine(load_prelude = FALSE)
  expect_error(engine$define(42, "val"), "non-empty character string")
  expect_error(engine$define("", "val"), "non-empty character string")
  expect_error(engine$define(c("a", "b"), "val"), "non-empty character string")
})

test_that("define() overwrites existing bindings", {
  thin()
  engine <- make_engine(load_prelude = FALSE)
  engine$define("x", 1)
  expect_equal(engine$eval_text("x"), 1)
  engine$define("x", 2)
  expect_equal(engine$eval_text("x"), 2)
})

# =============================================================================
# get_env()
# =============================================================================

test_that("get_env() provides access to engine bindings", {
  thin()
  engine <- make_engine(load_prelude = FALSE)
  engine$eval_text("(define test-binding 99)")
  env <- engine$get_env()
  expect_true(exists("test-binding", envir = env, inherits = FALSE))
  expect_equal(get("test-binding", envir = env), 99)
})

# =============================================================================
# eval_text() / eval_string()
# =============================================================================

test_that("eval_text returns last value of multiple expressions", {
  thin()
  engine <- make_engine(load_prelude = FALSE)
  result <- engine$eval_text("(define a 1) (define b 2) (+ a b)")
  expect_equal(result, 3)
})

test_that("eval_text with empty input returns NULL invisibly", {
  thin()
  engine <- make_engine(load_prelude = FALSE)
  result <- engine$eval_text("")
  expect_null(result)
})

test_that("eval_string is an alias for eval_text", {
  thin()
  engine <- make_engine(load_prelude = FALSE)
  expect_equal(engine$eval_string("(+ 1 2)"), 3)
})

# =============================================================================
# read() + eval()
# =============================================================================

test_that("read() parses source into expression list", {
  thin()
  engine <- make_engine(load_prelude = FALSE)
  exprs <- engine$read("(+ 1 2) (* 3 4)")
  expect_length(exprs, 2)
})

test_that("eval() evaluates multiple expressions sequentially", {
  thin()
  engine <- make_engine(load_prelude = FALSE)
  exprs <- engine$read("(define ea-x 10) (+ ea-x 5)")
  result <- engine$eval(exprs[[1]], exprs[[2]])
  expect_equal(result, 15)
})

# =============================================================================
# format_value()
# =============================================================================

test_that("format_value formats Arl values as strings", {
  thin()
  engine <- make_engine(load_prelude = FALSE)
  engine$eval_text("(define fv-lst (list 1 2 3))")
  result <- engine$format_value(engine$eval_text("fv-lst"))
  expect_true(is.character(result))
  expect_true(nzchar(result))
})

# =============================================================================
# inspect_compilation()
# =============================================================================

test_that("inspect_compilation returns parsed, expanded, compiled, and deparsed", {
  thin()
  engine <- make_engine(load_prelude = FALSE)
  result <- engine$inspect_compilation("(+ 1 2)")
  expect_true(is.list(result))
  expect_named(result, c("parsed", "expanded", "compiled", "compiled_deparsed"))
  expect_false(is.null(result$parsed))
  expect_false(is.null(result$compiled))
  expect_true(is.character(result$compiled_deparsed))
})

test_that("inspect_compilation with empty input returns NULLs", {
  thin()
  engine <- make_engine(load_prelude = FALSE)
  result <- engine$inspect_compilation("")
  expect_true(all(vapply(result, is.null, logical(1))))
})

# =============================================================================
# write()
# =============================================================================

test_that("write() converts expression to string", {
  thin()
  engine <- make_engine(load_prelude = FALSE)
  expr <- engine$read("(+ 1 2)")[[1]]
  result <- engine$write(expr)
  expect_equal(result, "(+ 1 2)")
})

# =============================================================================
# macroexpand()
# =============================================================================

test_that("macroexpand() expands macros in an expression", {
  thin()
  engine <- make_engine()
  expr <- engine$read("(when #t 42)")[[1]]
  expanded <- engine$macroexpand(expr)
  # when expands to an if form
  expect_true(is.call(expanded))
  expect_equal(as.character(expanded[[1]]), "if")
})

# =============================================================================
# load_file_in_env()
# =============================================================================

test_that("load_file_in_env evaluates a file in the engine env", {
  thin()
  engine <- make_engine(load_prelude = FALSE)
  path <- tempfile(fileext = ".arl")
  writeLines("(define lf-test-val 77)", path)
  on.exit(unlink(path))

  engine$load_file_in_env(path)
  expect_equal(engine$eval_text("lf-test-val"), 77)
})

Try the arl package in your browser

Any scripts or data that you put into this service are public.

arl documentation built on March 19, 2026, 5:09 p.m.