mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 22:09:09 +00:00
Merge branch 'trunk' of github.com:rtfeldman/roc into rename-map-to-dict
This commit is contained in:
commit
61728fd1d1
60 changed files with 1871 additions and 1302 deletions
|
@ -73,11 +73,9 @@ impl<'a> ClosureLayout<'a> {
|
|||
}
|
||||
fn from_unwrapped(arena: &'a Bump, layouts: &'a [Layout<'a>]) -> Self {
|
||||
debug_assert!(!layouts.is_empty());
|
||||
let layout = if layouts.len() == 1 {
|
||||
&layouts[0]
|
||||
} else {
|
||||
arena.alloc(Layout::Struct(layouts))
|
||||
};
|
||||
|
||||
// DO NOT unwrap 1-element records here!
|
||||
let layout = arena.alloc(Layout::Struct(layouts));
|
||||
|
||||
ClosureLayout {
|
||||
captured: &[],
|
||||
|
@ -88,6 +86,9 @@ impl<'a> ClosureLayout<'a> {
|
|||
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() {
|
||||
|
@ -104,6 +105,7 @@ impl<'a> ClosureLayout<'a> {
|
|||
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,
|
||||
|
@ -118,7 +120,15 @@ impl<'a> ClosureLayout<'a> {
|
|||
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() => {
|
||||
// this is a closure
|
||||
// special-case the `[ Closure1, Closure2, Closure3 ]` case, where none of
|
||||
// the tags have a payload
|
||||
let all_no_payload = tags.iter().all(|(_, arguments)| arguments.is_empty());
|
||||
|
||||
if all_no_payload {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
// otherwise, this is a closure with a payload
|
||||
let variant = union_sorted_tags_help(arena, tags, None, subs);
|
||||
|
||||
use UnionVariant::*;
|
||||
|
@ -148,9 +158,9 @@ impl<'a> ClosureLayout<'a> {
|
|||
Ok(Some(closure_layout))
|
||||
}
|
||||
Wrapped(tags) => {
|
||||
// Wrapped(Vec<'a, (TagName, &'a [Layout<'a>])>),
|
||||
let closure_layout =
|
||||
ClosureLayout::from_tag_union(arena, tags.into_bump_slice());
|
||||
|
||||
Ok(Some(closure_layout))
|
||||
}
|
||||
}
|
||||
|
@ -170,7 +180,10 @@ impl<'a> ClosureLayout<'a> {
|
|||
closure_layout: Self,
|
||||
ret_layout: &'a Layout<'a>,
|
||||
) -> Layout<'a> {
|
||||
let closure_data_layout = closure_layout.layout;
|
||||
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 = {
|
||||
|
@ -194,7 +207,10 @@ impl<'a> ClosureLayout<'a> {
|
|||
|
||||
pub fn as_named_layout(&self, symbol: Symbol) -> Layout<'a> {
|
||||
let layouts = if self.captured.is_empty() {
|
||||
self.layout.clone()
|
||||
match self.layout {
|
||||
Layout::Struct(fields) if fields.len() == 1 => fields[0].clone(),
|
||||
other => other.clone(),
|
||||
}
|
||||
} else if let Some((_, tag_args)) = self
|
||||
.captured
|
||||
.iter()
|
||||
|
@ -216,6 +232,13 @@ impl<'a> ClosureLayout<'a> {
|
|||
}
|
||||
|
||||
pub fn as_block_of_memory_layout(&self) -> Layout<'a> {
|
||||
match self.layout {
|
||||
Layout::Struct(fields) if fields.len() == 1 => fields[0].clone(),
|
||||
other => other.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn internal_layout(&self) -> Layout<'a> {
|
||||
self.layout.clone()
|
||||
}
|
||||
|
||||
|
@ -227,6 +250,7 @@ impl<'a> ClosureLayout<'a> {
|
|||
use crate::ir::Expr;
|
||||
|
||||
match self.layout {
|
||||
Layout::Struct(fields) if fields.len() == 1 => Err(symbols[0]),
|
||||
Layout::Struct(fields) => {
|
||||
debug_assert!(fields.len() > 1);
|
||||
debug_assert_eq!(fields.len(), symbols.len());
|
||||
|
@ -234,6 +258,8 @@ impl<'a> ClosureLayout<'a> {
|
|||
Ok(Expr::Struct(symbols))
|
||||
}
|
||||
Layout::Union(tags) => {
|
||||
// NOTE it's very important that this Union consists of Closure tags
|
||||
// and is not an unpacked 1-element record
|
||||
let expr = Expr::Tag {
|
||||
tag_layout: Layout::Union(tags),
|
||||
tag_name: TagName::Closure(original),
|
||||
|
@ -251,7 +277,13 @@ impl<'a> ClosureLayout<'a> {
|
|||
}
|
||||
|
||||
_ => {
|
||||
debug_assert_eq!(symbols.len(), 1);
|
||||
debug_assert_eq!(
|
||||
symbols.len(),
|
||||
1,
|
||||
"symbols {:?} for layout {:?}",
|
||||
&symbols,
|
||||
&self.layout
|
||||
);
|
||||
|
||||
Err(symbols[0])
|
||||
}
|
||||
|
@ -387,7 +419,8 @@ impl<'a> Layout<'a> {
|
|||
if let Layout::PhantomEmptyStruct = self {
|
||||
false
|
||||
} else {
|
||||
self.stack_size(1) == 0
|
||||
// self.stack_size(1) == 0
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue