Cleanup rust-hl-lua-modules
This commit is contained in:
parent
912cd1442d
commit
f064828575
@ -1,4 +1,5 @@
|
|||||||
#![feature(plugin_registrar)]
|
#![feature(plugin_registrar)]
|
||||||
|
#![feature(quote)]
|
||||||
|
|
||||||
extern crate rustc;
|
extern crate rustc;
|
||||||
extern crate syntax;
|
extern crate syntax;
|
||||||
@ -6,6 +7,7 @@ extern crate syntax;
|
|||||||
use std::gc::{GC, Gc};
|
use std::gc::{GC, Gc};
|
||||||
use syntax::parse::token;
|
use syntax::parse::token;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
|
use syntax::ext::build::AstBuilder;
|
||||||
use syntax::ext::base;
|
use syntax::ext::base;
|
||||||
use syntax::ext::quote::rt::ToSource;
|
use syntax::ext::quote::rt::ToSource;
|
||||||
use syntax::codemap;
|
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>)
|
pub fn expand_lua_module(ecx: &mut base::ExtCtxt, span: codemap::Span, _: Gc<ast::MetaItem>, input_item: Gc<ast::Item>)
|
||||||
-> Gc<ast::Item>
|
-> Gc<ast::Item>
|
||||||
{
|
{
|
||||||
|
let ecx: &base::ExtCtxt = &*ecx;
|
||||||
|
|
||||||
// checking that the input item is a module
|
// checking that the input item is a module
|
||||||
let module = match input_item.node {
|
let module = match input_item.node {
|
||||||
ast::ItemMod(ref module) => module,
|
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
|
return input_item
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// creating the new item that will be returned by the function
|
// 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
|
// it is just a clone of the input with more elements added to it
|
||||||
let mut newItem = input_item.deref().clone();
|
let mut new_item = input_item.deref().clone();
|
||||||
newItem.vis = ast::Public;
|
new_item.vis = ast::Public;
|
||||||
if input_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
|
// creating an array of the statements to add to the main Lua entry point
|
||||||
let moduleHandlerBody: Vec<String> = {
|
let module_handler_body: Vec<Gc<ast::Stmt>> = {
|
||||||
let mut moduleHandlerBody = Vec::new();
|
let mut module_handler_body = Vec::new();
|
||||||
|
|
||||||
for moditem in module.items.iter() {
|
for moditem in module.items.iter() {
|
||||||
let moditem_name = moditem.ident.to_source();
|
let moditem_name = moditem.ident.to_source();
|
||||||
|
|
||||||
match moditem.node {
|
match moditem.node {
|
||||||
ast::ItemFn(..) | ast::ItemStatic(..) =>
|
ast::ItemFn(..) | ast::ItemStatic(..) => {
|
||||||
moduleHandlerBody.push(format!(r#"
|
let moditem_name_slice = moditem_name.as_slice();
|
||||||
table.set("{0}".to_string(), {0});
|
let moditem_name_item = ecx.ident_of(moditem_name_slice);
|
||||||
"#, moditem_name)),
|
module_handler_body.push(
|
||||||
|
quote_stmt!(&*ecx,
|
||||||
|
table.set($moditem_name_slice.to_string(), $moditem_name_item);
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
ecx.span_warn(moditem.span,
|
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());
|
moditem_name).as_slice());
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
moduleHandlerBody
|
module_handler_body
|
||||||
};
|
};
|
||||||
|
|
||||||
// adding extern crate declarations
|
// adding extern crate declarations
|
||||||
{
|
{
|
||||||
let generatedCodeContent = format!(r#"
|
let view_items = quote_item!(ecx,
|
||||||
mod x {{
|
mod x {
|
||||||
extern crate lua = "rust-hl-lua";
|
extern crate lua = "rust-hl-lua";
|
||||||
extern crate libc;
|
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) {
|
let view_items = match view_items {
|
||||||
ecx.span_err(input_item.span, "internal error in the library");
|
Some(a) => a,
|
||||||
return input_item;
|
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]
|
#[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 {{
|
unsafe {{
|
||||||
let mut lua = self::lua::Lua::from_existing_state(lua, false);
|
$function_body
|
||||||
let mut table = lua.load_new_table();
|
|
||||||
|
|
||||||
{1}
|
|
||||||
|
|
||||||
::std::mem::forget(table);
|
|
||||||
1
|
|
||||||
}}
|
}}
|
||||||
}}
|
}}
|
||||||
"#, input_item.ident.to_source(), moduleHandlerBody.connect("\n"));
|
);
|
||||||
|
|
||||||
// creating a new Rust parser from this
|
let function = match function {
|
||||||
let mut parser = ::syntax::parse::new_parser_from_source_str(ecx.parse_sess(), ecx.cfg(), "".to_string(), generatedCodeContent);
|
Some(f) => f,
|
||||||
|
None => {
|
||||||
// getting all the items defined inside "generateCodeContent"
|
ecx.span_err(input_item.span,
|
||||||
loop {
|
"internal error in the library (could not parse function body)");
|
||||||
match parser.parse_item_with_outer_attributes() {
|
return input_item;
|
||||||
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; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
if !parser.eat(&token::EOF) {
|
// adding the function to the module
|
||||||
ecx.span_err(input_item.span, "internal error in the library");
|
match &mut new_item.node {
|
||||||
return input_item;
|
&ast::ItemMod(ref mut m) => {
|
||||||
}
|
m.items.push(function)
|
||||||
|
},
|
||||||
|
_ => { ecx.span_err(span, "internal error in the library"); return input_item; }
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// returning
|
// returning
|
||||||
box(GC) newItem
|
box(GC) new_item
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user