add documentation for let and while forms

This commit is contained in:
Ava Hahn 2023-03-08 12:02:20 -08:00
parent acb1e1c126
commit 896ed567fd
Signed by untrusted user who does not match committer: affine
GPG key ID: 3A4645B8CF806069
2 changed files with 39 additions and 61 deletions

View file

@ -69,9 +69,38 @@ Function calls are executed as soon as the tree is evaluated. See the following
In this example, ~(add 5 2)~ is evaluated first, its result is then passed to ~(add 3 ...)~. In infix form: ~3 + (5 + 2)~. In this example, ~(add 5 2)~ is evaluated first, its result is then passed to ~(add 3 ...)~. In infix form: ~3 + (5 + 2)~.
*** TODO Control flow *** Control flow
**** TODO if **** if
**** TODO while An if form is the most basic form of conditional evaluation offered by Relish.
It is a function that takes lazily evaluated arguments: a condition, a then clause, and an else clause.
If the condition evaluates to true, the then clause is evaluated and the result returned.
Otherwise the else clause is evaluated and the result is returned.
If the condition evaluates to neither true nor false (a non-boolean value) a type error is returned.
#+BEGIN_SRC lisp
;; simple condition
(if true
(echo "its true!")
(echo "its false!"))
;; more advanced condition, with hypothetical data
(if (get-my-flag global-state)
(echo "my flag is already on!")
(turn-on-my-flag global-state))
#+END_SRC
**** while
Another popular control flow structure is the *while loop*.
This is implemented as a condition followed by one or more bodies that are lazily evaluated only if the condition is true.
Like the *if form*, if the conditional returns a non-boolean value the *while loop* will return an error.
#+BEGIN_SRC lisp
(while (get-my-flag global-state) ;; if false, returns (nothing) immediately
(dothing) ;; this is evaluated
"simple token" ;; this is also evaluated
(toggle-my-flag global-state)) ;; this is also evaluated
#+END_SRC
**** TODO let **** TODO let
**** TODO circuit **** TODO circuit
*** TODO quote and eval *** TODO quote and eval
@ -166,7 +195,13 @@ Errors during configuration are non-terminal. In such a case any defaults which
- CFG_RELISH_PROMPT (default (echo "λ ")): A *function* definition which is called in order to output the prompt for each loop of the REPL. - CFG_RELISH_PROMPT (default (echo "λ ")): A *function* definition which is called in order to output the prompt for each loop of the REPL.
This function will be reloaded each REPL loop and will be called by the interpreter with no arguments. This function will be reloaded each REPL loop and will be called by the interpreter with no arguments.
** TODO Further configuration *** Further configuration
Further configuration can be done by loading scripts that contain more functions and data to evaluate.
Variables and functions defined in an external script loaded by your interpreter will persist in the symbol table.
#+BEGIN_SRC lisp
(load "my-extra-library-functions.rls")
#+END_SRC
** Compilation ** Compilation
#+BEGIN_SRC sh #+BEGIN_SRC sh

View file

@ -1,57 +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 <http://www.gnu.org/licenses/>.
*/
use crate::sym::SymTable;
use crate::segment::{Seg, Ctr};
pub const ECHO_DOCSTRING: &str =
"traverses any number of arguments. Prints their evaluated values on a new line for each.";
pub fn echo_callback(ast: &Seg, _syms: &mut SymTable) -> Result<Ctr, String> {
if ast.len() == 1 {
println!("{}", ast.car);
} else {
ast.circuit(&mut |arg: &Ctr| print!("{}", arg) == ());
}
Ok(Ctr::None)
}
pub const CONCAT_DOCSTRING: &str = "Iterates over N args of any type other than SYMBOL.
converts each argument to a string. Combines all strings.
Returns final (combined) string.";
pub fn concat_callback(ast: &Seg, _syms: &mut SymTable) -> Result<Ctr, String> {
let mut string = String::from("");
if !ast.circuit(&mut |arg: &Ctr| {
match arg {
// should be a thing here
Ctr::Symbol(_) => return false,
Ctr::String(s) => string.push_str(&s),
Ctr::Integer(i) => string.push_str(&i.to_string()),
Ctr::Float(f) => string.push_str(&f.to_string()),
Ctr::Bool(b) => string.push_str(&b.to_string()),
Ctr::Seg(c) => string.push_str(ast_as_string(c.clone(), true).as_str()),
Ctr::None => (),
}
return true;
}) {
eprintln!("dont know what to do witha symbol here")
}
return Ctr::String(string);
}