[][src]Macro glsp::eval

eval!() { /* proc-macro */ }

A convenient way to evaluate simple GameLisp code.

This macro is only available when the "compiler" feature flag is enabled.

The input must be a single string literal which represents zero or more valid GameLisp forms. Those forms are evaluated in order, and the final form's result is returned. The return type is a generic GResult<T> for any T which implements FromVal - you will usually need to bind it to a local variable with an explicit type.

let result: Root<Arr> = eval!(r#"
	(let n (+ 1 2 3 4))
	(arr n n n)
"#)?;

Rust's local variables can be captured, and/or mutated, using the unquote form (abbreviated as ~). They are copied into the form using the IntoVal trait. If they're mutated using the = form, then the local variables' values are updated when eval!() returns, using the FromVal trait.

let input = 100_i64;
let mut output = "hello".to_string();
let assigned_but_not_read: f32;

let result: Val = eval!(r#"
	(= ~output (str ~input))
	(= ~assigned_but_not_read 100.0)
"#)?;

Some Rust collection types, such as tuples, slices, Strings and HashMaps, will allocate a new GameLisp array, string or table when captured as a local variable. This is potentially expensive, especially for large collections. Also, if the resulting collection is mutated, those changes are not usually copied back into the local variable when eval!() returns.

let rust_tuple = (60_u8, 120_u16, 240_u32);
let glsp_arr = arr![60_u8, 120_u16, 240_u32];

let _: Val = eval!(r#"
	(= [~rust_tuple 2] 480)
	(= [~glsp_arr 2] 480)
"#)?;

//rust collection types make a copy, but glsp collection types are passed in by reference
assert!(rust_tuple.2 == 240);
assert!(glsp_arr.get::<u32>(2)? == 480);

eval!() is much faster than GameLisp's own (eval) function, because its body is compiled in advance. The first time each eval!() is executed, it has a small lazy-initialization cost (usually less than 0.1 milliseconds for small inputs). On each subsequent execution, the overhead is roughly one microsecond per eval!() call.

The input is macro-expanded using a generic, empty Runtime which does not have access to any of your own macros. The only macros you can use in eval!() are those provided by GameLisp's standard library, or those defined within the eval!() form itself.