#![allow(clippy::result_large_err)]
#![allow(clippy::type_complexity)]
pub mod apply;
mod array_list;
mod bitops;
pub mod builtins;
pub mod callback;
pub mod destructure;
pub mod dynamics;
pub mod env;
pub mod error;
pub mod eval;
pub mod ir_interp;
pub mod loader;
pub mod macros;
mod new;
mod regex;
pub mod special;
pub mod syntax_quote;
pub mod taps;
mod transients;
mod util;
mod virtualize;
pub use callback::invoke;
pub use env::{Env, GlobalEnv};
pub use error::{EvalError, EvalResult};
pub use eval::eval;
pub use loader::load_ns;
use std::sync::Arc;
pub fn gc_safepoint(env: &Env) {
if !cljrs_gc::gc_requested() && !cljrs_gc::CONFIG_CANCELLATION.in_progress() {
return;
}
if cljrs_gc::CONFIG_CANCELLATION.in_progress() {
cljrs_gc::safepoint();
return;
}
if !cljrs_gc::take_gc_request() {
cljrs_gc::safepoint();
return;
}
let Some(_stw_guard) = cljrs_gc::begin_stw() else {
cljrs_gc::safepoint();
return;
};
cljrs_gc::HEAP.collect(|visitor| {
cljrs_gc::HEAP.trace_registered_roots(visitor);
trace_env_roots(env, visitor);
});
}
fn trace_env_roots(env: &Env, visitor: &mut cljrs_gc::MarkVisitor) {
use cljrs_gc::Trace;
for frame in &env.frames {
for (_name, val) in &frame.bindings {
val.trace(visitor);
}
}
trace_globals(&env.globals, visitor);
}
fn trace_globals(globals: &GlobalEnv, visitor: &mut cljrs_gc::MarkVisitor) {
use cljrs_gc::GcVisitor as _;
let namespaces = globals.namespaces.read().unwrap();
for (_name, ns_ptr) in namespaces.iter() {
visitor.visit(ns_ptr);
}
}
pub fn standard_env_minimal() -> Arc<GlobalEnv> {
let globals = GlobalEnv::new();
builtins::register_all(&globals, "clojure.core");
globals.get_or_create_ns("user");
globals.refer_all("user", "clojure.core");
{
let mut env = Env::new(globals.clone(), "clojure.core");
let src = builtins::BOOTSTRAP_SOURCE;
let mut parser = cljrs_reader::Parser::new(src.to_string(), "<bootstrap>".to_string());
match parser.parse_all() {
Ok(forms) => {
for form in forms {
if let Err(e) = eval::eval(&form, &mut env) {
eprintln!("[bootstrap warning] {}: {:?}", form.span.start, e);
}
}
}
Err(e) => eprintln!("[bootstrap parse error] {:?}", e),
}
}
globals.refer_all("user", "clojure.core");
globals.mark_loaded("clojure.core");
{
let mut env = Env::new(globals.clone(), "user");
special::sync_star_ns(&mut env);
}
globals
}
pub fn standard_env() -> Arc<GlobalEnv> {
let globals = standard_env_minimal();
{
let mut env = Env::new(globals.clone(), "clojure.core");
let src = builtins::CLOJURE_TEST_SOURCE;
let mut parser = cljrs_reader::Parser::new(src.to_string(), "<clojure.test>".to_string());
match parser.parse_all() {
Ok(forms) => {
for form in forms {
if let Err(e) = eval::eval(&form, &mut env) {
eprintln!("[clojure.test warning] {}: {:?}", form.span.start, e);
}
}
}
Err(e) => eprintln!("[clojure.test parse error] {:?}", e),
}
globals.mark_loaded("clojure.test");
}
{
let mut env = Env::new(globals.clone(), "user");
special::sync_star_ns(&mut env);
}
globals
}
pub fn standard_env_with_paths(source_paths: Vec<std::path::PathBuf>) -> Arc<GlobalEnv> {
let globals = standard_env();
globals.set_source_paths(source_paths);
globals
}