mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 16:44:33 +00:00
use HostSpecializations from file.rs
This commit is contained in:
parent
5d9d2b7fea
commit
74f073b3c6
2 changed files with 13 additions and 143 deletions
|
@ -19,8 +19,7 @@ use roc_module::symbol::{
|
||||||
Symbol,
|
Symbol,
|
||||||
};
|
};
|
||||||
use roc_mono::ir::{
|
use roc_mono::ir::{
|
||||||
CapturedSymbols, EntryPoint, ExternalSpecializations, PartialProc, PendingSpecialization, Proc,
|
CapturedSymbols, EntryPoint, ExternalSpecializations, PartialProc, Proc, ProcLayout, Procs,
|
||||||
ProcLayout, Procs,
|
|
||||||
};
|
};
|
||||||
use roc_mono::layout::{Layout, LayoutCache, LayoutProblem};
|
use roc_mono::layout::{Layout, LayoutCache, LayoutProblem};
|
||||||
use roc_parse::ast::{self, StrLiteral, TypeAnnotation};
|
use roc_parse::ast::{self, StrLiteral, TypeAnnotation};
|
||||||
|
@ -3957,7 +3956,7 @@ fn make_specializations<'a>(
|
||||||
&mut mono_env,
|
&mut mono_env,
|
||||||
procs,
|
procs,
|
||||||
specializations_we_must_make,
|
specializations_we_must_make,
|
||||||
procs_base.specializations_for_host,
|
procs_base.host_specializations,
|
||||||
&mut layout_cache,
|
&mut layout_cache,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -3989,27 +3988,11 @@ struct ProcsBase<'a> {
|
||||||
partial_procs: BumpMap<Symbol, PartialProc<'a>>,
|
partial_procs: BumpMap<Symbol, PartialProc<'a>>,
|
||||||
module_thunks: &'a [Symbol],
|
module_thunks: &'a [Symbol],
|
||||||
/// A host-exposed function must be specialized; it's a seed for subsequent specializations
|
/// A host-exposed function must be specialized; it's a seed for subsequent specializations
|
||||||
specializations_for_host: BumpMap<Symbol, MutMap<ProcLayout<'a>, PendingSpecialization<'a>>>,
|
host_specializations: roc_mono::ir::HostSpecializations,
|
||||||
runtime_errors: BumpMap<Symbol, &'a str>,
|
runtime_errors: BumpMap<Symbol, &'a str>,
|
||||||
imported_module_thunks: &'a [Symbol],
|
imported_module_thunks: &'a [Symbol],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ProcsBase<'a> {
|
|
||||||
fn add_specialization_for_host(
|
|
||||||
&mut self,
|
|
||||||
symbol: Symbol,
|
|
||||||
layout: ProcLayout<'a>,
|
|
||||||
pending: PendingSpecialization<'a>,
|
|
||||||
) {
|
|
||||||
let all_pending = self
|
|
||||||
.specializations_for_host
|
|
||||||
.entry(symbol)
|
|
||||||
.or_insert_with(|| HashMap::with_capacity_and_hasher(1, default_hasher()));
|
|
||||||
|
|
||||||
all_pending.insert(layout, pending);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn build_pending_specializations<'a>(
|
fn build_pending_specializations<'a>(
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
|
@ -4031,7 +4014,7 @@ fn build_pending_specializations<'a>(
|
||||||
let mut procs_base = ProcsBase {
|
let mut procs_base = ProcsBase {
|
||||||
partial_procs: BumpMap::default(),
|
partial_procs: BumpMap::default(),
|
||||||
module_thunks: &[],
|
module_thunks: &[],
|
||||||
specializations_for_host: BumpMap::default(),
|
host_specializations: roc_mono::ir::HostSpecializations::new(),
|
||||||
runtime_errors: BumpMap::default(),
|
runtime_errors: BumpMap::default(),
|
||||||
imported_module_thunks,
|
imported_module_thunks,
|
||||||
};
|
};
|
||||||
|
@ -4138,41 +4121,12 @@ fn add_def_to_module<'a>(
|
||||||
// never gets called by Roc code, it will never
|
// never gets called by Roc code, it will never
|
||||||
// get specialized!
|
// get specialized!
|
||||||
if is_exposed {
|
if is_exposed {
|
||||||
let layout = match layout_cache.raw_from_var(
|
procs.host_specializations.insert_host_exposed(
|
||||||
mono_env.arena,
|
|
||||||
annotation,
|
|
||||||
mono_env.subs,
|
|
||||||
) {
|
|
||||||
Ok(l) => l,
|
|
||||||
Err(LayoutProblem::Erroneous) => {
|
|
||||||
let message = "top level function has erroneous type";
|
|
||||||
procs.runtime_errors.insert(symbol, message);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Err(LayoutProblem::UnresolvedTypeVar(v)) => {
|
|
||||||
let message = format!(
|
|
||||||
"top level function has unresolved type variable {:?}",
|
|
||||||
v
|
|
||||||
);
|
|
||||||
procs
|
|
||||||
.runtime_errors
|
|
||||||
.insert(symbol, mono_env.arena.alloc(message));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let pending = PendingSpecialization::from_exposed_function(
|
|
||||||
mono_env.arena,
|
|
||||||
mono_env.subs,
|
mono_env.subs,
|
||||||
|
symbol,
|
||||||
def.annotation,
|
def.annotation,
|
||||||
annotation,
|
annotation,
|
||||||
);
|
);
|
||||||
|
|
||||||
procs.add_specialization_for_host(
|
|
||||||
symbol,
|
|
||||||
ProcLayout::from_raw(mono_env.arena, layout),
|
|
||||||
pending,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let partial_proc = PartialProc::from_named_function(
|
let partial_proc = PartialProc::from_named_function(
|
||||||
|
@ -4192,51 +4146,23 @@ fn add_def_to_module<'a>(
|
||||||
// mark this symbols as a top-level thunk before any other work on the procs
|
// mark this symbols as a top-level thunk before any other work on the procs
|
||||||
module_thunks.push(symbol);
|
module_thunks.push(symbol);
|
||||||
|
|
||||||
|
let annotation = def.expr_var;
|
||||||
|
|
||||||
// If this is an exposed symbol, we need to
|
// If this is an exposed symbol, we need to
|
||||||
// register it as such. Otherwise, since it
|
// register it as such. Otherwise, since it
|
||||||
// never gets called by Roc code, it will never
|
// never gets called by Roc code, it will never
|
||||||
// get specialized!
|
// get specialized!
|
||||||
if is_exposed {
|
if is_exposed {
|
||||||
let annotation = def.expr_var;
|
procs.host_specializations.insert_host_exposed(
|
||||||
|
|
||||||
let top_level = match layout_cache.from_var(
|
|
||||||
mono_env.arena,
|
|
||||||
annotation,
|
|
||||||
mono_env.subs,
|
|
||||||
) {
|
|
||||||
Ok(l) => {
|
|
||||||
// remember, this is a 0-argument thunk
|
|
||||||
ProcLayout::new(mono_env.arena, &[], l)
|
|
||||||
}
|
|
||||||
Err(LayoutProblem::Erroneous) => {
|
|
||||||
let message = "top level function has erroneous type";
|
|
||||||
procs.runtime_errors.insert(symbol, message);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Err(LayoutProblem::UnresolvedTypeVar(v)) => {
|
|
||||||
let message = format!(
|
|
||||||
"top level function has unresolved type variable {:?}",
|
|
||||||
v
|
|
||||||
);
|
|
||||||
procs
|
|
||||||
.runtime_errors
|
|
||||||
.insert(symbol, mono_env.arena.alloc(message));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let pending = PendingSpecialization::from_exposed_function(
|
|
||||||
mono_env.arena,
|
|
||||||
mono_env.subs,
|
mono_env.subs,
|
||||||
|
symbol,
|
||||||
def.annotation,
|
def.annotation,
|
||||||
annotation,
|
annotation,
|
||||||
);
|
);
|
||||||
|
|
||||||
procs.add_specialization_for_host(symbol, top_level, pending);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let proc = PartialProc {
|
let proc = PartialProc {
|
||||||
annotation: def.expr_var,
|
annotation,
|
||||||
// This is a 0-arity thunk, so it has no arguments.
|
// This is a 0-arity thunk, so it has no arguments.
|
||||||
pattern_symbols: &[],
|
pattern_symbols: &[],
|
||||||
// This is a top-level definition, so it cannot capture anything
|
// This is a top-level definition, so it cannot capture anything
|
||||||
|
|
|
@ -2057,7 +2057,7 @@ pub fn specialize_all<'a>(
|
||||||
env: &mut Env<'a, '_>,
|
env: &mut Env<'a, '_>,
|
||||||
mut procs: Procs<'a>,
|
mut procs: Procs<'a>,
|
||||||
externals_others_need: std::vec::Vec<ExternalSpecializations<'a>>,
|
externals_others_need: std::vec::Vec<ExternalSpecializations<'a>>,
|
||||||
specializations_for_host: BumpMap<Symbol, MutMap<ProcLayout<'a>, PendingSpecialization<'a>>>,
|
specializations_for_host: HostSpecializations,
|
||||||
layout_cache: &mut LayoutCache<'a>,
|
layout_cache: &mut LayoutCache<'a>,
|
||||||
) -> Procs<'a> {
|
) -> Procs<'a> {
|
||||||
specialize_externals_others_need(env, &mut procs, externals_others_need, layout_cache);
|
specialize_externals_others_need(env, &mut procs, externals_others_need, layout_cache);
|
||||||
|
@ -2076,63 +2076,7 @@ pub fn specialize_all<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let it = specializations_for_host.into_iter();
|
specialize_host_specializations(env, &mut procs, layout_cache, specializations_for_host);
|
||||||
|
|
||||||
for (name, by_layout) in it {
|
|
||||||
for (outside_layout, pending) in by_layout.into_iter() {
|
|
||||||
// If we've already seen this (Symbol, Layout) combination before,
|
|
||||||
// don't try to specialize it again. If we do, we'll loop forever!
|
|
||||||
|
|
||||||
let partial_proc = if procs.specialized.is_specialized(name, &outside_layout) {
|
|
||||||
// already specialized, just continue
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
match procs.partial_procs.symbol_to_id(name) {
|
|
||||||
Some(v) => {
|
|
||||||
// Mark this proc as in-progress, so if we're dealing with
|
|
||||||
// mutually recursive functions, we don't loop forever.
|
|
||||||
// (We had a bug around this before this system existed!)
|
|
||||||
procs.specialized.mark_in_progress(name, outside_layout);
|
|
||||||
|
|
||||||
v
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
// TODO this assumes the specialization is done by another module
|
|
||||||
// make sure this does not become a problem down the road!
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match specialize(env, &mut procs, name, layout_cache, pending, partial_proc) {
|
|
||||||
Ok((proc, layout)) => {
|
|
||||||
// TODO thiscode is duplicated elsewhere
|
|
||||||
let top_level = ProcLayout::from_raw(env.arena, layout);
|
|
||||||
|
|
||||||
if procs.is_module_thunk(proc.name) {
|
|
||||||
debug_assert!(
|
|
||||||
top_level.arguments.is_empty(),
|
|
||||||
"{:?} from {:?}",
|
|
||||||
name,
|
|
||||||
layout
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
debug_assert_eq!(outside_layout, top_level, " in {:?}", name);
|
|
||||||
procs.specialized.insert_specialized(name, top_level, proc);
|
|
||||||
}
|
|
||||||
Err(SpecializeFailure {
|
|
||||||
attempted_layout, ..
|
|
||||||
}) => {
|
|
||||||
let proc = generate_runtime_error_function(env, name, attempted_layout);
|
|
||||||
|
|
||||||
let top_level = ProcLayout::from_raw(env.arena, attempted_layout);
|
|
||||||
|
|
||||||
procs.specialized.insert_specialized(name, top_level, proc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
procs
|
procs
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue