Add version to repl.
This commit is contained in:
parent
956c57e9d6
commit
cc546fcaab
@ -55,8 +55,9 @@ fn print_help() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("Rhai REPL tool");
|
let title = format!("Rhai REPL tool (version {})", env!("CARGO_PKG_VERSION"));
|
||||||
println!("==============");
|
println!("{}", title);
|
||||||
|
println!("{0:=<1$}", "", title.len());
|
||||||
print_help();
|
print_help();
|
||||||
|
|
||||||
// Initialize scripting engine
|
// Initialize scripting engine
|
||||||
|
152
src/engine.rs
152
src/engine.rs
@ -574,6 +574,7 @@ impl State {
|
|||||||
self.scope_level == 0
|
self.scope_level == 0
|
||||||
}
|
}
|
||||||
/// Get a mutable reference to the current function resolution cache.
|
/// Get a mutable reference to the current function resolution cache.
|
||||||
|
#[inline(always)]
|
||||||
pub fn fn_resolution_cache_mut(&mut self) -> &mut FnResolutionCache {
|
pub fn fn_resolution_cache_mut(&mut self) -> &mut FnResolutionCache {
|
||||||
if self.fn_resolution_caches.0.is_empty() {
|
if self.fn_resolution_caches.0.is_empty() {
|
||||||
self.fn_resolution_caches.0.push(BTreeMap::new());
|
self.fn_resolution_caches.0.push(BTreeMap::new());
|
||||||
@ -582,6 +583,7 @@ impl State {
|
|||||||
}
|
}
|
||||||
/// Push an empty function resolution cache onto the stack and make it current.
|
/// Push an empty function resolution cache onto the stack and make it current.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
#[inline(always)]
|
||||||
pub fn push_fn_resolution_cache(&mut self) {
|
pub fn push_fn_resolution_cache(&mut self) {
|
||||||
self.fn_resolution_caches
|
self.fn_resolution_caches
|
||||||
.0
|
.0
|
||||||
@ -592,6 +594,7 @@ impl State {
|
|||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// Panics if there are no more function resolution cache in the stack.
|
/// Panics if there are no more function resolution cache in the stack.
|
||||||
|
#[inline(always)]
|
||||||
pub fn pop_fn_resolution_cache(&mut self) {
|
pub fn pop_fn_resolution_cache(&mut self) {
|
||||||
let mut cache = self.fn_resolution_caches.0.pop().unwrap();
|
let mut cache = self.fn_resolution_caches.0.pop().unwrap();
|
||||||
cache.clear();
|
cache.clear();
|
||||||
@ -1915,7 +1918,11 @@ impl Engine {
|
|||||||
_ => unreachable!("expression cannot be evaluated: {:?}", expr),
|
_ => unreachable!("expression cannot be evaluated: {:?}", expr),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.check_data_size(result, expr.position())
|
#[cfg(not(feature = "unchecked"))]
|
||||||
|
self.check_data_size(&result)
|
||||||
|
.map_err(|err| err.fill_position(expr.position()))?;
|
||||||
|
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Evaluate a statements block.
|
/// Evaluate a statements block.
|
||||||
@ -2166,29 +2173,26 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If statement
|
// If statement
|
||||||
Stmt::If(expr, x, _) => self
|
Stmt::If(expr, x, _) => {
|
||||||
.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?
|
let guard_val = self
|
||||||
.as_bool()
|
.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?
|
||||||
.map_err(|err| self.make_type_mismatch_err::<bool>(err, expr.position()))
|
.as_bool()
|
||||||
.and_then(|guard_val| {
|
.map_err(|err| self.make_type_mismatch_err::<bool>(err, expr.position()))?;
|
||||||
if guard_val {
|
|
||||||
if !x.0.is_empty() {
|
if guard_val {
|
||||||
self.eval_stmt_block(
|
if !x.0.is_empty() {
|
||||||
scope, mods, state, lib, this_ptr, &x.0, true, level,
|
self.eval_stmt_block(scope, mods, state, lib, this_ptr, &x.0, true, level)
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Ok(Dynamic::UNIT)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if !x.1.is_empty() {
|
Ok(Dynamic::UNIT)
|
||||||
self.eval_stmt_block(
|
|
||||||
scope, mods, state, lib, this_ptr, &x.1, true, level,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Ok(Dynamic::UNIT)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}),
|
} else {
|
||||||
|
if !x.1.is_empty() {
|
||||||
|
self.eval_stmt_block(scope, mods, state, lib, this_ptr, &x.1, true, level)
|
||||||
|
} else {
|
||||||
|
Ok(Dynamic::UNIT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Switch statement
|
// Switch statement
|
||||||
Stmt::Switch(match_expr, x, _) => {
|
Stmt::Switch(match_expr, x, _) => {
|
||||||
@ -2258,17 +2262,16 @@ impl Engine {
|
|||||||
if !condition {
|
if !condition {
|
||||||
return Ok(Dynamic::UNIT);
|
return Ok(Dynamic::UNIT);
|
||||||
}
|
}
|
||||||
if body.is_empty() {
|
if !body.is_empty() {
|
||||||
continue;
|
match self.eval_stmt_block(scope, mods, state, lib, this_ptr, body, true, level)
|
||||||
}
|
{
|
||||||
|
Ok(_) => (),
|
||||||
match self.eval_stmt_block(scope, mods, state, lib, this_ptr, body, true, level) {
|
Err(err) => match *err {
|
||||||
Ok(_) => (),
|
EvalAltResult::LoopBreak(false, _) => (),
|
||||||
Err(err) => match *err {
|
EvalAltResult::LoopBreak(true, _) => return Ok(Dynamic::UNIT),
|
||||||
EvalAltResult::LoopBreak(false, _) => (),
|
_ => return Err(err),
|
||||||
EvalAltResult::LoopBreak(true, _) => return Ok(Dynamic::UNIT),
|
},
|
||||||
_ => return Err(err),
|
}
|
||||||
},
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -2286,18 +2289,13 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self
|
let condition = self
|
||||||
.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?
|
.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?
|
||||||
.as_bool()
|
.as_bool()
|
||||||
.map_err(|err| self.make_type_mismatch_err::<bool>(err, expr.position()))?
|
.map_err(|err| self.make_type_mismatch_err::<bool>(err, expr.position()))?;
|
||||||
{
|
|
||||||
if !*is_while {
|
if condition ^ *is_while {
|
||||||
return Ok(Dynamic::UNIT);
|
return Ok(Dynamic::UNIT);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if *is_while {
|
|
||||||
return Ok(Dynamic::UNIT);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -2364,9 +2362,11 @@ impl Engine {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.eval_stmt_block(
|
let result = self.eval_stmt_block(
|
||||||
scope, mods, state, lib, this_ptr, statements, true, level,
|
scope, mods, state, lib, this_ptr, statements, true, level,
|
||||||
) {
|
);
|
||||||
|
|
||||||
|
match result {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(err) => match *err {
|
Err(err) => match *err {
|
||||||
EvalAltResult::LoopBreak(false, _) => (),
|
EvalAltResult::LoopBreak(false, _) => (),
|
||||||
@ -2477,25 +2477,25 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return value
|
// Return value
|
||||||
Stmt::Return(ReturnType::Return, Some(expr), pos) => {
|
Stmt::Return(ReturnType::Return, Some(expr), pos) => EvalAltResult::Return(
|
||||||
let value = self
|
self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?
|
||||||
.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?
|
.flatten(),
|
||||||
.flatten();
|
*pos,
|
||||||
EvalAltResult::Return(value, *pos).into()
|
)
|
||||||
}
|
.into(),
|
||||||
|
|
||||||
// Empty return
|
// Empty return
|
||||||
Stmt::Return(ReturnType::Return, None, pos) => {
|
Stmt::Return(ReturnType::Return, None, pos) => {
|
||||||
EvalAltResult::Return(Default::default(), *pos).into()
|
EvalAltResult::Return(Dynamic::UNIT, *pos).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Throw value
|
// Throw value
|
||||||
Stmt::Return(ReturnType::Exception, Some(expr), pos) => {
|
Stmt::Return(ReturnType::Exception, Some(expr), pos) => EvalAltResult::ErrorRuntime(
|
||||||
let value = self
|
self.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?
|
||||||
.eval_expr(scope, mods, state, lib, this_ptr, expr, level)?
|
.flatten(),
|
||||||
.flatten();
|
*pos,
|
||||||
EvalAltResult::ErrorRuntime(value, *pos).into()
|
)
|
||||||
}
|
.into(),
|
||||||
|
|
||||||
// Empty throw
|
// Empty throw
|
||||||
Stmt::Return(ReturnType::Exception, None, pos) => {
|
Stmt::Return(ReturnType::Exception, None, pos) => {
|
||||||
@ -2640,24 +2640,18 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.check_data_size(result, stmt.position())
|
#[cfg(not(feature = "unchecked"))]
|
||||||
}
|
self.check_data_size(&result)
|
||||||
|
.map_err(|err| err.fill_position(stmt.position()))?;
|
||||||
|
|
||||||
/// Check a result to ensure that the data size is within allowable limit.
|
|
||||||
/// [`Position`] in [`EvalAltResult`] may be None and should be set afterwards.
|
|
||||||
#[cfg(feature = "unchecked")]
|
|
||||||
#[inline(always)]
|
|
||||||
fn check_data_size(&self, result: RhaiResult, _pos: Position) -> RhaiResult {
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check a result to ensure that the data size is within allowable limit.
|
/// Check a result to ensure that the data size is within allowable limit.
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
#[inline(always)]
|
fn check_data_size(&self, result: &RhaiResult) -> Result<(), Box<EvalAltResult>> {
|
||||||
fn check_data_size(&self, result: RhaiResult, pos: Position) -> RhaiResult {
|
|
||||||
// Simply return all errors
|
|
||||||
if result.is_err() {
|
if result.is_err() {
|
||||||
return result;
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no data size limits, just return
|
// If no data size limits, just return
|
||||||
@ -2672,7 +2666,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !_has_limit {
|
if !_has_limit {
|
||||||
return result;
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recursively calculate the size of a value (especially `Array` and `Map`)
|
// Recursively calculate the size of a value (especially `Array` and `Map`)
|
||||||
@ -2734,7 +2728,11 @@ impl Engine {
|
|||||||
.max_string_size
|
.max_string_size
|
||||||
.map_or(usize::MAX, NonZeroUsize::get)
|
.map_or(usize::MAX, NonZeroUsize::get)
|
||||||
{
|
{
|
||||||
return EvalAltResult::ErrorDataTooLarge("Length of string".to_string(), pos).into();
|
return EvalAltResult::ErrorDataTooLarge(
|
||||||
|
"Length of string".to_string(),
|
||||||
|
Position::NONE,
|
||||||
|
)
|
||||||
|
.into();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
@ -2744,7 +2742,8 @@ impl Engine {
|
|||||||
.max_array_size
|
.max_array_size
|
||||||
.map_or(usize::MAX, NonZeroUsize::get)
|
.map_or(usize::MAX, NonZeroUsize::get)
|
||||||
{
|
{
|
||||||
return EvalAltResult::ErrorDataTooLarge("Size of array".to_string(), pos).into();
|
return EvalAltResult::ErrorDataTooLarge("Size of array".to_string(), Position::NONE)
|
||||||
|
.into();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
@ -2754,14 +2753,17 @@ impl Engine {
|
|||||||
.max_map_size
|
.max_map_size
|
||||||
.map_or(usize::MAX, NonZeroUsize::get)
|
.map_or(usize::MAX, NonZeroUsize::get)
|
||||||
{
|
{
|
||||||
return EvalAltResult::ErrorDataTooLarge("Size of object map".to_string(), pos).into();
|
return EvalAltResult::ErrorDataTooLarge(
|
||||||
|
"Size of object map".to_string(),
|
||||||
|
Position::NONE,
|
||||||
|
)
|
||||||
|
.into();
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if the number of operations stay within limit.
|
/// Check if the number of operations stay within limit.
|
||||||
#[inline]
|
|
||||||
pub(crate) fn inc_operations(
|
pub(crate) fn inc_operations(
|
||||||
&self,
|
&self,
|
||||||
state: &mut State,
|
state: &mut State,
|
||||||
|
Loading…
Reference in New Issue
Block a user