mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 13:59:08 +00:00
alignment in multi tag pattern match
This commit is contained in:
parent
69734e837e
commit
0f1baef160
3 changed files with 130 additions and 14 deletions
|
@ -481,7 +481,7 @@ mod gen_tags {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
wrapper = \{} ->
|
wrapper = \{} ->
|
||||||
when 2 is
|
when 2 is
|
||||||
2 if False -> 0
|
2 if False -> 0
|
||||||
_ -> 42
|
_ -> 42
|
||||||
|
@ -499,7 +499,7 @@ mod gen_tags {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
wrapper = \{} ->
|
wrapper = \{} ->
|
||||||
when 2 is
|
when 2 is
|
||||||
2 if True -> 42
|
2 if True -> 42
|
||||||
_ -> 0
|
_ -> 0
|
||||||
|
@ -517,7 +517,7 @@ mod gen_tags {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
wrapper = \{} ->
|
wrapper = \{} ->
|
||||||
when 2 is
|
when 2 is
|
||||||
_ if False -> 0
|
_ if False -> 0
|
||||||
_ -> 42
|
_ -> 42
|
||||||
|
@ -637,7 +637,7 @@ mod gen_tags {
|
||||||
x : Maybe (Maybe Int)
|
x : Maybe (Maybe Int)
|
||||||
x = Just (Just 41)
|
x = Just (Just 41)
|
||||||
|
|
||||||
main =
|
main =
|
||||||
x
|
x
|
||||||
"#
|
"#
|
||||||
),
|
),
|
||||||
|
@ -701,11 +701,11 @@ mod gen_tags {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
wrapper = \{} ->
|
wrapper = \{} ->
|
||||||
x : [ Red, White, Blue ]
|
x : [ Red, White, Blue ]
|
||||||
x = Blue
|
x = Blue
|
||||||
|
|
||||||
y =
|
y =
|
||||||
when x is
|
when x is
|
||||||
Red -> 1
|
Red -> 1
|
||||||
White -> 2
|
White -> 2
|
||||||
|
@ -726,8 +726,8 @@ mod gen_tags {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
wrapper = \{} ->
|
wrapper = \{} ->
|
||||||
y =
|
y =
|
||||||
when 1 + 2 is
|
when 1 + 2 is
|
||||||
3 -> 3
|
3 -> 3
|
||||||
1 -> 1
|
1 -> 1
|
||||||
|
@ -745,7 +745,7 @@ mod gen_tags {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
r#"
|
r#"
|
||||||
y =
|
y =
|
||||||
if 1 + 2 > 0 then
|
if 1 + 2 > 0 then
|
||||||
3
|
3
|
||||||
else
|
else
|
||||||
|
@ -778,7 +778,7 @@ mod gen_tags {
|
||||||
x = Three (1 == 1) 32
|
x = Three (1 == 1) 32
|
||||||
|
|
||||||
when x is
|
when x is
|
||||||
Three bool int ->
|
Three bool int ->
|
||||||
{ bool, int }
|
{ bool, int }
|
||||||
#"
|
#"
|
||||||
),
|
),
|
||||||
|
@ -792,7 +792,7 @@ mod gen_tags {
|
||||||
x = Three (1 == 1) (if True then Red else if True then Green else Blue) 32
|
x = Three (1 == 1) (if True then Red else if True then Green else Blue) 32
|
||||||
|
|
||||||
when x is
|
when x is
|
||||||
Three bool color int ->
|
Three bool color int ->
|
||||||
{ bool, color, int }
|
{ bool, color, int }
|
||||||
#"
|
#"
|
||||||
),
|
),
|
||||||
|
@ -800,4 +800,72 @@ mod gen_tags {
|
||||||
(i64, bool, u8)
|
(i64, bool, u8)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn alignment_in_multi_tag_construction() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r"#
|
||||||
|
x : [ Three Bool Int, Empty ]
|
||||||
|
x = Three (1 == 1) 32
|
||||||
|
|
||||||
|
x
|
||||||
|
|
||||||
|
#"
|
||||||
|
),
|
||||||
|
(1, 32i64, true),
|
||||||
|
(i64, i64, bool)
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r"#
|
||||||
|
x : [ Three Bool [ Red, Green, Blue ] Int, Empty ]
|
||||||
|
x = Three (1 == 1) (if True then Red else if True then Green else Blue) 32
|
||||||
|
|
||||||
|
x
|
||||||
|
#"
|
||||||
|
),
|
||||||
|
(1, 32i64, true, 2u8),
|
||||||
|
(i64, i64, bool, u8)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn alignment_in_multi_tag_pattern_match() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r"#
|
||||||
|
x : [ Three Bool Int, Empty ]
|
||||||
|
x = Three (1 == 1) 32
|
||||||
|
|
||||||
|
when x is
|
||||||
|
Three bool int ->
|
||||||
|
{ bool, int }
|
||||||
|
|
||||||
|
Empty ->
|
||||||
|
{ bool: False, int: 0 }
|
||||||
|
#"
|
||||||
|
),
|
||||||
|
(32i64, true),
|
||||||
|
(i64, bool)
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r"#
|
||||||
|
x : [ Three Bool [ Red, Green, Blue ] Int, Empty ]
|
||||||
|
x = Three (1 == 1) (if True then Red else if True then Green else Blue) 32
|
||||||
|
|
||||||
|
when x is
|
||||||
|
Three bool color int ->
|
||||||
|
{ bool, color, int }
|
||||||
|
Empty ->
|
||||||
|
{ bool: False, color: Red, int: 0 }
|
||||||
|
#"
|
||||||
|
),
|
||||||
|
(32i64, true, 2u8),
|
||||||
|
(i64, bool, u8)
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2472,12 +2472,33 @@ pub fn with_hole<'a>(
|
||||||
.find(|(_, (key, _))| key == &tag_name)
|
.find(|(_, (key, _))| key == &tag_name)
|
||||||
.expect("tag must be in its own type");
|
.expect("tag must be in its own type");
|
||||||
|
|
||||||
|
let mut field_symbols_temp = Vec::with_capacity_in(args.len(), env.arena);
|
||||||
|
|
||||||
|
for (var, arg) in args.drain(..) {
|
||||||
|
// Layout will unpack this unwrapped tack if it only has one (non-zero-sized) field
|
||||||
|
let layout = layout_cache
|
||||||
|
.from_var(env.arena, var, env.subs)
|
||||||
|
.unwrap_or_else(|err| {
|
||||||
|
panic!("TODO turn fn_var into a RuntimeError {:?}", err)
|
||||||
|
});
|
||||||
|
|
||||||
|
let alignment = layout.alignment_bytes(8);
|
||||||
|
|
||||||
|
let symbol = possible_reuse_symbol(env, procs, &arg.value);
|
||||||
|
field_symbols_temp.push((
|
||||||
|
alignment,
|
||||||
|
symbol,
|
||||||
|
((var, arg), &*env.arena.alloc(symbol)),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
field_symbols_temp.sort_by(|a, b| b.0.cmp(&a.0));
|
||||||
|
|
||||||
let mut field_symbols: Vec<Symbol> = Vec::with_capacity_in(args.len(), arena);
|
let mut field_symbols: Vec<Symbol> = Vec::with_capacity_in(args.len(), arena);
|
||||||
let tag_id_symbol = env.unique_symbol();
|
let tag_id_symbol = env.unique_symbol();
|
||||||
field_symbols.push(tag_id_symbol);
|
field_symbols.push(tag_id_symbol);
|
||||||
|
|
||||||
for (_, arg) in args.iter() {
|
for (_, symbol, _) in field_symbols_temp.iter() {
|
||||||
field_symbols.push(possible_reuse_symbol(env, procs, &arg.value));
|
field_symbols.push(*symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut layouts: Vec<&'a [Layout<'a>]> =
|
let mut layouts: Vec<&'a [Layout<'a>]> =
|
||||||
|
@ -2498,7 +2519,11 @@ pub fn with_hole<'a>(
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut stmt = Stmt::Let(assigned, tag, layout, hole);
|
let mut stmt = Stmt::Let(assigned, tag, layout, hole);
|
||||||
let iter = args.into_iter().rev().zip(field_symbols.iter().rev());
|
let iter = field_symbols_temp
|
||||||
|
.drain(..)
|
||||||
|
.map(|x| x.2 .0)
|
||||||
|
.rev()
|
||||||
|
.zip(field_symbols.iter().rev());
|
||||||
|
|
||||||
stmt = assign_to_symbols(env, procs, layout_cache, iter, stmt);
|
stmt = assign_to_symbols(env, procs, layout_cache, iter, stmt);
|
||||||
|
|
||||||
|
@ -5370,6 +5395,20 @@ pub fn from_can_pattern<'a>(
|
||||||
let mut mono_args = Vec::with_capacity_in(arguments.len(), env.arena);
|
let mut mono_args = Vec::with_capacity_in(arguments.len(), env.arena);
|
||||||
// disregard the tag discriminant layout
|
// disregard the tag discriminant layout
|
||||||
|
|
||||||
|
let mut arguments = arguments.clone();
|
||||||
|
|
||||||
|
arguments.sort_by(|arg1, arg2| {
|
||||||
|
let ptr_bytes = 8;
|
||||||
|
|
||||||
|
let layout1 = layout_cache.from_var(env.arena, arg1.0, env.subs).unwrap();
|
||||||
|
let layout2 = layout_cache.from_var(env.arena, arg2.0, env.subs).unwrap();
|
||||||
|
|
||||||
|
let size1 = layout1.alignment_bytes(ptr_bytes);
|
||||||
|
let size2 = layout2.alignment_bytes(ptr_bytes);
|
||||||
|
|
||||||
|
size2.cmp(&size1)
|
||||||
|
});
|
||||||
|
|
||||||
// TODO make this assert pass, it currently does not because
|
// TODO make this assert pass, it currently does not because
|
||||||
// 0-sized values are dropped out
|
// 0-sized values are dropped out
|
||||||
// debug_assert_eq!(arguments.len(), argument_layouts[1..].len());
|
// debug_assert_eq!(arguments.len(), argument_layouts[1..].len());
|
||||||
|
|
|
@ -1099,6 +1099,15 @@ pub fn union_sorted_tags_help<'a>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
arg_layouts.sort_by(|layout1, layout2| {
|
||||||
|
let ptr_bytes = 8;
|
||||||
|
|
||||||
|
let size1 = layout1.alignment_bytes(ptr_bytes);
|
||||||
|
let size2 = layout2.alignment_bytes(ptr_bytes);
|
||||||
|
|
||||||
|
size2.cmp(&size1)
|
||||||
|
});
|
||||||
|
|
||||||
answer.push((tag_name, arg_layouts.into_bump_slice()));
|
answer.push((tag_name, arg_layouts.into_bump_slice()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue