Added no_std support
This commit is contained in:
parent
bffa3ed636
commit
c8a9df0a0a
13
.ci/build.sh
Executable file
13
.ci/build.sh
Executable file
@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
cargo build --verbose
|
||||
cargo test --verbose
|
||||
|
||||
if [ "$TRAVIS_RUST_VERSION" = "nightly" ]
|
||||
then
|
||||
cargo build --verbose --features no_stdlib
|
||||
cargo test --verbose --features no_stdlib
|
||||
fi
|
||||
|
@ -6,3 +6,5 @@ rust:
|
||||
matrix:
|
||||
allow_failures:
|
||||
- rust: nightly
|
||||
|
||||
script: bash ./.ci/build.sh
|
24
Cargo.toml
24
Cargo.toml
@ -15,14 +15,34 @@ include = [
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
num-traits = "*"
|
||||
num-traits = "0.2.11"
|
||||
|
||||
[dependencies.libm]
|
||||
version = "0.2.1"
|
||||
optional = true
|
||||
|
||||
[dependencies.core-error]
|
||||
version = "0.0.1-rc4"
|
||||
features = ["alloc"]
|
||||
optional = true
|
||||
|
||||
[dependencies.hashbrown]
|
||||
version = "0.7.1"
|
||||
default-features = false
|
||||
features = ["ahash", "nightly", "inline-more"]
|
||||
optional = true
|
||||
|
||||
[dependencies.ahash]
|
||||
version = "0.3.2"
|
||||
default-features = false
|
||||
optional = true
|
||||
|
||||
[features]
|
||||
#default = ["no_function", "no_index", "no_float", "only_i32", "no_stdlib", "unchecked", "no_optimize"]
|
||||
default = [ "optimize_full" ]
|
||||
debug_msgs = [] # print debug messages on function registrations and calls
|
||||
unchecked = [] # unchecked arithmetic
|
||||
no_stdlib = [] # no standard library of utility functions
|
||||
no_stdlib = ["num-traits/libm", "hashbrown", "core-error", "libm"] # no standard library of utility functions
|
||||
no_index = [] # no arrays and indexing
|
||||
no_float = [] # no floating-point
|
||||
no_function = [] # no script-defined functions
|
||||
|
@ -1,7 +1,8 @@
|
||||
//! Helper module which defines the `Any` trait to to allow dynamic value handling.
|
||||
|
||||
use std::{
|
||||
any::{type_name, TypeId},
|
||||
use crate::stdlib::{
|
||||
any::{self, type_name, TypeId},
|
||||
boxed::Box,
|
||||
fmt,
|
||||
};
|
||||
|
||||
@ -12,7 +13,7 @@ pub type Variant = dyn Any;
|
||||
pub type Dynamic = Box<Variant>;
|
||||
|
||||
/// A trait covering any type.
|
||||
pub trait Any: std::any::Any {
|
||||
pub trait Any: any::Any {
|
||||
/// Get the `TypeId` of this type.
|
||||
fn type_id(&self) -> TypeId;
|
||||
|
||||
@ -27,7 +28,7 @@ pub trait Any: std::any::Any {
|
||||
fn _closed(&self) -> _Private;
|
||||
}
|
||||
|
||||
impl<T: Clone + std::any::Any + ?Sized> Any for T {
|
||||
impl<T: Clone + any::Any + ?Sized> Any for T {
|
||||
fn type_id(&self) -> TypeId {
|
||||
TypeId::of::<T>()
|
||||
}
|
||||
|
17
src/api.rs
17
src/api.rs
@ -12,13 +12,15 @@ use crate::scope::Scope;
|
||||
#[cfg(not(feature = "no_optimize"))]
|
||||
use crate::optimize::optimize_ast;
|
||||
|
||||
use std::{
|
||||
use crate::stdlib::{
|
||||
any::{type_name, TypeId},
|
||||
fs::File,
|
||||
io::prelude::*,
|
||||
path::PathBuf,
|
||||
boxed::Box,
|
||||
string::{String, ToString},
|
||||
sync::Arc,
|
||||
vec::Vec,
|
||||
};
|
||||
#[cfg(not(feature = "no_stdlib"))]
|
||||
use crate::stdlib::{fs::File, io::prelude::*, path::PathBuf};
|
||||
|
||||
impl<'e> Engine<'e> {
|
||||
pub(crate) fn register_fn_raw(
|
||||
@ -115,6 +117,7 @@ impl<'e> Engine<'e> {
|
||||
parse(&mut tokens_stream.peekable(), self, scope)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_stdlib"))]
|
||||
fn read_file(path: PathBuf) -> Result<String, EvalAltResult> {
|
||||
let mut f = File::open(path.clone())
|
||||
.map_err(|err| EvalAltResult::ErrorReadingScriptFile(path.clone(), err))?;
|
||||
@ -127,12 +130,14 @@ impl<'e> Engine<'e> {
|
||||
}
|
||||
|
||||
/// Compile a file into an AST.
|
||||
#[cfg(not(feature = "no_stdlib"))]
|
||||
pub fn compile_file(&self, path: PathBuf) -> Result<AST, EvalAltResult> {
|
||||
self.compile_file_with_scope(&Scope::new(), path)
|
||||
}
|
||||
|
||||
/// Compile a file into an AST using own scope.
|
||||
/// The scope is useful for passing constants into the script for optimization.
|
||||
#[cfg(not(feature = "no_stdlib"))]
|
||||
pub fn compile_file_with_scope(
|
||||
&self,
|
||||
scope: &Scope,
|
||||
@ -145,11 +150,13 @@ impl<'e> Engine<'e> {
|
||||
}
|
||||
|
||||
/// Evaluate a file.
|
||||
#[cfg(not(feature = "no_stdlib"))]
|
||||
pub fn eval_file<T: Any + Clone>(&mut self, path: PathBuf) -> Result<T, EvalAltResult> {
|
||||
Self::read_file(path).and_then(|contents| self.eval::<T>(&contents))
|
||||
}
|
||||
|
||||
/// Evaluate a file with own scope.
|
||||
#[cfg(not(feature = "no_stdlib"))]
|
||||
pub fn eval_file_with_scope<T: Any + Clone>(
|
||||
&mut self,
|
||||
scope: &mut Scope,
|
||||
@ -234,6 +241,7 @@ impl<'e> Engine<'e> {
|
||||
///
|
||||
/// Note - if `retain_functions` is set to `true`, functions defined by previous scripts are _retained_
|
||||
/// and not cleared from run to run.
|
||||
#[cfg(not(feature = "no_stdlib"))]
|
||||
pub fn consume_file(
|
||||
&mut self,
|
||||
retain_functions: bool,
|
||||
@ -247,6 +255,7 @@ impl<'e> Engine<'e> {
|
||||
///
|
||||
/// Note - if `retain_functions` is set to `true`, functions defined by previous scripts are _retained_
|
||||
/// and not cleared from run to run.
|
||||
#[cfg(not(feature = "no_stdlib"))]
|
||||
pub fn consume_file_with_scope(
|
||||
&mut self,
|
||||
scope: &mut Scope,
|
||||
|
@ -17,9 +17,12 @@ use num_traits::{
|
||||
CheckedShr, CheckedSub,
|
||||
};
|
||||
|
||||
use std::{
|
||||
use crate::stdlib::{
|
||||
boxed::Box,
|
||||
fmt::{Debug, Display},
|
||||
format,
|
||||
ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Range, Rem, Shl, Shr, Sub},
|
||||
string::{String, ToString},
|
||||
{i32, i64, u32},
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
//! Helper module which defines `FnArgs` to make function calling easier.
|
||||
|
||||
use crate::any::{Any, Dynamic};
|
||||
use crate::stdlib::{string::String, vec, vec::Vec};
|
||||
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
use crate::engine::Array;
|
||||
|
@ -11,12 +11,17 @@ use crate::optimize::OptimizationLevel;
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
use crate::INT;
|
||||
|
||||
use std::{
|
||||
use crate::stdlib::{
|
||||
any::{type_name, TypeId},
|
||||
borrow::Cow,
|
||||
boxed::Box,
|
||||
collections::HashMap,
|
||||
format,
|
||||
iter::once,
|
||||
string::{String, ToString},
|
||||
sync::Arc,
|
||||
vec,
|
||||
vec::Vec,
|
||||
};
|
||||
|
||||
/// An dynamic array of `Dynamic` values.
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! Module containing error definitions for the parsing process.
|
||||
|
||||
use crate::parser::Position;
|
||||
use std::{char, error::Error, fmt};
|
||||
use crate::stdlib::{char, error::Error, fmt, string::String};
|
||||
|
||||
/// Error when tokenizing the script text.
|
||||
#[derive(Debug, Eq, PartialEq, Hash, Clone)]
|
||||
|
@ -4,7 +4,7 @@ use crate::any::{Any, Dynamic};
|
||||
use crate::engine::{Engine, FnCallArgs};
|
||||
use crate::parser::Position;
|
||||
use crate::result::EvalAltResult;
|
||||
use std::any::TypeId;
|
||||
use crate::stdlib::{any::TypeId, boxed::Box, string::ToString, vec};
|
||||
|
||||
/// A trait to register custom functions with the `Engine`.
|
||||
///
|
||||
|
@ -16,7 +16,7 @@
|
||||
//!
|
||||
//! And the Rust part:
|
||||
//!
|
||||
//! ```rust,no_run
|
||||
//! ```rust,ignore
|
||||
//! use rhai::{Engine, EvalAltResult, RegisterFn};
|
||||
//!
|
||||
//! fn main() -> Result<(), EvalAltResult>
|
||||
@ -37,8 +37,12 @@
|
||||
//!
|
||||
//! [Check out the README on GitHub for more information!](https://github.com/jonathandturner/rhai)
|
||||
|
||||
#![cfg_attr(feature = "no_stdlib", no_std)]
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
#[cfg(feature = "no_stdlib")]
|
||||
extern crate alloc;
|
||||
|
||||
// needs to be here, because order matters for macros
|
||||
macro_rules! debug_println {
|
||||
() => (
|
||||
@ -61,6 +65,8 @@ macro_rules! debug_println {
|
||||
);
|
||||
}
|
||||
|
||||
#[macro_use]
|
||||
mod stdlib;
|
||||
mod any;
|
||||
mod api;
|
||||
mod builtin;
|
||||
|
@ -5,7 +5,11 @@ use crate::engine::{Engine, FnCallArgs, KEYWORD_DEBUG, KEYWORD_DUMP_AST, KEYWORD
|
||||
use crate::parser::{map_dynamic_to_expr, Expr, FnDef, Stmt, AST};
|
||||
use crate::scope::{Scope, ScopeEntry, VariableType};
|
||||
|
||||
use std::sync::Arc;
|
||||
use crate::stdlib::{
|
||||
sync::Arc,
|
||||
vec::Vec, string::{String, ToString},
|
||||
boxed::Box, vec,
|
||||
};
|
||||
|
||||
/// Level of optimization performed
|
||||
#[derive(Debug, Eq, PartialEq, Hash, Clone, Copy)]
|
||||
|
@ -8,9 +8,19 @@ use crate::scope::{Scope, VariableType};
|
||||
#[cfg(not(feature = "no_optimize"))]
|
||||
use crate::optimize::optimize_ast;
|
||||
|
||||
use std::{
|
||||
borrow::Cow, char, cmp::Ordering, fmt, iter::Peekable, str::Chars, str::FromStr, sync::Arc,
|
||||
usize,
|
||||
use crate::stdlib::{
|
||||
borrow::Cow,
|
||||
boxed::Box,
|
||||
char,
|
||||
cmp::Ordering,
|
||||
fmt, format,
|
||||
iter::Peekable,
|
||||
str::Chars,
|
||||
str::FromStr,
|
||||
string::{String, ToString},
|
||||
sync::Arc,
|
||||
usize, vec,
|
||||
vec::Vec,
|
||||
};
|
||||
|
||||
/// The system integer type.
|
||||
|
@ -4,7 +4,14 @@ use crate::any::Dynamic;
|
||||
use crate::error::ParseError;
|
||||
use crate::parser::{Position, INT};
|
||||
|
||||
use std::{error::Error, fmt, path::PathBuf};
|
||||
use crate::stdlib::{
|
||||
error::Error,
|
||||
fmt,
|
||||
string::{String, ToString},
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "no_stdlib"))]
|
||||
use crate::stdlib::path::PathBuf;
|
||||
|
||||
/// Evaluation result.
|
||||
///
|
||||
@ -47,6 +54,7 @@ pub enum EvalAltResult {
|
||||
/// Wrapped value is the type of the actual result.
|
||||
ErrorMismatchOutputType(String, Position),
|
||||
/// Error reading from a script file. Wrapped value is the path of the script file.
|
||||
#[cfg(not(feature = "no_stdlib"))]
|
||||
ErrorReadingScriptFile(PathBuf, std::io::Error),
|
||||
/// Inappropriate member access.
|
||||
ErrorDotExpr(String, Position),
|
||||
@ -93,6 +101,7 @@ impl EvalAltResult {
|
||||
}
|
||||
Self::ErrorAssignmentToConstant(_, _) => "Assignment to a constant variable",
|
||||
Self::ErrorMismatchOutputType(_, _) => "Output type is incorrect",
|
||||
#[cfg(not(feature = "no_stdlib"))]
|
||||
Self::ErrorReadingScriptFile(_, _) => "Cannot read from script file",
|
||||
Self::ErrorDotExpr(_, _) => "Malformed dot expression",
|
||||
Self::ErrorArithmetic(_, _) => "Arithmetic error",
|
||||
@ -127,6 +136,7 @@ impl fmt::Display for EvalAltResult {
|
||||
}
|
||||
Self::LoopBreak => write!(f, "{}", desc),
|
||||
Self::Return(_, pos) => write!(f, "{} ({})", desc, pos),
|
||||
#[cfg(not(feature = "no_stdlib"))]
|
||||
Self::ErrorReadingScriptFile(path, err) => {
|
||||
write!(f, "{} '{}': {}", desc, path.display(), err)
|
||||
}
|
||||
@ -199,7 +209,9 @@ impl<T: AsRef<str>> From<T> for EvalAltResult {
|
||||
impl EvalAltResult {
|
||||
pub fn position(&self) -> Position {
|
||||
match self {
|
||||
Self::ErrorReadingScriptFile(_, _) | Self::LoopBreak => Position::none(),
|
||||
#[cfg(not(feature = "no_stdlib"))]
|
||||
Self::ErrorReadingScriptFile(_, _) => Position::none(),
|
||||
Self::LoopBreak => Position::none(),
|
||||
|
||||
Self::ErrorParsing(err) => err.position(),
|
||||
|
||||
@ -226,7 +238,9 @@ impl EvalAltResult {
|
||||
|
||||
pub(crate) fn set_position(&mut self, new_position: Position) {
|
||||
match self {
|
||||
Self::ErrorReadingScriptFile(_, _) | Self::LoopBreak => (),
|
||||
#[cfg(not(feature = "no_stdlib"))]
|
||||
Self::ErrorReadingScriptFile(_, _) => (),
|
||||
Self::LoopBreak => (),
|
||||
|
||||
Self::ErrorParsing(ParseError(_, ref mut pos))
|
||||
| Self::ErrorFunctionNotFound(_, ref mut pos)
|
||||
|
@ -3,7 +3,12 @@
|
||||
use crate::any::{Any, Dynamic};
|
||||
use crate::parser::{map_dynamic_to_expr, Expr, Position};
|
||||
|
||||
use std::borrow::Cow;
|
||||
use crate::stdlib::{
|
||||
borrow::Cow,
|
||||
iter,
|
||||
string::{String, ToString},
|
||||
vec::Vec,
|
||||
};
|
||||
|
||||
/// Type of a variable in the Scope.
|
||||
#[derive(Debug, Eq, PartialEq, Hash, Copy, Clone)]
|
||||
@ -193,7 +198,7 @@ impl<'a> Scope<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K> std::iter::Extend<(K, VariableType, Dynamic)> for Scope<'a>
|
||||
impl<'a, K> iter::Extend<(K, VariableType, Dynamic)> for Scope<'a>
|
||||
where
|
||||
K: Into<Cow<'a, str>>,
|
||||
{
|
||||
|
23
src/stdlib.rs
Normal file
23
src/stdlib.rs
Normal file
@ -0,0 +1,23 @@
|
||||
#[cfg(feature = "no_stdlib")]
|
||||
mod inner {
|
||||
pub use core::{
|
||||
any, arch, array, ascii, cell, char, clone, cmp, convert, default, f32, f64, ffi, fmt,
|
||||
future, hash, hint, i128, i16, i32, i64, i8, isize, iter, marker, mem, num, ops, option,
|
||||
panic, pin, prelude, ptr, result, slice, str, task, time, u128, u16, u32, u64, u8, usize,
|
||||
};
|
||||
|
||||
pub use alloc::{borrow, boxed, format, string, sync, vec};
|
||||
|
||||
pub use core_error as error;
|
||||
|
||||
pub mod collections {
|
||||
pub use hashbrown::HashMap;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_stdlib"))]
|
||||
mod inner {
|
||||
pub use std::*;
|
||||
}
|
||||
|
||||
pub use self::inner::*;
|
Loading…
Reference in New Issue
Block a user