Use a single enum for all helpers

This commit is contained in:
Brian Carroll 2021-12-15 08:48:19 +00:00
parent 3eb9e9f7ac
commit 307ab9ee83

View file

@ -22,27 +22,13 @@ pub const REFCOUNT_MAX: usize = 0;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum HelperOp { pub enum HelperOp {
Rc(RefcountOp),
Eq,
}
impl HelperOp {
fn rc(&self) -> RefcountOp {
match self {
Self::Rc(rc) => *rc,
_ => unreachable!(),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum RefcountOp {
Inc, Inc,
Dec, Dec,
DecRef, DecRef,
Eq,
} }
impl From<&ModifyRc> for RefcountOp { impl From<&ModifyRc> for HelperOp {
fn from(modify: &ModifyRc) -> Self { fn from(modify: &ModifyRc) -> Self {
match modify { match modify {
ModifyRc::Inc(..) => Self::Inc, ModifyRc::Inc(..) => Self::Inc,
@ -116,11 +102,8 @@ impl<'a> CodeGenHelp<'a> {
ModifyRc::Inc(structure, amount) => { ModifyRc::Inc(structure, amount) => {
let layout_isize = self.layout_isize; let layout_isize = self.layout_isize;
let (proc_name, new_procs_info) = self.get_or_create_proc_symbols_recursive( let (proc_name, new_procs_info) =
ident_ids, self.get_or_create_proc_symbols_recursive(ident_ids, &layout, HelperOp::Inc);
&layout,
HelperOp::Rc(RefcountOp::Inc),
);
// Define a constant for the amount to increment // Define a constant for the amount to increment
let amount_sym = self.create_symbol(ident_ids, "amount"); let amount_sym = self.create_symbol(ident_ids, "amount");
@ -146,11 +129,8 @@ impl<'a> CodeGenHelp<'a> {
} }
ModifyRc::Dec(structure) => { ModifyRc::Dec(structure) => {
let (proc_name, new_procs_info) = self.get_or_create_proc_symbols_recursive( let (proc_name, new_procs_info) =
ident_ids, self.get_or_create_proc_symbols_recursive(ident_ids, &layout, HelperOp::Dec);
&layout,
HelperOp::Rc(RefcountOp::Dec),
);
// Call helper proc, passing the Roc structure // Call helper proc, passing the Roc structure
let call_result_empty = self.create_symbol(ident_ids, "call_result_empty"); let call_result_empty = self.create_symbol(ident_ids, "call_result_empty");
@ -250,11 +230,13 @@ impl<'a> CodeGenHelp<'a> {
arena: &'a Bump, arena: &'a Bump,
ident_ids: &mut IdentIds, ident_ids: &mut IdentIds,
) -> Vec<'a, Proc<'a>> { ) -> Vec<'a, Proc<'a>> {
use HelperOp::*;
// Move the vector out of self, so we can loop over it safely // Move the vector out of self, so we can loop over it safely
let mut specs = std::mem::replace(&mut self.specs, Vec::with_capacity_in(0, arena)); let mut specs = std::mem::replace(&mut self.specs, Vec::with_capacity_in(0, arena));
let procs_iter = specs.drain(0..).map(|(layout, op, proc_symbol)| match op { let procs_iter = specs.drain(0..).map(|(layout, op, proc_symbol)| match op {
HelperOp::Rc(_) => { Inc | Dec | DecRef => {
debug_assert!(Self::is_rc_implemented_yet(&layout)); debug_assert!(Self::is_rc_implemented_yet(&layout));
match layout { match layout {
Layout::Builtin(Builtin::Str) => { Layout::Builtin(Builtin::Str) => {
@ -264,7 +246,7 @@ impl<'a> CodeGenHelp<'a> {
_ => todo!("Please update is_rc_implemented_yet for `{:?}`", layout), _ => todo!("Please update is_rc_implemented_yet for `{:?}`", layout),
} }
} }
HelperOp::Eq => match layout { Eq => match layout {
Layout::Builtin( Layout::Builtin(
Builtin::Int(_) | Builtin::Float(_) | Builtin::Bool | Builtin::Decimal, Builtin::Int(_) | Builtin::Float(_) | Builtin::Bool | Builtin::Decimal,
) => panic!( ) => panic!(
@ -381,17 +363,15 @@ impl<'a> CodeGenHelp<'a> {
self.specs.push((*layout, op, new_symbol)); self.specs.push((*layout, op, new_symbol));
let new_proc_layout = match op { let new_proc_layout = match op {
HelperOp::Rc(rc) => match rc { HelperOp::Inc => Some(ProcLayout {
RefcountOp::Inc => Some(ProcLayout {
arguments: self.arena.alloc([*layout, self.layout_isize]), arguments: self.arena.alloc([*layout, self.layout_isize]),
result: LAYOUT_UNIT, result: LAYOUT_UNIT,
}), }),
RefcountOp::Dec => Some(ProcLayout { HelperOp::Dec => Some(ProcLayout {
arguments: self.arena.alloc([*layout]), arguments: self.arena.alloc([*layout]),
result: LAYOUT_UNIT, result: LAYOUT_UNIT,
}), }),
RefcountOp::DecRef => None, HelperOp::DecRef => None,
},
HelperOp::Eq => Some(ProcLayout { HelperOp::Eq => Some(ProcLayout {
arguments: self.arena.alloc([*layout, *layout]), arguments: self.arena.alloc([*layout, *layout]),
result: LAYOUT_BOOL, result: LAYOUT_BOOL,
@ -416,13 +396,11 @@ impl<'a> CodeGenHelp<'a> {
fn gen_args(&self, op: HelperOp, layout: Layout<'a>) -> &'a [(Layout<'a>, Symbol)] { fn gen_args(&self, op: HelperOp, layout: Layout<'a>) -> &'a [(Layout<'a>, Symbol)] {
let roc_value = (layout, Symbol::ARG_1); let roc_value = (layout, Symbol::ARG_1);
match op { match op {
HelperOp::Rc(rc_op) => match rc_op { HelperOp::Inc => {
RefcountOp::Inc => {
let inc_amount = (self.layout_isize, Symbol::ARG_2); let inc_amount = (self.layout_isize, Symbol::ARG_2);
self.arena.alloc([roc_value, inc_amount]) self.arena.alloc([roc_value, inc_amount])
} }
RefcountOp::Dec | RefcountOp::DecRef => self.arena.alloc([roc_value]), HelperOp::Dec | HelperOp::DecRef => self.arena.alloc([roc_value]),
},
HelperOp::Eq => self.arena.alloc([roc_value, (layout, Symbol::ARG_2)]), HelperOp::Eq => self.arena.alloc([roc_value, (layout, Symbol::ARG_2)]),
} }
} }
@ -490,21 +468,22 @@ impl<'a> CodeGenHelp<'a> {
// Call the relevant Zig lowlevel to actually modify the refcount // Call the relevant Zig lowlevel to actually modify the refcount
let zig_call_result = self.create_symbol(ident_ids, "zig_call_result"); let zig_call_result = self.create_symbol(ident_ids, "zig_call_result");
let zig_call_expr = match op.rc() { let zig_call_expr = match op {
RefcountOp::Inc => Expr::Call(Call { HelperOp::Inc => Expr::Call(Call {
call_type: CallType::LowLevel { call_type: CallType::LowLevel {
op: LowLevel::RefCountInc, op: LowLevel::RefCountInc,
update_mode: UpdateModeId::BACKEND_DUMMY, update_mode: UpdateModeId::BACKEND_DUMMY,
}, },
arguments: self.arena.alloc([rc_ptr, Symbol::ARG_2]), arguments: self.arena.alloc([rc_ptr, Symbol::ARG_2]),
}), }),
RefcountOp::Dec | RefcountOp::DecRef => Expr::Call(Call { HelperOp::Dec | HelperOp::DecRef => Expr::Call(Call {
call_type: CallType::LowLevel { call_type: CallType::LowLevel {
op: LowLevel::RefCountDec, op: LowLevel::RefCountDec,
update_mode: UpdateModeId::BACKEND_DUMMY, update_mode: UpdateModeId::BACKEND_DUMMY,
}, },
arguments: self.arena.alloc([rc_ptr, alignment]), arguments: self.arena.alloc([rc_ptr, alignment]),
}), }),
_ => unreachable!(),
}; };
let zig_call_stmt = |next| Stmt::Let(zig_call_result, zig_call_expr, LAYOUT_UNIT, next); let zig_call_stmt = |next| Stmt::Let(zig_call_result, zig_call_expr, LAYOUT_UNIT, next);