From 40d1575ee1221d961c442ec1ebb531a103081337 Mon Sep 17 00:00:00 2001 From: jiyinyiyong Date: Sat, 4 Dec 2021 16:35:21 +0800 Subject: [PATCH] moving back to ternary-tree; tag 0.5.11 --- Cargo.lock | 16 +- Cargo.toml | 7 +- src/bin/cr.rs | 14 +- src/bin/injection/mod.rs | 14 +- src/builtins/lists.rs | 108 ++++++------- src/builtins/maps.rs | 28 ++-- src/builtins/meta.rs | 6 +- src/builtins/refs.rs | 4 +- src/builtins/sets.rs | 9 +- src/builtins/strings.rs | 15 +- src/builtins/syntax.rs | 44 +++--- src/call_stack.rs | 6 +- src/codegen/emit_js.rs | 45 +++--- src/codegen/emit_js/gen_stack.rs | 2 +- src/codegen/gen_ir.rs | 6 +- src/data/cirru.rs | 34 ++-- src/data/edn.rs | 11 +- src/primes.rs | 31 ++-- src/primes/finger_list.rs | 260 ------------------------------- src/runner.rs | 30 ++-- src/runner/preprocess.rs | 103 ++++++------ 21 files changed, 264 insertions(+), 529 deletions(-) delete mode 100644 src/primes/finger_list.rs diff --git a/Cargo.lock b/Cargo.lock index 2d33b191..6f6fd61e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -45,15 +45,15 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "calcit_runner" -version = "0.5.10" +version = "0.5.11" dependencies = [ "cirru_edn", "cirru_parser", "clap", "ctrlc", "dirs", - "fingertrees", "hex", + "im_ternary_tree", "lazy_static", "libloading", "notify", @@ -153,12 +153,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "fingertrees" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc7e8750923c1ac2d34ef651af47b0c63398d403866d1ab0718938817764a8b" - [[package]] name = "fsevent" version = "0.4.0" @@ -220,6 +214,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.2-a2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6e12b9f78052839cfa8d06f59653199863a57068d9393ec6bed1acec4a94559" + [[package]] name = "inotify" version = "0.7.1" diff --git a/Cargo.toml b/Cargo.toml index c9078a5e..4c4cfb49 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "calcit_runner" -version = "0.5.10" +version = "0.5.11" authors = ["jiyinyiyong "] edition = "2018" license = "MIT" @@ -30,9 +30,8 @@ notify = "4.0.17" walkdir = "2" hex = "0.4.3" rpds = "0.10.0" -fingertrees = "0.2.9" -# calcit_fingertrees = "0.0.3" -# calcit_fingertrees = { path = "/Users/chen/repo/calcit-lang/fingertree-rs" } +im_ternary_tree = "0.0.2-a2" +# im_ternary_tree = { path = "/Users/chen/repo/calcit-lang/ternary-tree" } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] libloading = "0.7.2" diff --git a/src/bin/cr.rs b/src/bin/cr.rs index 0d60a094..ba3b64b0 100644 --- a/src/bin/cr.rs +++ b/src/bin/cr.rs @@ -9,11 +9,12 @@ use std::time::Instant; #[cfg(not(target_arch = "wasm32"))] mod injection; +use im_ternary_tree::TernaryTreeList; use notify::{RecommendedWatcher, RecursiveMode, Watcher}; use calcit_runner::{ - builtins, call_stack, cli_args, codegen, codegen::emit_js::gen_stack, codegen::COMPILE_ERRORS_FILE, primes::finger_list::FingerList, - program, runner, snapshot, util, ProgramEntries, + builtins, call_stack, cli_args, codegen, codegen::emit_js::gen_stack, codegen::COMPILE_ERRORS_FILE, program, runner, snapshot, util, + ProgramEntries, }; pub struct CLIOptions { @@ -137,7 +138,7 @@ fn main() -> Result<(), String> { let started_time = Instant::now(); let v = - calcit_runner::run_program(entries.init_ns.to_owned(), entries.init_def.to_owned(), FingerList::new_empty()).map_err(|e| { + calcit_runner::run_program(entries.init_ns.to_owned(), entries.init_def.to_owned(), TernaryTreeList::Empty).map_err(|e| { for w in e.warnings { println!("{}", w); } @@ -264,14 +265,13 @@ fn recall_program(content: &str, entries: &ProgramEntries, settings: &CLIOptions let warnings = check_warnings.to_owned().into_inner(); throw_on_warnings(&warnings)?; } - let v = calcit_runner::run_program(entries.reload_ns.to_owned(), entries.reload_def.to_owned(), FingerList::new_empty()).map_err( - |e| { + let v = + calcit_runner::run_program(entries.reload_ns.to_owned(), entries.reload_def.to_owned(), TernaryTreeList::Empty).map_err(|e| { for w in e.warnings { println!("{}", w); } e.msg - }, - )?; + })?; let duration = Instant::now().duration_since(started_time); println!("took {}ms: {}", duration.as_micros() as f64 / 1000.0, v); Ok(()) diff --git a/src/bin/injection/mod.rs b/src/bin/injection/mod.rs index cfd2cb71..ca7dcb6a 100644 --- a/src/bin/injection/mod.rs +++ b/src/bin/injection/mod.rs @@ -3,11 +3,13 @@ use cirru_edn::Edn; use std::sync::Arc; use std::thread; +use im_ternary_tree::TernaryTreeList; + use calcit_runner::{ builtins, call_stack::{display_stack, CallStackList}, data::edn::{calcit_to_edn, edn_to_calcit}, - primes::{finger_list::FingerList, Calcit, CalcitErr, CalcitItems, CrListWrap}, + primes::{Calcit, CalcitErr, CalcitItems, CrListWrap}, runner::track, }; @@ -137,9 +139,9 @@ pub fn call_dylib_edn_fn(xs: &CalcitItems, call_stack: &CallStackList) -> Result def_ns, scope, args, body, .. } = &callback { - let mut real_args = FingerList::new_empty(); + let mut real_args = TernaryTreeList::Empty; for p in ps { - real_args = real_args.push(edn_to_calcit(&p)); + real_args = real_args.push_right(edn_to_calcit(&p)); } let r = runner::run_fn(&real_args, scope, args, body, def_ns.to_owned(), &copied_stack); match r { @@ -225,9 +227,9 @@ pub fn blocking_dylib_edn_fn(xs: &CalcitItems, call_stack: &CallStackList) -> Re def_ns, scope, args, body, .. } = &callback { - let mut real_args = FingerList::new_empty(); + let mut real_args = TernaryTreeList::Empty; for p in ps { - real_args = real_args.push(edn_to_calcit(&p)); + real_args = real_args.push_right(edn_to_calcit(&p)); } let r = runner::run_fn(&real_args, scope, args, body, def_ns.to_owned(), &copied_stack.clone()); match r { @@ -267,7 +269,7 @@ pub fn on_ctrl_c(xs: &CalcitItems, call_stack: &CallStackList) -> Result Result { - Ok(Calcit::List(Box::new(xs.to_owned()))) + Ok(Calcit::List(xs.to_owned())) } pub fn count(xs: &CalcitItems) -> Result { @@ -54,7 +55,7 @@ pub fn slice(xs: &CalcitItems) -> Result { }; let from_idx: usize = unsafe { from.to_int_unchecked() }; - Ok(Calcit::List(Box::new(ys.slice(from_idx, to_idx)?))) + Ok(Calcit::List(ys.slice(from_idx, to_idx)?)) } (a, b) => CalcitErr::err_str(format!("slice expected list and indexes: {} {}", a, b)), } @@ -65,14 +66,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) => Ok(Calcit::List(Box::new(ys.push(xs[1].to_owned())))), + Calcit::List(ys) => Ok(Calcit::List(ys.push_right(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)) => Ok(Calcit::List(Box::new(ys.unshift(a.to_owned())))), + (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"), } @@ -87,7 +88,7 @@ pub fn rest(xs: &CalcitItems) -> Result { if ys.is_empty() { Ok(Calcit::Nil) } else { - Ok(Calcit::List(Box::new(ys.rest()?))) + Ok(Calcit::List(ys.drop_left())) } } a => CalcitErr::err_str(format!("list:rest expected a list, got: {}", a)), @@ -104,7 +105,7 @@ pub fn butlast(xs: &CalcitItems) -> Result { if ys.is_empty() { Ok(Calcit::Nil) } else { - Ok(Calcit::List(Box::new(ys.butlast()?))) + Ok(Calcit::List(ys.butlast()?)) } } a => CalcitErr::err_str(format!("butlast expected a list, got: {}", a)), @@ -112,17 +113,17 @@ pub fn butlast(xs: &CalcitItems) -> Result { } pub fn concat(xs: &CalcitItems) -> Result { - let mut ys: CalcitItems = FingerList::new_empty(); + let mut ys: CalcitItems = TernaryTreeList::Empty; for x in xs { if let Calcit::List(zs) = x { - for z in &**zs { - ys = ys.push(z.to_owned()); + for z in zs { + ys = ys.push_right(z.to_owned()); } } else { return CalcitErr::err_str(format!("concat expects list arguments, got: {}", x)); } } - Ok(Calcit::List(Box::new(ys))) + Ok(Calcit::List(ys)) } pub fn range(xs: &CalcitItems) -> Result { @@ -142,27 +143,27 @@ pub fn range(xs: &CalcitItems) -> Result { }; if (bound - base).abs() < f64::EPSILON { - return Ok(Calcit::List(Box::new(FingerList::new_empty()))); + 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 = FingerList::new_empty(); + let mut ys: CalcitItems = TernaryTreeList::Empty; let mut i = base; if step > 0.0 { while i < bound { - ys = ys.push(Calcit::Number(i)); + ys = ys.push_right(Calcit::Number(i)); i += step; } } else { while i > bound { - ys = ys.push(Calcit::Number(i)); + ys = ys.push_right(Calcit::Number(i)); i += step; } } - Ok(Calcit::List(Box::new(ys))) + Ok(Calcit::List(ys)) } pub fn reverse(xs: &CalcitItems) -> Result { @@ -171,7 +172,7 @@ pub fn reverse(xs: &CalcitItems) -> Result { } match &xs[0] { Calcit::Nil => Ok(Calcit::Nil), - Calcit::List(ys) => Ok(Calcit::List(Box::new(ys.reverse()))), + Calcit::List(ys) => Ok(Calcit::List(ys.reverse())), a => CalcitErr::err_str(format!("butlast expected a list, got: {}", a)), } } @@ -189,16 +190,16 @@ pub fn foldl(xs: &CalcitItems, call_stack: &CallStackList) -> Result { - for x in &**xs { - let values = FingerList::from(&[Size(ret), Size(x.to_owned())]); + for x in xs { + let values = TernaryTreeList::from(&[ret, x.to_owned()]); ret = runner::run_fn(&values, scope, args, body, def_ns.to_owned(), call_stack)?; } Ok(ret) } (Calcit::List(xs), Calcit::Proc(proc)) => { - for x in &**xs { + for x in xs { // println!("foldl args, {} {}", ret, x.to_owned()); - ret = builtins::handle_proc(proc, &FingerList::from(&[Size(ret), Size(x.to_owned())]), call_stack)?; + ret = builtins::handle_proc(proc, &TernaryTreeList::from(&[ret, x.to_owned()]), call_stack)?; } Ok(ret) } @@ -210,7 +211,7 @@ pub fn foldl(xs: &CalcitItems, call_stack: &CallStackList) -> Result { for x in xs { - let values = FingerList::from(&[Size(ret), Size(x.to_owned())]); + let values = TernaryTreeList::from(&[ret, x.to_owned()]); ret = runner::run_fn(&values, scope, args, body, def_ns.to_owned(), call_stack)?; } Ok(ret) @@ -218,7 +219,7 @@ pub fn foldl(xs: &CalcitItems, call_stack: &CallStackList) -> Result { for x in xs { // println!("foldl args, {} {}", ret, x.to_owned()); - ret = builtins::handle_proc(proc, &FingerList::from(&[Size(ret), Size(x.to_owned())]), call_stack)?; + ret = builtins::handle_proc(proc, &TernaryTreeList::from(&[ret, x.to_owned()]), call_stack)?; } Ok(ret) } @@ -230,10 +231,7 @@ pub fn foldl(xs: &CalcitItems, call_stack: &CallStackList) -> Result { for (k, x) in xs { - let values = FingerList::from(&[ - Size(ret), - Size(Calcit::List(Box::new(FingerList::from(&[Size(k.to_owned()), Size(x.to_owned())])))), - ]); + let values = TernaryTreeList::from(&[ret, Calcit::List(TernaryTreeList::from(&[k.to_owned(), x.to_owned()]))]); ret = runner::run_fn(&values, scope, args, body, def_ns.to_owned(), call_stack)?; } Ok(ret) @@ -243,10 +241,7 @@ pub fn foldl(xs: &CalcitItems, call_stack: &CallStackList) -> Result Result { let mut state = acc.to_owned(); - for x in &**xs { - let values = FingerList::from(&[Size(state), Size(x.to_owned())]); + for x in xs { + let values = TernaryTreeList::from(&[state, x.to_owned()]); let pair = runner::run_fn(&values, scope, args, body, def_ns.to_owned(), call_stack)?; match pair { Calcit::Tuple(x0, x1) => match &*x0 { @@ -319,7 +314,7 @@ pub fn foldl_shortcut(xs: &CalcitItems, call_stack: &CallStackList) -> Result { let mut state = acc.to_owned(); for x in xs { - let values = FingerList::from(&[Size(state), Size(x.to_owned())]); + let values = TernaryTreeList::from(&[state, x.to_owned()]); let pair = runner::run_fn(&values, scope, args, body, def_ns.to_owned(), call_stack)?; match pair { Calcit::Tuple(x0, x1) => match &*x0 { @@ -356,10 +351,7 @@ pub fn foldl_shortcut(xs: &CalcitItems, call_stack: &CallStackList) -> Result { let mut state = acc.to_owned(); for (k, x) in xs { - let values = FingerList::from(&[ - Size(state), - Size(Calcit::List(Box::new(FingerList::from(&[Size(k.to_owned()), Size(x.to_owned())])))), - ]); + let values = TernaryTreeList::from(&[state, Calcit::List(TernaryTreeList::from(&[k.to_owned(), x.to_owned()]))]); let pair = runner::run_fn(&values, scope, args, body, def_ns.to_owned(), call_stack)?; match pair { Calcit::Tuple(x0, x1) => match &*x0 { @@ -419,7 +411,7 @@ pub fn foldr_shortcut(xs: &CalcitItems, call_stack: &CallStackList) -> Result match &*x0 { @@ -473,7 +465,7 @@ pub fn sort(xs: &CalcitItems, call_stack: &CallStackList) -> Result { let mut xs2: Vec<&Calcit> = xs.into_iter().collect::>(); xs2.sort_by(|a, b| -> Ordering { - let values = FingerList::from(&[Size((*a).to_owned()), Size((*b).to_owned())]); + let values = TernaryTreeList::from(&[(*a).to_owned(), (*b).to_owned()]); let v = runner::run_fn(&values, scope, args, body, def_ns.to_owned(), call_stack); match v { Ok(Calcit::Number(x)) if x < 0.0 => Ordering::Less, @@ -489,17 +481,17 @@ pub fn sort(xs: &CalcitItems, call_stack: &CallStackList) -> Result = FingerList::new_empty(); + let mut ys: TernaryTreeList = TernaryTreeList::Empty; for x in xs2.iter() { // TODO ?? - ys = ys.push((*x).to_owned()) + ys = ys.push_right((*x).to_owned()) } - Ok(Calcit::List(Box::new(ys))) + Ok(Calcit::List(ys)) } (Calcit::List(xs), Calcit::Proc(proc)) => { let mut xs2: Vec<&Calcit> = xs.into_iter().collect::>(); xs2.sort_by(|a, b| -> Ordering { - let values = FingerList::from(&[Size((*a).to_owned()), Size((*b).to_owned())]); + let values = TernaryTreeList::from(&[(*a).to_owned(), (*b).to_owned()]); let v = builtins::handle_proc(proc, &values, call_stack); match v { Ok(Calcit::Number(x)) if x < 0.0 => Ordering::Less, @@ -515,12 +507,12 @@ pub fn sort(xs: &CalcitItems, call_stack: &CallStackList) -> Result = FingerList::new_empty(); + let mut ys: TernaryTreeList = TernaryTreeList::Empty; for x in xs2.iter() { // TODO ?? - ys = ys.push((*x).to_owned()) + ys = ys.push_right((*x).to_owned()) } - Ok(Calcit::List(Box::new(ys))) + Ok(Calcit::List(ys)) } (a, b) => Err(CalcitErr::use_msg_stack( format!("sort expected list and function, got: {} {}", a, b), @@ -560,7 +552,7 @@ pub fn assoc_before(xs: &CalcitItems) -> Result { (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(Box::new(zs.assoc_before(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)), }, @@ -576,7 +568,7 @@ pub fn assoc_after(xs: &CalcitItems) -> Result { (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(Box::new(zs.assoc_after(idx, 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)), }, @@ -623,12 +615,12 @@ pub fn assoc(xs: &CalcitItems) -> Result { (Calcit::List(zs), Calcit::Number(n)) => match f64_to_usize(*n) { Ok(idx) => { if idx < zs.len() { - let mut ys = (**zs).to_owned(); + let mut ys = zs.to_owned(); // ys[idx] = xs[2].to_owned(); ys = ys.assoc(idx, xs[2].to_owned())?; - Ok(Calcit::List(Box::new(ys))) + Ok(Calcit::List(ys)) } else { - Ok(Calcit::List(Box::new(xs.to_owned()))) + Ok(Calcit::List(xs.to_owned())) } } Err(e) => CalcitErr::err_str(e), @@ -640,7 +632,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) => Ok(Calcit::List(Box::new(xs.dissoc(at)?))), + 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)), @@ -655,7 +647,7 @@ pub fn list_to_set(xs: &CalcitItems) -> Result { match &xs[0] { Calcit::List(ys) => { let mut zs = rpds::HashTrieSet::new_sync(); - for y in &**ys { + for y in ys { zs.insert_mut(y.to_owned()); } Ok(Calcit::Set(zs)) @@ -670,13 +662,13 @@ pub fn distinct(xs: &CalcitItems) -> Result { } match &xs[0] { Calcit::List(ys) => { - let mut zs = FingerList::new_empty(); - for y in &**ys { + let mut zs = TernaryTreeList::Empty; + for y in ys { if zs.index_of(y).is_none() { - zs = zs.push(y.to_owned()); + zs = zs.push_right(y.to_owned()); } } - Ok(Calcit::List(Box::new(zs))) + Ok(Calcit::List(zs)) } a => CalcitErr::err_str(format!("&list:distinct expected a list, got {}", a)), } diff --git a/src/builtins/maps.rs b/src/builtins/maps.rs index 9e794c07..b376d4e3 100644 --- a/src/builtins/maps.rs +++ b/src/builtins/maps.rs @@ -1,9 +1,9 @@ use std::sync::Arc; use cirru_edn::EdnKwd; +use im_ternary_tree::TernaryTreeList; use crate::builtins::records::find_in_fields; -use crate::primes::finger_list::{FingerList, Size}; use crate::primes::{Calcit, CalcitErr, CalcitItems, CrListWrap}; use crate::util::number::is_even; @@ -102,20 +102,20 @@ 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(Box::new( - FingerList::new_empty().push(k.to_owned()).push(v.to_owned()), - ))); + zs.insert_mut(Calcit::List( + TernaryTreeList::Empty.push_right(k.to_owned()).push_right(v.to_owned()), + )); } Ok(Calcit::Set(zs)) } Some(Calcit::Record(_name, fields, values)) => { let mut zs: rpds::HashTrieSetSync = rpds::HashTrieSet::new_sync(); for idx in 0..fields.len() { - zs.insert_mut(Calcit::List(Box::new( - FingerList::new_empty() - .push(Calcit::Keyword(fields[idx].to_owned())) - .push(values[idx].to_owned()), - ))); + zs.insert_mut(Calcit::List( + TernaryTreeList::Empty + .push_right(Calcit::Keyword(fields[idx].to_owned())) + .push_right(values[idx].to_owned()), + )); } Ok(Calcit::Set(zs)) } @@ -144,12 +144,12 @@ 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: FingerList = FingerList::new_empty(); + let mut ys: TernaryTreeList = TernaryTreeList::Empty; for (k, v) in m { - let zs: FingerList = FingerList::from(&[Size(k.to_owned()), Size(v.to_owned())]); - ys = ys.push(Calcit::List(Box::new(zs))); + let zs: TernaryTreeList = TernaryTreeList::from(&[k.to_owned(), v.to_owned()]); + ys = ys.push_right(Calcit::List(zs)); } - Ok(Calcit::List(Box::new(ys))) + Ok(Calcit::List(ys)) } Some(a) => CalcitErr::err_str(format!("&map:to-list expected a map, got: {}", a)), None => CalcitErr::err_str("&map:to-list expected a map, got nothing"), @@ -200,7 +200,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(Box::new(FingerList::from(&[Size(k.to_owned()), Size(v.to_owned())])))), + Some((k, v)) => Ok(Calcit::List(TernaryTreeList::from(&[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 9cd02859..c7dd80e7 100644 --- a/src/builtins/meta.rs +++ b/src/builtins/meta.rs @@ -49,7 +49,7 @@ pub fn type_of(xs: &CalcitItems) -> Result { } pub fn recur(xs: &CalcitItems) -> Result { - Ok(Calcit::Recur(Box::new(xs.to_owned()))) + Ok(Calcit::Recur(xs.to_owned())) } pub fn format_to_lisp(xs: &CalcitItems) -> Result { @@ -72,7 +72,7 @@ fn transform_code_to_cirru(x: &Calcit) -> Cirru { match x { Calcit::List(ys) => { let mut xs: Vec = Vec::with_capacity(ys.len()); - for y in &**ys { + for y in ys { xs.push(transform_code_to_cirru(y)); } Cirru::List(xs) @@ -295,7 +295,7 @@ 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 method_args = invoke_args.skip(1)?.unshift(value); + let method_args = invoke_args.drop_left().unshift(value); match &values[idx] { // dirty copy... diff --git a/src/builtins/refs.rs b/src/builtins/refs.rs index 021e6eda..59b0136f 100644 --- a/src/builtins/refs.rs +++ b/src/builtins/refs.rs @@ -4,8 +4,8 @@ use std::collections::HashMap; use std::sync::{Arc, RwLock}; use cirru_edn::EdnKwd; +use im_ternary_tree::TernaryTreeList; -use crate::primes::finger_list::{FingerList, Size}; use crate::primes::{Calcit, CalcitErr, CalcitItems, CalcitScope}; use crate::{call_stack::CallStackList, runner}; @@ -35,7 +35,7 @@ fn modify_ref(path: Arc, v: Calcit, call_stack: &CallStackList) -> Result<( Calcit::Fn { def_ns, scope, args, body, .. } => { - let values = FingerList::from(&[Size(v.to_owned()), Size(prev.to_owned())]); + let values = TernaryTreeList::from(&[v.to_owned(), prev.to_owned()]); runner::run_fn(&values, scope, args, body, def_ns.to_owned(), call_stack)?; } a => { diff --git a/src/builtins/sets.rs b/src/builtins/sets.rs index 9c8dd386..a76d79db 100644 --- a/src/builtins/sets.rs +++ b/src/builtins/sets.rs @@ -1,4 +1,5 @@ -use crate::primes::finger_list::FingerList; +use im_ternary_tree::TernaryTreeList; + use crate::primes::{Calcit, CalcitErr, CalcitItems}; pub fn new_set(xs: &CalcitItems) -> Result { @@ -80,11 +81,11 @@ 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 = FingerList::new_empty(); + let mut ys: CalcitItems = TernaryTreeList::Empty; for x in xs { - ys = ys.push(x.to_owned()); + ys = ys.push_right(x.to_owned()); } - Ok(Calcit::List(Box::new(ys))) + Ok(Calcit::List(ys)) } Some(a) => CalcitErr::err_str(format!("&set:to-list expected a set: {}", a)), None => CalcitErr::err_str("&set:to-list expected 1 argument, got none"), diff --git a/src/builtins/strings.rs b/src/builtins/strings.rs index 1a79057c..dbb8c462 100644 --- a/src/builtins/strings.rs +++ b/src/builtins/strings.rs @@ -1,8 +1,9 @@ use std::char; use std::cmp::Ordering; +use im_ternary_tree::TernaryTreeList; + use crate::primes; -use crate::primes::finger_list::FingerList; use crate::primes::{Calcit, CalcitErr, CalcitItems, CrListWrap}; use crate::util::number::f64_to_usize; @@ -61,13 +62,13 @@ 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 = FingerList::new_empty(); + let mut ys: CalcitItems = TernaryTreeList::Empty; for p in pieces { if !p.is_empty() { - ys = ys.push(Calcit::Str(p.to_owned().into())); + ys = ys.push_right(Calcit::Str(p.to_owned().into())); } } - Ok(Calcit::List(Box::new(ys))) + Ok(Calcit::List(ys)) } (Some(a), Some(b)) => CalcitErr::err_str(format!("split expected 2 strings, got: {} {}", a, b)), (_, _) => CalcitErr::err_str("split expected 2 arguments, got nothing"), @@ -99,11 +100,11 @@ pub fn split_lines(xs: &CalcitItems) -> Result { match xs.get(0) { Some(Calcit::Str(s)) => { let lines = s.split('\n'); - let mut ys = FingerList::new_empty(); + let mut ys = TernaryTreeList::Empty; for line in lines { - ys = ys.push(Calcit::Str(line.to_owned().into())); + ys = ys.push_right(Calcit::Str(line.to_owned().into())); } - Ok(Calcit::List(Box::new(ys))) + Ok(Calcit::List(ys)) } Some(a) => CalcitErr::err_str(format!("split-lines expected 1 string, got: {}", a)), _ => CalcitErr::err_str("split-lines expected 1 argument, got nothing"), diff --git a/src/builtins/syntax.rs b/src/builtins/syntax.rs index ec68035c..5e27a881 100644 --- a/src/builtins/syntax.rs +++ b/src/builtins/syntax.rs @@ -6,9 +6,10 @@ use std::cell::RefCell; use std::collections::HashSet; use std::sync::Arc; +use im_ternary_tree::TernaryTreeList; + use crate::builtins; use crate::call_stack::CallStackList; -use crate::primes::finger_list::{FingerList, Size}; use crate::primes::{gen_core_id, Calcit, CalcitErr, CalcitItems, CalcitScope}; use crate::runner; @@ -19,7 +20,7 @@ pub fn defn(expr: &CalcitItems, scope: &CalcitScope, file_ns: Arc) -> Resul def_ns: file_ns.to_owned(), id: gen_core_id(), scope: Arc::new(scope.to_owned()), - args: get_raw_args(xs)?, + args: Arc::new(get_raw_args(xs)?), body: Arc::new(expr.skip(2)?), }), (Some(a), Some(b)) => CalcitErr::err_str(format!("invalid args type for defn: {} , {}", a, b)), @@ -33,14 +34,11 @@ pub fn defmacro(expr: &CalcitItems, _scope: &CalcitScope, def_ns: Arc) -> R name: s.to_owned(), def_ns: def_ns.to_owned(), id: gen_core_id(), - args: get_raw_args(xs)?, + args: Arc::new(get_raw_args(xs)?), body: Arc::new(expr.skip(2)?), }), (Some(a), Some(b)) => CalcitErr::err_str(format!("invalid structure for defmacro: {} {}", a, b)), - _ => CalcitErr::err_str(format!( - "invalid structure for defmacro: {}", - Calcit::List(Box::new(expr.to_owned())) - )), + _ => CalcitErr::err_str(format!("invalid structure for defmacro: {}", Calcit::List(expr.to_owned()))), } } @@ -93,7 +91,7 @@ pub fn eval(expr: &CalcitItems, scope: &CalcitScope, file_ns: Arc, call_sta pub fn syntax_let(expr: &CalcitItems, scope: &CalcitScope, file_ns: Arc, call_stack: &CallStackList) -> Result { match expr.get(0) { - Some(Calcit::Nil) => runner::evaluate_lines(&expr.skip(1)?, scope, file_ns.to_owned(), call_stack), + Some(Calcit::Nil) => runner::evaluate_lines(&expr.drop_left(), scope, file_ns.to_owned(), call_stack), Some(Calcit::List(xs)) if xs.len() == 2 => { let mut body_scope = scope.to_owned(); match (&xs[0], &xs[1]) { @@ -103,7 +101,7 @@ pub fn syntax_let(expr: &CalcitItems, scope: &CalcitScope, file_ns: Arc, ca } (a, _) => return CalcitErr::err_str(format!("invalid binding name: {}", a)), } - runner::evaluate_lines(&expr.skip(1)?, &body_scope, file_ns.to_owned(), call_stack) + runner::evaluate_lines(&expr.drop_left(), &body_scope, file_ns.to_owned(), call_stack) } Some(Calcit::List(xs)) => CalcitErr::err_str(format!("invalid length: {:?}", xs)), Some(_) => CalcitErr::err_str(format!("invalid node for &let: {:?}", expr)), @@ -146,23 +144,23 @@ fn replace_code(c: &Calcit, scope: &CalcitScope, file_ns: Arc, call_stack: (Some(Calcit::Symbol { sym, .. }), Some(expr)) if &**sym == "~@" => { let ret = runner::evaluate_expr(expr, scope, file_ns.to_owned(), call_stack)?; match ret { - Calcit::List(zs) => Ok(SpanResult::Range(zs)), + Calcit::List(zs) => Ok(SpanResult::Range(Box::new(zs))), _ => Err(CalcitErr::use_str(format!("unknown result from unquote-slice: {}", ret))), } } (_, _) => { - let mut ret: FingerList = FingerList::new_empty(); - for y in &**ys { + let mut ret: TernaryTreeList = TernaryTreeList::Empty; + for y in ys { match replace_code(y, scope, file_ns.to_owned(), call_stack)? { - SpanResult::Single(z) => ret = ret.push(z), + SpanResult::Single(z) => ret = ret.push_right(z), SpanResult::Range(pieces) => { for piece in &*pieces { - ret = ret.push(piece.to_owned()); + ret = ret.push_right(piece.to_owned()); } } } } - Ok(SpanResult::Single(Calcit::List(Box::new(ret)))) + Ok(SpanResult::Single(Calcit::List(ret))) } }, _ => Ok(SpanResult::Single(c.to_owned())), @@ -172,7 +170,7 @@ fn replace_code(c: &Calcit, scope: &CalcitScope, file_ns: Arc, call_stack: pub fn has_unquote(xs: &Calcit) -> bool { match xs { Calcit::List(ys) => { - for y in &**ys { + for y in ys { if has_unquote(y) { return true; } @@ -202,7 +200,7 @@ pub fn macroexpand( match v { Calcit::Macro { def_ns, args, body, .. } => { // mutable operation - let mut rest_nodes = xs.skip(1)?; + let mut rest_nodes = xs.drop_left(); // println!("macro: {:?} ... {:?}", args, rest_nodes); // keep expanding until return value is not a recur loop { @@ -210,7 +208,7 @@ pub fn macroexpand( let v = runner::evaluate_lines(&body, &body_scope, def_ns.to_owned(), call_stack)?; match v { Calcit::Recur(rest_code) => { - rest_nodes = (*rest_code).to_owned(); + rest_nodes = rest_code.to_owned(); } _ => return Ok(v), } @@ -243,7 +241,7 @@ pub fn macroexpand_1( let v = runner::evaluate_expr(&xs[0], scope, file_ns.to_owned(), call_stack)?; match v { Calcit::Macro { def_ns, args, body, .. } => { - let body_scope = runner::bind_args(&args, &xs.skip(1)?, scope, call_stack)?; + let body_scope = runner::bind_args(&args, &xs.drop_left(), scope, call_stack)?; runner::evaluate_lines(&body, &body_scope, def_ns, call_stack) } _ => Ok(quoted_code), @@ -274,7 +272,7 @@ pub fn macroexpand_all( match v { Calcit::Macro { def_ns, args, body, .. } => { // mutable operation - let mut rest_nodes = xs.skip(1)?; + let mut rest_nodes = xs.drop_left(); let check_warnings: &RefCell> = &RefCell::new(vec![]); // println!("macro: {:?} ... {:?}", args, rest_nodes); // keep expanding until return value is not a recur @@ -283,7 +281,7 @@ pub fn macroexpand_all( let v = runner::evaluate_lines(&body, &body_scope, def_ns.to_owned(), call_stack)?; match v { Calcit::Recur(rest_code) => { - rest_nodes = (*rest_code).to_owned(); + rest_nodes = rest_code.to_owned(); } _ => { let (resolved, _v) = @@ -335,10 +333,10 @@ pub fn call_try(expr: &CalcitItems, scope: &CalcitScope, file_ns: Arc, call Calcit::Fn { def_ns, scope, args, body, .. } => { - let values = FingerList::from(&[Size(err_data)]); + let values = TernaryTreeList::from(&[err_data]); runner::run_fn(&values, &scope, &args, &body, def_ns, call_stack) } - Calcit::Proc(proc) => builtins::handle_proc(&proc, &FingerList::from(&[Size(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 6b928bbb..435d1cb6 100644 --- a/src/call_stack.rs +++ b/src/call_stack.rs @@ -13,7 +13,7 @@ pub struct CalcitStack { pub ns: Arc, pub def: Arc, pub code: Calcit, // built in functions may not contain code - pub args: CalcitItems, + pub args: Box, pub kind: StackKind, } @@ -49,7 +49,7 @@ pub fn extend_call_stack( ns: ns.to_owned(), def: def.to_owned(), code: code.to_owned(), - args: args.to_owned(), + args: Box::new(args.to_owned()), kind, }) } @@ -78,7 +78,7 @@ pub fn display_stack(failure: &str, stack: &CallStackList) -> Result<(), String> info.insert(Edn::kwd("def"), Edn::str(format!("{}/{}", s.ns, s.def))); info.insert(Edn::kwd("code"), Edn::Quote(cirru::calcit_to_cirru(&s.code)?)); let mut args: Vec = Vec::with_capacity(s.args.len()); - for a in &s.args { + for a in &*s.args { args.push(edn::calcit_to_edn(a)?); } info.insert(Edn::kwd("args"), Edn::List(args)); diff --git a/src/codegen/emit_js.rs b/src/codegen/emit_js.rs index 2cfe687a..5fde78cf 100644 --- a/src/codegen/emit_js.rs +++ b/src/codegen/emit_js.rs @@ -2,6 +2,8 @@ pub mod gen_stack; mod internal_states; mod snippets; +use im_ternary_tree::TernaryTreeList; + use std::cell::RefCell; use std::collections::{BTreeMap, HashMap, HashSet}; use std::fs; @@ -15,7 +17,6 @@ use crate::builtins::syntax::get_raw_args; use crate::builtins::{is_js_syntax_procs, is_proc_name}; use crate::call_stack::StackKind; use crate::primes; -use crate::primes::finger_list::FingerList; use crate::primes::{Calcit, CalcitItems, CalcitSyntax, ImportRule, SymbolResolved::*}; use crate::program; use crate::util::string::{has_ns_part, matches_digits, matches_js_var, wrap_js_str}; @@ -169,7 +170,7 @@ fn quote_to_js(xs: &Calcit, var_prefix: &str, keywords: &RefCell>) - Calcit::Proc(p) => Ok(format!("new {}CalcitSymbol({})", var_prefix, escape_cirru_str(p))), Calcit::List(ys) => { let mut chunk = String::from(""); - for y in &**ys { + for y in ys { if !chunk.is_empty() { chunk.push_str(", "); } @@ -285,7 +286,7 @@ fn gen_call_code( } let head = ys[0].to_owned(); - let body = ys.skip(1)?; + let body = ys.drop_left(); match &head { Calcit::Syntax(s, ..) => { match s { @@ -302,7 +303,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(), &FingerList::new_empty()); + 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"), @@ -327,7 +328,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(), &FingerList::new_empty()); + 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!( @@ -342,7 +343,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 = body.skip(2)?; - gen_stack::push_call_stack(ns, sym, StackKind::Codegen, xs.to_owned(), &FingerList::new_empty()); + gen_stack::push_call_stack(ns, sym, StackKind::Codegen, xs.to_owned(), &TernaryTreeList::Empty); let ret = gen_js_func(sym, &get_raw_args(ys)?, &func_body, ns, false, local_defs, file_imports, keywords); gen_stack::pop_call_stack(); match ret { @@ -357,7 +358,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(), &FingerList::new_empty()); + 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 ")), @@ -388,7 +389,7 @@ fn gen_call_code( } Calcit::Symbol { sym: s, .. } | Calcit::Proc(s) => { match &**s { - ";" => Ok(format!("(/* {} */ null)", Calcit::List(Box::new(body)))), + ";" => Ok(format!("(/* {} */ null)", Calcit::List(body))), "raise" => { // not core syntax, but treat as macro for better debugging experience @@ -416,7 +417,7 @@ fn gen_call_code( "echo" | "println" => { // not core syntax, but treat as macro for better debugging experience - let args = ys.skip(1)?; + let args = ys.drop_left(); let args_code = gen_args_code(&args, ns, local_defs, file_imports, keywords)?; Ok(format!("console.log({}printable({}))", proc_prefix, args_code)) } @@ -433,7 +434,7 @@ fn gen_call_code( } "new" => match body.get(0) { Some(ctor) => { - let args = body.skip(1)?; + let args = body.drop_left(); let args_code = gen_args_code(&args, ns, local_defs, file_imports, keywords)?; Ok(format!( "{}new {}({})", @@ -511,7 +512,7 @@ fn gen_call_code( if matches_js_var(name) { match body.get(0) { Some(obj) => { - let args = body.skip(1)?; + let args = body.drop_left(); let args_code = gen_args_code(&args, ns, local_defs, file_imports, keywords)?; Ok(format!( "{}{}.{}({})", @@ -531,7 +532,7 @@ fn gen_call_code( let name = s.strip_prefix('.').unwrap(); match body.get(0) { Some(obj) => { - let args = body.skip(1)?; + let args = body.drop_left(); let args_code = gen_args_code(&args, ns, local_defs, file_imports, keywords)?; Ok(format!( "{}{}invoke_method({})({},{})", @@ -696,7 +697,7 @@ fn gen_let_code( return Err(format!("&let expected body, but got empty, {}", xs.lisp_str())); } let pair = let_def_body[0].to_owned(); - let content = let_def_body.skip(1)?; + let content = let_def_body.drop_left(); match &pair { Calcit::Nil => { @@ -754,7 +755,7 @@ fn gen_let_code( Calcit::List(ys) if ys.len() > 2 => match (&ys[0], &ys[1]) { (Calcit::Syntax(sym, _ns), Calcit::List(zs)) if sym == &CalcitSyntax::CoreLet && zs.len() == 2 => match &zs[0] { Calcit::Symbol { sym: s2, .. } if !scoped_defs.contains(s2) => { - let_def_body = ys.skip(1)?; + let_def_body = ys.drop_left(); continue; } _ => (), @@ -926,7 +927,7 @@ fn uses_recur(xs: &Calcit) -> bool { Some(Calcit::Syntax(syn, _)) if syn == &CalcitSyntax::Defn => false, Some(Calcit::Symbol { sym, .. }) if &**sym == "defn" => false, _ => { - for y in &**ys { + for y in ys { if uses_recur(y) { return true; } @@ -940,7 +941,7 @@ fn uses_recur(xs: &Calcit) -> bool { fn gen_js_func( name: &str, - args: &Vec>, + args: &[Arc], raw_body: &CalcitItems, ns: &str, exported: bool, @@ -1001,7 +1002,7 @@ fn gen_js_func( snippets::tmpl_args_exact(args_count) }; - let mut body: CalcitItems = FingerList::new_empty(); + let mut body: CalcitItems = TernaryTreeList::Empty; let mut async_prefix: String = String::from(""); for line in raw_body { @@ -1015,7 +1016,7 @@ fn gen_js_func( } } } - body = body.push(line.to_owned()); + body = body.push_right(line.to_owned()); } if !body.is_empty() && uses_recur(&body[body.len() - 1]) { @@ -1055,7 +1056,7 @@ fn gen_js_func( } /// this is a very rough implementation for now -fn hinted_async(xs: &FingerList) -> bool { +fn hinted_async(xs: &TernaryTreeList) -> bool { for x in xs { match x { Calcit::Symbol { sym, .. } if &**sym == "async" => return true, @@ -1078,7 +1079,7 @@ fn contains_symbol(xs: &Calcit, y: &str) -> bool { false } Calcit::List(zs) => { - for z in &**zs { + for z in zs { if contains_symbol(z, y) { return true; } @@ -1238,14 +1239,14 @@ pub fn emit_js(entry_ns: &str, emit_path: &str) -> Result<(), String> { body: code, .. } => { - gen_stack::push_call_stack(def_ns, name, StackKind::Codegen, f.to_owned(), &FingerList::new_empty()); + 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(), &FingerList::new_empty()); + 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 d48eda23..ec665add 100644 --- a/src/codegen/emit_js/gen_stack.rs +++ b/src/codegen/emit_js/gen_stack.rs @@ -13,7 +13,7 @@ pub fn push_call_stack(ns: &str, def: &str, kind: StackKind, code: Calcit, args: ns: ns.into(), def: def.into(), code, - args: args.to_owned(), + args: Box::new(args.to_owned()), kind, }) } diff --git a/src/codegen/gen_ir.rs b/src/codegen/gen_ir.rs index c1e011cc..4e1394ff 100644 --- a/src/codegen/gen_ir.rs +++ b/src/codegen/gen_ir.rs @@ -197,7 +197,7 @@ fn dump_code(code: &Calcit) -> Edn { Calcit::Thunk(code, _) => dump_code(code), Calcit::List(xs) => { let mut ys: Vec = Vec::with_capacity(xs.len()); - for x in &**xs { + for x in xs { ys.push(dump_code(x)); } Edn::List(ys) @@ -214,9 +214,9 @@ fn dump_items_code(xs: &CalcitItems) -> Edn { Edn::List(ys) } -fn dump_args_code(xs: &Vec>) -> Edn { +fn dump_args_code(xs: &[Arc]) -> Edn { let mut ys: Vec = Vec::with_capacity(xs.len()); - for x in &**xs { + for x in xs { ys.push(Edn::sym(&*x.to_owned())); } Edn::List(ys) diff --git a/src/data/cirru.rs b/src/data/cirru.rs index 20e1c8b1..c09ca480 100644 --- a/src/data/cirru.rs +++ b/src/data/cirru.rs @@ -1,8 +1,8 @@ use std::sync::Arc; use cirru_parser::Cirru; +use im_ternary_tree::TernaryTreeList; -use crate::primes::finger_list::{FingerList, Size}; use crate::primes::Calcit; /// code is CirruNode, and this function parse code(rather than data) @@ -45,7 +45,7 @@ pub fn code_to_calcit(xs: &Cirru, ns: Arc, def: Arc) -> Result Ok(Calcit::Number(n as f64)), Err(e) => Err(format!("failed to parse hex: {} => {:?}", s, e)), }, - '\'' if s.len() > 1 => Ok(Calcit::List(Box::new(FingerList::new2( + '\'' if s.len() > 1 => Ok(Calcit::List(TernaryTreeList::from(&[ Calcit::Symbol { sym: String::from("quote").into(), ns: ns.to_owned(), @@ -58,9 +58,9 @@ pub fn code_to_calcit(xs: &Cirru, ns: Arc, def: Arc) -> Result 2 => Ok(Calcit::List(Box::new(FingerList::new2( + '~' if s.starts_with("~@") && s.chars().count() > 2 => Ok(Calcit::List(TernaryTreeList::from(&[ Calcit::Symbol { sym: String::from("~@").into(), ns: ns.to_owned(), @@ -73,8 +73,8 @@ pub fn code_to_calcit(xs: &Cirru, ns: Arc, def: Arc) -> Result 1 && !s.starts_with("~@") => Ok(Calcit::List(Box::new(FingerList::new2( + ]))), + '~' if s.chars().count() > 1 && !s.starts_with("~@") => Ok(Calcit::List(TernaryTreeList::from(&[ Calcit::Symbol { sym: String::from("~").into(), ns: ns.to_owned(), @@ -87,8 +87,8 @@ pub fn code_to_calcit(xs: &Cirru, ns: Arc, def: Arc) -> Result Ok(Calcit::List(Box::new(FingerList::new2( + ]))), + '@' => Ok(Calcit::List(TernaryTreeList::from(&[ Calcit::Symbol { sym: String::from("deref").into(), ns: ns.to_owned(), @@ -101,7 +101,7 @@ pub fn code_to_calcit(xs: &Cirru, ns: Arc, def: Arc) -> Result { if let Ok(f) = s.parse::() { @@ -118,18 +118,18 @@ pub fn code_to_calcit(xs: &Cirru, ns: Arc, def: Arc) -> Result { - let mut zs: Vec> = Vec::with_capacity(ys.len()); + let mut zs: Vec = Vec::with_capacity(ys.len()); for y in ys { match code_to_calcit(y, ns.to_owned(), def.to_owned()) { Ok(v) => { if !is_comment(&v) { - zs.push(Size(v.to_owned())); + zs.push(v.to_owned()); } } Err(e) => return Err(e), } } - Ok(Calcit::List(Box::new(FingerList::from(&zs)))) + Ok(Calcit::List(TernaryTreeList::from(&zs))) } } } @@ -139,11 +139,11 @@ pub fn cirru_to_calcit(xs: &Cirru) -> Calcit { match xs { Cirru::Leaf(s) => Calcit::Str((**s).into()), Cirru::List(ys) => { - let mut zs: Vec> = Vec::with_capacity(ys.len()); + let mut zs: Vec = Vec::with_capacity(ys.len()); for y in ys { - zs.push(Size(cirru_to_calcit(y))); + zs.push(cirru_to_calcit(y)); } - Calcit::List(Box::new(FingerList::from(&zs))) + Calcit::List(TernaryTreeList::from(&zs)) } } } @@ -157,7 +157,7 @@ pub fn calcit_data_to_cirru(xs: &Calcit) -> Result { Calcit::Str(s) => Ok(Cirru::Leaf((**s).into())), Calcit::List(ys) => { let mut zs: Vec = Vec::with_capacity(ys.len()); - for y in &**ys { + for y in ys { match calcit_data_to_cirru(y) { Ok(v) => { zs.push(v); @@ -193,7 +193,7 @@ pub fn calcit_to_cirru(x: &Calcit) -> Result { Calcit::Keyword(s) => Ok(Cirru::leaf(format!(":{}", s))), // TODO performance Calcit::List(xs) => { let mut ys: Vec = Vec::with_capacity(xs.len()); - for x in &**xs { + for x in xs { ys.push(calcit_to_cirru(x)?); } Ok(Cirru::List(ys)) diff --git a/src/data/edn.rs b/src/data/edn.rs index fc092030..f630a16a 100644 --- a/src/data/edn.rs +++ b/src/data/edn.rs @@ -2,9 +2,10 @@ use std::collections::hash_map::HashMap; use std::collections::hash_set::HashSet; use std::sync::Arc; +use im_ternary_tree::TernaryTreeList; + use crate::data::cirru; use crate::primes; -use crate::primes::finger_list::FingerList; use crate::primes::Calcit; use cirru_edn::{Edn, EdnKwd}; @@ -20,7 +21,7 @@ pub fn calcit_to_edn(x: &Calcit) -> Result { Calcit::Symbol { sym, .. } => Ok(Edn::Symbol((**sym).into())), Calcit::List(xs) => { let mut ys: Vec = Vec::with_capacity(xs.len()); - for x in &**xs { + for x in xs { ys.push(calcit_to_edn(x)?); } Ok(Edn::List(ys)) @@ -100,11 +101,11 @@ pub fn edn_to_calcit(x: &Edn) -> Calcit { ), Edn::Tuple(pair) => Calcit::Tuple(Arc::new(edn_to_calcit(&pair.0)), Arc::new(edn_to_calcit(&pair.1))), Edn::List(xs) => { - let mut ys: primes::CalcitItems = FingerList::new_empty(); + let mut ys: primes::CalcitItems = TernaryTreeList::Empty; for x in xs { - ys = ys.push(edn_to_calcit(x)) + ys = ys.push_right(edn_to_calcit(x)) } - Calcit::List(Box::new(ys)) + Calcit::List(ys) } Edn::Set(xs) => { let mut ys: rpds::HashTrieSetSync = rpds::HashTrieSet::new_sync(); diff --git a/src/primes.rs b/src/primes.rs index 7fefddab..d19bb6c2 100644 --- a/src/primes.rs +++ b/src/primes.rs @@ -1,4 +1,3 @@ -pub mod finger_list; mod syntax_name; use core::cmp::Ord; @@ -10,8 +9,8 @@ use std::hash::{Hash, Hasher}; use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; use std::sync::Arc; -use crate::primes::finger_list::FingerList; use cirru_edn::EdnKwd; +use im_ternary_tree::TernaryTreeList; static ID_GEN: AtomicUsize = AtomicUsize::new(0); @@ -40,11 +39,11 @@ pub enum ImportRule { // scope pub type CalcitScope = rpds::HashTrieMapSync, Calcit>; -pub type CalcitItems = FingerList; +pub type CalcitItems = TernaryTreeList; /// special types wraps vector of calcit data for displaying #[derive(Debug, Clone, PartialEq, PartialOrd)] -pub struct CrListWrap(pub FingerList); +pub struct CrListWrap(pub TernaryTreeList); #[derive(Debug, Clone)] pub enum Calcit { @@ -67,26 +66,26 @@ pub enum Calcit { /// to be used by FFIs Buffer(Vec), /// not for data, but for recursion - Recur(Box), - List(Box), + Recur(CalcitItems), + List(CalcitItems), Set(rpds::HashTrieSetSync), Map(rpds::HashTrieMapSync), Record(EdnKwd, Arc>, Arc>), // usize of keyword id Proc(Arc), Macro { - name: Arc, // name - def_ns: Arc, // ns - id: Arc, // an id - args: Vec>, // args - body: Arc, // body + name: Arc, // name + def_ns: Arc, // ns + id: Arc, // an id + args: Arc>>, // args + body: Arc, // body }, Fn { name: Arc, // name def_ns: Arc, // ns id: Arc, // an id scope: Arc, - args: Vec>, // args - body: Arc, // body + args: Arc>>, // args + body: Arc, // body }, Syntax(CalcitSyntax, Arc), // name, ns... notice that `ns` is a meta info } @@ -137,14 +136,14 @@ impl fmt::Display for Calcit { } Calcit::Recur(xs) => { f.write_str("(&recur")?; - for x in &**xs { + for x in xs { f.write_str(&format!(" {}", x))?; } f.write_str(")") } Calcit::List(xs) => { f.write_str("([]")?; - for x in &**xs { + for x in xs { f.write_str(&format!(" {}", x))?; } f.write_str(")") @@ -235,7 +234,7 @@ fn buffer_bit_hex(n: u8) -> String { /// special types wraps vector of calcit data for displaying impl fmt::Display for CrListWrap { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(&format_to_lisp(&Calcit::List(Box::new(self.0.to_owned())))) // TODO performance + f.write_str(&format_to_lisp(&Calcit::List(self.0.to_owned()))) // TODO performance } } diff --git a/src/primes/finger_list.rs b/src/primes/finger_list.rs deleted file mode 100644 index bc502cc0..00000000 --- a/src/primes/finger_list.rs +++ /dev/null @@ -1,260 +0,0 @@ -use std::fmt; - -use core::cmp::Ord; -use std::cmp::Eq; -use std::cmp::Ordering; -use std::cmp::Ordering::*; -use std::fmt::{Debug, Display}; -use std::hash::{Hash, Hasher}; - -use fingertrees::measure::Measured; -use fingertrees::monoid::Sum; -use std::ops::Index; - -use fingertrees::{ArcRefs, FingerTree}; - -pub use fingertrees::measure::Size; - -#[derive(Debug, Clone)] -pub struct FingerList(FingerTree>) -where - T: Clone; - -impl fmt::Display for FingerList -where - T: Debug + Clone + Hash + Ord + Display, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("(&finger-list ")?; - - for x in self.into_iter() { - f.write_str(" ")?; - f.write_str(&x.to_string())?; - } - - f.write_str(")") - } -} - -impl Hash for FingerList -where - T: Debug + Clone + Hash + Ord + Display, -{ - fn hash(&self, _state: &mut H) - where - H: Hasher, - { - for item in self.iter() { - item.hash(_state); - } - } -} - -impl Ord for FingerList -where - T: Debug + Clone + Hash + Ord + Display, -{ - fn cmp(&self, other: &Self) -> Ordering { - if self.len() == other.len() { - for idx in 0..self.len() { - let r = self[idx].cmp(&other[idx]); - if r == Equal { - continue; - } else { - return r; - } - } - Equal - } else { - self.len().cmp(&other.len()) - } - } -} - -impl PartialOrd for FingerList -where - T: Debug + Clone + Ord + Display + Hash, -{ - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Eq for FingerList where T: Debug + Clone + Ord + Display + Hash {} - -impl PartialEq for FingerList -where - T: Debug + Clone + Ord + Display + Hash, -{ - fn eq(&self, other: &Self) -> bool { - if self.len() == other.len() { - for idx in 0..self.len() { - if self[idx] != other[idx] { - return false; - } - } - true - } else { - false - } - } -} - -impl<'a, T> Index for FingerList -where - T: Clone + Eq + PartialEq + Debug + Ord + PartialOrd + Hash, -{ - type Output = T; - - fn index<'b>(&self, idx: usize) -> &Self::Output { - match self.0.find(|m| **m > idx) { - Some(value) => value, - None => unreachable!("out of bound"), - } - } -} - -impl FingerList -where - T: Debug + Clone + Ord + Display + Hash, -{ - pub fn get(&self, idx: usize) -> Option<&T> { - self.0.find(|m| **m > idx).map(|value| &**value) - } - - pub fn len(&self) -> usize { - match self.0.measure() { - Sum(s) => s, - } - } - - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } - - pub fn push(&self, item: T) -> Self { - let next = self.0.push_right(Size(item)); - Self(next) - } - pub fn rest(&self) -> Result { - let right = self.0.split_right(|measure| *measure > Sum(1)); - Ok(Self(right)) - } - - pub fn butlast(&self) -> Result { - let left = self.0.split_left(|measure| *measure > Sum(self.len() - 1)); - Ok(Self(left)) - } - pub fn unshift(&self, item: T) -> Self { - let next = self.0.push_left(Size(item)); - Self(next) - } - pub fn slice(&self, from: usize, to: usize) -> Result { - let right = self.0.split_right(|measure| *measure > Sum(from)); - let next = right.split_left(|measure| *measure > Sum(to - from)); - Ok(Self(next)) - } - pub fn reverse(&self) -> Self { - let mut xs: FingerTree> = FingerTree::new(); - for y in (&self.0).into_iter() { - xs = xs.push_left(y); - } - Self(xs) - } - - pub fn skip(&self, from: usize) -> Result { - let right = self.0.split_right(|measure| *measure > Sum(from)); - Ok(Self(right)) - } - - pub fn assoc(&self, from: usize, item: T) -> Result { - let left = self.0.split_left(|measure| *measure > Sum(from)); - let right = self.0.split_right(|measure| *measure > Sum(from + 1)); - Ok(Self(left.push_right(Size(item)).concat(&right).to_owned())) - } - - pub fn dissoc(&self, from: usize) -> Result { - let left = self.0.split_left(|measure| *measure > Sum(from)); - let right = self.0.split_right(|measure| *measure > Sum(from + 1)); - Ok(Self(left.concat(&right).to_owned())) - } - - pub fn assoc_before(&self, from: usize, item: T) -> Result { - let (left, right) = self.0.split(|measure| *measure > Sum(from)); - let next = right.push_left(Size(item)); - Ok(Self(left.concat(&next).to_owned())) - } - - pub fn assoc_after(&self, from: usize, item: T) -> Result { - let (left, right) = self.0.split(|measure| *measure > Sum(from + 1)); - let next = right.push_left(Size(item)); - Ok(Self(left.concat(&next).to_owned())) - } - - pub fn from(xs: &[Size]) -> Self { - Self(FingerTree::from(xs)) - } - - pub fn new_empty() -> Self { - Self(FingerTree::new()) - } - - pub fn new2(a: T, b: T) -> Self { - Self(FingerTree::new().push_right(Size(a)).push_right(Size(b))) - } - - pub fn new3(a: T, b: T, c: T) -> Self { - Self(FingerTree::new().push_right(Size(a)).push_right(Size(b)).push_right(Size(c))) - } - - pub fn iter(&self) -> FigerListRefIntoIterator { - FigerListRefIntoIterator { value: self, index: 0 } - } - - pub fn index_of(&self, item: &T) -> Option { - for (idx, y) in (&self.0).into_iter().enumerate() { - if item == &*y { - return Some(idx); - } - } - None - } -} - -// experimental code to turn `&FingerList<_>` into iterator -impl<'a, T> IntoIterator for &'a FingerList -where - T: Clone + Display + Eq + PartialEq + Debug + Ord + PartialOrd + Hash, -{ - type Item = &'a T; - type IntoIter = FigerListRefIntoIterator<'a, T>; - - fn into_iter(self) -> Self::IntoIter { - FigerListRefIntoIterator { value: self, index: 0 } - } -} - -pub struct FigerListRefIntoIterator<'a, T> -where - T: Clone + Display + Eq + PartialEq + Debug + Ord + PartialOrd + Hash, -{ - value: &'a FingerList, - index: usize, -} - -impl<'a, T> Iterator for FigerListRefIntoIterator<'a, T> -where - T: Clone + Display + Eq + PartialEq + Debug + Ord + PartialOrd + Hash, -{ - type Item = &'a T; - fn next(&mut self) -> Option { - if self.index < self.value.len() { - // println!("get: {} {}", self.value.format_inline(), self.index); - let idx = self.index; - self.index += 1; - Some(&self.value[idx]) - } else { - None - } - } -} diff --git a/src/runner.rs b/src/runner.rs index ba60b76b..46775165 100644 --- a/src/runner.rs +++ b/src/runner.rs @@ -1,12 +1,12 @@ pub mod preprocess; pub mod track; +use im_ternary_tree::TernaryTreeList; use std::sync::{Arc, RwLock}; use crate::builtins; use crate::builtins::is_proc_name; use crate::call_stack::{extend_call_stack, CallStackList, StackKind}; -use crate::primes::finger_list::{FingerList, Size}; use crate::primes::{Calcit, CalcitErr, CalcitItems, CalcitScope, CalcitSyntax, CrListWrap, SymbolResolved::*, CORE_NS}; use crate::program; use crate::util::string::has_ns_part; @@ -56,7 +56,7 @@ pub fn evaluate_expr(expr: &Calcit, scope: &CalcitScope, file_ns: Arc, call // println!("eval expr: {}", x); let v = evaluate_expr(x, scope, file_ns.to_owned(), call_stack)?; - let rest_nodes = xs.skip(1)?; + let rest_nodes = xs.drop_left(); let ret = match &v { Calcit::Proc(p) => { let values = evaluate_args(&rest_nodes, scope, file_ns.to_owned(), call_stack)?; @@ -137,7 +137,7 @@ pub fn evaluate_expr(expr: &Calcit, scope: &CalcitScope, file_ns: Arc, call let code = evaluate_lines(body, &body_scope, def_ns.to_owned(), &next_stack)?; match code { Calcit::Recur(ys) => { - current_values = ys.to_owned(); + current_values = Box::new(ys.to_owned()); } _ => { // println!("gen code: {} {}", x, &code.lisp_str())); @@ -170,7 +170,7 @@ pub fn evaluate_expr(expr: &Calcit, scope: &CalcitScope, file_ns: Arc, call call_stack, )), a => Err(CalcitErr::use_msg_stack( - format!("cannot be used as operator: {} in {}", a, CrListWrap((**xs).to_owned())), + format!("cannot be used as operator: {} in {}", a, CrListWrap(xs.to_owned())), call_stack, )), }; @@ -285,7 +285,7 @@ fn eval_symbol_from_program(sym: &str, ns: &str, call_stack: &CallStackList) -> pub fn run_fn( values: &CalcitItems, scope: &CalcitScope, - args: &Vec>, + args: &[Arc], body: &CalcitItems, file_ns: Arc, call_stack: &CallStackList, @@ -296,7 +296,7 @@ pub fn run_fn( let v = evaluate_lines(body, &body_scope, file_ns.to_owned(), call_stack)?; match v { Calcit::Recur(xs) => { - current_values = xs.to_owned(); + current_values = Box::new(xs.to_owned()); } result => return Ok(result), } @@ -306,7 +306,7 @@ pub fn run_fn( /// create new scope by writing new args /// notice that `&` is a mark for spreading, `?` for optional arguments pub fn bind_args( - args: &Vec>, + args: &[Arc], values: &CalcitItems, base_scope: &CalcitScope, call_stack: &CallStackList, @@ -348,11 +348,11 @@ pub fn bind_args( "&" => return Err(CalcitErr::use_msg_stack(format!("invalid & in args: {:?}", args), call_stack)), "?" => return Err(CalcitErr::use_msg_stack(format!("invalid ? in args: {:?}", args), call_stack)), _ => { - let mut chunk: CalcitItems = FingerList::new_empty(); + let mut chunk: CalcitItems = TernaryTreeList::Empty; while let Some(v) = values_pop_front() { - chunk = chunk.push(v.to_owned()); + chunk = chunk.push_right(v.to_owned()); } - scope.insert_mut(sym.to_owned(), Calcit::List(Box::new(chunk))); + scope.insert_mut(sym.to_owned(), Calcit::List(chunk)); if !is_args_empty() { return Err(CalcitErr::use_msg_stack( format!("extra args `{:?}` after spreading in `{:?}`", collected_args, args,), @@ -422,7 +422,7 @@ pub fn evaluate_args( file_ns: Arc, call_stack: &CallStackList, ) -> Result { - let mut ret: Vec> = Vec::with_capacity(items.len()); + let mut ret: Vec = Vec::with_capacity(items.len()); let mut spreading = false; for item in items { match item { @@ -435,7 +435,7 @@ pub fn evaluate_args( if spreading { match v { Calcit::List(xs) => { - for x in &*xs { + for x in &xs { // extract thunk before calling functions let y = match x { Calcit::Thunk(code, v) => match v { @@ -444,7 +444,7 @@ pub fn evaluate_args( }, _ => x.to_owned(), }; - ret.push(Size(y.to_owned())); + ret.push(y.to_owned()); } spreading = false } @@ -464,10 +464,10 @@ pub fn evaluate_args( }, _ => v.to_owned(), }; - ret.push(Size(y)); + ret.push(y); } } } } - Ok(FingerList::from(&ret)) + Ok(TernaryTreeList::from(&ret)) } diff --git a/src/runner/preprocess.rs b/src/runner/preprocess.rs index 93a7e669..1161e6a3 100644 --- a/src/runner/preprocess.rs +++ b/src/runner/preprocess.rs @@ -2,7 +2,6 @@ use crate::{ builtins::{is_js_syntax_procs, is_proc_name}, call_stack::{extend_call_stack, CalcitStack, CallStackList, StackKind}, primes, - primes::finger_list::{FingerList, Size}, primes::{Calcit, CalcitErr, CalcitItems, CalcitSyntax, ImportRule, SymbolResolved::*}, program, runner, }; @@ -11,6 +10,8 @@ use std::cell::RefCell; use std::collections::HashSet; use std::sync::Arc; +use im_ternary_tree::TernaryTreeList; + /// only macro and func are cared about during preprocessing /// only used in preprocess defs fn pick_macro_fn(x: Calcit) -> Option { @@ -65,7 +66,7 @@ pub fn preprocess_ns_def( def.to_owned(), StackKind::Fn, code.to_owned(), - &FingerList::new_empty(), + &TernaryTreeList::Empty, ); let (resolved_code, _resolve_value) = preprocess_expr(&code, &HashSet::new(), ns.to_owned(), check_warnings, &next_stack)?; @@ -304,7 +305,7 @@ fn process_list_call( ) -> Result<(Calcit, Option), CalcitErr> { let head = &xs[0]; let (head_form, head_evaled) = preprocess_expr(head, scope_defs, file_ns.to_owned(), check_warnings, call_stack)?; - let args = xs.skip(1)?; + let args = xs.drop_left(); let def_name = grab_def_name(head); // println!( @@ -327,8 +328,8 @@ fn process_list_call( match (&head_form, &head_evaled) { (Calcit::Keyword(..), _) => { if args.len() == 1 { - let code = Calcit::List(Box::new(FingerList::from(&[ - Size(Calcit::Symbol { + let code = Calcit::List(TernaryTreeList::from(&[ + Calcit::Symbol { sym: String::from("get").into(), ns: String::from(primes::CORE_NS).into(), at_def: String::from(primes::GENERATED_DEF).into(), @@ -337,10 +338,10 @@ fn process_list_call( def: String::from("get").into(), rule: None, })), - }), - Size(args[0].to_owned()), - Size(head.to_owned()), - ]))); + }, + args[0].to_owned(), + head.to_owned(), + ])); preprocess_expr(&code, scope_defs, file_ns.to_owned(), check_warnings, call_stack) } else { Err(CalcitErr::use_msg_stack(format!("{} expected single argument", head), call_stack)) @@ -361,7 +362,7 @@ fn process_list_call( // println!("eval macro: {}", primes::CrListWrap(xs.to_owned())); // println!("macro... {} {}", x, CrListWrap(current_values.to_owned())); - let code = Calcit::List(Box::new(xs.to_owned())); + let code = Calcit::List(xs.to_owned()); let next_stack = extend_call_stack(call_stack, def_ns.to_owned(), name.to_owned(), StackKind::Macro, code, &args); loop { @@ -371,7 +372,7 @@ fn process_list_call( let code = runner::evaluate_lines(body, &body_scope, def_ns.to_owned(), &next_stack)?; match code { Calcit::Recur(ys) => { - current_values = ys.to_owned(); + current_values = Box::new(ys.to_owned()); } _ => { // println!("gen code: {} {}", code, &code.lisp_str()); @@ -442,28 +443,28 @@ fn process_list_call( ) => { check_fn_args(f_args, &args, file_ns.to_owned(), f_name.to_owned(), def_name, check_warnings); let mut ys = Vec::with_capacity(args.len() + 1); - ys.push(Size(head_form)); + ys.push(head_form); for a in &args { let (form, _v) = preprocess_expr(a, scope_defs, file_ns.to_owned(), check_warnings, call_stack)?; - ys.push(Size(form)); + ys.push(form); } - Ok((Calcit::List(Box::new(FingerList::from(&ys))), None)) + Ok((Calcit::List(TernaryTreeList::from(&ys)), None)) } (_, _) => { let mut ys = Vec::with_capacity(args.len() + 1); - ys.push(Size(head_form)); + ys.push(head_form); for a in &args { let (form, _v) = preprocess_expr(a, scope_defs, file_ns.to_owned(), check_warnings, call_stack)?; - ys.push(Size(form)); + ys.push(form); } - Ok((Calcit::List(Box::new(FingerList::from(&ys))), None)) + Ok((Calcit::List(TernaryTreeList::from(&ys)), None)) } } } // detects arguments of top-level functions when possible fn check_fn_args( - defined_args: &Vec>, + defined_args: &[Arc], params: &CalcitItems, file_ns: Arc, f_name: Arc, @@ -551,12 +552,12 @@ pub fn preprocess_each_items( check_warnings: &RefCell>, call_stack: &CallStackList, ) -> Result { - let mut xs: CalcitItems = FingerList::from(&[Size(Calcit::Syntax(head.to_owned(), head_ns.to_owned()))]); + let mut xs: CalcitItems = TernaryTreeList::from(&[Calcit::Syntax(head.to_owned(), head_ns.to_owned())]); for a in args { let (form, _v) = preprocess_expr(a, scope_defs, file_ns.to_owned(), check_warnings, call_stack)?; - xs = xs.push(form); + xs = xs.push_right(form); } - Ok(Calcit::List(Box::new(xs))) + Ok(Calcit::List(xs)) } pub fn preprocess_defn( @@ -569,7 +570,7 @@ pub fn preprocess_defn( call_stack: &CallStackList, ) -> Result { // println!("defn args: {}", primes::CrListWrap(args.to_owned())); - let mut xs: CalcitItems = FingerList::from(&[Size(Calcit::Syntax(head.to_owned(), head_ns.to_owned()))]); + let mut xs: CalcitItems = TernaryTreeList::from(&[Calcit::Syntax(head.to_owned(), head_ns.to_owned())]); match (args.get(0), args.get(1)) { ( Some(Calcit::Symbol { @@ -582,20 +583,20 @@ pub fn preprocess_defn( ) => { let mut body_defs: HashSet> = scope_defs.to_owned(); - xs = xs.push(Calcit::Symbol { + xs = xs.push_right(Calcit::Symbol { sym: def_name.to_owned(), ns: def_name_ns.to_owned(), at_def: at_def.to_owned(), resolved: Some(Arc::new(ResolvedRaw)), }); - let mut zs: CalcitItems = FingerList::new_empty(); - for y in &**ys { + let mut zs: CalcitItems = TernaryTreeList::Empty; + for y in ys { match y { Calcit::Symbol { sym, ns: def_ns, at_def, .. } => { check_symbol(sym, args, check_warnings); - zs = zs.push(Calcit::Symbol { + zs = zs.push_right(Calcit::Symbol { sym: sym.to_owned(), ns: def_ns.to_owned(), at_def: at_def.to_owned(), @@ -614,15 +615,15 @@ pub fn preprocess_defn( } } } - xs = xs.push(Calcit::List(Box::new(zs))); + xs = xs.push_right(Calcit::List(zs)); for (idx, a) in args.into_iter().enumerate() { if idx >= 2 { let (form, _v) = preprocess_expr(a, &body_defs, file_ns.to_owned(), check_warnings, call_stack)?; - xs = xs.push(form); + xs = xs.push_right(form); } } - Ok(Calcit::List(Box::new(xs))) + Ok(Calcit::List(xs)) } (Some(a), Some(b)) => Err(CalcitErr::use_msg_stack( format!("defn/defmacro expected name and args: {} {}", a, b), @@ -657,7 +658,7 @@ pub fn preprocess_call_let( check_warnings: &RefCell>, call_stack: &CallStackList, ) -> Result { - let mut xs: CalcitItems = FingerList::from(&[Size(Calcit::Syntax(head.to_owned(), head_ns.to_owned()))]); + let mut xs: CalcitItems = TernaryTreeList::from(&[Calcit::Syntax(head.to_owned(), head_ns.to_owned())]); let mut body_defs: HashSet> = scope_defs.to_owned(); let binding = match args.get(0) { Some(Calcit::Nil) => Calcit::Nil, @@ -666,7 +667,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.to_owned(), check_warnings, call_stack)?; - Calcit::List(Box::new(FingerList::from(&[Size(ys[0].to_owned()), Size(form)]))) + Calcit::List(TernaryTreeList::from(&[ys[0].to_owned(), form])) } (a, b) => { return Err(CalcitErr::use_msg_stack( @@ -694,14 +695,14 @@ pub fn preprocess_call_let( )) } }; - xs = xs.push(binding); + xs = xs.push_right(binding); for (idx, a) in args.into_iter().enumerate() { if idx > 0 { let (form, _v) = preprocess_expr(a, &body_defs, file_ns.to_owned(), check_warnings, call_stack)?; - xs = xs.push(form); + xs = xs.push_right(form); } } - Ok(Calcit::List(Box::new(xs))) + Ok(Calcit::List(xs)) } pub fn preprocess_quote( @@ -711,11 +712,11 @@ pub fn preprocess_quote( _scope_defs: &HashSet>, _file_ns: Arc, ) -> Result { - let mut xs: CalcitItems = FingerList::from(&[Size(Calcit::Syntax(head.to_owned(), head_ns.to_owned()))]); + let mut xs: CalcitItems = TernaryTreeList::from(&[Calcit::Syntax(head.to_owned(), head_ns.to_owned())]); for a in args { - xs = xs.push(a.to_owned()); + xs = xs.push_right(a.to_owned()); } - Ok(Calcit::List(Box::new(xs))) + Ok(Calcit::List(xs)) } pub fn preprocess_defatom( @@ -727,13 +728,13 @@ pub fn preprocess_defatom( check_warnings: &RefCell>, call_stack: &CallStackList, ) -> Result { - let mut xs: CalcitItems = FingerList::from(&[Size(Calcit::Syntax(head.to_owned(), head_ns.to_owned()))]); + let mut xs: CalcitItems = TernaryTreeList::from(&[Calcit::Syntax(head.to_owned(), head_ns.to_owned())]); for a in args { // TODO let (form, _v) = preprocess_expr(a, scope_defs, file_ns.to_owned(), check_warnings, call_stack)?; - xs = xs.push(form.to_owned()); + xs = xs.push_right(form.to_owned()); } - Ok(Calcit::List(Box::new(xs))) + Ok(Calcit::List(xs)) } /// need to handle experssions inside unquote snippets @@ -746,9 +747,9 @@ pub fn preprocess_quasiquote( check_warnings: &RefCell>, call_stack: &CallStackList, ) -> Result { - let mut xs: CalcitItems = FingerList::from(&[Size(Calcit::Syntax(head.to_owned(), head_ns.to_owned()))]); + let mut xs: CalcitItems = TernaryTreeList::from(&[Calcit::Syntax(head.to_owned(), head_ns.to_owned())]); for a in args { - xs = xs.push(preprocess_quasiquote_internal( + xs = xs.push_right(preprocess_quasiquote_internal( a, scope_defs, file_ns.to_owned(), @@ -756,7 +757,7 @@ pub fn preprocess_quasiquote( call_stack, )?); } - Ok(Calcit::List(Box::new(xs))) + Ok(Calcit::List(xs)) } pub fn preprocess_quasiquote_internal( @@ -770,19 +771,19 @@ pub fn preprocess_quasiquote_internal( Calcit::List(ys) if ys.is_empty() => Ok(x.to_owned()), Calcit::List(ys) => match &ys[0] { Calcit::Symbol { sym, .. } if &**sym == "~" || &**sym == "~@" => { - let mut xs: CalcitItems = FingerList::new_empty(); - for y in &**ys { + let mut xs: CalcitItems = TernaryTreeList::Empty; + for y in ys { let (form, _) = preprocess_expr(y, scope_defs, file_ns.to_owned(), check_warnings, call_stack)?; - xs = xs.push(form.to_owned()); + xs = xs.push_right(form.to_owned()); } - Ok(Calcit::List(Box::new(xs))) + Ok(Calcit::List(xs)) } _ => { - let mut xs: CalcitItems = FingerList::new_empty(); - for y in &**ys { - xs = xs.push(preprocess_quasiquote_internal(y, scope_defs, file_ns.to_owned(), check_warnings, call_stack)?.to_owned()); + let mut xs: CalcitItems = TernaryTreeList::Empty; + for y in ys { + xs = xs.push_right(preprocess_quasiquote_internal(y, scope_defs, file_ns.to_owned(), check_warnings, call_stack)?.to_owned()); } - Ok(Calcit::List(Box::new(xs))) + Ok(Calcit::List(xs)) } }, _ => Ok(x.to_owned()),