Support negative index counting from end.

This commit is contained in:
Stephen Chung
2021-04-10 15:00:03 +08:00
parent 716e9cf779
commit 40fda5139d
9 changed files with 273 additions and 83 deletions

View File

@@ -654,6 +654,17 @@ fn optimize_expr(expr: &mut Expr, state: &mut State) {
result.set_position(*pos);
*expr = result;
}
// array[-int]
(Expr::Array(a, pos), Expr::IntegerConstant(i, _))
if *i < 0 && i.checked_abs().map(|n| n as usize <= a.len()).unwrap_or(false) && a.iter().all(Expr::is_pure) =>
{
// Array literal where everything is pure - promote the indexed item.
// All other items can be thrown away.
state.set_dirty();
let mut result = a.remove(a.len() - i.abs() as usize);
result.set_position(*pos);
*expr = result;
}
// map[string]
(Expr::Map(m, pos), Expr::StringConstant(s, _)) if m.0.iter().all(|(_, x)| x.is_pure()) => {
// Map literal where everything is pure - promote the indexed item.
@@ -669,6 +680,12 @@ fn optimize_expr(expr: &mut Expr, state: &mut State) {
state.set_dirty();
*expr = Expr::CharConstant(s.chars().nth(*i as usize).unwrap(), *pos);
}
// string[-int]
(Expr::StringConstant(s, pos), Expr::IntegerConstant(i, _)) if *i < 0 && i.checked_abs().map(|n| n as usize <= s.chars().count()).unwrap_or(false) => {
// String literal indexing - get the character
state.set_dirty();
*expr = Expr::CharConstant(s.chars().rev().nth(i.abs() as usize - 1).unwrap(), *pos);
}
// var[rhs]
(Expr::Variable(_, _, _), rhs) => optimize_expr(rhs, state),
// lhs[rhs]