Merge pull request #209 from rtfeldman/list-int

Code gen List.set for List Int
This commit is contained in:
Richard Feldman 2020-03-01 19:41:21 -05:00 committed by GitHub
commit 9f3e366644
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 49 additions and 3 deletions

View File

@ -358,7 +358,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
), ),
); );
// get : List a, Int -> Result a [ IndexOutOfBounds ]* // get : List elem, Int -> Result elem [ IndexOutOfBounds ]*
let index_out_of_bounds = SolvedType::TagUnion( let index_out_of_bounds = SolvedType::TagUnion(
vec![(TagName::Global("IndexOutOfBounds".into()), vec![])], vec![(TagName::Global("IndexOutOfBounds".into()), vec![])],
Box::new(SolvedType::Wildcard), Box::new(SolvedType::Wildcard),
@ -380,7 +380,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
), ),
); );
// set : List a, Int, a -> List a // set : List elem, Int, elem -> List elem
add_type( add_type(
Symbol::LIST_SET, Symbol::LIST_SET,
SolvedType::Func( SolvedType::Func(
@ -389,7 +389,7 @@ pub fn types() -> MutMap<Symbol, (SolvedType, Region)> {
), ),
); );
// map : List a, (a -> b) -> List b // map : List before, (before -> after) -> List after
add_type( add_type(
Symbol::LIST_MAP, Symbol::LIST_MAP,
SolvedType::Func( SolvedType::Func(

View File

@ -604,6 +604,29 @@ fn call_with_args<'a, B: Backend>(
Offset32::new(0), Offset32::new(0),
) )
} }
Symbol::LIST_SET => {
// set : List elem, Int, elem -> List elem
debug_assert!(args.len() == 3);
let list_ptr = args[0];
let elem_index = args[1];
let elem = args[2];
let elem_bytes = 8; // TODO Look this up instead of hardcoding it!
let elem_size = builder.ins().iconst(types::I64, elem_bytes);
// Multiply the requested index by the size of each element.
let offset = builder.ins().imul(elem_index, elem_size);
builder.ins().store_complex(
MemFlags::new(),
elem,
&[list_ptr, offset],
Offset32::new(0),
);
list_ptr
}
_ => { _ => {
let fn_id = match scope.get(&symbol) { let fn_id = match scope.get(&symbol) {
Some(ScopeEntry::Func{ func_id, .. }) => *func_id, Some(ScopeEntry::Func{ func_id, .. }) => *func_id,

View File

@ -604,6 +604,24 @@ fn call_with_args<'a, 'ctx, 'env>(
builder.build_load(elem_ptr, "List.get") builder.build_load(elem_ptr, "List.get")
} }
Symbol::LIST_SET => {
debug_assert!(args.len() == 3);
let list_ptr = args[0].into_pointer_value();
let elem_index = args[1].into_int_value();
let elem = args[2];
let builder = env.builder;
let elem_bytes = 8; // TODO Look this up instead of hardcoding it!
let elem_size = env.context.i64_type().const_int(elem_bytes, false);
let offset = builder.build_int_mul(elem_index, elem_size, "MUL_OFFSET");
let elem_ptr = unsafe { builder.build_gep(list_ptr, &[offset], "elem") };
builder.build_store(elem_ptr, elem);
list_ptr.into()
}
_ => { _ => {
let fn_val = env let fn_val = env
.module .module

View File

@ -351,6 +351,11 @@ mod test_gen {
assert_evals_to!("List.getUnsafe [ 12, 9, 6, 3 ] 1", 9, i64); assert_evals_to!("List.getUnsafe [ 12, 9, 6, 3 ] 1", 9, i64);
} }
#[test]
fn set_int_list() {
assert_evals_to!("List.getUnsafe (List.set [ 12, 9, 7, 3 ] 1 42) 1", 42, i64);
}
#[test] #[test]
fn branch_first_float() { fn branch_first_float() {
assert_evals_to!( assert_evals_to!(