Merge branch 'main' into builtin-task

This commit is contained in:
Sam Mohr 2024-07-03 00:42:48 -07:00
commit f61b303a59
No known key found for this signature in database
GPG key ID: EA41D161A3C1BC99
82 changed files with 2661 additions and 5699 deletions

View file

@ -755,28 +755,6 @@ pub fn desugar_expr<'a>(
})
}
// Replace an empty final def with a `Task.ok {}`
EmptyDefsFinal => {
let mut apply_args: Vec<&'a Loc<Expr<'a>>> = Vec::new_in(arena);
apply_args
.push(arena.alloc(Loc::at(loc_expr.region, Expr::Record(Collection::empty()))));
arena.alloc(Loc::at(
loc_expr.region,
Expr::Apply(
arena.alloc(Loc::at(
loc_expr.region,
Expr::Var {
module_name: ModuleName::TASK,
ident: "ok",
},
)),
arena.alloc(apply_args),
CalledVia::BangSuffix,
),
))
}
// note this only exists after desugaring
LowLevelDbg(_, _, _) => loc_expr,
}

View file

@ -621,9 +621,6 @@ pub fn canonicalize_expr<'a>(
use Expr::*;
let (expr, output) = match expr {
&ast::Expr::EmptyDefsFinal => {
internal_error!("EmptyDefsFinal should have been desugared")
}
&ast::Expr::Num(str) => {
let answer = num_expr_from_result(var_store, finish_parsing_num(str), region, env);
@ -2392,8 +2389,7 @@ pub fn is_valid_interpolation(expr: &ast::Expr<'_>) -> bool {
| ast::Expr::Backpassing(_, _, _)
| ast::Expr::SpaceBefore(_, _)
| ast::Expr::Str(StrLiteral::Block(_))
| ast::Expr::SpaceAfter(_, _)
| ast::Expr::EmptyDefsFinal => false,
| ast::Expr::SpaceAfter(_, _) => false,
// These can contain subexpressions, so we need to recursively check those
ast::Expr::Str(StrLiteral::Line(segments)) => {
segments.iter().all(|segment| match segment {

View file

@ -207,7 +207,7 @@ pub struct ListPatterns {
/// [ .., A, B ] -> patterns = [A, B], rest = 0
/// [ A, .., B ] -> patterns = [A, B], rest = 1
/// [ A, B, .. ] -> patterns = [A, B], rest = 2
pub opt_rest: Option<(usize, Option<Symbol>)>,
pub opt_rest: Option<(usize, Option<Loc<Symbol>>)>,
}
impl ListPatterns {
@ -793,7 +793,8 @@ pub fn canonicalize_pattern<'a>(
pattern_as.identifier.value,
) {
Ok(symbol) => {
rest_name = Some(symbol);
rest_name =
Some(Loc::at(pattern_as.identifier.region, symbol));
}
Err(pattern) => {
opt_erroneous = Some(pattern);
@ -997,6 +998,10 @@ impl<'a> BindingsFromPattern<'a> {
| OpaqueNotInScope(..) => (),
List { patterns, .. } => {
stack.extend(patterns.patterns.iter().rev().map(Pattern));
if let Some((_, Some(rest_sym))) = &patterns.opt_rest {
return Some((rest_sym.value, rest_sym.region));
}
}
}
}

View file

@ -129,46 +129,7 @@ pub fn unwrap_suffixed_expression<'a>(
internal_error!("BinOps should have been desugared in desugar_expr");
}
Expr::LowLevelDbg(dbg_src, arg, rest) => {
if is_expr_suffixed(&arg.value) {
// we cannot unwrap a suffixed expression within dbg
// e.g. dbg (foo! "bar")
return Err(EUnwrapped::Malformed);
}
match unwrap_suffixed_expression(arena, rest, maybe_def_pat) {
Ok(unwrapped_expr) => {
let new_dbg = arena.alloc(Loc::at(
loc_expr.region,
LowLevelDbg(dbg_src, arg, unwrapped_expr),
));
return Ok(new_dbg);
}
Err(EUnwrapped::UnwrappedDefExpr(unwrapped_expr)) => {
let new_dbg = arena.alloc(Loc::at(
loc_expr.region,
LowLevelDbg(dbg_src, arg, unwrapped_expr),
));
Err(EUnwrapped::UnwrappedDefExpr(new_dbg))
}
Err(EUnwrapped::UnwrappedSubExpr {
sub_arg: unwrapped_expr,
sub_pat,
sub_new,
}) => {
let new_dbg = arena.alloc(Loc::at(
loc_expr.region,
LowLevelDbg(dbg_src, arg, unwrapped_expr),
));
Err(EUnwrapped::UnwrappedSubExpr {
sub_arg: new_dbg,
sub_pat,
sub_new,
})
}
Err(EUnwrapped::Malformed) => Err(EUnwrapped::Malformed),
}
}
Expr::LowLevelDbg(..) => unwrap_low_level_dbg(arena, loc_expr, maybe_def_pat),
Expr::Expect(condition, continuation) => {
if is_expr_suffixed(&condition.value) {
@ -658,7 +619,8 @@ pub fn unwrap_suffixed_expression_defs_help<'a>(
let after_empty = split_defs.after.is_empty();
if before_empty && after_empty {
// NIL before, NIL after -> SINGLE DEF
let next_expr = match unwrap_suffixed_expression(arena,loc_ret,maybe_def_pat) {
// 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 }) => {
// We need to apply Task.ok here as the defs final expression was unwrapped
@ -688,7 +650,8 @@ pub fn unwrap_suffixed_expression_defs_help<'a>(
return unwrap_suffixed_expression(arena, apply_task_await(arena,def_expr.region,unwrapped_expr,def_pattern,next_expr), maybe_def_pat);
} else if after_empty {
// SOME before, NIL after -> LAST DEF
match unwrap_suffixed_expression(arena,loc_ret,maybe_def_pat){
// 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);
let new_defs = arena.alloc(Loc::at(loc_expr.region,Defs(arena.alloc(split_defs.before), applied_task_await)));
@ -767,6 +730,87 @@ pub fn unwrap_suffixed_expression_defs_help<'a>(
}
}
fn unwrap_low_level_dbg<'a>(
arena: &'a Bump,
loc_expr: &'a Loc<Expr<'a>>,
maybe_def_pat: Option<&'a Loc<Pattern<'a>>>,
) -> Result<&'a Loc<Expr<'a>>, EUnwrapped<'a>> {
match loc_expr.value {
LowLevelDbg(dbg_src, arg, rest) => {
if is_expr_suffixed(&arg.value) {
return match unwrap_suffixed_expression(arena, arg, maybe_def_pat) {
Ok(unwrapped_expr) => {
let new_dbg = arena.alloc(Loc::at(
loc_expr.region,
LowLevelDbg(dbg_src, unwrapped_expr, rest),
));
unwrap_low_level_dbg(arena, new_dbg, maybe_def_pat)
}
Err(EUnwrapped::UnwrappedSubExpr {
sub_arg,
sub_pat,
sub_new,
}) => {
let new_dbg = arena.alloc(Loc::at(
loc_expr.region,
LowLevelDbg(dbg_src, sub_new, rest),
));
unwrap_suffixed_expression(
arena,
apply_task_await(arena, new_dbg.region, sub_arg, sub_pat, new_dbg),
maybe_def_pat,
)
}
Err(EUnwrapped::UnwrappedDefExpr(..)) => {
internal_error!(
"unreachable, arg of LowLevelDbg should generate UnwrappedSubExpr instead"
);
}
Err(EUnwrapped::Malformed) => Err(EUnwrapped::Malformed),
};
}
match unwrap_suffixed_expression(arena, rest, maybe_def_pat) {
Ok(unwrapped_expr) => {
let new_dbg = arena.alloc(Loc::at(
loc_expr.region,
LowLevelDbg(dbg_src, arg, unwrapped_expr),
));
Ok(&*new_dbg)
}
Err(EUnwrapped::UnwrappedDefExpr(unwrapped_expr)) => {
let new_dbg = arena.alloc(Loc::at(
loc_expr.region,
LowLevelDbg(dbg_src, arg, unwrapped_expr),
));
Err(EUnwrapped::UnwrappedDefExpr(new_dbg))
}
Err(EUnwrapped::UnwrappedSubExpr {
sub_arg: unwrapped_expr,
sub_pat,
sub_new,
}) => {
let new_dbg = arena.alloc(Loc::at(
loc_expr.region,
LowLevelDbg(dbg_src, arg, unwrapped_expr),
));
Err(EUnwrapped::UnwrappedSubExpr {
sub_arg: new_dbg,
sub_pat,
sub_new,
})
}
Err(EUnwrapped::Malformed) => Err(EUnwrapped::Malformed),
}
}
_ => internal_error!(
"unreachable, expected a LowLevelDbg node to be passed into unwrap_low_level_dbg"
),
}
}
/// Helper for `Task.await (loc_arg) \loc_pat -> loc_new`
pub fn apply_task_await<'a>(
arena: &'a Bump,