mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 05:49:08 +00:00
Describe how a enum lambda set should be switched in the representation
This commit is contained in:
parent
f5e3105b37
commit
a93735473a
2 changed files with 43 additions and 48 deletions
|
@ -1,8 +1,8 @@
|
||||||
#![allow(clippy::manual_map)]
|
#![allow(clippy::manual_map)]
|
||||||
|
|
||||||
use crate::layout::{
|
use crate::layout::{
|
||||||
Builtin, CapturesNiche, ClosureCallOptions, ClosureRepresentation, LambdaName, LambdaSet,
|
Builtin, CapturesNiche, ClosureCallOptions, ClosureRepresentation, EnumDispatch, LambdaName,
|
||||||
Layout, LayoutCache, LayoutProblem, RawFunctionLayout, TagIdIntType, UnionLayout,
|
LambdaSet, Layout, LayoutCache, LayoutProblem, RawFunctionLayout, TagIdIntType, UnionLayout,
|
||||||
WrappedVariant,
|
WrappedVariant,
|
||||||
};
|
};
|
||||||
use bumpalo::collections::{CollectIn, Vec};
|
use bumpalo::collections::{CollectIn, Vec};
|
||||||
|
@ -3269,23 +3269,10 @@ fn specialize_external<'a>(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClosureRepresentation::MultiDispatch(layout) => match layout {
|
ClosureRepresentation::EnumDispatch(_) => {
|
||||||
Layout::Builtin(Builtin::Bool) => {
|
|
||||||
// just ignore this value, since it's not a capture
|
// just ignore this value, since it's not a capture
|
||||||
// IDEA don't pass this value in the future
|
// IDEA don't pass this value in the future
|
||||||
}
|
}
|
||||||
Layout::Builtin(Builtin::Int(IntWidth::U8)) => {
|
|
||||||
// just ignore this value, since it's not a capture
|
|
||||||
// IDEA don't pass this value in the future
|
|
||||||
}
|
|
||||||
other => {
|
|
||||||
// NOTE other values always should be wrapped in a 1-element record
|
|
||||||
unreachable!(
|
|
||||||
"{:?} is not a valid closure data representation",
|
|
||||||
other
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(None, CapturedSymbols::None) | (None, CapturedSymbols::Captured([])) => {}
|
(None, CapturedSymbols::None) | (None, CapturedSymbols::Captured([])) => {}
|
||||||
|
@ -5448,8 +5435,8 @@ where
|
||||||
hole,
|
hole,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ClosureRepresentation::MultiDispatch(layout) => match layout {
|
ClosureRepresentation::EnumDispatch(repr) => match repr {
|
||||||
Layout::Builtin(Builtin::Bool) => {
|
EnumDispatch::Bool => {
|
||||||
debug_assert_eq!(symbols.len(), 0);
|
debug_assert_eq!(symbols.len(), 0);
|
||||||
|
|
||||||
debug_assert_eq!(lambda_set.set.len(), 2);
|
debug_assert_eq!(lambda_set.set.len(), 2);
|
||||||
|
@ -5458,7 +5445,7 @@ where
|
||||||
|
|
||||||
Stmt::Let(assigned, expr, lambda_set_layout, hole)
|
Stmt::Let(assigned, expr, lambda_set_layout, hole)
|
||||||
}
|
}
|
||||||
Layout::Builtin(Builtin::Int(IntWidth::U8)) => {
|
EnumDispatch::U8 => {
|
||||||
debug_assert_eq!(symbols.len(), 0);
|
debug_assert_eq!(symbols.len(), 0);
|
||||||
|
|
||||||
debug_assert!(lambda_set.set.len() > 2);
|
debug_assert!(lambda_set.set.len() > 2);
|
||||||
|
@ -5471,9 +5458,6 @@ where
|
||||||
|
|
||||||
Stmt::Let(assigned, expr, lambda_set_layout, hole)
|
Stmt::Let(assigned, expr, lambda_set_layout, hole)
|
||||||
}
|
}
|
||||||
layout => {
|
|
||||||
internal_error!("Invalid layout for multi-dispatch closure: {:?}", layout)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -9228,8 +9212,8 @@ where
|
||||||
|
|
||||||
build_call(env, call, assigned, return_layout, env.arena.alloc(hole))
|
build_call(env, call, assigned, return_layout, env.arena.alloc(hole))
|
||||||
}
|
}
|
||||||
ClosureCallOptions::MultiDispatch(layout) => match layout {
|
ClosureCallOptions::EnumDispatch(repr) => match repr {
|
||||||
Layout::Builtin(Builtin::Bool) => {
|
EnumDispatch::Bool => {
|
||||||
let closure_tag_id_symbol = closure_data_symbol;
|
let closure_tag_id_symbol = closure_data_symbol;
|
||||||
|
|
||||||
lowlevel_enum_lambda_set_to_switch(
|
lowlevel_enum_lambda_set_to_switch(
|
||||||
|
@ -9245,7 +9229,7 @@ where
|
||||||
hole,
|
hole,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Layout::Builtin(Builtin::Int(IntWidth::U8)) => {
|
EnumDispatch::U8 => {
|
||||||
let closure_tag_id_symbol = closure_data_symbol;
|
let closure_tag_id_symbol = closure_data_symbol;
|
||||||
|
|
||||||
lowlevel_enum_lambda_set_to_switch(
|
lowlevel_enum_lambda_set_to_switch(
|
||||||
|
@ -9261,7 +9245,6 @@ where
|
||||||
hole,
|
hole,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
other => internal_error!("Unexpected multi-dispatch layout: {:?}", other),
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9446,8 +9429,8 @@ fn match_on_lambda_set<'a>(
|
||||||
hole,
|
hole,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ClosureCallOptions::MultiDispatch(layout) => match layout {
|
ClosureCallOptions::EnumDispatch(repr) => match repr {
|
||||||
Layout::Builtin(Builtin::Bool) => {
|
EnumDispatch::Bool => {
|
||||||
let closure_tag_id_symbol = closure_data_symbol;
|
let closure_tag_id_symbol = closure_data_symbol;
|
||||||
|
|
||||||
enum_lambda_set_to_switch(
|
enum_lambda_set_to_switch(
|
||||||
|
@ -9462,7 +9445,7 @@ fn match_on_lambda_set<'a>(
|
||||||
hole,
|
hole,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Layout::Builtin(Builtin::Int(IntWidth::U8)) => {
|
EnumDispatch::U8 => {
|
||||||
let closure_tag_id_symbol = closure_data_symbol;
|
let closure_tag_id_symbol = closure_data_symbol;
|
||||||
|
|
||||||
enum_lambda_set_to_switch(
|
enum_lambda_set_to_switch(
|
||||||
|
@ -9477,7 +9460,6 @@ fn match_on_lambda_set<'a>(
|
||||||
hole,
|
hole,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
other => internal_error!("Unexpected multi-dispatch layout: {:?}", other),
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -788,6 +788,12 @@ pub struct LambdaSet<'a> {
|
||||||
representation: &'a Layout<'a>,
|
representation: &'a Layout<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum EnumDispatch {
|
||||||
|
Bool,
|
||||||
|
U8,
|
||||||
|
}
|
||||||
|
|
||||||
/// representation of the closure *for a particular function*
|
/// representation of the closure *for a particular function*
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ClosureRepresentation<'a> {
|
pub enum ClosureRepresentation<'a> {
|
||||||
|
@ -804,11 +810,11 @@ pub enum ClosureRepresentation<'a> {
|
||||||
///
|
///
|
||||||
/// We MUST sort these according to their stack size before code gen!
|
/// We MUST sort these according to their stack size before code gen!
|
||||||
AlphabeticOrderStruct(&'a [Layout<'a>]),
|
AlphabeticOrderStruct(&'a [Layout<'a>]),
|
||||||
/// The closure dispatches to multiple functions, but none of them capture anything, so this is
|
|
||||||
/// a boolean or integer flag.
|
|
||||||
MultiDispatch(Layout<'a>),
|
|
||||||
/// The closure is one function that captures a single identifier, whose value is unwrapped.
|
/// The closure is one function that captures a single identifier, whose value is unwrapped.
|
||||||
UnwrappedCapture(Layout<'a>),
|
UnwrappedCapture(Layout<'a>),
|
||||||
|
/// The closure dispatches to multiple functions, but none of them capture anything, so this is
|
||||||
|
/// a boolean or integer flag.
|
||||||
|
EnumDispatch(EnumDispatch),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// How the closure should be seen when determining a call-by-name.
|
/// How the closure should be seen when determining a call-by-name.
|
||||||
|
@ -823,10 +829,10 @@ pub enum ClosureCallOptions<'a> {
|
||||||
field_layouts: &'a [Layout<'a>],
|
field_layouts: &'a [Layout<'a>],
|
||||||
field_order_hash: FieldOrderHash,
|
field_order_hash: FieldOrderHash,
|
||||||
},
|
},
|
||||||
/// The closure dispatches to multiple possible functions, none of which capture.
|
|
||||||
MultiDispatch(Layout<'a>),
|
|
||||||
/// The closure is one function that captures a single identifier, whose value is unwrapped.
|
/// The closure is one function that captures a single identifier, whose value is unwrapped.
|
||||||
UnwrappedCapture(Layout<'a>),
|
UnwrappedCapture(Layout<'a>),
|
||||||
|
/// The closure dispatches to multiple possible functions, none of which capture.
|
||||||
|
EnumDispatch(EnumDispatch),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> LambdaSet<'a> {
|
impl<'a> LambdaSet<'a> {
|
||||||
|
@ -842,7 +848,7 @@ impl<'a> LambdaSet<'a> {
|
||||||
pub fn is_represented(&self) -> Option<Layout<'a>> {
|
pub fn is_represented(&self) -> Option<Layout<'a>> {
|
||||||
if self.has_unwrapped_capture_repr() {
|
if self.has_unwrapped_capture_repr() {
|
||||||
Some(*self.representation)
|
Some(*self.representation)
|
||||||
} else if self.has_multi_dispatch_repr() {
|
} else if self.has_enum_dispatch_repr() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
match self.representation {
|
match self.representation {
|
||||||
|
@ -1036,11 +1042,13 @@ impl<'a> LambdaSet<'a> {
|
||||||
ClosureRepresentation::AlphabeticOrderStruct(fields)
|
ClosureRepresentation::AlphabeticOrderStruct(fields)
|
||||||
}
|
}
|
||||||
layout => {
|
layout => {
|
||||||
debug_assert!(
|
debug_assert!(self.has_enum_dispatch_repr(),);
|
||||||
self.has_multi_dispatch_repr(),
|
let enum_repr = match layout {
|
||||||
"Expected this to be a multi-dispatching closure, but it was something else!"
|
Layout::Builtin(Builtin::Bool) => EnumDispatch::Bool,
|
||||||
);
|
Layout::Builtin(Builtin::Int(IntWidth::U8)) => EnumDispatch::U8,
|
||||||
ClosureRepresentation::MultiDispatch(*layout)
|
other => internal_error!("Invalid layout for enum dispatch: {:?}", other),
|
||||||
|
};
|
||||||
|
ClosureRepresentation::EnumDispatch(enum_repr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1049,7 +1057,7 @@ impl<'a> LambdaSet<'a> {
|
||||||
self.set.len() == 1 && self.set[0].1.len() == 1
|
self.set.len() == 1 && self.set[0].1.len() == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_multi_dispatch_repr(&self) -> bool {
|
fn has_enum_dispatch_repr(&self) -> bool {
|
||||||
self.set.len() > 1 && self.set.iter().all(|(_, captures)| captures.is_empty())
|
self.set.len() > 1 && self.set.iter().all(|(_, captures)| captures.is_empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1077,8 +1085,13 @@ impl<'a> LambdaSet<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
layout => {
|
layout => {
|
||||||
debug_assert!(self.has_multi_dispatch_repr());
|
debug_assert!(self.has_enum_dispatch_repr());
|
||||||
ClosureCallOptions::MultiDispatch(*layout)
|
let enum_repr = match layout {
|
||||||
|
Layout::Builtin(Builtin::Bool) => EnumDispatch::Bool,
|
||||||
|
Layout::Builtin(Builtin::Int(IntWidth::U8)) => EnumDispatch::U8,
|
||||||
|
other => internal_error!("Invalid layout for enum dispatch: {:?}", other),
|
||||||
|
};
|
||||||
|
ClosureCallOptions::EnumDispatch(enum_repr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1106,7 +1119,7 @@ impl<'a> LambdaSet<'a> {
|
||||||
|
|
||||||
arguments.into_bump_slice()
|
arguments.into_bump_slice()
|
||||||
}
|
}
|
||||||
ClosureCallOptions::MultiDispatch(_) => {
|
ClosureCallOptions::EnumDispatch(_) => {
|
||||||
// No captures, don't pass this along
|
// No captures, don't pass this along
|
||||||
argument_layouts
|
argument_layouts
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue