summaryrefslogtreecommitdiff
path: root/dhall_generator
diff options
context:
space:
mode:
authorNadrieril Feneanar2019-04-06 00:43:09 +0200
committerGitHub2019-04-06 00:43:09 +0200
commit5eccde86fc3ccdeb34c9f8bb44de33d25e77f30c (patch)
tree76d0f0fc848887d2945d586b58847575ca31d0da /dhall_generator
parentf78af6d1e7f6c1dc39bde6cf97138327004ddb06 (diff)
parent6a675a13fcfafa057c44db84c3b0ca3b344cfdab (diff)
Merge pull request #48 from Nadrieril/exprf
Move recursion out of Expr for enhanced genericity
Diffstat (limited to 'dhall_generator')
-rw-r--r--dhall_generator/src/dhall_expr.rs164
-rw-r--r--dhall_generator/src/dhall_type.rs50
2 files changed, 92 insertions, 122 deletions
diff --git a/dhall_generator/src/dhall_expr.rs b/dhall_generator/src/dhall_expr.rs
index 41e558b..9da23b6 100644
--- a/dhall_generator/src/dhall_expr.rs
+++ b/dhall_generator/src/dhall_expr.rs
@@ -4,113 +4,123 @@ 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();
let expr: SubExpr<X, Import> = parse_expr(&input_str).unwrap();
let no_import =
|_: &Import| -> X { panic!("Don't use import in dhall!()") };
- let expr = rc(expr.map_embed(&no_import));
- let output = dhall_to_tokenstream_bx(&expr, &Context::new());
+ let expr = rc(expr.as_ref().map_embed(&no_import));
+ let output = quote_subexpr(&expr, &Context::new());
output.into()
}
-// Returns an expression of type Expr<_, _>. Expects interpolated variables
-// to be of type Rc<Expr<_, _>>.
-fn dhall_to_tokenstream(
- expr: &DhallExpr,
- ctx: &Context<Label, ()>,
-) -> TokenStream {
- use dhall_core::Expr::*;
- match expr.as_ref() {
- Var(_) => {
- let v = dhall_to_tokenstream_bx(expr, ctx);
- quote! { *#v }
- }
+// Returns an expression of type ExprF<T, _, _>, where T is the
+// type of the subexpressions after interpolation.
+pub fn quote_expr<TS>(expr: ExprF<TS, Label, X, X>) -> TokenStream
+where
+ TS: quote::ToTokens + std::fmt::Debug,
+{
+ let quote_map = |m: BTreeMap<Label, TS>| -> TokenStream {
+ let entries = m.into_iter().map(|(k, v)| {
+ let k = quote_label(&k);
+ quote!(m.insert(#k, #v);)
+ });
+ quote! { {
+ use std::collections::BTreeMap;
+ let mut m = BTreeMap::new();
+ #( #entries )*
+ m
+ } }
+ };
+
+ let quote_vec = |e: Vec<TS>| -> TokenStream {
+ quote! { vec![ #(#e),* ] }
+ };
+
+ use dhall_core::ExprF::*;
+ match expr {
+ Var(_) => unreachable!(),
Pi(x, t, b) => {
- let t = dhall_to_tokenstream_bx(t, ctx);
- let b = dhall_to_tokenstream_bx(b, &ctx.insert(x.clone(), ()));
- let x = label_to_tokenstream(x);
- quote! { dhall_core::Expr::Pi(#x, #t, #b) }
+ let x = quote_label(&x);
+ quote! { dhall_core::ExprF::Pi(#x, #t, #b) }
}
Lam(x, t, b) => {
- let t = dhall_to_tokenstream_bx(t, ctx);
- let b = dhall_to_tokenstream_bx(b, &ctx.insert(x.clone(), ()));
- let x = label_to_tokenstream(x);
- quote! { dhall_core::Expr::Lam(#x, #t, #b) }
+ let x = quote_label(&x);
+ quote! { dhall_core::ExprF::Lam(#x, #t, #b) }
}
App(f, a) => {
- let f = dhall_to_tokenstream_bx(f, ctx);
- let a = vec_to_tokenstream(a, ctx);
- quote! { dhall_core::Expr::App(#f, #a) }
+ let a = quote_vec(a);
+ quote! { dhall_core::ExprF::App(#f, #a) }
}
Const(c) => {
- let c = const_to_tokenstream(*c);
- quote! { dhall_core::Expr::Const(#c) }
+ let c = quote_const(c);
+ quote! { dhall_core::ExprF::Const(#c) }
}
Builtin(b) => {
- let b = builtin_to_tokenstream(*b);
- quote! { dhall_core::Expr::Builtin(#b) }
+ let b = quote_builtin(b);
+ quote! { dhall_core::ExprF::Builtin(#b) }
}
BinOp(o, a, b) => {
- let o = binop_to_tokenstream(*o);
- let a = dhall_to_tokenstream_bx(a, ctx);
- let b = dhall_to_tokenstream_bx(b, ctx);
- quote! { dhall_core::Expr::BinOp(#o, #a, #b) }
+ let o = quote_binop(o);
+ quote! { dhall_core::ExprF::BinOp(#o, #a, #b) }
}
NaturalLit(n) => {
- quote! { dhall_core::Expr::NaturalLit(#n) }
+ quote! { dhall_core::ExprF::NaturalLit(#n) }
}
BoolLit(b) => {
- quote! { dhall_core::Expr::BoolLit(#b) }
+ quote! { dhall_core::ExprF::BoolLit(#b) }
}
EmptyOptionalLit(x) => {
- let x = dhall_to_tokenstream_bx(x, ctx);
- quote! { dhall_core::Expr::EmptyOptionalLit(#x) }
+ quote! { dhall_core::ExprF::EmptyOptionalLit(#x) }
}
NEOptionalLit(x) => {
- let x = dhall_to_tokenstream_bx(x, ctx);
- quote! { dhall_core::Expr::NEOptionalLit(#x) }
+ quote! { dhall_core::ExprF::NEOptionalLit(#x) }
}
EmptyListLit(t) => {
- let t = dhall_to_tokenstream_bx(t, ctx);
- quote! { dhall_core::Expr::EmptyListLit(#t) }
+ quote! { dhall_core::ExprF::EmptyListLit(#t) }
}
NEListLit(es) => {
- let es = vec_to_tokenstream(es, ctx);
- quote! { dhall_core::Expr::NEListLit(#es) }
+ let es = quote_vec(es);
+ quote! { dhall_core::ExprF::NEListLit(#es) }
}
RecordType(m) => {
- let m = map_to_tokenstream(m, ctx);
- quote! { dhall_core::Expr::RecordType(#m) }
+ let m = quote_map(m);
+ quote! { dhall_core::ExprF::RecordType(#m) }
}
RecordLit(m) => {
- let m = map_to_tokenstream(m, ctx);
- quote! { dhall_core::Expr::RecordLit(#m) }
+ let m = quote_map(m);
+ quote! { dhall_core::ExprF::RecordLit(#m) }
}
UnionType(m) => {
- let m = map_to_tokenstream(m, ctx);
- quote! { dhall_core::Expr::UnionType(#m) }
+ let m = quote_map(m);
+ quote! { dhall_core::ExprF::UnionType(#m) }
}
e => unimplemented!("{:?}", e),
}
}
-// Returns an expression of type Rc<Expr<_, _>>
-fn dhall_to_tokenstream_bx(
- expr: &DhallExpr,
+// Returns an expression of type SubExpr<_, _>. Expects interpolated variables
+// to be of type SubExpr<_, _>.
+fn quote_subexpr(
+ expr: &SubExpr<X, X>,
ctx: &Context<Label, ()>,
) -> TokenStream {
- use dhall_core::Expr::*;
- match expr.as_ref() {
- Var(V(s, n)) => {
- match ctx.lookup(&s, *n) {
+ use dhall_core::ExprF::*;
+ match expr.as_ref().map_ref(
+ |e| quote_subexpr(e, ctx),
+ |l, e| quote_subexpr(e, &ctx.insert(l.clone(), ())),
+ |_| unreachable!(),
+ |_| unreachable!(),
+ |l| l.clone(),
+ ) {
+ Var(V(ref s, n)) => {
+ match ctx.lookup(s, n) {
// Non-free variable; interpolates as itself
Some(()) => {
let s: String = s.into();
let var = quote! { dhall_core::V(#s.into(), #n) };
- bx(quote! { dhall_core::Expr::Var(#var) })
+ bx(quote! { dhall_core::ExprF::Var(#var) })
}
// Free variable; interpolates as a rust variable
None => {
@@ -124,51 +134,25 @@ fn dhall_to_tokenstream_bx(
}
}
}
- _ => bx(dhall_to_tokenstream(expr, ctx)),
+ e => bx(quote_expr(e)),
}
}
-fn builtin_to_tokenstream(b: Builtin) -> TokenStream {
+fn quote_builtin(b: Builtin) -> TokenStream {
format!("dhall_core::Builtin::{:?}", b).parse().unwrap()
}
-fn const_to_tokenstream(c: Const) -> TokenStream {
+fn quote_const(c: Const) -> TokenStream {
format!("dhall_core::Const::{:?}", c).parse().unwrap()
}
-fn binop_to_tokenstream(b: BinOp) -> TokenStream {
+fn quote_binop(b: BinOp) -> TokenStream {
format!("dhall_core::BinOp::{:?}", b).parse().unwrap()
}
-fn label_to_tokenstream(l: &Label) -> TokenStream {
+fn quote_label(l: &Label) -> TokenStream {
let l = String::from(l);
- quote! { #l.into() }
-}
-
-fn map_to_tokenstream(
- m: &BTreeMap<Label, Rc<Expr<X, X>>>,
- ctx: &Context<Label, ()>,
-) -> TokenStream {
- let (keys, values): (Vec<TokenStream>, Vec<TokenStream>) = m
- .iter()
- .map(|(k, v)| {
- (label_to_tokenstream(k), dhall_to_tokenstream_bx(&*v, ctx))
- })
- .unzip();
- quote! { {
- use std::collections::BTreeMap;
- let mut m = BTreeMap::new();
- #( m.insert(#keys, #values); )*
- m
- } }
-}
-
-fn vec_to_tokenstream(
- e: &Vec<DhallExpr>,
- ctx: &Context<Label, ()>,
-) -> TokenStream {
- let e = e.iter().map(|x| dhall_to_tokenstream_bx(x, ctx));
- quote! { vec![ #(#e),* ] }
+ quote! { dhall_core::Label::from(#l) }
}
fn bx(x: TokenStream) -> TokenStream {
diff --git a/dhall_generator/src/dhall_type.rs b/dhall_generator/src/dhall_type.rs
index ac8eb4e..ec023bc 100644
--- a/dhall_generator/src/dhall_type.rs
+++ b/dhall_generator/src/dhall_type.rs
@@ -39,21 +39,17 @@ pub fn derive_for_struct(
.collect(),
syn::Fields::Unit => vec![],
};
- let fields = fields.into_iter().map(|(name, ty)| {
- constraints.push(ty.clone());
- quote! {
- m.insert(
- dhall_core::Label::from(#name),
- <#ty as dhall::Type>::get_type()
- );
- }
- });
- Ok(quote! { dhall_core::rc(dhall_core::Expr::RecordType({
- use std::collections::BTreeMap;
- let mut m = BTreeMap::new();
- #(#fields)*
- m
- })) })
+ let fields = fields
+ .into_iter()
+ .map(|(name, ty)| {
+ let name = dhall_core::Label::from(name);
+ constraints.push(ty.clone());
+ (name, quote!(<#ty as dhall::Type>::get_type()))
+ })
+ .collect();
+ let record =
+ crate::dhall_expr::quote_expr(dhall_core::ExprF::RecordType(fields));
+ Ok(quote! { dhall_core::rc(#record) })
}
pub fn derive_for_enum(
@@ -64,7 +60,7 @@ pub fn derive_for_enum(
.variants
.iter()
.map(|v| {
- let name = v.ident.to_string();
+ let name = dhall_core::Label::from(v.ident.to_string());
let ty = match &v.fields {
syn::Fields::Unnamed(fields) if fields.unnamed.is_empty() => {
Err(Error::new(
@@ -92,21 +88,13 @@ pub fn derive_for_enum(
};
let ty = ty?;
constraints.push(ty.clone());
- Ok(quote! {
- m.insert(
- dhall_core::Label::from(#name),
- <#ty as dhall::Type>::get_type()
- );
- })
+ Ok((name, quote!(<#ty as dhall::Type>::get_type())))
})
- .collect::<Result<Vec<_>, Error>>()?;
+ .collect::<Result<_, Error>>()?;
- Ok(quote! { dhall_core::rc(dhall_core::Expr::UnionType({
- use std::collections::BTreeMap;
- let mut m = BTreeMap::new();
- #(#variants)*
- m
- })) })
+ let union =
+ crate::dhall_expr::quote_expr(dhall_core::ExprF::UnionType(variants));
+ Ok(quote! { dhall_core::rc(#union) })
}
pub fn derive_type_inner(
@@ -168,9 +156,7 @@ pub fn derive_type_inner(
// Ensure that all the fields have a Type impl
let mut where_clause = orig_where_clause.clone();
for ty in constraints.iter() {
- where_clause
- .predicates
- .push(parse_quote!(#ty: dhall::Type));
+ where_clause.predicates.push(parse_quote!(#ty: dhall::Type));
}
let ident = &input.ident;