initial documentation (WIP)
This commit is contained in:
parent
1b22cab7dd
commit
47ce39062f
@ -91,14 +91,44 @@ pub enum FnType {
|
|||||||
InternalFn(FnDef),
|
InternalFn(FnDef),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Rhai's engine type. This is what you use to run Rhai scripts
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// extern crate rhai;
|
||||||
|
/// use rhai::Engine;
|
||||||
|
///
|
||||||
|
/// fn main() {
|
||||||
|
/// let mut engine = Engine::new();
|
||||||
|
///
|
||||||
|
/// if let Ok(result) = engine.eval::<i64>("40 + 2") {
|
||||||
|
/// println!("Answer: {}", result); // prints 42
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
pub struct Engine {
|
pub struct Engine {
|
||||||
pub fns: HashMap<String, Vec<FnType>>,
|
pub fns: HashMap<String, Vec<FnType>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A type containing information about current scope.
|
||||||
|
/// Useful for keeping state between `Engine` runs
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use rhai::{Engine, Scope};
|
||||||
|
///
|
||||||
|
/// let mut engine = Engine::new();
|
||||||
|
/// let mut my_scope = Scope::new();
|
||||||
|
///
|
||||||
|
/// assert!(engine.eval_with_scope::<()>(&mut my_scope, "let x = 5;").is_ok());
|
||||||
|
/// assert_eq!(engine.eval_with_scope::<i64>(&mut my_scope, "x + 1").unwrap(), 6);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Between runs, `Engine` only remembers functions when not using own `Scope`.
|
||||||
pub type Scope = Vec<(String, Box<Any>)>;
|
pub type Scope = Vec<(String, Box<Any>)>;
|
||||||
|
|
||||||
impl Engine {
|
impl Engine {
|
||||||
fn call_fn(&self,
|
/// Universal method for calling functions, that are either
|
||||||
|
/// registered with the `Engine` or written in Rhai
|
||||||
|
pub fn call_fn(&self,
|
||||||
name: &str,
|
name: &str,
|
||||||
arg1: Option<&mut Box<Any>>,
|
arg1: Option<&mut Box<Any>>,
|
||||||
arg2: Option<&mut Box<Any>>,
|
arg2: Option<&mut Box<Any>>,
|
||||||
@ -500,6 +530,8 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Register a type for use with Engine. Keep in mind that
|
||||||
|
/// your type must implement Clone.
|
||||||
pub fn register_type<T: Clone + Any>(&mut self) {
|
pub fn register_type<T: Clone + Any>(&mut self) {
|
||||||
fn clone_helper<T: Clone>(t: T) -> T {
|
fn clone_helper<T: Clone>(t: T) -> T {
|
||||||
t.clone()
|
t.clone()
|
||||||
@ -508,6 +540,7 @@ impl Engine {
|
|||||||
self.register_fn("clone", clone_helper as fn(T) -> T);
|
self.register_fn("clone", clone_helper as fn(T) -> T);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Register a get function for a member of a registered type
|
||||||
pub fn register_get<T: Clone + Any, U: Clone + Any, F>(&mut self, name: &str, get_fn: F)
|
pub fn register_get<T: Clone + Any, U: Clone + Any, F>(&mut self, name: &str, get_fn: F)
|
||||||
where F: 'static + Fn(&mut T) -> U
|
where F: 'static + Fn(&mut T) -> U
|
||||||
{
|
{
|
||||||
@ -516,6 +549,7 @@ impl Engine {
|
|||||||
self.register_fn(&get_name, get_fn);
|
self.register_fn(&get_name, get_fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Register a set function for a member of a registered type
|
||||||
pub fn register_set<T: Clone + Any, U: Clone + Any, F>(&mut self, name: &str, set_fn: F)
|
pub fn register_set<T: Clone + Any, U: Clone + Any, F>(&mut self, name: &str, set_fn: F)
|
||||||
where F: 'static + Fn(&mut T, U) -> ()
|
where F: 'static + Fn(&mut T, U) -> ()
|
||||||
{
|
{
|
||||||
@ -524,6 +558,7 @@ impl Engine {
|
|||||||
self.register_fn(&set_name, set_fn);
|
self.register_fn(&set_name, set_fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Shorthand for registering both getters and setters
|
||||||
pub fn register_get_set<T: Clone + Any, U: Clone + Any, F, G>(&mut self,
|
pub fn register_get_set<T: Clone + Any, U: Clone + Any, F, G>(&mut self,
|
||||||
name: &str,
|
name: &str,
|
||||||
get_fn: F,
|
get_fn: F,
|
||||||
@ -1187,6 +1222,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Evaluate a file
|
||||||
pub fn eval_file<T: Any + Clone>(&mut self, fname: &str) -> Result<T, EvalAltResult> {
|
pub fn eval_file<T: Any + Clone>(&mut self, fname: &str) -> Result<T, EvalAltResult> {
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
@ -1204,12 +1240,14 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Evaluate a string
|
||||||
pub fn eval<T: Any + Clone>(&mut self, input: &str) -> Result<T, EvalAltResult> {
|
pub fn eval<T: Any + Clone>(&mut self, input: &str) -> Result<T, EvalAltResult> {
|
||||||
let mut scope: Scope = Vec::new();
|
let mut scope: Scope = Vec::new();
|
||||||
|
|
||||||
self.eval_with_scope(&mut scope, input)
|
self.eval_with_scope(&mut scope, input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Evaluate with own scope
|
||||||
pub fn eval_with_scope<T: Any + Clone>(&mut self,
|
pub fn eval_with_scope<T: Any + Clone>(&mut self,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
input: &str)
|
input: &str)
|
||||||
@ -1254,6 +1292,9 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Evaluate a file, but only return errors, if there are any.
|
||||||
|
/// Useful for when you don't need the result, but still need
|
||||||
|
/// to keep track of possible errors
|
||||||
pub fn consume_file(&mut self, fname: &str) -> Result<(), EvalAltResult> {
|
pub fn consume_file(&mut self, fname: &str) -> Result<(), EvalAltResult> {
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
@ -1273,6 +1314,9 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Evaluate a string, but only return errors, if there are any.
|
||||||
|
/// Useful for when you don't need the result, but still need
|
||||||
|
/// to keep track of possible errors
|
||||||
pub fn consume(&mut self, input: &str) -> Result<(), EvalAltResult> {
|
pub fn consume(&mut self, input: &str) -> Result<(), EvalAltResult> {
|
||||||
let mut scope: Scope = Scope::new();
|
let mut scope: Scope = Scope::new();
|
||||||
|
|
||||||
@ -1281,6 +1325,9 @@ impl Engine {
|
|||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Evaluate a string with own scoppe, but only return errors, if there are any.
|
||||||
|
/// Useful for when you don't need the result, but still need
|
||||||
|
/// to keep track of possible errors
|
||||||
pub fn consume_with_scope(&mut self, scope: &mut Scope, input: &str) -> Result<(), EvalAltResult> {
|
pub fn consume_with_scope(&mut self, scope: &mut Scope, input: &str) -> Result<(), EvalAltResult> {
|
||||||
let tokens = lex(input);
|
let tokens = lex(input);
|
||||||
|
|
||||||
@ -1311,6 +1358,8 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Register the default library. That means, numberic types, char, bool
|
||||||
|
/// String, arithmetics and string concatenations.
|
||||||
pub fn register_default_lib(engine: &mut Engine) {
|
pub fn register_default_lib(engine: &mut Engine) {
|
||||||
engine.register_type::<i32>();
|
engine.register_type::<i32>();
|
||||||
engine.register_type::<u32>();
|
engine.register_type::<u32>();
|
||||||
@ -1388,6 +1437,7 @@ impl Engine {
|
|||||||
// (*ent).push(FnType::ExternalFn2(Box::new(idx)));
|
// (*ent).push(FnType::ExternalFn2(Box::new(idx)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Make a new engine
|
||||||
pub fn new() -> Engine {
|
pub fn new() -> Engine {
|
||||||
let mut engine = Engine { fns: HashMap::new() };
|
let mut engine = Engine { fns: HashMap::new() };
|
||||||
|
|
||||||
|
39
src/lib.rs
39
src/lib.rs
@ -1,4 +1,40 @@
|
|||||||
//! Rhai - embedded scripting for Rust
|
//! # Rhai - embedded scripting for Rust
|
||||||
|
//! Rhai is a tiny, simple and very fast embedded scripting language for Rust
|
||||||
|
//! that gives you a safe and easy way to add scripting to your applications.
|
||||||
|
//! It provides a familiar syntax based on JS and Rust and a simple Rust interface.
|
||||||
|
//! Here is a quick example. First, the contents of `my_script.rhai`:
|
||||||
|
//!
|
||||||
|
//! ```rust_todo_disable_testing_enable_highlighting
|
||||||
|
//! fn factorial(x) {
|
||||||
|
//! if x == 1 { return 1; }
|
||||||
|
//! x * factorial(x - 1)
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! compute_something(factorial(10))
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! And the Rust part:
|
||||||
|
//!
|
||||||
|
//! ```rust
|
||||||
|
//! use rhai::{FnRegister, Engine};
|
||||||
|
//!
|
||||||
|
//! fn compute_something(x: i64) -> bool {
|
||||||
|
//! (x % 40) == 0
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! let mut engine = Engine::new();
|
||||||
|
//! engine.register_fn("compute_something", compute_something);
|
||||||
|
//! # // Very ugly hack incoming, TODO
|
||||||
|
//! # use std::fs::{File, remove_file};
|
||||||
|
//! # use std::io::Write;
|
||||||
|
//! # use std::mem::drop;
|
||||||
|
//! # let mut f = File::create("my_script.rhai").unwrap();
|
||||||
|
//! # write!(f, "{}", "fn f(x) { if x == 1 { return 1; } x * f(x-1) } compute_something(f(10))");
|
||||||
|
//! assert!(engine.eval_file::<bool>("my_script.rhai").unwrap());
|
||||||
|
//! # let _ = remove_file("my_script.rhai");
|
||||||
|
//! ```
|
||||||
|
//!
|
||||||
|
//! [Check out the README on github for more information!](https://github.com/jonathandturner/rhai)
|
||||||
|
|
||||||
// lints required by Rhai
|
// lints required by Rhai
|
||||||
#![allow(unknown_lints,
|
#![allow(unknown_lints,
|
||||||
@ -16,3 +52,4 @@ mod tests;
|
|||||||
|
|
||||||
pub use engine::{Engine, Scope};
|
pub use engine::{Engine, Scope};
|
||||||
pub use fn_register::FnRegister;
|
pub use fn_register::FnRegister;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user