Allow dynamic loading of Lua functions
Dynamically loading Lua functions allows distributing implementations to multiple places. Additionally, migrate bit.* functions to the new framework.
This commit is contained in:
parent
f170c7bab2
commit
feb1a5d841
5 changed files with 243 additions and 174 deletions
2
Makefile
2
Makefile
|
@ -11,7 +11,7 @@ LDFLAGS = $(shell sdl-config --libs) $(USER_LDFLAGS)
|
|||
ifdef NO_LUA
|
||||
OBJECTS += lua-dummy.o
|
||||
else
|
||||
OBJECTS += lua.o
|
||||
OBJECTS += lua.o $(patsubst %.cpp,%.o,$(wildcard lua/*.cpp))
|
||||
CFLAGS += $(shell pkg-config lua5.1 --cflags)
|
||||
LDFLAGS += $(shell pkg-config lua5.1 --libs)
|
||||
endif
|
||||
|
|
32
lua-int.hpp
Normal file
32
lua-int.hpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
#ifndef _lua_int__hpp__included__
|
||||
#define _lua_int__hpp__included__
|
||||
|
||||
#include "lua.hpp"
|
||||
extern "C"
|
||||
{
|
||||
#include <lua.h>
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T get_numeric_argument(lua_State* LS, unsigned argindex, const char* fname)
|
||||
{
|
||||
if(lua_isnone(LS, argindex) || !lua_isnumber(LS, argindex)) {
|
||||
lua_pushfstring(LS, "argument #%i to %s must be numeric", argindex, fname);
|
||||
lua_error(LS);
|
||||
}
|
||||
return static_cast<T>(lua_tonumber(LS, argindex));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void get_numeric_argument(lua_State* LS, unsigned argindex, T& value, const char* fname)
|
||||
{
|
||||
if(lua_isnoneornil(LS, argindex))
|
||||
return;
|
||||
if(lua_isnone(LS, argindex) || !lua_isnumber(LS, argindex)) {
|
||||
lua_pushfstring(LS, "argument #%i to %s must be numeric if present", argindex, fname);
|
||||
lua_error(LS);
|
||||
}
|
||||
value = static_cast<T>(lua_tonumber(LS, argindex));
|
||||
}
|
||||
|
||||
#endif
|
260
lua.cpp
260
lua.cpp
|
@ -1,23 +1,108 @@
|
|||
#include "lua.hpp"
|
||||
#include "lua-int.hpp"
|
||||
#include "command.hpp"
|
||||
#include "misc.hpp"
|
||||
#include "memorymanip.hpp"
|
||||
#include "mainloop.hpp"
|
||||
#include <map>
|
||||
#include <string>
|
||||
extern "C" {
|
||||
#include <lua.h>
|
||||
#include <lualib.h>
|
||||
}
|
||||
#include <iostream>
|
||||
#include "fieldsplit.hpp"
|
||||
#define BITWISE_BITS 48
|
||||
#define BITWISE_MASK ((1ULL << (BITWISE_BITS)) - 1)
|
||||
|
||||
#define SETFIELDFUN(LSS, idx, name, fun) do { lua_pushcfunction(LSS, fun); lua_setfield(LSS, (idx) - 1, name); \
|
||||
} while(0)
|
||||
|
||||
namespace
|
||||
{
|
||||
std::map<std::string, lua_function*>* functions;
|
||||
lua_State* lua_initialized;
|
||||
window* tmp_win;
|
||||
|
||||
int lua_trampoline_function(lua_State* L)
|
||||
{
|
||||
void* ptr = lua_touserdata(L, lua_upvalueindex(1));
|
||||
lua_function* f = reinterpret_cast<lua_function*>(ptr);
|
||||
return f->invoke(L, tmp_win);
|
||||
}
|
||||
|
||||
//Pushes given table to top of stack, creating if needed.
|
||||
void recursive_lookup_table(lua_State* L, const std::string& tab)
|
||||
{
|
||||
if(tab == "") {
|
||||
lua_pushvalue(L, LUA_GLOBALSINDEX);
|
||||
return;
|
||||
}
|
||||
std::string u = tab;
|
||||
size_t split = u.find_last_of(".");
|
||||
std::string u1;
|
||||
std::string u2 = u;
|
||||
if(split < u.length()) {
|
||||
u1 = u.substr(0, split);
|
||||
u2 = u.substr(split + 1);
|
||||
}
|
||||
recursive_lookup_table(L, u1);
|
||||
lua_getfield(L, -1, u2.c_str());
|
||||
if(lua_type(L, -1) != LUA_TTABLE) {
|
||||
//Not a table, create a table.
|
||||
lua_pop(L, 1);
|
||||
lua_newtable(L);
|
||||
lua_setfield(L, -2, u2.c_str());
|
||||
lua_getfield(L, -1, u2.c_str());
|
||||
}
|
||||
//Get rid of previous table.
|
||||
lua_insert(L, -2);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
void register_lua_function(lua_State* L, const std::string& fun)
|
||||
{
|
||||
std::string u = fun;
|
||||
size_t split = u.find_last_of(".");
|
||||
std::string u1;
|
||||
std::string u2 = u;
|
||||
if(split < u.length()) {
|
||||
u1 = u.substr(0, split);
|
||||
u2 = u.substr(split + 1);
|
||||
}
|
||||
recursive_lookup_table(L, u1);
|
||||
void* ptr = reinterpret_cast<void*>((*functions)[fun]);
|
||||
lua_pushlightuserdata(L, ptr);
|
||||
lua_pushcclosure(L, lua_trampoline_function, 1);
|
||||
lua_setfield(L, -2, u2.c_str());
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
void register_lua_functions(lua_State* L)
|
||||
{
|
||||
if(functions)
|
||||
for(auto i = functions->begin(); i != functions->end(); i++)
|
||||
register_lua_function(L, i->first);
|
||||
lua_initialized = L;
|
||||
}
|
||||
}
|
||||
|
||||
lua_function::lua_function(const std::string& name) throw(std::bad_alloc)
|
||||
{
|
||||
if(!functions)
|
||||
functions = new std::map<std::string, lua_function*>();
|
||||
(*functions)[fname = name] = this;
|
||||
if(lua_initialized)
|
||||
register_lua_function(lua_initialized, fname);
|
||||
}
|
||||
|
||||
lua_function::~lua_function() throw()
|
||||
{
|
||||
if(!functions)
|
||||
return;
|
||||
functions->erase(fname);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
lua_State* L;
|
||||
lua_render_context* rctx = NULL;
|
||||
bool recursive_flag = false;
|
||||
|
@ -109,16 +194,6 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T get_numeric_argument(lua_State* LS, unsigned argindex, const char* fname)
|
||||
{
|
||||
if(lua_isnone(LS, argindex) || !lua_isnumber(LS, argindex)) {
|
||||
lua_pushfstring(L, "argument #%i to %s must be numeric", argindex, fname);
|
||||
lua_error(LS);
|
||||
}
|
||||
return static_cast<T>(lua_tonumber(LS, argindex));
|
||||
}
|
||||
|
||||
std::string get_string_argument(lua_State* LS, unsigned argindex, const char* fname)
|
||||
{
|
||||
if(lua_isnone(LS, argindex)) {
|
||||
|
@ -143,18 +218,6 @@ namespace
|
|||
return (lua_toboolean(LS, argindex) != 0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void get_numeric_argument(lua_State* LS, unsigned argindex, T& value, const char* fname)
|
||||
{
|
||||
if(lua_isnoneornil(LS, argindex))
|
||||
return;
|
||||
if(lua_isnone(LS, argindex) || !lua_isnumber(LS, argindex)) {
|
||||
lua_pushfstring(L, "argument #%i to %s must be numeric if present", argindex, fname);
|
||||
lua_error(LS);
|
||||
}
|
||||
value = static_cast<T>(lua_tonumber(LS, argindex));
|
||||
}
|
||||
|
||||
void do_eval_lua(const std::string& c, window* win) throw(std::bad_alloc)
|
||||
{
|
||||
push_string(c);
|
||||
|
@ -195,136 +258,6 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
int lua_symmetric_bitwise(lua_State* LS, uint64_t (*combine)(uint64_t chain, uint64_t arg), uint64_t init)
|
||||
{
|
||||
int stacksize = 0;
|
||||
while(!lua_isnone(LS, stacksize + 1))
|
||||
stacksize++;
|
||||
uint64_t ret = init;
|
||||
for(int i = 0; i < stacksize; i++)
|
||||
ret = combine(ret, get_numeric_argument<uint64_t>(LS, i + 1, "<bitwise function>"));
|
||||
lua_pushnumber(LS, ret);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua_shifter(lua_State* LS, uint64_t (*shift)(uint64_t base, uint64_t amount, uint64_t bits))
|
||||
{
|
||||
uint64_t base;
|
||||
uint64_t amount = 1;
|
||||
uint64_t bits = BITWISE_BITS;
|
||||
base = get_numeric_argument<uint64_t>(LS, 1, "<shift function>");
|
||||
get_numeric_argument(LS, 2, amount, "<shift function>");
|
||||
get_numeric_argument(LS, 3, bits, "<shift function>");
|
||||
lua_pushnumber(LS, shift(base, amount, bits));
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint64_t combine_none(uint64_t chain, uint64_t arg)
|
||||
{
|
||||
return (chain & ~arg) & BITWISE_MASK;
|
||||
}
|
||||
|
||||
uint64_t combine_any(uint64_t chain, uint64_t arg)
|
||||
{
|
||||
return (chain | arg) & BITWISE_MASK;
|
||||
}
|
||||
|
||||
uint64_t combine_all(uint64_t chain, uint64_t arg)
|
||||
{
|
||||
return (chain & arg) & BITWISE_MASK;
|
||||
}
|
||||
|
||||
uint64_t combine_parity(uint64_t chain, uint64_t arg)
|
||||
{
|
||||
return (chain ^ arg) & BITWISE_MASK;
|
||||
}
|
||||
|
||||
uint64_t shift_lrotate(uint64_t base, uint64_t amount, uint64_t bits)
|
||||
{
|
||||
uint64_t mask = ((1ULL << bits) - 1);
|
||||
base &= mask;
|
||||
base = (base << amount) | (base >> (bits - amount));
|
||||
return base & mask & BITWISE_MASK;
|
||||
}
|
||||
|
||||
uint64_t shift_rrotate(uint64_t base, uint64_t amount, uint64_t bits)
|
||||
{
|
||||
uint64_t mask = ((1ULL << bits) - 1);
|
||||
base &= mask;
|
||||
base = (base >> amount) | (base << (bits - amount));
|
||||
return base & mask & BITWISE_MASK;
|
||||
}
|
||||
|
||||
uint64_t shift_lshift(uint64_t base, uint64_t amount, uint64_t bits)
|
||||
{
|
||||
uint64_t mask = ((1ULL << bits) - 1);
|
||||
base <<= amount;
|
||||
return base & mask & BITWISE_MASK;
|
||||
}
|
||||
|
||||
uint64_t shift_lrshift(uint64_t base, uint64_t amount, uint64_t bits)
|
||||
{
|
||||
uint64_t mask = ((1ULL << bits) - 1);
|
||||
base &= mask;
|
||||
base >>= amount;
|
||||
return base & BITWISE_MASK;
|
||||
}
|
||||
|
||||
uint64_t shift_arshift(uint64_t base, uint64_t amount, uint64_t bits)
|
||||
{
|
||||
uint64_t mask = ((1ULL << bits) - 1);
|
||||
base &= mask;
|
||||
bool negative = ((base >> (bits - 1)) != 0);
|
||||
base >>= amount;
|
||||
base |= ((negative ? BITWISE_MASK : 0) << (bits - amount));
|
||||
return base & mask & BITWISE_MASK;
|
||||
}
|
||||
|
||||
int lua_bit_none(lua_State* LS)
|
||||
{
|
||||
return lua_symmetric_bitwise(LS, combine_none, BITWISE_MASK);
|
||||
}
|
||||
|
||||
int lua_bit_any(lua_State* LS)
|
||||
{
|
||||
return lua_symmetric_bitwise(LS, combine_any, 0);
|
||||
}
|
||||
|
||||
int lua_bit_all(lua_State* LS)
|
||||
{
|
||||
return lua_symmetric_bitwise(LS, combine_all, BITWISE_MASK);
|
||||
}
|
||||
|
||||
int lua_bit_parity(lua_State* LS)
|
||||
{
|
||||
return lua_symmetric_bitwise(LS, combine_parity, 0);
|
||||
}
|
||||
|
||||
int lua_bit_lrotate(lua_State* LS)
|
||||
{
|
||||
return lua_shifter(LS, shift_lrotate);
|
||||
}
|
||||
|
||||
int lua_bit_rrotate(lua_State* LS)
|
||||
{
|
||||
return lua_shifter(LS, shift_rrotate);
|
||||
}
|
||||
|
||||
int lua_bit_lshift(lua_State* LS)
|
||||
{
|
||||
return lua_shifter(LS, shift_lshift);
|
||||
}
|
||||
|
||||
int lua_bit_arshift(lua_State* LS)
|
||||
{
|
||||
return lua_shifter(LS, shift_arshift);
|
||||
}
|
||||
|
||||
int lua_bit_lrshift(lua_State* LS)
|
||||
{
|
||||
return lua_shifter(LS, shift_lrshift);
|
||||
}
|
||||
|
||||
int lua_print(lua_State* LS)
|
||||
{
|
||||
int stacksize = 0;
|
||||
|
@ -800,23 +733,6 @@ void init_lua(window* win) throw()
|
|||
lua_pushcfunction(L, lua_exec);
|
||||
lua_setglobal(L, "exec");
|
||||
|
||||
//Bit table.
|
||||
lua_newtable(L);
|
||||
SETFIELDFUN(L, -1, "none", lua_bit_none);
|
||||
SETFIELDFUN(L, -1, "bnot", lua_bit_none);
|
||||
SETFIELDFUN(L, -1, "any", lua_bit_any);
|
||||
SETFIELDFUN(L, -1, "bor", lua_bit_any);
|
||||
SETFIELDFUN(L, -1, "all", lua_bit_all);
|
||||
SETFIELDFUN(L, -1, "band", lua_bit_all);
|
||||
SETFIELDFUN(L, -1, "parity", lua_bit_parity);
|
||||
SETFIELDFUN(L, -1, "bxor", lua_bit_parity);
|
||||
SETFIELDFUN(L, -1, "lrotate", lua_bit_lrotate);
|
||||
SETFIELDFUN(L, -1, "rrotate", lua_bit_rrotate);
|
||||
SETFIELDFUN(L, -1, "lshift", lua_bit_lshift);
|
||||
SETFIELDFUN(L, -1, "arshift", lua_bit_arshift);
|
||||
SETFIELDFUN(L, -1, "lrshift", lua_bit_lrshift);
|
||||
lua_setglobal(L, "bit");
|
||||
|
||||
//Gui table.
|
||||
lua_newtable(L);
|
||||
SETFIELDFUN(L, -1, "resolution", lua_gui_resolution);
|
||||
|
@ -867,6 +783,8 @@ void init_lua(window* win) throw()
|
|||
SETFIELDFUN(L, -1, "readonly", lua_movie_readonly);
|
||||
SETFIELDFUN(L, -1, "set_readwrite", lua_movie_set_readwrite);
|
||||
lua_setglobal(L, "movie");
|
||||
|
||||
register_lua_functions(L);
|
||||
}
|
||||
|
||||
bool lua_requests_repaint = false;
|
||||
|
|
3
lua.hpp
3
lua.hpp
|
@ -12,6 +12,7 @@ struct lua_State;
|
|||
*/
|
||||
class lua_function
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Register function.
|
||||
*/
|
||||
|
@ -25,7 +26,7 @@ class lua_function
|
|||
* Invoke function.
|
||||
*/
|
||||
virtual int invoke(lua_State* L, window* win) = 0;
|
||||
private:
|
||||
protected:
|
||||
std::string fname;
|
||||
};
|
||||
|
||||
|
|
118
lua/bit.cpp
Normal file
118
lua/bit.cpp
Normal file
|
@ -0,0 +1,118 @@
|
|||
#include "lua-int.hpp"
|
||||
|
||||
#define BITWISE_BITS 48
|
||||
#define BITWISE_MASK ((1ULL << (BITWISE_BITS)) - 1)
|
||||
|
||||
namespace
|
||||
{
|
||||
uint64_t combine_none(uint64_t chain, uint64_t arg)
|
||||
{
|
||||
return (chain & ~arg) & BITWISE_MASK;
|
||||
}
|
||||
|
||||
uint64_t combine_any(uint64_t chain, uint64_t arg)
|
||||
{
|
||||
return (chain | arg) & BITWISE_MASK;
|
||||
}
|
||||
|
||||
uint64_t combine_all(uint64_t chain, uint64_t arg)
|
||||
{
|
||||
return (chain & arg) & BITWISE_MASK;
|
||||
}
|
||||
|
||||
uint64_t combine_parity(uint64_t chain, uint64_t arg)
|
||||
{
|
||||
return (chain ^ arg) & BITWISE_MASK;
|
||||
}
|
||||
|
||||
uint64_t shift_lrotate(uint64_t base, uint64_t amount, uint64_t bits)
|
||||
{
|
||||
uint64_t mask = ((1ULL << bits) - 1);
|
||||
base &= mask;
|
||||
base = (base << amount) | (base >> (bits - amount));
|
||||
return base & mask & BITWISE_MASK;
|
||||
}
|
||||
|
||||
uint64_t shift_rrotate(uint64_t base, uint64_t amount, uint64_t bits)
|
||||
{
|
||||
uint64_t mask = ((1ULL << bits) - 1);
|
||||
base &= mask;
|
||||
base = (base >> amount) | (base << (bits - amount));
|
||||
return base & mask & BITWISE_MASK;
|
||||
}
|
||||
|
||||
uint64_t shift_lshift(uint64_t base, uint64_t amount, uint64_t bits)
|
||||
{
|
||||
uint64_t mask = ((1ULL << bits) - 1);
|
||||
base <<= amount;
|
||||
return base & mask & BITWISE_MASK;
|
||||
}
|
||||
|
||||
uint64_t shift_lrshift(uint64_t base, uint64_t amount, uint64_t bits)
|
||||
{
|
||||
uint64_t mask = ((1ULL << bits) - 1);
|
||||
base &= mask;
|
||||
base >>= amount;
|
||||
return base & BITWISE_MASK;
|
||||
}
|
||||
|
||||
uint64_t shift_arshift(uint64_t base, uint64_t amount, uint64_t bits)
|
||||
{
|
||||
uint64_t mask = ((1ULL << bits) - 1);
|
||||
base &= mask;
|
||||
bool negative = ((base >> (bits - 1)) != 0);
|
||||
base >>= amount;
|
||||
base |= ((negative ? BITWISE_MASK : 0) << (bits - amount));
|
||||
return base & mask & BITWISE_MASK;
|
||||
}
|
||||
|
||||
template<uint64_t (*combine)(uint64_t chain, uint64_t arg), uint64_t init>
|
||||
class lua_symmetric_bitwise : public lua_function
|
||||
{
|
||||
public:
|
||||
lua_symmetric_bitwise(const std::string& s) : lua_function(s) {};
|
||||
int invoke(lua_State* L, window* win)
|
||||
{
|
||||
int stacksize = 0;
|
||||
while(!lua_isnone(L, stacksize + 1))
|
||||
stacksize++;
|
||||
uint64_t ret = init;
|
||||
for(int i = 0; i < stacksize; i++)
|
||||
ret = combine(ret, get_numeric_argument<uint64_t>(L, i + 1, fname.c_str()));
|
||||
lua_pushnumber(L, ret);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
template<uint64_t (*shift)(uint64_t base, uint64_t amount, uint64_t bits)>
|
||||
class lua_shifter : public lua_function
|
||||
{
|
||||
public:
|
||||
lua_shifter(const std::string& s) : lua_function(s) {};
|
||||
int invoke(lua_State* L, window* win)
|
||||
{
|
||||
uint64_t base;
|
||||
uint64_t amount = 1;
|
||||
uint64_t bits = BITWISE_BITS;
|
||||
base = get_numeric_argument<uint64_t>(L, 1, fname.c_str());
|
||||
get_numeric_argument(L, 2, amount, fname.c_str());
|
||||
get_numeric_argument(L, 3, bits, fname.c_str());
|
||||
lua_pushnumber(L, shift(base, amount, bits));
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
lua_symmetric_bitwise<combine_none, BITWISE_MASK> bit_none("bit.none");
|
||||
lua_symmetric_bitwise<combine_none, BITWISE_MASK> bit_bnot("bit.bnot");
|
||||
lua_symmetric_bitwise<combine_any, 0> bit_any("bit.any");
|
||||
lua_symmetric_bitwise<combine_any, 0> bit_bor("bit.bor");
|
||||
lua_symmetric_bitwise<combine_all, BITWISE_MASK> bit_all("bit.all");
|
||||
lua_symmetric_bitwise<combine_all, BITWISE_MASK> bit_band("bit.band");
|
||||
lua_symmetric_bitwise<combine_parity, 0> bit_parity("bit.parity");
|
||||
lua_symmetric_bitwise<combine_parity, 0> bit_bxor("bit.bxor");
|
||||
lua_shifter<shift_lrotate> bit_lrotate("bit.lrotate");
|
||||
lua_shifter<shift_rrotate> bit_rrotate("bit.rrotate");
|
||||
lua_shifter<shift_lshift> bit_lshift("bit.lshift");
|
||||
lua_shifter<shift_arshift> bit_arshift("bit.arshift");
|
||||
lua_shifter<shift_lrshift> bit_lrshift("bit.lrshift");
|
||||
}
|
Loading…
Add table
Reference in a new issue