Add string literal indexing and functon default value to optimizer.

This commit is contained in:
Stephen Chung 2020-03-16 12:41:52 +08:00
parent 5235ba71dd
commit 08abf07f83

View File

@ -270,11 +270,19 @@ fn optimize_expr<'a>(expr: Expr, state: &mut State<'a>) -> Expr {
(Expr::Array(mut items, _), Expr::IntegerConstant(i, _)) (Expr::Array(mut items, _), Expr::IntegerConstant(i, _))
if i >= 0 && (i as usize) < items.len() && items.iter().all(|x| x.is_pure()) => if i >= 0 && (i as usize) < items.len() && items.iter().all(|x| x.is_pure()) =>
{ {
// Array where everything is a pure - promote the indexed item. // Array literal where everything is pure - promote the indexed item.
// All other items can be thrown away. // All other items can be thrown away.
state.set_dirty(); state.set_dirty();
items.remove(i as usize) items.remove(i as usize)
} }
(Expr::StringConstant(s, pos), Expr::IntegerConstant(i, _))
if i >= 0 && (i as usize) < s.chars().count() =>
{
// String literal indexing - get the character
state.set_dirty();
Expr::CharConstant(s.chars().nth(i as usize).expect("should get char"), pos)
}
(lhs, rhs) => Expr::Index( (lhs, rhs) => Expr::Index(
Box::new(optimize_expr(lhs, state)), Box::new(optimize_expr(lhs, state)),
Box::new(optimize_expr(rhs, state)), Box::new(optimize_expr(rhs, state)),
@ -350,16 +358,13 @@ fn optimize_expr<'a>(expr: Expr, state: &mut State<'a>) -> Expr {
let engine = state.engine.expect("engine should be Some"); let engine = state.engine.expect("engine should be Some");
let mut arg_values: Vec<_> = args.iter().map(Expr::get_constant_value).collect(); let mut arg_values: Vec<_> = args.iter().map(Expr::get_constant_value).collect();
let call_args: FnCallArgs = arg_values.iter_mut().map(Dynamic::as_mut).collect(); let call_args: FnCallArgs = arg_values.iter_mut().map(Dynamic::as_mut).collect();
if let Ok(r) = engine.call_ext_fn_raw(&id, call_args, pos) { engine.call_ext_fn_raw(&id, call_args, pos).ok().map(|r|
r.and_then(|result| map_dynamic_to_expr(result, pos).0) r.or(def_value.clone()).and_then(|result| map_dynamic_to_expr(result, pos).0)
.map(|expr| { .map(|expr| {
state.set_dirty(); state.set_dirty();
expr expr
}) })).flatten()
.unwrap_or_else(|| Expr::FunctionCall(id, args, def_value, pos)) .unwrap_or_else(|| Expr::FunctionCall(id, args, def_value, pos))
} else {
Expr::FunctionCall(id, args, def_value, pos)
}
} }
// Optimize the function call arguments // Optimize the function call arguments
Expr::FunctionCall(id, args, def_value, pos) => { Expr::FunctionCall(id, args, def_value, pos) => {