diff --git a/Readme.org b/Readme.org index f4060e4..e591d71 100644 --- a/Readme.org +++ b/Readme.org @@ -470,8 +470,6 @@ This contains any executable target of this project. Notably the main shell file Note: this section will not show the status of each item unless you are viewing it with a proper orgmode viewer. Note: this section only tracks the state of incomplete TODO items. Having everything on here would be cluttered. -*** TODO Symbols defined within let by def statements must be pulled out and made global -*** TODO Def must eval args for symbol and doc *** TODO Shell prompt is fully configurable (L, R, and Delim) *** TODO Load (load a script) function Pull/Refactor the logic out of the configure functions. diff --git a/snippets/userlib.rls b/snippets/userlib.rls new file mode 100644 index 0000000..1e58d88 --- /dev/null +++ b/snippets/userlib.rls @@ -0,0 +1,30 @@ +;; 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 . +;; +;; USERLIB +;; This file contains a plethora of useful features that are not shipped in the STL + +(def prepend +'takes a list and appends an element to the back of it. + returns prepended list' + (elem list) + (reverse (append (reverse list) elem))) + +(def set +'sets an existing variable without touching its docstring' + (var val) + (let ((doc (get-doc var))) + (def (eval var) doc val))) \ No newline at end of file diff --git a/src/bin/main.rs b/src/bin/main.rs index 8a08e96..0bda1b9 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -78,7 +78,7 @@ fn main() -> ! { let mut rl = Reedline::create(); let maybe_hist: Box; if !hist_file_name.is_empty() { - maybe_hist = Box::new(FileBackedHistory::with_file(5, hist_file_name.into()) + maybe_hist = Box::new(FileBackedHistory::with_file(5000, hist_file_name.into()) .expect("error reading history!")); rl = rl.with_history(maybe_hist); } diff --git a/src/stl.rs b/src/stl.rs index 2242b89..5f5c988 100644 --- a/src/stl.rs +++ b/src/stl.rs @@ -481,6 +481,17 @@ pub fn static_stdlib(syms: &mut SymTable) -> Result<(), String> { }, ); + syms.insert( + "q".to_string(), + Symbol { + name: String::from("quote"), + args: Args::Lazy(1), + conditional_branches: true, + docs: decl::QUOTE_DOCSTRING.to_string(), + value: ValueType::Internal(Rc::new(decl::quote_callback)), + }, + ); + syms.insert( "eval".to_string(), Symbol { @@ -507,8 +518,8 @@ pub fn static_stdlib(syms: &mut SymTable) -> Result<(), String> { "get-doc".to_string(), Symbol { name: String::from("get-doc"), - args: Args::Lazy(1), - conditional_branches: true, + args: Args::Strict(vec![Type::Symbol]), + conditional_branches: false, docs: decl::GETDOC_DOCSTRING.to_string(), value: ValueType::Internal(Rc::new(decl::getdoc_callback)), } @@ -518,8 +529,8 @@ pub fn static_stdlib(syms: &mut SymTable) -> Result<(), String> { "set-doc".to_string(), Symbol { name: String::from("get-doc"), - args: Args::Lazy(2), - conditional_branches: true, + args: Args::Strict(vec![Type::Symbol, Type::String]), + conditional_branches: false, docs: decl::SETDOC_DOCSTRING.to_string(), value: ValueType::Internal(Rc::new(decl::setdoc_callback)), } diff --git a/src/stl/control.rs b/src/stl/control.rs index 6a6509c..3ceee80 100644 --- a/src/stl/control.rs +++ b/src/stl/control.rs @@ -205,8 +205,13 @@ pub fn let_callback(ast: &Seg, syms: &mut SymTable) -> Result { // we need to get any var declared from within the let eval forms // those need to exist in the outside context + // TODO: make this more optimal + // How can we skip iterations? + // implement a counter for number of calls to def + // store it inside the SymTable and Symbol + // only re-insert into global scope what is most recent for i in localsyms.iter() { - if !locals.contains(i.0) && !syms.contains_key(i.0) { + if !locals.contains(i.0) { syms.insert( i.0.clone(), i.1.clone(), diff --git a/src/stl/decl.rs b/src/stl/decl.rs index 4ffa56e..506d4d2 100644 --- a/src/stl/decl.rs +++ b/src/stl/decl.rs @@ -69,7 +69,7 @@ pub fn eval_callback(ast: &Seg, syms: &mut SymTable) -> Result { } }, _ => Ok(arguments) - }*/ + }*/ } } @@ -195,27 +195,28 @@ pub fn lambda_callback( } pub const GETDOC_DOCSTRING: &str = "accepts an unevaluated symbol, returns the doc string. -Returns an error if symbol is undefined"; +Returns an error if symbol is undefined. + +Note: make sure to quote the input like this: + (get-doc (quote symbol-name))"; pub fn getdoc_callback(ast: &Seg, syms: &mut SymTable) -> Result { - if ast.len() != 1 { - Err("get-doc only takes a single argument".to_string()) - } else { - if let Ctr::Symbol(ref symbol) = *ast.car { - if let Some(sym) = syms.get(symbol) { - Ok(Ctr::String(sym.docs.clone())) - } else { - Err("undefined symbol".to_string()) - } - + if let Ctr::Symbol(ref symbol) = *ast.car { + if let Some(sym) = syms.get(symbol) { + Ok(Ctr::String(sym.docs.clone())) } else { - Err("get-doc should only be called on a symbol".to_string()) + Err("undefined symbol".to_string()) } + } else { + Err("get-doc should only be called on a symbol".to_string()) } } pub const SETDOC_DOCSTRING: &str = "accepts a symbol and a doc string. -Returns an error if symbol is undefined, otherwise sets the symbols docstring to the argument."; +Returns an error if symbol is undefined, otherwise sets the symbols docstring to the argument. + +Note: make sure to quote the input like this: + (set-doc (quote symbol-name) my-new-docs)"; pub fn setdoc_callback(ast: &Seg, syms: &mut SymTable) -> Result { if ast.len() != 2 { diff --git a/tests/test_lib_decl.rs b/tests/test_lib_decl.rs index 2e2a41d..6db5b05 100644 --- a/tests/test_lib_decl.rs +++ b/tests/test_lib_decl.rs @@ -112,7 +112,7 @@ mod decl_lib_tests { let doc1 = "(def test-doc 'docs for test' 'test tests tests test')"; let doc2 = "(def test test-doc 'one')"; let doc3 = "(eq? (and - (eq? (get-doc test) test-doc) + (eq? (get-doc (quote test)) test-doc) (eq? test 'one')))"; let mut syms = SymTable::new(); @@ -337,8 +337,8 @@ mod decl_lib_tests { #[test] fn test_setget_doc_string() { - let highly_inadvisable = "(set-doc help 'help')"; - let document = "(get-doc help)"; + let highly_inadvisable = "(set-doc (q help) 'help')"; + let document = "(get-doc (q help))"; let mut syms = SymTable::new(); static_stdlib(&mut syms).unwrap(); dynamic_stdlib(&mut syms).unwrap();