diff options
Diffstat (limited to 'dhall_generator')
-rw-r--r-- | dhall_generator/Cargo.toml | 15 | ||||
-rw-r--r-- | dhall_generator/src/lib.rs | 87 |
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),* ] } +} |