Change to no_smartstring feature.
This commit is contained in:
parent
07efdddba3
commit
41b48d591f
@ -34,7 +34,7 @@ Breaking changes
|
|||||||
* The _reflections_ API such as `Engine::gen_fn_signatures`, `Module::update_fn_metadata` etc. are put under the `metadata` feature gate.
|
* The _reflections_ API such as `Engine::gen_fn_signatures`, `Module::update_fn_metadata` etc. are put under the `metadata` feature gate.
|
||||||
* The shebang `#!` is now a reserved symbol.
|
* The shebang `#!` is now a reserved symbol.
|
||||||
* Shebangs at the very beginning of script files are skipped when loading them.
|
* Shebangs at the very beginning of script files are skipped when loading them.
|
||||||
* [`smartstring`](https://crates.io/crates/smartstring) is used for identifiers.
|
* [`smartstring`](https://crates.io/crates/smartstring) is used for identifiers by default. Currently, a PR branch is pulled because it breaks on `no-std` builds. The official crate will be used once `smartstring` is fixed to support `no-std`.
|
||||||
|
|
||||||
Enhancements
|
Enhancements
|
||||||
------------
|
------------
|
||||||
|
@ -19,10 +19,12 @@ categories = ["no-std", "embedded", "wasm", "parser-implementations"]
|
|||||||
smallvec = { version = "1.6", default-features = false, features = ["union"] }
|
smallvec = { version = "1.6", default-features = false, features = ["union"] }
|
||||||
ahash = { version = "0.7", default-features = false }
|
ahash = { version = "0.7", default-features = false }
|
||||||
num-traits = { version = "0.2", default_features = false }
|
num-traits = { version = "0.2", default_features = false }
|
||||||
|
#smartstring = { version = "0.2.6" }
|
||||||
|
smartstring = { git = "https://github.com/okready/smartstring", branch = "fix-no_std-builds", default_features = false }
|
||||||
rhai_codegen = { version = "0.3.4", path = "codegen", features = ["metadata"] }
|
rhai_codegen = { version = "0.3.4", path = "codegen", features = ["metadata"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["smartstring"]
|
default = []
|
||||||
unchecked = [] # unchecked arithmetic
|
unchecked = [] # unchecked arithmetic
|
||||||
sync = [] # restrict to only types that implement Send + Sync
|
sync = [] # restrict to only types that implement Send + Sync
|
||||||
no_optimize = [] # no script optimizer
|
no_optimize = [] # no script optimizer
|
||||||
@ -40,6 +42,7 @@ internals = [] # expose internal data structures
|
|||||||
unicode-xid-ident = ["unicode-xid"] # allow Unicode Standard Annex #31 for identifiers.
|
unicode-xid-ident = ["unicode-xid"] # allow Unicode Standard Annex #31 for identifiers.
|
||||||
metadata = ["serde_json"] # enable exporting functions metadata
|
metadata = ["serde_json"] # enable exporting functions metadata
|
||||||
|
|
||||||
|
no_smartstring = [] # set Identifier=ImmutableString
|
||||||
no_std = ["smallvec/union", "num-traits/libm", "core-error", "libm", "ahash/compile-time-rng"]
|
no_std = ["smallvec/union", "num-traits/libm", "core-error", "libm", "ahash/compile-time-rng"]
|
||||||
|
|
||||||
# compiling for WASM
|
# compiling for WASM
|
||||||
@ -75,10 +78,6 @@ default_features = false
|
|||||||
features = ["alloc"]
|
features = ["alloc"]
|
||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
[dependencies.smartstring]
|
|
||||||
version = "0.2.6"
|
|
||||||
optional = true
|
|
||||||
|
|
||||||
[dependencies.unicode-xid]
|
[dependencies.unicode-xid]
|
||||||
version = "0.2"
|
version = "0.2"
|
||||||
default_features = false
|
default_features = false
|
||||||
|
@ -12,7 +12,7 @@ homepage = "https://github.com/rhaiscript/rhai/tree/no_std/no_std_test"
|
|||||||
repository = "https://github.com/rhaiscript/rhai"
|
repository = "https://github.com/rhaiscript/rhai"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rhai = { path = "../../", features = [ "no_std" ], default_features = false }
|
rhai = { path = "../../", features = [ "no_std" ] }
|
||||||
wee_alloc = { version = "0.4.5", default_features = false }
|
wee_alloc = { version = "0.4.5", default_features = false }
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
|
@ -1673,11 +1673,11 @@ impl From<&ImmutableString> for Dynamic {
|
|||||||
value.clone().into()
|
value.clone().into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(feature = "smartstring")]
|
#[cfg(not(feature = "no_smartstring"))]
|
||||||
impl From<&crate::Identifier> for Dynamic {
|
impl From<&crate::Identifier> for Dynamic {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from(value: &crate::Identifier) -> Self {
|
fn from(value: &crate::Identifier) -> Self {
|
||||||
value.to_string().into()
|
crate::stdlib::string::ToString::to_string(value).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
|
@ -137,11 +137,11 @@ pub use utils::ImmutableString;
|
|||||||
|
|
||||||
/// An identifier in Rhai. [`SmartString`](https://crates.io/crates/smartstring) is used because most
|
/// An identifier in Rhai. [`SmartString`](https://crates.io/crates/smartstring) is used because most
|
||||||
/// identifiers are ASCII and short, fewer than 23 characters, so they can be stored inline.
|
/// identifiers are ASCII and short, fewer than 23 characters, so they can be stored inline.
|
||||||
#[cfg(feature = "smartstring")]
|
#[cfg(not(feature = "no_smartstring"))]
|
||||||
pub type Identifier = smartstring::SmartString<smartstring::Compact>;
|
pub type Identifier = smartstring::SmartString<smartstring::Compact>;
|
||||||
|
|
||||||
/// An identifier in Rhai.
|
/// An identifier in Rhai.
|
||||||
#[cfg(not(feature = "smartstring"))]
|
#[cfg(feature = "no_smartstring")]
|
||||||
pub type Identifier = ImmutableString;
|
pub type Identifier = ImmutableString;
|
||||||
|
|
||||||
/// A trait to enable registering Rust functions.
|
/// A trait to enable registering Rust functions.
|
||||||
|
@ -16,7 +16,7 @@ use crate::stdlib::{
|
|||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
use crate::token::Token;
|
use crate::token::Token;
|
||||||
use crate::utils::StringInterner;
|
use crate::utils::IdentifierBuilder;
|
||||||
use crate::{
|
use crate::{
|
||||||
calc_fn_hash, calc_fn_params_hash, combine_hashes, Dynamic, EvalAltResult, Identifier,
|
calc_fn_hash, calc_fn_params_hash, combine_hashes, Dynamic, EvalAltResult, Identifier,
|
||||||
ImmutableString, NativeCallContext, Position, Shared, StaticVec,
|
ImmutableString, NativeCallContext, Position, Shared, StaticVec,
|
||||||
@ -149,7 +149,7 @@ pub struct Module {
|
|||||||
/// Does the [`Module`] contain indexed functions that have been exposed to the global namespace?
|
/// Does the [`Module`] contain indexed functions that have been exposed to the global namespace?
|
||||||
contains_indexed_global_functions: bool,
|
contains_indexed_global_functions: bool,
|
||||||
/// Interned strings
|
/// Interned strings
|
||||||
interned_strings: StringInterner,
|
identifiers: IdentifierBuilder,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Module {
|
impl Default for Module {
|
||||||
@ -166,7 +166,7 @@ impl Default for Module {
|
|||||||
all_type_iterators: Default::default(),
|
all_type_iterators: Default::default(),
|
||||||
indexed: false,
|
indexed: false,
|
||||||
contains_indexed_global_functions: false,
|
contains_indexed_global_functions: false,
|
||||||
interned_strings: Default::default(),
|
identifiers: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -700,7 +700,7 @@ impl Module {
|
|||||||
self.functions.insert(
|
self.functions.insert(
|
||||||
hash_fn,
|
hash_fn,
|
||||||
Box::new(FuncInfo {
|
Box::new(FuncInfo {
|
||||||
name: self.interned_strings.get(name),
|
name: self.identifiers.get(name),
|
||||||
namespace,
|
namespace,
|
||||||
access,
|
access,
|
||||||
params: param_types.len(),
|
params: param_types.len(),
|
||||||
|
@ -22,7 +22,7 @@ use crate::stdlib::{
|
|||||||
};
|
};
|
||||||
use crate::syntax::{CustomSyntax, MARKER_BLOCK, MARKER_EXPR, MARKER_IDENT};
|
use crate::syntax::{CustomSyntax, MARKER_BLOCK, MARKER_EXPR, MARKER_IDENT};
|
||||||
use crate::token::{is_keyword_function, is_valid_identifier, Token, TokenStream};
|
use crate::token::{is_keyword_function, is_valid_identifier, Token, TokenStream};
|
||||||
use crate::utils::{get_hasher, StringInterner};
|
use crate::utils::{get_hasher, IdentifierBuilder};
|
||||||
use crate::{
|
use crate::{
|
||||||
calc_fn_hash, Dynamic, Engine, Identifier, ImmutableString, LexError, ParseError,
|
calc_fn_hash, Dynamic, Engine, Identifier, ImmutableString, LexError, ParseError,
|
||||||
ParseErrorType, Position, Scope, Shared, StaticVec, AST,
|
ParseErrorType, Position, Scope, Shared, StaticVec, AST,
|
||||||
@ -44,7 +44,7 @@ struct ParseState<'e> {
|
|||||||
/// Reference to the scripting [`Engine`].
|
/// Reference to the scripting [`Engine`].
|
||||||
engine: &'e Engine,
|
engine: &'e Engine,
|
||||||
/// Interned strings.
|
/// Interned strings.
|
||||||
interned_strings: StringInterner,
|
interned_strings: IdentifierBuilder,
|
||||||
/// Encapsulates a local stack with variable names to simulate an actual runtime scope.
|
/// Encapsulates a local stack with variable names to simulate an actual runtime scope.
|
||||||
stack: Vec<(Identifier, AccessMode)>,
|
stack: Vec<(Identifier, AccessMode)>,
|
||||||
/// Size of the local variables stack upon entry of the current block scope.
|
/// Size of the local variables stack upon entry of the current block scope.
|
||||||
@ -166,7 +166,7 @@ impl<'e> ParseState<'e> {
|
|||||||
|
|
||||||
/// Get an interned string, creating one if it is not yet interned.
|
/// Get an interned string, creating one if it is not yet interned.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn get_interned_string(&mut self, text: impl AsRef<str> + Into<Identifier>) -> Identifier {
|
pub fn get_identifier(&mut self, text: impl AsRef<str> + Into<Identifier>) -> Identifier {
|
||||||
self.interned_strings.get(text)
|
self.interned_strings.get(text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -228,9 +228,9 @@ impl Expr {
|
|||||||
match self {
|
match self {
|
||||||
Self::Variable(x) if x.1.is_none() => {
|
Self::Variable(x) if x.1.is_none() => {
|
||||||
let ident = x.2;
|
let ident = x.2;
|
||||||
let getter = state.get_interned_string(crate::engine::make_getter(&ident.name));
|
let getter = state.get_identifier(crate::engine::make_getter(&ident.name));
|
||||||
let hash_get = calc_fn_hash(empty(), &getter, 1);
|
let hash_get = calc_fn_hash(empty(), &getter, 1);
|
||||||
let setter = state.get_interned_string(crate::engine::make_setter(&ident.name));
|
let setter = state.get_identifier(crate::engine::make_setter(&ident.name));
|
||||||
let hash_set = calc_fn_hash(empty(), &setter, 2);
|
let hash_set = calc_fn_hash(empty(), &setter, 2);
|
||||||
|
|
||||||
Self::Property(Box::new((
|
Self::Property(Box::new((
|
||||||
@ -351,7 +351,7 @@ fn parse_fn_call(
|
|||||||
|
|
||||||
return Ok(Expr::FnCall(
|
return Ok(Expr::FnCall(
|
||||||
Box::new(FnCallExpr {
|
Box::new(FnCallExpr {
|
||||||
name: state.get_interned_string(id),
|
name: state.get_identifier(id),
|
||||||
capture,
|
capture,
|
||||||
namespace,
|
namespace,
|
||||||
hash,
|
hash,
|
||||||
@ -396,7 +396,7 @@ fn parse_fn_call(
|
|||||||
|
|
||||||
return Ok(Expr::FnCall(
|
return Ok(Expr::FnCall(
|
||||||
Box::new(FnCallExpr {
|
Box::new(FnCallExpr {
|
||||||
name: state.get_interned_string(id),
|
name: state.get_identifier(id),
|
||||||
capture,
|
capture,
|
||||||
namespace,
|
namespace,
|
||||||
hash,
|
hash,
|
||||||
@ -755,7 +755,7 @@ fn parse_map_literal(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let expr = parse_expr(input, state, lib, settings.level_up())?;
|
let expr = parse_expr(input, state, lib, settings.level_up())?;
|
||||||
let name = state.get_interned_string(name);
|
let name = state.get_identifier(name);
|
||||||
template.insert(name.clone().into(), Default::default());
|
template.insert(name.clone().into(), Default::default());
|
||||||
map.push((Ident { name, pos }, expr));
|
map.push((Ident { name, pos }, expr));
|
||||||
|
|
||||||
@ -936,7 +936,7 @@ fn parse_primary(
|
|||||||
Token::IntegerConstant(x) => Expr::IntegerConstant(x, settings.pos),
|
Token::IntegerConstant(x) => Expr::IntegerConstant(x, settings.pos),
|
||||||
Token::CharConstant(c) => Expr::CharConstant(c, settings.pos),
|
Token::CharConstant(c) => Expr::CharConstant(c, settings.pos),
|
||||||
Token::StringConstant(s) => {
|
Token::StringConstant(s) => {
|
||||||
Expr::StringConstant(state.get_interned_string(s).into(), settings.pos)
|
Expr::StringConstant(state.get_identifier(s).into(), settings.pos)
|
||||||
}
|
}
|
||||||
Token::True => Expr::BoolConstant(true, settings.pos),
|
Token::True => Expr::BoolConstant(true, settings.pos),
|
||||||
Token::False => Expr::BoolConstant(false, settings.pos),
|
Token::False => Expr::BoolConstant(false, settings.pos),
|
||||||
@ -1034,7 +1034,7 @@ fn parse_primary(
|
|||||||
state.allow_capture = true;
|
state.allow_capture = true;
|
||||||
}
|
}
|
||||||
let var_name_def = Ident {
|
let var_name_def = Ident {
|
||||||
name: state.get_interned_string(s),
|
name: state.get_identifier(s),
|
||||||
pos: settings.pos,
|
pos: settings.pos,
|
||||||
};
|
};
|
||||||
Expr::Variable(Box::new((None, None, var_name_def)))
|
Expr::Variable(Box::new((None, None, var_name_def)))
|
||||||
@ -1048,7 +1048,7 @@ fn parse_primary(
|
|||||||
state.allow_capture = true;
|
state.allow_capture = true;
|
||||||
}
|
}
|
||||||
let var_name_def = Ident {
|
let var_name_def = Ident {
|
||||||
name: state.get_interned_string(s),
|
name: state.get_identifier(s),
|
||||||
pos: settings.pos,
|
pos: settings.pos,
|
||||||
};
|
};
|
||||||
Expr::Variable(Box::new((None, None, var_name_def)))
|
Expr::Variable(Box::new((None, None, var_name_def)))
|
||||||
@ -1057,7 +1057,7 @@ fn parse_primary(
|
|||||||
_ => {
|
_ => {
|
||||||
let index = state.access_var(&s, settings.pos);
|
let index = state.access_var(&s, settings.pos);
|
||||||
let var_name_def = Ident {
|
let var_name_def = Ident {
|
||||||
name: state.get_interned_string(s),
|
name: state.get_identifier(s),
|
||||||
pos: settings.pos,
|
pos: settings.pos,
|
||||||
};
|
};
|
||||||
Expr::Variable(Box::new((index, None, var_name_def)))
|
Expr::Variable(Box::new((index, None, var_name_def)))
|
||||||
@ -1076,7 +1076,7 @@ fn parse_primary(
|
|||||||
// Function call is allowed to have reserved keyword
|
// Function call is allowed to have reserved keyword
|
||||||
Token::LeftParen | Token::Bang if is_keyword_function(&s) => {
|
Token::LeftParen | Token::Bang if is_keyword_function(&s) => {
|
||||||
let var_name_def = Ident {
|
let var_name_def = Ident {
|
||||||
name: state.get_interned_string(s),
|
name: state.get_identifier(s),
|
||||||
pos: settings.pos,
|
pos: settings.pos,
|
||||||
};
|
};
|
||||||
Expr::Variable(Box::new((None, None, var_name_def)))
|
Expr::Variable(Box::new((None, None, var_name_def)))
|
||||||
@ -1084,7 +1084,7 @@ fn parse_primary(
|
|||||||
// Access to `this` as a variable is OK within a function scope
|
// Access to `this` as a variable is OK within a function scope
|
||||||
_ if s == KEYWORD_THIS && settings.is_function_scope => {
|
_ if s == KEYWORD_THIS && settings.is_function_scope => {
|
||||||
let var_name_def = Ident {
|
let var_name_def = Ident {
|
||||||
name: state.get_interned_string(s),
|
name: state.get_identifier(s),
|
||||||
pos: settings.pos,
|
pos: settings.pos,
|
||||||
};
|
};
|
||||||
Expr::Variable(Box::new((None, None, var_name_def)))
|
Expr::Variable(Box::new((None, None, var_name_def)))
|
||||||
@ -1177,7 +1177,7 @@ fn parse_primary(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let var_name_def = Ident {
|
let var_name_def = Ident {
|
||||||
name: state.get_interned_string(id2),
|
name: state.get_identifier(id2),
|
||||||
pos: pos2,
|
pos: pos2,
|
||||||
};
|
};
|
||||||
Expr::Variable(Box::new((index, namespace, var_name_def)))
|
Expr::Variable(Box::new((index, namespace, var_name_def)))
|
||||||
@ -1286,7 +1286,7 @@ fn parse_unary(
|
|||||||
|
|
||||||
Ok(Expr::FnCall(
|
Ok(Expr::FnCall(
|
||||||
Box::new(FnCallExpr {
|
Box::new(FnCallExpr {
|
||||||
name: state.get_interned_string("-"),
|
name: state.get_identifier("-"),
|
||||||
hash: FnCallHash::from_native(calc_fn_hash(empty(), "-", 1)),
|
hash: FnCallHash::from_native(calc_fn_hash(empty(), "-", 1)),
|
||||||
args,
|
args,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -1312,7 +1312,7 @@ fn parse_unary(
|
|||||||
|
|
||||||
Ok(Expr::FnCall(
|
Ok(Expr::FnCall(
|
||||||
Box::new(FnCallExpr {
|
Box::new(FnCallExpr {
|
||||||
name: state.get_interned_string("+"),
|
name: state.get_identifier("+"),
|
||||||
hash: FnCallHash::from_native(calc_fn_hash(empty(), "+", 1)),
|
hash: FnCallHash::from_native(calc_fn_hash(empty(), "+", 1)),
|
||||||
args,
|
args,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -1331,7 +1331,7 @@ fn parse_unary(
|
|||||||
|
|
||||||
Ok(Expr::FnCall(
|
Ok(Expr::FnCall(
|
||||||
Box::new(FnCallExpr {
|
Box::new(FnCallExpr {
|
||||||
name: state.get_interned_string("!"),
|
name: state.get_identifier("!"),
|
||||||
hash: FnCallHash::from_native(calc_fn_hash(empty(), "!", 1)),
|
hash: FnCallHash::from_native(calc_fn_hash(empty(), "!", 1)),
|
||||||
args,
|
args,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -1500,9 +1500,9 @@ fn make_dot_expr(
|
|||||||
// lhs.id
|
// lhs.id
|
||||||
(lhs, Expr::Variable(x)) if x.1.is_none() => {
|
(lhs, Expr::Variable(x)) if x.1.is_none() => {
|
||||||
let ident = x.2;
|
let ident = x.2;
|
||||||
let getter = state.get_interned_string(crate::engine::make_getter(&ident.name));
|
let getter = state.get_identifier(crate::engine::make_getter(&ident.name));
|
||||||
let hash_get = calc_fn_hash(empty(), &getter, 1);
|
let hash_get = calc_fn_hash(empty(), &getter, 1);
|
||||||
let setter = state.get_interned_string(crate::engine::make_setter(&ident.name));
|
let setter = state.get_identifier(crate::engine::make_setter(&ident.name));
|
||||||
let hash_set = calc_fn_hash(empty(), &setter, 2);
|
let hash_set = calc_fn_hash(empty(), &setter, 2);
|
||||||
|
|
||||||
let rhs = Expr::Property(Box::new(((getter, hash_get), (setter, hash_set), ident)));
|
let rhs = Expr::Property(Box::new(((getter, hash_get), (setter, hash_set), ident)));
|
||||||
@ -1674,7 +1674,7 @@ fn parse_binary_op(
|
|||||||
let hash = calc_fn_hash(empty(), &op, 2);
|
let hash = calc_fn_hash(empty(), &op, 2);
|
||||||
|
|
||||||
let op_base = FnCallExpr {
|
let op_base = FnCallExpr {
|
||||||
name: state.get_interned_string(op.as_ref()),
|
name: state.get_identifier(op.as_ref()),
|
||||||
hash: FnCallHash::from_native(hash),
|
hash: FnCallHash::from_native(hash),
|
||||||
capture: false,
|
capture: false,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -1742,7 +1742,7 @@ fn parse_binary_op(
|
|||||||
Box::new(FnCallExpr {
|
Box::new(FnCallExpr {
|
||||||
hash: FnCallHash::from_script(hash),
|
hash: FnCallHash::from_script(hash),
|
||||||
args,
|
args,
|
||||||
name: state.get_interned_string(OP_CONTAINS),
|
name: state.get_identifier(OP_CONTAINS),
|
||||||
..op_base
|
..op_base
|
||||||
}),
|
}),
|
||||||
pos,
|
pos,
|
||||||
@ -1830,9 +1830,9 @@ fn parse_custom_syntax(
|
|||||||
match required_token.as_str() {
|
match required_token.as_str() {
|
||||||
MARKER_IDENT => match input.next().unwrap() {
|
MARKER_IDENT => match input.next().unwrap() {
|
||||||
(Token::Identifier(s), pos) => {
|
(Token::Identifier(s), pos) => {
|
||||||
let name = state.get_interned_string(s);
|
let name = state.get_identifier(s);
|
||||||
segments.push(name.clone().into());
|
segments.push(name.clone().into());
|
||||||
tokens.push(state.get_interned_string(MARKER_IDENT));
|
tokens.push(state.get_identifier(MARKER_IDENT));
|
||||||
let var_name_def = Ident { name, pos };
|
let var_name_def = Ident { name, pos };
|
||||||
keywords.push(Expr::Variable(Box::new((None, None, var_name_def))));
|
keywords.push(Expr::Variable(Box::new((None, None, var_name_def))));
|
||||||
}
|
}
|
||||||
@ -1843,14 +1843,14 @@ fn parse_custom_syntax(
|
|||||||
},
|
},
|
||||||
MARKER_EXPR => {
|
MARKER_EXPR => {
|
||||||
keywords.push(parse_expr(input, state, lib, settings)?);
|
keywords.push(parse_expr(input, state, lib, settings)?);
|
||||||
let keyword = state.get_interned_string(MARKER_EXPR);
|
let keyword = state.get_identifier(MARKER_EXPR);
|
||||||
segments.push(keyword.clone().into());
|
segments.push(keyword.clone().into());
|
||||||
tokens.push(keyword);
|
tokens.push(keyword);
|
||||||
}
|
}
|
||||||
MARKER_BLOCK => match parse_block(input, state, lib, settings)? {
|
MARKER_BLOCK => match parse_block(input, state, lib, settings)? {
|
||||||
block @ Stmt::Block(_, _) => {
|
block @ Stmt::Block(_, _) => {
|
||||||
keywords.push(Expr::Stmt(Box::new(block.into())));
|
keywords.push(Expr::Stmt(Box::new(block.into())));
|
||||||
let keyword = state.get_interned_string(MARKER_BLOCK);
|
let keyword = state.get_identifier(MARKER_BLOCK);
|
||||||
segments.push(keyword.clone().into());
|
segments.push(keyword.clone().into());
|
||||||
tokens.push(keyword);
|
tokens.push(keyword);
|
||||||
}
|
}
|
||||||
@ -2120,7 +2120,7 @@ fn parse_for(
|
|||||||
ensure_not_statement_expr(input, "a boolean")?;
|
ensure_not_statement_expr(input, "a boolean")?;
|
||||||
let expr = parse_expr(input, state, lib, settings.level_up())?;
|
let expr = parse_expr(input, state, lib, settings.level_up())?;
|
||||||
|
|
||||||
let loop_var = state.get_interned_string(name);
|
let loop_var = state.get_identifier(name);
|
||||||
let prev_stack_len = state.stack.len();
|
let prev_stack_len = state.stack.len();
|
||||||
state.stack.push((loop_var.clone(), AccessMode::ReadWrite));
|
state.stack.push((loop_var.clone(), AccessMode::ReadWrite));
|
||||||
|
|
||||||
@ -2161,7 +2161,7 @@ fn parse_let(
|
|||||||
(_, pos) => return Err(PERR::VariableExpected.into_err(pos)),
|
(_, pos) => return Err(PERR::VariableExpected.into_err(pos)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let name = state.get_interned_string(name);
|
let name = state.get_identifier(name);
|
||||||
let var_def = Ident {
|
let var_def = Ident {
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
pos,
|
pos,
|
||||||
@ -2217,7 +2217,7 @@ fn parse_import(
|
|||||||
(_, pos) => return Err(PERR::VariableExpected.into_err(pos)),
|
(_, pos) => return Err(PERR::VariableExpected.into_err(pos)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let name = state.get_interned_string(name);
|
let name = state.get_identifier(name);
|
||||||
state.modules.push(name.clone());
|
state.modules.push(name.clone());
|
||||||
|
|
||||||
Ok(Stmt::Import(
|
Ok(Stmt::Import(
|
||||||
@ -2277,7 +2277,7 @@ fn parse_export(
|
|||||||
let rename = if match_token(input, Token::As).0 {
|
let rename = if match_token(input, Token::As).0 {
|
||||||
match input.next().unwrap() {
|
match input.next().unwrap() {
|
||||||
(Token::Identifier(s), pos) => Some(Ident {
|
(Token::Identifier(s), pos) => Some(Ident {
|
||||||
name: state.get_interned_string(s),
|
name: state.get_identifier(s),
|
||||||
pos,
|
pos,
|
||||||
}),
|
}),
|
||||||
(Token::Reserved(s), pos) if is_valid_identifier(s.chars()) => {
|
(Token::Reserved(s), pos) if is_valid_identifier(s.chars()) => {
|
||||||
@ -2292,7 +2292,7 @@ fn parse_export(
|
|||||||
|
|
||||||
exports.push((
|
exports.push((
|
||||||
Ident {
|
Ident {
|
||||||
name: state.get_interned_string(id),
|
name: state.get_identifier(id),
|
||||||
pos: id_pos,
|
pos: id_pos,
|
||||||
},
|
},
|
||||||
rename,
|
rename,
|
||||||
@ -2630,7 +2630,7 @@ fn parse_try_catch(
|
|||||||
let var_def = if match_token(input, Token::LeftParen).0 {
|
let var_def = if match_token(input, Token::LeftParen).0 {
|
||||||
let id = match input.next().unwrap() {
|
let id = match input.next().unwrap() {
|
||||||
(Token::Identifier(s), pos) => Ident {
|
(Token::Identifier(s), pos) => Ident {
|
||||||
name: state.get_interned_string(s),
|
name: state.get_identifier(s),
|
||||||
pos,
|
pos,
|
||||||
},
|
},
|
||||||
(_, pos) => return Err(PERR::VariableExpected.into_err(pos)),
|
(_, pos) => return Err(PERR::VariableExpected.into_err(pos)),
|
||||||
@ -2700,7 +2700,7 @@ fn parse_fn(
|
|||||||
if params.iter().any(|(p, _)| p == &s) {
|
if params.iter().any(|(p, _)| p == &s) {
|
||||||
return Err(PERR::FnDuplicatedParam(name, s).into_err(pos));
|
return Err(PERR::FnDuplicatedParam(name, s).into_err(pos));
|
||||||
}
|
}
|
||||||
let s = state.get_interned_string(s);
|
let s = state.get_identifier(s);
|
||||||
state.stack.push((s.clone(), AccessMode::ReadWrite));
|
state.stack.push((s.clone(), AccessMode::ReadWrite));
|
||||||
params.push((s, pos))
|
params.push((s, pos))
|
||||||
}
|
}
|
||||||
@ -2747,7 +2747,7 @@ fn parse_fn(
|
|||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Ok(ScriptFnDef {
|
Ok(ScriptFnDef {
|
||||||
name: state.get_interned_string(&name),
|
name: state.get_identifier(&name),
|
||||||
access,
|
access,
|
||||||
params,
|
params,
|
||||||
#[cfg(not(feature = "no_closure"))]
|
#[cfg(not(feature = "no_closure"))]
|
||||||
@ -2785,7 +2785,7 @@ fn make_curry_from_externals(
|
|||||||
|
|
||||||
let expr = Expr::FnCall(
|
let expr = Expr::FnCall(
|
||||||
Box::new(FnCallExpr {
|
Box::new(FnCallExpr {
|
||||||
name: state.get_interned_string(crate::engine::KEYWORD_FN_PTR_CURRY),
|
name: state.get_identifier(crate::engine::KEYWORD_FN_PTR_CURRY),
|
||||||
hash: FnCallHash::from_native(calc_fn_hash(
|
hash: FnCallHash::from_native(calc_fn_hash(
|
||||||
empty(),
|
empty(),
|
||||||
crate::engine::KEYWORD_FN_PTR_CURRY,
|
crate::engine::KEYWORD_FN_PTR_CURRY,
|
||||||
@ -2827,7 +2827,7 @@ fn parse_anon_fn(
|
|||||||
if params.iter().any(|(p, _)| p == &s) {
|
if params.iter().any(|(p, _)| p == &s) {
|
||||||
return Err(PERR::FnDuplicatedParam("".to_string(), s).into_err(pos));
|
return Err(PERR::FnDuplicatedParam("".to_string(), s).into_err(pos));
|
||||||
}
|
}
|
||||||
let s = state.get_interned_string(s);
|
let s = state.get_identifier(s);
|
||||||
state.stack.push((s.clone(), AccessMode::ReadWrite));
|
state.stack.push((s.clone(), AccessMode::ReadWrite));
|
||||||
params.push((s, pos))
|
params.push((s, pos))
|
||||||
}
|
}
|
||||||
@ -2895,8 +2895,7 @@ fn parse_anon_fn(
|
|||||||
body.hash(hasher);
|
body.hash(hasher);
|
||||||
let hash = hasher.finish();
|
let hash = hasher.finish();
|
||||||
|
|
||||||
let fn_name =
|
let fn_name = state.get_identifier(&(format!("{}{:016x}", crate::engine::FN_ANONYMOUS, hash)));
|
||||||
state.get_interned_string(&(format!("{}{:016x}", crate::engine::FN_ANONYMOUS, hash)));
|
|
||||||
|
|
||||||
// Define the function
|
// Define the function
|
||||||
let script = ScriptFnDef {
|
let script = ScriptFnDef {
|
||||||
|
26
src/utils.rs
26
src/utils.rs
@ -6,7 +6,6 @@ use crate::stdlib::{
|
|||||||
borrow::Borrow,
|
borrow::Borrow,
|
||||||
boxed::Box,
|
boxed::Box,
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
collections::BTreeSet,
|
|
||||||
fmt,
|
fmt,
|
||||||
fmt::{Debug, Display},
|
fmt::{Debug, Display},
|
||||||
hash::{BuildHasher, Hash, Hasher},
|
hash::{BuildHasher, Hash, Hasher},
|
||||||
@ -590,7 +589,7 @@ impl PartialOrd<ImmutableString> for String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "smartstring")]
|
#[cfg(not(feature = "no_smartstring"))]
|
||||||
impl From<ImmutableString> for Identifier {
|
impl From<ImmutableString> for Identifier {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from(value: ImmutableString) -> Self {
|
fn from(value: ImmutableString) -> Self {
|
||||||
@ -598,7 +597,7 @@ impl From<ImmutableString> for Identifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "smartstring")]
|
#[cfg(not(feature = "no_smartstring"))]
|
||||||
impl From<Identifier> for ImmutableString {
|
impl From<Identifier> for ImmutableString {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn from(value: Identifier) -> Self {
|
fn from(value: Identifier) -> Self {
|
||||||
@ -622,18 +621,27 @@ impl ImmutableString {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A collection of interned strings.
|
/// A factory of identifiers from text strings.
|
||||||
|
///
|
||||||
|
/// When [`SmartString`](https://crates.io/crates/smartstring) is used as [`Identifier`],
|
||||||
|
/// this just returns one because most identifiers in Rhai are short and ASCII-based.
|
||||||
|
///
|
||||||
|
/// When [`ImmutableString`] is used as [`Identifier`], this type acts as an interner which keeps a
|
||||||
|
/// collection of strings and returns shared instances, only creating a new string when it is not
|
||||||
|
/// yet interned.
|
||||||
#[derive(Debug, Clone, Default, Hash)]
|
#[derive(Debug, Clone, Default, Hash)]
|
||||||
pub struct StringInterner(BTreeSet<Identifier>);
|
pub struct IdentifierBuilder(
|
||||||
|
#[cfg(feature = "no_smartstring")] crate::stdlib::collections::BTreeSet<Identifier>,
|
||||||
|
);
|
||||||
|
|
||||||
impl StringInterner {
|
impl IdentifierBuilder {
|
||||||
/// Get an interned string, creating one if it is not yet interned.
|
/// Get an identifier from a text string.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn get(&mut self, text: impl AsRef<str> + Into<Identifier>) -> Identifier {
|
pub fn get(&mut self, text: impl AsRef<str> + Into<Identifier>) -> Identifier {
|
||||||
#[cfg(feature = "smartstring")]
|
#[cfg(not(feature = "no_smartstring"))]
|
||||||
return text.as_ref().into();
|
return text.as_ref().into();
|
||||||
|
|
||||||
#[cfg(not(feature = "smartstring"))]
|
#[cfg(feature = "no_smartstring")]
|
||||||
return self.0.get(text.as_ref()).cloned().unwrap_or_else(|| {
|
return self.0.get(text.as_ref()).cloned().unwrap_or_else(|| {
|
||||||
let s: Identifier = text.into();
|
let s: Identifier = text.into();
|
||||||
self.0.insert(s.clone());
|
self.0.insert(s.clone());
|
||||||
|
Loading…
Reference in New Issue
Block a user