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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
//! Various macros for integrating with the `gluon` vm.
//!
//! ## Derive Macros
//!
//! Custom derives for the following `gluon`-Traits are available:
//!
//! ### Getable
//!   
//! Derives `Getable` for any enum or struct as long as all fields also implement
//! `Getable` (generic type parameters included). If the type is generic over a
//! lifetime, the lifetime will be constrained to that of the `'vm` lifetime in the
//! trait definition.
//!
//! __Note:__ Newtype structs are expected to be their inner type on the Gluon side.
//!
//! #### Examples
//!
//! Marhalling this gluon type:
//!
//! ```gluon
//! type Comment =
//!     | Normal String
//!     | Multiline String
//!     | Doc String
//! ```
//!
//! To this rust enum:
//!
//! ```rust
//! #[macro_use]
//! extern crate gluon_codegen;
//! extern crate gluon;
//!
//! enum Comment {
//!     Normal(String),
//!     Multiline(String),
//!     Doc(String),
//! }
//! # fn main() {}
//! ```
//!
//! ### Pushable
//!
//! Derives `Pushable` for any enum or struct as long as all fields also implement
//! `Pushable` (generic type parameters included).
//!
//! __Note:__ Newtype structs are pushed as their inner type.
//!
//! #### Examples
//!
//! Allowing the `User` struct to be marshalled to gluon code:
//!
//! ```rust
//! #[macro_use]
//! extern crate gluon_codegen;
//! extern crate gluon;
//!
//! #[derive(Pushable)]
//! struct User {
//!     name: String,
//!     age: u32,
//! }
//! # fn main() {}
//! ```
//!
//! As this compatible Record:
//!
//! ```gluon
//! type User = { name: String, age: Int }
//! ```
//!
//! ### VmType
//!
//! Derives `VmType` for a rust type, mapping it to a gluon type.
//!
//! Alternatively, you can specify the corresponding gluon type with the
//! `#[gluon(vm_type = "<gluon_type>")]` attribute, where the gluon type is the fully qualified type name.
//! The gluon type must be registered before a binding using the mapped rust type is first loaded.
//!
//! If the rust type has type parameters, they have to implement `VmType` as well.
//! All lifetimes have to be `'static`.
//!
//! __Note:__ Newtype structs are mapped to their inner type.
//!
//! #### Examples
//!
//! Deriving `VmType` for a struct:
//!
//! ```rust
//! #[macro_use]
//! extern crate gluon_codegen;
//! extern crate gluon;
//!
//! // will map to: `{ string: String, number: Int, vec: Array Float }`
//! #[derive(VmType)]
//! struct Struct {
//!     string: String,
//!     number: u32,
//!     vec: Vec<f64>,
//! }
//! # fn main() {}
//! ```
//!
//! Mapping to an existing type, assuming the following gluon type in the module `types`:
//!
//! ```gluon
//! type Either l r = | Left l | Right r
//! ```
//!
//! Requires the additional `vm_type` attribute:
//!
//! ```rust
//! #[macro_use]
//! extern crate gluon_codegen;
//! extern crate gluon;
//!
//! #[derive(VmType)]
//! #[gluon(vm_type = "types.Either")]
//! enum Either<L, R> {
//!     Left(L),
//!     Right(R),
//! }
//! # fn main() {}
//! ```
//!
//! ### Userdata
//!
//! Derives `Userdata` and the required `Traverseable` and `VmType` for a rust type.
//! Note that you will still have to use `Thread::register_type` to register the
//! rust type with the vm before it is used.
//!
//! #### Examples
//!
//! Deriving `Userdata` for a type that will be opaque for the gluon code:
//!
//! ```rust
//! #[macro_use]
//! extern crate gluon_codegen;
//! extern crate gluon;
//!
//! use std::sync::Arc;
//!
//! // Userdata requires Debug + Send + Sync
//! #[derive(Userdata, Debug)]
//! struct Ident {
//!     group: Arc<str>,
//!     name: Arc<str>,
//! }
//! # fn main() {}
//! ```
//!

#![recursion_limit = "128"]

extern crate proc_macro;
extern crate proc_macro2;
#[macro_use]
extern crate quote;
extern crate syn;

mod attr;
mod functor;
mod getable;
mod pushable;
mod shared;
mod userdata;
mod vm_type;

#[doc(hidden)]
#[proc_macro_derive(Getable, attributes(gluon))]
pub fn getable(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    getable::derive(input.into()).into()
}

#[doc(hidden)]
#[proc_macro_derive(Pushable, attributes(gluon))]
pub fn pushable(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    pushable::derive(input.into()).into()
}

#[doc(hidden)]
#[proc_macro_derive(Userdata, attributes(gluon))]
pub fn userdata(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    userdata::derive(input.into()).into()
}

#[doc(hidden)]
#[proc_macro_derive(VmType, attributes(gluon))]
pub fn vm_type(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    vm_type::derive(input.into()).into()
}

#[doc(hidden)]
#[proc_macro_derive(Functor, attributes(functor))]
pub fn functor(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    functor::derive(input.into()).into()
}