Added USERLIB with prepend and set.
Added a q shortcut to quote get-doc and set-doc no longer conditionally evaluate args Fixed bug in let, documented potential performance improvements upped default history to 5k lines
This commit is contained in:
parent
a01df6b7b2
commit
1ee9ba55fb
7 changed files with 70 additions and 25 deletions
|
|
@ -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 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.
|
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 Shell prompt is fully configurable (L, R, and Delim)
|
||||||
*** TODO Load (load a script) function
|
*** TODO Load (load a script) function
|
||||||
Pull/Refactor the logic out of the configure functions.
|
Pull/Refactor the logic out of the configure functions.
|
||||||
|
|
|
||||||
30
snippets/userlib.rls
Normal file
30
snippets/userlib.rls
Normal file
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
;;
|
||||||
|
;; 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)))
|
||||||
|
|
@ -78,7 +78,7 @@ fn main() -> ! {
|
||||||
let mut rl = Reedline::create();
|
let mut rl = Reedline::create();
|
||||||
let maybe_hist: Box<FileBackedHistory>;
|
let maybe_hist: Box<FileBackedHistory>;
|
||||||
if !hist_file_name.is_empty() {
|
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!"));
|
.expect("error reading history!"));
|
||||||
rl = rl.with_history(maybe_hist);
|
rl = rl.with_history(maybe_hist);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
19
src/stl.rs
19
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(
|
syms.insert(
|
||||||
"eval".to_string(),
|
"eval".to_string(),
|
||||||
Symbol {
|
Symbol {
|
||||||
|
|
@ -507,8 +518,8 @@ pub fn static_stdlib(syms: &mut SymTable) -> Result<(), String> {
|
||||||
"get-doc".to_string(),
|
"get-doc".to_string(),
|
||||||
Symbol {
|
Symbol {
|
||||||
name: String::from("get-doc"),
|
name: String::from("get-doc"),
|
||||||
args: Args::Lazy(1),
|
args: Args::Strict(vec![Type::Symbol]),
|
||||||
conditional_branches: true,
|
conditional_branches: false,
|
||||||
docs: decl::GETDOC_DOCSTRING.to_string(),
|
docs: decl::GETDOC_DOCSTRING.to_string(),
|
||||||
value: ValueType::Internal(Rc::new(decl::getdoc_callback)),
|
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(),
|
"set-doc".to_string(),
|
||||||
Symbol {
|
Symbol {
|
||||||
name: String::from("get-doc"),
|
name: String::from("get-doc"),
|
||||||
args: Args::Lazy(2),
|
args: Args::Strict(vec![Type::Symbol, Type::String]),
|
||||||
conditional_branches: true,
|
conditional_branches: false,
|
||||||
docs: decl::SETDOC_DOCSTRING.to_string(),
|
docs: decl::SETDOC_DOCSTRING.to_string(),
|
||||||
value: ValueType::Internal(Rc::new(decl::setdoc_callback)),
|
value: ValueType::Internal(Rc::new(decl::setdoc_callback)),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -205,8 +205,13 @@ pub fn let_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, String> {
|
||||||
|
|
||||||
// we need to get any var declared from within the let eval forms
|
// we need to get any var declared from within the let eval forms
|
||||||
// those need to exist in the outside context
|
// 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() {
|
for i in localsyms.iter() {
|
||||||
if !locals.contains(i.0) && !syms.contains_key(i.0) {
|
if !locals.contains(i.0) {
|
||||||
syms.insert(
|
syms.insert(
|
||||||
i.0.clone(),
|
i.0.clone(),
|
||||||
i.1.clone(),
|
i.1.clone(),
|
||||||
|
|
|
||||||
|
|
@ -195,27 +195,28 @@ pub fn lambda_callback(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const GETDOC_DOCSTRING: &str = "accepts an unevaluated symbol, returns the doc string.
|
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<Ctr, String> {
|
pub fn getdoc_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, String> {
|
||||||
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 Ctr::Symbol(ref symbol) = *ast.car {
|
||||||
if let Some(sym) = syms.get(symbol) {
|
if let Some(sym) = syms.get(symbol) {
|
||||||
Ok(Ctr::String(sym.docs.clone()))
|
Ok(Ctr::String(sym.docs.clone()))
|
||||||
} else {
|
} else {
|
||||||
Err("undefined symbol".to_string())
|
Err("undefined symbol".to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Err("get-doc should only be called on a symbol".to_string())
|
Err("get-doc should only be called on a symbol".to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub const SETDOC_DOCSTRING: &str = "accepts a symbol and a doc 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<Ctr, String> {
|
pub fn setdoc_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, String> {
|
||||||
if ast.len() != 2 {
|
if ast.len() != 2 {
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ mod decl_lib_tests {
|
||||||
let doc1 = "(def test-doc 'docs for test' 'test tests tests test')";
|
let doc1 = "(def test-doc 'docs for test' 'test tests tests test')";
|
||||||
let doc2 = "(def test test-doc 'one')";
|
let doc2 = "(def test test-doc 'one')";
|
||||||
let doc3 = "(eq? (and
|
let doc3 = "(eq? (and
|
||||||
(eq? (get-doc test) test-doc)
|
(eq? (get-doc (quote test)) test-doc)
|
||||||
(eq? test 'one')))";
|
(eq? test 'one')))";
|
||||||
|
|
||||||
let mut syms = SymTable::new();
|
let mut syms = SymTable::new();
|
||||||
|
|
@ -337,8 +337,8 @@ mod decl_lib_tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_setget_doc_string() {
|
fn test_setget_doc_string() {
|
||||||
let highly_inadvisable = "(set-doc help 'help')";
|
let highly_inadvisable = "(set-doc (q help) 'help')";
|
||||||
let document = "(get-doc help)";
|
let document = "(get-doc (q help))";
|
||||||
let mut syms = SymTable::new();
|
let mut syms = SymTable::new();
|
||||||
static_stdlib(&mut syms).unwrap();
|
static_stdlib(&mut syms).unwrap();
|
||||||
dynamic_stdlib(&mut syms).unwrap();
|
dynamic_stdlib(&mut syms).unwrap();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue