Low-level to extract discriminant from a tag union

This commit is contained in:
Ayaz Hafiz 2022-10-04 16:17:05 -05:00
parent 7421485973
commit fd54cdfdd1
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
6 changed files with 41 additions and 4 deletions

View file

@ -84,6 +84,7 @@ macro_rules! map_symbol_to_lowlevel_and_arity {
LowLevel::PtrCast => unimplemented!(),
LowLevel::RefCountInc => unimplemented!(),
LowLevel::RefCountDec => unimplemented!(),
LowLevel::TagDiscriminant => unimplemented!(),
// these are not implemented, not sure why
LowLevel::StrFromInt => unimplemented!(),

View file

@ -6575,7 +6575,7 @@ fn run_low_level<'a, 'ctx, 'env>(
unreachable!("these are higher order, and are handled elsewhere")
}
BoxExpr | UnboxExpr => {
BoxExpr | UnboxExpr | TagDiscriminant => {
unreachable!("The {:?} operation is turned into mono Expr", op)
}

View file

@ -1856,7 +1856,7 @@ impl<'a> LowLevelCall<'a> {
Eq | NotEq => self.eq_or_neq(backend),
BoxExpr | UnboxExpr => {
BoxExpr | UnboxExpr | TagDiscriminant => {
unreachable!("The {:?} operation is turned into mono Expr", self.lowlevel)
}

View file

@ -111,6 +111,7 @@ pub enum LowLevel {
BoxExpr,
UnboxExpr,
Unreachable,
TagDiscriminant,
}
macro_rules! higher_order {
@ -211,12 +212,12 @@ macro_rules! map_symbol_to_lowlevel {
LowLevel::PtrCast => unimplemented!(),
LowLevel::RefCountInc => unimplemented!(),
LowLevel::RefCountDec => unimplemented!(),
LowLevel::TagDiscriminant => unimplemented!(),
// these are not implemented, not sure why
LowLevel::StrFromInt => unimplemented!(),
LowLevel::StrFromFloat => unimplemented!(),
LowLevel::NumIsFinite => unimplemented!(),
}
}
};

View file

@ -935,7 +935,7 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] {
ListIsUnique => arena.alloc_slice_copy(&[borrowed]),
BoxExpr | UnboxExpr => {
BoxExpr | UnboxExpr | TagDiscriminant => {
unreachable!("These lowlevel operations are turned into mono Expr's")
}

View file

@ -5444,6 +5444,41 @@ pub fn with_hole<'a>(
Stmt::Let(assigned, Expr::ExprUnbox { symbol: x }, layout, hole)
}
TagDiscriminant => {
debug_assert_eq!(arg_symbols.len(), 1);
let x = arg_symbols[0];
let x_layout = layout_cache.from_var(arena, args[0].0, env.subs).expect(
"TagDiscriminant only built in derived impls, which must type-check",
);
let x_union_layout = match x_layout {
Layout::Union(un) => un,
_ => internal_error!("TagDiscriminant can only apply to tags"),
};
let tag_id_layout = x_union_layout.tag_id_layout();
debug_assert!(tag_id_layout == Layout::u8() || tag_id_layout == Layout::u16());
let tag_id_sym = env.unique_symbol();
let cast_to_u16 = self::Call {
call_type: CallType::LowLevel {
op: LowLevel::NumIntCast,
update_mode: env.next_update_mode_id(),
},
arguments: env.arena.alloc([tag_id_sym]),
};
let hole = Stmt::Let(assigned, Expr::Call(cast_to_u16), Layout::u16(), hole);
Stmt::Let(
tag_id_sym,
Expr::GetTagId {
structure: x,
union_layout: x_union_layout,
},
tag_id_layout,
env.arena.alloc(hole),
)
}
_ => {
let call = self::Call {
call_type: CallType::LowLevel {