summaryrefslogtreecommitdiff
path: root/dhall/src/phase/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'dhall/src/phase/mod.rs')
-rw-r--r--dhall/src/phase/mod.rs235
1 files changed, 106 insertions, 129 deletions
diff --git a/dhall/src/phase/mod.rs b/dhall/src/phase/mod.rs
index ccedff2..2c5505c 100644
--- a/dhall/src/phase/mod.rs
+++ b/dhall/src/phase/mod.rs
@@ -1,17 +1,14 @@
-use std::borrow::Cow;
use std::fmt::Display;
use std::path::Path;
-use dhall_syntax::{Const, Import, Span, SubExpr, X};
+use dhall_syntax::{Builtin, Const, Expr};
-use crate::core::context::TypecheckContext;
-use crate::core::thunk::Thunk;
-use crate::core::value::Value;
+use crate::core::value::{ToExprOptions, Value};
+use crate::core::valuef::ValueF;
use crate::core::var::{AlphaVar, Shift, Subst};
-use crate::error::{EncodeError, Error, ImportError, TypeError, TypeMessage};
+use crate::error::{EncodeError, Error, ImportError, TypeError};
use resolve::ImportRoot;
-use typecheck::type_of_const;
pub(crate) mod binary;
pub(crate) mod normalize;
@@ -19,30 +16,23 @@ pub(crate) mod parse;
pub(crate) mod resolve;
pub(crate) mod typecheck;
-pub type ParsedSubExpr = SubExpr<Span, Import>;
-pub type DecodedSubExpr = SubExpr<X, Import>;
-pub type ResolvedSubExpr = SubExpr<Span, Normalized>;
-pub type NormalizedSubExpr = SubExpr<X, X>;
+pub type ParsedExpr = Expr<!>;
+pub type DecodedExpr = Expr<!>;
+pub type ResolvedExpr = Expr<Normalized>;
+pub type NormalizedExpr = Expr<Normalized>;
#[derive(Debug, Clone)]
-pub struct Parsed(ParsedSubExpr, ImportRoot);
+pub struct Parsed(ParsedExpr, ImportRoot);
/// An expression where all imports have been resolved
+///
+/// Invariant: there must be no `Import` nodes or `ImportAlt` operations left.
#[derive(Debug, Clone)]
-pub struct Resolved(ResolvedSubExpr);
+pub struct Resolved(ResolvedExpr);
/// A typed expression
#[derive(Debug, Clone)]
-pub enum Typed {
- // Any value, along with (optionally) its type
- Untyped(Thunk),
- Typed(Thunk, Box<Type>),
- // One of the base higher-kinded typed.
- // Used to avoid storing the same tower ot Type->Kind->Sort
- // over and over again. Also enables having Sort as a type
- // even though it doesn't itself have a type.
- Const(Const),
-}
+pub struct Typed(Value);
/// A normalized expression.
///
@@ -50,8 +40,6 @@ pub enum Typed {
#[derive(Debug, Clone)]
pub struct Normalized(Typed);
-pub type Type = Typed;
-
impl Parsed {
pub fn parse_file(f: &Path) -> Result<Parsed, Error> {
parse::parse_file(f)
@@ -59,11 +47,9 @@ impl Parsed {
pub fn parse_str(s: &str) -> Result<Parsed, Error> {
parse::parse_str(s)
}
- #[allow(dead_code)]
pub fn parse_binary_file(f: &Path) -> Result<Parsed, Error> {
parse::parse_binary_file(f)
}
- #[allow(dead_code)]
pub fn parse_binary(data: &[u8]) -> Result<Parsed, Error> {
parse::parse_binary(data)
}
@@ -71,12 +57,10 @@ impl Parsed {
pub fn resolve(self) -> Result<Resolved, ImportError> {
resolve::resolve(self)
}
- #[allow(dead_code)]
pub fn skip_resolve(self) -> Result<Resolved, ImportError> {
resolve::skip_resolve_expr(self)
}
- #[allow(dead_code)]
pub fn encode(&self) -> Result<Vec<u8>, EncodeError> {
crate::phase::binary::encode(&self.0)
}
@@ -84,15 +68,11 @@ impl Parsed {
impl Resolved {
pub fn typecheck(self) -> Result<Typed, TypeError> {
- typecheck::typecheck(self)
+ Ok(typecheck::typecheck(self.0)?.into_typed())
}
- pub fn typecheck_with(self, ty: &Type) -> Result<Typed, TypeError> {
- typecheck::typecheck_with(self, ty)
- }
- /// Pretends this expression has been typechecked. Use with care.
- #[allow(dead_code)]
- pub fn skip_typecheck(self) -> Typed {
- typecheck::skip_typecheck(self)
+ pub fn typecheck_with(self, ty: &Typed) -> Result<Typed, TypeError> {
+ Ok(typecheck::typecheck_with(self.0, ty.normalize_to_expr())?
+ .into_typed())
}
}
@@ -105,117 +85,110 @@ impl Typed {
///
/// However, `normalize` will not fail if the expression is ill-typed and will
/// leave ill-typed sub-expressions unevaluated.
- pub fn normalize(self) -> Normalized {
- match &self {
- Typed::Const(_) => {}
- Typed::Untyped(thunk) | Typed::Typed(thunk, _) => {
- thunk.normalize_nf();
- }
- }
+ pub fn normalize(mut self) -> Normalized {
+ self.normalize_mut();
Normalized(self)
}
- pub fn from_thunk_and_type(th: Thunk, t: Type) -> Self {
- Typed::Typed(th, Box::new(t))
+ pub(crate) fn from_const(c: Const) -> Self {
+ Typed(Value::from_const(c))
}
- pub fn from_thunk_untyped(th: Thunk) -> Self {
- Typed::Untyped(th)
+ pub(crate) fn from_valuef_and_type(v: ValueF, t: Typed) -> Self {
+ Typed(Value::from_valuef_and_type(v, t.into_value()))
}
- pub fn from_const(c: Const) -> Self {
- Typed::Const(c)
+ pub(crate) fn from_value(th: Value) -> Self {
+ Typed(th)
}
- pub fn from_value_untyped(v: Value) -> Self {
- Typed::from_thunk_untyped(Thunk::from_value(v))
+ pub(crate) fn const_type() -> Self {
+ Typed::from_const(Const::Type)
}
- // TODO: Avoid cloning if possible
- pub fn to_value(&self) -> Value {
- match self {
- Typed::Untyped(th) | Typed::Typed(th, _) => th.to_value(),
- Typed::Const(c) => Value::Const(*c),
- }
- }
- pub fn to_expr(&self) -> NormalizedSubExpr {
- self.to_value().normalize_to_expr()
- }
- pub fn to_expr_alpha(&self) -> NormalizedSubExpr {
- self.to_value().normalize_to_expr_maybe_alpha(true)
+ pub(crate) fn to_expr(&self) -> NormalizedExpr {
+ self.0.to_expr(ToExprOptions {
+ alpha: false,
+ normalize: false,
+ })
}
- pub fn to_thunk(&self) -> Thunk {
- match self {
- Typed::Untyped(th) | Typed::Typed(th, _) => th.clone(),
- Typed::Const(c) => Thunk::from_value(Value::Const(*c)),
- }
+ pub fn normalize_to_expr(&self) -> NormalizedExpr {
+ self.0.to_expr(ToExprOptions {
+ alpha: false,
+ normalize: true,
+ })
}
- // Deprecated
- pub fn to_type(&self) -> Type {
- self.clone().into_type()
+ pub(crate) fn normalize_to_expr_alpha(&self) -> NormalizedExpr {
+ self.0.to_expr(ToExprOptions {
+ alpha: true,
+ normalize: true,
+ })
}
- // Deprecated
- pub fn into_type(self) -> Type {
- self
+ pub(crate) fn to_value(&self) -> Value {
+ self.0.clone()
}
- pub fn to_normalized(&self) -> Normalized {
- self.clone().normalize()
+ pub(crate) fn into_value(self) -> Value {
+ self.0
}
- pub fn as_const(&self) -> Option<Const> {
- // TODO: avoid clone
- match &self.to_value() {
- Value::Const(c) => Some(*c),
- _ => None,
- }
+
+ pub(crate) fn normalize_mut(&mut self) {
+ self.0.normalize_mut()
}
- pub fn normalize_mut(&mut self) {
- match self {
- Typed::Untyped(th) | Typed::Typed(th, _) => th.normalize_mut(),
- Typed::Const(_) => {}
- }
+ pub(crate) fn get_type(&self) -> Result<Typed, TypeError> {
+ Ok(self.0.get_type()?.into_typed())
}
- pub fn get_type(&self) -> Result<Cow<'_, Type>, TypeError> {
- match self {
- Typed::Untyped(_) => Err(TypeError::new(
- &TypecheckContext::new(),
- TypeMessage::Untyped,
- )),
- Typed::Typed(_, t) => Ok(Cow::Borrowed(t)),
- Typed::Const(c) => Ok(Cow::Owned(type_of_const(*c)?)),
- }
+ pub fn make_builtin_type(b: Builtin) -> Self {
+ Typed::from_value(Value::from_builtin(b))
+ }
+ pub fn make_optional_type(t: Typed) -> Self {
+ Typed::from_value(
+ Value::from_builtin(Builtin::Optional).app(t.to_value()),
+ )
+ }
+ pub fn make_list_type(t: Typed) -> Self {
+ Typed::from_value(Value::from_builtin(Builtin::List).app(t.to_value()))
+ }
+ pub fn make_record_type(
+ kts: impl Iterator<Item = (String, Typed)>,
+ ) -> Self {
+ Typed::from_valuef_and_type(
+ ValueF::RecordType(
+ kts.map(|(k, t)| (k.into(), t.into_value())).collect(),
+ ),
+ Typed::const_type(),
+ )
+ }
+ pub fn make_union_type(
+ kts: impl Iterator<Item = (String, Option<Typed>)>,
+ ) -> Self {
+ Typed::from_valuef_and_type(
+ ValueF::UnionType(
+ kts.map(|(k, t)| (k.into(), t.map(|t| t.into_value())))
+ .collect(),
+ ),
+ Typed::const_type(),
+ )
}
}
impl Normalized {
- #[allow(dead_code)]
- pub fn to_expr(&self) -> NormalizedSubExpr {
- self.0.to_expr()
- }
- #[allow(dead_code)]
- pub fn to_expr_alpha(&self) -> NormalizedSubExpr {
- self.0.to_expr_alpha()
+ pub fn encode(&self) -> Result<Vec<u8>, EncodeError> {
+ crate::phase::binary::encode(&self.to_expr())
}
- #[allow(dead_code)]
- pub fn to_type(&self) -> Type {
- self.0.to_type()
+
+ pub(crate) fn to_expr(&self) -> NormalizedExpr {
+ self.0.normalize_to_expr()
}
- pub fn to_value(&self) -> Value {
- self.0.to_value()
+ pub(crate) fn to_expr_alpha(&self) -> NormalizedExpr {
+ self.0.normalize_to_expr_alpha()
}
- pub fn into_typed(self) -> Typed {
+ pub(crate) fn into_typed(self) -> Typed {
self.0
}
}
impl Shift for Typed {
fn shift(&self, delta: isize, var: &AlphaVar) -> Option<Self> {
- Some(match self {
- Typed::Untyped(th) => Typed::Untyped(th.shift(delta, var)?),
- Typed::Typed(th, t) => Typed::Typed(
- th.shift(delta, var)?,
- Box::new(t.shift(delta, var)?),
- ),
- Typed::Const(c) => Typed::Const(*c),
- })
+ Some(Typed(self.0.shift(delta, var)?))
}
}
@@ -225,16 +198,9 @@ impl Shift for Normalized {
}
}
-impl Subst<Typed> for Typed {
- fn subst_shift(&self, var: &AlphaVar, val: &Typed) -> Self {
- match self {
- Typed::Untyped(th) => Typed::Untyped(th.subst_shift(var, val)),
- Typed::Typed(th, t) => Typed::Typed(
- th.subst_shift(var, val),
- Box::new(t.subst_shift(var, val)),
- ),
- Typed::Const(c) => Typed::Const(*c),
- }
+impl Subst<Value> for Typed {
+ fn subst_shift(&self, var: &AlphaVar, val: &Value) -> Self {
+ Typed(self.0.subst_shift(var, val))
}
}
@@ -263,10 +229,21 @@ derive_traits_for_wrapper_struct!(Parsed);
derive_traits_for_wrapper_struct!(Resolved);
derive_traits_for_wrapper_struct!(Normalized);
+impl std::hash::Hash for Normalized {
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: std::hash::Hasher,
+ {
+ if let Ok(vec) = self.encode() {
+ vec.hash(state)
+ }
+ }
+}
+
impl Eq for Typed {}
impl PartialEq for Typed {
fn eq(&self, other: &Self) -> bool {
- self.to_value() == other.to_value()
+ self.0 == other.0
}
}