purescript_waterslide_derive/
lib.rs

1#![deny(warnings)]
2
3extern crate syn;
4extern crate proc_macro;
5extern crate proc_macro2;
6#[macro_use]
7extern crate quote;
8
9extern crate purescript_waterslide;
10
11mod purescript;
12mod generics;
13
14use quote::Tokens;
15use purescript::{make_purs_constructor_impl, make_purs_type};
16
17#[proc_macro_derive(AsPursType)]
18pub fn derive_purstype(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
19    let input = input.to_string();
20    let ast =
21        syn::parse_derive_input(&input).expect("Purescript waterslide could not parse input type");
22
23    let name = &ast.ident;
24    let generics = generics::shift_generics(&ast);
25    let placeholder_generics: Vec<Tokens> = ast.generics
26        .ty_params
27        .iter()
28        .map(generics::make_dummy_generic)
29        .collect();
30    let placeholder_generics_clone = placeholder_generics.clone();
31
32    let as_purs_constructor_impl = match make_purs_constructor_impl(&ast) {
33        Ok(generated_impl) => generated_impl,
34        Err(err) => panic!(
35            "Could not convert the input to Purescript type constructor: {:?}",
36            err
37        ),
38    };
39
40    let as_purs_impl = match make_purs_type(&ast) {
41        Ok(generated_impl) => generated_impl,
42        Err(err) => panic!("Could not convert the input to Purescript AST: {:?}", err),
43    };
44
45    let expanded = quote! {
46        impl#generics ::purescript_waterslide::AsPursConstructor for #name#generics {
47            fn as_purs_constructor() -> ::purescript_waterslide::PursConstructor {
48                #( #placeholder_generics )*
49
50                #as_purs_constructor_impl
51            }
52        }
53
54        impl#generics ::purescript_waterslide::AsPursType for #name#generics {
55            fn as_purs_type() -> ::purescript_waterslide::PursType {
56                #( #placeholder_generics_clone )*
57
58                #as_purs_impl
59            }
60        }
61    };
62
63    expanded.parse().unwrap()
64}