From 9e8ae42b2742e27a70a7fb8ea79ae21060d43fc1 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 2 Nov 2020 03:47:15 +0000 Subject: Normalize `with` by mutation. This is Cow-style mutation: we clone only what's shared and then mutate it. This it more legible and more efficient than the immutable version. --- dhall/src/semantics/nze/nir.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'dhall/src/semantics/nze/nir.rs') diff --git a/dhall/src/semantics/nze/nir.rs b/dhall/src/semantics/nze/nir.rs index 12f1b14..95eeba1 100644 --- a/dhall/src/semantics/nze/nir.rs +++ b/dhall/src/semantics/nze/nir.rs @@ -138,6 +138,24 @@ impl Nir { self.0.kind() } + /// The contents of a `Nir` are immutable and shared. If however we happen to be the sole + /// owners, we can mutate it directly. Otherwise, this clones the internal value first. + pub fn kind_mut(&mut self) -> &mut NirKind { + if Rc::get_mut(&mut self.0).is_none() { + // Clone self + let kind = self.kind().clone(); + *self = Nir::from_kind(kind); + } + Rc::get_mut(&mut self.0).unwrap().kind_mut() + } + /// If we are the sole owner of this Nir, we can avoid a clone. + pub fn into_kind(self) -> NirKind { + match Rc::try_unwrap(self.0) { + Ok(int) => int.into_kind(), + Err(rc) => rc.kind().clone(), + } + } + pub fn to_type(&self, u: impl Into) -> Type { Type::new(self.clone(), u.into()) } @@ -291,6 +309,12 @@ impl NirInternal { fn kind(&self) -> &NirKind { &self.kind } + fn kind_mut(&mut self) -> &mut NirKind { + self.kind.get_mut() + } + fn into_kind(self) -> NirKind { + self.kind.into_inner() + } } impl NirKind { -- cgit v1.2.3