turn toplevel expects into inline expects

This commit is contained in:
Folkert 2022-07-10 19:17:51 +02:00
parent 3b60acb938
commit 5df489ba23
No known key found for this signature in database
GPG Key ID: 1F17F6FFD112B97C
3 changed files with 60 additions and 3 deletions

View File

@ -10,7 +10,7 @@ use crate::num::{
use crate::pattern::{canonicalize_pattern, BindingsFromPattern, Pattern};
use crate::procedure::References;
use crate::scope::Scope;
use roc_collections::soa::Index;
use roc_collections::soa::{Index, Slice};
use roc_collections::{SendMap, VecMap, VecSet};
use roc_error_macros::internal_error;
use roc_module::called_via::CalledVia;
@ -2393,3 +2393,56 @@ fn get_lookup_symbols(expr: &Expr, var_store: &mut VarStore) -> Vec<(Symbol, Var
symbols
}
pub fn convert_toplevel_expect(mut loc_expr: Loc<Expr>) -> Loc<Expr> {
enum StoredDef {
NonRecursive(Region, Box<Def>),
Recursive(Region, Vec<Def>, IllegalCycleMark),
}
let mut stack = vec![];
let mut lookups_in_cond = vec![];
loop {
match loc_expr.value {
Expr::LetNonRec(boxed_def, remainder) => {
lookups_in_cond.extend(boxed_def.pattern_vars.iter().map(|(a, b)| (*a, *b)));
stack.push(StoredDef::NonRecursive(loc_expr.region, boxed_def));
loc_expr = *remainder;
}
Expr::LetRec(defs, remainder, mark) => {
for def in &defs {
lookups_in_cond.extend(def.pattern_vars.iter().map(|(a, b)| (*a, *b)));
}
stack.push(StoredDef::Recursive(loc_expr.region, defs, mark));
loc_expr = *remainder;
}
_ => break,
}
}
let expect_region = loc_expr.region;
let expect = Expr::Expect {
loc_condition: Box::new(loc_expr),
loc_continuation: Box::new(Loc::at_zero(Expr::EmptyRecord)),
lookups_in_cond,
};
let mut loc_expr = Loc::at(expect_region, expect);
for stored in stack {
match stored {
StoredDef::NonRecursive(region, boxed_def) => {
loc_expr = Loc::at(region, Expr::LetNonRec(boxed_def, Box::new(loc_expr)));
}
StoredDef::Recursive(region, defs, illegal_cycle_mark) => {
let let_rec = Expr::LetRec(defs, Box::new(loc_expr), illegal_cycle_mark);
loc_expr = Loc::at(region, let_rec);
}
}
}
loc_expr
}

View File

@ -4190,7 +4190,7 @@ pub fn build_procedures_expose_expects<'a, 'ctx, 'env>(
let expects: Vec<_> = procedures
.keys()
.filter_map(|(symbol, proc_layout)| {
if proc_layout.arguments.is_empty() && proc_layout.result == Layout::bool() {
if proc_layout.arguments.is_empty() && proc_layout.result == Layout::UNIT {
Some(*symbol)
} else {
None
@ -4210,7 +4210,7 @@ pub fn build_procedures_expose_expects<'a, 'ctx, 'env>(
let top_level = ProcLayout {
arguments: &[],
result: Layout::bool(),
result: Layout::UNIT,
captures_niche,
};

View File

@ -4766,6 +4766,8 @@ fn build_pending_specializations<'a>(
// mark this symbol as a top-level thunk before any other work on the procs
module_thunks.push(symbol);
let expr_var = Variable::EMPTY_RECORD;
let is_host_exposed = true;
// If this is an exposed symbol, we need to
@ -4805,6 +4807,8 @@ fn build_pending_specializations<'a>(
);
}
let body = roc_can::expr::convert_toplevel_expect(body);
let proc = PartialProc {
annotation: expr_var,
// This is a 0-arity thunk, so it has no arguments.