#include <lua.hpp>
-#include <Moof/Exception.hh>
#include <Moof/Log.hh>
typedef boost::shared_ptr<Script> ScriptP;
-struct Script
+class Script
{
+public:
+
typedef boost::function<int(Script&)> Function;
- enum TYPE
+ enum Type
{
NONE = LUA_TNONE,
NIL = LUA_TNIL,
THREAD = LUA_TTHREAD
};
- enum STATUS
+ enum Status
{
SUCCESS = 0,
YIELD = LUA_YIELD,
FILE_ERROR = LUA_ERRFILE
};
- enum PSEUDO_INDEX
+ enum PseudoIndex
{
REGISTRY = LUA_REGISTRYINDEX,
ENVIRONMENT = LUA_ENVIRONINDEX,
};
/**
- * This is the most noticeable abstraction on top of the standard Lua API.
+ * This is the most prominent abstraction on top of the standard Lua API.
* A Value object represents a value on the stack. More specifically, it
* represents a position on the stack. The distinction is only important
* when values are moved around on the stack or if the Value represents a
bool isLightData() const { return (bool)lua_islightuserdata(state, index); }
/**
- * Check the value and throw and error if its the wrong type. This
- * method never returns because it does a long jump. Consequently,
- * constructed C++ objects which exist on the stack between the current
- * frame and some lua function will not be destructed. That's not a
- * problem for objects that only exist on the stack, but any objects
- * that allocate memory on the heap (such as containers or strings) will
- * leak. Therefore, you should only call this method after cleaning up
- * such objects.
+ * Check the value and throw an error if its the wrong type. There's a
+ * little caveat: This method never returns because it does a long jump.
+ * Consequently, constructed C++ objects which exist on the stack
+ * between the current frame and some lua function will not be
+ * destructed. That's not a problem for objects that only exist on the
+ * stack, but any objects that allocate memory on the heap (such as
+ * containers or strings) will leak. Therefore, you should only call
+ * this method after cleaning up such objects. The best thing to do for
+ * defining functions is to simply check all the parameters at the
+ * get-go before any C++ objects are even constructed.
*/
- void requireType(TYPE type) const
+ void requireType(Type type) const
{
if (type != getType())
{
* Get the type of the value.
*/
- TYPE getType() const
+ Type getType() const
{
- return (TYPE)lua_type(state, index);
+ return (Type)lua_type(state, index);
}
/**
Script() :
- mState(luaL_newstate())
+ mState(0)
{
- lua_pushlightuserdata(mState, this);
- lua_setfield(mState, LUA_REGISTRYINDEX, "_script_obj");
+ reset();
}
~Script()
{
- if (mIsMainThread) lua_close(mState);
+ destroy();
}
return ScriptP(new Script);
}
+ void reset()
+ {
+ if (mState) destroy();
+ mState = luaL_newstate();
+ lua_pushlightuserdata(mState, this);
+ lua_setfield(mState, LUA_REGISTRYINDEX, "_script_obj");
+ }
+
void importStandardLibraries()
{
luaL_openlibs(mState);
}
+ void importBaseLibrary()
+ {
+ lua_pushcfunction(mState, luaopen_base);
+ push(LUA_COLIBNAME);
+ call(1, 0);
+ }
+
+ void importPackageLibrary()
+ {
+ lua_pushcfunction(mState, luaopen_package);
+ push(LUA_LOADLIBNAME);
+ call(1, 0);
+ }
+
+ void importStringLibrary()
+ {
+ lua_pushcfunction(mState, luaopen_string);
+ push(LUA_STRLIBNAME);
+ call(1, 0);
+ }
+
+ void importTableLibrary()
+ {
+ lua_pushcfunction(mState, luaopen_table);
+ push(LUA_TABLIBNAME);
+ call(1, 0);
+ }
+
+ void importMathLibrary()
+ {
+ lua_pushcfunction(mState, luaopen_math);
+ push(LUA_MATHLIBNAME);
+ call(1, 0);
+ }
+
+ void importIoLibrary()
+ {
+ lua_pushcfunction(mState, luaopen_io);
+ push(LUA_IOLIBNAME);
+ call(1, 0);
+ }
+
+ void importOsLibrary()
+ {
+ lua_pushcfunction(mState, luaopen_os);
+ push(LUA_OSLIBNAME);
+ call(1, 0);
+ }
+
+ void importDebugLibrary()
+ {
+ lua_pushcfunction(mState, luaopen_debug);
+ push(LUA_DBLIBNAME);
+ call(1, 0);
+ }
+
+
void importFunction(const std::string& name, const Function& function)
{
push(function);
}
- STATUS doString(const std::string& commands)
+ Status doString(const std::string& commands)
{
- return (STATUS)luaL_dostring(mState, commands.c_str());
+ return (Status)luaL_dostring(mState, commands.c_str());
}
- STATUS doFile(const std::string& file)
+ Status doFile(const std::string& file)
{
- return (STATUS)luaL_dofile(mState, file.c_str());
+ return (Status)luaL_dofile(mState, file.c_str());
}
lua_pushthread(mState);
}
- STATUS resume(int nargs)
+ Status resume(int nargs)
{
- return (STATUS)lua_resume(mState, nargs);
+ return (Status)lua_resume(mState, nargs);
}
- STATUS getStatus() const
+ Status getStatus() const
{
- return (STATUS)lua_status(mState);
+ return (Status)lua_status(mState);
}
int yield(int results)
lua_xmove(thread.mState, mState, n);
}
- STATUS pushCode(const std::string& filename)
+ Status pushCode(const std::string& filename)
{
- return (STATUS)luaL_loadfile(mState, filename.c_str());
+ return (Status)luaL_loadfile(mState, filename.c_str());
}
- STATUS pushCode(const std::string& name, const char* buffer, size_t size)
+ Status pushCode(const std::string& name, const char* buffer, size_t size)
{
- return (STATUS)luaL_loadbuffer(mState, buffer, size, name.c_str());
+ return (Status)luaL_loadbuffer(mState, buffer, size, name.c_str());
}
void* pushNewData(size_t size)
* is any number of return values, depending on the callee).
*/
- STATUS call(int nargs, int nresults = LUA_MULTRET)
+ Status call(int nargs, int nresults = LUA_MULTRET)
{
- return (STATUS)lua_pcall(mState, nargs, nresults, 0);
+ return (Status)lua_pcall(mState, nargs, nresults, 0);
}
}
-
- struct Exception : public Mf::Exception
- {
- explicit Exception(unsigned error) :
- Mf::Exception(error) {}
-
- void raise()
- {
- throw *this;
- }
- };
-
-
private:
Script(lua_State* state) :
return (*function)(*script);
}
+ void destroy()
+ {
+ if (mIsMainThread) lua_close(mState);
+ }
+
lua_State* mState;
bool mIsMainThread;
std::list<Function> mFunctions;