enable recursive definitions at the top-level

This commit is contained in:
Folkert 2020-10-14 01:06:17 +02:00
parent 2da2c25d32
commit 6aaba98d31

View file

@ -2166,98 +2166,27 @@ fn build_pending_specializations<'a>(
// Add modules' decls to Procs // Add modules' decls to Procs
for decl in decls { for decl in decls {
use roc_can::def::Declaration::*; use roc_can::def::Declaration::*;
use roc_can::expr::Expr::*;
use roc_can::pattern::Pattern::*;
match decl { match decl {
Declare(def) | Builtin(def) => match def.loc_pattern.value { Declare(def) | Builtin(def) => add_def_to_module(
Identifier(symbol) => { &mut layout_cache,
let is_exposed = exposed_to_host.contains(&symbol); &mut procs,
&mut mono_env,
match def.loc_expr.value { def,
Closure { &exposed_to_host,
function_type: annotation, false,
return_type: ret_var, ),
arguments: loc_args, DeclareRec(defs) => {
loc_body, for def in defs {
.. add_def_to_module(
} => { &mut layout_cache,
// this is a non-recursive declaration &mut procs,
let is_tail_recursive = false; &mut mono_env,
// If this is an exposed symbol, we need to def,
// register it as such. Otherwise, since it &exposed_to_host,
// never gets called by Roc code, it will never true,
// get specialized! )
if is_exposed {
let mut pattern_vars = bumpalo::collections::Vec::with_capacity_in(
loc_args.len(),
arena,
);
for (var, _) in loc_args.iter() {
pattern_vars.push(*var);
}
let layout = match layout_cache.from_var(
mono_env.arena,
annotation,
mono_env.subs,
) {
Ok(l) => l,
Err(err) => {
// a host-exposed function is not monomorphized
todo!("The host-exposed function {:?} does not have a valid layout (e.g. maybe the function wasn't monomorphic): {:?}", symbol, err)
}
};
procs.insert_exposed(symbol, layout, mono_env.subs, annotation);
}
procs.insert_named(
&mut mono_env,
&mut layout_cache,
symbol,
annotation,
loc_args,
*loc_body,
is_tail_recursive,
ret_var,
);
}
body => {
// If this is an exposed symbol, we need to
// register it as such. Otherwise, since it
// never gets called by Roc code, it will never
// get specialized!
if is_exposed {
let annotation = def.expr_var;
let layout = layout_cache.from_var(mono_env.arena, annotation, mono_env.subs).unwrap_or_else(|err|
todo!("TODO gracefully handle the situation where we expose a function to the host which doesn't have a valid layout (e.g. maybe the function wasn't monomorphic): {:?}", err)
);
procs.insert_exposed(symbol, layout, mono_env.subs, annotation);
}
let proc = PartialProc {
annotation: def.expr_var,
// This is a 0-arity thunk, so it has no arguments.
pattern_symbols: &[],
body,
// This is a 0-arity thunk, so it cannot be recursive
is_self_recursive: false,
};
procs.partial_procs.insert(symbol, proc);
procs.module_thunks.insert(symbol);
}
};
} }
other => {
todo!("TODO gracefully handle Declare({:?})", other);
}
},
DeclareRec(_defs) => {
todo!("TODO support DeclareRec");
} }
InvalidCycle(_loc_idents, _regions) => { InvalidCycle(_loc_idents, _regions) => {
todo!("TODO handle InvalidCycle"); todo!("TODO handle InvalidCycle");
@ -2278,6 +2207,103 @@ fn build_pending_specializations<'a>(
} }
} }
fn add_def_to_module<'a>(
layout_cache: &mut LayoutCache<'a>,
procs: &mut Procs<'a>,
mono_env: &mut roc_mono::ir::Env<'a, '_>,
def: roc_can::def::Def,
exposed_to_host: &MutSet<Symbol>,
is_recursive: bool,
) {
use roc_can::expr::Expr::*;
use roc_can::pattern::Pattern::*;
match def.loc_pattern.value {
Identifier(symbol) => {
let is_exposed = exposed_to_host.contains(&symbol);
match def.loc_expr.value {
Closure {
function_type: annotation,
return_type: ret_var,
arguments: loc_args,
loc_body,
..
} => {
// If this is an exposed symbol, we need to
// register it as such. Otherwise, since it
// never gets called by Roc code, it will never
// get specialized!
if is_exposed {
let mut pattern_vars = bumpalo::collections::Vec::with_capacity_in(
loc_args.len(),
mono_env.arena,
);
for (var, _) in loc_args.iter() {
pattern_vars.push(*var);
}
let layout = match layout_cache.from_var(
mono_env.arena,
annotation,
mono_env.subs,
) {
Ok(l) => l,
Err(err) => {
// a host-exposed function is not monomorphized
todo!("The host-exposed function {:?} does not have a valid layout (e.g. maybe the function wasn't monomorphic): {:?}", symbol, err)
}
};
procs.insert_exposed(symbol, layout, mono_env.subs, annotation);
}
procs.insert_named(
mono_env,
layout_cache,
symbol,
annotation,
loc_args,
*loc_body,
is_recursive,
ret_var,
);
}
body => {
// If this is an exposed symbol, we need to
// register it as such. Otherwise, since it
// never gets called by Roc code, it will never
// get specialized!
if is_exposed {
let annotation = def.expr_var;
let layout = layout_cache.from_var(mono_env.arena, annotation, mono_env.subs).unwrap_or_else(|err|
todo!("TODO gracefully handle the situation where we expose a function to the host which doesn't have a valid layout (e.g. maybe the function wasn't monomorphic): {:?}", err)
);
procs.insert_exposed(symbol, layout, mono_env.subs, annotation);
}
let proc = PartialProc {
annotation: def.expr_var,
// This is a 0-arity thunk, so it has no arguments.
pattern_symbols: &[],
body,
// This is a 0-arity thunk, so it cannot be recursive
is_self_recursive: false,
};
procs.partial_procs.insert(symbol, proc);
procs.module_thunks.insert(symbol);
}
};
}
other => {
todo!("TODO gracefully handle Declare({:?})", other);
}
}
}
fn run_task<'a>( fn run_task<'a>(
task: BuildTask<'a>, task: BuildTask<'a>,
arena: &'a Bump, arena: &'a Bump,