tatara_lisp_script/lib.rs
1//! tatara-lisp-script — scripting surface for tatara-lisp.
2//!
3//! Wraps `tatara-lisp-eval::Interpreter<ScriptCtx>` with a batteries-included
4//! stdlib (http, json, yaml, sops, file I/O, env, sha256, string ops) so a
5//! `.tlisp` file can replace a bash script. The binary (`tatara-script`)
6//! parses a .tlisp file, expands macros via tatara-lisp, and evaluates each
7//! form against this stdlib.
8//!
9//! # Usage from nix-run
10//!
11//! ```nix
12//! apps.tatara-script = {
13//! type = "app";
14//! program = "${tataraScript}/bin/tatara-script path/to/script.tlisp";
15//! };
16//! ```
17//!
18//! # Library surface
19//!
20//! Embedders that want to add domain-specific FFI on top of the stdlib can:
21//!
22//! ```rust,ignore
23//! use tatara_lisp_script::{Interpreter, ScriptCtx, install_stdlib};
24//!
25//! let mut interp: Interpreter<ScriptCtx> = Interpreter::new();
26//! let mut ctx = ScriptCtx::default();
27//! install_stdlib(&mut interp, &mut ctx);
28//! // Register more fns before eval_program.
29//! ```
30
31/// Owned temp-path registry — makes the `(tmp-dir)` / `(tmp-file)` leak
32/// unrepresentable. See the module docs for the incident it closes.
33pub mod scratch;
34pub mod script_ctx;
35pub mod stdlib;
36
37pub use script_ctx::ScriptCtx;
38pub use stdlib::install_stdlib;
39
40// Re-export the evaluator so embedders don't have to depend on tatara-lisp-eval
41// directly.
42pub use tatara_lisp::{read_spanned, Spanned};
43pub use tatara_lisp_eval::{Arity, EvalError, Interpreter, Value};
44
45/// Convenience: read + evaluate a tatara-lisp source string against a fresh
46/// interpreter with the full stdlib installed.
47///
48/// Primarily for tests and one-liner invocations. Binary entry points
49/// should construct the `Interpreter` directly to keep the host context
50/// available across calls.
51pub fn eval_str(src: &str) -> Result<Value, anyhow::Error> {
52 let forms = read_spanned(src).map_err(|e| anyhow::anyhow!("parse error: {e}"))?;
53 let mut interp: Interpreter<ScriptCtx> = Interpreter::new();
54 let mut ctx = ScriptCtx::default();
55 install_stdlib(&mut interp, &mut ctx);
56 interp
57 .eval_program(&forms, &mut ctx)
58 .map_err(|e| anyhow::anyhow!("eval error: {e:?}"))
59}