mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 06:14:46 +00:00
commit some crimes
This commit is contained in:
parent
e6f6b8c224
commit
3d0f2751f5
3 changed files with 233 additions and 105 deletions
|
@ -2239,17 +2239,21 @@ fn fabricate_effects_module<'a>(
|
||||||
|
|
||||||
module_ids.get_or_insert(&declared_name)
|
module_ids.get_or_insert(&declared_name)
|
||||||
};
|
};
|
||||||
|
let mut scope = roc_can::scope::Scope::new(module_id, &mut var_store);
|
||||||
|
|
||||||
let effect_symbol = {
|
let effect_symbol = {
|
||||||
let mut ident_ids_by_module = (*ident_ids_by_module).lock();
|
let mut ident_ids_by_module = (*ident_ids_by_module).lock();
|
||||||
|
|
||||||
let ident_ids: &mut IdentIds = ident_ids_by_module.get_mut(&module_id).unwrap();
|
let ident_ids: &mut IdentIds = ident_ids_by_module.get_mut(&module_id).unwrap();
|
||||||
|
//let ident_id = ident_ids.get_or_insert(&declared_name);
|
||||||
|
//Symbol::new(module_id, ident_id)
|
||||||
|
|
||||||
let ident_id = ident_ids.get_or_insert(&declared_name);
|
let ident = declared_name.clone().into();
|
||||||
Symbol::new(module_id, ident_id)
|
scope
|
||||||
|
.introduce(ident, &(ident_ids.clone()), ident_ids, Region::zero())
|
||||||
|
.unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut scope = roc_can::scope::Scope::new(module_id, &mut var_store);
|
|
||||||
let mut aliases = MutMap::default();
|
let mut aliases = MutMap::default();
|
||||||
let alias = {
|
let alias = {
|
||||||
let a_var = var_store.fresh();
|
let a_var = var_store.fresh();
|
||||||
|
@ -2273,14 +2277,14 @@ fn fabricate_effects_module<'a>(
|
||||||
actual,
|
actual,
|
||||||
);
|
);
|
||||||
|
|
||||||
scope.lookup_alias(effect_symbol).clone()
|
scope.lookup_alias(effect_symbol).unwrap().clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
aliases.insert(effect_symbol, alias);
|
aliases.insert(effect_symbol, alias);
|
||||||
|
|
||||||
let mut declarations = Vec::new();
|
let mut declarations = Vec::new();
|
||||||
|
|
||||||
let exposed_symbols = {
|
let exposed_vars_by_symbol = {
|
||||||
let module_ids = (*module_ids).lock();
|
let module_ids = (*module_ids).lock();
|
||||||
let mut ident_ids_by_module = (*ident_ids_by_module).lock();
|
let mut ident_ids_by_module = (*ident_ids_by_module).lock();
|
||||||
|
|
||||||
|
@ -2289,7 +2293,7 @@ fn fabricate_effects_module<'a>(
|
||||||
let ident_id = ident_ids.get_or_insert(&declared_name);
|
let ident_id = ident_ids.get_or_insert(&declared_name);
|
||||||
let effect_symbol = Symbol::new(module_id, ident_id);
|
let effect_symbol = Symbol::new(module_id, ident_id);
|
||||||
|
|
||||||
let mut exposed = MutSet::default();
|
let mut exposed_vars_by_symbol = Vec::new();
|
||||||
|
|
||||||
{
|
{
|
||||||
use bumpalo::collections::Vec;
|
use bumpalo::collections::Vec;
|
||||||
|
@ -2316,8 +2320,6 @@ fn fabricate_effects_module<'a>(
|
||||||
let ident_id = ident_ids.get_or_insert(&as_inlinable_string);
|
let ident_id = ident_ids.get_or_insert(&as_inlinable_string);
|
||||||
let symbol = Symbol::new(module_id, ident_id);
|
let symbol = Symbol::new(module_id, ident_id);
|
||||||
|
|
||||||
exposed.insert(symbol);
|
|
||||||
|
|
||||||
let annotation = roc_can::annotation::canonicalize_annotation(
|
let annotation = roc_can::annotation::canonicalize_annotation(
|
||||||
&mut can_env,
|
&mut can_env,
|
||||||
&mut scope,
|
&mut scope,
|
||||||
|
@ -2335,6 +2337,8 @@ fn fabricate_effects_module<'a>(
|
||||||
annotation,
|
annotation,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
exposed_vars_by_symbol.push((symbol, def.expr_var));
|
||||||
|
|
||||||
declarations.push(Declaration::Declare(def));
|
declarations.push(Declaration::Declare(def));
|
||||||
}
|
}
|
||||||
EffectsEntry::SpaceAfter(nested, _) | EffectsEntry::SpaceBefore(nested, _) => {
|
EffectsEntry::SpaceAfter(nested, _) | EffectsEntry::SpaceBefore(nested, _) => {
|
||||||
|
@ -2344,19 +2348,19 @@ fn fabricate_effects_module<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exposed
|
exposed_vars_by_symbol
|
||||||
};
|
};
|
||||||
|
|
||||||
use roc_can::module::ModuleOutput;
|
use roc_can::module::ModuleOutput;
|
||||||
let module_output = ModuleOutput {
|
let module_output = ModuleOutput {
|
||||||
aliases: MutMap::default(),
|
aliases,
|
||||||
rigid_variables: MutMap::default(),
|
rigid_variables: MutMap::default(),
|
||||||
declarations,
|
declarations,
|
||||||
exposed_imports: MutMap::default(),
|
exposed_imports: MutMap::default(),
|
||||||
lookups: Vec::new(),
|
lookups: Vec::new(),
|
||||||
problems: Vec::new(),
|
problems: Vec::new(),
|
||||||
ident_ids: IdentIds::default(),
|
ident_ids: IdentIds::default(),
|
||||||
exposed_vars_by_symbol: Vec::new(),
|
exposed_vars_by_symbol,
|
||||||
references: MutSet::default(),
|
references: MutSet::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ use crate::exhaustive::{Ctor, Guard, RenderAs, TagId};
|
||||||
use crate::layout::{Builtin, ClosureLayout, Layout, LayoutCache, LayoutProblem};
|
use crate::layout::{Builtin, ClosureLayout, Layout, LayoutCache, LayoutProblem};
|
||||||
use bumpalo::collections::Vec;
|
use bumpalo::collections::Vec;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use roc_collections::all::{default_hasher, MutMap, MutSet};
|
use roc_collections::all::{default_hasher, MutMap, MutSet, SendMap};
|
||||||
use roc_module::ident::{Ident, Lowercase, TagName};
|
use roc_module::ident::{Ident, Lowercase, TagName};
|
||||||
use roc_module::low_level::LowLevel;
|
use roc_module::low_level::LowLevel;
|
||||||
use roc_module::symbol::{IdentIds, ModuleId, Symbol};
|
use roc_module::symbol::{IdentIds, ModuleId, Symbol};
|
||||||
|
@ -1427,6 +1427,62 @@ pub fn specialize_all<'a>(
|
||||||
procs
|
procs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn hacky_hacky_hack_hack<'a>(
|
||||||
|
env: &mut Env<'a, '_>,
|
||||||
|
fn_var: Variable,
|
||||||
|
body: roc_can::expr::Expr,
|
||||||
|
arg_symbols: &[Symbol],
|
||||||
|
) -> roc_can::expr::Expr {
|
||||||
|
match env.subs.get(fn_var).content {
|
||||||
|
Content::Structure(FlatType::Func(args, closure_var, ret_var)) => {
|
||||||
|
let temp = env.unique_symbol();
|
||||||
|
|
||||||
|
let pattern = roc_can::pattern::Pattern::Identifier(temp);
|
||||||
|
let mut pattern_vars = SendMap::default();
|
||||||
|
pattern_vars.insert(temp, fn_var);
|
||||||
|
let def = roc_can::def::Def {
|
||||||
|
loc_pattern: Located::at_zero(pattern),
|
||||||
|
loc_expr: Located::at_zero(body),
|
||||||
|
expr_var: fn_var,
|
||||||
|
pattern_vars,
|
||||||
|
annotation: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut arguments: std::vec::Vec<(Variable, Located<roc_can::expr::Expr>)> =
|
||||||
|
std::vec::Vec::new();
|
||||||
|
|
||||||
|
for (symbol, var) in arg_symbols.iter().zip(args.iter()) {
|
||||||
|
arguments.push((*var, Located::at_zero(roc_can::expr::Expr::Var(*symbol))));
|
||||||
|
}
|
||||||
|
|
||||||
|
use roc_module::operator::CalledVia;
|
||||||
|
// Box<(Variable, Located<Expr>, Variable, Variable)>,
|
||||||
|
let boxed = (
|
||||||
|
fn_var,
|
||||||
|
Located::at_zero(roc_can::expr::Expr::Var(temp)),
|
||||||
|
closure_var,
|
||||||
|
ret_var,
|
||||||
|
);
|
||||||
|
let call_temp = roc_can::expr::Expr::Call(Box::new(boxed), arguments, CalledVia::Space);
|
||||||
|
|
||||||
|
roc_can::expr::Expr::LetNonRec(
|
||||||
|
Box::new(def),
|
||||||
|
Box::new(Located::at_zero(call_temp)),
|
||||||
|
ret_var,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Content::Alias(_, _, actual) => hacky_hacky_hack_hack(env, actual, body, arg_symbols),
|
||||||
|
Content::Structure(FlatType::TagUnion(tags, _)) => {
|
||||||
|
let mut it = tags.iter();
|
||||||
|
let (_, args) = it.next().unwrap();
|
||||||
|
let mut it = args.iter();
|
||||||
|
let var = it.next().unwrap();
|
||||||
|
hacky_hacky_hack_hack(env, *var, body, arg_symbols)
|
||||||
|
}
|
||||||
|
other => unreachable!("{:?}", other),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn specialize_external<'a>(
|
fn specialize_external<'a>(
|
||||||
env: &mut Env<'a, '_>,
|
env: &mut Env<'a, '_>,
|
||||||
procs: &mut Procs<'a>,
|
procs: &mut Procs<'a>,
|
||||||
|
@ -1453,8 +1509,6 @@ fn specialize_external<'a>(
|
||||||
let is_valid = matches!(unified, roc_unify::unify::Unified::Success(_));
|
let is_valid = matches!(unified, roc_unify::unify::Unified::Success(_));
|
||||||
debug_assert!(is_valid);
|
debug_assert!(is_valid);
|
||||||
|
|
||||||
let mut specialized_body = from_can(env, fn_var, body, procs, layout_cache);
|
|
||||||
|
|
||||||
// if this is a closure, add the closure record argument
|
// if this is a closure, add the closure record argument
|
||||||
let pattern_symbols = if let CapturedSymbols::Captured(_) = captured_symbols {
|
let pattern_symbols = if let CapturedSymbols::Captured(_) = captured_symbols {
|
||||||
let mut temp = Vec::from_iter_in(pattern_symbols.iter().copied(), env.arena);
|
let mut temp = Vec::from_iter_in(pattern_symbols.iter().copied(), env.arena);
|
||||||
|
@ -1464,9 +1518,73 @@ fn specialize_external<'a>(
|
||||||
pattern_symbols
|
pattern_symbols
|
||||||
};
|
};
|
||||||
|
|
||||||
let (proc_args, opt_closure_layout, ret_layout) =
|
let spec_proc =
|
||||||
build_specialized_proc_from_var(env, layout_cache, proc_name, pattern_symbols, fn_var)?;
|
build_specialized_proc_from_var(env, layout_cache, proc_name, pattern_symbols, fn_var)?;
|
||||||
|
|
||||||
|
match spec_proc {
|
||||||
|
SpecializedLayout::EmptyClosure(arg_layouts, ret_layout) => {
|
||||||
|
let mut arg_symbols = Vec::new_in(env.arena);
|
||||||
|
for _ in arg_layouts.iter() {
|
||||||
|
arg_symbols.push(env.unique_symbol());
|
||||||
|
}
|
||||||
|
|
||||||
|
let new_body = hacky_hacky_hack_hack(env, fn_var, body, &arg_symbols);
|
||||||
|
|
||||||
|
let specialized_body = from_can(env, fn_var, new_body, procs, layout_cache);
|
||||||
|
// determine the layout of aliases/rigids exposed to the host
|
||||||
|
let host_exposed_layouts = if host_exposed_variables.is_empty() {
|
||||||
|
HostExposedLayouts::NotHostExposed
|
||||||
|
} else {
|
||||||
|
let mut aliases = MutMap::default();
|
||||||
|
|
||||||
|
for (symbol, variable) in host_exposed_variables {
|
||||||
|
let layout = layout_cache
|
||||||
|
.from_var(env.arena, *variable, env.subs)
|
||||||
|
.unwrap();
|
||||||
|
aliases.insert(*symbol, layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
HostExposedLayouts::HostExposed {
|
||||||
|
rigids: MutMap::default(),
|
||||||
|
aliases,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// reset subs, so we don't get type errors when specializing for a different signature
|
||||||
|
layout_cache.rollback_to(cache_snapshot);
|
||||||
|
env.subs.rollback_to(snapshot);
|
||||||
|
|
||||||
|
let recursivity = if is_self_recursive {
|
||||||
|
SelfRecursive::SelfRecursive(JoinPointId(env.unique_symbol()))
|
||||||
|
} else {
|
||||||
|
SelfRecursive::NotSelfRecursive
|
||||||
|
};
|
||||||
|
|
||||||
|
let closure_data_layout = None;
|
||||||
|
|
||||||
|
let proc_args = Vec::from_iter_in(
|
||||||
|
arg_symbols
|
||||||
|
.iter()
|
||||||
|
.zip(arg_layouts.into_iter())
|
||||||
|
.map(|(s, l)| (l.clone(), *s)),
|
||||||
|
env.arena,
|
||||||
|
);
|
||||||
|
let proc_args = proc_args.into_bump_slice();
|
||||||
|
|
||||||
|
let proc = Proc {
|
||||||
|
name: proc_name,
|
||||||
|
args: proc_args,
|
||||||
|
body: specialized_body,
|
||||||
|
closure_data_layout,
|
||||||
|
ret_layout,
|
||||||
|
is_self_recursive: recursivity,
|
||||||
|
host_exposed_layouts,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(proc)
|
||||||
|
}
|
||||||
|
SpecializedLayout::Normal(proc_args, opt_closure_layout, ret_layout) => {
|
||||||
|
let mut specialized_body = from_can(env, fn_var, body, procs, layout_cache);
|
||||||
// unpack the closure symbols, if any
|
// unpack the closure symbols, if any
|
||||||
if let CapturedSymbols::Captured(captured) = captured_symbols {
|
if let CapturedSymbols::Captured(captured) = captured_symbols {
|
||||||
let mut layouts = Vec::with_capacity_in(captured.len(), env.arena);
|
let mut layouts = Vec::with_capacity_in(captured.len(), env.arena);
|
||||||
|
@ -1494,7 +1612,8 @@ fn specialize_external<'a>(
|
||||||
// layout is cached anyway, re-using the one found above leads to
|
// layout is cached anyway, re-using the one found above leads to
|
||||||
// issues (combining by-ref and by-move in pattern match
|
// issues (combining by-ref and by-move in pattern match
|
||||||
let layout = layout_cache.from_var(env.arena, *variable, env.subs)?;
|
let layout = layout_cache.from_var(env.arena, *variable, env.subs)?;
|
||||||
specialized_body = Stmt::Let(*symbol, expr, layout, env.arena.alloc(specialized_body));
|
specialized_body =
|
||||||
|
Stmt::Let(*symbol, expr, layout, env.arena.alloc(specialized_body));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1543,13 +1662,18 @@ fn specialize_external<'a>(
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(proc)
|
Ok(proc)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type SpecializedLayout<'a> = (
|
enum SpecializedLayout<'a> {
|
||||||
|
Normal(
|
||||||
&'a [(Layout<'a>, Symbol)],
|
&'a [(Layout<'a>, Symbol)],
|
||||||
Option<ClosureLayout<'a>>,
|
Option<ClosureLayout<'a>>,
|
||||||
Layout<'a>,
|
Layout<'a>,
|
||||||
);
|
),
|
||||||
|
EmptyClosure(&'a [Layout<'a>], Layout<'a>),
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
fn build_specialized_proc_from_var<'a>(
|
fn build_specialized_proc_from_var<'a>(
|
||||||
|
@ -1669,14 +1793,17 @@ fn build_specialized_proc_adapter<'a>(
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
fn build_specialized_proc<'a>(
|
fn build_specialized_proc<'a>(
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
_proc_name: Symbol,
|
proc_name: Symbol,
|
||||||
pattern_symbols: &[Symbol],
|
pattern_symbols: &[Symbol],
|
||||||
pattern_layouts: Vec<Layout<'a>>,
|
pattern_layouts: Vec<'a, Layout<'a>>,
|
||||||
opt_closure_layout: Option<ClosureLayout<'a>>,
|
opt_closure_layout: Option<ClosureLayout<'a>>,
|
||||||
ret_layout: Layout<'a>,
|
ret_layout: Layout<'a>,
|
||||||
) -> Result<SpecializedLayout<'a>, LayoutProblem> {
|
) -> Result<SpecializedLayout<'a>, LayoutProblem> {
|
||||||
|
use SpecializedLayout::*;
|
||||||
|
|
||||||
let mut proc_args = Vec::with_capacity_in(pattern_layouts.len(), arena);
|
let mut proc_args = Vec::with_capacity_in(pattern_layouts.len(), arena);
|
||||||
|
|
||||||
|
let pattern_layouts_slice = pattern_layouts.clone().into_bump_slice();
|
||||||
let pattern_layouts_len = pattern_layouts.len();
|
let pattern_layouts_len = pattern_layouts.len();
|
||||||
|
|
||||||
for (arg_layout, arg_name) in pattern_layouts.into_iter().zip(pattern_symbols.iter()) {
|
for (arg_layout, arg_name) in pattern_layouts.into_iter().zip(pattern_symbols.iter()) {
|
||||||
|
@ -1714,7 +1841,7 @@ fn build_specialized_proc<'a>(
|
||||||
|
|
||||||
let proc_args = proc_args.into_bump_slice();
|
let proc_args = proc_args.into_bump_slice();
|
||||||
|
|
||||||
Ok((proc_args, Some(layout), ret_layout))
|
Ok(Normal(proc_args, Some(layout), ret_layout))
|
||||||
}
|
}
|
||||||
Some(layout) => {
|
Some(layout) => {
|
||||||
// else if there is a closure layout, we're building the `f_closure` value
|
// else if there is a closure layout, we're building the `f_closure` value
|
||||||
|
@ -1729,7 +1856,7 @@ fn build_specialized_proc<'a>(
|
||||||
let closure_layout =
|
let closure_layout =
|
||||||
Layout::Struct(arena.alloc([function_ptr_layout, closure_data_layout]));
|
Layout::Struct(arena.alloc([function_ptr_layout, closure_data_layout]));
|
||||||
|
|
||||||
Ok((&[], None, closure_layout))
|
Ok(Normal(&[], None, closure_layout))
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
// else we're making a normal function, no closure problems to worry about
|
// else we're making a normal function, no closure problems to worry about
|
||||||
|
@ -1738,16 +1865,15 @@ fn build_specialized_proc<'a>(
|
||||||
// make sure there is not arg_closure argument without a closure layout
|
// make sure there is not arg_closure argument without a closure layout
|
||||||
debug_assert!(pattern_symbols.last() != Some(&Symbol::ARG_CLOSURE));
|
debug_assert!(pattern_symbols.last() != Some(&Symbol::ARG_CLOSURE));
|
||||||
|
|
||||||
// since this is not a closure, the number of arguments should match between symbols
|
match pattern_layouts_len - pattern_symbols.len() {
|
||||||
// and layout
|
0 => {
|
||||||
debug_assert_eq!(
|
|
||||||
pattern_layouts_len,
|
|
||||||
pattern_symbols.len(),
|
|
||||||
"Tried to zip two vecs with different lengths!"
|
|
||||||
);
|
|
||||||
let proc_args = proc_args.into_bump_slice();
|
let proc_args = proc_args.into_bump_slice();
|
||||||
|
|
||||||
Ok((proc_args, None, ret_layout))
|
Ok(Normal(proc_args, None, ret_layout))
|
||||||
|
}
|
||||||
|
1 => Ok(EmptyClosure(pattern_layouts_slice, ret_layout)),
|
||||||
|
_ => panic!(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,10 +109,8 @@ impl<'a> ClosureLayout<'a> {
|
||||||
|
|
||||||
use UnionVariant::*;
|
use UnionVariant::*;
|
||||||
match variant {
|
match variant {
|
||||||
Never | Unit => {
|
Never => Ok(None),
|
||||||
// a max closure size of 0 means this is a standard top-level function
|
Unit => Ok(None),
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
BoolUnion { .. } => {
|
BoolUnion { .. } => {
|
||||||
let closure_layout = ClosureLayout::from_bool(arena);
|
let closure_layout = ClosureLayout::from_bool(arena);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue