This commit is contained in:
parent
fb0f96a357
commit
39ae9cb977
2 changed files with 59 additions and 52 deletions
|
@ -20,13 +20,12 @@ impl ScriptService {
|
||||||
|
|
||||||
use rhai::{Array, Dynamic, Engine, Scope};
|
use rhai::{Array, Dynamic, Engine, Scope};
|
||||||
|
|
||||||
// Register FOR EACH loop with NEXT
|
engine
|
||||||
engine
|
|
||||||
.register_custom_syntax(
|
.register_custom_syntax(
|
||||||
&[
|
&[
|
||||||
"FOR", "EACH", "$ident$", "IN", "$expr$", "$block$","NEXT", "$ident$",
|
"FOR", "EACH", "$ident$", "IN", "$expr$", "$block$", "NEXT", "$ident$",
|
||||||
],
|
],
|
||||||
false,
|
true, // We're modifying the scope by adding the loop variable
|
||||||
|context, inputs| {
|
|context, inputs| {
|
||||||
// Get the iterator variable names
|
// Get the iterator variable names
|
||||||
let loop_var = inputs[0].get_string_value().unwrap();
|
let loop_var = inputs[0].get_string_value().unwrap();
|
||||||
|
@ -44,8 +43,8 @@ impl ScriptService {
|
||||||
// Evaluate the collection expression
|
// Evaluate the collection expression
|
||||||
let collection = context.eval_expression_tree(&inputs[1])?;
|
let collection = context.eval_expression_tree(&inputs[1])?;
|
||||||
|
|
||||||
// Get the block content as a string
|
// Get the block as an expression tree
|
||||||
let block = inputs[2].get_string_value().unwrap_or_default();
|
let block = &inputs[2];
|
||||||
|
|
||||||
// Convert to array
|
// Convert to array
|
||||||
let array: Array = if collection.is_array() {
|
let array: Array = if collection.is_array() {
|
||||||
|
@ -54,21 +53,28 @@ impl ScriptService {
|
||||||
return Err("FOR EACH can only iterate over arrays".into());
|
return Err("FOR EACH can only iterate over arrays".into());
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create a new scope for the loop
|
// Remember original scope length
|
||||||
let mut scope = Scope::new();
|
let orig_len = context.scope().len();
|
||||||
|
|
||||||
for item in array {
|
for item in array {
|
||||||
// Set the variable in the scope
|
// Push the loop variable into the scope
|
||||||
scope.set_value(loop_var.clone(), item);
|
context.scope_mut().push(loop_var.to_string(), item);
|
||||||
|
|
||||||
// Evaluate the block with the new scope
|
// Evaluate the block with the current scope
|
||||||
match context.engine().eval_with_scope::<()>(&mut scope, &block) {
|
match context.eval_expression_tree(block) {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(e) if e.to_string() == "EXIT FOR" => break,
|
Err(e) if e.to_string() == "EXIT FOR" => break,
|
||||||
Err(e) => return Err(e),
|
Err(e) => {
|
||||||
|
// Rewind the scope before returning error
|
||||||
|
context.scope_mut().rewind(orig_len);
|
||||||
|
return Err(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove the loop variable for next iteration
|
||||||
|
context.scope_mut().rewind(orig_len);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(Dynamic::UNIT)
|
Ok(Dynamic::UNIT)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -266,7 +272,8 @@ impl ScriptService {
|
||||||
result.push_str("}\n");
|
result.push_str("}\n");
|
||||||
result.push_str(&" ".repeat(current_indent));
|
result.push_str(&" ".repeat(current_indent));
|
||||||
result.push_str(trimmed);
|
result.push_str(trimmed);
|
||||||
result.push_str(";\n");
|
result.push(';');
|
||||||
|
result.push('\n');
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
panic!("NEXT without matching FOR EACH");
|
panic!("NEXT without matching FOR EACH");
|
||||||
|
@ -286,7 +293,7 @@ impl ScriptService {
|
||||||
|
|
||||||
let basic_commands = [
|
let basic_commands = [
|
||||||
"SET", "CREATE", "PRINT", "FOR", "FIND", "GET", "EXIT", "IF", "THEN", "ELSE",
|
"SET", "CREATE", "PRINT", "FOR", "FIND", "GET", "EXIT", "IF", "THEN", "ELSE",
|
||||||
"END IF", "WHILE", "WEND", "DO", "LOOP", "NEXT"
|
"END IF", "WHILE", "WEND", "DO", "LOOP",
|
||||||
];
|
];
|
||||||
|
|
||||||
let is_basic_command = basic_commands.iter().any(|&cmd| trimmed.starts_with(cmd));
|
let is_basic_command = basic_commands.iter().any(|&cmd| trimmed.starts_with(cmd));
|
||||||
|
|
Loading…
Add table
Reference in a new issue