From 2700af36adfac4390b9395ac2ed0e534b7eac887 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Thu, 30 Jan 2020 21:43:50 +0000 Subject: Use OnceCell to enable returning &ValKind --- Cargo.lock | 7 +++ dhall/Cargo.toml | 1 + dhall/src/semantics/builtins.rs | 6 +- dhall/src/semantics/nze/value.rs | 121 +++++++++++++++++---------------------- 4 files changed, 64 insertions(+), 71 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index de3fc27..c737e52 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -90,6 +90,7 @@ dependencies = [ "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "pest_consume 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -215,6 +216,11 @@ dependencies = [ "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "once_cell" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "opaque-debug" version = "0.2.3" @@ -529,6 +535,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" "checksum nom 5.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c618b63422da4401283884e6668d39f819a106ef51f5f59b81add00075da35ca" +"checksum once_cell 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1c601810575c99596d4afc46f78a678c80105117c379eb3650cf99b8a21ce5b" "checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" "checksum output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" "checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" diff --git a/dhall/Cargo.toml b/dhall/Cargo.toml index 1479eaa..2fbfb23 100644 --- a/dhall/Cargo.toml +++ b/dhall/Cargo.toml @@ -13,6 +13,7 @@ build = "build.rs" itertools = "0.8.0" hex = "0.3.2" lazy_static = "1.4.0" + once_cell = "1.3.1" percent-encoding = "2.1.0" pest = "2.1" pest_consume = "1.0" diff --git a/dhall/src/semantics/builtins.rs b/dhall/src/semantics/builtins.rs index 85ef294..c20fb77 100644 --- a/dhall/src/semantics/builtins.rs +++ b/dhall/src/semantics/builtins.rs @@ -43,9 +43,9 @@ impl BuiltinClosure { } /// This doesn't break the invariant because we already checked that the appropriate arguments /// did not normalize to something that allows evaluation to proceed. - pub fn normalize_mut(&mut self) { - for x in self.args.iter_mut() { - x.normalize_mut(); + pub fn normalize(&self) { + for x in self.args.iter() { + x.normalize(); } } pub fn to_tyexprkind(&self, venv: VarEnv) -> TyExprKind { diff --git a/dhall/src/semantics/nze/value.rs b/dhall/src/semantics/nze/value.rs index d25e8b5..945ee6e 100644 --- a/dhall/src/semantics/nze/value.rs +++ b/dhall/src/semantics/nze/value.rs @@ -1,4 +1,5 @@ -use std::cell::{Ref, RefCell}; +use once_cell::unsync::OnceCell; +use std::cell::RefCell; use std::collections::HashMap; use std::rc::Rc; @@ -28,7 +29,7 @@ struct ValueInternal { /// Exactly one of `thunk` of `kind` must be set at a given time. /// Once `thunk` is unset and `kind` is set, we never go back. thunk: RefCell>, - kind: RefCell>, + kind: OnceCell, /// This is None if and only if `form` is `Sort` (which doesn't have a type) ty: Option, span: Span, @@ -183,14 +184,14 @@ impl Value { /// This is what you want if you want to pattern-match on the value. /// WARNING: drop this ref before normalizing the same value or you will run into BorrowMut /// panics. - pub(crate) fn kind(&self) -> Ref { + pub(crate) fn kind(&self) -> &ValueKind { self.0.kind() } /// Converts a value back to the corresponding AST expression. pub(crate) fn to_expr(&self, opts: ToExprOptions) -> NormalizedExpr { if opts.normalize { - self.normalize_nf(); + self.normalize(); } self.to_tyexpr_noenv().to_expr(opts) @@ -204,18 +205,18 @@ impl Value { self.to_whnf_ignore_type() } - /// Normalizes contents to normal form; faster than `normalize_nf` if + /// Normalizes contents to normal form; faster than `normalize` if /// no one else shares this. pub(crate) fn normalize_mut(&mut self) { match Rc::get_mut(&mut self.0) { // Mutate directly if sole owner - Some(vint) => vint.normalize_nf_mut(), + Some(vint) => vint.normalize_mut(), // Otherwise mutate through the refcell - None => self.0.normalize_nf(), + None => self.normalize(), } } - pub(crate) fn normalize_nf(&self) { - self.0.normalize_nf() + pub(crate) fn normalize(&self) { + self.0.normalize() } pub(crate) fn app(&self, v: Value) -> Value { @@ -366,17 +367,19 @@ impl Value { impl ValueInternal { fn from_whnf(k: ValueKind, ty: Option, span: Span) -> Self { + let kind = OnceCell::new(); + kind.set(k).unwrap(); ValueInternal { thunk: RefCell::new(None), - kind: RefCell::new(Some(k)), + kind, ty, span, } } fn from_thunk(th: Thunk, ty: Option, span: Span) -> Self { ValueInternal { - kind: RefCell::new(None), thunk: RefCell::new(Some(th)), + kind: OnceCell::new(), ty, span, } @@ -385,38 +388,23 @@ impl ValueInternal { Value(Rc::new(self)) } - fn kind(&self) -> Ref { - self.normalize_whnf(); - Ref::map(self.kind.borrow(), |kind| kind.as_ref().unwrap()) - } - fn normalize_whnf(&self) { - if self.kind.borrow().is_none() { - let mut thunk_borrow = self.thunk.borrow_mut(); - let kind = thunk_borrow.as_ref().unwrap().eval(); - *thunk_borrow = None; - *self.kind.borrow_mut() = Some(kind); + fn kind(&self) -> &ValueKind { + if self.kind.get().is_none() { + let thunk = self.thunk.borrow_mut().take().unwrap(); + self.kind.set(thunk.eval()).unwrap(); } + self.kind.get().unwrap() } - fn normalize_nf(&self) { - self.normalize_whnf(); - self.kind.borrow_mut().as_mut().unwrap().normalize_mut() + fn normalize(&self) { + self.kind().normalize(); } // Avoids a RefCell lock - fn normalize_whnf_mut(&mut self) { - let self_thunk = RefCell::get_mut(&mut self.thunk); - if let Some(thunk) = &mut *self_thunk { - let self_kind = RefCell::get_mut(&mut self.kind); - let mut kind = thunk.eval(); - kind.normalize_mut(); - *self_kind = Some(kind); - *self_thunk = None; + fn normalize_mut(&mut self) { + if self.kind.get().is_none() { + let thunk = RefCell::get_mut(&mut self.thunk).take().unwrap(); + self.kind.set(thunk.eval()).unwrap(); } - } - // Avoids a RefCell lock - fn normalize_nf_mut(&mut self) { - self.normalize_whnf_mut(); - let self_kind = RefCell::get_mut(&mut self.kind); - self_kind.as_mut().unwrap().normalize_mut(); + self.normalize(); } fn get_type(&self) -> Result<&Value, TypeError> { @@ -432,7 +420,7 @@ impl ValueKind { Value::from_kind_and_type(self, t) } - pub(crate) fn normalize_mut(&mut self) { + pub(crate) fn normalize(&self) { match self { ValueKind::Var(..) | ValueKind::Const(_) @@ -442,52 +430,52 @@ impl ValueKind { | ValueKind::DoubleLit(_) => {} ValueKind::EmptyOptionalLit(tth) | ValueKind::EmptyListLit(tth) => { - tth.normalize_mut(); + tth.normalize(); } ValueKind::NEOptionalLit(th) => { - th.normalize_mut(); + th.normalize(); } ValueKind::LamClosure { annot, closure, .. } | ValueKind::PiClosure { annot, closure, .. } => { - annot.normalize_mut(); - closure.normalize_mut(); + annot.normalize(); + closure.normalize(); } - ValueKind::AppliedBuiltin(closure) => closure.normalize_mut(), + ValueKind::AppliedBuiltin(closure) => closure.normalize(), ValueKind::NEListLit(elts) => { - for x in elts.iter_mut() { - x.normalize_mut(); + for x in elts.iter() { + x.normalize(); } } ValueKind::RecordLit(kvs) => { - for x in kvs.values_mut() { - x.normalize_mut(); + for x in kvs.values() { + x.normalize(); } } ValueKind::RecordType(kvs) => { - for x in kvs.values_mut() { - x.normalize_mut(); + for x in kvs.values() { + x.normalize(); } } ValueKind::UnionType(kts) | ValueKind::UnionConstructor(_, kts, _) => { - for x in kts.values_mut().flat_map(|opt| opt) { - x.normalize_mut(); + for x in kts.values().flat_map(|opt| opt) { + x.normalize(); } } ValueKind::UnionLit(_, v, kts, _, _) => { - v.normalize_mut(); - for x in kts.values_mut().flat_map(|opt| opt) { - x.normalize_mut(); + v.normalize(); + for x in kts.values().flat_map(|opt| opt) { + x.normalize(); } } - ValueKind::TextLit(tlit) => tlit.normalize_mut(), + ValueKind::TextLit(tlit) => tlit.normalize(), ValueKind::Equivalence(x, y) => { - x.normalize_mut(); - y.normalize_mut(); + x.normalize(); + y.normalize(); } ValueKind::PartialExpr(e) => { - e.map_mut(Value::normalize_mut); + e.map_ref(Value::normalize); } } } @@ -563,7 +551,7 @@ impl Closure { } // TODO: somehow normalize the body. Might require to pass an env. - pub fn normalize_mut(&mut self) {} + pub fn normalize(&self) {} /// Convert this closure to a TyExpr pub fn to_tyexpr(&self, venv: VarEnv) -> TyExpr { self.apply_var(NzVar::new(venv.size())) @@ -634,9 +622,9 @@ impl TextLit { } /// Normalize the contained values. This does not break the invariant because we have already /// ensured that no contained values normalize to a TextLit. - pub fn normalize_mut(&mut self) { - for x in self.0.iter_mut() { - x.map_mut(Value::normalize_mut); + pub fn normalize(&self) { + for x in self.0.iter() { + x.map_ref(Value::normalize); } } } @@ -670,8 +658,7 @@ impl std::cmp::Eq for Closure {} impl std::fmt::Debug for Value { fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let vint: &ValueInternal = &self.0; - let kind_borrow = vint.kind.borrow(); - let mut x = if let Some(kind) = kind_borrow.as_ref() { + let mut x = if let Some(kind) = vint.kind.get() { if let ValueKind::Const(c) = kind { return write!(fmt, "{:?}", c); } else { @@ -680,10 +667,8 @@ impl std::fmt::Debug for Value { x } } else { - let thunk_borrow = vint.thunk.borrow(); - let th = thunk_borrow.as_ref().unwrap(); let mut x = fmt.debug_struct(&format!("Value@Thunk")); - x.field("thunk", th); + x.field("thunk", vint.thunk.borrow().as_ref().unwrap()); x }; if let Some(ty) = vint.ty.as_ref() { -- cgit v1.2.3