diff --git a/doc/src/start/examples/rust.md b/doc/src/start/examples/rust.md index 3784778d..b32d5529 100644 --- a/doc/src/start/examples/rust.md +++ b/doc/src/start/examples/rust.md @@ -3,7 +3,7 @@ Rust Examples {{#include ../../links.md}} -A number of examples can be found in the `examples` folder: +A number of examples can be found in the `examples` directory: | Example | Description | | ---------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | @@ -29,3 +29,12 @@ Examples can be run with the following command: ```bash cargo run --example {example_name} ``` + +`no-std` Samples +---------------- + +To illustrate `no-std` builds, a number of sample applications are available under the `no_std` directory: + +| Example | Environment | +| ------------------------------------------------------------------------------------- | :---------: | +| [`no_std_win`](https://github.com/jonathandturner/rhai/tree/master/no_std/no_std_win) | Windows API | diff --git a/doc/src/start/examples/scripts.md b/doc/src/start/examples/scripts.md index 20836aef..222b3604 100644 --- a/doc/src/start/examples/scripts.md +++ b/doc/src/start/examples/scripts.md @@ -6,7 +6,7 @@ Example Scripts Language Feature Scripts ----------------------- -There are also a number of examples scripts that showcase Rhai's features, all in the `scripts` folder: +There are also a number of examples scripts that showcase Rhai's features, all in the `scripts` directory: | Script | Description | | -------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | diff --git a/no_std/no_std_win/Cargo.toml b/no_std/no_std_win/Cargo.toml new file mode 100644 index 00000000..46140968 --- /dev/null +++ b/no_std/no_std_win/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "no_std_win" +version = "0.1.0" +edition = "2018" +authors = ["Stephen Chung"] +description = "no-std test application for the Windows API" +homepage = "https://github.com/jonathandturner/rhai/tree/master/no_std/no_std_win" +repository = "https://github.com/jonathandturner/rhai" + +[dependencies] +rhai = { path = "../../", features = [ "no_std" ], default_features = false } +wee_alloc = { version = "0.4.5", default_features = false } + +[profile.dev] +panic = "abort" + +[profile.release] +opt-level = "z" # optimize for size +debug = false +rpath = false +lto = "fat" +debug-assertions = false +codegen-units = 1 +panic = "abort" diff --git a/no_std/no_std_win/README.md b/no_std/no_std_win/README.md new file mode 100644 index 00000000..22af28b6 --- /dev/null +++ b/no_std/no_std_win/README.md @@ -0,0 +1,18 @@ +`no-std` Sample for Windows API +============================== + +This sample application is a bare-bones `no-std` build for the Windows API. + +[`wee_alloc`](https://crates.io/crates/wee_alloc) is used as the allocator. + + +To Compile +---------- + +The nightly compiler is required: + +```bash +cargo +nightly build --release +``` + +The release build is optimized for size. It can be changed to optimize on speed instead. diff --git a/no_std/no_std_win/src/main.rs b/no_std/no_std_win/src/main.rs new file mode 100644 index 00000000..4df87b2b --- /dev/null +++ b/no_std/no_std_win/src/main.rs @@ -0,0 +1,41 @@ +//! This is a `no-std` application for the Windows API that evaluates +//! a simple expression and uses the result as the return value. + +#![no_std] +#![feature(alloc_error_handler, start, core_intrinsics, lang_items)] + +extern crate alloc; +extern crate wee_alloc; + +#[global_allocator] +static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; + +use rhai::{Engine, INT}; + +#[start] +fn main(_argc: isize, _argv: *const *const u8) -> isize { + let engine = Engine::new(); + + // Evaluate a simple expression: 40 + 2 + engine.eval::("40 + 2").unwrap() as isize +} + +#[alloc_error_handler] +fn foo(_: core::alloc::Layout) -> ! { + core::intrinsics::abort(); +} + +#[panic_handler] +#[lang = "panic_impl"] +extern "C" fn rust_begin_panic(_: &core::panic::PanicInfo) -> ! { + core::intrinsics::abort(); +} + +#[lang = "eh_personality"] +extern "C" fn eh_personality() {} + +#[no_mangle] +extern "C" fn rust_eh_register_frames() {} + +#[no_mangle] +extern "C" fn rust_eh_unregister_frames() {} diff --git a/src/engine.rs b/src/engine.rs index 1466e015..25cbd2ca 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -1773,8 +1773,8 @@ impl Engine { Expr::CharConstant(x) => Ok(x.0.into()), Expr::FnPointer(x) => Ok(FnPtr::new_unchecked(x.0.clone()).into()), Expr::Variable(x) if (x.0).0 == KEYWORD_THIS => { - if let Some(ref val) = this_ptr { - Ok((*val).clone()) + if let Some(val) = this_ptr { + Ok(val.clone()) } else { Err(Box::new(EvalAltResult::ErrorUnboundedThis((x.0).1))) } @@ -1829,15 +1829,16 @@ impl Engine { // Not built in, map to `var = var op rhs` let op = &op[..op.len() - 1]; // extract operator without = let hash = calc_fn_hash(empty(), op, 2, empty()); + // Clone the LHS value let args = &mut [&mut lhs_ptr.clone(), &mut rhs_val]; - - // Set variable value - *lhs_ptr = self + // Run function + let (value, _) = self .exec_fn_call( state, lib, op, true, hash, args, false, false, None, level, ) - .map(|(v, _)| v) .map_err(|err| err.new_position(*op_pos))?; + // Set value to LHS + *lhs_ptr = value; } Ok(Default::default()) } @@ -2491,12 +2492,8 @@ impl Engine { for ((id, id_pos), rename) in list.iter() { // Mark scope variables as public if let Some(index) = scope.get_index(id).map(|(i, _)| i) { - let alias = rename - .as_ref() - .map(|(n, _)| n.clone()) - .unwrap_or_else(|| id.clone()); - - scope.set_entry_alias(index, alias); + let alias = rename.as_ref().map(|(n, _)| n).unwrap_or_else(|| id); + scope.set_entry_alias(index, alias.clone()); } else { return Err(Box::new(EvalAltResult::ErrorVariableNotFound( id.into(), diff --git a/src/optimize.rs b/src/optimize.rs index 945040ea..d47188a1 100644 --- a/src/optimize.rs +++ b/src/optimize.rs @@ -434,7 +434,7 @@ fn optimize_expr(expr: Expr, state: &mut State) -> Expr { (Expr::StringConstant(s), Expr::IntegerConstant(i)) if i.0 >= 0 && (i.0 as usize) < s.0.chars().count() => { // String literal indexing - get the character state.set_dirty(); - Expr::CharConstant(Box::new((s.0.chars().nth(i.0 as usize).expect("should get char"), s.1))) + Expr::CharConstant(Box::new((s.0.chars().nth(i.0 as usize).unwrap(), s.1))) } // lhs[rhs] (lhs, rhs) => Expr::Index(Box::new((optimize_expr(lhs, state), optimize_expr(rhs, state), x.2))), @@ -614,7 +614,7 @@ fn optimize_expr(expr: Expr, state: &mut State) -> Expr { state.set_dirty(); // Replace constant with value - state.find_constant(&name).expect("should find constant in scope!").clone().set_position(pos) + state.find_constant(&name).unwrap().clone().set_position(pos) } // Custom syntax @@ -655,10 +655,7 @@ fn optimize( && expr.as_ref().map(|v| v.is_constant()).unwrap_or(false) }) .for_each(|ScopeEntry { name, expr, .. }| { - state.push_constant( - name.as_ref(), - (**expr.as_ref().expect("should be Some(expr)")).clone(), - ) + state.push_constant(name.as_ref(), expr.as_ref().unwrap().as_ref().clone()) }); let orig_constants_len = state.constants.len();