summaryrefslogtreecommitdiff
path: root/dhall
diff options
context:
space:
mode:
authorNadrieril2020-01-30 21:43:50 +0000
committerNadrieril2020-01-30 22:00:23 +0000
commit2700af36adfac4390b9395ac2ed0e534b7eac887 (patch)
tree74974cee6eb59b84f73b9b44da9e694ce2d0be79 /dhall
parent884774dbf13fd0a0fb6936c4259527a30a285ff0 (diff)
Use OnceCell to enable returning &ValKind
Diffstat (limited to '')
-rw-r--r--dhall/Cargo.toml1
-rw-r--r--dhall/src/semantics/builtins.rs6
-rw-r--r--dhall/src/semantics/nze/value.rs121
3 files changed, 57 insertions, 71 deletions
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<Value> {
}
/// 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<Option<Thunk>>,
- kind: RefCell<Option<ValueKind>>,
+ kind: OnceCell<ValueKind>,
/// This is None if and only if `form` is `Sort` (which doesn't have a type)
ty: Option<Value>,
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<ValueKind> {
+ 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<Value>, 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<Value>, 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<ValueKind> {
- 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() {