diff options
-rw-r--r-- | dhall/src/binary.rs | 3 | ||||
-rw-r--r-- | dhall/src/main.rs | 3 | ||||
-rw-r--r-- | dhall/src/normalize.rs | 39 | ||||
-rw-r--r-- | dhall/src/typecheck.rs | 103 | ||||
-rw-r--r-- | dhall_core/src/core.rs | 45 | ||||
-rw-r--r-- | dhall_core/src/printer.rs | 6 | ||||
-rw-r--r-- | dhall_core/src/text.rs | 11 | ||||
-rw-r--r-- | dhall_generator/src/dhall_expr.rs | 7 |
8 files changed, 117 insertions, 100 deletions
diff --git a/dhall/src/binary.rs b/dhall/src/binary.rs index 235a55b..988891b 100644 --- a/dhall/src/binary.rs +++ b/dhall/src/binary.rs @@ -1,9 +1,8 @@ use dhall_core::*; use itertools::*; use serde_cbor::value::value as cbor; -use std::rc::Rc; -type ParsedExpr = Rc<Expr<X, Import>>; +type ParsedExpr = SubExpr<X, Import>; #[derive(Debug)] pub enum DecodeError { diff --git a/dhall/src/main.rs b/dhall/src/main.rs index 1a2e309..eb2206b 100644 --- a/dhall/src/main.rs +++ b/dhall/src/main.rs @@ -1,6 +1,5 @@ use std::error::Error; use std::io::{self, Read}; -use std::rc::Rc; use term_painter::ToStyle; use dhall::*; @@ -66,7 +65,7 @@ fn main() { } }; - let expr: Rc<Expr<_, _>> = rc(imports::panic_imports(&expr)); + let expr: SubExpr<_, _> = rc(imports::panic_imports(&expr)); let type_expr = match typecheck::type_of(expr.clone()) { Err(e) => { diff --git a/dhall/src/normalize.rs b/dhall/src/normalize.rs index a3a2318..5405e88 100644 --- a/dhall/src/normalize.rs +++ b/dhall/src/normalize.rs @@ -2,7 +2,6 @@ use dhall_core::*; use dhall_generator::dhall_expr; use std::fmt; -use std::rc::Rc; fn apply_builtin<S, A>( b: Builtin, @@ -44,13 +43,13 @@ where } // Normalize the important argument if let Some(i) = arg_to_eval { - args[i] = Rc::clone(&normalize_whnf(&args[i])); + args[i] = SubExpr::clone(&normalize_whnf(&args[i])); } let evaled_arg = arg_to_eval.map(|i| args[i].as_ref()); let ret = match (b, evaled_arg, args.as_slice()) { - (OptionalSome, _, [x, ..]) => rc(NEOptionalLit(Rc::clone(x))), - (OptionalNone, _, [t, ..]) => rc(EmptyOptionalLit(Rc::clone(t))), + (OptionalSome, _, [x, ..]) => rc(NEOptionalLit(SubExpr::clone(x))), + (OptionalNone, _, [t, ..]) => rc(EmptyOptionalLit(SubExpr::clone(t))), (NaturalIsZero, Some(NaturalLit(n)), _) => rc(BoolLit(*n == 0)), (NaturalEven, Some(NaturalLit(n)), _) => rc(BoolLit(*n % 2 == 0)), (NaturalOdd, Some(NaturalLit(n)), _) => rc(BoolLit(*n % 2 != 0)), @@ -76,7 +75,7 @@ where rc(NEListLit(ys)) } (ListIndexed, Some(EmptyListLit(t)), _) => { - let t = Rc::clone(t); + let t = SubExpr::clone(t); dhall_expr!([] : List ({ index : Natural, value : t })) } (ListIndexed, Some(NEListLit(xs)), _) => { @@ -101,7 +100,7 @@ where break rc(App(x.clone(), rest.to_vec())); } }; - let a0 = Rc::clone(a0); + let a0 = SubExpr::clone(a0); let a1 = shift(1, &V("a".into(), 0), &a0); // TODO: use Embed to avoid reevaluating g break dhall_expr!( @@ -122,7 +121,7 @@ where break rc(App(x.clone(), rest.to_vec())); } }; - let a0 = Rc::clone(a0); + let a0 = SubExpr::clone(a0); // TODO: use Embed to avoid reevaluating g break dhall_expr!( g @@ -133,13 +132,13 @@ where } } (ListFold, Some(EmptyListLit(_)), [_, _, _, _, nil, ..]) => { - Rc::clone(nil) + SubExpr::clone(nil) } (ListFold, Some(NEListLit(xs)), [_, _, _, cons, nil, ..]) => { - xs.iter().rev().fold(Rc::clone(nil), |acc, x| { + xs.iter().rev().fold(SubExpr::clone(nil), |acc, x| { let x = x.clone(); let acc = acc.clone(); - let cons = Rc::clone(cons); + let cons = SubExpr::clone(cons); dhall_expr!(cons x acc) }) } @@ -149,14 +148,14 @@ where // } (OptionalFold, Some(NEOptionalLit(x)), [_, _, _, just, _, ..]) => { let x = x.clone(); - let just = Rc::clone(just); + let just = SubExpr::clone(just); dhall_expr!(just x) } ( OptionalFold, Some(EmptyOptionalLit(_)), [_, _, _, _, nothing, ..], - ) => Rc::clone(nothing), + ) => SubExpr::clone(nothing), // // fold/build fusion // (OptionalFold, [_, App(box Builtin(OptionalBuild), [_, x, rest..]), rest..]) => { // normalize_whnf(&App(bx(x.clone()), rest.to_vec())) @@ -175,13 +174,15 @@ where break dhall_expr!(g Natural (λ(x : Natural) -> x + 1) 0); } } - (NaturalFold, Some(NaturalLit(0)), [_, _, _, zero]) => Rc::clone(zero), + (NaturalFold, Some(NaturalLit(0)), [_, _, _, zero]) => { + SubExpr::clone(zero) + } (NaturalFold, Some(NaturalLit(n)), [_, t, succ, zero]) => { let fold = rc(Builtin(NaturalFold)); let n = rc(NaturalLit(n - 1)); - let t = Rc::clone(t); - let succ = Rc::clone(succ); - let zero = Rc::clone(zero); + let t = SubExpr::clone(t); + let succ = SubExpr::clone(succ); + let zero = SubExpr::clone(zero); dhall_expr!(succ (fold n t succ zero)) } // (NaturalFold, Some(App(f2, args2)), _) => { @@ -273,7 +274,7 @@ where } (TextAppend, TextLit(x), TextLit(y)) => TextLit(x + y), (ListAppend, EmptyListLit(t), EmptyListLit(_)) => { - EmptyListLit(Rc::clone(t)) + EmptyListLit(SubExpr::clone(t)) } (ListAppend, EmptyListLit(_), _) => return y, (ListAppend, _, EmptyListLit(_)) => return x, @@ -326,7 +327,7 @@ where _ => rc(Projection(e, ls.clone())), } } - _ => Rc::clone(e), + _ => SubExpr::clone(e), } } @@ -344,5 +345,5 @@ where S: fmt::Debug, A: fmt::Debug, { - map_subexpr_rc(&normalize_whnf(&e), |x| normalize(Rc::clone(x))) + map_subexpr_rc(&normalize_whnf(&e), |x| normalize(SubExpr::clone(x))) } diff --git a/dhall/src/typecheck.rs b/dhall/src/typecheck.rs index f21721d..e769c7f 100644 --- a/dhall/src/typecheck.rs +++ b/dhall/src/typecheck.rs @@ -1,7 +1,6 @@ #![allow(non_snake_case)] use std::collections::HashSet; use std::fmt; -use std::rc::Rc; use crate::normalize::normalize; use dhall_core; @@ -113,7 +112,7 @@ where go::<S, T>(&mut ctx, eL0, eR0) } -fn type_of_builtin<S>(b: Builtin) -> Rc<Expr<S, X>> { +fn type_of_builtin<S>(b: Builtin) -> SubExpr<S, X> { use dhall_core::Builtin::*; match b { Bool | Natural | Integer | Double | Text => dhall_expr!(Type), @@ -184,16 +183,15 @@ fn type_of_builtin<S>(b: Builtin) -> Rc<Expr<S, X>> { /// is not necessary for just type-checking. If you actually care about the /// returned type then you may want to `normalize` it afterwards. pub fn type_with<S>( - ctx: &Context<Label, Rc<Expr<S, X>>>, - e: Rc<Expr<S, X>>, -) -> Result<Rc<Expr<S, X>>, TypeError<S>> + ctx: &Context<Label, SubExpr<S, X>>, + e: SubExpr<S, X>, +) -> Result<SubExpr<S, X>, TypeError<S>> where S: ::std::fmt::Debug, { use dhall_core::BinOp::*; use dhall_core::Builtin::*; use dhall_core::Const::*; - use dhall_core::Expr; use dhall_core::Expr::*; let mkerr = |msg: TypeMessage<_>| TypeError::new(ctx, e.clone(), msg); let ensure_const = |x: &SubExpr<_, _>, msg: TypeMessage<_>| match x.as_ref() @@ -266,7 +264,7 @@ where return Err(mkerr(NotAFunction(f.clone(), tf))); } }; - let tA = normalize(Rc::clone(tA)); + let tA = normalize(SubExpr::clone(tA)); let tA2 = normalized_type_with(ctx, a.clone())?; if prop_equal(tA.as_ref(), tA2.as_ref()) { let vx0 = &V(x.clone(), 0); @@ -280,9 +278,9 @@ where } Let(f, mt, r, b) => { let r = if let Some(t) = mt { - rc(Annot(Rc::clone(r), Rc::clone(t))) + rc(Annot(SubExpr::clone(r), SubExpr::clone(t))) } else { - Rc::clone(r) + SubExpr::clone(r) }; let tR = type_with(ctx, r)?; @@ -351,7 +349,7 @@ where EmptyListLit(t) => { let s = normalized_type_with(ctx, t.clone())?; ensure_is_type(s, InvalidListType(t.clone()))?; - let t = normalize(Rc::clone(t)); + let t = normalize(SubExpr::clone(t)); return Ok(dhall_expr!(List t)); } NEListLit(xs) => { @@ -377,7 +375,7 @@ where return Ok(dhall_expr!(Optional t)); } NEOptionalLit(x) => { - let t: Rc<Expr<_, _>> = type_with(ctx, x.clone())?; + let t: SubExpr<_, _> = type_with(ctx, x.clone())?; let s = normalized_type_with(ctx, t.clone())?; ensure_is_type(s, InvalidOptionalType(t.clone()))?; let t = normalize(t); @@ -451,9 +449,9 @@ where } pub fn normalized_type_with<S>( - ctx: &Context<Label, Rc<Expr<S, X>>>, - e: Rc<Expr<S, X>>, -) -> Result<Rc<Expr<S, X>>, TypeError<S>> + ctx: &Context<Label, SubExpr<S, X>>, + e: SubExpr<S, X>, +) -> Result<SubExpr<S, X>, TypeError<S>> where S: ::std::fmt::Debug, { @@ -464,8 +462,8 @@ where /// expression must be closed (i.e. no free variables), otherwise type-checking /// will fail. pub fn type_of<S: ::std::fmt::Debug>( - e: Rc<Expr<S, X>>, -) -> Result<Rc<Expr<S, X>>, TypeError<S>> { + e: SubExpr<S, X>, +) -> Result<SubExpr<S, X>, TypeError<S>> { let ctx = Context::new(); type_with(&ctx, e) //.map(|e| e.into_owned()) } @@ -474,63 +472,58 @@ pub fn type_of<S: ::std::fmt::Debug>( #[derive(Debug)] pub enum TypeMessage<S> { UnboundVariable, - InvalidInputType(Rc<Expr<S, X>>), - InvalidOutputType(Rc<Expr<S, X>>), - NotAFunction(Rc<Expr<S, X>>, Rc<Expr<S, X>>), - TypeMismatch( - Rc<Expr<S, X>>, - Rc<Expr<S, X>>, - Rc<Expr<S, X>>, - Rc<Expr<S, X>>, - ), - AnnotMismatch(Rc<Expr<S, X>>, Rc<Expr<S, X>>, Rc<Expr<S, X>>), + InvalidInputType(SubExpr<S, X>), + InvalidOutputType(SubExpr<S, X>), + NotAFunction(SubExpr<S, X>, SubExpr<S, X>), + TypeMismatch(SubExpr<S, X>, SubExpr<S, X>, SubExpr<S, X>, SubExpr<S, X>), + AnnotMismatch(SubExpr<S, X>, SubExpr<S, X>, SubExpr<S, X>), Untyped, - InvalidListElement(usize, Rc<Expr<S, X>>, Rc<Expr<S, X>>, Rc<Expr<S, X>>), - InvalidListType(Rc<Expr<S, X>>), - InvalidOptionalElement(Rc<Expr<S, X>>, Rc<Expr<S, X>>, Rc<Expr<S, X>>), + InvalidListElement(usize, SubExpr<S, X>, SubExpr<S, X>, SubExpr<S, X>), + InvalidListType(SubExpr<S, X>), + InvalidOptionalElement(SubExpr<S, X>, SubExpr<S, X>, SubExpr<S, X>), InvalidOptionalLiteral(usize), - InvalidOptionalType(Rc<Expr<S, X>>), - InvalidPredicate(Rc<Expr<S, X>>, Rc<Expr<S, X>>), + InvalidOptionalType(SubExpr<S, X>), + InvalidPredicate(SubExpr<S, X>, SubExpr<S, X>), IfBranchMismatch( - Rc<Expr<S, X>>, - Rc<Expr<S, X>>, - Rc<Expr<S, X>>, - Rc<Expr<S, X>>, + SubExpr<S, X>, + SubExpr<S, X>, + SubExpr<S, X>, + SubExpr<S, X>, ), - IfBranchMustBeTerm(bool, Rc<Expr<S, X>>, Rc<Expr<S, X>>, Rc<Expr<S, X>>), - InvalidField(Label, Rc<Expr<S, X>>), - InvalidFieldType(Label, Rc<Expr<S, X>>), - InvalidAlternative(Label, Rc<Expr<S, X>>), - InvalidAlternativeType(Label, Rc<Expr<S, X>>), + IfBranchMustBeTerm(bool, SubExpr<S, X>, SubExpr<S, X>, SubExpr<S, X>), + InvalidField(Label, SubExpr<S, X>), + InvalidFieldType(Label, SubExpr<S, X>), + InvalidAlternative(Label, SubExpr<S, X>), + InvalidAlternativeType(Label, SubExpr<S, X>), DuplicateAlternative(Label), - MustCombineARecord(Rc<Expr<S, X>>, Rc<Expr<S, X>>), + MustCombineARecord(SubExpr<S, X>, SubExpr<S, X>), FieldCollision(Label), - MustMergeARecord(Rc<Expr<S, X>>, Rc<Expr<S, X>>), - MustMergeUnion(Rc<Expr<S, X>>, Rc<Expr<S, X>>), + MustMergeARecord(SubExpr<S, X>, SubExpr<S, X>), + MustMergeUnion(SubExpr<S, X>, SubExpr<S, X>), UnusedHandler(HashSet<Label>), MissingHandler(HashSet<Label>), - HandlerInputTypeMismatch(Label, Rc<Expr<S, X>>, Rc<Expr<S, X>>), - HandlerOutputTypeMismatch(Label, Rc<Expr<S, X>>, Rc<Expr<S, X>>), - HandlerNotAFunction(Label, Rc<Expr<S, X>>), - NotARecord(Label, Rc<Expr<S, X>>, Rc<Expr<S, X>>), - MissingField(Label, Rc<Expr<S, X>>), - BinOpTypeMismatch(BinOp, Rc<Expr<S, X>>, Rc<Expr<S, X>>), - NoDependentLet(Rc<Expr<S, X>>, Rc<Expr<S, X>>), - NoDependentTypes(Rc<Expr<S, X>>, Rc<Expr<S, X>>), + HandlerInputTypeMismatch(Label, SubExpr<S, X>, SubExpr<S, X>), + HandlerOutputTypeMismatch(Label, SubExpr<S, X>, SubExpr<S, X>), + HandlerNotAFunction(Label, SubExpr<S, X>), + NotARecord(Label, SubExpr<S, X>, SubExpr<S, X>), + MissingField(Label, SubExpr<S, X>), + BinOpTypeMismatch(BinOp, SubExpr<S, X>, SubExpr<S, X>), + NoDependentLet(SubExpr<S, X>, SubExpr<S, X>), + NoDependentTypes(SubExpr<S, X>, SubExpr<S, X>), } /// A structured type error that includes context #[derive(Debug)] pub struct TypeError<S> { - pub context: Context<Label, Rc<Expr<S, X>>>, - pub current: Rc<Expr<S, X>>, + pub context: Context<Label, SubExpr<S, X>>, + pub current: SubExpr<S, X>, pub type_message: TypeMessage<S>, } impl<S> TypeError<S> { pub fn new( - context: &Context<Label, Rc<Expr<S, X>>>, - current: Rc<Expr<S, X>>, + context: &Context<Label, SubExpr<S, X>>, + current: SubExpr<S, X>, type_message: TypeMessage<S>, ) -> Self { TypeError { diff --git a/dhall_core/src/core.rs b/dhall_core/src/core.rs index 0ea8c83..b49515a 100644 --- a/dhall_core/src/core.rs +++ b/dhall_core/src/core.rs @@ -170,7 +170,8 @@ pub type ParsedExpr = SubExpr<X, Import>; pub type ResolvedExpr = SubExpr<X, X>; pub type DhallExpr = ResolvedExpr; -pub type SubExpr<Note, Embed> = Rc<Expr<Note, Embed>>; +#[derive(Debug, PartialEq, Eq)] +pub struct SubExpr<Note, Embed>(pub Rc<Expr<Note, Embed>>); /// Syntax tree for expressions #[derive(Debug, Clone, PartialEq, Eq)] @@ -315,13 +316,33 @@ impl<S: Clone, A: Clone> Expr<S, Expr<S, A>> { } } +impl<N, E> Clone for SubExpr<N, E> { + fn clone(&self) -> Self { + SubExpr(Rc::clone(&self.0)) + } +} + +impl<N, E> std::ops::Deref for SubExpr<N, E> { + type Target = Rc<Expr<N, E>>; + #[inline(always)] + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +// impl<N, E> SubExpr<N, E> { +// pub fn as_ref(&self) -> &Expr<N, E> { +// self.0.as_ref() +// } +// } + // Remains of a previous life, where everything was in Boxes -pub fn bx<T>(x: T) -> Rc<T> { - Rc::new(x) +pub fn bx<N, E>(x: Expr<N, E>) -> SubExpr<N, E> { + SubExpr(Rc::new(x)) } -pub fn rc<T>(x: T) -> Rc<T> { - Rc::new(x) +pub fn rc<N, E>(x: Expr<N, E>) -> SubExpr<N, E> { + SubExpr(Rc::new(x)) } fn add_ui(u: usize, i: isize) -> usize { @@ -401,7 +422,7 @@ where F2: FnOnce(&Label, &SubExpr<S, A>) -> SubExpr<S, A>, { match e.as_ref() { - Expr::Embed(_) => Rc::clone(e), + Expr::Embed(_) => SubExpr::clone(e), Expr::Note(_, e) => { map_subexpr_rc_binder(e, map_expr, map_under_binder) } @@ -500,8 +521,8 @@ where pub fn shift<S, A>( delta: isize, var: &V, - in_expr: &Rc<Expr<S, A>>, -) -> Rc<Expr<S, A>> { + in_expr: &SubExpr<S, A>, +) -> SubExpr<S, A> { use crate::Expr::*; let V(x, n) = var; let under_binder = |y: &Label, e: &SubExpr<_, _>| { @@ -529,9 +550,9 @@ pub fn shift<S, A>( /// pub fn subst<S, A>( var: &V, - value: &Rc<Expr<S, A>>, - in_expr: &Rc<Expr<S, A>>, -) -> Rc<Expr<S, A>> { + value: &SubExpr<S, A>, + in_expr: &SubExpr<S, A>, +) -> SubExpr<S, A> { use crate::Expr::*; let under_binder = |y: &Label, e: &SubExpr<_, _>| { let V(x, n) = var; @@ -540,7 +561,7 @@ pub fn subst<S, A>( subst(newvar, &shift(1, &V(y.clone(), 0), value), e) }; match in_expr.as_ref() { - Var(v) if var == v => Rc::clone(value), + Var(v) if var == v => SubExpr::clone(value), _ => map_subexpr_rc_binder( in_expr, |e| subst(var, value, e), diff --git a/dhall_core/src/printer.rs b/dhall_core/src/printer.rs index 1d1b063..b153d1b 100644 --- a/dhall_core/src/printer.rs +++ b/dhall_core/src/printer.rs @@ -8,6 +8,12 @@ impl<S, A: Display> Display for Expr<S, A> { } } +impl<S, A: Display> Display for SubExpr<S, A> { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + self.as_ref().fmt(f) + } +} + // There is a one-to-one correspondence between the formatter and the grammar. Each phase is // named after a corresponding grammar group, and the structure of the formatter reflects // the relationship between the corresponding grammar rules. This leads to the nice property diff --git a/dhall_core/src/text.rs b/dhall_core/src/text.rs index d377877..eef0797 100644 --- a/dhall_core/src/text.rs +++ b/dhall_core/src/text.rs @@ -1,18 +1,17 @@ use crate::*; use std::iter::FromIterator; use std::ops::Add; -use std::rc::Rc; #[derive(Debug, Clone, PartialEq, Eq)] pub struct InterpolatedText<Note, Embed> { head: String, - tail: Vec<(Rc<Expr<Note, Embed>>, String)>, + tail: Vec<(SubExpr<Note, Embed>, String)>, } -impl<N, E> From<(String, Vec<(Rc<Expr<N, E>>, String)>)> +impl<N, E> From<(String, Vec<(SubExpr<N, E>, String)>)> for InterpolatedText<N, E> { - fn from(x: (String, Vec<(Rc<Expr<N, E>>, String)>)) -> Self { + fn from(x: (String, Vec<(SubExpr<N, E>, String)>)) -> Self { InterpolatedText { head: x.0, tail: x.1, @@ -38,7 +37,7 @@ pub enum InterpolatedTextContents<Note, Embed> { impl<N, E> InterpolatedText<N, E> { pub fn map<N2, E2, F>(&self, mut f: F) -> InterpolatedText<N2, E2> where - F: FnMut(&Rc<Expr<N, E>>) -> Rc<Expr<N2, E2>>, + F: FnMut(&SubExpr<N, E>) -> SubExpr<N2, E2>, { InterpolatedText { head: self.head.clone(), @@ -52,7 +51,7 @@ impl<N, E> InterpolatedText<N, E> { use std::iter::once; once(InterpolatedTextContents::Text(self.head.clone())).chain( self.tail.iter().flat_map(|(e, s)| { - once(InterpolatedTextContents::Expr(Rc::clone(e))) + once(InterpolatedTextContents::Expr(SubExpr::clone(e))) .chain(once(InterpolatedTextContents::Text(s.clone()))) }), ) diff --git a/dhall_generator/src/dhall_expr.rs b/dhall_generator/src/dhall_expr.rs index 41e558b..e2187d6 100644 --- a/dhall_generator/src/dhall_expr.rs +++ b/dhall_generator/src/dhall_expr.rs @@ -4,7 +4,6 @@ use dhall_core::*; use proc_macro2::TokenStream; use quote::quote; use std::collections::BTreeMap; -use std::rc::Rc; pub fn dhall_expr(input: proc_macro::TokenStream) -> proc_macro::TokenStream { let input_str = input.to_string(); @@ -17,7 +16,7 @@ pub fn dhall_expr(input: proc_macro::TokenStream) -> proc_macro::TokenStream { } // Returns an expression of type Expr<_, _>. Expects interpolated variables -// to be of type Rc<Expr<_, _>>. +// to be of type SubExpr<_, _>. fn dhall_to_tokenstream( expr: &DhallExpr, ctx: &Context<Label, ()>, @@ -97,7 +96,7 @@ fn dhall_to_tokenstream( } } -// Returns an expression of type Rc<Expr<_, _>> +// Returns an expression of type SubExpr<_, _> fn dhall_to_tokenstream_bx( expr: &DhallExpr, ctx: &Context<Label, ()>, @@ -146,7 +145,7 @@ fn label_to_tokenstream(l: &Label) -> TokenStream { } fn map_to_tokenstream( - m: &BTreeMap<Label, Rc<Expr<X, X>>>, + m: &BTreeMap<Label, SubExpr<X, X>>, ctx: &Context<Label, ()>, ) -> TokenStream { let (keys, values): (Vec<TokenStream>, Vec<TokenStream>) = m |