mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 04:08:19 +00:00
Combine ! and ? into single TrySuffix AST node
This commit is contained in:
parent
cc5bf3f164
commit
3bc5c1dc12
42 changed files with 859 additions and 162 deletions
|
@ -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(),
|
||||
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
use crate::ast::{
|
||||
is_expr_suffixed, AssignedField, Collection, CommentOrNewline, Defs, Expr, ExtractSpaces,
|
||||
Implements, ImplementsAbilities, ImportAlias, ImportAsKeyword, ImportExposingKeyword,
|
||||
ImportedModuleName, IngestedFileAnnotation, IngestedFileImport, ModuleImport,
|
||||
ModuleImportParams, OldRecordBuilderField, Pattern, Spaceable, Spaced, Spaces, SpacesBefore,
|
||||
TypeAnnotation, TypeDef, TypeHeader, ValueDef,
|
||||
is_expr_suffixed, AssignedField, Collection, CommentOrNewline, Defs, Expr, ExtractSpaces, Implements, ImplementsAbilities, ImportAlias, ImportAsKeyword, ImportExposingKeyword, ImportedModuleName, IngestedFileAnnotation, IngestedFileImport, ModuleImport, ModuleImportParams, OldRecordBuilderField, Pattern, Spaceable, Spaced, Spaces, SpacesBefore, TryTarget, TypeAnnotation, TypeDef, TypeHeader, ValueDef
|
||||
};
|
||||
use crate::blankspace::{
|
||||
loc_space0_e, require_newline_or_eof, space0_after_e, space0_around_ee, space0_before_e,
|
||||
|
@ -169,7 +165,8 @@ fn record_field_access_chain<'a>() -> impl Parser<'a, Vec<'a, Suffix<'a>>, EExpr
|
|||
)
|
||||
)
|
||||
),
|
||||
map(byte(b'!', EExpr::Access), |_| Suffix::TaskAwaitBang),
|
||||
map(byte(b'!', EExpr::Access), |_| Suffix::TrySuffix(TryTarget::Task)),
|
||||
map(byte(b'?', EExpr::Access), |_| Suffix::TrySuffix(TryTarget::Result)),
|
||||
))
|
||||
}
|
||||
|
||||
|
@ -2177,7 +2174,7 @@ fn expr_to_pattern_help<'a>(arena: &'a Bump, expr: &Expr<'a>) -> Result<Pattern<
|
|||
| Expr::OptionalFieldInRecordBuilder(_, _)
|
||||
| Expr::RecordUpdate { .. }
|
||||
| Expr::UnaryOp(_, _)
|
||||
| Expr::TaskAwaitBang(..)
|
||||
| Expr::TrySuffix { .. }
|
||||
| Expr::Crash
|
||||
| Expr::OldRecordBuilder(..)
|
||||
| Expr::RecordBuilder { .. } => return Err(()),
|
||||
|
@ -3749,7 +3746,10 @@ fn apply_expr_access_chain<'a>(
|
|||
Suffix::Accessor(Accessor::TupleIndex(field)) => {
|
||||
Expr::TupleAccess(arena.alloc(value), field)
|
||||
}
|
||||
Suffix::TaskAwaitBang => Expr::TaskAwaitBang(arena.alloc(value)),
|
||||
Suffix::TrySuffix(target) => Expr::TrySuffix {
|
||||
target,
|
||||
expr: arena.alloc(value),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use crate::ast::TryTarget;
|
||||
use crate::parser::Progress::{self, *};
|
||||
use crate::parser::{BadInputError, EExpr, ParseResult, Parser};
|
||||
use crate::state::State;
|
||||
|
@ -377,7 +378,7 @@ impl<'a> Accessor<'a> {
|
|||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Suffix<'a> {
|
||||
Accessor(Accessor<'a>),
|
||||
TaskAwaitBang,
|
||||
TrySuffix(TryTarget),
|
||||
}
|
||||
|
||||
/// a `.foo` or `.1` accessor function
|
||||
|
|
|
@ -722,7 +722,7 @@ impl<'a> Normalize<'a> for Expr<'a> {
|
|||
Expr::RecordAccess(a, b) => Expr::RecordAccess(arena.alloc(a.normalize(arena)), b),
|
||||
Expr::AccessorFunction(a) => Expr::AccessorFunction(a),
|
||||
Expr::TupleAccess(a, b) => Expr::TupleAccess(arena.alloc(a.normalize(arena)), b),
|
||||
Expr::TaskAwaitBang(a) => Expr::TaskAwaitBang(arena.alloc(a.normalize(arena))),
|
||||
Expr::TrySuffix { expr: a, target } => Expr::TrySuffix { expr: arena.alloc(a.normalize(arena)), target },
|
||||
Expr::List(a) => Expr::List(a.normalize(arena)),
|
||||
Expr::RecordUpdate { update, fields } => Expr::RecordUpdate {
|
||||
update: arena.alloc(update.normalize(arena)),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue