mirror of
https://github.com/roc-lang/roc.git
synced 2025-07-24 15:03:46 +00:00
Merge pull request #7000 from smores56/try-suffix-ast-node
Combine ! and ? into single TrySuffix AST node
This commit is contained in:
commit
a14a110293
45 changed files with 921 additions and 188 deletions
|
@ -1,6 +1,6 @@
|
|||
#![allow(clippy::manual_map)]
|
||||
|
||||
use crate::suffixed::{apply_task_await, unwrap_suffixed_expression, EUnwrapped};
|
||||
use crate::suffixed::{apply_try_function, unwrap_suffixed_expression, EUnwrapped};
|
||||
use bumpalo::collections::Vec;
|
||||
use bumpalo::Bump;
|
||||
use roc_error_macros::internal_error;
|
||||
|
@ -220,11 +220,20 @@ pub fn desugar_value_def_suffixed<'a>(arena: &'a Bump, value_def: ValueDef<'a>)
|
|||
sub_arg,
|
||||
sub_pat,
|
||||
sub_new,
|
||||
target,
|
||||
}) => desugar_value_def_suffixed(
|
||||
arena,
|
||||
Body(
|
||||
loc_pattern,
|
||||
apply_task_await(arena, loc_expr.region, sub_arg, sub_pat, sub_new, None),
|
||||
apply_try_function(
|
||||
arena,
|
||||
loc_expr.region,
|
||||
sub_arg,
|
||||
sub_pat,
|
||||
sub_new,
|
||||
None,
|
||||
target,
|
||||
),
|
||||
),
|
||||
),
|
||||
Err(..) => Body(
|
||||
|
@ -254,6 +263,7 @@ pub fn desugar_value_def_suffixed<'a>(arena: &'a Bump, value_def: ValueDef<'a>)
|
|||
sub_arg,
|
||||
sub_pat,
|
||||
sub_new,
|
||||
target,
|
||||
}) => desugar_value_def_suffixed(
|
||||
arena,
|
||||
AnnotatedBody {
|
||||
|
@ -261,13 +271,14 @@ pub fn desugar_value_def_suffixed<'a>(arena: &'a Bump, value_def: ValueDef<'a>)
|
|||
ann_type,
|
||||
lines_between,
|
||||
body_pattern,
|
||||
body_expr: apply_task_await(
|
||||
body_expr: apply_try_function(
|
||||
arena,
|
||||
body_expr.region,
|
||||
sub_arg,
|
||||
sub_pat,
|
||||
sub_new,
|
||||
Some((ann_pattern, ann_type)),
|
||||
target,
|
||||
),
|
||||
},
|
||||
),
|
||||
|
@ -371,14 +382,23 @@ pub fn desugar_expr<'a>(
|
|||
|
||||
arena.alloc(Loc { region, value })
|
||||
}
|
||||
// desugar the sub_expression, but leave the TaskAwaitBang as this will
|
||||
// desugar the sub_expression, but leave the TrySuffix as this will
|
||||
// be unwrapped later in desugar_value_def_suffixed
|
||||
TaskAwaitBang(sub_expr) => {
|
||||
TrySuffix {
|
||||
expr: sub_expr,
|
||||
target,
|
||||
} => {
|
||||
let intermediate = arena.alloc(Loc::at(loc_expr.region, **sub_expr));
|
||||
let new_sub_loc_expr = desugar_expr(arena, intermediate, src, line_info, module_path);
|
||||
let new_sub_expr = arena.alloc(new_sub_loc_expr.value);
|
||||
|
||||
arena.alloc(Loc::at(loc_expr.region, TaskAwaitBang(new_sub_expr)))
|
||||
arena.alloc(Loc::at(
|
||||
loc_expr.region,
|
||||
TrySuffix {
|
||||
expr: new_sub_expr,
|
||||
target: *target,
|
||||
},
|
||||
))
|
||||
}
|
||||
RecordAccess(sub_expr, paths) => {
|
||||
let region = loc_expr.region;
|
||||
|
|
|
@ -648,9 +648,7 @@ pub fn canonicalize_expr<'a>(
|
|||
|
||||
(answer, Output::default())
|
||||
}
|
||||
ast::Expr::Record(fields) => {
|
||||
canonicalize_record(env, var_store, scope, region, *fields)
|
||||
}
|
||||
ast::Expr::Record(fields) => canonicalize_record(env, var_store, scope, region, *fields),
|
||||
ast::Expr::RecordUpdate {
|
||||
fields,
|
||||
update: loc_update,
|
||||
|
@ -1119,7 +1117,9 @@ pub fn canonicalize_expr<'a>(
|
|||
output,
|
||||
)
|
||||
}
|
||||
ast::Expr::TaskAwaitBang(..) => internal_error!("a Expr::TaskAwaitBang expression was not completely removed in desugar_value_def_suffixed"),
|
||||
ast::Expr::TrySuffix { .. } => internal_error!(
|
||||
"a Expr::TrySuffix expression was not completely removed in desugar_value_def_suffixed"
|
||||
),
|
||||
ast::Expr::Tag(tag) => {
|
||||
let variant_var = var_store.fresh();
|
||||
let ext_var = var_store.fresh();
|
||||
|
@ -1371,7 +1371,10 @@ pub fn canonicalize_expr<'a>(
|
|||
use roc_problem::can::RuntimeError::*;
|
||||
|
||||
let sub_region = Region::span_across(&loc_name.region, &loc_value.region);
|
||||
let problem = OptionalFieldInRecordBuilder {record: region, field: sub_region };
|
||||
let problem = OptionalFieldInRecordBuilder {
|
||||
record: region,
|
||||
field: sub_region,
|
||||
};
|
||||
env.problem(Problem::RuntimeError(problem.clone()));
|
||||
|
||||
(RuntimeError(problem), Output::default())
|
||||
|
@ -2515,7 +2518,7 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
|
|||
ast::Expr::TupleAccess(sub_expr, _)
|
||||
| ast::Expr::ParensAround(sub_expr)
|
||||
| ast::Expr::RecordAccess(sub_expr, _)
|
||||
| ast::Expr::TaskAwaitBang(sub_expr) => is_valid_interpolation(sub_expr),
|
||||
| ast::Expr::TrySuffix { expr: sub_expr, .. } => is_valid_interpolation(sub_expr),
|
||||
ast::Expr::Apply(loc_expr, args, _called_via) => {
|
||||
is_valid_interpolation(&loc_expr.value)
|
||||
&& args
|
||||
|
|
|
@ -6,7 +6,7 @@ use roc_error_macros::internal_error;
|
|||
use roc_module::called_via::CalledVia;
|
||||
use roc_module::ident::ModuleName;
|
||||
use roc_parse::ast::Expr::{self, *};
|
||||
use roc_parse::ast::{is_expr_suffixed, Pattern, TypeAnnotation, ValueDef, WhenBranch};
|
||||
use roc_parse::ast::{is_expr_suffixed, Pattern, TryTarget, TypeAnnotation, ValueDef, WhenBranch};
|
||||
use roc_region::all::{Loc, Region};
|
||||
use std::cell::Cell;
|
||||
|
||||
|
@ -34,14 +34,17 @@ pub enum EUnwrapped<'a> {
|
|||
/// e.g. x = first! (second! 42)
|
||||
/// The first unwrap will produce
|
||||
/// `UnwrappedDefExpr<first (second! 42)>`
|
||||
UnwrappedDefExpr(&'a Loc<Expr<'a>>),
|
||||
UnwrappedDefExpr {
|
||||
loc_expr: &'a Loc<Expr<'a>>,
|
||||
target: TryTarget,
|
||||
},
|
||||
|
||||
/// Suffixed sub expression
|
||||
/// e.g. x = first! (second! 42)
|
||||
/// In this example, the second unwrap (after unwrapping the top level `first!`) will produce
|
||||
/// `UnwrappedSubExpr<{ sub_arg: second 42, sub_pat: #!0_arg, sub_new: #!0_arg }>`
|
||||
UnwrappedSubExpr {
|
||||
/// the unwrapped expression argument for Task.await
|
||||
/// the unwrapped expression argument for `try` functions
|
||||
sub_arg: &'a Loc<Expr<'a>>,
|
||||
|
||||
/// the pattern for the closure
|
||||
|
@ -49,6 +52,9 @@ pub enum EUnwrapped<'a> {
|
|||
|
||||
/// the expression to replace the unwrapped
|
||||
sub_new: &'a Loc<Expr<'a>>,
|
||||
|
||||
/// The type of the target for the suffix, e.g. a Task or Result
|
||||
target: TryTarget,
|
||||
},
|
||||
|
||||
/// Malformed use of the suffix
|
||||
|
@ -59,12 +65,16 @@ fn init_unwrapped_err<'a>(
|
|||
arena: &'a Bump,
|
||||
unwrapped_expr: &'a Loc<Expr<'a>>,
|
||||
maybe_def_pat: Option<&'a Loc<Pattern<'a>>>,
|
||||
target: TryTarget,
|
||||
) -> Result<&'a Loc<Expr<'a>>, EUnwrapped<'a>> {
|
||||
match maybe_def_pat {
|
||||
Some(..) => {
|
||||
// we have a def pattern, so no need to generate a new pattern
|
||||
// as this should only be created in the first call from a def
|
||||
Err(EUnwrapped::UnwrappedDefExpr(unwrapped_expr))
|
||||
Err(EUnwrapped::UnwrappedDefExpr {
|
||||
loc_expr: unwrapped_expr,
|
||||
target,
|
||||
})
|
||||
}
|
||||
None => {
|
||||
// Provide an intermediate answer expression and pattern when unwrapping a
|
||||
|
@ -87,13 +97,14 @@ fn init_unwrapped_err<'a>(
|
|||
sub_arg: unwrapped_expr,
|
||||
sub_pat,
|
||||
sub_new,
|
||||
target,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Descend through the AST and unwrap each suffixed expression
|
||||
/// when an expression is unwrapped, we apply a `Task.await` and
|
||||
/// when an expression is unwrapped, we apply the appropriate try function and
|
||||
/// then descend through the AST again until there are no more suffixed
|
||||
/// expressions, or we hit an error
|
||||
pub fn unwrap_suffixed_expression<'a>(
|
||||
|
@ -103,10 +114,13 @@ pub fn unwrap_suffixed_expression<'a>(
|
|||
) -> Result<&'a Loc<Expr<'a>>, EUnwrapped<'a>> {
|
||||
let unwrapped_expression = {
|
||||
match loc_expr.value {
|
||||
Expr::TaskAwaitBang(sub_expr) => {
|
||||
Expr::TrySuffix {
|
||||
expr: sub_expr,
|
||||
target,
|
||||
} => {
|
||||
let unwrapped_sub_expr = arena.alloc(Loc::at(loc_expr.region, *sub_expr));
|
||||
|
||||
init_unwrapped_err(arena, unwrapped_sub_expr, maybe_def_pat)
|
||||
init_unwrapped_err(arena, unwrapped_sub_expr, maybe_def_pat, target)
|
||||
}
|
||||
|
||||
Expr::Defs(..) => unwrap_suffixed_expression_defs_help(arena, loc_expr, maybe_def_pat),
|
||||
|
@ -154,15 +168,22 @@ pub fn unwrap_suffixed_expression<'a>(
|
|||
.alloc(Loc::at(loc_expr.region, Expect(condition, unwrapped_expr)));
|
||||
return Ok(new_expect);
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedDefExpr(unwrapped_expr)) => {
|
||||
Err(EUnwrapped::UnwrappedDefExpr {
|
||||
loc_expr: unwrapped_expr,
|
||||
target,
|
||||
}) => {
|
||||
let new_expect = arena
|
||||
.alloc(Loc::at(loc_expr.region, Expect(condition, unwrapped_expr)));
|
||||
Err(EUnwrapped::UnwrappedDefExpr(new_expect))
|
||||
Err(EUnwrapped::UnwrappedDefExpr {
|
||||
loc_expr: new_expect,
|
||||
target,
|
||||
})
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedSubExpr {
|
||||
sub_arg: unwrapped_expr,
|
||||
sub_pat,
|
||||
sub_new,
|
||||
target,
|
||||
}) => {
|
||||
let new_expect = arena
|
||||
.alloc(Loc::at(loc_expr.region, Expect(condition, unwrapped_expr)));
|
||||
|
@ -170,6 +191,7 @@ pub fn unwrap_suffixed_expression<'a>(
|
|||
sub_arg: new_expect,
|
||||
sub_pat,
|
||||
sub_new,
|
||||
target,
|
||||
})
|
||||
}
|
||||
Err(EUnwrapped::Malformed) => Err(EUnwrapped::Malformed),
|
||||
|
@ -208,13 +230,14 @@ pub fn unwrap_suffixed_expression_parens_help<'a>(
|
|||
));
|
||||
Ok(new_parens)
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedDefExpr(..)) => {
|
||||
Err(EUnwrapped::UnwrappedDefExpr { .. }) => {
|
||||
internal_error!("unreachable, child expressions from ParensAround should generate UnwrappedSubExpr instead");
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedSubExpr {
|
||||
sub_arg,
|
||||
sub_pat,
|
||||
sub_new,
|
||||
target,
|
||||
}) => {
|
||||
let new_parens = arena.alloc(Loc::at(
|
||||
loc_expr.region,
|
||||
|
@ -224,6 +247,7 @@ pub fn unwrap_suffixed_expression_parens_help<'a>(
|
|||
sub_arg,
|
||||
sub_pat,
|
||||
sub_new: new_parens,
|
||||
target,
|
||||
})
|
||||
}
|
||||
Err(err) => Err(err),
|
||||
|
@ -247,13 +271,13 @@ pub fn unwrap_suffixed_expression_closure_help<'a>(
|
|||
let new_closure = arena.alloc(Loc::at(loc_expr.region, Expr::Closure(closure_args, unwrapped_expr)));
|
||||
Ok(new_closure)
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new }) => {
|
||||
let new_closure_loc_ret = apply_task_await(arena, loc_expr.region, sub_arg, sub_pat, sub_new, None);
|
||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new, target }) => {
|
||||
let new_closure_loc_ret = apply_try_function(arena, loc_expr.region, sub_arg, sub_pat, sub_new, None, target);
|
||||
let new_closure = arena.alloc(Loc::at(loc_expr.region, Expr::Closure(closure_args, new_closure_loc_ret)));
|
||||
Ok(new_closure)
|
||||
}
|
||||
Err(err) => {
|
||||
debug_assert!(false,"the closure Defs was malformd, got {:#?}", err);
|
||||
debug_assert!(false,"the closure Defs was malformed, got {:#?}", err);
|
||||
Err(EUnwrapped::Malformed)
|
||||
}
|
||||
}
|
||||
|
@ -278,22 +302,22 @@ pub fn unwrap_suffixed_expression_apply_help<'a>(
|
|||
Ok(new_arg) => {
|
||||
*arg = new_arg;
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedDefExpr(..)) => {
|
||||
Err(EUnwrapped::UnwrappedDefExpr { .. }) => {
|
||||
internal_error!("unreachable, unwrapped arg cannot be def expression as `None` was passed as pattern");
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new: new_arg }) => {
|
||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new: new_arg, target }) => {
|
||||
|
||||
*arg = new_arg;
|
||||
|
||||
let new_apply = arena.alloc(Loc::at(loc_expr.region, Apply(function, local_args, called_via)));
|
||||
return Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new: new_apply});
|
||||
return Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new: new_apply, target });
|
||||
}
|
||||
Err(err) => return Err(err),
|
||||
}
|
||||
}
|
||||
|
||||
// special case for when our Apply function is a suffixed Var (but not multiple suffixed)
|
||||
if let Expr::TaskAwaitBang(sub_expr) = function.value {
|
||||
if let Expr::TrySuffix { expr: sub_expr, target } = function.value {
|
||||
let unwrapped_function = arena.alloc(Loc::at(
|
||||
loc_expr.region,
|
||||
*sub_expr,
|
||||
|
@ -301,7 +325,7 @@ pub fn unwrap_suffixed_expression_apply_help<'a>(
|
|||
|
||||
let new_apply = arena.alloc(Loc::at(loc_expr.region, Expr::Apply(unwrapped_function, local_args, called_via)));
|
||||
|
||||
return init_unwrapped_err(arena, new_apply, maybe_def_pat);
|
||||
return init_unwrapped_err(arena, new_apply, maybe_def_pat, target);
|
||||
}
|
||||
|
||||
// function is another expression
|
||||
|
@ -310,15 +334,14 @@ pub fn unwrap_suffixed_expression_apply_help<'a>(
|
|||
let new_apply = arena.alloc(Loc::at(loc_expr.region, Expr::Apply(new_function, local_args, called_via)));
|
||||
Ok(new_apply)
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedDefExpr(unwrapped_function)) => {
|
||||
Err(EUnwrapped::UnwrappedDefExpr { loc_expr: unwrapped_function, target }) => {
|
||||
let new_apply = arena.alloc(Loc::at(loc_expr.region, Expr::Apply(unwrapped_function, local_args, called_via)));
|
||||
Err(EUnwrapped::UnwrappedDefExpr(new_apply))
|
||||
Err(EUnwrapped::UnwrappedDefExpr { loc_expr: new_apply, target })
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg: unwrapped_function, sub_pat, sub_new }) => {
|
||||
|
||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg: unwrapped_function, sub_pat, sub_new, target }) => {
|
||||
let new_apply = arena.alloc(Loc::at(loc_expr.region, Expr::Apply(sub_new, local_args, called_via)));
|
||||
|
||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg: unwrapped_function, sub_pat, sub_new:new_apply})
|
||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg: unwrapped_function, sub_pat, sub_new:new_apply, target })
|
||||
}
|
||||
Err(err) => Err(err)
|
||||
}
|
||||
|
@ -361,21 +384,23 @@ pub fn unwrap_suffixed_expression_if_then_else_help<'a>(
|
|||
|
||||
return unwrap_suffixed_expression(arena, new_if, maybe_def_pat);
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedDefExpr(..)) => {
|
||||
Err(EUnwrapped::UnwrappedDefExpr { .. }) => {
|
||||
internal_error!("unexpected, unwrapped if-then-else Def expr should have intermediate answer as `None` was passed as pattern");
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedSubExpr {
|
||||
sub_arg,
|
||||
sub_pat,
|
||||
sub_new,
|
||||
target,
|
||||
}) => {
|
||||
let unwrapped_expression = apply_task_await(
|
||||
let unwrapped_expression = apply_try_function(
|
||||
arena,
|
||||
sub_arg.region,
|
||||
sub_arg,
|
||||
sub_pat,
|
||||
sub_new,
|
||||
None,
|
||||
target,
|
||||
);
|
||||
|
||||
let mut new_if_thens = Vec::new_in(arena);
|
||||
|
@ -422,13 +447,14 @@ pub fn unwrap_suffixed_expression_if_then_else_help<'a>(
|
|||
|
||||
return unwrap_suffixed_expression(arena, new_if, maybe_def_pat);
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedDefExpr(..)) => {
|
||||
Err(EUnwrapped::UnwrappedDefExpr { .. }) => {
|
||||
internal_error!("unexpected, unwrapped if-then-else Def expr should have intermediate answer as `None` was passed as pattern");
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedSubExpr {
|
||||
sub_arg,
|
||||
sub_pat,
|
||||
sub_new,
|
||||
target,
|
||||
}) => {
|
||||
if before.is_empty() {
|
||||
let mut new_if_thens = Vec::new_in(arena);
|
||||
|
@ -445,13 +471,14 @@ pub fn unwrap_suffixed_expression_if_then_else_help<'a>(
|
|||
),
|
||||
));
|
||||
|
||||
let unwrapped_if_then = apply_task_await(
|
||||
let unwrapped_if_then = apply_try_function(
|
||||
arena,
|
||||
sub_arg.region,
|
||||
sub_arg,
|
||||
sub_pat,
|
||||
new_if,
|
||||
None,
|
||||
target,
|
||||
);
|
||||
|
||||
return unwrap_suffixed_expression(
|
||||
|
@ -473,13 +500,14 @@ pub fn unwrap_suffixed_expression_if_then_else_help<'a>(
|
|||
),
|
||||
));
|
||||
|
||||
let after_if_then = apply_task_await(
|
||||
let after_if_then = apply_try_function(
|
||||
arena,
|
||||
sub_arg.region,
|
||||
sub_arg,
|
||||
sub_pat,
|
||||
after_if,
|
||||
None,
|
||||
target,
|
||||
);
|
||||
|
||||
let before_if_then = arena.alloc(Loc::at(
|
||||
|
@ -507,16 +535,24 @@ pub fn unwrap_suffixed_expression_if_then_else_help<'a>(
|
|||
Expr::If(if_thens, unwrapped_final_else),
|
||||
)));
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedDefExpr(..)) => {
|
||||
Err(EUnwrapped::UnwrappedDefExpr { .. }) => {
|
||||
internal_error!("unexpected, unwrapped if-then-else Def expr should have intermediate answer as `None` was passed as pattern");
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedSubExpr {
|
||||
sub_arg,
|
||||
sub_pat,
|
||||
sub_new,
|
||||
target,
|
||||
}) => {
|
||||
let unwrapped_final_else =
|
||||
apply_task_await(arena, sub_arg.region, sub_arg, sub_pat, sub_new, None);
|
||||
let unwrapped_final_else = apply_try_function(
|
||||
arena,
|
||||
sub_arg.region,
|
||||
sub_arg,
|
||||
sub_pat,
|
||||
sub_new,
|
||||
None,
|
||||
target,
|
||||
);
|
||||
|
||||
let new_if = arena.alloc(Loc::at(
|
||||
loc_expr.region,
|
||||
|
@ -551,7 +587,7 @@ pub fn unwrap_suffixed_expression_when_help<'a>(
|
|||
if is_expr_suffixed(&branch_loc_expr.value) {
|
||||
let unwrapped_branch_value = match unwrap_suffixed_expression(arena, branch_loc_expr, None) {
|
||||
Ok(unwrapped_branch_value) => unwrapped_branch_value,
|
||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new }) => apply_task_await(arena, branch_loc_expr.region, sub_arg, sub_pat, sub_new, None),
|
||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new, target }) => apply_try_function(arena, branch_loc_expr.region, sub_arg, sub_pat, sub_new, None, target),
|
||||
Err(..) => return Err(EUnwrapped::Malformed),
|
||||
};
|
||||
|
||||
|
@ -578,12 +614,12 @@ pub fn unwrap_suffixed_expression_when_help<'a>(
|
|||
let new_when = arena.alloc(Loc::at(loc_expr.region, Expr::When(unwrapped_condition, branches)));
|
||||
Ok(new_when)
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new }) => {
|
||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new, target }) => {
|
||||
let new_when = arena.alloc(Loc::at(loc_expr.region, Expr::When(sub_new, branches)));
|
||||
let applied_task_await = apply_task_await(arena,loc_expr.region,sub_arg,sub_pat,new_when, None);
|
||||
let applied_task_await = apply_try_function(arena,loc_expr.region,sub_arg,sub_pat,new_when, None, target);
|
||||
Ok(applied_task_await)
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedDefExpr(..))
|
||||
Err(EUnwrapped::UnwrappedDefExpr { .. })
|
||||
| Err(EUnwrapped::Malformed) => Err(EUnwrapped::Malformed)
|
||||
}
|
||||
|
||||
|
@ -631,7 +667,7 @@ pub fn unwrap_suffixed_expression_defs_help<'a>(
|
|||
current_value_def.replace_expr(unwrapped_def);
|
||||
local_defs.replace_with_value_def(tag_index, current_value_def, def_expr.region);
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedDefExpr(unwrapped_expr)) => {
|
||||
Err(EUnwrapped::UnwrappedDefExpr { loc_expr: unwrapped_expr, target }) => {
|
||||
let split_defs = local_defs.split_defs_around(tag_index);
|
||||
let before_empty = split_defs.before.is_empty();
|
||||
let after_empty = split_defs.after.is_empty();
|
||||
|
@ -640,48 +676,60 @@ pub fn unwrap_suffixed_expression_defs_help<'a>(
|
|||
// We pass None as a def pattern here because it's desugaring of the ret expression
|
||||
let next_expr = match unwrap_suffixed_expression(arena,loc_ret, None) {
|
||||
Ok(next_expr) => next_expr,
|
||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new }) => {
|
||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new, target }) => {
|
||||
// We need to apply Task.ok here as the defs final expression was unwrapped
|
||||
apply_task_await(arena,def_expr.region,sub_arg,sub_pat,sub_new, None)
|
||||
apply_try_function(arena,def_expr.region,sub_arg,sub_pat,sub_new, None, target)
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedDefExpr(..)) | Err(EUnwrapped::Malformed) => {
|
||||
Err(EUnwrapped::UnwrappedDefExpr { .. }) | Err(EUnwrapped::Malformed) => {
|
||||
// TODO handle case when we have maybe_def_pat so can return an unwrapped up
|
||||
return Err(EUnwrapped::Malformed);
|
||||
},
|
||||
};
|
||||
return unwrap_suffixed_expression(arena, apply_task_await(arena,def_expr.region,unwrapped_expr,def_pattern,next_expr, ann_type), maybe_def_pat);
|
||||
return unwrap_suffixed_expression(
|
||||
arena,
|
||||
apply_try_function(
|
||||
arena,
|
||||
def_expr.region,
|
||||
unwrapped_expr,
|
||||
def_pattern,
|
||||
next_expr,
|
||||
ann_type,
|
||||
target,
|
||||
),
|
||||
maybe_def_pat
|
||||
);
|
||||
} else if before_empty {
|
||||
// NIL before, SOME after -> FIRST DEF
|
||||
let new_defs = arena.alloc(Loc::at(def_expr.region, Defs(arena.alloc(split_defs.after), loc_ret)));
|
||||
|
||||
let next_expr = match unwrap_suffixed_expression(arena,new_defs,maybe_def_pat){
|
||||
Ok(next_expr) => next_expr,
|
||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new }) => {
|
||||
apply_task_await(arena, def_expr.region, sub_arg, sub_pat, sub_new, None)
|
||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new, target }) => {
|
||||
apply_try_function(arena, def_expr.region, sub_arg, sub_pat, sub_new, None, target)
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedDefExpr(..)) | Err(EUnwrapped::Malformed) => {
|
||||
Err(EUnwrapped::UnwrappedDefExpr { .. }) | Err(EUnwrapped::Malformed) => {
|
||||
// TODO handle case when we have maybe_def_pat so can return an unwrapped up
|
||||
return Err(EUnwrapped::Malformed);
|
||||
},
|
||||
};
|
||||
|
||||
return unwrap_suffixed_expression(arena, apply_task_await(arena,def_expr.region,unwrapped_expr,def_pattern,next_expr,ann_type), maybe_def_pat);
|
||||
return unwrap_suffixed_expression(arena, apply_try_function(arena,def_expr.region,unwrapped_expr,def_pattern,next_expr, ann_type, target), maybe_def_pat);
|
||||
} else if after_empty {
|
||||
// SOME before, NIL after -> LAST DEF
|
||||
// We pass None as a def pattern here because it's desugaring of the ret expression
|
||||
match unwrap_suffixed_expression(arena,loc_ret,None){
|
||||
Ok(new_loc_ret) => {
|
||||
let applied_task_await = apply_task_await(arena, loc_expr.region, unwrapped_expr, def_pattern, new_loc_ret, ann_type);
|
||||
let applied_task_await = apply_try_function(arena, loc_expr.region, unwrapped_expr, def_pattern, new_loc_ret, ann_type, target);
|
||||
let new_defs = arena.alloc(Loc::at(loc_expr.region,Defs(arena.alloc(split_defs.before), applied_task_await)));
|
||||
return unwrap_suffixed_expression(arena, new_defs, maybe_def_pat);
|
||||
},
|
||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new }) => {
|
||||
let new_loc_ret = apply_task_await(arena,def_expr.region,sub_arg,sub_pat,sub_new, None);
|
||||
let applied_task_await = apply_task_await(arena, loc_expr.region, unwrapped_expr, def_pattern, new_loc_ret, ann_type);
|
||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new, target }) => {
|
||||
let new_loc_ret = apply_try_function(arena,def_expr.region,sub_arg,sub_pat,sub_new, None, target);
|
||||
let applied_task_await = apply_try_function(arena, loc_expr.region, unwrapped_expr, def_pattern, new_loc_ret, ann_type, target);
|
||||
let new_defs = arena.alloc(Loc::at(loc_expr.region,Defs(arena.alloc(split_defs.before), applied_task_await)));
|
||||
return unwrap_suffixed_expression(arena, new_defs, maybe_def_pat);
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedDefExpr(..)) => {
|
||||
Err(EUnwrapped::UnwrappedDefExpr { .. }) => {
|
||||
// TODO confirm this is correct with test case
|
||||
return Err(EUnwrapped::Malformed);
|
||||
}
|
||||
|
@ -695,28 +743,28 @@ pub fn unwrap_suffixed_expression_defs_help<'a>(
|
|||
|
||||
match unwrap_suffixed_expression(arena,after_defs,maybe_def_pat){
|
||||
Ok(new_loc_ret) => {
|
||||
let applied_await = apply_task_await(arena, loc_expr.region, unwrapped_expr, def_pattern, new_loc_ret, ann_type);
|
||||
let applied_await = apply_try_function(arena, loc_expr.region, unwrapped_expr, def_pattern, new_loc_ret, ann_type, target);
|
||||
let new_defs = arena.alloc(Loc::at(loc_expr.region,Defs(arena.alloc(split_defs.before), applied_await)));
|
||||
return unwrap_suffixed_expression(arena, new_defs, maybe_def_pat);
|
||||
},
|
||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new }) => {
|
||||
let new_loc_ret = apply_task_await(arena, def_expr.region, sub_arg, sub_pat, sub_new, None);
|
||||
let applied_await = apply_task_await(arena, loc_expr.region, unwrapped_expr, def_pattern, new_loc_ret, ann_type);
|
||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new, target }) => {
|
||||
let new_loc_ret = apply_try_function(arena, def_expr.region, sub_arg, sub_pat, sub_new, None, target);
|
||||
let applied_await = apply_try_function(arena, loc_expr.region, unwrapped_expr, def_pattern, new_loc_ret, ann_type, target);
|
||||
let new_defs = arena.alloc(Loc::at(loc_expr.region,Defs(arena.alloc(split_defs.before), applied_await)));
|
||||
return unwrap_suffixed_expression(arena, new_defs, maybe_def_pat);
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedDefExpr(..)) | Err(EUnwrapped::Malformed) => {
|
||||
Err(EUnwrapped::UnwrappedDefExpr { .. }) | Err(EUnwrapped::Malformed) => {
|
||||
// TODO handle case when we have maybe_def_pat so can return an unwrapped up
|
||||
return Err(EUnwrapped::Malformed);
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new }) => {
|
||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new, target }) => {
|
||||
let new_body_def = ValueDef::Body(def_pattern, sub_new);
|
||||
local_defs.replace_with_value_def(tag_index,new_body_def, sub_new.region);
|
||||
let new_defs_expr = arena.alloc(Loc::at(def_expr.region,Defs(arena.alloc(local_defs), loc_ret)));
|
||||
let replaced_def = apply_task_await(arena,def_expr.region,sub_arg,sub_pat,new_defs_expr, ann_type);
|
||||
let replaced_def = apply_try_function(arena,def_expr.region,sub_arg,sub_pat,new_defs_expr, ann_type, target);
|
||||
return unwrap_suffixed_expression(arena,replaced_def,maybe_def_pat);
|
||||
}
|
||||
Err(err) => return Err(err)
|
||||
|
@ -730,12 +778,12 @@ pub fn unwrap_suffixed_expression_defs_help<'a>(
|
|||
Ok(new_loc_ret) => {
|
||||
Ok(arena.alloc(Loc::at(loc_expr.region,Defs(arena.alloc(local_defs), new_loc_ret))))
|
||||
},
|
||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new }) => {
|
||||
let new_loc_ret = apply_task_await(arena, loc_expr.region,sub_arg,sub_pat,sub_new, None);
|
||||
Err(EUnwrapped::UnwrappedSubExpr { sub_arg, sub_pat, sub_new, target }) => {
|
||||
let new_loc_ret = apply_try_function(arena, loc_expr.region,sub_arg,sub_pat,sub_new, None, target);
|
||||
let new_defs = arena.alloc(Loc::at(loc_expr.region,Defs(arena.alloc(local_defs), new_loc_ret)));
|
||||
unwrap_suffixed_expression(arena, new_defs, None)
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedDefExpr(..)) => {
|
||||
Err(EUnwrapped::UnwrappedDefExpr { .. }) => {
|
||||
// TODO confirm this is correct with test case
|
||||
Err(EUnwrapped::Malformed)
|
||||
}
|
||||
|
@ -769,6 +817,7 @@ fn unwrap_low_level_dbg<'a>(
|
|||
sub_arg,
|
||||
sub_pat,
|
||||
sub_new,
|
||||
target,
|
||||
}) => {
|
||||
let new_dbg = arena.alloc(Loc::at(
|
||||
loc_expr.region,
|
||||
|
@ -777,18 +826,19 @@ fn unwrap_low_level_dbg<'a>(
|
|||
|
||||
unwrap_suffixed_expression(
|
||||
arena,
|
||||
apply_task_await(
|
||||
apply_try_function(
|
||||
arena,
|
||||
new_dbg.region,
|
||||
sub_arg,
|
||||
sub_pat,
|
||||
new_dbg,
|
||||
None,
|
||||
target,
|
||||
),
|
||||
maybe_def_pat,
|
||||
)
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedDefExpr(..)) => {
|
||||
Err(EUnwrapped::UnwrappedDefExpr { .. }) => {
|
||||
internal_error!(
|
||||
"unreachable, arg of LowLevelDbg should generate UnwrappedSubExpr instead"
|
||||
);
|
||||
|
@ -805,17 +855,24 @@ fn unwrap_low_level_dbg<'a>(
|
|||
));
|
||||
Ok(&*new_dbg)
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedDefExpr(unwrapped_expr)) => {
|
||||
Err(EUnwrapped::UnwrappedDefExpr {
|
||||
loc_expr: unwrapped_expr,
|
||||
target,
|
||||
}) => {
|
||||
let new_dbg = arena.alloc(Loc::at(
|
||||
loc_expr.region,
|
||||
LowLevelDbg(dbg_src, arg, unwrapped_expr),
|
||||
));
|
||||
Err(EUnwrapped::UnwrappedDefExpr(new_dbg))
|
||||
Err(EUnwrapped::UnwrappedDefExpr {
|
||||
loc_expr: new_dbg,
|
||||
target,
|
||||
})
|
||||
}
|
||||
Err(EUnwrapped::UnwrappedSubExpr {
|
||||
sub_arg: unwrapped_expr,
|
||||
sub_pat,
|
||||
sub_new,
|
||||
target,
|
||||
}) => {
|
||||
let new_dbg = arena.alloc(Loc::at(
|
||||
loc_expr.region,
|
||||
|
@ -825,6 +882,7 @@ fn unwrap_low_level_dbg<'a>(
|
|||
sub_arg: new_dbg,
|
||||
sub_pat,
|
||||
sub_new,
|
||||
target,
|
||||
})
|
||||
}
|
||||
Err(EUnwrapped::Malformed) => Err(EUnwrapped::Malformed),
|
||||
|
@ -836,25 +894,26 @@ fn unwrap_low_level_dbg<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
/// Helper for `Task.await loc_expr \loc_pat -> loc_cont`
|
||||
pub fn apply_task_await<'a>(
|
||||
/// Helper for try_function loc_expr \loc_pat -> loc_cont`
|
||||
pub fn apply_try_function<'a>(
|
||||
arena: &'a Bump,
|
||||
region: Region,
|
||||
loc_expr: &'a Loc<Expr<'a>>,
|
||||
loc_pat: &'a Loc<Pattern<'a>>,
|
||||
loc_cont: &'a Loc<Expr<'a>>,
|
||||
maybe_loc_ann: Option<(&'a Loc<Pattern>, &'a Loc<TypeAnnotation<'a>>)>,
|
||||
target: TryTarget,
|
||||
) -> &'a Loc<Expr<'a>> {
|
||||
let task_await_first_arg = match maybe_loc_ann {
|
||||
let try_function_first_arg = match maybe_loc_ann {
|
||||
Some((loc_ann_pat, loc_type)) => {
|
||||
// loc_ann_pat : loc_type
|
||||
// loc_pat = loc_expr!
|
||||
// loc_cont
|
||||
|
||||
// desugar to
|
||||
// Task.await
|
||||
// try_function
|
||||
// (
|
||||
// #!0_expr : Task loc_type _
|
||||
// #!0_expr : Target loc_type _
|
||||
// #!0_expr = loc_expr
|
||||
// #!0_expr
|
||||
// )
|
||||
|
@ -875,8 +934,12 @@ pub fn apply_task_await<'a>(
|
|||
let new_ident = arena.alloc(new_ident);
|
||||
|
||||
// #!0_expr (pattern)
|
||||
// #!0_expr : Task loc_type _
|
||||
// #!0_expr : Target loc_type _
|
||||
// #!0_expr = loc_expr
|
||||
let target_type_name = match target {
|
||||
TryTarget::Task => "Task",
|
||||
TryTarget::Result => "Result",
|
||||
};
|
||||
let value_def = ValueDef::AnnotatedBody {
|
||||
ann_pattern: arena.alloc(Loc::at(
|
||||
loc_ann_pat.region,
|
||||
|
@ -893,7 +956,7 @@ pub fn apply_task_await<'a>(
|
|||
loc_type.region,
|
||||
TypeAnnotation::Apply(
|
||||
arena.alloc(""),
|
||||
arena.alloc("Task"),
|
||||
arena.alloc(target_type_name),
|
||||
arena.alloc([
|
||||
*loc_type,
|
||||
Loc::at(loc_type.region, TypeAnnotation::Inferred),
|
||||
|
@ -918,7 +981,7 @@ pub fn apply_task_await<'a>(
|
|||
));
|
||||
|
||||
// (
|
||||
// #!0_expr : Task loc_type _
|
||||
// #!0_expr : Target loc_type _
|
||||
// #!0_expr = loc_expr
|
||||
// #!0_expr
|
||||
// )
|
||||
|
@ -935,7 +998,7 @@ pub fn apply_task_await<'a>(
|
|||
// loc_cont
|
||||
|
||||
// desugar to
|
||||
// Task.await loc_expr \loc_pat -> loc_cont
|
||||
// try_function loc_expr \loc_pat -> loc_cont
|
||||
loc_expr
|
||||
}
|
||||
};
|
||||
|
@ -945,25 +1008,29 @@ pub fn apply_task_await<'a>(
|
|||
// \x -> x!
|
||||
// \x -> x
|
||||
if is_matching_intermediate_answer(loc_pat, loc_cont) {
|
||||
return task_await_first_arg;
|
||||
return try_function_first_arg;
|
||||
}
|
||||
|
||||
// \loc_pat -> loc_cont
|
||||
let closure = arena.alloc(Loc::at(region, Closure(arena.alloc([*loc_pat]), loc_cont)));
|
||||
|
||||
// Task.await task_first_arg closure
|
||||
// try_function first_arg closure
|
||||
let (try_function_module, try_function_ident, called_via) = match target {
|
||||
TryTarget::Task => (ModuleName::TASK, "await", CalledVia::BangSuffix),
|
||||
TryTarget::Result => (ModuleName::RESULT, "try", CalledVia::QuestionSuffix),
|
||||
};
|
||||
arena.alloc(Loc::at(
|
||||
region,
|
||||
Apply(
|
||||
arena.alloc(Loc {
|
||||
region,
|
||||
value: Var {
|
||||
module_name: ModuleName::TASK,
|
||||
ident: "await",
|
||||
module_name: try_function_module,
|
||||
ident: try_function_ident,
|
||||
},
|
||||
}),
|
||||
arena.alloc([task_await_first_arg, closure]),
|
||||
CalledVia::BangSuffix,
|
||||
arena.alloc([try_function_first_arg, closure]),
|
||||
called_via,
|
||||
),
|
||||
))
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ use crate::Buf;
|
|||
use roc_module::called_via::{self, BinOp};
|
||||
use roc_parse::ast::{
|
||||
is_expr_suffixed, AssignedField, Base, Collection, CommentOrNewline, Expr, ExtractSpaces,
|
||||
OldRecordBuilderField, Pattern, WhenBranch,
|
||||
OldRecordBuilderField, Pattern, TryTarget, WhenBranch,
|
||||
};
|
||||
use roc_parse::ast::{StrLiteral, StrSegment};
|
||||
use roc_parse::ident::Accessor;
|
||||
|
@ -47,7 +47,7 @@ impl<'a> Formattable for Expr<'a> {
|
|||
| OpaqueRef(_)
|
||||
| Crash => false,
|
||||
|
||||
RecordAccess(inner, _) | TupleAccess(inner, _) | TaskAwaitBang(inner) => {
|
||||
RecordAccess(inner, _) | TupleAccess(inner, _) | TrySuffix { expr: inner, .. } => {
|
||||
inner.is_multiline()
|
||||
}
|
||||
|
||||
|
@ -520,9 +520,12 @@ impl<'a> Formattable for Expr<'a> {
|
|||
buf.push('.');
|
||||
buf.push_str(key);
|
||||
}
|
||||
TaskAwaitBang(expr) => {
|
||||
TrySuffix { expr, target } => {
|
||||
expr.format_with_options(buf, Parens::InApply, Newlines::Yes, indent);
|
||||
buf.push('!');
|
||||
match target {
|
||||
TryTarget::Task => buf.push('!'),
|
||||
TryTarget::Result => buf.push('?'),
|
||||
}
|
||||
}
|
||||
MalformedIdent(str, _) => {
|
||||
buf.indent(indent);
|
||||
|
|
|
@ -95,6 +95,10 @@ pub enum CalledVia {
|
|||
/// This call is the result of desugaring a Task.await from `!` syntax
|
||||
/// e.g. Stdout.line! "Hello" becomes Task.await (Stdout.line "Hello") \{} -> ...
|
||||
BangSuffix,
|
||||
|
||||
/// This call is the result of desugaring a Result.try from `?` syntax
|
||||
/// e.g. Dict.get? items "key" becomes Result.try (Dict.get items "key") \item -> ...
|
||||
QuestionSuffix,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
|
|
|
@ -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(),
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::ast::{
|
|||
Implements, ImplementsAbilities, ImportAlias, ImportAsKeyword, ImportExposingKeyword,
|
||||
ImportedModuleName, IngestedFileAnnotation, IngestedFileImport, ModuleImport,
|
||||
ModuleImportParams, OldRecordBuilderField, Pattern, Spaceable, Spaced, Spaces, SpacesBefore,
|
||||
TypeAnnotation, TypeDef, TypeHeader, ValueDef,
|
||||
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 +169,12 @@ 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 +2182,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 +3754,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,10 @@ 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)),
|
||||
|
|
|
@ -62,12 +62,13 @@ Defs {
|
|||
),
|
||||
Stmt(
|
||||
@97-111 Apply(
|
||||
@97-108 TaskAwaitBang(
|
||||
Var {
|
||||
@97-108 TrySuffix {
|
||||
target: Task,
|
||||
expr: Var {
|
||||
module_name: "Stdout",
|
||||
ident: "line",
|
||||
},
|
||||
),
|
||||
},
|
||||
[
|
||||
@110-111 Var {
|
||||
module_name: "",
|
||||
|
@ -80,12 +81,13 @@ Defs {
|
|||
],
|
||||
},
|
||||
@141-150 SpaceBefore(
|
||||
TaskAwaitBang(
|
||||
Var {
|
||||
TrySuffix {
|
||||
target: Task,
|
||||
expr: Var {
|
||||
module_name: "",
|
||||
ident: "printBar",
|
||||
},
|
||||
),
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
Newline,
|
||||
|
|
|
@ -26,12 +26,13 @@ Defs {
|
|||
(
|
||||
@11-23 SpaceAfter(
|
||||
Apply(
|
||||
@11-19 TaskAwaitBang(
|
||||
Var {
|
||||
@11-19 TrySuffix {
|
||||
target: Task,
|
||||
expr: Var {
|
||||
module_name: "Arg",
|
||||
ident: "list",
|
||||
},
|
||||
),
|
||||
},
|
||||
[
|
||||
@21-23 Record(
|
||||
[],
|
||||
|
@ -88,12 +89,13 @@ Defs {
|
|||
),
|
||||
(
|
||||
@83-98 SpaceAfter(
|
||||
TaskAwaitBang(
|
||||
Var {
|
||||
TrySuffix {
|
||||
target: Task,
|
||||
expr: Var {
|
||||
module_name: "Task",
|
||||
ident: "fromResult",
|
||||
},
|
||||
),
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
|
@ -152,12 +154,13 @@ Defs {
|
|||
@174-176 Pizza,
|
||||
),
|
||||
],
|
||||
@177-188 TaskAwaitBang(
|
||||
Var {
|
||||
@177-188 TrySuffix {
|
||||
target: Task,
|
||||
expr: Var {
|
||||
module_name: "Stdout",
|
||||
ident: "line",
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
TaskAwaitBang(
|
||||
TaskAwaitBang(
|
||||
TaskAwaitBang(
|
||||
Var {
|
||||
module_name: "Stdout",
|
||||
ident: "line",
|
||||
},
|
||||
),
|
||||
),
|
||||
)
|
|
@ -0,0 +1,13 @@
|
|||
TrySuffix {
|
||||
target: Task,
|
||||
expr: TrySuffix {
|
||||
target: Task,
|
||||
expr: TrySuffix {
|
||||
target: Task,
|
||||
expr: Var {
|
||||
module_name: "Stdout",
|
||||
ident: "line",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
|
@ -44,12 +44,13 @@ Defs {
|
|||
value_defs: [
|
||||
Stmt(
|
||||
@12-21 Apply(
|
||||
@12-13 TaskAwaitBang(
|
||||
Var {
|
||||
@12-13 TrySuffix {
|
||||
target: Task,
|
||||
expr: Var {
|
||||
module_name: "",
|
||||
ident: "a",
|
||||
},
|
||||
),
|
||||
},
|
||||
[
|
||||
@16-21 Str(
|
||||
PlainLine(
|
||||
|
@ -65,12 +66,13 @@ Defs {
|
|||
ident: "x",
|
||||
},
|
||||
@29-39 Apply(
|
||||
@29-32 TaskAwaitBang(
|
||||
Var {
|
||||
@29-32 TrySuffix {
|
||||
target: Task,
|
||||
expr: Var {
|
||||
module_name: "B",
|
||||
ident: "b",
|
||||
},
|
||||
),
|
||||
},
|
||||
[
|
||||
@34-39 Str(
|
||||
PlainLine(
|
||||
|
@ -85,12 +87,13 @@ Defs {
|
|||
},
|
||||
@45-49 SpaceBefore(
|
||||
Apply(
|
||||
@45-46 TaskAwaitBang(
|
||||
Var {
|
||||
@45-46 TrySuffix {
|
||||
target: Task,
|
||||
expr: Var {
|
||||
module_name: "",
|
||||
ident: "c",
|
||||
},
|
||||
),
|
||||
},
|
||||
[
|
||||
@48-49 Var {
|
||||
module_name: "",
|
|
@ -1,19 +1,21 @@
|
|||
Apply(
|
||||
@0-3 TaskAwaitBang(
|
||||
Var {
|
||||
@0-3 TrySuffix {
|
||||
target: Task,
|
||||
expr: Var {
|
||||
module_name: "",
|
||||
ident: "foo",
|
||||
},
|
||||
),
|
||||
},
|
||||
[
|
||||
@9-17 ParensAround(
|
||||
Apply(
|
||||
@9-12 TaskAwaitBang(
|
||||
Var {
|
||||
@9-12 TrySuffix {
|
||||
target: Task,
|
||||
expr: Var {
|
||||
module_name: "",
|
||||
ident: "bar",
|
||||
},
|
||||
),
|
||||
},
|
||||
[
|
||||
@14-17 Var {
|
||||
module_name: "",
|
|
@ -123,12 +123,13 @@ Full(
|
|||
@126-128 Pizza,
|
||||
),
|
||||
],
|
||||
@129-132 TaskAwaitBang(
|
||||
Var {
|
||||
@129-132 TrySuffix {
|
||||
target: Task,
|
||||
expr: Var {
|
||||
module_name: "A",
|
||||
ident: "x",
|
||||
},
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
Stmt(
|
||||
|
@ -144,12 +145,13 @@ Full(
|
|||
),
|
||||
],
|
||||
@171-205 Apply(
|
||||
@171-174 TaskAwaitBang(
|
||||
Var {
|
||||
@171-174 TrySuffix {
|
||||
target: Task,
|
||||
expr: Var {
|
||||
module_name: "B",
|
||||
ident: "y",
|
||||
},
|
||||
),
|
||||
},
|
||||
[
|
||||
@185-205 SpaceBefore(
|
||||
Record(
|
|
@ -108,12 +108,13 @@ Full(
|
|||
),
|
||||
],
|
||||
@167-202 Apply(
|
||||
@167-178 TaskAwaitBang(
|
||||
Var {
|
||||
@167-178 TrySuffix {
|
||||
target: Task,
|
||||
expr: Var {
|
||||
module_name: "Task",
|
||||
ident: "mapErr",
|
||||
},
|
||||
),
|
||||
},
|
||||
[
|
||||
@180-202 Tag(
|
||||
"UnableToCheckJQVersion",
|
|
@ -0,0 +1,13 @@
|
|||
TrySuffix {
|
||||
target: Result,
|
||||
expr: TrySuffix {
|
||||
target: Result,
|
||||
expr: TrySuffix {
|
||||
target: Result,
|
||||
expr: Var {
|
||||
module_name: "Stdout",
|
||||
ident: "line",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
Stdout.line???
|
|
@ -0,0 +1,5 @@
|
|||
main =
|
||||
a? "Bar"
|
||||
x = B.b? "Foo"
|
||||
|
||||
c? x
|
|
@ -0,0 +1,119 @@
|
|||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@0-49,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 1),
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
],
|
||||
type_defs: [],
|
||||
value_defs: [
|
||||
Body(
|
||||
@0-4 Identifier {
|
||||
ident: "main",
|
||||
},
|
||||
@12-49 SpaceBefore(
|
||||
Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
Index(2147483649),
|
||||
],
|
||||
regions: [
|
||||
@12-21,
|
||||
@26-39,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice(start = 0, length = 1),
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice(start = 1, length = 0),
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
],
|
||||
type_defs: [],
|
||||
value_defs: [
|
||||
Stmt(
|
||||
@12-21 Apply(
|
||||
@12-13 TrySuffix {
|
||||
target: Result,
|
||||
expr: Var {
|
||||
module_name: "",
|
||||
ident: "a",
|
||||
},
|
||||
},
|
||||
[
|
||||
@16-21 Str(
|
||||
PlainLine(
|
||||
"Bar",
|
||||
),
|
||||
),
|
||||
],
|
||||
Space,
|
||||
),
|
||||
),
|
||||
Body(
|
||||
@26-27 Identifier {
|
||||
ident: "x",
|
||||
},
|
||||
@29-39 Apply(
|
||||
@29-32 TrySuffix {
|
||||
target: Result,
|
||||
expr: Var {
|
||||
module_name: "B",
|
||||
ident: "b",
|
||||
},
|
||||
},
|
||||
[
|
||||
@34-39 Str(
|
||||
PlainLine(
|
||||
"Foo",
|
||||
),
|
||||
),
|
||||
],
|
||||
Space,
|
||||
),
|
||||
),
|
||||
],
|
||||
},
|
||||
@45-49 SpaceBefore(
|
||||
Apply(
|
||||
@45-46 TrySuffix {
|
||||
target: Result,
|
||||
expr: Var {
|
||||
module_name: "",
|
||||
ident: "c",
|
||||
},
|
||||
},
|
||||
[
|
||||
@48-49 Var {
|
||||
module_name: "",
|
||||
ident: "x",
|
||||
},
|
||||
],
|
||||
Space,
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
main =
|
||||
a? "Bar"
|
||||
x= B.b? "Foo"
|
||||
|
||||
c? x
|
|
@ -0,0 +1 @@
|
|||
foo? (bar? baz) (blah stuff)
|
|
@ -0,0 +1,45 @@
|
|||
Apply(
|
||||
@0-3 TrySuffix {
|
||||
target: Result,
|
||||
expr: Var {
|
||||
module_name: "",
|
||||
ident: "foo",
|
||||
},
|
||||
},
|
||||
[
|
||||
@9-17 ParensAround(
|
||||
Apply(
|
||||
@9-12 TrySuffix {
|
||||
target: Result,
|
||||
expr: Var {
|
||||
module_name: "",
|
||||
ident: "bar",
|
||||
},
|
||||
},
|
||||
[
|
||||
@14-17 Var {
|
||||
module_name: "",
|
||||
ident: "baz",
|
||||
},
|
||||
],
|
||||
Space,
|
||||
),
|
||||
),
|
||||
@22-32 ParensAround(
|
||||
Apply(
|
||||
@22-26 Var {
|
||||
module_name: "",
|
||||
ident: "blah",
|
||||
},
|
||||
[
|
||||
@27-32 Var {
|
||||
module_name: "",
|
||||
ident: "stuff",
|
||||
},
|
||||
],
|
||||
Space,
|
||||
),
|
||||
),
|
||||
],
|
||||
Space,
|
||||
)
|
|
@ -0,0 +1 @@
|
|||
foo? ( bar? baz) ( blah stuff)
|
|
@ -0,0 +1,17 @@
|
|||
app [main] {
|
||||
cli: "../basic-cli/platform/main.roc",
|
||||
}
|
||||
|
||||
import cli.Stdout
|
||||
|
||||
main =
|
||||
# is this a valid statement?
|
||||
"Foo" |> A.x?
|
||||
|
||||
# what about this?
|
||||
"Bar"
|
||||
|> B.y?
|
||||
{ config: "config" }
|
||||
|
||||
C.z "Bar"
|
||||
|
|
@ -0,0 +1,213 @@
|
|||
Full(
|
||||
FullAst {
|
||||
header: SpacesBefore {
|
||||
before: [],
|
||||
item: App(
|
||||
AppHeader {
|
||||
before_provides: [],
|
||||
provides: [
|
||||
@5-9 ExposedName(
|
||||
"main",
|
||||
),
|
||||
],
|
||||
before_packages: [],
|
||||
packages: @11-55 Collection {
|
||||
items: [
|
||||
@15-52 SpaceBefore(
|
||||
PackageEntry {
|
||||
shorthand: "cli",
|
||||
spaces_after_shorthand: [],
|
||||
platform_marker: None,
|
||||
package_name: @20-52 PackageName(
|
||||
"../basic-cli/platform/main.roc",
|
||||
),
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
],
|
||||
final_comments: [
|
||||
Newline,
|
||||
],
|
||||
},
|
||||
old_imports: None,
|
||||
old_provides_to_new_package: None,
|
||||
},
|
||||
),
|
||||
},
|
||||
defs: Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
Index(2147483649),
|
||||
],
|
||||
regions: [
|
||||
@57-74,
|
||||
@76-220,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 2),
|
||||
Slice(start = 2, length = 2),
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 2, length = 0),
|
||||
Slice(start = 4, length = 2),
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
Newline,
|
||||
Newline,
|
||||
Newline,
|
||||
Newline,
|
||||
Newline,
|
||||
],
|
||||
type_defs: [],
|
||||
value_defs: [
|
||||
ModuleImport(
|
||||
ModuleImport {
|
||||
before_name: [],
|
||||
name: @64-74 ImportedModuleName {
|
||||
package: Some(
|
||||
"cli",
|
||||
),
|
||||
name: ModuleName(
|
||||
"Stdout",
|
||||
),
|
||||
},
|
||||
params: None,
|
||||
alias: None,
|
||||
exposed: None,
|
||||
},
|
||||
),
|
||||
Body(
|
||||
@76-80 Identifier {
|
||||
ident: "main",
|
||||
},
|
||||
@120-220 SpaceBefore(
|
||||
Defs(
|
||||
Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
Index(2147483649),
|
||||
],
|
||||
regions: [
|
||||
@120-133,
|
||||
@162-205,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice(start = 0, length = 3),
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 0, length = 0),
|
||||
Slice(start = 3, length = 0),
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
Newline,
|
||||
LineComment(
|
||||
" what about this?",
|
||||
),
|
||||
],
|
||||
type_defs: [],
|
||||
value_defs: [
|
||||
Stmt(
|
||||
@120-133 BinOps(
|
||||
[
|
||||
(
|
||||
@120-125 Str(
|
||||
PlainLine(
|
||||
"Foo",
|
||||
),
|
||||
),
|
||||
@126-128 Pizza,
|
||||
),
|
||||
],
|
||||
@129-132 TrySuffix {
|
||||
target: Result,
|
||||
expr: Var {
|
||||
module_name: "A",
|
||||
ident: "x",
|
||||
},
|
||||
},
|
||||
),
|
||||
),
|
||||
Stmt(
|
||||
@162-205 BinOps(
|
||||
[
|
||||
(
|
||||
@162-167 Str(
|
||||
PlainLine(
|
||||
"Bar",
|
||||
),
|
||||
),
|
||||
@168-170 Pizza,
|
||||
),
|
||||
],
|
||||
@171-205 Apply(
|
||||
@171-174 TrySuffix {
|
||||
target: Result,
|
||||
expr: Var {
|
||||
module_name: "B",
|
||||
ident: "y",
|
||||
},
|
||||
},
|
||||
[
|
||||
@185-205 SpaceBefore(
|
||||
Record(
|
||||
[
|
||||
@187-203 RequiredValue(
|
||||
@187-193 "config",
|
||||
[],
|
||||
@195-203 Str(
|
||||
PlainLine(
|
||||
"config",
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
],
|
||||
Space,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
},
|
||||
@211-220 SpaceBefore(
|
||||
Apply(
|
||||
@211-214 Var {
|
||||
module_name: "C",
|
||||
ident: "z",
|
||||
},
|
||||
[
|
||||
@215-220 Str(
|
||||
PlainLine(
|
||||
"Bar",
|
||||
),
|
||||
),
|
||||
],
|
||||
Space,
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
LineComment(
|
||||
" is this a valid statement?",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
},
|
||||
},
|
||||
)
|
|
@ -0,0 +1,16 @@
|
|||
app [main] {
|
||||
cli: "../basic-cli/platform/main.roc",
|
||||
}
|
||||
|
||||
import cli.Stdout
|
||||
|
||||
main =
|
||||
# is this a valid statement?
|
||||
"Foo" |> A.x?
|
||||
|
||||
# what about this?
|
||||
"Bar" |> B.y?
|
||||
{ config: "config" }
|
||||
|
||||
C.z "Bar"
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
app [main] {
|
||||
cli: platform "",
|
||||
}
|
||||
|
||||
main =
|
||||
"jq --version"
|
||||
|> Cmd.new
|
||||
|> Cmd.status
|
||||
|> Result.mapErr? UnableToCheckJQVersion
|
|
@ -0,0 +1,134 @@
|
|||
Full(
|
||||
FullAst {
|
||||
header: SpacesBefore {
|
||||
before: [],
|
||||
item: App(
|
||||
AppHeader {
|
||||
before_provides: [
|
||||
Newline,
|
||||
],
|
||||
provides: [
|
||||
@74-78 ExposedName(
|
||||
"main",
|
||||
),
|
||||
],
|
||||
before_packages: [
|
||||
Newline,
|
||||
],
|
||||
packages: @6-44 Collection {
|
||||
items: [
|
||||
@30-37 SpaceBefore(
|
||||
PackageEntry {
|
||||
shorthand: "cli",
|
||||
spaces_after_shorthand: [],
|
||||
platform_marker: Some(
|
||||
[],
|
||||
),
|
||||
package_name: @35-37 PackageName(
|
||||
"",
|
||||
),
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
],
|
||||
final_comments: [
|
||||
Newline,
|
||||
],
|
||||
},
|
||||
old_imports: None,
|
||||
old_provides_to_new_package: None,
|
||||
},
|
||||
),
|
||||
},
|
||||
defs: Defs {
|
||||
tags: [
|
||||
Index(2147483648),
|
||||
],
|
||||
regions: [
|
||||
@88-204,
|
||||
],
|
||||
space_before: [
|
||||
Slice(start = 0, length = 2),
|
||||
],
|
||||
space_after: [
|
||||
Slice(start = 2, length = 1),
|
||||
],
|
||||
spaces: [
|
||||
Newline,
|
||||
Newline,
|
||||
Newline,
|
||||
],
|
||||
type_defs: [],
|
||||
value_defs: [
|
||||
Body(
|
||||
@88-92 Identifier {
|
||||
ident: "main",
|
||||
},
|
||||
@100-204 SpaceBefore(
|
||||
BinOps(
|
||||
[
|
||||
(
|
||||
@100-114 SpaceAfter(
|
||||
Str(
|
||||
PlainLine(
|
||||
"jq --version",
|
||||
),
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
@123-125 Pizza,
|
||||
),
|
||||
(
|
||||
@126-133 SpaceAfter(
|
||||
Var {
|
||||
module_name: "Cmd",
|
||||
ident: "new",
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
@142-144 Pizza,
|
||||
),
|
||||
(
|
||||
@145-155 SpaceAfter(
|
||||
Var {
|
||||
module_name: "Cmd",
|
||||
ident: "status",
|
||||
},
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
@164-166 Pizza,
|
||||
),
|
||||
],
|
||||
@167-204 Apply(
|
||||
@167-180 TrySuffix {
|
||||
target: Result,
|
||||
expr: Var {
|
||||
module_name: "Result",
|
||||
ident: "mapErr",
|
||||
},
|
||||
},
|
||||
[
|
||||
@182-204 Tag(
|
||||
"UnableToCheckJQVersion",
|
||||
),
|
||||
],
|
||||
Space,
|
||||
),
|
||||
),
|
||||
[
|
||||
Newline,
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
},
|
||||
},
|
||||
)
|
|
@ -0,0 +1,12 @@
|
|||
app ""
|
||||
packages {
|
||||
cli: "",
|
||||
}
|
||||
imports []
|
||||
provides [main] to cli
|
||||
|
||||
main =
|
||||
"jq --version"
|
||||
|> Cmd.new
|
||||
|> Cmd.status
|
||||
|> Result.mapErr? UnableToCheckJQVersion
|
|
@ -469,11 +469,16 @@ mod test_snapshots {
|
|||
pass/string_without_escape.expr,
|
||||
pass/sub_var_with_spaces.expr,
|
||||
pass/sub_with_spaces.expr,
|
||||
pass/suffixed.expr,
|
||||
pass/suffixed_multiple_defs.moduledefs,
|
||||
pass/suffixed_nested.expr,
|
||||
pass/suffixed_one_def.full,
|
||||
pass/suffixed_optional_last.full,
|
||||
pass/suffixed_bang.expr,
|
||||
pass/suffixed_bang_multiple_defs.moduledefs,
|
||||
pass/suffixed_bang_nested.expr,
|
||||
pass/suffixed_bang_one_def.full,
|
||||
pass/suffixed_bang_optional_last.full,
|
||||
pass/suffixed_question.expr,
|
||||
pass/suffixed_question_multiple_defs.moduledefs,
|
||||
pass/suffixed_question_nested.expr,
|
||||
pass/suffixed_question_one_def.full,
|
||||
pass/suffixed_question_optional_last.full,
|
||||
pass/tag_pattern.expr,
|
||||
pass/ten_times_eleven.expr,
|
||||
pass/three_arg_closure.expr,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue