repl: try putting the from_memory method on the AppMemory trait instead

This commit is contained in:
Brian Carroll 2022-01-28 11:00:49 +00:00
parent 6a9d31ec04
commit 46a3035759
2 changed files with 61 additions and 75 deletions

View File

@ -16,9 +16,9 @@ use roc_region::all::{Loc, Region};
use roc_types::subs::{Content, FlatType, GetSubsSlice, RecordFields, Subs, UnionTags, Variable}; use roc_types::subs::{Content, FlatType, GetSubsSlice, RecordFields, Subs, UnionTags, Variable};
use std::cmp::{max_by_key, min_by_key}; use std::cmp::{max_by_key, min_by_key};
use super::from_memory::{AppMemory, FromMemory}; use super::from_memory::AppMemory;
struct Env<'a, 'env, M: AppMemory> { struct Env<'a, 'env, M> {
arena: &'a Bump, arena: &'a Bump,
subs: &'env Subs, subs: &'env Subs,
ptr_bytes: u32, ptr_bytes: u32,
@ -40,7 +40,7 @@ pub enum ToAstProblem {
/// we get to a struct or tag, we know what the labels are and can turn them /// we get to a struct or tag, we know what the labels are and can turn them
/// back into the appropriate user-facing literals. /// back into the appropriate user-facing literals.
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub unsafe fn jit_to_ast<'a, M: AppMemory>( pub unsafe fn jit_to_ast<'a, M>(
arena: &'a Bump, arena: &'a Bump,
lib: Library, lib: Library,
main_fn_name: &str, main_fn_name: &str,
@ -87,7 +87,7 @@ 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, M: AppMemory>( fn unroll_newtypes<'a, M>(
env: &Env<'a, 'a, M>, env: &Env<'a, 'a, M>,
mut content: &'a Content, mut content: &'a Content,
) -> (Vec<'a, NewtypeKind<'a>>, &'a Content) { ) -> (Vec<'a, NewtypeKind<'a>>, &'a Content) {
@ -121,7 +121,7 @@ fn unroll_newtypes<'a, M: AppMemory>(
} }
} }
fn apply_newtypes<'a, M: AppMemory>( fn apply_newtypes<'a, M>(
env: &Env<'a, '_, M>, env: &Env<'a, '_, M>,
newtype_containers: Vec<'a, NewtypeKind<'a>>, newtype_containers: Vec<'a, NewtypeKind<'a>>,
mut expr: Expr<'a>, mut expr: Expr<'a>,
@ -149,14 +149,14 @@ fn apply_newtypes<'a, M: AppMemory>(
expr expr
} }
fn unroll_aliases<'a, M: AppMemory>(env: &Env<'a, 'a, M>, mut content: &'a Content) -> &'a Content { fn unroll_aliases<'a, M>(env: &Env<'a, 'a, M>, 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, M: AppMemory>( fn unroll_recursion_var<'a, M>(
env: &Env<'a, 'a, M>, env: &Env<'a, 'a, M>,
mut content: &'a Content, mut content: &'a Content,
) -> &'a Content { ) -> &'a Content {
@ -166,7 +166,7 @@ fn unroll_recursion_var<'a, M: AppMemory>(
content content
} }
fn get_tags_vars_and_variant<'a, M: AppMemory>( fn get_tags_vars_and_variant<'a, M>(
env: &Env<'a, '_, M>, env: &Env<'a, '_, M>,
tags: &UnionTags, tags: &UnionTags,
opt_rec_var: Option<Variable>, opt_rec_var: Option<Variable>,
@ -184,7 +184,7 @@ fn get_tags_vars_and_variant<'a, M: AppMemory>(
(vars_of_tag, union_variant) (vars_of_tag, union_variant)
} }
fn expr_of_tag<'a, M: AppMemory>( fn expr_of_tag<'a, M>(
env: &Env<'a, 'a, M>, env: &Env<'a, 'a, M>,
data_addr: usize, data_addr: usize,
tag_name: &TagName, tag_name: &TagName,
@ -207,7 +207,7 @@ fn expr_of_tag<'a, M: AppMemory>(
/// 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, M: AppMemory>( fn tag_id_from_data<'a, M>(
env: &Env<'a, 'a, M>, env: &Env<'a, 'a, M>,
union_layout: UnionLayout, union_layout: UnionLayout,
data_addr: usize, data_addr: usize,
@ -218,27 +218,37 @@ fn tag_id_from_data<'a, M: AppMemory>(
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 => u8::from_memory(&env.app_memory, tag_id_addr) as i64, Builtin::Bool => {
Builtin::Int(IntWidth::U8) => u8::from_memory(&env.app_memory, tag_id_addr) as i64, let value: u8 = env.app_memory.from_memory(tag_id_addr);
Builtin::Int(IntWidth::U16) => u16::from_memory(&env.app_memory, tag_id_addr) as i64, value as i64
}
Builtin::Int(IntWidth::U8) => {
let value: u8 = env.app_memory.from_memory(tag_id_addr);
value as i64
}
Builtin::Int(IntWidth::U16) => {
let value: u16 = env.app_memory.from_memory(tag_id_addr);
value 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
i64::from_memory(&env.app_memory, tag_id_addr) env.app_memory.from_memory(tag_id_addr)
} }
_ => unreachable!("invalid tag id layout"), _ => unreachable!("invalid tag id layout"),
} }
} }
fn deref_addr_of_addr<'a, M: AppMemory>(env: &Env<'a, 'a, M>, addr_of_addr: usize) -> usize { // TODO: inline this at call sites
usize::from_memory(&env.app_memory, addr_of_addr) fn deref_addr_of_addr<'a, M>(env: &Env<'a, 'a, M>, addr_of_addr: usize) -> usize {
env.app_memory.from_memory(addr_of_addr)
} }
/// Gets the tag ID of a union variant from its recursive pointer (that is, the pointer to the /// Gets the tag ID of a union variant from its recursive pointer (that is, the pointer to the
/// pointer to the data of the union variant). Returns /// pointer to the data of the union variant). Returns
/// - 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, M: AppMemory>( fn tag_id_from_recursive_ptr<'a, M>(
env: &Env<'a, 'a, M>, env: &Env<'a, 'a, M>,
union_layout: UnionLayout, union_layout: UnionLayout,
rec_addr: usize, rec_addr: usize,
@ -264,7 +274,7 @@ const OPAQUE_FUNCTION: Expr = Expr::Var {
ident: "<function>", ident: "<function>",
}; };
fn jit_to_ast_help<'a, M: AppMemory>( fn jit_to_ast_help<'a, M>(
env: &Env<'a, 'a, M>, env: &Env<'a, 'a, M>,
lib: Library, lib: Library,
main_fn_name: &str, main_fn_name: &str,
@ -440,7 +450,7 @@ fn jit_to_ast_help<'a, M: AppMemory>(
result.map(|e| apply_newtypes(env, newtype_containers, e)) result.map(|e| apply_newtypes(env, newtype_containers, e))
} }
fn tag_name_to_expr<'a, M: AppMemory>(env: &Env<'a, '_, M>, tag_name: &TagName) -> Expr<'a> { fn tag_name_to_expr<'a, M>(env: &Env<'a, '_, M>, tag_name: &TagName) -> Expr<'a> {
match tag_name { match tag_name {
TagName::Global(_) => Expr::GlobalTag( TagName::Global(_) => Expr::GlobalTag(
env.arena env.arena
@ -462,7 +472,7 @@ enum WhenRecursive<'a> {
Loop(Layout<'a>), Loop(Layout<'a>),
} }
fn addr_to_ast<'a, M: AppMemory>( fn addr_to_ast<'a, M>(
env: &Env<'a, 'a, M>, env: &Env<'a, 'a, M>,
addr: usize, addr: usize,
layout: &Layout<'a>, layout: &Layout<'a>,
@ -471,7 +481,7 @@ fn addr_to_ast<'a, M: AppMemory>(
) -> Expr<'a> { ) -> Expr<'a> {
macro_rules! helper { macro_rules! helper {
($ty:ty) => {{ ($ty:ty) => {{
let num = <$ty>::from_memory(&env.app_memory, addr); let num: $ty = env.app_memory.from_memory(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)
}}; }};
@ -485,7 +495,7 @@ fn addr_to_ast<'a, M: AppMemory>(
(_, 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::from_memory(&env.app_memory, addr); let num: bool = env.app_memory.from_memory(addr);
bool_to_ast(env, num, content) bool_to_ast(env, num, content)
} }
@ -515,8 +525,8 @@ fn addr_to_ast<'a, M: AppMemory>(
} }
} }
(_, Layout::Builtin(Builtin::List(elem_layout))) => { (_, Layout::Builtin(Builtin::List(elem_layout))) => {
let elem_addr = usize::from_memory(&env.app_memory, addr); let elem_addr: usize = env.app_memory.from_memory(addr);
let len = usize::from_memory(&env.app_memory, addr + env.ptr_bytes as usize); let len: usize = env.app_memory.from_memory(addr + env.ptr_bytes as usize);
list_to_ast(env, elem_addr, len, elem_layout, content) list_to_ast(env, elem_addr, len, elem_layout, content)
} }
@ -732,7 +742,7 @@ fn addr_to_ast<'a, M: AppMemory>(
apply_newtypes(env, newtype_containers, expr) apply_newtypes(env, newtype_containers, expr)
} }
fn list_to_ast<'a, M: AppMemory>( fn list_to_ast<'a, M>(
env: &Env<'a, 'a, M>, env: &Env<'a, 'a, M>,
addr: usize, addr: usize,
len: usize, len: usize,
@ -781,7 +791,7 @@ fn list_to_ast<'a, M: AppMemory>(
Expr::List(Collection::with_items(output)) Expr::List(Collection::with_items(output))
} }
fn single_tag_union_to_ast<'a, M: AppMemory>( fn single_tag_union_to_ast<'a, M>(
env: &Env<'a, 'a, M>, env: &Env<'a, 'a, M>,
addr: usize, addr: usize,
field_layouts: &'a [Layout<'a>], field_layouts: &'a [Layout<'a>],
@ -807,7 +817,7 @@ fn single_tag_union_to_ast<'a, M: AppMemory>(
Expr::Apply(loc_tag_expr, output, CalledVia::Space) Expr::Apply(loc_tag_expr, output, CalledVia::Space)
} }
fn sequence_of_expr<'a, I, M: AppMemory>( fn sequence_of_expr<'a, I, M>(
env: &Env<'a, 'a, M>, env: &Env<'a, 'a, M>,
addr: usize, addr: usize,
sequence: I, sequence: I,
@ -838,7 +848,7 @@ where
output output
} }
fn struct_to_ast<'a, M: AppMemory>( fn struct_to_ast<'a, M>(
env: &Env<'a, 'a, M>, env: &Env<'a, 'a, M>,
addr: usize, addr: usize,
field_layouts: &'a [Layout<'a>], field_layouts: &'a [Layout<'a>],
@ -955,7 +965,7 @@ 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, M: AppMemory>(env: &Env<'a, '_, M>, value: bool, content: &Content) -> Expr<'a> { fn bool_to_ast<'a, M>(env: &Env<'a, '_, M>, value: bool, content: &Content) -> Expr<'a> {
use Content::*; use Content::*;
let arena = env.arena; let arena = env.arena;
@ -1033,7 +1043,7 @@ fn bool_to_ast<'a, M: AppMemory>(env: &Env<'a, '_, M>, value: bool, content: &Co
} }
} }
fn byte_to_ast<'a, M: AppMemory>(env: &Env<'a, '_, M>, value: u8, content: &Content) -> Expr<'a> { fn byte_to_ast<'a, M>(env: &Env<'a, '_, M>, value: u8, content: &Content) -> Expr<'a> {
use Content::*; use Content::*;
let arena = env.arena; let arena = env.arena;
@ -1120,7 +1130,7 @@ fn byte_to_ast<'a, M: AppMemory>(env: &Env<'a, '_, M>, value: u8, content: &Cont
} }
} }
fn num_to_ast<'a, M: AppMemory>( fn num_to_ast<'a, M>(
env: &Env<'a, '_, M>, env: &Env<'a, '_, M>,
num_expr: Expr<'a>, num_expr: Expr<'a>,
content: &Content, content: &Content,

View File

@ -1,17 +1,9 @@
use std::mem::size_of; use std::mem::size_of;
pub trait FromMemory<M: AppMemory> { pub trait AppMemory<T> {
fn from_memory(memory: &M, address: usize) -> Self; fn from_memory(&self, addr: usize) -> T;
} }
// TODO: check if AppMemory trait is really needed!
// I wrote it to try to help with Rust type inference but it didn't really help
// Rust is complaining in eval.rs that it can't find instances like `u8: FromMemory<M>`
// I thought that the AppMemory trait might give it some more hints, but it's still not working.
pub trait AppMemory {}
impl AppMemory for AppMemoryInternal {}
impl<'a> AppMemory for AppMemoryExternal<'a> {}
/// A block of app memory in the same address space as the compiler /// A block of app memory in the same address space as the compiler
pub struct AppMemoryInternal; pub struct AppMemoryInternal;
@ -23,41 +15,25 @@ pub struct AppMemoryExternal<'a> {
macro_rules! impl_number_type { macro_rules! impl_number_type {
($t: ty) => { ($t: ty) => {
impl FromMemory<AppMemoryInternal> for $t { impl AppMemory<$t> for AppMemoryInternal {
fn from_memory(_: &AppMemoryInternal, address: usize) -> Self { fn from_memory(&self, addr: usize) -> $t {
let ptr = address as *const _; let ptr = addr as *const _;
unsafe { *ptr } unsafe { *ptr }
} }
} }
impl FromMemory<AppMemoryExternal<'_>> for $t { impl AppMemory<$t> for AppMemoryExternal<'_> {
fn from_memory(memory: &AppMemoryExternal, address: usize) -> Self { fn from_memory(&self, address: usize) -> $t {
const N: usize = size_of::<$t>(); const N: usize = size_of::<$t>();
let mut array = [0; N]; let mut array = [0; N];
array.copy_from_slice(&memory.bytes[address..][..N]); array.copy_from_slice(&self.bytes[address..][..N]);
Self::from_le_bytes(array) <$t>::from_le_bytes(array)
} }
} }
}; };
} }
impl FromMemory<AppMemoryInternal> for u8 { impl_number_type!(u8);
fn from_memory(_: &AppMemoryInternal, address: usize) -> Self {
let ptr = address as *const _;
unsafe { *ptr }
}
}
impl FromMemory<AppMemoryExternal<'_>> for u8 {
fn from_memory(memory: &AppMemoryExternal, address: usize) -> Self {
const N: usize = size_of::<u8>();
let mut array = [0; N];
array.copy_from_slice(&memory.bytes[address..][..N]);
Self::from_le_bytes(array)
}
}
// impl_number_type!(u8);
impl_number_type!(u16); impl_number_type!(u16);
impl_number_type!(u32); impl_number_type!(u32);
impl_number_type!(u64); impl_number_type!(u64);
@ -74,16 +50,16 @@ impl_number_type!(isize);
impl_number_type!(f32); impl_number_type!(f32);
impl_number_type!(f64); impl_number_type!(f64);
impl FromMemory<AppMemoryInternal> for bool { impl AppMemory<bool> for AppMemoryInternal {
fn from_memory(_: &AppMemoryInternal, address: usize) -> Self { fn from_memory(&self, addr: usize) -> bool {
let ptr = address as *const _; let ptr = addr as *const _;
unsafe { *ptr } unsafe { *ptr }
} }
} }
impl FromMemory<AppMemoryExternal<'_>> for bool { impl AppMemory<bool> for AppMemoryExternal<'_> {
fn from_memory(memory: &AppMemoryExternal, address: usize) -> Self { fn from_memory(&self, address: usize) -> bool {
memory.bytes[address] != 0 self.bytes[address] != 0
} }
} }
@ -97,7 +73,7 @@ mod tests {
let ptr = &value as *const u8; let ptr = &value as *const u8;
let addr = ptr as usize; let addr = ptr as usize;
let memory = AppMemoryInternal; let memory = AppMemoryInternal;
let recovered: u8 = u8::from_memory(&memory, addr); let recovered: u8 = memory.from_memory(addr);
assert_eq!(value, recovered); assert_eq!(value, recovered);
} }
@ -108,7 +84,7 @@ mod tests {
bytes: &[0, 0, value, 0, 0], bytes: &[0, 0, value, 0, 0],
}; };
let addr = 2; let addr = 2;
let recovered: u8 = u8::from_memory(&memory, addr); let recovered: u8 = memory.from_memory(addr);
assert_eq!(value, recovered); assert_eq!(value, recovered);
} }
@ -118,7 +94,7 @@ mod tests {
let ptr = &value as *const i64; let ptr = &value as *const i64;
let addr = ptr as usize; let addr = ptr as usize;
let memory = AppMemoryInternal; let memory = AppMemoryInternal;
let recovered: i64 = i64::from_memory(&memory, addr); let recovered: i64 = memory.from_memory(addr);
assert_eq!(value, recovered); assert_eq!(value, recovered);
} }
@ -133,7 +109,7 @@ mod tests {
], ],
}; };
let addr = 2; let addr = 2;
let recovered: i64 = i64::from_memory(&memory, addr); let recovered: i64 = memory.from_memory(addr);
assert_eq!(value, recovered); assert_eq!(value, recovered);
} }
} }