Clean up clippy.
This commit is contained in:
parent
21f822020f
commit
39dee556c4
1
.gitignore
vendored
1
.gitignore
vendored
@ -6,3 +6,4 @@ benches/results
|
||||
before*
|
||||
after*
|
||||
.rhai-repl-history.txt
|
||||
clippy.toml
|
||||
|
@ -46,6 +46,7 @@ Enhancements
|
||||
* `FnAccess::is_private`, `FnAccess::is_public`, `FnNamespace::is_module_namespace` and `FnNameSpace::is_global_namespace` are added for convenience.
|
||||
* `Iterator<Item=T>` type for functions metadata is simplified to `Iterator<T>`.
|
||||
* `Scope::remove` is added to remove a variable from a `Scope`, returning its value.
|
||||
* The code base is cleaner by running it through Clippy.
|
||||
|
||||
|
||||
Version 1.8.0
|
||||
|
@ -149,25 +149,23 @@ pub fn doc_attributes(attrs: &[syn::Attribute]) -> syn::Result<Vec<String>> {
|
||||
for attr in attrs {
|
||||
if let Some(i) = attr.path.get_ident() {
|
||||
if *i == "doc" {
|
||||
match attr.parse_meta()? {
|
||||
syn::Meta::NameValue(syn::MetaNameValue {
|
||||
lit: syn::Lit::Str(s),
|
||||
..
|
||||
}) => {
|
||||
let mut line = s.value();
|
||||
if let syn::Meta::NameValue(syn::MetaNameValue {
|
||||
lit: syn::Lit::Str(s),
|
||||
..
|
||||
}) = attr.parse_meta()?
|
||||
{
|
||||
let mut line = s.value();
|
||||
|
||||
if line.contains('\n') {
|
||||
// Must be a block comment `/** ... */`
|
||||
line.insert_str(0, "/**");
|
||||
line.push_str("*/");
|
||||
} else {
|
||||
// Single line - assume it is `///`
|
||||
line.insert_str(0, "///");
|
||||
}
|
||||
|
||||
comments.push(line);
|
||||
if line.contains('\n') {
|
||||
// Must be a block comment `/** ... */`
|
||||
line.insert_str(0, "/**");
|
||||
line.push_str("*/");
|
||||
} else {
|
||||
// Single line - assume it is `///`
|
||||
line.insert_str(0, "///");
|
||||
}
|
||||
_ => (),
|
||||
|
||||
comments.push(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -302,18 +302,15 @@ impl Parse for ExportedFn {
|
||||
let visibility = fn_all.vis;
|
||||
|
||||
// Determine if the function requires a call context
|
||||
match fn_all.sig.inputs.first() {
|
||||
Some(syn::FnArg::Typed(syn::PatType { ref ty, .. })) => {
|
||||
match flatten_type_groups(ty.as_ref()) {
|
||||
syn::Type::Path(p)
|
||||
if p.path == context_type_path1 || p.path == context_type_path2 =>
|
||||
{
|
||||
pass_context = true;
|
||||
}
|
||||
_ => {}
|
||||
if let Some(syn::FnArg::Typed(syn::PatType { ref ty, .. })) = fn_all.sig.inputs.first() {
|
||||
match flatten_type_groups(ty.as_ref()) {
|
||||
syn::Type::Path(p)
|
||||
if p.path == context_type_path1 || p.path == context_type_path2 =>
|
||||
{
|
||||
pass_context = true;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let skip_slots = if pass_context { 1 } else { 0 };
|
||||
@ -378,25 +375,22 @@ impl Parse for ExportedFn {
|
||||
}
|
||||
|
||||
// Check return type.
|
||||
match fn_all.sig.output {
|
||||
syn::ReturnType::Type(.., ref ret_type) => {
|
||||
match flatten_type_groups(ret_type.as_ref()) {
|
||||
syn::Type::Ptr(..) => {
|
||||
return Err(syn::Error::new(
|
||||
fn_all.sig.output.span(),
|
||||
"Rhai functions cannot return pointers",
|
||||
))
|
||||
}
|
||||
syn::Type::Reference(..) => {
|
||||
return Err(syn::Error::new(
|
||||
fn_all.sig.output.span(),
|
||||
"Rhai functions cannot return references",
|
||||
))
|
||||
}
|
||||
_ => {}
|
||||
if let syn::ReturnType::Type(.., ref ret_type) = fn_all.sig.output {
|
||||
match flatten_type_groups(ret_type.as_ref()) {
|
||||
syn::Type::Ptr(..) => {
|
||||
return Err(syn::Error::new(
|
||||
fn_all.sig.output.span(),
|
||||
"Rhai functions cannot return pointers",
|
||||
))
|
||||
}
|
||||
syn::Type::Reference(..) => {
|
||||
return Err(syn::Error::new(
|
||||
fn_all.sig.output.span(),
|
||||
"Rhai functions cannot return references",
|
||||
))
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
Ok(ExportedFn {
|
||||
entire_span,
|
||||
|
@ -138,38 +138,38 @@ impl Parse for Module {
|
||||
})?;
|
||||
// Gather and parse constants definitions.
|
||||
for item in &*content {
|
||||
match item {
|
||||
syn::Item::Const(syn::ItemConst {
|
||||
vis: syn::Visibility::Public(..),
|
||||
ref expr,
|
||||
ident,
|
||||
attrs,
|
||||
ty,
|
||||
..
|
||||
}) => consts.push(ExportedConst {
|
||||
if let syn::Item::Const(syn::ItemConst {
|
||||
vis: syn::Visibility::Public(..),
|
||||
ref expr,
|
||||
ident,
|
||||
attrs,
|
||||
ty,
|
||||
..
|
||||
}) = item
|
||||
{
|
||||
consts.push(ExportedConst {
|
||||
name: ident.to_string(),
|
||||
typ: ty.clone(),
|
||||
expr: expr.as_ref().clone(),
|
||||
cfg_attrs: crate::attrs::collect_cfg_attr(attrs),
|
||||
}),
|
||||
_ => {}
|
||||
})
|
||||
}
|
||||
}
|
||||
// Gather and parse type definitions.
|
||||
for item in &*content {
|
||||
match item {
|
||||
syn::Item::Type(syn::ItemType {
|
||||
vis: syn::Visibility::Public(..),
|
||||
ident,
|
||||
attrs,
|
||||
ty,
|
||||
..
|
||||
}) => custom_types.push(ExportedType {
|
||||
if let syn::Item::Type(syn::ItemType {
|
||||
vis: syn::Visibility::Public(..),
|
||||
ident,
|
||||
attrs,
|
||||
ty,
|
||||
..
|
||||
}) = item
|
||||
{
|
||||
custom_types.push(ExportedType {
|
||||
name: ident.to_string(),
|
||||
typ: ty.clone(),
|
||||
cfg_attrs: crate::attrs::collect_cfg_attr(attrs),
|
||||
}),
|
||||
_ => {}
|
||||
})
|
||||
}
|
||||
}
|
||||
// Gather and parse sub-module definitions.
|
||||
|
@ -270,11 +270,10 @@ impl Engine {
|
||||
// Make it a custom keyword/symbol if it is disabled or reserved
|
||||
if (!self.disabled_symbols.is_empty() && self.disabled_symbols.contains(s))
|
||||
|| token.map_or(false, |v| v.is_reserved())
|
||||
&& self.custom_keywords.is_empty()
|
||||
|| !self.custom_keywords.contains_key(s)
|
||||
{
|
||||
if self.custom_keywords.is_empty() || !self.custom_keywords.contains_key(s)
|
||||
{
|
||||
self.custom_keywords.insert(s.into(), None);
|
||||
}
|
||||
self.custom_keywords.insert(s.into(), None);
|
||||
}
|
||||
s.into()
|
||||
}
|
||||
|
@ -28,7 +28,6 @@ impl Engine {
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn definitions(&self) -> Definitions {
|
||||
Definitions {
|
||||
engine: self,
|
||||
@ -54,7 +53,6 @@ impl Engine {
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn definitions_with_scope<'e>(&'e self, scope: &'e Scope<'e>) -> Definitions<'e> {
|
||||
Definitions {
|
||||
engine: self,
|
||||
@ -112,7 +110,6 @@ impl<'e> Definitions<'e> {
|
||||
///
|
||||
/// The returned iterator yields all definition files as (filename, content) pairs.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn iter_files(&self) -> impl Iterator<Item = (String, String)> + '_ {
|
||||
IntoIterator::into_iter([
|
||||
(
|
||||
@ -182,7 +179,6 @@ impl<'e> Definitions<'e> {
|
||||
///
|
||||
/// Always starts with `module <module name>;`.
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
#[must_use]
|
||||
pub fn modules(&self) -> impl Iterator<Item = (String, String)> + '_ {
|
||||
let mut m = self
|
||||
.engine
|
||||
|
@ -9,24 +9,24 @@ bitflags! {
|
||||
/// Bit-flags containing all language options for the [`Engine`].
|
||||
pub struct LangOptions: u8 {
|
||||
/// Is `if`-expression allowed?
|
||||
const IF_EXPR = 0b_00000001;
|
||||
const IF_EXPR = 0b_0000_0001;
|
||||
/// Is `switch` expression allowed?
|
||||
const SWITCH_EXPR = 0b_00000010;
|
||||
const SWITCH_EXPR = 0b_0000_0010;
|
||||
/// Is statement-expression allowed?
|
||||
const STMT_EXPR = 0b_00000100;
|
||||
const STMT_EXPR = 0b_0000_0100;
|
||||
/// Is anonymous function allowed?
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
const ANON_FN = 0b_00001000;
|
||||
const ANON_FN = 0b_0000_1000;
|
||||
/// Is looping allowed?
|
||||
const LOOPING = 0b_00010000;
|
||||
const LOOPING = 0b_0001_0000;
|
||||
/// Is variables shadowing allowed?
|
||||
const SHADOW = 0b_00100000;
|
||||
const SHADOW = 0b_0010_0000;
|
||||
/// Strict variables mode?
|
||||
const STRICT_VAR = 0b_01000000;
|
||||
const STRICT_VAR = 0b_0100_0000;
|
||||
/// Raise error if an object map property does not exist?
|
||||
/// Returns `()` if `false`.
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
const FAIL_ON_INVALID_MAP_PROPERTY = 0b_10000000;
|
||||
const FAIL_ON_INVALID_MAP_PROPERTY = 0b_1000_0000;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -144,9 +144,9 @@ impl Engine {
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub(crate) fn format_type_name<'a>(&'a self, name: &'a str) -> std::borrow::Cow<'a, str> {
|
||||
if name.starts_with("&mut ") {
|
||||
let x = &name[5..];
|
||||
if let Some(x) = name.strip_prefix("&mut ") {
|
||||
let r = self.format_type_name(x);
|
||||
|
||||
return if x != r {
|
||||
format!("&mut {}", r).into()
|
||||
} else {
|
||||
@ -167,9 +167,9 @@ impl Engine {
|
||||
return None;
|
||||
})
|
||||
.unwrap_or_else(|| match name {
|
||||
"INT" => return type_name::<crate::INT>(),
|
||||
"INT" => type_name::<crate::INT>(),
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
"FLOAT" => return type_name::<crate::FLOAT>(),
|
||||
"FLOAT" => type_name::<crate::FLOAT>(),
|
||||
_ => map_std_type_name(name, false),
|
||||
})
|
||||
.into()
|
||||
|
@ -158,19 +158,13 @@ impl ConditionalExpr {
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn is_always_true(&self) -> bool {
|
||||
match self.condition {
|
||||
Expr::BoolConstant(true, ..) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.condition, Expr::BoolConstant(true, ..))
|
||||
}
|
||||
/// Is the condition always `false`?
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn is_always_false(&self) -> bool {
|
||||
match self.condition {
|
||||
Expr::BoolConstant(false, ..) => true,
|
||||
_ => false,
|
||||
}
|
||||
matches!(self.condition, Expr::BoolConstant(false, ..))
|
||||
}
|
||||
}
|
||||
|
||||
@ -388,7 +382,6 @@ impl StmtBlock {
|
||||
}
|
||||
/// Get an iterator over the statements of this statements block.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn iter(&self) -> impl Iterator<Item = &Stmt> {
|
||||
self.block.iter()
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ fn print_source(lines: &[String], pos: Position, offset: usize, window: (usize,
|
||||
println!("{0:>1$}", "^", pos + offset + line_no_len + 2);
|
||||
}
|
||||
} else {
|
||||
for n in start..=end {
|
||||
for (n, s) in lines.iter().enumerate().take(end + 1).skip(start) {
|
||||
let marker = if n == line { "> " } else { " " };
|
||||
|
||||
println!(
|
||||
@ -38,7 +38,7 @@ fn print_source(lines: &[String], pos: Position, offset: usize, window: (usize,
|
||||
marker,
|
||||
n + 1,
|
||||
line_no_len,
|
||||
lines[n],
|
||||
s,
|
||||
if n == line { "\x1b[39m" } else { "" },
|
||||
);
|
||||
|
||||
@ -161,7 +161,7 @@ fn print_debug_help() {
|
||||
|
||||
// Load script to debug.
|
||||
fn load_script(engine: &Engine) -> (rhai::AST, String) {
|
||||
if let Some(filename) = env::args().skip(1).next() {
|
||||
if let Some(filename) = env::args().nth(1) {
|
||||
let mut contents = String::new();
|
||||
|
||||
let filename = match Path::new(&filename).canonicalize() {
|
||||
@ -301,12 +301,7 @@ fn debug_callback(
|
||||
|
||||
match stdin().read_line(&mut input) {
|
||||
Ok(0) => break Ok(DebuggerCommand::Continue),
|
||||
Ok(_) => match input
|
||||
.trim()
|
||||
.split_whitespace()
|
||||
.collect::<Vec<_>>()
|
||||
.as_slice()
|
||||
{
|
||||
Ok(_) => match input.split_whitespace().collect::<Vec<_>>().as_slice() {
|
||||
["help" | "h"] => print_debug_help(),
|
||||
["exit" | "quit" | "q" | "kill", ..] => {
|
||||
println!("Script terminated. Bye!");
|
||||
@ -328,14 +323,14 @@ fn debug_callback(
|
||||
["source"] => {
|
||||
println!("{}", context.global_runtime_state().source().unwrap_or(""))
|
||||
}
|
||||
["list" | "l"] => print_current_source(&mut context, source, pos, &lines, (3, 6)),
|
||||
["list" | "l"] => print_current_source(&mut context, source, pos, lines, (3, 6)),
|
||||
["list" | "l", n] if n.parse::<usize>().is_ok() => {
|
||||
let num = n.parse::<usize>().unwrap();
|
||||
if num <= 0 || num > lines.len() {
|
||||
if num == 0 || num > lines.len() {
|
||||
eprintln!("\x1b[31mInvalid line: {}\x1b[39m", num);
|
||||
} else {
|
||||
let pos = Position::new(num as u16, 0);
|
||||
print_current_source(&mut context, source, pos, &lines, (3, 6));
|
||||
print_current_source(&mut context, source, pos, lines, (3, 6));
|
||||
}
|
||||
}
|
||||
["continue" | "c"] => break Ok(DebuggerCommand::Continue),
|
||||
@ -405,7 +400,7 @@ fn debug_callback(
|
||||
rhai::debugger::BreakPoint::AtPosition { pos, .. } => {
|
||||
let line_num = format!("[{}] line ", i + 1);
|
||||
print!("{}", line_num);
|
||||
print_source(&lines, *pos, line_num.len(), (0, 0));
|
||||
print_source(lines, *pos, line_num.len(), (0, 0));
|
||||
}
|
||||
_ => println!("[{}] {}", i + 1, bp),
|
||||
},
|
||||
@ -580,7 +575,7 @@ fn debug_callback(
|
||||
break Err(EvalAltResult::ErrorRuntime(value, pos).into());
|
||||
}
|
||||
["throw", ..] => {
|
||||
let msg = input.trim().splitn(2, ' ').skip(1).next().unwrap_or("");
|
||||
let msg = input.trim().split_once(' ').map(|(_, x)| x).unwrap_or("");
|
||||
break Err(EvalAltResult::ErrorRuntime(msg.trim().into(), pos).into());
|
||||
}
|
||||
["run" | "r"] => {
|
||||
|
@ -158,7 +158,7 @@ fn load_script_files(engine: &mut Engine) {
|
||||
.map_err(|err| err.into())
|
||||
.and_then(|mut ast| {
|
||||
ast.set_source(filename.to_string_lossy().to_string());
|
||||
Module::eval_ast_as_new(Scope::new(), &ast, &engine)
|
||||
Module::eval_ast_as_new(Scope::new(), &ast, engine)
|
||||
}) {
|
||||
Err(err) => {
|
||||
let filename = filename.to_string_lossy();
|
||||
@ -166,7 +166,7 @@ fn load_script_files(engine: &mut Engine) {
|
||||
eprintln!("{:=<1$}", "", filename.len());
|
||||
eprintln!("{}", filename);
|
||||
eprintln!("{:=<1$}", "", filename.len());
|
||||
eprintln!("");
|
||||
eprintln!();
|
||||
|
||||
print_error(&contents, *err);
|
||||
exit(1);
|
||||
@ -353,7 +353,7 @@ fn main() {
|
||||
|
||||
match rl.readline(prompt) {
|
||||
// Line continuation
|
||||
Ok(mut line) if line.ends_with("\\") => {
|
||||
Ok(mut line) if line.ends_with('\\') => {
|
||||
line.pop();
|
||||
input += &line;
|
||||
input.push('\n');
|
||||
@ -361,10 +361,12 @@ fn main() {
|
||||
Ok(line) => {
|
||||
input += &line;
|
||||
let cmd = input.trim();
|
||||
if !cmd.is_empty() && !cmd.starts_with('!') && cmd.trim() != "history" {
|
||||
if rl.add_history_entry(input.clone()) {
|
||||
history_offset += 1;
|
||||
}
|
||||
if !cmd.is_empty()
|
||||
&& !cmd.starts_with('!')
|
||||
&& cmd.trim() != "history"
|
||||
&& rl.add_history_entry(input.clone())
|
||||
{
|
||||
history_offset += 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ fn eprint_error(input: &str, mut err: EvalAltResult) {
|
||||
line_no.len() + pos.position().unwrap(),
|
||||
err_msg
|
||||
);
|
||||
eprintln!("");
|
||||
eprintln!();
|
||||
}
|
||||
|
||||
let lines: Vec<_> = input.split('\n').collect();
|
||||
@ -96,7 +96,7 @@ fn main() {
|
||||
eprintln!("{:=<1$}", "", filename.len());
|
||||
eprintln!("{}", filename);
|
||||
eprintln!("{:=<1$}", "", filename.len());
|
||||
eprintln!("");
|
||||
eprintln!();
|
||||
|
||||
eprint_error(contents, *err);
|
||||
}
|
||||
|
@ -322,22 +322,19 @@ impl Engine {
|
||||
|
||||
/// Check a result to ensure that it is valid.
|
||||
pub(crate) fn check_return_value(&self, mut result: RhaiResult, _pos: Position) -> RhaiResult {
|
||||
match result {
|
||||
Ok(ref mut r) => {
|
||||
// Concentrate all empty strings into one instance to save memory
|
||||
if let Dynamic(Union::Str(s, ..)) = r {
|
||||
if s.is_empty() {
|
||||
if !s.ptr_eq(&self.empty_string) {
|
||||
*s = self.const_empty_string();
|
||||
}
|
||||
return result;
|
||||
if let Ok(ref mut r) = result {
|
||||
// Concentrate all empty strings into one instance to save memory
|
||||
if let Dynamic(Union::Str(s, ..)) = r {
|
||||
if s.is_empty() {
|
||||
if !s.ptr_eq(&self.empty_string) {
|
||||
*s = self.const_empty_string();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
self.check_data_size(r, _pos)?;
|
||||
}
|
||||
_ => (),
|
||||
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
self.check_data_size(r, _pos)?;
|
||||
}
|
||||
|
||||
result
|
||||
|
@ -980,8 +980,8 @@ impl Engine {
|
||||
})?,
|
||||
offset,
|
||||
)
|
||||
} else if let Some(abs_index) = index.checked_abs() {
|
||||
let offset = abs_index as usize;
|
||||
} else {
|
||||
let offset = index.unsigned_abs() as usize;
|
||||
(
|
||||
// Count from end if negative
|
||||
s.chars().rev().nth(offset - 1).ok_or_else(|| {
|
||||
@ -990,9 +990,6 @@ impl Engine {
|
||||
})?,
|
||||
offset,
|
||||
)
|
||||
} else {
|
||||
let chars_len = s.chars().count();
|
||||
return Err(ERR::ErrorStringBounds(chars_len, index, idx_pos).into());
|
||||
};
|
||||
|
||||
Ok(Target::StringChar {
|
||||
|
@ -441,7 +441,6 @@ impl Engine {
|
||||
///
|
||||
/// It is up to the [`Engine`] to reactivate the debugger.
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub(crate) fn run_debugger_with_reset<'a>(
|
||||
&self,
|
||||
scope: &mut Scope,
|
||||
@ -464,7 +463,6 @@ impl Engine {
|
||||
///
|
||||
/// It is up to the [`Engine`] to reactivate the debugger.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub(crate) fn run_debugger_with_reset_raw<'a>(
|
||||
&self,
|
||||
scope: &mut Scope,
|
||||
@ -514,7 +512,6 @@ impl Engine {
|
||||
///
|
||||
/// It is up to the [`Engine`] to reactivate the debugger.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub(crate) fn run_debugger_raw<'a>(
|
||||
&self,
|
||||
scope: &mut Scope,
|
||||
|
@ -15,9 +15,7 @@ use std::prelude::v1::*;
|
||||
#[allow(dead_code)]
|
||||
pub fn calc_offset_len(length: usize, start: crate::INT, len: crate::INT) -> (usize, usize) {
|
||||
let start = if start < 0 {
|
||||
start.checked_abs().map_or(0, |positive_start| {
|
||||
length - usize::min(positive_start as usize, length)
|
||||
})
|
||||
length - usize::min(start.unsigned_abs() as usize, length)
|
||||
} else if start as usize >= length {
|
||||
return (length, 0);
|
||||
} else {
|
||||
@ -50,20 +48,14 @@ pub fn calc_index<E>(
|
||||
) -> Result<usize, E> {
|
||||
if start < 0 {
|
||||
if negative_count_from_end {
|
||||
let abs_start = start.unsigned_abs() as usize;
|
||||
|
||||
// Count from end if negative
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
return match start.checked_abs() {
|
||||
Some(positive_start) => {
|
||||
if (positive_start as usize) > length {
|
||||
err()
|
||||
} else {
|
||||
Ok(length - (positive_start as usize))
|
||||
}
|
||||
}
|
||||
None => err(),
|
||||
};
|
||||
#[cfg(feature = "unchecked")]
|
||||
return Ok(length - (start.abs() as usize));
|
||||
if abs_start > length {
|
||||
err()
|
||||
} else {
|
||||
Ok(length - abs_start)
|
||||
}
|
||||
} else {
|
||||
err()
|
||||
}
|
||||
|
@ -453,7 +453,7 @@ impl Engine {
|
||||
|
||||
// Check the data size of any `&mut` object, which may be changed.
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
if is_ref_mut && args.len() > 0 {
|
||||
if is_ref_mut && !args.is_empty() {
|
||||
self.check_data_size(args[0], pos)?;
|
||||
}
|
||||
|
||||
@ -1180,7 +1180,7 @@ impl Engine {
|
||||
if capture_scope && !scope.is_empty() {
|
||||
first_arg
|
||||
.iter()
|
||||
.map(|&v| v)
|
||||
.copied()
|
||||
.chain(a_expr.iter())
|
||||
.try_for_each(|expr| {
|
||||
self.get_arg_value(scope, global, caches, lib, this_ptr, expr, level)
|
||||
|
@ -173,10 +173,10 @@ pub fn calc_fn_hash(fn_name: &str, num: usize) -> u64 {
|
||||
pub fn calc_fn_params_hash(params: impl IntoIterator<Item = TypeId>) -> u64 {
|
||||
let s = &mut get_hasher();
|
||||
let mut len = 0;
|
||||
params
|
||||
.into_iter()
|
||||
.inspect(|_| len += 1)
|
||||
.for_each(|t| t.hash(s));
|
||||
params.into_iter().for_each(|t| {
|
||||
len += 1;
|
||||
t.hash(s)
|
||||
});
|
||||
len.hash(s);
|
||||
|
||||
match s.finish() {
|
||||
|
@ -37,17 +37,14 @@ pub use std::sync::Arc as Shared;
|
||||
|
||||
/// Synchronized shared object.
|
||||
#[cfg(not(feature = "sync"))]
|
||||
#[allow(dead_code)]
|
||||
pub use std::cell::RefCell as Locked;
|
||||
|
||||
/// Read-only lock guard for synchronized shared object.
|
||||
#[cfg(not(feature = "sync"))]
|
||||
#[allow(dead_code)]
|
||||
pub type LockGuard<'a, T> = std::cell::Ref<'a, T>;
|
||||
|
||||
/// Mutable lock guard for synchronized shared object.
|
||||
#[cfg(not(feature = "sync"))]
|
||||
#[allow(dead_code)]
|
||||
pub type LockGuardMut<'a, T> = std::cell::RefMut<'a, T>;
|
||||
|
||||
/// Synchronized shared object.
|
||||
@ -397,7 +394,7 @@ pub fn shared_take<T>(value: Shared<T>) -> T {
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
#[allow(dead_code)]
|
||||
pub fn locked_read<'a, T>(value: &'a Locked<T>) -> LockGuard<'a, T> {
|
||||
pub fn locked_read<T>(value: &Locked<T>) -> LockGuard<T> {
|
||||
#[cfg(not(feature = "sync"))]
|
||||
return value.borrow();
|
||||
|
||||
@ -409,7 +406,7 @@ pub fn locked_read<'a, T>(value: &'a Locked<T>) -> LockGuard<'a, T> {
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
#[allow(dead_code)]
|
||||
pub fn locked_write<'a, T>(value: &'a Locked<T>) -> LockGuardMut<'a, T> {
|
||||
pub fn locked_write<T>(value: &Locked<T>) -> LockGuardMut<T> {
|
||||
#[cfg(not(feature = "sync"))]
|
||||
return value.borrow_mut();
|
||||
|
||||
|
@ -56,7 +56,7 @@ pub fn by_value<T: Variant + Clone>(data: &mut Dynamic) -> T {
|
||||
|
||||
// We consume the argument and then replace it with () - the argument is not supposed to be used again.
|
||||
// This way, we avoid having to clone the argument again, because it is already a clone when passed here.
|
||||
return mem::take(data).cast::<T>();
|
||||
mem::take(data).cast::<T>()
|
||||
}
|
||||
|
||||
/// Trait to register custom Rust functions.
|
||||
|
@ -88,7 +88,7 @@ impl Engine {
|
||||
let orig_call_stack_len = global.debugger.call_stack().len();
|
||||
|
||||
// Put arguments into scope as variables
|
||||
scope.extend(fn_def.params.iter().cloned().zip(args.into_iter().map(|v| {
|
||||
scope.extend(fn_def.params.iter().cloned().zip(args.iter_mut().map(|v| {
|
||||
// Actually consume the arguments instead of cloning them
|
||||
mem::take(*v)
|
||||
})));
|
||||
@ -98,11 +98,7 @@ impl Engine {
|
||||
if self.debugger.is_some() {
|
||||
global.debugger.push_call_stack_frame(
|
||||
fn_def.name.clone(),
|
||||
scope
|
||||
.iter()
|
||||
.skip(orig_scope_len)
|
||||
.map(|(.., v)| v.clone())
|
||||
.collect(),
|
||||
scope.iter().skip(orig_scope_len).map(|(.., v)| v).collect(),
|
||||
global.source.clone(),
|
||||
pos,
|
||||
);
|
||||
|
@ -58,6 +58,7 @@
|
||||
|
||||
#![cfg_attr(feature = "no_std", no_std)]
|
||||
#![deny(missing_docs)]
|
||||
#![allow(clippy::unit_arg)]
|
||||
|
||||
#[cfg(feature = "no_std")]
|
||||
extern crate alloc;
|
||||
|
@ -128,10 +128,9 @@ impl FuncInfo {
|
||||
|
||||
let typ = typ.trim();
|
||||
|
||||
if typ.starts_with("rhai::") {
|
||||
return Self::format_type(&typ[6..], is_return_type);
|
||||
} else if typ.starts_with("&mut ") {
|
||||
let x = &typ[5..];
|
||||
if let Some(x) = typ.strip_prefix("rhai::") {
|
||||
return Self::format_type(x, is_return_type);
|
||||
} else if let Some(x) = typ.strip_prefix("&mut ") {
|
||||
let r = Self::format_type(x, false);
|
||||
return if r == x {
|
||||
typ.into()
|
||||
@ -1896,7 +1895,6 @@ impl Module {
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
#[cfg(feature = "internals")]
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn iter_script_fn_info(
|
||||
&self,
|
||||
) -> impl Iterator<
|
||||
|
@ -20,6 +20,7 @@ use std::{ops::AddAssign, slice::Iter, vec::IntoIter};
|
||||
/// let mut engine = Engine::new();
|
||||
/// engine.set_module_resolver(collection);
|
||||
/// ```
|
||||
#[derive(Default)]
|
||||
pub struct ModuleResolversCollection(Vec<Box<dyn ModuleResolver>>);
|
||||
|
||||
impl ModuleResolversCollection {
|
||||
@ -41,7 +42,7 @@ impl ModuleResolversCollection {
|
||||
/// ```
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
pub const fn new() -> Self {
|
||||
Self(Vec::new())
|
||||
}
|
||||
/// Append a [module resolver][ModuleResolver] to the end.
|
||||
|
@ -374,7 +374,7 @@ impl ModuleResolver for FileModuleResolver {
|
||||
pos: Position,
|
||||
) -> Option<RhaiResultOf<crate::AST>> {
|
||||
// Construct the script file path
|
||||
let file_path = self.get_file_path(path, source_path.map(|s| Path::new(s)));
|
||||
let file_path = self.get_file_path(path, source_path.map(Path::new));
|
||||
|
||||
// Load the script file and compile it
|
||||
Some(
|
||||
|
@ -212,26 +212,21 @@ fn optimize_stmt_block(
|
||||
};
|
||||
|
||||
// Flatten blocks
|
||||
loop {
|
||||
if let Some(n) = statements.iter().position(|s| match s {
|
||||
Stmt::Block(block, ..) if !block.iter().any(Stmt::is_block_dependent) => true,
|
||||
_ => false,
|
||||
}) {
|
||||
let (first, second) = statements.split_at_mut(n);
|
||||
let stmt = mem::take(&mut second[0]);
|
||||
let mut stmts = match stmt {
|
||||
Stmt::Block(block, ..) => block,
|
||||
stmt => unreachable!("Stmt::Block expected but gets {:?}", stmt),
|
||||
};
|
||||
statements = first
|
||||
.iter_mut()
|
||||
.map(mem::take)
|
||||
.chain(stmts.iter_mut().map(mem::take))
|
||||
.chain(second.iter_mut().skip(1).map(mem::take))
|
||||
.collect();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
while let Some(n) = statements.iter().position(
|
||||
|s| matches!(s, Stmt::Block(block, ..) if !block.iter().any(Stmt::is_block_dependent)),
|
||||
) {
|
||||
let (first, second) = statements.split_at_mut(n);
|
||||
let stmt = mem::take(&mut second[0]);
|
||||
let mut stmts = match stmt {
|
||||
Stmt::Block(block, ..) => block,
|
||||
stmt => unreachable!("Stmt::Block expected but gets {:?}", stmt),
|
||||
};
|
||||
statements = first
|
||||
.iter_mut()
|
||||
.map(mem::take)
|
||||
.chain(stmts.iter_mut().map(mem::take))
|
||||
.chain(second.iter_mut().skip(1).map(mem::take))
|
||||
.collect();
|
||||
|
||||
is_dirty = true;
|
||||
}
|
||||
@ -606,7 +601,7 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
||||
.iter()
|
||||
.all(|r| expressions[r.index()].is_always_true())
|
||||
{
|
||||
for r in ranges.iter().filter(|r| r.contains(value)) {
|
||||
if let Some(r) = ranges.iter().find(|r| r.contains(value)) {
|
||||
let range_block = &mut expressions[r.index()];
|
||||
|
||||
if range_block.is_always_true() {
|
||||
@ -698,11 +693,9 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
||||
optimize_expr(&mut b.condition, state, false);
|
||||
optimize_expr(&mut b.expr, state, false);
|
||||
|
||||
if b.is_always_false() {
|
||||
if !b.expr.is_unit() {
|
||||
b.expr = Expr::Unit(b.expr.position());
|
||||
state.set_dirty();
|
||||
}
|
||||
if b.is_always_false() && !b.expr.is_unit() {
|
||||
b.expr = Expr::Unit(b.expr.position());
|
||||
state.set_dirty();
|
||||
}
|
||||
}
|
||||
|
||||
@ -958,10 +951,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, _chaining: bool) {
|
||||
***x = optimize_stmt_block(mem::take(&mut **x), state, true, true, false);
|
||||
|
||||
// { Stmt(Expr) } - promote
|
||||
match &mut ****x {
|
||||
[ Stmt::Expr(e) ] => { state.set_dirty(); *expr = mem::take(e); }
|
||||
_ => ()
|
||||
}
|
||||
if let [ Stmt::Expr(e) ] = &mut ****x { state.set_dirty(); *expr = mem::take(e); }
|
||||
}
|
||||
// ()?.rhs
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
@ -1010,11 +1000,11 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, _chaining: bool) {
|
||||
*expr = result;
|
||||
}
|
||||
// array[-int]
|
||||
(Expr::Array(a, pos), Expr::IntegerConstant(i, ..)) if *i < 0 && i.checked_abs().map(|n| n as usize <= a.len()).unwrap_or(false) && a.iter().all(Expr::is_pure) => {
|
||||
(Expr::Array(a, pos), Expr::IntegerConstant(i, ..)) if *i < 0 && i.unsigned_abs() as usize <= a.len() && a.iter().all(Expr::is_pure) => {
|
||||
// Array literal where everything is pure - promote the indexed item.
|
||||
// All other items can be thrown away.
|
||||
state.set_dirty();
|
||||
let index = a.len() - i.abs() as usize;
|
||||
let index = a.len() - i.unsigned_abs() as usize;
|
||||
let mut result = mem::take(&mut a[index]);
|
||||
result.set_position(*pos);
|
||||
*expr = result;
|
||||
@ -1035,10 +1025,10 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, _chaining: bool) {
|
||||
*expr = Expr::BoolConstant((*n & (1 << (*i as usize))) != 0, *pos);
|
||||
}
|
||||
// int[-int]
|
||||
(Expr::IntegerConstant(n, pos), Expr::IntegerConstant(i, ..)) if *i < 0 && i.checked_abs().map(|i| i as usize <= crate::INT_BITS).unwrap_or(false) => {
|
||||
(Expr::IntegerConstant(n, pos), Expr::IntegerConstant(i, ..)) if *i < 0 && i.unsigned_abs() as usize <= crate::INT_BITS => {
|
||||
// Bit-field literal indexing - get the bit
|
||||
state.set_dirty();
|
||||
*expr = Expr::BoolConstant((*n & (1 << (crate::INT_BITS - i.abs() as usize))) != 0, *pos);
|
||||
*expr = Expr::BoolConstant((*n & (1 << (crate::INT_BITS - i.unsigned_abs() as usize))) != 0, *pos);
|
||||
}
|
||||
// string[int]
|
||||
(Expr::StringConstant(s, pos), Expr::IntegerConstant(i, ..)) if *i >= 0 && (*i as usize) < s.chars().count() => {
|
||||
@ -1047,10 +1037,10 @@ fn optimize_expr(expr: &mut Expr, state: &mut OptimizerState, _chaining: bool) {
|
||||
*expr = Expr::CharConstant(s.chars().nth(*i as usize).unwrap(), *pos);
|
||||
}
|
||||
// string[-int]
|
||||
(Expr::StringConstant(s, pos), Expr::IntegerConstant(i, ..)) if *i < 0 && i.checked_abs().map(|n| n as usize <= s.chars().count()).unwrap_or(false) => {
|
||||
(Expr::StringConstant(s, pos), Expr::IntegerConstant(i, ..)) if *i < 0 && i.unsigned_abs() as usize <= s.chars().count() => {
|
||||
// String literal indexing - get the character
|
||||
state.set_dirty();
|
||||
*expr = Expr::CharConstant(s.chars().rev().nth(i.abs() as usize - 1).unwrap(), *pos);
|
||||
*expr = Expr::CharConstant(s.chars().rev().nth(i.unsigned_abs() as usize - 1).unwrap(), *pos);
|
||||
}
|
||||
// var[rhs]
|
||||
(Expr::Variable(..), rhs) => optimize_expr(rhs, state, true),
|
||||
|
@ -290,7 +290,7 @@ pub mod array_functions {
|
||||
if array.is_empty() {
|
||||
Dynamic::UNIT
|
||||
} else {
|
||||
array.pop().unwrap_or_else(|| Dynamic::UNIT)
|
||||
array.pop().unwrap_or(Dynamic::UNIT)
|
||||
}
|
||||
}
|
||||
/// Remove the first element from the array and return it.
|
||||
@ -1344,7 +1344,7 @@ pub mod array_functions {
|
||||
array.dedup_by(|x, y| {
|
||||
comparer
|
||||
.call_raw(&ctx, None, [y.clone(), x.clone()])
|
||||
.unwrap_or_else(|_| Dynamic::FALSE)
|
||||
.unwrap_or(Dynamic::FALSE)
|
||||
.as_bool()
|
||||
.unwrap_or(false)
|
||||
});
|
||||
|
@ -96,16 +96,11 @@ impl<T: Debug + Copy + PartialOrd> Iterator for StepRange<T> {
|
||||
|
||||
self.from = (self.add)(self.from, self.step)?;
|
||||
|
||||
if self.dir > 0 {
|
||||
if self.from >= self.to {
|
||||
self.dir = 0;
|
||||
}
|
||||
} else if self.dir < 0 {
|
||||
if self.from <= self.to {
|
||||
self.dir = 0;
|
||||
}
|
||||
} else {
|
||||
unreachable!("`dir` != 0");
|
||||
match self.dir.cmp(&0) {
|
||||
Ordering::Greater if self.from >= self.to => self.dir = 0,
|
||||
Ordering::Less if self.from <= self.to => self.dir = 0,
|
||||
Ordering::Equal => unreachable!("`dir` != 0"),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
Some(v)
|
||||
@ -184,28 +179,15 @@ impl CharsStream {
|
||||
0,
|
||||
);
|
||||
}
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
return if let Some(abs_from) = from.checked_abs() {
|
||||
let num_chars = string.chars().count();
|
||||
let offset = if num_chars < (abs_from as usize) {
|
||||
0
|
||||
} else {
|
||||
num_chars - (abs_from as usize)
|
||||
};
|
||||
Self(string.chars().skip(offset).take(len as usize).collect(), 0)
|
||||
} else {
|
||||
Self(string.chars().skip(0).take(len as usize).collect(), 0)
|
||||
};
|
||||
|
||||
#[cfg(feature = "unchecked")]
|
||||
return Self(
|
||||
string
|
||||
.chars()
|
||||
.skip(from as usize)
|
||||
.take(len as usize)
|
||||
.collect(),
|
||||
0,
|
||||
);
|
||||
let abs_from = from.unsigned_abs() as usize;
|
||||
let num_chars = string.chars().count();
|
||||
let offset = if num_chars < abs_from {
|
||||
0
|
||||
} else {
|
||||
num_chars - abs_from
|
||||
};
|
||||
Self(string.chars().skip(offset).take(len as usize).collect(), 0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ mod map_functions {
|
||||
/// ```
|
||||
pub fn remove(map: &mut Map, property: &str) -> Dynamic {
|
||||
if !map.is_empty() {
|
||||
map.remove(property).unwrap_or_else(|| Dynamic::UNIT)
|
||||
map.remove(property).unwrap_or(Dynamic::UNIT)
|
||||
} else {
|
||||
Dynamic::UNIT
|
||||
}
|
||||
|
@ -534,20 +534,17 @@ mod string_functions {
|
||||
}
|
||||
|
||||
let start = if start < 0 {
|
||||
if let Some(n) = start.checked_abs() {
|
||||
let chars: Vec<_> = string.chars().collect();
|
||||
let num_chars = chars.len();
|
||||
if n as usize > num_chars {
|
||||
0
|
||||
} else {
|
||||
chars
|
||||
.into_iter()
|
||||
.take(num_chars - n as usize)
|
||||
.collect::<String>()
|
||||
.len()
|
||||
}
|
||||
} else {
|
||||
let abs_start = start.unsigned_abs() as usize;
|
||||
let chars: Vec<_> = string.chars().collect();
|
||||
let num_chars = chars.len();
|
||||
if abs_start > num_chars {
|
||||
0
|
||||
} else {
|
||||
chars
|
||||
.into_iter()
|
||||
.take(num_chars - abs_start)
|
||||
.collect::<String>()
|
||||
.len()
|
||||
}
|
||||
} else if start == 0 {
|
||||
0
|
||||
@ -615,20 +612,17 @@ mod string_functions {
|
||||
}
|
||||
|
||||
let start = if start < 0 {
|
||||
if let Some(n) = start.checked_abs() {
|
||||
let chars = string.chars().collect::<Vec<_>>();
|
||||
let num_chars = chars.len();
|
||||
if n as usize > num_chars {
|
||||
0
|
||||
} else {
|
||||
chars
|
||||
.into_iter()
|
||||
.take(num_chars - n as usize)
|
||||
.collect::<String>()
|
||||
.len()
|
||||
}
|
||||
} else {
|
||||
let abs_start = start.unsigned_abs() as usize;
|
||||
let chars = string.chars().collect::<Vec<_>>();
|
||||
let num_chars = chars.len();
|
||||
if abs_start > num_chars {
|
||||
0
|
||||
} else {
|
||||
chars
|
||||
.into_iter()
|
||||
.take(num_chars - abs_start)
|
||||
.collect::<String>()
|
||||
.len()
|
||||
}
|
||||
} else if start == 0 {
|
||||
0
|
||||
@ -694,15 +688,13 @@ mod string_functions {
|
||||
.chars()
|
||||
.nth(index as usize)
|
||||
.map_or_else(|| Dynamic::UNIT, Into::into)
|
||||
} else if let Some(abs_index) = index.checked_abs() {
|
||||
} else {
|
||||
// Count from end if negative
|
||||
string
|
||||
.chars()
|
||||
.rev()
|
||||
.nth((abs_index as usize) - 1)
|
||||
.nth((index.unsigned_abs() as usize) - 1)
|
||||
.map_or_else(|| Dynamic::UNIT, Into::into)
|
||||
} else {
|
||||
Dynamic::UNIT
|
||||
}
|
||||
}
|
||||
/// Set the `index` position in the string to a new `character`.
|
||||
@ -736,11 +728,12 @@ mod string_functions {
|
||||
.enumerate()
|
||||
.map(|(i, ch)| if i == index { character } else { ch })
|
||||
.collect();
|
||||
} else if let Some(abs_index) = index.checked_abs() {
|
||||
} else {
|
||||
let abs_index = index.unsigned_abs() as usize;
|
||||
let string_len = string.chars().count();
|
||||
|
||||
if abs_index as usize <= string_len {
|
||||
let index = string_len - (abs_index as usize);
|
||||
if abs_index <= string_len {
|
||||
let index = string_len - abs_index;
|
||||
*string = string
|
||||
.chars()
|
||||
.enumerate()
|
||||
@ -820,15 +813,12 @@ mod string_functions {
|
||||
let offset = if string.is_empty() || len <= 0 {
|
||||
return ctx.engine().const_empty_string();
|
||||
} else if start < 0 {
|
||||
if let Some(n) = start.checked_abs() {
|
||||
chars.extend(string.chars());
|
||||
if n as usize > chars.len() {
|
||||
0
|
||||
} else {
|
||||
chars.len() - n as usize
|
||||
}
|
||||
} else {
|
||||
let abs_start = start.unsigned_abs() as usize;
|
||||
chars.extend(string.chars());
|
||||
if abs_start > chars.len() {
|
||||
0
|
||||
} else {
|
||||
chars.len() - abs_start
|
||||
}
|
||||
} else if start as usize >= string.chars().count() {
|
||||
return ctx.engine().const_empty_string();
|
||||
@ -952,15 +942,12 @@ mod string_functions {
|
||||
string.make_mut().clear();
|
||||
return;
|
||||
} else if start < 0 {
|
||||
if let Some(n) = start.checked_abs() {
|
||||
chars.extend(string.chars());
|
||||
if n as usize > chars.len() {
|
||||
0
|
||||
} else {
|
||||
chars.len() - n as usize
|
||||
}
|
||||
} else {
|
||||
let abs_start = start.unsigned_abs() as usize;
|
||||
chars.extend(string.chars());
|
||||
if abs_start > chars.len() {
|
||||
0
|
||||
} else {
|
||||
chars.len() - abs_start
|
||||
}
|
||||
} else if start as usize >= string.chars().count() {
|
||||
string.make_mut().clear();
|
||||
@ -1256,23 +1243,17 @@ mod string_functions {
|
||||
#[rhai_fn(name = "split")]
|
||||
pub fn split_at(ctx: NativeCallContext, string: &mut ImmutableString, index: INT) -> Array {
|
||||
if index <= 0 {
|
||||
if let Some(n) = index.checked_abs() {
|
||||
let num_chars = string.chars().count();
|
||||
if n as usize > num_chars {
|
||||
vec![
|
||||
ctx.engine().const_empty_string().into(),
|
||||
string.as_str().into(),
|
||||
]
|
||||
} else {
|
||||
let prefix: String = string.chars().take(num_chars - n as usize).collect();
|
||||
let prefix_len = prefix.len();
|
||||
vec![prefix.into(), string[prefix_len..].into()]
|
||||
}
|
||||
} else {
|
||||
let abs_index = index.unsigned_abs() as usize;
|
||||
let num_chars = string.chars().count();
|
||||
if abs_index > num_chars {
|
||||
vec![
|
||||
ctx.engine().const_empty_string().into(),
|
||||
string.as_str().into(),
|
||||
]
|
||||
} else {
|
||||
let prefix: String = string.chars().take(num_chars - abs_index).collect();
|
||||
let prefix_len = prefix.len();
|
||||
vec![prefix.into(), string[prefix_len..].into()]
|
||||
}
|
||||
} else {
|
||||
let prefix: String = string.chars().take(index as usize).collect();
|
||||
|
@ -265,10 +265,8 @@ impl ParseSettings {
|
||||
#[cfg(not(feature = "unchecked"))]
|
||||
#[inline]
|
||||
pub fn ensure_level_within_max_limit(&self, limit: usize) -> ParseResult<()> {
|
||||
if limit > 0 {
|
||||
if self.level > limit {
|
||||
return Err(PERR::ExprTooDeep.into_err(self.pos));
|
||||
}
|
||||
if limit > 0 && self.level > limit {
|
||||
return Err(PERR::ExprTooDeep.into_err(self.pos));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -531,11 +529,14 @@ impl Engine {
|
||||
#[cfg(any(feature = "no_function", feature = "no_module"))]
|
||||
let is_global = false;
|
||||
|
||||
if settings.options.contains(LangOptions::STRICT_VAR) && index.is_none() {
|
||||
if !is_global && !self.global_sub_modules.contains_key(root) {
|
||||
return Err(PERR::ModuleUndefined(root.to_string())
|
||||
.into_err(namespace.position()));
|
||||
}
|
||||
if settings.options.contains(LangOptions::STRICT_VAR)
|
||||
&& index.is_none()
|
||||
&& !is_global
|
||||
&& !self.global_sub_modules.contains_key(root)
|
||||
{
|
||||
return Err(
|
||||
PERR::ModuleUndefined(root.to_string()).into_err(namespace.position())
|
||||
);
|
||||
}
|
||||
|
||||
namespace.set_index(index);
|
||||
@ -595,11 +596,13 @@ impl Engine {
|
||||
#[cfg(any(feature = "no_function", feature = "no_module"))]
|
||||
let is_global = false;
|
||||
|
||||
if settings.options.contains(LangOptions::STRICT_VAR) && index.is_none() {
|
||||
if !is_global && !self.global_sub_modules.contains_key(root) {
|
||||
return Err(PERR::ModuleUndefined(root.to_string())
|
||||
.into_err(namespace.position()));
|
||||
}
|
||||
if settings.options.contains(LangOptions::STRICT_VAR)
|
||||
&& index.is_none()
|
||||
&& !is_global
|
||||
&& !self.global_sub_modules.contains_key(root)
|
||||
{
|
||||
return Err(PERR::ModuleUndefined(root.to_string())
|
||||
.into_err(namespace.position()));
|
||||
}
|
||||
|
||||
namespace.set_index(index);
|
||||
@ -1755,11 +1758,14 @@ impl Engine {
|
||||
#[cfg(any(feature = "no_function", feature = "no_module"))]
|
||||
let is_global = false;
|
||||
|
||||
if settings.options.contains(LangOptions::STRICT_VAR) && index.is_none() {
|
||||
if !is_global && !self.global_sub_modules.contains_key(root) {
|
||||
return Err(PERR::ModuleUndefined(root.to_string())
|
||||
.into_err(namespace.position()));
|
||||
}
|
||||
if settings.options.contains(LangOptions::STRICT_VAR)
|
||||
&& index.is_none()
|
||||
&& !is_global
|
||||
&& !self.global_sub_modules.contains_key(root)
|
||||
{
|
||||
return Err(
|
||||
PERR::ModuleUndefined(root.to_string()).into_err(namespace.position())
|
||||
);
|
||||
}
|
||||
|
||||
namespace.set_index(index);
|
||||
@ -2519,13 +2525,13 @@ impl Engine {
|
||||
const KEYWORD_SEMICOLON: &str = Token::SemiColon.literal_syntax();
|
||||
const KEYWORD_CLOSE_BRACE: &str = Token::RightBrace.literal_syntax();
|
||||
|
||||
let self_terminated = match required_token.as_str() {
|
||||
let self_terminated = matches!(
|
||||
required_token.as_str(),
|
||||
// It is self-terminating if the last symbol is a block
|
||||
CUSTOM_SYNTAX_MARKER_BLOCK => true,
|
||||
CUSTOM_SYNTAX_MARKER_BLOCK |
|
||||
// If the last symbol is `;` or `}`, it is self-terminating
|
||||
KEYWORD_SEMICOLON | KEYWORD_CLOSE_BRACE => true,
|
||||
_ => false,
|
||||
};
|
||||
KEYWORD_SEMICOLON | KEYWORD_CLOSE_BRACE
|
||||
);
|
||||
|
||||
Ok(Expr::Custom(
|
||||
crate::ast::CustomExpr {
|
||||
@ -2794,12 +2800,12 @@ impl Engine {
|
||||
// let name ...
|
||||
let (name, pos) = parse_var_name(input)?;
|
||||
|
||||
if !self.allow_shadowing() && state.stack.iter().any(|(v, ..)| v == &name) {
|
||||
if !self.allow_shadowing() && state.stack.iter().any(|(v, ..)| v == name) {
|
||||
return Err(PERR::VariableExists(name.to_string()).into_err(pos));
|
||||
}
|
||||
|
||||
if let Some(ref filter) = self.def_var_filter {
|
||||
let will_shadow = state.stack.iter().any(|(v, ..)| v == &name);
|
||||
let will_shadow = state.stack.iter().any(|(v, ..)| v == name);
|
||||
let level = settings.level;
|
||||
let is_const = access == AccessMode::ReadOnly;
|
||||
let info = VarDefInfo {
|
||||
@ -3192,7 +3198,6 @@ impl Engine {
|
||||
level: 0,
|
||||
options,
|
||||
pos,
|
||||
..settings
|
||||
};
|
||||
|
||||
let func = self.parse_fn(
|
||||
|
@ -455,7 +455,7 @@ impl<'de> Deserializer<'de> for &mut DynamicDeserializer<'de> {
|
||||
let second = iter.next();
|
||||
if let (Some((key, value)), None) = (first, second) {
|
||||
visitor.visit_enum(EnumDeserializer {
|
||||
tag: &key,
|
||||
tag: key,
|
||||
content: DynamicDeserializer::from_dynamic(value),
|
||||
})
|
||||
} else {
|
||||
|
@ -439,7 +439,7 @@ impl Hash for Dynamic {
|
||||
mem::discriminant(&self.0).hash(state);
|
||||
|
||||
match self.0 {
|
||||
Union::Unit(..) => ().hash(state),
|
||||
Union::Unit(..) => (),
|
||||
Union::Bool(ref b, ..) => b.hash(state),
|
||||
Union::Str(ref s, ..) => s.hash(state),
|
||||
Union::Char(ref c, ..) => c.hash(state),
|
||||
@ -1018,17 +1018,11 @@ impl Dynamic {
|
||||
#[must_use]
|
||||
pub fn is_read_only(&self) -> bool {
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
match self.0 {
|
||||
// Shared values do not consider the current access mode
|
||||
//Union::Shared(.., ReadOnly) => return true,
|
||||
Union::Shared(ref cell, ..) => {
|
||||
return match locked_read(cell).access_mode() {
|
||||
ReadWrite => false,
|
||||
ReadOnly => true,
|
||||
}
|
||||
}
|
||||
|
||||
_ => (),
|
||||
if let Union::Shared(ref cell, ..) = self.0 {
|
||||
return match locked_read(cell).access_mode() {
|
||||
ReadWrite => false,
|
||||
ReadOnly => true,
|
||||
};
|
||||
}
|
||||
|
||||
match self.access_mode() {
|
||||
@ -1368,14 +1362,11 @@ impl Dynamic {
|
||||
#[must_use]
|
||||
pub fn is_locked(&self) -> bool {
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
match self.0 {
|
||||
Union::Shared(ref _cell, ..) => {
|
||||
#[cfg(not(feature = "sync"))]
|
||||
return _cell.try_borrow().is_err();
|
||||
#[cfg(feature = "sync")]
|
||||
return false;
|
||||
}
|
||||
_ => (),
|
||||
if let Union::Shared(ref _cell, ..) = self.0 {
|
||||
#[cfg(not(feature = "sync"))]
|
||||
return _cell.try_borrow().is_err();
|
||||
#[cfg(feature = "sync")]
|
||||
return false;
|
||||
}
|
||||
|
||||
false
|
||||
@ -1791,7 +1782,7 @@ impl Dynamic {
|
||||
#[cfg(feature = "no_closure")]
|
||||
let typ = v.type_name();
|
||||
|
||||
v.try_cast::<T>().ok_or_else(|| typ)
|
||||
v.try_cast::<T>().ok_or(typ)
|
||||
})
|
||||
.collect(),
|
||||
Union::Blob(..) if TypeId::of::<T>() == TypeId::of::<u8>() => Ok(self.cast::<Vec<T>>()),
|
||||
@ -1813,7 +1804,7 @@ impl Dynamic {
|
||||
#[cfg(feature = "no_closure")]
|
||||
let typ = v.type_name();
|
||||
|
||||
v.read_lock::<T>().ok_or_else(|| typ).map(|v| v.clone())
|
||||
v.read_lock::<T>().ok_or(typ).map(|v| v.clone())
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
@ -170,14 +170,14 @@ impl<'a> FromIterator<&'a str> for ImmutableString {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromIterator<String> for ImmutableString {
|
||||
impl FromIterator<String> for ImmutableString {
|
||||
#[inline]
|
||||
fn from_iter<T: IntoIterator<Item = String>>(iter: T) -> Self {
|
||||
Self(iter.into_iter().collect::<SmartString>().into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> FromIterator<SmartString> for ImmutableString {
|
||||
impl FromIterator<SmartString> for ImmutableString {
|
||||
#[inline]
|
||||
fn from_iter<T: IntoIterator<Item = SmartString>>(iter: T) -> Self {
|
||||
Self(iter.into_iter().collect::<SmartString>().into())
|
||||
|
@ -112,7 +112,7 @@ impl Clone for Scope<'_> {
|
||||
.collect(),
|
||||
names: self.names.clone(),
|
||||
aliases: self.aliases.clone(),
|
||||
dummy: self.dummy.clone(),
|
||||
dummy: self.dummy,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -437,11 +437,9 @@ impl Scope<'_> {
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn is_constant(&self, name: &str) -> Option<bool> {
|
||||
self.get_index(name).and_then(|(.., access)| {
|
||||
Some(match access {
|
||||
AccessMode::ReadWrite => false,
|
||||
AccessMode::ReadOnly => true,
|
||||
})
|
||||
self.get_index(name).map(|(.., access)| match access {
|
||||
AccessMode::ReadWrite => false,
|
||||
AccessMode::ReadOnly => true,
|
||||
})
|
||||
}
|
||||
/// Update the value of the named entry in the [`Scope`] if it already exists and is not constant.
|
||||
|
Loading…
Reference in New Issue
Block a user