Change loops to iterators.

This commit is contained in:
Stephen Chung 2022-10-18 15:44:24 +08:00
parent c5a111ddb2
commit 4642895de8
4 changed files with 137 additions and 183 deletions

View File

@ -440,10 +440,7 @@ impl Module {
} }
first = false; first = false;
if f.access == FnAccess::Private { if f.access != FnAccess::Private {
continue;
}
#[cfg(not(feature = "no_custom_syntax"))] #[cfg(not(feature = "no_custom_syntax"))]
let operator = def.engine.custom_keywords.contains_key(&f.name) let operator = def.engine.custom_keywords.contains_key(&f.name)
|| (!f.name.contains('$') && !is_valid_function_name(&f.name)); || (!f.name.contains('$') && !is_valid_function_name(&f.name));
@ -453,6 +450,7 @@ impl Module {
f.write_definition(writer, def, operator)?; f.write_definition(writer, def, operator)?;
} }
}
Ok(()) Ok(())
} }

View File

@ -166,10 +166,7 @@ pub fn format_map_as_json(map: &Map) -> String {
if let Some(val) = value.read_lock::<Map>() { if let Some(val) = value.read_lock::<Map>() {
result.push_str(&format_map_as_json(&*val)); result.push_str(&format_map_as_json(&*val));
continue; } else if value.is::<()>() {
}
if value.is::<()>() {
result.push_str("null"); result.push_str("null");
} else { } else {
write!(result, "{:?}", value).unwrap(); write!(result, "{:?}", value).unwrap();

View File

@ -379,55 +379,39 @@ impl Engine {
Expr::InterpolatedString(x, _) => { Expr::InterpolatedString(x, _) => {
let mut concat = self.get_interned_string("").into(); let mut concat = self.get_interned_string("").into();
let target = &mut concat; let target = &mut concat;
let mut result = Ok(Dynamic::UNIT);
let mut op_info = OpAssignment::new_op_assignment(OP_CONCAT, Position::NONE); let mut op_info = OpAssignment::new_op_assignment(OP_CONCAT, Position::NONE);
let root = ("", Position::NONE); let root = ("", Position::NONE);
for expr in &**x { let result = x
.iter()
.try_for_each(|expr| {
let item = let item =
match self.eval_expr(scope, global, caches, lib, this_ptr, expr, level) { self.eval_expr(scope, global, caches, lib, this_ptr, expr, level)?;
Ok(r) => r,
err => {
result = err;
break;
}
};
op_info.pos = expr.start_position(); op_info.pos = expr.start_position();
if let Err(err) = self.eval_op_assignment( self.eval_op_assignment(
global, caches, lib, &op_info, target, root, item, level, global, caches, lib, &op_info, target, root, item, level,
) {
result = Err(err);
break;
}
}
self.check_return_value(
result.map(|_| concat.take_or_clone()),
expr.start_position(),
) )
})
.map(|_| concat.take_or_clone());
self.check_return_value(result, expr.start_position())
} }
#[cfg(not(feature = "no_index"))] #[cfg(not(feature = "no_index"))]
Expr::Array(x, ..) => { Expr::Array(x, ..) => {
let mut array = crate::Array::with_capacity(x.len());
let mut result = Ok(Dynamic::UNIT);
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
let mut total_data_sizes = (0, 0, 0); let mut total_data_sizes = (0, 0, 0);
for item_expr in &**x { x.iter()
let value = match self .try_fold(
.eval_expr(scope, global, caches, lib, this_ptr, item_expr, level) crate::Array::with_capacity(x.len()),
{ |mut array, item_expr| {
Ok(r) => r.flatten(), let value = self
err => { .eval_expr(scope, global, caches, lib, this_ptr, item_expr, level)?
result = err; .flatten();
break;
}
};
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
if self.has_data_size_limit() { if self.has_data_size_limit() {
@ -445,29 +429,23 @@ impl Engine {
} }
array.push(value); array.push(value);
}
result.map(|_| array.into()) Ok(array)
},
)
.map(Into::into)
} }
#[cfg(not(feature = "no_object"))] #[cfg(not(feature = "no_object"))]
Expr::Map(x, ..) => { Expr::Map(x, ..) => {
let mut map = x.1.clone();
let mut result = Ok(Dynamic::UNIT);
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
let mut total_data_sizes = (0, 0, 0); let mut total_data_sizes = (0, 0, 0);
for (key, value_expr) in &x.0 { x.0.iter()
let value = match self .try_fold(x.1.clone(), |mut map, (key, value_expr)| {
.eval_expr(scope, global, caches, lib, this_ptr, value_expr, level) let value = self
{ .eval_expr(scope, global, caches, lib, this_ptr, value_expr, level)?
Ok(r) => r.flatten(), .flatten();
err => {
result = err;
break;
}
};
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
if self.has_data_size_limit() { if self.has_data_size_limit() {
@ -484,9 +462,10 @@ impl Engine {
} }
*map.get_mut(key.as_str()).unwrap() = value; *map.get_mut(key.as_str()).unwrap() = value;
}
result.map(|_| map.into()) Ok(map)
})
.map(Into::into)
} }
Expr::And(x, ..) => { Expr::And(x, ..) => {
@ -498,17 +477,17 @@ impl Engine {
}) })
}); });
if let Ok(true) = lhs { match lhs {
self.eval_expr(scope, global, caches, lib, this_ptr, &x.rhs, level) Ok(true) => self
.eval_expr(scope, global, caches, lib, this_ptr, &x.rhs, level)
.and_then(|v| { .and_then(|v| {
v.as_bool() v.as_bool()
.map_err(|typ| { .map_err(|typ| {
self.make_type_mismatch_err::<bool>(typ, x.rhs.position()) self.make_type_mismatch_err::<bool>(typ, x.rhs.position())
}) })
.map(Into::into) .map(Into::into)
}) }),
} else { _ => lhs.map(Into::into),
lhs.map(Into::into)
} }
} }
@ -521,17 +500,17 @@ impl Engine {
}) })
}); });
if let Ok(false) = lhs { match lhs {
self.eval_expr(scope, global, caches, lib, this_ptr, &x.rhs, level) Ok(false) => self
.eval_expr(scope, global, caches, lib, this_ptr, &x.rhs, level)
.and_then(|v| { .and_then(|v| {
v.as_bool() v.as_bool()
.map_err(|typ| { .map_err(|typ| {
self.make_type_mismatch_err::<bool>(typ, x.rhs.position()) self.make_type_mismatch_err::<bool>(typ, x.rhs.position())
}) })
.map(Into::into) .map(Into::into)
}) }),
} else { _ => lhs.map(Into::into),
lhs.map(Into::into)
} }
} }
@ -542,7 +521,7 @@ impl Engine {
Ok(value) if value.is::<()>() => { Ok(value) if value.is::<()>() => {
self.eval_expr(scope, global, caches, lib, this_ptr, &x.rhs, level) self.eval_expr(scope, global, caches, lib, this_ptr, &x.rhs, level)
} }
Ok(_) | Err(_) => lhs, _ => lhs,
} }
} }

View File

@ -48,13 +48,11 @@ impl Engine {
global.scope_level += 1; global.scope_level += 1;
} }
let mut result = Ok(Dynamic::UNIT); let result = statements.iter().try_fold(Dynamic::UNIT, |_, stmt| {
for stmt in statements {
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
let imports_len = global.num_imports(); let imports_len = global.num_imports();
result = self.eval_stmt( let result = self.eval_stmt(
scope, scope,
global, global,
caches, caches,
@ -63,11 +61,7 @@ impl Engine {
stmt, stmt,
restore_orig_state, restore_orig_state,
level, level,
); )?;
if result.is_err() {
break;
}
#[cfg(not(feature = "no_module"))] #[cfg(not(feature = "no_module"))]
if matches!(stmt, Stmt::Import(..)) { if matches!(stmt, Stmt::Import(..)) {
@ -92,7 +86,9 @@ impl Engine {
} }
} }
} }
}
Ok(result)
});
// If imports list is modified, pop the functions lookup cache // If imports list is modified, pop the functions lookup cache
caches.rewind_fn_resolution_caches(orig_fn_resolution_caches_len); caches.rewind_fn_resolution_caches(orig_fn_resolution_caches_len);
@ -429,17 +425,12 @@ impl Engine {
}; };
match cond_result { match cond_result {
Ok(true) => { Ok(true) => result = Ok(Some(&block.expr)),
result = Ok(Some(&block.expr)); Ok(false) => continue,
_ => result = cond_result.map(|_| None),
}
break; break;
} }
Ok(false) => (),
_ => {
result = cond_result.map(|_| None);
break;
}
}
}
result result
} else if value.is::<INT>() && !ranges.is_empty() { } else if value.is::<INT>() && !ranges.is_empty() {
@ -469,7 +460,6 @@ impl Engine {
Ok(false) => continue, Ok(false) => continue,
_ => result = cond_result.map(|_| None), _ => result = cond_result.map(|_| None),
} }
break; break;
} }
@ -626,9 +616,9 @@ impl Engine {
scope.push(var_name.name.clone(), ()); scope.push(var_name.name.clone(), ());
let index = scope.len() - 1; let index = scope.len() - 1;
let mut loop_result = Ok(Dynamic::UNIT); let loop_result = func(iter_obj)
.enumerate()
for (x, iter_value) in func(iter_obj).enumerate() { .try_for_each(|(x, iter_value)| {
// Increment counter // Increment counter
if counter_index < usize::MAX { if counter_index < usize::MAX {
// As the variable increments from 0, this should always work // As the variable increments from 0, this should always work
@ -637,12 +627,11 @@ impl Engine {
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
if index_value > crate::MAX_USIZE_INT { if index_value > crate::MAX_USIZE_INT {
loop_result = Err(ERR::ErrorArithmetic( return Err(ERR::ErrorArithmetic(
format!("for-loop counter overflow: {x}"), format!("for-loop counter overflow: {x}"),
counter.pos, counter.pos,
) )
.into()); .into());
break;
} }
*scope.get_mut_by_index(counter_index).write_lock().unwrap() = *scope.get_mut_by_index(counter_index).write_lock().unwrap() =
@ -651,43 +640,34 @@ impl Engine {
let value = match iter_value { let value = match iter_value {
Ok(v) => v.flatten(), Ok(v) => v.flatten(),
Err(err) => { Err(err) => return Err(err.fill_position(expr.position())),
loop_result = Err(err.fill_position(expr.position()));
break;
}
}; };
*scope.get_mut_by_index(index).write_lock().unwrap() = value; *scope.get_mut_by_index(index).write_lock().unwrap() = value;
if let Err(err) = self.track_operation(global, statements.position()) { self.track_operation(global, statements.position())?;
loop_result = Err(err);
break;
}
if statements.is_empty() { if statements.is_empty() {
continue; return Ok(());
} }
let result = self.eval_stmt_block( self.eval_stmt_block(
scope, global, caches, lib, this_ptr, statements, true, level, scope, global, caches, lib, this_ptr, statements, true, level,
); )
.map(|_| ())
match result { .or_else(|err| match *err {
Ok(_) => (), ERR::LoopBreak(false, ..) => Ok(()),
Err(err) => match *err { _ => Err(err),
ERR::LoopBreak(false, ..) => (), })
ERR::LoopBreak(true, ..) => break, })
_ => { .or_else(|err| match *err {
loop_result = Err(err); ERR::LoopBreak(true, ..) => Ok(()),
break; _ => Err(err),
} });
},
}
}
scope.rewind(orig_scope_len); scope.rewind(orig_scope_len);
loop_result loop_result.map(|_| Dynamic::UNIT)
} else { } else {
Err(ERR::ErrorFor(expr.start_position()).into()) Err(ERR::ErrorFor(expr.start_position()).into())
} }