Refactor.
This commit is contained in:
parent
796206f293
commit
d6b0f99781
@ -25,7 +25,7 @@ Enhancements
|
|||||||
* `Scope` is now serializable and deserializable via `serde`.
|
* `Scope` is now serializable and deserializable via `serde`.
|
||||||
* `Scope` now contains a const generic parameter that allows specifying how many entries to be kept inline.
|
* `Scope` now contains a const generic parameter that allows specifying how many entries to be kept inline.
|
||||||
* `parse_json` function is added to parse a JSON string into an object map.
|
* `parse_json` function is added to parse a JSON string into an object map.
|
||||||
* Methods return maximum limits (e.g. `max_string_len`) are now available even under `unchecked` in order to avoid unnecessary feature flags in third-party library code.
|
* Methods returning maximum limits (e.g. `Engine::max_string_len`) are now available even under `unchecked` in order to avoid unnecessary feature flags in third-party library code.
|
||||||
|
|
||||||
|
|
||||||
Version 1.10.1
|
Version 1.10.1
|
||||||
|
@ -101,6 +101,27 @@ impl Default for Limits {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Engine {
|
impl Engine {
|
||||||
|
/// Is there a data size limit set?
|
||||||
|
#[inline]
|
||||||
|
pub(crate) const fn has_data_size_limit(&self) -> bool {
|
||||||
|
self.limits.max_string_size.is_some()
|
||||||
|
|| {
|
||||||
|
#[cfg(not(feature = "no_index"))]
|
||||||
|
{
|
||||||
|
self.limits.max_array_size.is_some()
|
||||||
|
}
|
||||||
|
#[cfg(feature = "no_index")]
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|| {
|
||||||
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
{
|
||||||
|
self.limits.max_map_size.is_some()
|
||||||
|
}
|
||||||
|
#[cfg(feature = "no_object")]
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
/// Set the maximum levels of function calls allowed for a script in order to avoid
|
/// Set the maximum levels of function calls allowed for a script in order to avoid
|
||||||
/// infinite recursion and stack overflows.
|
/// infinite recursion and stack overflows.
|
||||||
///
|
///
|
||||||
@ -137,10 +158,9 @@ impl Engine {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn max_operations(&self) -> u64 {
|
pub const fn max_operations(&self) -> u64 {
|
||||||
if let Some(n) = self.limits.max_operations {
|
match self.limits.max_operations {
|
||||||
n.get()
|
Some(n) => n.get(),
|
||||||
} else {
|
None => 0,
|
||||||
0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Set the maximum number of imported [modules][crate::Module] allowed for a script.
|
/// Set the maximum number of imported [modules][crate::Module] allowed for a script.
|
||||||
@ -183,10 +203,9 @@ impl Engine {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn max_expr_depth(&self) -> usize {
|
pub const fn max_expr_depth(&self) -> usize {
|
||||||
if let Some(n) = self.limits.max_expr_depth {
|
match self.limits.max_expr_depth {
|
||||||
n.get()
|
Some(n) => n.get(),
|
||||||
} else {
|
None => 0,
|
||||||
0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// The depth limit for expressions in functions (0 for unlimited).
|
/// The depth limit for expressions in functions (0 for unlimited).
|
||||||
@ -196,10 +215,9 @@ impl Engine {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn max_function_expr_depth(&self) -> usize {
|
pub const fn max_function_expr_depth(&self) -> usize {
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
return if let Some(n) = self.limits.max_function_expr_depth {
|
return match self.limits.max_function_expr_depth {
|
||||||
n.get()
|
Some(n) => n.get(),
|
||||||
} else {
|
None => 0,
|
||||||
0
|
|
||||||
};
|
};
|
||||||
#[cfg(feature = "no_function")]
|
#[cfg(feature = "no_function")]
|
||||||
return 0;
|
return 0;
|
||||||
@ -216,10 +234,9 @@ impl Engine {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn max_string_size(&self) -> usize {
|
pub const fn max_string_size(&self) -> usize {
|
||||||
if let Some(n) = self.limits.max_string_size {
|
match self.limits.max_string_size {
|
||||||
n.get()
|
Some(n) => n.get(),
|
||||||
} else {
|
None => 0,
|
||||||
0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Set the maximum length of [arrays][crate::Array] (0 for unlimited).
|
/// Set the maximum length of [arrays][crate::Array] (0 for unlimited).
|
||||||
@ -238,10 +255,9 @@ impl Engine {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn max_array_size(&self) -> usize {
|
pub const fn max_array_size(&self) -> usize {
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
return if let Some(n) = self.limits.max_array_size {
|
return match self.limits.max_array_size {
|
||||||
n.get()
|
Some(n) => n.get(),
|
||||||
} else {
|
None => 0,
|
||||||
0
|
|
||||||
};
|
};
|
||||||
#[cfg(feature = "no_index")]
|
#[cfg(feature = "no_index")]
|
||||||
return 0;
|
return 0;
|
||||||
@ -262,10 +278,9 @@ impl Engine {
|
|||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn max_map_size(&self) -> usize {
|
pub const fn max_map_size(&self) -> usize {
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
return if let Some(n) = self.limits.max_map_size {
|
return match self.limits.max_map_size {
|
||||||
n.get()
|
Some(n) => n.get(),
|
||||||
} else {
|
None => 0,
|
||||||
0
|
|
||||||
};
|
};
|
||||||
#[cfg(feature = "no_object")]
|
#[cfg(feature = "no_object")]
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -45,7 +45,6 @@ fn print_source(lines: &[String], pos: Position, offset: usize, window: (usize,
|
|||||||
if n == line {
|
if n == line {
|
||||||
if let Some(pos) = pos.position() {
|
if let Some(pos) = pos.position() {
|
||||||
let shift = offset + line_no_len + marker.len() + 2;
|
let shift = offset + line_no_len + marker.len() + 2;
|
||||||
|
|
||||||
println!("{0:>1$}{2:>3$}", "│ ", shift, "\x1b[36m^\x1b[39m", pos + 10);
|
println!("{0:>1$}{2:>3$}", "│ ", shift, "\x1b[36m^\x1b[39m", pos + 10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -310,10 +309,11 @@ fn debug_callback(
|
|||||||
["node"] => {
|
["node"] => {
|
||||||
if pos.is_none() {
|
if pos.is_none() {
|
||||||
println!("{:?}", node);
|
println!("{:?}", node);
|
||||||
} else if let Some(source) = source {
|
|
||||||
println!("{:?} {} @ {:?}", node, source, pos);
|
|
||||||
} else {
|
} else {
|
||||||
println!("{:?} @ {:?}", node, pos);
|
match source {
|
||||||
|
Some(source) => println!("{:?} {} @ {:?}", node, source, pos),
|
||||||
|
None => println!("{:?} @ {:?}", node, pos),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
println!();
|
println!();
|
||||||
}
|
}
|
||||||
@ -339,20 +339,14 @@ fn debug_callback(
|
|||||||
["over" | "o"] => break Ok(DebuggerCommand::StepOver),
|
["over" | "o"] => break Ok(DebuggerCommand::StepOver),
|
||||||
["next" | "n"] => break Ok(DebuggerCommand::Next),
|
["next" | "n"] => break Ok(DebuggerCommand::Next),
|
||||||
["scope"] => println!("{}", context.scope()),
|
["scope"] => println!("{}", context.scope()),
|
||||||
["print" | "p", "this"] => {
|
["print" | "p", "this"] => match context.this_ptr() {
|
||||||
if let Some(value) = context.this_ptr() {
|
Some(value) => println!("=> {:?}", value),
|
||||||
println!("=> {:?}", value);
|
None => println!("`this` pointer is unbound."),
|
||||||
} else {
|
},
|
||||||
println!("`this` pointer is unbound.");
|
["print" | "p", var_name] => match context.scope().get_value::<Dynamic>(var_name) {
|
||||||
}
|
Some(value) => println!("=> {:?}", value),
|
||||||
}
|
None => eprintln!("Variable not found: {}", var_name),
|
||||||
["print" | "p", var_name] => {
|
},
|
||||||
if let Some(value) = context.scope().get_value::<Dynamic>(var_name) {
|
|
||||||
println!("=> {:?}", value);
|
|
||||||
} else {
|
|
||||||
eprintln!("Variable not found: {}", var_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
["print" | "p"] => {
|
["print" | "p"] => {
|
||||||
println!("{}", context.scope().clone_visible());
|
println!("{}", context.scope().clone_visible());
|
||||||
if let Some(value) = context.this_ptr() {
|
if let Some(value) = context.this_ptr() {
|
||||||
|
@ -482,27 +482,30 @@ fn main() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
"!!" => {
|
"!!" => {
|
||||||
if let Some(line) = rl.history().last() {
|
match rl.history().last() {
|
||||||
|
Some(line) => {
|
||||||
replacement = Some(line.clone());
|
replacement = Some(line.clone());
|
||||||
replacement_index = history_offset + rl.history().len() - 1;
|
replacement_index = history_offset + rl.history().len() - 1;
|
||||||
} else {
|
}
|
||||||
eprintln!("No lines history!");
|
None => eprintln!("No lines history!"),
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
_ if cmd.starts_with("!?") => {
|
_ if cmd.starts_with("!?") => {
|
||||||
let text = cmd[2..].trim();
|
let text = cmd[2..].trim();
|
||||||
if let Some((n, line)) = rl
|
let history = rl
|
||||||
.history()
|
.history()
|
||||||
.iter()
|
.iter()
|
||||||
.rev()
|
.rev()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.find(|&(.., h)| h.contains(text))
|
.find(|&(.., h)| h.contains(text));
|
||||||
{
|
|
||||||
|
match history {
|
||||||
|
Some((n, line)) => {
|
||||||
replacement = Some(line.clone());
|
replacement = Some(line.clone());
|
||||||
replacement_index = history_offset + (rl.history().len() - 1 - n);
|
replacement_index = history_offset + (rl.history().len() - 1 - n);
|
||||||
} else {
|
}
|
||||||
eprintln!("History line not found: {}", text);
|
None => eprintln!("History line not found: {}", text),
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
use super::GlobalRuntimeState;
|
use super::GlobalRuntimeState;
|
||||||
use crate::types::dynamic::Union;
|
use crate::types::dynamic::Union;
|
||||||
use crate::{Dynamic, Engine, Position, RhaiResultOf, ERR};
|
use crate::{Dynamic, Engine, Position, RhaiResultOf, ERR};
|
||||||
use std::num::NonZeroUsize;
|
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
|
|
||||||
@ -21,40 +20,40 @@ impl Engine {
|
|||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Union::Array(ref arr, ..) => {
|
Union::Array(ref arr, ..) => {
|
||||||
arr.iter()
|
arr.iter()
|
||||||
.fold((0, 0, 0), |(arrays, maps, strings), value| match value.0 {
|
.fold((0, 0, 0), |(ax, mx, sx), value| match value.0 {
|
||||||
Union::Array(..) => {
|
Union::Array(..) => {
|
||||||
let (a, m, s) = Self::calc_data_sizes(value, false);
|
let (a, m, s) = Self::calc_data_sizes(value, false);
|
||||||
(arrays + a + 1, maps + m, strings + s)
|
(ax + a + 1, mx + m, sx + s)
|
||||||
}
|
}
|
||||||
Union::Blob(ref a, ..) => (arrays + 1 + a.len(), maps, strings),
|
Union::Blob(ref a, ..) => (ax + 1 + a.len(), mx, sx),
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Union::Map(..) => {
|
Union::Map(..) => {
|
||||||
let (a, m, s) = Self::calc_data_sizes(value, false);
|
let (a, m, s) = Self::calc_data_sizes(value, false);
|
||||||
(arrays + a + 1, maps + m, strings + s)
|
(ax + a + 1, mx + m, sx + s)
|
||||||
}
|
}
|
||||||
Union::Str(ref s, ..) => (arrays + 1, maps, strings + s.len()),
|
Union::Str(ref s, ..) => (ax + 1, mx, sx + s.len()),
|
||||||
_ => (arrays + 1, maps, strings),
|
_ => (ax + 1, mx, sx),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Union::Blob(ref arr, ..) => (arr.len(), 0, 0),
|
Union::Blob(ref blob, ..) => (blob.len(), 0, 0),
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Union::Map(ref map, ..) => {
|
Union::Map(ref map, ..) => {
|
||||||
map.values()
|
map.values()
|
||||||
.fold((0, 0, 0), |(arrays, maps, strings), value| match value.0 {
|
.fold((0, 0, 0), |(ax, mx, sx), value| match value.0 {
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Union::Array(..) => {
|
Union::Array(..) => {
|
||||||
let (a, m, s) = Self::calc_data_sizes(value, false);
|
let (a, m, s) = Self::calc_data_sizes(value, false);
|
||||||
(arrays + a, maps + m + 1, strings + s)
|
(ax + a, mx + m + 1, sx + s)
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
Union::Blob(ref a, ..) => (arrays + a.len(), maps, strings),
|
Union::Blob(ref a, ..) => (ax + a.len(), mx, sx),
|
||||||
Union::Map(..) => {
|
Union::Map(..) => {
|
||||||
let (a, m, s) = Self::calc_data_sizes(value, false);
|
let (a, m, s) = Self::calc_data_sizes(value, false);
|
||||||
(arrays + a, maps + m + 1, strings + s)
|
(ax + a, mx + m + 1, sx + s)
|
||||||
}
|
}
|
||||||
Union::Str(ref s, ..) => (arrays, maps + 1, strings + s.len()),
|
Union::Str(ref s, ..) => (ax, mx + 1, sx + s.len()),
|
||||||
_ => (arrays, maps + 1, strings),
|
_ => (ax, mx + 1, sx),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Union::Str(ref s, ..) => (0, 0, s.len()),
|
Union::Str(ref s, ..) => (0, 0, s.len()),
|
||||||
@ -70,43 +69,34 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is there a data size limit set?
|
|
||||||
pub(crate) const fn has_data_size_limit(&self) -> bool {
|
|
||||||
self.max_string_size() > 0 || self.max_array_size() > 0 || self.max_map_size() > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Raise an error if any data size exceeds limit.
|
/// Raise an error if any data size exceeds limit.
|
||||||
pub(crate) fn raise_err_if_over_data_size_limit(
|
pub(crate) fn raise_err_if_over_data_size_limit(
|
||||||
&self,
|
&self,
|
||||||
sizes: (usize, usize, usize),
|
(_arr, _map, s): (usize, usize, usize),
|
||||||
pos: Position,
|
pos: Position,
|
||||||
) -> RhaiResultOf<()> {
|
) -> RhaiResultOf<()> {
|
||||||
let (_arr, _map, s) = sizes;
|
if self
|
||||||
|
|
||||||
if s > self
|
|
||||||
.limits
|
.limits
|
||||||
.max_string_size
|
.max_string_size
|
||||||
.map_or(usize::MAX, NonZeroUsize::get)
|
.map_or(false, |max| s > max.get())
|
||||||
{
|
{
|
||||||
return Err(ERR::ErrorDataTooLarge("Length of string".to_string(), pos).into());
|
return Err(ERR::ErrorDataTooLarge("Length of string".to_string(), pos).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
if _arr
|
if self
|
||||||
> self
|
|
||||||
.limits
|
.limits
|
||||||
.max_array_size
|
.max_array_size
|
||||||
.map_or(usize::MAX, NonZeroUsize::get)
|
.map_or(false, |max| _arr > max.get())
|
||||||
{
|
{
|
||||||
return Err(ERR::ErrorDataTooLarge("Size of array".to_string(), pos).into());
|
return Err(ERR::ErrorDataTooLarge("Size of array".to_string(), pos).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
if _map
|
if self
|
||||||
> self
|
|
||||||
.limits
|
.limits
|
||||||
.max_map_size
|
.max_map_size
|
||||||
.map_or(usize::MAX, NonZeroUsize::get)
|
.map_or(false, |max| _map > max.get())
|
||||||
{
|
{
|
||||||
return Err(ERR::ErrorDataTooLarge("Size of object map".to_string(), pos).into());
|
return Err(ERR::ErrorDataTooLarge("Size of object map".to_string(), pos).into());
|
||||||
}
|
}
|
||||||
|
@ -496,13 +496,10 @@ impl Engine {
|
|||||||
|
|
||||||
let event = match event {
|
let event = match event {
|
||||||
Some(e) => e,
|
Some(e) => e,
|
||||||
None => {
|
None => match global.debugger.is_break_point(&global.source, node) {
|
||||||
if let Some(bp) = global.debugger.is_break_point(&global.source, node) {
|
Some(bp) => DebuggerEvent::BreakPoint(bp),
|
||||||
DebuggerEvent::BreakPoint(bp)
|
None => return Ok(None),
|
||||||
} else {
|
},
|
||||||
return Ok(None);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.run_debugger_raw(scope, global, lib, this_ptr, node, event, level)
|
self.run_debugger_raw(scope, global, lib, this_ptr, node, event, level)
|
||||||
|
@ -107,10 +107,9 @@ impl GlobalRuntimeState<'_> {
|
|||||||
} else {
|
} else {
|
||||||
crate::eval::DebuggerStatus::CONTINUE
|
crate::eval::DebuggerStatus::CONTINUE
|
||||||
},
|
},
|
||||||
if let Some((ref init, ..)) = engine.debugger {
|
match engine.debugger {
|
||||||
init(engine)
|
Some((ref init, ..)) => init(engine),
|
||||||
} else {
|
None => Dynamic::UNIT,
|
||||||
Dynamic::UNIT
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
|
@ -77,14 +77,11 @@ impl BuildHasher for StraightHasherBuilder {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn get_hasher() -> ahash::AHasher {
|
pub fn get_hasher() -> ahash::AHasher {
|
||||||
if let Some([seed1, seed2, seed3, seed4]) = config::AHASH_SEED {
|
match config::AHASH_SEED {
|
||||||
if seed1 | seed2 | seed3 | seed4 != 0 {
|
Some([seed1, seed2, seed3, seed4]) if seed1 | seed2 | seed3 | seed4 != 0 => {
|
||||||
ahash::RandomState::with_seeds(seed1, seed2, seed3, seed4).build_hasher()
|
ahash::RandomState::with_seeds(seed1, seed2, seed3, seed4).build_hasher()
|
||||||
} else {
|
|
||||||
ahash::AHasher::default()
|
|
||||||
}
|
}
|
||||||
} else {
|
_ => ahash::AHasher::default(),
|
||||||
ahash::AHasher::default()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1742,10 +1742,9 @@ impl Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref variables) = other.variables {
|
if let Some(ref variables) = other.variables {
|
||||||
if let Some(ref mut m) = self.variables {
|
match self.variables {
|
||||||
m.extend(variables.iter().map(|(k, v)| (k.clone(), v.clone())));
|
Some(ref mut m) => m.extend(variables.iter().map(|(k, v)| (k.clone(), v.clone()))),
|
||||||
} else {
|
None => self.variables = other.variables.clone(),
|
||||||
self.variables = other.variables.clone();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1767,10 +1766,9 @@ impl Module {
|
|||||||
self.dynamic_functions_filter += &other.dynamic_functions_filter;
|
self.dynamic_functions_filter += &other.dynamic_functions_filter;
|
||||||
|
|
||||||
if let Some(ref type_iterators) = other.type_iterators {
|
if let Some(ref type_iterators) = other.type_iterators {
|
||||||
if let Some(ref mut t) = self.type_iterators {
|
match self.type_iterators {
|
||||||
t.extend(type_iterators.iter().map(|(&k, v)| (k, v.clone())));
|
Some(ref mut t) => t.extend(type_iterators.iter().map(|(&k, v)| (k, v.clone()))),
|
||||||
} else {
|
None => self.type_iterators = other.type_iterators.clone(),
|
||||||
self.type_iterators = other.type_iterators.clone();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.all_functions = None;
|
self.all_functions = None;
|
||||||
|
@ -322,10 +322,9 @@ impl FileModuleResolver {
|
|||||||
|
|
||||||
let scope = Scope::new();
|
let scope = Scope::new();
|
||||||
|
|
||||||
let m: Shared<_> = if let Some(global) = global {
|
let m: Shared<_> = match global {
|
||||||
Module::eval_ast_as_new_raw(engine, scope, global, &ast)
|
Some(global) => Module::eval_ast_as_new_raw(engine, scope, global, &ast),
|
||||||
} else {
|
None => Module::eval_ast_as_new(scope, &ast, engine),
|
||||||
Module::eval_ast_as_new(scope, &ast, engine)
|
|
||||||
}
|
}
|
||||||
.map_err(|err| Box::new(ERR::ErrorInModule(path.to_string(), err, pos)))?
|
.map_err(|err| Box::new(ERR::ErrorInModule(path.to_string(), err, pos)))?
|
||||||
.into();
|
.into();
|
||||||
|
@ -551,13 +551,14 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
|||||||
// switch const { case if condition => stmt, _ => def } => if condition { stmt } else { def }
|
// switch const { case if condition => stmt, _ => def } => if condition { stmt } else { def }
|
||||||
optimize_expr(&mut b.condition, state, false);
|
optimize_expr(&mut b.condition, state, false);
|
||||||
|
|
||||||
let else_stmt = if let Some(index) = def_case {
|
let else_stmt = match def_case {
|
||||||
|
Some(index) => {
|
||||||
let mut def_stmt =
|
let mut def_stmt =
|
||||||
Stmt::Expr(mem::take(&mut expressions[*index].expr).into());
|
Stmt::Expr(mem::take(&mut expressions[*index].expr).into());
|
||||||
optimize_stmt(&mut def_stmt, state, true);
|
optimize_stmt(&mut def_stmt, state, true);
|
||||||
def_stmt.into()
|
def_stmt.into()
|
||||||
} else {
|
}
|
||||||
StmtBlock::NONE
|
_ => StmtBlock::NONE,
|
||||||
};
|
};
|
||||||
|
|
||||||
*stmt = Stmt::If(
|
*stmt = Stmt::If(
|
||||||
@ -616,13 +617,14 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
|||||||
// switch const { range if condition => stmt, _ => def } => if condition { stmt } else { def }
|
// switch const { range if condition => stmt, _ => def } => if condition { stmt } else { def }
|
||||||
optimize_expr(&mut condition, state, false);
|
optimize_expr(&mut condition, state, false);
|
||||||
|
|
||||||
let else_stmt = if let Some(index) = def_case {
|
let else_stmt = match def_case {
|
||||||
|
Some(index) => {
|
||||||
let mut def_stmt =
|
let mut def_stmt =
|
||||||
Stmt::Expr(mem::take(&mut expressions[*index].expr).into());
|
Stmt::Expr(mem::take(&mut expressions[*index].expr).into());
|
||||||
optimize_stmt(&mut def_stmt, state, true);
|
optimize_stmt(&mut def_stmt, state, true);
|
||||||
def_stmt.into()
|
def_stmt.into()
|
||||||
} else {
|
}
|
||||||
StmtBlock::NONE
|
_ => StmtBlock::NONE,
|
||||||
};
|
};
|
||||||
|
|
||||||
let if_stmt =
|
let if_stmt =
|
||||||
@ -665,12 +667,13 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b
|
|||||||
// Promote the default case
|
// Promote the default case
|
||||||
state.set_dirty();
|
state.set_dirty();
|
||||||
|
|
||||||
if let Some(index) = def_case {
|
match def_case {
|
||||||
|
Some(index) => {
|
||||||
let mut def_stmt = Stmt::Expr(mem::take(&mut expressions[*index].expr).into());
|
let mut def_stmt = Stmt::Expr(mem::take(&mut expressions[*index].expr).into());
|
||||||
optimize_stmt(&mut def_stmt, state, true);
|
optimize_stmt(&mut def_stmt, state, true);
|
||||||
*stmt = def_stmt;
|
*stmt = def_stmt;
|
||||||
} else {
|
}
|
||||||
*stmt = StmtBlock::empty(*pos).into();
|
_ => *stmt = StmtBlock::empty(*pos).into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// switch
|
// switch
|
||||||
|
@ -82,12 +82,13 @@ mod map_functions {
|
|||||||
/// print(m); // prints "#{a: 1, b: 42, c: 3, x: 0}"
|
/// print(m); // prints "#{a: 1, b: 42, c: 3, x: 0}"
|
||||||
/// ```
|
/// ```
|
||||||
pub fn set(map: &mut Map, property: &str, value: Dynamic) {
|
pub fn set(map: &mut Map, property: &str, value: Dynamic) {
|
||||||
if let Some(value_ref) = map.get_mut(property) {
|
match map.get_mut(property) {
|
||||||
*value_ref = value;
|
Some(value_ref) => *value_ref = value,
|
||||||
} else {
|
_ => {
|
||||||
map.insert(property.into(), value);
|
map.insert(property.into(), value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/// Clear the object map.
|
/// Clear the object map.
|
||||||
pub fn clear(map: &mut Map) {
|
pub fn clear(map: &mut Map) {
|
||||||
if !map.is_empty() {
|
if !map.is_empty() {
|
||||||
|
@ -239,10 +239,9 @@ mod string_functions {
|
|||||||
/// Clear the string, making it empty.
|
/// Clear the string, making it empty.
|
||||||
pub fn clear(string: &mut ImmutableString) {
|
pub fn clear(string: &mut ImmutableString) {
|
||||||
if !string.is_empty() {
|
if !string.is_empty() {
|
||||||
if let Some(s) = string.get_mut() {
|
match string.get_mut() {
|
||||||
s.clear();
|
Some(s) => s.clear(),
|
||||||
} else {
|
_ => *string = ImmutableString::new(),
|
||||||
*string = ImmutableString::new();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -287,13 +286,15 @@ mod string_functions {
|
|||||||
/// print(text); // prints "hello"
|
/// print(text); // prints "hello"
|
||||||
/// ```
|
/// ```
|
||||||
pub fn trim(string: &mut ImmutableString) {
|
pub fn trim(string: &mut ImmutableString) {
|
||||||
if let Some(s) = string.get_mut() {
|
match string.get_mut() {
|
||||||
|
Some(s) => {
|
||||||
let trimmed = s.trim();
|
let trimmed = s.trim();
|
||||||
|
|
||||||
if trimmed != s {
|
if trimmed != s {
|
||||||
*s = trimmed.into();
|
*s = trimmed.into();
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
None => {
|
||||||
let trimmed = string.trim();
|
let trimmed = string.trim();
|
||||||
|
|
||||||
if trimmed != string {
|
if trimmed != string {
|
||||||
@ -301,6 +302,7 @@ mod string_functions {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/// Remove the last character from the string and return it.
|
/// Remove the last character from the string and return it.
|
||||||
///
|
///
|
||||||
/// If the string is empty, `()` is returned.
|
/// If the string is empty, `()` is returned.
|
||||||
|
@ -215,10 +215,9 @@ impl<'de> Deserialize<'de> for Scope<'de> {
|
|||||||
where
|
where
|
||||||
A: SeqAccess<'de>,
|
A: SeqAccess<'de>,
|
||||||
{
|
{
|
||||||
let mut scope = if let Some(size) = access.size_hint() {
|
let mut scope = match access.size_hint() {
|
||||||
Scope::with_capacity(size)
|
Some(size) => Scope::with_capacity(size),
|
||||||
} else {
|
None => Scope::new(),
|
||||||
Scope::new()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
while let Some(ScopeEntry {
|
while let Some(ScopeEntry {
|
||||||
|
@ -37,10 +37,9 @@ impl Serialize for Dynamic {
|
|||||||
Union::Decimal(ref x, ..) => {
|
Union::Decimal(ref x, ..) => {
|
||||||
use rust_decimal::prelude::ToPrimitive;
|
use rust_decimal::prelude::ToPrimitive;
|
||||||
|
|
||||||
if let Some(v) = x.to_f64() {
|
match x.to_f64() {
|
||||||
ser.serialize_f64(v)
|
Some(v) => ser.serialize_f64(v),
|
||||||
} else {
|
None => ser.serialize_str(&x.to_string()),
|
||||||
ser.serialize_str(&x.to_string())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(feature = "decimal")]
|
#[cfg(feature = "decimal")]
|
||||||
@ -48,10 +47,9 @@ impl Serialize for Dynamic {
|
|||||||
Union::Decimal(ref x, ..) => {
|
Union::Decimal(ref x, ..) => {
|
||||||
use rust_decimal::prelude::ToPrimitive;
|
use rust_decimal::prelude::ToPrimitive;
|
||||||
|
|
||||||
if let Some(v) = x.to_f32() {
|
match x.to_f32() {
|
||||||
ser.serialize_f32(v)
|
Some(v) => ser.serialize_f32(v),
|
||||||
} else {
|
_ => ser.serialize_str(&x.to_string()),
|
||||||
ser.serialize_str(&x.to_string())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user