diff --git a/src/bin/main.rs b/src/bin/main.rs deleted file mode 100644 index 9565a5a..0000000 --- a/src/bin/main.rs +++ /dev/null @@ -1,147 +0,0 @@ -/* 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 dirs::home_dir; -use relish::ast::{ast_to_string, eval, func_call, lex, new_ast, Ctr, FTable, VTable}; -use relish::aux::configure; -use rustyline::error::ReadlineError; -use rustyline::Editor; -use std::cell::RefCell; -use std::env; -use std::rc::Rc; - -fn main() { - let mut rl = Editor::<()>::new(); - - const HIST_FILE: &str = "/.relish_hist"; - const CONFIG_FILE_DEFAULT: &str = "/.relishrc"; - - let mut hist: String = "".to_owned(); - let mut cfg: String = "".to_owned(); - - if let Some(home) = home_dir() { - if let Some(h) = home.to_str() { - hist = h.to_owned() + HIST_FILE; - cfg = h.to_owned() + CONFIG_FILE_DEFAULT; - } - } - - if hist != "" { - // ignore result. it loads or it doesnt. - let _ = rl.load_history(&hist); - } - - let vt = Rc::new(RefCell::new(VTable::new())); - let conf_file; - let ft; - match env::var("RELISH_CFG_FILE") { - Ok(s) => { - conf_file = s - }, - Err(e) => { - eprintln!("{}", e); - conf_file = cfg; - }, - } - - match configure(conf_file, vt.clone()) { - Ok(f) => ft = f, - Err(e) => { - ft = Rc::new(RefCell::new(FTable::new())); - eprintln!("{}", e); - }, - } - - loop { - let readline: Result; - // Rust is pain - let tmp_ft_clone = ft.clone(); - // this is not okay - let t_ft_c_b = tmp_ft_clone.borrow(); - let pfunc = t_ft_c_b.get("CFG_RELISH_PROMPT"); - if let Some(fnc) = pfunc { - match func_call( - fnc.clone(), - new_ast(Ctr::None, Ctr::None), - vt.clone(), - ft.clone(), - ) { - Err(s) => { - eprintln!("Couldnt generate prompt: {}", s); - readline = rl.readline(""); - } - - Ok(c) => match c { - Ctr::Symbol(s) => readline = rl.readline(&s.to_owned()), - Ctr::String(s) => readline = rl.readline(&s), - Ctr::Integer(i) => readline = rl.readline(&format!("{}", i)), - Ctr::Float(f) => readline = rl.readline(&format!("{}", f)), - Ctr::Bool(b) => readline = rl.readline(&format!("{}", b)), - Ctr::Seg(c) => readline = rl.readline(&ast_to_string(c.clone())), - Ctr::None => readline = rl.readline(""), - }, - } - } else { - readline = rl.readline(""); - } - - match readline { - Ok(line) => { - rl.add_history_entry(line.as_str()); - let mut l = line.as_str().to_owned(); - if !l.starts_with("(") { - l = "(".to_owned() + &l; - } - - if !l.ends_with(")") { - l = l + ")"; - } - - match lex(l) { - Ok(a) => match eval(a.clone(), vt.clone(), ft.clone(), false) { - Ok(a) => match a { - Ctr::Symbol(s) => println!("{}", s), - Ctr::String(s) => println!("{}", s), - Ctr::Integer(i) => println!("{}", i), - Ctr::Float(f) => println!("{}", f), - Ctr::Bool(b) => println!("{}", b), - Ctr::Seg(c) => println!("{}", ast_to_string(c.clone())), - Ctr::None => (), - }, - Err(s) => { - println!("{}", s); - } - }, - Err(s) => { - println!("{}", s); - } - } - } - - Err(ReadlineError::Interrupted) => break, - - Err(ReadlineError::Eof) => return, - Err(err) => { - eprintln!("Prompt error: {:?}", err); - break; - } - } - } - if hist != "" { - rl.save_history(&hist).unwrap(); - } -} diff --git a/src/control.rs b/src/control.rs deleted file mode 100644 index 9032397..0000000 --- a/src/control.rs +++ /dev/null @@ -1,40 +0,0 @@ -/* 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::append::get_append; -use crate::func::{func_declare, FTable, Ast}; -use crate::segment::Ctr; -use crate::str::{get_concat, get_echo}; -use crate::vars::{get_export, VTable}; -use std::cell::RefCell; -use std::rc::Rc; - -pub fn get_if() -> Function { - return Function { - name: String::from("if"), - loose_syms: false, - eval_lazy: true, - args: Args::Lazy(-1), - function: Operation::Internal( - Box::new(|args: Ast, vars: Rc>, funcs: Rc>| -> Ctr { - // Either 2 long or 3 long. - // arg 1 must eval to a bool - // then eval arg 2 or 3 - }) - ), - }; -} diff --git a/src/lib.rs b/src/lib.rs index 1a34393..4dfaebe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,16 +15,13 @@ * along with this program. If not, see . */ -/*mod append; -mod config; - */ + +//mod config; mod eval; mod lex; mod segment; mod sym; mod stl; -/*mod stl; -mod str;*/ pub mod ast { pub use crate::eval::eval; @@ -36,12 +33,9 @@ pub mod ast { }; } -/*pub mod stdlib { - pub use crate::append::get_append; - pub use crate::stl::get_stdlib; - pub use crate::str::{get_concat, get_echo}; - pub use crate::vars::get_export; -}*/ +pub mod stdlib { + pub use crate::stl::{static_stdlib, dynamic_stdlib}; +} /*pub mod aux { pub use crate::config::configure; diff --git a/src/stl.rs b/src/stl.rs index c74cf8a..e63d0f1 100644 --- a/src/stl.rs +++ b/src/stl.rs @@ -21,35 +21,56 @@ use crate::sym::{SymTable, Symbol, ValueType, Args, UserFn}; use std::env; use std::rc::Rc; -fn store_stdlib(env: bool, syms: &mut SymTable) -> Result<(), String> { - syms.insert("def".to_string(), Symbol { - name: String::from("export"), - args: Args::Lazy(2), - conditional_branches: false, - value: ValueType::Internal(Rc::new( move |ast: &Seg, syms: &mut SymTable| -> Ctr { - _store_callback(ast, syms, env) - }, - )), - }); +pub mod control; +pub mod append; +//pub mod str; +/// static_stdlib +/// inserts all stdlib functions that can be inserted without +/// any kind of further configuration data into a symtable +pub fn static_stdlib(syms: &mut SymTable) -> Result<(), String> { syms.insert("append".to_string(), Symbol { name: String::from("append"), args: Args::Infinite, conditional_branches: false, - value: ValueType::Internal(Rc::new(_append_callback)), + value: ValueType::Internal(Rc::new(append::append_callback)), + }); + + syms.insert("expand".to_string(), Symbol { + name: String::from("expand"), + args: Args::Strict(vec![Type::Seg]), + conditional_branches: false, + value: ValueType::Internal(Rc::new(append::expand_callback)), + }); + + syms.insert("if".to_string(), Symbol { + name: String::from("if"), + args: Args::Lazy(3), + conditional_branches: true, + value: ValueType::Internal(Rc::new(control::if_callback)), }); Ok(()) } +/// dynamic_stdlib +/// takes configuration data and uses it to insert dynamic +/// callbacks with configuration into a symtable +pub fn dynamic_stdlib(env: bool, syms: &mut SymTable) -> Result<(), String> { + syms.insert("def".to_string(), Symbol { + name: String::from("export"), + args: Args::Lazy(2), + conditional_branches: false, + value: ValueType::Internal(Rc::new( move |ast: &Seg, syms: &mut SymTable| -> Result { + _store_callback(ast, syms, env) + }, + )), + }); -fn _append_callback (_ast: &Seg, _syms: &mut SymTable) -> Ctr { - // if car is a list, append cdr - // otherwise create a list out of all arguments - todo!() + Ok(()) } -fn _store_callback (ast: &Seg, syms: &mut SymTable, env_cfg: bool) -> Ctr { +fn _store_callback (ast: &Seg, syms: &mut SymTable, env_cfg: bool) -> Result { let is_var = ast.len() == 2; if let Ctr::Symbol(ref identifier) = *ast.car { match &*ast.cdr { @@ -65,9 +86,9 @@ fn _store_callback (ast: &Seg, syms: &mut SymTable, env_cfg: bool) -> Ctr { env::set_var(identifier.clone(), val.car.to_string()); } } else { - eprintln!("impossible args to export") + return Err("impossible args to export".to_string()); }, - Err(e) => eprintln!("couldnt eval symbol: {}", e), + Err(e) => return Err(format!("couldnt eval symbol: {}", e)), }, Ctr::Seg(data_tree) if !is_var => { if let Ctr::Seg(ref args) = *data_tree.car { @@ -80,8 +101,7 @@ fn _store_callback (ast: &Seg, syms: &mut SymTable, env_cfg: bool) -> Ctr { false } }) { - eprintln!("all arguments defined for function must be of type symbol"); - return Ctr::None; + return Err("all arguments defined for function must be of type symbol".to_string()); }; if let Ctr::Seg(ref bodies) = *data_tree.cdr { @@ -98,12 +118,10 @@ fn _store_callback (ast: &Seg, syms: &mut SymTable, env_cfg: bool) -> Ctr { conditional_branches: false, }); } else { - eprintln!("expected one or more function bodies in function definition"); - return Ctr::None; + return Err("expected one or more function bodies in function definition".to_string()); } } else { - eprintln!("expected list of arguments in function definition"); - return Ctr::None; + return Err("expected list of arguments in function definition".to_string()); } } Ctr::None => { @@ -112,11 +130,11 @@ fn _store_callback (ast: &Seg, syms: &mut SymTable, env_cfg: bool) -> Ctr { env::remove_var(identifier); } }, - _ => eprintln!("args not in standard form"), + _ => return Err("args not in standard form".to_string()), } } else { - eprintln!("first argument to export must be a symbol"); + return Err("first argument to export must be a symbol".to_string()); } - Ctr::None + Ok(Ctr::None) } diff --git a/src/stl/append.rs b/src/stl/append.rs new file mode 100644 index 0000000..1e46fa2 --- /dev/null +++ b/src/stl/append.rs @@ -0,0 +1,52 @@ +/* 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::segment::{Ctr, Seg}; +use crate::sym::{SymTable}; + +// Some essential operations below +pub fn append_callback (ast: &Seg, _syms: &mut SymTable) -> Result { + // if car is a list, append cdr + // otherwise create a list out of all arguments + if let Ctr::Seg(ref s) = *ast.car { + let mut temp = s.clone(); + temp.append(ast.cdr.clone()); + Ok(Ctr::Seg(temp)) + } else { + let mut temp = Seg::new(); + let mut car_iter = &ast.car; + let mut cdr_iter = &ast.cdr; + loop { + temp.append(car_iter.clone()); + if let Ctr::Seg(ref s) = **cdr_iter { + car_iter = &s.car; + cdr_iter = &s.cdr; + } else { + break; + } + } + + Ok(Ctr::Seg(temp)) + } +} + +pub fn expand_callback (ast: &Seg, _syms: &mut SymTable) -> Result { + if let Ctr::Seg(_) = *ast.car { + Ok(*ast.car.clone()) + } else { + Err("non list passed to expand!".to_string()) + } +} diff --git a/src/stl/control.rs b/src/stl/control.rs new file mode 100644 index 0000000..4a4c801 --- /dev/null +++ b/src/stl/control.rs @@ -0,0 +1,62 @@ +/* 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::segment::{Ctr, Seg}; +use crate::eval::eval; +use crate::sym::SymTable; + +pub fn if_callback (ast: &Seg, syms: &mut SymTable) -> Result { + if let Ctr::Seg(ref cond_form) = *ast.car { + if let Ctr::Bool(cond) = *eval(cond_form, syms)? { + if let Ctr::Seg(ref first_form) = *ast.cdr { + if cond { + match *first_form.car { + Ctr::Seg(ref first_arg) => Ok(*eval(first_arg, syms)?), + _ => Ok(*eval(&Seg::from_mono(first_form.car.clone()), syms)?), + } + } else { + if let Ctr::Seg(ref second_form) = *first_form.cdr { + match *second_form.car { + Ctr::Seg(ref second_arg) => Ok(*eval(second_arg, syms)?), + _ => Ok(*eval(&Seg::from_mono(second_form.car.clone()), syms)?), + } + } else { + Err("impossible condition: args not in standard form".to_string()) + } + } + } else { + Err("impossible condition: not 3 args to if".to_string()) + } + } else { + Err("first argument to if must evaluate to be a boolean".to_string()) + } + } else { + Err("impossible condition: not 3 args to if".to_string()) + } +} + +fn let_callback (_ast: &Seg, _syms: &mut SymTable) -> Result { + todo!() +} + +fn while_callback (_ast: &Seg, _syms: &mut SymTable) -> Result { + todo!() +} + +fn map_callback (_ast: &Seg, _syms: &mut SymTable) -> Result { + todo!() +} diff --git a/src/str.rs b/src/stl/str.rs similarity index 99% rename from src/str.rs rename to src/stl/str.rs index 191d4ec..418d252 100644 --- a/src/str.rs +++ b/src/stl/str.rs @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - +/* use crate::func::{Args, FTable, Function, Operation}; use crate::segment::{ast_as_string, circuit, Ast, Ctr}; use crate::vars::VTable; @@ -83,3 +83,4 @@ pub fn get_concat() -> Function { )), }; } +*/ diff --git a/src/sym.rs b/src/sym.rs index c5e087d..a5db769 100644 --- a/src/sym.rs +++ b/src/sym.rs @@ -39,7 +39,7 @@ pub struct UserFn { */ #[derive(Clone)] pub enum ValueType { - Internal(Rc Ctr>), + Internal(Rc Result>), FuncForm(UserFn), VarForm(Box) } @@ -237,7 +237,7 @@ impl Symbol { match &self.value { ValueType::VarForm(ref f) => Ok(Box::new(*f.clone())), - ValueType::Internal(ref f) => Ok(Box::new(f(evaluated_args, syms))), + ValueType::Internal(ref f) => Ok(Box::new(f(evaluated_args, syms)?)), ValueType::FuncForm(ref f) => { // stores any value overwritten by local state // If this ever becomes ASYNC this will need to diff --git a/tests/stl.rs b/tests/stl.rs deleted file mode 100644 index b9b4188..0000000 --- a/tests/stl.rs +++ /dev/null @@ -1,62 +0,0 @@ -/* 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::append::get_append; -use crate::func::{func_declare, FTable}; -use crate::segment::Ctr; -use crate::str::{get_concat, get_echo}; -use crate::control::{get_if}; -use crate::vars::{get_export, VTable}; -use std::cell::RefCell; -use std::rc::Rc; - -pub fn get_stdlib(conf: Rc>) -> Result>, String> { - let ft = Rc::new(RefCell::new(FTable::new())); - 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); - } - if let Some(s) = func_declare(ft.clone(), Rc::new(RefCell::new(get_concat()))) { - return Err(s); - } - - let mut cfg_env = true; - match conf.borrow().get(&String::from("CFG_RELISH_ENV")) { - None => { - println!("CFG_RELISH_ENV not defined. defaulting to ON.") - } - Some(ctr) => match (**ctr).clone() { - Ctr::String(ref s) => cfg_env = s.eq("0"), - _ => { - println!("Invalid value for CFG_RELISH_ENV. must be a string (0 or 1)."); - println!("Defaulting CFG_RELISH_ENV to ON"); - } - }, - } - - if let Some(s) = func_declare(ft.clone(), Rc::new(RefCell::new(get_export(cfg_env)))) { - return Err(s); - } - - if let Some(s) = func_declare(ft.clone(), Rc::new(RefCell::new(get_if()))) { - return Err(s); - } - - return Ok(ft); -} diff --git a/tests/test_func.rs b/tests/test_func.rs index 28a7027..54e9ed2 100644 --- a/tests/test_func.rs +++ b/tests/test_func.rs @@ -1,4 +1,5 @@ mod func_tests { + use std::rc::Rc; use relish::ast::lex; use relish::ast::{SymTable, Type, UserFn}; use relish::ast::{Args, Symbol, Ctr, Seg, ValueType}; @@ -10,14 +11,14 @@ mod func_tests { name: String::from("test_func_in"), conditional_branches: false, args: Args::Strict(vec![Type::Bool]), - value: ValueType::Internal(Box::new( - |a: &Seg, _: &mut SymTable| -> Ctr { + value: ValueType::Internal(Rc::new( + |a: &Seg, _: &mut SymTable| -> Result { let inner = a; let mut is_bool = false; if let Ctr::Bool(_) = *inner.car { is_bool = true; } - Ctr::Bool(is_bool) + Ok(Ctr::Bool(is_bool)) }, )), }; @@ -123,17 +124,17 @@ mod func_tests { name: String::from("test_inner"), conditional_branches: false, args: Args::Strict(vec![Type::Bool]), - value: ValueType::Internal(Box::new( - |a: &Seg, _: &mut SymTable| -> Ctr { + value: ValueType::Internal(Rc::new( + |a: &Seg, _: &mut SymTable| -> Result { let inner = a; if let Ctr::Bool(b) = *inner.car { if b { - Ctr::String("test".to_string()) + Ok(Ctr::String("test".to_string())) } else { - Ctr::None + Ok(Ctr::None) } } else { - Ctr::None + Err("not a bool".to_string()) } }, )), @@ -184,14 +185,14 @@ mod func_tests { name: String::from("test_func_in"), conditional_branches: false, args: Args::Strict(vec![Type::Bool]), - value: ValueType::Internal(Box::new( - |a: &Seg, _: &mut SymTable| -> Ctr { + value: ValueType::Internal(Rc::new( + |a: &Seg, _: &mut SymTable| -> Result { let inner = a; let mut is_bool = false; if let Ctr::Bool(_) = *inner.car { is_bool = true; } - Ctr::Bool(is_bool) + Ok(Ctr::Bool(is_bool)) }, )), }; @@ -279,14 +280,14 @@ mod func_tests { name: String::from("test_func_in"), conditional_branches: false, args: Args::Strict(vec![Type::Bool]), - value: ValueType::Internal(Box::new( - |a: &Seg, _: &mut SymTable| -> Ctr { + value: ValueType::Internal(Rc::new( + |a: &Seg, _: &mut SymTable| -> Result { let inner = a; let mut is_bool = false; if let Ctr::Bool(_) = *inner.car { is_bool = true; } - Ctr::Bool(is_bool) + Ok(Ctr::Bool(is_bool)) }, )), }; diff --git a/tests/test_lib_append.rs b/tests/test_lib_append.rs index 7bcbc9c..236cffa 100644 --- a/tests/test_lib_append.rs +++ b/tests/test_lib_append.rs @@ -1,46 +1,22 @@ mod append_lib_tests { - use relish::ast::{ast_to_string, eval, lex, Ctr, FTable, VTable}; - use relish::stdlib::get_stdlib; - use std::cell::RefCell; - use std::rc::Rc; + use relish::ast::{Ctr, eval, lex, SymTable}; + use relish::stdlib::{static_stdlib, dynamic_stdlib}; #[test] fn test_append_to_empty_list() { - let document = "(append () 1 2 3)"; - let result = "(1 2 3)"; - let vt = Rc::new(RefCell::new(VTable::new())); - let ft: Rc>; - match get_stdlib(vt.clone()) { - Ok(f) => ft = f, - Err(s) => { - ft = Rc::new(RefCell::new(FTable::new())); - println!("Couldnt get stdlib: {}!", s); - assert!(false) + let document = "(append () 1)"; + let result = "(1)"; + + let mut syms = SymTable::new(); + static_stdlib(&mut syms).unwrap(); + dynamic_stdlib(false, &mut syms).unwrap(); + + if let Ok(tree) = lex(&document.to_string()) { + if let Ctr::Seg(ref s) = *eval(&tree, &mut syms).unwrap() { + assert_eq!(s.to_string(), result); } - } - - match lex(document.to_string()) { - Err(s) => { - println!("Couldnt lex {}: {}\n", document, s); - assert!(false); - } - - Ok(tree) => match eval(tree, vt.clone(), ft.clone(), false) { - Err(s) => { - println!("Couldnt eval {}: {}\n", document, s); - assert!(false); - } - - Ok(ctr) => match ctr { - Ctr::Symbol(_) => assert!(false), - Ctr::String(_) => assert!(false), - Ctr::Integer(_) => assert!(false), - Ctr::Float(_) => assert!(false), - Ctr::Bool(_) => assert!(false), - Ctr::Seg(s) => assert_eq!(ast_to_string(s), result), - Ctr::None => assert!(false), - }, - }, + } else { + assert!(false) } } @@ -48,79 +24,35 @@ mod append_lib_tests { fn test_append_to_full_list() { let document = "(append (1 2) 3)"; let result = "(1 2 3)"; - let vt = Rc::new(RefCell::new(VTable::new())); - let ft: Rc>; - match get_stdlib(vt.clone()) { - Ok(f) => ft = f, - Err(s) => { - ft = Rc::new(RefCell::new(FTable::new())); - println!("Couldnt get stdlib: {}!", s); - assert!(false) + + let mut syms = SymTable::new(); + static_stdlib(&mut syms).unwrap(); + dynamic_stdlib(false, &mut syms).unwrap(); + + if let Ok(tree) = lex(&document.to_string()) { + if let Ctr::Seg(ref s) = *eval(&tree, &mut syms).unwrap() { + assert_eq!(s.to_string(), result); } - } - - match lex(document.to_string()) { - Err(s) => { - println!("Couldnt lex {}: {}\n", document, s); - assert!(false); - } - - Ok(tree) => match eval(tree, vt.clone(), ft.clone(), false) { - Err(s) => { - println!("Couldnt eval {}: {}\n", document, s); - assert!(false); - } - - Ok(ctr) => match ctr { - Ctr::Symbol(_) => assert!(false), - Ctr::String(_) => assert!(false), - Ctr::Integer(_) => assert!(false), - Ctr::Float(_) => assert!(false), - Ctr::Bool(_) => assert!(false), - Ctr::Seg(s) => assert_eq!(ast_to_string(s), result), - Ctr::None => assert!(false), - }, - }, + } else { + assert!(false); } } #[test] fn test_mono_append() { let document = "(append)"; - let result = "()"; - let vt = Rc::new(RefCell::new(VTable::new())); - let ft: Rc>; - match get_stdlib(vt.clone()) { - Ok(f) => ft = f, - Err(s) => { - ft = Rc::new(RefCell::new(FTable::new())); - println!("Couldnt get stdlib: {}!", s); - assert!(false) + let result = "()"; + + let mut syms = SymTable::new(); + static_stdlib(&mut syms).unwrap(); + dynamic_stdlib(false, &mut syms).unwrap(); + + if let Ok(tree) = lex(&document.to_string()) { + if let Ctr::Seg(ref s) = *eval(&tree, &mut syms).unwrap() { + assert_eq!(s.to_string(), result); } - } - - match lex(document.to_string()) { - Err(s) => { - println!("Couldnt lex {}: {}\n", document, s); - assert!(false); - } - - Ok(tree) => match eval(tree, vt.clone(), ft.clone(), false) { - Err(s) => { - println!("Couldnt eval {}: {}\n", document, s); - assert!(false); - } - - Ok(ctr) => match ctr { - Ctr::Symbol(_) => assert!(false), - Ctr::String(_) => assert!(false), - Ctr::Integer(_) => assert!(false), - Ctr::Float(_) => assert!(false), - Ctr::Bool(_) => assert!(false), - Ctr::Seg(s) => assert_eq!(ast_to_string(s), result), - Ctr::None => assert!(false), - }, - }, + } else { + assert!(false); } } @@ -128,39 +60,17 @@ mod append_lib_tests { fn test_append_no_list() { let document = "(append 'test' 1 2 3)"; let result = "('test' 1 2 3)"; - let vt = Rc::new(RefCell::new(VTable::new())); - let ft: Rc>; - match get_stdlib(vt.clone()) { - Ok(f) => ft = f, - Err(s) => { - ft = Rc::new(RefCell::new(FTable::new())); - println!("Couldnt get stdlib: {}!", s); - assert!(false) + + let mut syms = SymTable::new(); + static_stdlib(&mut syms).unwrap(); + dynamic_stdlib(false, &mut syms).unwrap(); + + if let Ok(tree) = lex(&document.to_string()) { + if let Ctr::Seg(ref s) = *eval(&tree, &mut syms).unwrap() { + assert_eq!(s.to_string(), result); } - } - - match lex(document.to_string()) { - Err(s) => { - println!("Couldnt lex {}: {}\n", document, s); - assert!(false); - } - - Ok(tree) => match eval(tree, vt.clone(), ft.clone(), false) { - Err(s) => { - println!("Couldnt eval {}: {}\n", document, s); - assert!(false); - } - - Ok(ctr) => match ctr { - Ctr::Symbol(_) => assert!(false), - Ctr::String(_) => assert!(false), - Ctr::Integer(_) => assert!(false), - Ctr::Float(_) => assert!(false), - Ctr::Bool(_) => assert!(false), - Ctr::Seg(s) => assert_eq!(ast_to_string(s), result), - Ctr::None => assert!(false), - }, - }, + } else { + assert!(false); } } } diff --git a/tests/test_lib_control.rs b/tests/test_lib_control.rs new file mode 100644 index 0000000..b6d5bb4 --- /dev/null +++ b/tests/test_lib_control.rs @@ -0,0 +1,64 @@ +mod control_lib_tests { + use relish::ast::{Ctr, eval, lex, SymTable}; + use relish::stdlib::{static_stdlib, dynamic_stdlib}; + + #[test] + fn test_if_first_case_singlet() { + let document = "(if true 1 2)"; + let result = 1; + + let mut syms = SymTable::new(); + static_stdlib(&mut syms).unwrap(); + dynamic_stdlib(false, &mut syms).unwrap(); + + if let Ok(tree) = lex(&document.to_string()) { + if let Ctr::Integer(i) = *eval(&tree, &mut syms).unwrap() { + assert_eq!(i, result); + } else { + assert!(false); + } + } else { + assert!(false); + } + } + + #[test] + fn test_if_second_case_singlet() { + let document = "(if false 1 2)"; + let result = 2; + + let mut syms = SymTable::new(); + static_stdlib(&mut syms).unwrap(); + dynamic_stdlib(false, &mut syms).unwrap(); + + if let Ok(tree) = lex(&document.to_string()) { + if let Ctr::Integer(i) = *eval(&tree, &mut syms).unwrap() { + assert_eq!(i, result); + } else { + assert!(false); + } + } else { + assert!(false); + } + } + + #[test] + fn test_complex_case_call() { + let document = "(if true (append () 1) 2)"; + let result = "(1)"; + + let mut syms = SymTable::new(); + static_stdlib(&mut syms).unwrap(); + dynamic_stdlib(false, &mut syms).unwrap(); + + if let Ok(tree) = lex(&document.to_string()) { + if let Ctr::Seg(ref i) = *eval(&tree, &mut syms).unwrap() { + assert_eq!(i.to_string(), result); + } else { + assert!(false); + } + } else { + assert!(false); + } + } +} diff --git a/tests/test_lib_str.rs b/tests/test_lib_str.rs index 382b65e..6f45e56 100644 --- a/tests/test_lib_str.rs +++ b/tests/test_lib_str.rs @@ -1,4 +1,4 @@ -mod str_lib_tests { +/*mod str_lib_tests { use relish::ast::{eval, lex, Ctr, FTable, VTable}; use relish::stdlib::get_stdlib; use std::cell::RefCell; @@ -124,3 +124,4 @@ mod str_lib_tests { } } } +*/ diff --git a/tests/test_vars.rs b/tests/test_vars.rs index 9197e01..f412c06 100644 --- a/tests/test_vars.rs +++ b/tests/test_vars.rs @@ -1,62 +1,35 @@ -/*mod var_lib_tests { - use relish::ast::{eval, lex, SYM_TABLE}; - use relish::ast::{Args, Symbol, Ctr, Seg, ValueType, UserFn}; +mod var_lib_tests { + use relish::ast::{eval, lex, SymTable, Ctr}; + use relish::stdlib::{static_stdlib, dynamic_stdlib}; #[test] fn test_variable_export_and_lookup() { let doc1 = "(export test 1)"; - let doc2 = "(concat test)"; - let result = "1"; + let doc2 = "test"; + let result = 1; - match get_stdlib(vt.clone()) { - Ok(f) => ft = f, - Err(s) => { - ft = Rc::new(RefCell::new(FTable::new())); - println!("Couldnt get stdlib: {}!", s); + let mut syms = SymTable::new(); + static_stdlib(&mut syms).unwrap(); + dynamic_stdlib(false, &mut syms).unwrap(); + + if let Ok(tree) = lex(&doc1.to_string()) { + if let Ctr::None = *eval(&tree, &mut syms).unwrap() { + // pass + } else { assert!(false); } + } else { + assert!(false); } - match lex(doc1.to_string()) { - Err(s) => { - println!("Couldnt lex {}: {}", doc1, s); + if let Ok(tree) = lex(&doc2.to_string()) { + if let Ctr::Integer(i) = *eval(&tree, &mut syms).unwrap() { + assert_eq!(i, result); + } else { assert!(false); } - - Ok(tree) => match eval(tree, vt.clone(), ft.clone(), false) { - Err(s) => { - println!("Couldnt eval {}: {}", doc2, s); - assert!(false); - } - - Ok(ctr) => { - println!("{:#?}", vt); - match ctr { - Ctr::None => assert!(true), - _ => assert!(false), - } - } - }, - } - - match lex(doc2.to_string()) { - Err(s) => { - println!("Couldnt lex {}: {}", doc2, s); - assert!(false); - } - - Ok(tree) => match eval(tree, vt.clone(), ft.clone(), false) { - Err(s) => { - println!("Couldnt eval {}: {}", doc2, s); - assert!(false); - } - - Ok(ctr) => match ctr { - Ctr::String(s) => assert_eq!(s, result), - _ => assert!(false), - }, - }, + } else { + assert!(false); } } } -*/