Reduce cloning.
This commit is contained in:
parent
94313ca095
commit
44d6a5e466
@ -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
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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(),
|
||||
)
|
||||
}
|
||||
|
@ -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())
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
)
|
||||
Some(if value.cast::<bool>() {
|
||||
Expr::True(pos)
|
||||
} else {
|
||||
Expr::False(pos)
|
||||
})
|
||||
} 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
|
||||
}
|
||||
}
|
||||
|
20
src/scope.rs
20
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(),
|
||||
|
Loading…
Reference in New Issue
Block a user