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
//!# Tealr_derive
//!The derive macros used by [tealr](https://github.com/lenscas/tealr/tree/master/tealr).
//!
//!Tealr is a crate that can generate `.d.tl` files for types that are exposed to `lua`/`teal` through [rlua](https://crates.io/crates/rlua) and [mlua](https://crates.io/crates/rlua)
//!
//!Read the [README.md](https://github.com/lenscas/tealr/tree/master/README.md) in [tealr](https://github.com/lenscas/tealr/tree/master) for more information.
#[macro_use]
extern crate quote;
#[cfg(any(
feature = "embed_compiler_from_local",
feature = "embed_compiler_from_download"
))]
mod embed_compiler;
#[cfg(feature = "derive")]
mod from_to_lua;
#[cfg(feature = "derive")]
mod user_data;
#[cfg(any(
feature = "embed_compiler_from_local",
feature = "embed_compiler_from_download"
))]
use embed_compiler::EmbedOptions;
use proc_macro::TokenStream;
use venial::parse_declaration;
#[cfg(feature = "derive")]
#[proc_macro_derive(RluaUserData, attributes(tealr))]
pub fn rlua_user_data_derive(input: TokenStream) -> TokenStream {
use user_data::impl_rlua_user_data_derive;
let ast = parse_declaration(input.into()).unwrap();
impl_rlua_user_data_derive(&ast).into()
}
#[cfg(feature = "derive")]
#[proc_macro_derive(MluaUserData, attributes(tealr))]
pub fn mlua_user_data_derive(input: TokenStream) -> TokenStream {
use user_data::impl_mlua_user_data_derive;
let ast = parse_declaration(input.into()).unwrap();
impl_mlua_user_data_derive(&ast).into()
}
#[cfg(feature = "derive")]
#[proc_macro_derive(ToTypename, attributes(tealr))]
pub fn type_representation_derive(input: TokenStream) -> TokenStream {
use user_data::impl_type_representation_derive;
let ast = parse_declaration(input.into()).unwrap();
impl_type_representation_derive(&ast).into()
}
#[cfg(feature = "derive")]
#[proc_macro_derive(RluaTealDerive, attributes(tealr))]
pub fn rlua_teal_derive(input: TokenStream) -> TokenStream {
use crate::user_data::{impl_rlua_user_data_derive, impl_type_representation_derive};
let ast = parse_declaration(input.into()).unwrap();
let mut stream = impl_type_representation_derive(&ast);
stream.extend(impl_rlua_user_data_derive(&ast));
stream.into()
}
#[cfg(feature = "derive")]
#[proc_macro_derive(MluaTealDerive, attributes(tealr))]
pub fn mlua_teal_derive(input: TokenStream) -> TokenStream {
use crate::user_data::impl_type_representation_derive;
use user_data::impl_mlua_user_data_derive;
let ast = parse_declaration(input.into()).unwrap();
let mut stream = impl_type_representation_derive(&ast);
stream.extend(impl_mlua_user_data_derive(&ast));
stream.into()
}
#[cfg(feature = "compile")]
mod compile_inline_teal;
///Compiles the given teal code at compile time to lua.
///
///The macro tries it best to pass the correct `--include-dir` to tl using `CARGO_MANIFEST_DIR`.
///However, this isn't always where you want it to be. In that case you can add an extra argument that will be joined with `CARGO_MANIFEST_DIR` using [std::path::PathBuf::join](std::path::PathBuf#method.join)
///
///## Compile time requirement!
///At this point in time this requires you to have the teal compiler installed and accessible in the path as `tl`.
///
///## Example
///```
///# use tealr_derive::compile_inline_teal;
///assert_eq!(compile_inline_teal!("local a : number = 1"),"local a = 1\n")
///```
#[cfg(feature = "compile")]
#[proc_macro]
pub fn compile_inline_teal(input: TokenStream) -> TokenStream {
use crate::compile_inline_teal::compile_inline_teal;
compile_inline_teal(input.into()).into()
}
/// Embeds the teal compiler, making it easy to load teal files directly.
///
/// It can either download the given version from Github (default), luarocks or uses the compiler already installed on your system
/// Compiling it without the lua5.3 compatibility library and embedding it into your application.
///
/// It returns a closure that takes the file that needs to run
/// and returns valid lua code that both prepares the lua vm so it can run teal files and
/// loads the given file using `require`, returning the result of the file that got loaded.
/// ## NOTE!
/// Due to how the teal files are being loaded, they won't be typed checked.
/// More info on: [https://github.com/teal-language/tl/blob/master/docs/tutorial.md](https://github.com/teal-language/tl/blob/master/docs/tutorial.md) (Search for "loader")
///
/// ## Compile time requirement!
/// A Teal compiler needs to be accessible in the path as `tl`. Running the teal compiler through command line (which this macro does) requires extra dependencies.
///
/// ## Example
/// Downloads:
/// ```rust
/// # use tealr_derive::embed_compiler;
/// //This downloads from github
/// let compiler = embed_compiler!("v0.9.0");
///
/// let compiler = embed_compiler!(Github(version = "v0.9.0"));
/// let compiler = embed_compiler!(Luarocks(version = "v0.9.0"));
/// let lua_code = compiler("your_teal_file.tl");
/// ```
/// From filesystem
/// This example is not tested so it can show a nice path. There is however a test for it in /tests/
/// ```ignore
/// let compiler = embed_compiler!(Local(path = "some/path/to/tl.tl"));
/// //This tries to find the teal compiler on its own
/// let compiler = embed_compiler!(Local());
/// ```
#[cfg(any(
feature = "embed_compiler_from_local",
feature = "embed_compiler_from_download"
))]
#[proc_macro]
pub fn embed_compiler(input: TokenStream) -> TokenStream {
use syn::parse_macro_input;
let input = parse_macro_input!(input as EmbedOptions);
let compiler = embed_compiler::get_teal(input);
let primed_vm_string = format!(
"local tl = (function()\n{}\nend)()\ntl.loader()\n",
compiler
);
let stream = quote! {
|require:&str| {
format!("{}\n return require('{}')",#primed_vm_string,require)
}
};
stream.into()
}
#[cfg(feature = "derive")]
#[proc_macro_derive(MluaFromToLua, attributes(tealr, lua_doc, tealr_doc))]
pub fn mlua_from_to_lua(input: TokenStream) -> TokenStream {
crate::from_to_lua::mlua_from_to_lua(input.into()).into()
}
#[cfg(feature = "derive")]
#[proc_macro_derive(RluaFromToLua, attributes(tealr, lua_doc, tealr_doc))]
pub fn rlua_from_to_lua(input: TokenStream) -> TokenStream {
crate::from_to_lua::rlua_from_to_lua(input.into()).into()
}