mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-30 07:14:46 +00:00
pattern match on single-tag tag unions
in LLVM and crane
This commit is contained in:
parent
b5abed5f54
commit
6253d2d1af
4 changed files with 60 additions and 7 deletions
|
@ -11,7 +11,7 @@ use inkwell::{AddressSpace, FloatPredicate, IntPredicate};
|
||||||
use crate::llvm::convert::{
|
use crate::llvm::convert::{
|
||||||
basic_type_from_layout, collection_wrapper, get_array_type, get_fn_type,
|
basic_type_from_layout, collection_wrapper, get_array_type, get_fn_type,
|
||||||
};
|
};
|
||||||
use roc_collections::all::{ImMap, MutMap};
|
use roc_collections::all::ImMap;
|
||||||
use roc_module::symbol::{Interns, Symbol};
|
use roc_module::symbol::{Interns, Symbol};
|
||||||
use roc_mono::expr::{Expr, Proc, Procs};
|
use roc_mono::expr::{Expr, Proc, Procs};
|
||||||
use roc_mono::layout::{Builtin, Layout};
|
use roc_mono::layout::{Builtin, Layout};
|
||||||
|
@ -316,11 +316,10 @@ pub fn build_expr<'a, 'ctx, 'env>(
|
||||||
BasicValueEnum::StructValue(struct_val.into_struct_value())
|
BasicValueEnum::StructValue(struct_val.into_struct_value())
|
||||||
}
|
}
|
||||||
Tag {
|
Tag {
|
||||||
tag_id,
|
union_size,
|
||||||
arguments,
|
arguments,
|
||||||
tag_layout,
|
|
||||||
..
|
..
|
||||||
} => {
|
} if *union_size == 1 => {
|
||||||
/*
|
/*
|
||||||
// put the discriminant in the first slot
|
// put the discriminant in the first slot
|
||||||
let discriminant = (
|
let discriminant = (
|
||||||
|
@ -393,6 +392,16 @@ pub fn build_expr<'a, 'ctx, 'env>(
|
||||||
.build_extract_value(struct_val, index, "field_access")
|
.build_extract_value(struct_val, index, "field_access")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
AccessAtIndex { index, expr, .. } => {
|
||||||
|
let builder = env.builder;
|
||||||
|
|
||||||
|
// Get Struct val
|
||||||
|
let struct_val = build_expr(env, &scope, parent, expr, procs).into_struct_value();
|
||||||
|
|
||||||
|
builder
|
||||||
|
.build_extract_value(struct_val, *index as u32, "tag_field_access")
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
panic!("I don't yet know how to LLVM build {:?}", expr);
|
panic!("I don't yet know how to LLVM build {:?}", expr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ pub fn basic_type_from_layout<'ctx>(
|
||||||
.as_basic_type_enum()
|
.as_basic_type_enum()
|
||||||
}
|
}
|
||||||
Union(tags) if tags.len() == 1 => {
|
Union(tags) if tags.len() == 1 => {
|
||||||
let (_, layouts) = tags.into_iter().next().unwrap();
|
let (_, layouts) = tags.iter().next().unwrap();
|
||||||
|
|
||||||
// Determine types
|
// Determine types
|
||||||
let mut field_types = Vec::with_capacity_in(layouts.len(), arena);
|
let mut field_types = Vec::with_capacity_in(layouts.len(), arena);
|
||||||
|
@ -82,7 +82,7 @@ pub fn basic_type_from_layout<'ctx>(
|
||||||
.struct_type(field_types.into_bump_slice(), false)
|
.struct_type(field_types.into_bump_slice(), false)
|
||||||
.as_basic_type_enum()
|
.as_basic_type_enum()
|
||||||
}
|
}
|
||||||
Union(tags) => {
|
Union(_) => {
|
||||||
// TODO make this dynamic
|
// TODO make this dynamic
|
||||||
let ptr_size = std::mem::size_of::<i64>();
|
let ptr_size = std::mem::size_of::<i64>();
|
||||||
let union_size = layout.stack_size(ptr_size as u32);
|
let union_size = layout.stack_size(ptr_size as u32);
|
||||||
|
|
|
@ -708,6 +708,38 @@ mod test_gen {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn when_one_element_tag() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
x : [ Pair Int Int ]
|
||||||
|
x = Pair 0x2 0x3
|
||||||
|
|
||||||
|
when x is
|
||||||
|
Pair l r -> l + r
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
5,
|
||||||
|
i64
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn twice_record_access() {
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
x = {a: 0x2, b: 0x3 }
|
||||||
|
|
||||||
|
x.a + x.b
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
5,
|
||||||
|
i64
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn gen_when_one_branch() {
|
fn gen_when_one_branch() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
|
@ -1312,5 +1344,17 @@ mod test_gen {
|
||||||
19,
|
19,
|
||||||
i64
|
i64
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assert_evals_to!(
|
||||||
|
indoc!(
|
||||||
|
r#"
|
||||||
|
rec = { x: 15, y: 17, z: 19 }
|
||||||
|
|
||||||
|
rec.z + rec.x
|
||||||
|
"#
|
||||||
|
),
|
||||||
|
34,
|
||||||
|
i64
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -910,7 +910,7 @@ fn store_pattern2<'a>(
|
||||||
match argument {
|
match argument {
|
||||||
Identifier(symbol) => {
|
Identifier(symbol) => {
|
||||||
// store immediately in the given symbol
|
// store immediately in the given symbol
|
||||||
stored.push((*symbol, layout.clone(), load));
|
stored.push((*symbol, arg_layout.clone(), load));
|
||||||
}
|
}
|
||||||
Underscore => {
|
Underscore => {
|
||||||
// ignore
|
// ignore
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue