mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 00:24:34 +00:00
Wrap layouts in a LayoutRepr
constructor
Part 1 of support semantic layout representations.
This commit is contained in:
parent
c2d2bd4bb9
commit
c3eeb5e2cc
32 changed files with 1254 additions and 1021 deletions
|
@ -12,6 +12,8 @@ use roc_collections::{default_hasher, BumpMap};
|
|||
use roc_module::symbol::Symbol;
|
||||
use roc_target::TargetInfo;
|
||||
|
||||
use crate::layout::LayoutRepr;
|
||||
|
||||
use super::{Builtin, FieldOrderHash, LambdaSet, Layout, SeenRecPtrs, UnionLayout};
|
||||
|
||||
macro_rules! cache_interned_layouts {
|
||||
|
@ -48,23 +50,23 @@ macro_rules! cache_interned_layouts {
|
|||
cache_interned_layouts! {
|
||||
0, VOID, pub, Layout::VOID_NAKED
|
||||
1, UNIT, pub, Layout::UNIT_NAKED
|
||||
2, BOOL, pub, Layout::Builtin(Builtin::Bool)
|
||||
3, U8, pub, Layout::Builtin(Builtin::Int(IntWidth::U8))
|
||||
4, U16, pub, Layout::Builtin(Builtin::Int(IntWidth::U16))
|
||||
5, U32, pub, Layout::Builtin(Builtin::Int(IntWidth::U32))
|
||||
6, U64, pub, Layout::Builtin(Builtin::Int(IntWidth::U64))
|
||||
7, U128, pub, Layout::Builtin(Builtin::Int(IntWidth::U128))
|
||||
8, I8, pub, Layout::Builtin(Builtin::Int(IntWidth::I8))
|
||||
9, I16, pub, Layout::Builtin(Builtin::Int(IntWidth::I16))
|
||||
10, I32, pub, Layout::Builtin(Builtin::Int(IntWidth::I32))
|
||||
11, I64, pub, Layout::Builtin(Builtin::Int(IntWidth::I64))
|
||||
12, I128, pub, Layout::Builtin(Builtin::Int(IntWidth::I128))
|
||||
13, F32, pub, Layout::Builtin(Builtin::Float(FloatWidth::F32))
|
||||
14, F64, pub, Layout::Builtin(Builtin::Float(FloatWidth::F64))
|
||||
15, DEC, pub, Layout::Builtin(Builtin::Decimal)
|
||||
16, STR, pub, Layout::Builtin(Builtin::Str)
|
||||
17, OPAQUE_PTR, pub, Layout::Boxed(Layout::VOID)
|
||||
18, NAKED_RECURSIVE_PTR, pub(super), Layout::RecursivePointer(Layout::VOID)
|
||||
2, BOOL, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Bool) }
|
||||
3, U8, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Int(IntWidth::U8)) }
|
||||
4, U16, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Int(IntWidth::U16)) }
|
||||
5, U32, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Int(IntWidth::U32)) }
|
||||
6, U64, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Int(IntWidth::U64)) }
|
||||
7, U128, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Int(IntWidth::U128)) }
|
||||
8, I8, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Int(IntWidth::I8)) }
|
||||
9, I16, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Int(IntWidth::I16)) }
|
||||
10, I32, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Int(IntWidth::I32)) }
|
||||
11, I64, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Int(IntWidth::I64)) }
|
||||
12, I128, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Int(IntWidth::I128)) }
|
||||
13, F32, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Float(FloatWidth::F32)) }
|
||||
14, F64, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Float(FloatWidth::F64)) }
|
||||
15, DEC, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Decimal) }
|
||||
16, STR, pub, Layout{ repr: LayoutRepr::Builtin(Builtin::Str) }
|
||||
17, OPAQUE_PTR, pub, Layout{ repr: LayoutRepr::Boxed(Layout::VOID) }
|
||||
18, NAKED_RECURSIVE_PTR, pub(super), Layout{ repr: LayoutRepr::RecursivePointer(Layout::VOID) }
|
||||
|
||||
; 19
|
||||
}
|
||||
|
@ -107,10 +109,14 @@ impl_to_from_int_width! {
|
|||
}
|
||||
|
||||
impl<'a> Layout<'a> {
|
||||
pub(super) const VOID_NAKED: Self = Layout::Union(UnionLayout::NonRecursive(&[]));
|
||||
pub(super) const UNIT_NAKED: Self = Layout::Struct {
|
||||
field_layouts: &[],
|
||||
field_order_hash: FieldOrderHash::ZERO_FIELD_HASH,
|
||||
pub(super) const VOID_NAKED: Self = Layout {
|
||||
repr: LayoutRepr::Union(UnionLayout::NonRecursive(&[])),
|
||||
};
|
||||
pub(super) const UNIT_NAKED: Self = Layout {
|
||||
repr: LayoutRepr::Struct {
|
||||
field_layouts: &[],
|
||||
field_order_hash: FieldOrderHash::ZERO_FIELD_HASH,
|
||||
},
|
||||
};
|
||||
|
||||
pub const fn float_width(w: FloatWidth) -> InLayout<'static> {
|
||||
|
@ -138,7 +144,7 @@ pub trait LayoutInterner<'a>: Sized {
|
|||
// allocations when values already have interned representations.
|
||||
fn insert(&mut self, value: Layout<'a>) -> InLayout<'a>;
|
||||
|
||||
/// Creates a [LambdaSet], including caching the [Layout::LambdaSet] representation of the
|
||||
/// Creates a [LambdaSet], including caching the [LayoutRepr::LambdaSet] representation of the
|
||||
/// lambda set onto itself.
|
||||
fn insert_lambda_set(
|
||||
&mut self,
|
||||
|
@ -209,17 +215,18 @@ pub trait LayoutInterner<'a>: Sized {
|
|||
|
||||
fn chase_recursive(&self, mut layout: InLayout<'a>) -> Layout<'a> {
|
||||
loop {
|
||||
match self.get(layout) {
|
||||
Layout::RecursivePointer(l) => layout = l,
|
||||
other => return other,
|
||||
let lay = self.get(layout);
|
||||
match lay.repr {
|
||||
LayoutRepr::RecursivePointer(l) => layout = l,
|
||||
_ => return lay,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn chase_recursive_in(&self, mut layout: InLayout<'a>) -> InLayout<'a> {
|
||||
loop {
|
||||
match self.get(layout) {
|
||||
Layout::RecursivePointer(l) => layout = l,
|
||||
match self.get(layout).repr {
|
||||
LayoutRepr::RecursivePointer(l) => layout = l,
|
||||
_ => return layout,
|
||||
}
|
||||
}
|
||||
|
@ -271,9 +278,9 @@ pub trait LayoutInterner<'a>: Sized {
|
|||
D::Doc: Clone,
|
||||
A: Clone,
|
||||
{
|
||||
use Layout::*;
|
||||
use LayoutRepr::*;
|
||||
|
||||
match self.get(layout) {
|
||||
match self.get(layout).repr {
|
||||
Builtin(builtin) => builtin.to_doc(alloc, self, seen_rec, parens),
|
||||
Struct { field_layouts, .. } => {
|
||||
let fields_doc = field_layouts
|
||||
|
@ -353,7 +360,7 @@ pub trait LayoutInterner<'a>: Sized {
|
|||
///
|
||||
/// ```ignore(illustrative)
|
||||
/// fn is_rec_ptr<'a>(interner: &impl LayoutInterner<'a>, layout: InLayout<'a>) -> bool {
|
||||
/// if matches!(interner.get(layout), Layout::RecursivePointer(..)) {
|
||||
/// if matches!(interner.get(layout), LayoutRepr::RecursivePointer(..)) {
|
||||
/// return true;
|
||||
/// }
|
||||
///
|
||||
|
@ -639,7 +646,9 @@ impl<'a> GlobalLayoutInterner<'a> {
|
|||
set,
|
||||
..normalized
|
||||
};
|
||||
let lambda_set_layout = Layout::LambdaSet(full_lambda_set);
|
||||
let lambda_set_layout = Layout {
|
||||
repr: LayoutRepr::LambdaSet(full_lambda_set),
|
||||
};
|
||||
|
||||
vec[slot.0] = lambda_set_layout;
|
||||
|
||||
|
@ -945,9 +954,9 @@ macro_rules! st_impl {
|
|||
representation,
|
||||
full_layout: slot,
|
||||
};
|
||||
self.vec[slot.0] = Layout::LambdaSet(lambda_set);
|
||||
self.vec[slot.0] = Layout { repr: LayoutRepr::LambdaSet(lambda_set) };
|
||||
|
||||
let _old = self.map.insert(Layout::LambdaSet(lambda_set), slot);
|
||||
let _old = self.map.insert(Layout { repr: LayoutRepr::LambdaSet(lambda_set) }, slot);
|
||||
debug_assert!(_old.is_none());
|
||||
|
||||
let _old = self.normalized_lambda_set_map
|
||||
|
@ -1003,7 +1012,7 @@ mod reify {
|
|||
use bumpalo::{collections::Vec, Bump};
|
||||
use roc_module::symbol::Symbol;
|
||||
|
||||
use crate::layout::{Builtin, LambdaSet, Layout, UnionLayout};
|
||||
use crate::layout::{Builtin, LambdaSet, Layout, LayoutRepr, UnionLayout};
|
||||
|
||||
use super::{InLayout, LayoutInterner, NeedsRecursionPointerFixup};
|
||||
|
||||
|
@ -1014,26 +1023,29 @@ mod reify {
|
|||
slot: InLayout<'a>,
|
||||
normalized_layout: Layout<'a>,
|
||||
) -> Layout<'a> {
|
||||
match normalized_layout {
|
||||
Layout::Builtin(builtin) => {
|
||||
Layout::Builtin(reify_builtin(arena, interner, slot, builtin))
|
||||
let repr = match normalized_layout.repr {
|
||||
LayoutRepr::Builtin(builtin) => {
|
||||
LayoutRepr::Builtin(reify_builtin(arena, interner, slot, builtin))
|
||||
}
|
||||
Layout::Struct {
|
||||
LayoutRepr::Struct {
|
||||
field_order_hash,
|
||||
field_layouts,
|
||||
} => Layout::Struct {
|
||||
} => LayoutRepr::Struct {
|
||||
field_order_hash,
|
||||
field_layouts: reify_layout_slice(arena, interner, slot, field_layouts),
|
||||
},
|
||||
Layout::Boxed(lay) => Layout::Boxed(reify_layout(arena, interner, slot, lay)),
|
||||
Layout::Union(un) => Layout::Union(reify_union(arena, interner, slot, un)),
|
||||
Layout::LambdaSet(ls) => Layout::LambdaSet(reify_lambda_set(arena, interner, slot, ls)),
|
||||
Layout::RecursivePointer(l) => {
|
||||
LayoutRepr::Boxed(lay) => LayoutRepr::Boxed(reify_layout(arena, interner, slot, lay)),
|
||||
LayoutRepr::Union(un) => LayoutRepr::Union(reify_union(arena, interner, slot, un)),
|
||||
LayoutRepr::LambdaSet(ls) => {
|
||||
LayoutRepr::LambdaSet(reify_lambda_set(arena, interner, slot, ls))
|
||||
}
|
||||
LayoutRepr::RecursivePointer(l) => {
|
||||
// If the layout is not void at its point then it has already been solved as
|
||||
// another recursive union's layout, do not change it.
|
||||
Layout::RecursivePointer(if l == Layout::VOID { slot } else { l })
|
||||
LayoutRepr::RecursivePointer(if l == Layout::VOID { slot } else { l })
|
||||
}
|
||||
}
|
||||
};
|
||||
Layout { repr }
|
||||
}
|
||||
|
||||
fn reify_layout<'a>(
|
||||
|
@ -1173,7 +1185,7 @@ mod reify {
|
|||
}
|
||||
|
||||
mod equiv {
|
||||
use crate::layout::{self, Layout, UnionLayout};
|
||||
use crate::layout::{self, LayoutRepr, UnionLayout};
|
||||
|
||||
use super::{InLayout, LayoutInterner};
|
||||
|
||||
|
@ -1209,8 +1221,8 @@ mod equiv {
|
|||
if l1 == l2 {
|
||||
continue;
|
||||
}
|
||||
use Layout::*;
|
||||
match (interner.get(l1), interner.get(l2)) {
|
||||
use LayoutRepr::*;
|
||||
match (interner.get(l1).repr, interner.get(l2).repr) {
|
||||
(RecursivePointer(rec), _) => stack.push((rec, l2)),
|
||||
(_, RecursivePointer(rec)) => stack.push((l1, rec)),
|
||||
(Builtin(b1), Builtin(b2)) => {
|
||||
|
@ -1318,7 +1330,7 @@ mod equiv {
|
|||
pub mod dbg {
|
||||
use roc_module::symbol::Symbol;
|
||||
|
||||
use crate::layout::{Builtin, LambdaSet, Layout, UnionLayout};
|
||||
use crate::layout::{Builtin, LambdaSet, LayoutRepr, UnionLayout};
|
||||
|
||||
use super::{InLayout, LayoutInterner};
|
||||
|
||||
|
@ -1326,12 +1338,12 @@ pub mod dbg {
|
|||
|
||||
impl<'a, 'r, I: LayoutInterner<'a>> std::fmt::Debug for Dbg<'a, 'r, I> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self.0.get(self.1) {
|
||||
Layout::Builtin(b) => f
|
||||
match self.0.get(self.1).repr {
|
||||
LayoutRepr::Builtin(b) => f
|
||||
.debug_tuple("Builtin")
|
||||
.field(&DbgBuiltin(self.0, b))
|
||||
.finish(),
|
||||
Layout::Struct {
|
||||
LayoutRepr::Struct {
|
||||
field_order_hash,
|
||||
field_layouts,
|
||||
} => f
|
||||
|
@ -1339,13 +1351,15 @@ pub mod dbg {
|
|||
.field("hash", &field_order_hash)
|
||||
.field("fields", &DbgFields(self.0, field_layouts))
|
||||
.finish(),
|
||||
Layout::Boxed(b) => f.debug_tuple("Boxed").field(&Dbg(self.0, b)).finish(),
|
||||
Layout::Union(un) => f.debug_tuple("Union").field(&DbgUnion(self.0, un)).finish(),
|
||||
Layout::LambdaSet(ls) => f
|
||||
LayoutRepr::Boxed(b) => f.debug_tuple("Boxed").field(&Dbg(self.0, b)).finish(),
|
||||
LayoutRepr::Union(un) => {
|
||||
f.debug_tuple("Union").field(&DbgUnion(self.0, un)).finish()
|
||||
}
|
||||
LayoutRepr::LambdaSet(ls) => f
|
||||
.debug_tuple("LambdaSet")
|
||||
.field(&DbgLambdaSet(self.0, ls))
|
||||
.finish(),
|
||||
Layout::RecursivePointer(rp) => {
|
||||
LayoutRepr::RecursivePointer(rp) => {
|
||||
f.debug_tuple("RecursivePointer").field(&rp.0).finish()
|
||||
}
|
||||
}
|
||||
|
@ -1467,7 +1481,7 @@ mod insert_lambda_set {
|
|||
use roc_module::symbol::Symbol;
|
||||
use roc_target::TargetInfo;
|
||||
|
||||
use crate::layout::{LambdaSet, Layout};
|
||||
use crate::layout::{LambdaSet, Layout, LayoutRepr};
|
||||
|
||||
use super::{GlobalLayoutInterner, InLayout, LayoutInterner, NeedsRecursionPointerFixup};
|
||||
|
||||
|
@ -1509,7 +1523,9 @@ mod insert_lambda_set {
|
|||
|
||||
let lambda_set =
|
||||
interner.insert_lambda_set(arena, TEST_ARGS, TEST_RET, TEST_SET, FIXUP, Layout::UNIT);
|
||||
let lambda_set_layout_in = interner.insert(Layout::LambdaSet(lambda_set));
|
||||
let lambda_set_layout_in = interner.insert(Layout {
|
||||
repr: LayoutRepr::LambdaSet(lambda_set),
|
||||
});
|
||||
assert_eq!(lambda_set.full_layout, lambda_set_layout_in);
|
||||
}
|
||||
|
||||
|
@ -1558,35 +1574,37 @@ mod insert_recursive_layout {
|
|||
use bumpalo::Bump;
|
||||
use roc_target::TargetInfo;
|
||||
|
||||
use crate::layout::{Builtin, InLayout, Layout, UnionLayout};
|
||||
use crate::layout::{Builtin, InLayout, Layout, LayoutRepr, UnionLayout};
|
||||
|
||||
use super::{GlobalLayoutInterner, LayoutInterner};
|
||||
|
||||
const TARGET_INFO: TargetInfo = TargetInfo::default_x86_64();
|
||||
|
||||
fn make_layout<'a>(arena: &'a Bump, interner: &mut impl LayoutInterner<'a>) -> Layout<'a> {
|
||||
Layout::Union(UnionLayout::Recursive(&*arena.alloc([
|
||||
&*arena.alloc([
|
||||
interner.insert(Layout::Builtin(Builtin::List(Layout::NAKED_RECURSIVE_PTR))),
|
||||
]),
|
||||
let list_rec = Layout {
|
||||
repr: LayoutRepr::Builtin(Builtin::List(Layout::NAKED_RECURSIVE_PTR)),
|
||||
};
|
||||
let repr = LayoutRepr::Union(UnionLayout::Recursive(&*arena.alloc([
|
||||
&*arena.alloc([interner.insert(list_rec)]),
|
||||
&*arena.alloc_slice_fill_iter([interner.insert(Layout::struct_no_name_order(
|
||||
&*arena.alloc([Layout::NAKED_RECURSIVE_PTR]),
|
||||
))]),
|
||||
])))
|
||||
])));
|
||||
Layout { repr }
|
||||
}
|
||||
|
||||
fn get_rec_ptr_index<'a>(interner: &impl LayoutInterner<'a>, layout: InLayout<'a>) -> usize {
|
||||
match interner.chase_recursive(layout) {
|
||||
Layout::Union(UnionLayout::Recursive(&[&[l1], &[l2]])) => {
|
||||
match (interner.get(l1), interner.get(l2)) {
|
||||
match interner.chase_recursive(layout).repr {
|
||||
LayoutRepr::Union(UnionLayout::Recursive(&[&[l1], &[l2]])) => {
|
||||
match (interner.get(l1).repr, interner.get(l2).repr) {
|
||||
(
|
||||
Layout::Builtin(Builtin::List(l1)),
|
||||
Layout::Struct {
|
||||
LayoutRepr::Builtin(Builtin::List(l1)),
|
||||
LayoutRepr::Struct {
|
||||
field_order_hash: _,
|
||||
field_layouts: &[l2],
|
||||
},
|
||||
) => match (interner.get(l1), interner.get(l2)) {
|
||||
(Layout::RecursivePointer(i1), Layout::RecursivePointer(i2)) => {
|
||||
) => match (interner.get(l1).repr, interner.get(l2).repr) {
|
||||
(LayoutRepr::RecursivePointer(i1), LayoutRepr::RecursivePointer(i2)) => {
|
||||
assert_eq!(i1, i2);
|
||||
assert_ne!(i1, Layout::VOID);
|
||||
i1.0
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue