Add index assignment and augmented assignment

This allows for syntax like `foo['a'] = 1` and more complex assignments
like `foo.bar()[a() + b()] += 1`

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2024-10-18 22:03:10 -07:00
parent 43891bd2a3
commit 283eaa1ebe
9 changed files with 221 additions and 45 deletions

View File

@@ -587,7 +587,13 @@ impl Parser {
let expr = self.expr()?;
let stmt: StmtP;
if expr.as_any_ref().downcast_ref::<GetExpr>().is_some()
// TODO Parser::stmt_wrapped - complex assign statements could probably be cleaner and
// probably need their own function at this point.
let is_get_expr = expr.as_any_ref().downcast_ref::<GetExpr>().is_some();
let is_index_expr = expr.as_any_ref().downcast_ref::<IndexExpr>().is_some();
if (is_get_expr || is_index_expr)
&& mat!(
self,
TokenKind::Eq,
@@ -598,15 +604,28 @@ impl Parser {
)
{
let op = self.prev.clone().unwrap();
let expr = expr.as_any().downcast::<GetExpr>().unwrap();
let rhs = self.expr()?;
// unpack the GetExpr and turn it into a SetExpr instead
stmt = Box::new(SetStmt {
expr: expr.expr,
name: expr.name,
op,
rhs,
});
// unpack the GetExpr or IndexExpr and turn it into a SetExpr instead
if is_get_expr {
let expr = expr.as_any().downcast::<GetExpr>().unwrap();
stmt = Box::new(SetStmt {
expr: expr.expr,
name: expr.name,
op,
rhs,
});
} else if is_index_expr {
let expr = expr.as_any().downcast::<IndexExpr>().unwrap();
stmt = Box::new(IndexAssignStmt {
expr: expr.expr,
index: expr.index,
op,
rhs,
});
} else {
unreachable!()
}
} else {
stmt = Box::new(ExprStmt { expr });
}