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