Lines
100 %
Functions
Branches
//! DO / DO* / DOLIST edge-case coverage — static-eval branches,
//! non-terminating-loop fallback, multi-statement bodies, &c.
use super::common::{
compile_and_validate, compile_expect_error, wrap_with_runtime_i32, wrap_with_runtime_ratio,
};
#[test]
fn do_with_bool_end_test() {
compile_and_validate("(do ((i 0 (+ i 1))) (#t i))");
}
fn do_static_evaluable_loop() {
// Fully static; the eval-time loop runs to completion and the
// result form is the final i.
compile_and_validate("(do ((i 0 (+ i 1))) ((= i 5) i))");
fn do_with_complex_step_expression() {
// IDX is a runtime Index; the counter `i` and the complex step stay in the
// Index stratum (mixing an index counter with a Scalar bound is refused).
compile_and_validate(&wrap_with_runtime_i32(
"(do ((i 0 (+ i (- IDX 1)))) ((>= i IDX)) (debug i))",
));
fn do_star_with_dependent_step() {
// IDX is a runtime Index bound; the counter `i`, the dependent var `j`, and
// the end-test stay in the Index stratum (an index counter cannot be
// compared against a Scalar — the implicit bridge is gone).
"(do* ((i 0 (+ i 1)) (j i (- j 1))) ((>= i IDX) j))",
fn dolist_no_body_errors() {
// DOLIST requires at least one body form.
let err = compile_expect_error("(dolist (x '(1 2 3)))");
assert!(err.contains("DOLIST"), "got: {err}");
fn dolist_with_multi_form_body() {
compile_and_validate(
"(let* ((acc 0)) \
(dolist (x '(1 2 3)) \
(debug \"step\") \
(setf acc (+ acc x)) \
(debug acc)) \
acc)",
);
fn dolist_with_no_loop_var_init_errors() {
let err = compile_expect_error("(dolist () 0)");
fn do_missing_var_list_errors() {
let err = compile_expect_error("(do)");
assert!(err.contains("DO"), "got: {err}");
fn do_star_missing_end_clause_errors() {
let err = compile_expect_error("(do* ((i 0 (+ i 1))))");
assert!(err.contains("DO*"), "got: {err}");
fn do_with_multi_result_form() {
compile_and_validate("(do ((i 0 (+ i 1))) ((= i 3) (debug \"done\") i))");
/// DO* sequential init where the second var depends on the first
/// at runtime — exercises the runtime-init path in `compile_do_star`.
fn do_star_runtime_dependent_init() {
compile_and_validate(&wrap_with_runtime_ratio(
"(do* ((a X) (b a (- b 1))) ((<= b 0) b))",