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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use crate::{
global_data, Accessor, CompleteFunction, CompleteImpl, Data, DataStructure, Enum, Execution,
Field, Generics, Ident, Program, Struct, StructStruct, Tracker, TupleStruct, Type, TypeNode,
UnitStruct, WipFunction, WipImpl,
};
use proc_macro2::TokenStream;
use syn::DeriveInput;
pub fn derive<TokenStream>(input: TokenStream, run: fn(Execution)) -> TokenStream
where
TokenStream: Into<proc_macro2::TokenStream> + From<proc_macro2::TokenStream>,
{
let input = input.into();
let output = derive2(input, run);
global_data::clear();
output.into()
}
fn derive2(input: TokenStream, run: fn(Execution)) -> TokenStream {
let input = syn::parse2(input).unwrap();
let ty = syn_to_type(input);
let tracker = Tracker::new();
run(Execution {
ty: &ty,
tracker: &tracker,
});
let program = tracker_to_program(tracker);
program.compile()
}
fn syn_to_type(input: DeriveInput) -> Type {
let attrs: Vec<_> = input
.attrs
.into_iter()
.map(std::convert::Into::into)
.collect();
let mut generics = Generics::syn_to_generics(input.generics);
let data = match input.data {
syn::Data::Struct(data) => match data.fields {
syn::Fields::Named(fields) => Data::Struct(Struct::Struct(StructStruct {
fields: fields
.named
.into_iter()
.map(|field| Field {
attrs: field.attrs,
accessor: Accessor::Name(Ident::from(field.ident.unwrap())),
element: Type::syn_to_type(field.ty, &mut generics.param_map),
})
.collect(),
attrs,
})),
syn::Fields::Unnamed(fields) => Data::Struct(Struct::Tuple(TupleStruct {
fields: fields
.unnamed
.into_iter()
.enumerate()
.map(|(i, field)| Field {
attrs: field.attrs,
accessor: Accessor::Index(i),
element: Type::syn_to_type(field.ty, &mut generics.param_map),
})
.collect(),
attrs,
})),
syn::Fields::Unit => Data::Struct(Struct::Unit(UnitStruct { attrs })),
},
syn::Data::Enum(data) => {
Data::Enum(Enum {
variants: Vec::new(),
attrs,
})
}
syn::Data::Union(_) => unimplemented!("union"),
};
Type(TypeNode::DataStructure(Box::new(DataStructure {
name: Ident::from(input.ident),
generics,
data,
})))
}
fn tracker_to_program(tracker: Tracker) -> Program {
Program {
crates: tracker.crates.into_inner(),
impls: tracker
.impls
.into_inner()
.into_iter()
.map(into_complete_impl)
.collect(),
}
}
fn into_complete_impl(imp: WipImpl) -> CompleteImpl {
if imp.has_generics() {
return imp.compute_trait_bounds();
}
CompleteImpl {
trait_ty: imp.trait_ty,
ty: imp.ty,
functions: imp
.functions
.into_inner()
.into_iter()
.map(|function| {
let function: WipFunction = function;
let values: Option<_> = function.values.into();
let invokes: Option<_> = function.invokes.into();
let macros: Option<_> = function.macros.into();
CompleteFunction {
self_ty: function.self_ty,
f: function.f,
values: values.unwrap(),
invokes: invokes.unwrap(),
macros: macros.unwrap(),
ret: function.ret,
}
})
.collect(),
result: None,
}
}