Merge pull request #200 from schungx/master
Documentation improvements and syncing up.
This commit is contained in:
commit
fc891dcdac
29
.github/workflows/benchmark.yml
vendored
Normal file
29
.github/workflows/benchmark.yml
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
name: Benchmark
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
benchmark:
|
||||
name: Run Rust benchmark
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: rustup toolchain update nightly && rustup default nightly
|
||||
- name: Run benchmark
|
||||
run: cargo +nightly bench | tee output.txt
|
||||
- name: Store benchmark result
|
||||
uses: rhysd/github-action-benchmark@v1
|
||||
with:
|
||||
name: Rust Benchmark
|
||||
tool: 'cargo'
|
||||
output-file-path: output.txt
|
||||
# Use personal access token instead of GITHUB_TOKEN due to https://github.community/t5/GitHub-Actions/Github-action-not-triggering-gh-pages-upon-push/td-p/26869/highlight/false
|
||||
github-token: ${{ secrets.RHAI }}
|
||||
auto-push: true
|
||||
# Show alert with commit comment on detecting possible performance regression
|
||||
alert-threshold: '200%'
|
||||
comment-on-alert: true
|
||||
fail-on-alert: true
|
||||
alert-comment-cc-users: '@schungx'
|
@ -75,3 +75,6 @@ optional = true
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
instant= { version = "0.1.4", features = ["wasm-bindgen"] } # WASM implementation of std::time::Instant
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = [ "serde", "internals" ]
|
||||
|
14
README.md
14
README.md
@ -68,9 +68,13 @@ Scripts can be evaluated directly from the editor.
|
||||
License
|
||||
-------
|
||||
|
||||
Licensed under either of <a href="LICENSE-APACHE.txt">Apache License, Version
|
||||
2.0</a> or <a href="LICENSE-MIT.txt">MIT license</a> at your option.
|
||||
Licensed under either:
|
||||
|
||||
Unless you explicitly state otherwise, any contribution intentionally submitted
|
||||
for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
|
||||
be dual licensed as above, without any additional terms or conditions.
|
||||
* [Apache License, Version 2.0](https://github.com/jonathandturner/rhai/blob/master/LICENSE-APACHE.txt), or
|
||||
* [MIT license](https://github.com/jonathandturner/rhai/blob/master/LICENSE-MIT.txt)
|
||||
|
||||
at your option.
|
||||
|
||||
Unless explicitly stated otherwise, any contribution intentionally submitted
|
||||
for inclusion in this crate, as defined in the Apache-2.0 license, shall
|
||||
be dual-licensed as above, without any additional terms or conditions.
|
||||
|
@ -18,6 +18,7 @@ New features
|
||||
* Anonymous functions in the syntax of a closure, e.g. `|x, y, z| x + y - z`.
|
||||
* Custom syntax now works even without the `internals` feature.
|
||||
* Currying of function pointers is supported via the `curry` keyword.
|
||||
* `Module::set_indexer_get_set_fn` is added as a shorthand of both `Module::set_indexer_get_fn` and `Module::set_indexer_set_fn`.
|
||||
|
||||
Breaking changes
|
||||
----------------
|
||||
|
@ -34,9 +34,9 @@ mod private {
|
||||
use crate::fn_native::SendSync;
|
||||
use crate::stdlib::any::Any;
|
||||
|
||||
/// A sealed trait that prevents other crates from implementing [Variant].
|
||||
/// A sealed trait that prevents other crates from implementing [`Variant`].
|
||||
///
|
||||
/// [Variant]: super::Variant
|
||||
/// [`Variant`]: super::Variant
|
||||
pub trait Sealed {}
|
||||
|
||||
impl<T: Any + Clone + SendSync> Sealed for T {}
|
||||
@ -810,8 +810,3 @@ impl From<Box<FnPtr>> for Dynamic {
|
||||
Self(Union::FnPtr(value))
|
||||
}
|
||||
}
|
||||
|
||||
/// Private type which ensures that `rhai::Any` and `rhai::AnyExt` can only
|
||||
/// be implemented by this crate.
|
||||
#[doc(hidden)]
|
||||
pub struct _Private;
|
||||
|
@ -11,7 +11,7 @@ use crate::parser::{Expr, FnAccess, ImmutableString, ReturnType, ScriptFnDef, St
|
||||
use crate::r#unsafe::unsafe_cast_var_name_to_lifetime;
|
||||
use crate::result::EvalAltResult;
|
||||
use crate::scope::{EntryType as ScopeEntryType, Scope};
|
||||
use crate::syntax::{CustomSyntax, EvalContext, Expression};
|
||||
use crate::syntax::{CustomSyntax, EvalContext};
|
||||
use crate::token::Position;
|
||||
use crate::utils::StaticVec;
|
||||
|
||||
@ -38,7 +38,12 @@ pub type Array = Vec<Dynamic>;
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
pub type Map = HashMap<ImmutableString, Dynamic>;
|
||||
|
||||
/// A stack of imported modules.
|
||||
/// [INTERNALS] A stack of imported modules.
|
||||
/// Exported under the `internals` feature only.
|
||||
///
|
||||
/// ## WARNING
|
||||
///
|
||||
/// This type is volatile and may change.
|
||||
pub type Imports<'a> = Vec<(Cow<'a, str>, Module)>;
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
@ -189,12 +194,17 @@ impl<T: Into<Dynamic>> From<T> for Target<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A type that holds all the current states of the Engine.
|
||||
/// [INTERNALS] A type that holds all the current states of the Engine.
|
||||
/// Exported under the `internals` feature only.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This type uses some unsafe code, mainly for avoiding cloning of local variable names via
|
||||
/// direct lifetime casting.
|
||||
///
|
||||
/// ## WARNING
|
||||
///
|
||||
/// This type is volatile and may change.
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash, Default)]
|
||||
pub struct State {
|
||||
/// Normally, access to variables are parsed with a relative offset into the scope to avoid a lookup.
|
||||
@ -1020,7 +1030,7 @@ impl Engine {
|
||||
map.entry(index).or_insert(Default::default()).into()
|
||||
} else {
|
||||
let index = idx
|
||||
.downcast_ref::<String>()
|
||||
.downcast_ref::<ImmutableString>()
|
||||
.ok_or_else(|| EvalAltResult::ErrorStringIndexExpr(idx_pos))?;
|
||||
|
||||
map.get_mut(index.as_str())
|
||||
@ -1050,22 +1060,20 @@ impl Engine {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
_ => {
|
||||
let val_type_name = val.type_name();
|
||||
let type_name = val.type_name();
|
||||
let args = &mut [val, &mut idx];
|
||||
self.exec_fn_call(
|
||||
state, lib, FN_IDX_GET, true, 0, args, is_ref, true, None, level,
|
||||
)
|
||||
.map(|(v, _)| v.into())
|
||||
.map_err(|e| match *e {
|
||||
EvalAltResult::ErrorFunctionNotFound(..) => {
|
||||
Box::new(EvalAltResult::ErrorIndexingType(
|
||||
self.map_type_name(val_type_name).into(),
|
||||
Position::none(),
|
||||
))
|
||||
}
|
||||
_ => e,
|
||||
.map_err(|err| match *err {
|
||||
EvalAltResult::ErrorFunctionNotFound(_, _) => Box::new(
|
||||
EvalAltResult::ErrorIndexingType(type_name.into(), Position::none()),
|
||||
),
|
||||
_ => err,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,12 @@ use crate::stdlib::{
|
||||
string::{String, ToString},
|
||||
};
|
||||
|
||||
/// Error when tokenizing the script text.
|
||||
/// [INTERNALS] Error encountered when tokenizing the script text.
|
||||
/// Exported under the `internals` feature only.
|
||||
///
|
||||
/// ## WARNING
|
||||
///
|
||||
/// This type is volatile and may change.
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
|
||||
#[non_exhaustive]
|
||||
pub enum LexError {
|
||||
|
@ -5,12 +5,13 @@ use crate::engine::Engine;
|
||||
use crate::module::{FuncReturn, Module};
|
||||
use crate::parser::ScriptFnDef;
|
||||
use crate::result::EvalAltResult;
|
||||
use crate::stdlib::vec::Vec;
|
||||
use crate::token::{is_valid_identifier, Position};
|
||||
use crate::utils::{ImmutableString, StaticVec};
|
||||
use crate::Scope;
|
||||
|
||||
use crate::stdlib::{boxed::Box, convert::TryFrom, fmt, mem, rc::Rc, string::String, sync::Arc};
|
||||
use crate::stdlib::{
|
||||
boxed::Box, convert::TryFrom, fmt, mem, rc::Rc, string::String, sync::Arc, vec::Vec,
|
||||
};
|
||||
|
||||
/// Trait that maps to `Send + Sync` only under the `sync` feature.
|
||||
#[cfg(feature = "sync")]
|
||||
|
@ -166,7 +166,7 @@ pub use token::{get_next_token, parse_string_literal, InputStream, Token, Tokeni
|
||||
|
||||
#[cfg(feature = "internals")]
|
||||
#[deprecated(note = "this type is volatile and may change")]
|
||||
pub use parser::{CustomExpr, Expr, ReturnType, ScriptFnDef, Stmt};
|
||||
pub use parser::{CustomExpr, Expr, FloatWrapper, ReturnType, ScriptFnDef, Stmt};
|
||||
|
||||
#[cfg(feature = "internals")]
|
||||
#[deprecated(note = "this type is volatile and may change")]
|
||||
|
@ -758,6 +758,40 @@ impl Module {
|
||||
)
|
||||
}
|
||||
|
||||
/// Set a pair of Rust index getter and setter functions, returning both hash keys.
|
||||
/// This is a shorthand for `set_indexer_get_fn` and `set_indexer_set_fn`.
|
||||
///
|
||||
/// If there are similar existing Rust functions, they are replaced.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use rhai::{Module, ImmutableString};
|
||||
///
|
||||
/// let mut module = Module::new();
|
||||
/// let (hash_get, hash_set) = module.set_indexer_get_set_fn(
|
||||
/// |x: &mut i64, y: ImmutableString| {
|
||||
/// Ok(*x + y.len() as i64)
|
||||
/// },
|
||||
/// |x: &mut i64, y: ImmutableString, value: i64| {
|
||||
/// *x = y.len() as i64 + value;
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// );
|
||||
/// assert!(module.contains_fn(hash_get));
|
||||
/// assert!(module.contains_fn(hash_set));
|
||||
/// ```
|
||||
pub fn set_indexer_get_set_fn<A: Variant + Clone, B: Variant + Clone, T: Variant + Clone>(
|
||||
&mut self,
|
||||
getter: impl Fn(&mut A, B) -> FuncReturn<T> + SendSync + 'static,
|
||||
setter: impl Fn(&mut A, B, T) -> FuncReturn<()> + SendSync + 'static,
|
||||
) -> (u64, u64) {
|
||||
(
|
||||
self.set_indexer_get_fn(getter),
|
||||
self.set_indexer_set_fn(setter),
|
||||
)
|
||||
}
|
||||
|
||||
/// Set a Rust function taking four parameters into the module, returning a hash key.
|
||||
///
|
||||
/// If there is a similar existing Rust function, it is replaced.
|
||||
@ -1094,11 +1128,17 @@ impl Module {
|
||||
}
|
||||
}
|
||||
|
||||
/// A chain of module names to qualify a variable or function call.
|
||||
/// A `u64` hash key is kept for quick search purposes.
|
||||
/// [INTERNALS] A chain of module names to qualify a variable or function call.
|
||||
/// Exported under the `internals` feature only.
|
||||
///
|
||||
/// A `u64` hash key is cached for quick search purposes.
|
||||
///
|
||||
/// A `StaticVec` is used because most module-level access contains only one level,
|
||||
/// and it is wasteful to always allocate a `Vec` with one element.
|
||||
///
|
||||
/// ## WARNING
|
||||
///
|
||||
/// This type is volatile and may change.
|
||||
#[derive(Clone, Eq, PartialEq, Default, Hash)]
|
||||
pub struct ModuleRef(StaticVec<(String, Position)>, Option<NonZeroUsize>);
|
||||
|
||||
|
@ -456,7 +456,7 @@ fn optimize_expr(expr: Expr, state: &mut State) -> Expr {
|
||||
// "xxx" in "xxxxx"
|
||||
(Expr::StringConstant(a), Expr::StringConstant(b)) => {
|
||||
state.set_dirty();
|
||||
if b.0.contains(a.0.as_ref()) { Expr::True(a.1) } else { Expr::False(a.1) }
|
||||
if b.0.contains(a.0.as_str()) { Expr::True(a.1) } else { Expr::False(a.1) }
|
||||
}
|
||||
// 'x' in "xxxxx"
|
||||
(Expr::CharConstant(a), Expr::StringConstant(b)) => {
|
||||
@ -560,7 +560,7 @@ fn optimize_expr(expr: Expr, state: &mut State) -> Expr {
|
||||
let has_script_fn = state.lib.iter_fn().find(|(_, _, _, f)| {
|
||||
if !f.is_script() { return false; }
|
||||
let fn_def = f.get_fn_def();
|
||||
&fn_def.name == name && (args.len()..=args.len() + 1).contains(&fn_def.params.len())
|
||||
fn_def.name.as_str() == name && (args.len()..=args.len() + 1).contains(&fn_def.params.len())
|
||||
}).is_some();
|
||||
|
||||
#[cfg(feature = "no_function")]
|
||||
|
@ -342,11 +342,16 @@ impl fmt::Display for FnAccess {
|
||||
}
|
||||
}
|
||||
|
||||
/// A scripted function definition.
|
||||
/// [INTERNALS] A type containing information on a scripted function.
|
||||
/// Exported under the `internals` feature only.
|
||||
///
|
||||
/// ## WARNING
|
||||
///
|
||||
/// This type is volatile and may change.
|
||||
#[derive(Debug, Clone, Hash)]
|
||||
pub struct ScriptFnDef {
|
||||
/// Function name.
|
||||
pub name: String,
|
||||
pub name: ImmutableString,
|
||||
/// Function access mode.
|
||||
pub access: FnAccess,
|
||||
/// Names of function parameters.
|
||||
@ -376,7 +381,12 @@ impl fmt::Display for ScriptFnDef {
|
||||
}
|
||||
}
|
||||
|
||||
/// `return`/`throw` statement.
|
||||
/// [INTERNALS] A type encapsulating the mode of a `return`/`throw` statement.
|
||||
/// Exported under the `internals` feature only.
|
||||
///
|
||||
/// ## WARNING
|
||||
///
|
||||
/// This type is volatile and may change.
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash)]
|
||||
pub enum ReturnType {
|
||||
/// `return` statement.
|
||||
@ -477,7 +487,8 @@ impl ParseSettings {
|
||||
}
|
||||
}
|
||||
|
||||
/// A statement.
|
||||
/// [INTERNALS] A Rhai statement.
|
||||
/// Exported under the `internals` feature only.
|
||||
///
|
||||
/// Each variant is at most one pointer in size (for speed),
|
||||
/// with everything being allocated together in one single tuple.
|
||||
@ -582,6 +593,12 @@ impl Stmt {
|
||||
}
|
||||
}
|
||||
|
||||
/// [INTERNALS] A type wrapping a custom syntax definition.
|
||||
/// Exported under the `internals` feature only.
|
||||
///
|
||||
/// ## WARNING
|
||||
///
|
||||
/// This type is volatile and may change.
|
||||
#[derive(Clone)]
|
||||
pub struct CustomExpr(pub StaticVec<Expr>, pub Shared<FnCustomSyntaxEval>);
|
||||
|
||||
@ -597,6 +614,15 @@ impl Hash for CustomExpr {
|
||||
}
|
||||
}
|
||||
|
||||
/// [INTERNALS] A type wrapping a floating-point number.
|
||||
/// Exported under the `internals` feature only.
|
||||
///
|
||||
/// This type is mainly used to provide a standard `Hash` implementation
|
||||
/// to floating-point numbers, allowing `Expr` to derive `Hash` automatically.
|
||||
///
|
||||
/// ## WARNING
|
||||
///
|
||||
/// This type is volatile and may change.
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
#[derive(Debug, PartialEq, PartialOrd, Clone)]
|
||||
pub struct FloatWrapper(pub FLOAT, pub Position);
|
||||
@ -609,10 +635,15 @@ impl Hash for FloatWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
/// An expression.
|
||||
/// [INTERNALS] An expression sub-tree.
|
||||
/// Exported under the `internals` feature only.
|
||||
///
|
||||
/// Each variant is at most one pointer in size (for speed),
|
||||
/// with everything being allocated together in one single tuple.
|
||||
///
|
||||
/// ## WARNING
|
||||
///
|
||||
/// This type is volatile and may change.
|
||||
#[derive(Debug, Clone, Hash)]
|
||||
pub enum Expr {
|
||||
/// Integer constant.
|
||||
@ -2852,7 +2883,7 @@ fn parse_fn(
|
||||
let params = params.into_iter().map(|(p, _)| p).collect();
|
||||
|
||||
Ok(ScriptFnDef {
|
||||
name,
|
||||
name: name.into(),
|
||||
access,
|
||||
params,
|
||||
body,
|
||||
@ -2940,7 +2971,7 @@ fn parse_anon_fn(
|
||||
let hash = s.finish();
|
||||
|
||||
// Create unique function name
|
||||
let fn_name = format!("{}{}", FN_ANONYMOUS, hash);
|
||||
let fn_name: ImmutableString = format!("{}{:16x}", FN_ANONYMOUS, hash).into();
|
||||
|
||||
let script = ScriptFnDef {
|
||||
name: fn_name.clone(),
|
||||
@ -2950,7 +2981,7 @@ fn parse_anon_fn(
|
||||
pos: settings.pos,
|
||||
};
|
||||
|
||||
let expr = Expr::FnPointer(Box::new((fn_name.into(), settings.pos)));
|
||||
let expr = Expr::FnPointer(Box::new((fn_name, settings.pos)));
|
||||
|
||||
Ok((expr, script))
|
||||
}
|
||||
|
124
src/token.rs
124
src/token.rs
@ -136,89 +136,181 @@ impl fmt::Debug for Position {
|
||||
}
|
||||
}
|
||||
|
||||
/// Tokens.
|
||||
/// [INTERNALS] A Rhai language token.
|
||||
/// Exported under the `internals` feature only.
|
||||
///
|
||||
/// ## WARNING
|
||||
///
|
||||
/// This type is volatile and may change.
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum Token {
|
||||
/// An `INT` constant.
|
||||
IntegerConstant(INT),
|
||||
/// A `FLOAT` constaint.
|
||||
///
|
||||
/// Never appears under the `no_float` feature.
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
FloatConstant(FLOAT),
|
||||
/// An identifier.
|
||||
Identifier(String),
|
||||
/// A character constant.
|
||||
CharConstant(char),
|
||||
/// A string constant.
|
||||
StringConstant(String),
|
||||
/// `{`
|
||||
LeftBrace,
|
||||
/// `}`
|
||||
RightBrace,
|
||||
/// `(`
|
||||
LeftParen,
|
||||
/// `)`
|
||||
RightParen,
|
||||
/// `[`
|
||||
LeftBracket,
|
||||
/// `]`
|
||||
RightBracket,
|
||||
/// `+`
|
||||
Plus,
|
||||
/// `+` (unary)
|
||||
UnaryPlus,
|
||||
/// `-`
|
||||
Minus,
|
||||
/// `-` (unary)
|
||||
UnaryMinus,
|
||||
/// `*`
|
||||
Multiply,
|
||||
/// `/`
|
||||
Divide,
|
||||
/// `%`
|
||||
Modulo,
|
||||
/// `~`
|
||||
PowerOf,
|
||||
/// `<<`
|
||||
LeftShift,
|
||||
/// `>>`
|
||||
RightShift,
|
||||
/// `;`
|
||||
SemiColon,
|
||||
/// `:`
|
||||
Colon,
|
||||
/// `::`
|
||||
DoubleColon,
|
||||
/// `,`
|
||||
Comma,
|
||||
/// `.`
|
||||
Period,
|
||||
/// `#{`
|
||||
MapStart,
|
||||
/// `=`
|
||||
Equals,
|
||||
/// `true`
|
||||
True,
|
||||
/// `false`
|
||||
False,
|
||||
/// `let`
|
||||
Let,
|
||||
/// `const`
|
||||
Const,
|
||||
/// `if`
|
||||
If,
|
||||
/// `else`
|
||||
Else,
|
||||
/// `while`
|
||||
While,
|
||||
/// `loop`
|
||||
Loop,
|
||||
/// `for`
|
||||
For,
|
||||
/// `in`
|
||||
In,
|
||||
/// `<`
|
||||
LessThan,
|
||||
/// `>`
|
||||
GreaterThan,
|
||||
/// `<=`
|
||||
LessThanEqualsTo,
|
||||
/// `>=`
|
||||
GreaterThanEqualsTo,
|
||||
/// `==`
|
||||
EqualsTo,
|
||||
/// `!=`
|
||||
NotEqualsTo,
|
||||
/// `!`
|
||||
Bang,
|
||||
/// `|`
|
||||
Pipe,
|
||||
/// `||`
|
||||
Or,
|
||||
/// `^`
|
||||
XOr,
|
||||
/// `&`
|
||||
Ampersand,
|
||||
/// `&&`
|
||||
And,
|
||||
/// `fn`
|
||||
///
|
||||
/// Never appears under the `no_function` feature.
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
Fn,
|
||||
/// `continue`
|
||||
Continue,
|
||||
/// `break`
|
||||
Break,
|
||||
/// `return`
|
||||
Return,
|
||||
/// `throw`
|
||||
Throw,
|
||||
/// `+=`
|
||||
PlusAssign,
|
||||
/// `-=`
|
||||
MinusAssign,
|
||||
/// `*=`
|
||||
MultiplyAssign,
|
||||
/// `/=`
|
||||
DivideAssign,
|
||||
/// `<<=`
|
||||
LeftShiftAssign,
|
||||
/// `>>=`
|
||||
RightShiftAssign,
|
||||
/// `&=`
|
||||
AndAssign,
|
||||
/// `|=`
|
||||
OrAssign,
|
||||
/// `^=`
|
||||
XOrAssign,
|
||||
/// `%=`
|
||||
ModuloAssign,
|
||||
/// `~=`
|
||||
PowerOfAssign,
|
||||
/// `private`
|
||||
///
|
||||
/// Never appears under the `no_function` feature.
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
Private,
|
||||
/// `import`
|
||||
///
|
||||
/// Never appears under the `no_module` feature.
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
Import,
|
||||
/// `export`
|
||||
///
|
||||
/// Never appears under the `no_module` feature.
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
Export,
|
||||
/// `as`
|
||||
///
|
||||
/// Never appears under the `no_module` feature.
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
As,
|
||||
/// A lexer error.
|
||||
LexError(Box<LexError>),
|
||||
/// A comment block.
|
||||
Comment(String),
|
||||
/// A reserved symbol.
|
||||
Reserved(String),
|
||||
/// A custom keyword.
|
||||
Custom(String),
|
||||
/// End of the input stream.
|
||||
EOF,
|
||||
}
|
||||
|
||||
@ -566,7 +658,7 @@ impl Token {
|
||||
}
|
||||
}
|
||||
|
||||
/// Is this token a reserved keyword?
|
||||
/// Is this token a reserved symbol?
|
||||
pub fn is_reserved(&self) -> bool {
|
||||
match self {
|
||||
Self::Reserved(_) => true,
|
||||
@ -589,7 +681,12 @@ impl From<Token> for String {
|
||||
}
|
||||
}
|
||||
|
||||
/// State of the tokenizer.
|
||||
/// [INTERNALS] State of the tokenizer.
|
||||
/// Exported under the `internals` feature only.
|
||||
///
|
||||
/// ## WARNING
|
||||
///
|
||||
/// This type is volatile and may change.
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Default)]
|
||||
pub struct TokenizeState {
|
||||
/// Maximum length of a string (0 = unlimited).
|
||||
@ -604,7 +701,12 @@ pub struct TokenizeState {
|
||||
pub include_comments: bool,
|
||||
}
|
||||
|
||||
/// Trait that encapsulates a peekable character input stream.
|
||||
/// [INTERNALS] Trait that encapsulates a peekable character input stream.
|
||||
/// Exported under the `internals` feature only.
|
||||
///
|
||||
/// ## WARNING
|
||||
///
|
||||
/// This trait is volatile and may change.
|
||||
pub trait InputStream {
|
||||
/// Get the next character
|
||||
fn get_next(&mut self) -> Option<char>;
|
||||
@ -628,7 +730,12 @@ pub fn is_valid_identifier(name: impl Iterator<Item = char>) -> bool {
|
||||
first_alphabetic
|
||||
}
|
||||
|
||||
/// Parse a string literal wrapped by `enclosing_char`.
|
||||
/// [INTERNALS] Parse a string literal wrapped by `enclosing_char`.
|
||||
/// Exported under the `internals` feature only.
|
||||
///
|
||||
/// ## WARNING
|
||||
///
|
||||
/// This type is volatile and may change.
|
||||
pub fn parse_string_literal(
|
||||
stream: &mut impl InputStream,
|
||||
state: &mut TokenizeState,
|
||||
@ -794,7 +901,12 @@ fn scan_comment(
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the next token.
|
||||
/// [INTERNALS] Get the next token from the `InputStream`.
|
||||
/// Exported under the `internals` feature only.
|
||||
///
|
||||
/// ## WARNING
|
||||
///
|
||||
/// This type is volatile and may change.
|
||||
pub fn get_next_token(
|
||||
stream: &mut impl InputStream,
|
||||
state: &mut TokenizeState,
|
||||
|
@ -92,9 +92,12 @@ pub fn calc_fn_spec<'a>(
|
||||
s.finish()
|
||||
}
|
||||
|
||||
/// A type to hold a number of values in static storage for no-allocation, quick access.
|
||||
/// [INTERNALS] An array-like type that holds a number of values in static storage for no-allocation, quick access.
|
||||
/// Exported under the `internals` feature only.
|
||||
///
|
||||
/// If too many items are stored, it converts into using a `Vec`.
|
||||
///
|
||||
///
|
||||
/// This is essentially a knock-off of the [`staticvec`](https://crates.io/crates/staticvec) crate.
|
||||
/// This simplified implementation here is to avoid pulling in another crate.
|
||||
///
|
||||
@ -130,6 +133,10 @@ pub fn calc_fn_spec<'a>(
|
||||
/// # Safety
|
||||
///
|
||||
/// This type uses some unsafe code (mainly for uninitialized/unused array slots) for efficiency.
|
||||
///
|
||||
/// ## WARNING
|
||||
///
|
||||
/// This type is volatile and may change.
|
||||
//
|
||||
// TODO - remove unsafe code
|
||||
pub struct StaticVec<T> {
|
||||
|
@ -104,5 +104,19 @@ fn test_function_pointers() -> Result<(), Box<EvalAltResult>> {
|
||||
42
|
||||
);
|
||||
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
assert_eq!(
|
||||
engine.eval::<INT>(
|
||||
r#"
|
||||
fn foo(x) { this.data += x; }
|
||||
|
||||
let x = #{ data: 40, action: Fn("foo") };
|
||||
x.action(2);
|
||||
x.data
|
||||
"#
|
||||
)?,
|
||||
42
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user