summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNadrieril2019-03-26 22:35:46 +0100
committerNadrieril2019-03-26 22:35:46 +0100
commit23e12ffc4421414abbd089759dab9c50aefeac0c (patch)
treeda1cfb1f2744fd85f1f3f6b25858db99311a315f
parentfd293b7919d84faa2ac0df05ddd25c0386dc4c67 (diff)
Derive DhallType for structs
Diffstat (limited to '')
-rw-r--r--Cargo.lock9
-rw-r--r--dhall/src/dhall_type.rs77
-rw-r--r--dhall/src/lib.rs2
-rw-r--r--dhall/tests/dhall_type.rs37
-rw-r--r--dhall_core/src/dhall_type.rs10
-rw-r--r--dhall_core/src/lib.rs2
-rw-r--r--dhall_generator/Cargo.toml1
-rw-r--r--dhall_generator/src/dhall_expr.rs4
-rw-r--r--dhall_generator/src/dhall_type.rs86
9 files changed, 194 insertions, 34 deletions
diff --git a/Cargo.lock b/Cargo.lock
index cfbe901..e00159c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -60,7 +60,7 @@ version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -97,6 +97,7 @@ dependencies = [
"itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -223,7 +224,7 @@ dependencies = [
"pest_meta 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -307,7 +308,7 @@ dependencies = [
[[package]]
name = "syn"
-version = "0.15.27"
+version = "0.15.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -438,7 +439,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "92514fb95f900c9b5126e32d020f5c6d40564c27a5ea6d1d7d9f157a96623560"
"checksum serde_cbor 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "45cd6d95391b16cd57e88b68be41d504183b7faae22030c0cc3b3f73dd57b2fd"
"checksum sha-1 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9d1f3b5de8a167ab06834a7c883bd197f2191e1dda1a22d9ccfeedbf9aded"
-"checksum syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)" = "525bd55255f03c816e5d7f615587bd13030c7103354fadb104993dcee6a788ec"
+"checksum syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1825685f977249735d510a242a6727b46efe914bb67e38d30c071b1b72b1d5c2"
"checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
"checksum term-painter 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "dcaa948f0e3e38470cd8dc8dcfe561a75c9e43f28075bb183845be2b9b3c08cf"
"checksum typed-arena 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c6c06a92aef38bb4dc5b0df00d68496fc31307c5344c867bb61678c6e1671ec5"
diff --git a/dhall/src/dhall_type.rs b/dhall/src/dhall_type.rs
new file mode 100644
index 0000000..8abef32
--- /dev/null
+++ b/dhall/src/dhall_type.rs
@@ -0,0 +1,77 @@
+use dhall_core::*;
+use dhall_generator::*;
+
+#[derive(Debug, Clone)]
+pub enum DhallConversionError {}
+
+pub trait DhallType: Sized {
+ fn dhall_type() -> DhallExpr;
+ // fn as_dhall(&self) -> DhallExpr;
+ // fn from_dhall(e: DhallExpr) -> Result<Self, DhallConversionError>;
+}
+
+impl DhallType for bool {
+ fn dhall_type() -> DhallExpr {
+ dhall_expr!(Bool)
+ }
+}
+
+impl DhallType for Natural {
+ fn dhall_type() -> DhallExpr {
+ dhall_expr!(Natural)
+ }
+}
+
+impl DhallType for Integer {
+ fn dhall_type() -> DhallExpr {
+ dhall_expr!(Integer)
+ }
+}
+
+impl DhallType for String {
+ fn dhall_type() -> DhallExpr {
+ dhall_expr!(Text)
+ }
+}
+
+impl<A: DhallType, B: DhallType> DhallType for (A, B) {
+ fn dhall_type() -> DhallExpr {
+ let ta = A::dhall_type();
+ let tb = B::dhall_type();
+ dhall_expr!({ _1: ta, _2: tb })
+ }
+}
+
+impl<T: DhallType> DhallType for Option<T> {
+ fn dhall_type() -> DhallExpr {
+ let t = T::dhall_type();
+ dhall_expr!(Optional t)
+ }
+}
+
+impl<T: DhallType> DhallType for Vec<T> {
+ fn dhall_type() -> DhallExpr {
+ let t = T::dhall_type();
+ dhall_expr!(List t)
+ }
+}
+
+impl<'a, T: DhallType> DhallType for &'a T {
+ fn dhall_type() -> DhallExpr {
+ T::dhall_type()
+ }
+}
+
+impl<T> DhallType for std::marker::PhantomData<T> {
+ fn dhall_type() -> DhallExpr {
+ dhall_expr!({})
+ }
+}
+
+impl<T: DhallType, E: DhallType> DhallType for Result<T, E> {
+ fn dhall_type() -> DhallExpr {
+ let tt = T::dhall_type();
+ let te = E::dhall_type();
+ dhall_expr!(< Ok: tt | Err: te>)
+ }
+}
diff --git a/dhall/src/lib.rs b/dhall/src/lib.rs
index d9f9edb..c0c1d6f 100644
--- a/dhall/src/lib.rs
+++ b/dhall/src/lib.rs
@@ -10,8 +10,10 @@
mod normalize;
pub use crate::normalize::*;
pub mod binary;
+mod dhall_type;
pub mod imports;
pub mod typecheck;
+pub use dhall_type::*;
pub use crate::imports::*;
diff --git a/dhall/tests/dhall_type.rs b/dhall/tests/dhall_type.rs
index cbb71a4..0e27ad0 100644
--- a/dhall/tests/dhall_type.rs
+++ b/dhall/tests/dhall_type.rs
@@ -1,15 +1,32 @@
#![feature(proc_macro_hygiene)]
-use dhall_core::*;
+use dhall::*;
use dhall_generator::*;
-#[derive(DhallType)]
-struct A {
- _field1: bool,
- // field2: Option<bool>,
-}
-
#[test]
-fn test_dhall_type_a() {
- assert_eq!(A::dhall_type(), dhall_expr!(False));
- // assert_eq!(A::dhall_type(), dhall_expr!({ field1: Bool }));
+fn test_dhall_type() {
+ assert_eq!(bool::dhall_type(), dhall_expr!(Bool));
+ assert_eq!(String::dhall_type(), dhall_expr!(Text));
+ assert_eq!(
+ <(bool, Option<String>)>::dhall_type(),
+ dhall_expr!({ _1: Bool, _2: Optional Text })
+ );
+
+ #[derive(DhallType)]
+ #[allow(dead_code)]
+ struct A {
+ field1: bool,
+ field2: Option<bool>,
+ }
+ assert_eq!(
+ A::dhall_type(),
+ dhall_expr!({ field1: Bool, field2: Optional Bool })
+ );
+
+ #[derive(DhallType)]
+ #[allow(dead_code)]
+ struct B<'a, T: 'a> {
+ field1: &'a T,
+ field2: Option<T>,
+ }
+ assert_eq!(<B<'static, bool>>::dhall_type(), A::dhall_type());
}
diff --git a/dhall_core/src/dhall_type.rs b/dhall_core/src/dhall_type.rs
deleted file mode 100644
index 3635e67..0000000
--- a/dhall_core/src/dhall_type.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-use crate::*;
-
-#[derive(Debug, Clone)]
-pub enum DhallConversionError {}
-
-pub trait DhallType: Sized {
- fn dhall_type() -> DhallExpr;
- // fn as_dhall(&self) -> DhallExpr;
- // fn from_dhall(e: DhallExpr) -> Result<Self, DhallConversionError>;
-}
diff --git a/dhall_core/src/lib.rs b/dhall_core/src/lib.rs
index b15c644..0874b09 100644
--- a/dhall_core/src/lib.rs
+++ b/dhall_core/src/lib.rs
@@ -18,6 +18,4 @@ mod printer;
pub use crate::printer::*;
mod parser;
pub use crate::parser::*;
-mod dhall_type;
-pub use dhall_type::*;
pub mod context;
diff --git a/dhall_generator/Cargo.toml b/dhall_generator/Cargo.toml
index ada6707..2a6ca67 100644
--- a/dhall_generator/Cargo.toml
+++ b/dhall_generator/Cargo.toml
@@ -12,4 +12,5 @@ doctest = false
itertools = "0.8.0"
quote = "0.6.11"
proc-macro2 = "0.4.27"
+syn = "0.15.29"
dhall_core = { path = "../dhall_core" }
diff --git a/dhall_generator/src/dhall_expr.rs b/dhall_generator/src/dhall_expr.rs
index 1ee4d1a..bc9da22 100644
--- a/dhall_generator/src/dhall_expr.rs
+++ b/dhall_generator/src/dhall_expr.rs
@@ -89,6 +89,10 @@ fn dhall_to_tokenstream(
let m = map_to_tokenstream(m, ctx);
quote! { dhall_core::Expr::RecordLit(#m) }
}
+ UnionType(m) => {
+ let m = map_to_tokenstream(m, ctx);
+ quote! { dhall_core::Expr::UnionType(#m) }
+ }
e => unimplemented!("{:?}", e),
}
}
diff --git a/dhall_generator/src/dhall_type.rs b/dhall_generator/src/dhall_type.rs
index 7cfd945..b305ca0 100644
--- a/dhall_generator/src/dhall_type.rs
+++ b/dhall_generator/src/dhall_type.rs
@@ -1,15 +1,85 @@
extern crate proc_macro;
// use dhall_core::*;
-// use proc_macro2::TokenStream;
-use quote::quote;
+use proc_macro::TokenStream;
+use quote::{quote, quote_spanned};
+use syn::spanned::Spanned;
+use syn::{parse_macro_input, parse_quote, DeriveInput};
-pub fn derive_dhall_type(_input: proc_macro::TokenStream) -> proc_macro::TokenStream {
- (quote!{
- impl DhallType for A {
+pub fn derive_dhall_type(input: TokenStream) -> TokenStream {
+ let input = parse_macro_input!(input as DeriveInput);
+
+ // List of types that must impl DhallType
+ let mut constraints = vec![];
+
+ let dhall_type = match &input.data {
+ syn::Data::Struct(data) => match &data.fields {
+ syn::Fields::Named(fields) => {
+ let fields = fields.named.iter()
+ .map(|f| {
+ let name = f.ident.as_ref().unwrap().to_string();
+ let ty = &f.ty;
+ constraints.push(ty.clone());
+ quote!( m.insert(dhall_core::Label::from(#name), <#ty as dhall::DhallType>::dhall_type()); )
+ });
+ quote! { dhall_core::rc(dhall_core::Expr::RecordType({
+ use std::collections::BTreeMap;
+ let mut m = BTreeMap::new();
+ #(#fields)*
+ m
+ })) }
+ }
+ _ => quote!(dhall_generator::dhall_expr!(Bool)),
+ },
+ _ => quote!(dhall_generator::dhall_expr!(Bool)),
+ };
+
+ let mut generics = input.generics.clone();
+ generics.make_where_clause();
+ let (impl_generics, ty_generics, orig_where_clause) =
+ generics.split_for_impl();
+ let orig_where_clause = orig_where_clause.unwrap();
+
+ // Hygienic errors
+ let assertions = constraints.iter().enumerate().map(|(i, ty)| {
+ // Ensure that ty: DhallType, with an appropriate span
+ let assert_name =
+ syn::Ident::new(&format!("_AssertDhallType{}", i), ty.span());
+ let mut local_where_clause = orig_where_clause.clone();
+ local_where_clause
+ .predicates
+ .push(parse_quote!(#ty: dhall::DhallType));
+ let phantoms = generics.params.iter().map(|param| match param {
+ syn::GenericParam::Type(syn::TypeParam { ident, .. }) => {
+ quote!(#ident)
+ }
+ syn::GenericParam::Lifetime(syn::LifetimeDef {
+ lifetime, ..
+ }) => quote!(&#lifetime ()),
+ _ => unimplemented!(),
+ });
+ quote_spanned! {ty.span()=>
+ struct #assert_name #impl_generics #local_where_clause {
+ _phantom: std::marker::PhantomData<(#(#phantoms),*)>
+ };
+ }
+ });
+
+ // Ensure that all the fields have a DhallType impl
+ let mut where_clause = orig_where_clause.clone();
+ for ty in constraints.iter() {
+ where_clause
+ .predicates
+ .push(parse_quote!(#ty: dhall::DhallType));
+ }
+
+ let ident = &input.ident;
+ let tokens = quote! {
+ impl #impl_generics dhall::DhallType for #ident #ty_generics #where_clause {
fn dhall_type() -> dhall_core::DhallExpr {
- dhall_core::rc(dhall_core::Expr::BoolLit(false))
+ #(#assertions)*
+ #dhall_type
}
}
- }).into()
+ };
+ TokenStream::from(tokens)
}
-