module Rufus::Lua::StateMixin
Rufus::Lua::Lib
contains all the raw C API Lua
methods. The methods here are shared by all the rufus-lua classes that have to deal with a Lua
state. They are protected since they aren't meant to be called directly.
The entry point of rufus-lua is Rufus::Lua::State
, look there.
Constants
- LUA_ENVIRONINDEX
- LUA_GCCOLLECT
- LUA_GCCOUNT
- LUA_GCCOUNTB
- LUA_GCRESTART
- LUA_GCSETPAUSE
- LUA_GCSETSTEPMUL
- LUA_GCSTEP
- LUA_GCSTOP
Lua
GC constants- LUA_GLOBALSINDEX
- LUA_MULTRET
- LUA_NOREF
- LUA_REFNIL
- LUA_REGISTRYINDEX
- SIMPLE_TYPES
- TBOOLEAN
- TFUNCTION
- TLIGHTUSERDATA
- TNIL
- TNONE
- TNUMBER
- TSTRING
- TTABLE
- TTHREAD
- TUSERDATA
Protected Instance Methods
This method will raise an error with err > 0, else it will immediately return.
# File lib/rufus/lua/state.rb, line 323 def fail_if_error(kind, err, bndng, filename, lineno) return if err < 1 s = Lib.lua_tolstring(@pointer, -1, nil).read_string Lib.lua_settop(@pointer, -2) fail LuaError.new(kind, err, s, bndng, filename, lineno) end
This method is used to fetch/cache references to library methods like 'math.sin' or 'coroutine.resume'. The caching is done at the Lua
state level (ie, all Lua
objects available via the state share the cache.
(Not sure yet about this yet)
# File lib/rufus/lua/state.rb, line 54 def fetch_library_method(s) m = @pointer.__lib_method_cache[s] return m if m @pointer.__lib_method_cache[s] = loadstring_and_call("return #{s}", nil, nil, nil) end
Given the name of a Lua
global variable, will return its value (or nil if there is nothing bound under that name).
# File lib/rufus/lua/state.rb, line 336 def get_global(name) stack_load_global(name) stack_pop end
This method holds the 'eval' mechanism.
# File lib/rufus/lua/state.rb, line 65 def loadstring_and_call(s, bndng, filename, lineno) bottom = stack_top chunk = filename ? "#{filename}:#{lineno}" : 'line' err = Lib.luaL_loadbuffer(@pointer, s, s.bytesize, chunk) fail_if_error('eval:compile', err, bndng, filename, lineno) pcall(bottom, 0, bndng, filename, lineno) # arg_count is set to 0 end
Assumes the Lua
stack is loaded with a ref to a method and arg_count arguments (on top of the method), will then call that Lua
method and return a result.
Will raise an error in case of failure.
# File lib/rufus/lua/state.rb, line 297 def pcall(stack_bottom, arg_count, bndng, filename, lineno) #err = Lib.lua_pcall(@pointer, 0, 1, 0) # When there's only 1 return value. # Use LUA_MULTRET (-1) the rest of the time err = Lib.lua_pcall(@pointer, arg_count, LUA_MULTRET, @error_handler) fail_if_error('eval:pcall', err, bndng, filename, lineno) return_result(stack_bottom) end
Outputs the stack to the stdout
# File lib/rufus/lua/state.rb, line 108 def print_stack(msg=nil) puts "\n=stack= #{msg ? "(#{msg})" : ""}" puts "top : #{stack_top}" print stack_to_s puts "= =" end
Returns the result of a function call or a coroutine.resume().
# File lib/rufus/lua/state.rb, line 281 def return_result(stack_bottom) count = stack_top - stack_bottom return nil if count == 0 return stack_pop if count == 1 (1..count).collect { |pos| stack_pop }.reverse end
Fetches the top value on the stack (or the one specified by the optional pos parameter), but does not 'pop' it.
# File lib/rufus/lua/state.rb, line 138 def stack_fetch(pos=-1) type, tname = stack_type_at(pos) case type when TNIL then nil when TSTRING then len = FFI::MemoryPointer.new(:size_t) ptr = Lib.lua_tolstring(@pointer, pos, len) ptr.read_string(len.read_long) when TBOOLEAN then (Lib.lua_toboolean(@pointer, pos) == 1) when TNUMBER then Lib.lua_tonumber(@pointer, pos) when TTABLE then Table.new(@pointer) # warning : this pops up the item from the stack ! when TFUNCTION then Function.new(@pointer) when TTHREAD then Coroutine.new(@pointer) else tname end end
Loads a field of the table currently on the top of the stack
# File lib/rufus/lua/state.rb, line 253 def stack_load_field(name) Lib.lua_getfield(@pointer, -1, name) end
Loads a Lua
global value on top of the stack
# File lib/rufus/lua/state.rb, line 246 def stack_load_global(name) Lib.lua_getfield(@pointer, LUA_GLOBALSINDEX, name) end
Loads a path (for example “debug.traceback”) on top of the stack.
# File lib/rufus/lua/state.rb, line 260 def stack_load_path(path) ps = path.split('.') stack_load_global(ps.shift) while ps.first stack_load_field(ps.shift) Lib.lua_remove(@pointer, -2) end end
Loads the Lua
object registered with the given ref on top of the stack
# File lib/rufus/lua/state.rb, line 274 def stack_load_ref(ref) Lib.lua_rawgeti(@pointer, LUA_REGISTRYINDEX, @ref) end
Pops the top value of lua state's stack and returns it.
# File lib/rufus/lua/state.rb, line 166 def stack_pop r = stack_fetch stack_unstack if r.class != Rufus::Lua::Table r end
Given a Ruby instance, will attempt to push it on the Lua
stack.
# File lib/rufus/lua/state.rb, line 190 def stack_push(o) return stack_push(o.to_lua) if o.respond_to?(:to_lua) case o when NilClass then Lib.lua_pushnil(@pointer) when TrueClass then Lib.lua_pushboolean(@pointer, 1) when FalseClass then Lib.lua_pushboolean(@pointer, 0) when Integer then Lib.lua_pushinteger(@pointer, o) when Float then Lib.lua_pushnumber(@pointer, o) when String then Lib.lua_pushlstring(@pointer, o, o.bytesize) when Symbol then Lib.lua_pushlstring(@pointer, o.to_s, o.to_s.bytesize) when Hash then stack_push_hash(o) when Array then stack_push_array(o) else raise( ArgumentError.new( "don't know how to pass Ruby instance of #{o.class} to Lua")) end end
Pushes an array on top of the Lua
stack.
# File lib/rufus/lua/state.rb, line 232 def stack_push_array(a) Lib.lua_createtable(@pointer, a.size, 0) # since we already know the size of the table... a.each_with_index do |e, i| stack_push(i + 1) stack_push(e) Lib.lua_settable(@pointer, -3) end end
Pushes a hash on top of the Lua
stack.
# File lib/rufus/lua/state.rb, line 218 def stack_push_hash(h) Lib.lua_createtable(@pointer, 0, h.size) # since we already know the size of the table... h.each do |k, v| stack_push(k) stack_push(v) Lib.lua_settable(@pointer, -3) end end
Returns a string representation of the state's stack.
# File lib/rufus/lua/state.rb, line 78 def stack_to_s # warning : don't touch at stack[0] s = (1..stack_top).inject([]) { |a, i| type, tname = stack_type_at(i) val = if type == TSTRING "\"#{stack_fetch(i)}\"" elsif SIMPLE_TYPES.include?(type) stack_fetch(i).to_s elsif type == TTABLE "(# is #{Lib.lua_objlen(@pointer, i)})" else '' end a << "#{i} : #{tname} (#{type}) #{val}" a }.reverse.join("\n") s += "\n" if s.length > 0 s end
Returns the offset (int) of the top element of the stack.
# File lib/rufus/lua/state.rb, line 118 def stack_top Lib.lua_gettop(@pointer) end
Returns a pair type (int) and type name (string) of the element on top of the Lua
state's stack. There is an optional pos paramter to peek at other elements of the stack.
# File lib/rufus/lua/state.rb, line 127 def stack_type_at(pos=-1) type = Lib.lua_type(@pointer, pos) tname = Lib.lua_typename(@pointer, type) [ type, tname ] end
Makes sure the stack loses its top element (but doesn't return it).
# File lib/rufus/lua/state.rb, line 176 def stack_unstack new_top = stack_top - 1 new_top = 0 if new_top < 0 # # there are no safeguard in Lua, setting top to -2 work well # when the stack is crowded, but it has bad side effects when the # stack is empty... Now safeguarding by ourselves. Lib.lua_settop(@pointer, new_top) end