1#[macro_use]
2extern crate lazy_static;
3
4pub mod data;
5
6pub mod builtins;
7pub mod call_stack;
8pub mod cli_args;
9pub mod codegen;
10pub mod primes;
11pub mod program;
12pub mod runner;
13pub mod snapshot;
14pub mod util;
15
16use dirs::home_dir;
17use std::cell::RefCell;
18use std::fs;
19use std::path::Path;
20use std::sync::Arc;
21
22pub use primes::{Calcit, CalcitErr, CalcitItems};
23
24pub fn load_core_snapshot() -> Result<snapshot::Snapshot, String> {
25 let bytes = include_bytes!("./cirru/calcit-core.cirru");
27 let core_content = String::from_utf8_lossy(bytes).to_string();
28 let core_data = cirru_edn::parse(&core_content)?;
29 snapshot::load_snapshot_data(&core_data, "calcit-internal://calcit-core.cirru")
30}
31
32#[derive(Clone, Debug)]
33pub struct ProgramEntries {
34 pub init_fn: Arc<str>,
35 pub init_ns: Arc<str>,
36 pub init_def: Arc<str>,
37 pub reload_fn: Arc<str>,
38 pub reload_ns: Arc<str>,
39 pub reload_def: Arc<str>,
40}
41
42pub fn run_program(init_ns: Arc<str>, init_def: Arc<str>, params: CalcitItems) -> Result<Calcit, CalcitErr> {
43 let check_warnings: RefCell<Vec<String>> = RefCell::new(vec![]);
44
45 match runner::preprocess::preprocess_ns_def(
47 init_ns.to_owned(),
48 init_def.to_owned(),
49 init_def.to_owned(),
50 None,
51 &check_warnings,
52 &rpds::List::new_sync(),
53 ) {
54 Ok(_) => (),
55 Err(failure) => {
56 eprintln!("\nfailed preprocessing, {}", failure);
57 call_stack::display_stack(&failure.msg, &failure.stack)?;
58 return CalcitErr::err_str(failure.msg);
59 }
60 }
61
62 let warnings = check_warnings.into_inner();
63 if !warnings.is_empty() {
64 return Err(CalcitErr {
65 msg: format!("Found {} warnings, runner blocked", warnings.len()),
66 warnings,
67 stack: rpds::List::new_sync(),
68 });
69 }
70 match program::lookup_evaled_def(&init_ns, &init_def) {
71 None => CalcitErr::err_str(format!("entry not initialized: {}/{}", init_ns, init_def)),
72 Some(entry) => match entry {
73 Calcit::Fn {
74 def_ns, scope, args, body, ..
75 } => {
76 let result = runner::run_fn(¶ms, &scope, &args, &body, def_ns, &rpds::List::new_sync());
77 match result {
78 Ok(v) => Ok(v),
79 Err(failure) => {
80 eprintln!("\nfailed, {}", failure);
81 call_stack::display_stack(&failure.msg, &failure.stack)?;
82 Err(failure)
83 }
84 }
85 }
86 _ => CalcitErr::err_str(format!("expected function entry, got: {}", entry)),
87 },
88 }
89}
90
91pub fn load_module(path: &str, base_dir: &Path) -> Result<snapshot::Snapshot, String> {
92 let mut file_path = String::from(path);
93 if file_path.ends_with('/') {
94 file_path.push_str("compact.cirru");
95 }
96
97 let fullpath: String = if file_path.starts_with("./") {
98 let new_path = base_dir.join(file_path);
99 new_path.to_str().unwrap().to_string()
100 } else if file_path.starts_with('/') {
101 file_path
102 } else {
103 match home_dir() {
104 Some(buf) => {
105 let home = buf.as_path();
106 let p = home.join(".config/calcit/modules/").join(file_path);
107 p.to_str().unwrap().to_string()
108 }
109 None => return Err(String::from("failed to load $HOME")),
110 }
111 };
112
113 println!("loading module: {}", fullpath);
114
115 let content = fs::read_to_string(&fullpath).unwrap_or_else(|_| panic!("expected Cirru snapshot {:?}", fullpath));
116 let data = cirru_edn::parse(&content)?;
117 let snapshot = snapshot::load_snapshot_data(&data, &fullpath)?;
119 Ok(snapshot)
120}