seq_runtime/closures.rs
1//! Closure support for Seq
2//!
3//! Provides runtime functions for creating and managing closures (quotations with captured environments).
4//!
5//! A closure consists of:
6//! - Function pointer (the compiled quotation code)
7//! - Environment (Arc-shared array of captured values for TCO support)
8//!
9//! Note: These extern "C" functions use Value and slice pointers, which aren't technically FFI-safe,
10//! but they work correctly when called from LLVM-generated code (not actual C interop).
11//!
12//! ## Type Support Status
13//!
14//! Currently supported capture types:
15//! - **Int** (via `env_get_int`)
16//! - **Bool** (via `env_get_bool`) - returns i64 (0/1)
17//! - **Float** (via `env_get_float`) - returns f64
18//! - **String** (via `env_get_string`)
19//! - **Quotation** (via `env_get_quotation`) - returns function pointer as i64
20//! - **Variant / Map and other heterogeneous values** (via the generic
21//! `env_push_value` path) - shipped in PR #402.
22//!
23//! Types still to be added:
24//! - Closure (nested closures with their own environments)
25//!
26//! See <https://github.com/navicore/patch-seq> for roadmap.
27//!
28//! ## Module Layout
29//!
30//! Per-concern sub-modules:
31//! - `env` — environment allocation (`create_env`), population (`env_set`),
32//! and the generic `env_get` reader.
33//! - `accessors` — type-specific readers (`env_get_int`, `env_get_bool`,
34//! `env_get_float`, `env_get_string`, `env_get_quotation`,
35//! `env_push_string`, `env_push_value`) that avoid returning a full
36//! `Value` enum across the FFI boundary.
37//! - `construct` — closure value creation: `make_closure` (wraps a
38//! prebuilt env) and `push_closure` (pops captures off the stack).
39
40/// Maximum number of captured values allowed in a closure environment.
41/// This prevents unbounded memory allocation and potential resource exhaustion.
42pub const MAX_CAPTURES: usize = 1024;
43
44mod accessors;
45mod construct;
46mod env;
47
48pub use accessors::{
49 patch_seq_env_get_bool, patch_seq_env_get_float, patch_seq_env_get_int,
50 patch_seq_env_get_quotation, patch_seq_env_get_string, patch_seq_env_push_string,
51 patch_seq_env_push_value,
52};
53pub use construct::{patch_seq_make_closure, patch_seq_push_closure};
54pub use env::{patch_seq_create_env, patch_seq_env_get, patch_seq_env_set};
55
56// Public re-exports with short names for internal use
57pub use patch_seq_create_env as create_env;
58pub use patch_seq_env_get as env_get;
59pub use patch_seq_env_get_bool as env_get_bool;
60pub use patch_seq_env_get_float as env_get_float;
61pub use patch_seq_env_get_int as env_get_int;
62pub use patch_seq_env_get_quotation as env_get_quotation;
63pub use patch_seq_env_get_string as env_get_string;
64pub use patch_seq_env_push_string as env_push_string;
65pub use patch_seq_env_push_value as env_push_value;
66pub use patch_seq_env_set as env_set;
67pub use patch_seq_make_closure as make_closure;
68pub use patch_seq_push_closure as push_closure;
69
70#[cfg(test)]
71mod tests;