Lines
100 %
Functions
Branches
//! DO / DO* with runtime-valued bounds. `N` is bound to a real
//! runtime Ratio via the host fn; the loop test exercises the
//! compile_do_runtime path that allocates a wasm local for `I` and
//! emits the step/test wasm.
use super::common::{compile_and_validate, compile_expect_error};
/// Wraps a do-loop body so `N` is a runtime Ratio.
fn wrap_with_runtime_n(body: &str) -> String {
// N is a loop bound — a count — so it is a runtime Index (I32). ADR-0028:
// an integer counter loop stays in the Index stratum end to end.
format!("(let* ((N (entity-count))) {body})")
}
#[test]
fn runtime_do_simple() {
compile_and_validate(&wrap_with_runtime_n("(do ((I 0 (+ I 1))) ((>= I N) I))"));
fn runtime_do_with_body() {
compile_and_validate(&wrap_with_runtime_n(
"(let* ((SUM 0)) \
(do ((I 0 (+ I 1))) ((>= I N) SUM) \
(setf SUM (+ SUM I))))",
));
fn runtime_do_star() {
compile_and_validate(&wrap_with_runtime_n("(do* ((I 0 (+ I 1))) ((>= I N) I))"));
fn runtime_do_multiple_vars() {
"(do ((I 0 (+ I 1)) (J N (- J 1))) ((>= I J) (+ I J)))",
fn runtime_do_no_result_form() {
compile_and_validate(&wrap_with_runtime_n("(do ((I 0 (+ I 1))) ((>= I N)))"));
/// A runtime DO whose accumulator step is `(cons <host-fn> acc)` drives the
/// pair-element inference walker (`infer_result_pair_element` →
/// `step_pair_element` → `resolve_pair_element_from_expr`), which eval-probes
/// the pure-native cons car (gated by `is_pure_native_expr` / `head_is_native`)
/// to size the accumulator local. The car here is a native host-fn call, so
/// the probe fires and the accumulator is sized to its element type.
fn runtime_do_cons_accumulator_pure_native_car() {
"(do ((I 0 (+ I 1)) (ACC nil (cons (transaction-post-date 0) ACC))) ((>= I N) ACC))",
/// Same accumulator shape but the cons car wraps a USER function. The
/// pair-element walker (`is_pure_native_expr` / `names_user_callable`) must
/// REFUSE to eval-probe a user-callable subtree — so inference can't recurse
/// into (possibly non-terminating) user code. With the car un-probeable the
/// nil-init accumulator can't be sized from it and falls to the nil default,
/// so this `(cons <user-fn> nil-acc)` shape is a clean STRUCTURED compile
/// error, never a compiler overflow. (Probing it instead would be the DoS bug
/// the guard exists to prevent.)
fn runtime_do_cons_accumulator_user_fn_car_not_probed() {
let err = compile_expect_error(&wrap_with_runtime_n(
"(defun g (x) (* x 2)) \
(do ((I 0 (+ I 1)) (ACC nil (cons (g (transaction-post-date 0)) ACC))) ((>= I N) ACC))",
assert!(!err.is_empty(), "expected a structured compile error");