WIP partial implementation for desugar_defs_node_suffixed

This commit is contained in:
Luke Boswell 2024-03-19 12:57:30 +11:00
parent 3b2e9e36b8
commit 406ffdffab
No known key found for this signature in database
GPG key ID: F6DB3C9DB47377B0
4 changed files with 105 additions and 7 deletions

View file

@ -131,7 +131,7 @@ fn desugar_value_def<'a>(
} }
} }
pub fn desugar_defs<'a>( pub fn desugar_defs_node_values<'a>(
arena: &'a Bump, arena: &'a Bump,
defs: &mut roc_parse::ast::Defs<'a>, defs: &mut roc_parse::ast::Defs<'a>,
src: &'a str, src: &'a str,
@ -143,6 +143,84 @@ pub fn desugar_defs<'a>(
} }
} }
fn desugar_defs_node_suffixed<'a>(
_arena: &'a Bump,
_src: &'a str,
_line_info: &mut Option<LineInfo>,
_module_path: &str,
loc_expr: &'a Loc<Expr<'a>>,
) -> &'a Loc<Expr<'a>> {
match loc_expr.value {
Defs(defs, _loc_ret) => {
match search_suffixed_defs(&defs.value_defs, 0) {
FindSuffixedDefs::NoneFound => loc_expr,
FindSuffixedDefs::FirstSuffixedAtIndex(index) => {
if defs.value_defs.len() == 1 {
assert!(index == 0, "we have only one value_def and so it must be Suffixed ");
// We have only one value_def and it must be Suffixed
// replace Defs with an Apply(Task.await) and Closure of loc_return
dbg!("We have only one value_def and it must be Suffixed", loc_expr.value);
loc_expr
} else if index == 0 {
assert!(defs.value_defs.len() > 1, "we know we have other Defs that will need to be considered");
// We have a Suffixed in first index, and also other nodes in Defs
// pop the first Suffixed and recurse on Defs (without first) to handle any other Suffixed
// the result will be wrapped in an Apply(Task.await) and Closure
dbg!("We have a Suffixed in first index, and also other nodes in Defs", loc_expr.value);
loc_expr
} else {
// The first Suffixed is in the middle of our Defs
// We will keep the value_defs before the Suffixed in our Defs node
// We take the value_defs after the Suffixed and create a new Defs node using the current loc_return
// Then recurse on the new Defs node, wrap the result in an Apply(Task.await) and Closure,
// which will become the new loc_return
dbg!("The first Suffixed is in the middle of our Defs", loc_expr.value);
loc_expr
}
}
}
},
_ => unreachable!("should only be passed a Defs node as it is called from within desugar_expr for Defs"),
}
}
enum FindSuffixedDefs {
NoneFound,
FirstSuffixedAtIndex(usize),
}
fn search_suffixed_defs<'a>(value_defs: &std::vec::Vec<ValueDef<'a>>, index: usize) -> FindSuffixedDefs {
use roc_parse::ast::ValueDef::Body;
if index < value_defs.len() {
match value_defs.get(index) {
Some(Body(_, expr)) =>
match expr.value {
Apply(sub_expr,_,_) => {
match sub_expr.value {
roc_parse::ast::Expr::Suffixed(_) => {
FindSuffixedDefs::FirstSuffixedAtIndex(index)
}
_ => search_suffixed_defs(value_defs, index + 1),
}
}
_ => search_suffixed_defs(value_defs, index + 1),
}
_ => search_suffixed_defs(value_defs, index + 1),
}
} else {
FindSuffixedDefs::NoneFound
}
}
/// Reorder the expression tree based on operator precedence and associativity rules, /// Reorder the expression tree based on operator precedence and associativity rules,
/// then replace the BinOp nodes with Apply nodes. Also drop SpaceBefore and SpaceAfter nodes. /// then replace the BinOp nodes with Apply nodes. Also drop SpaceBefore and SpaceAfter nodes.
pub fn desugar_expr<'a>( pub fn desugar_expr<'a>(
@ -362,12 +440,19 @@ pub fn desugar_expr<'a>(
module_path, module_path,
), ),
Defs(defs, loc_ret) => { Defs(defs, loc_ret) => {
let mut defs = (*defs).clone();
desugar_defs(arena, &mut defs, src, line_info, module_path);
let mut defs = (*defs).clone();
desugar_defs_node_values(arena, &mut defs, src, line_info, module_path);
let loc_ret = desugar_expr(arena, loc_ret, src, line_info, module_path); let loc_ret = desugar_expr(arena, loc_ret, src, line_info, module_path);
arena.alloc(Loc::at(loc_expr.region, Defs(arena.alloc(defs), loc_ret))) // Desugar any Suffixed nodes
desugar_defs_node_suffixed(
arena,
src,
line_info,
module_path,
arena.alloc(Loc::at(loc_expr.region, Defs(arena.alloc(defs), loc_ret))),
)
} }
Apply(loc_fn, loc_args, called_via) => { Apply(loc_fn, loc_args, called_via) => {
let mut desugared_args = Vec::with_capacity_in(loc_args.len(), arena); let mut desugared_args = Vec::with_capacity_in(loc_args.len(), arena);
@ -619,7 +704,14 @@ pub fn desugar_expr<'a>(
}) })
} }
LowLevelDbg(_, _, _) => unreachable!("Only exists after desugaring"), LowLevelDbg(_, _, _) => unreachable!("Only exists after desugaring"),
Suffixed(_) => todo!(), Suffixed(expr) => {
// This is desugared in Defs, leave the node here
// Any nodes that don't get desugared will be caught by canonicalize_expr
arena.alloc(Loc {
value: Suffixed(expr),
region: loc_expr.region,
})
}
} }
} }

View file

@ -1441,7 +1441,12 @@ pub fn canonicalize_expr<'a>(
bad_expr bad_expr
); );
} }
ast::Expr::Suffixed(_) => todo!(), bad_expr @ ast::Expr::Suffixed(_) => {
internal_error!(
"A suffixed expression did not get desugared somehow: {:#?}",
bad_expr
);
},
}; };
// At the end, diff used_idents and defined_idents to see which were unused. // At the end, diff used_idents and defined_idents to see which were unused.

View file

@ -312,7 +312,7 @@ pub fn canonicalize_module_defs<'a>(
// visited a BinOp node we'd recursively try to apply this to each of its nested // visited a BinOp node we'd recursively try to apply this to each of its nested
// operators, and then again on *their* nested operators, ultimately applying the // operators, and then again on *their* nested operators, ultimately applying the
// rules multiple times unnecessarily. // rules multiple times unnecessarily.
crate::desugar::desugar_defs(arena, loc_defs, src, &mut None, module_path); crate::desugar::desugar_defs_node_values(arena, loc_defs, src, &mut None, module_path);
let mut rigid_variables = RigidVariables::default(); let mut rigid_variables = RigidVariables::default();

View file

@ -114,6 +114,7 @@ impl ModuleName {
pub const DECODE: &'static str = "Decode"; pub const DECODE: &'static str = "Decode";
pub const HASH: &'static str = "Hash"; pub const HASH: &'static str = "Hash";
pub const INSPECT: &'static str = "Inspect"; pub const INSPECT: &'static str = "Inspect";
pub const TASK: &'static str = "Task";
pub const JSON: &'static str = "TotallyNotJson"; pub const JSON: &'static str = "TotallyNotJson";
pub fn as_str(&self) -> &str { pub fn as_str(&self) -> &str {