diff --git a/src/append.rs b/src/append.rs new file mode 100644 index 0000000..7a6c01d --- /dev/null +++ b/src/append.rs @@ -0,0 +1,68 @@ +/* relish: versatile lisp shell + * Copyright (C) 2021 Aidan Hahn + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +use crate::func::{FTable, Function, Args, Operation}; +use crate::vars::{VTable}; +use crate::segment::{Ctr, Ast, circuit, list_idx, list_append, new_ast}; +use std::rc::Rc; +use std::cell::RefCell; + +pub fn get_append() -> Function { + return Function{ + name: String::from("append"), + loose_syms: false, + eval_lazy: false, + args: Args::Lazy(-1), + function: Operation::Internal( + |a: Ast, _b: Rc>, _c: Rc>| -> Ctr { + let ptr = list_idx(a.clone(), 0); + match ptr { + Ctr::Seg(ref c) => { + let acpy = a.clone(); + match acpy.borrow().cdr.clone() { + Ctr::Seg(cn) => { + // append to list case + if !circuit(cn, &mut |arg: &Ctr| -> bool { + list_append(c.clone(), arg.clone()); + return true; + }) { + eprintln!("get_append circuit loop should not have returned false"); + } + }, + _ => { + eprintln!("get_append args somehow not in standard form"); + } + } + + return ptr; + }, + _ => { + let n = new_ast(Ctr::None, Ctr::None); + if !circuit(a, &mut |arg: &Ctr| -> bool { + list_append(n.clone(), arg.clone()); + return true; + }) { + eprintln!("get_append circuit loop should not have returned false"); + } + + return Ctr::Seg(n); + } + } + } + ) + }; +} diff --git a/src/bin/main.rs b/src/bin/main.rs index cea578f..1b180c1 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -98,7 +98,7 @@ fn main() { return }, Err(err) => { - println!("Prompt error: {:?}", err); + eprintln!("Prompt error: {:?}", err); break } } diff --git a/src/lib.rs b/src/lib.rs index c441a1e..23bac7b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,6 +22,7 @@ mod eval; mod vars; mod stl; mod str; +mod append; pub mod ast { pub use crate::segment::{Seg, Ctr, ast_to_string, Type, Ast, new_ast}; @@ -36,4 +37,5 @@ pub mod ast { pub mod stdlib { pub use crate::stl::{get_stdlib}; pub use crate::str::{get_echo}; + pub use crate::append::{get_append}; } diff --git a/src/stl.rs b/src/stl.rs index 0ffeed6..6a4690b 100644 --- a/src/stl.rs +++ b/src/stl.rs @@ -14,7 +14,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + use crate::str::get_echo; +use crate::append::get_append; use crate::func::{FTable, func_declare}; use std::rc::Rc; use std::cell::RefCell; @@ -24,6 +26,9 @@ pub fn get_stdlib() -> Result>, String> { if let Some(s) = func_declare(ft.clone(), Rc::new(RefCell::new(get_echo()))) { return Err(s) } + if let Some(s) = func_declare(ft.clone(), Rc::new(RefCell::new(get_append()))) { + return Err(s) + } return Ok(ft) } diff --git a/src/str.rs b/src/str.rs index 6384ad3..d0dfe6f 100644 --- a/src/str.rs +++ b/src/str.rs @@ -21,6 +21,8 @@ use crate::segment::{Ctr, Ast, circuit, ast_as_string}; use std::rc::Rc; use std::cell::RefCell; +// Current primitive is to use a get_NNNNN function defined for each library function which returns a not-previously-owned +// copy of the Function struct. pub fn get_echo() -> Function { return Function{ name: String::from("echo"), @@ -44,8 +46,7 @@ pub fn get_echo() -> Function { string.push_str("\n"); return true; }) { - // TODO: use custom logger - println!("Echo failure!") + eprintln!("circuit loop in echo should not have returned false") } return Ctr::String(string); }