No need to specify number of variables added/removed for custom syntax.
This commit is contained in:
@@ -1357,8 +1357,8 @@ impl Stmt {
|
||||
pub struct CustomExpr {
|
||||
/// List of keywords.
|
||||
pub keywords: StaticVec<Expr>,
|
||||
/// Delta number of variables in the scope.
|
||||
pub scope_delta: isize,
|
||||
/// Is the current [`Scope`][crate::Scope] modified?
|
||||
pub scope_changed: bool,
|
||||
/// List of tokens actually parsed.
|
||||
pub tokens: StaticVec<Identifier>,
|
||||
}
|
||||
|
@@ -1024,7 +1024,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut State) {
|
||||
|
||||
// Custom syntax
|
||||
Expr::Custom(x, _) => {
|
||||
if x.scope_delta != 0 {
|
||||
if x.scope_changed {
|
||||
state.propagate_constants = false;
|
||||
}
|
||||
x.keywords.iter_mut().for_each(|expr| optimize_expr(expr, state));
|
||||
|
@@ -1848,22 +1848,12 @@ fn parse_custom_syntax(
|
||||
let mut tokens: StaticVec<_> = Default::default();
|
||||
|
||||
// Adjust the variables stack
|
||||
match syntax.scope_delta {
|
||||
delta if delta > 0 => {
|
||||
// Add enough empty variable names to the stack.
|
||||
// Empty variable names act as a barrier so earlier variables will not be matched.
|
||||
// Variable searches stop at the first empty variable name.
|
||||
let empty = state.get_identifier("");
|
||||
state.stack.resize(
|
||||
state.stack.len() + delta as usize,
|
||||
(empty, AccessMode::ReadWrite),
|
||||
);
|
||||
}
|
||||
delta if delta < 0 && state.stack.len() <= delta.abs() as usize => state.stack.clear(),
|
||||
delta if delta < 0 => state
|
||||
.stack
|
||||
.truncate(state.stack.len() - delta.abs() as usize),
|
||||
_ => (),
|
||||
if syntax.scope_changed {
|
||||
// Add an empty variable name to the stack.
|
||||
// Empty variable names act as a barrier so earlier variables will not be matched.
|
||||
// Variable searches stop at the first empty variable name.
|
||||
let empty = state.get_identifier("");
|
||||
state.stack.push((empty, AccessMode::ReadWrite));
|
||||
}
|
||||
|
||||
let parse_func = &syntax.parse;
|
||||
@@ -1936,7 +1926,7 @@ fn parse_custom_syntax(
|
||||
Box::new(CustomExpr {
|
||||
keywords,
|
||||
tokens,
|
||||
scope_delta: syntax.scope_delta,
|
||||
scope_changed: syntax.scope_changed,
|
||||
}),
|
||||
pos,
|
||||
))
|
||||
|
@@ -87,28 +87,33 @@ pub struct CustomSyntax {
|
||||
pub parse: Box<FnCustomSyntaxParse>,
|
||||
/// Custom syntax implementation function.
|
||||
pub func: Shared<FnCustomSyntaxEval>,
|
||||
/// Delta number of variables in the scope.
|
||||
pub scope_delta: isize,
|
||||
/// Any variables added/removed in the scope?
|
||||
pub scope_changed: bool,
|
||||
}
|
||||
|
||||
impl Engine {
|
||||
/// Register a custom syntax with the [`Engine`].
|
||||
///
|
||||
/// * `keywords` holds a slice of strings that define the custom syntax.
|
||||
/// * `new_vars` is the number of new variables declared by this custom syntax, or the number of variables removed (if negative).
|
||||
/// * `scope_changed` specifies variables have been added/removed by this custom syntax.
|
||||
/// * `func` is the implementation function.
|
||||
///
|
||||
/// # Notes
|
||||
/// # Caveat - Do not change beyond block scope
|
||||
///
|
||||
/// If `new_vars` is positive, then a number of new variables are expected to be pushed into the
|
||||
/// current [`Scope`][crate::Scope].
|
||||
/// If `scope_changed` is `true`, then the current [`Scope`][crate::Scope] is assumed to be
|
||||
/// modified by this custom syntax.
|
||||
///
|
||||
/// If `new_vars` is negative, then it is expected that only the top `new_vars` variables in the
|
||||
/// current [`Scope`][crate::Scope] will be _popped_. Do not randomly remove variables.
|
||||
/// Adding new variables and/or removing variables are allowed. Simply modifying the values of
|
||||
/// variables does NOT count, so `false` should be passed in this case.
|
||||
///
|
||||
/// However, only variables declared within the current _block scope_ should be touched,
|
||||
/// since they all go away at the end of the block.
|
||||
///
|
||||
/// Variables in parent blocks should be left untouched as they persist beyond the current block.
|
||||
pub fn register_custom_syntax<S: AsRef<str> + Into<Identifier>>(
|
||||
&mut self,
|
||||
keywords: &[S],
|
||||
new_vars: isize,
|
||||
scope_changed: bool,
|
||||
func: impl Fn(&mut EvalContext, &[Expression]) -> RhaiResult + SendSync + 'static,
|
||||
) -> Result<&mut Self, ParseError> {
|
||||
let keywords = keywords.as_ref();
|
||||
@@ -203,7 +208,7 @@ impl Engine {
|
||||
Ok(Some(segments[stream.len()].clone()))
|
||||
}
|
||||
},
|
||||
new_vars,
|
||||
scope_changed,
|
||||
func,
|
||||
);
|
||||
|
||||
@@ -215,7 +220,7 @@ impl Engine {
|
||||
///
|
||||
/// This function is very low level.
|
||||
///
|
||||
/// * `new_vars` is the number of new variables declared by this custom syntax, or the number of variables removed (if negative).
|
||||
/// * `scope_changed` specifies variables have been added/removed by this custom syntax.
|
||||
/// * `parse` is the parsing function.
|
||||
/// * `func` is the implementation function.
|
||||
///
|
||||
@@ -227,7 +232,7 @@ impl Engine {
|
||||
parse: impl Fn(&[ImmutableString], &str) -> Result<Option<ImmutableString>, ParseError>
|
||||
+ SendSync
|
||||
+ 'static,
|
||||
new_vars: isize,
|
||||
scope_changed: bool,
|
||||
func: impl Fn(&mut EvalContext, &[Expression]) -> RhaiResult + SendSync + 'static,
|
||||
) -> &mut Self {
|
||||
self.custom_syntax.insert(
|
||||
@@ -235,7 +240,7 @@ impl Engine {
|
||||
Box::new(CustomSyntax {
|
||||
parse: Box::new(parse),
|
||||
func: (Box::new(func) as Box<FnCustomSyntaxEval>).into(),
|
||||
scope_delta: new_vars,
|
||||
scope_changed,
|
||||
}),
|
||||
);
|
||||
self
|
||||
|
Reference in New Issue
Block a user