summaryrefslogtreecommitdiff
path: root/dhall_generator
diff options
context:
space:
mode:
Diffstat (limited to 'dhall_generator')
-rw-r--r--dhall_generator/Cargo.toml15
-rw-r--r--dhall_generator/src/lib.rs87
2 files changed, 102 insertions, 0 deletions
diff --git a/dhall_generator/Cargo.toml b/dhall_generator/Cargo.toml
new file mode 100644
index 0000000..ada6707
--- /dev/null
+++ b/dhall_generator/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+name = "dhall_generator"
+version = "0.1.0"
+authors = ["Nadrieril <nadrieril@users.noreply.github.com>"]
+edition = "2018"
+
+[lib]
+proc-macro = true
+doctest = false
+
+[dependencies]
+itertools = "0.8.0"
+quote = "0.6.11"
+proc-macro2 = "0.4.27"
+dhall_core = { path = "../dhall_core" }
diff --git a/dhall_generator/src/lib.rs b/dhall_generator/src/lib.rs
new file mode 100644
index 0000000..85f9ce2
--- /dev/null
+++ b/dhall_generator/src/lib.rs
@@ -0,0 +1,87 @@
+extern crate proc_macro;
+use proc_macro2::TokenStream;
+use proc_macro2::Literal;
+use quote::quote;
+use dhall_core::*;
+
+#[proc_macro]
+pub fn dhall(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+ let input_str = input.to_string();
+ let expr = parser::parse_expr_pest(&input_str).unwrap();
+ let output = dhall_to_tokenstream(&expr);
+ output.into()
+}
+
+// Returns an expression of type Expr<_, _>. Expects input variables
+// to be of type Box<Expr<_, _>> (future-proof for structural sharing).
+fn dhall_to_tokenstream(expr: &Expr<X, X>) -> TokenStream {
+ use dhall_core::Expr::*;
+ match expr {
+ Var(V(s, _)) => {
+ let v: TokenStream = s.parse().unwrap();
+ quote!{ (*#v).clone() }
+ },
+ Lam(x, ref t, ref b) => {
+ let x = Literal::string(x);
+ let t = dhall_to_tokenstream_bx(t);
+ let b = dhall_to_tokenstream_bx(b);
+ quote!{ Lam(#x, #t, #b) }
+ }
+ App(ref f, ref a) => {
+ let f = dhall_to_tokenstream_bx(f);
+ let a = dhall_to_tokenstream_bx(a);
+ quote!{ App(#f, #a) }
+ }
+ Builtin(ref b) => {
+ let b = builtin_to_tokenstream(b);
+ quote!{ Builtin(#b) }
+ },
+ OptionalLit(ref t, ref es) => {
+ let t = option_tks(t.as_ref().map(deref).map(dhall_to_tokenstream_bx));
+ let es = vec_tks(es.into_iter().map(dhall_to_tokenstream));
+ quote!{ OptionalLit(#t, #es) }
+ }
+ e => unimplemented!("{:?}", e),
+ }
+}
+
+// Returns an expression of type Box<Expr<_, _>>
+fn dhall_to_tokenstream_bx(expr: &Expr<X, X>) -> TokenStream {
+ use dhall_core::Expr::*;
+ match expr {
+ Var(V(s, _)) => {
+ let v: TokenStream = s.parse().unwrap();
+ quote!{ #v.clone() }
+ },
+ e => bx(dhall_to_tokenstream(e)),
+ }
+}
+
+fn builtin_to_tokenstream(b: &Builtin) -> TokenStream {
+ use dhall_core::Builtin::*;
+ match b {
+ Optional => quote!{ Optional },
+ b => unimplemented!("{:?}", b),
+ }
+}
+
+fn deref<T>(x: &Box<T>) -> &T {
+ &*x
+}
+
+fn bx(x: TokenStream) -> TokenStream {
+ quote!{ bx(#x) }
+}
+
+fn option_tks(x: Option<TokenStream>) -> TokenStream {
+ match x {
+ Some(x) => quote!{ Some(#x) },
+ None => quote!{ None },
+ }
+}
+
+fn vec_tks<T>(x: T) -> TokenStream
+where T: Iterator<Item=TokenStream>
+{
+ quote!{ vec![ #(#x),* ] }
+}