mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 06:14:46 +00:00
all tests passing + clippy satisfied
This commit is contained in:
parent
40f0588696
commit
06bc187f8b
8 changed files with 177 additions and 139 deletions
|
@ -1511,16 +1511,6 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
|
||||||
increment_refcount_layout(env, parent, layout_ids, value, &layout);
|
increment_refcount_layout(env, parent, layout_ids, value, &layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
match layout {
|
|
||||||
Layout::Builtin(Builtin::List(MemoryMode::Refcounted, _)) => {
|
|
||||||
increment_refcount_list(env, parent, value.into_struct_value());
|
|
||||||
build_exp_stmt(env, layout_ids, scope, parent, cont)
|
|
||||||
}
|
|
||||||
_ => build_exp_stmt(env, layout_ids, scope, parent, cont),
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
build_exp_stmt(env, layout_ids, scope, parent, cont)
|
build_exp_stmt(env, layout_ids, scope, parent, cont)
|
||||||
}
|
}
|
||||||
Dec(symbol, cont) => {
|
Dec(symbol, cont) => {
|
||||||
|
|
|
@ -24,7 +24,6 @@ use roc_region::all::{Located, Region};
|
||||||
use roc_solve::module::SolvedModule;
|
use roc_solve::module::SolvedModule;
|
||||||
use roc_solve::solve;
|
use roc_solve::solve;
|
||||||
use roc_types::solved_types::Solved;
|
use roc_types::solved_types::Solved;
|
||||||
use roc_types::solved_types::SolvedType;
|
|
||||||
use roc_types::subs::{Subs, VarStore, Variable};
|
use roc_types::subs::{Subs, VarStore, Variable};
|
||||||
use roc_types::types::Alias;
|
use roc_types::types::Alias;
|
||||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||||
|
@ -308,7 +307,7 @@ fn start_phase<'a>(module_id: ModuleId, phase: Phase, state: &mut State<'a>) ->
|
||||||
decls,
|
decls,
|
||||||
finished_info,
|
finished_info,
|
||||||
ident_ids,
|
ident_ids,
|
||||||
pending_specializations: state.all_pending_specializations.clone(),
|
exposed_to_host: state.exposed_to_host.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Phase::MakeSpecializations => {
|
Phase::MakeSpecializations => {
|
||||||
|
@ -647,8 +646,7 @@ enum BuildTask<'a> {
|
||||||
ident_ids: IdentIds,
|
ident_ids: IdentIds,
|
||||||
decls: Vec<Declaration>,
|
decls: Vec<Declaration>,
|
||||||
finished_info: FinishedInfo<'a>,
|
finished_info: FinishedInfo<'a>,
|
||||||
// TODO remove?
|
exposed_to_host: MutSet<Symbol>,
|
||||||
pending_specializations: MutMap<Symbol, MutMap<Layout<'a>, PendingSpecialization>>,
|
|
||||||
},
|
},
|
||||||
MakeSpecializations {
|
MakeSpecializations {
|
||||||
module_id: ModuleId,
|
module_id: ModuleId,
|
||||||
|
@ -717,8 +715,6 @@ pub fn load_and_typecheck(
|
||||||
) -> Result<LoadedModule, LoadingProblem> {
|
) -> Result<LoadedModule, LoadingProblem> {
|
||||||
use LoadResult::*;
|
use LoadResult::*;
|
||||||
|
|
||||||
// Reserve one CPU for the main thread, and let all the others be eligible
|
|
||||||
|
|
||||||
match load(
|
match load(
|
||||||
arena,
|
arena,
|
||||||
filename,
|
filename,
|
||||||
|
@ -1980,7 +1976,7 @@ fn make_specializations<'a>(
|
||||||
);
|
);
|
||||||
|
|
||||||
let external_specializations_requested = procs.externals_we_need.clone();
|
let external_specializations_requested = procs.externals_we_need.clone();
|
||||||
let (procedures, _param_map) = procs.get_specialized_procs_help(mono_env.arena);
|
let procedures = procs.get_specialized_procs_without_rc(mono_env.arena);
|
||||||
|
|
||||||
Msg::MadeSpecializations {
|
Msg::MadeSpecializations {
|
||||||
module_id: home,
|
module_id: home,
|
||||||
|
@ -2005,7 +2001,7 @@ fn build_pending_specializations<'a>(
|
||||||
_module_timing: ModuleTiming,
|
_module_timing: ModuleTiming,
|
||||||
mut layout_cache: LayoutCache<'a>,
|
mut layout_cache: LayoutCache<'a>,
|
||||||
// TODO remove
|
// TODO remove
|
||||||
_pending_specializations: MutMap<Symbol, MutMap<Layout<'a>, PendingSpecialization>>,
|
exposed_to_host: MutSet<Symbol>,
|
||||||
finished_info: FinishedInfo<'a>,
|
finished_info: FinishedInfo<'a>,
|
||||||
) -> Msg<'a> {
|
) -> Msg<'a> {
|
||||||
let mut procs = Procs::default();
|
let mut procs = Procs::default();
|
||||||
|
@ -2029,13 +2025,7 @@ fn build_pending_specializations<'a>(
|
||||||
match decl {
|
match decl {
|
||||||
Declare(def) | Builtin(def) => match def.loc_pattern.value {
|
Declare(def) | Builtin(def) => match def.loc_pattern.value {
|
||||||
Identifier(symbol) => {
|
Identifier(symbol) => {
|
||||||
let is_exposed = finished_info
|
let is_exposed = exposed_to_host.contains(&symbol);
|
||||||
.exposed_vars_by_symbol
|
|
||||||
.iter()
|
|
||||||
.find(|(k, _)| *k == symbol)
|
|
||||||
.is_some();
|
|
||||||
|
|
||||||
let is_exposed = is_exposed && !(format!("{:?}", home) == "Utils");
|
|
||||||
|
|
||||||
match def.loc_expr.value {
|
match def.loc_expr.value {
|
||||||
Closure {
|
Closure {
|
||||||
|
@ -2094,7 +2084,6 @@ fn build_pending_specializations<'a>(
|
||||||
// get specialized!
|
// get specialized!
|
||||||
if is_exposed {
|
if is_exposed {
|
||||||
let annotation = def.expr_var;
|
let annotation = def.expr_var;
|
||||||
let ret_var = def.expr_var;
|
|
||||||
let layout = layout_cache.from_var(mono_env.arena, annotation, mono_env.subs).unwrap_or_else(|err|
|
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)
|
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)
|
||||||
);
|
);
|
||||||
|
@ -2195,7 +2184,7 @@ fn run_task<'a>(
|
||||||
layout_cache,
|
layout_cache,
|
||||||
solved_subs,
|
solved_subs,
|
||||||
finished_info,
|
finished_info,
|
||||||
pending_specializations,
|
exposed_to_host,
|
||||||
} => Ok(build_pending_specializations(
|
} => Ok(build_pending_specializations(
|
||||||
arena,
|
arena,
|
||||||
solved_subs,
|
solved_subs,
|
||||||
|
@ -2204,7 +2193,7 @@ fn run_task<'a>(
|
||||||
decls,
|
decls,
|
||||||
module_timing,
|
module_timing,
|
||||||
layout_cache,
|
layout_cache,
|
||||||
pending_specializations,
|
exposed_to_host,
|
||||||
finished_info,
|
finished_info,
|
||||||
)),
|
)),
|
||||||
MakeSpecializations {
|
MakeSpecializations {
|
||||||
|
|
|
@ -14,19 +14,18 @@ mod helpers;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_load {
|
mod test_load {
|
||||||
use crate::helpers::fixtures_dir;
|
use crate::helpers::fixtures_dir;
|
||||||
|
use bumpalo::Bump;
|
||||||
use inlinable_string::InlinableString;
|
use inlinable_string::InlinableString;
|
||||||
use roc_can::def::Declaration::*;
|
use roc_can::def::Declaration::*;
|
||||||
use roc_can::def::Def;
|
use roc_can::def::Def;
|
||||||
use roc_collections::all::MutMap;
|
use roc_collections::all::MutMap;
|
||||||
use roc_constrain::module::SubsByModule;
|
use roc_constrain::module::SubsByModule;
|
||||||
use roc_load::file::{load, LoadedModule, Phase};
|
use roc_load::file::LoadedModule;
|
||||||
use roc_module::symbol::{Interns, ModuleId};
|
use roc_module::symbol::{Interns, ModuleId};
|
||||||
use roc_types::pretty_print::{content_to_string, name_all_type_vars};
|
use roc_types::pretty_print::{content_to_string, name_all_type_vars};
|
||||||
use roc_types::subs::Subs;
|
use roc_types::subs::Subs;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
const GOAL_PHASE: Phase = Phase::SolveTypes;
|
|
||||||
|
|
||||||
// HELPERS
|
// HELPERS
|
||||||
|
|
||||||
fn load_fixture(
|
fn load_fixture(
|
||||||
|
@ -36,12 +35,13 @@ mod test_load {
|
||||||
) -> LoadedModule {
|
) -> LoadedModule {
|
||||||
let src_dir = fixtures_dir().join(dir_name);
|
let src_dir = fixtures_dir().join(dir_name);
|
||||||
let filename = src_dir.join(format!("{}.roc", module_name));
|
let filename = src_dir.join(format!("{}.roc", module_name));
|
||||||
let loaded = load(
|
let arena = Bump::new();
|
||||||
|
let loaded = roc_load::file::load_and_typecheck(
|
||||||
|
&arena,
|
||||||
filename,
|
filename,
|
||||||
roc_builtins::std::standard_stdlib(),
|
roc_builtins::std::standard_stdlib(),
|
||||||
src_dir.as_path(),
|
src_dir.as_path(),
|
||||||
subs_by_module,
|
subs_by_module,
|
||||||
GOAL_PHASE,
|
|
||||||
);
|
);
|
||||||
let loaded_module = loaded.expect("Test module failed to load");
|
let loaded_module = loaded.expect("Test module failed to load");
|
||||||
|
|
||||||
|
@ -132,12 +132,13 @@ mod test_load {
|
||||||
let subs_by_module = MutMap::default();
|
let subs_by_module = MutMap::default();
|
||||||
let src_dir = fixtures_dir().join("interface_with_deps");
|
let src_dir = fixtures_dir().join("interface_with_deps");
|
||||||
let filename = src_dir.join("Primary.roc");
|
let filename = src_dir.join("Primary.roc");
|
||||||
let loaded = load(
|
let arena = Bump::new();
|
||||||
|
let loaded = roc_load::file::load_and_typecheck(
|
||||||
|
&arena,
|
||||||
filename,
|
filename,
|
||||||
roc_builtins::std::standard_stdlib(),
|
roc_builtins::std::standard_stdlib(),
|
||||||
src_dir.as_path(),
|
src_dir.as_path(),
|
||||||
subs_by_module,
|
subs_by_module,
|
||||||
GOAL_PHASE,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut loaded_module = loaded.expect("Test module failed to load");
|
let mut loaded_module = loaded.expect("Test module failed to load");
|
||||||
|
|
|
@ -14,20 +14,19 @@ mod helpers;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_uniq_load {
|
mod test_uniq_load {
|
||||||
use crate::helpers::fixtures_dir;
|
use crate::helpers::fixtures_dir;
|
||||||
|
use bumpalo::Bump;
|
||||||
use inlinable_string::InlinableString;
|
use inlinable_string::InlinableString;
|
||||||
use roc_builtins::unique;
|
use roc_builtins::unique;
|
||||||
use roc_can::def::Declaration::*;
|
use roc_can::def::Declaration::*;
|
||||||
use roc_can::def::Def;
|
use roc_can::def::Def;
|
||||||
use roc_collections::all::MutMap;
|
use roc_collections::all::MutMap;
|
||||||
use roc_constrain::module::SubsByModule;
|
use roc_constrain::module::SubsByModule;
|
||||||
use roc_load::file::{load, LoadedModule, Phase};
|
use roc_load::file::LoadedModule;
|
||||||
use roc_module::symbol::{Interns, ModuleId};
|
use roc_module::symbol::{Interns, ModuleId};
|
||||||
use roc_types::pretty_print::{content_to_string, name_all_type_vars};
|
use roc_types::pretty_print::{content_to_string, name_all_type_vars};
|
||||||
use roc_types::subs::Subs;
|
use roc_types::subs::Subs;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
const GOAL_PHASE: Phase = Phase::SolveTypes;
|
|
||||||
|
|
||||||
// HELPERS
|
// HELPERS
|
||||||
|
|
||||||
fn load_fixture(
|
fn load_fixture(
|
||||||
|
@ -35,14 +34,15 @@ mod test_uniq_load {
|
||||||
module_name: &str,
|
module_name: &str,
|
||||||
subs_by_module: SubsByModule,
|
subs_by_module: SubsByModule,
|
||||||
) -> LoadedModule {
|
) -> LoadedModule {
|
||||||
|
let arena = Bump::new();
|
||||||
let src_dir = fixtures_dir().join(dir_name);
|
let src_dir = fixtures_dir().join(dir_name);
|
||||||
let filename = src_dir.join(format!("{}.roc", module_name));
|
let filename = src_dir.join(format!("{}.roc", module_name));
|
||||||
let loaded = load(
|
let loaded = roc_load::file::load_and_typecheck(
|
||||||
|
&arena,
|
||||||
filename,
|
filename,
|
||||||
unique::uniq_stdlib(),
|
unique::uniq_stdlib(),
|
||||||
src_dir.as_path(),
|
src_dir.as_path(),
|
||||||
subs_by_module,
|
subs_by_module,
|
||||||
GOAL_PHASE,
|
|
||||||
);
|
);
|
||||||
let loaded_module = loaded.expect("Test module failed to load");
|
let loaded_module = loaded.expect("Test module failed to load");
|
||||||
|
|
||||||
|
@ -129,15 +129,16 @@ mod test_uniq_load {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn interface_with_deps() {
|
fn interface_with_deps() {
|
||||||
|
let arena = Bump::new();
|
||||||
let subs_by_module = MutMap::default();
|
let subs_by_module = MutMap::default();
|
||||||
let src_dir = fixtures_dir().join("interface_with_deps");
|
let src_dir = fixtures_dir().join("interface_with_deps");
|
||||||
let filename = src_dir.join("Primary.roc");
|
let filename = src_dir.join("Primary.roc");
|
||||||
let loaded = load(
|
let loaded = roc_load::file::load_and_typecheck(
|
||||||
|
&arena,
|
||||||
filename,
|
filename,
|
||||||
roc_builtins::std::standard_stdlib(),
|
roc_builtins::std::standard_stdlib(),
|
||||||
src_dir.as_path(),
|
src_dir.as_path(),
|
||||||
subs_by_module,
|
subs_by_module,
|
||||||
GOAL_PHASE,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut loaded_module = loaded.expect("Test module failed to load");
|
let mut loaded_module = loaded.expect("Test module failed to load");
|
||||||
|
|
|
@ -194,6 +194,37 @@ impl<'a> Procs<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_specialized_procs_without_rc(
|
||||||
|
self,
|
||||||
|
arena: &'a Bump,
|
||||||
|
) -> MutMap<(Symbol, Layout<'a>), Proc<'a>> {
|
||||||
|
let mut result = MutMap::with_capacity_and_hasher(self.specialized.len(), default_hasher());
|
||||||
|
|
||||||
|
for (key, in_prog_proc) in self.specialized.into_iter() {
|
||||||
|
match in_prog_proc {
|
||||||
|
InProgress => unreachable!("The procedure {:?} should have be done by now", key),
|
||||||
|
Done(proc) => {
|
||||||
|
result.insert(key, proc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (_, proc) in result.iter_mut() {
|
||||||
|
use self::SelfRecursive::*;
|
||||||
|
if let SelfRecursive(id) = proc.is_self_recursive {
|
||||||
|
proc.body = crate::tail_recursion::make_tail_recursive(
|
||||||
|
arena,
|
||||||
|
id,
|
||||||
|
proc.name,
|
||||||
|
proc.body.clone(),
|
||||||
|
proc.args,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
// TODO investigate make this an iterator?
|
// TODO investigate make this an iterator?
|
||||||
pub fn get_specialized_procs(self, arena: &'a Bump) -> MutMap<(Symbol, Layout<'a>), Proc<'a>> {
|
pub fn get_specialized_procs(self, arena: &'a Bump) -> MutMap<(Symbol, Layout<'a>), Proc<'a>> {
|
||||||
let mut result = MutMap::with_capacity_and_hasher(self.specialized.len(), default_hasher());
|
let mut result = MutMap::with_capacity_and_hasher(self.specialized.len(), default_hasher());
|
||||||
|
@ -223,7 +254,7 @@ impl<'a> Procs<'a> {
|
||||||
let borrow_params = arena.alloc(crate::borrow::infer_borrow(arena, &result));
|
let borrow_params = arena.alloc(crate::borrow::infer_borrow(arena, &result));
|
||||||
|
|
||||||
for (_, proc) in result.iter_mut() {
|
for (_, proc) in result.iter_mut() {
|
||||||
// crate::inc_dec::visit_proc(arena, borrow_params, proc);
|
crate::inc_dec::visit_proc(arena, borrow_params, proc);
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
result
|
||||||
|
@ -263,7 +294,7 @@ impl<'a> Procs<'a> {
|
||||||
let borrow_params = arena.alloc(crate::borrow::infer_borrow(arena, &result));
|
let borrow_params = arena.alloc(crate::borrow::infer_borrow(arena, &result));
|
||||||
|
|
||||||
for (_, proc) in result.iter_mut() {
|
for (_, proc) in result.iter_mut() {
|
||||||
// crate::inc_dec::visit_proc(arena, borrow_params, proc);
|
crate::inc_dec::visit_proc(arena, borrow_params, proc);
|
||||||
}
|
}
|
||||||
|
|
||||||
(result, borrow_params)
|
(result, borrow_params)
|
||||||
|
@ -332,7 +363,7 @@ impl<'a> Procs<'a> {
|
||||||
let is_self_recursive = false;
|
let is_self_recursive = false;
|
||||||
|
|
||||||
match patterns_to_when(env, layout_cache, loc_args, ret_var, loc_body) {
|
match patterns_to_when(env, layout_cache, loc_args, ret_var, loc_body) {
|
||||||
Ok((pattern_vars, pattern_symbols, body)) => {
|
Ok((_, pattern_symbols, body)) => {
|
||||||
// an anonymous closure. These will always be specialized already
|
// an anonymous closure. These will always be specialized already
|
||||||
// by the surrounding context, so we can add pending specializations
|
// by the surrounding context, so we can add pending specializations
|
||||||
// for them immediately.
|
// for them immediately.
|
||||||
|
@ -386,9 +417,12 @@ impl<'a> Procs<'a> {
|
||||||
self.specialized
|
self.specialized
|
||||||
.insert((symbol, layout.clone()), InProgress);
|
.insert((symbol, layout.clone()), InProgress);
|
||||||
|
|
||||||
|
let outside_layout = layout.clone();
|
||||||
|
|
||||||
match specialize(env, self, symbol, layout_cache, pending, partial_proc)
|
match specialize(env, self, symbol, layout_cache, pending, partial_proc)
|
||||||
{
|
{
|
||||||
Ok((proc, layout)) => {
|
Ok((proc, layout)) => {
|
||||||
|
debug_assert_eq!(outside_layout, layout);
|
||||||
self.specialized.insert((symbol, layout), Done(proc));
|
self.specialized.insert((symbol, layout), Done(proc));
|
||||||
}
|
}
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
|
@ -398,6 +432,7 @@ impl<'a> Procs<'a> {
|
||||||
);
|
);
|
||||||
self.runtime_errors
|
self.runtime_errors
|
||||||
.insert(symbol, env.arena.alloc(error_msg));
|
.insert(symbol, env.arena.alloc(error_msg));
|
||||||
|
panic!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -459,11 +494,6 @@ impl<'a> Procs<'a> {
|
||||||
// We're done with that tuple, so move layout back out to avoid cloning it.
|
// We're done with that tuple, so move layout back out to avoid cloning it.
|
||||||
let (name, layout) = tuple;
|
let (name, layout) = tuple;
|
||||||
|
|
||||||
// now we have to pull some tricks to extract the return var and pattern vars from Subs
|
|
||||||
match get_args_ret_var(env.subs, fn_var) {
|
|
||||||
Some((pattern_vars, ret_var)) => {
|
|
||||||
let pattern_vars =
|
|
||||||
Vec::from_iter_in(pattern_vars.into_iter(), env.arena).into_bump_slice();
|
|
||||||
let pending = PendingSpecialization::from_var(env.subs, fn_var);
|
let pending = PendingSpecialization::from_var(env.subs, fn_var);
|
||||||
|
|
||||||
// This should only be called when pending_specializations is Some.
|
// This should only be called when pending_specializations is Some.
|
||||||
|
@ -494,32 +524,12 @@ impl<'a> Procs<'a> {
|
||||||
format!("TODO generate a RuntimeError message for {:?}", error);
|
format!("TODO generate a RuntimeError message for {:?}", error);
|
||||||
self.runtime_errors
|
self.runtime_errors
|
||||||
.insert(symbol, env.arena.alloc(error_msg));
|
.insert(symbol, env.arena.alloc(error_msg));
|
||||||
|
panic!();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
other => {
|
|
||||||
unreachable!(
|
|
||||||
"trying to insert a symbol that is not a function: {:?} {:?}",
|
|
||||||
name, other
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_args_ret_var(subs: &Subs, var: Variable) -> Option<(std::vec::Vec<Variable>, Variable)> {
|
|
||||||
match subs.get_without_compacting(var).content {
|
|
||||||
Content::Structure(FlatType::Func(pattern_vars, _closure_var, ret_var)) => {
|
|
||||||
Some((pattern_vars, ret_var))
|
|
||||||
}
|
|
||||||
Content::Structure(FlatType::Apply(Symbol::ATTR_ATTR, args)) => {
|
|
||||||
get_args_ret_var(subs, args[1])
|
|
||||||
}
|
|
||||||
Content::Alias(_, _, actual) => get_args_ret_var(subs, actual),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_pending<'a>(
|
fn add_pending<'a>(
|
||||||
|
@ -1240,11 +1250,6 @@ pub fn specialize_all<'a>(
|
||||||
mut procs: Procs<'a>,
|
mut procs: Procs<'a>,
|
||||||
layout_cache: &mut LayoutCache<'a>,
|
layout_cache: &mut LayoutCache<'a>,
|
||||||
) -> Procs<'a> {
|
) -> Procs<'a> {
|
||||||
// add the specializations that other modules require of us
|
|
||||||
use roc_constrain::module::{to_type, FreeVars};
|
|
||||||
use roc_solve::solve::{insert_type_into_subs, unsafe_copy_var_help};
|
|
||||||
use roc_types::subs::VarStore;
|
|
||||||
|
|
||||||
let it = procs.externals_others_need.specs.clone();
|
let it = procs.externals_others_need.specs.clone();
|
||||||
let it = it
|
let it = it
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -1308,20 +1313,36 @@ pub fn specialize_all<'a>(
|
||||||
// Mark this proc as in-progress, so if we're dealing with
|
// Mark this proc as in-progress, so if we're dealing with
|
||||||
// mutually recursive functions, we don't loop forever.
|
// mutually recursive functions, we don't loop forever.
|
||||||
// (We had a bug around this before this system existed!)
|
// (We had a bug around this before this system existed!)
|
||||||
procs.specialized.insert((name, layout.clone()), InProgress);
|
let outside_layout = layout.clone();
|
||||||
|
procs
|
||||||
|
.specialized
|
||||||
|
.insert((name, outside_layout.clone()), InProgress);
|
||||||
|
|
||||||
match specialize(env, &mut procs, name, layout_cache, pending, partial_proc) {
|
match specialize(
|
||||||
|
env,
|
||||||
|
&mut procs,
|
||||||
|
name,
|
||||||
|
layout_cache,
|
||||||
|
pending.clone(),
|
||||||
|
partial_proc,
|
||||||
|
) {
|
||||||
|
Ok((proc, layout)) if outside_layout != layout => {
|
||||||
|
println!("Layouts don't match for function {:?}", proc.name,);
|
||||||
|
dbg!(outside_layout, layout, &pending.solved_type);
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
Ok((proc, layout)) => {
|
Ok((proc, layout)) => {
|
||||||
|
procs.specialized.remove(&(name, outside_layout));
|
||||||
procs.specialized.insert((name, layout), Done(proc));
|
procs.specialized.insert((name, layout), Done(proc));
|
||||||
}
|
}
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
|
let error_msg = env.arena.alloc(format!(
|
||||||
|
"TODO generate a RuntimeError message for {:?}",
|
||||||
|
error
|
||||||
|
));
|
||||||
|
|
||||||
|
procs.runtime_errors.insert(name, error_msg);
|
||||||
panic!("failed to specialize {:?}", name);
|
panic!("failed to specialize {:?}", name);
|
||||||
// let error_msg = env.arena.alloc(format!(
|
|
||||||
// "TODO generate a RuntimeError message for {:?}",
|
|
||||||
// error
|
|
||||||
// ));
|
|
||||||
//
|
|
||||||
// procs.runtime_errors.insert(name, error_msg);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1392,7 +1413,9 @@ fn build_specialized_proc_from_var<'a>(
|
||||||
Content::Structure(FlatType::Func(pattern_vars, _closure_var, ret_var)) => {
|
Content::Structure(FlatType::Func(pattern_vars, _closure_var, ret_var)) => {
|
||||||
build_specialized_proc(env, layout_cache, pattern_symbols, &pattern_vars, ret_var)
|
build_specialized_proc(env, layout_cache, pattern_symbols, &pattern_vars, ret_var)
|
||||||
}
|
}
|
||||||
Content::Structure(FlatType::Apply(Symbol::ATTR_ATTR, args)) => {
|
Content::Structure(FlatType::Apply(Symbol::ATTR_ATTR, args))
|
||||||
|
if !pattern_symbols.is_empty() =>
|
||||||
|
{
|
||||||
build_specialized_proc_from_var(env, layout_cache, pattern_symbols, args[1])
|
build_specialized_proc_from_var(env, layout_cache, pattern_symbols, args[1])
|
||||||
}
|
}
|
||||||
Content::Alias(_, _, actual) => {
|
Content::Alias(_, _, actual) => {
|
||||||
|
@ -1473,20 +1496,22 @@ fn specialize_solved_type<'a>(
|
||||||
let mut free_vars = FreeVars::default();
|
let mut free_vars = FreeVars::default();
|
||||||
let mut var_store = VarStore::new_from_subs(env.subs);
|
let mut var_store = VarStore::new_from_subs(env.subs);
|
||||||
|
|
||||||
|
let before = var_store.peek();
|
||||||
|
|
||||||
let normal_type = to_type(&solved_type, &mut free_vars, &mut var_store);
|
let normal_type = to_type(&solved_type, &mut free_vars, &mut var_store);
|
||||||
|
|
||||||
let variables_introduced = var_store.peek() as usize - (env.subs.len() - 1);
|
let after = var_store.peek();
|
||||||
|
let variables_introduced = after - before;
|
||||||
|
|
||||||
env.subs.extend_by(variables_introduced);
|
env.subs.extend_by(variables_introduced as usize);
|
||||||
|
|
||||||
let fn_var = insert_type_into_subs(env.subs, &normal_type);
|
let fn_var = insert_type_into_subs(env.subs, &normal_type);
|
||||||
|
|
||||||
|
match specialize_external(env, procs, proc_name, layout_cache, fn_var, partial_proc) {
|
||||||
|
Ok(proc) => {
|
||||||
let layout = layout_cache
|
let layout = layout_cache
|
||||||
.from_var(&env.arena, fn_var, env.subs)
|
.from_var(&env.arena, fn_var, env.subs)
|
||||||
.unwrap_or_else(|err| panic!("TODO handle invalid function {:?}", err));
|
.unwrap_or_else(|err| panic!("TODO handle invalid function {:?}", err));
|
||||||
|
|
||||||
match specialize_external(env, procs, proc_name, layout_cache, fn_var, partial_proc) {
|
|
||||||
Ok(proc) => {
|
|
||||||
env.subs.rollback_to(snapshot);
|
env.subs.rollback_to(snapshot);
|
||||||
Ok((proc, layout))
|
Ok((proc, layout))
|
||||||
}
|
}
|
||||||
|
@ -1497,6 +1522,30 @@ fn specialize_solved_type<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct FunctionLayouts<'a> {
|
||||||
|
full: Layout<'a>,
|
||||||
|
arguments: &'a [Layout<'a>],
|
||||||
|
result: Layout<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> FunctionLayouts<'a> {
|
||||||
|
pub fn from_layout(layout: Layout<'a>) -> Self {
|
||||||
|
match &layout {
|
||||||
|
Layout::FunctionPointer(arguments, result) => FunctionLayouts {
|
||||||
|
arguments,
|
||||||
|
result: (*result).clone(),
|
||||||
|
full: layout,
|
||||||
|
},
|
||||||
|
_ => FunctionLayouts {
|
||||||
|
full: layout.clone(),
|
||||||
|
arguments: &[],
|
||||||
|
result: layout,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn with_hole<'a>(
|
pub fn with_hole<'a>(
|
||||||
env: &mut Env<'a, '_>,
|
env: &mut Env<'a, '_>,
|
||||||
can_expr: roc_can::expr::Expr,
|
can_expr: roc_can::expr::Expr,
|
||||||
|
@ -1679,14 +1728,12 @@ pub fn with_hole<'a>(
|
||||||
if procs.module_thunks.contains(&symbol) {
|
if procs.module_thunks.contains(&symbol) {
|
||||||
let partial_proc = procs.partial_procs.get(&symbol).unwrap();
|
let partial_proc = procs.partial_procs.get(&symbol).unwrap();
|
||||||
let fn_var = partial_proc.annotation;
|
let fn_var = partial_proc.annotation;
|
||||||
let ret_var = fn_var; // These are the same for a thunk.
|
|
||||||
|
|
||||||
// This is a top-level declaration, which will code gen to a 0-arity thunk.
|
// This is a top-level declaration, which will code gen to a 0-arity thunk.
|
||||||
let result = call_by_name(
|
let result = call_by_name(
|
||||||
env,
|
env,
|
||||||
procs,
|
procs,
|
||||||
fn_var,
|
fn_var,
|
||||||
ret_var,
|
|
||||||
symbol,
|
symbol,
|
||||||
std::vec::Vec::new(),
|
std::vec::Vec::new(),
|
||||||
layout_cache,
|
layout_cache,
|
||||||
|
@ -2386,7 +2433,6 @@ pub fn with_hole<'a>(
|
||||||
env,
|
env,
|
||||||
procs,
|
procs,
|
||||||
fn_var,
|
fn_var,
|
||||||
ret_var,
|
|
||||||
proc_name,
|
proc_name,
|
||||||
loc_args,
|
loc_args,
|
||||||
layout_cache,
|
layout_cache,
|
||||||
|
@ -2567,7 +2613,6 @@ pub fn from_can<'a>(
|
||||||
.from_var(env.arena, cond_var, env.subs)
|
.from_var(env.arena, cond_var, env.subs)
|
||||||
.expect("invalid cond_layout");
|
.expect("invalid cond_layout");
|
||||||
|
|
||||||
dbg!("in an if");
|
|
||||||
let mut stmt = from_can(env, final_else.value, procs, layout_cache);
|
let mut stmt = from_can(env, final_else.value, procs, layout_cache);
|
||||||
|
|
||||||
for (loc_cond, loc_then) in branches.into_iter().rev() {
|
for (loc_cond, loc_then) in branches.into_iter().rev() {
|
||||||
|
@ -3561,7 +3606,6 @@ fn call_by_name<'a>(
|
||||||
env: &mut Env<'a, '_>,
|
env: &mut Env<'a, '_>,
|
||||||
procs: &mut Procs<'a>,
|
procs: &mut Procs<'a>,
|
||||||
fn_var: Variable,
|
fn_var: Variable,
|
||||||
ret_var: Variable,
|
|
||||||
proc_name: Symbol,
|
proc_name: Symbol,
|
||||||
loc_args: std::vec::Vec<(Variable, Located<roc_can::expr::Expr>)>,
|
loc_args: std::vec::Vec<(Variable, Located<roc_can::expr::Expr>)>,
|
||||||
layout_cache: &mut LayoutCache<'a>,
|
layout_cache: &mut LayoutCache<'a>,
|
||||||
|
@ -3685,16 +3729,22 @@ fn call_by_name<'a>(
|
||||||
pending,
|
pending,
|
||||||
partial_proc,
|
partial_proc,
|
||||||
) {
|
) {
|
||||||
Ok((proc, _layout)) => {
|
Ok((proc, layout)) => {
|
||||||
procs
|
debug_assert_eq!(full_layout, layout);
|
||||||
.specialized
|
let function_layout = FunctionLayouts::from_layout(layout);
|
||||||
.insert((proc_name, full_layout.clone()), Done(proc));
|
|
||||||
|
procs.specialized.remove(&(proc_name, full_layout));
|
||||||
|
|
||||||
|
procs.specialized.insert(
|
||||||
|
(proc_name, function_layout.full.clone()),
|
||||||
|
Done(proc),
|
||||||
|
);
|
||||||
|
|
||||||
let call = Expr::FunctionCall {
|
let call = Expr::FunctionCall {
|
||||||
call_type: CallType::ByName(proc_name),
|
call_type: CallType::ByName(proc_name),
|
||||||
ret_layout: ret_layout.clone(),
|
ret_layout: function_layout.result.clone(),
|
||||||
full_layout: full_layout.clone(),
|
full_layout: function_layout.full,
|
||||||
arg_layouts,
|
arg_layouts: function_layout.arguments,
|
||||||
args: field_symbols,
|
args: field_symbols,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3704,7 +3754,7 @@ fn call_by_name<'a>(
|
||||||
.zip(field_symbols.iter().rev());
|
.zip(field_symbols.iter().rev());
|
||||||
|
|
||||||
let result =
|
let result =
|
||||||
Stmt::Let(assigned, call, ret_layout.clone(), hole);
|
Stmt::Let(assigned, call, function_layout.result, hole);
|
||||||
|
|
||||||
assign_to_symbols(env, procs, layout_cache, iter, result)
|
assign_to_symbols(env, procs, layout_cache, iter, result)
|
||||||
}
|
}
|
||||||
|
@ -3716,7 +3766,8 @@ fn call_by_name<'a>(
|
||||||
|
|
||||||
procs.runtime_errors.insert(proc_name, error_msg);
|
procs.runtime_errors.insert(proc_name, error_msg);
|
||||||
|
|
||||||
Stmt::RuntimeError(error_msg)
|
panic!();
|
||||||
|
// Stmt::RuntimeError(error_msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -250,10 +250,13 @@ impl<'a> LayoutCache<'a> {
|
||||||
seen: MutSet::default(),
|
seen: MutSet::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
self.layouts
|
self.layouts
|
||||||
.entry(var)
|
.entry(var)
|
||||||
.or_insert_with(|| Layout::from_var(&mut env, var))
|
.or_insert_with(|| Layout::from_var(&mut env, var))
|
||||||
.clone()
|
.clone()
|
||||||
|
*/
|
||||||
|
Layout::from_var(&mut env, var)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,7 +373,7 @@ fn layout_from_flat_type<'a>(
|
||||||
|
|
||||||
// correct the memory mode of unique lists
|
// correct the memory mode of unique lists
|
||||||
match Layout::from_var(env, wrapped_var)? {
|
match Layout::from_var(env, wrapped_var)? {
|
||||||
Layout::Builtin(Builtin::List(_, elem_layout)) => {
|
Layout::Builtin(Builtin::List(_ignored, elem_layout)) => {
|
||||||
let uniqueness_var = args[0];
|
let uniqueness_var = args[0];
|
||||||
let uniqueness_content =
|
let uniqueness_content =
|
||||||
subs.get_without_compacting(uniqueness_var).content;
|
subs.get_without_compacting(uniqueness_var).content;
|
||||||
|
|
|
@ -72,10 +72,13 @@ impl SolvedBool {
|
||||||
match boolean {
|
match boolean {
|
||||||
Bool::Shared => SolvedBool::SolvedShared,
|
Bool::Shared => SolvedBool::SolvedShared,
|
||||||
Bool::Container(cvar, mvars) => {
|
Bool::Container(cvar, mvars) => {
|
||||||
debug_assert!(matches!(
|
match subs.get_without_compacting(*cvar).content {
|
||||||
subs.get_without_compacting(*cvar).content,
|
crate::subs::Content::FlexVar(_) => {}
|
||||||
crate::subs::Content::FlexVar(_)
|
crate::subs::Content::Structure(FlatType::Boolean(Bool::Shared)) => {
|
||||||
));
|
return SolvedBool::SolvedShared;
|
||||||
|
}
|
||||||
|
other => panic!("Container var is not flex but {:?}", other),
|
||||||
|
}
|
||||||
|
|
||||||
SolvedBool::SolvedContainer(
|
SolvedBool::SolvedContainer(
|
||||||
VarId::from_var(*cvar, subs),
|
VarId::from_var(*cvar, subs),
|
||||||
|
|
|
@ -203,7 +203,7 @@ impl fmt::Debug for Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sometimes it's useful to see the expansion of the alias
|
// Sometimes it's useful to see the expansion of the alias
|
||||||
write!(f, "[ but actually {:?} ]", _actual)?;
|
// write!(f, "[ but actually {:?} ]", _actual)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue