Evaluation context for LISP expressions.
Context::default()
only provides very basic utilities. To obtain an
evaluation context with useful functions available, use
Context::base()
.
Context
maintains separate environments for "core" (special forms, etc.),
"lang" (basic functions, vectors, and more), and "user" definitions. Most of
the provided methods operate on the "user" environment, as the intended use
case keeps the other environments immutable once they have been initialized.
You can insert
additional definitions here to make them available
throughout the runtime. These definitions will not go out of scope
automatically, but can be overridden (see get
for
semantic details).
Base context - defines a number of useful functions and constants for
use in the runtime.
use parsley::prelude::*;
let mut ctx = Context::base();
assert_eq!(
ctx.eval(
sexp![SExp::sym("null?"), SExp::sym("null")]
).unwrap(),
SExp::from(true),
);
println!("{}", ctx.get("eq?").unwrap());
println!("{}", ctx.get("+").unwrap());
Math functions that are less commonly used. Intended to be layered on top of the base context.
use parsley::prelude::*;
let mut ctx = &mut Context::base().math();
let mut asrt = |lhs, rhs| {
assert_eq!(ctx.run(lhs).unwrap(), ctx.run(rhs).unwrap())
};
asrt("(is-nan NaN)", "#t");
asrt("(floor -4.07326)", "-5");
asrt("(ceil 7.1)", "8");
asrt("(hypot 3 4)", "5");
asrt("(recip 100)", "0.01");
asrt("(log (exp 7))", "7");
Start capturing printed content in a buffer.
Capture display
and write
statement output in a buffer.
Get the captured side-effect output.
Add a new, nested scope.
See Context::pop for a usage example.
Remove the most recently added scope.
If the stack height is 1, all definitions will be cleared, and the
global scope will be replaced with an empty one.
use parsley::prelude::*;
let mut ctx = Context::default();
assert_eq!(ctx.get("x"), None);
ctx.push();
ctx.define("x", SExp::Null);
assert_eq!(ctx.get("x"), Some(SExp::Null));
ctx.pop();
assert_eq!(ctx.get("x"), None);
Create a new definition in the current scope.
Get the definition for a symbol in the execution environment.
Returns None
if no definition is found.
This method searches for a definition in the following order:
- The core language
- User definitions, starting from the most recent scope and working
backward to the top-level
- Language-level definitions
What this means is that definitions populated in the lang
field can be
overridden inside the runtime (e.g. in a REPL), but special form keywords
cannot. For example, we can (define null "foo")
, but we cannot
(set! and or)
.
let ctx = parsley::Context::default();
assert!(ctx.get("potato").is_none());
use parsley::prelude::*;
let mut ctx = Context::default();
ctx.define("x", SExp::from(3));
assert_eq!(ctx.get("x"), Some(SExp::from(3)));
Re-bind an existing definition to a new value.
Returns Ok
if an existing definition was found and updated. Returns
Err
if no definition exists.
use parsley::prelude::*;
let mut ctx = Context::default();
assert!(ctx.set("x", SExp::from(false)).is_err());
ctx.define("x", SExp::from(3));
assert_eq!(ctx.get("x"), Some(SExp::from(3)));
assert!(ctx.set("x", SExp::from("potato")).is_ok());
assert_eq!(ctx.get("x"), Some(SExp::from("potato")));
Run a code snippet in an existing Context
.
use parsley::prelude::*;
let mut ctx = Context::base();
assert!(ctx.run("x").is_err());
assert!(ctx.run("(define x 6)").is_ok());
assert_eq!(ctx.run("x").unwrap(), SExp::from(6));
Evaluate an S-Expression in a context.
The context will retain any definitions bound during evaluation
(e.g. define
, set!
).
use parsley::prelude::*;
let result = Context::base().eval(
sexp![SExp::sym("eq?"), 0, 1]
);
assert_eq!(result.unwrap(), SExp::from(false));
use parsley::prelude::*;
let mut ctx = Context::base();
let exp1 = sexp![SExp::sym("define"), SExp::sym("x"), 10];
let exp2 = SExp::sym("x");
ctx.eval(exp1);
assert_eq!(ctx.eval(exp2).unwrap(), SExp::from(10));
Returns the "default value" for a type. Read more
Writes a slice of bytes into this writer, returning whether the write succeeded. Read more
Writes a [char
] into this writer, returning whether the write succeeded. Read more
Glue for usage of the [write!
] macro with implementors of this trait. Read more
🔬 This is a nightly-only experimental API. (try_from
)
The type returned in the event of a conversion error.
🔬 This is a nightly-only experimental API. (try_from
)
Immutably borrows from an owned value. Read more
🔬 This is a nightly-only experimental API. (get_type_id
)
this method will likely be replaced by an associated static
🔬 This is a nightly-only experimental API. (try_from
)
The type returned in the event of a conversion error.
🔬 This is a nightly-only experimental API. (try_from
)
Mutably borrows from an owned value. Read more