X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2FMoof%2FScript.hh;h=974dce78d6e8e12c1151035adb162591524eb6ae;hp=2f285cecc2bcdd740529783fcc8d4f7ea0fa581b;hb=00612586426be6d9a976f141a25ffc1f0d284501;hpb=e495074443d9fd7bc16137084cf9de3d031b75c4 diff --git a/src/Moof/Script.hh b/src/Moof/Script.hh index 2f285ce..974dce7 100644 --- a/src/Moof/Script.hh +++ b/src/Moof/Script.hh @@ -1,43 +1,28 @@ -/******************************************************************************* - - Copyright (c) 2009, Charles McGarvey - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*******************************************************************************/ +/*] Copyright (c) 2009-2010, Charles McGarvey [************************** +**] All rights reserved. +* +* vi:ts=4 sw=4 tw=75 +* +* Distributable under the terms and conditions of the 2-clause BSD license; +* see the file COPYING for a complete text of the license. +* +**************************************************************************/ #ifndef _MOOF_SCRIPT_HH_ #define _MOOF_SCRIPT_HH_ /** * @file Script.hh - * A thin wrapper over Lua. This is not meant as a complicated binding package - * between C++ and Lua. It does not try to make the boundary invisible. It - * does not hide the concept of the Lua stack, but rather provides that - * mechanism with a certain level of abstraction while also providing a cleaner, - * more consistent API. + * A thin wrapper over Lua. This is not meant as a complicated binding + * package between C++ and Lua. It is not meant to obscure the division + * between C++ and Lua but rather to clarify it and make it more + * manageable. It does not hide the concept of the Lua stack, but rather + * provides that mechanism with a certain level of abstraction while also + * providing a cleaner, more consistent API. */ +#include #include #include #include @@ -46,11 +31,8 @@ #include #include #include - #include -#include - namespace Mf { @@ -79,7 +61,7 @@ public: THREAD = LUA_TTHREAD }; - enum Status + enum Result { SUCCESS = 0, YIELD = LUA_YIELD, @@ -98,126 +80,158 @@ public: }; /** - * 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 - * negative index on the stack (the value of which will change as things are - * pushed onto and popped from the stack). + * This is the most prominent abstraction on top of the standard Lua + * API. A Slot object represents a value on the stack. More + * specifically, it represents a position on the stack. The + * distinction is only important when objects are moved around on the + * stack or if the Slot represents a negative index on the stack (the + * value of which will change as things are pushed onto and popped from + * the stack). */ - struct Value + struct Slot { /** - * You have direct access to the index of the value on the stack being - * represented. + * You have direct access to the index of the value on the stack + * being represented. */ int index; - /** - * A default-constructed Value is invalid until a valid Value is - * assigned to it. The only method that should be called on such a - * Value is isValid(), otherwise chaos may ensue. In this case, the - * Value will be invalid even if index is manually changed to a valid - * index. You have to index the script itself to get a valid Value. - */ - Value(lua_State* s = 0, int i = 0) : + Slot(const Script& s, int i = 0) : index(i), - state(s) {} + mScript(const_cast(s)) {} /** - * A copied value presently points to the same value, except the real - * index is used. That means that if a value that refers to a frame - * referenced from the top of the stack will have its normalized index - * copied into the new value object. + * A copied value presently points to the same value, except the + * real index is used. That means that if a value that refers to a + * frame referenced from the top of the stack will have its + * normalized index copied into the new value object. */ - Value(const Value& copy) : - index(copy.getRealIndex()), - state(copy.state) {} + //Slot(const Slot& copy) : + //index(copy.positiveIndex()), + //mScript(copy.mScript) {} // check the type of the value - bool isBoolean() const { return (bool)lua_isboolean(state, index); } - bool isFunction() const { return (bool)lua_isfunction(state, index); } - bool isNil() const { return (bool)lua_isnil(state, index); } - bool isNone() const { return (bool)lua_isnone(state, index); } - bool isValid() const { return state != 0 && !isNone(); } - bool isNoneOrNil() const { return (bool)lua_isnoneornil(state, index); } - bool isNumber() const { return (bool)lua_isnumber(state, index); } - bool isString() const { return (bool)lua_isstring(state, index); } - bool isTable() const { return (bool)lua_istable(state, index); } - bool isThread() const { return (bool)lua_isthread(state, index); } - bool isData() const { return (bool)lua_isuserdata(state, index); } - bool isLightData() const { return (bool)lua_islightuserdata(state, index); } + bool isBoolean() const + { return (bool)lua_isboolean(mScript.mState, index); } + bool isImportedFunction() const + { return (bool)lua_iscfunction(mScript.mState, index); } + bool isFunction() const + { return (bool)lua_isfunction(mScript.mState, index); } + bool isNil() const + { return (bool)lua_isnil(mScript.mState, index); } + bool isNone() const + { return (bool)lua_isnone(mScript.mState, index); } + bool isNoneOrNil() const + { return (bool)lua_isnoneornil(mScript.mState, index); } + bool isNumber() const + { return (bool)lua_isnumber(mScript.mState, index); } + bool isString() const + { return (bool)lua_isstring(mScript.mState, index); } + bool isTable() const + { return (bool)lua_istable(mScript.mState, index); } + bool isThread() const + { return (bool)lua_isthread(mScript.mState, index); } + bool isData() const + { return (bool)lua_isuserdata(mScript.mState, index); } + bool isLightData() const + { return (bool)lua_islightuserdata(mScript.mState, index); } /** - * 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. + * 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 t) const { - if (type != getType()) + if (t != type()) { - luaL_typerror(state, index, lua_typename(state, type)); + luaL_typerror(mScript.mState, index, + lua_typename(mScript.mState, t)); } } - void throwError(const char* error) + void raise(const char* error) { - luaL_argerror(state, index, error); + luaL_argerror(mScript.mState, index, error); } - Value& requireBoolean() + Slot& requireBoolean() { - if (!isBoolean()) luaL_typerror(state, index, "boolean"); + if (!isBoolean()) + { + luaL_typerror(mScript.mState, index, "boolean"); + } return *this; } - Value& requireNumber() + Slot& requireNumber() { - if (!isNumber()) luaL_typerror(state, index, "number"); + if (!isNumber()) + { + luaL_typerror(mScript.mState, index, "number"); + } return *this; } - Value& requireString() + Slot& requireString() { - if (!isString()) luaL_typerror(state, index, "string"); + if (!isString()) + { + luaL_typerror(mScript.mState, index, "string"); + } return *this; } - Value& requireTable() + Slot& requireTable() { - if (!isTable()) luaL_typerror(state, index, "table"); + if (!isTable()) + { + luaL_typerror(mScript.mState, index, "table"); + } return *this; } - Value& requireFunction() + Slot& requireFunction() { - if (!isFunction()) luaL_typerror(state, index, "function"); + if (!isFunction()) + { + luaL_typerror(mScript.mState, index, "function"); + } return *this; } - Value& requireData() + Slot& requireData() { - if (!isData()) luaL_typerror(state, index, "data"); + if (!isData()) + { + luaL_typerror(mScript.mState, index, "data"); + } return *this; } - Value& requireNil() + Slot& requireNil() { - if (!isNil()) luaL_typerror(state, index, "nil"); + if (!isNil()) + { + luaL_typerror(mScript.mState, index, "nil"); + } return *this; } - Value& requireThread() + Slot& requireThread() { - if (!isThread()) luaL_typerror(state, index, "thread"); + if (!isThread()) + { + luaL_typerror(mScript.mState, index, "thread"); + } return *this; } @@ -226,94 +240,96 @@ public: * Get the type of the value. */ - Type getType() const + Type type() const { - return (Type)lua_type(state, index); + return (Type)lua_type(mScript.mState, index); } /** * Get the name of the type of the value as a string. */ - std::string getTypeName() const + std::string typeName() const { - return std::string(luaL_typename(state, index)); + return std::string(luaL_typename(mScript.mState, index)); } /** - * Get the length of the value according to the definition given by Lua. + * Get the length of the value according to the definition given by + * Lua. */ - size_t getLength() const + size_t length() const { - return lua_objlen(state, index); + return lua_objlen(mScript.mState, index); } - int getRealIndex() const + int positiveIndex() const { - if (index < 0) return lua_gettop(state) + 1 + index; + if (index < 0) return index + lua_gettop(mScript.mState) + 1; else return index; } /** - * Get a pointer value (for userdata, tables, threads, and functions). + * Get a pointer value (for userdata, tables, threads, and + * functions). */ - const void* getIdentifier() const + const void* id() const { - return lua_topointer(state, index); + return lua_topointer(mScript.mState, index); } + bool isIdentical(const Slot& rhs) const + { + return &mScript == &(rhs.mScript) && index == rhs.index; + } - bool operator == (const Value& rhs) const + operator bool () const { - return (bool)lua_equal(state, index, rhs.index); + return !isNone(); } - bool operator != (const Value& rhs) const + + + bool operator == (const Slot& rhs) const + { + return (bool)lua_equal(mScript.mState, index, rhs.index); + } + bool operator != (const Slot& rhs) const { return !(*this == rhs); } - bool operator < (const Value& rhs) const + + bool operator < (const Slot& rhs) const { - return (bool)lua_lessthan(state, index, rhs.index); + return (bool)lua_lessthan(mScript.mState, index, rhs.index); } - bool operator <= (const Value& rhs) const + bool operator <= (const Slot& rhs) const { return *this < rhs || *this == rhs; } - bool operator > (const Value& rhs) const + bool operator > (const Slot& rhs) const { return !(*this <= rhs); } - bool operator >= (const Value& rhs) const + bool operator >= (const Slot& rhs) const { return !(*this < rhs); } - operator bool () const - { - return (bool)lua_toboolean(state, index); - } - - Value& operator = (const Value& rhs) - { - rhs.pushCopy(); - replaceWithTop(); - return *this; - } /** * Convert the underlying value to a C++ type. */ - template + template bool get(T& value) const { if (isNumber()) { - value = (T)lua_tointeger(state, index); + value = (T)lua_tointeger(mScript.mState, index); return true; } return false; @@ -323,7 +339,7 @@ public: { if (isNumber()) { - value = (float)lua_tonumber(state, index); + value = (float)lua_tonumber(mScript.mState, index); return true; } return false; @@ -332,7 +348,7 @@ public: { if (isNumber()) { - value = (double)lua_tonumber(state, index); + value = (double)lua_tonumber(mScript.mState, index); return true; } return false; @@ -342,62 +358,82 @@ public: { if (isBoolean()) { - value = (bool)lua_toboolean(state, index); + value = (bool)lua_toboolean(mScript.mState, index); return true; } return false; } - bool get(std::string& value) const + bool get(const char*& value, size_t& size) const { if (isString()) { - size_t size; - const char* str = lua_tolstring(state, index, &size); + value = lua_tolstring(mScript.mState, index, &size); + return true; + } + return false; + } + + bool get(std::string& value) const + { + const char* str; + size_t size; + if (get(str, size)) + { value.assign(str, size); return true; } return false; } - template + bool get(void*& value) const + { + if (isData()) + { + value = lua_touserdata(mScript.mState, index); + return true; + } + return false; + } + + template bool get(std::vector& array) const { if (!isTable()) return false; array.clear(); - Value value(state, -1); - int realIndex = getRealIndex(); + Slot value = mScript[-1]; + int realIndex = positiveIndex(); bool done = false; for (int i = 1; !done; ++i) { - lua_rawgeti(state, realIndex, i); + lua_rawgeti(mScript.mState, realIndex, i); T v; if (value.get(v)) array.push_back(v); else done = true; - lua_pop(state, 1); + mScript.pop(); } return true; } - template + template bool get(std::map& dictionary) const { if (!isTable()) return false; dictionary.clear(); - Value key(state, -2); - Value value(state, -1); - int realIndex = getRealIndex(); + Slot key = mScript[-2]; + Slot value = mScript[-1]; + int realIndex = positiveIndex(); - lua_pushnil(state); - while (lua_next(state, realIndex) != 0) + mScript.pushNil(); + while (lua_next(mScript.mState, realIndex) != 0) { std::string k; if (!key.isNumber() && key.get(k)) @@ -405,68 +441,161 @@ public: T v; if (value.get(v)) dictionary[k] = v; } - lua_pop(state, 1); + mScript.pop(); } - lua_pop(state, 1); + mScript.pop(); return true; } + /** + * Get the value of a field from the table. + */ + + template + bool get(T& value, V field) const + { + bool ret = pushField(field).get(value); + mScript.pop(); + return ret; + } + + + template + void setField(T field, V value) + { + mScript.push(field); + mScript.push(value); + setField(); + } + + void setField() + { + lua_settable(mScript.mState, index); + } + + + template + void setField(const std::string& field, T value) + { + setField(field.c_str(), value); + } + template + void setField(const char* field, T value) + { + mScript.push(value); + lua_setfield(mScript.mState, index, field); + } /** - * Copy the value and push the copy to the stack. + * This set method, as opposed to the others, sets the value of the + * actual slot. The others set table values. */ + template + void set(T value) + { + mScript.push(value); + replace(); + } - void pushCopy() const + void set() { - lua_pushvalue(state, index); + replace(); } + /** * Replace this value with the value at the top of the stack. */ - void replaceWithTop() + void replace() { - lua_replace(state, index); + lua_replace(mScript.mState, index); } void remove() { - lua_remove(state, index); + lua_remove(mScript.mState, index); + } + + void pop() + { + // removes this slot, taking with it everything above it + mScript.pop(mScript.stackSize() - index + 1); } /** - * Inserts the top-most value on the stack at position index, shifting other - * values as needed. + * Inserts the top-most value on the stack at position index, + * shifting other values as needed. */ void insertTopHere() { - lua_insert(state, index); + lua_insert(mScript.mState, index); } + + /** + * Copy the value and push the copy to the stack. + */ + + Slot pushCopy() const + { + lua_pushvalue(mScript.mState, index); + return mScript.top(); + } - void pushMetatable() const + Slot pushMetaTable() const { - lua_getmetatable(state, index); + lua_getmetatable(mScript.mState, index); + return mScript.top(); } - void pushField() const + Slot pushEnvironment() const { - lua_gettable(state, index); + lua_getfenv(mScript.mState, index); + return mScript.top(); } - void pushField(const std::string& name) const + + Slot pushField() const { - lua_getfield(state, index, name.c_str()); + lua_gettable(mScript.mState, index); + return mScript.top(); } + template + Slot pushField(T index) const + { + mScript.push(index); + return pushField(); + } + + Slot pushField(const std::string& name) const + { + return pushField(name.c_str()); + } + Slot pushField(const char* name) const + { + lua_getfield(mScript.mState, index, name); + return mScript.top(); + } + + + Script& script() + { + return mScript; + } + + const Script& script() const + { + return mScript; + } private: - lua_State* state; + Script& mScript; }; @@ -491,8 +620,7 @@ public: { if (mState) destroy(); mState = luaL_newstate(); - lua_pushlightuserdata(mState, this); - lua_setfield(mState, LUA_REGISTRYINDEX, "_script_obj"); + registry().setField("Script_hh_Object", (void*)this); } @@ -564,15 +692,14 @@ public: lua_setglobal(mState, name.c_str()); } - - Status doString(const std::string& commands) + Result doString(const std::string& commands) { - return (Status)luaL_dostring(mState, commands.c_str()); + return (Result)luaL_dostring(mState, commands.c_str()); } - Status doFile(const std::string& file) + Result doFile(const std::string& file) { - return (Status)luaL_dofile(mState, file.c_str()); + return (Result)luaL_dofile(mState, file.c_str()); } @@ -590,14 +717,14 @@ public: lua_pushthread(mState); } - Status resume(int nargs) + Result resume(int nargs) { - return (Status)lua_resume(mState, nargs); + return (Result)lua_resume(mState, nargs); } - Status getStatus() const + Result getStatus() const { - return (Status)lua_status(mState); + return (Result)lua_status(mState); } int yield(int results) @@ -612,16 +739,17 @@ public: /** - * Throw an error with the value at the top of the stack. 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. + * Throw an error with the value at the top of the stack. 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. */ - void throwError() + void raise() { lua_error(mState); } @@ -631,52 +759,53 @@ public: * Get significant values. */ - Value getGlobalTable() const + Slot globals() const { - return Value(mState, GLOBALS); + return Slot(*this, GLOBALS); } - Value getRegistryTable() const + Slot registry() const { - return Value(mState, REGISTRY); + return Slot(*this, REGISTRY); } - Value getEnvironmentTable() const + Slot environment() const { - return Value(mState, ENVIRONMENT); + return Slot(*this, ENVIRONMENT); } - Value getTop() const + Slot top() const { - return Value(mState, lua_gettop(mState)); + return Slot(*this, stackSize()); } /** - * Get the size of the stack; this is also the index of the top-most value. + * Get the size of the stack; this is also the index of the top-most + * value. */ - int getSize() const + int stackSize() const { return lua_gettop(mState); } - void setSize(int size) + void setStackSize(int size) { lua_settop(mState, size); } - void clear() + void clearStack() { - setSize(0); + setStackSize(0); } /** - * Makes sure there is at least extra more places on the stack. Returns - * false if space couldn't be created. Just like with the regular Lua API, - * you are responsible to make sure the stack is big enough to hold whatever - * you want to push on it. This is usually only an issue if you're pushing - * stuff in a loop. + * Makes sure there is at least extra more places on the stack. + * Returns false if space couldn't be created. Just like with the + * regular Lua API, you are responsible to make sure the stack is big + * enough to hold whatever you want to push on it. This is usually + * only an issue if you're pushing stuff in a loop. */ bool checkStack(int extra) @@ -686,10 +815,10 @@ public: /** - * Concatenates the top-most n values on the stack. + * Concatenates the top-most n slots on the stack. */ - void concat(int n) + void concatenate(int n = 2) { lua_concat(mState, n); } @@ -699,93 +828,109 @@ public: * Push some values onto the stack. */ - template - void push(T value) + template + Slot push(T value) { lua_pushinteger(mState, lua_Integer(value)); + return top(); } - void push(bool value) + Slot push(bool value) { lua_pushboolean(mState, int(value)); + return top(); } - void push(float value) + Slot push(float value) { lua_pushnumber(mState, (lua_Number)value); + return top(); } - void push(double value) + Slot push(double value) { lua_pushnumber(mState, (lua_Number)value); + return top(); } - void push(const std::string& value) + Slot push(const std::string& value) { lua_pushlstring(mState, value.c_str(), value.length()); + return top(); } - void push(const char* value) + Slot push(const char* value) { lua_pushstring(mState, value); + return top(); } - void push(const char* value, size_t length) + Slot push(const char* value, size_t length) { lua_pushlstring(mState, value, length); + return top(); } - void push(const Function& function) + Slot push(const Function& function) { mFunctions.push_back(function); - lua_pushlightuserdata(mState, (void*)&mFunctions.back()); lua_pushcclosure(mState, dispatchCall, 1); + return top(); } - void push(void* data) + Slot push(void* data) { lua_pushlightuserdata(mState, data); + return top(); } - void pushNil() + Slot pushNil() { lua_pushnil(mState); + return top(); } - void pushFromThread(Script& thread, int n) + Slot pushFromThread(Script& thread, int n) { lua_xmove(thread.mState, mState, n); + return top(); } - Status pushCode(const std::string& filename) + Slot pushCode(const std::string& file, Result& result) { - return (Status)luaL_loadfile(mState, filename.c_str()); + result = (Result)luaL_loadfile(mState, file.c_str()); + return top(); } - Status pushCode(const std::string& name, const char* buffer, size_t size) + Slot pushCode(const std::string& name, const char* buffer, + size_t size, Result& result) { - return (Status)luaL_loadbuffer(mState, buffer, size, name.c_str()); + result = (Result)luaL_loadbuffer(mState, + buffer, size, name.c_str()); + return top(); } - void* pushNewData(size_t size) + Slot pushNewData(void*& data, size_t size) { - return lua_newuserdata(mState, size); + data = lua_newuserdata(mState, size); + return top(); } - void pushNewTable() + Slot pushNewTable(int narr = 0, int nrec = 0) { - lua_newtable(mState); + lua_createtable(mState, narr, nrec); + return top(); } /** * Call a function on the stack. The correct procedure is to push a - * function onto the stack followed by nargs arguments. This method will - * pop them off upon return, leaving up to nresults return values (default - * is any number of return values, depending on the callee). + * function onto the stack followed by nargs arguments. This method + * will pop them off upon return, leaving up to nresults return values + * (default is any number of return values, depending on the callee). */ - Status call(int nargs, int nresults = LUA_MULTRET) + Result call(int nargs = 0, int nresults = LUA_MULTRET) { - return (Status)lua_pcall(mState, nargs, nresults, 0); + return (Result)lua_pcall(mState, nargs, nresults, 0); } @@ -800,27 +945,12 @@ public: /** - * Index into the stack to get a Value. + * Index into the stack to get a Slot. */ - Value operator [] (int index) const - { - return Value(mState, index); - } - - - /** - * Getting and setting fields of a table. - */ - - void get(const std::string& field, int index = GLOBALS) const - { - lua_getfield(mState, index, field.c_str()); - } - - void set(const std::string& field, int index = GLOBALS) + Slot operator [] (int index) const { - lua_setfield(mState, index, field.c_str()); + return Slot(*this, index); } @@ -872,7 +1002,7 @@ private: const Function* function = (const Function*)lua_touserdata(state, lua_upvalueindex(1)); - lua_getfield(state, LUA_REGISTRYINDEX, "_script_obj"); + lua_getfield(state, LUA_REGISTRYINDEX, "Script_hh_Object"); Script* script = (Script*)lua_touserdata(state, -1); lua_pop(state, 1); @@ -890,9 +1020,36 @@ private: }; +inline std::ostream& operator << (std::ostream& stream, + const Script::Slot& slot) +{ + if (slot.isString()) + { + std::string str; + slot.get(str); + stream << str; + } + else if (slot.isBoolean()) + { + bool value; + slot.get(value); + if (value) stream << "true"; + else stream << "false"; + } + else if (slot.isNil()) + { + stream << "nil"; + } + else + { + stream << slot.typeName() << " (" << slot.id() << ")"; + } + + return stream; +} + + } // namespace Mf #endif // _MOOF_SCRIPT_HH_ -/** vim: set ts=4 sw=4 tw=80: *************************************************/ -