diff --git a/examples/repl.rs b/examples/repl.rs index e166b54c..d4679842 100644 --- a/examples/repl.rs +++ b/examples/repl.rs @@ -141,18 +141,18 @@ fn main() { .compile_with_scope(&scope, &script) .map_err(EvalAltResult::ErrorParsing) .and_then(|r| { - ast_u = r; + ast_u = r.clone(); #[cfg(not(feature = "no_optimize"))] { engine.set_optimization_level(OptimizationLevel::Full); - ast = engine.optimize_ast(&scope, &ast_u); + ast = engine.optimize_ast(&scope, r); engine.set_optimization_level(OptimizationLevel::None); } #[cfg(feature = "no_optimize")] { - ast = ast_u.clone(); + ast = r; } // Merge the AST into the main diff --git a/src/any.rs b/src/any.rs index 7e7494e8..1a7bda22 100644 --- a/src/any.rs +++ b/src/any.rs @@ -125,7 +125,7 @@ impl fmt::Debug for Variant { impl Clone for Dynamic { fn clone(&self) -> Self { - Any::into_dynamic(self.as_ref()) + self.as_ref().into_dynamic() } } diff --git a/src/api.rs b/src/api.rs index a8d32933..047cf525 100644 --- a/src/api.rs +++ b/src/api.rs @@ -986,7 +986,7 @@ impl<'e> Engine<'e> { } /// Optimize the `AST` with constants defined in an external Scope. - /// An optimized copy of the `AST` is returned while the original `AST` is untouched. + /// An optimized copy of the `AST` is returned while the original `AST` is consumed. /// /// Although optimization is performed by default during compilation, sometimes it is necessary to /// _re_-optimize an AST. For example, when working with constants that are passed in via an @@ -997,11 +997,11 @@ impl<'e> Engine<'e> { /// compiled just once. Before evaluation, constants are passed into the `Engine` via an external scope /// (i.e. with `scope.push_constant(...)`). Then, the `AST is cloned and the copy re-optimized before running. #[cfg(not(feature = "no_optimize"))] - pub fn optimize_ast(&self, scope: &Scope, ast: &AST) -> AST { + pub fn optimize_ast(&self, scope: &Scope, ast: AST) -> AST { optimize_into_ast( self, scope, - ast.0.clone(), + ast.0, ast.1.iter().map(|fn_def| fn_def.as_ref().clone()).collect(), ) } diff --git a/src/engine.rs b/src/engine.rs index f37388f7..8f4f418f 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -452,10 +452,11 @@ impl Engine<'_> { scope.extend( // Put arguments into scope as variables - variable name is copied + // TODO - avoid copying variable name fn_def .params .iter() - .zip(args.iter().map(|x| (*x).into_dynamic())) + .zip(args.into_iter().map(|x| (*x).into_dynamic())) .map(|(name, value)| (name.clone(), ScopeEntryType::Normal, value)), ); @@ -481,7 +482,7 @@ impl Engine<'_> { fn_def .params .iter() - .zip(args.iter().map(|x| (*x).into_dynamic())) + .zip(args.into_iter().map(|x| (*x).into_dynamic())) .map(|(name, value)| (name, ScopeEntryType::Normal, value)), ); @@ -1227,6 +1228,7 @@ impl Engine<'_> { *scope.get_mut(entry) = rhs_val.clone(); Ok(rhs_val) } + ScopeSource { typ: ScopeEntryType::Constant, .. @@ -1560,6 +1562,7 @@ impl Engine<'_> { if let Some(type_iterators) = &self.type_iterators { if let Some(iter_fn) = type_iterators.get(&tid) { // Add the loop variable - variable name is copied + // TODO - avoid copying variable name scope.push(name.clone(), ()); let entry = ScopeSource { @@ -1622,11 +1625,13 @@ impl Engine<'_> { // Let statement Stmt::Let(name, Some(expr), _) => { let val = self.eval_expr(scope, expr, level)?; + // TODO - avoid copying variable name in inner block? scope.push_dynamic_value(name.clone(), ScopeEntryType::Normal, val, false); Ok(().into_dynamic()) } Stmt::Let(name, None, _) => { + // TODO - avoid copying variable name in inner block? scope.push(name.clone(), ()); Ok(().into_dynamic()) } @@ -1634,6 +1639,7 @@ impl Engine<'_> { // Const statement Stmt::Const(name, expr, _) if expr.is_constant() => { let val = self.eval_expr(scope, expr, level)?; + // TODO - avoid copying variable name in inner block? scope.push_dynamic_value(name.clone(), ScopeEntryType::Constant, val, true); Ok(().into_dynamic()) } diff --git a/src/optimize.rs b/src/optimize.rs index 4dcbf7b3..ec5d3688 100644 --- a/src/optimize.rs +++ b/src/optimize.rs @@ -480,7 +480,7 @@ fn optimize_expr<'a>(expr: Expr, state: &mut State<'a>) -> Expr { // Otherwise use the default value, if any def_value.clone() } - }).and_then(|result| map_dynamic_to_expr(result, pos).0) + }).and_then(|result| map_dynamic_to_expr(result, pos)) .map(|expr| { state.set_dirty(); expr diff --git a/src/parser.rs b/src/parser.rs index 0ce3e30d..8dcbbc98 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -221,15 +221,15 @@ impl AST { /// # } /// ``` pub fn merge(&self, other: &Self) -> Self { - let Self(ast, functions) = self; + let Self(statements, functions) = self; - let ast = match (ast.is_empty(), other.0.is_empty()) { + let ast = match (statements.is_empty(), other.0.is_empty()) { (false, false) => { - let mut ast = ast.clone(); - ast.extend(other.0.iter().cloned()); - ast + let mut statements = statements.clone(); + statements.extend(other.0.iter().cloned()); + statements } - (false, true) => ast.clone(), + (false, true) => statements.clone(), (true, false) => other.0.clone(), (true, true) => vec![], }; @@ -1733,8 +1733,8 @@ fn parse_map_literal<'a>( PERR::MissingToken("}".into(), "to end this object map literal".into()) .into_err_eof() })? { - (Token::Identifier(s), pos) => (s.clone(), pos), - (Token::StringConst(s), pos) => (s.clone(), pos), + (Token::Identifier(s), pos) => (s, pos), + (Token::StringConst(s), pos) => (s, pos), (_, pos) if map.is_empty() => { return Err(PERR::MissingToken( "}".into(), @@ -2727,35 +2727,27 @@ pub fn parse<'a, 'e>( /// Map a `Dynamic` value to an expression. /// /// Returns Some(expression) if conversion is successful. Otherwise None. -pub fn map_dynamic_to_expr(value: Dynamic, pos: Position) -> (Option, Dynamic) { +pub fn map_dynamic_to_expr(value: Dynamic, pos: Position) -> Option { if value.is::() { - let value2 = value.clone(); - (Some(Expr::IntegerConstant(value.cast(), pos)), value2) + Some(Expr::IntegerConstant(value.cast(), pos)) } else if value.is::() { - let value2 = value.clone(); - (Some(Expr::CharConstant(value.cast(), pos)), value2) + Some(Expr::CharConstant(value.cast(), pos)) } else if value.is::() { - let value2 = value.clone(); - (Some(Expr::StringConstant(value.cast(), pos)), value2) + Some(Expr::StringConstant(value.cast(), pos)) } else if value.is::() { - let value2 = value.clone(); - ( - Some(if value.cast::() { - Expr::True(pos) - } else { - Expr::False(pos) - }), - value2, - ) + Some(if value.cast::() { + Expr::True(pos) + } else { + Expr::False(pos) + }) } else { #[cfg(not(feature = "no_float"))] { if value.is::() { - let value2 = value.clone(); - return (Some(Expr::FloatConstant(value.cast(), pos)), value2); + return Some(Expr::FloatConstant(value.cast(), pos)); } } - (None, value) + None } } diff --git a/src/scope.rs b/src/scope.rs index d3740f4c..14f53cb5 100644 --- a/src/scope.rs +++ b/src/scope.rs @@ -126,17 +126,15 @@ impl<'a> Scope<'a> { value: Dynamic, map_expr: bool, ) { - let (expr, value) = if map_expr { - map_dynamic_to_expr(value, Position::none()) - } else { - (None, value) - }; - self.0.push(Entry { name: name.into(), typ: entry_type, - value, - expr, + value: value.clone(), + expr: if map_expr { + map_dynamic_to_expr(value, Position::none()) + } else { + None + }, }); } @@ -163,15 +161,15 @@ impl<'a> Scope<'a> { .find(|(_, Entry { name, .. })| name == key) .map( |( - i, + index, Entry { name, typ, value, .. }, )| { ( EntryRef { - name: name.as_ref(), - index: i, + name, + index, typ: *typ, }, value.clone(),