mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 23:04:49 +00:00
Merge branch 'trunk' of https://github.com/rtfeldman/roc into add-dec-types
This commit is contained in:
commit
67eef2c97f
82 changed files with 3791 additions and 2228 deletions
|
@ -4,7 +4,7 @@ use self::InProgressProc::*;
|
|||
use crate::exhaustive::{Ctor, Guard, RenderAs, TagId};
|
||||
use crate::layout::{
|
||||
Builtin, ClosureRepresentation, LambdaSet, Layout, LayoutCache, LayoutProblem,
|
||||
RawFunctionLayout, UnionLayout, WrappedVariant, TAG_SIZE,
|
||||
RawFunctionLayout, UnionLayout, WrappedVariant,
|
||||
};
|
||||
use bumpalo::collections::Vec;
|
||||
use bumpalo::Bump;
|
||||
|
@ -2083,18 +2083,16 @@ fn specialize_external<'a>(
|
|||
tag_id,
|
||||
..
|
||||
} => {
|
||||
debug_assert_eq!(field_layouts.len() - 1, captured.len());
|
||||
// TODO check for field_layouts.len() == 1 and do a rename in that case?
|
||||
for (mut index, (symbol, _variable)) in captured.iter().enumerate() {
|
||||
// the field layouts do store the tag, but the tag value is
|
||||
// not captured. So we drop the layout of the tag ID here
|
||||
index += 1;
|
||||
debug_assert!(matches!(union_layout, UnionLayout::NonRecursive(_)));
|
||||
debug_assert_eq!(field_layouts.len(), captured.len());
|
||||
|
||||
// TODO therefore should the wrapped here not be RecordOrSingleTagUnion?
|
||||
for (index, (symbol, _variable)) in captured.iter().enumerate() {
|
||||
let expr = Expr::UnionAtIndex {
|
||||
tag_id,
|
||||
structure: Symbol::ARG_CLOSURE,
|
||||
index: index as _,
|
||||
// union at index still expects the index to be +1; it thinks
|
||||
// the tag id is stored
|
||||
index: index as u64,
|
||||
union_layout,
|
||||
};
|
||||
|
||||
|
@ -3152,118 +3150,123 @@ pub fn with_hole<'a>(
|
|||
branches,
|
||||
final_else,
|
||||
} => {
|
||||
let ret_layout = layout_cache
|
||||
.from_var(env.arena, branch_var, env.subs)
|
||||
.expect("invalid ret_layout");
|
||||
let cond_layout = layout_cache
|
||||
.from_var(env.arena, cond_var, env.subs)
|
||||
.expect("invalid cond_layout");
|
||||
match (
|
||||
layout_cache.from_var(env.arena, branch_var, env.subs),
|
||||
layout_cache.from_var(env.arena, cond_var, env.subs),
|
||||
) {
|
||||
(Ok(ret_layout), Ok(cond_layout)) => {
|
||||
// if the hole is a return, then we don't need to merge the two
|
||||
// branches together again, we can just immediately return
|
||||
let is_terminated = matches!(hole, Stmt::Ret(_));
|
||||
|
||||
// if the hole is a return, then we don't need to merge the two
|
||||
// branches together again, we can just immediately return
|
||||
let is_terminated = matches!(hole, Stmt::Ret(_));
|
||||
if is_terminated {
|
||||
let terminator = hole;
|
||||
|
||||
if is_terminated {
|
||||
let terminator = hole;
|
||||
let mut stmt = with_hole(
|
||||
env,
|
||||
final_else.value,
|
||||
branch_var,
|
||||
procs,
|
||||
layout_cache,
|
||||
assigned,
|
||||
terminator,
|
||||
);
|
||||
|
||||
let mut stmt = with_hole(
|
||||
env,
|
||||
final_else.value,
|
||||
branch_var,
|
||||
procs,
|
||||
layout_cache,
|
||||
assigned,
|
||||
terminator,
|
||||
);
|
||||
for (loc_cond, loc_then) in branches.into_iter().rev() {
|
||||
let branching_symbol = env.unique_symbol();
|
||||
|
||||
for (loc_cond, loc_then) in branches.into_iter().rev() {
|
||||
let branching_symbol = env.unique_symbol();
|
||||
let then = with_hole(
|
||||
env,
|
||||
loc_then.value,
|
||||
branch_var,
|
||||
procs,
|
||||
layout_cache,
|
||||
assigned,
|
||||
terminator,
|
||||
);
|
||||
|
||||
let then = with_hole(
|
||||
env,
|
||||
loc_then.value,
|
||||
branch_var,
|
||||
procs,
|
||||
layout_cache,
|
||||
assigned,
|
||||
terminator,
|
||||
);
|
||||
stmt = cond(env, branching_symbol, cond_layout, then, stmt, ret_layout);
|
||||
|
||||
stmt = cond(env, branching_symbol, cond_layout, then, stmt, ret_layout);
|
||||
// add condition
|
||||
stmt = with_hole(
|
||||
env,
|
||||
loc_cond.value,
|
||||
cond_var,
|
||||
procs,
|
||||
layout_cache,
|
||||
branching_symbol,
|
||||
env.arena.alloc(stmt),
|
||||
);
|
||||
}
|
||||
stmt
|
||||
} else {
|
||||
let assigned_in_jump = env.unique_symbol();
|
||||
let id = JoinPointId(env.unique_symbol());
|
||||
|
||||
// add condition
|
||||
stmt = with_hole(
|
||||
env,
|
||||
loc_cond.value,
|
||||
cond_var,
|
||||
procs,
|
||||
layout_cache,
|
||||
branching_symbol,
|
||||
env.arena.alloc(stmt),
|
||||
);
|
||||
}
|
||||
stmt
|
||||
} else {
|
||||
let assigned_in_jump = env.unique_symbol();
|
||||
let id = JoinPointId(env.unique_symbol());
|
||||
|
||||
let terminator = env
|
||||
.arena
|
||||
.alloc(Stmt::Jump(id, env.arena.alloc([assigned_in_jump])));
|
||||
|
||||
let mut stmt = with_hole(
|
||||
env,
|
||||
final_else.value,
|
||||
branch_var,
|
||||
procs,
|
||||
layout_cache,
|
||||
assigned_in_jump,
|
||||
terminator,
|
||||
);
|
||||
|
||||
for (loc_cond, loc_then) in branches.into_iter().rev() {
|
||||
let branching_symbol = possible_reuse_symbol(env, procs, &loc_cond.value);
|
||||
|
||||
let then = with_hole(
|
||||
env,
|
||||
loc_then.value,
|
||||
branch_var,
|
||||
procs,
|
||||
layout_cache,
|
||||
assigned_in_jump,
|
||||
terminator,
|
||||
);
|
||||
|
||||
stmt = cond(env, branching_symbol, cond_layout, then, stmt, ret_layout);
|
||||
|
||||
// add condition
|
||||
stmt = assign_to_symbol(
|
||||
env,
|
||||
procs,
|
||||
layout_cache,
|
||||
cond_var,
|
||||
loc_cond,
|
||||
branching_symbol,
|
||||
stmt,
|
||||
);
|
||||
}
|
||||
|
||||
let layout = layout_cache
|
||||
.from_var(env.arena, branch_var, env.subs)
|
||||
.unwrap_or_else(|err| panic!("TODO turn fn_var into a RuntimeError {:?}", err));
|
||||
|
||||
let param = Param {
|
||||
symbol: assigned,
|
||||
layout,
|
||||
borrow: false,
|
||||
};
|
||||
|
||||
Stmt::Join {
|
||||
id,
|
||||
parameters: env.arena.alloc([param]),
|
||||
remainder: env.arena.alloc(stmt),
|
||||
body: hole,
|
||||
let terminator = env
|
||||
.arena
|
||||
.alloc(Stmt::Jump(id, env.arena.alloc([assigned_in_jump])));
|
||||
|
||||
let mut stmt = with_hole(
|
||||
env,
|
||||
final_else.value,
|
||||
branch_var,
|
||||
procs,
|
||||
layout_cache,
|
||||
assigned_in_jump,
|
||||
terminator,
|
||||
);
|
||||
|
||||
for (loc_cond, loc_then) in branches.into_iter().rev() {
|
||||
let branching_symbol =
|
||||
possible_reuse_symbol(env, procs, &loc_cond.value);
|
||||
|
||||
let then = with_hole(
|
||||
env,
|
||||
loc_then.value,
|
||||
branch_var,
|
||||
procs,
|
||||
layout_cache,
|
||||
assigned_in_jump,
|
||||
terminator,
|
||||
);
|
||||
|
||||
stmt = cond(env, branching_symbol, cond_layout, then, stmt, ret_layout);
|
||||
|
||||
// add condition
|
||||
stmt = assign_to_symbol(
|
||||
env,
|
||||
procs,
|
||||
layout_cache,
|
||||
cond_var,
|
||||
loc_cond,
|
||||
branching_symbol,
|
||||
stmt,
|
||||
);
|
||||
}
|
||||
|
||||
let layout = layout_cache
|
||||
.from_var(env.arena, branch_var, env.subs)
|
||||
.unwrap_or_else(|err| {
|
||||
panic!("TODO turn fn_var into a RuntimeError {:?}", err)
|
||||
});
|
||||
|
||||
let param = Param {
|
||||
symbol: assigned,
|
||||
layout,
|
||||
borrow: false,
|
||||
};
|
||||
|
||||
Stmt::Join {
|
||||
id,
|
||||
parameters: env.arena.alloc([param]),
|
||||
remainder: env.arena.alloc(stmt),
|
||||
body: hole,
|
||||
}
|
||||
}
|
||||
}
|
||||
(Err(_), _) => Stmt::RuntimeError("invalid ret_layout"),
|
||||
(_, Err(_)) => Stmt::RuntimeError("invalid cond_layout"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4037,29 +4040,20 @@ fn construct_closure_data<'a>(
|
|||
tag_name,
|
||||
union_layout,
|
||||
} => {
|
||||
let tag_id_symbol = env.unique_symbol();
|
||||
let mut tag_symbols = Vec::with_capacity_in(symbols.len() + 1, env.arena);
|
||||
tag_symbols.push(tag_id_symbol);
|
||||
tag_symbols.extend(symbols);
|
||||
|
||||
let expr1 = Expr::Literal(Literal::Int(tag_id as i128));
|
||||
let expr2 = Expr::Tag {
|
||||
let expr = Expr::Tag {
|
||||
tag_id,
|
||||
tag_layout: union_layout,
|
||||
union_size,
|
||||
tag_name,
|
||||
arguments: tag_symbols.into_bump_slice(),
|
||||
arguments: symbols,
|
||||
};
|
||||
|
||||
let hole = Stmt::Let(
|
||||
Stmt::Let(
|
||||
assigned,
|
||||
expr2,
|
||||
expr,
|
||||
lambda_set.runtime_representation(),
|
||||
env.arena.alloc(hole),
|
||||
);
|
||||
|
||||
let hole = env.arena.alloc(hole);
|
||||
Stmt::Let(tag_id_symbol, expr1, Layout::Builtin(Builtin::Int64), hole)
|
||||
)
|
||||
}
|
||||
ClosureRepresentation::Other(Layout::Struct(field_layouts)) => {
|
||||
debug_assert_eq!(field_layouts.len(), symbols.len());
|
||||
|
@ -4137,17 +4131,17 @@ fn convert_tag_union<'a>(
|
|||
hole,
|
||||
),
|
||||
ByteUnion(tag_names) => {
|
||||
let tag_id = tag_names
|
||||
.iter()
|
||||
.position(|key| key == &tag_name)
|
||||
.expect("tag must be in its own type");
|
||||
let opt_tag_id = tag_names.iter().position(|key| key == &tag_name);
|
||||
|
||||
Stmt::Let(
|
||||
assigned,
|
||||
Expr::Literal(Literal::Byte(tag_id as u8)),
|
||||
Layout::Builtin(Builtin::Int8),
|
||||
hole,
|
||||
)
|
||||
match opt_tag_id {
|
||||
Some(tag_id) => Stmt::Let(
|
||||
assigned,
|
||||
Expr::Literal(Literal::Byte(tag_id as u8)),
|
||||
Layout::Builtin(Builtin::Int8),
|
||||
hole,
|
||||
),
|
||||
None => Stmt::RuntimeError("tag must be in its own type"),
|
||||
}
|
||||
}
|
||||
|
||||
Newtype {
|
||||
|
@ -4187,15 +4181,13 @@ fn convert_tag_union<'a>(
|
|||
let opt_tag_id_symbol;
|
||||
|
||||
use WrappedVariant::*;
|
||||
let (tag, layout) = match variant {
|
||||
let (tag, union_layout) = match variant {
|
||||
Recursive { sorted_tag_layouts } => {
|
||||
debug_assert!(sorted_tag_layouts.len() > 1);
|
||||
let tag_id_symbol = env.unique_symbol();
|
||||
opt_tag_id_symbol = Some(tag_id_symbol);
|
||||
opt_tag_id_symbol = None;
|
||||
|
||||
field_symbols = {
|
||||
let mut temp = Vec::with_capacity_in(field_symbols_temp.len() + 1, arena);
|
||||
temp.push(tag_id_symbol);
|
||||
|
||||
temp.extend(field_symbols_temp.iter().map(|r| r.1));
|
||||
|
||||
|
@ -4220,7 +4212,7 @@ fn convert_tag_union<'a>(
|
|||
arguments: field_symbols,
|
||||
};
|
||||
|
||||
(tag, Layout::Union(union_layout))
|
||||
(tag, union_layout)
|
||||
}
|
||||
NonNullableUnwrapped {
|
||||
fields,
|
||||
|
@ -4248,15 +4240,13 @@ fn convert_tag_union<'a>(
|
|||
arguments: field_symbols,
|
||||
};
|
||||
|
||||
(tag, Layout::Union(union_layout))
|
||||
(tag, union_layout)
|
||||
}
|
||||
NonRecursive { sorted_tag_layouts } => {
|
||||
let tag_id_symbol = env.unique_symbol();
|
||||
opt_tag_id_symbol = Some(tag_id_symbol);
|
||||
opt_tag_id_symbol = None;
|
||||
|
||||
field_symbols = {
|
||||
let mut temp = Vec::with_capacity_in(field_symbols_temp.len() + 1, arena);
|
||||
temp.push(tag_id_symbol);
|
||||
let mut temp = Vec::with_capacity_in(field_symbols_temp.len(), arena);
|
||||
|
||||
temp.extend(field_symbols_temp.iter().map(|r| r.1));
|
||||
|
||||
|
@ -4280,19 +4270,17 @@ fn convert_tag_union<'a>(
|
|||
arguments: field_symbols,
|
||||
};
|
||||
|
||||
(tag, Layout::Union(union_layout))
|
||||
(tag, union_layout)
|
||||
}
|
||||
NullableWrapped {
|
||||
nullable_id,
|
||||
nullable_name: _,
|
||||
sorted_tag_layouts,
|
||||
} => {
|
||||
let tag_id_symbol = env.unique_symbol();
|
||||
opt_tag_id_symbol = Some(tag_id_symbol);
|
||||
opt_tag_id_symbol = None;
|
||||
|
||||
field_symbols = {
|
||||
let mut temp = Vec::with_capacity_in(field_symbols_temp.len() + 1, arena);
|
||||
temp.push(tag_id_symbol);
|
||||
|
||||
temp.extend(field_symbols_temp.iter().map(|r| r.1));
|
||||
|
||||
|
@ -4319,7 +4307,7 @@ fn convert_tag_union<'a>(
|
|||
arguments: field_symbols,
|
||||
};
|
||||
|
||||
(tag, Layout::Union(union_layout))
|
||||
(tag, union_layout)
|
||||
}
|
||||
NullableUnwrapped {
|
||||
nullable_id,
|
||||
|
@ -4333,8 +4321,6 @@ fn convert_tag_union<'a>(
|
|||
|
||||
field_symbols = {
|
||||
let mut temp = Vec::with_capacity_in(field_symbols_temp.len() + 1, arena);
|
||||
// FIXME drop tag
|
||||
temp.push(tag_id_symbol);
|
||||
|
||||
temp.extend(field_symbols_temp.iter().map(|r| r.1));
|
||||
|
||||
|
@ -4354,11 +4340,11 @@ fn convert_tag_union<'a>(
|
|||
arguments: field_symbols,
|
||||
};
|
||||
|
||||
(tag, Layout::Union(union_layout))
|
||||
(tag, union_layout)
|
||||
}
|
||||
};
|
||||
|
||||
let mut stmt = Stmt::Let(assigned, tag, layout, hole);
|
||||
let mut stmt = Stmt::Let(assigned, tag, Layout::Union(union_layout), hole);
|
||||
let iter = field_symbols_temp
|
||||
.into_iter()
|
||||
.map(|x| x.2 .0)
|
||||
|
@ -4372,7 +4358,7 @@ fn convert_tag_union<'a>(
|
|||
stmt = Stmt::Let(
|
||||
tag_id_symbol,
|
||||
Expr::Literal(Literal::Int(tag_id as i128)),
|
||||
Layout::Builtin(TAG_SIZE),
|
||||
union_layout.tag_id_layout(),
|
||||
arena.alloc(stmt),
|
||||
);
|
||||
}
|
||||
|
@ -5674,25 +5660,9 @@ fn store_tag_pattern<'a>(
|
|||
) -> StorePattern<'a> {
|
||||
use Pattern::*;
|
||||
|
||||
// rosetree-like structures don't store the tag ID, the others do from the perspective of the IR
|
||||
// The backend can make different choices there (and will, for UnionLayout::NullableUnwrapped)
|
||||
let write_tag = !matches!(union_layout, UnionLayout::NonNullableUnwrapped(_));
|
||||
|
||||
let mut arg_layouts = Vec::with_capacity_in(arguments.len(), env.arena);
|
||||
let mut is_productive = false;
|
||||
|
||||
if write_tag {
|
||||
// add an element for the tag discriminant
|
||||
arg_layouts.push(Layout::Builtin(TAG_SIZE));
|
||||
}
|
||||
|
||||
for (_, layout) in arguments {
|
||||
arg_layouts.push(*layout);
|
||||
}
|
||||
|
||||
for (index, (argument, arg_layout)) in arguments.iter().enumerate().rev() {
|
||||
let index = if write_tag { index + 1 } else { index };
|
||||
|
||||
let mut arg_layout = *arg_layout;
|
||||
|
||||
if let Layout::RecursivePointer = arg_layout {
|
||||
|
@ -7086,8 +7056,7 @@ fn from_can_pattern_help<'a>(
|
|||
ctors.push(Ctor {
|
||||
tag_id: TagId(i as u8),
|
||||
name: tag_name.clone(),
|
||||
// don't include tag discriminant in arity
|
||||
arity: args.len() - 1,
|
||||
arity: args.len(),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -7100,13 +7069,13 @@ fn from_can_pattern_help<'a>(
|
|||
|
||||
debug_assert_eq!(
|
||||
arguments.len(),
|
||||
argument_layouts[1..].len(),
|
||||
argument_layouts.len(),
|
||||
"The {:?} tag got {} arguments, but its layout expects {}!",
|
||||
tag_name,
|
||||
arguments.len(),
|
||||
argument_layouts[1..].len(),
|
||||
argument_layouts.len(),
|
||||
);
|
||||
let it = argument_layouts[1..].iter();
|
||||
let it = argument_layouts.iter();
|
||||
|
||||
for ((_, loc_pat), layout) in arguments.iter().zip(it) {
|
||||
mono_args.push((
|
||||
|
@ -7162,8 +7131,8 @@ fn from_can_pattern_help<'a>(
|
|||
|
||||
let mut mono_args = Vec::with_capacity_in(arguments.len(), env.arena);
|
||||
|
||||
debug_assert_eq!(arguments.len(), argument_layouts[1..].len());
|
||||
let it = argument_layouts[1..].iter();
|
||||
debug_assert_eq!(arguments.len(), argument_layouts.len());
|
||||
let it = argument_layouts.iter();
|
||||
|
||||
for ((_, loc_pat), layout) in arguments.iter().zip(it) {
|
||||
mono_args.push((
|
||||
|
@ -7293,7 +7262,7 @@ fn from_can_pattern_help<'a>(
|
|||
let it = if tag_name == &nullable_name {
|
||||
[].iter()
|
||||
} else {
|
||||
argument_layouts[1..].iter()
|
||||
argument_layouts.iter()
|
||||
};
|
||||
|
||||
for ((_, loc_pat), layout) in arguments.iter().zip(it) {
|
||||
|
@ -7364,7 +7333,7 @@ fn from_can_pattern_help<'a>(
|
|||
[].iter()
|
||||
} else {
|
||||
// FIXME drop tag
|
||||
argument_layouts[1..].iter()
|
||||
argument_layouts.iter()
|
||||
};
|
||||
|
||||
for ((_, loc_pat), layout) in arguments.iter().zip(it) {
|
||||
|
@ -7720,7 +7689,7 @@ where
|
|||
env,
|
||||
lambda_set.set,
|
||||
closure_tag_id_symbol,
|
||||
Layout::Builtin(crate::layout::TAG_SIZE),
|
||||
union_layout.tag_id_layout(),
|
||||
closure_data_symbol,
|
||||
lambda_set.is_represented(),
|
||||
to_lowlevel_call,
|
||||
|
@ -7738,7 +7707,7 @@ where
|
|||
Stmt::Let(
|
||||
closure_tag_id_symbol,
|
||||
expr,
|
||||
Layout::Builtin(Builtin::Int64),
|
||||
union_layout.tag_id_layout(),
|
||||
env.arena.alloc(result),
|
||||
)
|
||||
}
|
||||
|
@ -7879,7 +7848,7 @@ fn match_on_lambda_set<'a>(
|
|||
lambda_set.set,
|
||||
lambda_set.runtime_representation(),
|
||||
closure_tag_id_symbol,
|
||||
Layout::Builtin(crate::layout::TAG_SIZE),
|
||||
union_layout.tag_id_layout(),
|
||||
closure_data_symbol,
|
||||
argument_symbols,
|
||||
argument_layouts,
|
||||
|
@ -7897,7 +7866,7 @@ fn match_on_lambda_set<'a>(
|
|||
Stmt::Let(
|
||||
closure_tag_id_symbol,
|
||||
expr,
|
||||
Layout::Builtin(Builtin::Int64),
|
||||
union_layout.tag_id_layout(),
|
||||
env.arena.alloc(result),
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue