Make for loops for efficient.

This commit is contained in:
Stephen Chung 2021-12-31 15:59:13 +08:00
parent 97900320e1
commit e3aa2c19ce
3 changed files with 85 additions and 18 deletions

26
scripts/for3.rhai Normal file
View File

@ -0,0 +1,26 @@
const MAX = 100;
const CHECK = ((MAX - 1) ** 2) * MAX;
print("Ready... Go!");
let now = timestamp();
print(`Creating ${MAX} closures...`);
let list = [];
for i in 0..MAX {
list.push(|| i ** 2);
}
print(`Time = ${now.elapsed} seconds...`);
print(`Summing ${MAX} closures...`);
let sum = 0;
for f in list {
sum += f.call();
}
print(`Sum = ${sum} (should be ${CHECK})`);
print(`Finished. Total run time = ${now.elapsed} seconds.`);

View File

@ -2892,16 +2892,18 @@ impl Engine {
if let Some(func) = func {
// Add the loop variables
let orig_scope_len = scope.len();
let counter_index = counter.as_ref().map(|Ident { name, .. }| {
scope.push(unsafe_cast_var_name_to_lifetime(name), 0 as INT);
let counter_index = if let Some(counter) = counter {
scope.push(unsafe_cast_var_name_to_lifetime(&counter.name), 0 as INT);
scope.len() - 1
});
} else {
usize::MAX
};
scope.push(unsafe_cast_var_name_to_lifetime(name), ());
let index = scope.len() - 1;
for (x, iter_value) in func(iter_obj).enumerate() {
// Increment counter
if let Some(c) = counter_index {
if counter_index < usize::MAX {
#[cfg(not(feature = "unchecked"))]
if x > INT::MAX as usize {
return Err(ERR::ErrorArithmetic(
@ -2911,26 +2913,37 @@ impl Engine {
.into());
}
let mut counter_var = scope
.get_mut_by_index(c)
.write_lock::<INT>()
.expect("`INT`");
*counter_var = x as INT;
let index_value = (x as INT).into();
#[cfg(not(feature = "no_closure"))]
{
let index_var = scope.get_mut_by_index(counter_index);
if index_var.is_shared() {
*index_var.write_lock().expect("`Dynamic`") = index_value;
} else {
*index_var = index_value;
}
}
#[cfg(feature = "no_closure")]
{
*scope.get_mut_by_index(counter_index) = index_value;
}
}
let loop_var = scope.get_mut_by_index(index);
let value = iter_value.flatten();
#[cfg(not(feature = "no_closure"))]
let loop_var_is_shared = loop_var.is_shared();
{
let loop_var = scope.get_mut_by_index(index);
if loop_var.is_shared() {
*loop_var.write_lock().expect("`Dynamic`") = value;
} else {
*loop_var = value;
}
}
#[cfg(feature = "no_closure")]
let loop_var_is_shared = false;
if loop_var_is_shared {
let mut value_ref = loop_var.write_lock().expect("`Dynamic`");
*value_ref = value;
} else {
*loop_var = value;
{
*scope.get_mut_by_index(index) = value;
}
#[cfg(not(feature = "unchecked"))]

View File

@ -371,3 +371,31 @@ fn test_for_module_iterator() -> Result<(), Box<EvalAltResult>> {
Ok(())
}
#[test]
#[cfg(not(feature = "no_closure"))]
fn test_for_capture() -> Result<(), Box<EvalAltResult>> {
let engine = Engine::new();
assert_eq!(
engine.eval::<INT>(
"
let a = [];
for (x, i) in 100..110 {
a += || i + x;
}
let sum = 0;
for fp in a {
sum += fp.call();
}
sum
"
)?,
1180
);
Ok(())
}