summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock7
-rw-r--r--dhall/Cargo.toml1
-rw-r--r--dhall/src/semantics/builtins.rs6
-rw-r--r--dhall/src/semantics/nze/value.rs121
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)",
@@ -216,6 +217,11 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -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<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() {