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

fail_if_error(kind, err, bndng, filename, lineno) click to toggle source

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
fetch_library_method(s) click to toggle source

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
get_global(name) click to toggle source

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
loadstring_and_call(s, bndng, filename, lineno) click to toggle source

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
pcall(stack_bottom, arg_count, bndng, filename, lineno) click to toggle source

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
print_stack(msg=nil) click to toggle source

Outputs the stack to the stdout

return_result(stack_bottom) click to toggle source

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
stack_fetch(pos=-1) click to toggle source

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
stack_load_field(name) click to toggle source

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
stack_load_global(name) click to toggle source

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
stack_load_path(path) click to toggle source

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
stack_load_ref(ref) click to toggle source

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
stack_pop() click to toggle source

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
stack_push(o) click to toggle source

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
stack_push_array(a) click to toggle source

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
stack_push_hash(h) click to toggle source

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
stack_to_s() click to toggle source

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
stack_top() click to toggle source

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
stack_type_at(pos=-1) click to toggle source

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
stack_unstack() click to toggle source

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