Combine ! and ? into single TrySuffix AST node

This commit is contained in:
Sam Mohr 2024-08-14 22:14:08 -07:00
parent cc5bf3f164
commit 3bc5c1dc12
No known key found for this signature in database
GPG key ID: EA41D161A3C1BC99
42 changed files with 859 additions and 162 deletions

View file

@ -392,6 +392,15 @@ pub enum StrLiteral<'a> {
Block(&'a [&'a [StrSegment<'a>]]),
}
/// Values that can be tried, extracting success values or "returning early" on failure
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum TryTarget {
/// Tasks suffixed with ! are `Task.await`ed
Task,
/// Results suffixed with ? are `Result.try`ed
Result,
}
/// A parsed expression. This uses lifetimes extensively for two reasons:
///
/// 1. It uses Bump::alloc for all allocations, which returns a reference.
@ -426,8 +435,11 @@ pub enum Expr<'a> {
/// Look up exactly one field on a tuple, e.g. `(x, y).1`.
TupleAccess(&'a Expr<'a>, &'a str),
/// Task await bang - i.e. the ! in `File.readUtf8! path`
TaskAwaitBang(&'a Expr<'a>),
/// Early return on failures - e.g. the ! in `File.readUtf8! path`
TrySuffix {
target: TryTarget,
expr: &'a Expr<'a>,
},
// Collection Literals
List(Collection<'a, &'a Loc<Expr<'a>>>),
@ -555,9 +567,9 @@ pub fn split_loc_exprs_around<'a>(
/// Checks if the bang suffix is applied only at the top level of expression
pub fn is_top_level_suffixed(expr: &Expr) -> bool {
// TODO: should we check BinOps with pizza where the last expression is TaskAwaitBang?
// TODO: should we check BinOps with pizza where the last expression is TrySuffix?
match expr {
Expr::TaskAwaitBang(..) => true,
Expr::TrySuffix { .. } => true,
Expr::Apply(a, _, _) => is_top_level_suffixed(&a.value),
Expr::SpaceBefore(a, _) => is_top_level_suffixed(a),
Expr::SpaceAfter(a, _) => is_top_level_suffixed(a),
@ -571,7 +583,7 @@ pub fn is_expr_suffixed(expr: &Expr) -> bool {
// expression without arguments, `read!`
Expr::Var { .. } => false,
Expr::TaskAwaitBang(..) => true,
Expr::TrySuffix { .. } => true,
// expression with arguments, `line! "Foo"`
Expr::Apply(sub_loc_expr, apply_args, _) => {
@ -995,7 +1007,7 @@ impl<'a, 'b> RecursiveValueDefIter<'a, 'b> {
}
RecordAccess(expr, _)
| TupleAccess(expr, _)
| TaskAwaitBang(expr)
| TrySuffix { expr, .. }
| SpaceBefore(expr, _)
| SpaceAfter(expr, _)
| ParensAround(expr) => expr_stack.push(expr),
@ -2486,7 +2498,7 @@ impl<'a> Malformed for Expr<'a> {
RecordAccess(inner, _) |
TupleAccess(inner, _) |
TaskAwaitBang(inner) => inner.is_malformed(),
TrySuffix { expr: inner, .. } => inner.is_malformed(),
List(items) => items.is_malformed(),