basic backpassing

This commit is contained in:
Folkert 2021-03-05 22:33:34 +01:00
parent 4a89ecca2a
commit 42654debbf
7 changed files with 252 additions and 41 deletions

View file

@ -31,6 +31,110 @@ fn new_op_expr<'a>(
}
}
fn desugar_defs<'a>(
arena: &'a Bump,
region: Region,
defs: &'a [&'a Located<Def<'a>>],
mut loc_ret: &'a Located<Expr<'a>>,
) -> &'a Located<Expr<'a>> {
use roc_parse::ast::Def::*;
let mut desugared_defs = Vec::with_capacity_in(defs.len(), arena);
let mut it = defs.iter();
'outer: while let Some(loc_def) = it.next() {
let mut def = &loc_def.value;
let desugared_def = 'inner: loop {
match def {
Body(loc_pattern, loc_expr) | Nested(Body(loc_pattern, loc_expr)) => {
break 'inner Body(loc_pattern, desugar_expr(arena, loc_expr));
}
Backpassing(loc_patterns, loc_expr)
| Nested(Backpassing(loc_patterns, loc_expr)) => {
// first desugar the body, because it may contain `|>`
let desugared = desugar_expr(arena, loc_expr);
match &desugared.value {
Expr::Apply(function, arguments, called_via) => {
// now what?
let body = desugar_defs(arena, region, it.as_slice(), loc_ret);
let closure = Expr::Closure(loc_patterns, body);
// &'a [&'a Loc<Expr<'a>>]
let mut new_arguments: Vec<'a, &'a Located<Expr<'a>>> =
Vec::with_capacity_in(arguments.len() + 1, arena);
new_arguments.extend(arguments.iter());
new_arguments.push(arena.alloc(Located::at_zero(closure)));
let expr =
Expr::Apply(function, new_arguments.into_bump_slice(), *called_via);
loc_ret = arena.alloc(Located::at(region, expr));
break 'outer;
}
_ => todo!(),
}
}
SpaceBefore(inner_def, _)
| SpaceAfter(inner_def, _)
| Nested(SpaceBefore(inner_def, _))
| Nested(SpaceAfter(inner_def, _)) => {
def = inner_def;
continue;
}
Nested(Nested(inner_def)) => {
def = inner_def;
continue;
}
alias @ Alias { .. } => break 'inner Nested(alias),
Nested(alias @ Alias { .. }) => break 'inner Nested(alias),
ann @ Annotation(_, _) => break 'inner Nested(ann),
Nested(ann @ Annotation(_, _)) => break 'inner Nested(ann),
AnnotatedBody {
ann_pattern,
ann_type,
comment,
body_pattern,
body_expr,
}
| Nested(AnnotatedBody {
ann_pattern,
ann_type,
comment,
body_pattern,
body_expr,
}) => {
break 'inner AnnotatedBody {
ann_pattern,
ann_type,
comment: *comment,
body_pattern: *body_pattern,
body_expr: desugar_expr(arena, body_expr),
};
}
Nested(NotYetImplemented(s)) => todo!("{}", s),
NotYetImplemented(s) => todo!("{}", s),
}
};
let loc_def = Located {
value: desugared_def,
region: loc_def.region,
};
desugared_defs.push(&*arena.alloc(loc_def));
}
let desugared_defs = desugared_defs.into_bump_slice();
arena.alloc(Located {
value: Defs(desugared_defs, desugar_expr(arena, loc_ret)),
region,
})
}
pub fn desugar_def<'a>(arena: &'a Bump, def: &'a Def<'a>) -> Def<'a> {
use roc_parse::ast::Def::*;
@ -38,6 +142,9 @@ pub fn desugar_def<'a>(arena: &'a Bump, def: &'a Def<'a>) -> Def<'a> {
Body(loc_pattern, loc_expr) | Nested(Body(loc_pattern, loc_expr)) => {
Body(loc_pattern, desugar_expr(arena, loc_expr))
}
Backpassing(_loc_patterns, _loc_expr) | Nested(Backpassing(_loc_patterns, _loc_expr)) => {
panic!("invalid at this position");
}
SpaceBefore(def, _)
| SpaceAfter(def, _)
| Nested(SpaceBefore(def, _))
@ -173,23 +280,7 @@ pub fn desugar_expr<'a>(arena: &'a Bump, loc_expr: &'a Located<Expr<'a>>) -> &'a
}
BinOp(_) | Nested(BinOp(_)) => desugar_bin_op(arena, loc_expr),
Defs(defs, loc_ret) | Nested(Defs(defs, loc_ret)) => {
let mut desugared_defs = Vec::with_capacity_in(defs.len(), arena);
for loc_def in defs.iter() {
let loc_def = Located {
value: desugar_def(arena, &loc_def.value),
region: loc_def.region,
};
desugared_defs.push(&*arena.alloc(loc_def));
}
let desugared_defs = desugared_defs.into_bump_slice();
arena.alloc(Located {
value: Defs(desugared_defs, desugar_expr(arena, loc_ret)),
region: loc_expr.region,
})
desugar_defs(arena, loc_expr.region, *defs, loc_ret)
}
Apply(loc_fn, loc_args, called_via) | Nested(Apply(loc_fn, loc_args, called_via)) => {
let mut desugared_args = Vec::with_capacity_in(loc_args.len(), arena);