Skip to main content

sim_lib_lang_clojure/
recur.rs

1use sim_kernel::{
2    Cx, Ref, Result,
3    control::{ControlAbort, ControlPrompt, abort, default_control_result_shape, prompt},
4};
5
6use crate::clojure_recur_prompt_symbol;
7
8/// Returns the control-prompt [`Ref`] that delimits a Clojure `loop`/`recur` target.
9pub fn clojure_loop_prompt_ref() -> Ref {
10    Ref::Symbol(clojure_recur_prompt_symbol())
11}
12
13/// Runs `body` inside the Clojure `loop` prompt so a nested [`clojure_recur`] can rebind it.
14///
15/// Maps the surface `loop` form onto a kernel control prompt; behavior lives in
16/// the control organ, not this profile.
17pub fn clojure_loop_prompt<F>(cx: &mut Cx, input: Ref, body: F) -> Result<Ref>
18where
19    F: FnOnce(&mut Cx) -> Result<Ref>,
20{
21    prompt(
22        cx,
23        ControlPrompt::new(
24            clojure_loop_prompt_ref(),
25            input,
26            default_control_result_shape(),
27        ),
28        body,
29    )
30}
31
32/// Aborts to the enclosing Clojure `loop` prompt with new bindings, implementing `recur`.
33pub fn clojure_recur(cx: &mut Cx, value: Ref) -> Result<Ref> {
34    abort(
35        cx,
36        ControlAbort::new(
37            clojure_loop_prompt_ref(),
38            value,
39            default_control_result_shape(),
40        ),
41    )
42}