help function displays values not

Signed-off-by: Ava Hahn <ava@aidanis.online>
This commit is contained in:
Ava Hahn 2023-03-06 15:12:59 -08:00
parent 8d79037d4d
commit de29bbf950
Signed by untrusted user who does not match committer: affine
GPG key ID: 3A4645B8CF806069
6 changed files with 127 additions and 103 deletions

View file

@ -36,8 +36,7 @@ pub fn static_stdlib(syms: &mut SymTable) -> Result<(), String> {
name: String::from("append"),
args: Args::Infinite,
conditional_branches: false,
docs: "traverses any number of arguments collecting them into a list.
If the first argument is a list, all other arguments are added sequentially to the end of the list contained in the first argument.".to_string(),
docs: append::APPEND_DOCSTRING.to_string(),
value: ValueType::Internal(Rc::new(append::append_callback)),
},
);
@ -48,7 +47,7 @@ If the first argument is a list, all other arguments are added sequentially to t
name: String::from("echo"),
args: Args::Infinite,
conditional_branches: false,
docs: "traverses any number of arguments. Prints their evaluated values on a new line for each.".to_string(),
docs: ECHO_DOCSTRING.to_string(),
value: ValueType::Internal(Rc::new(_echo_callback)),
},
);
@ -59,14 +58,7 @@ If the first argument is a list, all other arguments are added sequentially to t
name: String::from("if"),
args: Args::Lazy(3),
conditional_branches: true,
docs: "accepts three bodies, a condition, an unevaluated consequence, and an alternative consequence.
If the condition is evaluated to true, the first consequence is evaluated.
If the condition is evaluated to false, the second consequence is evaluated.
Otherwise, an error is thrown.
example: (if my-state-switch
(do-my-thing)
(else-an-other-thing))".to_string(),
docs: control::IF_DOCSTRING.to_string(),
value: ValueType::Internal(Rc::new(control::if_callback)),
},
);
@ -77,20 +69,7 @@ example: (if my-state-switch
name: String::from("let"),
args: Args::Infinite,
conditional_branches: true,
docs: "creates a stack of local variables for a sequence of operations.
returns the result of the final operation.
example: (let ((step1 'hello')
(step2 (concat step1 '-'))
(step3 (concat step2 'world')))
(echo step3)
(some-func some-args))
In this example step1, step2, and step3 are created sequentially.
Then, the echo form is evaluated, printing 'hello-world'.
Finally, the some-func form is evaluated.
Since the call to some-func is the final form, its value is returned."
.to_string(),
docs: control::LET_DOCSTRING.to_string(),
value: ValueType::Internal(Rc::new(control::let_callback)),
},
);
@ -101,13 +80,7 @@ Since the call to some-func is the final form, its value is returned."
name: String::from("while"),
args: Args::Infinite,
conditional_branches: true,
docs: "traverses a list of N un-evaluated forms.
the first form is expected to evaluate to a boolean. if it evaluates to false, while will stop and return. Otherwise, while will evaluate each form in a loop.
example: (while (check-my-state)
(do-thing-1 args)
(do-thing-2 args)
(edit-state my-state))".to_string(),
docs: control::WHILE_DOCSTRING.to_string(),
value: ValueType::Internal(Rc::new(control::while_callback)),
},
);
@ -118,17 +91,7 @@ example: (while (check-my-state)
name: String::from("circuit"),
args: Args::Infinite,
conditional_branches: true,
docs: "traverses a list of N un-evaluated forms.
evaluates each one until it stops. Circuit will stop when a form errors during evaluation.
Circuit will also stop when a form does not evaluate to a boolean, or evaluates to false.
example: (circuit (eq? (do-operation) myresult)
(and state1 state2 (boolean-operation3))
false
(do-another-operation))
in this example, do-another-operation will not be called"
.to_string(),
docs: control::CIRCUIT_DOCSTRING.to_string(),
value: ValueType::Internal(Rc::new(control::circuit_callback)),
},
);
@ -139,11 +102,8 @@ in this example, do-another-operation will not be called"
name: String::from("and"),
args: Args::Infinite,
conditional_branches: false,
docs: "traverses a list of N arguments, all of which are expected to be boolean.
starts with arg1 AND arg2, and then calculates prev_result AND next_arg.
returns final result."
.to_string(),
value: ValueType::Internal(Rc::new(boolean::bool_and_callback)),
docs: boolean::AND_DOCSTRING.to_string(),
value: ValueType::Internal(Rc::new(boolean::and_callback)),
},
);
@ -153,11 +113,8 @@ returns final result."
name: String::from("or"),
args: Args::Infinite,
conditional_branches: false,
docs: "traverses a list of N arguments, all of which are expected to be boolean.
starts with arg1 OR arg2, and then calculates prev_result OR next_arg.
returns final result."
.to_string(),
value: ValueType::Internal(Rc::new(boolean::bool_or_callback)),
docs: boolean::OR_DOCSTRING.to_string(),
value: ValueType::Internal(Rc::new(boolean::or_callback)),
},
);
@ -167,10 +124,8 @@ returns final result."
name: String::from("not"),
args: Args::Strict(vec![Type::Bool]),
conditional_branches: false,
docs: "takes a single argument (expects a boolean).
returns false if arg is true or true if arg is false."
.to_string(),
value: ValueType::Internal(Rc::new(boolean::bool_not_callback)),
docs: boolean::NOT_DOCSTRING.to_string(),
value: ValueType::Internal(Rc::new(boolean::not_callback)),
},
);
@ -180,11 +135,8 @@ returns false if arg is true or true if arg is false."
name: String::from("eq?"),
args: Args::Infinite,
conditional_branches: false,
docs: "traverses a list of N arguments.
returns true if all arguments hold the same value.
NOTE: 1 and 1.0 are the same, but '1' 'one' or one (symbol) aren't"
.to_string(),
value: ValueType::Internal(Rc::new(boolean::bool_iseq_callback)),
docs: boolean::ISEQ_DOCSTRING.to_string(),
value: ValueType::Internal(Rc::new(boolean::iseq_callback)),
},
);
@ -194,11 +146,8 @@ NOTE: 1 and 1.0 are the same, but '1' 'one' or one (symbol) aren't"
name: String::from("toggle"),
args: Args::Lazy(1),
conditional_branches: true,
docs: "switches a boolean symbol between true or false.
Takes a single argument (a symbol). Looks it up in the variable table.
Either sets the symbol to true if it is currently false, or vice versa."
.to_string(),
value: ValueType::Internal(Rc::new(boolean::bool_toggle_callback)),
docs: boolean::TOGGLE_DOCSTRING.to_string(),
value: ValueType::Internal(Rc::new(boolean::toggle_callback)),
},
);
@ -208,7 +157,7 @@ Either sets the symbol to true if it is currently false, or vice versa."
name: String::from("help"),
args: Args::Strict(vec![Type::Symbol]),
conditional_branches: true,
docs: "prints help text for a given symbol. Expects only one argument.".to_string(),
docs: HELP_DOCSTRING.to_string(),
value: ValueType::Internal(Rc::new(_help_callback)),
},
);
@ -233,19 +182,7 @@ pub fn dynamic_stdlib(syms: &mut SymTable) -> Result<(), String> {
name: String::from("define"),
args: Args::Infinite,
conditional_branches: true,
docs: "allows user to define functions and variables.
A call may take one of three forms:
1. variable declaration:
Takes a name, doc string, and a value.
(def myvar 'my special variable' 'my var value')
2. function declaration:
Takes a name, doc string, list of arguments, and one or more bodies to evaluate.
Result of evaluating the final body is returned.
(def myfunc 'does a thing' (myarg1 myarg2) (dothing myarg1 myarg2) (add myarg1 myarg2))
3. symbol un-definition:
Takes just a name. Removes variable from table.
(def useless-var)"
.to_string(),
docs: STORE_DOCSTRING.to_string(),
value: ValueType::Internal(Rc::new(
move |ast: &Seg, syms: &mut SymTable| -> Result<Ctr, String> {
_store_callback(ast, syms, env_cfg_user_form)
@ -257,6 +194,8 @@ pub fn dynamic_stdlib(syms: &mut SymTable) -> Result<(), String> {
Ok(())
}
pub const ECHO_DOCSTRING: &str = "traverses any number of arguments. Prints their evaluated values on a new line for each.";
fn _echo_callback(ast: &Seg, _syms: &mut SymTable) -> Result<Ctr, String> {
if ast.len() == 1 {
println!("{}", ast.car);
@ -267,6 +206,8 @@ fn _echo_callback(ast: &Seg, _syms: &mut SymTable) -> Result<Ctr, String> {
Ok(Ctr::None)
}
pub const HELP_DOCSTRING: &str = "prints help text for a given symbol. Expects only one argument.";
fn _help_callback(ast: &Seg, syms: &mut SymTable) -> Result<Ctr, String> {
if ast.len() != 1 {
return Err("help only takes a single argument".to_string());
@ -285,8 +226,8 @@ ARGS: {1}\n
DOCUMENTATION:\n
{2}\n
CURRENT VALUE AND/OR BODY:
(TODO)",
sym.name, args_str, sym.docs
{3}",
sym.name, args_str, sym.docs, sym.value
);
} else {
return Err("undefined symbol".to_string());
@ -298,6 +239,19 @@ CURRENT VALUE AND/OR BODY:
Ok(Ctr::None)
}
pub const STORE_DOCSTRING: &str = "allows user to define functions and variables.
A call may take one of three forms:
1. variable declaration:
Takes a name, doc string, and a value.
(def myvar 'my special variable' 'my var value')
2. function declaration:
Takes a name, doc string, list of arguments, and one or more bodies to evaluate.
Result of evaluating the final body is returned.
(def myfunc 'does a thing' (myarg1 myarg2) (dothing myarg1 myarg2) (add myarg1 myarg2))
3. symbol un-definition:
Takes just a name. Removes variable from table.
(def useless-var)";
fn _store_callback(ast: &Seg, syms: &mut SymTable, env_cfg: bool) -> Result<Ctr, String> {
let is_var = ast.len() == 3;
if let Ctr::Symbol(ref identifier) = *ast.car {