mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 13:59:08 +00:00
remove ClosureData type
This commit is contained in:
parent
e63eea7389
commit
051712c90b
1 changed files with 0 additions and 276 deletions
|
@ -300,282 +300,6 @@ impl<'a> LambdaSet<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct ClosureLayout<'a> {
|
||||
/// the layout that this specific closure captures
|
||||
/// uses a Vec instead of a MutMap because it's Hash
|
||||
/// the vec is likely to be small, so linear search is fine
|
||||
pub captured: &'a [(TagName, &'a [Layout<'a>])],
|
||||
|
||||
/// use with care; there is some stuff happening here re. unwrapping
|
||||
/// one-element records that might cause issues
|
||||
pub layout: &'a Layout<'a>,
|
||||
}
|
||||
|
||||
impl<'a> ClosureLayout<'a> {
|
||||
fn from_unit(arena: &'a Bump) -> Self {
|
||||
let layout = Layout::PhantomEmptyStruct;
|
||||
let layouts = arena.alloc(layout);
|
||||
ClosureLayout {
|
||||
captured: &[],
|
||||
layout: layouts,
|
||||
}
|
||||
}
|
||||
fn from_bool(arena: &'a Bump) -> Self {
|
||||
let layout = Layout::Builtin(Builtin::Int1);
|
||||
let layouts = arena.alloc(layout);
|
||||
ClosureLayout {
|
||||
captured: &[],
|
||||
layout: layouts,
|
||||
}
|
||||
}
|
||||
fn from_byte(arena: &'a Bump) -> Self {
|
||||
let layout = Layout::Builtin(Builtin::Int8);
|
||||
let layouts = arena.alloc(layout);
|
||||
ClosureLayout {
|
||||
captured: &[],
|
||||
layout: layouts,
|
||||
}
|
||||
}
|
||||
fn from_unwrapped(arena: &'a Bump, tag_name: TagName, layouts: &'a [Layout<'a>]) -> Self {
|
||||
debug_assert!(!layouts.is_empty());
|
||||
|
||||
// DO NOT unwrap 1-element records here!
|
||||
let layout = arena.alloc(Layout::Struct(layouts));
|
||||
|
||||
ClosureLayout {
|
||||
captured: &*arena.alloc([(tag_name, &*arena.alloc([*layout]) as &[_])]),
|
||||
layout,
|
||||
}
|
||||
}
|
||||
|
||||
fn from_tag_union(arena: &'a Bump, tags: &'a [(TagName, &'a [Layout<'a>])]) -> Self {
|
||||
debug_assert!(tags.len() > 1);
|
||||
|
||||
// if the closed-over value is actually a layout, it should be wrapped in a 1-element record
|
||||
debug_assert!(matches!(tags[0].0, TagName::Closure(_)));
|
||||
|
||||
let mut tag_arguments = Vec::with_capacity_in(tags.len(), arena);
|
||||
|
||||
for (_, tag_args) in tags.iter() {
|
||||
tag_arguments.push(&tag_args[0..]);
|
||||
}
|
||||
|
||||
ClosureLayout {
|
||||
captured: tags,
|
||||
layout: arena.alloc(Layout::Union(UnionLayout::NonRecursive(
|
||||
tag_arguments.into_bump_slice(),
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_wrapped(&self) -> crate::ir::Wrapped {
|
||||
use crate::ir::Wrapped;
|
||||
|
||||
match self.layout {
|
||||
Layout::Struct(fields) if fields.len() == 1 => Wrapped::SingleElementRecord,
|
||||
Layout::Struct(_) => Wrapped::RecordOrSingleTagUnion,
|
||||
Layout::Union(_) => Wrapped::MultiTagUnion,
|
||||
_ => Wrapped::SingleElementRecord,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_var(
|
||||
arena: &'a Bump,
|
||||
subs: &Subs,
|
||||
closure_var: Variable,
|
||||
) -> Result<Option<Self>, LayoutProblem> {
|
||||
let mut tags = std::vec::Vec::new();
|
||||
match roc_types::pretty_print::chase_ext_tag_union(subs, closure_var, &mut tags) {
|
||||
Ok(()) | Err((_, Content::FlexVar(_))) if !tags.is_empty() => {
|
||||
// otherwise, this is a closure with a payload
|
||||
let variant = union_sorted_tags_help(arena, tags, None, subs);
|
||||
|
||||
use UnionVariant::*;
|
||||
match variant {
|
||||
Never | Unit | UnitWithArguments => {
|
||||
// the closure layout is zero-sized, but there is something in it (e.g. `{}`)
|
||||
|
||||
let closure_layout = ClosureLayout::from_unit(arena);
|
||||
Ok(Some(closure_layout))
|
||||
}
|
||||
BoolUnion { .. } => {
|
||||
let closure_layout = ClosureLayout::from_bool(arena);
|
||||
|
||||
Ok(Some(closure_layout))
|
||||
}
|
||||
ByteUnion(_) => {
|
||||
let closure_layout = ClosureLayout::from_byte(arena);
|
||||
|
||||
Ok(Some(closure_layout))
|
||||
}
|
||||
Unwrapped(tag_name, layouts) => {
|
||||
let closure_layout = ClosureLayout::from_unwrapped(
|
||||
arena,
|
||||
tag_name,
|
||||
layouts.into_bump_slice(),
|
||||
);
|
||||
|
||||
Ok(Some(closure_layout))
|
||||
}
|
||||
Wrapped(variant) => {
|
||||
use WrappedVariant::*;
|
||||
|
||||
match variant {
|
||||
NonRecursive {
|
||||
sorted_tag_layouts: tags,
|
||||
} => {
|
||||
let closure_layout =
|
||||
ClosureLayout::from_tag_union(arena, tags.into_bump_slice());
|
||||
Ok(Some(closure_layout))
|
||||
}
|
||||
|
||||
_ => panic!("handle recursive layouts"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(()) | Err((_, Content::FlexVar(_))) => {
|
||||
// a max closure size of 0 means this is a standart top-level function
|
||||
Ok(None)
|
||||
}
|
||||
_ => panic!("called ClosureLayout.from_var on invalid input"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extend_function_layout(
|
||||
arena: &'a Bump,
|
||||
argument_layouts: &'a [Layout<'a>],
|
||||
closure_layout: Self,
|
||||
ret_layout: &'a Layout<'a>,
|
||||
) -> Layout<'a> {
|
||||
let closure_data_layout = match closure_layout.layout {
|
||||
Layout::Struct(fields) if fields.len() == 1 => &fields[0],
|
||||
other => other,
|
||||
};
|
||||
|
||||
// define the function pointer
|
||||
let function_ptr_layout = {
|
||||
let mut temp = Vec::from_iter_in(argument_layouts.iter().cloned(), arena);
|
||||
temp.push(*closure_data_layout);
|
||||
Layout::FunctionPointer(temp.into_bump_slice(), ret_layout)
|
||||
};
|
||||
|
||||
function_ptr_layout
|
||||
}
|
||||
|
||||
pub fn stack_size(&self, pointer_size: u32) -> u32 {
|
||||
self.layout.stack_size(pointer_size)
|
||||
}
|
||||
pub fn contains_refcounted(&self) -> bool {
|
||||
self.layout.contains_refcounted()
|
||||
}
|
||||
pub fn safe_to_memcpy(&self) -> bool {
|
||||
self.layout.safe_to_memcpy()
|
||||
}
|
||||
|
||||
pub fn as_named_layout(&self, symbol: Symbol) -> Layout<'a> {
|
||||
let layouts = if self.captured.is_empty() {
|
||||
match self.layout {
|
||||
Layout::Struct(fields) if fields.len() == 1 => fields[0],
|
||||
other => *other,
|
||||
}
|
||||
} else if let Some((_, tag_args)) = self
|
||||
.captured
|
||||
.iter()
|
||||
.find(|(tn, _)| *tn == TagName::Closure(symbol))
|
||||
{
|
||||
if tag_args.len() == 1 {
|
||||
tag_args[0]
|
||||
} else {
|
||||
Layout::Struct(tag_args)
|
||||
}
|
||||
} else {
|
||||
unreachable!(
|
||||
"invariant broken, TagName::Closure({:?}) is not in {:?}",
|
||||
symbol, &self.captured
|
||||
);
|
||||
};
|
||||
|
||||
layouts
|
||||
}
|
||||
|
||||
pub fn as_block_of_memory_layout(&self) -> Layout<'a> {
|
||||
match self.layout {
|
||||
Layout::Struct(fields) if fields.len() == 1 => fields[0],
|
||||
other => *other,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn internal_layout(&self) -> Layout<'a> {
|
||||
*self.layout
|
||||
}
|
||||
|
||||
pub fn build_closure_data(
|
||||
&self,
|
||||
original: Symbol,
|
||||
symbols: &'a [Symbol],
|
||||
) -> BuildClosureData<'a> {
|
||||
use crate::ir::Expr;
|
||||
|
||||
match self.layout {
|
||||
Layout::Struct(fields) if fields.len() == 1 => BuildClosureData::Alias(symbols[0]),
|
||||
Layout::Struct(fields) => {
|
||||
debug_assert!(fields.len() > 1);
|
||||
debug_assert_eq!(fields.len(), symbols.len());
|
||||
|
||||
BuildClosureData::Struct(Expr::Struct(symbols))
|
||||
}
|
||||
Layout::Union(UnionLayout::NonRecursive(tags)) => {
|
||||
// NOTE it's very important that this Union consists of Closure tags
|
||||
// and is not an unpacked 1-element record
|
||||
|
||||
let tag_id = self
|
||||
.captured
|
||||
.iter()
|
||||
.position(|(tn, _)| *tn == TagName::Closure(original))
|
||||
.unwrap() as _;
|
||||
|
||||
BuildClosureData::Union {
|
||||
tag_layout: Layout::Union(UnionLayout::NonRecursive(tags)),
|
||||
tag_name: TagName::Closure(original),
|
||||
tag_id,
|
||||
union_size: tags.len() as u8,
|
||||
}
|
||||
}
|
||||
Layout::PhantomEmptyStruct => {
|
||||
debug_assert_eq!(symbols.len(), 1);
|
||||
|
||||
BuildClosureData::Struct(Expr::Struct(&[]))
|
||||
}
|
||||
|
||||
_ => {
|
||||
debug_assert_eq!(
|
||||
symbols.len(),
|
||||
1,
|
||||
"symbols {:?} for layout {:?}",
|
||||
&symbols,
|
||||
&self.layout
|
||||
);
|
||||
|
||||
BuildClosureData::Alias(symbols[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum BuildClosureData<'a> {
|
||||
Alias(Symbol),
|
||||
Struct(crate::ir::Expr<'a>),
|
||||
Union {
|
||||
tag_layout: Layout<'a>,
|
||||
tag_name: TagName,
|
||||
tag_id: u8,
|
||||
union_size: u8,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Copy)]
|
||||
pub enum MemoryMode {
|
||||
Unique,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue