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

View File

@ -371,3 +371,31 @@ fn test_for_module_iterator() -> Result<(), Box<EvalAltResult>> {
Ok(()) 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(())
}