2 #include "ScriptException.h"
8 #include <lua50/lauxlib.h>
9 #include <lua50/lualib.h>
14 static void LineHook(lua_State
*L
, lua_Debug
*ar
) {
15 std::cerr
<< ar
->currentline
<< std::endl
;
18 static void CallHook(lua_State
*L
, lua_Debug
*ar
) {
19 std::cerr
<< ar
->source
<< ' ' << ar
->name
<< std::endl
;
24 assert( (None
== LUA_TNONE
) && (Nil
== LUA_TNIL
) &&
25 (Boolean
== LUA_TBOOLEAN
) && (LightUserData
== LUA_TLIGHTUSERDATA
) &&
26 (Number
== LUA_TNUMBER
) && (String
== LUA_TSTRING
) &&
27 (Table
== LUA_TTABLE
) && (Function
== LUA_TFUNCTION
) &&
28 (UserData
== LUA_TUSERDATA
) && (Thread
== LUA_TTHREAD
) );
32 throw ScriptException("Failed to initialize Lua virtual machine");
34 lua_pushstring(lua
, "_ERRORMESSAGE");
35 lua_pushlightuserdata(lua
, this);
36 lua_pushcclosure(lua
, printError
, 1);
37 lua_settable(lua
, LUA_GLOBALSINDEX
);
39 lua_register(lua
, "trace", printMessage
);
41 static const luaL_reg lualibs
[] = {
42 {"base", luaopen_base
},
43 {"table", luaopen_table
},
45 {"string", luaopen_string
},
46 {"math", luaopen_math
},
47 {"debug", luaopen_debug
},
48 // {"loadlib", luaopen_loadlib},
52 const luaL_reg
*lib
= lualibs
;
53 for(; lib
->func
; lib
++) {
54 lib
->func(lua
); /* open library */
55 lua_settop(lua
, 0); /* discard any results */
59 lua_sethook(lua
, CallHook
, LUA_MASKCALL
, 0);
60 lua_sethook(lua
, LineHook
, LUA_MASKLINE
, 0);
72 void VM::compileFile(const char *name
) {
73 if( lua_dofile(lua
, name
) )
74 throw ScriptException("Failed to compile script file");
77 void VM::compileSource(const std::string
& src
) {
78 if( lua_dostring(lua
, src
.c_str()) )
79 throw ScriptException("Failed to compile script string");
82 void VM::compileSource(const char *buffer
, int size
) {
87 lua_setgcthreshold(lua
, 0); // collected garbage
90 bool VM::next(int index
) {
91 if( ! lua_istable(lua
, index
) )
92 throw ScriptException("Tried to use next() on a non-table object");
94 return (0 != lua_next(lua
, index
));
97 void VM::pop(int n
/*= 1*/) {
101 void VM::setTable(int index
) {
102 if( lua_istable(lua
, index
) == 0 )
103 throw ScriptException("Tried to use object as table");
105 lua_settable(lua
, index
);
108 void VM::setTableRaw(int index
) {
109 if( lua_istable(lua
,index
) == 0 )
110 throw ScriptException("Tried to use object as table");
112 lua_rawset(lua
, index
);
115 void VM::setTableRawI(int index
, int n
) {
116 if( lua_istable(lua
, index
) == 0 )
117 throw ScriptException("Tried to use object as table");
119 lua_rawseti(lua
, index
, n
);
122 void VM::call(int args
, int results
) {
123 if( lua_isfunction(lua
, -args
- 1) == 0 )
124 throw ScriptException("Called invalid script function\n");
126 lua_pushliteral(lua
, "_ERRORMESSAGE");
127 lua_gettable(lua
, LUA_GLOBALSINDEX
); // get traceback function
130 int errnr
= lua_pcall(lua
, args
, results
, 1);
133 const char *msg
= lua_tostring(lua
, -1);
135 msg
= "(error with no message)";
138 throw ScriptException(msg
);
140 throw ScriptException(err
);
147 void VM::registerClass(const char *name
, const script::Table
& table
) {
148 lua_pushstring(lua
, name
);
149 lua_getref(lua
, table
.ref
);
150 lua_settable(lua
, LUA_GLOBALSINDEX
);
153 void VM::unregisterClass(const char *name
) {
154 lua_pushstring(lua
, name
);
156 lua_settable(lua
, LUA_GLOBALSINDEX
);
159 void VM::getGlobal(const std::string
& name
) {
160 lua_getglobal(lua
, name
.c_str());
163 void VM::getGlobal(const char *name
) {
164 lua_getglobal(lua
, name
);
167 void VM::setGlobal(const std::string
& name
) {
168 lua_setglobal(lua
, name
.c_str());
171 void VM::setGlobal(const char *name
) {
172 lua_setglobal(lua
, name
);
175 void VM::pushValue(int index
) {
176 lua_pushvalue(lua
, index
);
183 void VM::pushNumber(float x
) {
184 lua_pushnumber(lua
, x
);
187 void VM::pushBoolean(bool b
) {
188 lua_pushboolean(lua
, b
);
191 void VM::pushString(const std::string
& str
) {
192 lua_pushstring(lua
, str
.c_str());
195 void VM::pushString(const char *str
) {
196 lua_pushstring(lua
, str
);
199 void VM::pushTable(const script::Table
& tab
) {
200 assert( lua
== tab
.lua
);
203 lua_getref(lua
, tab
.ref
);
208 void VM::pushCFunction(CFunction f
) {
209 lua_pushcclosure(lua
, f
, 0);
212 void VM::pushCClosure(CFunction f
, int n
) {
213 lua_pushcclosure(lua
, f
, n
);
215 void VM::remove( int index
) {
216 lua_remove(lua
, index
);
219 int VM::getType(int index
) const {
220 return lua_type(lua
, index
);
223 const char *VM::getTypeName(int type
) const {
224 return lua_typename(lua
, type
);
227 bool VM::isType(int index
, VM::Type type
) const {
228 return ( lua_type(lua
, index
) == type
);
231 bool VM::isCFunction(int index
) const {
232 return ( lua_iscfunction(lua
, index
) != 0 );
235 bool VM::isFunction(int index
) const {
236 return ( lua_type(lua
, index
) == LUA_TFUNCTION
);
239 bool VM::isNil(int index
) const {
240 return ( lua_type(lua
, index
) == LUA_TNIL
);
243 bool VM::isNumber(int index
) const {
244 return ( lua_type(lua
, index
) == LUA_TNUMBER
);
247 bool VM::isString(int index
) const {
248 return ( lua_type(lua
, index
) == LUA_TSTRING
);
251 bool VM::isTable(int index
) const {
252 return ( lua_type(lua
, index
) == LUA_TTABLE
);
255 bool VM::isUserData(int index
) const {
256 return ( lua_type(lua
, index
) == LUA_TUSERDATA
);
259 bool VM::isBoolean(int index
) const {
260 return ( lua_type(lua
, index
) == LUA_TBOOLEAN
);
263 bool VM::isEqual(int index1
, int index2
) const {
264 return ( lua_equal(lua
, index1
, index2
) != 0 );
267 bool VM::isLess(int index1
, int index2
) const {
268 return ( lua_lessthan(lua
, index1
, index2
) != 0 );
271 int VM::stackSpace() const {
272 //return luaL_stackspace(lua);
276 bool VM::toBoolean(int index
) const {
277 if( lua_type(lua
, index
) != LUA_TBOOLEAN
)
278 throw ScriptException("Tried to use non-boolean as boolean");
280 return lua_toboolean(lua
, index
);
283 float VM::toNumber(int index
) const {
284 if( lua_type(lua
, index
) != LUA_TNUMBER
)
285 throw ScriptException("Tried to use non-number as number");
287 return lua_tonumber(lua
, index
);
290 const char *VM::toString(int index
) const {
291 if( ! lua_isstring(lua
, index
) )
292 throw ScriptException("Tried to use non-string as string");
294 return lua_tostring(lua
, index
);
297 script::Table
VM::toTable(int index
) const {
298 if ( ! lua_istable(lua
, index
) )
299 throw ScriptException("Tried to use non-table as table");
300 lua_pushvalue(lua
, index
);
304 tab
.ref
= lua_ref(lua
, true);
308 VM::CFunction
VM::toCFunction(int index
) const {
309 if( lua_iscfunction(lua
, index
) == 0 )
310 throw ScriptException("Tried to use non C-function as C-function");
312 return lua_tocfunction(lua
, index
);
315 void *VM::toUserData(int index
) const {
316 if( lua_isuserdata(lua
, index
) == 0 )
317 throw ScriptException("Tried to use object as user data");
319 return lua_touserdata(lua
, index
);
322 int VM::top() const {
323 return lua_gettop(lua
);
326 void VM::stackTrace(int level
, std::string
& trace
) const {
328 // memset(&ar, 0, sizeof(ar));
329 if( ! lua_getstack(lua
, 1 + level
, &ar
) ) {
334 if( ! lua_getinfo(lua
, "Snl", &ar
) ) {
340 sprintf(str
, "at %s(%s:%i)", ar
.name
, ar
.source
, ar
.currentline
);
344 int VM::printError(lua_State
* lua
) {
345 assert( lua_isstring(lua
, -1) );
346 assert( lua_isuserdata(lua
, lua_upvalueindex(1)) );
348 const char *msg
= lua_tostring(lua
, -1);
349 VM
*vm
= (VM
*)lua_touserdata(lua
, lua_upvalueindex(1));
353 const short MAX_LEVEL
= 20;
354 std::string trace
[MAX_LEVEL
];
356 for( ; level
< MAX_LEVEL
; ++level
) {
357 vm
->stackTrace(level
, trace
[level
]);
358 if( trace
[level
] == "" )
362 vm
->err
= vm
->err
+ "\nStack trace:";
363 vm
->err
= vm
->err
+ "\n\t " + trace
[level
];
367 /* std::cerr << msg << std::endl;
369 std::cerr << "Stack trace:";
370 for ( int i = 0 ; i < level ; ++i )
371 std::cerr << trace[i] << std::endl;
377 int VM::printMessage( lua_State
* lua
) {
378 assert( lua_isstring(lua
, 1) );
380 const char *msg
= lua_tostring(lua
, 1);
384 // memset(&ar, 0, sizeof(ar));
385 lua_getstack(lua
, 1, &ar
);
386 lua_getinfo(lua
, "Snl", &ar
);
389 std::cerr
<< "script: " << msg
<< " at "
390 << ar
.source
<< ar
.currentline
<< std::endl
;
395 void VM::getRef(int ref
) {
396 lua_getref(lua
, ref
);
399 int VM::ref(bool lock
) {
400 return lua_ref(lua
, lock
);
403 void VM::unref(int ref
) {
404 lua_unref(lua
, ref
);