initial documentation (WIP)

This commit is contained in:
Lukáš Hozda 2017-10-28 22:33:00 +02:00
parent 1b22cab7dd
commit 47ce39062f
2 changed files with 89 additions and 2 deletions

View File

@ -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() };

View File

@ -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;