mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 06:14:46 +00:00
commit
519b4f2a12
10 changed files with 99 additions and 203 deletions
|
@ -116,7 +116,7 @@ fn jit_to_ast_help<'a>(
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
Layout::Builtin(Builtin::List(_, elem_layout)) => Ok(run_jit_function!(
|
Layout::Builtin(Builtin::List(elem_layout)) => Ok(run_jit_function!(
|
||||||
lib,
|
lib,
|
||||||
main_fn_name,
|
main_fn_name,
|
||||||
(*const u8, usize),
|
(*const u8, usize),
|
||||||
|
@ -125,12 +125,6 @@ fn jit_to_ast_help<'a>(
|
||||||
Layout::Builtin(other) => {
|
Layout::Builtin(other) => {
|
||||||
todo!("add support for rendering builtin {:?} to the REPL", other)
|
todo!("add support for rendering builtin {:?} to the REPL", other)
|
||||||
}
|
}
|
||||||
Layout::PhantomEmptyStruct => Ok(run_jit_function!(lib, main_fn_name, &u8, |_| {
|
|
||||||
Expr::Record {
|
|
||||||
fields: &[],
|
|
||||||
final_comments: env.arena.alloc([]),
|
|
||||||
}
|
|
||||||
})),
|
|
||||||
Layout::Struct(field_layouts) => {
|
Layout::Struct(field_layouts) => {
|
||||||
let ptr_to_ast = |ptr: *const u8| match content {
|
let ptr_to_ast = |ptr: *const u8| match content {
|
||||||
Content::Structure(FlatType::Record(fields, _)) => {
|
Content::Structure(FlatType::Record(fields, _)) => {
|
||||||
|
@ -247,7 +241,6 @@ fn jit_to_ast_help<'a>(
|
||||||
|
|
||||||
Layout::Closure(_, _, _) => Err(ToAstProblem::FunctionLayout),
|
Layout::Closure(_, _, _) => Err(ToAstProblem::FunctionLayout),
|
||||||
Layout::FunctionPointer(_, _) => Err(ToAstProblem::FunctionLayout),
|
Layout::FunctionPointer(_, _) => Err(ToAstProblem::FunctionLayout),
|
||||||
Layout::Pointer(_) => todo!("add support for rendering pointers in the REPL"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,7 +291,7 @@ fn ptr_to_ast<'a>(
|
||||||
items: &[],
|
items: &[],
|
||||||
final_comments: &[],
|
final_comments: &[],
|
||||||
},
|
},
|
||||||
Layout::Builtin(Builtin::List(_, elem_layout)) => {
|
Layout::Builtin(Builtin::List(elem_layout)) => {
|
||||||
// Turn the (ptr, len) wrapper struct into actual ptr and len values.
|
// Turn the (ptr, len) wrapper struct into actual ptr and len values.
|
||||||
let len = unsafe { *(ptr.offset(env.ptr_bytes as isize) as *const usize) };
|
let len = unsafe { *(ptr.offset(env.ptr_bytes as isize) as *const usize) };
|
||||||
let ptr = unsafe { *(ptr as *const *const u8) };
|
let ptr = unsafe { *(ptr as *const *const u8) };
|
||||||
|
|
|
@ -906,9 +906,7 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
|
||||||
arguments,
|
arguments,
|
||||||
tag_layout,
|
tag_layout,
|
||||||
..
|
..
|
||||||
} if *union_size == 1
|
} if *union_size == 1 && matches!(tag_layout, UnionLayout::NonRecursive(_)) => {
|
||||||
&& matches!(tag_layout, Layout::Union(UnionLayout::NonRecursive(_))) =>
|
|
||||||
{
|
|
||||||
let it = arguments.iter();
|
let it = arguments.iter();
|
||||||
|
|
||||||
let ctx = env.context;
|
let ctx = env.context;
|
||||||
|
@ -956,7 +954,7 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
Tag {
|
Tag {
|
||||||
arguments,
|
arguments,
|
||||||
tag_layout: Layout::Union(UnionLayout::NonRecursive(fields)),
|
tag_layout: UnionLayout::NonRecursive(fields),
|
||||||
union_size,
|
union_size,
|
||||||
tag_id,
|
tag_id,
|
||||||
..
|
..
|
||||||
|
@ -1044,7 +1042,7 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
|
||||||
}
|
}
|
||||||
Tag {
|
Tag {
|
||||||
arguments,
|
arguments,
|
||||||
tag_layout: Layout::Union(UnionLayout::Recursive(fields)),
|
tag_layout: UnionLayout::Recursive(fields),
|
||||||
union_size,
|
union_size,
|
||||||
tag_id,
|
tag_id,
|
||||||
..
|
..
|
||||||
|
@ -1119,7 +1117,7 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
Tag {
|
Tag {
|
||||||
arguments,
|
arguments,
|
||||||
tag_layout: Layout::Union(UnionLayout::NonNullableUnwrapped(fields)),
|
tag_layout: UnionLayout::NonNullableUnwrapped(fields),
|
||||||
union_size,
|
union_size,
|
||||||
tag_id,
|
tag_id,
|
||||||
..
|
..
|
||||||
|
@ -1195,10 +1193,10 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
|
||||||
Tag {
|
Tag {
|
||||||
arguments,
|
arguments,
|
||||||
tag_layout:
|
tag_layout:
|
||||||
Layout::Union(UnionLayout::NullableWrapped {
|
UnionLayout::NullableWrapped {
|
||||||
nullable_id,
|
nullable_id,
|
||||||
other_tags: fields,
|
other_tags: fields,
|
||||||
}),
|
},
|
||||||
union_size,
|
union_size,
|
||||||
tag_id,
|
tag_id,
|
||||||
..
|
..
|
||||||
|
@ -1287,11 +1285,11 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
|
||||||
Tag {
|
Tag {
|
||||||
arguments,
|
arguments,
|
||||||
tag_layout:
|
tag_layout:
|
||||||
Layout::Union(UnionLayout::NullableUnwrapped {
|
UnionLayout::NullableUnwrapped {
|
||||||
nullable_id,
|
nullable_id,
|
||||||
other_fields,
|
other_fields,
|
||||||
..
|
..
|
||||||
}),
|
},
|
||||||
union_size,
|
union_size,
|
||||||
tag_id,
|
tag_id,
|
||||||
tag_name,
|
tag_name,
|
||||||
|
@ -1387,8 +1385,6 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
|
||||||
data_ptr.into()
|
data_ptr.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
Tag { .. } => unreachable!("tags should have a Union or RecursiveUnion layout"),
|
|
||||||
|
|
||||||
Reset(_) => todo!(),
|
Reset(_) => todo!(),
|
||||||
Reuse { .. } => todo!(),
|
Reuse { .. } => todo!(),
|
||||||
|
|
||||||
|
@ -2180,7 +2176,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
|
||||||
let (value, layout) = load_symbol_and_layout(scope, symbol);
|
let (value, layout) = load_symbol_and_layout(scope, symbol);
|
||||||
|
|
||||||
match layout {
|
match layout {
|
||||||
Layout::Builtin(Builtin::List(_, _)) => {
|
Layout::Builtin(Builtin::List(_)) => {
|
||||||
debug_assert!(value.is_struct_value());
|
debug_assert!(value.is_struct_value());
|
||||||
|
|
||||||
// because of how we insert DECREF for lists, we can't guarantee that
|
// because of how we insert DECREF for lists, we can't guarantee that
|
||||||
|
@ -3360,11 +3356,9 @@ pub fn build_proc<'a, 'ctx, 'env>(
|
||||||
}
|
}
|
||||||
|
|
||||||
Layout::Builtin(_) => {}
|
Layout::Builtin(_) => {}
|
||||||
Layout::PhantomEmptyStruct => {}
|
|
||||||
Layout::Struct(_) => {}
|
Layout::Struct(_) => {}
|
||||||
Layout::Union(_) => {}
|
Layout::Union(_) => {}
|
||||||
Layout::RecursivePointer => {}
|
Layout::RecursivePointer => {}
|
||||||
Layout::Pointer(_) => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3587,7 +3581,7 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
match list_layout {
|
match list_layout {
|
||||||
Layout::Builtin(Builtin::EmptyList) => default,
|
Layout::Builtin(Builtin::EmptyList) => default,
|
||||||
Layout::Builtin(Builtin::List(_, element_layout)) => {
|
Layout::Builtin(Builtin::List(element_layout)) => {
|
||||||
let argument_layouts = &[**element_layout, *default_layout];
|
let argument_layouts = &[**element_layout, *default_layout];
|
||||||
|
|
||||||
let roc_function_call = roc_function_call(
|
let roc_function_call = roc_function_call(
|
||||||
|
@ -3629,8 +3623,8 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
||||||
match (list_layout, return_layout) {
|
match (list_layout, return_layout) {
|
||||||
(Layout::Builtin(Builtin::EmptyList), _) => empty_list(env),
|
(Layout::Builtin(Builtin::EmptyList), _) => empty_list(env),
|
||||||
(
|
(
|
||||||
Layout::Builtin(Builtin::List(_, element_layout)),
|
Layout::Builtin(Builtin::List(element_layout)),
|
||||||
Layout::Builtin(Builtin::List(_, result_layout)),
|
Layout::Builtin(Builtin::List(result_layout)),
|
||||||
) => {
|
) => {
|
||||||
let argument_layouts = &[**element_layout];
|
let argument_layouts = &[**element_layout];
|
||||||
|
|
||||||
|
@ -3660,9 +3654,9 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
match (list1_layout, list2_layout, return_layout) {
|
match (list1_layout, list2_layout, return_layout) {
|
||||||
(
|
(
|
||||||
Layout::Builtin(Builtin::List(_, element1_layout)),
|
Layout::Builtin(Builtin::List(element1_layout)),
|
||||||
Layout::Builtin(Builtin::List(_, element2_layout)),
|
Layout::Builtin(Builtin::List(element2_layout)),
|
||||||
Layout::Builtin(Builtin::List(_, result_layout)),
|
Layout::Builtin(Builtin::List(result_layout)),
|
||||||
) => {
|
) => {
|
||||||
let argument_layouts = &[**element1_layout, **element2_layout];
|
let argument_layouts = &[**element1_layout, **element2_layout];
|
||||||
|
|
||||||
|
@ -3704,10 +3698,10 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
match (list1_layout, list2_layout, list3_layout, return_layout) {
|
match (list1_layout, list2_layout, list3_layout, return_layout) {
|
||||||
(
|
(
|
||||||
Layout::Builtin(Builtin::List(_, element1_layout)),
|
Layout::Builtin(Builtin::List(element1_layout)),
|
||||||
Layout::Builtin(Builtin::List(_, element2_layout)),
|
Layout::Builtin(Builtin::List(element2_layout)),
|
||||||
Layout::Builtin(Builtin::List(_, element3_layout)),
|
Layout::Builtin(Builtin::List(element3_layout)),
|
||||||
Layout::Builtin(Builtin::List(_, result_layout)),
|
Layout::Builtin(Builtin::List(result_layout)),
|
||||||
) => {
|
) => {
|
||||||
let argument_layouts =
|
let argument_layouts =
|
||||||
&[**element1_layout, **element2_layout, **element3_layout];
|
&[**element1_layout, **element2_layout, **element3_layout];
|
||||||
|
@ -3754,8 +3748,8 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
||||||
match (list_layout, return_layout) {
|
match (list_layout, return_layout) {
|
||||||
(Layout::Builtin(Builtin::EmptyList), _) => empty_list(env),
|
(Layout::Builtin(Builtin::EmptyList), _) => empty_list(env),
|
||||||
(
|
(
|
||||||
Layout::Builtin(Builtin::List(_, element_layout)),
|
Layout::Builtin(Builtin::List(element_layout)),
|
||||||
Layout::Builtin(Builtin::List(_, result_layout)),
|
Layout::Builtin(Builtin::List(result_layout)),
|
||||||
) => {
|
) => {
|
||||||
let argument_layouts = &[Layout::Builtin(Builtin::Usize), **element_layout];
|
let argument_layouts = &[Layout::Builtin(Builtin::Usize), **element_layout];
|
||||||
|
|
||||||
|
@ -3786,7 +3780,7 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
match list_layout {
|
match list_layout {
|
||||||
Layout::Builtin(Builtin::EmptyList) => empty_list(env),
|
Layout::Builtin(Builtin::EmptyList) => empty_list(env),
|
||||||
Layout::Builtin(Builtin::List(_, element_layout)) => {
|
Layout::Builtin(Builtin::List(element_layout)) => {
|
||||||
let argument_layouts = &[**element_layout];
|
let argument_layouts = &[**element_layout];
|
||||||
|
|
||||||
let roc_function_call = roc_function_call(
|
let roc_function_call = roc_function_call(
|
||||||
|
@ -3818,8 +3812,8 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
||||||
(_, Layout::Builtin(Builtin::EmptyList))
|
(_, Layout::Builtin(Builtin::EmptyList))
|
||||||
| (Layout::Builtin(Builtin::EmptyList), _) => empty_list(env),
|
| (Layout::Builtin(Builtin::EmptyList), _) => empty_list(env),
|
||||||
(
|
(
|
||||||
Layout::Builtin(Builtin::List(_, before_layout)),
|
Layout::Builtin(Builtin::List(before_layout)),
|
||||||
Layout::Builtin(Builtin::List(_, after_layout)),
|
Layout::Builtin(Builtin::List(after_layout)),
|
||||||
) => {
|
) => {
|
||||||
let argument_layouts = &[**before_layout];
|
let argument_layouts = &[**before_layout];
|
||||||
|
|
||||||
|
@ -3862,8 +3856,8 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
||||||
(_, Layout::Builtin(Builtin::EmptyList))
|
(_, Layout::Builtin(Builtin::EmptyList))
|
||||||
| (Layout::Builtin(Builtin::EmptyList), _) => empty_list(env),
|
| (Layout::Builtin(Builtin::EmptyList), _) => empty_list(env),
|
||||||
(
|
(
|
||||||
Layout::Builtin(Builtin::List(_, before_layout)),
|
Layout::Builtin(Builtin::List(before_layout)),
|
||||||
Layout::Builtin(Builtin::List(_, after_layout)),
|
Layout::Builtin(Builtin::List(after_layout)),
|
||||||
) => {
|
) => {
|
||||||
let argument_layouts = &[**before_layout];
|
let argument_layouts = &[**before_layout];
|
||||||
|
|
||||||
|
@ -3913,7 +3907,7 @@ fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
match list_layout {
|
match list_layout {
|
||||||
Layout::Builtin(Builtin::EmptyList) => empty_list(env),
|
Layout::Builtin(Builtin::EmptyList) => empty_list(env),
|
||||||
Layout::Builtin(Builtin::List(_, element_layout)) => {
|
Layout::Builtin(Builtin::List(element_layout)) => {
|
||||||
use crate::llvm::bitcode::build_compare_wrapper;
|
use crate::llvm::bitcode::build_compare_wrapper;
|
||||||
|
|
||||||
let argument_layouts = &[**element_layout, **element_layout];
|
let argument_layouts = &[**element_layout, **element_layout];
|
||||||
|
@ -4181,7 +4175,7 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
match list_layout {
|
match list_layout {
|
||||||
Layout::Builtin(Builtin::EmptyList) => empty_list(env),
|
Layout::Builtin(Builtin::EmptyList) => empty_list(env),
|
||||||
Layout::Builtin(Builtin::List(_, element_layout)) => list_drop(
|
Layout::Builtin(Builtin::List(element_layout)) => list_drop(
|
||||||
env,
|
env,
|
||||||
layout_ids,
|
layout_ids,
|
||||||
original_wrapper,
|
original_wrapper,
|
||||||
|
@ -4450,7 +4444,7 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
// no elements, so nothing to remove
|
// no elements, so nothing to remove
|
||||||
empty_list(env)
|
empty_list(env)
|
||||||
}
|
}
|
||||||
Layout::Builtin(Builtin::List(_, element_layout)) => list_set(
|
Layout::Builtin(Builtin::List(element_layout)) => list_set(
|
||||||
env,
|
env,
|
||||||
layout_ids,
|
layout_ids,
|
||||||
list,
|
list,
|
||||||
|
@ -4471,7 +4465,7 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
// no elements, so nothing to remove
|
// no elements, so nothing to remove
|
||||||
empty_list(env)
|
empty_list(env)
|
||||||
}
|
}
|
||||||
Layout::Builtin(Builtin::List(_, element_layout)) => list_set(
|
Layout::Builtin(Builtin::List(element_layout)) => list_set(
|
||||||
env,
|
env,
|
||||||
layout_ids,
|
layout_ids,
|
||||||
list,
|
list,
|
||||||
|
@ -4648,7 +4642,7 @@ fn run_low_level<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
match list_layout {
|
match list_layout {
|
||||||
Layout::Builtin(Builtin::EmptyList) => dict_empty(env),
|
Layout::Builtin(Builtin::EmptyList) => dict_empty(env),
|
||||||
Layout::Builtin(Builtin::List(_, key_layout)) => {
|
Layout::Builtin(Builtin::List(key_layout)) => {
|
||||||
set_from_list(env, layout_ids, list, key_layout)
|
set_from_list(env, layout_ids, list, key_layout)
|
||||||
}
|
}
|
||||||
_ => unreachable!("invalid dict layout"),
|
_ => unreachable!("invalid dict layout"),
|
||||||
|
|
|
@ -56,11 +56,6 @@ fn build_hash_layout<'a, 'ctx, 'env>(
|
||||||
val.into_struct_value(),
|
val.into_struct_value(),
|
||||||
),
|
),
|
||||||
|
|
||||||
Layout::PhantomEmptyStruct => {
|
|
||||||
// just does nothing and returns the seed
|
|
||||||
seed
|
|
||||||
}
|
|
||||||
|
|
||||||
Layout::Union(union_layout) => {
|
Layout::Union(union_layout) => {
|
||||||
build_hash_tag(env, layout_ids, layout, union_layout, seed, val)
|
build_hash_tag(env, layout_ids, layout, union_layout, seed, val)
|
||||||
}
|
}
|
||||||
|
@ -91,10 +86,6 @@ fn build_hash_layout<'a, 'ctx, 'env>(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
Layout::Pointer(_) => {
|
|
||||||
unreachable!("unused")
|
|
||||||
}
|
|
||||||
|
|
||||||
Layout::FunctionPointer(_, _) | Layout::Closure(_, _, _) => {
|
Layout::FunctionPointer(_, _) | Layout::Closure(_, _, _) => {
|
||||||
unreachable!("the type system will guarantee these are never hashed")
|
unreachable!("the type system will guarantee these are never hashed")
|
||||||
}
|
}
|
||||||
|
@ -157,7 +148,7 @@ fn hash_builtin<'a, 'ctx, 'env>(
|
||||||
Builtin::Set(_) => {
|
Builtin::Set(_) => {
|
||||||
todo!("Implement Hash for Set")
|
todo!("Implement Hash for Set")
|
||||||
}
|
}
|
||||||
Builtin::List(_, element_layout) => build_hash_list(
|
Builtin::List(element_layout) => build_hash_list(
|
||||||
env,
|
env,
|
||||||
layout_ids,
|
layout_ids,
|
||||||
layout,
|
layout,
|
||||||
|
|
|
@ -14,7 +14,7 @@ use inkwell::types::{BasicTypeEnum, PointerType};
|
||||||
use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue, StructValue};
|
use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue, StructValue};
|
||||||
use inkwell::{AddressSpace, IntPredicate};
|
use inkwell::{AddressSpace, IntPredicate};
|
||||||
use roc_builtins::bitcode;
|
use roc_builtins::bitcode;
|
||||||
use roc_mono::layout::{Builtin, InPlace, Layout, LayoutIds, MemoryMode};
|
use roc_mono::layout::{Builtin, InPlace, Layout, LayoutIds};
|
||||||
|
|
||||||
fn list_returned_from_zig<'a, 'ctx, 'env>(
|
fn list_returned_from_zig<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
|
@ -196,12 +196,12 @@ pub fn list_join<'a, 'ctx, 'env>(
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
match outer_list_layout {
|
match outer_list_layout {
|
||||||
Layout::Builtin(Builtin::EmptyList)
|
Layout::Builtin(Builtin::EmptyList)
|
||||||
| Layout::Builtin(Builtin::List(_, Layout::Builtin(Builtin::EmptyList))) => {
|
| Layout::Builtin(Builtin::List(Layout::Builtin(Builtin::EmptyList))) => {
|
||||||
// If the input list is empty, or if it is a list of empty lists
|
// If the input list is empty, or if it is a list of empty lists
|
||||||
// then simply return an empty list
|
// then simply return an empty list
|
||||||
empty_list(env)
|
empty_list(env)
|
||||||
}
|
}
|
||||||
Layout::Builtin(Builtin::List(_, Layout::Builtin(Builtin::List(_, element_layout)))) => {
|
Layout::Builtin(Builtin::List(Layout::Builtin(Builtin::List(element_layout)))) => {
|
||||||
call_bitcode_fn_returns_list(
|
call_bitcode_fn_returns_list(
|
||||||
env,
|
env,
|
||||||
&[
|
&[
|
||||||
|
@ -231,13 +231,7 @@ pub fn list_reverse<'a, 'ctx, 'env>(
|
||||||
// this pointer will never actually be dereferenced
|
// this pointer will never actually be dereferenced
|
||||||
Layout::Builtin(Builtin::Int64),
|
Layout::Builtin(Builtin::Int64),
|
||||||
),
|
),
|
||||||
Layout::Builtin(Builtin::List(memory_mode, elem_layout)) => (
|
Layout::Builtin(Builtin::List(elem_layout)) => (InPlace::Clone, *elem_layout),
|
||||||
match memory_mode {
|
|
||||||
MemoryMode::Unique => InPlace::InPlace,
|
|
||||||
MemoryMode::Refcounted => InPlace::Clone,
|
|
||||||
},
|
|
||||||
*elem_layout,
|
|
||||||
),
|
|
||||||
|
|
||||||
_ => unreachable!("Invalid layout {:?} in List.reverse", list_layout),
|
_ => unreachable!("Invalid layout {:?} in List.reverse", list_layout),
|
||||||
};
|
};
|
||||||
|
@ -264,7 +258,7 @@ pub fn list_get_unsafe<'a, 'ctx, 'env>(
|
||||||
let builder = env.builder;
|
let builder = env.builder;
|
||||||
|
|
||||||
match list_layout {
|
match list_layout {
|
||||||
Layout::Builtin(Builtin::List(_, elem_layout)) => {
|
Layout::Builtin(Builtin::List(elem_layout)) => {
|
||||||
let elem_type = basic_type_from_layout(env, elem_layout);
|
let elem_type = basic_type_from_layout(env, elem_layout);
|
||||||
let ptr_type = get_ptr_type(&elem_type, AddressSpace::Generic);
|
let ptr_type = get_ptr_type(&elem_type, AddressSpace::Generic);
|
||||||
// Load the pointer to the array data
|
// Load the pointer to the array data
|
||||||
|
@ -861,7 +855,7 @@ pub fn list_concat<'a, 'ctx, 'env>(
|
||||||
// then simply return an empty list
|
// then simply return an empty list
|
||||||
empty_list(env)
|
empty_list(env)
|
||||||
}
|
}
|
||||||
Layout::Builtin(Builtin::List(_, elem_layout)) => call_bitcode_fn_returns_list(
|
Layout::Builtin(Builtin::List(elem_layout)) => call_bitcode_fn_returns_list(
|
||||||
env,
|
env,
|
||||||
&[
|
&[
|
||||||
pass_list_as_i128(env, first_list),
|
pass_list_as_i128(env, first_list),
|
||||||
|
|
|
@ -99,7 +99,7 @@ fn build_eq_builtin<'a, 'ctx, 'env>(
|
||||||
Builtin::Float16 => float_cmp(FloatPredicate::OEQ, "eq_f16"),
|
Builtin::Float16 => float_cmp(FloatPredicate::OEQ, "eq_f16"),
|
||||||
|
|
||||||
Builtin::Str => str_equal(env, lhs_val, rhs_val),
|
Builtin::Str => str_equal(env, lhs_val, rhs_val),
|
||||||
Builtin::List(_, elem) => build_list_eq(
|
Builtin::List(elem) => build_list_eq(
|
||||||
env,
|
env,
|
||||||
layout_ids,
|
layout_ids,
|
||||||
&Layout::Builtin(*builtin),
|
&Layout::Builtin(*builtin),
|
||||||
|
@ -159,11 +159,6 @@ fn build_eq<'a, 'ctx, 'env>(
|
||||||
rhs_val,
|
rhs_val,
|
||||||
),
|
),
|
||||||
|
|
||||||
Layout::PhantomEmptyStruct => {
|
|
||||||
// always equal to itself
|
|
||||||
env.context.bool_type().const_int(1, false).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
Layout::RecursivePointer => match when_recursive {
|
Layout::RecursivePointer => match when_recursive {
|
||||||
WhenRecursive::Unreachable => {
|
WhenRecursive::Unreachable => {
|
||||||
unreachable!("recursion pointers should never be compared directly")
|
unreachable!("recursion pointers should never be compared directly")
|
||||||
|
@ -197,10 +192,6 @@ fn build_eq<'a, 'ctx, 'env>(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
Layout::Pointer(_) => {
|
|
||||||
unreachable!("unused")
|
|
||||||
}
|
|
||||||
|
|
||||||
Layout::FunctionPointer(_, _) | Layout::Closure(_, _, _) => {
|
Layout::FunctionPointer(_, _) | Layout::Closure(_, _, _) => {
|
||||||
unreachable!("the type system will guarantee these are never compared")
|
unreachable!("the type system will guarantee these are never compared")
|
||||||
}
|
}
|
||||||
|
@ -258,7 +249,7 @@ fn build_neq_builtin<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
result.into()
|
result.into()
|
||||||
}
|
}
|
||||||
Builtin::List(_, elem) => {
|
Builtin::List(elem) => {
|
||||||
let is_equal = build_list_eq(
|
let is_equal = build_list_eq(
|
||||||
env,
|
env,
|
||||||
layout_ids,
|
layout_ids,
|
||||||
|
@ -338,19 +329,10 @@ fn build_neq<'a, 'ctx, 'env>(
|
||||||
result.into()
|
result.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
Layout::PhantomEmptyStruct => {
|
|
||||||
// always equal to itself
|
|
||||||
env.context.bool_type().const_int(1, false).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
Layout::RecursivePointer => {
|
Layout::RecursivePointer => {
|
||||||
unreachable!("recursion pointers should never be compared directly")
|
unreachable!("recursion pointers should never be compared directly")
|
||||||
}
|
}
|
||||||
|
|
||||||
Layout::Pointer(_) => {
|
|
||||||
unreachable!("unused")
|
|
||||||
}
|
|
||||||
|
|
||||||
Layout::FunctionPointer(_, _) | Layout::Closure(_, _, _) => {
|
Layout::FunctionPointer(_, _) | Layout::Closure(_, _, _) => {
|
||||||
unreachable!("the type system will guarantee these are never compared")
|
unreachable!("the type system will guarantee these are never compared")
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,10 +112,6 @@ pub fn basic_type_from_layout<'a, 'ctx, 'env>(
|
||||||
let closure_data_layout = closure_layout.runtime_representation();
|
let closure_data_layout = closure_layout.runtime_representation();
|
||||||
basic_type_from_layout(env, &closure_data_layout)
|
basic_type_from_layout(env, &closure_data_layout)
|
||||||
}
|
}
|
||||||
Pointer(layout) => basic_type_from_layout(env, &layout)
|
|
||||||
.ptr_type(AddressSpace::Generic)
|
|
||||||
.into(),
|
|
||||||
PhantomEmptyStruct => env.context.struct_type(&[], false).into(),
|
|
||||||
Struct(sorted_fields) => basic_type_from_record(env, sorted_fields),
|
Struct(sorted_fields) => basic_type_from_record(env, sorted_fields),
|
||||||
Union(variant) => {
|
Union(variant) => {
|
||||||
use UnionLayout::*;
|
use UnionLayout::*;
|
||||||
|
@ -174,7 +170,7 @@ pub fn basic_type_from_builtin<'a, 'ctx, 'env>(
|
||||||
Float16 => context.f16_type().as_basic_type_enum(),
|
Float16 => context.f16_type().as_basic_type_enum(),
|
||||||
Dict(_, _) | EmptyDict => zig_dict_type(env).into(),
|
Dict(_, _) | EmptyDict => zig_dict_type(env).into(),
|
||||||
Set(_) | EmptySet => zig_dict_type(env).into(),
|
Set(_) | EmptySet => zig_dict_type(env).into(),
|
||||||
List(_, _) | EmptyList => zig_list_type(env).into(),
|
List(_) | EmptyList => zig_list_type(env).into(),
|
||||||
Str | EmptyStr => zig_str_type(env).into(),
|
Str | EmptyStr => zig_str_type(env).into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue, Str
|
||||||
use inkwell::{AddressSpace, IntPredicate};
|
use inkwell::{AddressSpace, IntPredicate};
|
||||||
use roc_module::symbol::Interns;
|
use roc_module::symbol::Interns;
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
use roc_mono::layout::{Builtin, Layout, LayoutIds, MemoryMode, UnionLayout};
|
use roc_mono::layout::{Builtin, Layout, LayoutIds, UnionLayout};
|
||||||
|
|
||||||
pub const REFCOUNT_MAX: usize = 0_usize;
|
pub const REFCOUNT_MAX: usize = 0_usize;
|
||||||
|
|
||||||
|
@ -469,21 +469,17 @@ fn modify_refcount_builtin<'a, 'ctx, 'env>(
|
||||||
use Builtin::*;
|
use Builtin::*;
|
||||||
|
|
||||||
match builtin {
|
match builtin {
|
||||||
List(memory_mode, element_layout) => {
|
List(element_layout) => {
|
||||||
if let MemoryMode::Refcounted = memory_mode {
|
let function = modify_refcount_list(
|
||||||
let function = modify_refcount_list(
|
env,
|
||||||
env,
|
layout_ids,
|
||||||
layout_ids,
|
mode,
|
||||||
mode,
|
when_recursive,
|
||||||
when_recursive,
|
layout,
|
||||||
layout,
|
element_layout,
|
||||||
element_layout,
|
);
|
||||||
);
|
|
||||||
|
|
||||||
Some(function)
|
Some(function)
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Set(element_layout) => {
|
Set(element_layout) => {
|
||||||
let key_layout = &Layout::Struct(&[]);
|
let key_layout = &Layout::Struct(&[]);
|
||||||
|
@ -724,8 +720,6 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
|
||||||
Some(function)
|
Some(function)
|
||||||
}
|
}
|
||||||
|
|
||||||
PhantomEmptyStruct => None,
|
|
||||||
|
|
||||||
Layout::RecursivePointer => match when_recursive {
|
Layout::RecursivePointer => match when_recursive {
|
||||||
WhenRecursive::Unreachable => {
|
WhenRecursive::Unreachable => {
|
||||||
unreachable!("recursion pointers should never be hashed directly")
|
unreachable!("recursion pointers should never be hashed directly")
|
||||||
|
@ -746,7 +740,7 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
FunctionPointer(_, _) | Pointer(_) => None,
|
FunctionPointer(_, _) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1689,7 +1683,7 @@ pub fn refcount_offset<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>, layout: &Layou
|
||||||
let value_bytes = layout.stack_size(env.ptr_bytes) as u64;
|
let value_bytes = layout.stack_size(env.ptr_bytes) as u64;
|
||||||
|
|
||||||
match layout {
|
match layout {
|
||||||
Layout::Builtin(Builtin::List(_, _)) => env.ptr_bytes as u64,
|
Layout::Builtin(Builtin::List(_)) => env.ptr_bytes as u64,
|
||||||
Layout::Builtin(Builtin::Str) => env.ptr_bytes as u64,
|
Layout::Builtin(Builtin::Str) => env.ptr_bytes as u64,
|
||||||
Layout::RecursivePointer | Layout::Union(_) => env.ptr_bytes as u64,
|
Layout::RecursivePointer | Layout::Union(_) => env.ptr_bytes as u64,
|
||||||
_ => (env.ptr_bytes as u64).max(value_bytes),
|
_ => (env.ptr_bytes as u64).max(value_bytes),
|
||||||
|
|
|
@ -377,16 +377,6 @@ fn lowlevel_spec(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_variant_types(
|
fn build_variant_types(
|
||||||
builder: &mut FuncDefBuilder,
|
|
||||||
layout: &Layout,
|
|
||||||
) -> Option<Result<Vec<TypeId>>> {
|
|
||||||
match layout {
|
|
||||||
Layout::Union(union_layout) => Some(build_variant_types_help(builder, union_layout)),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_variant_types_help(
|
|
||||||
builder: &mut FuncDefBuilder,
|
builder: &mut FuncDefBuilder,
|
||||||
union_layout: &UnionLayout,
|
union_layout: &UnionLayout,
|
||||||
) -> Result<Vec<TypeId>> {
|
) -> Result<Vec<TypeId>> {
|
||||||
|
@ -435,7 +425,7 @@ fn expr_spec(
|
||||||
arguments,
|
arguments,
|
||||||
} => {
|
} => {
|
||||||
let value_id = build_tuple_value(builder, env, block, arguments)?;
|
let value_id = build_tuple_value(builder, env, block, arguments)?;
|
||||||
let variant_types = build_variant_types(builder, tag_layout).unwrap()?;
|
let variant_types = build_variant_types(builder, tag_layout)?;
|
||||||
builder.add_make_union(block, &variant_types, *tag_id as u32, value_id)
|
builder.add_make_union(block, &variant_types, *tag_id as u32, value_id)
|
||||||
}
|
}
|
||||||
Struct(fields) => build_tuple_value(builder, env, block, fields),
|
Struct(fields) => build_tuple_value(builder, env, block, fields),
|
||||||
|
@ -525,16 +515,14 @@ fn layout_spec(builder: &mut FuncDefBuilder, layout: &Layout) -> Result<TypeId>
|
||||||
|
|
||||||
match layout {
|
match layout {
|
||||||
Builtin(builtin) => builtin_spec(builder, builtin),
|
Builtin(builtin) => builtin_spec(builder, builtin),
|
||||||
PhantomEmptyStruct => todo!(),
|
|
||||||
Struct(fields) => build_tuple_type(builder, fields),
|
Struct(fields) => build_tuple_type(builder, fields),
|
||||||
Union(union_layout) => {
|
Union(union_layout) => {
|
||||||
let variant_types = build_variant_types_help(builder, union_layout)?;
|
let variant_types = build_variant_types(builder, union_layout)?;
|
||||||
builder.add_union_type(&variant_types)
|
builder.add_union_type(&variant_types)
|
||||||
}
|
}
|
||||||
RecursivePointer => todo!(),
|
RecursivePointer => todo!(),
|
||||||
FunctionPointer(_, _) => todo!(),
|
FunctionPointer(_, _) => todo!(),
|
||||||
Closure(_, _, _) => todo!(),
|
Closure(_, _, _) => todo!(),
|
||||||
Pointer(_) => todo!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -550,7 +538,7 @@ fn builtin_spec(builder: &mut FuncDefBuilder, builtin: &Builtin) -> Result<TypeI
|
||||||
Str => todo!(),
|
Str => todo!(),
|
||||||
Dict(_, _) => todo!(),
|
Dict(_, _) => todo!(),
|
||||||
Set(_) => todo!(),
|
Set(_) => todo!(),
|
||||||
List(_, _) => {
|
List(_) => {
|
||||||
// TODO should incorporate the element type into the name
|
// TODO should incorporate the element type into the name
|
||||||
Ok(builder.add_named_type(MOD_LIST, TypeName(b"List")))
|
Ok(builder.add_named_type(MOD_LIST, TypeName(b"List")))
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
use self::InProgressProc::*;
|
use self::InProgressProc::*;
|
||||||
use crate::exhaustive::{Ctor, Guard, RenderAs, TagId};
|
use crate::exhaustive::{Ctor, Guard, RenderAs, TagId};
|
||||||
use crate::layout::{
|
use crate::layout::{
|
||||||
Builtin, ClosureRepresentation, LambdaSet, Layout, LayoutCache, LayoutProblem, MemoryMode,
|
Builtin, ClosureRepresentation, LambdaSet, Layout, LayoutCache, LayoutProblem, UnionLayout,
|
||||||
UnionLayout, WrappedVariant, TAG_SIZE,
|
WrappedVariant, TAG_SIZE,
|
||||||
};
|
};
|
||||||
use bumpalo::collections::Vec;
|
use bumpalo::collections::Vec;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
|
@ -1150,7 +1150,7 @@ pub enum Expr<'a> {
|
||||||
Call(Call<'a>),
|
Call(Call<'a>),
|
||||||
|
|
||||||
Tag {
|
Tag {
|
||||||
tag_layout: Layout<'a>,
|
tag_layout: UnionLayout<'a>,
|
||||||
tag_name: TagName,
|
tag_name: TagName,
|
||||||
tag_id: u8,
|
tag_id: u8,
|
||||||
union_size: u8,
|
union_size: u8,
|
||||||
|
@ -3371,10 +3371,7 @@ pub fn with_hole<'a>(
|
||||||
Stmt::Let(
|
Stmt::Let(
|
||||||
assigned,
|
assigned,
|
||||||
expr,
|
expr,
|
||||||
Layout::Builtin(Builtin::List(
|
Layout::Builtin(Builtin::List(env.arena.alloc(elem_layout))),
|
||||||
MemoryMode::Refcounted,
|
|
||||||
env.arena.alloc(elem_layout),
|
|
||||||
)),
|
|
||||||
hole,
|
hole,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -3406,12 +3403,10 @@ pub fn with_hole<'a>(
|
||||||
elems: arg_symbols,
|
elems: arg_symbols,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mode = MemoryMode::Refcounted;
|
|
||||||
|
|
||||||
let stmt = Stmt::Let(
|
let stmt = Stmt::Let(
|
||||||
assigned,
|
assigned,
|
||||||
expr,
|
expr,
|
||||||
Layout::Builtin(Builtin::List(mode, env.arena.alloc(elem_layout))),
|
Layout::Builtin(Builtin::List(env.arena.alloc(elem_layout))),
|
||||||
hole,
|
hole,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -4140,10 +4135,15 @@ fn construct_closure_data<'a>(
|
||||||
tag_symbols.push(tag_id_symbol);
|
tag_symbols.push(tag_id_symbol);
|
||||||
tag_symbols.extend(symbols);
|
tag_symbols.extend(symbols);
|
||||||
|
|
||||||
|
let tag_layout = match lambda_set.runtime_representation() {
|
||||||
|
Layout::Union(inner) => inner,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
let expr1 = Expr::Literal(Literal::Int(tag_id as i128));
|
let expr1 = Expr::Literal(Literal::Int(tag_id as i128));
|
||||||
let expr2 = Expr::Tag {
|
let expr2 = Expr::Tag {
|
||||||
tag_id,
|
tag_id,
|
||||||
tag_layout: lambda_set.runtime_representation(),
|
tag_layout,
|
||||||
union_size,
|
union_size,
|
||||||
tag_name,
|
tag_name,
|
||||||
arguments: tag_symbols.into_bump_slice(),
|
arguments: tag_symbols.into_bump_slice(),
|
||||||
|
@ -4305,17 +4305,17 @@ fn convert_tag_union<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_assert!(layouts.len() > 1);
|
debug_assert!(layouts.len() > 1);
|
||||||
let layout = Layout::Union(UnionLayout::Recursive(layouts.into_bump_slice()));
|
let union_layout = UnionLayout::Recursive(layouts.into_bump_slice());
|
||||||
|
|
||||||
let tag = Expr::Tag {
|
let tag = Expr::Tag {
|
||||||
tag_layout: layout,
|
tag_layout: union_layout,
|
||||||
tag_name,
|
tag_name,
|
||||||
tag_id: tag_id as u8,
|
tag_id: tag_id as u8,
|
||||||
union_size,
|
union_size,
|
||||||
arguments: field_symbols,
|
arguments: field_symbols,
|
||||||
};
|
};
|
||||||
|
|
||||||
(tag, layout)
|
(tag, Layout::Union(union_layout))
|
||||||
}
|
}
|
||||||
NonNullableUnwrapped {
|
NonNullableUnwrapped {
|
||||||
fields,
|
fields,
|
||||||
|
@ -4333,17 +4333,17 @@ fn convert_tag_union<'a>(
|
||||||
temp.into_bump_slice()
|
temp.into_bump_slice()
|
||||||
};
|
};
|
||||||
|
|
||||||
let layout = Layout::Union(UnionLayout::NonNullableUnwrapped(fields));
|
let union_layout = UnionLayout::NonNullableUnwrapped(fields);
|
||||||
|
|
||||||
let tag = Expr::Tag {
|
let tag = Expr::Tag {
|
||||||
tag_layout: layout,
|
tag_layout: union_layout,
|
||||||
tag_name,
|
tag_name,
|
||||||
tag_id: tag_id as u8,
|
tag_id: tag_id as u8,
|
||||||
union_size,
|
union_size,
|
||||||
arguments: field_symbols,
|
arguments: field_symbols,
|
||||||
};
|
};
|
||||||
|
|
||||||
(tag, layout)
|
(tag, Layout::Union(union_layout))
|
||||||
}
|
}
|
||||||
NonRecursive { sorted_tag_layouts } => {
|
NonRecursive { sorted_tag_layouts } => {
|
||||||
let tag_id_symbol = env.unique_symbol();
|
let tag_id_symbol = env.unique_symbol();
|
||||||
|
@ -4365,18 +4365,17 @@ fn convert_tag_union<'a>(
|
||||||
layouts.push(arg_layouts);
|
layouts.push(arg_layouts);
|
||||||
}
|
}
|
||||||
|
|
||||||
let layout =
|
let union_layout = UnionLayout::NonRecursive(layouts.into_bump_slice());
|
||||||
Layout::Union(UnionLayout::NonRecursive(layouts.into_bump_slice()));
|
|
||||||
|
|
||||||
let tag = Expr::Tag {
|
let tag = Expr::Tag {
|
||||||
tag_layout: layout,
|
tag_layout: union_layout,
|
||||||
tag_name,
|
tag_name,
|
||||||
tag_id: tag_id as u8,
|
tag_id: tag_id as u8,
|
||||||
union_size,
|
union_size,
|
||||||
arguments: field_symbols,
|
arguments: field_symbols,
|
||||||
};
|
};
|
||||||
|
|
||||||
(tag, layout)
|
(tag, Layout::Union(union_layout))
|
||||||
}
|
}
|
||||||
NullableWrapped {
|
NullableWrapped {
|
||||||
nullable_id,
|
nullable_id,
|
||||||
|
@ -4402,20 +4401,20 @@ fn convert_tag_union<'a>(
|
||||||
layouts.push(arg_layouts);
|
layouts.push(arg_layouts);
|
||||||
}
|
}
|
||||||
|
|
||||||
let layout = Layout::Union(UnionLayout::NullableWrapped {
|
let union_layout = UnionLayout::NullableWrapped {
|
||||||
nullable_id,
|
nullable_id,
|
||||||
other_tags: layouts.into_bump_slice(),
|
other_tags: layouts.into_bump_slice(),
|
||||||
});
|
};
|
||||||
|
|
||||||
let tag = Expr::Tag {
|
let tag = Expr::Tag {
|
||||||
tag_layout: layout,
|
tag_layout: union_layout,
|
||||||
tag_name,
|
tag_name,
|
||||||
tag_id: tag_id as u8,
|
tag_id: tag_id as u8,
|
||||||
union_size,
|
union_size,
|
||||||
arguments: field_symbols,
|
arguments: field_symbols,
|
||||||
};
|
};
|
||||||
|
|
||||||
(tag, layout)
|
(tag, Layout::Union(union_layout))
|
||||||
}
|
}
|
||||||
NullableUnwrapped {
|
NullableUnwrapped {
|
||||||
nullable_id,
|
nullable_id,
|
||||||
|
@ -4437,20 +4436,20 @@ fn convert_tag_union<'a>(
|
||||||
temp.into_bump_slice()
|
temp.into_bump_slice()
|
||||||
};
|
};
|
||||||
|
|
||||||
let layout = Layout::Union(UnionLayout::NullableUnwrapped {
|
let union_layout = UnionLayout::NullableUnwrapped {
|
||||||
nullable_id,
|
nullable_id,
|
||||||
other_fields,
|
other_fields,
|
||||||
});
|
};
|
||||||
|
|
||||||
let tag = Expr::Tag {
|
let tag = Expr::Tag {
|
||||||
tag_layout: layout,
|
tag_layout: union_layout,
|
||||||
tag_name,
|
tag_name,
|
||||||
tag_id: tag_id as u8,
|
tag_id: tag_id as u8,
|
||||||
union_size,
|
union_size,
|
||||||
arguments: field_symbols,
|
arguments: field_symbols,
|
||||||
};
|
};
|
||||||
|
|
||||||
(tag, layout)
|
(tag, Layout::Union(union_layout))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -40,24 +40,19 @@ pub enum Layout<'a> {
|
||||||
/// A layout that is empty (turns into the empty struct in LLVM IR
|
/// A layout that is empty (turns into the empty struct in LLVM IR
|
||||||
/// but for our purposes, not zero-sized, so it does not get dropped from data structures
|
/// but for our purposes, not zero-sized, so it does not get dropped from data structures
|
||||||
/// this is important for closures that capture zero-sized values
|
/// this is important for closures that capture zero-sized values
|
||||||
PhantomEmptyStruct,
|
|
||||||
Struct(&'a [Layout<'a>]),
|
Struct(&'a [Layout<'a>]),
|
||||||
Union(UnionLayout<'a>),
|
Union(UnionLayout<'a>),
|
||||||
RecursivePointer,
|
RecursivePointer,
|
||||||
/// A function. The types of its arguments, then the type of its return value.
|
/// A function. The types of its arguments, then the type of its return value.
|
||||||
FunctionPointer(&'a [Layout<'a>], &'a Layout<'a>),
|
FunctionPointer(&'a [Layout<'a>], &'a Layout<'a>),
|
||||||
Closure(&'a [Layout<'a>], LambdaSet<'a>, &'a Layout<'a>),
|
Closure(&'a [Layout<'a>], LambdaSet<'a>, &'a Layout<'a>),
|
||||||
Pointer(&'a Layout<'a>),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Layout<'a> {
|
impl<'a> Layout<'a> {
|
||||||
pub fn in_place(&self) -> InPlace {
|
pub fn in_place(&self) -> InPlace {
|
||||||
match self {
|
match self {
|
||||||
Layout::Builtin(Builtin::EmptyList) => InPlace::InPlace,
|
Layout::Builtin(Builtin::EmptyList) => InPlace::InPlace,
|
||||||
Layout::Builtin(Builtin::List(memory_mode, _)) => match memory_mode {
|
Layout::Builtin(Builtin::List(_)) => InPlace::Clone,
|
||||||
MemoryMode::Unique => InPlace::InPlace,
|
|
||||||
MemoryMode::Refcounted => InPlace::Clone,
|
|
||||||
},
|
|
||||||
Layout::Builtin(Builtin::EmptyStr) => InPlace::InPlace,
|
Layout::Builtin(Builtin::EmptyStr) => InPlace::InPlace,
|
||||||
Layout::Builtin(Builtin::Str) => InPlace::Clone,
|
Layout::Builtin(Builtin::Str) => InPlace::Clone,
|
||||||
Layout::Builtin(Builtin::Int1) => InPlace::Clone,
|
Layout::Builtin(Builtin::Int1) => InPlace::Clone,
|
||||||
|
@ -337,12 +332,6 @@ impl<'a> LambdaSet<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Copy)]
|
|
||||||
pub enum MemoryMode {
|
|
||||||
Unique,
|
|
||||||
Refcounted,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
pub enum Builtin<'a> {
|
pub enum Builtin<'a> {
|
||||||
Int128,
|
Int128,
|
||||||
|
@ -359,7 +348,7 @@ pub enum Builtin<'a> {
|
||||||
Str,
|
Str,
|
||||||
Dict(&'a Layout<'a>, &'a Layout<'a>),
|
Dict(&'a Layout<'a>, &'a Layout<'a>),
|
||||||
Set(&'a Layout<'a>),
|
Set(&'a Layout<'a>),
|
||||||
List(MemoryMode, &'a Layout<'a>),
|
List(&'a Layout<'a>),
|
||||||
EmptyStr,
|
EmptyStr,
|
||||||
EmptyList,
|
EmptyList,
|
||||||
EmptyDict,
|
EmptyDict,
|
||||||
|
@ -483,7 +472,6 @@ impl<'a> Layout<'a> {
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Builtin(builtin) => builtin.safe_to_memcpy(),
|
Builtin(builtin) => builtin.safe_to_memcpy(),
|
||||||
PhantomEmptyStruct => true,
|
|
||||||
Struct(fields) => fields
|
Struct(fields) => fields
|
||||||
.iter()
|
.iter()
|
||||||
.all(|field_layout| field_layout.safe_to_memcpy()),
|
.all(|field_layout| field_layout.safe_to_memcpy()),
|
||||||
|
@ -508,10 +496,6 @@ impl<'a> Layout<'a> {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
Closure(_, closure_layout, _) => closure_layout.safe_to_memcpy(),
|
Closure(_, closure_layout, _) => closure_layout.safe_to_memcpy(),
|
||||||
Pointer(_) => {
|
|
||||||
// We cannot memcpy pointers, because then we would have the same pointer in multiple places!
|
|
||||||
false
|
|
||||||
}
|
|
||||||
RecursivePointer => {
|
RecursivePointer => {
|
||||||
// We cannot memcpy pointers, because then we would have the same pointer in multiple places!
|
// We cannot memcpy pointers, because then we would have the same pointer in multiple places!
|
||||||
false
|
false
|
||||||
|
@ -523,12 +507,7 @@ impl<'a> Layout<'a> {
|
||||||
// For this calculation, we don't need an accurate
|
// For this calculation, we don't need an accurate
|
||||||
// stack size, we just need to know whether it's zero,
|
// stack size, we just need to know whether it's zero,
|
||||||
// so it's fine to use a pointer size of 1.
|
// so it's fine to use a pointer size of 1.
|
||||||
if let Layout::PhantomEmptyStruct = self {
|
false
|
||||||
false
|
|
||||||
} else {
|
|
||||||
// self.stack_size(1) == 0
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stack_size(&self, pointer_size: u32) -> u32 {
|
pub fn stack_size(&self, pointer_size: u32) -> u32 {
|
||||||
|
@ -536,7 +515,6 @@ impl<'a> Layout<'a> {
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Builtin(builtin) => builtin.stack_size(pointer_size),
|
Builtin(builtin) => builtin.stack_size(pointer_size),
|
||||||
PhantomEmptyStruct => 0,
|
|
||||||
Struct(fields) => {
|
Struct(fields) => {
|
||||||
let mut sum = 0;
|
let mut sum = 0;
|
||||||
|
|
||||||
|
@ -570,7 +548,6 @@ impl<'a> Layout<'a> {
|
||||||
Closure(_, lambda_set, _) => lambda_set.stack_size(pointer_size),
|
Closure(_, lambda_set, _) => lambda_set.stack_size(pointer_size),
|
||||||
FunctionPointer(_, _) => pointer_size,
|
FunctionPointer(_, _) => pointer_size,
|
||||||
RecursivePointer => pointer_size,
|
RecursivePointer => pointer_size,
|
||||||
Pointer(_) => pointer_size,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -600,10 +577,8 @@ impl<'a> Layout<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Layout::Builtin(builtin) => builtin.alignment_bytes(pointer_size),
|
Layout::Builtin(builtin) => builtin.alignment_bytes(pointer_size),
|
||||||
Layout::PhantomEmptyStruct => 0,
|
|
||||||
Layout::RecursivePointer => pointer_size,
|
Layout::RecursivePointer => pointer_size,
|
||||||
Layout::FunctionPointer(_, _) => pointer_size,
|
Layout::FunctionPointer(_, _) => pointer_size,
|
||||||
Layout::Pointer(_) => pointer_size,
|
|
||||||
Layout::Closure(_, captured, _) => {
|
Layout::Closure(_, captured, _) => {
|
||||||
pointer_size.max(captured.alignment_bytes(pointer_size))
|
pointer_size.max(captured.alignment_bytes(pointer_size))
|
||||||
}
|
}
|
||||||
|
@ -626,7 +601,7 @@ impl<'a> Layout<'a> {
|
||||||
|
|
||||||
RecursivePointer => true,
|
RecursivePointer => true,
|
||||||
|
|
||||||
Builtin(List(MemoryMode::Refcounted, _)) | Builtin(Str) => true,
|
Builtin(List(_)) | Builtin(Str) => true,
|
||||||
|
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
@ -640,7 +615,6 @@ impl<'a> Layout<'a> {
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Builtin(builtin) => builtin.is_refcounted(),
|
Builtin(builtin) => builtin.is_refcounted(),
|
||||||
PhantomEmptyStruct => false,
|
|
||||||
Struct(fields) => fields.iter().any(|f| f.contains_refcounted()),
|
Struct(fields) => fields.iter().any(|f| f.contains_refcounted()),
|
||||||
Union(variant) => {
|
Union(variant) => {
|
||||||
use UnionLayout::*;
|
use UnionLayout::*;
|
||||||
|
@ -659,7 +633,7 @@ impl<'a> Layout<'a> {
|
||||||
}
|
}
|
||||||
RecursivePointer => true,
|
RecursivePointer => true,
|
||||||
Closure(_, closure_layout, _) => closure_layout.contains_refcounted(),
|
Closure(_, closure_layout, _) => closure_layout.contains_refcounted(),
|
||||||
FunctionPointer(_, _) | Pointer(_) => false,
|
FunctionPointer(_, _) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -673,7 +647,6 @@ impl<'a> Layout<'a> {
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Builtin(builtin) => builtin.to_doc(alloc, parens),
|
Builtin(builtin) => builtin.to_doc(alloc, parens),
|
||||||
PhantomEmptyStruct => alloc.text("{}"),
|
|
||||||
Struct(fields) => {
|
Struct(fields) => {
|
||||||
let fields_doc = fields.iter().map(|x| x.to_doc(alloc, parens));
|
let fields_doc = fields.iter().map(|x| x.to_doc(alloc, parens));
|
||||||
|
|
||||||
|
@ -706,7 +679,6 @@ impl<'a> Layout<'a> {
|
||||||
.append(" |} -> ")
|
.append(" |} -> ")
|
||||||
.append(result.to_doc(alloc, Parens::InFunction))
|
.append(result.to_doc(alloc, Parens::InFunction))
|
||||||
}
|
}
|
||||||
Pointer(_) => todo!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -878,7 +850,7 @@ impl<'a> Builtin<'a> {
|
||||||
Str | EmptyStr => Builtin::STR_WORDS * pointer_size,
|
Str | EmptyStr => Builtin::STR_WORDS * pointer_size,
|
||||||
Dict(_, _) | EmptyDict => Builtin::DICT_WORDS * pointer_size,
|
Dict(_, _) | EmptyDict => Builtin::DICT_WORDS * pointer_size,
|
||||||
Set(_) | EmptySet => Builtin::SET_WORDS * pointer_size,
|
Set(_) | EmptySet => Builtin::SET_WORDS * pointer_size,
|
||||||
List(_, _) | EmptyList => Builtin::LIST_WORDS * pointer_size,
|
List(_) | EmptyList => Builtin::LIST_WORDS * pointer_size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -904,7 +876,7 @@ impl<'a> Builtin<'a> {
|
||||||
Str | EmptyStr => pointer_size,
|
Str | EmptyStr => pointer_size,
|
||||||
Dict(_, _) | EmptyDict => pointer_size,
|
Dict(_, _) | EmptyDict => pointer_size,
|
||||||
Set(_) | EmptySet => pointer_size,
|
Set(_) | EmptySet => pointer_size,
|
||||||
List(_, _) | EmptyList => pointer_size,
|
List(_) | EmptyList => pointer_size,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -914,7 +886,7 @@ impl<'a> Builtin<'a> {
|
||||||
match self {
|
match self {
|
||||||
Int128 | Int64 | Int32 | Int16 | Int8 | Int1 | Usize | Float128 | Float64 | Float32
|
Int128 | Int64 | Int32 | Int16 | Int8 | Int1 | Usize | Float128 | Float64 | Float32
|
||||||
| Float16 | EmptyStr | EmptyDict | EmptyList | EmptySet => true,
|
| Float16 | EmptyStr | EmptyDict | EmptyList | EmptySet => true,
|
||||||
Str | Dict(_, _) | Set(_) | List(_, _) => false,
|
Str | Dict(_, _) | Set(_) | List(_) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -925,10 +897,7 @@ impl<'a> Builtin<'a> {
|
||||||
match self {
|
match self {
|
||||||
Int128 | Int64 | Int32 | Int16 | Int8 | Int1 | Usize | Float128 | Float64 | Float32
|
Int128 | Int64 | Int32 | Int16 | Int8 | Int1 | Usize | Float128 | Float64 | Float32
|
||||||
| Float16 | EmptyStr | EmptyDict | EmptyList | EmptySet => false,
|
| Float16 | EmptyStr | EmptyDict | EmptyList | EmptySet => false,
|
||||||
List(mode, element_layout) => match mode {
|
List(_) => true,
|
||||||
MemoryMode::Refcounted => true,
|
|
||||||
MemoryMode::Unique => element_layout.contains_refcounted(),
|
|
||||||
},
|
|
||||||
|
|
||||||
Str | Dict(_, _) | Set(_) => true,
|
Str | Dict(_, _) | Set(_) => true,
|
||||||
}
|
}
|
||||||
|
@ -961,7 +930,7 @@ impl<'a> Builtin<'a> {
|
||||||
EmptySet => alloc.text("EmptySet"),
|
EmptySet => alloc.text("EmptySet"),
|
||||||
|
|
||||||
Str => alloc.text("Str"),
|
Str => alloc.text("Str"),
|
||||||
List(_, layout) => alloc
|
List(layout) => alloc
|
||||||
.text("List ")
|
.text("List ")
|
||||||
.append(layout.to_doc(alloc, Parens::InTypeParam)),
|
.append(layout.to_doc(alloc, Parens::InTypeParam)),
|
||||||
Set(layout) => alloc
|
Set(layout) => alloc
|
||||||
|
@ -1901,11 +1870,7 @@ pub fn list_layout_from_elem<'a>(
|
||||||
_ => {
|
_ => {
|
||||||
let elem_layout = Layout::from_var(env, elem_var)?;
|
let elem_layout = Layout::from_var(env, elem_var)?;
|
||||||
|
|
||||||
// This is a normal list.
|
Ok(Layout::Builtin(Builtin::List(env.arena.alloc(elem_layout))))
|
||||||
Ok(Layout::Builtin(Builtin::List(
|
|
||||||
MemoryMode::Refcounted,
|
|
||||||
env.arena.alloc(elem_layout),
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1971,7 +1936,7 @@ impl<'a> std::convert::TryFrom<&Layout<'a>> for ListLayout<'a> {
|
||||||
fn try_from(value: &Layout<'a>) -> Result<Self, Self::Error> {
|
fn try_from(value: &Layout<'a>) -> Result<Self, Self::Error> {
|
||||||
match value {
|
match value {
|
||||||
Layout::Builtin(Builtin::EmptyList) => Ok(ListLayout::EmptyList),
|
Layout::Builtin(Builtin::EmptyList) => Ok(ListLayout::EmptyList),
|
||||||
Layout::Builtin(Builtin::List(_, element)) => Ok(ListLayout::List(element)),
|
Layout::Builtin(Builtin::List(element)) => Ok(ListLayout::List(element)),
|
||||||
_ => Err(()),
|
_ => Err(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue