mirror of
https://github.com/roc-lang/roc.git
synced 2024-09-22 08:17:40 +03:00
Revert "Attempt a mono/ approach for List.get"
This reverts commit f0b76f41da
.
This commit is contained in:
parent
f0b76f41da
commit
d97e16de7e
@ -480,7 +480,7 @@ fn from_can<'a>(
|
||||
Expr::FunctionPointer(symbol)
|
||||
}
|
||||
|
||||
Call(boxed, mut loc_args, _) => {
|
||||
Call(boxed, loc_args, _) => {
|
||||
use IntOrFloat::*;
|
||||
|
||||
let (fn_var, loc_expr, ret_var) = *boxed;
|
||||
@ -555,106 +555,6 @@ fn from_can<'a>(
|
||||
};
|
||||
|
||||
match from_can(env, loc_expr.value, procs, None) {
|
||||
Expr::Load(Symbol::LIST_GET) => {
|
||||
// Expand to a bounds check around List.getUnsafe.
|
||||
//
|
||||
// We do this during monomorphization instead of code gen
|
||||
// because it returns an open union around `Err` and
|
||||
// we discard tag names prior to code gen. This means that
|
||||
// (for example) if this `Err` ends up unifying to
|
||||
// [ Foo, OutOfBounds ], then code gen won't know what
|
||||
// integer discriminant OutOfBounds corresponds to anymore,
|
||||
// so it won't know what integer to return.
|
||||
//
|
||||
// At this stage we still have tag names to work with,
|
||||
// so we can return Err OutOfBounds and let the subsequent
|
||||
// stages turn it into the appropriate integer discriminant.
|
||||
|
||||
let arena = env.arena;
|
||||
let list_symbol = env.fresh_symbol();
|
||||
|
||||
// We need owned versions of the arguments' Expr values
|
||||
// for later. We obtain them using .drain() because the
|
||||
// alternative of calling .remove(0) twice would result in
|
||||
// wasted work shifting around the remaining Vec elements.
|
||||
let ((list_expr, list_layout), (index_expr, index_layout)) = {
|
||||
let mut opt_arg0 = None;
|
||||
let mut opt_arg1 = None;
|
||||
|
||||
for (index, (var, loc_expr)) in loc_args.drain(..).enumerate() {
|
||||
let mono_expr = from_can(env, loc_expr.value, procs, None);
|
||||
let layout =
|
||||
Layout::from_var(env.arena, var, env.subs, env.pointer_size)
|
||||
.expect("invalid arg layout when converting List.get");
|
||||
|
||||
match index {
|
||||
0 => opt_arg0 = Some((mono_expr, layout)),
|
||||
1 => opt_arg1 = Some((mono_expr, layout)),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
(opt_arg0.unwrap(), opt_arg1.unwrap())
|
||||
};
|
||||
let ret_layout =
|
||||
Layout::from_var(env.arena, ret_var, env.subs, env.pointer_size)
|
||||
.expect("invalid ret_layout");
|
||||
let cond = Expr::CallByName(
|
||||
Symbol::LIST_IS_EMPTY, // TODO FIXME proper bounds check instead of just isEmpty
|
||||
bumpalo::vec![in arena; (Expr::Load(list_symbol), list_layout.clone())]
|
||||
.into_bump_slice(),
|
||||
);
|
||||
|
||||
let (ok_layout, err_layout) = match ret_layout {
|
||||
// Err comes before Ok because they're sorted alphabetically
|
||||
Layout::Union([[_err_discrim, err_layout], [_ok_discrim, ok_layout]]) => {
|
||||
(ok_layout, err_layout)
|
||||
}
|
||||
_ => {
|
||||
unreachable!("Invalid ret_layout for Result");
|
||||
}
|
||||
};
|
||||
|
||||
let then_branch = {
|
||||
let payload_expr = Expr::CallByName(
|
||||
Symbol::LIST_GET_UNSAFE,
|
||||
bumpalo::vec![in arena;
|
||||
(Expr::Load(list_symbol), list_layout.clone()),
|
||||
(index_expr, index_layout),
|
||||
]
|
||||
.into_bump_slice(),
|
||||
);
|
||||
|
||||
build_ok(arena, ret_layout.clone(), payload_expr, ok_layout.clone())
|
||||
};
|
||||
|
||||
let else_branch = {
|
||||
// OutOfBounds is zero-sized
|
||||
// TODO FIXME this isn't always zero-sized! Could be an int if union is nonempty.
|
||||
let payload_expr = Expr::Struct(&[]);
|
||||
|
||||
build_err(arena, ret_layout.clone(), payload_expr, err_layout.clone())
|
||||
};
|
||||
|
||||
let branch_symbol = env.fresh_symbol();
|
||||
let cond_expr = Expr::Cond {
|
||||
cond_symbol: branch_symbol,
|
||||
branch_symbol,
|
||||
cond_layout: Layout::Builtin(Builtin::Bool),
|
||||
pass: (&[], arena.alloc(then_branch)),
|
||||
fail: (&[], arena.alloc(else_branch)),
|
||||
ret_layout,
|
||||
};
|
||||
|
||||
Expr::Store(
|
||||
bumpalo::vec![in &arena;
|
||||
(list_symbol, list_layout, list_expr),
|
||||
(branch_symbol, Layout::Builtin(Builtin::Bool), cond)
|
||||
]
|
||||
.into_bump_slice(),
|
||||
env.arena.alloc(cond_expr),
|
||||
)
|
||||
}
|
||||
Expr::Load(proc_name) => {
|
||||
// Some functions can potentially mutate in-place.
|
||||
// If we have one of those, switch to the in-place version if appropriate.
|
||||
@ -733,7 +633,8 @@ fn from_can<'a>(
|
||||
};
|
||||
|
||||
expr = Expr::Store(
|
||||
bumpalo::vec![in env.arena; (branch_symbol, Layout::Builtin(Builtin::Bool), cond)].into_bump_slice(),
|
||||
env.arena
|
||||
.alloc(vec![(branch_symbol, Layout::Builtin(Builtin::Bool), cond)]),
|
||||
env.arena.alloc(cond_expr),
|
||||
);
|
||||
}
|
||||
@ -1800,45 +1701,3 @@ pub fn specialize_equality<'a>(
|
||||
arena.alloc([(lhs, layout.clone()), (rhs, layout.clone())]),
|
||||
)
|
||||
}
|
||||
|
||||
// Discriminant is always 0, and Err is alphabetically before Ok
|
||||
const ERR_TAG_ID: u8 = 1;
|
||||
const OK_TAG_ID: u8 = 2;
|
||||
|
||||
fn build_ok<'a>(
|
||||
arena: &'a Bump,
|
||||
result_layout: Layout<'a>,
|
||||
payload_expr: Expr<'a>,
|
||||
payload_layout: Layout<'a>,
|
||||
) -> Expr<'a> {
|
||||
let mut arguments = Vec::with_capacity_in(1, arena);
|
||||
|
||||
arguments.push((payload_expr, payload_layout));
|
||||
|
||||
Expr::Tag {
|
||||
tag_layout: result_layout,
|
||||
tag_name: TagName::Global("Ok".into()),
|
||||
tag_id: OK_TAG_ID,
|
||||
union_size: 2,
|
||||
arguments: arguments.into_bump_slice(),
|
||||
}
|
||||
}
|
||||
|
||||
fn build_err<'a>(
|
||||
arena: &'a Bump,
|
||||
result_layout: Layout<'a>,
|
||||
payload_expr: Expr<'a>,
|
||||
payload_layout: Layout<'a>,
|
||||
) -> Expr<'a> {
|
||||
let mut arguments = Vec::with_capacity_in(1, arena);
|
||||
|
||||
arguments.push((payload_expr, payload_layout));
|
||||
|
||||
Expr::Tag {
|
||||
tag_layout: result_layout,
|
||||
tag_name: TagName::Global("Err".into()),
|
||||
tag_id: ERR_TAG_ID,
|
||||
union_size: 2,
|
||||
arguments: arguments.into_bump_slice(),
|
||||
}
|
||||
}
|
||||
|
@ -420,10 +420,10 @@ fn union_sorted_tags_help<'a>(
|
||||
let mut result = Vec::with_capacity_in(tags_vec.len(), arena);
|
||||
|
||||
for (tag_name, arguments) in tags_vec {
|
||||
// +1 to reserve space for the discriminant
|
||||
// resverse space for the tag discriminant
|
||||
let mut arg_layouts = Vec::with_capacity_in(arguments.len() + 1, arena);
|
||||
|
||||
// add the discriminant
|
||||
// add the tag discriminant
|
||||
arg_layouts.push(Layout::Builtin(Builtin::Int64));
|
||||
|
||||
for var in arguments {
|
||||
@ -434,7 +434,6 @@ fn union_sorted_tags_help<'a>(
|
||||
|
||||
result.push((tag_name, arg_layouts.into_bump_slice()));
|
||||
}
|
||||
|
||||
UnionVariant::Wrapped(result)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user