mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 14:54:47 +00:00
Merge remote-tracking branch 'origin/trunk' into specialize-lowlevel
This commit is contained in:
commit
e81087f913
14 changed files with 1156 additions and 730 deletions
|
@ -3022,351 +3022,63 @@ pub fn with_hole<'a>(
|
|||
variant_var,
|
||||
name: tag_name,
|
||||
arguments: args,
|
||||
ext_var,
|
||||
..
|
||||
} => {
|
||||
let arena = env.arena;
|
||||
|
||||
debug_assert!(!matches!(
|
||||
env.subs.get_without_compacting(variant_var).content,
|
||||
Content::Structure(FlatType::Func(_, _, _))
|
||||
));
|
||||
convert_tag_union(
|
||||
env,
|
||||
variant_var,
|
||||
assigned,
|
||||
hole,
|
||||
tag_name,
|
||||
procs,
|
||||
layout_cache,
|
||||
args,
|
||||
arena,
|
||||
)
|
||||
}
|
||||
|
||||
ZeroArgumentTag {
|
||||
variant_var,
|
||||
name: tag_name,
|
||||
arguments: args,
|
||||
ext_var,
|
||||
..
|
||||
} => {
|
||||
use crate::layout::UnionVariant::*;
|
||||
let arena = env.arena;
|
||||
|
||||
let desc = env.subs.get_without_compacting(variant_var);
|
||||
|
||||
if let Content::Structure(FlatType::Func(arg_vars, _, ret_var)) = desc.content {
|
||||
let mut loc_pattern_args = vec![];
|
||||
let mut loc_expr_args = vec![];
|
||||
|
||||
let proc_symbol = env.unique_symbol();
|
||||
|
||||
for arg_var in arg_vars {
|
||||
let arg_symbol = env.unique_symbol();
|
||||
|
||||
let loc_pattern =
|
||||
Located::at_zero(roc_can::pattern::Pattern::Identifier(arg_symbol));
|
||||
|
||||
let loc_expr = Located::at_zero(roc_can::expr::Expr::Var(arg_symbol));
|
||||
|
||||
loc_pattern_args.push((arg_var, loc_pattern));
|
||||
loc_expr_args.push((arg_var, loc_expr));
|
||||
}
|
||||
|
||||
let loc_body = Located::at_zero(roc_can::expr::Expr::Tag {
|
||||
variant_var: ret_var,
|
||||
name: tag_name,
|
||||
arguments: loc_expr_args,
|
||||
ext_var,
|
||||
});
|
||||
|
||||
let inserted = procs.insert_anonymous(
|
||||
tag_union_to_function(
|
||||
env,
|
||||
proc_symbol,
|
||||
variant_var,
|
||||
loc_pattern_args,
|
||||
loc_body,
|
||||
CapturedSymbols::None,
|
||||
arg_vars,
|
||||
ret_var,
|
||||
tag_name,
|
||||
ext_var,
|
||||
procs,
|
||||
variant_var,
|
||||
layout_cache,
|
||||
);
|
||||
|
||||
match inserted {
|
||||
Ok(_layout) => {
|
||||
todo!("depends on 0-argument tag unions having a lambda union")
|
||||
// return Stmt::Let(
|
||||
// assigned,
|
||||
// todo!(), // call_by_pointer(env, procs, proc_symbol, layout),
|
||||
// layout,
|
||||
// hole,
|
||||
// );
|
||||
}
|
||||
Err(runtime_error) => {
|
||||
return Stmt::RuntimeError(env.arena.alloc(format!(
|
||||
"RuntimeError {} line {} {:?}",
|
||||
file!(),
|
||||
line!(),
|
||||
runtime_error,
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let res_variant = crate::layout::union_sorted_tags(env.arena, variant_var, env.subs);
|
||||
|
||||
let variant = match res_variant {
|
||||
Ok(cached) => cached,
|
||||
Err(LayoutProblem::UnresolvedTypeVar(_)) => {
|
||||
return Stmt::RuntimeError(env.arena.alloc(format!(
|
||||
"UnresolvedTypeVar {} line {}",
|
||||
file!(),
|
||||
line!()
|
||||
)));
|
||||
}
|
||||
Err(LayoutProblem::Erroneous) => {
|
||||
return Stmt::RuntimeError(env.arena.alloc(format!(
|
||||
"Erroneous {} line {}",
|
||||
file!(),
|
||||
line!()
|
||||
)));
|
||||
}
|
||||
};
|
||||
|
||||
match variant {
|
||||
Never => unreachable!(
|
||||
"The `[]` type has no constructors, source var {:?}",
|
||||
variant_var
|
||||
),
|
||||
Unit | UnitWithArguments => let_empty_struct(assigned, hole),
|
||||
BoolUnion { ttrue, .. } => Stmt::Let(
|
||||
assigned,
|
||||
Expr::Literal(Literal::Bool(tag_name == ttrue)),
|
||||
Layout::Builtin(Builtin::Int1),
|
||||
hole,
|
||||
),
|
||||
ByteUnion(tag_names) => {
|
||||
let tag_id = tag_names
|
||||
.iter()
|
||||
.position(|key| key == &tag_name)
|
||||
.expect("tag must be in its own type");
|
||||
|
||||
Stmt::Let(
|
||||
assigned,
|
||||
Expr::Literal(Literal::Byte(tag_id as u8)),
|
||||
Layout::Builtin(Builtin::Int8),
|
||||
hole,
|
||||
)
|
||||
}
|
||||
|
||||
Unwrapped(_, field_layouts) => {
|
||||
let field_symbols_temp = sorted_field_symbols(env, procs, layout_cache, args);
|
||||
|
||||
let mut field_symbols = Vec::with_capacity_in(field_layouts.len(), env.arena);
|
||||
field_symbols.extend(field_symbols_temp.iter().map(|r| r.1));
|
||||
let field_symbols = field_symbols.into_bump_slice();
|
||||
|
||||
// Layout will unpack this unwrapped tack if it only has one (non-zero-sized) field
|
||||
let layout = layout_cache
|
||||
.from_var(env.arena, variant_var, env.subs)
|
||||
.unwrap_or_else(|err| {
|
||||
panic!("TODO turn fn_var into a RuntimeError {:?}", err)
|
||||
});
|
||||
|
||||
// even though this was originally a Tag, we treat it as a Struct from now on
|
||||
let stmt = if let [only_field] = field_symbols {
|
||||
let mut hole = hole.clone();
|
||||
substitute_in_exprs(env.arena, &mut hole, assigned, *only_field);
|
||||
hole
|
||||
} else {
|
||||
Stmt::Let(assigned, Expr::Struct(field_symbols), layout, hole)
|
||||
};
|
||||
|
||||
let iter = field_symbols_temp.into_iter().map(|(_, _, data)| data);
|
||||
assign_to_symbols(env, procs, layout_cache, iter, stmt)
|
||||
}
|
||||
Wrapped(variant) => {
|
||||
let union_size = variant.number_of_tags() as u8;
|
||||
let (tag_id, _) = variant.tag_name_to_id(&tag_name);
|
||||
|
||||
let field_symbols_temp = sorted_field_symbols(env, procs, layout_cache, args);
|
||||
|
||||
let field_symbols;
|
||||
let opt_tag_id_symbol;
|
||||
|
||||
use WrappedVariant::*;
|
||||
let (tag, 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);
|
||||
|
||||
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));
|
||||
|
||||
temp.into_bump_slice()
|
||||
};
|
||||
|
||||
let mut layouts: Vec<&'a [Layout<'a>]> =
|
||||
Vec::with_capacity_in(sorted_tag_layouts.len(), env.arena);
|
||||
|
||||
for (_, arg_layouts) in sorted_tag_layouts.into_iter() {
|
||||
layouts.push(arg_layouts);
|
||||
}
|
||||
|
||||
debug_assert!(layouts.len() > 1);
|
||||
let layout =
|
||||
Layout::Union(UnionLayout::Recursive(layouts.into_bump_slice()));
|
||||
|
||||
let tag = Expr::Tag {
|
||||
tag_layout: layout,
|
||||
tag_name,
|
||||
tag_id: tag_id as u8,
|
||||
union_size,
|
||||
arguments: field_symbols,
|
||||
};
|
||||
|
||||
(tag, layout)
|
||||
}
|
||||
NonNullableUnwrapped {
|
||||
fields,
|
||||
tag_name: wrapped_tag_name,
|
||||
} => {
|
||||
debug_assert_eq!(tag_name, wrapped_tag_name);
|
||||
|
||||
opt_tag_id_symbol = None;
|
||||
|
||||
field_symbols = {
|
||||
let mut temp =
|
||||
Vec::with_capacity_in(field_symbols_temp.len(), arena);
|
||||
|
||||
temp.extend(field_symbols_temp.iter().map(|r| r.1));
|
||||
|
||||
temp.into_bump_slice()
|
||||
};
|
||||
|
||||
let layout = Layout::Union(UnionLayout::NonNullableUnwrapped(fields));
|
||||
|
||||
let tag = Expr::Tag {
|
||||
tag_layout: layout,
|
||||
tag_name,
|
||||
tag_id: tag_id as u8,
|
||||
union_size,
|
||||
arguments: field_symbols,
|
||||
};
|
||||
|
||||
(tag, layout)
|
||||
}
|
||||
NonRecursive { sorted_tag_layouts } => {
|
||||
let tag_id_symbol = env.unique_symbol();
|
||||
opt_tag_id_symbol = Some(tag_id_symbol);
|
||||
|
||||
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));
|
||||
|
||||
temp.into_bump_slice()
|
||||
};
|
||||
|
||||
let mut layouts: Vec<&'a [Layout<'a>]> =
|
||||
Vec::with_capacity_in(sorted_tag_layouts.len(), env.arena);
|
||||
|
||||
for (_, arg_layouts) in sorted_tag_layouts.into_iter() {
|
||||
layouts.push(arg_layouts);
|
||||
}
|
||||
|
||||
let layout =
|
||||
Layout::Union(UnionLayout::NonRecursive(layouts.into_bump_slice()));
|
||||
|
||||
let tag = Expr::Tag {
|
||||
tag_layout: layout,
|
||||
tag_name,
|
||||
tag_id: tag_id as u8,
|
||||
union_size,
|
||||
arguments: field_symbols,
|
||||
};
|
||||
|
||||
(tag, layout)
|
||||
}
|
||||
NullableWrapped {
|
||||
nullable_id,
|
||||
nullable_name: _,
|
||||
sorted_tag_layouts,
|
||||
} => {
|
||||
let tag_id_symbol = env.unique_symbol();
|
||||
opt_tag_id_symbol = Some(tag_id_symbol);
|
||||
|
||||
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));
|
||||
|
||||
temp.into_bump_slice()
|
||||
};
|
||||
|
||||
let mut layouts: Vec<&'a [Layout<'a>]> =
|
||||
Vec::with_capacity_in(sorted_tag_layouts.len(), env.arena);
|
||||
|
||||
for (_, arg_layouts) in sorted_tag_layouts.into_iter() {
|
||||
layouts.push(arg_layouts);
|
||||
}
|
||||
|
||||
let layout = Layout::Union(UnionLayout::NullableWrapped {
|
||||
nullable_id,
|
||||
other_tags: layouts.into_bump_slice(),
|
||||
});
|
||||
|
||||
let tag = Expr::Tag {
|
||||
tag_layout: layout,
|
||||
tag_name,
|
||||
tag_id: tag_id as u8,
|
||||
union_size,
|
||||
arguments: field_symbols,
|
||||
};
|
||||
|
||||
(tag, layout)
|
||||
}
|
||||
NullableUnwrapped {
|
||||
nullable_id,
|
||||
nullable_name: _,
|
||||
other_name: _,
|
||||
other_fields,
|
||||
} => {
|
||||
// FIXME drop tag
|
||||
let tag_id_symbol = env.unique_symbol();
|
||||
opt_tag_id_symbol = Some(tag_id_symbol);
|
||||
|
||||
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));
|
||||
|
||||
temp.into_bump_slice()
|
||||
};
|
||||
|
||||
let layout = Layout::Union(UnionLayout::NullableUnwrapped {
|
||||
nullable_id,
|
||||
other_fields,
|
||||
});
|
||||
|
||||
let tag = Expr::Tag {
|
||||
tag_layout: layout,
|
||||
tag_name,
|
||||
tag_id: tag_id as u8,
|
||||
union_size,
|
||||
arguments: field_symbols,
|
||||
};
|
||||
|
||||
(tag, layout)
|
||||
}
|
||||
};
|
||||
|
||||
let mut stmt = Stmt::Let(assigned, tag, layout, hole);
|
||||
let iter = field_symbols_temp
|
||||
.into_iter()
|
||||
.map(|x| x.2 .0)
|
||||
.rev()
|
||||
.zip(field_symbols.iter().rev());
|
||||
|
||||
stmt = assign_to_symbols(env, procs, layout_cache, iter, stmt);
|
||||
|
||||
if let Some(tag_id_symbol) = opt_tag_id_symbol {
|
||||
// define the tag id
|
||||
stmt = Stmt::Let(
|
||||
tag_id_symbol,
|
||||
Expr::Literal(Literal::Int(tag_id as i128)),
|
||||
Layout::Builtin(TAG_SIZE),
|
||||
arena.alloc(stmt),
|
||||
);
|
||||
}
|
||||
|
||||
stmt
|
||||
}
|
||||
)
|
||||
} else {
|
||||
convert_tag_union(
|
||||
env,
|
||||
variant_var,
|
||||
assigned,
|
||||
hole,
|
||||
tag_name,
|
||||
procs,
|
||||
layout_cache,
|
||||
args,
|
||||
arena,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4468,6 +4180,347 @@ fn construct_closure_data<'a>(
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn convert_tag_union<'a>(
|
||||
env: &mut Env<'a, '_>,
|
||||
variant_var: Variable,
|
||||
assigned: Symbol,
|
||||
hole: &'a Stmt<'a>,
|
||||
tag_name: TagName,
|
||||
procs: &mut Procs<'a>,
|
||||
layout_cache: &mut LayoutCache<'a>,
|
||||
args: std::vec::Vec<(Variable, Located<roc_can::expr::Expr>)>,
|
||||
arena: &'a Bump,
|
||||
) -> Stmt<'a> {
|
||||
use crate::layout::UnionVariant::*;
|
||||
let res_variant = crate::layout::union_sorted_tags(env.arena, variant_var, env.subs);
|
||||
let variant = match res_variant {
|
||||
Ok(cached) => cached,
|
||||
Err(LayoutProblem::UnresolvedTypeVar(_)) => {
|
||||
return Stmt::RuntimeError(env.arena.alloc(format!(
|
||||
"UnresolvedTypeVar {} line {}",
|
||||
file!(),
|
||||
line!()
|
||||
)))
|
||||
}
|
||||
Err(LayoutProblem::Erroneous) => {
|
||||
return Stmt::RuntimeError(env.arena.alloc(format!(
|
||||
"Erroneous {} line {}",
|
||||
file!(),
|
||||
line!()
|
||||
)));
|
||||
}
|
||||
};
|
||||
match variant {
|
||||
Never => unreachable!(
|
||||
"The `[]` type has no constructors, source var {:?}",
|
||||
variant_var
|
||||
),
|
||||
Unit | UnitWithArguments => {
|
||||
Stmt::Let(assigned, Expr::Struct(&[]), Layout::Struct(&[]), hole)
|
||||
}
|
||||
BoolUnion { ttrue, .. } => Stmt::Let(
|
||||
assigned,
|
||||
Expr::Literal(Literal::Bool(tag_name == ttrue)),
|
||||
Layout::Builtin(Builtin::Int1),
|
||||
hole,
|
||||
),
|
||||
ByteUnion(tag_names) => {
|
||||
let tag_id = tag_names
|
||||
.iter()
|
||||
.position(|key| key == &tag_name)
|
||||
.expect("tag must be in its own type");
|
||||
|
||||
Stmt::Let(
|
||||
assigned,
|
||||
Expr::Literal(Literal::Byte(tag_id as u8)),
|
||||
Layout::Builtin(Builtin::Int8),
|
||||
hole,
|
||||
)
|
||||
}
|
||||
|
||||
Unwrapped(field_layouts) => {
|
||||
let field_symbols_temp = sorted_field_symbols(env, procs, layout_cache, args);
|
||||
|
||||
let mut field_symbols = Vec::with_capacity_in(field_layouts.len(), env.arena);
|
||||
field_symbols.extend(field_symbols_temp.iter().map(|r| r.1));
|
||||
let field_symbols = field_symbols.into_bump_slice();
|
||||
|
||||
// Layout will unpack this unwrapped tack if it only has one (non-zero-sized) field
|
||||
let layout = layout_cache
|
||||
.from_var(env.arena, variant_var, env.subs)
|
||||
.unwrap_or_else(|err| panic!("TODO turn fn_var into a RuntimeError {:?}", err));
|
||||
|
||||
// even though this was originally a Tag, we treat it as a Struct from now on
|
||||
let stmt = Stmt::Let(assigned, Expr::Struct(field_symbols), layout, hole);
|
||||
|
||||
let iter = field_symbols_temp.into_iter().map(|(_, _, data)| data);
|
||||
assign_to_symbols(env, procs, layout_cache, iter, stmt)
|
||||
}
|
||||
Wrapped(variant) => {
|
||||
let union_size = variant.number_of_tags() as u8;
|
||||
let (tag_id, _) = variant.tag_name_to_id(&tag_name);
|
||||
|
||||
let field_symbols_temp = sorted_field_symbols(env, procs, layout_cache, args);
|
||||
|
||||
let field_symbols;
|
||||
let opt_tag_id_symbol;
|
||||
|
||||
use WrappedVariant::*;
|
||||
let (tag, 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);
|
||||
|
||||
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));
|
||||
|
||||
temp.into_bump_slice()
|
||||
};
|
||||
|
||||
let mut layouts: Vec<&'a [Layout<'a>]> =
|
||||
Vec::with_capacity_in(sorted_tag_layouts.len(), env.arena);
|
||||
|
||||
for (_, arg_layouts) in sorted_tag_layouts.into_iter() {
|
||||
layouts.push(arg_layouts);
|
||||
}
|
||||
|
||||
debug_assert!(layouts.len() > 1);
|
||||
let layout = Layout::Union(UnionLayout::Recursive(layouts.into_bump_slice()));
|
||||
|
||||
let tag = Expr::Tag {
|
||||
tag_layout: layout,
|
||||
tag_name,
|
||||
tag_id: tag_id as u8,
|
||||
union_size,
|
||||
arguments: field_symbols,
|
||||
};
|
||||
|
||||
(tag, layout)
|
||||
}
|
||||
NonNullableUnwrapped {
|
||||
fields,
|
||||
tag_name: wrapped_tag_name,
|
||||
} => {
|
||||
debug_assert_eq!(tag_name, wrapped_tag_name);
|
||||
|
||||
opt_tag_id_symbol = None;
|
||||
|
||||
field_symbols = {
|
||||
let mut temp = Vec::with_capacity_in(field_symbols_temp.len(), arena);
|
||||
|
||||
temp.extend(field_symbols_temp.iter().map(|r| r.1));
|
||||
|
||||
temp.into_bump_slice()
|
||||
};
|
||||
|
||||
let layout = Layout::Union(UnionLayout::NonNullableUnwrapped(fields));
|
||||
|
||||
let tag = Expr::Tag {
|
||||
tag_layout: layout,
|
||||
tag_name,
|
||||
tag_id: tag_id as u8,
|
||||
union_size,
|
||||
arguments: field_symbols,
|
||||
};
|
||||
|
||||
(tag, layout)
|
||||
}
|
||||
NonRecursive { sorted_tag_layouts } => {
|
||||
let tag_id_symbol = env.unique_symbol();
|
||||
opt_tag_id_symbol = Some(tag_id_symbol);
|
||||
|
||||
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));
|
||||
|
||||
temp.into_bump_slice()
|
||||
};
|
||||
|
||||
let mut layouts: Vec<&'a [Layout<'a>]> =
|
||||
Vec::with_capacity_in(sorted_tag_layouts.len(), env.arena);
|
||||
|
||||
for (_, arg_layouts) in sorted_tag_layouts.into_iter() {
|
||||
layouts.push(arg_layouts);
|
||||
}
|
||||
|
||||
let layout =
|
||||
Layout::Union(UnionLayout::NonRecursive(layouts.into_bump_slice()));
|
||||
|
||||
let tag = Expr::Tag {
|
||||
tag_layout: layout,
|
||||
tag_name,
|
||||
tag_id: tag_id as u8,
|
||||
union_size,
|
||||
arguments: field_symbols,
|
||||
};
|
||||
|
||||
(tag, layout)
|
||||
}
|
||||
NullableWrapped {
|
||||
nullable_id,
|
||||
nullable_name: _,
|
||||
sorted_tag_layouts,
|
||||
} => {
|
||||
let tag_id_symbol = env.unique_symbol();
|
||||
opt_tag_id_symbol = Some(tag_id_symbol);
|
||||
|
||||
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));
|
||||
|
||||
temp.into_bump_slice()
|
||||
};
|
||||
|
||||
let mut layouts: Vec<&'a [Layout<'a>]> =
|
||||
Vec::with_capacity_in(sorted_tag_layouts.len(), env.arena);
|
||||
|
||||
for (_, arg_layouts) in sorted_tag_layouts.into_iter() {
|
||||
layouts.push(arg_layouts);
|
||||
}
|
||||
|
||||
let layout = Layout::Union(UnionLayout::NullableWrapped {
|
||||
nullable_id,
|
||||
other_tags: layouts.into_bump_slice(),
|
||||
});
|
||||
|
||||
let tag = Expr::Tag {
|
||||
tag_layout: layout,
|
||||
tag_name,
|
||||
tag_id: tag_id as u8,
|
||||
union_size,
|
||||
arguments: field_symbols,
|
||||
};
|
||||
|
||||
(tag, layout)
|
||||
}
|
||||
NullableUnwrapped {
|
||||
nullable_id,
|
||||
nullable_name: _,
|
||||
other_name: _,
|
||||
other_fields,
|
||||
} => {
|
||||
// FIXME drop tag
|
||||
let tag_id_symbol = env.unique_symbol();
|
||||
opt_tag_id_symbol = Some(tag_id_symbol);
|
||||
|
||||
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));
|
||||
|
||||
temp.into_bump_slice()
|
||||
};
|
||||
|
||||
let layout = Layout::Union(UnionLayout::NullableUnwrapped {
|
||||
nullable_id,
|
||||
other_fields,
|
||||
});
|
||||
|
||||
let tag = Expr::Tag {
|
||||
tag_layout: layout,
|
||||
tag_name,
|
||||
tag_id: tag_id as u8,
|
||||
union_size,
|
||||
arguments: field_symbols,
|
||||
};
|
||||
|
||||
(tag, layout)
|
||||
}
|
||||
};
|
||||
|
||||
let mut stmt = Stmt::Let(assigned, tag, layout, hole);
|
||||
let iter = field_symbols_temp
|
||||
.into_iter()
|
||||
.map(|x| x.2 .0)
|
||||
.rev()
|
||||
.zip(field_symbols.iter().rev());
|
||||
|
||||
stmt = assign_to_symbols(env, procs, layout_cache, iter, stmt);
|
||||
|
||||
if let Some(tag_id_symbol) = opt_tag_id_symbol {
|
||||
// define the tag id
|
||||
stmt = Stmt::Let(
|
||||
tag_id_symbol,
|
||||
Expr::Literal(Literal::Int(tag_id as i128)),
|
||||
Layout::Builtin(TAG_SIZE),
|
||||
arena.alloc(stmt),
|
||||
);
|
||||
}
|
||||
|
||||
stmt
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn tag_union_to_function<'a>(
|
||||
env: &mut Env<'a, '_>,
|
||||
arg_vars: std::vec::Vec<Variable>,
|
||||
ret_var: Variable,
|
||||
tag_name: TagName,
|
||||
ext_var: Variable,
|
||||
procs: &mut Procs<'a>,
|
||||
variant_var: Variable,
|
||||
layout_cache: &mut LayoutCache<'a>,
|
||||
assigned: Symbol,
|
||||
hole: &'a Stmt<'a>,
|
||||
) -> Stmt<'a> {
|
||||
let mut loc_pattern_args = vec![];
|
||||
let mut loc_expr_args = vec![];
|
||||
let proc_symbol = env.unique_symbol();
|
||||
for arg_var in arg_vars {
|
||||
let arg_symbol = env.unique_symbol();
|
||||
|
||||
let loc_pattern = Located::at_zero(roc_can::pattern::Pattern::Identifier(arg_symbol));
|
||||
|
||||
let loc_expr = Located::at_zero(roc_can::expr::Expr::Var(arg_symbol));
|
||||
|
||||
loc_pattern_args.push((arg_var, loc_pattern));
|
||||
loc_expr_args.push((arg_var, loc_expr));
|
||||
}
|
||||
let loc_body = Located::at_zero(roc_can::expr::Expr::Tag {
|
||||
variant_var: ret_var,
|
||||
name: tag_name,
|
||||
arguments: loc_expr_args,
|
||||
ext_var,
|
||||
});
|
||||
let inserted = procs.insert_anonymous(
|
||||
env,
|
||||
proc_symbol,
|
||||
variant_var,
|
||||
loc_pattern_args,
|
||||
loc_body,
|
||||
CapturedSymbols::None,
|
||||
ret_var,
|
||||
layout_cache,
|
||||
);
|
||||
match inserted {
|
||||
Ok(layout) => Stmt::Let(
|
||||
assigned,
|
||||
call_by_pointer(env, procs, proc_symbol, layout),
|
||||
layout,
|
||||
hole,
|
||||
),
|
||||
Err(runtime_error) => Stmt::RuntimeError(env.arena.alloc(format!(
|
||||
"RuntimeError {} line {} {:?}",
|
||||
file!(),
|
||||
line!(),
|
||||
runtime_error,
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn sorted_field_symbols<'a>(
|
||||
env: &mut Env<'a, '_>,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue