mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 00:01:16 +00:00
enable recursive definitions at the top-level
This commit is contained in:
parent
2da2c25d32
commit
6aaba98d31
1 changed files with 115 additions and 89 deletions
|
@ -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,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue