Cleanup rust-hl-lua-modules
parent
912cd1442d
commit
f064828575
|
@ -1,4 +1,5 @@
|
|||
#![feature(plugin_registrar)]
|
||||
#![feature(quote)]
|
||||
|
||||
extern crate rustc;
|
||||
extern crate syntax;
|
||||
|
@ -6,6 +7,7 @@ extern crate syntax;
|
|||
use std::gc::{GC, Gc};
|
||||
use syntax::parse::token;
|
||||
use syntax::ast;
|
||||
use syntax::ext::build::AstBuilder;
|
||||
use syntax::ext::base;
|
||||
use syntax::ext::quote::rt::ToSource;
|
||||
use syntax::codemap;
|
||||
|
@ -20,124 +22,148 @@ pub fn plugin_registrar(reg: &mut ::rustc::plugin::Registry) {
|
|||
pub fn expand_lua_module(ecx: &mut base::ExtCtxt, span: codemap::Span, _: Gc<ast::MetaItem>, input_item: Gc<ast::Item>)
|
||||
-> Gc<ast::Item>
|
||||
{
|
||||
let ecx: &base::ExtCtxt = &*ecx;
|
||||
|
||||
// checking that the input item is a module
|
||||
let module = match input_item.node {
|
||||
ast::ItemMod(ref module) => module,
|
||||
_ => {
|
||||
ecx.span_err(input_item.span, "`export_lua_module` extension is only allowed on modules");
|
||||
ecx.span_err(input_item.span,
|
||||
"`export_lua_module` extension is only allowed on modules");
|
||||
return input_item
|
||||
}
|
||||
};
|
||||
|
||||
// creating the new item that will be returned by the function
|
||||
// it is just a clone of the input with more elements added to it
|
||||
let mut newItem = input_item.deref().clone();
|
||||
newItem.vis = ast::Public;
|
||||
let mut new_item = input_item.deref().clone();
|
||||
new_item.vis = ast::Public;
|
||||
if input_item.vis != ast::Public {
|
||||
ecx.span_warn(input_item.span, "`export_lua_module` will turn the module into a public module");
|
||||
ecx.span_warn(input_item.span,
|
||||
"`export_lua_module` will turn the module into a public module");
|
||||
}
|
||||
|
||||
// creating an array of the lines of code to add to the main Lua entry point
|
||||
let moduleHandlerBody: Vec<String> = {
|
||||
let mut moduleHandlerBody = Vec::new();
|
||||
// creating an array of the statements to add to the main Lua entry point
|
||||
let module_handler_body: Vec<Gc<ast::Stmt>> = {
|
||||
let mut module_handler_body = Vec::new();
|
||||
|
||||
for moditem in module.items.iter() {
|
||||
let moditem_name = moditem.ident.to_source();
|
||||
|
||||
match moditem.node {
|
||||
ast::ItemFn(..) | ast::ItemStatic(..) =>
|
||||
moduleHandlerBody.push(format!(r#"
|
||||
table.set("{0}".to_string(), {0});
|
||||
"#, moditem_name)),
|
||||
ast::ItemFn(..) | ast::ItemStatic(..) => {
|
||||
let moditem_name_slice = moditem_name.as_slice();
|
||||
let moditem_name_item = ecx.ident_of(moditem_name_slice);
|
||||
module_handler_body.push(
|
||||
quote_stmt!(&*ecx,
|
||||
table.set($moditem_name_slice.to_string(), $moditem_name_item);
|
||||
)
|
||||
)
|
||||
},
|
||||
|
||||
_ => {
|
||||
ecx.span_warn(moditem.span,
|
||||
format!("item `{}` is neiter a function nor a static and will thus be ignored by `export_lua_module`",
|
||||
format!("item `{}` is neiter a function nor a static
|
||||
and will thus be ignored by `export_lua_module`",
|
||||
moditem_name).as_slice());
|
||||
continue
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
moduleHandlerBody
|
||||
module_handler_body
|
||||
};
|
||||
|
||||
// adding extern crate declarations
|
||||
{
|
||||
let generatedCodeContent = format!(r#"
|
||||
mod x {{
|
||||
let view_items = quote_item!(ecx,
|
||||
mod x {
|
||||
extern crate lua = "rust-hl-lua";
|
||||
extern crate libc;
|
||||
}}
|
||||
"#);
|
||||
|
||||
// creating a new Rust parser from this
|
||||
let mut parser = ::syntax::parse::new_parser_from_source_str(ecx.parse_sess(), ecx.cfg(), "".to_string(), generatedCodeContent);
|
||||
|
||||
// getting all the items defined inside "generateCodeContent"
|
||||
match parser.parse_item_with_outer_attributes() {
|
||||
None => (),
|
||||
Some(m) => {
|
||||
let m = match m.node {
|
||||
ast::ItemMod(ref m) => m,
|
||||
_ => { ecx.span_err(span, "internal error in the library"); return input_item; }
|
||||
};
|
||||
|
||||
let ref mut mutNewItem = match &mut newItem.node {
|
||||
&ast::ItemMod(ref mut m) => m,
|
||||
_ => { ecx.span_err(span, "internal error in the library"); return input_item; }
|
||||
};
|
||||
|
||||
for i in m.view_items.iter() {
|
||||
mutNewItem.view_items.unshift(i.clone())
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if !parser.eat(&token::EOF) {
|
||||
ecx.span_err(input_item.span, "internal error in the library");
|
||||
return input_item;
|
||||
let view_items = match view_items {
|
||||
Some(a) => a,
|
||||
None => {
|
||||
ecx.span_err(input_item.span,
|
||||
"internal error in the library (could not parse view items)");
|
||||
return input_item;
|
||||
}
|
||||
};
|
||||
|
||||
// getting all the items
|
||||
let view_items = match view_items.node {
|
||||
ast::ItemMod(ref m) => m,
|
||||
_ => { ecx.span_err(span, "internal error in the library"); return input_item; }
|
||||
};
|
||||
|
||||
let ref mut mut_new_item = match &mut new_item.node {
|
||||
&ast::ItemMod(ref mut m) => m,
|
||||
_ => { ecx.span_err(span, "internal error in the library"); return input_item; }
|
||||
};
|
||||
|
||||
for i in view_items.view_items.iter() {
|
||||
mut_new_item.view_items.unshift(i.clone())
|
||||
}
|
||||
}
|
||||
|
||||
// generating the source code that we will add inside the module
|
||||
// generating the function that we will add inside the module
|
||||
{
|
||||
let generatedCodeContent = format!(r#"
|
||||
let function_body = {
|
||||
let mut function_body = Vec::new();
|
||||
|
||||
function_body.push(quote_stmt!(ecx,
|
||||
let mut lua = self::lua::Lua::from_existing_state(lua, false);
|
||||
));
|
||||
|
||||
function_body.push(quote_stmt!(ecx,
|
||||
let mut table = lua.load_new_table();
|
||||
));
|
||||
|
||||
function_body.push_all_move(module_handler_body);
|
||||
|
||||
function_body.push(quote_stmt!(ecx,
|
||||
::std::mem::forget(table);
|
||||
));
|
||||
|
||||
ecx.block(span.clone(), function_body, Some(
|
||||
quote_expr!(ecx, 1)
|
||||
))
|
||||
};
|
||||
|
||||
// identifier for "luaopen_mylib"
|
||||
let luaopen_id = ecx.ident_of(format!("luaopen_{}", input_item.ident.to_source())
|
||||
.as_slice());
|
||||
|
||||
// building the function itself
|
||||
let function = quote_item!(ecx,
|
||||
#[no_mangle]
|
||||
pub extern "C" fn luaopen_{0}(lua: *mut self::libc::c_void) -> self::libc::c_int {{
|
||||
pub extern "C" fn $luaopen_id(lua: *mut self::libc::c_void) -> self::libc::c_int {{
|
||||
unsafe {{
|
||||
let mut lua = self::lua::Lua::from_existing_state(lua, false);
|
||||
let mut table = lua.load_new_table();
|
||||
|
||||
{1}
|
||||
|
||||
::std::mem::forget(table);
|
||||
1
|
||||
$function_body
|
||||
}}
|
||||
}}
|
||||
"#, input_item.ident.to_source(), moduleHandlerBody.connect("\n"));
|
||||
);
|
||||
|
||||
// creating a new Rust parser from this
|
||||
let mut parser = ::syntax::parse::new_parser_from_source_str(ecx.parse_sess(), ecx.cfg(), "".to_string(), generatedCodeContent);
|
||||
|
||||
// getting all the items defined inside "generateCodeContent"
|
||||
loop {
|
||||
match parser.parse_item_with_outer_attributes() {
|
||||
None => break,
|
||||
Some(i) => match &mut newItem.node {
|
||||
// moving them into "newItem"
|
||||
&ast::ItemMod(ref mut m) => m.items.push(i),
|
||||
_ => { ecx.span_err(span, "internal error in the library"); return input_item; }
|
||||
}
|
||||
let function = match function {
|
||||
Some(f) => f,
|
||||
None => {
|
||||
ecx.span_err(input_item.span,
|
||||
"internal error in the library (could not parse function body)");
|
||||
return input_item;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if !parser.eat(&token::EOF) {
|
||||
ecx.span_err(input_item.span, "internal error in the library");
|
||||
return input_item;
|
||||
}
|
||||
// adding the function to the module
|
||||
match &mut new_item.node {
|
||||
&ast::ItemMod(ref mut m) => {
|
||||
m.items.push(function)
|
||||
},
|
||||
_ => { ecx.span_err(span, "internal error in the library"); return input_item; }
|
||||
};
|
||||
}
|
||||
|
||||
// returning
|
||||
box(GC) newItem
|
||||
box(GC) new_item
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue