diff --git a/Cargo.lock b/Cargo.lock index c4e95951..f831695d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -45,7 +45,7 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "calcit_runner" -version = "0.5.0-a21" +version = "0.5.0-a22" dependencies = [ "cirru_edn", "cirru_parser", @@ -53,6 +53,7 @@ dependencies = [ "ctrlc", "dirs", "hex 0.4.3", + "im_ternary_tree", "lazy_static", "libloading", "notify", @@ -219,6 +220,12 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "im_ternary_tree" +version = "0.0.1-a4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4fa8823f84cd8522750074e30a82355d90ac0566da927d0a9f0c0127f608f53" + [[package]] name = "inotify" version = "0.7.1" diff --git a/Cargo.toml b/Cargo.toml index 55429704..f02ac520 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "calcit_runner" -version = "0.5.0-a21" +version = "0.5.0-a22" authors = ["jiyinyiyong "] edition = "2018" license = "MIT" @@ -30,6 +30,8 @@ notify = "4.0.17" walkdir = "2" hex = "0.4.3" rpds = "0.10.0" +im_ternary_tree = "0.0.1-a4" +# im_ternary_tree = { path = "/Users/chen/repo/calcit-lang/ternary-tree" } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] libloading = "0.7.1" diff --git a/package.json b/package.json index e17e5a8b..226543e9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@calcit/procs", - "version": "0.5.0-a21", + "version": "0.5.0-a22", "main": "./lib/calcit.procs.js", "devDependencies": { "@types/node": "^16.10.5", diff --git a/src/bin/cr.rs b/src/bin/cr.rs index cf5f212e..0c0fb5f7 100644 --- a/src/bin/cr.rs +++ b/src/bin/cr.rs @@ -14,6 +14,7 @@ use notify::{RecommendedWatcher, RecursiveMode, Watcher}; use calcit_runner::{ builtins, call_stack, cli_args, codegen, codegen::emit_js::gen_stack, codegen::COMPILE_ERRORS_FILE, program, runner, snapshot, util, }; +use im_ternary_tree::TernaryTreeList; pub struct ProgramSettings { entry_path: PathBuf, @@ -103,7 +104,7 @@ fn main() -> Result<(), String> { &calcit_runner::primes::BUILTIN_CLASSES_ENTRY.to_string().into_boxed_str(), None, check_warnings, - &rpds::Vector::new_sync(), + &TernaryTreeList::Empty, ) .map_err(|e| e.msg)?; @@ -114,7 +115,7 @@ fn main() -> Result<(), String> { } else { let started_time = Instant::now(); - let v = calcit_runner::run_program(init_fn, rpds::vector_sync![]).map_err(|e| { + let v = calcit_runner::run_program(init_fn, TernaryTreeList::Empty).map_err(|e| { for w in e.warnings { println!("{}", w); } @@ -223,7 +224,7 @@ fn recall_program(content: &str, init_fn: &str, reload_fn: &str, settings: &Prog } else { // run from `reload_fn` after reload let started_time = Instant::now(); - let v = calcit_runner::run_program(reload_fn, rpds::vector_sync![]).map_err(|e| { + let v = calcit_runner::run_program(reload_fn, TernaryTreeList::Empty).map_err(|e| { for w in e.warnings { println!("{}", w); } @@ -267,7 +268,7 @@ fn run_codegen(init_fn: &str, reload_fn: &str, emit_path: &str, ir_mode: bool) - gen_stack::clear_stack(); // preprocess to init - match runner::preprocess::preprocess_ns_def(&init_ns, &init_def, &init_def, None, check_warnings, &rpds::Vector::new_sync()) { + match runner::preprocess::preprocess_ns_def(&init_ns, &init_def, &init_def, None, check_warnings, &TernaryTreeList::Empty) { Ok(_) => (), Err(failure) => { println!("\nfailed preprocessing, {}", failure); @@ -285,7 +286,7 @@ fn run_codegen(init_fn: &str, reload_fn: &str, emit_path: &str, ir_mode: bool) - } // preprocess to reload - match runner::preprocess::preprocess_ns_def(&reload_ns, &reload_def, &init_def, None, check_warnings, &rpds::Vector::new_sync()) { + match runner::preprocess::preprocess_ns_def(&reload_ns, &reload_def, &init_def, None, check_warnings, &TernaryTreeList::Empty) { Ok(_) => (), Err(failure) => { println!("\nfailed preprocessing, {}", failure); diff --git a/src/bin/injection/mod.rs b/src/bin/injection/mod.rs index 4aeb1e27..c5e39d0a 100644 --- a/src/bin/injection/mod.rs +++ b/src/bin/injection/mod.rs @@ -10,6 +10,7 @@ use calcit_runner::{ primes::{Calcit, CalcitErr, CalcitItems, CrListWrap}, runner::track, }; +use im_ternary_tree::TernaryTreeList; /// FFI protocol types type EdnFfi = fn(args: Vec) -> Result; @@ -48,7 +49,7 @@ pub fn call_dylib_edn(xs: &CalcitItems, _call_stack: &CallStackVec) -> Result = Vec::with_capacity(xs.len()); - for (idx, v) in xs.iter().enumerate() { + for (idx, v) in xs.into_iter().enumerate() { if idx > 1 { ys.push(calcit_to_edn(v).map_err(CalcitErr::use_str)?); } @@ -70,7 +71,7 @@ pub fn call_dylib_edn(xs: &CalcitItems, _call_stack: &CallStackVec) -> Result Result { let mut s = String::from(""); - for (idx, x) in xs.iter().enumerate() { + for (idx, x) in xs.into_iter().enumerate() { if idx > 0 { s.push(' '); } @@ -103,7 +104,7 @@ pub fn call_dylib_edn_fn(xs: &CalcitItems, call_stack: &CallStackVec) -> Result< }; let mut ys: Vec = Vec::with_capacity(xs.len() - 2); let callback = xs[xs.len() - 1].clone(); - for (idx, v) in xs.iter().enumerate() { + for (idx, v) in xs.into_iter().enumerate() { if idx > 1 && idx < xs.len() - 1 { ys.push(calcit_to_edn(v).map_err(CalcitErr::use_str)?); } @@ -134,9 +135,9 @@ pub fn call_dylib_edn_fn(xs: &CalcitItems, call_stack: &CallStackVec) -> Result< ys.to_owned(), Arc::new(move |ps: Vec| -> Result { if let Calcit::Fn(_, def_ns, _, def_scope, args, body) = &callback { - let mut real_args = rpds::vector_sync![]; + let mut real_args = TernaryTreeList::Empty; for p in ps { - real_args.push_back_mut(edn_to_calcit(&p)); + real_args = real_args.push(edn_to_calcit(&p)); } let r = runner::run_fn(&real_args, def_scope, args, body, def_ns, &copied_stack); match r { @@ -189,7 +190,7 @@ pub fn blocking_dylib_edn_fn(xs: &CalcitItems, call_stack: &CallStackVec) -> Res }; let mut ys: Vec = Vec::with_capacity(xs.len() - 2); let callback = xs[xs.len() - 1].clone(); - for (idx, v) in xs.iter().enumerate() { + for (idx, v) in xs.into_iter().enumerate() { if idx > 1 && idx < xs.len() - 1 { ys.push(calcit_to_edn(v).map_err(CalcitErr::use_str)?); } @@ -218,9 +219,9 @@ pub fn blocking_dylib_edn_fn(xs: &CalcitItems, call_stack: &CallStackVec) -> Res ys.to_owned(), Arc::new(move |ps: Vec| -> Result { if let Calcit::Fn(_, def_ns, _, def_scope, args, body) = &callback { - let mut real_args = rpds::vector_sync![]; + let mut real_args = TernaryTreeList::Empty; for p in ps { - real_args.push_back_mut(edn_to_calcit(&p)); + real_args = real_args.push(edn_to_calcit(&p)); } let r = runner::run_fn(&real_args, def_scope, args, body, def_ns, &copied_stack.clone()); match r { @@ -256,7 +257,7 @@ pub fn on_ctrl_c(xs: &CalcitItems, call_stack: &CallStackVec) -> Result Result { let mut s = String::from(""); - for (idx, x) in xs.iter().enumerate() { + for (idx, x) in xs.into_iter().enumerate() { if idx > 0 { s.push(' '); } diff --git a/src/builtins/lists.rs b/src/builtins/lists.rs index 4faff950..6aa0982c 100644 --- a/src/builtins/lists.rs +++ b/src/builtins/lists.rs @@ -6,7 +6,9 @@ use crate::util::number::f64_to_usize; use crate::builtins; use crate::call_stack::CallStackVec; use crate::runner; -use crate::util::{contains, insert}; +use crate::util::contains; + +use im_ternary_tree::TernaryTreeList; pub fn new_list(xs: &CalcitItems) -> Result { Ok(Calcit::List(xs.to_owned())) @@ -54,14 +56,7 @@ pub fn slice(xs: &CalcitItems) -> Result { }; let from_idx: usize = unsafe { from.to_int_unchecked() }; - // TODO slow copy - let mut zs = rpds::Vector::new_sync(); - for (idx, y) in ys.iter().enumerate() { - if idx >= from_idx && idx < to_idx { - zs.push_back_mut(y.to_owned()); - } - } - Ok(Calcit::List(zs)) + Ok(Calcit::List(ys.slice(from_idx, to_idx))) } (a, b) => CalcitErr::err_str(&format!("slice expected list and indexes: {} {}", a, b)), } @@ -72,25 +67,14 @@ pub fn append(xs: &CalcitItems) -> Result { return CalcitErr::err_str(format!("append expected 2 arguments, got: {}", CrListWrap(xs.to_owned()))); } match &xs[0] { - Calcit::List(ys) => { - let mut zs = ys.to_owned(); - zs.push_back_mut(xs[1].to_owned()); - Ok(Calcit::List(zs)) - } + Calcit::List(ys) => Ok(Calcit::List(ys.push(xs[1].to_owned()))), a => CalcitErr::err_str(&format!("append expected a list: {}", a)), } } pub fn prepend(xs: &CalcitItems) -> Result { match (xs.get(0), xs.get(1)) { - (Some(Calcit::List(ys)), Some(a)) => { - let mut zs = rpds::VectorSync::new_sync(); - zs.push_back_mut(a.to_owned()); - for y in ys.iter() { - zs.push_back_mut(y.to_owned()); - } - Ok(Calcit::List(zs)) - } + (Some(Calcit::List(ys)), Some(a)) => Ok(Calcit::List(ys.unshift(a.to_owned()))), (Some(a), _) => CalcitErr::err_str(format!("prepend expected list, got: {}", a)), (None, _) => CalcitErr::err_str("prepend expected 2 arguments, got nothing"), } @@ -105,13 +89,7 @@ pub fn rest(xs: &CalcitItems) -> Result { if ys.is_empty() { Ok(Calcit::Nil) } else { - let mut zs = rpds::Vector::new_sync(); - for (idx, y) in ys.iter().enumerate() { - if idx > 0 { - zs.push_back_mut(y.to_owned()); - } - } - Ok(Calcit::List(zs)) + Ok(Calcit::List(ys.rest())) } } a => CalcitErr::err_str(format!("list:rest expected a list, got: {}", a)), @@ -129,7 +107,7 @@ pub fn butlast(xs: &CalcitItems) -> Result { Ok(Calcit::Nil) } else { let mut zs = ys.to_owned(); - zs.drop_last_mut(); + zs = zs.butlast(); Ok(Calcit::List(zs)) } } @@ -138,11 +116,11 @@ pub fn butlast(xs: &CalcitItems) -> Result { } pub fn concat(xs: &CalcitItems) -> Result { - let mut ys: CalcitItems = rpds::vector_sync![]; + let mut ys: CalcitItems = TernaryTreeList::Empty; for x in xs { if let Calcit::List(zs) = x { - for z in zs.iter() { - ys.push_back_mut(z.to_owned()); + for z in zs { + ys = ys.push(z.to_owned()); } } else { return CalcitErr::err_str(format!("concat expects list arguments, got: {}", x)); @@ -168,23 +146,23 @@ pub fn range(xs: &CalcitItems) -> Result { }; if (bound - base).abs() < f64::EPSILON { - return Ok(Calcit::List(rpds::vector_sync![])); + return Ok(Calcit::List(TernaryTreeList::Empty)); } if step == 0.0 || (bound > base && step < 0.0) || (bound < base && step > 0.0) { return CalcitErr::err_str("range cannot construct list with step 0"); } - let mut ys: CalcitItems = rpds::vector_sync![]; + let mut ys: CalcitItems = TernaryTreeList::Empty; let mut i = base; if step > 0.0 { while i < bound { - ys.push_back_mut(Calcit::Number(i)); + ys = ys.push(Calcit::Number(i)); i += step; } } else { while i > bound { - ys.push_back_mut(Calcit::Number(i)); + ys = ys.push(Calcit::Number(i)); i += step; } } @@ -197,13 +175,7 @@ pub fn reverse(xs: &CalcitItems) -> Result { } match &xs[0] { Calcit::Nil => Ok(Calcit::Nil), - Calcit::List(ys) => { - let mut zs: CalcitItems = rpds::vector_sync![]; - for idx in 0..ys.len() { - zs.push_back_mut(ys[ys.len() - 1 - idx].to_owned()); - } - Ok(Calcit::List(zs)) - } + Calcit::List(ys) => Ok(Calcit::List(ys.reverse())), a => CalcitErr::err_str(format!("butlast expected a list, got: {}", a)), } } @@ -217,7 +189,7 @@ pub fn foldl(xs: &CalcitItems, call_stack: &CallStackVec) -> Result { for x in xs { - let values = rpds::vector_sync![ret, x.to_owned()]; + let values = TernaryTreeList::from(&vec![ret, x.to_owned()]); ret = runner::run_fn(&values, def_scope, args, body, def_ns, call_stack)?; } Ok(ret) @@ -225,14 +197,14 @@ pub fn foldl(xs: &CalcitItems, call_stack: &CallStackVec) -> Result { for x in xs { // println!("foldl args, {} {}", ret, x.to_owned()); - ret = builtins::handle_proc(proc, &rpds::vector_sync![ret, x.to_owned()], call_stack)?; + ret = builtins::handle_proc(proc, &TernaryTreeList::from(&vec![ret, x.to_owned()]), call_stack)?; } Ok(ret) } // also handles set (Calcit::Set(xs), Calcit::Fn(_, def_ns, _, def_scope, args, body)) => { for x in xs { - let values = rpds::vector_sync![ret, x.to_owned()]; + let values = TernaryTreeList::from(&vec![ret, x.to_owned()]); ret = runner::run_fn(&values, def_scope, args, body, def_ns, call_stack)?; } Ok(ret) @@ -240,14 +212,14 @@ pub fn foldl(xs: &CalcitItems, call_stack: &CallStackVec) -> Result { for x in xs { // println!("foldl args, {} {}", ret, x.to_owned()); - ret = builtins::handle_proc(proc, &rpds::vector_sync![ret, x.to_owned()], call_stack)?; + ret = builtins::handle_proc(proc, &TernaryTreeList::from(&vec![ret, x.to_owned()]), call_stack)?; } Ok(ret) } // also handles map (Calcit::Map(xs), Calcit::Fn(_, def_ns, _, def_scope, args, body)) => { for (k, x) in xs { - let values = rpds::vector_sync![ret, Calcit::List(rpds::vector_sync![k.to_owned(), x.to_owned()])]; + let values = TernaryTreeList::from(&vec![ret, Calcit::List(TernaryTreeList::from(&vec![k.to_owned(), x.to_owned()]))]); ret = runner::run_fn(&values, def_scope, args, body, def_ns, call_stack)?; } Ok(ret) @@ -257,7 +229,7 @@ pub fn foldl(xs: &CalcitItems, call_stack: &CallStackVec) -> Result Result { let mut state = acc.to_owned(); for x in xs { - let values = rpds::vector_sync![state, x.to_owned()]; + let values = TernaryTreeList::from(&vec![state, x.to_owned()]); let pair = runner::run_fn(&values, def_scope, args, body, def_ns, call_stack)?; match pair { Calcit::Tuple(x0, x1) => match *x0 { @@ -320,7 +292,7 @@ pub fn foldl_shortcut(xs: &CalcitItems, call_stack: &CallStackVec) -> Result { let mut state = acc.to_owned(); for x in xs { - let values = rpds::vector_sync![state, x.to_owned()]; + let values = TernaryTreeList::from(&vec![state, x.to_owned()]); let pair = runner::run_fn(&values, def_scope, args, body, def_ns, call_stack)?; match pair { Calcit::Tuple(x0, x1) => match *x0 { @@ -352,7 +324,7 @@ pub fn foldl_shortcut(xs: &CalcitItems, call_stack: &CallStackVec) -> Result { let mut state = acc.to_owned(); for (k, x) in xs { - let values = rpds::vector_sync![state, Calcit::List(rpds::vector_sync![k.to_owned(), x.to_owned()])]; + let values = TernaryTreeList::from(&vec![state, Calcit::List(TernaryTreeList::from(&vec![k.to_owned(), x.to_owned()]))]); let pair = runner::run_fn(&values, def_scope, args, body, def_ns, call_stack)?; match pair { Calcit::Tuple(x0, x1) => match *x0 { @@ -407,7 +379,7 @@ pub fn foldr_shortcut(xs: &CalcitItems, call_stack: &CallStackVec) -> Result match *x0 { @@ -454,9 +426,9 @@ pub fn sort(xs: &CalcitItems, call_stack: &CallStackVec) -> Result { - let mut xs2: Vec<&Calcit> = xs.iter().collect::>(); + let mut xs2: Vec<&Calcit> = xs.into_iter().collect::>(); xs2.sort_by(|a, b| -> Ordering { - let values = rpds::vector_sync![a.to_owned().to_owned(), b.to_owned().to_owned()]; + let values = TernaryTreeList::from(&vec![a.to_owned().to_owned(), b.to_owned().to_owned()]); let v = runner::run_fn(&values, def_scope, args, body, def_ns, call_stack); match v { Ok(Calcit::Number(x)) if x < 0.0 => Ordering::Less, @@ -472,17 +444,17 @@ pub fn sort(xs: &CalcitItems, call_stack: &CallStackVec) -> Result = rpds::VectorSync::new_sync(); + let mut ys: TernaryTreeList = TernaryTreeList::Empty; for x in xs2.iter() { // TODO ?? - ys.push_back_mut(x.to_owned().to_owned()) + ys = ys.push(x.to_owned().to_owned()) } Ok(Calcit::List(ys)) } (Calcit::List(xs), Calcit::Proc(proc)) => { - let mut xs2: Vec<&Calcit> = xs.iter().collect::>(); + let mut xs2: Vec<&Calcit> = xs.into_iter().collect::>(); xs2.sort_by(|a, b| -> Ordering { - let values = rpds::vector_sync![a.to_owned().to_owned(), b.to_owned().to_owned()]; + let values = TernaryTreeList::from(&vec![a.to_owned().to_owned(), b.to_owned().to_owned()]); let v = builtins::handle_proc(proc, &values, call_stack); match v { Ok(Calcit::Number(x)) if x < 0.0 => Ordering::Less, @@ -498,10 +470,10 @@ pub fn sort(xs: &CalcitItems, call_stack: &CallStackVec) -> Result = rpds::VectorSync::new_sync(); + let mut ys: TernaryTreeList = TernaryTreeList::Empty; for x in xs2.iter() { // TODO ?? - ys.push_back_mut(x.to_owned().to_owned()) + ys = ys.push(x.to_owned().to_owned()) } Ok(Calcit::List(ys)) } @@ -542,8 +514,8 @@ pub fn assoc_before(xs: &CalcitItems) -> Result { match (&xs[0], &xs[1]) { (Calcit::List(zs), Calcit::Number(n)) => match f64_to_usize(*n) { Ok(idx) => { - let ys = insert(zs, idx, xs[2].to_owned()); - Ok(Calcit::List(ys)) + // let ys = insert(zs, idx, xs[2].to_owned()); + Ok(Calcit::List(zs.assoc_before(idx, xs[2].to_owned()))) } Err(e) => CalcitErr::err_str(format!("assoc-before expect usize, {}", e)), }, @@ -558,8 +530,8 @@ pub fn assoc_after(xs: &CalcitItems) -> Result { match (&xs[0], &xs[1]) { (Calcit::List(zs), Calcit::Number(n)) => match f64_to_usize(*n) { Ok(idx) => { - let ys = insert(zs, idx + 1, xs[2].to_owned()); - Ok(Calcit::List(ys)) + // let ys = insert(zs, idx + 1, xs[2].to_owned()); + Ok(Calcit::List(zs.assoc_after(idx, xs[2].to_owned()))) } Err(e) => CalcitErr::err_str(format!("assoc-after expect usize, {}", e)), }, @@ -607,7 +579,8 @@ pub fn assoc(xs: &CalcitItems) -> Result { Ok(idx) => { if idx < zs.len() { let mut ys = zs.to_owned(); - ys[idx] = xs[2].to_owned(); + // ys[idx] = xs[2].to_owned(); + ys = ys.assoc(idx, xs[2].to_owned()); Ok(Calcit::List(ys)) } else { Ok(Calcit::List(xs.to_owned())) @@ -622,15 +595,7 @@ pub fn assoc(xs: &CalcitItems) -> Result { pub fn dissoc(xs: &CalcitItems) -> Result { match (xs.get(0), xs.get(1)) { (Some(Calcit::List(xs)), Some(Calcit::Number(n))) => match f64_to_usize(*n) { - Ok(at) => { - let mut ys: rpds::VectorSync = rpds::Vector::new_sync(); - for (idx, x) in xs.iter().enumerate() { - if idx != at { - ys.push_back_mut(x.to_owned()); - } - } - Ok(Calcit::List(ys.to_owned())) - } + Ok(at) => Ok(Calcit::List(xs.dissoc(at))), Err(e) => CalcitErr::err_str(format!("dissoc expected number, {}", e)), }, (Some(a), ..) => CalcitErr::err_str(format!("list dissoc expected a list, got: {}", a)), @@ -660,10 +625,10 @@ pub fn distinct(xs: &CalcitItems) -> Result { } match &xs[0] { Calcit::List(ys) => { - let mut zs = rpds::VectorSync::new_sync(); + let mut zs = TernaryTreeList::Empty; for y in ys { if !contains(&zs, y) { - zs.push_back_mut(y.to_owned()); + zs = zs.push(y.to_owned()); } } Ok(Calcit::List(zs)) diff --git a/src/builtins/maps.rs b/src/builtins/maps.rs index 00e21969..0d0947ae 100644 --- a/src/builtins/maps.rs +++ b/src/builtins/maps.rs @@ -5,6 +5,8 @@ use crate::primes::{Calcit, CalcitErr, CalcitItems, CrListWrap}; use crate::util::number::is_even; +use im_ternary_tree::TernaryTreeList; + pub fn call_new_map(xs: &CalcitItems) -> Result { if is_even(xs.len()) { let n = xs.len() >> 1; @@ -95,7 +97,9 @@ pub fn to_pairs(xs: &CalcitItems) -> Result { Some(Calcit::Map(ys)) => { let mut zs: rpds::HashTrieSetSync = rpds::HashTrieSet::new_sync(); for (k, v) in ys { - zs.insert_mut(Calcit::List(rpds::vector_sync![].push_back(k.to_owned()).push_back(v.to_owned()))); + zs.insert_mut(Calcit::List( + TernaryTreeList::Empty.append(k.to_owned(), false).append(v.to_owned(), false), + )); } Ok(Calcit::Set(zs)) } @@ -103,9 +107,9 @@ pub fn to_pairs(xs: &CalcitItems) -> Result { let mut zs: rpds::HashTrieSetSync = rpds::HashTrieSet::new_sync(); for idx in 0..fields.len() { zs.insert_mut(Calcit::List( - rpds::vector_sync![] - .push_back(Calcit::Keyword(fields[idx].to_owned())) - .push_back(values[idx].to_owned()), + TernaryTreeList::Empty + .append(Calcit::Keyword(fields[idx].to_owned()), false) + .append(values[idx].to_owned(), false), )); } Ok(Calcit::Set(zs)) @@ -135,10 +139,10 @@ pub fn call_merge_non_nil(xs: &CalcitItems) -> Result { pub fn to_list(xs: &CalcitItems) -> Result { match xs.get(0) { Some(Calcit::Map(m)) => { - let mut ys: rpds::VectorSync = rpds::vector_sync![]; + let mut ys: TernaryTreeList = TernaryTreeList::Empty; for (k, v) in m { - let zs: rpds::VectorSync = rpds::vector_sync![k.to_owned(), v.to_owned()]; - ys.push_back_mut(Calcit::List(zs)); + let zs: TernaryTreeList = TernaryTreeList::from(&vec![k.to_owned(), v.to_owned()]); + ys = ys.push(Calcit::List(zs)); } Ok(Calcit::List(ys)) } @@ -191,7 +195,7 @@ pub fn first(xs: &CalcitItems) -> Result { match xs.get(0) { Some(Calcit::Map(ys)) => match ys.iter().next() { // TODO order may not be stable enough - Some((k, v)) => Ok(Calcit::List(rpds::vector_sync![k.to_owned(), v.to_owned()])), + Some((k, v)) => Ok(Calcit::List(TernaryTreeList::from(&vec![k.to_owned(), v.to_owned()]))), None => Ok(Calcit::Nil), }, Some(a) => CalcitErr::err_str(format!("map:first expected a map, got: {}", a)), diff --git a/src/builtins/meta.rs b/src/builtins/meta.rs index 3ea2829f..de8186a4 100644 --- a/src/builtins/meta.rs +++ b/src/builtins/meta.rs @@ -12,6 +12,7 @@ use crate::{ use cirru_edn::EdnKwd; use cirru_parser::{Cirru, CirruWriterOptions}; +use im_ternary_tree::TernaryTreeList; use std::cmp::Ordering; use std::sync::atomic; @@ -326,14 +327,14 @@ pub fn invoke_method(name: &str, invoke_args: &CalcitItems, call_stack: &CallSta Calcit::Record(_, fields, values) => { match find_in_fields(fields, &EdnKwd::from(name)) { Some(idx) => { - let mut method_args: rpds::VectorSync = rpds::vector_sync![]; - method_args.push_back_mut(value); + let mut method_args: TernaryTreeList = TernaryTreeList::Empty; + method_args = method_args.push(value); let mut at_first = true; for x in invoke_args { if at_first { at_first = false } else { - method_args.push_back_mut(x.to_owned()) + method_args = method_args.push(x.to_owned()) } } diff --git a/src/builtins/records.rs b/src/builtins/records.rs index 126508d0..1831fe28 100644 --- a/src/builtins/records.rs +++ b/src/builtins/records.rs @@ -18,11 +18,11 @@ pub fn new_record(xs: &CalcitItems) -> Result { let mut fields: Vec = Vec::with_capacity(xs.len()); let mut values: Vec = Vec::with_capacity(xs.len()); - for (idx, x) in xs.iter().enumerate() { + for (idx, x) in xs.into_iter().enumerate() { if idx > 0 { match x { Calcit::Symbol(s, ..) | Calcit::Str(s) => { - fields.push(EdnKwd::from(s)); + fields.push(EdnKwd::from(&*s)); } Calcit::Keyword(s) => { fields.push(s.to_owned()); diff --git a/src/builtins/refs.rs b/src/builtins/refs.rs index db53eda8..486d9a3f 100644 --- a/src/builtins/refs.rs +++ b/src/builtins/refs.rs @@ -4,6 +4,7 @@ use std::collections::HashMap; use std::sync::RwLock; use cirru_edn::EdnKwd; +use im_ternary_tree::TernaryTreeList; use crate::primes::{Calcit, CalcitErr, CalcitItems, CalcitScope}; use crate::{call_stack::CallStackVec, runner}; @@ -32,7 +33,7 @@ fn modify_ref(path: &str, v: Calcit, call_stack: &CallStackVec) -> Result<(), Ca for f in listeners.values() { match f { Calcit::Fn(_, def_ns, _, def_scope, args, body) => { - let values = rpds::vector_sync![v.to_owned(), prev.to_owned()]; + let values = TernaryTreeList::from(&vec![v.to_owned(), prev.to_owned()]); runner::run_fn(&values, def_scope, args, body, def_ns, call_stack)?; } a => { diff --git a/src/builtins/sets.rs b/src/builtins/sets.rs index f7826f86..6dfd6618 100644 --- a/src/builtins/sets.rs +++ b/src/builtins/sets.rs @@ -1,4 +1,5 @@ use crate::primes::{Calcit, CalcitErr, CalcitItems}; +use im_ternary_tree::TernaryTreeList; pub fn new_set(xs: &CalcitItems) -> Result { let mut ys = rpds::HashTrieSet::new_sync(); @@ -79,9 +80,9 @@ pub fn call_intersection(xs: &CalcitItems) -> Result { pub fn set_to_list(xs: &CalcitItems) -> Result { match xs.get(0) { Some(Calcit::Set(xs)) => { - let mut ys: CalcitItems = rpds::vector_sync![]; + let mut ys: CalcitItems = TernaryTreeList::Empty; for x in xs { - ys.push_back_mut(x.to_owned()); + ys = ys.push(x.to_owned()); } Ok(Calcit::List(ys)) } diff --git a/src/builtins/strings.rs b/src/builtins/strings.rs index 059a80be..12df1273 100644 --- a/src/builtins/strings.rs +++ b/src/builtins/strings.rs @@ -5,6 +5,8 @@ use crate::primes; use crate::primes::{Calcit, CalcitErr, CalcitItems, CrListWrap}; use crate::util::number::f64_to_usize; +use im_ternary_tree::TernaryTreeList; + pub fn binary_str_concat(xs: &CalcitItems) -> Result { match (xs.get(0), xs.get(1)) { (Some(Calcit::Nil), Some(Calcit::Nil)) => Ok(Calcit::new_str("")), @@ -60,10 +62,10 @@ pub fn split(xs: &CalcitItems) -> Result { match (xs.get(0), xs.get(1)) { (Some(Calcit::Str(s)), Some(Calcit::Str(pattern))) => { let pieces = (**s).split(&**pattern); - let mut ys: CalcitItems = rpds::vector_sync![]; + let mut ys: CalcitItems = TernaryTreeList::Empty; for p in pieces { if !p.is_empty() { - ys.push_back_mut(Calcit::Str(p.to_owned().into_boxed_str())); + ys = ys.push(Calcit::Str(p.to_owned().into_boxed_str())); } } Ok(Calcit::List(ys)) @@ -98,9 +100,9 @@ pub fn split_lines(xs: &CalcitItems) -> Result { match xs.get(0) { Some(Calcit::Str(s)) => { let lines = s.split('\n'); - let mut ys = rpds::vector_sync![]; + let mut ys = TernaryTreeList::Empty; for line in lines { - ys.push_back_mut(Calcit::Str(line.to_owned().into_boxed_str())); + ys = ys.push(Calcit::Str(line.to_owned().into_boxed_str())); } Ok(Calcit::List(ys)) } diff --git a/src/builtins/syntax.rs b/src/builtins/syntax.rs index 2929d459..7421b53a 100644 --- a/src/builtins/syntax.rs +++ b/src/builtins/syntax.rs @@ -11,6 +11,8 @@ use crate::primes::{gen_core_id, Calcit, CalcitErr, CalcitItems, CalcitScope}; use crate::runner; use crate::util::{skip, slice}; +use im_ternary_tree::TernaryTreeList; + pub fn defn(expr: &CalcitItems, scope: &CalcitScope, file_ns: &str) -> Result { match (expr.get(0), expr.get(1)) { (Some(Calcit::Symbol(s, ..)), Some(Calcit::List(xs))) => Ok(Calcit::Fn( @@ -135,13 +137,13 @@ fn replace_code(c: &Calcit, scope: &CalcitScope, file_ns: &str, call_stack: &Cal } } (_, _) => { - let mut ret = rpds::vector_sync![]; + let mut ret = TernaryTreeList::Empty; for y in ys { match replace_code(y, scope, file_ns, call_stack)? { - SpanResult::Single(z) => ret.push_back_mut(z), + SpanResult::Single(z) => ret = ret.push(z), SpanResult::Range(pieces) => { - for piece in pieces.iter() { - ret.push_back_mut(piece.to_owned()); + for piece in &pieces { + ret = ret.push(piece.to_owned()); } } } @@ -301,10 +303,10 @@ pub fn call_try(expr: &CalcitItems, scope: &CalcitScope, file_ns: &str, call_sta let err_data = Calcit::Str(failure.msg.to_owned().into_boxed_str()); match f { Calcit::Fn(_, def_ns, _, def_scope, args, body) => { - let values = rpds::vector_sync![err_data]; + let values = TernaryTreeList::from(&[err_data]); runner::run_fn(&values, &def_scope, &args, &body, &def_ns, call_stack) } - Calcit::Proc(proc) => builtins::handle_proc(&proc, &rpds::vector_sync![err_data], call_stack), + Calcit::Proc(proc) => builtins::handle_proc(&proc, &TernaryTreeList::from(&[err_data]), call_stack), a => CalcitErr::err_str(format!("try expected a function handler, got: {}", a)), } } diff --git a/src/call_stack.rs b/src/call_stack.rs index 4fa50fc9..2f63cc92 100644 --- a/src/call_stack.rs +++ b/src/call_stack.rs @@ -3,9 +3,13 @@ use crate::data::edn; use crate::primes::{Calcit, CalcitItems}; use cirru_edn::Edn; use std::collections::HashMap; +use std::fmt; use std::fs; +use std::hash::Hash; -#[derive(Debug, PartialEq, Clone)] +use im_ternary_tree::TernaryTreeList; + +#[derive(Debug, PartialEq, Clone, Eq, Ord, PartialOrd, Hash)] pub struct CalcitStack { pub ns: String, pub def: String, @@ -14,7 +18,7 @@ pub struct CalcitStack { pub kind: StackKind, } -#[derive(Debug, PartialEq, Clone)] +#[derive(Debug, PartialEq, Clone, Eq, Ord, PartialOrd, Hash)] pub enum StackKind { Fn, Proc, @@ -23,14 +27,20 @@ pub enum StackKind { Codegen, // track preprocessing } -pub type CallStackVec = rpds::VectorSync; +impl fmt::Display for CalcitStack { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "TODO") + } +} + +pub type CallStackVec = TernaryTreeList; // TODO impl fmt /// create new entry to the tree pub fn extend_call_stack(stack: &CallStackVec, ns: &str, def: &str, kind: StackKind, code: Calcit, args: &CalcitItems) -> CallStackVec { let mut s2 = stack.to_owned(); - s2.push_back_mut(CalcitStack { + s2 = s2.push(CalcitStack { ns: ns.to_owned(), def: def.to_owned(), code, diff --git a/src/codegen/emit_js.rs b/src/codegen/emit_js.rs index ff7b973c..b784727f 100644 --- a/src/codegen/emit_js.rs +++ b/src/codegen/emit_js.rs @@ -8,6 +8,7 @@ use std::fs; use std::path::Path; use cirru_edn::EdnKwd; +use im_ternary_tree::TernaryTreeList; use crate::builtins::meta::{js_gensym, reset_js_gensym_index}; use crate::builtins::{is_js_syntax_procs, is_proc_name}; @@ -295,7 +296,7 @@ fn gen_call_code( } return match (body.get(0), body.get(1)) { (Some(condition), Some(true_branch)) => { - gen_stack::push_call_stack(ns, "if", StackKind::Codegen, xs.to_owned(), &rpds::vector_sync![]); + gen_stack::push_call_stack(ns, "if", StackKind::Codegen, xs.to_owned(), &TernaryTreeList::Empty); let false_code = match body.get(2) { Some(fal) => to_js_code(fal, ns, local_defs, file_imports, keywords, &None)?, None => String::from("null"), @@ -320,7 +321,7 @@ fn gen_call_code( (Some(Calcit::Symbol(sym, ..)), Some(v)) => { // let _name = escape_var(sym); // TODO let ref_path = wrap_js_str(&format!("{}/{}", ns, sym.to_owned())); - gen_stack::push_call_stack(ns, sym, StackKind::Codegen, xs.to_owned(), &rpds::vector_sync![]); + gen_stack::push_call_stack(ns, sym, StackKind::Codegen, xs.to_owned(), &TernaryTreeList::Empty); let value_code = &to_js_code(v, ns, local_defs, file_imports, keywords, &None)?; gen_stack::pop_call_stack(); Ok(format!( @@ -335,7 +336,7 @@ fn gen_call_code( CalcitSyntax::Defn => match (body.get(0), body.get(1)) { (Some(Calcit::Symbol(sym, ..)), Some(Calcit::List(ys))) => { let func_body = skip(&body, 2); - gen_stack::push_call_stack(ns, sym, StackKind::Codegen, xs.to_owned(), &rpds::vector_sync![]); + gen_stack::push_call_stack(ns, sym, StackKind::Codegen, xs.to_owned(), &TernaryTreeList::Empty); let ret = gen_js_func(sym, ys, &func_body, ns, false, local_defs, file_imports, keywords); gen_stack::pop_call_stack(); match ret { @@ -350,7 +351,7 @@ fn gen_call_code( CalcitSyntax::Quasiquote => Ok(format!("(/* Unexpected quasiquote {} */ null)", xs.lisp_str())), CalcitSyntax::Try => match (body.get(0), body.get(1)) { (Some(expr), Some(handler)) => { - gen_stack::push_call_stack(ns, "try", StackKind::Codegen, xs.to_owned(), &rpds::vector_sync![]); + gen_stack::push_call_stack(ns, "try", StackKind::Codegen, xs.to_owned(), &TernaryTreeList::Empty); let next_return_label = match return_label { Some(x) => Some(x.to_owned()), None => Some(String::from("return ")), @@ -686,7 +687,7 @@ fn gen_let_code( Calcit::Nil => { // non content defs_code - for (idx, x) in content.iter().enumerate() { + for (idx, x) in content.into_iter().enumerate() { if idx == content.len() - 1 { body_part.push_str(&to_js_code(x, ns, &scoped_defs, file_imports, keywords, &return_label)?); body_part.push('\n'); @@ -709,7 +710,7 @@ fn gen_let_code( defs_code.push_str(&format!("let {} = {};\n", left, right)); if scoped_defs.contains(&sym) { - for (idx, x) in content.iter().enumerate() { + for (idx, x) in content.into_iter().enumerate() { if idx == content.len() - 1 { body_part.push_str(&to_js_code(x, ns, &scoped_defs, file_imports, keywords, &return_label)?); body_part.push('\n'); @@ -749,7 +750,7 @@ fn gen_let_code( } } - for (idx, x) in content.iter().enumerate() { + for (idx, x) in content.into_iter().enumerate() { if idx == content.len() - 1 { body_part.push_str(&to_js_code(x, ns, &scoped_defs, file_imports, keywords, &return_label)?); body_part.push('\n'); @@ -883,7 +884,7 @@ fn list_to_js_code( ) -> Result { // TODO default returnLabel="return " let mut result = String::from(""); - for (idx, x) in xs.iter().enumerate() { + for (idx, x) in xs.into_iter().enumerate() { // result = result & "// " & $x & "\n" if idx == xs.len() - 1 { let line = to_js_code(x, ns, &local_defs, file_imports, keywords, &Some(return_label.to_owned()))?; @@ -990,7 +991,7 @@ fn gen_js_func( snippets::tmpl_args_exact(args_count) }; - let mut body: CalcitItems = rpds::VectorSync::new_sync(); + let mut body: CalcitItems = TernaryTreeList::Empty; let mut async_prefix: String = String::from(""); for line in raw_body { @@ -1004,7 +1005,7 @@ fn gen_js_func( } } } - body.push_back_mut(line.to_owned()); + body = body.push(line.to_owned()); } if !body.is_empty() && uses_recur(&body[body.len() - 1]) { @@ -1044,7 +1045,7 @@ fn gen_js_func( } /// this is a very rough implementation for now -fn hinted_async(xs: &rpds::VectorSync) -> bool { +fn hinted_async(xs: &TernaryTreeList) -> bool { for x in xs { match x { Calcit::Symbol(sym, ..) if &**sym == "async" => return true, @@ -1221,14 +1222,14 @@ pub fn emit_js(entry_ns: &str, emit_path: &str) -> Result<(), String> { defs_code.push_str(&format!("\nvar {} = $calcit_procs.{};\n", escape_var(&def), escape_var(&def))); } Calcit::Fn(name, def_ns, _, _, args, code) => { - gen_stack::push_call_stack(def_ns, name, StackKind::Codegen, f.to_owned(), &rpds::vector_sync![]); + gen_stack::push_call_stack(def_ns, name, StackKind::Codegen, f.to_owned(), &TernaryTreeList::Empty); defs_code.push_str(&gen_js_func(&def, args, code, &ns, true, &def_names, &file_imports, &keywords)?); gen_stack::pop_call_stack(); } Calcit::Thunk(code, _) => { // TODO need topological sorting for accuracy // values are called directly, put them after fns - gen_stack::push_call_stack(&ns, &def, StackKind::Codegen, (**code).to_owned(), &rpds::vector_sync![]); + gen_stack::push_call_stack(&ns, &def, StackKind::Codegen, (**code).to_owned(), &TernaryTreeList::Empty); vals_code.push_str(&format!( "\nexport var {} = {};\n", escape_var(&def), diff --git a/src/codegen/emit_js/gen_stack.rs b/src/codegen/emit_js/gen_stack.rs index 718f8673..a34e617a 100644 --- a/src/codegen/emit_js/gen_stack.rs +++ b/src/codegen/emit_js/gen_stack.rs @@ -1,15 +1,17 @@ use std::sync::RwLock; +use im_ternary_tree::TernaryTreeList; + use crate::call_stack::{CalcitStack, CallStackVec, StackKind}; use crate::primes::{Calcit, CalcitItems}; lazy_static! { - static ref CALL_STACK: RwLock> = RwLock::new(rpds::vector_sync![]); + static ref CALL_STACK: RwLock> = RwLock::new(TernaryTreeList::Empty); } pub fn push_call_stack(ns: &str, def: &str, kind: StackKind, code: Calcit, args: &CalcitItems) { let mut stack = CALL_STACK.write().unwrap(); - (*stack).push_back_mut(CalcitStack { + *stack = stack.push(CalcitStack { ns: ns.to_owned(), def: def.to_owned(), code, @@ -19,18 +21,15 @@ pub fn push_call_stack(ns: &str, def: &str, kind: StackKind, code: Calcit, args: } pub fn pop_call_stack() { - let stack = &mut CALL_STACK.write().unwrap(); - (*stack).drop_last_mut(); + let mut stack = CALL_STACK.write().unwrap(); + if !stack.is_empty() { + *stack = stack.butlast(); + } } pub fn clear_stack() { - let stack = &mut CALL_STACK.write().unwrap(); - loop { - if stack.is_empty() { - break; - } - (*stack).drop_last_mut(); - } + let mut stack = CALL_STACK.write().unwrap(); + *stack = TernaryTreeList::Empty; } pub fn get_gen_stack() -> CallStackVec { diff --git a/src/data/cirru.rs b/src/data/cirru.rs index 692b2fa4..7dfd0801 100644 --- a/src/data/cirru.rs +++ b/src/data/cirru.rs @@ -1,5 +1,6 @@ use crate::primes::{Calcit, CalcitItems}; use cirru_parser::Cirru; +use im_ternary_tree::TernaryTreeList; /// code is CirruNode, and this function parse code(rather than data) pub fn code_to_calcit(xs: &Cirru, ns: &str, def: &str) -> Result { @@ -32,14 +33,14 @@ pub fn code_to_calcit(xs: &Cirru, ns: &str, def: &str) -> Result Err(e) => Err(format!("failed to parse hex: {} => {:?}", s, e)), }, '\'' if s.len() > 1 => Ok(Calcit::List( - rpds::vector_sync![] - .push_back(Calcit::Symbol( + TernaryTreeList::Empty + .push(Calcit::Symbol( String::from("quote").into_boxed_str(), ns.to_owned().into(), def.to_owned().into(), None, )) - .push_back(Calcit::Symbol( + .push(Calcit::Symbol( String::from(&s[1..]).into_boxed_str(), ns.to_owned().into(), def.to_owned().into(), @@ -48,14 +49,14 @@ pub fn code_to_calcit(xs: &Cirru, ns: &str, def: &str) -> Result )), // TODO also detect simple variables '~' if s.starts_with("~@") && s.chars().count() > 2 => Ok(Calcit::List( - rpds::vector_sync![] - .push_back(Calcit::Symbol( + TernaryTreeList::Empty + .push(Calcit::Symbol( String::from("~@").into_boxed_str(), ns.to_owned().into(), def.to_owned().into(), None, )) - .push_back(Calcit::Symbol( + .push(Calcit::Symbol( String::from(&s[2..]).into_boxed_str(), ns.to_owned().into(), def.to_owned().into(), @@ -63,14 +64,14 @@ pub fn code_to_calcit(xs: &Cirru, ns: &str, def: &str) -> Result )), )), '~' if s.chars().count() > 1 && !s.starts_with("~@") => Ok(Calcit::List( - rpds::vector_sync![] - .push_back(Calcit::Symbol( + TernaryTreeList::Empty + .push(Calcit::Symbol( String::from("~").into_boxed_str(), ns.to_owned().into(), def.to_owned().into(), None, )) - .push_back(Calcit::Symbol( + .push(Calcit::Symbol( String::from(&s[1..]).into_boxed_str(), ns.to_owned().into(), def.to_owned().into(), @@ -78,14 +79,14 @@ pub fn code_to_calcit(xs: &Cirru, ns: &str, def: &str) -> Result )), )), '@' => Ok(Calcit::List( - rpds::vector_sync![] - .push_back(Calcit::Symbol( + TernaryTreeList::Empty + .push(Calcit::Symbol( String::from("deref").into_boxed_str(), ns.to_owned().into(), def.to_owned().into(), None, )) - .push_back(Calcit::Symbol( + .push(Calcit::Symbol( String::from(&s[1..]).into_boxed_str(), ns.to_owned().into(), def.to_owned().into(), @@ -103,12 +104,12 @@ pub fn code_to_calcit(xs: &Cirru, ns: &str, def: &str) -> Result }, }, Cirru::List(ys) => { - let mut zs: CalcitItems = rpds::VectorSync::new_sync(); + let mut zs: CalcitItems = TernaryTreeList::Empty; for y in ys { match code_to_calcit(y, ns, def) { Ok(v) => { if !is_comment(&v) { - zs.push_back_mut(v.to_owned()) + zs = zs.push(v.to_owned()) } else { } } @@ -125,9 +126,9 @@ pub fn cirru_to_calcit(xs: &Cirru) -> Calcit { match xs { Cirru::Leaf(s) => Calcit::Str(s.to_owned()), Cirru::List(ys) => { - let mut zs: CalcitItems = rpds::vector_sync![]; + let mut zs: CalcitItems = TernaryTreeList::Empty; for y in ys { - zs.push_back_mut(cirru_to_calcit(y)) + zs = zs.push(cirru_to_calcit(y)) } Calcit::List(zs) } diff --git a/src/data/edn.rs b/src/data/edn.rs index 25051158..13aa0fee 100644 --- a/src/data/edn.rs +++ b/src/data/edn.rs @@ -6,6 +6,7 @@ use crate::primes; use crate::primes::Calcit; use cirru_edn::{Edn, EdnKwd}; +use im_ternary_tree::TernaryTreeList; // values does not fit are just represented with specical indicates pub fn calcit_to_edn(x: &Calcit) -> Result { @@ -98,9 +99,9 @@ pub fn edn_to_calcit(x: &Edn) -> Calcit { ), Edn::Tuple(pair) => Calcit::Tuple(Box::new(edn_to_calcit(&pair.0)), Box::new(edn_to_calcit(&pair.1))), Edn::List(xs) => { - let mut ys: primes::CalcitItems = rpds::vector_sync![]; + let mut ys: primes::CalcitItems = TernaryTreeList::Empty; for x in xs { - ys.push_back_mut(edn_to_calcit(x)) + ys = ys.push(edn_to_calcit(x)) } Calcit::List(ys) } diff --git a/src/lib.rs b/src/lib.rs index 69a62693..2f1793cb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,6 +18,8 @@ use std::cell::RefCell; use std::fs; use std::path::Path; +use im_ternary_tree::TernaryTreeList; + pub use primes::{Calcit, CalcitErr, CalcitItems}; pub fn load_core_snapshot() -> Result { @@ -40,7 +42,7 @@ pub fn run_program(init_fn: &str, params: CalcitItems) -> Result (), Err(failure) => { @@ -55,14 +57,14 @@ pub fn run_program(init_fn: &str, params: CalcitItems) -> Result CalcitErr::err_str(format!("entry not initialized: {}/{}", init_ns, init_def)), Some(entry) => match entry { Calcit::Fn(_, f_ns, _, def_scope, args, body) => { - let result = runner::run_fn(¶ms, &def_scope, &args, &body, &f_ns, &rpds::VectorSync::new_sync()); + let result = runner::run_fn(¶ms, &def_scope, &args, &body, &f_ns, &TernaryTreeList::Empty); match result { Ok(v) => Ok(v), Err(failure) => { diff --git a/src/primes.rs b/src/primes.rs index 1b20d675..93eb5310 100644 --- a/src/primes.rs +++ b/src/primes.rs @@ -9,12 +9,13 @@ use std::hash::{Hash, Hasher}; use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; use cirru_edn::EdnKwd; +use im_ternary_tree::TernaryTreeList; static ID_GEN: AtomicUsize = AtomicUsize::new(0); // scope pub type CalcitScope = rpds::HashTrieMapSync, Calcit>; -pub type CalcitItems = rpds::VectorSync; +pub type CalcitItems = TernaryTreeList; pub use syntax_name::CalcitSyntax; @@ -37,7 +38,9 @@ pub enum ImportRule { /// special types wraps vector of calcit data for displaying #[derive(Debug, Clone, PartialEq, PartialOrd)] -pub struct CrListWrap(pub rpds::VectorSync); +pub struct CrListWrap(pub TernaryTreeList); + +pub struct CalcitList(pub Box>); #[derive(Debug, Clone)] pub enum Calcit { @@ -232,7 +235,7 @@ pub fn format_to_lisp(x: &Calcit) -> String { match x { Calcit::List(ys) => { let mut s = String::from("("); - for (idx, y) in ys.iter().enumerate() { + for (idx, y) in ys.into_iter().enumerate() { if idx > 0 { s.push(' '); } @@ -527,7 +530,7 @@ pub fn gen_core_id() -> Box { pub struct CalcitErr { pub msg: String, pub warnings: Vec, - pub stack: rpds::VectorSync, + pub stack: TernaryTreeList, } impl fmt::Display for CalcitErr { @@ -548,14 +551,14 @@ impl CalcitErr { CalcitErr { msg: msg.into(), warnings: vec![], - stack: rpds::Vector::new_sync(), + stack: TernaryTreeList::Empty, } } pub fn err_str>(msg: T) -> Result { Err(CalcitErr { msg: msg.into(), warnings: vec![], - stack: rpds::Vector::new_sync(), + stack: TernaryTreeList::Empty, }) } pub fn use_msg_stack>(msg: T, stack: &CallStackVec) -> Self { diff --git a/src/runner.rs b/src/runner.rs index 8d2f0e6c..dda28318 100644 --- a/src/runner.rs +++ b/src/runner.rs @@ -7,6 +7,8 @@ use crate::call_stack::{extend_call_stack, CallStackVec, StackKind}; use crate::primes::{Calcit, CalcitErr, CalcitItems, CalcitScope, CalcitSyntax, CrListWrap, SymbolResolved::*, CORE_NS}; use crate::program; use crate::util::skip; + +use im_ternary_tree::TernaryTreeList; use std::sync::{Arc, RwLock}; pub fn evaluate_expr(expr: &Calcit, scope: &CalcitScope, file_ns: &str, call_stack: &CallStackVec) -> Result { @@ -317,9 +319,9 @@ pub fn bind_args( return Err(CalcitErr::use_msg_stack(format!("invalid ? in args: {:?}", args), call_stack)) } Calcit::Symbol(s, ..) => { - let mut chunk: CalcitItems = rpds::vector_sync![]; + let mut chunk: CalcitItems = TernaryTreeList::Empty; while let Some(v) = values_pop_front() { - chunk.push_back_mut(v.to_owned()); + chunk = chunk.push(v.to_owned()); } scope.insert_mut(s.to_owned(), Calcit::List(chunk)); if !is_args_empty() { @@ -396,7 +398,7 @@ pub fn evaluate_args( file_ns: &str, call_stack: &CallStackVec, ) -> Result { - let mut ret: CalcitItems = rpds::vector_sync![]; + let mut ret: CalcitItems = TernaryTreeList::Empty; let mut spreading = false; for item in items { match item { @@ -409,7 +411,7 @@ pub fn evaluate_args( if spreading { match v { Calcit::List(xs) => { - for x in xs.iter() { + for x in &xs { // extract thunk before calling functions let y = match x { Calcit::Thunk(code, v) => match v { @@ -418,7 +420,7 @@ pub fn evaluate_args( }, _ => x.to_owned(), }; - ret.push_back_mut(y.to_owned()); + ret = ret.push(y.to_owned()); } spreading = false } @@ -438,7 +440,7 @@ pub fn evaluate_args( }, _ => v.to_owned(), }; - ret.push_back_mut(y); + ret = ret.push(y); } } } diff --git a/src/runner/preprocess.rs b/src/runner/preprocess.rs index 7382d701..10b758e6 100644 --- a/src/runner/preprocess.rs +++ b/src/runner/preprocess.rs @@ -10,6 +10,8 @@ use crate::util::skip; use std::cell::RefCell; use std::collections::HashSet; +use im_ternary_tree::TernaryTreeList; + /// returns the resolved symbol, /// if code related is not preprocessed, do it internally pub fn preprocess_ns_def( @@ -19,7 +21,7 @@ pub fn preprocess_ns_def( raw_sym: &str, import_rule: Option, // returns form and possible value check_warnings: &RefCell>, - call_stack: &rpds::VectorSync, + call_stack: &TernaryTreeList, ) -> Result<(Calcit, Option), CalcitErr> { let ns = &raw_ns.to_owned().into_boxed_str(); let def = &raw_def.to_owned().into_boxed_str(); @@ -45,7 +47,7 @@ pub fn preprocess_ns_def( // write a nil value first to prevent dead loop program::write_evaled_def(ns, def, Calcit::Nil).map_err(|e| CalcitErr::use_msg_stack(e, call_stack))?; - let next_stack = extend_call_stack(call_stack, ns, def, StackKind::Fn, code.to_owned(), &rpds::vector_sync![]); + let next_stack = extend_call_stack(call_stack, ns, def, StackKind::Fn, code.to_owned(), &TernaryTreeList::Empty); let (resolved_code, _resolve_value) = preprocess_expr(&code, &HashSet::new(), ns, check_warnings, &next_stack)?; // println!("\n resolve code to run: {:?}", resolved_code); @@ -261,7 +263,7 @@ fn process_list_call( match (head_form.to_owned(), head_evaled) { (Calcit::Keyword(..), _) => { if args.len() == 1 { - let code = Calcit::List(rpds::vector_sync![ + let code = Calcit::List(TernaryTreeList::from(&vec![ Calcit::Symbol( String::from("get").into_boxed_str(), String::from(primes::CORE_NS).into_boxed_str(), @@ -269,12 +271,12 @@ fn process_list_call( Some(Box::new(ResolvedDef( String::from(primes::CORE_NS).into_boxed_str(), String::from("get").into_boxed_str(), - None - ))) + None, + ))), ), args[0].to_owned(), - head.to_owned() - ]); + head.to_owned(), + ])); preprocess_expr(&code, scope_defs, file_ns, check_warnings, call_stack) } else { Err(CalcitErr::use_msg_stack(format!("{} expected single argument", head), call_stack)) @@ -344,18 +346,18 @@ fn process_list_call( (_, Some(Calcit::Fn(f_name, _name_ns, _id, _scope, f_args, _f_body))) => { check_fn_args(&f_args, &args, file_ns, &f_name, &def_name, check_warnings); - let mut ys = rpds::vector_sync![head_form]; - for a in args.iter() { + let mut ys = TernaryTreeList::from(&[head_form]); + for a in &args { let (form, _v) = preprocess_expr(a, scope_defs, file_ns, check_warnings, call_stack)?; - ys.push_back_mut(form); + ys = ys.push(form); } Ok((Calcit::List(ys), None)) } (_, _) => { - let mut ys = rpds::vector_sync![head_form]; - for a in args.iter() { + let mut ys = TernaryTreeList::from(&[head_form]); + for a in &args { let (form, _v) = preprocess_expr(a, scope_defs, file_ns, check_warnings, call_stack)?; - ys.push_back_mut(form); + ys = ys.push(form); } Ok((Calcit::List(ys), None)) } @@ -452,10 +454,10 @@ pub fn preprocess_each_items( check_warnings: &RefCell>, call_stack: &CallStackVec, ) -> Result { - let mut xs: CalcitItems = rpds::vector_sync![Calcit::Syntax(head.to_owned(), head_ns.to_owned().into())]; + let mut xs: CalcitItems = TernaryTreeList::from(&[Calcit::Syntax(head.to_owned(), head_ns.to_owned().into())]); for a in args { let (form, _v) = preprocess_expr(a, scope_defs, file_ns, check_warnings, call_stack)?; - xs.push_back_mut(form); + xs = xs.push(form); } Ok(Calcit::List(xs)) } @@ -470,23 +472,23 @@ pub fn preprocess_defn( call_stack: &CallStackVec, ) -> Result { // println!("defn args: {}", primes::CrListWrap(args.to_owned())); - let mut xs: CalcitItems = rpds::vector_sync![Calcit::Syntax(head.to_owned(), head_ns.to_owned().into())]; + let mut xs: CalcitItems = TernaryTreeList::from(&[Calcit::Syntax(head.to_owned(), head_ns.to_owned().into())]); match (args.get(0), args.get(1)) { (Some(Calcit::Symbol(def_name, def_name_ns, at_def, _)), Some(Calcit::List(ys))) => { let mut body_defs: HashSet> = scope_defs.to_owned(); - xs.push_back_mut(Calcit::Symbol( + xs = xs.push(Calcit::Symbol( def_name.to_owned(), def_name_ns.to_owned(), at_def.to_owned(), Some(Box::new(ResolvedRaw)), )); - let mut zs: CalcitItems = rpds::vector_sync![]; + let mut zs: CalcitItems = TernaryTreeList::Empty; for y in ys { match y { Calcit::Symbol(sym, def_ns, at_def, _) => { check_symbol(sym, args, check_warnings); - zs.push_back_mut(Calcit::Symbol( + zs = zs.push(Calcit::Symbol( sym.to_owned(), def_ns.to_owned(), at_def.to_owned(), @@ -505,12 +507,12 @@ pub fn preprocess_defn( } } } - xs.push_back_mut(Calcit::List(zs)); + xs = xs.push(Calcit::List(zs)); - for (idx, a) in args.iter().enumerate() { + for (idx, a) in args.into_iter().enumerate() { if idx >= 2 { let (form, _v) = preprocess_expr(a, &body_defs, file_ns, check_warnings, call_stack)?; - xs.push_back_mut(form); + xs = xs.push(form); } } Ok(Calcit::List(xs)) @@ -548,7 +550,7 @@ pub fn preprocess_call_let( check_warnings: &RefCell>, call_stack: &CallStackVec, ) -> Result { - let mut xs: CalcitItems = rpds::vector_sync![Calcit::Syntax(head.to_owned(), head_ns.to_owned().into())]; + let mut xs: CalcitItems = TernaryTreeList::from(&[Calcit::Syntax(head.to_owned(), head_ns.to_owned().into())]); let mut body_defs: HashSet> = scope_defs.to_owned(); let binding = match args.get(0) { Some(Calcit::Nil) => Calcit::Nil, @@ -557,7 +559,7 @@ pub fn preprocess_call_let( check_symbol(sym, args, check_warnings); body_defs.insert(sym.to_owned()); let (form, _v) = preprocess_expr(a, &body_defs, file_ns, check_warnings, call_stack)?; - Calcit::List(rpds::vector_sync![ys[0].to_owned(), form]) + Calcit::List(TernaryTreeList::from(&[ys[0].to_owned(), form])) } (a, b) => { return Err(CalcitErr::use_msg_stack( @@ -585,11 +587,11 @@ pub fn preprocess_call_let( )) } }; - xs.push_back_mut(binding); - for (idx, a) in args.iter().enumerate() { + xs = xs.push(binding); + for (idx, a) in args.into_iter().enumerate() { if idx > 0 { let (form, _v) = preprocess_expr(a, &body_defs, file_ns, check_warnings, call_stack)?; - xs.push_back_mut(form); + xs = xs.push(form); } } Ok(Calcit::List(xs)) @@ -602,9 +604,9 @@ pub fn preprocess_quote( _scope_defs: &HashSet>, _file_ns: &str, ) -> Result { - let mut xs: CalcitItems = rpds::vector_sync![Calcit::Syntax(head.to_owned(), head_ns.to_owned().into())]; + let mut xs: CalcitItems = TernaryTreeList::from(&[Calcit::Syntax(head.to_owned(), head_ns.to_owned().into())]); for a in args { - xs.push_back_mut(a.to_owned()); + xs = xs.push(a.to_owned()); } Ok(Calcit::List(xs)) } @@ -618,11 +620,11 @@ pub fn preprocess_defatom( check_warnings: &RefCell>, call_stack: &CallStackVec, ) -> Result { - let mut xs: CalcitItems = rpds::vector_sync![Calcit::Syntax(head.to_owned(), head_ns.to_owned().into())]; + let mut xs: CalcitItems = TernaryTreeList::from(&[Calcit::Syntax(head.to_owned(), head_ns.to_owned().into())]); for a in args { // TODO let (form, _v) = preprocess_expr(a, scope_defs, file_ns, check_warnings, call_stack)?; - xs.push_back_mut(form.to_owned()); + xs = xs.push(form.to_owned()); } Ok(Calcit::List(xs)) } @@ -637,9 +639,9 @@ pub fn preprocess_quasiquote( check_warnings: &RefCell>, call_stack: &CallStackVec, ) -> Result { - let mut xs: CalcitItems = rpds::vector_sync![Calcit::Syntax(head.to_owned(), head_ns.to_owned().into())]; + let mut xs: CalcitItems = TernaryTreeList::from(&[Calcit::Syntax(head.to_owned(), head_ns.to_owned().into())]); for a in args { - xs.push_back_mut(preprocess_quasiquote_internal(a, scope_defs, file_ns, check_warnings, call_stack)?); + xs = xs.push(preprocess_quasiquote_internal(a, scope_defs, file_ns, check_warnings, call_stack)?); } Ok(Calcit::List(xs)) } @@ -655,17 +657,17 @@ pub fn preprocess_quasiquote_internal( Calcit::List(ys) if ys.is_empty() => Ok(x.to_owned()), Calcit::List(ys) => match &ys[0] { Calcit::Symbol(s, _, _, _) if &**s == "~" || &**s == "~@" => { - let mut xs: CalcitItems = rpds::vector_sync![]; + let mut xs: CalcitItems = TernaryTreeList::Empty; for y in ys { let (form, _) = preprocess_expr(y, scope_defs, file_ns, check_warnings, call_stack)?; - xs.push_back_mut(form.to_owned()); + xs = xs.push(form.to_owned()); } Ok(Calcit::List(xs)) } _ => { - let mut xs: CalcitItems = rpds::vector_sync![]; + let mut xs: CalcitItems = TernaryTreeList::Empty; for y in ys { - xs.push_back_mut(preprocess_quasiquote_internal(y, scope_defs, file_ns, check_warnings, call_stack)?.to_owned()); + xs = xs.push(preprocess_quasiquote_internal(y, scope_defs, file_ns, check_warnings, call_stack)?.to_owned()); } Ok(Calcit::List(xs)) } diff --git a/src/util.rs b/src/util.rs index 861a70f8..59255a90 100644 --- a/src/util.rs +++ b/src/util.rs @@ -4,51 +4,28 @@ pub mod string; use std::cmp::Ordering; use crate::primes::Calcit; +use im_ternary_tree::TernaryTreeList; -pub fn skip(xs: &rpds::VectorSync, skipped: usize) -> rpds::VectorSync { - let mut ys: rpds::VectorSync = rpds::Vector::new_sync(); - for (idx, x) in xs.iter().enumerate() { - if idx >= skipped { - ys.push_back_mut(x.to_owned()); - } - } - ys +pub fn skip(xs: &TernaryTreeList, skipped: usize) -> TernaryTreeList { + xs.slice(skipped, xs.len()) } -pub fn slice(xs: &rpds::VectorSync, from: usize, to: usize) -> rpds::VectorSync { - let mut ys: rpds::VectorSync = rpds::Vector::new_sync(); - for (idx, x) in xs.iter().enumerate() { - if idx >= from && idx < to { - ys.push_back_mut(x.to_owned()); - } - } - ys +pub fn slice(xs: &TernaryTreeList, from: usize, to: usize) -> TernaryTreeList { + xs.slice(from, to) } -pub fn contains(xs: &rpds::VectorSync, y: &Calcit) -> bool { - for x in xs.iter() { - if x == y { - return true; - } - } - false +pub fn contains(xs: &TernaryTreeList, y: &Calcit) -> bool { + xs.index_of(y) >= 0 } -pub fn insert(xs: &rpds::VectorSync, pos: usize, y: Calcit) -> rpds::VectorSync { - let mut ys: rpds::VectorSync = rpds::Vector::new_sync(); +pub fn insert(xs: &TernaryTreeList, pos: usize, y: Calcit) -> TernaryTreeList { + let mut ys: TernaryTreeList = TernaryTreeList::Empty; match pos.cmp(&xs.len()) { - Ordering::Less => { - for (idx, x) in xs.iter().enumerate() { - if idx == pos { - ys.push_back_mut(y.to_owned()); - } - ys.push_back_mut(x.to_owned()); - } - } + Ordering::Less => ys = ys.assoc_before(pos, y), Ordering::Equal => { ys = xs.to_owned(); - ys.push_back_mut(y.to_owned()); + ys = ys.push(y.to_owned()); } Ordering::Greater => { println!("[Error] TODO error") diff --git a/ts-src/calcit.procs.ts b/ts-src/calcit.procs.ts index 8d8bb4d1..fe11ab56 100644 --- a/ts-src/calcit.procs.ts +++ b/ts-src/calcit.procs.ts @@ -1,5 +1,5 @@ // CALCIT VERSION -export const calcit_version = "0.5.0-a21"; +export const calcit_version = "0.5.0-a22"; import { overwriteComparator, initTernaryTreeMap } from "@calcit/ternary-tree"; import { parse, ICirruNode } from "@cirru/parser.ts";