1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
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!{ {
let x: Expr<_, _> = (*#v).clone();
x
} }
},
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) }
},
BinOp(ref o, ref a, ref b) => {
let o = binop_to_tokenstream(o);
let a = dhall_to_tokenstream_bx(a);
let b = dhall_to_tokenstream_bx(b);
quote!{ BinOp(#o, #a, #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) }
}
ListLit(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!{ ListLit(#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!{ {
let x: Box<Expr<_, _>> = #v.clone();
x
} }
},
e => bx(dhall_to_tokenstream(e)),
}
}
fn builtin_to_tokenstream(b: &Builtin) -> TokenStream {
format!("{:?}", b).parse().unwrap()
}
fn binop_to_tokenstream(b: &BinOp) -> TokenStream {
format!("{:?}", b).parse().unwrap()
}
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),* ] }
}
|