Reduce cloning.

This commit is contained in:
Stephen Chung 2020-04-05 17:44:48 +08:00
parent 94313ca095
commit 44d6a5e466
7 changed files with 44 additions and 48 deletions

View File

@ -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

View File

@ -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()
}
}

View File

@ -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(),
)
}

View File

@ -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())
}

View File

@ -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

View File

@ -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<Expr>, Dynamic) {
pub fn map_dynamic_to_expr(value: Dynamic, pos: Position) -> Option<Expr> {
if value.is::<INT>() {
let value2 = value.clone();
(Some(Expr::IntegerConstant(value.cast(), pos)), value2)
Some(Expr::IntegerConstant(value.cast(), pos))
} else if value.is::<char>() {
let value2 = value.clone();
(Some(Expr::CharConstant(value.cast(), pos)), value2)
Some(Expr::CharConstant(value.cast(), pos))
} else if value.is::<String>() {
let value2 = value.clone();
(Some(Expr::StringConstant(value.cast(), pos)), value2)
Some(Expr::StringConstant(value.cast(), pos))
} else if value.is::<bool>() {
let value2 = value.clone();
(
Some(if value.cast::<bool>() {
Expr::True(pos)
} else {
Expr::False(pos)
}),
value2,
)
})
} else {
#[cfg(not(feature = "no_float"))]
{
if value.is::<FLOAT>() {
let value2 = value.clone();
return (Some(Expr::FloatConstant(value.cast(), pos)), value2);
return Some(Expr::FloatConstant(value.cast(), pos));
}
}
(None, value)
None
}
}

View File

@ -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(),