#![allow(clippy::result_large_err)]
#![allow(clippy::type_complexity)]
use cljrs_builtins::builtins;
use cljrs_env::env::{Env, GlobalEnv};
use cljrs_env::error::EvalResult;
use cljrs_reader::Form;
use cljrs_value::{CljxFn, Value};
use std::sync::Arc;
pub mod apply;
mod arity;
pub mod destructure;
pub mod eval;
pub mod macros;
pub mod special;
pub mod syntax_quote;
mod virtualize;
pub fn standard_env_minimal(
eval_fn: Option<fn(&Form, &mut Env) -> EvalResult>,
call_cljrs_fn: Option<fn(&CljxFn, &[Value], &mut Env) -> EvalResult>,
on_fn_defined: Option<fn(&CljxFn, &mut Env)>,
) -> Arc<GlobalEnv> {
let globals = GlobalEnv::new(
eval_fn.unwrap_or(eval::eval),
call_cljrs_fn.unwrap_or(apply::call_cljrs_fn),
on_fn_defined,
);
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 {
let _alloc_frame = cljrs_gc::push_alloc_frame();
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(
eval_fn: Option<fn(&Form, &mut Env) -> EvalResult>,
call_cljrs_fn: Option<fn(&CljxFn, &[Value], &mut Env) -> EvalResult>,
on_fn_defined: Option<fn(&CljxFn, &mut Env)>,
) -> Arc<GlobalEnv> {
let globals = standard_env_minimal(eval_fn, call_cljrs_fn, on_fn_defined);
{
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 {
let _alloc_frame = cljrs_gc::push_alloc_frame();
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(
eval_fn: Option<fn(&Form, &mut Env) -> EvalResult>,
call_cljrs_fn: Option<fn(&CljxFn, &[Value], &mut Env) -> EvalResult>,
on_fn_defined: Option<fn(&CljxFn, &mut Env)>,
source_paths: Vec<std::path::PathBuf>,
) -> Arc<GlobalEnv> {
let globals = standard_env(eval_fn, call_cljrs_fn, on_fn_defined);
globals.set_source_paths(source_paths);
globals
}