diff --git a/src/api/definitions/mod.rs b/src/api/definitions/mod.rs index 7be44611..18d9c992 100644 --- a/src/api/definitions/mod.rs +++ b/src/api/definitions/mod.rs @@ -440,18 +440,16 @@ impl Module { } first = false; - if f.access == FnAccess::Private { - continue; + if f.access != FnAccess::Private { + #[cfg(not(feature = "no_custom_syntax"))] + let operator = def.engine.custom_keywords.contains_key(&f.name) + || (!f.name.contains('$') && !is_valid_function_name(&f.name)); + + #[cfg(feature = "no_custom_syntax")] + let operator = !f.name.contains('$') && !is_valid_function_name(&f.name); + + f.write_definition(writer, def, operator)?; } - - #[cfg(not(feature = "no_custom_syntax"))] - let operator = def.engine.custom_keywords.contains_key(&f.name) - || (!f.name.contains('$') && !is_valid_function_name(&f.name)); - - #[cfg(feature = "no_custom_syntax")] - let operator = !f.name.contains('$') && !is_valid_function_name(&f.name); - - f.write_definition(writer, def, operator)?; } Ok(()) diff --git a/src/api/json.rs b/src/api/json.rs index 24069fdd..c22d682c 100644 --- a/src/api/json.rs +++ b/src/api/json.rs @@ -166,10 +166,7 @@ pub fn format_map_as_json(map: &Map) -> String { if let Some(val) = value.read_lock::() { result.push_str(&format_map_as_json(&*val)); - continue; - } - - if value.is::<()>() { + } else if value.is::<()>() { result.push_str("null"); } else { write!(result, "{:?}", value).unwrap(); diff --git a/src/eval/expr.rs b/src/eval/expr.rs index c09b48a3..d86c3da6 100644 --- a/src/eval/expr.rs +++ b/src/eval/expr.rs @@ -379,114 +379,93 @@ impl Engine { Expr::InterpolatedString(x, _) => { let mut concat = self.get_interned_string("").into(); let target = &mut concat; - let mut result = Ok(Dynamic::UNIT); let mut op_info = OpAssignment::new_op_assignment(OP_CONCAT, Position::NONE); let root = ("", Position::NONE); - for expr in &**x { - let item = - match self.eval_expr(scope, global, caches, lib, this_ptr, expr, level) { - Ok(r) => r, - err => { - result = err; - break; - } - }; + let result = x + .iter() + .try_for_each(|expr| { + let item = + self.eval_expr(scope, global, caches, lib, this_ptr, expr, level)?; - op_info.pos = expr.start_position(); + op_info.pos = expr.start_position(); - if let Err(err) = self.eval_op_assignment( - global, caches, lib, &op_info, target, root, item, level, - ) { - result = Err(err); - break; - } - } + self.eval_op_assignment( + global, caches, lib, &op_info, target, root, item, level, + ) + }) + .map(|_| concat.take_or_clone()); - self.check_return_value( - result.map(|_| concat.take_or_clone()), - expr.start_position(), - ) + self.check_return_value(result, expr.start_position()) } #[cfg(not(feature = "no_index"))] Expr::Array(x, ..) => { - let mut array = crate::Array::with_capacity(x.len()); - let mut result = Ok(Dynamic::UNIT); - #[cfg(not(feature = "unchecked"))] let mut total_data_sizes = (0, 0, 0); - for item_expr in &**x { - let value = match self - .eval_expr(scope, global, caches, lib, this_ptr, item_expr, level) - { - Ok(r) => r.flatten(), - err => { - result = err; - break; - } - }; + x.iter() + .try_fold( + crate::Array::with_capacity(x.len()), + |mut array, item_expr| { + let value = self + .eval_expr(scope, global, caches, lib, this_ptr, item_expr, level)? + .flatten(); - #[cfg(not(feature = "unchecked"))] - if self.has_data_size_limit() { - let val_sizes = Self::calc_data_sizes(&value, true); + #[cfg(not(feature = "unchecked"))] + if self.has_data_size_limit() { + let val_sizes = Self::calc_data_sizes(&value, true); - total_data_sizes = ( - total_data_sizes.0 + val_sizes.0, - total_data_sizes.1 + val_sizes.1, - total_data_sizes.2 + val_sizes.2, - ); - self.raise_err_if_over_data_size_limit( - total_data_sizes, - item_expr.position(), - )?; - } + total_data_sizes = ( + total_data_sizes.0 + val_sizes.0, + total_data_sizes.1 + val_sizes.1, + total_data_sizes.2 + val_sizes.2, + ); + self.raise_err_if_over_data_size_limit( + total_data_sizes, + item_expr.position(), + )?; + } - array.push(value); - } + array.push(value); - result.map(|_| array.into()) + Ok(array) + }, + ) + .map(Into::into) } #[cfg(not(feature = "no_object"))] Expr::Map(x, ..) => { - let mut map = x.1.clone(); - let mut result = Ok(Dynamic::UNIT); - #[cfg(not(feature = "unchecked"))] let mut total_data_sizes = (0, 0, 0); - for (key, value_expr) in &x.0 { - let value = match self - .eval_expr(scope, global, caches, lib, this_ptr, value_expr, level) - { - Ok(r) => r.flatten(), - err => { - result = err; - break; + x.0.iter() + .try_fold(x.1.clone(), |mut map, (key, value_expr)| { + let value = self + .eval_expr(scope, global, caches, lib, this_ptr, value_expr, level)? + .flatten(); + + #[cfg(not(feature = "unchecked"))] + if self.has_data_size_limit() { + let delta = Self::calc_data_sizes(&value, true); + total_data_sizes = ( + total_data_sizes.0 + delta.0, + total_data_sizes.1 + delta.1, + total_data_sizes.2 + delta.2, + ); + self.raise_err_if_over_data_size_limit( + total_data_sizes, + value_expr.position(), + )?; } - }; - #[cfg(not(feature = "unchecked"))] - if self.has_data_size_limit() { - let delta = Self::calc_data_sizes(&value, true); - total_data_sizes = ( - total_data_sizes.0 + delta.0, - total_data_sizes.1 + delta.1, - total_data_sizes.2 + delta.2, - ); - self.raise_err_if_over_data_size_limit( - total_data_sizes, - value_expr.position(), - )?; - } + *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, ..) => { @@ -498,17 +477,17 @@ impl Engine { }) }); - if let Ok(true) = lhs { - self.eval_expr(scope, global, caches, lib, this_ptr, &x.rhs, level) + match lhs { + Ok(true) => self + .eval_expr(scope, global, caches, lib, this_ptr, &x.rhs, level) .and_then(|v| { v.as_bool() .map_err(|typ| { self.make_type_mismatch_err::(typ, x.rhs.position()) }) .map(Into::into) - }) - } else { - lhs.map(Into::into) + }), + _ => lhs.map(Into::into), } } @@ -521,17 +500,17 @@ impl Engine { }) }); - if let Ok(false) = lhs { - self.eval_expr(scope, global, caches, lib, this_ptr, &x.rhs, level) + match lhs { + Ok(false) => self + .eval_expr(scope, global, caches, lib, this_ptr, &x.rhs, level) .and_then(|v| { v.as_bool() .map_err(|typ| { self.make_type_mismatch_err::(typ, x.rhs.position()) }) .map(Into::into) - }) - } else { - lhs.map(Into::into) + }), + _ => lhs.map(Into::into), } } @@ -542,7 +521,7 @@ impl Engine { Ok(value) if value.is::<()>() => { self.eval_expr(scope, global, caches, lib, this_ptr, &x.rhs, level) } - Ok(_) | Err(_) => lhs, + _ => lhs, } } diff --git a/src/eval/stmt.rs b/src/eval/stmt.rs index 77e39dea..387b434e 100644 --- a/src/eval/stmt.rs +++ b/src/eval/stmt.rs @@ -48,13 +48,11 @@ impl Engine { global.scope_level += 1; } - let mut result = Ok(Dynamic::UNIT); - - for stmt in statements { + let result = statements.iter().try_fold(Dynamic::UNIT, |_, stmt| { #[cfg(not(feature = "no_module"))] let imports_len = global.num_imports(); - result = self.eval_stmt( + let result = self.eval_stmt( scope, global, caches, @@ -63,11 +61,7 @@ impl Engine { stmt, restore_orig_state, level, - ); - - if result.is_err() { - break; - } + )?; #[cfg(not(feature = "no_module"))] if matches!(stmt, Stmt::Import(..)) { @@ -92,7 +86,9 @@ impl Engine { } } } - } + + Ok(result) + }); // If imports list is modified, pop the functions lookup cache caches.rewind_fn_resolution_caches(orig_fn_resolution_caches_len); @@ -429,16 +425,11 @@ impl Engine { }; match cond_result { - Ok(true) => { - result = Ok(Some(&block.expr)); - break; - } - Ok(false) => (), - _ => { - result = cond_result.map(|_| None); - break; - } + Ok(true) => result = Ok(Some(&block.expr)), + Ok(false) => continue, + _ => result = cond_result.map(|_| None), } + break; } result @@ -469,7 +460,6 @@ impl Engine { Ok(false) => continue, _ => result = cond_result.map(|_| None), } - break; } @@ -626,68 +616,58 @@ impl Engine { scope.push(var_name.name.clone(), ()); let index = scope.len() - 1; - let mut loop_result = Ok(Dynamic::UNIT); + let loop_result = func(iter_obj) + .enumerate() + .try_for_each(|(x, iter_value)| { + // Increment counter + if counter_index < usize::MAX { + // As the variable increments from 0, this should always work + // since any overflow will first be caught below. + let index_value = x as INT; - for (x, iter_value) in func(iter_obj).enumerate() { - // Increment counter - if counter_index < usize::MAX { - // As the variable increments from 0, this should always work - // since any overflow will first be caught below. - let index_value = x as INT; - - #[cfg(not(feature = "unchecked"))] - if index_value > crate::MAX_USIZE_INT { - loop_result = Err(ERR::ErrorArithmetic( - format!("for-loop counter overflow: {x}"), - counter.pos, - ) - .into()); - break; - } - - *scope.get_mut_by_index(counter_index).write_lock().unwrap() = - Dynamic::from_int(index_value); - } - - let value = match iter_value { - Ok(v) => v.flatten(), - Err(err) => { - loop_result = Err(err.fill_position(expr.position())); - break; - } - }; - - *scope.get_mut_by_index(index).write_lock().unwrap() = value; - - if let Err(err) = self.track_operation(global, statements.position()) { - loop_result = Err(err); - break; - } - - if statements.is_empty() { - continue; - } - - let result = self.eval_stmt_block( - scope, global, caches, lib, this_ptr, statements, true, level, - ); - - match result { - Ok(_) => (), - Err(err) => match *err { - ERR::LoopBreak(false, ..) => (), - ERR::LoopBreak(true, ..) => break, - _ => { - loop_result = Err(err); - break; + #[cfg(not(feature = "unchecked"))] + if index_value > crate::MAX_USIZE_INT { + return Err(ERR::ErrorArithmetic( + format!("for-loop counter overflow: {x}"), + counter.pos, + ) + .into()); } - }, - } - } + + *scope.get_mut_by_index(counter_index).write_lock().unwrap() = + Dynamic::from_int(index_value); + } + + let value = match iter_value { + Ok(v) => v.flatten(), + Err(err) => return Err(err.fill_position(expr.position())), + }; + + *scope.get_mut_by_index(index).write_lock().unwrap() = value; + + self.track_operation(global, statements.position())?; + + if statements.is_empty() { + return Ok(()); + } + + self.eval_stmt_block( + scope, global, caches, lib, this_ptr, statements, true, level, + ) + .map(|_| ()) + .or_else(|err| match *err { + ERR::LoopBreak(false, ..) => Ok(()), + _ => Err(err), + }) + }) + .or_else(|err| match *err { + ERR::LoopBreak(true, ..) => Ok(()), + _ => Err(err), + }); scope.rewind(orig_scope_len); - loop_result + loop_result.map(|_| Dynamic::UNIT) } else { Err(ERR::ErrorFor(expr.start_position()).into()) }