Provide Position to debug.
This commit is contained in:
parent
5443368359
commit
40b6a014ae
@ -14,11 +14,13 @@ Breaking changes
|
|||||||
----------------
|
----------------
|
||||||
|
|
||||||
* `Engine::on_progress` now takes `u64` instead of `&u64`.
|
* `Engine::on_progress` now takes `u64` instead of `&u64`.
|
||||||
|
* The closure for `Engine::on_debug` now takes an additional `Position` parameter.
|
||||||
|
|
||||||
Enhancements
|
Enhancements
|
||||||
------------
|
------------
|
||||||
|
|
||||||
* Capturing a constant variable in a closure is now supported, with no cloning.
|
* Capturing a constant variable in a closure is now supported, with no cloning.
|
||||||
|
* Provides position info for `debug` statements.
|
||||||
|
|
||||||
|
|
||||||
Version 0.19.7
|
Version 0.19.7
|
||||||
|
@ -22,10 +22,12 @@ When embedding Rhai into an application, it is usually necessary to trap `print`
|
|||||||
(for logging into a tracking log, for example) with the `Engine::on_print` and `Engine::on_debug` methods:
|
(for logging into a tracking log, for example) with the `Engine::on_print` and `Engine::on_debug` methods:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
// Any function or closure that takes an '&str' argument can be used to override
|
// Any function or closure that takes an '&str' argument can be used to override 'print'.
|
||||||
// 'print' and 'debug'
|
|
||||||
engine.on_print(|x| println!("hello: {}", x));
|
engine.on_print(|x| println!("hello: {}", x));
|
||||||
engine.on_debug(|x| println!("DEBUG: {}", x));
|
|
||||||
|
// Any function or closure that takes a '&str' and a 'Position' argument can be used to
|
||||||
|
// override 'debug'.
|
||||||
|
engine.on_debug(|x, pos| println!("DEBUG at {:?}: {}", pos, x));
|
||||||
|
|
||||||
// Example: quick-'n-dirty logging
|
// Example: quick-'n-dirty logging
|
||||||
let logbook = Arc::new(RwLock::new(Vec::<String>::new()));
|
let logbook = Arc::new(RwLock::new(Vec::<String>::new()));
|
||||||
@ -35,7 +37,9 @@ let log = logbook.clone();
|
|||||||
engine.on_print(move |s| log.write().unwrap().push(format!("entry: {}", s)));
|
engine.on_print(move |s| log.write().unwrap().push(format!("entry: {}", s)));
|
||||||
|
|
||||||
let log = logbook.clone();
|
let log = logbook.clone();
|
||||||
engine.on_debug(move |s| log.write().unwrap().push(format!("DEBUG: {}", s)));
|
engine.on_debug(move |s, pos| log.write().unwrap().push(
|
||||||
|
format!("DEBUG at {:?}: {}", pos, s)
|
||||||
|
));
|
||||||
|
|
||||||
// Evaluate script
|
// Evaluate script
|
||||||
engine.eval::<()>(script)?;
|
engine.eval::<()>(script)?;
|
||||||
|
@ -4,7 +4,8 @@ use crate::ast::{Expr, FnCallExpr, Ident, IdentX, ReturnType, Stmt};
|
|||||||
use crate::dynamic::{map_std_type_name, AccessMode, Union, Variant};
|
use crate::dynamic::{map_std_type_name, AccessMode, Union, Variant};
|
||||||
use crate::fn_call::run_builtin_op_assignment;
|
use crate::fn_call::run_builtin_op_assignment;
|
||||||
use crate::fn_native::{
|
use crate::fn_native::{
|
||||||
CallableFunction, IteratorFn, OnPrintCallback, OnProgressCallback, OnVarCallback,
|
CallableFunction, IteratorFn, OnDebugCallback, OnPrintCallback, OnProgressCallback,
|
||||||
|
OnVarCallback,
|
||||||
};
|
};
|
||||||
use crate::module::NamespaceRef;
|
use crate::module::NamespaceRef;
|
||||||
use crate::optimize::OptimizationLevel;
|
use crate::optimize::OptimizationLevel;
|
||||||
@ -626,7 +627,7 @@ pub struct Engine {
|
|||||||
/// Callback closure for implementing the `print` command.
|
/// Callback closure for implementing the `print` command.
|
||||||
pub(crate) print: OnPrintCallback,
|
pub(crate) print: OnPrintCallback,
|
||||||
/// Callback closure for implementing the `debug` command.
|
/// Callback closure for implementing the `debug` command.
|
||||||
pub(crate) debug: OnPrintCallback,
|
pub(crate) debug: OnDebugCallback,
|
||||||
/// Callback closure for progress reporting.
|
/// Callback closure for progress reporting.
|
||||||
pub(crate) progress: Option<OnProgressCallback>,
|
pub(crate) progress: Option<OnProgressCallback>,
|
||||||
|
|
||||||
@ -677,7 +678,7 @@ pub fn is_anonymous_fn(fn_name: &str) -> bool {
|
|||||||
fn_name.starts_with(FN_ANONYMOUS)
|
fn_name.starts_with(FN_ANONYMOUS)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Print/debug to stdout
|
/// Print to stdout
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn default_print(_s: &str) {
|
fn default_print(_s: &str) {
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
@ -685,6 +686,14 @@ fn default_print(_s: &str) {
|
|||||||
println!("{}", _s);
|
println!("{}", _s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Debug to stdout
|
||||||
|
#[inline(always)]
|
||||||
|
fn default_debug(_s: &str, _pos: Position) {
|
||||||
|
#[cfg(not(feature = "no_std"))]
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
println!("{:?} | {}", _pos, _s);
|
||||||
|
}
|
||||||
|
|
||||||
/// Search for a module within an imports stack.
|
/// Search for a module within an imports stack.
|
||||||
/// [`Position`] in [`EvalAltResult`] is [`None`][Position::None] and must be set afterwards.
|
/// [`Position`] in [`EvalAltResult`] is [`None`][Position::None] and must be set afterwards.
|
||||||
pub fn search_imports(
|
pub fn search_imports(
|
||||||
@ -741,7 +750,7 @@ impl Engine {
|
|||||||
|
|
||||||
// default print/debug implementations
|
// default print/debug implementations
|
||||||
print: Box::new(default_print),
|
print: Box::new(default_print),
|
||||||
debug: Box::new(default_print),
|
debug: Box::new(default_debug),
|
||||||
|
|
||||||
// progress callback
|
// progress callback
|
||||||
progress: None,
|
progress: None,
|
||||||
@ -797,7 +806,7 @@ impl Engine {
|
|||||||
resolve_var: None,
|
resolve_var: None,
|
||||||
|
|
||||||
print: Box::new(|_| {}),
|
print: Box::new(|_| {}),
|
||||||
debug: Box::new(|_| {}),
|
debug: Box::new(|_, _| {}),
|
||||||
progress: None,
|
progress: None,
|
||||||
|
|
||||||
optimization_level: if cfg!(feature = "no_optimize") {
|
optimization_level: if cfg!(feature = "no_optimize") {
|
||||||
|
@ -1808,16 +1808,21 @@ impl Engine {
|
|||||||
///
|
///
|
||||||
/// // Override action of 'print' function
|
/// // Override action of 'print' function
|
||||||
/// let logger = result.clone();
|
/// let logger = result.clone();
|
||||||
/// engine.on_debug(move |s| logger.write().unwrap().push_str(s));
|
/// engine.on_debug(move |s, pos| logger.write().unwrap().push_str(
|
||||||
|
/// &format!("{:?} > {}", pos, s)
|
||||||
|
/// ));
|
||||||
///
|
///
|
||||||
/// engine.consume(r#"debug("hello");"#)?;
|
/// engine.consume(r#"let x = "hello"; debug(x);"#)?;
|
||||||
///
|
///
|
||||||
/// assert_eq!(*result.read().unwrap(), r#""hello""#);
|
/// assert_eq!(*result.read().unwrap(), r#"1:18 > "hello""#);
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn on_debug(&mut self, callback: impl Fn(&str) + SendSync + 'static) -> &mut Self {
|
pub fn on_debug(
|
||||||
|
&mut self,
|
||||||
|
callback: impl Fn(&str, Position) + SendSync + 'static,
|
||||||
|
) -> &mut Self {
|
||||||
self.debug = Box::new(callback);
|
self.debug = Box::new(callback);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -211,13 +211,16 @@ impl Engine {
|
|||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
KEYWORD_DEBUG => (
|
KEYWORD_DEBUG => (
|
||||||
(self.debug)(result.as_str().map_err(|typ| {
|
(self.debug)(
|
||||||
|
result.as_str().map_err(|typ| {
|
||||||
EvalAltResult::ErrorMismatchOutputType(
|
EvalAltResult::ErrorMismatchOutputType(
|
||||||
self.map_type_name(type_name::<ImmutableString>()).into(),
|
self.map_type_name(type_name::<ImmutableString>()).into(),
|
||||||
typ.into(),
|
typ.into(),
|
||||||
pos,
|
pos,
|
||||||
)
|
)
|
||||||
})?)
|
})?,
|
||||||
|
pos,
|
||||||
|
)
|
||||||
.into(),
|
.into(),
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
|
@ -356,7 +356,14 @@ pub type OnProgressCallback = Box<dyn Fn(u64) -> Option<Dynamic> + Send + Sync +
|
|||||||
pub type OnPrintCallback = Box<dyn Fn(&str) + 'static>;
|
pub type OnPrintCallback = Box<dyn Fn(&str) + 'static>;
|
||||||
/// A standard callback function for printing.
|
/// A standard callback function for printing.
|
||||||
#[cfg(feature = "sync")]
|
#[cfg(feature = "sync")]
|
||||||
pub type OnPrintCallback<T, R> = Box<dyn Fn(&str) + Send + Sync + 'static>;
|
pub type OnPrintCallback = Box<dyn Fn(&str) + Send + Sync + 'static>;
|
||||||
|
|
||||||
|
/// A standard callback function for debugging.
|
||||||
|
#[cfg(not(feature = "sync"))]
|
||||||
|
pub type OnDebugCallback = Box<dyn Fn(&str, Position) + 'static>;
|
||||||
|
/// A standard callback function for debugging.
|
||||||
|
#[cfg(feature = "sync")]
|
||||||
|
pub type OnDebugCallback = Box<dyn Fn(&str, Position) + Send + Sync + 'static>;
|
||||||
|
|
||||||
/// A standard callback function for variable access.
|
/// A standard callback function for variable access.
|
||||||
#[cfg(not(feature = "sync"))]
|
#[cfg(not(feature = "sync"))]
|
||||||
|
@ -2,7 +2,7 @@ use rhai::{Engine, EvalAltResult, RegisterFn, INT};
|
|||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_print() -> Result<(), Box<EvalAltResult>> {
|
fn test_print_debug() -> Result<(), Box<EvalAltResult>> {
|
||||||
let logbook = Arc::new(RwLock::new(Vec::<String>::new()));
|
let logbook = Arc::new(RwLock::new(Vec::<String>::new()));
|
||||||
|
|
||||||
// Redirect print/debug output to 'log'
|
// Redirect print/debug output to 'log'
|
||||||
@ -13,16 +13,20 @@ fn test_print() -> Result<(), Box<EvalAltResult>> {
|
|||||||
|
|
||||||
engine
|
engine
|
||||||
.on_print(move |s| log1.write().unwrap().push(format!("entry: {}", s)))
|
.on_print(move |s| log1.write().unwrap().push(format!("entry: {}", s)))
|
||||||
.on_debug(move |s| log2.write().unwrap().push(format!("DEBUG: {}", s)));
|
.on_debug(move |s, pos| {
|
||||||
|
log2.write()
|
||||||
|
.unwrap()
|
||||||
|
.push(format!("DEBUG at {:?}: {}", pos, s))
|
||||||
|
});
|
||||||
|
|
||||||
// Evaluate script
|
// Evaluate script
|
||||||
engine.eval::<()>("print(40 + 2)")?;
|
engine.eval::<()>("print(40 + 2)")?;
|
||||||
engine.eval::<()>(r#"debug("hello!")"#)?;
|
engine.eval::<()>(r#"let x = "hello!"; debug(x)"#)?;
|
||||||
|
|
||||||
// 'logbook' captures all the 'print' and 'debug' output
|
// 'logbook' captures all the 'print' and 'debug' output
|
||||||
assert_eq!(logbook.read().unwrap().len(), 2);
|
assert_eq!(logbook.read().unwrap().len(), 2);
|
||||||
assert_eq!(logbook.read().unwrap()[0], "entry: 42");
|
assert_eq!(logbook.read().unwrap()[0], "entry: 42");
|
||||||
assert_eq!(logbook.read().unwrap()[1], r#"DEBUG: "hello!""#);
|
assert_eq!(logbook.read().unwrap()[1], r#"DEBUG at 1:19: "hello!""#);
|
||||||
|
|
||||||
for entry in logbook.read().unwrap().iter() {
|
for entry in logbook.read().unwrap().iter() {
|
||||||
println!("{}", entry);
|
println!("{}", entry);
|
||||||
|
Loading…
Reference in New Issue
Block a user