write implementation

This commit is contained in:
Folkert 2021-06-20 21:55:04 +02:00
parent aba01ad62a
commit 5e1077bf3e
2 changed files with 107 additions and 6 deletions

View file

@ -1596,11 +1596,105 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
EmptyArray => empty_polymorphic_list(env), EmptyArray => empty_polymorphic_list(env),
Array { elem_layout, elems } => list_literal(env, scope, elem_layout, elems), Array { elem_layout, elems } => list_literal(env, scope, elem_layout, elems),
RuntimeErrorFunction(_) => todo!(), RuntimeErrorFunction(_) => todo!(),
CoerceToTagId { .. } => {
// we will do more here in the future
env.context.struct_type(&[], false).const_zero().into() CoerceToTagId {
tag_id,
structure,
index,
union_layout,
} => {
let builder = env.builder;
// cast the argument bytes into the desired shape for this tag
let (argument, _structure_layout) = load_symbol_and_layout(scope, structure);
match union_layout {
UnionLayout::NonRecursive(tag_layouts) => {
debug_assert!(argument.is_struct_value());
let field_layouts = tag_layouts[*tag_id as usize];
let struct_layout = Layout::Struct(field_layouts);
let struct_type = basic_type_from_layout(env, &struct_layout);
let struct_value = access_index_struct_value(
builder,
argument.into_struct_value(),
struct_type.into_struct_type(),
);
builder
.build_extract_value(struct_value, *index as u32, "")
.expect("desired field did not decode")
}
UnionLayout::Recursive(tag_layouts) => {
debug_assert!(argument.is_pointer_value());
let field_layouts = tag_layouts[*tag_id as usize];
let struct_layout = Layout::Struct(field_layouts);
let struct_type = basic_type_from_layout(env, &struct_layout);
lookup_at_index_ptr(
env,
field_layouts,
*index as usize,
argument.into_pointer_value(),
struct_type.into_struct_type(),
&struct_layout,
)
}
UnionLayout::NonNullableUnwrapped(_) => todo!(),
UnionLayout::NullableWrapped {
nullable_id,
other_tags,
} => {
debug_assert!(argument.is_pointer_value());
debug_assert_ne!(*tag_id as i64, *nullable_id);
let tag_index = if (*tag_id as i64) < *nullable_id {
*tag_id
} else {
tag_id - 1
};
let field_layouts = other_tags[tag_index as usize];
let struct_layout = Layout::Struct(field_layouts);
let struct_type = basic_type_from_layout(env, &struct_layout);
lookup_at_index_ptr(
env,
field_layouts,
*index as usize,
argument.into_pointer_value(),
struct_type.into_struct_type(),
&struct_layout,
)
}
UnionLayout::NullableUnwrapped {
nullable_id,
other_fields,
} => {
debug_assert!(argument.is_pointer_value());
debug_assert_ne!(*tag_id != 0, *nullable_id);
let field_layouts = other_fields;
let struct_layout = Layout::Struct(field_layouts);
let struct_type = basic_type_from_layout(env, &struct_layout);
lookup_at_index_ptr(
env,
field_layouts,
*index as usize,
argument.into_pointer_value(),
struct_type.into_struct_type(),
&struct_layout,
)
}
}
} }
GetTagId { GetTagId {
structure, structure,
union_layout, union_layout,

View file

@ -1361,8 +1361,13 @@ impl<'a> Expr<'a> {
.text("GetTagId ") .text("GetTagId ")
.append(symbol_to_doc(alloc, *structure)), .append(symbol_to_doc(alloc, *structure)),
CoerceToTagId { tag_id, structure } => alloc CoerceToTagId {
.text(format!("CoerceToTagId {} ", tag_id)) tag_id,
structure,
index,
..
} => alloc
.text(format!("CoerceToTagId (Id {}) (Index {}) ", tag_id, index))
.append(symbol_to_doc(alloc, *structure)), .append(symbol_to_doc(alloc, *structure)),
} }
} }
@ -5546,10 +5551,12 @@ fn substitute_in_expr<'a>(
None => None, None => None,
}, },
CoerceToTagId { structure, tag_id } => match substitute(subs, *structure) { CoerceToTagId { structure, tag_id, index, union_layout } => match substitute(subs, *structure) {
Some(structure) => Some(CoerceToTagId { Some(structure) => Some(CoerceToTagId {
structure, structure,
tag_id: *tag_id, tag_id: *tag_id,
index: *index,
union_layout: *union_layout,
}), }),
None => None, None => None,
}, },