repl: Separate app from env

This commit is contained in:
Brian Carroll 2022-02-04 09:56:32 +00:00
parent 8c3d272a78
commit fdf8363b7e
2 changed files with 117 additions and 97 deletions

View file

@ -292,7 +292,7 @@ fn gen_and_eval_llvm<'a>(
let res_answer = jit_to_ast( let res_answer = jit_to_ast(
&arena, &arena,
&app, app,
main_fn_name, main_fn_name,
main_fn_layout, main_fn_layout,
content, content,

View file

@ -18,10 +18,9 @@ use roc_types::subs::{Content, FlatType, GetSubsSlice, RecordFields, Subs, Union
use crate::ReplApp; use crate::ReplApp;
struct Env<'a, 'env, A> { struct Env<'a, 'env> {
arena: &'a Bump, arena: &'a Bump,
subs: &'env Subs, subs: &'env Subs,
app: &'a A,
target_info: TargetInfo, target_info: TargetInfo,
interns: &'env Interns, interns: &'env Interns,
home: ModuleId, home: ModuleId,
@ -42,7 +41,7 @@ pub enum ToAstProblem {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn jit_to_ast<'a, A: ReplApp>( pub fn jit_to_ast<'a, A: ReplApp>(
arena: &'a Bump, arena: &'a Bump,
app: &'a A, app: A,
main_fn_name: &str, main_fn_name: &str,
layout: ProcLayout<'a>, layout: ProcLayout<'a>,
content: &'a Content, content: &'a Content,
@ -54,7 +53,6 @@ pub fn jit_to_ast<'a, A: ReplApp>(
let env = Env { let env = Env {
arena, arena,
subs, subs,
app,
target_info, target_info,
interns, interns,
home, home,
@ -66,7 +64,7 @@ pub fn jit_to_ast<'a, A: ReplApp>(
result, result,
} => { } => {
// this is a thunk // this is a thunk
jit_to_ast_help(&env, main_fn_name, &result, content) jit_to_ast_help(&env, app, main_fn_name, &result, content)
} }
_ => Err(ToAstProblem::FunctionLayout), _ => Err(ToAstProblem::FunctionLayout),
} }
@ -86,8 +84,8 @@ enum NewtypeKind<'a> {
/// ///
/// The returned list of newtype containers is ordered by increasing depth. As an example, /// The returned list of newtype containers is ordered by increasing depth. As an example,
/// `A ({b : C 123})` will have the unrolled list `[Tag(A), RecordField(b), Tag(C)]`. /// `A ({b : C 123})` will have the unrolled list `[Tag(A), RecordField(b), Tag(C)]`.
fn unroll_newtypes<'a, A: ReplApp>( fn unroll_newtypes<'a>(
env: &Env<'a, 'a, A>, env: &Env<'a, 'a>,
mut content: &'a Content, mut content: &'a Content,
) -> (Vec<'a, NewtypeKind<'a>>, &'a Content) { ) -> (Vec<'a, NewtypeKind<'a>>, &'a Content) {
let mut newtype_containers = Vec::with_capacity_in(1, env.arena); let mut newtype_containers = Vec::with_capacity_in(1, env.arena);
@ -120,8 +118,8 @@ fn unroll_newtypes<'a, A: ReplApp>(
} }
} }
fn apply_newtypes<'a, A: ReplApp>( fn apply_newtypes<'a>(
env: &Env<'a, '_, A>, env: &Env<'a, '_>,
newtype_containers: Vec<'a, NewtypeKind<'a>>, newtype_containers: Vec<'a, NewtypeKind<'a>>,
mut expr: Expr<'a>, mut expr: Expr<'a>,
) -> Expr<'a> { ) -> Expr<'a> {
@ -148,25 +146,22 @@ fn apply_newtypes<'a, A: ReplApp>(
expr expr
} }
fn unroll_aliases<'a, A: ReplApp>(env: &Env<'a, 'a, A>, mut content: &'a Content) -> &'a Content { fn unroll_aliases<'a>(env: &Env<'a, 'a>, mut content: &'a Content) -> &'a Content {
while let Content::Alias(_, _, real) = content { while let Content::Alias(_, _, real) = content {
content = env.subs.get_content_without_compacting(*real); content = env.subs.get_content_without_compacting(*real);
} }
content content
} }
fn unroll_recursion_var<'a, A: ReplApp>( fn unroll_recursion_var<'a>(env: &Env<'a, 'a>, mut content: &'a Content) -> &'a Content {
env: &Env<'a, 'a, A>,
mut content: &'a Content,
) -> &'a Content {
while let Content::RecursionVar { structure, .. } = content { while let Content::RecursionVar { structure, .. } = content {
content = env.subs.get_content_without_compacting(*structure); content = env.subs.get_content_without_compacting(*structure);
} }
content content
} }
fn get_tags_vars_and_variant<'a, A: ReplApp>( fn get_tags_vars_and_variant<'a>(
env: &Env<'a, '_, A>, env: &Env<'a, '_>,
tags: &UnionTags, tags: &UnionTags,
opt_rec_var: Option<Variable>, opt_rec_var: Option<Variable>,
) -> (MutMap<TagName, std::vec::Vec<Variable>>, UnionVariant<'a>) { ) -> (MutMap<TagName, std::vec::Vec<Variable>>, UnionVariant<'a>) {
@ -184,7 +179,8 @@ fn get_tags_vars_and_variant<'a, A: ReplApp>(
} }
fn expr_of_tag<'a, A: ReplApp>( fn expr_of_tag<'a, A: ReplApp>(
env: &Env<'a, 'a, A>, env: &Env<'a, 'a>,
app: &A,
data_addr: usize, data_addr: usize,
tag_name: &TagName, tag_name: &TagName,
arg_layouts: &'a [Layout<'a>], arg_layouts: &'a [Layout<'a>],
@ -198,7 +194,7 @@ fn expr_of_tag<'a, A: ReplApp>(
// NOTE assumes the data bytes are the first bytes // NOTE assumes the data bytes are the first bytes
let it = arg_vars.iter().copied().zip(arg_layouts.iter()); let it = arg_vars.iter().copied().zip(arg_layouts.iter());
let output = sequence_of_expr(env, data_addr, it, when_recursive); let output = sequence_of_expr(env, app, data_addr, it, when_recursive);
let output = output.into_bump_slice(); let output = output.into_bump_slice();
Expr::Apply(loc_tag_expr, output, CalledVia::Space) Expr::Apply(loc_tag_expr, output, CalledVia::Space)
@ -207,7 +203,8 @@ fn expr_of_tag<'a, A: ReplApp>(
/// Gets the tag ID of a union variant, assuming that the tag ID is stored alongside (after) the /// Gets the tag ID of a union variant, assuming that the tag ID is stored alongside (after) the
/// tag data. The caller is expected to check that the tag ID is indeed stored this way. /// tag data. The caller is expected to check that the tag ID is indeed stored this way.
fn tag_id_from_data<'a, A: ReplApp>( fn tag_id_from_data<'a, A: ReplApp>(
env: &Env<'a, 'a, A>, env: &Env<'a, 'a>,
app: &A,
union_layout: UnionLayout, union_layout: UnionLayout,
data_addr: usize, data_addr: usize,
) -> i64 { ) -> i64 {
@ -217,13 +214,13 @@ fn tag_id_from_data<'a, A: ReplApp>(
let tag_id_addr = data_addr + offset as usize; let tag_id_addr = data_addr + offset as usize;
match union_layout.tag_id_builtin() { match union_layout.tag_id_builtin() {
Builtin::Bool => env.app.deref_bool(tag_id_addr) as i64, Builtin::Bool => app.deref_bool(tag_id_addr) as i64,
Builtin::Int(IntWidth::U8) => env.app.deref_u8(tag_id_addr) as i64, Builtin::Int(IntWidth::U8) => app.deref_u8(tag_id_addr) as i64,
Builtin::Int(IntWidth::U16) => env.app.deref_u16(tag_id_addr) as i64, Builtin::Int(IntWidth::U16) => app.deref_u16(tag_id_addr) as i64,
Builtin::Int(IntWidth::U64) => { Builtin::Int(IntWidth::U64) => {
// used by non-recursive unions at the // used by non-recursive unions at the
// moment, remove if that is no longer the case // moment, remove if that is no longer the case
env.app.deref_i64(tag_id_addr) app.deref_i64(tag_id_addr)
} }
_ => unreachable!("invalid tag id layout"), _ => unreachable!("invalid tag id layout"),
} }
@ -234,12 +231,13 @@ fn tag_id_from_data<'a, A: ReplApp>(
/// - the tag ID /// - the tag ID
/// - the address of the data of the union variant, unmasked if the pointer held the tag ID /// - the address of the data of the union variant, unmasked if the pointer held the tag ID
fn tag_id_from_recursive_ptr<'a, A: ReplApp>( fn tag_id_from_recursive_ptr<'a, A: ReplApp>(
env: &Env<'a, 'a, A>, env: &Env<'a, 'a>,
app: &A,
union_layout: UnionLayout, union_layout: UnionLayout,
rec_addr: usize, rec_addr: usize,
) -> (i64, usize) { ) -> (i64, usize) {
let tag_in_ptr = union_layout.stores_tag_id_in_pointer(env.target_info); let tag_in_ptr = union_layout.stores_tag_id_in_pointer(env.target_info);
let addr_with_id = env.app.deref_usize(rec_addr); let addr_with_id = app.deref_usize(rec_addr);
if tag_in_ptr { if tag_in_ptr {
let (_, tag_id_mask) = UnionLayout::tag_id_pointer_bits_and_mask(env.target_info); let (_, tag_id_mask) = UnionLayout::tag_id_pointer_bits_and_mask(env.target_info);
@ -247,7 +245,7 @@ fn tag_id_from_recursive_ptr<'a, A: ReplApp>(
let data_addr = addr_with_id & !tag_id_mask; let data_addr = addr_with_id & !tag_id_mask;
(tag_id as i64, data_addr) (tag_id as i64, data_addr)
} else { } else {
let tag_id = tag_id_from_data(env, union_layout, addr_with_id); let tag_id = tag_id_from_data(env, app, union_layout, addr_with_id);
(tag_id, addr_with_id) (tag_id, addr_with_id)
} }
} }
@ -258,7 +256,8 @@ const OPAQUE_FUNCTION: Expr = Expr::Var {
}; };
fn jit_to_ast_help<'a, A: ReplApp>( fn jit_to_ast_help<'a, A: ReplApp>(
env: &Env<'a, 'a, A>, env: &Env<'a, 'a>,
mut app: A,
main_fn_name: &str, main_fn_name: &str,
layout: &Layout<'a>, layout: &Layout<'a>,
content: &'a Content, content: &'a Content,
@ -266,15 +265,15 @@ fn jit_to_ast_help<'a, A: ReplApp>(
let (newtype_containers, content) = unroll_newtypes(env, content); let (newtype_containers, content) = unroll_newtypes(env, content);
let content = unroll_aliases(env, content); let content = unroll_aliases(env, content);
let result = match layout { let result = match layout {
Layout::Builtin(Builtin::Bool) => Ok(env Layout::Builtin(Builtin::Bool) => Ok(app.call_function(main_fn_name, |num: bool| {
.app bool_to_ast(env, &app, num, content)
.call_function(main_fn_name, |num: bool| bool_to_ast(env, num, content))), })),
Layout::Builtin(Builtin::Int(int_width)) => { Layout::Builtin(Builtin::Int(int_width)) => {
use IntWidth::*; use IntWidth::*;
macro_rules! helper { macro_rules! helper {
($ty:ty) => { ($ty:ty) => {
env.app.call_function(main_fn_name, |num: $ty| { app.call_function(main_fn_name, |num: $ty| {
num_to_ast(env, number_literal_to_ast(env.arena, num), content) num_to_ast(env, number_literal_to_ast(env.arena, num), content)
}) })
}; };
@ -283,8 +282,7 @@ fn jit_to_ast_help<'a, A: ReplApp>(
let result = match int_width { let result = match int_width {
U8 | I8 => { U8 | I8 => {
// NOTE: `helper!` does not handle 8-bit numbers yet // NOTE: `helper!` does not handle 8-bit numbers yet
env.app app.call_function(main_fn_name, |num: u8| byte_to_ast(env, &app, num, content))
.call_function(main_fn_name, |num: u8| byte_to_ast(env, num, content))
} }
U16 => helper!(u16), U16 => helper!(u16),
U32 => helper!(u32), U32 => helper!(u32),
@ -303,7 +301,7 @@ fn jit_to_ast_help<'a, A: ReplApp>(
macro_rules! helper { macro_rules! helper {
($ty:ty) => { ($ty:ty) => {
env.app.call_function(main_fn_name, |num: $ty| { app.call_function(main_fn_name, |num: $ty| {
num_to_ast(env, number_literal_to_ast(env.arena, num), content) num_to_ast(env, number_literal_to_ast(env.arena, num), content)
}) })
}; };
@ -317,15 +315,13 @@ fn jit_to_ast_help<'a, A: ReplApp>(
Ok(result) Ok(result)
} }
Layout::Builtin(Builtin::Str) => { Layout::Builtin(Builtin::Str) => Ok(app
Ok(env.app.call_function(main_fn_name, |string: &'static str| { .call_function(main_fn_name, |string: &'static str| {
str_to_ast(env.arena, env.arena.alloc(string)) str_to_ast(env.arena, env.arena.alloc(string))
})) })),
} Layout::Builtin(Builtin::List(elem_layout)) => Ok(app
Layout::Builtin(Builtin::List(elem_layout)) => Ok(env
.app
.call_function(main_fn_name, |(addr, len): (usize, usize)| { .call_function(main_fn_name, |(addr, len): (usize, usize)| {
list_to_ast(env, addr, len, elem_layout, content) list_to_ast(env, &app, addr, len, elem_layout, content)
})), })),
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)
@ -333,10 +329,11 @@ fn jit_to_ast_help<'a, A: ReplApp>(
Layout::Struct(field_layouts) => { Layout::Struct(field_layouts) => {
let struct_addr_to_ast = |addr: usize| match content { let struct_addr_to_ast = |addr: usize| match content {
Content::Structure(FlatType::Record(fields, _)) => { Content::Structure(FlatType::Record(fields, _)) => {
Ok(struct_to_ast(env, addr, field_layouts, *fields)) Ok(struct_to_ast(env, &app, addr, field_layouts, *fields))
} }
Content::Structure(FlatType::EmptyRecord) => Ok(struct_to_ast( Content::Structure(FlatType::EmptyRecord) => Ok(struct_to_ast(
env, env,
&app,
addr, addr,
field_layouts, field_layouts,
RecordFields::empty(), RecordFields::empty(),
@ -348,6 +345,7 @@ fn jit_to_ast_help<'a, A: ReplApp>(
Ok(single_tag_union_to_ast( Ok(single_tag_union_to_ast(
env, env,
&app,
addr, addr,
field_layouts, field_layouts,
tag_name, tag_name,
@ -359,6 +357,7 @@ fn jit_to_ast_help<'a, A: ReplApp>(
Ok(single_tag_union_to_ast( Ok(single_tag_union_to_ast(
env, env,
&app,
addr, addr,
field_layouts, field_layouts,
tag_name, tag_name,
@ -382,7 +381,7 @@ fn jit_to_ast_help<'a, A: ReplApp>(
let result_stack_size = layout.stack_size(env.target_info); let result_stack_size = layout.stack_size(env.target_info);
env.app.call_function_dynamic_size( app.call_function_dynamic_size(
main_fn_name, main_fn_name,
result_stack_size as usize, result_stack_size as usize,
struct_addr_to_ast, struct_addr_to_ast,
@ -390,22 +389,29 @@ fn jit_to_ast_help<'a, A: ReplApp>(
} }
Layout::Union(UnionLayout::NonRecursive(_)) => { Layout::Union(UnionLayout::NonRecursive(_)) => {
let size = layout.stack_size(env.target_info); let size = layout.stack_size(env.target_info);
Ok(env Ok(
.app app.call_function_dynamic_size(main_fn_name, size as usize, |addr: usize| {
.call_function_dynamic_size(main_fn_name, size as usize, |addr: usize| { addr_to_ast(env, &app, addr, layout, WhenRecursive::Unreachable, content)
addr_to_ast(env, addr, layout, WhenRecursive::Unreachable, content) }),
})) )
} }
Layout::Union(UnionLayout::Recursive(_)) Layout::Union(UnionLayout::Recursive(_))
| Layout::Union(UnionLayout::NonNullableUnwrapped(_)) | Layout::Union(UnionLayout::NonNullableUnwrapped(_))
| Layout::Union(UnionLayout::NullableUnwrapped { .. }) | Layout::Union(UnionLayout::NullableUnwrapped { .. })
| Layout::Union(UnionLayout::NullableWrapped { .. }) => { | Layout::Union(UnionLayout::NullableWrapped { .. }) => {
let size = layout.stack_size(env.target_info); let size = layout.stack_size(env.target_info);
Ok(env Ok(
.app app.call_function_dynamic_size(main_fn_name, size as usize, |addr: usize| {
.call_function_dynamic_size(main_fn_name, size as usize, |addr: usize| { addr_to_ast(
addr_to_ast(env, addr, layout, WhenRecursive::Loop(*layout), content) env,
})) &app,
addr,
layout,
WhenRecursive::Loop(*layout),
content,
)
}),
)
} }
Layout::RecursivePointer => { Layout::RecursivePointer => {
unreachable!("RecursivePointers can only be inside structures") unreachable!("RecursivePointers can only be inside structures")
@ -415,7 +421,7 @@ fn jit_to_ast_help<'a, A: ReplApp>(
result.map(|e| apply_newtypes(env, newtype_containers, e)) result.map(|e| apply_newtypes(env, newtype_containers, e))
} }
fn tag_name_to_expr<'a, A: ReplApp>(env: &Env<'a, '_, A>, tag_name: &TagName) -> Expr<'a> { fn tag_name_to_expr<'a>(env: &Env<'a, '_>, tag_name: &TagName) -> Expr<'a> {
match tag_name { match tag_name {
TagName::Global(_) => Expr::GlobalTag( TagName::Global(_) => Expr::GlobalTag(
env.arena env.arena
@ -438,7 +444,8 @@ enum WhenRecursive<'a> {
} }
fn addr_to_ast<'a, A: ReplApp>( fn addr_to_ast<'a, A: ReplApp>(
env: &Env<'a, 'a, A>, env: &Env<'a, 'a>,
app: &A,
addr: usize, addr: usize,
layout: &Layout<'a>, layout: &Layout<'a>,
when_recursive: WhenRecursive<'a>, when_recursive: WhenRecursive<'a>,
@ -446,7 +453,7 @@ fn addr_to_ast<'a, A: ReplApp>(
) -> Expr<'a> { ) -> Expr<'a> {
macro_rules! helper { macro_rules! helper {
($method: ident, $ty: ty) => {{ ($method: ident, $ty: ty) => {{
let num: $ty = env.app.$method(addr); let num: $ty = app.$method(addr);
num_to_ast(env, number_literal_to_ast(env.arena, num), content) num_to_ast(env, number_literal_to_ast(env.arena, num), content)
}}; }};
@ -460,9 +467,9 @@ fn addr_to_ast<'a, A: ReplApp>(
(_, Layout::Builtin(Builtin::Bool)) => { (_, Layout::Builtin(Builtin::Bool)) => {
// TODO: bits are not as expected here. // TODO: bits are not as expected here.
// num is always false at the moment. // num is always false at the moment.
let num: bool = env.app.deref_bool(addr); let num: bool = app.deref_bool(addr);
bool_to_ast(env, num, content) bool_to_ast(env, app, num, content)
} }
(_, Layout::Builtin(Builtin::Int(int_width))) => { (_, Layout::Builtin(Builtin::Int(int_width))) => {
use IntWidth::*; use IntWidth::*;
@ -490,32 +497,32 @@ fn addr_to_ast<'a, A: ReplApp>(
} }
} }
(_, Layout::Builtin(Builtin::List(elem_layout))) => { (_, Layout::Builtin(Builtin::List(elem_layout))) => {
let elem_addr = env.app.deref_usize(addr); let elem_addr = app.deref_usize(addr);
let len = env.app.deref_usize(addr + env.target_info.ptr_width() as usize); let len = app.deref_usize(addr + env.target_info.ptr_width() as usize);
list_to_ast(env, elem_addr, len, elem_layout, content) list_to_ast(env, app, elem_addr, len, elem_layout, content)
} }
(_, Layout::Builtin(Builtin::Str)) => { (_, Layout::Builtin(Builtin::Str)) => {
let arena_str = env.app.deref_str(addr); let arena_str = app.deref_str(addr);
str_to_ast(env.arena, arena_str) str_to_ast(env.arena, arena_str)
} }
(_, Layout::Struct(field_layouts)) => match content { (_, Layout::Struct(field_layouts)) => match content {
Content::Structure(FlatType::Record(fields, _)) => { Content::Structure(FlatType::Record(fields, _)) => {
struct_to_ast(env, addr, field_layouts, *fields) struct_to_ast(env, app, addr, field_layouts, *fields)
} }
Content::Structure(FlatType::TagUnion(tags, _)) => { Content::Structure(FlatType::TagUnion(tags, _)) => {
debug_assert_eq!(tags.len(), 1); debug_assert_eq!(tags.len(), 1);
let (tag_name, payload_vars) = unpack_single_element_tag_union(env.subs, *tags); let (tag_name, payload_vars) = unpack_single_element_tag_union(env.subs, *tags);
single_tag_union_to_ast(env, addr, field_layouts, tag_name, payload_vars) single_tag_union_to_ast(env, app, addr, field_layouts, tag_name, payload_vars)
} }
Content::Structure(FlatType::FunctionOrTagUnion(tag_name, _, _)) => { Content::Structure(FlatType::FunctionOrTagUnion(tag_name, _, _)) => {
let tag_name = &env.subs[*tag_name]; let tag_name = &env.subs[*tag_name];
single_tag_union_to_ast(env, addr, field_layouts, tag_name, &[]) single_tag_union_to_ast(env, app, addr, field_layouts, tag_name, &[])
} }
Content::Structure(FlatType::EmptyRecord) => { Content::Structure(FlatType::EmptyRecord) => {
struct_to_ast(env, addr, &[], RecordFields::empty()) struct_to_ast(env, app, addr, &[], RecordFields::empty())
} }
other => { other => {
unreachable!( unreachable!(
@ -531,7 +538,7 @@ fn addr_to_ast<'a, A: ReplApp>(
opt_name: _, opt_name: _,
}, WhenRecursive::Loop(union_layout)) => { }, WhenRecursive::Loop(union_layout)) => {
let content = env.subs.get_content_without_compacting(*structure); let content = env.subs.get_content_without_compacting(*structure);
addr_to_ast(env, addr, &union_layout, when_recursive, content) addr_to_ast(env, app, addr, &union_layout, when_recursive, content)
} }
other => unreachable!("Something had a RecursivePointer layout, but instead of being a RecursionVar and having a known recursive layout, I found {:?}", other), other => unreachable!("Something had a RecursivePointer layout, but instead of being a RecursionVar and having a known recursive layout, I found {:?}", other),
} }
@ -556,14 +563,14 @@ fn addr_to_ast<'a, A: ReplApp>(
}; };
// Because this is a `NonRecursive`, the tag ID is definitely after the data. // Because this is a `NonRecursive`, the tag ID is definitely after the data.
let tag_id = tag_id_from_data(env, union_layout, addr); let tag_id = tag_id_from_data(env, app, union_layout, addr);
// use the tag ID as an index, to get its name and layout of any arguments // use the tag ID as an index, to get its name and layout of any arguments
let (tag_name, arg_layouts) = let (tag_name, arg_layouts) =
&tags_and_layouts[tag_id as usize]; &tags_and_layouts[tag_id as usize];
expr_of_tag( expr_of_tag(
env, env, app,
addr, addr,
tag_name, tag_name,
arg_layouts, arg_layouts,
@ -588,11 +595,11 @@ fn addr_to_ast<'a, A: ReplApp>(
_ => unreachable!("any other variant would have a different layout"), _ => unreachable!("any other variant would have a different layout"),
}; };
let (tag_id, ptr_to_data) = tag_id_from_recursive_ptr(env, *union_layout, addr); let (tag_id, ptr_to_data) = tag_id_from_recursive_ptr(env, app, *union_layout, addr);
let (tag_name, arg_layouts) = &tags_and_layouts[tag_id as usize]; let (tag_name, arg_layouts) = &tags_and_layouts[tag_id as usize];
expr_of_tag( expr_of_tag(
env, env, app,
ptr_to_data, ptr_to_data,
tag_name, tag_name,
arg_layouts, arg_layouts,
@ -616,10 +623,10 @@ fn addr_to_ast<'a, A: ReplApp>(
_ => unreachable!("any other variant would have a different layout"), _ => unreachable!("any other variant would have a different layout"),
}; };
let data_addr = env.app.deref_usize(addr); let data_addr = app.deref_usize(addr);
expr_of_tag( expr_of_tag(
env, env, app,
data_addr, data_addr,
&tag_name, &tag_name,
arg_layouts, arg_layouts,
@ -646,12 +653,12 @@ fn addr_to_ast<'a, A: ReplApp>(
_ => unreachable!("any other variant would have a different layout"), _ => unreachable!("any other variant would have a different layout"),
}; };
let data_addr = env.app.deref_usize(addr); let data_addr = app.deref_usize(addr);
if data_addr == 0 { if data_addr == 0 {
tag_name_to_expr(env, &nullable_name) tag_name_to_expr(env, &nullable_name)
} else { } else {
expr_of_tag( expr_of_tag(
env, env, app,
data_addr, data_addr,
&other_name, &other_name,
other_arg_layouts, other_arg_layouts,
@ -677,17 +684,17 @@ fn addr_to_ast<'a, A: ReplApp>(
_ => unreachable!("any other variant would have a different layout"), _ => unreachable!("any other variant would have a different layout"),
}; };
let data_addr = env.app.deref_usize(addr); let data_addr = app.deref_usize(addr);
if data_addr == 0 { if data_addr == 0 {
tag_name_to_expr(env, &nullable_name) tag_name_to_expr(env, &nullable_name)
} else { } else {
let (tag_id, data_addr) = tag_id_from_recursive_ptr(env, *union_layout, addr); let (tag_id, data_addr) = tag_id_from_recursive_ptr(env, app, *union_layout, addr);
let tag_id = if tag_id > nullable_id.into() { tag_id - 1 } else { tag_id }; let tag_id = if tag_id > nullable_id.into() { tag_id - 1 } else { tag_id };
let (tag_name, arg_layouts) = &tags_and_layouts[tag_id as usize]; let (tag_name, arg_layouts) = &tags_and_layouts[tag_id as usize];
expr_of_tag( expr_of_tag(
env, env, app,
data_addr, data_addr,
tag_name, tag_name,
arg_layouts, arg_layouts,
@ -707,7 +714,8 @@ fn addr_to_ast<'a, A: ReplApp>(
} }
fn list_to_ast<'a, A: ReplApp>( fn list_to_ast<'a, A: ReplApp>(
env: &Env<'a, 'a, A>, env: &Env<'a, 'a>,
app: &A,
addr: usize, addr: usize,
len: usize, len: usize,
elem_layout: &Layout<'a>, elem_layout: &Layout<'a>,
@ -740,6 +748,7 @@ fn list_to_ast<'a, A: ReplApp>(
let (newtype_containers, elem_content) = unroll_newtypes(env, elem_content); let (newtype_containers, elem_content) = unroll_newtypes(env, elem_content);
let expr = addr_to_ast( let expr = addr_to_ast(
env, env,
app,
elem_addr, elem_addr,
elem_layout, elem_layout,
WhenRecursive::Unreachable, WhenRecursive::Unreachable,
@ -756,7 +765,8 @@ fn list_to_ast<'a, A: ReplApp>(
} }
fn single_tag_union_to_ast<'a, A: ReplApp>( fn single_tag_union_to_ast<'a, A: ReplApp>(
env: &Env<'a, 'a, A>, env: &Env<'a, 'a>,
app: &A,
addr: usize, addr: usize,
field_layouts: &'a [Layout<'a>], field_layouts: &'a [Layout<'a>],
tag_name: &TagName, tag_name: &TagName,
@ -769,11 +779,11 @@ fn single_tag_union_to_ast<'a, A: ReplApp>(
let output = if field_layouts.len() == payload_vars.len() { let output = if field_layouts.len() == payload_vars.len() {
let it = payload_vars.iter().copied().zip(field_layouts); let it = payload_vars.iter().copied().zip(field_layouts);
sequence_of_expr(env, addr, it, WhenRecursive::Unreachable).into_bump_slice() sequence_of_expr(env, app, addr, it, WhenRecursive::Unreachable).into_bump_slice()
} else if field_layouts.is_empty() && !payload_vars.is_empty() { } else if field_layouts.is_empty() && !payload_vars.is_empty() {
// happens for e.g. `Foo Bar` where unit structures are nested and the inner one is dropped // happens for e.g. `Foo Bar` where unit structures are nested and the inner one is dropped
let it = payload_vars.iter().copied().zip([&Layout::Struct(&[])]); let it = payload_vars.iter().copied().zip([&Layout::Struct(&[])]);
sequence_of_expr(env, addr, it, WhenRecursive::Unreachable).into_bump_slice() sequence_of_expr(env, app, addr, it, WhenRecursive::Unreachable).into_bump_slice()
} else { } else {
unreachable!() unreachable!()
}; };
@ -782,7 +792,8 @@ fn single_tag_union_to_ast<'a, A: ReplApp>(
} }
fn sequence_of_expr<'a, I, A: ReplApp>( fn sequence_of_expr<'a, I, A: ReplApp>(
env: &Env<'a, 'a, A>, env: &Env<'a, 'a>,
app: &A,
addr: usize, addr: usize,
sequence: I, sequence: I,
when_recursive: WhenRecursive<'a>, when_recursive: WhenRecursive<'a>,
@ -800,7 +811,7 @@ where
for (var, layout) in sequence { for (var, layout) in sequence {
let content = subs.get_content_without_compacting(var); let content = subs.get_content_without_compacting(var);
let expr = addr_to_ast(env, field_addr, layout, when_recursive, content); let expr = addr_to_ast(env, app, field_addr, layout, when_recursive, content);
let loc_expr = Loc::at_zero(expr); let loc_expr = Loc::at_zero(expr);
output.push(&*arena.alloc(loc_expr)); output.push(&*arena.alloc(loc_expr));
@ -813,7 +824,8 @@ where
} }
fn struct_to_ast<'a, A: ReplApp>( fn struct_to_ast<'a, A: ReplApp>(
env: &Env<'a, 'a, A>, env: &Env<'a, 'a>,
app: &A,
addr: usize, addr: usize,
field_layouts: &'a [Layout<'a>], field_layouts: &'a [Layout<'a>],
record_fields: RecordFields, record_fields: RecordFields,
@ -836,6 +848,7 @@ fn struct_to_ast<'a, A: ReplApp>(
let loc_expr = &*arena.alloc(Loc { let loc_expr = &*arena.alloc(Loc {
value: addr_to_ast( value: addr_to_ast(
env, env,
app,
addr, addr,
&Layout::Struct(field_layouts), &Layout::Struct(field_layouts),
WhenRecursive::Unreachable, WhenRecursive::Unreachable,
@ -870,6 +883,7 @@ fn struct_to_ast<'a, A: ReplApp>(
let loc_expr = &*arena.alloc(Loc { let loc_expr = &*arena.alloc(Loc {
value: addr_to_ast( value: addr_to_ast(
env, env,
app,
field_addr, field_addr,
field_layout, field_layout,
WhenRecursive::Unreachable, WhenRecursive::Unreachable,
@ -929,7 +943,12 @@ fn unpack_two_element_tag_union(
(tag_name1, payload_vars1, tag_name2, payload_vars2) (tag_name1, payload_vars1, tag_name2, payload_vars2)
} }
fn bool_to_ast<'a, A: ReplApp>(env: &Env<'a, '_, A>, value: bool, content: &Content) -> Expr<'a> { fn bool_to_ast<'a, A: ReplApp>(
env: &Env<'a, '_>,
app: &A,
value: bool,
content: &Content,
) -> Expr<'a> {
use Content::*; use Content::*;
let arena = env.arena; let arena = env.arena;
@ -963,7 +982,7 @@ fn bool_to_ast<'a, A: ReplApp>(env: &Env<'a, '_, A>, value: bool, content: &Cont
let content = env.subs.get_content_without_compacting(var); let content = env.subs.get_content_without_compacting(var);
let loc_payload = &*arena.alloc(Loc { let loc_payload = &*arena.alloc(Loc {
value: bool_to_ast(env, value, content), value: bool_to_ast(env, app, value, content),
region: Region::zero(), region: Region::zero(),
}); });
@ -999,7 +1018,7 @@ fn bool_to_ast<'a, A: ReplApp>(env: &Env<'a, '_, A>, value: bool, content: &Cont
Alias(_, _, var) => { Alias(_, _, var) => {
let content = env.subs.get_content_without_compacting(*var); let content = env.subs.get_content_without_compacting(*var);
bool_to_ast(env, value, content) bool_to_ast(env, app, value, content)
} }
other => { other => {
unreachable!("Unexpected FlatType {:?} in bool_to_ast", other); unreachable!("Unexpected FlatType {:?} in bool_to_ast", other);
@ -1007,7 +1026,12 @@ fn bool_to_ast<'a, A: ReplApp>(env: &Env<'a, '_, A>, value: bool, content: &Cont
} }
} }
fn byte_to_ast<'a, A: ReplApp>(env: &Env<'a, '_, A>, value: u8, content: &Content) -> Expr<'a> { fn byte_to_ast<'a, A: ReplApp>(
env: &Env<'a, '_>,
app: &A,
value: u8,
content: &Content,
) -> Expr<'a> {
use Content::*; use Content::*;
let arena = env.arena; let arena = env.arena;
@ -1047,7 +1071,7 @@ fn byte_to_ast<'a, A: ReplApp>(env: &Env<'a, '_, A>, value: u8, content: &Conten
let content = env.subs.get_content_without_compacting(var); let content = env.subs.get_content_without_compacting(var);
let loc_payload = &*arena.alloc(Loc { let loc_payload = &*arena.alloc(Loc {
value: byte_to_ast(env, value, content), value: byte_to_ast(env, app, value, content),
region: Region::zero(), region: Region::zero(),
}); });
@ -1091,7 +1115,7 @@ fn byte_to_ast<'a, A: ReplApp>(env: &Env<'a, '_, A>, value: u8, content: &Conten
Alias(_, _, var) => { Alias(_, _, var) => {
let content = env.subs.get_content_without_compacting(*var); let content = env.subs.get_content_without_compacting(*var);
byte_to_ast(env, value, content) byte_to_ast(env, app, value, content)
} }
other => { other => {
unreachable!("Unexpected FlatType {:?} in bool_to_ast", other); unreachable!("Unexpected FlatType {:?} in bool_to_ast", other);
@ -1099,11 +1123,7 @@ fn byte_to_ast<'a, A: ReplApp>(env: &Env<'a, '_, A>, value: u8, content: &Conten
} }
} }
fn num_to_ast<'a, A: ReplApp>( fn num_to_ast<'a>(env: &Env<'a, '_>, num_expr: Expr<'a>, content: &Content) -> Expr<'a> {
env: &Env<'a, '_, A>,
num_expr: Expr<'a>,
content: &Content,
) -> Expr<'a> {
use Content::*; use Content::*;
let arena = env.arena; let arena = env.arena;